File indexing completed on 2024-05-12 15:55:07

0001 /***************************************************************************
0002                           kocrstartdia.cpp  -  description
0003                              -------------------
0004     begin                : Fri Now 10 2000
0005     copyright            : (C) 2000 by Klaas Freitag
0006     email                : freitag@suse.de
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *  This file may be distributed and/or modified under the terms of the    *
0012  *  GNU General Public License version 2 as published by the Free Software *
0013  *  Foundation and appearing in the file COPYING included in the           *
0014  *  packaging of this file.                                                *
0015  *
0016  *  As a special exception, permission is given to link this program       *
0017  *  with any version of the KADMOS ocr/icr engine of reRecognition GmbH,   *
0018  *  Kreuzlingen and distribute the resulting executable without            *
0019  *  including the source code for KADMOS in the source distribution.       *
0020  *
0021  *  As a special exception, permission is given to link this program       *
0022  *  with any edition of Qt, and distribute the resulting executable,       *
0023  *  without including the source code for Qt in the source distribution.   *
0024  *                                                                         *
0025  ***************************************************************************/
0026 
0027 #include "ocrkadmosdialog.h"
0028 
0029 #include <qlayout.h>
0030 #include <qlabel.h>
0031 #include <qfileinfo.h>
0032 #include <qtooltip.h>
0033 #include <qdir.h>
0034 #include <qmap.h>
0035 #include <qradiobutton.h>
0036 #include <qcombobox.h>
0037 #include <qcheckbox.h>
0038 #include <qstringlist.h>
0039 
0040 #include <kconfig.h>
0041 #include <kglobal.h>
0042 #include <KLocalizedString>
0043 #include <kseparator.h>
0044 #include <kmessagebox.h>
0045 #include <kstandarddirs.h>
0046 #include <QVBoxLayout>
0047 #include <QHBoxLayout>
0048 
0049 #include "ocrkadmosengine.h"
0050 #include "ocr_logging.h"
0051 
0052 /* defines for konfig-reading */
0053 #define CFG_GROUP_KADMOS "Kadmos"
0054 #define CFG_KADMOS_CLASSIFIER_PATH "classifierPath"
0055 #define CFG_KADMOS_CLASSIFIER      "classifier"
0056 
0057 #define CNTRY_CZ i18n( "Czech Republic, Slovakia")
0058 #define CNTRY_GB i18n( "Great Britain, USA" )
0059 
0060 KadmosDialog::KadmosDialog(QWidget *parent)
0061     : OcrBaseDialog(parent),
0062       m_cbNoise(0),
0063       m_cbAutoscale(0),
0064       m_haveNorm(false)
0065 {
0066     //qCDebug(OCR_LOG);
0067     // Layout-Boxes
0068     findClassifiers();
0069 }
0070 
0071 QString KadmosDialog::ocrEngineLogo() const
0072 {
0073     return ("kadmoslogo.png");
0074 }
0075 
0076 QString KadmosDialog::ocrEngineName() const
0077 {
0078     return (OcrEngine::engineName(OcrEngine::EngineKadmos));
0079 }
0080 
0081 QString KadmosDialog::ocrEngineDesc() const
0082 {
0083     return (OcrKadmosEngine::engineDesc());
0084 }
0085 
0086 OcrEngine::EngineError KadmosDialog::findClassifiers()
0087 {
0088     findClassifierPath();
0089 
0090     KLocale *locale = KLocale::global();
0091     const QStringList allCountries = locale->allCountriesList();
0092     for (QStringList::const_iterator it = allCountries.constBegin();
0093             it != allCountries.constEnd(); ++it) {
0094         m_longCountry2short[locale->countryCodeToName(*it)] = *it;
0095     }
0096     m_longCountry2short[i18n("European Countries")] = "eu";
0097     m_longCountry2short[CNTRY_CZ] = "cz";
0098     m_longCountry2short[CNTRY_GB] = "us";
0099 
0100     QStringList lst;
0101 
0102     /* custom Path */
0103     if (! m_customClassifierPath.isEmpty()) {
0104         QDir dir(m_customClassifierPath);
0105 
0106         QStringList lst1 = dir.entryList(QStringList("ttf*.rec"));
0107 
0108         for (QStringList::Iterator it = lst1.begin(); it != lst1.end(); ++it) {
0109             lst << m_customClassifierPath + *it;
0110         }
0111 
0112         lst1 = dir.entryList(QStringList("hand*.rec"));
0113 
0114         for (QStringList::Iterator it = lst1.begin(); it != lst1.end(); ++it) {
0115             lst << m_customClassifierPath + *it;
0116         }
0117 
0118         lst1 = dir.entryList(QStringList("norm*.rec"));
0119 
0120         for (QStringList::Iterator it = lst1.begin(); it != lst1.end(); ++it) {
0121             lst << m_customClassifierPath + *it;
0122         }
0123     } else {
0124         /* standard location */
0125         KStandardDirs stdDir;
0126         //qCDebug(OCR_LOG) << "Starting to read resources";
0127 
0128         lst = stdDir.findAllResources("data",
0129                                       "kooka/classifiers/*.rec",
0130                                       KStandardDirs::Recursive | KStandardDirs::NoDuplicates);
0131     }
0132 
0133     /* no go through lst and sort out hand-, ttf- and norm classifier */
0134     for (QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) {
0135         //qCDebug(OCR_LOG) << "Checking file:" << (*it);
0136         QFileInfo fi(*it);
0137         QString name = fi.fileName().toLower();
0138 
0139         if (name.startsWith("ttf")) {
0140             QString lang = name.mid(3, 2);
0141             if (allCountries.contains(lang)) {
0142                 QString lngCountry = locale->countryCodeToName(lang);
0143                 if (lngCountry.isEmpty()) {
0144                     lngCountry = name;
0145                 }
0146                 m_ttfClassifier << lngCountry;
0147                 //qCDebug(OCR_LOG) << "TTF: Insert country" << lngCountry;
0148             } else if (lang == "cz") {
0149                 m_ttfClassifier << CNTRY_CZ;
0150             } else if (lang == "us") {
0151                 m_ttfClassifier << CNTRY_GB;
0152             } else {
0153                 m_ttfClassifier << name;
0154                 //qCDebug(OCR_LOG) << "TTF: Unknown country";
0155             }
0156         } else if (name.startsWith("hand")) {
0157             QString lang = name.mid(4, 2);
0158             if (allCountries.contains(lang)) {
0159                 QString lngCountry = locale->countryCodeToName(lang);
0160                 if (lngCountry.isEmpty()) {
0161                     lngCountry = name;
0162                 }
0163                 m_handClassifier << lngCountry;
0164             } else if (lang == "cz") {
0165                 m_handClassifier << i18n("Czech Republic, Slovakia");
0166             } else if (lang == "us") {
0167                 m_handClassifier << i18n("Great Britain, USA");
0168             } else {
0169                 //qCDebug(OCR_LOG) << "HAND: Unknown country" << lang;
0170                 m_handClassifier << name;
0171             }
0172         } else if (name.startsWith("norm")) {
0173             m_haveNorm = true;
0174         }
0175 
0176         //qCDebug(OCR_LOG) << "Found classifier:" << (*it);
0177         m_classifierPath << *it;
0178     }
0179 
0180     if (m_handClassifier.count() + m_ttfClassifier.count() > 0) {
0181         /* There are classifiers */
0182         return OcrEngine::ENG_OK;
0183     } else {
0184         /* Classifier are missing */
0185         return OcrEngine::ENG_DATA_MISSING;
0186     }
0187 }
0188 
0189 OcrEngine::EngineError KadmosDialog::findClassifierPath()
0190 {
0191     KStandardDirs stdDir;
0192     OcrEngine::EngineError err = OcrEngine::ENG_OK;
0193 
0194     const KConfigGroup grp = KSharedConfig::openConfig()->group(CFG_GROUP_KADMOS);
0195     m_customClassifierPath = grp.readPathEntry(CFG_KADMOS_CLASSIFIER_PATH, "");
0196 #if 0
0197     if (m_customClassifierPath == "NotFound") {
0198         /* Wants the classifiers from the standard kde paths */
0199         KMessageBox::error(0, i18n("The classifier files for KADMOS could not be found.\n"
0200                                    "OCR with KADMOS will not be possible.\n\n"
0201                                    "Change the OCR engine in the preferences dialog."),
0202                            i18n("Installation Error"));
0203     } else {
0204         m_classifierPath = customPath;
0205     }
0206 #endif
0207     return err;
0208 
0209 }
0210 
0211 OcrEngine::EngineError KadmosDialog::setupGui()
0212 {
0213 
0214     OcrEngine::EngineError err = OcrBaseDialog::setupGui();
0215 
0216     // setupPreprocessing( addVBoxPage(   i18n("Preprocessing")));
0217     // setupSegmentation(  addVBoxPage(   i18n("Segmentation")));
0218     // setupClassification( addVBoxPage( i18n("Classification")));
0219 
0220     /* continue page setup on the first page */
0221     QWidget *page = new QWidget(this);
0222     QVBoxLayout *pageVBoxLayout = new QVBoxLayout(page);
0223     pageVBoxLayout->setMargin(0);
0224 
0225     // FIXME: dynamic classifier reading.
0226 
0227     new QLabel(i18n("Please classify the font type and language of the text on the image:"), page);
0228     QWidget *locBox = new QWidget(page);
0229     QHBoxLayout *locBoxHBoxLayout = new QHBoxLayout(locBox);
0230     locBoxHBoxLayout->setMargin(0);
0231     pageVBoxLayout->addWidget(locBox);
0232     m_bbFont = new Q3ButtonGroup(1, Qt::Horizontal, i18n("Font Type Selection"), locBox);
0233     locBoxHBoxLayout->addWidget(m_bbFont);
0234 
0235     m_rbMachine = new QRadioButton(i18n("Machine print"), m_bbFont);
0236     m_rbHand    = new QRadioButton(i18n("Hand writing"),  m_bbFont);
0237     m_rbNorm    = new QRadioButton(i18n("Norm font"),     m_bbFont);
0238 
0239     m_gbLang = new Q3GroupBox(1, Qt::Horizontal, i18n("Country"), locBox);
0240     locBoxHBoxLayout->addWidget(m_gbLang);
0241 
0242     m_cbLang = new QComboBox(m_gbLang);
0243     m_cbLang->setItemText(m_cbLang->currentIndex(), KLocale::defaultCountry());
0244 
0245     connect(m_bbFont, &Q3ButtonGroup::clicked, this, &KadmosDialog::slFontChanged);
0246     m_rbMachine->setChecked(true);
0247 
0248     /* --- */
0249     QWidget *innerBox = new QWidget(page);
0250     QHBoxLayout *innerBoxHBoxLayout = new QHBoxLayout(innerBox);
0251     innerBoxHBoxLayout->setMargin(0);
0252     pageVBoxLayout->addWidget(innerBox);
0253     innerBoxHBoxLayout->setSpacing(KDialog::spacingHint());
0254 
0255     Q3ButtonGroup *cbGroup = new Q3ButtonGroup(1, Qt::Horizontal, i18n("OCR Modifier"), innerBox);
0256     innerBoxHBoxLayout->addWidget(cbGroup);
0257     Q_CHECK_PTR(cbGroup);
0258 
0259     m_cbNoise = new QCheckBox(i18n("Enable automatic noise reduction"), cbGroup);
0260     m_cbAutoscale = new QCheckBox(i18n("Enable automatic scaling"), cbGroup);
0261 
0262     addExtraSetupWidget(page);
0263 
0264     if (err != OcrEngine::ENG_OK) {
0265         enableFields(false);
0266         enableButton(User1, false);
0267     }
0268 
0269     if (m_ttfClassifier.count() == 0) {
0270         m_rbMachine->setEnabled(false);
0271     }
0272     if (m_handClassifier.count() == 0) {
0273         m_rbHand->setEnabled(false);
0274     }
0275     if (!m_haveNorm) {
0276         m_rbNorm->setEnabled(false);
0277     }
0278 
0279     if ((m_ttfClassifier.count() + m_handClassifier.count()) == 0 && ! m_haveNorm) {
0280         KMessageBox::error(0, i18n("The classifier files for KADMOS could not be found.\n"
0281                                    "OCR with KADMOS will not be possible.\n\n"
0282                                    "Change the OCR engine in the preferences dialog."),
0283                            i18n("Installation Error"));
0284         err = OcrEngine::ENG_BAD_SETUP;
0285     } else {
0286         slotFontChanged(0);    // Load machine print font language list
0287     }
0288 
0289     ocrShowInfo(QString());
0290     return err;
0291 }
0292 
0293 void KadmosDialog::slotFontChanged(int id)
0294 {
0295     m_cbLang->clear();
0296 
0297     const KConfigGroup grp = KSharedConfig::openConfig()->group(CFG_GROUP_KADMOS);
0298     m_customClassifierPath = grp.readPathEntry(CFG_KADMOS_CLASSIFIER_PATH, "");
0299 
0300     bool enable = true;
0301 
0302     if (id == 0) { /* Machine Print */
0303         m_cbLang->addItems(m_ttfClassifier);
0304     } else if (id == 1) { /* Hand Writing */
0305         m_cbLang->addItems(m_handClassifier);
0306     } else if (id == 2) { /* Norm Font */
0307         enable = false;
0308     }
0309     m_cbLang->setEnabled(enable);
0310 }
0311 
0312 void KadmosDialog::setupPreprocessing(QWidget *box)
0313 {
0314 }
0315 
0316 void KadmosDialog::setupSegmentation(QWidget *box)
0317 {
0318 }
0319 
0320 void KadmosDialog::setupClassification(QWidget *box)
0321 {
0322 }
0323 
0324 /*
0325  * returns the complete path of the classifier selected in the
0326  * GUI in the parameter path. The result value indicates if there
0327  * was one found.
0328  */
0329 
0330 bool KadmosDialog::getSelClassifier(QString &path) const
0331 {
0332     QString classifier = getSelClassifierName();
0333 
0334     QString cmplPath;
0335     /*
0336      * Search the complete path for the classifier file name
0337      * returned from the getSelClassifierName method
0338      */
0339     for (QStringList::ConstIterator it = m_classifierPath.begin();
0340             it != m_classifierPath.end(); ++it) {
0341         QFileInfo fi(*it);
0342         if (fi.fileName() == classifier) {
0343             cmplPath = *it;
0344             break;
0345         }
0346     }
0347 
0348     bool res = true;
0349 
0350     if (cmplPath.isEmpty()) {
0351         /* hm, no path was found */
0352         //qCDebug(OCR_LOG) << "Error: The entire path is empty";
0353         res = false;
0354     } else {
0355         /* Check if the classifier exists on the HD. If not, return an empty string */
0356         QFileInfo fi(cmplPath);
0357 
0358         if (res && ! fi.exists()) {
0359             //qCDebug(OCR_LOG) << "Classifier file does not exist";
0360             path = i18n("Classifier file %1 does not exist", classifier);
0361             res = false;
0362         }
0363 
0364         if (res && ! fi.isReadable()) {
0365             //qCDebug(OCR_LOG) << "Classifier file could not be read";
0366             path = i18n("Classifier file %1 is not readable", classifier);
0367             res = false;
0368         }
0369 
0370         if (res) {
0371             path = cmplPath;
0372         }
0373     }
0374     return res;
0375 }
0376 
0377 QString KadmosDialog::getSelClassifierName() const
0378 {
0379     QAbstractButton *butt = m_bbFont->selected();
0380 
0381     QString fType, rType;
0382 
0383     if (butt) {
0384         int fontTypeID = m_bbFont->id(butt);
0385         if (fontTypeID == 0) {
0386             fType = "ttf";
0387         } else if (fontTypeID == 1) {
0388             fType = "hand";
0389         } else if (fontTypeID == 2) {
0390             fType = "norm";
0391         } else {
0392             //qCDebug(OCR_LOG) << "Error: Wrong font type ID";
0393         }
0394     }
0395 
0396     /* Get the long text from the combo box */
0397     QString selLang = m_cbLang->currentText();
0398     QString trans;
0399     if (fType != "norm" && m_longCountry2short.contains(selLang)) {
0400         QString langType = m_longCountry2short[selLang];
0401         trans = fType + langType + ".rec";
0402     } else {
0403         if (selLang.endsWith(".rec")) {
0404             /* can be a undetected */
0405             trans = selLang;
0406         } else if (fType == "norm") {
0407             trans = "norm.rec";
0408         } else {
0409             //qCDebug(OCR_LOG) << "Error: Not a valid classifier";
0410         }
0411     }
0412     //qCDebug(OCR_LOG) << "Returning" << trans;
0413     return (trans);
0414 }
0415 
0416 bool KadmosDialog::getAutoScale()
0417 {
0418     return (m_cbAutoscale ? m_cbAutoscale->isChecked() : false);
0419 }
0420 
0421 bool KadmosDialog::getNoiseReduction()
0422 {
0423     return (m_cbNoise ? m_cbNoise->isChecked() : false);
0424 
0425 }
0426 
0427 KadmosDialog::~KadmosDialog()
0428 {
0429 
0430 }
0431 
0432 void KadmosDialog::slotWriteConfig()
0433 {
0434     //qCDebug(OCR_LOG);
0435 
0436     OcrBaseDialog::slotWriteConfig();
0437 
0438     //KConfig *conf = KSharedConfig::openConfig();
0439     // TODO: must be something to save here!
0440 }
0441 
0442 void KadmosDialog::enableFields(bool state)
0443 {
0444     m_cbNoise->setEnabled(state);
0445     m_cbAutoscale->setEnabled(state);
0446 
0447     m_bbFont->setEnabled(state);
0448     m_gbLang->setEnabled(state);
0449 }