diff options
Diffstat (limited to 'kbabel/kbabeldict/modules')
74 files changed, 18694 insertions, 0 deletions
diff --git a/kbabel/kbabeldict/modules/Makefile.am b/kbabel/kbabeldict/modules/Makefile.am new file mode 100644 index 00000000..1807fb23 --- /dev/null +++ b/kbabel/kbabeldict/modules/Makefile.am @@ -0,0 +1,7 @@ + +if include_DBSEARCHENGINE +DB_SUBDIR=dbsearchengine +endif + +SUBDIRS = pocompendium poauxiliary $(DB_SUBDIR) tmx + diff --git a/kbabel/kbabeldict/modules/dbsearchengine/AUTHOR b/kbabel/kbabeldict/modules/dbsearchengine/AUTHOR new file mode 100644 index 00000000..2a79312d --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/AUTHOR @@ -0,0 +1 @@ +Andrea Rizzi <rizzi@kde.org>
\ No newline at end of file diff --git a/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.cpp b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.cpp new file mode 100644 index 00000000..ac55335d --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.cpp @@ -0,0 +1,1899 @@ +/*************************************************************************** + KDBSearchEngine.cpp - description + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + (C) 2005 by Stanislav Visnovsky + email : rizzi@kde.org + ***************************************************************************/ + +/* + Translation search engine + + + Copyright 2000 + 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 Qt library by Trolltech AS, Norway (or with modified versions * + * of Qt that use the same license as Qt), 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 * + * Qt. 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 <qtextedit.h> +#include <qprogressdialog.h> + +#include <qinputdialog.h> +#include <kdeversion.h> +#include <klocale.h> +#include <kdebug.h> +#include <kio/netaccess.h> +#include <kmessagebox.h> +#include <kfiledialog.h> +#include <kurlrequester.h> +#include <kstandarddirs.h> + +#include "kapplication.h" +#include "KDBSearchEngine.h" + +#include "dbscan.h" + +#include "errno.h" +#include "stdio.h" +#include "stdlib.h" +#include <sys/time.h> +#include "preferenceswidget.h" +#include "dbse_factory.h" +#include <qprogressbar.h> +#include <qpushbutton.h> +#include <klineedit.h> +#include <kconfig.h> + +#include <qdir.h> +#include <qradiobutton.h> +#include <qcheckbox.h> +#include <qspinbox.h> +#include <qslider.h> +#include <qmemarray.h> + +#include "database.h" + +#include "catalogsettings.h" + +#define BIGNUMBER 400000000 + +using namespace KBabel; + +KDBSearchEngine::KDBSearchEngine (QObject * parent, const char *name): +SearchEngine (parent, name) +{ + edited = "unknown"; + dm = 0; //Database Manager + pw = 0; //Preference widget + lang = ""; + dbOpened = false; + dbname = ""; + lasterror = i18n ("No error"); + connect (this, SIGNAL (hasError (const QString &)), + SLOT (setLastError (const QString &))); + + IAmReady = true; // I don't know if it is a good idea, no DB loaded!!! + + scanInProgress = false; + searching = false; + stopNow = false; + + norm = false; // Normalize white space = FALSE + comm = true; // Remove Comments = TRUE + +} + + +KDBSearchEngine::~KDBSearchEngine () +{ +} + + + +bool +KDBSearchEngine::loadDatabase (QString database, bool noask = false) +{ + bool ret = true; + bool asked = false; + if (noask) + asked = true; + if (dm != 0) + { + delete dm; + dm = 0; + } + + QDir dir (database); + if (!dir.exists ()) + { + if (asked + || KMessageBox::questionYesNo (0, + i18n + ("Database folder does not exist:\n%1\n" + "Do you want to create it now?"). + arg (database), QString::null, i18n("Create Folder"), i18n("Do Not Create")) == + KMessageBox::Yes) + { + asked = true; + + QStringList dirList; + while (!dir.exists () && !dir.dirName ().isEmpty ()) + { + dirList.prepend (dir.dirName ()); + dir.setPath (dir.path () + "/.."); + } + + for (QStringList::Iterator it = dirList.begin (); + it != dirList.end (); ++it) + { + if (!dir.mkdir (*it)) + { + KMessageBox::sorry (0, + i18n + ("It was not possible to create folder %1"). + arg (dir.path () + "/" + + (*it))); + ret = false; + break; + } + dir.cd (*it); + } + } + else + { + ret = false; + } + } + + if (ret) + { + // test, if there are both of ,old and standard databases + QString transFile = database + "/translations." + lang + ".db"; + + bool oldstuff = QFile::exists (transFile + ",old"); + bool newstuff = QFile::exists (transFile); + + if (oldstuff && newstuff) + { + // there is an old db2 database, ask user + + if (KMessageBox:: + questionYesNo (0, + i18n + ("<p>There are backup database files from previous versions " + "of KBabel. However, another version of KBabel (probably from KDE 3.1.1 or 3.1.2) " + "created a new database. As a result, your KBabel installation contains two versions " + "of database files. Unfortunatelly, the old and new version " + "can not be merged. You need to choose one of them.<br/><br/>" + "If you choose the old version, the new one will be removed. " + "If you choose the new version, the old database files will be left alone " + "and you need to remove them manually. Otherwise this message will be displayed " + "again (the old files are at $KDEHOME/share/apps/kbabeldict/dbsearchengine/*,old).</p>"), + i18n ("Old Database Found"), + i18n ("Use &Old Database"), + i18n ("Use &New Database")) == + KMessageBox::Yes) + { + // remove the new files + QFile::remove (transFile); + QFile::remove (database + "/wordsindex." + lang + + ".db"); + QFile::remove (database + "/keysindex." + lang + ".db"); + QFile::remove (database + "/catalogsinfo." + lang + + ".db"); + + // rename the old files + KIO::NetAccess::copy (KURL (transFile + ",old"), + KURL (transFile), 0); + KIO::NetAccess:: + copy (KURL + (database + "/wordsindex." + lang + + ".db,old"), + KURL (database + "/wordsindex." + lang + + ".db"), 0); + KIO::NetAccess:: + copy (KURL + (database + "/keysindex." + lang + ".db,old"), + KURL (database + "/keysindex." + lang + + ".db"), 0); + KIO::NetAccess:: + copy (KURL + (database + "/catalogsinfo." + lang + + ".db,old"), + KURL (database + "/catalogsinfo." + lang + + ".db"), 0); + + QFile::remove (transFile + ",old"); + QFile::remove (database + "/wordsindex." + lang + + ".db,old"); + QFile::remove (database + "/keysindex." + lang + + ".db,old"); + QFile::remove (database + "/catalogsinfo." + lang + + ".db,old"); + } + } + else if (oldstuff) + { + // rename the old files + KIO::NetAccess::copy (KURL (transFile + ",old"), + KURL (transFile), 0); + KIO::NetAccess:: + copy (KURL (database + "/wordsindex." + lang + ".db,old"), + KURL (database + "/wordsindex." + lang + ".db"), 0); + KIO::NetAccess:: + copy (KURL (database + "/keysindex." + lang + ".db,old"), + KURL (database + "/keysindex." + lang + ".db"), 0); + KIO::NetAccess:: + copy (KURL + (database + "/catalogsinfo." + lang + ".db,old"), + KURL (database + "/catalogsinfo." + lang + ".db"), 0); + + QFile::remove (transFile + ",old"); + QFile::remove (database + "/wordsindex." + lang + ".db,old"); + QFile::remove (database + "/keysindex." + lang + ".db,old"); + QFile::remove (database + "/catalogsinfo." + lang + + ".db,old"); + } + + dm = new DataBaseManager (database, lang, this, "Database manager"); + + if (!dm->isOk ()) + { + if (asked + || KMessageBox::questionYesNo (0, + i18n + ("Database files not found.\nDo you want to create them now?"), QString::null, i18n("Create"), i18n("Do Not Create")) + == KMessageBox::Yes) + { + //fprintf(stderr,"SI\n"); + ret = dm->createDataBase (database, lang); + } + else + ret = false; + } + else + ret = true; + } + +//Wrong errore hangdling + + if (ret) + totalRecord = dm->count (); + else + totalRecord = 0; + + return ret; +} + + +/* + Set if the research have to consider multiple spaces as a single one. + */ + +void +KDBSearchEngine::setNormalizeSpace (bool normalize) +{ + norm = normalize; +} + + +void +KDBSearchEngine::setRemoveInternalComment (bool internalcomment) +{ + comm = internalcomment; +} + +/* + Set if the research have to be Case Sensitive or not + */ + +void +KDBSearchEngine::setCaseSensitive (bool sensitive) +{ + sens = sensitive; +} + +/* + Set the a string containing all char that must be ignored + during the search. + */ + +void +KDBSearchEngine::setRemoveCharString (QString chartoremove) +{ + remchar = chartoremove; +} + +/* + Return true if there's a search in progress. + */ +bool +KDBSearchEngine::isSearching () const +{ + return searching; +} + + + + +/* + Add a search string in the list of the string to search for. + Returns the ID of the string in the list. + Returns -1 if there is a problem (may be search in progress) + */ + +int +KDBSearchEngine::addSearchString (QString searchString, int rule) +{ + if (searching || scanInProgress) + return -1; + SearchEntry e; + e.string = QString (searchString); + e.rules = rule; + searchStringList.append (e); + return searchStringList.count (); +} + + +/* + Start the research in the database of all the string in the list + + */ + +bool +KDBSearchEngine::startSearch (const QString & str, uint pluralForm, + const SearchFilter * filter) +{ + + if (autoUpdate) + { + updateSettings (); + } + + + int l1 = 0, l2 = 0; + if (defSub1) + l1 = defLimit1; + if (defSub2) + l2 = defLimit2; + + return startSingleSearch (str, l1, l2); + + +} + +bool +KDBSearchEngine::startSearchInTranslation (QString s) +{ + + if (autoUpdate) + { + updateSettings (); + } + + + int l1 = 0, l2 = 0; + if (defSub1) + l1 = defLimit1; + if (defSub2) + l2 = defLimit2; + + + return startSingleSearch (s, l1, l2, true); + +} + + +bool +KDBSearchEngine::openDb (bool noask = false) +{ + if (!dbOpened) + { + dbOpened = loadDatabase (dbname, noask); //Try first to open it now + if (!dbOpened) // Still not opened!! + { + hasError (i18n ("Cannot open the database")); + return false; + } + } + + return true; +} + + + + +bool +KDBSearchEngine::messagesForFilter (const SearchFilter * filter, + QValueList < SearchResult > &resultList, + QString & error) +{ + + int count = 0; + stopNow = false; // Remove dirty. + SearchResult m; + + if (searching) + { + error = i18n ("Another search has already been started"); + return false; + } + + if (scanInProgress) + { + error = + i18n ("Unable to search now: a PO file scan is in progress"); + return false; + } + + + if (!openDb ()) + { + error = i18n ("Unable to open the database"); + return false; + } + + if (totalRecord <= 0) + { + error = i18n ("Database empty"); + return false; + } + + QString package = filter->location (); + + int step = (totalRecord / 30) + 1; + int ntra, nref; + int req = dm->searchCatalogInfo (package); + if (req == -1) + { + error = i18n ("No entry for this package in the database."); + return false; + } + DataBaseItem item; + int i, h; + kdDebug (0) << "looking for catalog " << req << endl; + + progressStarts (i18n ("Searching for %1 in database").arg (package)); + + for (item = dm->firstItem (); !item.isNull (); item = dm->nextItem ()) + { + count++; + if (count % step == 0) + { + emit progress (100 * count / totalRecord); + kapp->processEvents (100); + } + if (stopNow) + { + stopNow = false; + searching = false; + emit finished (); + return true; // No error, stopped! + } + + ntra = item.numTra; + for (i = 0; i < ntra; i++) + { + nref = item.translations[i].numRef; + + for (h = 0; h < nref; h++) + { + if (item.translations[i].infoRef[h] == req) + { + m.found = item.key; + m.translation = item.translations[i].translation; + resultList.append (m); + } + } + } + + } + + return true; +} + +void +KDBSearchEngine::repeat () +{ + + int count = 0; + stopNow = false; // Remove dirty. + + if (searching) + { + return; + } + + if (scanInProgress) + { + return; + } + + + if (!openDb ()) + { + return; + } + + if (totalRecord <= 0) + { + return; + } + + int step = (totalRecord / 30) + 1; + int ntra, nref; + + DataBaseItem item; + int i, h, tot; + + int req = dm->searchCatalogInfo ("kdelibs.po"); + if (req == -1) + kdDebug (0) << "No kdelibs.po found!" << endl; + + + QProgressDialog *pd = + new QProgressDialog (i18n ("Looking for repetitions"), i18n ("Stop"), + 100); + + connect (this, SIGNAL (progress (int)), pd, SLOT (setProgress (int))); + connect (this, SIGNAL (finished ()), pd, SLOT (close ())); + connect (pd, SIGNAL (cancelled ()), this, SLOT (stopSearch ())); + + + QString txt = "// %1 repetitions, %2 translation(s)\ni18n(\"%3\");\n"; + QString id; + int min; + bool ok = false; + + min = + QInputDialog::getInteger (i18n ("Minimum Repetition"), + i18n + ("Insert the minimum number of repetitions for a string:"), + 2, 1, 999999, 1, &ok); + + if (!ok) + return; + + pd->show (); + + progressStarts (i18n ("Searching repeated string")); + + static QTextEdit *mle = new QTextEdit (); + mle->clear (); + + bool inlibs; + + for (item = dm->firstItem (); !item.isNull (); item = dm->nextItem ()) + { + count++; + if (count % step == 0) + { + emit progress (100 * count / totalRecord); + kapp->processEvents (100); + } + if (stopNow) + { + stopNow = false; + searching = false; + emit finished (); + return; // No error, stopped! + } + tot = 0; + inlibs = false; + ntra = item.numTra; + for (i = 0; i < ntra; i++) + { + nref = item.translations[i].numRef; + for (h = 0; h < nref; h++) + if (item.translations[i].infoRef[h] == req) + inlibs = true; + + tot += nref; + } + + if (tot >= min && !inlibs) + { + id = item.key; + id = id.replace ("\n", "\"\n\""); + mle->append (txt.arg (tot).arg (ntra).arg (id)); + + } + } + + + emit progress (100); + emit finished (); + mle->resize (400, 400); + mle->show (); + + delete pd; + return; +} + + + +bool +KDBSearchEngine::startSearchNow (int searchmode) +{ + if (searchmode == -1) + searchmode = mode; + int count = 0; + stopNow = false; // Remove dirty. + clearResults (); + + + if (searching) + { + hasError (i18n ("Another search has already been started")); + return false; + } + + if (scanInProgress) + { + hasError (i18n + ("Unable to search now: a PO file scan is in progress")); + return false; + } + + + if (!openDb ()) + return false; + + + if (totalRecord <= 0) + { + hasError (i18n ("Database empty")); + return false; + } + + + + searching = true; + + emit started (); + + bool allkey = (searchmode == MD_ALL_GOOD_KEYS); + + bool equal, contains, contained, regexp, intra; + + intra = searchmode & MD_IN_TRANSLATION; + + QString msgIdFound; + QString msgId; + QString msgStr; + //QString msgIdRequested; + SearchResult *aresult; + TranslationInfo *adescription; + SearchList searchList; + int i, len, files, h; + len = remchar.length (); + + int n, m; //,word; + QString *id; + + QString mainRequest = searchStringList[0].string; + + + SearchList::Iterator it, it1; + QString *idMod; + bool foundSomething = false; + + searchList = searchStringList; //Create a copy and modify it + if (!allkey) + { + for (it = searchList.begin (); it != searchList.end (); ++it) + { + idMod = &((*it).string); + int pos; + for (i = 0; i < len; i++) + { + while ((pos = idMod->find (remchar.at (i))) != -1) + idMod->remove (pos, 1); + } + + if (comm) + idMod->replace (QRegExp ("\\_\\:.*\\\\n"), ""); //Read it from catalog !!! (NOT ONLY HERE) + + + if (norm) + idMod->simplifyWhiteSpace (); + if (!sens) + *idMod = idMod->upper (); + } + + } + + timeval now; + gettimeofday (&now, NULL); + //fprintf(stderr,"\n%ld.%ld\n",now.tv_sec,now.tv_usec); + //double tim=1.0*now.tv_usec/1000000.0+now.tv_sec; + int pos; + + + + DataBaseItem item; + + + //Now we can browse the whole db or the "good keys" + QValueList < KeyAndScore > goodkeys; + int totalprogress; + + bool gk = (searchmode == MD_GOOD_KEYS) || allkey; + int k = 0; + + if (gk) + { + goodkeys = searchWords (mainRequest, thre, threorig, listmax); //FIX IT, mainReq? + if (stopNow) + { + stopNow = false; + searching = false; + emit finished (); + return false; + } + if (goodkeys.count () == 0) + gk = false; // if no good keys, use the whole database + } + + // prepare progress values + totalprogress = gk ? goodkeys.count () : totalRecord; + int step = (totalprogress / 30) + 1; + if( step > 100 ) + step = 100; + + emit progress (0); + kapp->processEvents (100); + if (stopNow) + { + stopNow = false; + searching = false; + emit finished (); + return true; // No error, stopped! + } + + + for (item = gk ? (dm->getItem (goodkeys[0])) : (dm->firstItem ()); + !item.isNull (); + item = gk ? (dm->getItem (goodkeys[++k])) : (dm->nextItem ())) + { + +// Emit progress, process event and check stop now + if (count % step == 0) + { + emit progress (100 * count / /*QMAX( */ + totalprogress /*,1) */ ); + kapp->processEvents (100); + + if (stopNow) + { + stopNow = false; + searching = false; + emit finished (); + return true; // No error, stopped! + } + } + + // fprintf(stderr,"%s\n",(const char *)item.key.utf8()); + msgIdFound = item.key; //Check if this is OK with UTF8 + +// searchmode && MD_IN_TRANSLATION) + + count++; + + + + msgId = msgIdFound; + + if (!allkey) + { + + //Remove character in list of character to be ignored + for (i = 0; i < len; i++) + while ((pos = msgId.find (remchar.at (i))) != -1) + msgId.remove (pos, 1); + + //Remove context information from id found + if (comm) + msgId.replace (QRegExp ("\\_\\:.*\\\\n"), ""); + + + if (norm) + msgId.simplifyWhiteSpace (); + if (!sens) + msgId = msgId.upper (); + } + + + + it = searchList.begin (); + idMod = &((*it).string); + bool foundExact = false; + + for (it1 = searchStringList.begin (); + it1 != searchStringList.end (); it1++) + { + + id = &((*it1).string); + uint nn = 0; + do + { + if (intra) + { + msgId = item.translations[nn].translation; + if (!allkey) + { + //Remove character in list of character to be ignored + for (i = 0; i < len; i++) + while ((pos = + msgId.find (remchar.at (i))) != + -1) + msgId.remove (pos, 1); + + //Remove context information from id found + if (comm) + msgId. + replace (QRegExp ("\\_\\:.*\\\\n"), + ""); + + + if (norm) + msgId.simplifyWhiteSpace (); + if (!sens) + msgId = msgId.upper (); + } + + + } + + + int rules = (*it).rules; + + if (rules & Equal) + equal = (*idMod == msgId); + else + equal = false; + + if (rules & Contains) + contains = idMod->contains (msgId); + else + contains = false; + + if (rules & Contained) + contained = msgId.contains (*idMod); + else + contained = false; + + if (!foundExact && (rules & RegExp)) + { + QRegExp reg (*idMod); + regexp = (reg.search (msgId) != -1); + } + else + regexp = false; + nn++; + } + while (intra && nn < item.numTra); + + if (equal || contains || contained || regexp || allkey) + { + + if (equal) + foundExact = true; + + m = item.numTra; //Translations found. + + for (n = 0; n < m; n++) + { + + foundSomething = true; + + + msgStr = item.translations[n].translation; + + files = item.translations[n].numRef; + + aresult = new SearchResult (); + + results.setAutoDelete (true); + if (!gk) + aresult->score = + score (mainRequest, msgIdFound); + else + aresult->score = goodkeys[k].score; + + if (intra) + aresult->score = + score (mainRequest, + item.translations[n].translation); + + + SearchResult *s = 0; + for (s = results.first (); s != 0; + s = results.next ()) + { + if (s->score > aresult->score) + { + results.insert (results.at (), + aresult); + break; + } + + } + if (s == 0) //no break or empty list + results.append (aresult); + + +/* if(*id==msgIdFound) //Put it first of the list + results.prepend(aresult); + else + results.append(aresult); +*/ + aresult->requested = *id; + aresult->found = msgIdFound; + aresult->translation = msgStr; + aresult->descriptions.setAutoDelete (true); + for (h = 0; h < files; h++) + { + + aresult->descriptions.append (adescription = + new + TranslationInfo + ()); + int rr = item.translations[n].infoRef[h]; + + InfoItem info = dm->getCatalogInfo (rr); + + + adescription->location = info.catalogName; + adescription->translator = + info.lastTranslator; + adescription->filePath = info.lastFullPath; + } + + emit numberOfResultsChanged (results.count ()); + emit resultFound (aresult); + +// if(*id==msgIdFound) //Put it first of the list so th order change + emit resultsReordered (); + + + + } + } + // idMod=searchList.next(); + it++; + idMod = &((*it).string); + } + + + } + gettimeofday (&now, NULL); + //fprintf(stderr,"%ld.%ld\n",now.tv_sec,now.tv_usec); + + //fprintf(stderr,"Finish, %d (of %d) records in %f seconds!!\n",count,totalRecord, 1.0*now.tv_usec/1000000.0+now.tv_sec-tim); + emit progress (100); + emit finished (); + + searching = false; + return true; //foundSomething; +} + +/* + Start a search for a single string + */ + +bool +KDBSearchEngine::startSingleSearch (QString searchString, + unsigned int pattern1Limit, + unsigned int /*pattern2Limit */ , + bool inTranslation) +{ + /* + Check Ret + value. + */ + + unsigned int nw = 0; + int in = 0, len = 0; + clearList (); + addSearchString (searchString, defRule); + + + + QRegExp reg ("[a-zA-Z0-9_%" /*+remchar */ + regaddchar + "]+"); + while ((in = reg.search (searchString, in + len)) != -1) + { + nw++; + len = reg.matchedLength (); + } + in = 0; + len = 0; + // fprintf(stderr,"asas %d\n",nw); + + if (mode == MD_ALL_GOOD_KEYS && !inTranslation) + return startSearchNow (); + + + + if ((nw < pattern1Limit) && (nw > 1)) + for (unsigned int k = 0; k < nw; k++) + { + in = reg.search (searchString, in + len); + len = reg.matchedLength (); + QString regToAdd = searchString; + regToAdd.replace (in, len, "[a-zA-Z0-9_%" + regaddchar + "]*"); + regToAdd.append ("$"); + regToAdd.prepend ("^"); +// fprintf(stderr,"%s",(const char *)regToAdd.local8Bit()); + addSearchString (regToAdd, RegExp); + } + + if (inTranslation) + return startSearchNow (MD_IN_TRANSLATION); + else + return startSearchNow (); + + return false; + +} + + +/* + Start a search for a list of string + */ + +//bool KDBSearchEngine::startListSearch(QPtrList<QString> searchStrList) +//{ + // searchStringList=searchStrList; +// return startSearchNow(); +//} +/* + Stop the current search + */ + + + +void +KDBSearchEngine::setLanguageCode (const QString & ll) +{ + if (ll == lang) + return; + + lang = ll; + if (dbOpened) //if opened open it again with new code, what about close before open ? + dbOpened = loadDatabase (dbname); + +} + +void +KDBSearchEngine::setLanguage (const QString & languageCode, + const QString & /*languageName */ ) +{ + setLanguageCode (languageCode); +} + +void +KDBSearchEngine::stopSearch () +{ + stopNow = true; +} + + +void +KDBSearchEngine::clearList () +{ + searchStringList.clear (); +} + +bool +KDBSearchEngine::isReady () const +{ + return IAmReady; +} + + +void +KDBSearchEngine::saveSettings (KConfigBase * config) +{ +// updateSettings(); //maybe with autoupdate + KConfigGroupSaver cgs (config, "KDBSearchEngine"); +#if KDE_IS_VERSION(3,1,3) + config->writePathEntry ("Filename", dbname); +#else + config->writeEntry ("Filename", dbname); +#endif + config->writeEntry ("Language", lang); + + + config->writeEntry ("CaseSensitive", sens); + config->writeEntry ("Normalize", norm); + config->writeEntry ("RemoveContext", comm); + + config->writeEntry ("Rules", defRule); + config->writeEntry ("Limit1", defLimit1); + config->writeEntry ("Limit2", defLimit2); + config->writeEntry ("Substitution1", defSub1); + config->writeEntry ("Substitution2", defSub2); + + config->writeEntry ("RegExp", regaddchar); + config->writeEntry ("RemoveCharacter", remchar); + + config->writeEntry ("Threshold1", thre); + config->writeEntry ("Threshold2", threorig); + config->writeEntry ("ListMax", listmax); + config->writeEntry ("Mode", mode); + config->writeEntry ("CommonThrs", commonthre); + config->writeEntry ("ReturnNothing", retnot); + + config->writeEntry ("AutoAuthor", autoauthor); + config->writeEntry ("AutoUp", autoup); + +} + + +void +KDBSearchEngine::readSettings (KConfigBase * config) +{ + QString newName; + + KConfigGroupSaver cgs (config, "KDBSearchEngine"); + + QString defaultLang; + QString oldLang = lang; + Defaults::Identity def; + defaultLang = def.languageCode (); + lang = config->readEntry ("Language", defaultLang); + + QString defaultDir; + KStandardDirs *dirs = KGlobal::dirs (); + if (dirs) + { + defaultDir = dirs->saveLocation ("data"); + if (defaultDir.right (1) != "/") + defaultDir += "/"; + defaultDir += "kbabeldict/dbsearchengine"; + } + + newName = config->readPathEntry ("Filename", defaultDir); + + if (newName != dbname || oldLang != lang) + { + dbname = newName; + if (dbOpened) //Reload only if it is opened + dbOpened = loadDatabase (dbname); + } + + sens = config->readBoolEntry ("CaseSensitive", false); + norm = config->readBoolEntry ("Normalize", true); + comm = config->readBoolEntry ("RemoveContext", true); + + defRule = config->readNumEntry ("Rules", 1); + defLimit1 = config->readNumEntry ("Limit1", 20); + defLimit2 = config->readNumEntry ("Limit2", 8); + + thre = config->readNumEntry ("Threshold1", 50); + threorig = config->readNumEntry ("Threshold2", 50); + listmax = config->readNumEntry ("ListMax", 500); + mode = config->readNumEntry ("Mode", MD_GOOD_KEYS); + + defSub1 = config->readBoolEntry ("Substitution1", true); + defSub2 = config->readBoolEntry ("Substitution2", false); + + regaddchar = config->readEntry ("RegExp"); + remchar = config->readEntry ("RemoveCharacter", "&.:"); + commonthre = config->readNumEntry ("CommonThrs", 300); + retnot = config->readBoolEntry ("ReturnNothing", false); + autoauthor = config->readEntry ("AutoAuthor"); + autoup = config->readBoolEntry ("AutoUp", true); + + setSettings (); +} + +PrefWidget * +KDBSearchEngine::preferencesWidget (QWidget * parent) +{ + + pw = new PreferencesWidget (parent); + setSettings (); + connect (pw, SIGNAL (restoreNow ()), this, SLOT (setSettings ())); + connect (pw, SIGNAL (applyNow ()), this, SLOT (updateSettings ())); + connect (pw, SIGNAL (destroyed ()), this, SLOT (prefDestr ())); + connect (pw->dbpw->scanPB_2, SIGNAL (clicked ()), this, SLOT (scan ())); + connect (pw->dbpw->scanrecPB, SIGNAL (clicked ()), this, + SLOT (scanRecur ())); + connect (pw->dbpw->scanFilePB, SIGNAL (clicked ()), this, + SLOT (scanFile ())); + connect (pw->dbpw->repeatPB, SIGNAL (clicked ()), this, SLOT (repeat ())); + + + return pw; +} + +void +KDBSearchEngine::scanRecur () +{ + if (scanInProgress) + return; + updateSettings (); + + if (!openDb ()) + return; + scanInProgress = true; + PoScanner *sca = new PoScanner (dm, this, "Po Scanner"); + QString cvsdir; + cvsdir = + KFileDialog::getExistingDirectory ("", 0, + i18n + ("Select Folder to Scan Recursively")); + + if (cvsdir.isEmpty ()) + { + scanInProgress = false; + return; + } + if (pw) + { + connect (sca, SIGNAL (patternProgress (int)), pw->dbpw->totalPB, + SLOT (setProgress (int))); + connect (sca, SIGNAL (fileLoading (int)), pw->dbpw->loadingPB, + SLOT (setProgress (int))); + connect (sca, SIGNAL (fileProgress (int)), pw->dbpw->processPB, + SLOT (setProgress (int))); + } + + connect (sca, SIGNAL (patternProgress (int)), SIGNAL (progress (int))); //Kbabel progress bar + + connect (sca, SIGNAL (added (int)), pw, SLOT (setEntries (int))); + connect (sca, SIGNAL (filename (QString)), pw, SLOT (setName (QString))); + + + progressStarts (i18n ("Scanning folder %1").arg (cvsdir)); + connect (sca, SIGNAL (patternFinished ()), SIGNAL (progressEnds ())); + + sca->scanPattern (cvsdir, "*.po", true); + disconnect (this, SIGNAL (progress (int))); +//disconnect(SIGNAL(patternStarted()),this,SIGNAL(started()) ); + disconnect (this, SIGNAL (progressEnds ())); + if (pw) + { + disconnect (pw->dbpw->totalPB, SLOT (setProgress (int))); + disconnect (pw->dbpw->loadingPB, SLOT (setProgress (int))); + disconnect (pw->dbpw->processPB, SLOT (setProgress (int))); + } + totalRecord = dm->count (); + + scanInProgress = false; + dm->sync (); + delete sca; +} + + +void +KDBSearchEngine::scan () +{ + if (scanInProgress) + return; + updateSettings (); + + if (!openDb ()) + return; + scanInProgress = true; + PoScanner *sca = new PoScanner (dm, this, "Po Scanner"); + QString cvsdir; + + cvsdir = + KFileDialog::getExistingDirectory ("", 0, + i18n ("Select Folder to Scan")); + if (cvsdir.isEmpty ()) + { + scanInProgress = false; + return; + } + if (pw) + { + connect (sca, SIGNAL (patternProgress (int)), pw->dbpw->totalPB, + SLOT (setProgress (int))); + connect (sca, SIGNAL (fileLoading (int)), pw->dbpw->loadingPB, + SLOT (setProgress (int))); + connect (sca, SIGNAL (fileProgress (int)), pw->dbpw->processPB, + SLOT (setProgress (int))); + } + connect (sca, SIGNAL (patternProgress (int)), SIGNAL (progress (int))); + progressStarts (i18n ("Scanning folder %1").arg (cvsdir)); + connect (sca, SIGNAL (patternFinished ()), SIGNAL (progressEnds ())); + + connect (sca, SIGNAL (added (int)), pw, SLOT (setEntries (int))); + connect (sca, SIGNAL (filename (QString)), pw, SLOT (setName (QString))); + + + + sca->scanPattern (cvsdir, "*.po", false); + + disconnect (this, SIGNAL (progress (int))); +//disconnect(SIGNAL(patternStarted()),this,SIGNAL(started()) ); + disconnect (this, SIGNAL (progressEnds ())); + if (pw) + { + disconnect (pw->dbpw->totalPB, SLOT (setProgress (int))); + disconnect (pw->dbpw->loadingPB, SLOT (setProgress (int))); + disconnect (pw->dbpw->processPB, SLOT (setProgress (int))); + } + totalRecord = dm->count (); + + scanInProgress = false; + + dm->sync (); + delete sca; +} + +void +KDBSearchEngine::scanFile () +{ + if (scanInProgress) + return; + updateSettings (); + + if (!openDb ()) + return; + scanInProgress = true; + PoScanner *sca = new PoScanner (dm, this, "Po Scanner"); + QString cvsdir; + pw->dbpw->totalPB->setProgress (0); + + cvsdir = + KFileDialog::getOpenFileName ("", "*.po", 0, + i18n ("Select PO File to Scan")); + if (cvsdir.isEmpty ()) + { + scanInProgress = false; + return; + } + if (pw) + { + connect (sca, SIGNAL (fileLoading (int)), pw->dbpw->loadingPB, + SLOT (setProgress (int))); + connect (sca, SIGNAL (fileProgress (int)), pw->dbpw->processPB, + SLOT (setProgress (int))); + } + connect (sca, SIGNAL (fileProgress (int)), SIGNAL (progress (int))); + progressStarts (i18n ("Scanning file %1").arg (directory (cvsdir, 0))); + connect (sca, SIGNAL (fileFinished ()), SIGNAL (progressEnds ())); + + connect (sca, SIGNAL (added (int)), pw, SLOT (setEntries (int))); + connect (sca, SIGNAL (filename (QString)), pw, SLOT (setName (QString))); + + + + sca->scanFile (cvsdir); + + sca->disconnect (SIGNAL (fileProgress (int)), this, + SIGNAL (progress (int))); +//disconnect(SIGNAL(patternStarted()),this,SIGNAL(started()) ); + sca->disconnect (SIGNAL (fileFinished ()), this, + SIGNAL (progressEnds ())); + if (pw) + { + disconnect (pw->dbpw->loadingPB, SLOT (setProgress (int))); + disconnect (pw->dbpw->processPB, SLOT (setProgress (int))); + } + + totalRecord = dm->count (); + + scanInProgress = false; + + dm->sync (); + delete sca; +} + +const KAboutData * +KDBSearchEngine::about () const +{ + + return DbSeFactory::instance ()->aboutData (); + +} + +QString +KDBSearchEngine::name () const +{ + return i18n ("Translation Database"); +} + +QString +KDBSearchEngine::id () const +{ + return QString ("KDBSearchEngine"); +} + +QString +KDBSearchEngine::lastError () +{ + return lasterror; +} + +void +KDBSearchEngine::prefDestr () +{ + pw = 0; +} + + +void +KDBSearchEngine::setSettings () +{ + + if (pw == 0) + return; + + pw->dbpw->dirInput->setURL (dbname); + pw->dbpw->caseSensitiveCB->setChecked (sens); + pw->dbpw->normalizeCB->setChecked (norm); + pw->dbpw->removeContextCB->setChecked (comm); + + pw->dbpw->oneWordSubCB->setChecked (defSub1); + pw->dbpw->twoWordSubCB->setChecked (defSub2); + + + if (defRule == 8) + pw->dbpw->RegExpRB->setChecked (true); + else + { + pw->dbpw->normalTextRB->setChecked (true); + pw->dbpw->equalCB->setChecked (defRule & Equal); + pw->dbpw->containsCB->setChecked (defRule & Contains); + pw->dbpw->containedCB->setChecked (defRule & Contained); + } + + pw->dbpw->oneWordSubSB->setValue (defLimit1); + pw->dbpw->twoWordSubSB->setValue (defLimit2); + + pw->dbpw->maxSB->setValue (listmax); + pw->dbpw->thresholdSL->setValue (thre); + pw->dbpw->thresholdOrigSL->setValue (threorig); + + pw->dbpw->allRB->setChecked (mode == MD_ALL_DB); + pw->dbpw->slistRB->setChecked (mode == MD_GOOD_KEYS); + pw->dbpw->rlistRB->setChecked (mode == MD_ALL_GOOD_KEYS); + + pw->dbpw->nothingCB->setChecked (retnot); + pw->dbpw->freqSB->setValue (commonthre); + + pw->dbpw->regExpLE->setText (regaddchar); + pw->dbpw->ignoreLE->setText (remchar); + + pw->dbpw->authorLE->setText (autoauthor); + pw->dbpw->autoAddCB_2->setChecked (autoup); + + + +} + + +void +KDBSearchEngine::updateSettings () +{ + if (pw == 0) + return; + + QString newName = pw->dbpw->dirInput->url (); + + if (newName != dbname) + { + kdDebug (0) << "Database changed" << endl; + dbname = newName; + if (dbOpened) + dbOpened = loadDatabase (dbname); + } + + sens = pw->dbpw->caseSensitiveCB->isChecked (); + norm = pw->dbpw->normalizeCB->isChecked (); + comm = pw->dbpw->removeContextCB->isChecked (); + + int tmpRule = 0; + if (pw->dbpw->RegExpRB->isChecked ()) + tmpRule = RegExp; + else + { + if (pw->dbpw->equalCB->isChecked ()) + tmpRule += Equal; + if (pw->dbpw->containsCB->isChecked ()) + tmpRule += Contains; + if (pw->dbpw->containedCB->isChecked ()) + tmpRule += Contained; + } + + defRule = tmpRule; + + defLimit1 = pw->dbpw->oneWordSubSB->text ().toInt (); + defLimit2 = pw->dbpw->twoWordSubSB->text ().toInt (); + defSub1 = pw->dbpw->oneWordSubCB->isChecked (); + defSub2 = pw->dbpw->twoWordSubCB->isChecked (); + + listmax = pw->dbpw->maxSB->value (); + thre = pw->dbpw->thresholdSL->value (); + threorig = pw->dbpw->thresholdOrigSL->value (); + + if (pw->dbpw->allRB->isChecked ()) + mode = MD_ALL_DB; + if (pw->dbpw->slistRB->isChecked ()) + mode = MD_GOOD_KEYS; + if (pw->dbpw->rlistRB->isChecked ()) + mode = MD_ALL_GOOD_KEYS; + + + regaddchar = pw->dbpw->regExpLE->text (); + remchar = pw->dbpw->ignoreLE->text (); + + retnot = pw->dbpw->nothingCB->isChecked (); + commonthre = pw->dbpw->freqSB->value (); + + autoauthor = pw->dbpw->authorLE->text (); + autoup = pw->dbpw->autoAddCB_2->isChecked (); + + +} + +void +KDBSearchEngine::setLastError (const QString & er) +{ + lasterror = er; +} + +QString +KDBSearchEngine::translate (const QString & text, const uint pluralForm) +{ + if (!openDb ()) + return QString::null; +/* + +if(!dbOpened) + { + dbOpened=loadDatabase(dbname); //Try first to open it now + if(!dbOpened) // Still not opened!! + { + //emit anerror + hasError(i18n("Database not opened")); + return QString::null; + } + } +*/ + + DataBaseItem dbit = dm->getItem (text); + + if (dbit.isNull ()) + return QString::null; + if (dbit.numTra == 1) + return dbit.translations[0].translation; + + uint32 n = dbit.numTra; + uint32 max = 0, nmax = 0; + for (uint32 i = 0; i < n; i++) + if (dbit.translations[i].numRef > max) + { + nmax = i; + max = dbit.translations[i].numRef; + } + + return dbit.translations[nmax].translation; + + +} + +QValueList < KeyAndScore > KDBSearchEngine::searchWords (QString phrase, + int threshold, + int thresholdorig, + uint32 max) +{ + QValueList < QString > wordlist; + + if (!openDb ()) + { + QValueList < KeyAndScore > a; + return a; + } + + progressStarts (i18n ("Searching words")); + + QValueList < QString >::Iterator wlit; + wordlist = dm->wordsIn (phrase); + int + nw = wordlist.count (); +//QMemArray<WordItem> wi(nw); + QMemArray < uint32 > numofloc (nw), currentloc (nw); + QMemArray < int > + score (nw); + QMemArray < uint32 * >loc (nw), locorig (nw); + QValueList < uint32 > resloc; + QValueList < int > + resfound; + QValueList < KeyAndScore > keylist; +//wi.resize(wordlist.count()); + int + totalprogress = 0; + int + totrec = dm->count (); + uint32 + cthre = totrec * commonthre / 10000; + int + i = 0, common = 0; + for (wlit = wordlist.begin (); wlit != wordlist.end (); ++wlit) + { + WordItem + wi = dm->getWordLocations (*wlit); + if (!wi.notFound ()) + { + if (wi.count < cthre) + score[i] = 1; + else + { + score[i] = 0; + common++; + } + + locorig[i] = loc[i] = wi.locations; + totalprogress += numofloc[i] = wi.count; + currentloc[i] = 0; +// score[i]=wi.score; + //wi[i]=WordItem(wi[i]); + //wi[i].locations.detach(); + i++; +// } + // else + // common++; + + + + } + } + bool + cs = (common == nw); //All words are common; + if (totalprogress == 0) + totalprogress = 1; + int + step = totalprogress / 30 + 1; + int + count = 0; + int + thrs = (wordlist.count () * threshold) / 100; + if (thrs < 1) + thrs = 1; // whole database ??? + + int + tot = i; +//nt32 jmin=0; + int + found; + uint32 + min; //Big ? + bool + empty = false; + + + while (!empty) + { + + empty = true; + found = retnot ? common : 0; + if (thrs <= found) + thrs = found + 1; // whole database ??? + + min = BIGNUMBER; + for (int j = 0; j < tot; j++) + if (cs || score[j]) + { + if (numofloc[j] > currentloc[j]) // Check if there's still something to do. + empty = false; + if (loc[j][0] < min) //Found the minimum head + min = loc[j][0]; + + + } + if (min != BIGNUMBER) + { + for (int j = 0; j < tot; j++) + if (cs || score[j]) + { + if (loc[j][0] == min) //Count the heads, move forward + { + found++; + count++; + //check stopnow here + if (count % step == 0) + { + emit + progress (100 * count / totalprogress); + kapp->processEvents (100); + } + if (stopNow) + { + return keylist; + } + + currentloc[j]++; + if (numofloc[j] == currentloc[j]) //End reached + loc[j][0] = BIGNUMBER; //so set head to a big number + else //Go on.. + { + loc[j]++; + } + } + } //end of for + bool + inserted = false; + + + + if (found >= thrs) + { + //Words count in key. + int + nword = 0; + + int + in = 0, len = 0; + QString + keyst = dm->getKey (min); + QRegExp + reg ("[a-zA-Z0-9_%" /*+remchar */ + regaddchar + "]+"); + while ((in = reg.search (keyst, in + len)) != -1) + { + nword++; + len = reg.matchedLength (); + } + + if (found >= nword * thresholdorig / 100) // + { + + if (resfound.count () <= max + || (*resfound.end () < found)) + if ((*resfound.end ()) >= found) + { + inserted = true; + resloc.append (min); + resfound.append (found); + + } + else + for (uint32 j = 0; j < resloc.count (); + j++) + { + if (resfound[j] < found || (resfound[j] == found && 0)) //Orig word + { + resloc.insert (resloc.at (j), + min); + resfound.insert (resfound. + at (j), + found); + inserted = true; + break; + } + } + if (!inserted) + { + resloc.append (min); + resfound.append (found); + } + + } + } + + } + + } + int + nres = (resloc.count () < max) ? resloc.count () : max; + + for (int j = 0; j < nres; j++) + { + QString + strkey = dm->getKey (resloc[j]); + int + stdscore = KDBSearchEngine::score (phrase, strkey); + int + sc = 0; + + if (stdscore < 99) + { + int + in = 0, len = 0, nword = 0; + int + remove = retnot ? common : 0; + QRegExp + reg ("[a-zA-Z0-9_%" /*+remchar */ + regaddchar + "]+"); + while ((in = reg.search (strkey, in + len)) != -1) + { + nword++; + len = reg.matchedLength (); + } + +// kdDebug(0) << nword << "NWORD " << resfound[j] << "FOUND " +// << resfound[j]-remove << "REAL " << remove << "to be remove " << endl; + if (nword < 1) + nword = 1; + sc = 70 - resfound[j] * 70 / nw + abs (nword - + (resfound[j] - + remove)) * 30 / + nword + 2; + sc = 100 - sc; +// kdDebug(0) <<" Score : " << sc << endl; + + } + else + sc = stdscore; + + KeyAndScore + key (strkey, sc); + +// kdDebug(0) << (QString) key << " [" << key.score << "]" << endl; + keylist.append (key); + } + +//kdDebug(0) << "Here!" << endl; + + for (int j = 0; j < tot; j++) + { + free (locorig[j]); + } + progressStarts (i18n ("Process output")); + return keylist; +} + +void +KDBSearchEngine::stringChanged (const QStringList & o, + const QString & translated, const uint, + const QString &) +{ + + QString orig = o.first (); // FIXME: plural forms + + // skip empty originals or translated texts + if (orig.isEmpty () || translated.isEmpty ()) + return; + + if (autoup) + { + if (openDb (true)) //true= no ask + { + + dm->putNewTranslation (orig, translated, + dm->catalogRef (directory (edited, 0), + autoauthor, edited)); + //kdDebug(0) << "Changed " << orig << " " << translated << endl; + dm->sync (); + } + } + +} + +void +KDBSearchEngine::setEditedFile (const QString & file) +{ + + edited = file; //kdDebug(0) << edited << endl; +} + +KeyAndScore::KeyAndScore (const QString & a, int sc): +QString (a) +{ + score = sc; +} + +KeyAndScore::KeyAndScore ():QString () +{ + score = 0; +} + +#include "KDBSearchEngine.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.h b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.h new file mode 100644 index 00000000..058444db --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.h @@ -0,0 +1,333 @@ + +/*************************************************************************** + KDBSearchEngine.h - description + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + email : rizzi@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + * In addition, as a special exception, the copyright holders give * + * permission to link the code of this program with any edition of * + * the Qt library by Trolltech AS, Norway (or with modified versions * + * of Qt that use the same license as Qt), 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 * + * Qt. 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. * + ***************************************************************************/ +/* + Translation search engine + + + Copyright 2000 + Andrea Rizzi rizzi@kde.org + +*/ + + +/* + * This is a database engine specific + * structure, I think I must found a way to + * make it more "standard" + */ + +#ifndef _KDBSEARCH_ENGINE_ +#define _KDBSEARCH_ENGINE_ +#include <qobject.h> +#include <qptrlist.h> +#include <qstring.h> +#include <qmemarray.h> +#include <qvaluelist.h> + + +#include "database.h" +#include "searchengine.h" +#include "preferenceswidget.h" + + +//value of mode +#define MD_ALL_DB 1 +#define MD_GOOD_KEYS 2 +#define MD_ALL_GOOD_KEYS 3 +#define MD_IN_TRANSLATION 4 + +class SearchEntry +{ + public: + QString string; + int rules; +}; + +class KeyAndScore : public QString +{ + public: + KeyAndScore(); + KeyAndScore(const QString &a,int sc); + int score; +}; + +typedef QValueList<SearchEntry> SearchList; + +/* USE searchengine.h structure +class CatalogDescription +{ + public: + char language[6]; // How many character chinese language needs? + // QString is better ? + QString filename; + QString dateOfScan; //When you add this to database (last time) + QString authorOfScan; + QString fileHeader; //msgid "" +}; + + */ + +class KDBSearchEngine : public SearchEngine +{ + Q_OBJECT + +public: + + + KDBSearchEngine(QObject *parent=0,const char *name=0); + ~KDBSearchEngine(); + enum Rules {Equal = 1, Contains = 2, Contained = 4, RegExp = 8}; + enum FormatRules { Dots = 1, Ampersand = 2, FirstWordUpper = 4, //Not yet used + AllWordUpper = 8, AmpersanAlwaysFirst = 16 }; + + /* + Set the directory where db file are located + */ + + void setDBName(QString filename); + + /* + Set if the research have to consider multiple spaces as a single one. + */ + + void setNormalizeSpace(bool normalize); + + /* + Set if the research have to be Case Sensitive or not + */ + + void setCaseSensitive(bool sensitive); + + + /* + ignore ":_ bla bla \n" in msgid + + */ + + void setRemoveInternalComment(bool internalcomment); + + /* + Set the a string containing all char that must be ignored + during the search. + */ + + + void setRemoveCharString(QString chartoremove); + + /* + Enable an output filter that format Uppercase/lowercase + method could be; + 0 = Disabled; + 1 = English pattern; + 2 = Only first; + */ + + void enableCapitalFilter(int method); + + /* + Enable an output filter that format special characters + method could be; + 0 = Disabled; + 1 = Put ... at the end if needed (remove if present but no needed); + 2 = Put an accelerator (or remove); + 4 = Remove %* if not present in msgid. + 8 = Change %d,%s etc with %1 %2 etc if needed. + */ + + void enableCharFilter(int method); + + /* + Sets the rules to decide when 2 string match (Uppercase and remove char + are not set here) + 1 = EQUAL + 2 = SEARCH STRING IS CONTAINED IN DATABASE STRING (use with care, if you search nothing + it will produce a dangerouse output) + 4 = DATABASE STRING IS CONTAINED IN SEARCH STRING (it exclude msgid "") + 8 = String is a regexp. (exclude 1 2 4) + */ + + void setMatchingRules(int rules); + + /* + Search Engine methods reimplemented + */ + + + + virtual bool messagesForFilter(const SearchFilter* filter + , QValueList<SearchResult>& resultList, QString& error); + + + virtual void setLanguageCode(const QString& lang); + virtual void setLanguage(const QString& languageCode, const QString& languageName); + + virtual void setEditedFile(const QString& file); + + virtual bool isReady() const ; + virtual bool isSearching() const; + + virtual void saveSettings(KConfigBase *config); + virtual void readSettings(KConfigBase *config); + + virtual PrefWidget *preferencesWidget(QWidget *parent); + + virtual const KAboutData *about() const; + + virtual QString name() const; + + virtual QString id() const; + + virtual QString lastError(); + + virtual QString translate(const QString& text, uint pluralForm); + + virtual void stringChanged( const QStringList& orig, const QString& translated + , const uint translationPluralForm, const QString& description); + + +public slots: + + void scan(); + void scanRecur(); + void scanFile(); + /* + Add a search string in the list of the string to search for. + Returns the ID of the string in the list. + Returns -1 if there is a problem (may be search in + progress) + */ + + int addSearchString(QString searchString, int rule=Equal); + + /* + Start the research in the database of all the string in the list + search mode -1 means use global mode; + */ + bool startSearchNow(int searchmode=-1); + + /* + Start a search for a single string + If the number of word of your string is less than patternXlimit + the KDBSearchEngine will search for all string with X * substituted to + X word. + For example if pattern1limit is 4 and you search "My name is Andrea" + This string will also match with: + "Your name is Andrea", "My dog is Andrea", "My name was Andrea", "My name is Joe" + + Do not set pattern2limit too high. + + If a patternlimit is > 0 rules 8 (* means any word) is added. + + */ + + bool startSingleSearch(QString searchString,unsigned int pattern1Limit,unsigned int pattern2Limit, + bool inTranslation=false); + + /* + Start a search for a list of string + */ + +// bool startListSearch(QPtrList<QString> searchStrList); + +/* + * Return a list of key in database that contains some + * words of the given string phrase. + * thresholdin is a number from 0 to 100 a key is good + * if at least the threshold% of words are found + * thresholdout a key is good if the found words represnt + * at least the thresholdorig% of the words in the key + * max is the maximum number of results + */ + +QValueList<KeyAndScore> searchWords(QString phrase,int threshold, + int thresholdorig ,uint32 max); + + + /* + Stop the current search + */ + + virtual void stopSearch(); + virtual bool startSearch(const QString& text, uint pluralForm, const SearchFilter* filter); + virtual bool startSearchInTranslation(QString s); + + void clearList(); +signals: + void found(SearchResult *); +private slots: + void updateSettings(); //Use widget settings + void setSettings(); //Fill widget with actual settings + void prefDestr(); + void setLastError(const QString&); + void repeat(); +private: + /* + Reload database info (and keep the dbase opened). + */ + bool loadDatabase(QString database,bool); + + bool openDb(bool); + + PreferencesWidget *pw; + bool IAmReady; + int methodFilterChar; + int methodFilterCapital; + int defRule; + int defLimit1; + int defLimit2; + int thre; + int threorig; + int commonthre; + int listmax; + int mode; + bool retnot; + bool defSub1; + bool defSub2; + bool stopNow; + bool searching; + bool norm,sens,comm; + int numofresult; + char * filename; + QString remchar; + QString regaddchar; + QString dbname; + bool dbOpened; +// GDBM_FILE db; + DataBaseManager * dm; +// datum key, value; +// QMemArray<CatalogDescription *> catinfo; + SearchList searchStringList; + int totalRecord; + QString lasterror; + QString lang; + bool scanInProgress; + QString edited; + bool autoup; + QString autoauthor; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine/Makefile.am b/kbabel/kbabeldict/modules/dbsearchengine/Makefile.am new file mode 100644 index 00000000..8504999a --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/Makefile.am @@ -0,0 +1,34 @@ +## Makefile.am for DBSE + +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +#SUBDIRS = + + +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +kde_module_LTLIBRARIES = kbabeldict_dbsearchengine.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes) $(DBIV_INCLUDES) + +# which sources should be compiled for kbabel +kbabeldict_dbsearchengine_la_SOURCES = KDBSearchEngine.cpp preferenceswidget.cpp \ + dbse_factory.cpp dbseprefwidget.ui database.cpp dbscan.cpp +#database.cpp dbscan.cpp +kbabeldict_dbsearchengine_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO) $(LIB_DBIV) +kbabeldict_dbsearchengine_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined \ + $(DBIV_LDFLAGS) + + +# these are the headers for your project +noinst_HEADERS = KDBSearchEngine.h preferenceswidget.h dbse_factory.h \ + database.h dbscan.h + + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +kde_services_DATA = dbsearchengine.desktop +EXTRA_DIST = $(kde_services_DATA) + diff --git a/kbabel/kbabeldict/modules/dbsearchengine/STRUCTURE b/kbabel/kbabeldict/modules/dbsearchengine/STRUCTURE new file mode 100644 index 00000000..0a53a0fe --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/STRUCTURE @@ -0,0 +1,25 @@ + + +key = original text + +data + 0..3 num of translation (n) + + translations + 0..3 num of file references (m) + 4..(4+m*4) file references + 4+m*4..first\0 translation + + +---------------------------------------------------- +Files structure. + + +"it" is the language + +catalogsinfo.it.db //Info about the catalog +keysindex.it.db //index of numofkeys->key +translations.it.db //guess.. (key->translation) +wordsindex.it.db //index of word->numofkey + + diff --git a/kbabel/kbabeldict/modules/dbsearchengine/TODO b/kbabel/kbabeldict/modules/dbsearchengine/TODO new file mode 100644 index 00000000..0e7fbd3a --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/TODO @@ -0,0 +1,27 @@ +TODO List fore KDE Database Translation Search Engine + +-Finish the port (use settings) done +-Improve settings (filter output) +-Database handling (and creation...) Done +-output filters +-fix fix fix... + +-delete item if putItem(nullitem) +-use matthias mask function for regexp +-remove bug of word split F&ormat is F ormat <- add remchar to charregexp + + +Major rewrite: +-New settings interface. +-addFunction from dbscan to database Done ? +-Edit function +-database manager +-download compendium from the internet + +Matthias ask: +- searching in translations, equivalent to searching in msgids (SearchEngine::startTranslationSearch(QString s) ) +- the absolute path of the files and maybe the number of the entry in the file ( maybe I will add this information to the TranslationInfo ) +- the possibility to get a list of all entries in a po file from the database. For this, I think, I will create a interface and send it to you. Maybe something like this: class TranslationDatabase { +public: // name is something like "kbabel.po" QList<CatalogItem> entriesOfFile(QString name); } + + diff --git a/kbabel/kbabeldict/modules/dbsearchengine/configure.in.bot b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.bot new file mode 100644 index 00000000..58d6118f --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.bot @@ -0,0 +1,5 @@ +if test "x$with_berkeley_db" = xcheck && test -z "$LIB_DBIV"; then + echo "" + echo "Dictionary plugin \"Translation Database\" for KBabel will not be built! Please install Berkeley Database IV. See http://www.sleepycat.com for more information.)" + echo "" +fi diff --git a/kbabel/kbabeldict/modules/dbsearchengine/configure.in.in b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.in new file mode 100644 index 00000000..fbc3f1a8 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.in @@ -0,0 +1,143 @@ +AC_ARG_WITH(berkeley-db, + [AC_HELP_STRING(--with-berkeley-db, + [enable the dictionary plugin based on Berkeley DB IV @<:@default=check@:>@])], + [], with_berkeley_db=check) + +LIB_DBIV="" +if test "x$with_berkeley_db" != xno; then + +AC_MSG_CHECKING([for Berkeley Database IV]) + +db_libraries="" +db_includes="" +db_name="" +ac_db_name="db" +ac_db_includes="" +ac_db_libraries="" +ac_db_include_file="db.h" + +AC_ARG_WITH(db-dir, + AC_HELP_STRING([--with-db-dir=DIR],[where the root of Berkeley DB IV is installed]), + [ ac_db_includes=-I"$withval"/include + ac_db_libraries=-L"$withval"/lib + ]) +AC_ARG_WITH(db-include-dir, + AC_HELP_STRING([--with-db-include-dir=DIR],[where the includes of Berkeley DB IV are installed]), + [ ac_db_includes=-I"$withval" + ]) +AC_ARG_WITH(db-include, + AC_HELP_STRING([--with-db-include=FILE],[path to the Berkeley DB IV header file]), + [ ac_db_include_file=-I"$withval" + ]) +AC_ARG_WITH(db-lib-dir, + AC_HELP_STRING([--with-db-lib-dir=DIR],[where the libs of Berkeley DB IV are installed]), + [ ac_db_libraries=-L"$withval" + ]) +AC_ARG_WITH(db-name, + AC_HELP_STRING([--with-db-name=NAME],[name of the Berkeley DB IV library (default db)]), + [ ac_db_name="$withval" + ]) + +AC_DEFUN([KDE_CHECK_DB_VERSION], +[ +ifelse($3,,,[LIBS="$kde_db_safe -l$3"]) +AC_TRY_LINK([ +#include <$2> +], +[ +#if DB_VERSION_MAJOR == 4 +DB *db; +#if DB_VERSION_MINOR > 0 +db->open( db, NULL, "test.db", NULL, DB_BTREE, DB_CREATE, 0644 ); +#else +db->open( db, "test.db", NULL, DB_BTREE, DB_CREATE, 0644 ); +#endif +#else +error +#endif +], +kde_cv_berk_database=$1 +) +]) + +AC_CACHE_VAL(kde_cv_berk_database, +[ +kde_safe_LDFLAGS=$LDFLAGS +kde_db_safe_LIBS=$LIBS +LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $all_libraries $ac_db_libraries $all_includes $ac_db_includes" + +kde_cv_berk_database=NO +if test "xNO" = "x$kde_cv_berk_database" ; then + KDE_CHECK_DB_VERSION($ac_db_name, $ac_db_include_file, $ac_db_name) +fi +if test "xNO" = "x$kde_cv_berk_database" ; then + KDE_CHECK_DB_VERSION(db4, db4/db.h, db4) +fi +if test "xNO" = "x$kde_cv_berk_database" ; then + KDE_CHECK_DB_VERSION(db4-db, db.h, db4) +fi +if test "xNO" = "x$kde_cv_berk_database" ; then + KDE_CHECK_DB_VERSION(db, db.h, db) +fi + +LIBS=$kde_db_safe_LIBS +LDFLAGS=$kde_safe_LDFLAGS + +]) + +kde_db_header="" +DBSEARCHENGINE=dbsearchengine + +case "$kde_cv_berk_database" in + NO) + AC_MSG_RESULT(no) + LIB_DBIV="" + DBSEARCHENGINE="" + ;; + db) + LIB_DBIV="-l$ac_db_name" + kde_db_header=db.h + AC_MSG_RESULT(-l$ac_db_name) + AC_DEFINE_UNQUOTED(HAVE_DB_DB_H, 1, [DB 4 header location] ) + ;; + db4-db) + LIB_DBIV='-ldb4' + kde_db_header=db.h + AC_MSG_RESULT("flag is -ldb4 and header is db.h") + AC_DEFINE_UNQUOTED(HAVE_DB_DB_H, 1, [DB 4 header location] ) + ;; + db4) + LIB_DBIV='-ldb4' + kde_db_header=db4/db.h + AC_MSG_RESULT(-ldb4) + AC_DEFINE_UNQUOTED(HAVE_DB4_DB_H, 1, [DB 4 header location] ) + ;; + $ac_db_name) + LIB_DBIV="-l$ac_db_name" + kde_db_header="$ac_db_include_file" + AC_MSG_RESULT(user specified $ac_db_name) + if test "x$ac_db_include_file" = "xdb.h" ; then + AC_DEFINE_UNQUOTED(HAVE_DB_DB_H, 1, [DB 4 header location] ) + else + AC_DEFINE_UNQUOTED(USE_DB_H_PATH, <$ac_db_include_file>, [DB 4 header path]) + fi + + ;; +esac + +DBIV_LDFLAGS="$ac_db_libraries" +DBIV_INCLUDES="$ac_db_includes" +DBIV_NAME="$ac_db_name" + +if test "x$with_berkeley_db" != xcheck && test -z "$LIB_DBIV"; then + AC_MSG_ERROR([--with-berkeley-db was given, but test for Berkeley DB IV failed]) +fi +fi + +AC_SUBST(DBIV_INCLUDES) +AC_SUBST(DBIV_LDFLAGS) +AC_SUBST(DBIV_NAME) + +AC_SUBST(LIB_DBIV) + +AM_CONDITIONAL(include_DBSEARCHENGINE, test -n "$DBSEARCHENGINE") diff --git a/kbabel/kbabeldict/modules/dbsearchengine/database.cpp b/kbabel/kbabeldict/modules/dbsearchengine/database.cpp new file mode 100644 index 00000000..003a3a95 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/database.cpp @@ -0,0 +1,1533 @@ +/*************************************************************************** + database.cpp - + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + email : rizzi@kde.org + ***************************************************************************/ + +/* + Translation search engine + + + Copyright 2000 + Andrea Rizzi rizzi@kde.org + Copyright 2003 Stanislav Visnovsky visnovsky@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 Qt library by Trolltech AS, Norway (or with modified versions * + * of Qt that use the same license as Qt), 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 * + * Qt. 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 <stdlib.h> +#include <kdebug.h> +#include <string.h> +#include <resources.h> +#include "database.h" +#include <unistd.h> + +#include <qfile.h> + +#include <ktempfile.h> +#include <kio/netaccess.h> + +WordItem::WordItem (char *data, QString w) +{ + word = w; + + count = *(uint32 *) data; + + data += 4; +//score=*(int *)data; + data += 4; + + + locations = (uint32 *) malloc (4 * count); + memcpy (locations, data, 4 * count); + + +} + +WordItem::WordItem (QString w) +{ + locations = NULL; + count = 0; + word = w; + score = -1; // it means no references found. +} + +/* + +WordItem::WordItem(const WordItem &wi) +{ + count=wi.count; + score=wi.score; + word=wi.word; + locations.duplicate(wi.locations); + locations.detach(); +} + +WordItem& WordItem::operator=(const WordItem & wi ) +{ +WordItem *i=new WordItem(wi); +i->locations.detach(); +return *i; +} +*/ + +bool +WordItem::notFound () +{ + return (score == -1); +} + +InfoItem::InfoItem () +{ + catalogName = "No catalog"; + lastTranslator = "No translator"; + lastFullPath = ""; + charset = "No charset"; + language = "No language"; +} + +InfoItem::InfoItem (const char *rawData, QString lang) +{ + const char *rd; + rd = rawData; + int len; + unsigned int secs; + // I'll change the charset handling if needed + + charset = "Utf8"; + + catalogName = QString::fromUtf8 (rd); + len = strlen (rd) + 1; + rd += len; + lastTranslator = QString::fromUtf8 (rd); + len = strlen (rd) + 1; + rd += len; + secs = *(unsigned int *) rd; + revisionDate.setTime_t (secs); + rd += 4; + lastFullPath = QString::fromUtf8 (rd); + len = strlen (rd) + 1; + rd += len; + + + language = lang; +} + +void +InfoItem::rawData (char *rawData) +{ + char *rd; + rd = rawData; + + strcpy (rd, catalogName.utf8 ()); + rd += strlen (rd) + 1; + strcpy (rd, lastTranslator.utf8 ()); + rd += strlen (rd) + 1; + + + //QDate Time problem!!!!!!!!!!! + QDateTime zeroDate; + zeroDate.setTime_t (0); + *(unsigned int *) rd = -revisionDate.secsTo (zeroDate); + rd += 4; + strcpy (rd, lastFullPath.utf8 ()); + rd += strlen (rd) + 1; + + *rd = 0; //Empty for further info + +} + +int +InfoItem::size () +{ + int _size; + _size = 0; + _size += 1; // 1 Empty field; + _size += 3; // Terminating \0 of next 3 strings + _size += 4; // Int size (date) + _size += strlen (catalogName.utf8 ()); + _size += strlen (lastTranslator.utf8 ()); + _size += strlen (lastFullPath.utf8 ()); + + return _size; +} + +// this is a quick hack to copy a local file +int +copy_hack (QFile & input, QFile & output) +{ + if (!input.isOpen ()) + { + if (!input.open (IO_ReadOnly)) + return -1; + } + + if (!output.isOpen ()) + { + if (!output.open (IO_WriteOnly)) + return -1; + } + + char buffer[10240]; + int s = 0; + while (!input.atEnd ()) + { + s = input.readBlock (buffer, 10240); + output.writeBlock (buffer, s); + } + output.close (); + input.close (); + return 0; +} + +DataBaseItem::DataBaseItem () +{ + numTra = 0; + location = 0; +} + +DataBaseItem::DataBaseItem (char *_key, char *_data) +{ + + char *data = _data; + key = QString::fromUtf8 (_key); + + unsigned int i, r; + numTra = *(uint32 *) data; + data += 4; + location = *(uint32 *) data; + data += 4; + + for (i = 0; i < numTra; i++) + { + + TranslationItem tr; + tr.numRef = *(uint32 *) data; + + data += 4; + for (r = 0; r < tr.numRef; r++) + { + + int ref; + ref = *(uint32 *) data; + data += 4; + + tr.infoRef.append (ref); + } + tr.translation = QString::fromUtf8 ((const char *) data); + translations.append (tr); + data += strlen (data) + 1; + + } + +} + +uint32 +DataBaseItem::sizeKey () +{ + return strlen (key.utf8 ()) + 1; +} + +uint32 +DataBaseItem::sizeData () +{ + unsigned int i, _size = 4; + _size += numTra * 4; + _size += 4; // location + for (i = 0; i < numTra; i++) + { + _size += strlen (translations[i].translation.utf8 ()) + 1; // +1 is for \0 + _size += translations[i].numRef * 4; + } + return _size; +} + +void +DataBaseItem::toRawKey (char *_key) +{ + strcpy (_key, key.utf8 ()); +} + +void +DataBaseItem::toRawData (char *_data) +{ + char *data = _data; + unsigned int i, r; + + *(uint32 *) data = numTra; + + data += 4; + + *(uint32 *) data = location; + data += 4; + + for (i = 0; i < numTra; i++) + { + TranslationItem tr (translations[i]); + *(uint32 *) data = tr.numRef; + data += 4; + for (r = 0; r < tr.numRef; r++) + { + *(uint32 *) data = tr.infoRef[r]; //sub i with r + + data += 4; + } + strcpy ((char *) data, tr.translation.utf8 ()); + data += strlen (tr.translation.utf8 ()) + 1; + } + +} + + +DataBaseManager::DataBaseManager (QString directory, QString lang, + QObject * parent, const char *name): +QObject (parent, name) +{ + QString filename; + + language = lang; + iAmOk = true; + basedir = directory; + indexDb = wordDb = infoDb = db = 0; + openDataBase (); + + +} + +void +DataBaseManager::openDataBase () +{ + kdDebug () << "Opendatabase" << endl; + QString directory; + directory = basedir; + QString ll = "." + language; + if (ll == ".") + ll = ".NOLANG"; + + QString transfilename = "%1/translations%2.db"; + transfilename = transfilename.arg (directory).arg (ll); + + QString infofilename = "%1/catalogsinfo%2.db"; + infofilename = infofilename.arg (directory).arg (ll); + + QString wordsfilename = "%1/wordsindex%2.db"; + wordsfilename = wordsfilename.arg (directory).arg (ll); + + QString keysfilename = "%1/keysindex%2.db"; + keysfilename = keysfilename.arg (directory).arg (ll); + + cursor = 0; + int ret; + + if (!db) + db_create (&db, 0, 0); + + db_create (&infoDb, 0, 0); + db_create (&wordDb, 0, 0); + db_create (&indexDb, 0, 0); + + ret = db->open (db, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + transfilename.local8Bit (), 0, DB_BTREE, 0, 0644); + + if (ret == DB_OLD_VERSION) + { + kdDebug (KBABEL_SEARCH) << "Trying upgrade" << endl; + // try upgrade + + KTempFile transFile, infoFile, keysFile, wordsFile; + + // do the upgrade on the translation file + QFile transfilenameFile (transfilename); + + if ((ret = copy_hack (transfilenameFile, *transFile.file ())) == 0) + { + ret = db->upgrade (db, transFile.name ().local8Bit (), 0); + } + + if (ret != 0) + { + kdDebug (KBABEL_SEARCH) << "Cannot upgrade translations, " << + ret << endl; + // cleanup + transFile.unlink (); + iAmOk = false; + emit cannotOpenDB (ret); + return; + } + + // do the upgrade on the info file + QFile infofilenameFile (infofilename); + if ((ret = copy_hack (infofilenameFile, *infoFile.file ())) == 0) + { + ret = + infoDb->upgrade (infoDb, infoFile.name ().local8Bit (), + 0); + } + + if (ret != 0) + { + kdDebug (KBABEL_SEARCH) << "Cannot upgrade catalogsinfo" << + endl; + // cleanup + transFile.unlink (); + infoFile.unlink (); + iAmOk = false; + emit cannotOpenDB (ret); + return; + } + + // do the upgrade on the words file + QFile wordfilenameFile (wordsfilename); + if ((ret = copy_hack (wordfilenameFile, *wordsFile.file ())) == 0) + { + ret = + wordDb->upgrade (wordDb, wordsFile.name ().local8Bit (), + 0); + } + + if (ret != 0) + { + kdDebug (KBABEL_SEARCH) << "Cannot upgrade words" << endl; + // cleanup + transFile.unlink (); + infoFile.unlink (); + wordsFile.unlink (); + iAmOk = false; + emit cannotOpenDB (ret); + return; + } + + // do the upgrade on the keys file + QFile keysfilenameFile (keysfilename); + if ((ret = copy_hack (keysfilenameFile, *keysFile.file ())) == 0) + { + ret = + indexDb->upgrade (indexDb, keysFile.name ().local8Bit (), + 0); + } + + if (ret != 0) + { + kdDebug (KBABEL_SEARCH) << "Cannot upgrade keys" << endl; + // cleanup + transFile.unlink (); + infoFile.unlink (); + wordsFile.unlink (); + keysFile.unlink (); + iAmOk = false; + emit cannotOpenDB (ret); + return; + } + + kdDebug (KBABEL_SEARCH) << "Files upgraded, copying" << endl; + // use temporary file instead + if (ret == 0) + { + KIO::NetAccess::del (KURL::fromPathOrURL (transfilename)); + copy_hack (*transFile.file (), transfilenameFile); + transFile.unlink (); + + KIO::NetAccess::del (KURL::fromPathOrURL (infofilename)); + copy_hack (*infoFile.file (), infofilenameFile); + infoFile.unlink (); + + KIO::NetAccess::del (KURL::fromPathOrURL (wordsfilename)); + copy_hack (*wordsFile.file (), wordfilenameFile); + wordsFile.unlink (); + + KIO::NetAccess::del (KURL::fromPathOrURL (keysfilename)); + copy_hack (*keysFile.file (), keysfilenameFile); + keysFile.unlink (); + + ret = db->open (db, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + transfilename.local8Bit (), 0, DB_BTREE, 0, + 0644); + if (ret != 0) + { + kdWarning (KBABEL_SEARCH) << + "transFilename database can't be opened." << endl; + kdWarning (KBABEL_SEARCH) << + "Please, report this incident and how to reproduce it to kbabel@kde.org." + << endl; + iAmOk = false; + emit cannotOpenDB (ret); + return; + } + + } + kdDebug (KBABEL_SEARCH) << "Upgrade done OK" << endl; + } + +// Open catalogs information database + + + + ret = infoDb->open (infoDb, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + infofilename.local8Bit (), 0, DB_RECNO, 0, 0644); + if (ret != 0) + { + iAmOk = false; + emit cannotOpenDB (ret); + //Process error here. + } + else + loadInfo (); + + + +// Words index database + + ret = wordDb->open (wordDb, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + wordsfilename.local8Bit (), 0, DB_BTREE, 0, 0644); + if (ret != 0) + { + iAmOk = false; + emit cannotOpenDB (ret); + //Process error here. + } + +//Index of keys. + + ret = indexDb->open (indexDb, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + keysfilename.local8Bit (), 0, DB_RECNO, 0, 0644); + if (ret != 0) + { + iAmOk = false; + emit cannotOpenDB (ret); + //Process error here. + } + + +} + +void +DataBaseManager::closeDataBase () +{ + if (iAmOk) + { + db->sync (db, 0); + db->close (db, 0); + + infoDb->sync (infoDb, 0); + infoDb->close (infoDb, 0); + + wordDb->sync (wordDb, 0); + wordDb->close (wordDb, 0); + + indexDb->sync (indexDb, 0); + indexDb->close (indexDb, 0); + + // can not be opened again + indexDb = wordDb = infoDb = db = 0; + + } + +} + + +// I'm not sure this is a good function !!! + +void +DataBaseManager::sync () +{ +// if(iAmOk) +// { +// db->sync(db,0); +// infoDb->sync(infoDb,0); +// cursor=0; +// } + + // closeDataBase(); +// openDataBase(); + + db->sync (db, 0); + infoDb->sync (infoDb, 0); + wordDb->sync (wordDb, 0); + indexDb->sync (indexDb, 0); + loadInfo (); +} + + +DataBaseManager::~DataBaseManager () +{ + closeDataBase (); +} + +int +DataBaseManager::putItem (DataBaseItem * item, bool ow) +{ + DBT key, data; + + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + bool ret; + + uint32 loc = 0; + if (item->location == 0) + { + loc = item->location = appendKey (item->key); +// kdDebug(0) << "New key " << item->location << endl; + } + key.size = item->sizeKey (); + data.size = item->sizeData (); + + key.data = malloc (key.size); + data.data = malloc (data.size); + + + item->toRawKey ((char *) key.data); + item->toRawData ((char *) data.data); + + + if (ow) + ret = db->put (db, 0, &key, &data, 0); + else + ret = db->put (db, 0, &key, &data, DB_NOOVERWRITE); + +//check ret + + if (loc != 0) //I'm new! + { + uint32 location = loc; + + QValueList < QString > wlist; + + wlist = wordsIn (item->key); + + QValueList < QString >::Iterator wlistit; + + for (wlistit = wlist.begin (); wlistit != wlist.end (); ++wlistit) + { + addLocation (*wlistit, location); + } + + } + + free (key.data); + free (data.data); //READ DOCU !!!! + + return ret; + +} + +DataBaseItem +DataBaseManager::getItem (QString key) +{ + if (!iAmOk) + return DataBaseItem (); + + + DBT _key, data; + + memset (&_key, 0, sizeof (DBT)); + + memset (&data, 0, sizeof (DBT)); + + int len = strlen (key.utf8 ()); + _key.data = malloc (len + 1); + _key.size = len + 1; + strcpy ((char *) _key.data, key.utf8 ()); + + + int ret; + ret = db->get (db, 0, &_key, &data, 0); + + if (ret != 0) + { + free (_key.data); + return DataBaseItem (); //return an empty database item + } + + DataBaseItem returnItem = + DataBaseItem ((char *) _key.data, (char *) data.data); + + free (_key.data); + return returnItem; + +} + + + + +DataBaseItem +DataBaseManager::cursorGet (uint32 flags) +{ + + if (!iAmOk) + return DataBaseItem (); + int re; + DBT key, data; + + memset (&key, 0, sizeof (DBT)); + + memset (&data, 0, sizeof (DBT)); + + if (cursor == 0) + re = db->cursor (db, 0, &cursor, 0); + + int ret; + if ((ret = cursor->c_get (cursor, &key, &data, flags)) == 0) + { + return DataBaseItem ((char *) key.data, (char *) data.data); + } + else + { + kdDebug (KBABEL_SEARCH) << QString ("...cursor getting...%1"). + arg (ret) << endl; + + return DataBaseItem (); + } +} + + +DataBaseItem +DataBaseManager::firstItem () +{ + return cursorGet (DB_FIRST); +} + +DataBaseItem +DataBaseManager::currentItem () +{ + return cursorGet (DB_CURRENT); +} + + +DataBaseItem +DataBaseManager::nextItem () +{ + return cursorGet (DB_NEXT); +} + + +bool +DataBaseManager::isOk () +{ + return iAmOk; +} + +int +DataBaseManager::count () +{ + DB_BTREE_STAT *dstat = 0; +#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3 + db->stat (db, NULL, &dstat, DB_FAST_STAT); +#else + db->stat (db, &dstat, DB_FAST_STAT); +#endif + int ret = dstat->bt_nkeys; + free (dstat); + + return ret; +} + +int +DataBaseManager::current () +{ +// THIS FUNCTION SEEM TO NOT WORK (not used) + if (!iAmOk) + return 0; + + DBT key, data; + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + if (cursor != 0) + db->cursor (db, 0, &cursor, 0); + cursor->c_get (cursor, &key, &data, DB_GET_RECNO); + return *(uint32 *) (data.data); + +} + +int +DataBaseManager::createDataBase (QString directory, + QString language, int mode) +{ + QString filename; + QString ll = "." + language; + if (ll == ".") + ll = ".NOLANG"; + filename = "%1/translations%2.db"; + filename = filename.arg (directory).arg (ll); + + rename (filename.local8Bit (), filename.local8Bit () + ",old"); + +//kdDebug(0) << QString("Creating %1").arg(filename) << endl; + + iAmOk = true; + + int ret; + + if (!db) + { + if (db_create (&db, 0, 0) != 0) + { + kdDebug() << "db_create db failed" << endl; + iAmOk = false; + return false; + } + } + + db->set_flags (db, DB_RECNUM); + ret = db->open (db, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + filename.local8Bit (), 0, DB_BTREE, DB_CREATE | DB_EXCL, + mode); + if (ret != 0) + { + kdDebug() << "db->open " << filename << " " << mode << " failed" << endl; + iAmOk = false; + } + + + filename = "%1/catalogsinfo%2.db"; + filename = filename.arg (directory).arg (ll); + rename (filename.local8Bit (), filename.local8Bit () + ",old"); + + db_create (&infoDb, 0, 0); + ret = infoDb->open (infoDb, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + filename.local8Bit (), 0, DB_RECNO, DB_CREATE, mode); + if (ret != 0) + iAmOk = false; + + + + filename = "%1/wordsindex%2.db"; + filename = filename.arg (directory).arg (ll); + rename (filename.local8Bit (), filename.local8Bit () + ",old"); + + db_create (&wordDb, 0, 0); + ret = wordDb->open (wordDb, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + filename.local8Bit (), 0, DB_BTREE, DB_CREATE, mode); + if (ret != 0) + iAmOk = false; + + + + filename = "%1/keysindex%2.db"; + filename = filename.arg (directory).arg (ll); + rename (filename.local8Bit (), filename.local8Bit () + ",old"); + + db_create (&indexDb, 0, 0); + ret = indexDb->open (indexDb, +#if DB_VERSION_MINOR > 0 + NULL, +#endif + filename.local8Bit (), 0, DB_RECNO, DB_CREATE, mode); + if (ret != 0) + iAmOk = false; + + + + if (iAmOk) + loadInfo (); + else + kdDebug (KBABEL_SEARCH) << QString ("I am NOT ok : %1"). + arg (ret) << endl; + +//THIS IS WRONG, rewrite the error handling. + return iAmOk; + +} + +InfoItem +DataBaseManager::getCatalogInfo (int n) +{ + + DBT key; + DBT data; + + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + key.data = &n; + key.size = 4; + +//Check for errors + int ret = infoDb->get (infoDb, 0, &key, &data, 0); //DB_SET_RECNO); + + if (ret) + { + return InfoItem (); + } + +// kdDebug(0) << QString("Trad %1").arg(ret) << endl; + + InfoItem it ((char *) data.data, language); +//free(data.data); // Read docu for this!!!! + + return it; + +} + +int +DataBaseManager::addCatalogInfo (InfoItem * catInfo, int cat = -1) +{ + DBT data; + DBT key; + + // clean up data + memset (&data, 0, sizeof (DBT)); + memset (&key, 0, sizeof (DBT)); + + int ret = 0, err; + if (cat >= 0) + ret = cat; + key.size = 4; + key.data = &ret; + data.size = catInfo->size (); + data.data = malloc (data.size); + + catInfo->rawData ((char *) data.data); + + // store the catalog data into database + if (cat >= 0) + err = infoDb->put (infoDb, 0, &key, &data, 0); + else + err = infoDb->put (infoDb, 0, &key, &data, DB_APPEND); + + + ret = *(int *) key.data; + + // Append to the list of catalogInfo + info.append (*catInfo); + + // cleanup unneeded data memory + free (data.data); + return ret; +} + +int +DataBaseManager::searchCatalogInfo (QString location) +{ + int n = 0; + QValueList < InfoItem >::Iterator it; + for (it = info.begin (); it != info.end (); ++it) + { + n++; + if ((*it).catalogName == location) + return n; + } + return -1; +} + +bool +DataBaseManager::putCatalogInfo (int refnum, InfoItem * catInfo) +{ + DBT data; + DBT key; + + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + int ret; + key.size = 4; + key.data = &refnum; + + data.size = catInfo->size (); + data.data = malloc (data.size); + catInfo->rawData ((char *) data.data); + + ret = infoDb->put (infoDb, 0, &key, &data, 0); + + free (data.data); + + return (ret == 0); +} + +void +DataBaseManager::loadInfo () +{ + int nrec; + DB_BTREE_STAT *stat; +// memset(&stat,0,sizeof(DB_BTREE_STAT)); +#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3 + if (infoDb->stat (infoDb, NULL, &stat, DB_FAST_STAT)) + fprintf (stderr, "Cannot stat\n"); +#else + if (infoDb->stat (infoDb, &stat, DB_FAST_STAT)) + fprintf (stderr, "Cannot stat\n"); +#endif + nrec = stat->bt_nkeys; + free (stat); + + info.clear (); + for (int i = 1; i <= nrec; i++) // I think DB2 Recno are 1 based. + { + info.append (getCatalogInfo (i)); + } + +} + + +QValueList < QString > DataBaseManager::wordsIn (QString string) +{ + QString + a; + QValueList < QString > words; + int + i, + l; + + a = string.simplifyWhiteSpace (); + a = a.stripWhiteSpace (); + a = a.lower (); + l = a.length (); + + int + c = 0; + //words.setAutoDelete(true); //Not sure... check if it is en. + QString + m; + for (i = 0; i < l; i++) + if (a[i].isLetterOrNumber ()) + { + m += a[i]; + } + else if (a[i].isSpace ()) + { + words.append (m); + c++; // C++ ;-) + m = ""; + } + words.append (m); + + return words; +} + + + +WordItem +DataBaseManager::getWordLocations (QString word) +{ + + QString keystring = word.lower (); + + DBT key; + DBT data; + + char *keydata; + + int intlen = strlen (keystring.utf8 ()); + + keydata = (char *) malloc (intlen + 1); + strcpy (keydata, keystring.utf8 ()); + + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + key.data = keydata; + key.size = intlen + 1; + +//Check for errors + int ret = wordDb->get (wordDb, 0, &key, &data, 0); //DB_SET_RECNO); +//MAYBE THIS WORD IS NO WHERE!! + if (ret) + { + free (keydata); + return WordItem (keystring); + } + + + WordItem it ((char *) data.data, keystring); + + free (keydata); + + +// kdDebug(0) << ((uint32 *)it.locations.data())[0] << endl; + + return it; + +} + + +bool +DataBaseManager::addLocation (QString word, unsigned int location) +{ + + QString keystring = word.lower (); + + + DBT key; + DBT data; + + char *keydata; + char *newdata; + + int intlen = strlen (keystring.utf8 ()); + + keydata = (char *) malloc (intlen + 1); + strcpy (keydata, keystring.utf8 ()); + + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + key.data = keydata; + key.size = intlen + 1; + + strcpy ((char *) key.data, keystring.utf8 ()); + +//Check for errors + int ret = wordDb->get (wordDb, 0, &key, &data, 0); //DB_SET_RECNO); + +//Check if you get something or not + if (ret == 0) // CHANGE IT!!!!! if found something + { + uint32 *d; + d = (uint32 *) data.data; + uint32 num = d[0]; + uint32 loc = 0; //Position from 0 to num-1 + int totalrecord = count (); + uint32 step = 1; + + int antibounce = 0; +//d+=4; +//int score=d[1]; +//d+=4; + bool forward, end = false; + + d[1] = 0; //Before the begin... + + d += 2; //1 uint32! + + +//Try to guess... + loc = location * num / totalrecord + 1; + if (loc >= num) + loc = num - 1; + + + + +//Continue if next is smaller or if previous is greater +//before the while check if it is ok + if (loc == 0) + { + if (d[loc] > location) + end = true; + else + loc = 1; + } + + if ((loc == num) && !end) + { + if (d[loc - 1] < location) + end = true; + else + loc = num - 1; + } + + + + while ((!end) && ((forward = (d[loc]) < location) + || ((loc > 0) && (d[loc - 1] > location)))) + { + + antibounce++; + //calculate step or use antibounce + if (abs ((int) d[loc] - (int) location) < 50 + || antibounce > 100) + step = 1; //Go linear... + else + { + step = + (abs (d[loc] - location) * num) / totalrecord + 1; + + } + + kdDebug (KBABEL_SEARCH) << "Insert:" << location << + " We are at: " << loc << " i.e. " << d[loc] << " Step:" + << step << endl; + if (loc > 0) + { + if (forward) + kdDebug (KBABEL_SEARCH) << "Go " << "forward" << + " prev is " << d[loc - 1] << endl; + else + kdDebug (KBABEL_SEARCH) << "Go " << "backward" << + " prev is " << d[loc - 1] << endl; + } + + if (forward) + { + if (loc + step < num) + loc += step; // Go forward + else + loc = num; // Go to num + } + else + { + if (loc > step) + loc -= step; //Go backward + else + loc = 0; // Go to 0 + } + + //Now check if I am in the right place [THIS IS NOT NECESSARY] + + //check if loc and loc -1 are well defined 1<loc<num-1 + if (loc > num) + loc = num; //Must not happen, idem + + if (loc == 0) + { + if (d[loc] > location) + end = true; + else + loc = 1; + } + + if ((loc == num) && !end) + { + if (d[loc - 1] < location) + end = true; + else + loc = num - 1; + } + + } + + if (loc == num) + kdDebug (KBABEL_SEARCH) << "END" << endl; + if (loc == 0) + kdDebug (KBABEL_SEARCH) << "BEGIN" << endl; + + if (loc > 0) + kdDebug (KBABEL_SEARCH) << location << " inserted between " << + d[loc - 1] << " and " << d[loc] << endl; + + if ((loc < num && location == d[loc]) || (loc > 0 && location == d[loc - 1])) //What about word repetition + { + free (keydata); + return true; //Why true ?? + } + + + +//Now insert and put back in the database! + newdata = (char *) malloc (4 * (num + 3)); //uint32*(num+score+1..NUM+new) + memcpy (newdata, data.data, 4 + 4 + 4 * loc); + char *secondpart = (char *) data.data; + secondpart += 4 * (loc + 2); + memcpy ((newdata + 4 * (loc + 3)), secondpart, (num - loc) * 4); + uint32 *intdata = (uint32 *) newdata; + intdata[0] = num + 1; + //ADD HERE code to recalc score + intdata[loc + 2] = location; + +//ok send it to database! + memset (&data, 0, sizeof (DBT)); + + data.data = newdata; + data.size = 4 * (3 + num); + } //found sounthing + else + { //found nothing + newdata = (char *) malloc (4 * 3); + uint32 *intdata = (uint32 *) newdata; + intdata[0] = 1; + intdata[1] = 1; + intdata[2] = location; + memset (&data, 0, sizeof (DBT)); + data.data = newdata; + data.size = 4 * 3; + } + + memset (&key, 0, sizeof (DBT)); +//memset(&data,0,sizeof(DBT)); + + key.data = keydata; + key.size = intlen + 1; + + ret = wordDb->put (wordDb, 0, &key, &data, 0); //DB_SET_RECNO); + + + free (newdata); + free (keydata); +//return it; + + return true; +} + + +bool +DataBaseManager::removeLocation (QString /*word */ , int /*location */ ) +{ + +//#warning TODO: REMOVE LOCATION + return true; + +} + +uint32 +DataBaseManager::appendKey (QString _key) +{ + + DBT key; + DBT data; + + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + + uint32 ret = 0, err; + key.size = 4; + key.data = &ret; + + data.size = strlen (_key.utf8 ()) + 1; + data.data = malloc (data.size); + + strcpy ((char *) data.data, _key.utf8 ()); + + err = indexDb->put (indexDb, 0, &key, &data, DB_APPEND); + + if (err) + ret = 0; + else + ret = *(uint32 *) key.data; + +//kdDebug(0) << QString("Append result %1,err = %1").arg(ret).arg(err) << endl; + + + free (data.data); + + return ret; + +} + +QString +DataBaseManager::getKey (uint32 n) +{ + + DBT key; + DBT data; + + memset (&key, 0, sizeof (DBT)); + memset (&data, 0, sizeof (DBT)); + + key.data = &n; + key.size = 4; + +//Check for errors + int ret = indexDb->get (indexDb, 0, &key, &data, 0); //DB_SET_RECNO); + if (ret) + return QString::null; + + return QString::fromUtf8 ((char *) data.data); + +// kdDebug(0) << QString("Trad %1").arg(ret) << endl; + +} + +int +DataBaseManager::catalogRef (QString location, QString author, QString path) +{ + InfoItem cinfo; + int cat, catnum; + cat = searchCatalogInfo (location); + + if (cat == -1) //Not exist + { + cinfo.catalogName = location; + cinfo.lastTranslator = author; + cinfo.lastFullPath = path; + //TO DO: + // //Add date info + + kdDebug (0) << "New catalog " << endl; + catnum = addCatalogInfo (&cinfo); + //sync(); + kdDebug (0) << "Ref " << catnum << endl; + } + else + { + cinfo = getCatalogInfo (cat); + //Update date. + + //last path must be updated + cinfo.lastFullPath = path; + kdDebug (0) << "New full path " << path << endl; + kdDebug (0) << "Ref " << cat << endl; + + catnum = addCatalogInfo (&cinfo, cat); + kdDebug (0) << " must be equal to " << catnum << endl; + + catnum = cat; + } + + return catnum; +} + +int +DataBaseManager::putNewTranslation (QString key, QString tran, int catalog, + bool ow) +{ + int catnum = catalog; + int count = 0; + QString msgid = key; + DataBaseItem dbit = getItem (msgid); + + if (dbit.numTra == 0) //Not found + { + dbit.numTra += 1; + + // use local variable, dbit.translations is QValueList and + // will create own copy + TranslationItem tra; + tra.numRef = 1; + tra.translation = tran; + tra.infoRef.append (catnum); + dbit.translations.append (tra); + dbit.key = key; + + //Check ret value + count++; + + int aa = putItem (&dbit); + if (aa) + kdDebug (0) << QString ("-----------put code ") << aa << endl; + } + else + { + // key exists + + QString msgstr = tran; + bool found_catalog_info = false, foundTr = false, isThisOne = false; + + QValueList < TranslationItem >::Iterator ittr; + bool rem = false; + + // check all translations in the list + for (ittr = dbit.translations.begin (); + ittr != dbit.translations.end (); rem ? ittr : ++ittr) + { + rem = false; + found_catalog_info = false; + + // is the translation one we should put there? + isThisOne = (*ittr).translation == msgstr; + + // is there the catnum we are looking for? + if ((*ittr).infoRef.find (catnum) != (*ittr).infoRef.end ()) + { + found_catalog_info = true; + if (ow && !isThisOne) + { + // I'll look for my catalog reference to del old + kdDebug (0) << "Removing the old translation " << endl; + (*ittr).numRef -= 1; + (*ittr).infoRef.remove (catnum); + if ((*ittr).numRef == 0) + { + dbit.numTra -= 1; + // point the iterator to the next valid item + ittr = dbit.translations.remove (ittr); + rem = true; + } + } + } + + if (isThisOne) + { + if (!found_catalog_info) + { + //There are no reference of this catalog for this translation => add it + (*ittr).infoRef.append (catnum); + (*ittr).numRef += 1; + } + foundTr = true; // Ok, we found this translation, no need to add it. + } + } + + if (!foundTr) //This translation is new => Add it ! + { + count++; + TranslationItem tra; + tra.numRef = 1; + tra.translation = msgstr; + tra.infoRef.append (catnum); + + dbit.translations.append (tra); + dbit.numTra += 1; + } + + //put the new item in database overwriting the old one. + //Check ret value + int aa = putItem (&dbit, true); + if (aa) + kdDebug (0) << QString ("-----------put code ") << aa << endl; + + } + return count; +} + + +void +DataBaseManager::rebuildIndexes () +{ +// uint32 loc; +#if 0 +//Reset the 2 databases here. + + while (0 /*browse keys here */ ) + { + loc = item->location = appendKey (item->key); + + uint32 location = loc; + + QValueList < QString > wlist; + + wlist = wordsIn (item->key); + + QValueList < QString >::Iterator wlistit; + + for (wlistit = wlist.begin (); wlistit != wlist.end (); ++wlistit) + { + addLocation (*wlistit, location); + } + + } +#endif +} + + + +#include "database.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine/database.h b/kbabel/kbabeldict/modules/dbsearchengine/database.h new file mode 100644 index 00000000..bf4767df --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/database.h @@ -0,0 +1,329 @@ +/*************************************************************************** + database.h - + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + email : rizzi@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * * + * In addition, as a special exception, the copyright holders give * + * permission to link the code of this program with any edition of * + * the Qt library by Trolltech AS, Norway (or with modified versions * + * of Qt that use the same license as Qt), 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 * + * Qt. 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. * + ***************************************************************************/ +/* + Translation search engine + + + Copyright 2000 + Andrea Rizzi rizzi@kde.org + +*/ + + +#ifndef _DATABASE_H_ +#define _DATABASE_H_ + +#include <config.h> + +#ifdef USE_DB_H_PATH +#include USE_DB_H_PATH +#else +#ifdef HAVE_DB4_DB_H +#include <db4/db.h> +#else +#include <db.h> +#endif +#endif + +#define uint32 u_int32_t + +#include <qvaluelist.h> +#include <qptrlist.h> +#include <qstring.h> +#include <qobject.h> +#include <qdatetime.h> +#include <qcstring.h> //bytearray + + +class WordItem // Returned by getWordLocations +{ + public: + + WordItem(char *data,QString w); + WordItem(QString w); + //WordItem(const WordItem &wi); + //WordItem& operator=(const WordItem & wi ); + + //The word (key in database) + QString word; + //Sorted locations + //QByteArray locations; //too many problems with this.. + //NOTE: + //This is allocated only if you call WordItem(char *data,QString w); + //YOU MUST FREE IT when you do not need it anymore + //No destructor will do it !!! + + uint32 *locations; + + + uint32 count; + //Is this word common ? + int score; + + bool notFound(); +}; + + +class InfoItem +{ + public: + + //Create the NO INFO item + InfoItem(); + + // Create an info item from raw data + InfoItem(const char *rawData,QString lang); + + QString catalogName; + QString lastFullPath; + + QString lastTranslator; + QDateTime revisionDate; + QString charset; + QString language; + + + int size(); + void rawData(char *); + +}; + +class TranslationItem +{ + public: + QString translation; + QValueList<int> infoRef; + uint32 numRef; + +}; + +class DataBaseItem +{ + public: + /* + Create empty class; + */ + DataBaseItem(); + + /* + Create a DataBaseItem from raw data + */ + DataBaseItem(char *_key,char *_data); + + /* + return the size (in raw data) of this item. + */ + uint32 sizeData(); + uint32 sizeKey(); + + bool isNull() { return (numTra==0); } + + /* + You MUST allocate data of sizeData() byte. + */ + void toRawData(char *_data); + void toRawKey(char *_key); + + QString key; + QValueList<TranslationItem> translations; + uint32 numTra; + uint32 location; +}; + +class DataBaseManager : public QObject +{ + + Q_OBJECT + + public: + /* + Main constructor. + directory is the name of the directory where the database structre + is stored. + + DIRECTORY/translations.$LANG.db The trasnaltion archive + DIRECTORY/catalogsinfo.$LANG.db Info about catalogs + + //Not yet implemented + DIRECTORY/wordsindex.$LANG.db Index of words + + + */ + + DataBaseManager(QString directory,QString lang,QObject *parent=0,const char *name=0); + ~DataBaseManager(); + /* + Create a new databse structure. + + */ + int createDataBase(QString directory,QString language,int mode=0664); + + + + + /* + Put a DataBaseItem into the database. + + if ow==false enter the new DataBaseItem only + if the key of DataBaseItem does not previously exist + + It also update the wordIndex. + + */ + + int putItem(DataBaseItem *item,bool ow=false); + + DataBaseItem getItem(QString key); + + /* + @return the first entry in the database. + */ + + DataBaseItem firstItem(); + + /* + @return the current entry of the database. + */ + + DataBaseItem currentItem(); + + /* + @return the next entry in the database. + */ + + DataBaseItem nextItem(); + + + /* + * Add a new translation to the database + * catalog is a valid catalog refnum (use catalogRef to get one) + * if ow is true a translation of a key coming from catalog is + * overwritten if you provide a new translation + */ + + int putNewTranslation(QString key,QString tran,int catalog,bool ow=true); + + /* + @return info about catalog n + */ + + InfoItem getCatalogInfo(int n); + + /* + Add an entry to catalogsinfo database and + @return a refnum for the new added item + */ + + int addCatalogInfo(InfoItem *catInfo,int); + + /* + Search an Item with the same "location" and + @return its refnum. + */ + + int searchCatalogInfo(QString location); + + /* Get a catalog info for location, + * if it doesn't exist it will create one. + * @return the refnum + */ + + int catalogRef(QString location,QString author,QString path); + + /* + Put at refnum the catInfo + @return true if everything is OK + */ + + bool putCatalogInfo(int refnum, InfoItem *catInfo); + + /* + Get word info + */ + WordItem getWordLocations(QString word); + + /* + Add a location for word + */ + bool addLocation(QString word, unsigned int location); + + /* + Remove location for word + */ + bool removeLocation(QString word, int location); + + + /* + * Rebuild location and word indexes + */ + void rebuildIndexes(); + + uint32 appendKey(class QString); + + QString getKey(uint32 n); + + /* + Load the catalogs info. + */ + void loadInfo(); + + + void sync(); + + bool isOk(); + int count(); + int current(); + + void openDataBase(); + void closeDataBase(); + + static QValueList<QString> wordsIn(QString string); + + signals: + + void cannotOpenDB(int); + + + protected: + DataBaseItem cursorGet(uint32 flags); + + QString language; + QString basedir; + QValueList<InfoItem> info; + + DB *db,*infoDb,*wordDb,*indexDb; + DBC *cursor; + bool iAmOk; + bool indexOk; //Database could word without word index +}; + + + + + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbscan.cpp b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.cpp new file mode 100644 index 00000000..87b39e61 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + dbscan.cpp - Scan for po files to add in the DB + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + email : rizzi@kde.org + ***************************************************************************/ + +/* + Translation search engine + + + Copyright 2000 + 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 Qt library by Trolltech AS, Norway (or with modified versions * + * of Qt that use the same license as Qt), 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 * + * Qt. 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 "dbscan.h" + +#include <qdir.h> +#include <qfile.h> +#include <kapplication.h> +#include <kurl.h> +#include <kdebug.h> + +using namespace KBabel; + +PoScanner::PoScanner(DataBaseManager *dbm, + QObject *parent,const char *name):QObject(parent,name) +{ +dm=dbm; +removeOldCatalogTranslation=false; //Check if this flag do something. +count=0; +} + +bool PoScanner::scanPattern(QString pathName,QString pattern,bool rec) +{ +int tot; + +//Only one progress bar!! +bool pb=false; +static bool called=false; +if (!called) +{ pb=true; count=0;} +called=true; + +kdDebug(0) << QString("cat: %1, %2").arg(pathName).arg(pattern) << endl; + +if(pb) +{emit patternStarted(); +emit patternProgress(0); +} + QDir d(pathName,pattern); + d.setMatchAllDirs(true); + const QFileInfoList* files = d.entryInfoList(); + tot=files->count(); + QPtrListIterator<QFileInfo> it(*files); +kdDebug(0) << tot << endl; + for ( int i=0; i<tot; i++ ) + { + if ((*it)->isDir()) + { + if(rec) + { + kdDebug(0) << d[i] << endl; + if(d[i]!="." && d[i]!="..") + scanPattern(pathName+"/"+d[i],pattern,true); + } + } else + { + kdDebug(0) << d[i] << endl; + scanFile(pathName+"/"+d[i]); + } + + if(pb) + + emit patternProgress(100*i/tot); + + //printf( "%s\n", d[i] ); + + ++it; + } + + + +if(pb) +emit patternProgress(100); + + +if(pb) +emit patternFinished(); +if(pb){called=false;count=0;} + +return true; +} + + + + +bool PoScanner::scanFile(QString fileName) +{ + + +emit fileStarted(); + +InfoItem cinfo; +Catalog * catalog=new Catalog(this,"ScanPoCatalog"); + + +QString location=fileName.right(fileName.length()-fileName.findRev("/")-1); +connect(catalog,SIGNAL(signalProgress(int)),this,SIGNAL(fileLoading(int))); +emit filename(location); +emit fileProgress(0); +emit fileLoading(0); + +KURL u(fileName); + +ConversionStatus rr=catalog->openURL(u); +if(rr != OK && rr !=RECOVERED_PARSE_ERROR ) +{ + delete catalog; + return false; +} +emit fileLoading(100); + +QString author; +if(rr != HEADER_ERROR) + author=catalog->lastTranslator(); +else author=QString("unknown"); + +int catnum=dm->catalogRef(location,author,fileName); + +uint i,tot; +tot=catalog->numberOfEntries(); +//DataBaseItem dbit; +bool fuzzy; +bool untra; + +//kdDebug(0) << QString("Tot: %1").arg(tot) << endl; + +for (i=0;i<tot;i++) //Skip header = ???? +{ + + //Faster ? + if(i % 10==0) + { + emit fileProgress(100*i/tot); + emit added(count); + kapp->processEvents(100); + } + + fuzzy=catalog->isFuzzy(i); + untra=catalog->isUntranslated(i); + + + if(!fuzzy && !untra) + { + int res; + QString msgid,msgstr; + msgid=catalog->msgid(i,true).first(); + kdWarning() << "Translation database does not support plural forms" << endl; + msgstr=catalog->msgstr(i).first(); + res=dm->putNewTranslation(msgid,msgstr,catnum,false); + count+=res; + } + + +} + + +// kdDebug(0) << QString("File finished") << endl; + +emit fileProgress(0); +emit fileLoading(0); +emit fileFinished(); +// dm->loadInfo(); // Sync the list of catalogs NOT NEEDED (?) + +delete catalog; + +//clear(); +return true; + +} +#include "dbscan.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbscan.h b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.h new file mode 100644 index 00000000..c151509e --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.h @@ -0,0 +1,86 @@ +/*************************************************************************** + dbscan.h - + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + email : rizzi@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * * + * In addition, as a special exception, the copyright holders give * + * permission to link the code of this program with any edition of * + * the Qt library by Trolltech AS, Norway (or with modified versions * + * of Qt that use the same license as Qt), 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 * + * Qt. 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. * + ***************************************************************************/ +/* + Translation search engine + + + Copyright 2000 + Andrea Rizzi rizzi@kde.org + +*/ + + +#ifndef _DBSCAN_H_ +#define _DBSCAN_H_ + +#include <catalog.h> +#include "database.h" + +class PoScanner : public QObject +{ + Q_OBJECT + +public: + + PoScanner(DataBaseManager *dbm,QObject *parent=0,const char *name=0); + + /* + Scan a single PO file. + */ + bool scanFile(QString fileName); + + /* + Scan a list of space separated files with possible MetaCharacters + */ + bool scanPattern(QString pathName,QString pattern="*.po",bool rec=false); + + + + +signals: + void fileStarted(); + void fileProgress(int); + void fileFinished(); + void fileLoading(int); + void patternStarted(); + void patternProgress(int); + void patternFinished(); + void added(int); + void filename(QString); +private: + + // If true when a translation is found in a CATALOG the old translation for this CATALOG + // will be removed + bool removeOldCatalogTranslation; + int count; + DataBaseManager *dm; +// InfoItem cinfo; +}; + + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.cpp b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.cpp new file mode 100644 index 00000000..37332167 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.cpp @@ -0,0 +1,82 @@ + +#include <klocale.h> +#include <kinstance.h> +#include <kaboutdata.h> +#include <kdebug.h> + +#include "dbse_factory.h" +#include "KDBSearchEngine.h" + + +extern "C" +{ + KDE_EXPORT void *init_kbabeldict_dbsearchengine() + { + return new DbSeFactory; + } +} + + +KInstance *DbSeFactory::s_instance = 0; +KAboutData *DbSeFactory::s_about = 0; + + +DbSeFactory::DbSeFactory( QObject *parent, const char *name) + : KLibFactory(parent,name) +{ +} + +DbSeFactory::~DbSeFactory() +{ + if(s_instance) + { + delete s_instance; + s_instance=0; + } + + if(s_about) + { + delete s_about; + s_about=0; + } +} + + +QObject *DbSeFactory::createObject( QObject *parent, const char *name, + const char *classname, const QStringList &) +{ + if(QCString(classname) != "SearchEngine") + { + kdError() << "not a SearchEngine requested" << endl; + return 0; + } + + KDBSearchEngine *se = new KDBSearchEngine(parent,name); + + emit objectCreated(se); + return se; +} + + +KInstance *DbSeFactory::instance() +{ + if(!s_instance) + { + + s_about = new KAboutData( "kdbsearchengine", + I18N_NOOP("Translation Database") + , "0.3" , +I18N_NOOP("A fast translation search engine based on databases") + , KAboutData::License_GPL + , I18N_NOOP("Copyright 2000-2001 by Andrea Rizzi") + ,0,0, "rizzi@kde.org"); + + s_about->addAuthor("Andrea Rizzi",0,"rizzi@kde.org"); + + s_instance = new KInstance(s_about); + } + + return s_instance; +} + +#include "dbse_factory.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.h b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.h new file mode 100644 index 00000000..6a9f9f3d --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.h @@ -0,0 +1,26 @@ +#ifndef DBSE_FACTORY_H +#define DBSE_FACTORY_H + +#include <klibloader.h> +class KInstance; +class KAboutData; + +class DbSeFactory : public KLibFactory +{ + Q_OBJECT +public: + DbSeFactory( QObject *parent=0, const char *name=0); + ~DbSeFactory(); + + virtual QObject *createObject( QObject *parent=0, const char *name=0, + const char *classname="QObject", + const QStringList &args = QStringList()); + + static KInstance *instance(); + +private: + static KInstance *s_instance; + static KAboutData *s_about; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbsearchengine.desktop b/kbabel/kbabeldict/modules/dbsearchengine/dbsearchengine.desktop new file mode 100644 index 00000000..6aed2e40 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/dbsearchengine.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +Type=Service +Name=Translation Database for KBabelDict +Name[bg]=БД с преводи за KBabelDict +Name[br]=Stlennvon geriaoueg evit KBabelDict +Name[bs]=Baza prijevoda za KBabelDict +Name[ca]=Base de dades de traducció per a KBabelDict +Name[cs]=Databáze překladů pro KBabelDict +Name[cy]=Cronfa ddata Cyfieithiadau i KBabelDict +Name[da]=Oversættelsesdatabase for KBabelDict +Name[de]=Übersetzungsdatenbank für KBabelDict +Name[el]=Βάση δεδομένων μετάφρασης για το KBabelDict +Name[es]=Base de datos de traducciones para KBabelDict +Name[et]=KBabelDicti tõlgete andmebaas +Name[eu]=Itzulpen datu-basea KBabelDict-entzat +Name[fa]=دادگان ترجمه برای KBabelDict +Name[fi]=KBabelDict-ohjelman käännöstietokanta +Name[fr]=Base de données des traductions pour KBabelDict +Name[ga]=Cuimhne Aistriúcháin le haghaidh KBabelDict +Name[gl]=Base de datos de traducións de KBabelDict +Name[hi]=के-बेबल-डिक्श के लिए अनुवाद डाटाबेस +Name[hu]=Fordítási adatbázis a KBabelDicthez +Name[is]=Þýðingagagnagrunnur fyrir KBabel orðabókina +Name[it]=Banca dati di traduzioni per KBabelDict +Name[ja]=KBabelDict トランザクションデータベース +Name[ka]=თარგმნის მონაცემთა ბაზა KBabelDict-სთვის +Name[kk]=KBabelDict-тың аударма деректер қоры +Name[lt]=KBabelDict vertimų duomenų bazė +Name[ms]=Pangkalan Data Penterjemahan KBabelDict +Name[nb]=Oversettelsesdatabase for KBabelDict +Name[nds]=Översettendatenbank för KBabelDict +Name[ne]=KBabelDict का लागि अनुबाद डाटाबेस +Name[nl]=Vertalingendatabase voor KBabelDict +Name[nn]=Omsetjingsdatabase for KBabelDict +Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦ-ਕੋਸ਼ ਲਈ ਅਨੁਵਾਦ ਡਾਟਾਬੇਸ +Name[pl]=Baza tłumaczeń dla KBabelDict +Name[pt]=Base de Dados de Traduções do KBabelDict +Name[pt_BR]=Banco de Dados de Traduções para o KBabelDict +Name[ru]=База данных переводов для KBabelDict +Name[sk]=Databáza prekladov pre KBabelDict +Name[sl]=Zbirka prevodov za KBabelDict +Name[sr]=Преводилачка база података за KBabelDict +Name[sr@Latn]=Prevodilačka baza podataka za KBabelDict +Name[sv]=Översättningsdatabas för Kbabeldict +Name[ta]=Kபாபேலுக்கான மொழிபெயர்ப்பு தரவுத்தளம் +Name[tg]=Базаи маълумоти тарҷумаҳо барои KBabelDict +Name[tr]=KBabelDict için Çeviri Veritabanı +Name[uk]=База даних перекладів для KBabelDict +Name[zh_CN]=KBabelDict 的翻译数据库 +Name[zh_TW]=KBabelDict 翻譯資料庫 +X-KDE-Library=kbabeldict_dbsearchengine +ServiceTypes=KBabelDictModule diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbseprefwidget.ui b/kbabel/kbabeldict/modules/dbsearchengine/dbseprefwidget.ui new file mode 100644 index 00000000..d18ecaef --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/dbseprefwidget.ui @@ -0,0 +1,1036 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>DBSearchEnginePref</class> +<author>Andrea Rizzi <rizzi@kde.org></author> +<widget class="QWidget"> + <property name="name"> + <cstring>DBSEPrefWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>414</width> + <height>426</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>TabWidget6</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string></string> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>Widget4</cstring> + </property> + <attribute name="title"> + <string>Generic</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>ButtonGroup2</cstring> + </property> + <property name="title"> + <string>Search Mode</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>allRB</cstring> + </property> + <property name="text"> + <string>Search in whole database (slow)</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Scroll the whole database and return everything that matches +according to the rules defined in tabs <strong> Generic </strong> +and <strong>Match</strong></string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>slistRB</cstring> + </property> + <property name="text"> + <string>Search in list of "good keys" (best)</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Search in a list of <em>good keys</em> (see <strong>Good keys</strong> tab) with rules defined in <strong>Search</strong> tab. +This is the best way to search because the <em>good keys</em> list probably contains all the keys that match with your query. However, it is smaller than the whole database.</string> + </property> + </widget> + <widget class="QRadioButton" row="2" column="0"> + <property name="name"> + <cstring>rlistRB</cstring> + </property> + <property name="text"> + <string>Return the list of "good keys" (fast)</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Returns the whole <em>good keys</em> list. Rules defined in <strong>Search</strong> tab are ignored.</string> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>caseSensitiveCB</cstring> + </property> + <property name="text"> + <string>Case sensitive</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>If it is checked the search will be case sensitive. It is ignored if you use <em>Return the list of "good keys"</em> search mode.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>normalizeCB</cstring> + </property> + <property name="text"> + <string>Normalize white space</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Remove white spaces at the beginning and at the end of the phrase. +It also substitutes groups of more than one space character with only one space character.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>removeContextCB</cstring> + </property> + <property name="text"> + <string>Remove context comment</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Remove, if exists, the _:comment</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout11</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel3</cstring> + </property> + <property name="text"> + <string>Character to be ignored:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>ignoreLE</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>Widget5</cstring> + </property> + <attribute name="title"> + <string>Search</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>ButtonGroup1</cstring> + </property> + <property name="title"> + <string>Matching Method</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer row="1" column="0"> + <property name="name"> + <cstring>Spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="2" column="0"> + <property name="name"> + <cstring>Spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="2" column="1"> + <property name="name"> + <cstring>containedCB</cstring> + </property> + <property name="text"> + <string>Query is contained</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Match if query is contained in database string</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="1"> + <property name="name"> + <cstring>containsCB</cstring> + </property> + <property name="text"> + <string>Query contains</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Match if query contains the database string</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>normalTextRB</cstring> + </property> + <property name="text"> + <string>Normal text</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Consider the search string as normal text.</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="1"> + <property name="name"> + <cstring>equalCB</cstring> + </property> + <property name="text"> + <string>Equal</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Match if query and database string are equal</string> + </property> + </widget> + <spacer row="3" column="0"> + <property name="name"> + <cstring>Spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QRadioButton" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>RegExpRB</cstring> + </property> + <property name="text"> + <string>Regular expression</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Consider the search string as a regular expression</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox3</cstring> + </property> + <property name="title"> + <string>Word Substitution</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>If you use one or two <em>word substitution</em> each time you search a phrase with less than the specified number of words, the search engine will also search for all phrases that differ from the original one in one or two words.<p> +<strong>Example:</strong><br> +If you search for <em>My name is Andrea</em> and you have activated <em>one word substitution</em> you may also find phrases like <em>My name is Joe</em> or <em>Your name is Andrea</em>.</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer row="3" column="0"> + <property name="name"> + <cstring>Spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>oneWordSubCB</cstring> + </property> + <property name="text"> + <string>Use one word substitution</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>Spacer9</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>TextLabel1</cstring> + </property> + <property name="text"> + <string>Max number of words in the query:</string> + </property> + </widget> + <widget class="QSpinBox" row="3" column="2"> + <property name="name"> + <cstring>twoWordSubSB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maxValue"> + <number>14</number> + </property> + <property name="value"> + <number>10</number> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>twoWordSubCB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Use two word substitution</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>TextLabel2</cstring> + </property> + <property name="text"> + <string>Max number of words in the query:</string> + </property> + </widget> + <widget class="QLayoutWidget" row="5" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel5_3</cstring> + </property> + <property name="text"> + <string>[A-Za-z0-9_%</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>regExpLE</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel6_2</cstring> + </property> + <property name="text"> + <string>]</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="4" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>TextLabel4</cstring> + </property> + <property name="text"> + <string>Local characters for regular expressions:</string> + </property> + </widget> + <widget class="QSpinBox" row="1" column="2"> + <property name="name"> + <cstring>oneWordSubSB</cstring> + </property> + <property name="maxValue"> + <number>200</number> + </property> + <property name="minValue"> + <number>2</number> + </property> + <property name="value"> + <number>40</number> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>Widget6</cstring> + </property> + <attribute name="title"> + <string>Database</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>TextLabel7_2</cstring> + </property> + <property name="text"> + <string>Database folder:</string> + </property> + </widget> + <widget class="KURLRequester" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>dirInput</cstring> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>autoAddCB_2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Auto add entry to database</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Automatically add an entry to the database if a new translation is notified by someone (may be kbabel)</string> + </property> + </widget> + <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_4</cstring> + </property> + <property name="text"> + <string>Auto added entry author:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>authorLE</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Put here the name and email address that you want to use as <em>last translator</em> filed when you auto-add entry to the database (e.g. when you modify a translation with kbabel).<p></string> + </property> + </widget> + </hbox> + </widget> + <widget class="QPushButton" row="4" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>scanFilePB</cstring> + </property> + <property name="text"> + <string>Scan Single PO File...</string> + </property> + </widget> + <widget class="QPushButton" row="5" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>scanPB_2</cstring> + </property> + <property name="text"> + <string>Scan Folder...</string> + </property> + </widget> + <widget class="QPushButton" row="6" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>scanrecPB</cstring> + </property> + <property name="text"> + <string>Scan Folder && Subfolders...</string> + </property> + </widget> + <widget class="QLayoutWidget" row="8" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout5</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>filenameLB</cstring> + </property> + <property name="text"> + <string>Scanning file:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>entriesLB</cstring> + </property> + <property name="text"> + <string>Entries added:</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="9" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QProgressBar" row="2" column="1"> + <property name="name"> + <cstring>processPB</cstring> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="centerIndicator"> + <bool>true</bool> + </property> + <property name="indicatorFollowsStyle"> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel1_3</cstring> + </property> + <property name="text"> + <string>Total progress:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>TextLabel3_3</cstring> + </property> + <property name="text"> + <string>Processing file:</string> + </property> + </widget> + <widget class="QProgressBar" row="0" column="1"> + <property name="name"> + <cstring>totalPB</cstring> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="centerIndicator"> + <bool>true</bool> + </property> + </widget> + <widget class="QProgressBar" row="1" column="1"> + <property name="name"> + <cstring>loadingPB</cstring> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="centerIndicator"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>TextLabel2_3</cstring> + </property> + <property name="text"> + <string>Loading file:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QPushButton" row="10" column="2"> + <property name="name"> + <cstring>exportPB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Export...</string> + </property> + </widget> + <widget class="QPushButton" row="10" column="0"> + <property name="name"> + <cstring>statPB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Statistics</string> + </property> + </widget> + <widget class="QPushButton" row="10" column="1"> + <property name="name"> + <cstring>repeatPB</cstring> + </property> + <property name="text"> + <string>Repeated Strings</string> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Good Keys</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox4</cstring> + </property> + <property name="title"> + <string>Generic</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Here you can define how to fill the <em>good keys list</em>.<p> +You can set the minimum number of words of the query that a key must have to be inserted in the <em>good keys list</em>.<p> +You can also set the minimum number of words of the key that the query must have to insert the key in the list.<p> +These two numbers are the percentage of the total number of words. If the result of this percentage is less than one, the engine will set it to one.<p> +Finally you can set the maximum number of entries in the list.</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>TextLabel3_2</cstring> + </property> + <property name="text"> + <string>Minimum number of words of the key also in the query (%):</string> + </property> + <property name="textFormat"> + <enum>RichText</enum> + </property> + </widget> + <widget class="QSlider" row="1" column="0"> + <property name="name"> + <cstring>thresholdSL</cstring> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>SpinBox5</cstring> + </property> + <property name="suffix"> + <string>%</string> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>TextLabel2_2</cstring> + </property> + <property name="text"> + <string>Minimum number of query words in the key (%):</string> + </property> + </widget> + <widget class="QSpinBox" row="4" column="1"> + <property name="name"> + <cstring>maxSB</cstring> + </property> + <property name="maxValue"> + <number>5000</number> + </property> + <property name="value"> + <number>30</number> + </property> + </widget> + <widget class="QSpinBox" row="3" column="1"> + <property name="name"> + <cstring>SpinBox6</cstring> + </property> + <property name="suffix"> + <string>%</string> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>TextLabel4_2</cstring> + </property> + <property name="text"> + <string>Max list length:</string> + </property> + </widget> + <widget class="QSlider" row="3" column="0"> + <property name="name"> + <cstring>thresholdOrigSL</cstring> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox3_2</cstring> + </property> + <property name="title"> + <string>Frequent Words</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel1_2</cstring> + </property> + <property name="text"> + <string>Discard words more frequent than:</string> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>freqSB</cstring> + </property> + <property name="suffix"> + <string>/10000</string> + </property> + <property name="maxValue"> + <number>10000</number> + </property> + <property name="lineStep"> + <number>1</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>nothingCB</cstring> + </property> + <property name="text"> + <string>Frequent words are considered as in every key</string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </vbox> + </widget> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>thresholdSL</sender> + <signal>valueChanged(int)</signal> + <receiver>SpinBox5</receiver> + <slot>setValue(int)</slot> + </connection> + <connection> + <sender>thresholdOrigSL</sender> + <signal>valueChanged(int)</signal> + <receiver>SpinBox6</receiver> + <slot>setValue(int)</slot> + </connection> + <connection> + <sender>SpinBox5</sender> + <signal>valueChanged(int)</signal> + <receiver>thresholdSL</receiver> + <slot>setValue(int)</slot> + </connection> + <connection> + <sender>SpinBox6</sender> + <signal>valueChanged(int)</signal> + <receiver>thresholdOrigSL</receiver> + <slot>setValue(int)</slot> + </connection> +</connections> +<includes> + <include location="local" impldecl="in declaration">klocale.h</include> + <include location="global" impldecl="in declaration">kseparator.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kbabel/kbabeldict/modules/dbsearchengine/makemsgdb.C b/kbabel/kbabeldict/modules/dbsearchengine/makemsgdb.C new file mode 100644 index 00000000..a83d947b --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/makemsgdb.C @@ -0,0 +1,327 @@ +#include <stdio.h> +#include <time.h> +#include <errno.h> +#include <gdbm.h> +#include <string.h> + +void removechar (char *s, int c) +{ + int i, l; + l = strlen (s); + if ((c >= l) || (c < 0)) + return; + for (i = c; i < l; i++) + s[i] = s[i + 1]; +} +void removeallc (char *s, char c) +{ + char *pos; + while ((pos = strchr (s, c)) != 0) + removechar (s, (long int) pos - (long int) s); + +} + +void normalizestr (char *s) +{ + char *pos; + while ((pos = strstr (s, "#~")) != 0) { + removechar (s, (long int) pos - (long int) s); + removechar (s, (long int) pos - (long int) s); + } + while (strchr (s, ' ') == s) + removechar (s, 0); +} + +void freadline(char *buff,FILE *f) +{ +char c; +while ((fread(&c,1,1,f)==1) && (c!='\n')) + { + *buff=c; + buff++; + } +*buff=0; + +} + +int makePoDb(const char* sourceName,const char* outputName) +{ +static bool open = false; +int m=0,n=0,h=0; +GDBM_FILE db; +datum key,value; +char *s,a[20000],b[2000],k[2000],v[2000]; +int i,*np,nmax=0,co=-1,oldref[2000]; +long int tim; +FILE *mlf; +bool nextIsFuzzy; +bool isAMsgId=true; +/* char keystring[1000],valuestring[1000]; */ + +/*Read headers, refnum end other info */ +db = gdbm_open((char *)outputName,1024,GDBM_READER,0666,0); +mlf = fopen(sourceName,"r"); +if(strrchr(sourceName,'/')!=0) +sourceName=strrchr(sourceName,'/')+1; + +if(!(db==0)) + { + printf("ciao\n"); + key.dptr=a; + strcpy(a,"__@REFNUM__"); + key.dsize=strlen(a)+1; + value = gdbm_fetch(db,key); + np=(int*)value.dptr; + nmax=*np; + for(i=0;i<nmax;i++) { + sprintf(a,"__@%d__",i); + key.dsize=strlen(a)+1; + value = gdbm_fetch(db,key); + if(strcmp(value.dptr,sourceName)==0) + oldref[++co]=i; + // printf("File %s in Date %s\nRef # %d, oldref[%d]=%d\n",value.dptr,value.dptr+1+strlen(value.dptr),i,co,oldref[co]); + } + gdbm_close(db); + } + + +db = gdbm_open((char *)outputName,1024,GDBM_WRCREAT,0666,0); +if(db==0) return 0; + +nmax++; +//sourceName=strrchr(sourceName,'/')+1; + if(open) return 0; + open=true; + + key.dptr=a; + strcpy(a,"__@REFNUM__"); + key.dsize=strlen(a)+1; + value.dptr=(char *)&nmax; + value.dsize=4; + gdbm_store(db,key,value,GDBM_REPLACE); + sprintf(a,"__@%d__",nmax-1); + key.dsize=strlen(a)+1; + strcpy(v,sourceName); + value.dptr=v; + time(&tim); +// ctime(&tim); + // fprintf(stderr,"%s %s\n",v,ctime(&tim)); + strcpy(v+strlen(v)+1,ctime(&tim)); + value.dsize=strlen(v)+2+strlen(v+strlen(v)+1); + gdbm_store(db,key,value,GDBM_REPLACE); + + while(!feof(mlf)) + { + freadline(a,mlf); + normalizestr(a); +// printf("#%s#\n",a); + +// while (st.find("#~")==0) +// st = st.right(st.length()-2); +// while (st.find(" ")==0) +// st = st.right(st.length()-1); + + if(isAMsgId) nextIsFuzzy=false; + if(strstr(a,"#,")==a) + if(strstr(a,"fuzzy")!=0) nextIsFuzzy=true; + isAMsgId=(strstr(a,"msgid")); + if(isAMsgId && !nextIsFuzzy) + { + *b='\0'; + clearerr(mlf); + while(!feof(mlf) && !(strstr(a,"msgstr")==a)) + { + strcat(b,strchr(a,'"')+1); + *strrchr(b,'\"')= '\0'; //" + freadline(a,mlf); + normalizestr(a); + + + if(b+strlen(b)==strstr(b,"\\n")+2) + { + b[strlen(b)-2]='\n'; + b[strlen(b)-1]='\0'; + } + } + + // fprintf(stderr,"MSGID#%s#\n",b); + //} + + if(b[0]!='\0') { + key.dptr=k; + strcpy(k,b); + key.dsize=strlen(key.dptr)+1; + int lines=0; + *b='\0'; + while(!feof(mlf) && !(strstr(a,"msgid")==a) && !(strchr(a,'"')==0)) + { + lines++; + strcat(b,strchr(a,'"')+1); + *strrchr(b,'\"')= '\0'; //" + freadline(a,mlf); + normalizestr(a); + + + if(b+strlen(b)==strstr(b,"\\n")+2) + { + b[strlen(b)-2]='\n'; + b[strlen(b)-1]='\0'; + } + } + value.dptr=v; + int *t; + int *nr,*re; //,*md; //Number of references,ref + + t=(int *)value.dptr; + *t=1; + strcpy(value.dptr+4,b); + nr=(int *)(value.dptr+4+strlen(value.dptr+4)+1); + *nr=1; + nr++; + *nr=nmax-1; + value.dsize=strlen(value.dptr+4)+1+4+8; + // fprintf(stderr,"MSGSTR#%s#nref=%d\n",value.dptr+4, +// *(int*)(value.dptr+4+strlen(value.dptr+4)+1 )); + + if(b[0]!='\0') { + if(gdbm_store(db,key,value,GDBM_INSERT)) + { + // fprintf(stderr,"*** Key exists ***\n"); + + gdbm_sync(db); + gdbm_close(db); + db = gdbm_open((char *)outputName,1024,GDBM_READER,0,0); + datum oldvalue; + oldvalue= gdbm_fetch(db,key); + gdbm_sync(db); + gdbm_close(db); + db = gdbm_open((char *)outputName,1024,GDBM_WRCREAT,0,0); + + t=(int *)oldvalue.dptr; + int i,r,j; //counters + int v=*t; //Number of strings + int *nr,*re,*md; //Number of references,ref + bool exist=false,here,modif=false; + char *os=oldvalue.dptr+4; + // fprintf(stderr,"**Searching string #%s#\n",b); + for(i=0;i<v;i++) + { + + exist=false; //REMOVE THIS LINE!!! + here=false; + // fprintf(stderr,"**STRING %d #%s# len=%d %s\n",i,os,strlen(os),b); + if(strcmp(os,b)==0) { + exist=true; + here=true; + // fprintf(stderr,"That's good\n"); + } + os+=strlen(os)+1; //End of string + nr=(int *)os; + os+=(*nr+1)*4; + re=nr; + modif=false; + // fprintf(stderr,"refernces %d\n",*nr); + for(j=0;j<*nr;j++) + { + re++; + + if(here) + { + // printf("reference #%d\n",*re); + for(r=0;r<=co;r++) + { + // fprintf(stderr,"%d==%d ?-->",oldref[co],*re); + if(oldref[r]==*re) + { + modif=true; + // fprintf(stderr,"Yes\n"); + *re=(nmax-1); + } //else fprintf(stderr,"No\n"); + } + // fprintf(stderr,"qui\n"); + if(!modif) + md=nr; + // fprintf(stderr,"modif %s\n",modif ? "true":"false"); + } + } + + } + + if(!exist) + { + int oldlen=(long int)os-(long int)oldvalue.dptr-4; + memcpy(a+4,oldvalue.dptr+4,oldlen); +// fprintf(stderr,"***!exist Old len is %d+4 1st str is %s\n",oldlen,a+4); + v++; + t=(int *)a; + *t=v; + // fprintf(stderr,"b=%s",b); + strcpy(a+4+oldlen,b); + re=(int *)(a+4+oldlen+strlen(b)+1); + *re=1; + re++; + *re=nmax-1; + //fprintf(stderr,"a+4=%s a+4+oldlen=%s",a+4,a+4+oldlen); + value.dptr=a; + value.dsize=oldlen+strlen(b)+1+4+8; + gdbm_store(db,key,value,GDBM_REPLACE); + n++; + } else + { + if(!modif) + { +// fprintf(stderr,"grossa crisi %d\n",*md); +// fprintf(stderr,"Old num of ref \n"); + int oldlen1=(long int)(md)-(long int)(oldvalue.dptr)-4; + int oldlen2=(long int)(os)-(long int)(md)-4; //-4 because nr + memcpy(a+4,oldvalue.dptr+4,oldlen1); + memcpy(a+4+oldlen1+8,oldvalue.dptr+4+oldlen1+4,oldlen2); + re=(int *)(a+4+oldlen1); + *re=(*md )+1; + // *re++; + re++; + *re=nmax-1; + t=(int *)a; + *t=v; + value.dptr=a; + value.dsize=oldlen1+oldlen2+4+8; + gdbm_store(db,key,value,GDBM_REPLACE); + n++; + } + else //if (modif) + { + value.dptr=oldvalue.dptr; + value.dsize=oldvalue.dsize; + gdbm_store(db,key,value,GDBM_REPLACE); + } + } + + h++; + } else { + + m++; + } + } + } + + } + + + } + + fclose(mlf); + gdbm_close(db); + open=false; + printf("new Key in database %d\n old key found %d\n value added %d\n",m,h,n); + return m+n; +} + + + +main(int argc,char **argv) +{ +int i; +for(i=1;i<argc;i++) + printf("File %s:\nEntry added to dbase: %d\n",argv[i],makePoDb(argv[i],"messages2.db")); + +} diff --git a/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.cpp b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.cpp new file mode 100644 index 00000000..3bb65934 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.cpp @@ -0,0 +1,111 @@ +#include <qradiobutton.h> +#include <qslider.h> +#include <qspinbox.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <klocale.h> +#include <kfiledialog.h> +#include <kurlrequester.h> +#include <qtoolbutton.h> +#include <klineedit.h> +#include <kstandarddirs.h> + +#include "dbseprefwidget.h" +#include "preferenceswidget.h" + +PreferencesWidget::PreferencesWidget(QWidget *parent, const char* name) + : PrefWidget(parent,name) +{ + QVBoxLayout *layout = new QVBoxLayout(this); +// QLabel *label = new QLabel(i18n("Settings for KDE database search engine"),this); +// layout->addWidget(label); + + dbpw = new DBSearchEnginePref(this); + dbpw->dirInput->setMode(KFile::Directory | KFile::LocalOnly); + + layout->addWidget(dbpw); + resize(QSize(200,200).expandedTo(minimumSizeHint())); + +// connect(dbpw->browseTB_3,SIGNAL(clicked()),SLOT(browse1())); + + emit restoreNow(); //Fill with actual params. + +} + +PreferencesWidget::~PreferencesWidget() +{ +} + +void PreferencesWidget::apply() +{ +emit applyNow(); +} + +void PreferencesWidget::cancel() +{ +emit restoreNow(); +} + +void PreferencesWidget::standard() +{ + + +dbpw->caseSensitiveCB->setChecked(false); +dbpw->normalizeCB->setChecked(true); +dbpw->removeContextCB->setChecked(true); + +dbpw->oneWordSubCB->setChecked(true); +dbpw->twoWordSubCB->setChecked(false); + + +dbpw->RegExpRB->setChecked(false); +dbpw->normalTextRB->setChecked(true); +dbpw->equalCB->setChecked( true ); +dbpw->containsCB->setChecked( true); +dbpw->containedCB->setChecked( true ); + + +dbpw->oneWordSubSB->setValue(20); +dbpw->twoWordSubSB->setValue(8); + +dbpw->maxSB->setValue(500); +dbpw->thresholdSL->setValue(50); +dbpw->thresholdOrigSL->setValue(50); + +dbpw->allRB->setChecked( false); +dbpw->slistRB->setChecked( true); +dbpw->rlistRB->setChecked( false ); + +dbpw->nothingCB->setChecked(true); +dbpw->freqSB->setValue(300); + +dbpw->ignoreLE->setText("&.:"); + +dbpw->autoAddCB_2->setChecked(true); + +QString defaultDir; + KStandardDirs * dirs = KGlobal::dirs(); + if(dirs) + { + defaultDir = dirs->saveLocation("data"); + if(defaultDir.right(1)!="/") + defaultDir+="/"; + defaultDir += "kbabeldict/dbsearchengine"; + } + + dbpw->dirInput->setURL(defaultDir); +} + +void PreferencesWidget::setName(QString n) +{ +dbpw->filenameLB->setText(i18n("Scanning file: %1").arg(n)); +} + +void PreferencesWidget::setEntries(int i) +{ +dbpw->entriesLB->setText(i18n("Entries added: %1").arg(i)); + +} + +#include "preferenceswidget.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.h b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.h new file mode 100644 index 00000000..599408cd --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.h @@ -0,0 +1,28 @@ +#ifndef PREFERENCESWIDGET_H +#define PREFERENCESWIDGET_H + +#include "searchengine.h" +#include "dbseprefwidget.h" + +class PreferencesWidget : public PrefWidget +{ + Q_OBJECT + +public: + PreferencesWidget(QWidget *parent=0, const char* name=0); + virtual ~PreferencesWidget(); + + virtual void apply(); + virtual void cancel(); + virtual void standard(); + DBSearchEnginePref *dbpw; +public slots: + void setName(QString); + void setEntries(int); +signals: + void applyNow(); + void restoreNow(); + +}; + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/AUTHOR b/kbabel/kbabeldict/modules/dbsearchengine2/AUTHOR new file mode 100644 index 00000000..2a79312d --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/AUTHOR @@ -0,0 +1 @@ +Andrea Rizzi <rizzi@kde.org>
\ No newline at end of file diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.cpp new file mode 100644 index 00000000..5bf088b8 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.cpp @@ -0,0 +1,686 @@ +/*************************************************************************** + 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 Qt library by Trolltech AS, Norway (or with modified versions * + * of Qt that use the same license as Qt), 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 * + * Qt. 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 <klineedit.h> +#include <kapplication.h> +#include <qpushbutton.h> +#include <kurlrequester.h> +#include <qcheckbox.h> +#include <knuminput.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> + +#include <qmap.h> + +#include <kdebug.h> +#define i18n (const char *) + +KDBSearchEngine2::KDBSearchEngine2(QObject *parent,const char*name) + : SearchEngine(parent,name) + { + pw=0; + dbDirectory="."; + + di=0; //Database Interface is not yet initialized + + connect(this,SIGNAL(hasError(QString)),SLOT(setLastError(QString))); + + 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(QString str) +{ + kdDebug(0) << "Start a new search. Looking for: " << str << endl; + + static QString 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 + + QString 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,SIGNAL(newResult(QueryResult)),this,SLOT(receiveResult(QueryResult))); + strategy.exec(searchingString); disconnect(&strategy,SIGNAL(newResult(QueryResult)),this,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(QString str) +{ + if(autoupdate) + { + updateSettings(); + } + + //TODO!!!! + return true; + +} + + + +bool KDBSearchEngine2::messagesForPackage(const QString& package + , QValueList<Message>& resultList, QString& error) +{ + //FIXME implement this (needs filters) + return true; +} + + +void KDBSearchEngine2::setLastError(QString er) +{ + lasterror=er; +} + +QString KDBSearchEngine2::translate(const QString 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) + QString requested; + QString found; + QString translation; + QString plainTranslation; + QString plainFound; + QString plainRequested; + int score; + QPtrList<TranslationInfo> 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,SIGNAL(newResult(QueryResult)),this,SLOT(receiveResult(QueryResult))); + //FIXME: what wbout ready() + if(!di->mainOk()) return false; //check if the main DB is OK. + + return true; + } + +} +const KAboutData *KDBSearchEngine2::about() const +{ + return DbSe2Factory::instance()->aboutData(); +} + +void KDBSearchEngine2::stringChanged( QString orig, QString translated + , QString description) +{ + + if(!init()) return; + //if(translated.isEmpty()) return; + InputInfo ii; + if(description.find("fuzzy",false)==-1) + di->addEntry(orig,translated,&ii); + +} + +PrefWidget * KDBSearchEngine2::preferencesWidget(QWidget *parent) +{ + + pw = new KDB2PreferencesWidget(parent); + kdDebug(0) << "new KDB2 preferences widget" << endl; + setSettings(); + connect(pw,SIGNAL(restoreNow()),this,SLOT(setSettings())); + connect(pw,SIGNAL(applyNow()),this,SLOT(updateSettings())); + connect(pw,SIGNAL(destroyed()),this,SLOT(prefDestr())); + + + connect(pw->dbpw->scanAll,SIGNAL(clicked()),this,SLOT(scanAllPressed())); + connect(pw->dbpw->scanSource,SIGNAL(clicked()),this,SLOT(scanNowPressed())); + connect(pw->dbpw->addSource,SIGNAL(clicked()),this,SLOT(addSource())); + connect(pw->dbpw->editSource,SIGNAL(clicked()),this,SLOT(editSource())); + connect(pw->dbpw->removeSource,SIGNAL(clicked()),this,SLOT(removeSource())); + + + return pw; +} + +void KDBSearchEngine2::saveSettings(KConfigBase *config) +{ + KConfigGroupSaver 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(QMap<QString,MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt) + { + sourceNumber++; + config->setGroup("DBImportSource-"+QString::number(sourceNumber)); + config->writeEntry("Name",sourceIt.key()); + sourceIt.data().writeConfig(config); + } +} + +void KDBSearchEngine2::readSettings(KConfigBase *config) +{ + + /*QString defaultDir; + KStandardDirs * dirs = KGlobal::dirs(); + if(dirs) + { + defaultDir = dirs->saveLocation("data"); + if(defaultDir.right(1)!="/") + defaultDir+="/"; + defaultDir += "kbabeldict/dbsearchengine2"; + } +*/ + KConfigGroupSaver 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-"+QString::number(sourceNumber)); + QString 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(QMap<QString,MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt) + { + pw->dbpw->sourceList->insertItem(sourceIt.key()); + } + } + +} + +void KDBSearchEngine2::updateSettings() +{ + if(!pw) return; + + QString 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(QString sourceName) +{ + //FIXME: an error here would be nice + if(!init()) return; + + + for(QValueList<MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); sourceIt++) + { + if((*sourceIt).getName()==sourceName) + { + QValueList<KURL> urls=(*sourceIt).urls(); + PoScanner ps(di); + for(QValueList<KURL>::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; + } + QString sourceName; + sourceName=pw->dbpw->sourceList->currentText(); + if(!init()) return; + if(sources.contains(sourceName)) + { + QValueList<KURL> urls=sources[sourceName].urls(); + PoScanner ps(di); + for(QValueList<KURL>::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(QMap<QString,MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt) + { + QValueList<KURL> urls=(*sourceIt).urls(); + for(QValueList<KURL>::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; + } + QString sourceName; + sourceName=pw->dbpw->sourceList->currentText(); + + if(sources.contains(sourceName)) + { + bool nameIsNew; + QString newName; + SourceDialog sd; + do{ + sources[sourceName].setDialogValues(&sd); + sd.sourceName->setText(sourceName); + if(sd.exec()==QDialog::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; + } + QString sourceName; + sourceName=pw->dbpw->sourceList->currentText(); + sources.remove(sourceName); + pw->dbpw->sourceList->removeItem(pw->dbpw->sourceList->currentItem()); + +} + +void KDBSearchEngine2::addSource() +{ + QString newName; + SourceDialog sd; + bool nameIsNew; + do{ + if(sd.exec()==QDialog::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); + + +} +QString KDBSearchEngine2::searchTranslation( const QString 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(); + +} + +QString KDBSearchEngine2::fuzzyTranslation( const QString 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" + diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.h b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.h new file mode 100644 index 00000000..0db19c6c --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.h @@ -0,0 +1,202 @@ +/* **************************************************************************** + +DBSE2 +Andrea Rizzi + +**************************************************************************** */ + +#ifndef DBSEARCH_ENGINE2_H +#define DBSEARCH_ENGINE2_H + +#include <searchengine.h> +#include <qdialog.h> + +#include "database.h" +#include "dbse2_factory.h" +#include "preferenceswidget.h" +#include "dbscan.h" +#include "sourcedialog.h" + +//#include "DBSESettings.h" + +class KDBSearchEngine2 : public SearchEngine +{ + Q_OBJECT + + public: + + KDBSearchEngine2(QObject *parent=0, const char *name=0); + virtual ~KDBSearchEngine2(); + + //init if needed. + bool init(); + + /** @return true, if a search is currently active */ + bool isSearching() const {return searching;} + + void stopSearch() { if(di) di->stop();} + + + + /** @returns true, if it was initialized correctly */ + bool isReady() const {return iAmReady; } + + + void saveSettings(KConfigBase *config); + void readSettings(KConfigBase *config); + + + QString translate(const QString text); + + QString fuzzyTranslation(const QString text, int &score); + QString searchTranslation(const QString, int &score ); + + /** + * Finds all messages belonging to package package. If nothing is found, + * the list is empty. + * @param package The name of the file, something like "kbabel.po" + * @param resultList Will contain the found messages afterwards + * @param error If an error occured, this should contain a description + * + * @return true, if successfull + */ + bool messagesForPackage(const QString& package + , QValueList<Message>& resultList, QString& error); + + /** + * @returns true, if the searchresults are given as rich text + * the default implementation returns false + */ + bool usesRichTextResults(){return true;} + + /** @returns true, if the the entries in the database can be edited */ + bool isEditable(){return false;} + + /** + * @returns a widget which lets the user setup all preferences of this + * search engine. The returned widget should not be bigger than + * 400x400. If you need more space, you maybe want to use + * a tabbed widget. + * @param parent the parent of the returned widget + */ + virtual PrefWidget* preferencesWidget(QWidget *parent); + + /** @returns information about this SearchEngine */ + virtual const KAboutData *about() const; + + /** @returns the i18n name of this search engine */ + QString name() const {return i18n("DB SearchEngine II");} + + /** @returns a untranslated name of this engine */ + QString id() const {return "dbse2";} + + /** @returns the last error message */ + QString lastError() {return lasterror;} + + + /** + * sets the engine to always ask the preferences dialog for settings + * if is existing before starting the search. + */ + virtual void setAutoUpdateOptions(bool activate) + { + autoupdate=activate; + } + + + + public slots: + + void receiveResult(QueryResult r); + + /** + * starts a search for string s in the original text + * @returns false, if an error occured. Use @ref lastError + * to get the last error message + */ + bool startSearch(QString s); + + /** + * starts a search for string s in the translated text + * @returns false, if an error occured. Use @ref lastError + * to get the last error message + */ + bool startSearchInTranslation(QString s); + + + /** stops a search */ + // virtual void stopSearch() ; + + + /** + * This method allows a search engine to use different settings depending + * on the edited file. The default implementation does nothing. + * @param file The edited file with path + */ + // virtual void setEditedFile(QString file); + + /** + * This method allows a search engine to use different settings depending + * on the edited package. The default implementation does nothing. + * @param package The name of the package, that is currently translated. + */ + // virtual void setEditedPackage(QString package); + + /** + * This method allows a search engine to use different settings depending + * on the language code. The default implementation does nothing. + * @param lang The current language code (e.g. de). + */ + // virtual void setLanguageCode(QString lang); + // virtual void setLanguage(QString languageCode, QString languageName); + + + + /** + * This method is called, if something has been changed in the + * current file. See @ref setEditedFile if you want to know the file + * name + * @param orig the original string + * @param translation the translated string + */ + + void stringChanged( QString orig, QString translated + , QString description); + + //void scan(); + + void setLastError(QString er); + + //Slots for preference dialog + // void scanSource(QString sourceName); + void scanNowPressed(); + void scanAllPressed(); + void editSource(); + void removeSource(); + void addSource(); + + + private: + DataBaseInterface *di; + bool searching; + bool iAmReady; + bool autoupdate; + QString lasterror; + KDB2PreferencesWidget *pw; + + //PrefWidg -> DBSE + void updateSettings(); + //DBSE -> PrefWidg + void setSettings(); + + DBSESettings settings; + QString dbDirectory; + bool autoAdd,useSentence,useGlossary,useExact; + bool useDivide,useAlpha,useWordByWord,useDynamic; + uint numberOfResult; + QMap<QString,MessagesSource> sources; + +}; + + +#endif // SEARCH_ENGINE2_H diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/Makefile.am b/kbabel/kbabeldict/modules/dbsearchengine2/Makefile.am new file mode 100644 index 00000000..cdcd3083 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/Makefile.am @@ -0,0 +1,34 @@ +## Makefile.am for DBSE2 + +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +#SUBDIRS = + + +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +kde_module_LTLIBRARIES = kbabeldict_dbsearchengine2.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/../.. -I$(srcdir)/../../../common $(all_includes) -I$(DBIV_INCLUDES) + +# which sources should be compiled for kbabel +kbabeldict_dbsearchengine2_la_SOURCES = dbscan.cpp preferenceswidget.cpp dbse2.ui KDBSearchEngine2.cpp database.cpp dbentries.cpp dbse2_factory.cpp sourcedialog.ui algorithms.cpp chunk.cpp + +#kbabeldict_dbsearchengine2_la_SOURCES = KDBSearchEngine2.cpp database.cpp dbentries.cpp dbse2_factory.cpp +kbabeldict_dbsearchengine2_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO) $(LIB_DBIV)_cxx +kbabeldict_dbsearchengine2_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined -L$(DBIV_LDFLAGS) + + +# these are the headers for your project +noinst_HEADERS = KDBSearchEngine2.h database.h dbentries.h dbse2_factory.h +#chunk.h algorithms.h + + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +kde_services_DATA = dbsearchengine2.desktop +EXTRA_DIST = $(kde_services_DATA) + + diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/README b/kbabel/kbabeldict/modules/dbsearchengine2/README new file mode 100644 index 00000000..907ab84e --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/README @@ -0,0 +1,21 @@ +If you want to test this new plugin: +launch +# make ; make install in this directory +then (to create the database) +# source compile +# cp scan ~/mytestdir +# cd ~/mytestdir +# ./scan file.po (I suggest to download and scan $LANG.messages) + +ok now you can launch kbabel, you should be in the same +directory you launched "scan" from. + +# kbabel + + +change kbabel settings to use "DB Search Engine II" or use +CTRL+2 to search. + + +Bye +Andrea diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.cpp new file mode 100644 index 00000000..0ca040e8 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.cpp @@ -0,0 +1,425 @@ +// +// C++ Implementation: algorithms +// +// Description: +// +// +// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "algorithms.h" +#include <qstringlist.h> +#include <kdebug.h> + +//FIXME: remove +#define i18n (const char*) + +DataBaseInterface::ResultList ExactSearchAlgorithm::exec(const QString& query ) +{ + DataBaseInterface::ResultList res; + DataBaseInterface::MainEntry e=di->get(query,0); + + QStringList trs=e.second.getTranslations(); + + for(QStringList::iterator it=trs.begin();it!=trs.end();++it) + { + + emit newResult(QueryResult(*it,e.first.getString(),settings->scoreExact)); + + res.push_back(QueryResult(*it)); + } + kdDebug(0) <<"Exact algo found " << res.count() << "entries" << endl; + return res; +} + + +DataBaseInterface::ResultList GenericSearchAlgorithm::exec(const QString& query ) +{ + DataBaseInterface::ResultList res; + // ExactSearchAlgorithm exact(query,settings); + uint countResults=0; + for(QValueList<AbstractSearchAlgorithm *>::iterator algoit = algoChain.begin(); algoit!=algoChain.end() && countResults < maxResults; algoit++) + { + connect(*algoit,SIGNAL(newResult(QueryResult)),this,SIGNAL(newResult(QueryResult))); + kdDebug(0) << "Algo pointer" << (*algoit) << endl; + res+=(*algoit)->exec(query); + countResults=res.count(); + kdDebug(0) << "Count = " << countResults << endl; + disconnect(*algoit,SIGNAL(newResult(QueryResult)),this,SIGNAL(newResult(QueryResult))); + } + return res; +} + +void GenericSearchAlgorithm::addAlgorithm( AbstractSearchAlgorithm * algo ) +{ + algoChain.append(algo); +} + +DataBaseInterface::ResultList AlphaSearchAlgorithm::exec( const QString & query ) +{ + DataBaseInterface::ResultList res; + DBItemMultiIndex::IndexList il=di->getAlpha(query); + + for(DBItemMultiIndex::IndexList::iterator it=il.begin();it!=il.end()&&!di->stopNow();++it) + { + DataBaseInterface::MainEntry e=di->getFromIndex(*it); + QStringList trs=e.second.getTranslations(); + for(QStringList::iterator it=trs.begin();it!=trs.end() && !di->stopNow();++it) + { + QueryResult r(di->format(di->simple(*it,true),query),e.first.getString(),settings->scoreAlpha); + emit newResult(r); + res.push_back(r); + } + } + kdDebug(0) <<"Alpha algo found " << res.count() << "entries" << endl; + + return res; +} + +DataBaseInterface::ResultList SentenceArchiveSearchAlgorithm::exec( const QString & query ) +{ + DataBaseInterface::ResultList res; + + DataBaseInterface::MainEntry e = di->getSentence(query); + + QStringList trs=e.second.getTranslations(); + + kdDebug(0) << "Count in sentence archive " << trs.count()<< endl; + + for(QStringList::iterator it=trs.begin();it!=trs.end();++it) + { + QueryResult r(di->format(di->simple(*it,true),query),e.first.getString(),settings->scoreSentence); + emit newResult(r); + + res.push_back(r); + } + kdDebug(0) <<"Sentence algo found " << res.count() << "entries" << endl; + + return res; +} + +DataBaseInterface::ResultList ChunkByChunkSearchAlgorithm::exec( const QString & query ) +{ + ResultList res; + factory->setQuery(query); + QPtrList<AbstractChunk> chunks=factory->chunks(); + kdDebug(0) << "Number of chunks " << chunks.count() << endl; + chunks.setAutoDelete(true); //I should delete the chunks myself + QStringList querySeparators=factory->separators(); + + //This prevents recursive loop. + if (chunks.count()<=1) return res; + + QStringList translations,tmpTranslations; + + translations.push_back(""); //FIXME this is needed to start , but is not good + int finalscore=0; + int i=0; + QMap<QString,bool> translationUsed; + + //Loop on all chunk + for(AbstractChunk *it=chunks.first();it && !di->stopNow(); it=chunks.next()) + { + kdDebug(0) << "Process next chunk" << endl; + int chunkscore=0; + QValueList<QueryResult> r=it->translations(); + kdDebug(0) << "Number of results for this chunk " << r.count() << endl; + + if(r.count()<1) { + // kdDebug(0) << "Nothing found for:" << it->translations() << endl; + chunkscore=-10; + + } + else + { + //FIXME: check this, why 0? it is the best one? + chunkscore=r[0].score(); + kdDebug(0) << "ChunkScore " << chunkscore << endl; + tmpTranslations.clear(); + + + //Loop on results + translationUsed.clear(); + for(ResultList::iterator it1=r.begin();it1!=r.end() &&!di->stopNow(); ++it1) + { + QString chunkTranslation= (*it1).result(); + if(!translationUsed.contains(chunkTranslation)) + { + translationUsed[chunkTranslation]=true; + kdDebug(0) << "a translation is: " << chunkTranslation << endl; + for(QStringList::iterator it2=translations.begin();it2!=translations.end() && !di->stopNow() ; it2++) + { + QString prevTranslation=*it2; + tmpTranslations.push_back(prevTranslation+chunkTranslation+querySeparators[i]); + kdDebug(0) << "..appending it to " << prevTranslation << endl; + } + } + } + + translations=tmpTranslations; + + } + + //kdDebug(0) << it-> << r[0].result() << "#" << querySeparators[i] << endl; + i++; + finalscore+=chunkscore; + + kdDebug(0) << "partial score " << finalscore; + } + kdDebug(0) << "this is finishd" << endl; + if(settings->scoreChunkByChunk==0) + settings->scoreChunkByChunk=1; +// FIXME:fix the score system +// finalscore/=(i*100*100/settings->scoreChunkByChunk); //change 100 to 120(?) to lower this result (done) + + if (finalscore<50) return res; + + for(QStringList::iterator it2=translations.begin();it2!=translations.end() && !di->stopNow() ; it2++) + { + QString theTranslation=*it2; + QueryResult qr(di->format(theTranslation,query),i18n("CHUNK BY CHUNK"),finalscore); + qr.setRichOriginal(i18n("<h3>Chunk by chunk</h3>CHANGE THIS TEXT!!!!This translation is" + "obtained translating the sentences and using a" + "fuzzy sentence translation database.<br>" + " <b>Do not rely on it</b>. Translations may be fuzzy.<br>")); + qr.setRichResult("<font color=#800000>"+theTranslation+"</font>") ; + emit newResult(qr); + res.push_back(qr); + } + + + return res; + + +} + +ChunkByChunkSearchAlgorithm::ChunkByChunkSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ): AbstractSearchAlgorithm(dbi,sets) , factory(0) +{ + +} + + +SentenceArchiveSearchAlgorithm::SentenceArchiveSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ): AbstractSearchAlgorithm(dbi,sets) +{ +} + +FuzzyChunkSearchAlgorithm::FuzzyChunkSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ) : AbstractSearchAlgorithm(dbi,sets) +{ + +} + + +DataBaseInterface::ResultList FuzzyChunkSearchAlgorithm::exec( const QString & query ) +{ + //FIXME: this code is shit too + ResultList res; + factory->setQuery(query); + QPtrList<AbstractChunk> querychunks = factory->chunks(); + querychunks.setAutoDelete(true); + + typedef QMap<QString,QValueList<unsigned int> > ResultMap; + ResultMap rmap; //result of words index query + unsigned int notfound=0,frequent=0,nchunks = querychunks.count(); + + //Get index list for each word + for(AbstractChunk *it=querychunks.first(); it &&!di->stopNow() ; it=querychunks.next() ) + { + QValueList<uint> locations = (*it).locationReferences(); + + if(locations.count()>0) + { + rmap[(*it).chunkString()] = locations; + + if(locations.count()>1000) //FIXME NORMALIZE THIS!!! + { + frequent++; + kdDebug(0) << "\""<<(*it).chunkString() << "\" is frequent" <<endl; + } + } + else + notfound++; + + } + + + //Now we have a map (rmap) "word in query->list of occurency" + + QValueList<unsigned int>::iterator countpos[nchunks+1]; + + + QValueList<unsigned int> il; + for(int i = 0;i<=nchunks&&!di->stopNow();i++) + countpos[i]=il.end(); + + unsigned int bestcount=0; + while(!rmap.isEmpty()) + { + unsigned int ref,count; + ref=(unsigned int)-1; + count=0; + + + //This will find the min head and count how many times it occurs + for(ResultMap::iterator it = rmap.begin();it!=rmap.end()&&!di->stopNow();++it) + { + unsigned int thisref=it.data().first(); + if(thisref<ref) + { + ref=thisref; + count=0; + } + if(thisref==ref) + { + count++; + } + + } + + + for(ResultMap::iterator it = rmap.begin();it!=rmap.end()&&!di->stopNow();) + { + it.data().remove(ref); + + //kdDebug(0)<< ((frequent<(nwords-notfound)) && (it.data().count()>350)) <<endl; + //FIXME: I think the frequent word check is not in the right place + if(it.data().isEmpty() || (((frequent+notfound)<nchunks) && (it.data().count()>1000))) + //very dirty hack... + { + + ResultMap::iterator it2=it; + it++; + rmap.remove(it2); + } + else it++; + + } + + //This should be configurable or optimized: + if(count>=(nchunks-notfound)*0.50 && count!=0) + { + il.insert(countpos[count],ref); + for(unsigned int i = nchunks;i>=count;i--) + if(countpos[i]==countpos[count]) + countpos[i]--; + } + } + + //loop on number of words found + int bestscore=0; + + for(unsigned int wf=nchunks;wf>0;wf-- ){ + for(QValueList<unsigned int>::iterator it=countpos[wf];it!=countpos[wf-1] ;++it) + { //loop on entries with same number of word found + DataBaseInterface::MainEntry e; + e=di->getFromIndex(*it); + QStringList trs=e.second.getTranslations(); + for(QStringList::iterator it=trs.begin();it!=trs.end()&&!di->stopNow();++it) + { + unsigned int cinr=factory->chunks(*it).count(); //chunk in result + //compute a score, lets kbabel sort now, it should be fast... + int score=90*wf/nchunks-(signed int)90*(((nchunks-cinr)>0)?(nchunks-cinr):(cinr-nchunks))/(nchunks*10); + if(score>bestscore) bestscore=score; + if(score>bestscore*0.40) + { + // kdDebug(0) << "s: "<<score << " wf: "<<wf<<" nwords: "<<nwords<<" winr: "<<winr + // <<" 90*wf/nwords: "<<90*wf/nwords << " -:" << 90*(((nwords-winr)>0)?(nwords-winr):(winr-nwords))/(nwords*10)<< endl; + // FIXME: format better the richtext + QString ori=e.first.getString(); + QString re=di->format(di->simple(*it,true),query); + QueryResult r(re,ori,score); + for(QPtrListIterator<AbstractChunk> it(querychunks); it.current() && di->stopNow() ; ++it){ + ori=ori.replace(QRegExp((*it)->chunkString(),false),"<font color=#000080><u><b>"+(*it)->chunkString()+"</b></u></font>"); + } + r.setRichOriginal(ori); + if(!di->stopNow()) + emit newResult(r); + res.push_back(r); + } + } + } + } + return res; + +} + +DataBaseInterface::ResultList CorrelationSearchAlgorithm::exec( const QString & query ) +{ + //FIXME, this code is shit. + DataBaseInterface::ResultList res; + if(di->words(query).count()>1) return res; + QMap<QString,float> corRes = di->correlation(query,0,false); + float max=0,max1=0,max2=0; + QString best,best1,best2; + + for(QMap<QString,float>::iterator it = corRes.begin(); it !=corRes.end(); ++it) + { + if(it.data()>max) + { + max2=max1; + best2=best1; + max1=max; + best1=best; + best = it.key(); + max=it.data(); + + } + + + } + if(!best.isEmpty()) + { + double myscore=0.01*max*settings->scoreDynamic; + QueryResult r(di->format(best,query),i18n("DYNAMIC DICT:"),myscore); + r.setRichOriginal(i18n("<h3>Dynamic Dictionary</h3>This is a dynamic dictionary created" + " looking for correlation of original and translated words.<br>" + " <b>Do not rely on it</b>. Translations may be fuzzy.<br>")); + r.setRichResult("<font size=+2 color=#A00000>"+di->format(best,query)+"</font>") ; + res.push_back(r); + if(!di->stopNow()) + emit newResult(r); + } + if(!best1.isEmpty()) + { + double myscore=0.01*max1*settings->scoreDynamic; + QueryResult r(di->format(best1,query),i18n("DYNAMIC DICT:"),myscore); + r.setRichOriginal(i18n("<h3>Dynamic Dictionary</h3>This is a dynamic dictionary created" + " looking for correlation of original and translated words.<br>" + " <b>Do not rely on it</b>. Translations may be fuzzy.<br>")); + r.setRichResult("<font size=+2 color=#800000>"+di->format(best1,query)+"</font>") ; + res.push_back(r); + if(!di->stopNow()) + emit newResult(r); + } + + kdDebug(0) << "Correlation algorithm found" << res.count() << "results"; + return res; + +} + +GenericSearchAlgorithm::GenericSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ): AbstractSearchAlgorithm(dbi,sets) +{ + maxResults = 5; //FIXME use as default somthing from DBSESettings +} + +SingleWordSearchAlgorithm::SingleWordSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ) : GenericSearchAlgorithm(dbi,sets), + exact(dbi,sets), alpha(dbi,sets), sentence(dbi,sets), corr(dbi,sets), chunk(dbi,sets),casefactory(dbi) + { + addAlgorithm(&exact); + addAlgorithm(&alpha); + addAlgorithm(&sentence); + chunk.setChunkFactory(&casefactory); + addAlgorithm(&chunk); + addAlgorithm(&corr); +} + +DataBaseInterface::ResultList SingleWordSearchAlgorithm::exec( const QString & query ) +{ + if(di->words(query).count()>1) + return ResultList(); + return GenericSearchAlgorithm::exec(query); +} + + +//#include "algorithms.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.h b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.h new file mode 100644 index 00000000..5f9ee682 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.h @@ -0,0 +1,157 @@ +// +// C++ Interface: strategies +// +// Description: +// +// +// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DBSE2_STRATEGIES_H +#define DBSE2_STRATEGIES_H + +#include "database.h" +#include "chunk.h" +#include <qobject.h> + +class AbstractSearchAlgorithm : public QObject +{ + Q_OBJECT + public: + + typedef QValueList<QueryResult> ResultList; + + AbstractSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) + { + di=dbi; + settings=sets; + } + /** + * this contains the algo and return some results. + */ + virtual DataBaseInterface::ResultList exec(const QString& query)=0; + + signals: + void newResult(QueryResult); + + protected: + DataBaseInterface *di; + DBSESettings *settings; + +}; + + + +class ExactSearchAlgorithm : public AbstractSearchAlgorithm +{ + Q_OBJECT + public: + ExactSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) : AbstractSearchAlgorithm(dbi,sets) {} + + virtual DataBaseInterface::ResultList exec(const QString& query); +}; + +class AlphaSearchAlgorithm : public AbstractSearchAlgorithm +{ + Q_OBJECT + public: + AlphaSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) : AbstractSearchAlgorithm(dbi,sets) {} + + virtual DataBaseInterface::ResultList exec(const QString& query); +}; + +class SentenceArchiveSearchAlgorithm : public AbstractSearchAlgorithm +{ + Q_OBJECT + public: + SentenceArchiveSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) ; + + virtual DataBaseInterface::ResultList exec(const QString& query); +}; + +class ChunkByChunkSearchAlgorithm : public AbstractSearchAlgorithm +{ + Q_OBJECT + public: + ChunkByChunkSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets); + + virtual DataBaseInterface::ResultList exec(const QString& query); + + void setChunkFactory(AbstractChunkFactory *_factory) + { + factory=_factory; + } + protected: + AbstractChunkFactory *factory; +}; + +class FuzzyChunkSearchAlgorithm : public AbstractSearchAlgorithm +{ + Q_OBJECT + public: + FuzzyChunkSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets); + + virtual DataBaseInterface::ResultList exec(const QString& query); + void setChunkFactory(AbstractChunkFactory *_factory) + { + factory=_factory; + } + protected: + AbstractChunkFactory *factory; +}; + +class GenericSearchAlgorithm : public AbstractSearchAlgorithm +{ + Q_OBJECT + public: + GenericSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) ; + + virtual ResultList exec(const QString& query); + + void addAlgorithm(AbstractSearchAlgorithm *algo); + void setMaxResultNumber(uint num){maxResults=num;} + + + protected: + QValueList<AbstractSearchAlgorithm *> algoChain; + uint maxResults; + }; + + +class CorrelationSearchAlgorithm : public AbstractSearchAlgorithm +{ + Q_OBJECT + public: + CorrelationSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) : AbstractSearchAlgorithm(dbi,sets) {} + virtual ResultList exec(const QString& query); +}; + + + +class SingleWordSearchAlgorithm : public GenericSearchAlgorithm +{ + Q_OBJECT + public: + SingleWordSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets); + virtual DataBaseInterface::ResultList exec(const QString& query); + + private: + ExactSearchAlgorithm exact; + AlphaSearchAlgorithm alpha; + SentenceArchiveSearchAlgorithm sentence; + CorrelationSearchAlgorithm corr; + ChunkByChunkSearchAlgorithm chunk; + CaseBasedWordChunkFactory casefactory; +}; + + +class UpdateChunkIndexAlgorithm +{ + +}; + + + +#endif //DBSE2_STRATEGIES_H diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/chunk.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.cpp new file mode 100644 index 00000000..7c62748a --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.cpp @@ -0,0 +1,203 @@ +// +// C++ Implementation: chunk +// +// Description: +// +// +// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "chunk.h" +#include "algorithms.h" +#include <kdebug.h> + + + +AbstractChunk::~AbstractChunk( ) +{ +} + +WordChunk::WordChunk( DataBaseInterface * di, QString _word ) : AbstractChunk(di) +{ + word=_word; +} + +QValueList<QueryResult> WordChunk::translations( ) +{ + DataBaseInterface::ResultList r; + SingleWordSearchAlgorithm sa(di,di->getSettings()); + r=sa.exec(word); + return r; +} + +//QValueList<QueryResult> WordChunk::translationsFromReference( uint reference ) +//{ +//} + +QValueList< uint > WordChunk::locationReferences( ) +{ + QValueList<uint> res=di->getWordIndex(word); + kdDebug(0) << "Number of locations " << res.count() <<endl ; + return res; +/* DBItemMainKey *k = new DBItemMainKey(word); + DBItemMultiIndex *d = new DBItemMultiIndex(); + if(wordsindex->get(k,d)!=DB_NOTFOUND) + return d->getList(); + else + return QValueList<uint> tmpList; +*/ +} + +void WordChunk::setLocationReferences( QValueList< uint > ) +{ +} + +SentenceChunk::SentenceChunk( DataBaseInterface * di, QString _sentence ): AbstractChunk(di) +{ + sentence=_sentence; +} + +QValueList<QueryResult> SentenceChunk::translations( ) +{ + GenericSearchAlgorithm g(di,di->getSettings()); + + ExactSearchAlgorithm e(di,di->getSettings()); + AlphaSearchAlgorithm a(di,di->getSettings()); + SentenceArchiveSearchAlgorithm s(di,di->getSettings()); + + g.addAlgorithm(&e); + g.addAlgorithm(&a); + g.addAlgorithm(&s); + + return g.exec(sentence); + +} + +//QValueList<QueryResult> SentenceChunk::translationsFromReference( uint reference ) +//{ +// +//} + +QValueList< uint > SentenceChunk::locationReferences( ) +{ +} + +void SentenceChunk::setLocationReferences( QValueList< uint > ) +{ +} + +QPtrList< AbstractChunk> WordChunkFactory::chunks() +{ + QString str=di->simple(string); + QPtrList<AbstractChunk> list; + if(str.isEmpty()) return list; + _separators.clear(); + kdDebug(0) << "Word chunks of:" <<str << endl; + int pos; + QString sep; + QRegExp r("(\\s)"); + do { + pos=r.search(str); + + sep=r.cap(1); + if(!str.left(pos).isEmpty()){ + //WordChunk *c=new WordChunk(di,di->simple(str.left(pos))) + list.append(new WordChunk(di,str.left(pos))); + _separators.append(sep); + } + else + { + uint current=_separators.count()-1; + _separators[current]=_separators[current]+sep; + } + str=str.remove(0,pos+1); + } while(!str.isEmpty() && pos != -1); + + return list; +} + + + +QPtrList<AbstractChunk> SentenceChunkFactory::chunks() +{ + QString str=string; + QPtrList<AbstractChunk> list; + if(str.isEmpty()) return list; + + // kdDebug(0) << s << endl; + + int pos; + + + do { + QRegExp re("((\\.|;|\\?|\\!|:)( |$|\\\\n\\n))"); + pos=re.search(str); + QString sep=re.cap(1); + + if(!str.left(pos).isEmpty()) + { + list.append(new SentenceChunk(di,str.left(pos).stripWhiteSpace())); + _separators.append(sep); + } + else + { + uint current=_separators.count()-1; + _separators[current]=_separators[current]+sep; + } + + str=str.remove(0,pos+re.cap(1).length()); + } while(!str.isEmpty() && pos != -1); + + + return list; + +} +QPtrList< AbstractChunk > CaseBasedWordChunkFactory::chunks( ) +{ + QString str=string; + QPtrList<AbstractChunk> list; + if(str.isEmpty()) return list; + uint slen=str.length(); + kdDebug(0) << "CaseWordChunk string:" << str << endl; + QString tmpWord; + bool upcase; + for(uint i=0;i<=slen;i++) + { + bool tmpCase=(str[i]==str[i].upper()); + if(upcase!=tmpCase) + { + if(!tmpWord.isEmpty() && !tmpWord.isNull()){ + list.append(new WordChunk(di,tmpWord)); + _separators.append(""); + } + kdDebug(0) << "CaseWordChunk:" << tmpWord << endl; + tmpWord=""; + + } + tmpWord+=str[i]; + upcase=tmpCase; + } + + return list; +} + +WordChunkFactory::WordChunkFactory( DataBaseInterface * _di ) : AbstractChunkFactory(_di) +{ +} + +SentenceChunkFactory::SentenceChunkFactory( DataBaseInterface * _di ): AbstractChunkFactory(_di) +{ +} + +CaseBasedWordChunkFactory::CaseBasedWordChunkFactory( DataBaseInterface * _di ): AbstractChunkFactory(_di) +{ +} + + + + + + + diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/chunk.h b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.h new file mode 100644 index 00000000..5c5fcb93 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.h @@ -0,0 +1,151 @@ +// +// C++ Interface: chunk +// +// Description: +// +// +// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DBSE2_CHUNK_H +#define DBSE2_CHUNK_H +#include <qstring.h> +#include <qvaluelist.h> +#include "database.h" + +/** + * Abstract class for text chunks. + * Examples of chunks are "Words" or "Sentences" + * This abstraction allow to use generic algorithm on chunks, + * like chunkByChunk translation or chunk indexing. + */ +class AbstractChunk +{ + public: + AbstractChunk(DataBaseInterface *_di) {di=_di;} + virtual ~AbstractChunk(); + /** + * This function should return a list of translation for the current chunk. + */ + virtual QValueList<QueryResult> translations()=0; + + //FIXME: is this in the right place, better in factory? check that stuff + //virtual QValueList<QueryResult> translationsFromReference(uint reference)=0; + virtual QValueList<uint> locationReferences()=0; + virtual void setLocationReferences(QValueList<uint>)=0; + virtual QString chunkString()=0; + + protected: + DataBaseInterface *di; +}; + +/** + * Concrete impl of Chunk, in this case chunks are words. + */ +class WordChunk : public AbstractChunk +{ + public: + WordChunk(DataBaseInterface *di,QString _word); + virtual QValueList<QueryResult> translations(); + //virtual QValueList<QueryResult> translationsFromReference(uint reference); + virtual QValueList<uint> locationReferences(); + virtual void setLocationReferences(QValueList<uint>); + virtual QString chunkString(){return word;} + + //static QValueList<WordChunk> divide(QString); + private: + QString word; +}; + +/** + * Concrete impl of Chunk, in this case chunks are sentences. + */ +class SentenceChunk : public AbstractChunk +{ + public: + SentenceChunk(DataBaseInterface *di,QString _sentence); + virtual QValueList<QueryResult> translations(); + //virtual QValueList<QueryResult> translationsFromReference(uint reference); + virtual QValueList<uint> locationReferences(); + virtual void setLocationReferences(QValueList<uint>); + virtual QString chunkString(){return sentence;} + + // static QValueList<SentenceChunk> divide(QString); + + private: + QString sentence; +}; + + +/********************************** + CHUNK FACTORIES +**********************************/ + + +class AbstractChunkFactory +{ + public: + AbstractChunkFactory(DataBaseInterface *_di) + { + di=_di; + } + virtual ~AbstractChunkFactory(){} + virtual QPtrList<AbstractChunk> chunks()=0; + /** + Change th string and return the chunks + */ + virtual QPtrList<AbstractChunk> chunks(const QString& s) + { + string=s; + return chunks(); + } + /** + * Returns the list of separators of last @ref chunks() call + */ + + virtual QStringList separators(){ return _separators;} + void setQuery(const QString& s) + { + string=s; + } + protected: + QString string; + QStringList _separators; + DataBaseInterface *di; +}; + +class WordChunkFactory : public AbstractChunkFactory +{ + public: + WordChunkFactory(DataBaseInterface *_di); + /** + YOU SHOULD DELETE THE CHUNKS!! + */ + virtual QPtrList<AbstractChunk> chunks(); +}; + +class CaseBasedWordChunkFactory : public AbstractChunkFactory +{ + public: + CaseBasedWordChunkFactory(DataBaseInterface *_di); + /** + YOU SHOULD DELETE THE CHUNKS!! + */ + virtual QPtrList<AbstractChunk> chunks(); +}; + +class SentenceChunkFactory : public AbstractChunkFactory +{ + public: + SentenceChunkFactory(DataBaseInterface *_di); + + /** + YOU SHOULD DELETE THE CHUNKS!! + */ + virtual QPtrList<AbstractChunk> chunks(); +}; + + +#endif //_CHUNK_H_ diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/database.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/database.cpp new file mode 100644 index 00000000..ea0e8379 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/database.cpp @@ -0,0 +1,752 @@ +/* + +DBSE 3 +(c) 2000-2003 Andrea Rizzi +License: GPLv2 + +*/ +#include <math.h> +#include "database.h" + +#include <qregexp.h> +#include <qdict.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kmessagebox.h> + +#define i18n (const char*) + + + + + + +DataBase::DataBase(QString dbpath,QString dbname, QString dblang) : Db(0,DB_CXX_NO_EXCEPTIONS) +{ + + filename=dbpath+"."+dblang+".db"; + database=dbname; + +} + +int DataBase::open(DBTYPE type,unsigned int flags) +{ + int ret; + ret = Db::open( +#if DB_VERSION_MINOR > 0 + NULL, +#endif + (const char*)filename.local8Bit(),(const char *)database.local8Bit(),type,flags,0644); + mytype=type; + return ret; +} + +unsigned int DataBase::getLast() +{ + if(mytype!=DB_RECNO) + return 0; + + Dbc *cur; + cursor(0,&cur,0); + DBItemNum index; + DBItemMainKey key; + cur->get(&index,&key,DB_LAST); + return index.getNum(); + +} + + + + + +QueryResult::QueryResult(QString r) +{ + res=r; +} +QueryResult::QueryResult(QString r,QString o,int s) +{ + res=r; + richr=r; + orig=o; + richo=o; + sco=s; +} + +QueryResult::QueryResult() +{ + res=""; +} + + + + +DataBaseInterface::DataBaseInterface(QString dir, DBSESettings *sets) +{ + + //FIXME Better db names!! + main = openMyDataBase(dir+"/testm","main","it",DB_BTREE); + alpha = openMyDataBase(dir+"/testa","alpha","it",DB_BTREE); + numindex = openMyDataBase(dir+"/testn","numindex","it",DB_RECNO); + wordsindex = openMyDataBase(dir+"/testw","wordsindex","it",DB_BTREE); + sentence = openMyDataBase(dir+"/tests","sentence","it",DB_BTREE); + corr = openMyDataBase(dir+"/testc","corr","it",DB_BTREE); + transword = openMyDataBase(dir+"/testt","transword","it",DB_RECNO); + + // kdDebug(0) << main << endl; + // kdDebug(0) << alpha << endl; + settings=sets; + _stopNow=false; +} + +DataBaseInterface::~DataBaseInterface() +{ + + if(main){ + main->close(0); + delete main; + } + if(numindex){ + numindex->close(0); + delete numindex; + } + + if(alpha){ + alpha->close(0); + delete alpha; + } + if(wordsindex){ + wordsindex->close(0); + delete wordsindex; + } + if(sentence){ + sentence->close(0); + delete sentence; + } + +} + +DataBase *DataBaseInterface::openMyDataBase(const QString& prefix,const QString& name,const QString& l,DBTYPE tt) +{ + + DataBase *aDb = new DataBase(prefix,name,l); + if(aDb==0){ + return 0; + } + else + { + if(aDb->open(tt)!=0) + { + kdDebug(0) << "Database '"<< name <<"'do not exist, I try to create it.." << endl; + //ask only the first time. + static bool create=( KMessageBox::questionYesNo(0,"Database do not exist. Do you want to create it now?", + i18n("Create Database"), i18n("Create"), i18n("Do Not Create"))==KMessageBox::Yes); + if(create) + if(aDb->open(tt,DB_CREATE)!=0) + { + kdDebug(0) << "...cannot create!!"<< endl; + return 0; + } + else + { + kdDebug(0) << "...done!" << endl; + return aDb; + } + } + + } + return aDb; +} + +/* + * query functions. + * + */ + + +DataBaseInterface::MainEntry DataBaseInterface::get(const QString& query,SearchFilter *filter) +{ + static int counter=1; + counter++; + DBItemMainKey k(query); + DBItemMainData d; + //int r= + main->get(&k,&d); + // kdDebug(0) << "MAINDB->GET returned: " << r << endl; + if(counter%5==0) kapp->processEvents(100); + // kdDebug(0) << "events processed" << endl; + return qMakePair(k,d); + +} + +/* + * put functions + * * + */ + + +bool DataBaseInterface::addEntry(QString original,QString translated,InputInfo *info) +{ + DBItemMainKey mk(original); + DBItemMainData md; + QMap<QString, int> correlationDiff; + bool newentry=false; + //try to get + kdDebug(0) << "Inserting the pair:" << endl; + kdDebug(0) << "ORIGINAL:" << original << endl; + kdDebug(0) << "TRANSLATED:" << translated << endl; + + if(main->get(&mk,&md)==DB_NOTFOUND) + { + kdDebug(0) << "new entry" << endl; + newentry=true; + //This is a new entry, create index entry + DBItemNum *nind; + int newid=numindex->getLast()+1; + nind=new DBItemNum(newid); + numindex->put(nind,&mk); + + delete nind; + + md.clear(); + md.setIndexnumber(newid); + + + //Update secondary index alpha + DBItemMainKey ka(simple(original)); + DBItemMultiIndex in; + if(alpha->get(&ka,&in)==DB_NOTFOUND) in.clear() ; + //alpha->get(&ka,&in); + in.addEntry(newid); + alpha->put(&ka,&in); + kdDebug(0) << "Updating the word index " << endl; + //Update words index + QStringList ws=words(original); + for(QStringList::iterator it = ws.begin(); it!=ws.end(); ++it) + { + DBItemMainKey word(*it); + DBItemMultiIndex win; + if(wordsindex->get(&word,&win)==DB_NOTFOUND) win.clear(); + win.addEntry(newid); + wordsindex->put(&word,&win); + } + + kdDebug(0) << "new entry preparation DONE" << endl; + } + else + { + + kdDebug(0) << "It exists!" <<endl; + } + + + //Update sentence index + QStringList so=sentences(original); + QStringList st=sentences(translated); + if(so.count()==st.count() && st.count() >1 ) //we already hav a database for single string. + { + kdDebug(0) << "inside sentence loop" << endl; + for(int i=0; i< so.count() ; i++) + { + DBItemMainKey sk(so[i]); + DBItemMainData sd; + if(sentence->get(&sk,&sd)==DB_NOTFOUND&&!newentry) + kdDebug(0) << "Warning: new sentence for old entry, do we changed sentence definition? " << endl; + + kdDebug(0) << "here alive" << endl; + + // if(clean) + sd.removeRef(info->ref()); + kdDebug(0) << "now alive" << endl; + sd.addTranslation(st[i],info->ref()); + kdDebug(0) << "still alive" << endl; + + sentence->put(&sk,&sd); + + } + + + + } + kdDebug(0) << "Fuzzy sentence archive updated" << endl; + + + + //Add that translation, link to ref for information on that translation + + if(!translated.isEmpty()) + { + //loop on all translations to update correlation + QStringList tmpTranslations=md.getTranslations(); + for(QStringList::iterator otIt=tmpTranslations.begin(); otIt!=tmpTranslations.end();++otIt) + { + QStringList wt=words(*otIt); + for(QStringList::iterator it = wt.begin(); it!=wt.end(); ++it) + { + if(correlationDiff.contains(*it)) + correlationDiff[*it]--; + else + correlationDiff[*it]=-1; + } + } + + //clean so that we have only one translation per catalog. + md.removeRef(info->ref()); + md.addTranslation(translated,info->ref()); + + tmpTranslations=md.getTranslations(); + for(QStringList::iterator otIt=tmpTranslations.begin(); otIt!=tmpTranslations.end();++otIt) + { + QStringList wt=words(*otIt); + for(QStringList::iterator it = wt.begin(); it!=wt.end(); ++it) + { + if(correlationDiff.contains(*it)) + correlationDiff[*it]++; + else + correlationDiff[*it]=1; + } + } + + //FIXME: use the correlationDIff map somehow + + } + + //finally put! + return (main->put(&mk,&md)==0); + +} + + +bool DataBaseInterface::removeEntry(QString original) +{ + DBItemMainKey mk(original); + DBItemMainData md; + + //FIXME implement remove + //try to get + if(main->get(&mk,&md)==DB_NOTFOUND) + { + /* //This is a new entry, create index entry + DBItemNum *nind; + int newid=numindex->getLast()+1; + nind=new DBItemNum(newid); + numindex->put(nind,&mk); + + delete nind; + + md.clear(); + md.setIndexnumber(newid); + + + //Update secondary index alpha + DBItemMainKey ka(simple(original)); + DBItemMultiIndex in; + if(alpha->get(&ka,&in)==DB_NOTFOUND) in.clear() ; + //alpha->get(&ka,&in); + in.addEntry(newid); + alpha->put(&ka,&in); + + //Update words index + QStringList ws=words(original); + for(QStringList::iterator it = ws.begin(); it!=ws.end(); it++) + { + DBItemMainKey word(*it); + DBItemMultiIndex win; + if(wordsindex->get(&word,&win)==DB_NOTFOUND) win.clear(); + win.addEntry(newid); + wordsindex->put(&word,&win); + } + + //Update sentence index + QStringList so=sentences(original); + QStringList st=sentences(translated); + if(so.count()==st.count() && st.count() >1 ) //we already hav a database for single string. + { + for(int i=0; i< so.count() ; i++) + { + DBItemMainKey sk(so[i]); + DBItemMainKey sd(st[i]); //should be a list i.e. main data? + sentence->put(&sk,&sd); + + } + } + +*/ + } + + + return false; + +} + + + +QMap<QString,float> DataBaseInterface::correlation(QString word,SearchFilter *filter,bool notify, float minSign) +{ + QDict<unsigned int> res; + // res.setAutoDelete(true); + QMap<QString, float>final; + DBItemMultiIndex::IndexList il; + unsigned int tot=0; + unsigned int background=0; + unsigned int nocck; + QString sword=simple(word); + DBItemMainKey *k = new DBItemMainKey(sword); + DBItemMultiIndex *d = new DBItemMultiIndex(); + if(wordsindex->get(k,d)!=DB_NOTFOUND) + { + + il=d->getList(); + kdDebug(0) << il.count()<<endl; + tot=0; + for(QValueList<unsigned int>::iterator it=il.begin();it!=il.end();++it) + { + numindex->get(*it,k); + + + // QValueList<QueryResult> trad=exactMatch(k->getString(),filter); + + MainEntry e=get(k->getString(),filter); + QStringList trad=e.second.getTranslations(); + + nocck=words(k->getString()).contains(sword); + for( QStringList::iterator it2=trad.begin();it2!=trad.end();++it2) + { + + QStringList w=words(*it2); + unsigned int numWords = w.count()*10+1; + unsigned int wei=100000/sqrt(numWords); //weight (is the best one?) + + background+=(numWords-nocck)*wei; + QDict<uint> count; + //count.setAutoDelete(true); + //FIXME:SET AUTODELETE FOR ALL DICTS + for(QStringList::iterator it1=w.begin();it1!=w.end();it1++) + { + uint *ip; + if(!(ip=count[*it1])) count.insert(*it1,new uint(1)); + else + (*ip)++; + } + + for(QStringList::iterator it1=w.begin();it1!=w.end();it1++) + { + uint *ip; + if(*(count[*it1])==nocck) //add only if same number of entry (it cuts articles) + if(!(ip=res[*it1])) res.insert(*it1,new uint(wei)); + else + (*ip)+=wei; + } + + } + } + + unsigned int sqrBG=sqrt((1.0*background+1)/10000); + + for(QDictIterator<uint> it(res) ; it.current(); ++it) + { + float sign=1.0*(*(it.current()))/(10000.0*sqrBG); + if(sign >minSign){ + final[it.currentKey()]=sign; + kdDebug(0) << it.currentKey() <<" Score:" << 1.0*(*(it.current()))/10000 << "/" <<sqrBG << " = " <<sign << endl; + } + } + + kdDebug(0) << "final count " <<final.count()<< endl; + } + + return final; +} + +QStringList DataBaseInterface::words(QString s) +{ + QString str=simple(s); + QStringList list; + + int pos; + + do { + pos=str.find(QRegExp("\\s")); + // if(!simple(str.left(pos)).isEmpty()) + // list.append(simple(str.left(pos))); + if(!str.left(pos).isEmpty()) + list.append(str.left(pos)); + str=str.remove(0,pos+1); + } while(!str.isEmpty() && pos != -1); + + return list; +} + +QString DataBaseInterface::simple(QString str,bool ck) +{ + QString res; + if(ck) + res=str; //case keep + else + res=str.lower(); //lowercase + //FIXME: uncoment the foll. line (check speed) + res=res.replace(QRegExp("(<(.*)>)(.*)(</\\2>)"),"\\3"); //remove enclosing tags + + + //Try to get rid of regexps. + // res=res.replace(QRegExp("(('|-|_|\\s|[^\\w%])+)")," "); //strip non-word char + // res=res.replace(QRegExp("(('|-|_)+)")," "); //strip non-word char + // res=res.replace(QRegExp("[^\\w\\s%]"),""); //strip non-word char + + QString r; + QChar c; + bool wasSpace=true; + uint len=res.length(); + for(uint i=0; i<len;i++) + { + c=res[i]; + if(c.isLetterOrNumber()) + { + r+=c; + wasSpace=false; + } + else + { + if(!wasSpace && c.isSpace()) + { + r+=' '; + wasSpace=true; + } + else + { + if(!wasSpace && (c=='-' || c=='\'' || c=='_')) + { + r+=' '; + wasSpace=true; + } + else + { + if(c=='%'){ + r+=c; + wasSpace=false; + } + } + } + } + // wasSpace=c.isSpace(); + } + if(r[len-1].isSpace()) + r.truncate(len-1); + res=r; + //kdDebug(0) << "Simple: "<<res<< endl; + //res=res.simplifyWhiteSpace(); //remove double spaces + //res=res.stripWhiteSpace(); //" as " -> "as" + + // kdDebug(0) << res << endl; + return res; +} + +QStringList DataBaseInterface::sentences(QString s) +{ + QString str=s; + QStringList list; + + // kdDebug(0) << s << endl; + + int pos; + + + do { + QRegExp re("((\\.|;|\\?|\\!|:)( |$|\\\\n\\n))"); + pos=re.search(str); + if(!str.left(pos).isEmpty()) + list.append(str.left(pos).stripWhiteSpace()); + + kdDebug(0) << str.left(pos) << endl; + + str=str.remove(0,pos+re.cap(1).length()); + } while(!str.isEmpty() && pos != -1); + + + return list; +} + +QStringList DataBaseInterface::sentencesSeparator(QString s) +{ + QString str=s; + QStringList list; + + // kdDebug(0) << s << endl; + + int pos; + + do { + QRegExp re; + re.setPattern("([.:?!;]( |$|\\\\n\\n))"); + pos = re.search(str); + QString separator=re.cap(1); + if(pos!=-1){ + list.append(separator); + } + + str=str.remove(0,pos+1); + } while(!str.isEmpty() && pos != -1); + + return list; +} + +bool DataBaseInterface::isUpper(QChar s) +{ + return s==s.upper(); +} + +bool DataBaseInterface::isLower(QChar s) +{ + return s==s.lower(); +} + + + +QString DataBaseInterface::format(QString _s,QString t) +{ + //FIXME use settings + //FIXME use regexp + + QString s=_s; + QString noTagT=t.replace(QRegExp("(<(.*)>)(.*)(</\\2>)"),"\\3"); + QChar first=noTagT[noTagT.find(QRegExp("\\w"))]; + bool firstCapital=isUpper(first); + + /* +bool dotsAtEnd=(t.find("...")+3==t.length()); +bool gtgtAtEnd=(t.find(">>")+2==t.length()); +bool ltltAtEnd=(t.find("<<")==t.length()-2); + +bool columnAtEnd=(t.find(":")+1==t.length()); +*/ + + bool allupper=(t.upper()==t); + + + if(firstCapital) + s[0]=s[0].upper(); + else + s[0]=s[0].lower(); + + //if(dotsAtEnd) + // s+="..."; + + /*if(gtgtAtEnd) + s+=">>"; + +if(ltltAtEnd) + s+="<<"; + +if(columnAtEnd) + s+=":"; +*/ + + if(allupper) + s=s.upper(); + + int pos=t.find(QRegExp("&")); + if(pos>=0) { + QChar accel=t[t.find(QRegExp("&"))+1]; + if(accel!='&') + { + + pos=s.find(accel,false); + if(pos<0) + pos=0; + s.insert(pos,"&"); + } + } + s=formatRegExp(s,t,".*(\\.\\.\\.|:|>>|<<|\\.|\\?)$", + "^(.*)$", + "\\1@CAP1@"); + s=formatRegExp(s,t,"(<(.*)>).*(\\.\\.\\.|:|>>|<<|\\.|\\?)*(</\\2>)$", + "^(.*)$", + "@CAP1@\\1@CAP3@@CAP4@"); + + return s; + +} + + +QString DataBaseInterface::formatRegExp(QString _s, QString t, QString tre,QString stringSearch,QString stringReplace) +{ + QString s=_s; + QRegExp templateRegExp(tre); + //QString stringSearch = "(.*)!@CAP1@$"; // use @CAP1.. fot caps in templates + //QString stringReplace = "\\1@CAP1@"; // use \1, \2 for caps in str and @CAP1 fot caps in template + + + if(templateRegExp.exactMatch(t)) + { + QStringList caps=templateRegExp.capturedTexts(); + int i=0; + for(QStringList::iterator capit=caps.begin();capit!=caps.end();++capit) + { + QString phRegExp="(?!\\\\)@CAP"+QString::number(i)+"@"; + //kdDebug(0) << "phRegExp: " << phRegExp << endl; + //kdDebug(0) << "cap[" << i << "]: "<< *capit<< endl; + + stringReplace = stringReplace.replace(QRegExp(phRegExp),*capit); + stringSearch = stringSearch.replace(QRegExp(phRegExp),*capit); + i++; + + } + // kdDebug(0) << "stringSearch " << stringSearch << endl; + // kdDebug(0) << "stringReplace " << stringReplace << endl; + QRegExp stringSearchRegExp = QRegExp(stringSearch); + // kdDebug(0) << "before: "<<s<<endl; + s = s.replace(stringSearchRegExp,stringReplace); + // kdDebug(0) << "after: "<<s<<endl; + + } + + return s; +} + +DBItemMultiIndex::IndexList DataBaseInterface::getAlpha( const QString & query ) +{ + DBItemMainKey *k = new DBItemMainKey(simple(query)); + DBItemMultiIndex *d = new DBItemMultiIndex(); + alpha->get(k,d); + + return d->getList(); +} + +DataBaseInterface::MainEntry DataBaseInterface::getFromIndex( uint i ) +{ + DBItemMainKey k; + numindex->get(i,&k); + return get(k.getString(),0); //FIXME: this is a BUG right now but the filter should be removed +} + +DataBaseInterface::MainEntry DataBaseInterface::getSentence( const QString & query ) +{ + + static int counter=1; + counter++; + DBItemMainKey k(query); + DBItemMainData d; + sentence->get(&k,&d); + if(counter%5==0) kapp->processEvents(100); + return qMakePair(k,d); + +} + +DBItemMultiIndex::IndexList DataBaseInterface::getWordIndex( const QString & query ) +{ + DBItemMainKey k = DBItemMainKey(query); + DBItemMultiIndex d = DBItemMultiIndex(); + if(wordsindex->get(&k,&d)!=DB_NOTFOUND){ + return d.getList(); + } + else + { + QValueList<unsigned int> tmpList; + return tmpList; + } + +} + + + +//#include "database.moc.cpp" + diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/database.h b/kbabel/kbabeldict/modules/dbsearchengine2/database.h new file mode 100644 index 00000000..c447fa59 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/database.h @@ -0,0 +1,237 @@ +/* + + DBSE 3 + (c) 2000-2003 Andrea Rizzi + License: GPLv2 + +*/ +#ifndef DATABASE_2_H +#define DATABASE_2_H + +#include <qstring.h> +#include <qvaluelist.h> +#include <db4/db_cxx.h> +#include <qobject.h> +#include <qregexp.h> + +#include "dbentries.h" + + +class DBSESettings +{ +public: + //DatabaseInterface Settings + uint scoreWordByWord; + uint scoreGlossary; + uint scoreDivide; + uint scoreExact; + uint scoreSentence; + uint scoreAlpha; + uint scoreDynamic; + uint scoreChunkByChunk; + uint minScore; + bool firstCapital; + bool allCapital; + bool accelerator; + bool sameLetter; + + + +}; + + +class DataBase : Db +{ + public: + DataBase(QString dbpath, QString dbname, QString dblang); + + int open(DBTYPE type,unsigned int flags=0); + +//Standard access (overload std functions) + + + +int del(DBItem * key){ + key->set(); + int r = Db::del(0,key,0); + key->get(); + return r; + } + + + +int get(DBItem * key,DBItem *data){ + key->set(); + data->set(); + int r = Db::get(0,key,data,0); + key->get(); + data->get(); + return r; + } + int put(DBItem * key,DBItem *data,int fl=0){ + key->set(); + data->set(); + int r= Db::put(0,key,data,0); + key->get(); + data->get(); + return r; + } + + int del(DBItemNum * key){ + int r = Db::del(0,key,0); + return r; + } + + int get(DBItemNum * key,DBItem *data){ + data->set(); + int r = Db::get(0,key,data,0); + data->get(); + return r; + } + int put(DBItemNum * key,DBItem *data) + { + data->set(); + int r= Db::put(0,key,data,0); + data->get(); + return r; + } + +//Overload, using this you loose the Key!! + int del(int i){DBItemNum n(i); return del(&n);} + int get(int i,DBItem *data){DBItemNum n(i); return get(&n,data);} + int put(int i,DBItem *data){DBItemNum n(i); return put(&n,data);} + + unsigned int getLast(); + int close(unsigned int i) {return Db::close( i); } + +//For scrolling + // int getFirst(DBItem *key,DBItem *data,QString table); + // int getNext(DBItem *key,DBItem *data,QString table); + // bool isEnd(QString table); +private: + QString filename; + QString database; + DBTYPE mytype; +}; + + + + + +class QueryResult //from DBInterface to KDBSearchEngine +{ +public: + QueryResult(); + QueryResult(QString r); + QueryResult(QString r,QString o,int s); + void setRichResult(QString r) { richr=r; } + void setRichOriginal(QString r) { richo=r; } + + QString richResult() {return richr;} + QString richOriginal() {return richo;} + + QString result(){ return res; } + QString original() {return orig; } + int score() {return sco;} +//info contains originalkey,catalog,date,author etc... + ResultInfo info(){ResultInfo i; i.info="no info"; return i;} + + +private: + QString res; + QString orig; + QString richr; + QString richo; + int sco; + +}; + +class SearchFilter +{ + int filter; //placeholder +}; + + + +class DataBaseInterface : public QObject +{ + + public: + //move result list typedef to AbstractAlgorthm or somewhere else + typedef QValueList<QueryResult> ResultList; + typedef QPair<DBItemMainKey,DBItemMainData> MainEntry; + + DataBaseInterface( QString dir, DBSESettings *sets); + ~DataBaseInterface(); + + //Ask the Database to stop now. + void stop(bool b=true) {_stopNow=b;} + + //Search words + ResultList wordsMatch(QString query,SearchFilter *filter=0,bool notify=true); + + //Edit database functions. + //addEntry and sync all the tables + bool addEntry(QString original,QString translated,InputInfo *info); + //FIXME:implement me! + bool removeEntry(QString original); + + //FIXME: go persistent! + QMap<QString,float> correlation(QString word,SearchFilter *filter=0,bool notify=true,float minSign=0.2); + + + // Read the database + MainEntry get(const QString& query,SearchFilter *filter=0); + MainEntry getFromIndex(uint i); + DBItemMultiIndex::IndexList getAlpha(const QString& query); + DBItemMultiIndex::IndexList getWordIndex(const QString& query); + MainEntry getSentence(const QString& query); + + //Database status check functions + bool mainOk() {return main!=0;} + bool catalogOk() {return catalog!=0;} + bool alphaOk() {return alpha!=0;} + bool sentenceOk() {return sentence!=0;} + bool numindexOk() {return numindex!=0;} + bool wordsindexOk() {return wordsindex!=0;} + bool externalOk() {return external!=0;} + bool wordOk() {return word!=0;} + bool transwordOk() {return transword!=0;} + bool correlationOk() {return corr!=0;} + bool stopNow() {return _stopNow;} + + // signals: + // void newResult(QueryResult); + + DBSESettings *getSettings() {return settings;} + + private: + DataBase * openMyDataBase(const QString& prefix,const QString& name,const QString& l,DBTYPE tt); + DataBase *main; + DataBase *numindex; + DataBase *wordsindex; + DataBase *catalog; + DataBase *alpha; + DataBase *sentence; + DataBase *word; + DataBase *external; + DataBase *transword; + DataBase *corr; + bool _stopNow; + DBSESettings *settings; + + //FIXME:Move to KBabel common library. + public: + QString format( QString _s,QString t); + QString formatRegExp(QString _s, QString t, QString tre,QString stringSearch,QString stringReplace); + static QStringList words(QString s); + static QStringList sentences(QString s); + static QStringList sentencesSeparator(QString s); + static QString simple(QString str,bool ck=false); + static bool isUpper(QChar s); + static bool isLower(QChar s); + + }; + +#endif + diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.cpp new file mode 100644 index 00000000..4f048f9c --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.cpp @@ -0,0 +1,171 @@ +#include "dbentries.h" +#include <qdatastream.h> + + +void DBItem::set() +{ + QBuffer b(mydata); + b.open( IO_WriteOnly ); + QDataStream s(&b); + write(&s); + b.close(); + set_data(mydata.data()); + set_size(mydata.size()); + +} + void DBItem::get() + { + mydata.resize(get_size()); + mydata.duplicate((const char *)get_data(),(unsigned int)get_size()); + + QDataStream *s = new QDataStream(mydata,IO_ReadOnly); + read(s); + delete s; + } + + + +DBItemMainKey::DBItemMainKey() +{ + sstr=""; + //set(); +} + +DBItemMainKey::DBItemMainKey(QString searchstring) +{ + sstr=searchstring; + //set(); +} + +void DBItemMainKey::read(QDataStream *s) +{ +*s >> sstr; +} + +void DBItemMainKey::write(QDataStream *s) +{ + *s << sstr; + } + + + + + +DBItemMainData::DBItemMainData() +{ + clear(); + //set(); +} + +void DBItemMainData::clear() +{ + indexnumber=0; + translations.clear(); + //set(); +} + +void DBItemMainData::read(QDataStream *s) +{ +*s >> indexnumber >> translations; +} + +void DBItemMainData::write(QDataStream *s) +{ + *s << (Q_UINT32)indexnumber << translations; +} + +void DBItemMainData::addTranslation(QString str, unsigned int ref) +{ +//get(); + if(translations[str].find(ref)==translations[str].end()) // If it do not exists + translations[str].append(ref); //add a new reference. + else + { + + } +//set(); + +} + +void DBItemMainData::removeTranslation(QString str, unsigned int ref) +{ +//get(); + translations[str].remove(ref); + if(translations[str].isEmpty()) + translations.remove(str); +//set(); + +} + +void DBItemMainData::removeRef( unsigned int ref) +{ +//get(); +QMapIterator<QString,QValueList<unsigned int> > it2; + for(QMapIterator<QString,QValueList<unsigned int> > it = translations.begin(); + it!= translations.end(); /* it++*/) + { //Dirty hack + it2=it; + it++; + if(it2.data().find(ref)!=it2.data().end()) + removeTranslation(it2.key(),ref); + } + +//set(); +} + +QStringList DBItemMainData::getTranslations() +{ +//get(); +QStringList result; + for(QMapIterator<QString,QValueList<unsigned int> > it = translations.begin(); + it!= translations.end(); it++) + result.append(it.key()); + +return result; + +} + +QValueList<unsigned int> DBItemMainData::getReferences(QString str) +{ +//get(); +return translations[str]; //this also add a "str" entry but we do not call set()! +} + + + +DBItemMultiIndex::DBItemMultiIndex() +{ +list.clear(); +//set(); +} + +void DBItemMultiIndex::addEntry(unsigned int index) +{ +// get(); + if(list.find(index)==list.end()) + { + list.append(index); + qHeapSort(list); + // set(); + + } + +} + +void DBItemMultiIndex::removeEntry(unsigned int index) +{ +// get(); + list.remove(index); +// set(); +} + + +void DBItemMultiIndex::read(QDataStream *s) +{ +*s >> list; +} + +void DBItemMultiIndex::write(QDataStream *s) +{ + *s << list; + } diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.h b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.h new file mode 100644 index 00000000..0a40878c --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.h @@ -0,0 +1,170 @@ +#ifndef DBENTRIES_H +#define DBENTRIES_H + +#include <db4/db_cxx.h> +#include <qstring.h> +#include <qbuffer.h> +#include <qmap.h> +#include <qstringlist.h> +#include <qdatetime.h> + +class CatalogInfo +{ + + QString author; + QDateTime datetime; + QString filename; + QString filepath; + + +}; + +class ResultInfo +{ +public: +//Common info + QString original; //placeholder + +// +//Multi reference info + QValueList<CatalogInfo> catalogs; + + QString info; + +}; + +class InputInfo +{ +public: + unsigned int ref() {return 1;} + +}; + +class DBItem : public Dbt +{ +public: + + virtual ~DBItem(){} + + virtual bool isEmpty(){return empty;} +//void fromDbt(Dbt *dbt); + + void set(); + void get(); + + +protected: + virtual void read(QDataStream *s) = 0; + virtual void write(QDataStream *s) = 0; + QByteArray mydata; + bool empty; + +}; + +class DBItemMainKey : public DBItem +{ + public: + DBItemMainKey(); + DBItemMainKey(QString searchstring); + + + QString getString(){ return sstr;} + +private: + + virtual void read(QDataStream *s); + virtual void write(QDataStream *s); + + QString sstr; + +}; + + +class DBItemMainData : public DBItem +{ + public: + + typedef QMapIterator<QString,QValueList<unsigned int> > TranslationIterator; + typedef QMap<QString,QValueList<unsigned int> > TranslationMap; + + DBItemMainData(); + + QStringList getTranslations(); + QValueList<unsigned int> getReferences(QString str); + + void clear(); + + +//Add a translation with reference ref, if translation exists append +// ref to the list of references + void addTranslation(QString str,unsigned int ref); + void removeTranslation(QString str,unsigned int ref); + +//remove any reference to ref, if ref is the only reference of a translation +// the translation is removed + void removeRef(unsigned int ref); + + unsigned int getIndexnumber(){ return indexnumber; } + void setIndexnumber(int i){ indexnumber=i; } + +private: + + virtual void read(QDataStream *s); + virtual void write(QDataStream *s); + + unsigned int indexnumber; + TranslationMap translations; + +}; + + +class DBItemMultiIndex : public DBItem +{ + public: + typedef QValueList<unsigned int> IndexList; + + DBItemMultiIndex(); + // DBItemMultiIndex(IndexList l); + + void addEntry(unsigned int index); + void removeEntry(unsigned int index); + + IndexList getList(){ return list;} + void clear() {list.clear();} + +private: + + virtual void read(QDataStream *s); + virtual void write(QDataStream *s); + + IndexList list; + +}; + + +class DBItemNum : public Dbt +{ + public: + DBItemNum(){ + set_data(&num); + set_size(4); + num=0; + } + DBItemNum(unsigned int i){ + set_data(&num); + set_size(4); + num=i; + } + + unsigned int getNum(){ num=*(unsigned int *)get_data(); return num;} + +private: + + unsigned int num; + +}; + + + + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.cpp new file mode 100644 index 00000000..b19b2db2 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.cpp @@ -0,0 +1,280 @@ +/*************************************************************************** + dbscan.cpp - Scan for po files to add in the DB + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + email : rizzi@kde.org + ***************************************************************************/ + +/* + Translation search engine + + + Copyright 2000 + Andrea Rizzi rizzi@kde.org + + License GPL v 2.0 + +*/ +#include "dbscan.h" +#include <kconfig.h> +#include <qdir.h> +#include <qfile.h> +#include <kapplication.h> +#include <kurl.h> +#include <kdebug.h> +#include <klineedit.h> +#include <kurlrequester.h> +#include <kcombobox.h> + +using namespace KBabel; + +MessagesSource::MessagesSource() +{ + //FIXMR: check if we should put something in that constructor +} +void MessagesSource::writeConfig(KConfigBase *config) +{ + config->writeEntry("Location",location.url()); + config->writeEntry("LocationType",type); + config->writeEntry("ProjectName",projectName); + config->writeEntry("ProjectKeywords",projectKeywords); + config->writeEntry("Status",status); +} + +void MessagesSource::readConfig(KConfigBase *config) +{ + location=config->readEntry("Location"); + type=config->readNumEntry("LocationType",0); + projectName=config->readEntry("ProjectName"); + projectKeywords=config->readEntry("ProjectKeywords"); + status=config->readEntry("Status"); + +} + +void MessagesSource::setDialogValues(SourceDialog *sd) +{ + sd->projectName->setText(projectName); + sd->projectKeywords->setText(projectKeywords); + sd->sourceLocation->setURL(location.url()); + sd->status->setCurrentText(status); + sd->type->setCurrentItem(type); +} +void MessagesSource::getDialogValues(SourceDialog *sd) +{ + projectName=sd->projectName->text(); + projectKeywords=sd->projectKeywords->text(); + location=sd->sourceLocation->url(); + status=sd->status->currentText(); + type=sd->type->currentItem(); +} + +QValueList<KURL> MessagesSource::urls() +{ + QValueList<KURL> urlList; + if(type==0) + urlList.append(location); + if(type==1|| type==2) + urlList=filesInDir(location,(type==2)); + + return urlList; + +} + +QValueList<KURL> MessagesSource::filesInDir(KURL url,bool recursive) +{ + QValueList<KURL> result; + QDir d(url.path()); + d.setMatchAllDirs(true); + kdDebug(0) << d.count() << " files in dir "<< url.path()<<endl; + const QFileInfoList* files = d.entryInfoList(); + kdDebug(0) << files << endl; + + // QPtrListIterator<QFileInfo> it(*files); + if(files){ + for (QPtrListIterator<QFileInfo> fileit(*files); !fileit.atLast(); ++fileit ) + { + if ((*fileit)->isDir()) + { + if(recursive) + { + if((*fileit)->fileName()!="." && (*fileit)->fileName() !="..") + { + result+=filesInDir(KURL((*fileit)->absFilePath()),recursive); + kdDebug(0) << "Recursion done for " << (*fileit)->fileName() << endl; + } + } + + } + else + { + kdDebug(0) << (*fileit)->fileName() << endl; + result.append(KURL((*fileit)->absFilePath())); + } + } + } + kdDebug(0) << result.count() << endl; + + return result; +} + +//FIXME: clean this class +PoScanner::PoScanner(DataBaseInterface *dbi, + QObject *parent,const char *name):QObject(parent,name) +{ + di=dbi; + removeOldCatalogTranslation=true; + count=0; +} + +bool PoScanner::scanPattern(QString pathName,QString pattern,bool rec) +{ +int tot; +//Only one progress bar!! + +bool pb=false; +static bool called=false; +if (!called) +{ pb=true; count=0;} +called=true; + +kdDebug(0) << QString("Scanning: %1, %2").arg(pathName).arg(pattern) << endl; + +if(pb) +{ +emit patternStarted(); +emit patternProgress(0); +} + QDir d(pathName,pattern); + d.setMatchAllDirs(true); + const QFileInfoList* files = d.entryInfoList(); + tot=files->count(); + QPtrListIterator<QFileInfo> it(*files); +kdDebug(0) << tot << endl; + for ( int i=0; i<tot; i++ ) + { + if ((*it)->isDir()) + { + if(rec) + { + kdDebug(0) << d[i] << endl; + if(d[i]!="." && d[i]!="..") + scanPattern(pathName+"/"+d[i],pattern,true); + } + } else + { + kdDebug(0) << d[i] << endl; + scanFile(pathName+"/"+d[i]); + } + + if(pb) + + emit patternProgress(100*i/tot); + + + ++it; + } + + + +if(pb) +emit patternProgress(100); + + +if(pb) +emit patternFinished(); +if(pb){called=false;count=0;} + +return true; +} + +bool PoScanner::scanFile(QString fileName) +{ + KURL u(fileName); + return scanURL(u); +} + +bool PoScanner::scanURL(KURL u) +{ + + +emit fileStarted(); + +Catalog * catalog=new Catalog(this,"ScanPoCatalog"); + +QString pretty=u.prettyURL(); +QString location=pretty.right(pretty.length()-pretty.findRev("/")-1); + +connect(catalog,SIGNAL(signalProgress(int)),this,SIGNAL(fileLoading(int))); +emit filename(location); +emit fileProgress(0); +emit fileLoading(0); + +bool error; + +ConversionStatus rr=catalog->openURL(u); +if(rr != OK && rr !=RECOVERED_PARSE_ERROR ) +{ + delete catalog; + return false; +} +emit fileLoading(100); + +QString author; +if(rr != HEADER_ERROR) + author=catalog->lastTranslator(); +else author=QString(""); + +//int catnum=dm->catalogRef(location,author,fileName); +InputInfo ii; + + +uint i,tot; +tot=catalog->numberOfEntries(); + +bool fuzzy; +bool untra; + + +for (i=0;i<tot;i++) //Skip header = ???? +{ + + if(i % 10==0) + { + emit fileProgress(100*i/tot); + emit added(count); + kapp->processEvents(100); + } + + fuzzy=catalog->isFuzzy(i); + untra=catalog->isUntranslated(i); + + + if(!fuzzy && !untra) + { + int res; + QString msgid,msgstr; + msgid=catalog->msgid(i,true).first(); + msgstr=catalog->msgstr(i).first(); + res=di->addEntry(msgid,msgstr,&ii); + count+=res; + } + + +} + + +// kdDebug(0) << QString("File finished") << endl; + +emit fileProgress(0); +emit fileLoading(0); +emit fileFinished(); +// dm->loadInfo(); // Sync the list of catalogs NOT NEEDED (?) + +delete catalog; + +//clear(); +return true; + +} +#include "dbscan.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.h b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.h new file mode 100644 index 00000000..990d556c --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.h @@ -0,0 +1,120 @@ +/*************************************************************************** + dbscan.h - + ------------------- + begin : Fri Sep 8 2000 + copyright : (C) 2000 by Andrea Rizzi + email : rizzi@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + Translation search engine + Copyright 2000 + Andrea Rizzi rizzi@kde.org + +*/ + + +#ifndef _DBSCAN_H_ +#define _DBSCAN_H_ + +#include <catalog.h> +#include <kurl.h> +#include "database.h" + +#include "sourcedialog.h" + +class KConfigBase; + +class MessagesSource +{ + //FIXME Use KURL and add network support + + public: + MessagesSource(); + void writeConfig(KConfigBase *config); + void readConfig(KConfigBase *config); + void setDialogValues(SourceDialog *sd); + void getDialogValues(SourceDialog *sd); + + /** + * It returns a list of urls to scan, the list contains single file if type is "SingleFile" + * or a list of files if type is "SingleDir" or "RecDir" + */ + QValueList<KURL> urls(); + + private: + QValueList<KURL> filesInDir(KURL url,bool recursive); + + KURL location; + // The source type "SingleFile" =0, "SingleDirectory"=1, "RecursiveDirectory"=2 + uint type; + + /** + * A filter to apply on source files +*/ + + SearchFilter filter; + + QString projectName; + QString projectKeywords; + QString status; +}; + + +class PoScanner : public QObject +{ + Q_OBJECT; + + public: + + PoScanner(DataBaseInterface *dbi,QObject *parent=0,const char *name=0); + + /* + Scan a single PO file. + */ + bool scanFile(QString fileName); + + /* + Scan a single URL file. + */ + bool scanURL(KURL u); + + + /* + Scan a list of space separated files with possible MetaCharacters + */ + bool scanPattern(QString pathName,QString pattern="*.po",bool rec=false); + + + + + signals: + void fileStarted(); + void fileProgress(int); + void fileFinished(); + void fileLoading(int); + void patternStarted(); + void patternProgress(int); + void patternFinished(); + void added(int); + void filename(QString); + private: + + // If true when a translation is found in a CATALOG the old translation for this CATALOG + // will be removed + bool removeOldCatalogTranslation; + int count; + DataBaseInterface *di; + // InfoItem cinfo; +}; + + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbse2.ui b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2.ui new file mode 100644 index 00000000..327a9d9d --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2.ui @@ -0,0 +1,732 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>DBSearchEnginePrefWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Form1</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>447</width> + <height>483</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>tabWidget2</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>General</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Database</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>DB folder:</string> + </property> + </widget> + <widget class="KURLRequester" row="0" column="1"> + <property name="name"> + <cstring>dbDirectory</cstring> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>autoUpdate</cstring> + </property> + <property name="text"> + <string>Automatic update in kbabel</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>New Entries</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Author:</string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="2"> + <property name="name"> + <cstring>checkBox2</cstring> + </property> + <property name="text"> + <string>From kbabel</string> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kLineEdit1</cstring> + </property> + </widget> + </grid> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Algorithm</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Minimum score:</string> + </property> + </widget> + <spacer row="4" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + <widget class="Line" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Algorithms to Use</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="text"> + <string>Score:</string> + </property> + </widget> + <widget class="KIntSpinBox" row="6" column="2"> + <property name="name"> + <cstring>scoreWordByWord</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="1" column="2"> + <property name="name"> + <cstring>scoreGlossary</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabel3_2_2</cstring> + </property> + <property name="text"> + <string>Score:</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0"> + <property name="name"> + <cstring>useSentence</cstring> + </property> + <property name="text"> + <string>Fuzzy sentence archive</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>useGlossary</cstring> + </property> + <property name="text"> + <string>Glossary</string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>useExact</cstring> + </property> + <property name="text"> + <string>Exact </string> + </property> + </widget> + <widget class="KIntSpinBox" row="4" column="2"> + <property name="name"> + <cstring>scoreDivide</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="0" column="2"> + <property name="name"> + <cstring>scoreExact</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="3" column="2"> + <property name="name"> + <cstring>scoreSentence</cstring> + </property> + </widget> + <widget class="QCheckBox" row="4" column="0"> + <property name="name"> + <cstring>useDivide</cstring> + </property> + <property name="text"> + <string>Sentence by sentence</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>useAlpha</cstring> + </property> + <property name="text"> + <string>Alphanumeric</string> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>textLabel3_2_3</cstring> + </property> + <property name="text"> + <string>Score:</string> + </property> + </widget> + <widget class="QLabel" row="4" column="1"> + <property name="name"> + <cstring>textLabel3_2_4</cstring> + </property> + <property name="text"> + <string>Score:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Score:</string> + </property> + </widget> + <widget class="KIntSpinBox" row="2" column="2"> + <property name="name"> + <cstring>scoreAlpha</cstring> + </property> + </widget> + <widget class="QLabel" row="6" column="1"> + <property name="name"> + <cstring>textLabel3_2_6</cstring> + </property> + <property name="text"> + <string>Score:</string> + </property> + </widget> + <widget class="QLabel" row="5" column="1"> + <property name="name"> + <cstring>textLabel3_2_5</cstring> + </property> + <property name="text"> + <string>Score:</string> + </property> + </widget> + <widget class="QCheckBox" row="6" column="0"> + <property name="name"> + <cstring>useWordByWord</cstring> + </property> + <property name="text"> + <string>Word by word</string> + </property> + </widget> + <widget class="QCheckBox" row="5" column="0"> + <property name="name"> + <cstring>useDynamic</cstring> + </property> + <property name="text"> + <string>Dynamic dictionary</string> + </property> + </widget> + <widget class="KIntSpinBox" row="5" column="2"> + <property name="name"> + <cstring>scoreDynamic</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Preferred number of results:</string> + </property> + </widget> + <widget class="KIntSpinBox" row="2" column="2"> + <property name="name"> + <cstring>numberOfResult</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="3" column="2"> + <property name="name"> + <cstring>minScore</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Output</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox4</cstring> + </property> + <property name="title"> + <string>Output Processing</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="3" column="0"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>firstCapital</cstring> + </property> + <property name="text"> + <string>First capital letter match</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>allCapital</cstring> + </property> + <property name="text"> + <string>All capital letter match</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>accelerator</cstring> + </property> + <property name="text"> + <string>Accelerator symbol (&&)</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="1"> + <property name="name"> + <cstring>sameLetter</cstring> + </property> + <property name="text"> + <string>Try to use same letter</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox5</cstring> + </property> + <property name="title"> + <string>Custom Rules</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Original string regexp:</string> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kLineEdit1_2</cstring> + </property> + </widget> + <widget class="QListView" row="3" column="0" rowspan="3" colspan="2"> + <column> + <property name="text"> + <string>Enabled</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Description</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <item> + <property name="text"> + <string>New Item</string> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap></pixmap> + </property> + <property name="pixmap"> + <pixmap></pixmap> + </property> + </item> + <property name="name"> + <cstring>customRules</cstring> + </property> + </widget> + <spacer row="5" column="2"> + <property name="name"> + <cstring>spacer7_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton" row="4" column="2"> + <property name="name"> + <cstring>deleteRule</cstring> + </property> + <property name="text"> + <string>Delete</string> + </property> + </widget> + <widget class="QPushButton" row="3" column="2"> + <property name="name"> + <cstring>addRule</cstring> + </property> + <property name="text"> + <string>Add</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3_3</cstring> + </property> + <property name="text"> + <string>Replace string:</string> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kLineEdit3</cstring> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kLineEdit2</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string>Translated regexp(search):</string> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Import</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox6</cstring> + </property> + <property name="title"> + <string>Options</string> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkLang</cstring> + </property> + <property name="geometry"> + <rect> + <x>20</x> + <y>30</y> + <width>150</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Check language</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>useFilters</cstring> + </property> + <property name="geometry"> + <rect> + <x>20</x> + <y>60</y> + <width>140</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Use current filters</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>dateToday</cstring> + </property> + <property name="geometry"> + <rect> + <x>20</x> + <y>90</y> + <width>180</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Set date to today</string> + </property> + </widget> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox7</cstring> + </property> + <property name="title"> + <string>Sources</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>editSource</cstring> + </property> + <property name="text"> + <string>Edit</string> + </property> + </widget> + <widget class="KPushButton" row="2" column="1"> + <property name="name"> + <cstring>removeSource</cstring> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + <widget class="KPushButton" row="3" column="1"> + <property name="name"> + <cstring>scanSource</cstring> + </property> + <property name="text"> + <string>Scan Now</string> + </property> + </widget> + <widget class="KPushButton" row="0" column="1"> + <property name="name"> + <cstring>addSource</cstring> + </property> + <property name="text"> + <string>Add</string> + </property> + </widget> + <spacer row="4" column="1"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + <widget class="KPushButton" row="5" column="1"> + <property name="name"> + <cstring>scanAll</cstring> + </property> + <property name="text"> + <string>Scan All</string> + </property> + </widget> + <widget class="QListBox" row="0" column="0" rowspan="6" colspan="1"> + <property name="name"> + <cstring>sourceList</cstring> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Filters</string> + </attribute> + </widget> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.cpp new file mode 100644 index 00000000..9c286052 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.cpp @@ -0,0 +1,83 @@ + +#include <klocale.h> +#include <kinstance.h> +#include <kaboutdata.h> +#include <kdebug.h> + +#include "dbse2_factory.h" +#include "KDBSearchEngine2.h" + + +extern "C" +{ + KDE_EXPORT void *init_kbabeldict_dbsearchengine2() +// void *init_libdbsearchengine2() + { + return new DbSe2Factory; + } +}; + + +KInstance *DbSe2Factory::s_instance = 0; +KAboutData *DbSe2Factory::s_about = 0; + + +DbSe2Factory::DbSe2Factory( QObject *parent, const char *name) + : KLibFactory(parent,name) +{ +} + +DbSe2Factory::~DbSe2Factory() +{ + if(s_instance) + { + delete s_instance; + s_instance=0; + } + + if(s_about) + { + delete s_about; + s_about=0; + } +} + + +QObject *DbSe2Factory::createObject( QObject *parent, const char *name, + const char *classname, const QStringList &) +{ + if(QCString(classname) != "SearchEngine") + { + kdError() << "not a SearchEngine requested" << endl; + return 0; + } + + KDBSearchEngine2 *se = new KDBSearchEngine2(parent,name); + + emit objectCreated(se); + return se; +} + + +KInstance *DbSe2Factory::instance() +{ + if(!s_instance) + { + + s_about = new KAboutData( "kdbsearchengine2", + I18N_NOOP("Translation Database") + , "1.99" , +I18N_NOOP("A fast translation search engine based on databases") + , KAboutData::License_GPL + , I18N_NOOP("Copyright 2000-2003 by Andrea Rizzi") + ,0,0, "rizzi@kde.org"); + + s_about->addAuthor("Andrea Rizzi",0,"rizzi@kde.org"); + + s_instance = new KInstance(s_about); + } + + return s_instance; +} + +#include "dbse2_factory.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.h b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.h new file mode 100644 index 00000000..4285d53c --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.h @@ -0,0 +1,26 @@ +#ifndef DBSE2_FACTORY_H +#define DBSE2_FACTORY_H + +#include <klibloader.h> +class KInstance; +class KAboutData; + +class DbSe2Factory : public KLibFactory +{ + Q_OBJECT +public: + DbSe2Factory( QObject *parent=0, const char *name=0); + ~DbSe2Factory(); + + virtual QObject *createObject( QObject *parent=0, const char *name=0, + const char *classname="QObject", + const QStringList &args = QStringList()); + + static KInstance *instance(); + +private: + static KInstance *s_instance; + static KAboutData *s_about; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbsearchengine2.desktop b/kbabel/kbabeldict/modules/dbsearchengine2/dbsearchengine2.desktop new file mode 100644 index 00000000..a46bfff1 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbsearchengine2.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +Type=Service +Name=Translation Database v2 for KBabelDict +Name[bg]=БД с преводи v2 за KBabelDict +Name[br]=Stlennvon geriaoueg v2 evit KBabelDict +Name[bs]=Baza prijevoda v2 za KBabelDict +Name[ca]=Base de dades de traducció v2 per a KBabelDict +Name[cs]=Databáze překladů v2 pro KBabelDict +Name[cy]=Cronfa ddata Cyfieithiadau v2 i KBabelDict +Name[da]=Oversættelsesdatabase v2 for KBabelDict +Name[de]=Übersetzungsdatenbank Version 2 für KBabelDict +Name[el]=Βάση δεδομένων μετάφρασης έκδοση 2 για το KBabelDict +Name[es]=Base de datos de traducciones v2 para KBabelDict +Name[et]=KBabelDicti tõlgete andmebaas (versioon 2) +Name[eu]=v2 itzulpen datu-basea KBabelDict-entzat +Name[fa]=دادگان ترجمۀ نسخه ۲ برای KBabelDict +Name[fi]=KBabelDict-ohjelman käännöstietokanta v2 +Name[fr]=Base de données des traductions v2 pour KBabelDict +Name[ga]=Cuimhne Aistriúcháin (v2) le haghaidh KBabelDict +Name[gl]=Base de datos de traducións v2 de KBabelDict +Name[hi]=के-बेबल-डिक्श के लिए अनुवाद डाटाबेस वी2 +Name[hu]=Fordítási adatbázis (v2) a KBabelDicthez +Name[is]=Þýðingagagnagrunnur v2 fyrir KBabel orðabókina +Name[it]=Banca dati delle traduzioni v2 per KBabelDict +Name[ja]=KBabelDict トランザクションデータベース v2 +Name[ka]=თარგმნის მონაცემთა ბაზა ვ2 KBabelDict-სთვის +Name[kk]=KBabelDict-тың аударма деректер қорының 2-нұсқасы +Name[lt]=KBabelDict vertimų duomenų bazės 2 versija +Name[ms]=Pangkalan Data Penterjemahan v2 KBabelDict +Name[nb]=Oversettelsesdatabase versjon 2 for KBabelDict +Name[nds]=Översettendatenbank V2 för KBabelDict +Name[ne]=KBabelDict का लागि अनुबाद डाटाबेस v2 +Name[nl]=Vertalingendatabase versie2 voor KBabelDict +Name[nn]=Omsetjingsdatabase versjon 2 for KBabelDict +Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦ-ਕੋਸ਼ ਲਈ ਅਨੁਵਾਦ ਡਾਟਾਬੇਸ ਵਰਜਨ2 +Name[pl]=Baza tłumaczeń v2 dla KBabelDict +Name[pt]=Base de Dados de Traduções v2 do KBabelDict +Name[pt_BR]=Banco de Dados de Traduções v2 para o KBabelDict +Name[ru]=Версия 2 базы данных перевода для KBabelDict +Name[sk]=Databáza prekladov v2 pre KBabelDict +Name[sl]=Zbirka prevodov različice 2 za KBabelDict +Name[sr]=Преводилачка база података v2 за KBabelDict +Name[sr@Latn]=Prevodilačka baza podataka v2 za KBabelDict +Name[sv]=Översättningsdatabas version 2 för Kbabeldict +Name[ta]= Kபாபேலுக்கான மொழிபெயர்ப்பு தரவுத்தளம் v2 +Name[tg]=Тафсири 2 базаи маълумоти тарҷумаҳо барои KBabelDict +Name[tr]=KBabelDict için Çeviri Veritabanı v2 +Name[uk]=Версія 2 бази даних перекладів для KBabelDict +Name[zh_CN]=KBabelDict 的翻译数据库 v2 +Name[zh_TW]=KBabelDict 翻譯資料庫 v2 +X-KDE-Library=kbabeldict_dbsearchengine2 +ServiceTypes=KBabelDictModule diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbseprefwidget.ui b/kbabel/kbabeldict/modules/dbsearchengine2/dbseprefwidget.ui new file mode 100644 index 00000000..c233265f --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbseprefwidget.ui @@ -0,0 +1,1039 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>DBSearchEnginePref</class> +<author>Andrea Rizzi <rizzi@kde.org></author> +<widget class="QWidget"> + <property name="name"> + <cstring>DBSEPrefWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>414</width> + <height>426</height> + </rect> + </property> + <property name="caption"> + <string>DBSEPrefWidget</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>TabWidget6</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string></string> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>Widget4</cstring> + </property> + <attribute name="title"> + <string>Generic</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>ButtonGroup2</cstring> + </property> + <property name="title"> + <string>Search Mode</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>allRB</cstring> + </property> + <property name="text"> + <string>Search in whole database (slow)</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Scroll the whole database and return everything that matches +according to the rules defined in tabs <strong> Generic </strong> +and <strong>Match</strong></string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>slistRB</cstring> + </property> + <property name="text"> + <string>Search in list of "good keys" (best)</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Search in a list of <em>good keys</em> (see <strong>Good keys</strong> tab) with rules defined in <strong>Search</strong> tab. +This is the best way to search because the <em>good keys</em> list probably contains all the keys that match with your query. However, it is smaller than the whole database.</string> + </property> + </widget> + <widget class="QRadioButton" row="2" column="0"> + <property name="name"> + <cstring>rlistRB</cstring> + </property> + <property name="text"> + <string>Return the list of "good keys" (fast)</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Returns the whole <em>good keys</em> list. Rules defined in <strong>Search</strong> tab are ignored.</string> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>caseSensitiveCB</cstring> + </property> + <property name="text"> + <string>Case sensitive</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>If it is checked the search will be case sensitive. It is ignored if you use <em>Return the list of "good keys"</em> search mode.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>normalizeCB</cstring> + </property> + <property name="text"> + <string>Normalize white space</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Remove white spaces at the beginning and at the end of the phrase. +It also substitutes groups of more than one space character with only one space character.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>removeContextCB</cstring> + </property> + <property name="text"> + <string>Remove context comment</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Remove, if exists, the _:comment</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout11</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel3</cstring> + </property> + <property name="text"> + <string>Character to be ignored:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>ignoreLE</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>Widget5</cstring> + </property> + <attribute name="title"> + <string>Search</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>ButtonGroup1</cstring> + </property> + <property name="title"> + <string>Matching Method</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer row="1" column="0"> + <property name="name"> + <cstring>Spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="2" column="0"> + <property name="name"> + <cstring>Spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="2" column="1"> + <property name="name"> + <cstring>containedCB</cstring> + </property> + <property name="text"> + <string>Query is contained</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Match if query is contained in database string</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="1"> + <property name="name"> + <cstring>containsCB</cstring> + </property> + <property name="text"> + <string>Query contains</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Match if query contains the database string</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>normalTextRB</cstring> + </property> + <property name="text"> + <string>Normal text</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Consider the search string as normal text.</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="1"> + <property name="name"> + <cstring>equalCB</cstring> + </property> + <property name="text"> + <string>Equal</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Match if query and database string are equal</string> + </property> + </widget> + <spacer row="3" column="0"> + <property name="name"> + <cstring>Spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QRadioButton" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>RegExpRB</cstring> + </property> + <property name="text"> + <string>Regular expression</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Consider the search string as a regular expression</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox3</cstring> + </property> + <property name="title"> + <string>Word Substitution</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>If you use one or two <em>word substitution</em> each time you search a phrase with less than the specified number of words, the search engine will also search for all phrases that differ from the original one in one or two words.<p> +<strong>Example:</strong><br> +If you search for <em>My name is Andrea</em> and you have activated <em>one word substitution</em> you may also find phrases like <em>My name is Joe</em> or <em>Your name is Andrea</em>.</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer row="3" column="0"> + <property name="name"> + <cstring>Spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>oneWordSubCB</cstring> + </property> + <property name="text"> + <string>Use one word substitution</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>Spacer9</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>TextLabel1</cstring> + </property> + <property name="text"> + <string>Max number of words in the query:</string> + </property> + </widget> + <widget class="QSpinBox" row="3" column="2"> + <property name="name"> + <cstring>twoWordSubSB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maxValue"> + <number>14</number> + </property> + <property name="value"> + <number>10</number> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>twoWordSubCB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Use two word substitution</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>TextLabel2</cstring> + </property> + <property name="text"> + <string>Max number of words in the query:</string> + </property> + </widget> + <widget class="QLayoutWidget" row="5" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel5_3</cstring> + </property> + <property name="text"> + <string>[A-Za-z0-9_%</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>regExpLE</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel6_2</cstring> + </property> + <property name="text"> + <string>]</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="4" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>TextLabel4</cstring> + </property> + <property name="text"> + <string>Local characters for regular expressions:</string> + </property> + </widget> + <widget class="QSpinBox" row="1" column="2"> + <property name="name"> + <cstring>oneWordSubSB</cstring> + </property> + <property name="maxValue"> + <number>200</number> + </property> + <property name="minValue"> + <number>2</number> + </property> + <property name="value"> + <number>40</number> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>Widget6</cstring> + </property> + <attribute name="title"> + <string>Database</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>TextLabel7_2</cstring> + </property> + <property name="text"> + <string>Database folder:</string> + </property> + </widget> + <widget class="KURLRequester" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>dirInput</cstring> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>autoAddCB_2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Auto add entry to database</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>Automatically add an entry to the database if a new translation is notified by someone (may be kbabel)</string> + </property> + </widget> + <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_4</cstring> + </property> + <property name="text"> + <string>Auto added entry author:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>authorLE</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Put here the name and email address that you want to use as <em>last translator</em> filed when you auto-add entry to the database (e.g. when you modify a translation with kbabel).<p></string> + </property> + </widget> + </hbox> + </widget> + <widget class="QPushButton" row="4" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>scanFilePB</cstring> + </property> + <property name="text"> + <string>Scan Single PO File</string> + </property> + </widget> + <widget class="QPushButton" row="5" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>scanPB_2</cstring> + </property> + <property name="text"> + <string>Scan Folder</string> + </property> + </widget> + <widget class="QPushButton" row="6" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>scanrecPB</cstring> + </property> + <property name="text"> + <string>Scan Folder && Subfolders</string> + </property> + </widget> + <widget class="QLayoutWidget" row="8" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout5</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>filenameLB</cstring> + </property> + <property name="text"> + <string>Scanning file:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>entriesLB</cstring> + </property> + <property name="text"> + <string>Entries added:</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="9" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QProgressBar" row="2" column="1"> + <property name="name"> + <cstring>processPB</cstring> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="centerIndicator"> + <bool>true</bool> + </property> + <property name="indicatorFollowsStyle"> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel1_3</cstring> + </property> + <property name="text"> + <string>Total progress:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>TextLabel3_3</cstring> + </property> + <property name="text"> + <string>Processing file:</string> + </property> + </widget> + <widget class="QProgressBar" row="0" column="1"> + <property name="name"> + <cstring>totalPB</cstring> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="centerIndicator"> + <bool>true</bool> + </property> + </widget> + <widget class="QProgressBar" row="1" column="1"> + <property name="name"> + <cstring>loadingPB</cstring> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="centerIndicator"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>TextLabel2_3</cstring> + </property> + <property name="text"> + <string>Loading file:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QPushButton" row="10" column="2"> + <property name="name"> + <cstring>exportPB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Export...</string> + </property> + </widget> + <widget class="QPushButton" row="10" column="0"> + <property name="name"> + <cstring>statPB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Statistics</string> + </property> + </widget> + <widget class="QPushButton" row="10" column="1"> + <property name="name"> + <cstring>repeatPB</cstring> + </property> + <property name="text"> + <string>Repeated Strings</string> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Good Keys</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox4</cstring> + </property> + <property name="title"> + <string>Generic</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qml>Here you can define how to fill the <em>good keys list</em>.<p> +You can set the minimum number of words of the query that a key must have to be inserted in the <em>good keys list</em>.<p> +You can also set the minimum number of words of the key that the query must have to insert the key in the list.<p> +These two numbers are the percentage of the total number of words. If the result of this percentage is less than one, the engine will set it to one.<p> +Finally you can set the maximum number of entries in the list.</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>TextLabel3_2</cstring> + </property> + <property name="text"> + <string>Minimum number of words of the key also in the query (%):</string> + </property> + <property name="textFormat"> + <enum>RichText</enum> + </property> + </widget> + <widget class="QSlider" row="1" column="0"> + <property name="name"> + <cstring>thresholdSL</cstring> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>SpinBox5</cstring> + </property> + <property name="suffix"> + <string>%</string> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>TextLabel2_2</cstring> + </property> + <property name="text"> + <string>Minimum number of query words in the key (%):</string> + </property> + </widget> + <widget class="QSpinBox" row="4" column="1"> + <property name="name"> + <cstring>maxSB</cstring> + </property> + <property name="maxValue"> + <number>5000</number> + </property> + <property name="value"> + <number>30</number> + </property> + </widget> + <widget class="QSpinBox" row="3" column="1"> + <property name="name"> + <cstring>SpinBox6</cstring> + </property> + <property name="suffix"> + <string>%</string> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>TextLabel4_2</cstring> + </property> + <property name="text"> + <string>Max list length:</string> + </property> + </widget> + <widget class="QSlider" row="3" column="0"> + <property name="name"> + <cstring>thresholdOrigSL</cstring> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox3_2</cstring> + </property> + <property name="title"> + <string>Frequent Words</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel1_2</cstring> + </property> + <property name="text"> + <string>Discard words more frequent than:</string> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>freqSB</cstring> + </property> + <property name="suffix"> + <string>/10000</string> + </property> + <property name="maxValue"> + <number>10000</number> + </property> + <property name="lineStep"> + <number>1</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>nothingCB</cstring> + </property> + <property name="text"> + <string>Frequent words are considered as in every key</string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + </spacer> + </vbox> + </widget> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>thresholdSL</sender> + <signal>valueChanged(int)</signal> + <receiver>SpinBox5</receiver> + <slot>setValue(int)</slot> + </connection> + <connection> + <sender>thresholdOrigSL</sender> + <signal>valueChanged(int)</signal> + <receiver>SpinBox6</receiver> + <slot>setValue(int)</slot> + </connection> + <connection> + <sender>SpinBox5</sender> + <signal>valueChanged(int)</signal> + <receiver>thresholdSL</receiver> + <slot>setValue(int)</slot> + </connection> + <connection> + <sender>SpinBox6</sender> + <signal>valueChanged(int)</signal> + <receiver>thresholdOrigSL</receiver> + <slot>setValue(int)</slot> + </connection> +</connections> +<includes> + <include location="local" impldecl="in declaration">klocale.h</include> + <include location="global" impldecl="in declaration">kseparator.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.cpp new file mode 100644 index 00000000..7634a799 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.cpp @@ -0,0 +1,98 @@ +#include <qradiobutton.h> +#include <qslider.h> +#include <qspinbox.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <klocale.h> +#include <kfiledialog.h> +#include <kurlrequester.h> +#include <qtoolbutton.h> +#include <klineedit.h> +#include <kstandarddirs.h> +#include <knuminput.h> + +#include "dbse2.h" +#include "preferenceswidget.h" + +KDB2PreferencesWidget::KDB2PreferencesWidget(QWidget *parent, const char* name) + : PrefWidget(parent,name) +{ + QVBoxLayout *layout = new QVBoxLayout(this); +// QLabel *label = new QLabel(i18n("Settings for KDE Database Search Engine"),this); +// layout->addWidget(label); + + dbpw = new DBSearchEnginePrefWidget(this); + dbpw->dbDirectory->setMode(KFile::Directory | KFile::LocalOnly); + dbpw->show(); + layout->addWidget(dbpw); + setMinimumSize(300,300); + + standard(); + +// connect(dbpw->browseTB_3,SIGNAL(clicked()),SLOT(browse1())); + + emit restoreNow(); //Fill with actual params. + +} + +KDB2PreferencesWidget::~KDB2PreferencesWidget() +{ +} + +void KDB2PreferencesWidget::apply() +{ +emit applyNow(); +} + +void KDB2PreferencesWidget::cancel() +{ +emit restoreNow(); +} + +void KDB2PreferencesWidget::standard() +{ +QString defaultDir; + KStandardDirs * dirs = KGlobal::dirs(); + if(dirs) + { + defaultDir = dirs->saveLocation("data"); + if(defaultDir.right(1)!="/") + defaultDir+="/"; + defaultDir += "kbabeldict/dbsearchengine2"; + } +dbpw->dbDirectory->setURL(defaultDir); + +dbpw->autoUpdate->setChecked(true); + +dbpw->useSentence->setChecked(true); +dbpw->useGlossary->setChecked(true); +dbpw->useExact->setChecked(true); +dbpw->useDivide->setChecked(true); +dbpw->useAlpha->setChecked(true); +dbpw->useWordByWord->setChecked(true); +dbpw->useDynamic->setChecked(true); +dbpw->scoreDivide->setValue(90); +dbpw->scoreExact->setValue(100); +dbpw->scoreSentence->setValue(90); +dbpw->scoreWordByWord->setValue(70); +dbpw->scoreGlossary->setValue(98); +dbpw->scoreAlpha->setValue(98); +dbpw->scoreDynamic->setValue(80); + +dbpw->numberOfResult->setValue(5); +dbpw->minScore->setValue(60); + +dbpw->firstCapital->setChecked(true); +dbpw->allCapital->setChecked(false); +dbpw->accelerator->setChecked(true); +dbpw->sameLetter->setChecked(true); +dbpw->checkLang->setChecked(true); +dbpw->useFilters->setChecked(false); +dbpw->dateToday->setChecked(false); +/* + */ + //dbpw->dirInput->setURL(defaultDir); +} + +#include "preferenceswidget.moc" diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.h b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.h new file mode 100644 index 00000000..4714fd13 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.h @@ -0,0 +1,26 @@ +#ifndef PREFERENCESWIDGET_H +#define PREFERENCESWIDGET_H + +#include "searchengine.h" +#include "dbse2.h" + +class KDB2PreferencesWidget : public PrefWidget +{ + Q_OBJECT + +public: + KDB2PreferencesWidget(QWidget *parent=0, const char* name=0); + virtual ~KDB2PreferencesWidget(); + + virtual void apply(); + virtual void cancel(); + virtual void standard(); + DBSearchEnginePrefWidget *dbpw; + +signals: + void applyNow(); + void restoreNow(); + +}; + +#endif diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/sourcedialog.ui b/kbabel/kbabeldict/modules/dbsearchengine2/sourcedialog.ui new file mode 100644 index 00000000..3f4030a0 --- /dev/null +++ b/kbabel/kbabeldict/modules/dbsearchengine2/sourcedialog.ui @@ -0,0 +1,266 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>SourceDialog</class> +<widget class="QDialog"> + <property name="name"> + <cstring>SourceDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>415</width> + <height>385</height> + </rect> + </property> + <property name="caption"> + <string>Edit Source</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="2" column="1"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton" row="2" column="0"> + <property name="name"> + <cstring>ok</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + </widget> + <widget class="KPushButton" row="2" column="2"> + <property name="name"> + <cstring>cancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + </widget> + <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Additional Informations</string> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="geometry"> + <rect> + <x>11</x> + <y>76</y> + <width>108</width> + <height>29</height> + </rect> + </property> + <property name="text"> + <string>Status: </string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>projectName</cstring> + </property> + <property name="geometry"> + <rect> + <x>125</x> + <y>22</y> + <width>182</width> + <height>21</height> + </rect> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>projectKeywords</cstring> + </property> + <property name="geometry"> + <rect> + <x>125</x> + <y>49</y> + <width>182</width> + <height>21</height> + </rect> + </property> + </widget> + <widget class="KComboBox"> + <property name="name"> + <cstring>status</cstring> + </property> + <property name="geometry"> + <rect> + <x>125</x> + <y>76</y> + <width>182</width> + <height>29</height> + </rect> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="geometry"> + <rect> + <x>11</x> + <y>22</y> + <width>108</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Project name:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="geometry"> + <rect> + <x>11</x> + <y>49</y> + <width>108</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Project keywords:</string> + </property> + </widget> + </widget> + <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>General Info</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>sourceName</cstring> + </property> + </widget> + <widget class="KComboBox" row="1" column="1"> + <item> + <property name="text"> + <string>Single File</string> + </property> + </item> + <item> + <property name="text"> + <string>Single Folder</string> + </property> + </item> + <item> + <property name="text"> + <string>Recursive Folder</string> + </property> + </item> + <property name="name"> + <cstring>type</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Source name:</string> + </property> + </widget> + <widget class="KURLRequester" row="2" column="1"> + <property name="name"> + <cstring>sourceLocation</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Type:</string> + </property> + </widget> + <widget class="KPushButton" row="3" column="1"> + <property name="name"> + <cstring>filterDialog</cstring> + </property> + <property name="text"> + <string>Setup Filter...</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Location:</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0"> + <property name="name"> + <cstring>useFilter</cstring> + </property> + <property name="text"> + <string>Use filter</string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>ok</sender> + <signal>clicked()</signal> + <receiver>SourceDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>cancel</sender> + <signal>clicked()</signal> + <receiver>SourceDialog</receiver> + <slot>reject()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kbabel/kbabeldict/modules/poauxiliary/Makefile.am b/kbabel/kbabeldict/modules/poauxiliary/Makefile.am new file mode 100644 index 00000000..75509337 --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/Makefile.am @@ -0,0 +1,36 @@ +## Makefile.am for poauxiliary + +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +#SUBDIRS = + + +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +kde_module_LTLIBRARIES = kbabeldict_poauxiliary.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes) + + +kbabeldict_poauxiliary_la_SOURCES = poauxiliary.cpp preferenceswidget.cpp\ + pa_factory.cpp pwidget.ui +kbabeldict_poauxiliary_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO) +kbabeldict_poauxiliary_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined + + + +# these are the headers for your project +noinst_HEADERS = poauxiliary.h preferenceswidget.h pa_factory.h + + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + + +# this is where the kdelnk file will go +#datadir = $(kde_datadir)/kbabeldict/modules +#data_DATA = poauxiliary.rc + +kde_services_DATA = poauxiliary.desktop +EXTRA_DIST = $(kde_services_DATA) diff --git a/kbabel/kbabeldict/modules/poauxiliary/pa_factory.cpp b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.cpp new file mode 100644 index 00000000..1448e2b0 --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.cpp @@ -0,0 +1,110 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <klocale.h> +#include <kinstance.h> +#include <kaboutdata.h> +#include <kdebug.h> + +#include "pa_factory.h" +#include "poauxiliary.h" + + +extern "C" +{ + KDE_EXPORT void *init_kbabeldict_poauxiliary() + { + return new PaFactory; + } +} + + +KInstance *PaFactory::s_instance = 0; +KAboutData *PaFactory::s_about = 0; + + +PaFactory::PaFactory( QObject *parent, const char *name) + : KLibFactory(parent,name) +{ +} + +PaFactory::~PaFactory() +{ + if(s_instance) + { + delete s_instance; + s_instance=0; + } + + if(s_about) + { + delete s_about; + s_about=0; + } +} + + +QObject *PaFactory::createObject( QObject *parent, const char *name + , const char *classname, const QStringList &) +{ + if(QCString(classname) != "SearchEngine") + { + kdError() << "not a SearchEngine requested" << endl; + return 0; + } + + return new PoAuxiliary(parent,name); +} + + +KInstance *PaFactory::instance() +{ + if(!s_instance) + { + s_about = new KAboutData( "poauxiliary", I18N_NOOP("PO Auxiliary") + , "1.0" + , I18N_NOOP("A simple module for exact searching in a PO file") + , KAboutData::License_GPL + , "Copyright 2000, Matthias Kiefer" + ,0,0, "kiefer@kde.org"); + + s_about->addAuthor("Matthias Kiefer",0,"kiefer@kde.org"); + + s_instance = new KInstance(s_about); + } + + return s_instance; +} + +#include "pa_factory.moc" diff --git a/kbabel/kbabeldict/modules/poauxiliary/pa_factory.h b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.h new file mode 100644 index 00000000..8871a538 --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.h @@ -0,0 +1,60 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef PA_FACTORY_H +#define PA_FACTORY_H + +#include <klibloader.h> +class KInstance; +class KAboutData; + +class PaFactory : public KLibFactory +{ + Q_OBJECT +public: + PaFactory( QObject *parent=0, const char *name=0); + ~PaFactory(); + + virtual QObject *createObject( QObject *parent=0, const char *name=0 + , const char *classname="QObject" + , const QStringList &args = QStringList()); + + static KInstance *instance(); + +private: + static KInstance *s_instance; + static KAboutData *s_about; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.cpp b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.cpp new file mode 100644 index 00000000..373f123d --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.cpp @@ -0,0 +1,554 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <klocale.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kinstance.h> + +#include <qregexp.h> +#include <qtimer.h> +#include <qstylesheet.h> + +#include "poauxiliary.h" +#include "preferenceswidget.h" +#include "pa_factory.h" + +#include <resources.h> +#include <catalog.h> + +using namespace KBabel; + +PoAuxiliary::PoAuxiliary(QObject *parent, const char *name) + : SearchEngine(parent, name) +{ + catalog = new Catalog(this, "PoAuxiliary::catalog"); + prefWidget=0; + error=false; + stop=false; + active=false; + loading=false; + initialized=false; + + ignoreFuzzy=true; + + loadTimer = new QTimer(this); + connect(loadTimer,SIGNAL(timeout()),this,SLOT(loadAuxiliary())); + + msgidDict.setAutoDelete(true); +} + +PoAuxiliary::~PoAuxiliary() +{ + results.clear(); +} + +bool PoAuxiliary::isReady() const +{ + return !error; +} + + +bool PoAuxiliary::isSearching() const +{ + return active; +} + + +void PoAuxiliary::saveSettings(KConfigBase *config) +{ + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + config->writeEntry("Auxiliary", url); + config->writeEntry("IgnoreFuzzy",ignoreFuzzy); +} + +void PoAuxiliary::readSettings(KConfigBase *config) +{ + bool needLoading=false; + + QString newPath = config->readEntry("Auxiliary" + ,"../../../de/messages/@DIR1@/@PACKAGE@.po"); + if(!initialized) + { + url = newPath; + } + else if(newPath != url) + { + url = newPath; + needLoading = true; + } + + ignoreFuzzy = config->readBoolEntry("IgnoreFuzzy",true); + + if(needLoading && !loadTimer->isActive()) + { + kdDebug(KBABEL_SEARCH) << "readSettings" << endl; + loadTimer->start(100,true); + } + + restoreSettings(); +} + +PrefWidget *PoAuxiliary::preferencesWidget(QWidget *parent) +{ + prefWidget = new AuxiliaryPreferencesWidget(parent,"pocompendium_prefwidget"); + connect(prefWidget, SIGNAL(applySettings()), this, SLOT(applySettings())); + connect(prefWidget, SIGNAL(restoreSettings()) + , this, SLOT(restoreSettings())); + + restoreSettings(); + + return prefWidget; +} + +const KAboutData *PoAuxiliary::about() const +{ + return PaFactory::instance()->aboutData(); +} + + +QString PoAuxiliary::name() const +{ + return i18n("PO Auxiliary"); +} + +QString PoAuxiliary::id() const +{ + return "poauxiliary"; +} + +QString PoAuxiliary::lastError() +{ + return errorMsg; +} + +bool PoAuxiliary::startSearch(const QString& t, uint pluralForm, const SearchFilter*filter) +{ + QString text(t); + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + if(!initialized) + { + loadAuxiliary(); + } + + if(error) + return false; + + if(isSearching()) + return false; + + stop=false; + active = true; + emit started(); + + clearResults(); + + kapp->processEvents(100); + + text.replace("\n",""); + + Entry *entry = msgidDict[text]; + if(entry) + { + if( !(entry->fuzzy && ignoreFuzzy) ) + { + SearchResult *result = new SearchResult; + result->requested =QStyleSheet::convertFromPlainText(text); + result->found = QStyleSheet::convertFromPlainText(text); + result->translation = + QStyleSheet::convertFromPlainText(entry->translation); + + result->plainRequested = text; + result->plainFound=text; + result->plainTranslation=entry->translation; + result->score=100; + + if(entry->fuzzy) + { + result->translation="<qt><font color=\"red\">"+i18n("fuzzy") + +"</font><hr/>" + result->translation+"</qt>"; + } + + TranslationInfo *info = new TranslationInfo; + info->location = auxPackage; + info->translator = auxTranslator; + info->description = entry->comment; + info->filePath = auxURL; + result->descriptions.append(info); + + results.append(result); + + emit numberOfResultsChanged(1); + emit resultFound(result); + } + } + + + active = false; + stop = false; + emit finished(); + + return true; +} + + +bool PoAuxiliary::startSearchInTranslation(const QString& text) +{ + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + if(!initialized) + { + loadAuxiliary(); + } + + if(error) + return false; + + if(isSearching()) + return false; + + stop=false; + active = true; + emit started(); + + clearResults(); + + kapp->processEvents(100); + + Entry *entry = msgstrDict[text]; + if(entry) + { + if( !(entry->fuzzy && ignoreFuzzy) ) + { + SearchResult *result = new SearchResult; + result->requested =QStyleSheet::convertFromPlainText(entry->orig); + result->found = QStyleSheet::convertFromPlainText(entry->orig); + result->translation = + QStyleSheet::convertFromPlainText(text); + + result->plainRequested = entry->orig; + result->plainFound=entry->orig; + result->plainTranslation=text; + result->score=100; + + if(entry->fuzzy) + { + result->translation="<qt><font color=\"red\">"+i18n("fuzzy") + +"</font><hr/>" + result->translation+"</qt>"; + } + + TranslationInfo *info = new TranslationInfo; + info->location = auxPackage; + info->translator = auxTranslator; + info->description = entry->comment; + info->filePath = auxURL; + result->descriptions.append(info); + + results.append(result); + + emit numberOfResultsChanged(1); + emit resultFound(result); + } + } + + + active = false; + stop = false; + emit finished(); + + return true; +} + +void PoAuxiliary::stopSearch() +{ + stop=true; +} + + +void PoAuxiliary::applySettings() +{ + if(!prefWidget) + return; + + bool needLoading=false; + + if(isSearching()) + stopSearch(); + + QString newPath = prefWidget->url(); + if(!initialized) + { + url = newPath; + } + else if(newPath != url) + { + url = newPath; + needLoading=true; + } + + ignoreFuzzy = prefWidget->ignoreFuzzy(); + + if(needLoading && !loadTimer->isActive()) + { + loadTimer->start(100,true); + } +} + +void PoAuxiliary::restoreSettings() +{ + if(!prefWidget) + return; + + prefWidget->setURL(url); + prefWidget->setIgnoreFuzzy(ignoreFuzzy); +} + +void PoAuxiliary::loadAuxiliary() +{ + if(loadTimer->isActive()) + loadTimer->stop(); + + if(loading) + return; + + loading=true; + error=false; + + QString path=url; + + if(path.contains("@LANG@")) + { + path.replace("@LANG@",langCode); + } + if(path.contains("@PACKAGE@")) + { + int pos=package.findRev("/"); + if( pos<0 ) pos=0; + path.replace("@PACKAGE@",package.mid(pos)); + } + if(path.contains("@PACKAGEDIR@")) + { + QString packagedir; + int pos=package.findRev("/"); + if( pos > 0 ) packagedir=package.left(pos); + else packagedir=""; + path.replace("@PACKAGEDIR@",packagedir); + kdDebug(KBABEL_SEARCH) << "Packagedir found " << packagedir << endl; + } + QRegExp reg("@DIR[0-9]+@"); + if(path.contains(reg)) + { + int pos=reg.search(path); + int len = reg.matchedLength(); + + while(pos>=0) + { + QString num=path.mid(pos+4,len-5); + + bool ok; + int number=num.toInt(&ok); + if(ok) + { + QString dir=directory(editedFile,number); + QString s("@DIR%1@"); + path.replace(s.arg(number),dir); + + pos+=dir.length(); + } + + pos=reg.search(path); + len = reg.matchedLength(); + } + } + + KURL u; + QRegExp rel("^[a-zA-Z]+:"); + if(rel.search(path) >= 0) + { + u=path; + } + else if(path[0] != '/') // relative path + { + KURL temp(editedFile); + QString dir = temp.directory(); + kdDebug(KBABEL_SEARCH) << dir << endl; + u.setPath(dir+"/"+path); + u.cleanPath(); + kdDebug(KBABEL_SEARCH) << u.prettyURL() << endl; + } + else + { + u.setPath(path); + } + + emit progressStarts(i18n("Loading PO auxiliary")); + connect(catalog, SIGNAL(signalProgress(int)) + , this, SIGNAL(progress(int))); + + ConversionStatus stat = catalog->openURL(u); + if( stat != OK && stat != RECOVERED_PARSE_ERROR) + { + kdDebug(KBABEL_SEARCH) << "error while opening file " << u.prettyURL() << endl; + + if( !error ) + { + error = true; + errorMsg = i18n("Error while trying to open file for PO Auxiliary module:\n%1") + .arg(u.prettyURL()); + emit hasError(errorMsg); + } + } + else + { + error = false; + // build index for fast search + msgidDict.clear(); + msgstrDict.clear(); + + emit progressStarts(i18n("Building index")); + + int total = catalog->numberOfEntries(); + for(int i=0; i < total; i++) + { + if( (100*(i+1))%total < 100 ) + { + emit progress((100*(i+1))/total); + kapp->processEvents(100); + } + + Entry *e = new Entry; + // FIXME: should care about plural forms + e->orig = catalog->msgid(i).first(); + e->orig.replace("\n",""); + kdWarning() << "PoAuxialiary does not support plural forms" << endl; + e->translation = catalog->msgstr(i).first(); + e->comment = catalog->comment(i); + e->fuzzy = catalog->isFuzzy(i); + + msgidDict.insert(catalog->msgid(i,true).first(),e); + msgstrDict.insert(e->translation,e); + } + + auxPackage = catalog->packageName(); + auxURL = catalog->currentURL().url(); + auxTranslator = catalog->lastTranslator(); + } + + disconnect(catalog, SIGNAL(signalProgress(int)) + , this, SIGNAL(progress(int))); + + emit progressEnds(); + + initialized=true; + + loading=false; + + catalog->clear(); +} + + +void PoAuxiliary::setEditedFile(const QString& file) +{ + if(initialized && (url.contains("@DIR") || KURL::isRelativeURL(url)) + && file!=editedFile && !loadTimer->isActive() ) + { + initialized=false; + } + + editedFile=file; +} + + +void PoAuxiliary::setEditedPackage(const QString& pack) +{ + if(initialized && url.contains("@PACKAGE@") && pack!=package + && !loadTimer->isActive() ) + { + initialized=false; + } + + package=pack; +} + + +void PoAuxiliary::setLanguageCode(const QString& lang) +{ + if(initialized && url.contains("@LANG@") && lang!=langCode + && !loadTimer->isActive() ) + { + initialized=false; + } + + langCode=lang; +} + +bool PoAuxiliary::usesRichTextResults() +{ + return true; +} + +QString PoAuxiliary::translate(const QString& text, uint pluralForm) +{ + if(!initialized) + { + loadAuxiliary(); + } + + if(error) + { + return QString::null; + } + + Entry *entry = msgidDict[text]; + if(entry) + { + return entry->translation; + } + + return QString::null; +} + + +#include "poauxiliary.moc" diff --git a/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.desktop b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.desktop new file mode 100644 index 00000000..5629930e --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.desktop @@ -0,0 +1,51 @@ +[Desktop Entry] +Type=Service +Name=Auxiliary PO Module for KBabelDict +Name[bg]=Помощен PO модул за KBabelDict +Name[bs]=Pomoćni PO modul za KBabelDict +Name[ca]=Mòdul PO auxiliar per a KBabelDict +Name[cs]=Doplňkový PO modul pro KBabelDict +Name[cy]=Modiwl PO Ategol i KBabelDict +Name[da]=Auxiliary PO-module for KBabelDict +Name[de]=PO-Hilfsdatei-Modul für KBabelDict +Name[el]=Άρθρωμα βοηθητικού PO για το KBabelDict +Name[es]=Módulo PO auxiliar para KBabelDict +Name[et]=KBabelDicti PO liitlasfaili moodul +Name[eu]=PO modulu laguntzailea KBabelDict-entzat +Name[fa]=پیمانۀ کمکی PO برای KBabelDict +Name[fi]=KBabelDict-ohjelman PO-apumoduuli +Name[fr]=Module de PO auxiliaire pour KBabelDict +Name[gl]=Módulo de PO auxiliar para KBabelDict +Name[hi]=के-बेबल-डिक्श के लिए ऑक्जिलरी पीओ मॉड्यूल +Name[hu]=Kiegészítő PO modul a KBabelDicthez +Name[is]=Viðbótar PO eining fyrir KBabel orðabókina +Name[it]=Modulo ausiliario PO per KBabelDict +Name[ja]=KBabelDict 補助 PO モジュール +Name[ka]=დამხმარე PO მოდული KBabelDict-სთვის +Name[kk]=KBabelDict-тың қосымша PO модулі +Name[lt]=KBabelDict papildomo PO žodyno modulis +Name[ms]=Modul Auksillari PO untuk KBabelDict +Name[nb]=Hjelpeordlistemodul for KBabelDict +Name[nds]=PO-Hülpdateimoduul för KBabelDict +Name[ne]=KBabelDict का लागि सहायक पीओ मोड्युल +Name[nl]=Alternatieve PO-module voor KBabelDict +Name[nn]=Jamføringsmodul for KBabelDict +Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦਕੋਸ਼ ਲਈ ਸਹਾਇਕ PO ਸਹਾਇਕ +Name[pl]=Moduł pomocniczego pliku PO dla KBabelDict +Name[pt]=Módulo de PO Auxiliar para o KBabelDict +Name[pt_BR]=Módulo Auxiliar PO para o KBabelDict +Name[ru]=Вспомогательный модуль PO для KBabelDict +Name[sk]=Iný PO súbore pre KBabelDict +Name[sl]=Dodatni modul PO za KBabelDict +Name[sr]=Помоћни PO модул за KBabelDict +Name[sr@Latn]=Pomoćni PO modul za KBabelDict +Name[sv]=Hjälp-PO modul för Kbabeldict +Name[ta]=Kபாபேலுக்கான இரண்டாம் PO கூறு +Name[tg]=Модули ёрирасони PO барои KBabelDict +Name[tr]=KBabelDict için Yardımcı PO Modülü +Name[uk]=Модуль допоміжного словника PO для KBabelDict +Name[zh_CN]=KBabelDict 的 PO 辅助词典模块 +Name[zh_TW]=KBabelDict 輔助 PO 模組 +X-KDE-Library=kbabeldict_poauxiliary +ServiceTypes=KBabelDictModule +Applications=kbabel diff --git a/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.h b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.h new file mode 100644 index 00000000..27fecba6 --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.h @@ -0,0 +1,136 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + +#ifndef POAUXILIARY_H +#define POAUXILIARY_H + +#include "searchengine.h" + +#include <qguardedptr.h> +#include <qdict.h> +class QTimer; + +namespace KBabel +{ + class Catalog; +} + +class AuxiliaryPreferencesWidget; + +class PoAuxiliary : public SearchEngine +{ + Q_OBJECT + +public: + PoAuxiliary(QObject *parent=0, const char *name=0); + virtual ~PoAuxiliary(); + + virtual bool isReady() const; + + virtual QString translate(const QString& text, uint pluralForm); + + virtual bool isSearching() const; + + virtual void saveSettings(KConfigBase *config); + virtual void readSettings(KConfigBase *config); + + virtual PrefWidget *preferencesWidget(QWidget *parent); + + virtual const KAboutData *about() const; + + virtual QString name() const; + + virtual QString id() const; + + virtual QString lastError(); + + virtual bool usesRichTextResults(); + +public slots: + virtual bool startSearch(const QString& text, unsigned int pluralForm + , const SearchFilter*filter); + virtual bool startSearchInTranslation(const QString& text); + + virtual void stopSearch(); + + virtual void setEditedFile(const QString&); + virtual void setEditedPackage(const QString&); + virtual void setLanguageCode(const QString&); + + +protected slots: + /** reads the current settings from the preferences dialog */ + void applySettings(); + + /** sets the current settings in the preferences dialog */ + void restoreSettings(); + + void loadAuxiliary(); + +private: + QGuardedPtr<AuxiliaryPreferencesWidget> prefWidget; + KBabel::Catalog *catalog; + QString auxPackage; + QString auxTranslator; + QString auxURL; + + QString url; + bool ignoreFuzzy; + + QString editedFile; + QString package; + QString langCode; + + bool error; + QString errorMsg; + + bool stop; + bool active; + bool loading; + bool initialized; + + QTimer *loadTimer; + + struct Entry + { + QString orig; + QString translation; + QString comment; + bool fuzzy; + }; + + QDict<Entry> msgidDict; + QDict<Entry> msgstrDict; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.cpp b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.cpp new file mode 100644 index 00000000..e8d48032 --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.cpp @@ -0,0 +1,115 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <kfiledialog.h> +#include <qpushbutton.h> +#include <klineedit.h> +#include <klocale.h> +#include <kurlrequester.h> + +#include "preferenceswidget.h" +#include "pwidget.h" + +AuxiliaryPreferencesWidget::AuxiliaryPreferencesWidget(QWidget *parent, const char* name) + : PrefWidget(parent,name) + , changed(false) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + prefWidget = new PWidget(this); + layout->addWidget(prefWidget); + + + connect(prefWidget->urlInput->lineEdit(),SIGNAL(textChanged(const QString&)) + , this, SLOT(setChanged())); +} + +AuxiliaryPreferencesWidget::~AuxiliaryPreferencesWidget() +{ +} + + +void AuxiliaryPreferencesWidget::apply() +{ + emit applySettings(); +} + +void AuxiliaryPreferencesWidget::cancel() +{ + emit restoreSettings(); +} + +void AuxiliaryPreferencesWidget::standard() +{ + prefWidget->urlInput->setURL("@PACKAGE@.po"); + changed=true; +} + +void AuxiliaryPreferencesWidget::setURL(const QString url) +{ + prefWidget->urlInput->setURL(url); + changed=false; +} + +QString AuxiliaryPreferencesWidget::url() +{ + changed = false; + return prefWidget->urlInput->url(); +} + +bool AuxiliaryPreferencesWidget::ignoreFuzzy() +{ + changed=false; + return prefWidget->fuzzyBtn->isChecked(); +} + +void AuxiliaryPreferencesWidget::setIgnoreFuzzy(bool flag) +{ + prefWidget->fuzzyBtn->setChecked(flag); +} + +bool AuxiliaryPreferencesWidget::settingsChanged() const +{ + return changed; +} + +void AuxiliaryPreferencesWidget::setChanged() +{ + changed=true; +} + + +#include "preferenceswidget.moc" diff --git a/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.h b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.h new file mode 100644 index 00000000..45488158 --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.h @@ -0,0 +1,77 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef PREFERENCESWIDGET_H +#define PREFERENCESWIDGET_H + +#include "searchengine.h" + +class PWidget; + +class AuxiliaryPreferencesWidget : public PrefWidget +{ + Q_OBJECT + +public: + AuxiliaryPreferencesWidget(QWidget *parent=0, const char* name=0); + virtual ~AuxiliaryPreferencesWidget(); + + virtual void apply(); + virtual void cancel(); + virtual void standard(); + + void setURL(const QString url); + QString url(); + + void setIgnoreFuzzy(bool); + bool ignoreFuzzy(); + + bool settingsChanged() const; + +signals: + void restoreSettings(); + void applySettings(); + +public: + PWidget *prefWidget; + +protected slots: + void setChanged(); + +private: + bool changed; + +}; + +#endif diff --git a/kbabel/kbabeldict/modules/poauxiliary/pwidget.ui b/kbabel/kbabeldict/modules/poauxiliary/pwidget.ui new file mode 100644 index 00000000..8179caed --- /dev/null +++ b/kbabel/kbabeldict/modules/poauxiliary/pwidget.ui @@ -0,0 +1,133 @@ +<!DOCTYPE UI><UI> +<class>PWidget</class> +<widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>PWidget</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>335</width> + <height>306</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string></string> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel1</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>&Path to auxiliary file:</string> + </property> + <property> + <name>buddy</name> + <cstring>urlInput</cstring> + </property> + </widget> + <widget> + <class>KURLRequester</class> + <property stdset="1"> + <name>name</name> + <cstring>urlInput</cstring> + </property> + </widget> + <widget> + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>fuzzyBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>&Ignore fuzzy entries</string> + </property> + </widget> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel1_2</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string><qt><p> +The following variables will be replaced in the path if available: +<ul> +<li><b>@PACKAGE@</b>: the name of the currently translated application or package</li> +<li><b>@LANG@</b>: the language code</li> +<li><b>@DIR<em>n</em>@</b>: where n is a positive integer. This expands to the nth folder counted from the filename</li> +</ul></p></qt></string> + </property> + </widget> + <spacer> + <property> + <name>name</name> + <cstring>Spacer1</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KURLRequester</class> + <header location="global">kurlrequester.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image> + <name>image0</name> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> + </image> +</images> +</UI> diff --git a/kbabel/kbabeldict/modules/pocompendium/Makefile.am b/kbabel/kbabeldict/modules/pocompendium/Makefile.am new file mode 100644 index 00000000..b4fe4974 --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/Makefile.am @@ -0,0 +1,39 @@ +## Makefile.am for pocompendium + +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +#SUBDIRS = + + +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +kde_module_LTLIBRARIES = kbabeldict_pocompendium.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes) + + +# which sources should be compiled for kbabel +kbabeldict_pocompendium_la_SOURCES = pocompendium.cpp preferenceswidget.cpp \ + pc_factory.cpp pwidget.ui compendiumdata.cpp + +kbabeldict_pocompendium_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO) +kbabeldict_pocompendium_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined + + + +# these are the headers for your project +noinst_HEADERS = pocompendium.h preferenceswidget.h pc_factory.h \ + compendiumdata.h + + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + + +# this is where the kdelnk file will go +#datadir = $(kde_datadir)/kbabeldict/modules +#data_DATA = pocompendium.rc + +kde_services_DATA = pocompendium.desktop +EXTRA_DIST = $(kde_services_DATA) diff --git a/kbabel/kbabeldict/modules/pocompendium/compendiumdata.cpp b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.cpp new file mode 100644 index 00000000..d862b236 --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.cpp @@ -0,0 +1,261 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2001 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 "compendiumdata.h" + +#include <resources.h> +#include <catalog.h> +#include <tagextractor.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> + +using namespace KBabel; + +CompendiumData::CompendiumData(QObject *parent) + : QObject(parent) + , _active(false) + , _error(false) + , _initialized(false) + , _catalog(0) + , _exactDict(9887) + , _allDict(9887) + , _wordDict(9887) + , _textonlyDict(9887) +{ + _catalog = new Catalog(this, "CompendiumData::catalog", QString::null); + _exactDict.setAutoDelete(true); + _allDict.setAutoDelete(true); + _wordDict.setAutoDelete(true); + _textonlyDict.setAutoDelete(true); +} + + +bool CompendiumData::load(KURL url) +{ + if(_active) + return false; + + + _error = false; + _active = true; + + _exactDict.clear(); + _allDict.clear(); + _wordDict.clear(); + _textonlyDict.clear(); + + + emit progressStarts(i18n("Loading PO compendium")); + connect(_catalog, SIGNAL(signalProgress(int)), this, SIGNAL(progress(int))); + + ConversionStatus stat=_catalog->openURL(url); + + disconnect(_catalog, SIGNAL(signalProgress(int)) + , this, SIGNAL(progress(int))); + + + if( stat!= OK && stat != RECOVERED_PARSE_ERROR) + { + kdDebug(KBABEL_SEARCH) << "error while opening file " << url.prettyURL() << endl; + + _error = true; + _errorMsg = i18n("Error while trying to read file for PO Compendium module:\n%1") + .arg(url.prettyURL()); + + emit progressEnds(); + + _active = false; + _initialized=true; + + return false; + } + + emit progressStarts(i18n("Building indices")); + + int total = _catalog->numberOfEntries(); + for(int i=0; i < total; i++) + { + if( (100*(i+1))%total < 100 ) + { + emit progress((100*(i+1))/total); + kapp->processEvents(100); + } + + // FIXME: shoudl care about plural forms + QString temp = _catalog->msgid(i,true).first(); + + int *index = new int(i); + _exactDict.insert(temp,index); + + + temp = simplify(temp); + temp = temp.lower(); + + if(!temp.isEmpty() && temp.length() > 1) + { + // add to allDict + QValueList<int> *indexList=_allDict[temp]; + + if(!indexList) + { + indexList = new QValueList<int>; + _allDict.insert(temp,indexList); + } + + indexList->append(i); + + // add to textonlyDict + QString temp1 = temp; + temp1.remove( ' ' ); + + indexList=_textonlyDict[temp1]; + + if(!indexList) + { + indexList = new QValueList<int>; + _textonlyDict.insert(temp1,indexList); + kdDebug() << "Adding " << temp1 << endl; + } + + indexList->append(i); + + // add to wordDict + QStringList wList = wordList(temp); + for ( QStringList::Iterator it = wList.begin() + ; it != wList.end(); ++it ) + { + if( (*it).length() > 1) + { + indexList=_wordDict[*it]; + + if(!indexList) + { + indexList = new QValueList<int>; + _wordDict.insert(*it,indexList); + } + + indexList->append(i); + } + } + } + } + + // remove words, that are too frequent + uint max=_allDict.count()/10; + QDictIterator< QValueList<int> > it(_wordDict); + while ( it.current() ) + { + if(it.current()->count() > max) + { + _wordDict.remove(it.currentKey()); + } + else + { + ++it; + } + } + + + _initialized=true; + + emit progressEnds(); + + + + _active = false; + + return true; +} + +const int* CompendiumData::exactDict(const QString text) const +{ + return _exactDict[text]; +} + +const QValueList<int>* CompendiumData::allDict(const QString text) const +{ + return _allDict[text]; +} + +const QValueList<int>* CompendiumData::wordDict(const QString text) const +{ + return _wordDict[text]; +} + +const QValueList<int>* CompendiumData::textonlyDict(const QString text) const +{ + return _textonlyDict[text]; +} + + +void CompendiumData::registerObject(QObject *obj) +{ + if(!_registered.containsRef(obj)) + _registered.append(obj); +} + +bool CompendiumData::unregisterObject(QObject *obj) +{ + _registered.removeRef(obj); + + return _registered.count()==0; +} + +bool CompendiumData::hasObjects() const +{ + return _registered.count()==0; +} + +QString CompendiumData::simplify(const QString string) +{ + QString result; + + TagExtractor te; + te.setString(string); + result=te.plainString(); + + result=result.simplifyWhiteSpace(); + result=result.stripWhiteSpace(); + + return result; +} + +QStringList CompendiumData::wordList(const QString string) +{ + QString result=CompendiumData::simplify(string); + + return QStringList::split(' ',result); +} + +#include "compendiumdata.moc" diff --git a/kbabel/kbabeldict/modules/pocompendium/compendiumdata.h b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.h new file mode 100644 index 00000000..2fec45cb --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.h @@ -0,0 +1,105 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2001 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ +#ifndef COMPENDIUMDATA_H +#define COMPENDIUMDATA_H + + +#include <kurl.h> +#include <qdict.h> +#include <qobject.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qptrlist.h> + +namespace KBabel +{ +class Catalog; +} + +class CompendiumData : public QObject +{ + Q_OBJECT + +public: + CompendiumData(QObject *parent=0); + + bool load(KURL url); + + const KBabel::Catalog *catalog() const { return _catalog; } + const int *exactDict(const QString text) const; + const QValueList<int> *allDict(const QString text) const; + const QValueList<int> *wordDict(const QString text) const; + const QValueList<int> *textonlyDict(const QString text) const; + + bool active() const { return _active; } + bool initialized() const { return _initialized; } + bool hasErrors() const { return _error; } + QString errorMsg() const { return _errorMsg; } + + /** registers an object, that uses this data */ + void registerObject(QObject *); + /** + * unregisters an object, that uses this data + * + * @return true, if this was the last object + */ + bool unregisterObject(QObject *); + + bool hasObjects() const; + + + static QString simplify(const QString text); + static QStringList wordList(const QString text); + +signals: + void progressStarts(const QString); + void progressEnds(); + void progress(int); + + +private: + bool _active; + bool _error; + bool _initialized; + QString _errorMsg; + + KBabel::Catalog *_catalog; + QDict<int> _exactDict; + QDict< QValueList<int> > _allDict; + QDict< QValueList<int> > _wordDict; + QDict< QValueList<int> > _textonlyDict; + + QPtrList<QObject> _registered; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/pocompendium/pc_factory.cpp b/kbabel/kbabeldict/modules/pocompendium/pc_factory.cpp new file mode 100644 index 00000000..882cc064 --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/pc_factory.cpp @@ -0,0 +1,110 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <klocale.h> +#include <kinstance.h> +#include <kaboutdata.h> +#include <kdebug.h> + +#include "pc_factory.h" +#include "pocompendium.h" + + +extern "C" +{ + KDE_EXPORT void *init_kbabeldict_pocompendium() + { + return new PcFactory; + } +} + + +KInstance *PcFactory::s_instance = 0; +KAboutData *PcFactory::s_about = 0; + + +PcFactory::PcFactory( QObject *parent, const char *name) + : KLibFactory(parent,name) +{ +} + +PcFactory::~PcFactory() +{ + if(s_instance) + { + delete s_instance; + s_instance=0; + } + + if(s_about) + { + delete s_about; + s_about=0; + } +} + + +QObject *PcFactory::createObject( QObject *parent, const char *name + , const char *classname, const QStringList &) +{ + if(QCString(classname) != "SearchEngine") + { + kdError() << "not a SearchEngine requested" << endl; + return 0; + } + + return new PoCompendium(parent,name); +} + + +KInstance *PcFactory::instance() +{ + if(!s_instance) + { + s_about = new KAboutData( "pocompendium", I18N_NOOP("PO Compendium") + , "1.0" + , I18N_NOOP("A module for searching in a PO file") + , KAboutData::License_GPL + , "Copyright 2000-2001, Matthias Kiefer" + ,0,0, "kiefer@kde.org"); + + s_about->addAuthor("Matthias Kiefer",0,"kiefer@kde.org"); + + s_instance = new KInstance(s_about); + } + + return s_instance; +} + +#include "pc_factory.moc" diff --git a/kbabel/kbabeldict/modules/pocompendium/pc_factory.h b/kbabel/kbabeldict/modules/pocompendium/pc_factory.h new file mode 100644 index 00000000..d52fadfe --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/pc_factory.h @@ -0,0 +1,60 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef PC_FACTORY_H +#define PC_FACTORY_H + +#include <klibloader.h> +class KInstance; +class KAboutData; + +class PcFactory : public KLibFactory +{ + Q_OBJECT +public: + PcFactory( QObject *parent=0, const char *name=0); + ~PcFactory(); + + virtual QObject *createObject( QObject *parent=0, const char *name=0 + , const char *classname="QObject" + , const QStringList &args = QStringList()); + + static KInstance *instance(); + +private: + static KInstance *s_instance; + static KAboutData *s_about; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/pocompendium/pocompendium.cpp b/kbabel/kbabeldict/modules/pocompendium/pocompendium.cpp new file mode 100644 index 00000000..0cd79fb3 --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/pocompendium.cpp @@ -0,0 +1,1246 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2003 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <klocale.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kstaticdeleter.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kinstance.h> +#include <kio/netaccess.h> + +#include <qregexp.h> +#include <qtextstream.h> +#include <qtimer.h> + +#include "resources.h" +#include "compendiumdata.h" +#include "pocompendium.h" +#include "preferenceswidget.h" +#include "pc_factory.h" + +#include <catalog.h> +#include <catalogitem.h> + +// ngram length and minimal matching for fuzzy search +#define NGRAM_LEN 3 +#define LIM_NGRAM 50 + +using namespace KBabel; + +static KStaticDeleter< QDict<CompendiumData> > compDataDeleter; +QDict<CompendiumData> *PoCompendium::_compDict = 0; + +PoCompendium::PoCompendium(QObject *parent, const char *name) + : SearchEngine(parent, name) +{ + prefWidget=0; + data=0; + error=false; + stop=false; + active=false; + initialized=false; + loading=false; + + langCode = KGlobal::locale()->language(); + + caseSensitive = false; + ignoreFuzzy=true; + wholeWords=true; + + matchEqual = true; + matchNGram = true; + matchIsContained = false; + matchContains = true; + matchWords=true; + + + loadTimer = new QTimer(this); + connect(loadTimer,SIGNAL(timeout()),this,SLOT(slotLoadCompendium())); +} + +PoCompendium::~PoCompendium() +{ + if(isSearching()) + { + stopSearch(); + } + + unregisterData(); +} + +bool PoCompendium::isReady() const +{ + return (isSearching() || !error); +} + + +bool PoCompendium::isSearching() const +{ + return (active || loading); +} + + +void PoCompendium::saveSettings(KConfigBase *config ) +{ + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + config->writeEntry("CaseSensitive",caseSensitive); + config->writeEntry("IgnoreFuzzy", ignoreFuzzy); + config->writeEntry("WholeWords", wholeWords); + + config->writeEntry("MatchEqual", matchEqual); + config->writeEntry("MatchIsContained",matchIsContained); + config->writeEntry("MatchContains", matchContains); + config->writeEntry("MatchWords", matchWords); + config->writeEntry("MatchNGram", matchNGram); + + config->writeEntry("Compendium", url); +} + +void PoCompendium::readSettings(KConfigBase *config) +{ + caseSensitive = config->readBoolEntry("CaseSensitive", false); + ignoreFuzzy = config->readBoolEntry("IgnoreFuzzy",true); + wholeWords = config->readBoolEntry("WholeWords",true); + + matchEqual = config->readBoolEntry("MatchEqual", true); + matchIsContained = config->readBoolEntry("MatchIsContained", false); + matchContains = config->readBoolEntry("MatchContains",true); + matchWords = config->readBoolEntry("MatchWords",true); + matchNGram = config->readBoolEntry("MatchNGram",true); + + QString newPath = config->readEntry("Compendium","http://i18n.kde.org/po_overview/@LANG@.messages"); + if(!initialized) + { + url = newPath; + } + else if(newPath != url) + { + url = newPath; + loadCompendium(); + } + + + restoreSettings(); +} + +PrefWidget *PoCompendium::preferencesWidget(QWidget *parent) +{ + prefWidget = new CompendiumPreferencesWidget(parent,"pocompendium_prefwidget"); + kdDebug(KBABEL_SEARCH) << "PreferencesWidget is " << prefWidget << endl; + connect(prefWidget, SIGNAL(applySettings()), this, SLOT(applySettings())); + connect(prefWidget, SIGNAL(restoreSettings()) + , this, SLOT(restoreSettings())); + + restoreSettings(); + + return prefWidget; +} + +const KAboutData *PoCompendium::about() const +{ + return PcFactory::instance()->aboutData(); +} + + +QString PoCompendium::name() const +{ + return i18n("PO Compendium"); +} + +QString PoCompendium::id() const +{ + return "pocompendium"; +} + +QString PoCompendium::lastError() +{ + return errorMsg; +} + +bool PoCompendium::searchExact(const QString& text, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& ) +{ + const int *index = data->exactDict(text); + if(index) + { + foundIndices.append(*index); + + SearchResult *result = new SearchResult; + result->requested = text; + result->found = data->catalog()->msgid(*index); +#warning kdWarning() << "PoCompendium can't return plural form translation" << endl; + result->translation = data->catalog()->msgstr(*index).first(); + result->score = 100; + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = catalogInfo.lastTranslator; + info->description = data->catalog()->comment(*index); + result->descriptions.append(info); + + addResult(result, results); + return true; + } + + return false; + +} + +bool PoCompendium::searchCaseInsensitive(const QString& text, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& ) +{ + QString searchStr = text.lower(); + + const QValueList<int> *indexList = data->allDict(text.lower()); + if(indexList) + { + QValueList<int>::ConstIterator it; + for( it = indexList->begin(); it != indexList->end(); ++it ) + { + if(foundIndices.contains(*it)) + { + continue; + } + + if(ignoreFuzzy && data->catalog()->isFuzzy(*it)) + { + continue; + } + + + QString origStr = data->catalog()->msgid(*it).first(); + origStr = CompendiumData::simplify(origStr); + + + if(!caseSensitive) + { + origStr = origStr.lower(); + } + + if(origStr==searchStr) + { + foundIndices.append(*it); + + SearchResult *result = new SearchResult; + result->requested = text; + result->found = data->catalog()->msgid(*it); + result->translation = *(data->catalog()->msgstr(*it).at(pluralForm)); + result->score = score(result->requested,*(result->found.at(pluralForm))); + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = catalogInfo.lastTranslator; + info->description = data->catalog()->comment(*it); + result->descriptions.append(info); + + addResult(result, results); + return true; + } + } + } + return false; +} + +bool PoCompendium::searchTextOnly(const QString& text, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& ) +{ + QString searchStr = text.lower(); + QString t = text; + t.remove( " " ); + + const QValueList<int> *indexList = data->textonlyDict(t.lower()); + if(indexList) + { + QValueList<int>::ConstIterator it; + for( it = indexList->begin(); it != indexList->end(); ++it ) + { + if(foundIndices.contains(*it)) + { + continue; + } + + if(ignoreFuzzy && data->catalog()->isFuzzy(*it)) + { + continue; + } + + + QString origStr = data->catalog()->msgid(*it).first(); + origStr = CompendiumData::simplify(origStr); + + + foundIndices.append(*it); + + SearchResult *result = new SearchResult; + result->requested = text; + result->found = data->catalog()->msgid(*it).first(); +#warning kdWarning() << "PoCompendium can't return plural form translation" << endl; + result->translation = data->catalog()->msgstr(*it).first(); + result->score = score(result->requested,*(result->found.at(pluralForm))); + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = catalogInfo.lastTranslator; + info->description = data->catalog()->comment(*it); + result->descriptions.append(info); + + addResult(result, results); + return true; + } + } + return false; +} + +bool PoCompendium::searchWords(const QString& searchStr, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices ) +{ + uint checkCounter = 0; + bool foundResults = false; + + QStringList wList = CompendiumData::wordList(searchStr); + for ( QStringList::Iterator wit = wList.begin() + ; wit != wList.end(); ++wit ) + { + if(stop) + break; + + const QValueList<int> *indexList = data->wordDict((*wit).lower()); + if(indexList) + { + QValueList<int>::ConstIterator it; + for( it = indexList->begin(); it != indexList->end(); ++it ) + { + if(stop) + break; + + if(foundIndices.contains(*it)) + { + continue; + } + + if(checkedIndices.contains(*it)) + { + continue; + } + + checkedIndices.append(*it); + checkCounter++; + + if(ignoreFuzzy && data->catalog()->isFuzzy(*it)) + { + continue; + } + + if( (100*(checkCounter+1))%catalogInfo.total < 100) + { + emit progress( (50*checkCounter+1)/catalogInfo.total); + } + + kapp->processEvents(100); + + QString origStr = data->catalog()->msgid(*it).first(); + origStr = CompendiumData::simplify(origStr); + + + if(!caseSensitive) + { + origStr = origStr.lower(); + } + + bool found = false; + if(matchWords) + { + if(!caseSensitive) + { + found=true; + } + else + { + QString s=*wit; + QString o=origStr; + + if(wholeWords) + { + s=" "+*wit+" "; + o=" "+origStr+" "; + } + if(o.contains(s)) + { + found=true; + } + } + } + + + if(!found && origStr==searchStr) + { + found =true; + } + + // if there is an string which just contains ignored characters, + // continue + if(!found && origStr.isEmpty() || + (origStr.length() == 1 && searchStr.length() > 1)) + { + continue; + } + + + if(!found && matchContains && !wholeWords) + { + QString s=maskString(searchStr); + QRegExp searchReg(s); + + if(searchReg.search(origStr) >= 0) + found=true; + } + + if(!found && matchIsContained && !wholeWords) + { + QString s=maskString(origStr); + QRegExp reg(s); + + if(reg.search(searchStr) >= 0) + { + found = true; + } + } + if(!found && matchWords && !wholeWords) + { + QStringList list = CompendiumData::wordList(searchStr); + + for ( QStringList::Iterator wit2 = list.begin() + ; wit2 != list.end(); ++wit2 ) + { + QString s=maskString(*wit2); + QRegExp reg(s); + + if(reg.search(origStr) >= 0) + { + found = true; + } + } + } + + if(found) + { + foundIndices.append(*it); + + SearchResult *result = new SearchResult; + result->requested = searchStr; // FIXME:here should be the original text + result->found = data->catalog()->msgid(*it).first(); +#warning kdWarning() << "PoCompendium can't return plural form translation" << endl; + result->translation = data->catalog()->msgstr(*it).first(); + result->score = score(result->requested,*(result->found.at(pluralForm))); + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = catalogInfo.lastTranslator; + info->description = data->catalog()->comment(*it); + result->descriptions.append(info); + + addResult(result, results); + + foundResults = true; + } + } + } + } + + return foundResults; +} + +bool PoCompendium::searchNGram(const QString& searchStr, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices ) +{ + uint checkCounter = 0; + bool foundResults = false; + + QRegExp searchReg; + if(matchContains) + { + QString s=maskString(searchStr); + searchReg.setPattern(s); + } + + + bool breakLoop=false; + int i=-1; + while(!breakLoop) + { + if(stop) + { + breakLoop=true; + break; + } + + i++; + + if(i >= catalogInfo.total) + { + breakLoop = true; + break; + } + + if( (100*(checkCounter+1))%catalogInfo.total < 100) + { + emit progress( 50+(50*(checkCounter+1))/catalogInfo.total); + } + + if(checkedIndices.contains(i)) + { + continue; + } + + checkedIndices.append(i); + checkCounter++; + + if(ignoreFuzzy && data->catalog()->isFuzzy(i)) + { + continue; + } + + if(foundIndices.contains(i)) + { + continue; + } + + kapp->processEvents(100); + + QString origStr = data->catalog()->msgid(i).first(); + origStr = CompendiumData::simplify(origStr); + + if(!caseSensitive) + { + origStr = origStr.lower(); + } + + + // if there is an string which just contains ignored characters, + // continue + if(origStr.isEmpty() || + (origStr.length() == 1 && searchStr.length() > 1)) + { + continue; + } + + bool found = false; + if(matchContains && searchReg.search(origStr) >= 0) + { + found=true; + } + + if(!found && matchIsContained) + { + QString s=maskString(origStr); + QRegExp reg(s); + + if(reg.search(searchStr) >= 0) + { + found = true; + } + } + + if(!found && matchWords) + { + QStringList list = CompendiumData::wordList(searchStr); + + for ( QStringList::Iterator wit2 = list.begin() + ; wit2 != list.end(); ++wit2 ) + { + QString s=maskString(*wit2); + + if(wholeWords) + { + origStr = " "+origStr+" "; + s=" "+s+" "; + } + QRegExp reg(s); + + if(reg.search(origStr) >= 0) + { + found = true; + } + } + } + + if(!found && matchNGram) + { + // to get more results one could + // interchange searchStr and origStr when + // the latter is shorter + + found = ( ngramMatch(searchStr,origStr,NGRAM_LEN) + > LIM_NGRAM ); + } + + if(found) + { + foundIndices.append(i); + + SearchResult *result = new SearchResult; + result->requested = searchStr; + result->found = data->catalog()->msgid(i).first(); + result->translation = data->catalog()->msgstr(i).first(); +#warning kdWarning() << "PoCompendium can't return plural form translation" << endl; + result->score = score(result->requested,*(result->found.at(pluralForm))); + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = catalogInfo.lastTranslator; + info->description = data->catalog()->comment(i); + result->descriptions.append(info); + + addResult(result, results); + + foundResults = true; + } + } + + return foundResults; +} + +bool PoCompendium::startSearch(const QString& text, uint pluralForm, const SearchFilter* filter) +{ + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + if(isSearching()) + return false; + + clearResults(); + stop = false; + active = true; + + if(!initialized) + { + if(loadTimer->isActive()) + loadTimer->stop(); + + slotLoadCompendium(); + } + + if(error || !data) + { + active = false; + return false; + } + + if(data->active()) + { + active = false; + return true; + } + + emit started(); + + + QValueList<int> foundIndices; + QValueList<int> checkedIndices; + + // first, exact search + searchExact(text, pluralForm, results, foundIndices, checkedIndices); + + QString searchStr=CompendiumData::simplify(text); + + + if(!caseSensitive) + { + searchStr = searchStr.lower(); + + // do case insensite search if necessary + searchCaseInsensitive(searchStr, pluralForm, results, foundIndices, checkedIndices); + } + + // search without whitespace + searchTextOnly(searchStr, pluralForm, results, foundIndices, checkedIndices); + + // now, search based on words (contains, is contained, etc) + searchWords(searchStr, pluralForm, results, foundIndices, checkedIndices); + + + if( matchNGram || + (!wholeWords && (matchContains || matchIsContained || matchWords)) + ) + { + // search based on ngrams + searchNGram(searchStr, pluralForm, results, foundIndices, checkedIndices); + } + + emit progress(100); + + active = false; + stop = false; + emit finished(); + + return true; +} + +void PoCompendium::stopSearch() +{ + stop=true; +} + + +void PoCompendium::applySettings() +{ + if(!prefWidget) + return; + + if(isSearching()) + stopSearch(); + + caseSensitive = prefWidget->caseSensitive(); + ignoreFuzzy = prefWidget->ignoreFuzzy(); + wholeWords = prefWidget->wholeWords(); + + matchEqual = prefWidget->matchEqual(); + matchNGram = prefWidget->matchNGram(); + matchIsContained = prefWidget->matchIsContained(); + matchContains = prefWidget->matchContains(); + matchWords = prefWidget->matchWords(); + + + bool needLoading=false; + + + QString newPath = prefWidget->url(); + if(!initialized) + { + url = newPath; + } + else if(newPath != url) + { + url = newPath; + needLoading = true; + } + + if(needLoading) + { + loadCompendium(); + initialized=false; + } +} + +void PoCompendium::restoreSettings() +{ + if(!prefWidget) + return; + + prefWidget->setCaseSensitive(caseSensitive); + prefWidget->setIgnoreFuzzy(ignoreFuzzy); + prefWidget->setWholeWords(wholeWords); + prefWidget->setURL(url); + + prefWidget->setMatchEqual(matchEqual); + prefWidget->setMatchNGram(matchNGram); + prefWidget->setMatchIsContained(matchIsContained); + prefWidget->setMatchContains(matchContains); + prefWidget->setMatchWords(matchWords); +} + +void PoCompendium::loadCompendium() +{ + if(!loading && !loadTimer->isActive()) + loadTimer->start(100,true); +} + +void PoCompendium::slotLoadCompendium() +{ + if(loading) + return; + + if(loadTimer->isActive()) + loadTimer->stop(); + + loading = true; + + if(data) + { + unregisterData(); + } + + + QString path=url; + + if(path.contains("@LANG@")) + { + path.replace("@LANG@",langCode); + } + KURL u=KCmdLineArgs::makeURL(path.local8Bit()); + realURL = u.url(); + + registerData(); + + + if(!data) + { + kdError() << "no data object in pocompendium?" << endl; + + loading=false; + return; + } + + if(!data->initialized()) + { + if(!data->active()) + { + data->load(u); + recheckData(); + if(error) + { + emit hasError(errorMsg); + } + } + else + { + connect(data, SIGNAL(progressEnds()), this, SLOT(recheckData())); + } + } + else + { + recheckData(); + if(error) + { + emit hasError(errorMsg); + } + } + + initialized=true; +} + +void PoCompendium::recheckData() +{ + if(data) + { + disconnect(data, SIGNAL(progressEnds()), this, SLOT(recheckData())); + + error = data->hasErrors(); + errorMsg = data->errorMsg(); + + if(!error) + { + catalogInfo = Catalog::headerInfo(data->catalog()->header()); + catalogInfo.total = data->catalog()->numberOfEntries(); + catalogInfo.fuzzy = data->catalog()->numberOfFuzzies(); + catalogInfo.untranslated = data->catalog()->numberOfUntranslated(); + } + } + + loading=false; +} + +QString PoCompendium::maskString(QString s) +{ + s.replace("\\","\\\\"); + s.replace("\?","\\?"); + s.replace("[","\\["); + s.replace(".","\\."); + s.replace("*","\\*"); + s.replace("+","\\+"); + s.replace("^","\\^"); + s.replace("$","\\$"); + s.replace("(","\\("); + s.replace(")","\\)"); + s.replace("{","\\{"); + s.replace("}","\\}"); + s.replace("|","\\|"); + + return s; +} + +void PoCompendium::addResult(SearchResult *result, QPtrList<SearchResult>& res) +{ + if(res.last() && res.last()->score >= result->score) + { + res.append(result); + } + else + { + SearchResult *sr; + for(sr = res.first(); sr != 0; sr=res.next()) + { + if(sr->score < result->score) + { + int pos = res.at(); + if( pos < 0 ) pos = 0; + res.insert( pos,result); + emit resultsReordered(); + break; + } + } + + if(!sr) + { + res.append(result); + } + } + + emit numberOfResultsChanged(res.count()); + emit resultFound(result); +} + + +void PoCompendium::setLanguageCode(const QString& lang) +{ + if(initialized && url.contains("@LANG@") && lang!=langCode + && !loadTimer->isActive() ) + { + initialized=false; + } + + langCode=lang; +} + +QString PoCompendium::translate(const QString& text, uint pluralForm) +{ + if(!initialized) + { + if(loadTimer->isActive()) + loadTimer->stop(); + + slotLoadCompendium(); + } + + if(error || !data || data->active()) + { + return QString::null; + } + + + const int *index = data->exactDict(text); + + if(index) + { +#warning kdWarning() << "PoCompendium can't return plural form translation" << endl; + return data->catalog()->msgstr(*index).first(); + } + + return QString::null; +} + +QString PoCompendium::fuzzyTranslation(const QString& text, int &score, const uint pluralForm) +{ + if(!initialized) + { + if(loadTimer->isActive()) + loadTimer->stop(); + + slotLoadCompendium(); + } + + if(error || !data || data->active()) + { + return QString::null; + } + + // try to find fuzzy string + bool breakLoop = false; + stop = false; + int i=-1; + int best_matching = -1; + int best_match = 0; + int total = data->catalog()->numberOfEntries(); + + QString searchStr = CompendiumData::simplify(text); + + //kdDebug(750) << "find best match for " << searchStr << endl; + + while(!breakLoop) + { + + // progress and loop control + if(stop) + { + breakLoop=true; + break; + } + + i++; + + if(i >= total) + { + breakLoop = true; + break; + } + + if( (100*(i+1))%total < 100) + { + emit progress( (100*(i+1))/total); + } + + // get a message from the catalog FIXME: plurals + QString origStr = data->catalog()->msgid(i).first(); + origStr = CompendiumData::simplify(origStr); + + // don't match too long strings for short search string + if (origStr.length() > 2*searchStr.length()) + continue; + // kdDebug(750) << i << ": matching " << origStr << endl; + + int ngram_result = ngramMatch(searchStr,origStr); + + if (ngram_result > best_match) { + best_match = ngram_result; + best_matching = i; + + // kdDebug(750) << "[" << ngram_result << "] " << text << "-" + // << origStr << endl; + } + } + + if (best_match > LIM_NGRAM) { + score = best_match; +#warning kdWarning() << "PoCompendium can't return plural form translation" << endl; + return data->catalog()->msgstr(best_matching).first(); + } + + return QString::null; +} + + +QString PoCompendium::searchTranslation(const QString& text, int &sc, const uint pluralForm) +{ + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + if(isSearching()) + return QString::null; + + clearResults(); + stop = false; + active = true; + + if(!initialized) + { + if(loadTimer->isActive()) + loadTimer->stop(); + + slotLoadCompendium(); + } + + if(error || !data) + { + active = false; + return QString::null; + } + + if(data->active()) + { + active = false; + return QString::null; + } + + emit started(); + + QPtrList<SearchResult> res; + + QValueList<int> foundIndices; + QValueList<int> checkedIndices; + + // first, exact search + if( searchExact(text, pluralForm, res, foundIndices, checkedIndices) ) + { + active = false; + stop = false; + emit finished(); + + // found, this is the best + sc = res.first()->score; + return res.first()->translation; + } + + QString searchStr=CompendiumData::simplify(text); + + + if(!caseSensitive) + { + searchStr = searchStr.lower(); + + // do case insensite search if necessary + if( searchCaseInsensitive(searchStr, pluralForm, res, foundIndices, checkedIndices) ) + { + active = false; + stop = false; + emit finished(); + + // found, return this one + sc = res.first()->score; + return res.first()->translation; + } + } + + // search without whitespace + QString s = searchStr; + s.remove( ' ' ); + if( searchTextOnly(s, pluralForm, res, foundIndices, checkedIndices) ) + { + active = false; + stop = false; + emit finished(); + + // found, return this one + sc = res.first()->score; + return res.first()->translation; + } + + // now, search based on words (contains, is contained, etc) + searchWords(searchStr, pluralForm, res, foundIndices, checkedIndices); + + if( matchNGram || + (!wholeWords && (matchContains || matchIsContained || matchWords)) + ) + { + // search based on ngrams + searchNGram(searchStr, pluralForm, res, foundIndices, checkedIndices); + } + + active = false; + stop = false; + + // now, pick up the best one from not exact translations + if( res.count() > 0 ) { + + emit finished(); + + sc = res.first()->score; + return res.first()->translation; + } + + sc = 0; + + return QString::null; +} + + +void PoCompendium::unregisterData() +{ + if(data) + { + disconnect(data, SIGNAL(progressStarts(const QString&)), this + , SIGNAL(progressStarts(const QString&))); + disconnect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds())); + disconnect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int))); + + if(data->active()) + { + disconnect(data,SIGNAL(progressEnds()),this,SLOT(recheckData())); + } + + if(data->unregisterObject(this)) + { + if(!data->active()) + { + compendiumDict()->remove(realURL); + } + else + { + connect(data,SIGNAL(progressEnds()),this,SLOT(removeData())); + } + } + + data=0; + } +} + +void PoCompendium::registerData() +{ + data = compendiumDict()->find(realURL); + if(!data) + { + data = new CompendiumData; + compendiumDict()->insert(realURL,data); + } + + data->registerObject(this); + + if(data->active()) + { + emit progressStarts(i18n("Loading PO compendium")); + } + + connect(data, SIGNAL( + progressStarts(const QString&)), this + , SIGNAL(progressStarts(const QString&))); + connect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds())); + connect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int))); +} + +void PoCompendium::removeData() +{ + const QObject *s=sender(); + if(s && s->inherits("CompendiumData")) + { + const CompendiumData *d=static_cast<const CompendiumData*>(s); + if(d) + { + QDictIterator<CompendiumData> it(*compendiumDict()); + while(it.current()) + { + if(it.current() == d) + { + if(!d->hasObjects()) + { + compendiumDict()->remove(it.currentKey()); + } + + break; + } + + ++it; + } + } + + } +} + +QDict<CompendiumData> *PoCompendium::compendiumDict() +{ + if(!_compDict) + { + _compDict=compDataDeleter.setObject( new QDict<CompendiumData> ); + _compDict->setAutoDelete(true); + } + + return _compDict; +} + + + +#include "pocompendium.moc" diff --git a/kbabel/kbabeldict/modules/pocompendium/pocompendium.desktop b/kbabel/kbabeldict/modules/pocompendium/pocompendium.desktop new file mode 100644 index 00000000..ac9ee368 --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/pocompendium.desktop @@ -0,0 +1,50 @@ +[Desktop Entry] +Type=Service +Name=PO Compendium Module for KBabelDict +Name[bg]=PO компендиум за KBabelDict +Name[bs]=Modul PO kompendijuma za KBabelDict +Name[ca]=Mòdul del Compendi PO per a KBabelDict +Name[cs]=Modul s PO kompendiem pro KBabelDict +Name[cy]=Modiwl Compendiwm PO i KBabelDict +Name[da]=PO-kompendium-module for KBabelDict +Name[de]=PO-Kompendium-Modul für KBabelDict +Name[el]=Άρθρωμα επιτομής PO για το KBabelDict +Name[es]=Módulo de compendio de PO para KBabelDict +Name[et]=KBabelDicti PO kompendiumi moodul +Name[eu]=PO laburpen modulua KBabelDict-entzat +Name[fa]=پیمانۀ مختصر PO برای KBabelDict +Name[fi]=KBabelDict-ohjelman PO-kokoelmatiedostomoduuli +Name[fr]=Module de fichier de référence PO pour KBabelDict +Name[gl]=Módulo de compendio PO para KBabelDict +Name[hi]=के-बेबल-डिक्श के लिए पीओ कम्पेंडियम मॉड्यूल +Name[hu]=PO összefoglaló modul a KBabelDicthez +Name[is]=PO ágrips eining fyrir KBabel orðabókina +Name[it]=Modulo PO Compendium per KBabelDict +Name[ja]=KBabelDict PO 要約モジュール +Name[ka]=PO კონსპექტის მოდული KBabelDict-სთვის +Name[kk]=KBabelDict-тың PO аудармалар жиынтық модулі +Name[lt]=KBabelDict PO tekstyno modulis +Name[ms]=Modul Kompendium PO untuk KBabelDict +Name[nb]=PO-kompendiummodul for KBabelDict +Name[nds]=PO-Kompendiummoduul för KBabelDict +Name[ne]=KBabelDict का लागि संक्षेप पीओ मोड्युल +Name[nl]=PO-samenvattingmodule voor KBabelDict +Name[nn]=PO-kompendiemodul for KBabelDict +Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦਕੋਸ਼ ਲਈ PO ਸੰਖੇਪ ਮੈਡੀਊਲ +Name[pl]=Moduł Kompendium PO dla KBabelDict +Name[pt]=Módulo de Compêndio de PO para o KBabelDict +Name[pt_BR]=Módulo de Compêndio PO para o KBabelDict +Name[ru]=Модуль описания PO для KBabelDict +Name[sk]=Kompendium pre KBabelDict +Name[sl]=Modul zbornika PO za KBabelDict +Name[sr]=Модул PO зборника за KBabelDict +Name[sr@Latn]=Modul PO zbornika za KBabelDict +Name[sv]=PO-kompendiemodul för Kbabeldict +Name[ta]=Kபாபேலுக்கான காம்பென்டியம் PO கூறு +Name[tg]=Модули тасвири PO барои KBabelDict +Name[tr]=KBabelDict için PO Özet Modülü +Name[uk]=Модуль збірки перекладів PO для KBabelDict +Name[zh_CN]=KBabelDict 的 PO 概要词典模块 +Name[zh_TW]=KBabelDict PO 摘要模組 +X-KDE-Library=kbabeldict_pocompendium +ServiceTypes=KBabelDictModule diff --git a/kbabel/kbabeldict/modules/pocompendium/pocompendium.h b/kbabel/kbabeldict/modules/pocompendium/pocompendium.h new file mode 100644 index 00000000..6d92fb58 --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/pocompendium.h @@ -0,0 +1,147 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + +#ifndef POCOMPENDIUM_H +#define POCOMPENDIUM_H + +#include <poinfo.h> + +#include "compendiumdata.h" +#include "searchengine.h" + +#include <qdict.h> +#include <qfile.h> +#include <qguardedptr.h> +#include <qptrlist.h> + +class CompendiumPreferencesWidget; +class KConfigBase; +class QTimer; + +class PoCompendium : public SearchEngine +{ + Q_OBJECT + +public: + PoCompendium(QObject *parent=0, const char *name=0); + virtual ~PoCompendium(); + + virtual bool isReady() const; + + virtual QString translate(const QString&text, uint pluralForm); + virtual QString searchTranslation(const QString&, int &score, const uint pluralForm); + virtual QString fuzzyTranslation(const QString&, int &score, const uint pluralForm); + + virtual bool isSearching() const; + + virtual void saveSettings(KConfigBase *config); + virtual void readSettings(KConfigBase *config); + + virtual PrefWidget *preferencesWidget(QWidget *parent); + + virtual const KAboutData *about() const; + + virtual QString name() const; + + virtual QString id() const; + + virtual QString lastError(); + + +public slots: + virtual bool startSearch(const QString& s, uint pluralForm = 0, const SearchFilter* filter = 0); + virtual void stopSearch(); + virtual void setLanguageCode(const QString& lang); + +protected slots: + /** reads the current settings from the preferences dialog */ + void applySettings(); + + /** sets the current settings in the preferences dialog */ + void restoreSettings(); + + void slotLoadCompendium(); + + void recheckData(); + void removeData(); + +protected: + void loadCompendium(); + void addResult(SearchResult *, QPtrList<SearchResult>& allResults); + QString maskString(QString string); + + void registerData(); + void unregisterData(); + + bool searchExact(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices ); + bool searchTextOnly(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices ); + bool searchCaseInsensitive(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices ); + bool searchWords(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices ); + bool searchNGram(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices ); + +private: + QGuardedPtr<CompendiumPreferencesWidget> prefWidget; + CompendiumData *data; + KBabel::PoInfo catalogInfo; + QTimer *loadTimer; + + QString url; + QString realURL; + QString langCode; + + bool caseSensitive; + bool ignoreFuzzy; + bool wholeWords; + + bool matchEqual; + bool matchIsContained; + bool matchContains; + bool matchWords; + bool matchNGram; + + bool buildIndex; + uint freeMemDelay; + + bool error; + QString errorMsg; + + bool stop; + bool active; + bool initialized; + bool loading; + + static QDict<CompendiumData> *_compDict; + static QDict<CompendiumData> *compendiumDict(); +}; + +#endif diff --git a/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.cpp b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.cpp new file mode 100644 index 00000000..c3ce730d --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.cpp @@ -0,0 +1,352 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <kfiledialog.h> +#include <qpushbutton.h> +#include <qwhatsthis.h> +#include <klineedit.h> +#include <klocale.h> +#include <kurlrequester.h> + +#include "preferenceswidget.h" +#include "pwidget.h" + +CompendiumPreferencesWidget::CompendiumPreferencesWidget(QWidget *parent, const char* name) + : PrefWidget(parent,name) + , changed(false) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + prefWidget = new CompendiumPWidget(this); + layout->addWidget(prefWidget); + + connect(prefWidget->caseBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->equalBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->ngramBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->containsBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->fuzzyBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->wholeBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + + connect(prefWidget->urlInput->lineEdit(),SIGNAL(textChanged(const QString&)) + , this, SLOT(setChanged())); + + connect(prefWidget->equalBtn, SIGNAL(toggled(bool)) + , this, SLOT(equalBtnToggled(bool))); + connect(prefWidget->ngramBtn, SIGNAL(toggled(bool)) + , this, SLOT(ngramBtnToggled(bool))); + connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool)) + , this, SLOT(isContainedBtnToggled(bool))); + connect(prefWidget->containsBtn, SIGNAL(toggled(bool)) + , this, SLOT(containsBtnToggled(bool))); + connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool)) + , this, SLOT(hasWordBtnToggled(bool))); + + + QString whatsthis=i18n("<qt><p><b>Parameters</b></p>" + "<p>Here you can fine-tune searching within the PO file. " + "For example if you want to perform a case sensitive search, or if " + "you want fuzzy messages to be ignored.</p></qt>" ); + QWhatsThis::add(prefWidget->caseBtn,whatsthis); + QWhatsThis::add(prefWidget->fuzzyBtn,whatsthis); + QWhatsThis::add(prefWidget->wholeBtn,whatsthis); + + whatsthis = i18n("<qt><p><b>Comparison Options</b></p>" + "<p>Choose here which messages you want to have treated as a matching " + "message.</p></qt>"); + QWhatsThis::add(prefWidget->equalBtn,whatsthis); + QWhatsThis::add(prefWidget->containsBtn,whatsthis); + QWhatsThis::add(prefWidget->isContainedBtn,whatsthis); + QWhatsThis::add(prefWidget->hasWordBtn,whatsthis); + + whatsthis = i18n("<qt><p><b>3-Gram-matching</b></p>" + "<p>A message matches another if most of its 3-letter groups are " + "contained in the other message. e.g. 'abc123' matches 'abcx123c12'.</p></qt>"); + QWhatsThis::add(prefWidget->ngramBtn,whatsthis); + + whatsthis = i18n("<qt><p><b>Location</b></p>" + "<p>Configure here which file is to be used for searching." + "</p></qt>"); + QWhatsThis::add(prefWidget->urlInput,whatsthis); +} + +CompendiumPreferencesWidget::~CompendiumPreferencesWidget() +{ +} + + +void CompendiumPreferencesWidget::apply() +{ + emit applySettings(); +} + +void CompendiumPreferencesWidget::cancel() +{ + emit restoreSettings(); +} + +void CompendiumPreferencesWidget::standard() +{ + prefWidget->urlInput->setURL("http://i18n.kde.org/po_overview/@LANG@.messages"); + prefWidget->caseBtn->setChecked(false); + prefWidget->equalBtn->setChecked(true); + prefWidget->ngramBtn->setChecked(true); + prefWidget->isContainedBtn->setChecked(false); + prefWidget->containsBtn->setChecked(false); + prefWidget->wholeBtn->setChecked(true); + prefWidget->hasWordBtn->setChecked(true); + + prefWidget->fuzzyBtn->setChecked(true); + + changed=true; +} + +void CompendiumPreferencesWidget::setURL(const QString url) +{ + prefWidget->urlInput->setURL(url); + changed=false; +} + +void CompendiumPreferencesWidget::setCaseSensitive(bool on) +{ + prefWidget->caseBtn->setChecked(on); + changed=false; +} + +void CompendiumPreferencesWidget::setMatchEqual(bool on) +{ + prefWidget->equalBtn->setChecked(on); + changed=false; +} + +void CompendiumPreferencesWidget::setMatchNGram(bool on) +{ + prefWidget->ngramBtn->setChecked(on); + changed=false; +} + +void CompendiumPreferencesWidget::setMatchIsContained(bool on) +{ + prefWidget->isContainedBtn->setChecked(on); + changed=false; +} + +void CompendiumPreferencesWidget::setMatchContains(bool on) +{ + prefWidget->containsBtn->setChecked(on); + changed=false; +} + +void CompendiumPreferencesWidget::setIgnoreFuzzy(bool on) +{ + prefWidget->fuzzyBtn->setChecked(on); + changed=false; +} + +void CompendiumPreferencesWidget::setWholeWords(bool on) +{ + prefWidget->wholeBtn->setChecked(on); + changed=false; +} + + +void CompendiumPreferencesWidget::setMatchWords(bool on) +{ + prefWidget->hasWordBtn->setChecked(on); + changed=false; +} + + + +QString CompendiumPreferencesWidget::url() +{ + changed=false; + return prefWidget->urlInput->url(); +} + +bool CompendiumPreferencesWidget::caseSensitive() +{ + changed=false; + + return prefWidget->caseBtn->isChecked(); +} + +bool CompendiumPreferencesWidget::matchEqual() +{ + changed=false; + + return prefWidget->equalBtn->isChecked(); +} + +bool CompendiumPreferencesWidget::matchNGram() +{ + changed=false; + + return prefWidget->ngramBtn->isChecked(); +} + +bool CompendiumPreferencesWidget::matchIsContained() +{ + changed=false; + + return prefWidget->isContainedBtn->isChecked(); +} + +bool CompendiumPreferencesWidget::matchContains() +{ + changed=false; + + return prefWidget->containsBtn->isChecked(); +} + +bool CompendiumPreferencesWidget::ignoreFuzzy() +{ + changed=false; + + return prefWidget->fuzzyBtn->isChecked(); +} + + +bool CompendiumPreferencesWidget::wholeWords() +{ + changed=false; + + return prefWidget->wholeBtn->isChecked(); +} + + +bool CompendiumPreferencesWidget::matchWords() +{ + changed=false; + + return prefWidget->hasWordBtn->isChecked(); +} + + + +bool CompendiumPreferencesWidget::settingsChanged() const +{ + return changed; +} + +void CompendiumPreferencesWidget::setChanged() +{ + changed=true; +} + + +void CompendiumPreferencesWidget::equalBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->containsBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->equalBtn->setChecked(true); + } + } +} + +void CompendiumPreferencesWidget::ngramBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->equalBtn->isChecked() + && !prefWidget->containsBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->equalBtn->setChecked(true); + } + } +} + +void CompendiumPreferencesWidget::isContainedBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->equalBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->containsBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->isContainedBtn->setChecked(true); + } + } +} + +void CompendiumPreferencesWidget::containsBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->equalBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->containsBtn->setChecked(true); + } + } +} + +void CompendiumPreferencesWidget::hasWordBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->equalBtn->isChecked() + && !prefWidget->containsBtn->isChecked()) + { + prefWidget->hasWordBtn->setChecked(true); + } + } +} + + + +#include "preferenceswidget.moc" diff --git a/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.h b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.h new file mode 100644 index 00000000..db70df4d --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.h @@ -0,0 +1,97 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef PREFERENCESWIDGET_H +#define PREFERENCESWIDGET_H + +#include "searchengine.h" + +class CompendiumPWidget; + +class CompendiumPreferencesWidget : public PrefWidget +{ + Q_OBJECT + +public: + CompendiumPreferencesWidget(QWidget *parent=0, const char* name=0); + virtual ~CompendiumPreferencesWidget(); + + virtual void apply(); + virtual void cancel(); + virtual void standard(); + + void setURL(const QString url); + void setMatchEqual(bool); + void setMatchNGram(bool); + void setMatchIsContained(bool); + void setMatchContains(bool); + void setIgnoreFuzzy(bool); + void setMatchWords(bool); + void setWholeWords(bool); + void setCaseSensitive(bool); + + QString url(); + bool matchEqual(); + bool matchNGram(); + bool matchIsContained(); + bool matchContains(); + bool ignoreFuzzy(); + bool matchWords(); + bool wholeWords(); + bool caseSensitive(); + + + bool settingsChanged() const; + +signals: + void restoreSettings(); + void applySettings(); + +public: + CompendiumPWidget *prefWidget; + +protected slots: + void setChanged(); + void equalBtnToggled(bool); + void ngramBtnToggled(bool); + void isContainedBtnToggled(bool); + void containsBtnToggled(bool); + void hasWordBtnToggled(bool); + +private: + bool changed; + +}; + +#endif diff --git a/kbabel/kbabeldict/modules/pocompendium/pwidget.ui b/kbabel/kbabeldict/modules/pocompendium/pwidget.ui new file mode 100644 index 00000000..8f54b087 --- /dev/null +++ b/kbabel/kbabeldict/modules/pocompendium/pwidget.ui @@ -0,0 +1,280 @@ +<!DOCTYPE UI><UI> +<class>CompendiumPWidget</class> +<include location="global">kseparator.h</include> +<widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>PWidget</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>452</width> + <height>291</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string></string> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QGroupBox</class> + <property stdset="1"> + <name>name</name> + <cstring>GroupBox1</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>&Path to Compendium File</string> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>KURLRequester</class> + <property stdset="1"> + <name>name</name> + <cstring>urlInput</cstring> + </property> + </widget> + </vbox> + </widget> + <widget> + <class>QButtonGroup</class> + <property stdset="1"> + <name>name</name> + <cstring>ButtonGroup1</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>Options</string> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout4</cstring> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget row="1" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>fuzzyBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Ignore &fuzzy strings</string> + </property> + </widget> + <widget row="0" column="1" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>wholeBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Onl&y whole words</string> + </property> + </widget> + <widget row="0" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>caseBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Case sensiti&ve</string> + </property> + </widget> + </grid> + </widget> + <widget> + <class>KSeparator</class> + <property stdset="1"> + <name>name</name> + <cstring>Line1</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Horizontal</enum> + </property> + </widget> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel3</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>A text matches if:</string> + </property> + </widget> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout3</cstring> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget row="0" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>equalBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>E&qual to searched text</string> + </property> + </widget> + <widget row="2" column="1" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>hasWordBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Contains a &word of searched text</string> + </property> + </widget> + <widget row="1" column="1" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>isContainedBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Co&ntained in searched text</string> + </property> + </widget> + <widget row="1" column="0" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>ngramBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>&Similar to searched text</string> + </property> + </widget> + <widget row="0" column="1" > + <class>QCheckBox</class> + <property stdset="1"> + <name>name</name> + <cstring>containsBtn</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Contains searched te&xt</string> + </property> + </widget> + </grid> + </widget> + </vbox> + </widget> + <spacer> + <property> + <name>name</name> + <cstring>Spacer1</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KURLRequester</class> + <header location="global">kurlrequester.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image> + <name>image0</name> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> + </image> +</images> +<tabstops> + <tabstop>caseBtn</tabstop> +</tabstops> +</UI> diff --git a/kbabel/kbabeldict/modules/tmx/Makefile.am b/kbabel/kbabeldict/modules/tmx/Makefile.am new file mode 100644 index 00000000..f0f54b01 --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/Makefile.am @@ -0,0 +1,34 @@ +## Makefile.am for tmxcompendium + +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +#SUBDIRS = + + +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +kde_module_LTLIBRARIES = kbabeldict_tmxcompendium.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes) + + +# which sources should be compiled for kbabel +kbabeldict_tmxcompendium_la_SOURCES = tmxcompendium.cpp preferenceswidget.cpp \ + pc_factory.cpp pwidget.ui tmxcompendiumdata.cpp + +kbabeldict_tmxcompendium_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO) +kbabeldict_tmxcompendium_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined + + + +# these are the headers for your project +noinst_HEADERS = tmxcompendium.h preferenceswidget.h pc_factory.h \ + tmxcompendiumdata.h + + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +kde_services_DATA = tmxcompendium.desktop +EXTRA_DIST = $(kde_services_DATA) diff --git a/kbabel/kbabeldict/modules/tmx/pc_factory.cpp b/kbabel/kbabeldict/modules/tmx/pc_factory.cpp new file mode 100644 index 00000000..a3dcfdf9 --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/pc_factory.cpp @@ -0,0 +1,111 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <klocale.h> +#include <kinstance.h> +#include <kaboutdata.h> +#include <kdebug.h> + +#include "pc_factory.h" +#include "tmxcompendium.h" + + +extern "C" +{ + KDE_EXPORT void *init_kbabeldict_tmxcompendium() + { + return new PcFactory; + } +} + + +KInstance *PcFactory::s_instance = 0; +KAboutData *PcFactory::s_about = 0; + + +PcFactory::PcFactory( QObject *parent, const char *name) + : KLibFactory(parent,name) +{ +} + +PcFactory::~PcFactory() +{ + if(s_instance) + { + delete s_instance; + s_instance=0; + } + + if(s_about) + { + delete s_about; + s_about=0; + } +} + + +QObject *PcFactory::createObject( QObject *parent, const char *name + , const char *classname, const QStringList &) +{ + if(QCString(classname) != "SearchEngine") + { + kdError() << "not a SearchEngine requested" << endl; + return 0; + } + + return new TmxCompendium(parent,name); +} + + +KInstance *PcFactory::instance() +{ + if(!s_instance) + { + s_about = new KAboutData( "tmxcompendium", I18N_NOOP("TMX Compendium") + , "1.0" + , I18N_NOOP("A module for searching in a TMX file") + , KAboutData::License_GPL + , "Copyright 2002, Stanislav Visnovsky" + ,0,0, "visnovsky@kde.org"); + + s_about->addAuthor("Matthias Kiefer",0,"kiefer@kde.org"); + s_about->addAuthor("Stanislav Visnovsky",0,"visnovsky@kde.org"); + + s_instance = new KInstance(s_about); + } + + return s_instance; +} + +#include "pc_factory.moc" diff --git a/kbabel/kbabeldict/modules/tmx/pc_factory.h b/kbabel/kbabeldict/modules/tmx/pc_factory.h new file mode 100644 index 00000000..5ef08277 --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/pc_factory.h @@ -0,0 +1,62 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef PC_FACTORY_H +#define PC_FACTORY_H + +#include <klibloader.h> +class KInstance; +class KAboutData; + +class PcFactory : public KLibFactory +{ + Q_OBJECT +public: + PcFactory( QObject *parent=0, const char *name=0); + ~PcFactory(); + + virtual QObject *createObject( QObject *parent=0, const char *name=0 + , const char *classname="QObject" + , const QStringList &args = QStringList()); + + static KInstance *instance(); + +private: + static KInstance *s_instance; + static KAboutData *s_about; +}; + +#endif diff --git a/kbabel/kbabeldict/modules/tmx/preferenceswidget.cpp b/kbabel/kbabeldict/modules/tmx/preferenceswidget.cpp new file mode 100644 index 00000000..1202496d --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/preferenceswidget.cpp @@ -0,0 +1,334 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <kfiledialog.h> +#include <qpushbutton.h> +#include <qwhatsthis.h> +#include <klineedit.h> +#include <klocale.h> +#include <kurlrequester.h> + +#include "preferenceswidget.h" +#include "pwidget.h" + +TmxCompendiumPreferencesWidget::TmxCompendiumPreferencesWidget(QWidget *parent, const char* name) + : PrefWidget(parent,name) + , changed(false) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + prefWidget = new TmxCompendiumPWidget(this); + layout->addWidget(prefWidget); + + connect(prefWidget->caseBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->equalBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->ngramBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->containsBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + connect(prefWidget->wholeBtn, SIGNAL(toggled(bool)) + , this, SLOT(setChanged())); + + connect(prefWidget->urlInput->lineEdit(),SIGNAL(textChanged(const QString&)) + , this, SLOT(setChanged())); + + connect(prefWidget->equalBtn, SIGNAL(toggled(bool)) + , this, SLOT(equalBtnToggled(bool))); + connect(prefWidget->ngramBtn, SIGNAL(toggled(bool)) + , this, SLOT(ngramBtnToggled(bool))); + connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool)) + , this, SLOT(isContainedBtnToggled(bool))); + connect(prefWidget->containsBtn, SIGNAL(toggled(bool)) + , this, SLOT(containsBtnToggled(bool))); + connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool)) + , this, SLOT(hasWordBtnToggled(bool))); + + + QString whatsthis=i18n("<qt><p><b>Parameters</b></p>" + "<p>Here you can fine-tune searching within the PO file. " + "For example, if you want to perform a case sensitive search.</p></qt>" ); + QWhatsThis::add(prefWidget->caseBtn,whatsthis); + QWhatsThis::add(prefWidget->wholeBtn,whatsthis); + + whatsthis = i18n("<qt><p><b>Comparison Options</b></p>" + "<p>Choose here which messages you want to have treated as a matching " + "message.</p></qt>"); + QWhatsThis::add(prefWidget->equalBtn,whatsthis); + QWhatsThis::add(prefWidget->containsBtn,whatsthis); + QWhatsThis::add(prefWidget->isContainedBtn,whatsthis); + QWhatsThis::add(prefWidget->hasWordBtn,whatsthis); + + whatsthis = i18n("<qt><p><b>3-Gram-matching</b></p>" + "<p>A message matches another if most of its 3-letter groups are " + "contained in the other message. e.g. 'abc123' matches 'abcx123c12'.</p></qt>"); + QWhatsThis::add(prefWidget->ngramBtn,whatsthis); + + whatsthis = i18n("<qt><p><b>Location</b></p>" + "<p>Configure here which file is to be used for searching." + "</p></qt>"); + QWhatsThis::add(prefWidget->urlInput,whatsthis); +} + +TmxCompendiumPreferencesWidget::~TmxCompendiumPreferencesWidget() +{ +} + + +void TmxCompendiumPreferencesWidget::apply() +{ + emit applySettings(); +} + +void TmxCompendiumPreferencesWidget::cancel() +{ + emit restoreSettings(); +} + +void TmxCompendiumPreferencesWidget::standard() +{ + prefWidget->urlInput->setURL("http://i18n.kde.org/po_overview/@LANG@.messages"); + prefWidget->caseBtn->setChecked(false); + prefWidget->equalBtn->setChecked(true); + prefWidget->ngramBtn->setChecked(true); + prefWidget->isContainedBtn->setChecked(false); + prefWidget->containsBtn->setChecked(false); + prefWidget->wholeBtn->setChecked(true); + prefWidget->hasWordBtn->setChecked(true); + + changed=true; +} + +void TmxCompendiumPreferencesWidget::setURL(const QString url) +{ + prefWidget->urlInput->setURL(url); + changed=false; +} + +void TmxCompendiumPreferencesWidget::setCaseSensitive(bool on) +{ + prefWidget->caseBtn->setChecked(on); + changed=false; +} + +void TmxCompendiumPreferencesWidget::setMatchEqual(bool on) +{ + prefWidget->equalBtn->setChecked(on); + changed=false; +} + +void TmxCompendiumPreferencesWidget::setMatchNGram(bool on) +{ + prefWidget->ngramBtn->setChecked(on); + changed=false; +} + +void TmxCompendiumPreferencesWidget::setMatchIsContained(bool on) +{ + prefWidget->isContainedBtn->setChecked(on); + changed=false; +} + +void TmxCompendiumPreferencesWidget::setMatchContains(bool on) +{ + prefWidget->containsBtn->setChecked(on); + changed=false; +} + +void TmxCompendiumPreferencesWidget::setWholeWords(bool on) +{ + prefWidget->wholeBtn->setChecked(on); + changed=false; +} + + +void TmxCompendiumPreferencesWidget::setMatchWords(bool on) +{ + prefWidget->hasWordBtn->setChecked(on); + changed=false; +} + + + +QString TmxCompendiumPreferencesWidget::url() +{ + changed=false; + return prefWidget->urlInput->url(); +} + +bool TmxCompendiumPreferencesWidget::caseSensitive() +{ + changed=false; + + return prefWidget->caseBtn->isChecked(); +} + +bool TmxCompendiumPreferencesWidget::matchEqual() +{ + changed=false; + + return prefWidget->equalBtn->isChecked(); +} + +bool TmxCompendiumPreferencesWidget::matchNGram() +{ + changed=false; + + return prefWidget->ngramBtn->isChecked(); +} + +bool TmxCompendiumPreferencesWidget::matchIsContained() +{ + changed=false; + + return prefWidget->isContainedBtn->isChecked(); +} + +bool TmxCompendiumPreferencesWidget::matchContains() +{ + changed=false; + + return prefWidget->containsBtn->isChecked(); +} + +bool TmxCompendiumPreferencesWidget::wholeWords() +{ + changed=false; + + return prefWidget->wholeBtn->isChecked(); +} + + +bool TmxCompendiumPreferencesWidget::matchWords() +{ + changed=false; + + return prefWidget->hasWordBtn->isChecked(); +} + + + +bool TmxCompendiumPreferencesWidget::settingsChanged() const +{ + return changed; +} + +void TmxCompendiumPreferencesWidget::setChanged() +{ + changed=true; +} + + +void TmxCompendiumPreferencesWidget::equalBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->containsBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->equalBtn->setChecked(true); + } + } +} + +void TmxCompendiumPreferencesWidget::ngramBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->equalBtn->isChecked() + && !prefWidget->containsBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->equalBtn->setChecked(true); + } + } +} + +void TmxCompendiumPreferencesWidget::isContainedBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->equalBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->containsBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->isContainedBtn->setChecked(true); + } + } +} + +void TmxCompendiumPreferencesWidget::containsBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->equalBtn->isChecked() + && !prefWidget->hasWordBtn->isChecked()) + { + prefWidget->containsBtn->setChecked(true); + } + } +} + +void TmxCompendiumPreferencesWidget::hasWordBtnToggled(bool on) +{ + if(!on) + { + if(!prefWidget->isContainedBtn->isChecked() + && !prefWidget->ngramBtn->isChecked() + && !prefWidget->equalBtn->isChecked() + && !prefWidget->containsBtn->isChecked()) + { + prefWidget->hasWordBtn->setChecked(true); + } + } +} + + + +#include "preferenceswidget.moc" diff --git a/kbabel/kbabeldict/modules/tmx/preferenceswidget.h b/kbabel/kbabeldict/modules/tmx/preferenceswidget.h new file mode 100644 index 00000000..c8356c3d --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/preferenceswidget.h @@ -0,0 +1,97 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef PREFERENCESWIDGET_H +#define PREFERENCESWIDGET_H + +#include "searchengine.h" + +class TmxCompendiumPWidget; + +class TmxCompendiumPreferencesWidget : public PrefWidget +{ + Q_OBJECT + +public: + TmxCompendiumPreferencesWidget(QWidget *parent=0, const char* name=0); + virtual ~TmxCompendiumPreferencesWidget(); + + virtual void apply(); + virtual void cancel(); + virtual void standard(); + + void setURL(const QString url); + void setMatchEqual(bool); + void setMatchNGram(bool); + void setMatchIsContained(bool); + void setMatchContains(bool); + void setMatchWords(bool); + void setWholeWords(bool); + void setCaseSensitive(bool); + + QString url(); + bool matchEqual(); + bool matchNGram(); + bool matchIsContained(); + bool matchContains(); + bool matchWords(); + bool wholeWords(); + bool caseSensitive(); + + + bool settingsChanged() const; + +signals: + void restoreSettings(); + void applySettings(); + +public: + TmxCompendiumPWidget *prefWidget; + +protected slots: + void setChanged(); + void equalBtnToggled(bool); + void ngramBtnToggled(bool); + void isContainedBtnToggled(bool); + void containsBtnToggled(bool); + void hasWordBtnToggled(bool); + +private: + bool changed; + +}; + +#endif diff --git a/kbabel/kbabeldict/modules/tmx/pwidget.ui b/kbabel/kbabeldict/modules/tmx/pwidget.ui new file mode 100644 index 00000000..ef6c9967 --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/pwidget.ui @@ -0,0 +1,216 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>TmxCompendiumPWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>TMXPWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>452</width> + <height>291</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox1</cstring> + </property> + <property name="title"> + <string>&Path to Compendium File</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="KURLRequester"> + <property name="name"> + <cstring>urlInput</cstring> + </property> + </widget> + </vbox> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>ButtonGroup1</cstring> + </property> + <property name="title"> + <string>Options</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QCheckBox" row="0" column="1"> + <property name="name"> + <cstring>wholeBtn</cstring> + </property> + <property name="text"> + <string>Onl&y whole words</string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>caseBtn</cstring> + </property> + <property name="text"> + <string>Case sensiti&ve</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel3</cstring> + </property> + <property name="text"> + <string>A text matches if:</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout3</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>equalBtn</cstring> + </property> + <property name="text"> + <string>E&qual to searched text</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="1"> + <property name="name"> + <cstring>hasWordBtn</cstring> + </property> + <property name="text"> + <string>Contains a &word of searched text</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="1"> + <property name="name"> + <cstring>isContainedBtn</cstring> + </property> + <property name="text"> + <string>Co&ntained in searched text</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>ngramBtn</cstring> + </property> + <property name="text"> + <string>&Similar to searched text</string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="1"> + <property name="name"> + <cstring>containsBtn</cstring> + </property> + <property name="text"> + <string>Contains searched te&xt</string> + </property> + </widget> + </grid> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KURLRequester</class> + <header location="global">kurlrequester.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> + </image> +</images> +<tabstops> + <tabstop>caseBtn</tabstop> +</tabstops> +<includes> + <include location="global" impldecl="in declaration">kseparator.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> +</includehints> +</UI> diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendium.cpp b/kbabel/kbabeldict/modules/tmx/tmxcompendium.cpp new file mode 100644 index 00000000..152bc536 --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/tmxcompendium.cpp @@ -0,0 +1,1007 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 <klocale.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kstaticdeleter.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kinstance.h> +#include <kio/netaccess.h> + +#include <qtextstream.h> +#include <qtimer.h> + +#include "tmxcompendiumdata.h" +#include "tmxcompendium.h" +#include "preferenceswidget.h" +#include "pc_factory.h" + +#include <catalogitem.h> + +// ngram length and minimal matching for fuzzy search +#define NGRAM_LEN 3 +#define LIM_NGRAM 50 + +static KStaticDeleter< QDict<TmxCompendiumData> > compDataDeleter; +QDict<TmxCompendiumData> *TmxCompendium::_compDict = 0; + +TmxCompendium::TmxCompendium(QObject *parent, const char *name) + : SearchEngine(parent, name) +{ + prefWidget=0; + data=0; + error=false; + stop=false; + active=false; + initialized=false; + loading=false; + + langCode = KGlobal::locale()->language(); + + caseSensitive = false; + wholeWords=true; + + matchEqual = true; + matchNGram = true; + matchIsContained = false; + matchContains = true; + matchWords=true; + + + loadTimer = new QTimer(this); + connect(loadTimer,SIGNAL(timeout()),this,SLOT(slotLoadCompendium())); +} + +TmxCompendium::~TmxCompendium() +{ + if(isSearching()) + { + stopSearch(); + } + + unregisterData(); +} + +bool TmxCompendium::isReady() const +{ + return (isSearching() || !error); +} + + +bool TmxCompendium::isSearching() const +{ + return (active || loading); +} + + +void TmxCompendium::saveSettings(KConfigBase *config) +{ + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + config->writeEntry("CaseSensitive",caseSensitive); + config->writeEntry("WholeWords", wholeWords); + + config->writeEntry("MatchEqual", matchEqual); + config->writeEntry("MatchIsContained",matchIsContained); + config->writeEntry("MatchContains", matchContains); + config->writeEntry("MatchWords", matchWords); + config->writeEntry("MatchNGram", matchNGram); + + config->writeEntry("Compendium", url); +} + +void TmxCompendium::readSettings(KConfigBase *config) +{ + caseSensitive = config->readBoolEntry("CaseSensitive", false); + wholeWords = config->readBoolEntry("WholeWords",true); + + matchEqual = config->readBoolEntry("MatchEqual", true); + matchIsContained = config->readBoolEntry("MatchIsContained", false); + matchContains = config->readBoolEntry("MatchContains",true); + matchWords = config->readBoolEntry("MatchWords",true); + matchNGram = config->readBoolEntry("MatchNGram",true); + + QString newPath = config->readEntry("Compendium","http://i18n.kde.org/po_overview/@LANG@.messages"); + if(!initialized) + { + url = newPath; + } + else if(newPath != url) + { + url = newPath; + loadCompendium(); + } + + + restoreSettings(); +} + +PrefWidget *TmxCompendium::preferencesWidget(QWidget *parent) +{ + prefWidget = new TmxCompendiumPreferencesWidget(parent,"tmxcompendium_prefwidget"); + connect(prefWidget, SIGNAL(applySettings()), this, SLOT(applySettings())); + connect(prefWidget, SIGNAL(restoreSettings()) + , this, SLOT(restoreSettings())); + + restoreSettings(); + + return prefWidget; +} + +const KAboutData *TmxCompendium::about() const +{ + return PcFactory::instance()->aboutData(); +} + + +QString TmxCompendium::name() const +{ + return i18n("TMX Compendium"); +} + +QString TmxCompendium::id() const +{ + return "tmxcompendium"; +} + +QString TmxCompendium::lastError() +{ + return errorMsg; +} + + +bool TmxCompendium::startSearch(const QString& text, uint pluralForm, const SearchFilter*) +{ + if(autoUpdate && prefWidget && prefWidget->settingsChanged()) + { + applySettings(); + } + + if(isSearching()) + return false; + + clearResults(); + stop = false; + active = true; + + if(!initialized) + { + if(loadTimer->isActive()) + loadTimer->stop(); + + slotLoadCompendium(); + } + + if(error || !data) + { + active = false; + return false; + } + + if(data->active()) + { + active = false; + return true; + } + + emit started(); + + + QValueList<int> foundIndices; + QValueList<int> checkedIndices; + uint checkCounter=0; + + const int *index = data->exactDict(text); + if(index) + { + foundIndices.append(*index); + + SearchResult *result = new SearchResult; + result->requested = text; + result->found = data->msgid(*index); + result->translation = data->msgstr(*index); + result->score = 100; + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = QString::null; + info->description = QString::null; + result->descriptions.append(info); + + results.append(result); + + emit numberOfResultsChanged(results.count()); + emit resultFound(result); + } + + QString searchStr=TmxCompendiumData::simplify(text); + + + if(!caseSensitive) + { + searchStr = searchStr.lower(); + } + + QString temp = searchStr; + temp = temp.lower(); + + const QValueList<int> *indexList = data->allDict(temp); + if(indexList) + { + QValueList<int>::ConstIterator it; + for( it = indexList->begin(); it != indexList->end(); ++it ) + { + if(foundIndices.contains(*it)) + { + continue; + } + + QString origStr = data->msgid(*it); + origStr = TmxCompendiumData::simplify(origStr); + + + if(!caseSensitive) + { + origStr = origStr.lower(); + } + + if(origStr==searchStr) + { + foundIndices.append(*it); + + SearchResult *result = new SearchResult; + result->requested = text; + result->found = data->msgid(*it); + result->translation = data->msgstr(*it); + // FIXME: handle plural forms properly + result->score = score(result->requested,result->found.first()); + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = QString::null; + info->description = QString::null; + result->descriptions.append(info); + + addResult(result); + } + } + } + + QStringList wList = TmxCompendiumData::wordList(searchStr); + for ( QStringList::Iterator wit = wList.begin() + ; wit != wList.end(); ++wit ) + { + if(stop) + break; + + indexList = data->wordDict((*wit).lower()); + if(indexList) + { + QValueList<int>::ConstIterator it; + for( it = indexList->begin(); it != indexList->end(); ++it ) + { + if(stop) + break; + + if(foundIndices.contains(*it)) + { + continue; + } + + if(checkedIndices.contains(*it)) + { + continue; + } + + checkedIndices.append(*it); + checkCounter++; + + if( (100*(checkCounter+1))%data->numberOfEntries() < 100) + { + emit progress( (100*(checkCounter+1))/data->numberOfEntries()); + } + + kapp->processEvents(100); + + QString origStr = data->msgid(*it); + origStr = TmxCompendiumData::simplify(origStr); + + + if(!caseSensitive) + { + origStr = origStr.lower(); + } + + bool found = false; + if(matchWords) + { + if(!caseSensitive) + { + found=true; + } + else + { + QString s=*wit; + QString o=origStr; + + if(wholeWords) + { + s=" "+*wit+" "; + o=" "+origStr+" "; + } + if(o.contains(s)) + { + found=true; + } + } + } + + + if(!found && origStr==searchStr) + { + found =true; + } + + // if there is an string which just contains ignored characters, + // continue + if(!found && origStr.isEmpty() || + (origStr.length() == 1 && text.length() > 1)) + { + continue; + } + + + if(!found && matchContains && !wholeWords) + { + QString s=maskString(searchStr); + QRegExp searchReg(s); + + if(searchReg.search(origStr) >= 0) + found=true; + } + + if(!found && matchIsContained && !wholeWords) + { + QString s=maskString(origStr); + QRegExp reg(s); + + if(reg.search(searchStr) >= 0) + { + found = true; + } + } + if(!found && matchWords && !wholeWords) + { + QStringList list = TmxCompendiumData::wordList(searchStr); + + for ( QStringList::Iterator wit2 = list.begin() + ; wit2 != list.end(); ++wit2 ) + { + QString s=maskString(*wit2); + QRegExp reg(s); + + if(reg.search(origStr) >= 0) + { + found = true; + } + } + } + + if(found) + { + foundIndices.append(*it); + + SearchResult *result = new SearchResult; + result->requested = text; + result->found = data->msgid(*it); + result->translation = data->msgstr(*it); + // FIXME: handle plural forms properly + result->score = score(result->requested,(result->found.first())); + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = QString::null; + info->description = QString::null; + result->descriptions.append(info); + + addResult(result); + } + } + } + } + + + if( matchNGram || + (!wholeWords && (matchContains || matchIsContained || matchWords)) + ) + { + QRegExp searchReg; + if(matchContains) + { + QString s=maskString(searchStr); + searchReg.setPattern(s); + } + + + bool breakLoop=false; + int i=-1; + while(!breakLoop) + { + if(stop) + { + breakLoop=true; + break; + } + + i++; + + if(checkedIndices.contains(i)) + { + continue; + } + + checkedIndices.append(i); + checkCounter++; + + if(foundIndices.contains(i)) + { + continue; + } + + kapp->processEvents(100); + + if(i >= data->numberOfEntries()) + { + breakLoop = true; + break; + } + + if( (100*(checkCounter+1))%data->numberOfEntries() < 100) + { + emit progress( (100*(checkCounter+1))/data->numberOfEntries()); + } + + QString origStr = data->msgid(i); + origStr = TmxCompendiumData::simplify(origStr); + + if(!caseSensitive) + { + origStr = origStr.lower(); + } + + + // if there is an string which just contains ignored characters, + // continue + if(origStr.isEmpty() || + (origStr.length() == 1 && text.length() > 1)) + { + continue; + } + + bool found = false; + if(matchContains && searchReg.search(origStr) >= 0) + { + found=true; + } + + + if(!found && matchIsContained) + { + QString s=maskString(origStr); + QRegExp reg(s); + + if(reg.search(searchStr) >= 0) + { + found = true; + } + } + if(!found && matchWords) + { + QStringList list = TmxCompendiumData::wordList(searchStr); + + for ( QStringList::Iterator wit2 = list.begin() + ; wit2 != list.end(); ++wit2 ) + { + QString s=maskString(*wit2); + + if(wholeWords) + { + origStr = " "+origStr+" "; + s=" "+s+" "; + } + QRegExp reg(s); + + if(reg.search(origStr) >= 0) + { + found = true; + } + } + } + + if(!found && matchNGram) + { + // to get more results one could + // interchange searchStr and origStr when + // the latter is shorter + + found = ( ngramMatch(searchStr,origStr,NGRAM_LEN) + > LIM_NGRAM ); + } + + if(found) + { + foundIndices.append(i); + + SearchResult *result = new SearchResult; + result->requested = text; + result->found = data->msgid(i); + result->translation = data->msgstr(i); + // FIXME: handle plural forms properly + result->score = score(result->requested,(result->found.first())); + + TranslationInfo *info = new TranslationInfo; + info->location = directory(realURL,0); + info->translator = QString::null; + info->description = QString::null; + result->descriptions.append(info); + + addResult(result); + } + } + } + + if( (100*(checkCounter+1))/data->numberOfEntries() < 100 && !stop) + { + for(int i=(100*(checkCounter+1))/data->numberOfEntries(); i<=100; i++) + { + emit progress(i); + } + } + + + active = false; + stop = false; + emit finished(); + + return true; +} + +void TmxCompendium::stopSearch() +{ + stop=true; +} + + +void TmxCompendium::applySettings() +{ + if(!prefWidget) + return; + + if(isSearching()) + stopSearch(); + + caseSensitive = prefWidget->caseSensitive(); + wholeWords = prefWidget->wholeWords(); + + matchEqual = prefWidget->matchEqual(); + matchNGram = prefWidget->matchNGram(); + matchIsContained = prefWidget->matchIsContained(); + matchContains = prefWidget->matchContains(); + matchWords = prefWidget->matchWords(); + + + bool needLoading=false; + + + QString newPath = prefWidget->url(); + if(!initialized) + { + url = newPath; + } + else if(newPath != url) + { + url = newPath; + needLoading = true; + } + + if(needLoading) + { + loadCompendium(); + initialized=false; + } +} + +void TmxCompendium::restoreSettings() +{ + if(!prefWidget) + return; + + prefWidget->setCaseSensitive(caseSensitive); + prefWidget->setWholeWords(wholeWords); + prefWidget->setURL(url); + + prefWidget->setMatchEqual(matchEqual); + prefWidget->setMatchNGram(matchNGram); + prefWidget->setMatchIsContained(matchIsContained); + prefWidget->setMatchContains(matchContains); + prefWidget->setMatchWords(matchWords); +} + +void TmxCompendium::loadCompendium() +{ + if(!loading && !loadTimer->isActive()) + loadTimer->start(100,true); +} + +void TmxCompendium::slotLoadCompendium() +{ + if(loading) + return; + + if(loadTimer->isActive()) + loadTimer->stop(); + + loading = true; + + if(data) + { + unregisterData(); + } + + + QString path=url; + + if(path.contains("@LANG@")) + { + path.replace("@LANG@",langCode); + } + KURL u=KCmdLineArgs::makeURL(path.local8Bit()); + realURL = u.url(); + + registerData(); + + + if(!data) + { + kdError() << "no data object in tmxcompendium?" << endl; + + loading=false; + return; + } + + if(!data->initialized()) + { + if(!data->active()) + { + data->load(u,langCode); + recheckData(); + if(error) + { + emit hasError(errorMsg); + } + } + else + { + connect(data, SIGNAL(progressEnds()), this, SLOT(recheckData())); + } + } + else + { + recheckData(); + if(error) + { + emit hasError(errorMsg); + } + } + + initialized=true; +} + +void TmxCompendium::recheckData() +{ + if(data) + { + disconnect(data, SIGNAL(progressEnds()), this, SLOT(recheckData())); + + error = data->hasErrors(); + errorMsg = data->errorMsg(); + } + + loading=false; +} + +QString TmxCompendium::maskString(QString s) const +{ + s.replace('\\',"\\\\"); + s.replace('?',"\\?"); + s.replace('[',"\\["); + s.replace('.',"\\."); + s.replace('*',"\\*"); + s.replace('+',"\\+"); + s.replace('^',"\\^"); + s.replace('$',"\\$"); + s.replace('(',"\\("); + s.replace(')',"\\)"); + s.replace('{',"\\{"); + s.replace('}',"\\}"); + s.replace('|',"\\|"); + + return s; +} + +void TmxCompendium::addResult(SearchResult *result) +{ + if(results.last() && results.last()->score >= result->score) + { + results.append(result); + } + else + { + SearchResult *sr; + for(sr = results.first(); sr != 0; sr=results.next()) + { + if(sr->score < result->score) + { + results.insert(results.at(),result); + emit resultsReordered(); + break; + } + } + + if(!sr) + { + results.append(result); + } + } + + emit numberOfResultsChanged(results.count()); + emit resultFound(result); +} + + +void TmxCompendium::setLanguageCode(const QString& lang) +{ + if(initialized && url.contains("@LANG@") && lang!=langCode + && !loadTimer->isActive() ) + { + initialized=false; + } + + langCode=lang; +} + +QString TmxCompendium::translate(const QString& text, uint pluralForm) +{ + if(!initialized) + { + if(loadTimer->isActive()) + loadTimer->stop(); + + slotLoadCompendium(); + } + + if(error || !data || data->active()) + { + return QString::null; + } + + + const int *index = data->exactDict(text); + + if(index) + { + return data->msgstr(*index); + } + + return QString::null; +} + +QString TmxCompendium::fuzzyTranslation(const QString& text, int &score, uint pluralForm) +{ + if(!initialized) + { + if(loadTimer->isActive()) + loadTimer->stop(); + + slotLoadCompendium(); + } + + if(error || !data || data->active()) + { + return QString::null; + } + + // try to find fuzzy string + bool breakLoop = false; + stop = false; + int i=-1; + int best_matching = -1; + int best_match = 0; + int total = data->numberOfEntries(); + + QString searchStr = TmxCompendiumData::simplify(text); + + //kdDebug(750) << "find best match for " << searchStr << endl; + + while(!breakLoop) + { + + // progress and loop control + if(stop) + { + breakLoop=true; + break; + } + + i++; + + if(i >= total) + { + breakLoop = true; + break; + } + + if( (100*(i+1))%total < 100) + { + emit progress( (100*(i+1))/total); + } + + // get a message from the catalog + QString origStr = data->msgid(i); + origStr = TmxCompendiumData::simplify(origStr); + + // don't match too long strings for short search string + if (origStr.length() > 2*searchStr.length()) + continue; + // kdDebug(750) << i << ": matching " << origStr << endl; + + int ngram_result = ngramMatch(searchStr,origStr); + + if (ngram_result > best_match) { + best_match = ngram_result; + best_matching = i; + + // kdDebug(750) << "[" << ngram_result << "] " << text << "-" + // << origStr << endl; + } + } + + if (best_match > LIM_NGRAM) { + score = best_match; + return data->msgstr(best_matching); + } + + return QString::null; +} + + +void TmxCompendium::unregisterData() +{ + if(data) + { + disconnect(data, SIGNAL(progressStarts(const QString&)), this + , SIGNAL(progressStarts(const QString&))); + disconnect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds())); + disconnect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int))); + + if(data->active()) + { + disconnect(data,SIGNAL(progressEnds()),this,SLOT(recheckData())); + } + + if(data->unregisterObject(this)) + { + if(!data->active()) + { + compendiumDict()->remove(realURL); + } + else + { + connect(data,SIGNAL(progressEnds()),this,SLOT(removeData())); + } + } + + data=0; + } +} + +void TmxCompendium::registerData() +{ + data = compendiumDict()->find(realURL); + if(!data) + { + data = new TmxCompendiumData; + compendiumDict()->insert(realURL,data); + } + + data->registerObject(this); + + if(data->active()) + { + emit progressStarts(i18n("Loading PO compendium")); + } + + connect(data, SIGNAL(progressStarts(const QString&)), this + , SIGNAL(progressStarts(const QString&))); + connect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds())); + connect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int))); +} + +void TmxCompendium::removeData() +{ + const QObject *s=sender(); + if(s && s->inherits("TmxCompendiumData")) + { + const TmxCompendiumData *d=static_cast<const TmxCompendiumData*>(s); + if(d) + { + QDictIterator<TmxCompendiumData> it(*compendiumDict()); + while(it.current()) + { + if(it.current() == d) + { + if(!d->hasObjects()) + { + compendiumDict()->remove(it.currentKey()); + } + + break; + } + + ++it; + } + } + + } +} + +QDict<TmxCompendiumData> *TmxCompendium::compendiumDict() +{ + if(!_compDict) + { + _compDict=compDataDeleter.setObject( new QDict<TmxCompendiumData> ); + _compDict->setAutoDelete(true); + } + + return _compDict; +} + + + +#include "tmxcompendium.moc" diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendium.desktop b/kbabel/kbabeldict/modules/tmx/tmxcompendium.desktop new file mode 100644 index 00000000..cae7d333 --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/tmxcompendium.desktop @@ -0,0 +1,50 @@ +[Desktop Entry] +Type=Service +Name=TMX Compendium Module for KBabelDict +Name[bg]=TMX компендиум за KBabelDict +Name[bs]=Modul TMX kompendijuma za KBabelDict +Name[ca]=Mòdul del Compendi TMX per a KBabelDict +Name[cs]=Modul s TMX kompendiem pro KBabelDict +Name[cy]=Modiwl Compendiwm TMX i KBabelDict +Name[da]=TMX kompendium-module for KBabelDict +Name[de]=TMX-Kompendium-Modul für KBabelDict +Name[el]=Άρθρωμα επιτομής TMX για το KBabelDict +Name[es]=Módulo de compendio TMX para KBabelDict +Name[et]=KBabelDicti TMX kompendiumi moodul +Name[eu]=TMX laburpen modulua KBabelDict-entzat +Name[fa]=پیمانۀ مختصر TMX برای KBabelDict +Name[fi]=KBabelDict-ohjelman TMX-kokoelmatiedostomoduuli +Name[fr]=Module de fichier de référence des TMX pour KBabelDict +Name[gl]=Módulo de compendio TMX para KBabelDict +Name[hi]=के-बेबल-डिक्श के लिए टीएमएक्स कम्पेंडियम मॉड्यूल +Name[hu]=TMX összefoglaló modul a KBabelDicthez +Name[is]=TMX ágrips eining fyrir KBabel orðabókina +Name[it]=Modulo TMX Compendium per KBabelDict +Name[ja]=KBabelDict TMX 要約モジュール +Name[ka]=TMX კონსპექტის მოდული KBabelDict-სთვის +Name[kk]=KBabelDict-тың TMX аудармалар жиынтық модулі +Name[lt]=KBabelDict TMX tekstyno modulis +Name[ms]=Modul Kompendium TMX untuk KBabelDict +Name[nb]=TMX-kompendium-modul for KBabelDict +Name[nds]=TMX-Kompendiummoduul för KBabelDict +Name[ne]=KBabelDict का लागि टीएमएक्स संक्षेप मोड्युल +Name[nl]=TMX-samenvattingmodule voor KBabelDict +Name[nn]=TMX-kompendiemodul for KBabelDict +Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦਕੋਸ਼ ਲਈ TMX ਅਨੁਵਾਦ ਮੈਡੀਊਲ +Name[pl]=Moduł Kompendium TMX dla KBabelDict +Name[pt]=Módulo de Compêndio de TMX para o KBabelDict +Name[pt_BR]=Módulo de Compêndio TMX para o KBabelDict +Name[ru]=Модуль описания TMX для KBabelDict +Name[sk]=TMX kompendium pre KBabelDict +Name[sl]=Modul zbornika TMX za KBabelDict +Name[sr]=Модул TMX зборника за KBabelDict +Name[sr@Latn]=Modul TMX zbornika za KBabelDict +Name[sv]=TMX-kompendiemodul för Kbabeldict +Name[ta]=Kபாபேலுக்கான காம்பென்டியம் TMX கூறு +Name[tg]=Модули тасвири TMX барои KBabelDict +Name[tr]=KBabelDict için TMX Özet Modülü +Name[uk]=Модуль збірки перекладів TMX для KBabelDict +Name[zh_CN]=KBabelDict 的 TMX 概要词典模块 +Name[zh_TW]=KBabelDict TMX 摘要模組 +X-KDE-Library=kbabeldict_tmxcompendium +ServiceTypes=KBabelDictModule diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendium.h b/kbabel/kbabeldict/modules/tmx/tmxcompendium.h new file mode 100644 index 00000000..9a2f8fba --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/tmxcompendium.h @@ -0,0 +1,137 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + +#ifndef TMXCOMPENDIUM_H +#define TMXCOMPENDIUM_H + +#include "tmxcompendiumdata.h" +#include "searchengine.h" + +#include <qdict.h> +#include <qfile.h> +#include <qguardedptr.h> + +class TmxCompendiumPreferencesWidget; +class KConfigBase; +class QTimer; + +class TmxCompendium : public SearchEngine +{ + Q_OBJECT + +public: + TmxCompendium(QObject *parent=0, const char *name=0); + virtual ~TmxCompendium(); + + virtual bool isReady() const; + + virtual QString translate(const QString& text, uint pluralForm); + virtual QString fuzzyTranslation(const QString& text, int &score, uint pluralForm); + + virtual bool isSearching() const; + + virtual void saveSettings(KConfigBase *config); + virtual void readSettings(KConfigBase *config); + + virtual PrefWidget *preferencesWidget(QWidget *parent); + + virtual const KAboutData *about() const; + + virtual QString name() const; + + virtual QString id() const; + + virtual QString lastError(); + + +public slots: + virtual bool startSearch(const QString& text, uint pluralForm, const SearchFilter* filter); + virtual void stopSearch(); + virtual void setLanguageCode(const QString& lang); + +protected slots: + /** reads the current settings from the preferences dialog */ + void applySettings(); + + /** sets the current settings in the preferences dialog */ + void restoreSettings(); + + void slotLoadCompendium(); + + void recheckData(); + void removeData(); + +protected: + void loadCompendium(); + void addResult(SearchResult *); + QString maskString(QString string) const; + + void registerData(); + void unregisterData(); + +private: + QGuardedPtr<TmxCompendiumPreferencesWidget> prefWidget; + TmxCompendiumData *data; + QTimer *loadTimer; + + QString url; + QString realURL; + QString langCode; + + bool caseSensitive; + bool wholeWords; + + bool matchEqual; + bool matchIsContained; + bool matchContains; + bool matchWords; + bool matchNGram; + + bool buildIndex; + uint freeMemDelay; + + bool error; + QString errorMsg; + + bool stop; + bool active; + bool initialized; + bool loading; + + static QDict<TmxCompendiumData> *_compDict; + static QDict<TmxCompendiumData> *compendiumDict(); +}; + +#endif diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.cpp b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.cpp new file mode 100644 index 00000000..3fa84aa4 --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.cpp @@ -0,0 +1,308 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2001 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 "tmxcompendiumdata.h" + +#include <qdom.h> +#include <qfile.h> + +#include <tagextractor.h> +#include <resources.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <kio/netaccess.h> + +using namespace KBabel; + +TmxCompendiumData::TmxCompendiumData(QObject *parent) + : QObject(parent) + , _active(false) + , _error(false) + , _initialized(false) + , _exactDict(9887) + , _allDict(9887) + , _wordDict(9887) +{ + _exactDict.setAutoDelete(true); + _allDict.setAutoDelete(true); + _wordDict.setAutoDelete(true); +} + + +bool TmxCompendiumData::load(const KURL& url, const QString& language) +{ + kdDebug(KBABEL_SEARCH) << "Load " << url.url() << " in " << language << endl; + if(_active) + return false; + + + _error = false; + _active = true; + + _exactDict.clear(); + _allDict.clear(); + _wordDict.clear(); + + + emit progressStarts(i18n("Loading TMX compendium")); + + QDomDocument doc( "mydocument" ); + + QString target; + + if( KIO::NetAccess::download( url, target ) ) + { + QFile f( target ); + if ( !f.open( IO_ReadOnly ) ) + { + _error = true; + _errorMsg = i18n( "Cannot open the file." ); + } + else if ( !doc.setContent( &f ) ) { + _error = true; + _errorMsg = i18n( "Cannot parse XML data." ); + } + f.close(); + KIO::NetAccess::removeTempFile(target); + } else { + _error = true; + _errorMsg = i18n( "Cannot open the file." ); + } + + QDomElement docElem = doc.documentElement(); + + if( docElem.tagName() != "tmx" || !(docElem.hasAttribute("version") + && docElem.attribute("version") == "1.4" ) ) + { + _error = true; + _errorMsg = i18n( "Unsupported format."); + } + + + if( _error ) + { + _errorMsg = i18n("Error while trying to read file for TMX Compendium module:\n" + "%1\n" + "Reason: %2") + .arg(url.prettyURL()).arg(_errorMsg); + + kdDebug(KBABEL_SEARCH) << "Error: " << _errorMsg << endl; + + emit progressEnds(); + + _active = false; + _initialized=true; + + return false; + } + + emit progressStarts(i18n("Building indices")); + + QDomNodeList tuTags = docElem.elementsByTagName("tu"); + uint total = tuTags.count(); + + _originals.clear(); + _originals.resize(total); + _translations.clear(); + _translations.resize(total); + + uint lastindex = 0; + + for(uint i=0; i < total; i++) + { + if( (100*(i+1))%total < 100 ) + { + emit progress((100*(i+1))/total); + kapp->processEvents(100); + } + + QDomNodeList tuvTags = tuTags.item(i).toElement().elementsByTagName("tuv"); + QString english, other; + for( uint j = 0 ; j < tuvTags.count() ; j++ ) + { + QDomElement el = tuvTags.item(j).toElement(); + if( el.attribute("xml:lang").upper() == "EN" ) english = el.text(); + if( el.attribute("xml:lang").upper().startsWith(language.upper()) ) + other = el.text(); + } + + if( !english.isEmpty() && !other.isEmpty() ) + { + kdDebug(KBABEL_SEARCH) << english << " to " << lastindex << endl; + _originals[lastindex] = english; + _translations[lastindex] = other; + + QString temp = english; + + int *index = new int(lastindex); + _exactDict.insert(temp,index); + + temp = simplify(temp); + temp = temp.lower(); + + if(!temp.isEmpty() && temp.length() > 1) + { + QValueList<int> *indexList=_allDict[temp]; + + if(!indexList) + { + indexList = new QValueList<int>; + _allDict.insert(temp,indexList); + } + + indexList->append(lastindex); + + QStringList wList = wordList(temp); + for ( QStringList::Iterator it = wList.begin() + ; it != wList.end(); ++it ) + { + if( (*it).length() > 1) + { + indexList=_wordDict[*it]; + + if(!indexList) + { + indexList = new QValueList<int>; + _wordDict.insert(*it,indexList); + } + + indexList->append(lastindex); + } + } + } + lastindex++; + } + } + + + // remove words, that are too frequent + uint max=_allDict.count()/10; + QDictIterator< QValueList<int> > it(_wordDict); + while ( it.current() ) + { + if(it.current()->count() > max) + { + _wordDict.remove(it.currentKey()); + } + else + { + ++it; + } + } + + if( lastindex == 0) + { + _error = true; + _errorMsg = i18n("Empty database."); + } + + kdDebug(KBABEL_SEARCH) << "load done" << endl; + + _initialized=true; + + emit progressEnds(); + + _active = false; + + return true; +} + +const int* TmxCompendiumData::exactDict(const QString& text) const +{ + return _exactDict[text]; +} + +const QValueList<int>* TmxCompendiumData::allDict(const QString& text) const +{ + return _allDict[text]; +} + +const QValueList<int>* TmxCompendiumData::wordDict(const QString& text) const +{ + return _wordDict[text]; +} + +const QString TmxCompendiumData::msgid(const int index) const +{ + return _originals[index]; +} + +const QString TmxCompendiumData::msgstr(const int index) const +{ + return _translations[index]; +} + + +void TmxCompendiumData::registerObject(QObject *obj) +{ + if(!_registered.containsRef(obj)) + _registered.append(obj); +} + +bool TmxCompendiumData::unregisterObject(QObject *obj) +{ + _registered.removeRef(obj); + + return _registered.count()==0; +} + +bool TmxCompendiumData::hasObjects() const +{ + return _registered.count()==0; +} + +QString TmxCompendiumData::simplify(const QString& string) +{ + QString result; + + TagExtractor te; + te.setString(string); + result=te.plainString(); + + result=result.simplifyWhiteSpace(); + result=result.stripWhiteSpace(); + + return result; +} + +QStringList TmxCompendiumData::wordList(const QString& string) +{ + QString result=TmxCompendiumData::simplify(string); + + return QStringList::split(' ',result); +} + +#include "tmxcompendiumdata.moc" diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.h b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.h new file mode 100644 index 00000000..bc88a92e --- /dev/null +++ b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.h @@ -0,0 +1,106 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2001 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2002 by Stanislav Visnovsky + <visnovsky@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ +#ifndef TMXCOMPENDIUMDATA_H +#define TMXCOMPENDIUMDATA_H + + +#include <kurl.h> +#include <qdict.h> +#include <qobject.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qvaluevector.h> +#include <qptrlist.h> + +class TmxCompendiumData : public QObject +{ + Q_OBJECT + +public: + TmxCompendiumData(QObject *parent=0); + + bool load(const KURL& url, const QString& language); + + const int *exactDict(const QString& text) const; + const QValueList<int> *allDict(const QString& text) const; + const QValueList<int> *wordDict(const QString& text) const; + + const QString msgid(const int index) const; + const QString msgstr(const int index) const; + const int numberOfEntries() const { return _exactDict.count(); } + + bool active() const { return _active; } + bool initialized() const { return _initialized; } + bool hasErrors() const { return _error; } + QString errorMsg() const { return _errorMsg; } + + /** registers an object, that uses this data */ + void registerObject(QObject *); + /** + * unregisters an object, that uses this data + * + * @return true, if this was the last object + */ + bool unregisterObject(QObject *); + + bool hasObjects() const; + + + static QString simplify(const QString& text); + static QStringList wordList(const QString& text); + +signals: + void progressStarts(const QString&); + void progressEnds(); + void progress(int); + + +private: + bool _active; + bool _error; + bool _initialized; + QString _errorMsg; + + QDict<int> _exactDict; + QDict< QValueList<int> > _allDict; + QDict< QValueList<int> > _wordDict; + + QValueVector<QString> _originals; + QValueVector<QString> _translations; + + QPtrList<QObject> _registered; +}; + +#endif |