File indexing completed on 2024-04-21 15:12:06

0001 /************************************************************************
0002  *                                  *
0003  *  This file is part of Kooka, a scanning/OCR application using    *
0004  *  Qt <http://www.qt.io> and KDE Frameworks <http://www.kde.org>.  *
0005  *                                  *
0006  *  Copyright (C) 2000-2016 Klaas Freitag <freitag@suse.de>     *
0007  *                          Jonathan Marten <jjm@keelhaul.me.uk>    *
0008  *                                  *
0009  *  Kooka is free software; you can redistribute it and/or modify it    *
0010  *  under the terms of the GNU Library General Public License as    *
0011  *  published by the Free Software Foundation and appearing in the  *
0012  *  file COPYING included in the packaging of this file;  either    *
0013  *  version 2 of the License, or (at your option) any later version.    *
0014  *                                  *
0015  *  As a special exception, permission is given to link this program    *
0016  *  with any version of the KADMOS OCR/ICR engine (a product of     *
0017  *  reRecognition GmbH, Kreuzlingen), and distribute the resulting  *
0018  *  executable without including the source code for KADMOS in the  *
0019  *  source distribution.                        *
0020  *                                  *
0021  *  This program is distributed in the hope that it will be useful, *
0022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of  *
0023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *
0024  *  GNU General Public License for more details.            *
0025  *                                  *
0026  *  You should have received a copy of the GNU General Public       *
0027  *  License along with this program;  see the file COPYING.  If     *
0028  *  not, see <http://www.gnu.org/licenses/>.                *
0029  *                                  *
0030  ************************************************************************/
0031 
0032 #include "prefspages.h"
0033 
0034 #include <qlayout.h>
0035 #include <qcheckbox.h>
0036 #include <qlabel.h>
0037 #include <qradiobutton.h>
0038 #include <qbuttongroup.h>
0039 #include <qgroupbox.h>
0040 #include <qcombobox.h>
0041 
0042 #include <klocalizedstring.h>
0043 #include <kmessagebox.h>
0044 #include <kurlrequester.h>
0045 #include <kseparator.h>
0046 #include <kconfigskeleton.h>
0047 
0048 #include "scansettings.h"
0049 #include "imagefilter.h"
0050 
0051 #include "kookapref.h"
0052 #include "kookagallery.h"
0053 #include "formatdialog.h"
0054 #include "thumbview.h"
0055 #include "pluginmanager.h"
0056 #include "abstractocrengine.h"
0057 #include "kookasettings.h"
0058 #include "kooka_logging.h"
0059 
0060 
0061 //  Abstract base
0062 
0063 KookaPrefsPage::KookaPrefsPage(KPageDialog *parent)
0064     : QWidget(parent)
0065 {
0066     mLayout = new QVBoxLayout(this);
0067 }
0068 
0069 //  "General" page
0070 
0071 KookaGeneralPage::KookaGeneralPage(KPageDialog *parent)
0072     : KookaPrefsPage(parent)
0073 {
0074     mLayout->addStretch(9);             // push down to bottom
0075 
0076     QGroupBox *gb = new QGroupBox(i18n("Hidden Messages"), this);
0077     QGridLayout *gl = new QGridLayout(gb);
0078 
0079     /* Enable messages and questions */
0080     QLabel *lab = new QLabel(i18n("Use this button to reenable all messages and questions which\nhave been hidden by using \"Don't ask me again\"."), gb);
0081     gl->addWidget(lab, 0, 0);
0082 
0083     mEnableMessagesButton = new QPushButton(i18n("Enable Messages/Questions"), gb);
0084     connect(mEnableMessagesButton, &QPushButton::clicked, this, &KookaGeneralPage::slotEnableWarnings);
0085     gl->addWidget(mEnableMessagesButton, 1, 0, Qt::AlignRight);
0086 
0087     mLayout->addWidget(gb);
0088 }
0089 
0090 void KookaGeneralPage::saveSettings()
0091 {
0092 }
0093 
0094 void KookaGeneralPage::defaultSettings()
0095 {
0096 }
0097 
0098 void KookaGeneralPage::slotEnableWarnings()
0099 {
0100     qCDebug(KOOKA_LOG);
0101 
0102     KMessageBox::enableAllMessages();
0103     FormatDialog::forgetRemembered();
0104     KSharedConfig::openConfig()->reparseConfiguration();
0105 
0106     mEnableMessagesButton->setEnabled(false);           // show this has been done
0107 }
0108 
0109 //  "Startup" page
0110 
0111 KookaStartupPage::KookaStartupPage(KPageDialog *parent)
0112     : KookaPrefsPage(parent)
0113 {
0114     /* Query for network scanner (Checkbox) */
0115     const KConfigSkeletonItem *item = ScanSettings::self()->startupOnlyLocalItem();
0116     Q_ASSERT(item!=nullptr);
0117     mNetQueryCheck = new QCheckBox(item->label(), this);
0118     mNetQueryCheck->setToolTip(item->toolTip());
0119     mLayout->addWidget(mNetQueryCheck);
0120 
0121     /* Show scanner selection box on startup (Checkbox) */
0122     item = ScanSettings::self()->startupSkipAskItem();
0123     Q_ASSERT(item!=nullptr);
0124     mSelectScannerCheck = new QCheckBox(item->label(), this);
0125     mSelectScannerCheck->setToolTip(item->toolTip());
0126     mLayout->addWidget(mSelectScannerCheck);
0127 
0128     /* Read startup image on startup (Checkbox) */
0129     item = KookaSettings::self()->startupReadImageItem();
0130     Q_ASSERT(item!=nullptr);
0131     mRestoreImageCheck = new QCheckBox(item->label(), this);
0132     mRestoreImageCheck->setToolTip(item->toolTip());
0133     mLayout->addWidget(mRestoreImageCheck);
0134 
0135     applySettings();
0136 }
0137 
0138 void KookaStartupPage::saveSettings()
0139 {
0140     ScanSettings::setStartupSkipAsk(!mSelectScannerCheck->isChecked());
0141     ScanSettings::setStartupOnlyLocal(!mNetQueryCheck->isChecked());
0142     ScanSettings::self()->save();
0143 
0144     KookaSettings::setStartupReadImage(mRestoreImageCheck->isChecked());
0145     KookaSettings::self()->save();
0146 }
0147 
0148 void KookaStartupPage::defaultSettings()
0149 {
0150     ScanSettings::self()->startupSkipAskItem()->setDefault();
0151     ScanSettings::self()->startupOnlyLocalItem()->setDefault();
0152     KookaSettings::self()->startupReadImageItem()->setDefault();
0153     applySettings();
0154 }
0155 
0156 
0157 void KookaStartupPage::applySettings()
0158 {
0159     mSelectScannerCheck->setChecked(!ScanSettings::startupSkipAsk());
0160     mNetQueryCheck->setChecked(!ScanSettings::startupOnlyLocal());
0161     mRestoreImageCheck->setChecked(KookaSettings::startupReadImage());
0162 }
0163 
0164 
0165 //  "Saving" page
0166 
0167 KookaSavingPage::KookaSavingPage(KPageDialog *parent)
0168     : KookaPrefsPage(parent)
0169 {
0170     const KConfigSkeletonItem *item = KookaSettings::self()->saverAskForFormatItem();
0171     Q_ASSERT(item!=nullptr);
0172     mAskSaveFormat = new QCheckBox(item->label(), this);
0173     mAskSaveFormat->setToolTip(item->toolTip());
0174     mLayout->addWidget(mAskSaveFormat);
0175 
0176     mLayout->addSpacing(2 * DialogBase::verticalSpacing());
0177 
0178     item = KookaSettings::self()->saverAskForFilenameItem();
0179     mAskFileName = new QCheckBox(item->label(), this);
0180     mAskFileName->setToolTip(item->toolTip());
0181     mLayout->addWidget(mAskFileName);
0182 
0183     QButtonGroup *bg = new QButtonGroup(this);
0184     QGridLayout *gl = new QGridLayout;
0185     gl->setVerticalSpacing(0);
0186     gl->setColumnMinimumWidth(0, 3*DialogBase::verticalSpacing());
0187 
0188     item = KookaSettings::self()->saverAskBeforeScanItem();
0189     Q_ASSERT(item!=nullptr);
0190     mAskBeforeScan = new QRadioButton(item->label(), this);
0191     mAskBeforeScan->setEnabled(mAskFileName->isChecked());
0192     mAskBeforeScan->setToolTip(item->toolTip());
0193     connect(mAskFileName, &QCheckBox::toggled, mAskBeforeScan, &QRadioButton::setEnabled);
0194     bg->addButton(mAskBeforeScan);
0195     gl->addWidget(mAskBeforeScan, 0, 1);
0196 
0197     item = KookaSettings::self()->saverAskAfterScanItem();
0198     Q_ASSERT(item!=nullptr);
0199     mAskAfterScan = new QRadioButton(item->label(), this);
0200     mAskAfterScan->setEnabled(mAskFileName->isChecked());
0201     mAskAfterScan->setToolTip(item->toolTip());
0202     connect(mAskFileName, &QCheckBox::toggled, mAskAfterScan, &QRadioButton::setEnabled);
0203     bg->addButton(mAskAfterScan);
0204     gl->addWidget(mAskAfterScan, 1, 1);
0205 
0206     mLayout->addLayout(gl);
0207 
0208     applySettings();
0209 }
0210 
0211 void KookaSavingPage::saveSettings()
0212 {
0213     KookaSettings::setSaverAskForFormat(mAskSaveFormat->isChecked());
0214     KookaSettings::setSaverAskForFilename(mAskFileName->isChecked());
0215     KookaSettings::setSaverAskBeforeScan(mAskBeforeScan->isChecked());
0216     KookaSettings::self()->save();
0217 }
0218 
0219 void KookaSavingPage::defaultSettings()
0220 {
0221     KookaSettings::self()->saverAskForFormatItem()->setDefault();
0222     KookaSettings::self()->saverAskForFilenameItem()->setDefault();
0223     KookaSettings::self()->saverAskBeforeScanItem()->setDefault();
0224     applySettings();
0225 }
0226 
0227 
0228 void KookaSavingPage::applySettings()
0229 {
0230     mAskSaveFormat->setChecked(KookaSettings::saverAskForFormat());
0231     mAskFileName->setChecked(KookaSettings::saverAskForFilename());
0232     bool askBefore = KookaSettings::saverAskBeforeScan();
0233     mAskBeforeScan->setChecked(askBefore);
0234     mAskAfterScan->setChecked(!askBefore);
0235 }
0236 
0237 //  "Gallery/Thumbnail" page
0238 
0239 KookaThumbnailPage::KookaThumbnailPage(KPageDialog *parent)
0240     : KookaPrefsPage(parent)
0241 {
0242     // Gallery options
0243     QGroupBox *gb = new QGroupBox(i18n("Image Gallery"), this);
0244     QGridLayout *gl = new QGridLayout(gb);
0245     gl->setColumnStretch(1, 1);
0246 
0247     /* Layout */
0248     const KConfigSkeletonItem *item = KookaSettings::self()->galleryLayoutItem();
0249     Q_ASSERT(item!=nullptr);
0250     QLabel *lab = new QLabel(item->label(), gb);
0251     lab->setToolTip(item->toolTip());
0252     gl->addWidget(lab, 0, 0, Qt::AlignRight);
0253 
0254     mGalleryLayoutCombo = new QComboBox(gb);
0255     mGalleryLayoutCombo->setToolTip(item->toolTip());
0256 // TODO: eliminate former enums
0257     mGalleryLayoutCombo->addItem(i18n("Not shown"), KookaSettings::RecentNone);
0258     mGalleryLayoutCombo->addItem(i18n("At top"), KookaSettings::RecentAtTop);
0259     mGalleryLayoutCombo->addItem(i18n("At bottom"), KookaSettings::RecentAtBottom);
0260 
0261     lab->setBuddy(mGalleryLayoutCombo);
0262     gl->addWidget(mGalleryLayoutCombo, 0, 1);
0263 
0264     /* Allow renaming */
0265     item = KookaSettings::self()->galleryAllowRenameItem();
0266     Q_ASSERT(item!=nullptr);
0267     mAllowRenameCheck = new QCheckBox(item->label(), gb);
0268     mAllowRenameCheck->setToolTip(item->toolTip());
0269     gl->addWidget(mAllowRenameCheck, 1, 0, 1, 2);
0270 
0271     mLayout->addWidget(gb);
0272 
0273     // Thumbnail View options
0274     gb = new QGroupBox(i18n("Thumbnail View"), this);
0275     gl = new QGridLayout(gb);
0276     gl->setColumnStretch(1, 1);
0277 
0278     // Do we want a background image?
0279     item = KookaSettings::self()->thumbnailCustomBackgroundItem();
0280     Q_ASSERT(item!=nullptr);
0281     mCustomBackgroundCheck = new QCheckBox(item->label(), this);
0282     mCustomBackgroundCheck->setToolTip(item->toolTip());
0283     connect(mCustomBackgroundCheck, &QCheckBox::toggled, this, &KookaThumbnailPage::slotCustomThumbBgndToggled);
0284     gl->addWidget(mCustomBackgroundCheck, 2, 0, 1, 2);
0285 
0286     /* Background image */
0287     item = KookaSettings::self()->thumbnailBackgroundPathItem();
0288     Q_ASSERT(item!=nullptr);
0289     lab = new QLabel(item->label(), this);
0290     lab->setToolTip(item->toolTip());
0291     gl->addWidget(lab, 3, 0, Qt::AlignRight);
0292 
0293     /* Image file selector */
0294     mTileSelector = new KUrlRequester(this);
0295     mTileSelector->setToolTip(item->toolTip());
0296     mTileSelector->setMode(KFile::File|KFile::ExistingOnly|KFile::LocalOnly);
0297     mTileSelector->setFilter(ImageFilter::kdeFilter(ImageFilter::Reading));
0298     gl->addWidget(mTileSelector, 3, 1);
0299     lab->setBuddy(mTileSelector);
0300 
0301     gl->setRowMinimumHeight(4, 2*DialogBase::verticalSpacing());
0302 
0303     /* Preview size */
0304     item = KookaSettings::self()->thumbnailPreviewSizeItem();
0305     Q_ASSERT(item!=nullptr);
0306     lab = new QLabel(item->label(), this);
0307     lab->setToolTip(item->toolTip());
0308     gl->addWidget(lab, 5, 0, Qt::AlignRight);
0309 
0310     mThumbSizeCombo = new QComboBox(this);
0311     mThumbSizeCombo->setToolTip(item->toolTip());
0312     mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeEnormous), KIconLoader::SizeEnormous);
0313     mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeHuge), KIconLoader::SizeHuge);
0314     mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeLarge), KIconLoader::SizeLarge);
0315     mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeMedium), KIconLoader::SizeMedium);
0316     mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeSmallMedium), KIconLoader::SizeSmallMedium);
0317     gl->addWidget(mThumbSizeCombo, 5, 1);
0318     lab->setBuddy(mThumbSizeCombo);
0319 
0320     mLayout->addWidget(gb);
0321 
0322     applySettings();
0323     slotCustomThumbBgndToggled(mCustomBackgroundCheck->isChecked());
0324 }
0325 
0326 void KookaThumbnailPage::saveSettings()
0327 {
0328     KookaSettings::setGalleryAllowRename(mAllowRenameCheck->isChecked());
0329     KookaSettings::setGalleryLayout(mGalleryLayoutCombo->itemData(mGalleryLayoutCombo->currentIndex()).toInt());
0330 
0331     KookaSettings::setThumbnailCustomBackground(mCustomBackgroundCheck->isChecked());
0332     KookaSettings::setThumbnailBackgroundPath(mTileSelector->url().url(QUrl::PreferLocalFile));
0333 
0334     int size = mThumbSizeCombo->itemData(mThumbSizeCombo->currentIndex()).toInt();
0335     if (size>0) KookaSettings::setThumbnailPreviewSize(size);
0336 
0337     KookaSettings::self()->save();
0338 }
0339 
0340 void KookaThumbnailPage::defaultSettings()
0341 {
0342     KookaSettings::self()->galleryLayoutItem()->setDefault();
0343     KookaSettings::self()->galleryAllowRenameItem()->setDefault();
0344     KookaSettings::self()->thumbnailCustomBackgroundItem()->setDefault();
0345     KookaSettings::self()->thumbnailBackgroundPathItem()->setDefault();
0346     KookaSettings::self()->thumbnailPreviewSizeItem()->setDefault();
0347 
0348     applySettings();
0349     slotCustomThumbBgndToggled(false);
0350 }
0351 
0352 
0353 void KookaThumbnailPage::applySettings()
0354 {
0355     mGalleryLayoutCombo->setCurrentIndex(KookaSettings::galleryLayout());
0356     mAllowRenameCheck->setChecked(KookaSettings::galleryAllowRename());
0357     mCustomBackgroundCheck->setChecked(KookaSettings::thumbnailCustomBackground());
0358 
0359     mTileSelector->setUrl(QUrl::fromLocalFile(KookaSettings::thumbnailBackgroundPath()));
0360 
0361     KIconLoader::StdSizes size = static_cast<KIconLoader::StdSizes>(KookaSettings::thumbnailPreviewSize());
0362     int sel = mThumbSizeCombo->findData(size, Qt::UserRole, Qt::MatchExactly);
0363     if (sel!=-1) mThumbSizeCombo->setCurrentIndex(sel);
0364     //else kWarning() << "Cannot find combo index for size" << size;
0365 }
0366 
0367 void KookaThumbnailPage::slotCustomThumbBgndToggled(bool state)
0368 {
0369     mTileSelector->setEnabled(state);
0370 }
0371 
0372 //  "OCR" page
0373 
0374 KookaOcrPage::KookaOcrPage(KPageDialog *parent)
0375     : KookaPrefsPage(parent)
0376 {
0377     QGridLayout *lay = new QGridLayout;
0378     lay->setColumnStretch(1, 9);
0379 
0380     const QString configuredEngine = KookaSettings::ocrEngineName();
0381     qCDebug(KOOKA_LOG) << "configured engine" << configuredEngine;
0382     int engineIndex = 0;
0383 
0384     mEngineCombo = new QComboBox(this);
0385     mOcrPlugins = PluginManager::self()->allPlugins(PluginManager::OcrPlugin);
0386     qCDebug(KOOKA_LOG) << "have" << mOcrPlugins.count() << "OCR plugins";
0387 
0388     mEngineCombo->addItem(i18n("None"), QString());
0389     for (QMap<QString,AbstractPluginInfo>::const_iterator it = mOcrPlugins.constBegin();
0390          it!=mOcrPlugins.constEnd(); ++it)
0391     {
0392         const AbstractPluginInfo &info = it.value();
0393         if (info.key==configuredEngine) engineIndex = mEngineCombo->count();
0394         mEngineCombo->addItem(QIcon::fromTheme(info.icon), info.name, info.key);
0395     }
0396 
0397     connect(mEngineCombo, QOverload<int>::of(&QComboBox::activated), this, &KookaOcrPage::slotEngineSelected);
0398     lay->addWidget(mEngineCombo, 0, 1);
0399 
0400     QLabel *lab = new QLabel(i18n("OCR Engine:"), this);
0401     lab->setBuddy(mEngineCombo);
0402     lay->addWidget(lab, 0, 0, Qt::AlignRight);
0403 
0404     lay->setRowMinimumHeight(1, 2*DialogBase::verticalSpacing());
0405 
0406     mOcrAdvancedButton = new QPushButton(i18n("OCR Engine Settings..."), this);
0407     connect(mOcrAdvancedButton, &QPushButton::clicked, this, &KookaOcrPage::slotOcrAdvanced);
0408     lay->addWidget(mOcrAdvancedButton, 2, 1, Qt::AlignRight);
0409 
0410     lay->setRowMinimumHeight(3, 2*DialogBase::verticalSpacing());
0411 
0412     KSeparator *sep = new KSeparator(Qt::Horizontal, this);
0413     lay->addWidget(sep, 4, 0, 1, 2);
0414     lay->setRowMinimumHeight(5, 2*DialogBase::verticalSpacing());
0415 
0416     mDescLabel = new QLabel("?", this);
0417     mDescLabel->setOpenExternalLinks(true);
0418     mDescLabel->setWordWrap(true);
0419     lay->addWidget(mDescLabel, 6, 0, 1, 2, Qt::AlignTop);
0420     lay->setRowStretch(6, 1);
0421 
0422     mLayout->addLayout(lay);
0423 
0424     mEngineCombo->setCurrentIndex(engineIndex);
0425     slotEngineSelected(mEngineCombo->currentIndex());
0426 }
0427 
0428 
0429 void KookaOcrPage::saveSettings()
0430 {
0431     KookaSettings::setOcrEngineName(mEngineCombo->currentData().toString());
0432 }
0433 
0434 
0435 void KookaOcrPage::defaultSettings()
0436 {
0437     mEngineCombo->setCurrentIndex(0);
0438     slotEngineSelected(mEngineCombo->currentIndex());
0439 }
0440 
0441 
0442 void KookaOcrPage::slotEngineSelected(int i)
0443 {
0444     const QString pluginKey = mEngineCombo->currentData().toString();
0445     qCDebug(KOOKA_LOG) << "selected" << pluginKey;
0446 
0447     QString msg;                    // description message
0448     bool enableAdvanced = false;            // for the moment, anyway
0449 
0450     if (pluginKey.isEmpty())                // no engine selected
0451     {
0452         msg = i18n("No OCR engine is selected. Select and configure one to be able to perform OCR.");
0453     }
0454     else                        // an engine is selected,
0455     {                           // try to load its plugin
0456         const AbstractPlugin *plugin = PluginManager::self()->loadPlugin(PluginManager::OcrPlugin, pluginKey);
0457         const AbstractOcrEngine *engine = qobject_cast<const AbstractOcrEngine *>(plugin);
0458         if (engine==nullptr)                // plugin not found
0459         {
0460             msg = i18n("Unknown engine '%1'.", pluginKey);
0461         }
0462         else
0463         {
0464             msg = engine->pluginInfo()->description;
0465             enableAdvanced = engine->hasAdvancedSettings();
0466         }
0467     }
0468 
0469     mDescLabel->setText(msg);               // show description text
0470     mOcrAdvancedButton->setEnabled(enableAdvanced); // enable button if applicable
0471 }
0472 
0473 
0474 void KookaOcrPage::slotOcrAdvanced()
0475 {
0476     AbstractPlugin *plugin = PluginManager::self()->currentPlugin(PluginManager::OcrPlugin);
0477     AbstractOcrEngine *engine = qobject_cast<AbstractOcrEngine *>(plugin);
0478     Q_ASSERT(engine!=nullptr);
0479     Q_ASSERT(engine->hasAdvancedSettings());
0480 
0481     engine->openAdvancedSettings();
0482 }