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 }