1 /************************************************************************
2 * *
3 * This file is part of Kooka, a scanning/OCR application using *
4 * Qt <http://www.qt.io> and KDE Frameworks <http://www.kde.org>. *
5 * *
6 * Copyright (C) 2000-2016 Klaas Freitag <freitag@suse.de> *
7 * Jonathan Marten <jjm@keelhaul.me.uk> *
8 * *
9 * Kooka is free software; you can redistribute it and/or modify it *
10 * under the terms of the GNU Library General Public License as *
11 * published by the Free Software Foundation and appearing in the *
12 * file COPYING included in the packaging of this file; either *
13 * version 2 of the License, or (at your option) any later version. *
14 * *
15 * As a special exception, permission is given to link this program *
16 * with any version of the KADMOS OCR/ICR engine (a product of *
17 * reRecognition GmbH, Kreuzlingen), and distribute the resulting *
18 * executable without including the source code for KADMOS in the *
19 * source distribution. *
20 * *
21 * This program is distributed in the hope that it will be useful, *
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
24 * GNU General Public License for more details. *
25 * *
26 * You should have received a copy of the GNU General Public *
27 * License along with this program; see the file COPYING. If *
28 * not, see <http://www.gnu.org/licenses/>. *
29 * *
30 ************************************************************************/
31
32 #include "prefspages.h"
33
34 #include <qlayout.h>
35 #include <qcheckbox.h>
36 #include <qlabel.h>
37 #include <qradiobutton.h>
38 #include <qbuttongroup.h>
39 #include <qgroupbox.h>
40 #include <qcombobox.h>
41 #include <qdebug.h>
42
43 #include <klocalizedstring.h>
44 #include <kmessagebox.h>
45 #include <kurlrequester.h>
46 #include <kseparator.h>
47 #include <kconfigskeleton.h>
48
49 #include "scansettings.h"
50 #include "imagefilter.h"
51
52 #include "kookapref.h"
53 #include "kookagallery.h"
54 #include "formatdialog.h"
55 #include "thumbview.h"
56 #include "pluginmanager.h"
57 #include "abstractocrengine.h"
58 #include "kookasettings.h"
59
60
61 // Abstract base
62
KookaPrefsPage(KPageDialog * parent)63 KookaPrefsPage::KookaPrefsPage(KPageDialog *parent)
64 : QWidget(parent)
65 {
66 mLayout = new QVBoxLayout(this);
67 }
68
69 // "General" page
70
KookaGeneralPage(KPageDialog * parent)71 KookaGeneralPage::KookaGeneralPage(KPageDialog *parent)
72 : KookaPrefsPage(parent)
73 {
74 mLayout->addStretch(9); // push down to bottom
75
76 QGroupBox *gb = new QGroupBox(i18n("Hidden Messages"), this);
77 QGridLayout *gl = new QGridLayout(gb);
78
79 /* Enable messages and questions */
80 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);
81 gl->addWidget(lab, 0, 0);
82
83 mEnableMessagesButton = new QPushButton(i18n("Enable Messages/Questions"), gb);
84 connect(mEnableMessagesButton, &QPushButton::clicked, this, &KookaGeneralPage::slotEnableWarnings);
85 gl->addWidget(mEnableMessagesButton, 1, 0, Qt::AlignRight);
86
87 mLayout->addWidget(gb);
88 }
89
saveSettings()90 void KookaGeneralPage::saveSettings()
91 {
92 }
93
defaultSettings()94 void KookaGeneralPage::defaultSettings()
95 {
96 }
97
slotEnableWarnings()98 void KookaGeneralPage::slotEnableWarnings()
99 {
100 //qDebug();
101
102 KMessageBox::enableAllMessages();
103 FormatDialog::forgetRemembered();
104 KSharedConfig::openConfig()->reparseConfiguration();
105
106 mEnableMessagesButton->setEnabled(false); // show this has been done
107 }
108
109 // "Startup" page
110
KookaStartupPage(KPageDialog * parent)111 KookaStartupPage::KookaStartupPage(KPageDialog *parent)
112 : KookaPrefsPage(parent)
113 {
114 /* Query for network scanner (Checkbox) */
115 const KConfigSkeletonItem *item = ScanSettings::self()->startupOnlyLocalItem();
116 Q_ASSERT(item!=nullptr);
117 mNetQueryCheck = new QCheckBox(item->label(), this);
118 mNetQueryCheck->setToolTip(item->toolTip());
119 mLayout->addWidget(mNetQueryCheck);
120
121 /* Show scanner selection box on startup (Checkbox) */
122 item = ScanSettings::self()->startupSkipAskItem();
123 Q_ASSERT(item!=nullptr);
124 mSelectScannerCheck = new QCheckBox(item->label(), this);
125 mSelectScannerCheck->setToolTip(item->toolTip());
126 mLayout->addWidget(mSelectScannerCheck);
127
128 /* Read startup image on startup (Checkbox) */
129 item = KookaSettings::self()->startupReadImageItem();
130 Q_ASSERT(item!=nullptr);
131 mRestoreImageCheck = new QCheckBox(item->label(), this);
132 mRestoreImageCheck->setToolTip(item->toolTip());
133 mLayout->addWidget(mRestoreImageCheck);
134
135 applySettings();
136 }
137
saveSettings()138 void KookaStartupPage::saveSettings()
139 {
140 ScanSettings::setStartupSkipAsk(!mSelectScannerCheck->isChecked());
141 ScanSettings::setStartupOnlyLocal(!mNetQueryCheck->isChecked());
142 ScanSettings::self()->save();
143
144 KookaSettings::setStartupReadImage(mRestoreImageCheck->isChecked());
145 KookaSettings::self()->save();
146 }
147
defaultSettings()148 void KookaStartupPage::defaultSettings()
149 {
150 ScanSettings::self()->startupSkipAskItem()->setDefault();
151 ScanSettings::self()->startupOnlyLocalItem()->setDefault();
152 KookaSettings::self()->startupReadImageItem()->setDefault();
153 applySettings();
154 }
155
156
applySettings()157 void KookaStartupPage::applySettings()
158 {
159 mSelectScannerCheck->setChecked(!ScanSettings::startupSkipAsk());
160 mNetQueryCheck->setChecked(!ScanSettings::startupOnlyLocal());
161 mRestoreImageCheck->setChecked(KookaSettings::startupReadImage());
162 }
163
164
165 // "Saving" page
166
KookaSavingPage(KPageDialog * parent)167 KookaSavingPage::KookaSavingPage(KPageDialog *parent)
168 : KookaPrefsPage(parent)
169 {
170 const KConfigSkeletonItem *item = KookaSettings::self()->saverAskForFormatItem();
171 Q_ASSERT(item!=nullptr);
172 mAskSaveFormat = new QCheckBox(item->label(), this);
173 mAskSaveFormat->setToolTip(item->toolTip());
174 mLayout->addWidget(mAskSaveFormat);
175
176 mLayout->addSpacing(2 * DialogBase::verticalSpacing());
177
178 item = KookaSettings::self()->saverAskForFilenameItem();
179 mAskFileName = new QCheckBox(item->label(), this);
180 mAskFileName->setToolTip(item->toolTip());
181 mLayout->addWidget(mAskFileName);
182
183 QButtonGroup *bg = new QButtonGroup(this);
184 QGridLayout *gl = new QGridLayout;
185 gl->setVerticalSpacing(0);
186 gl->setColumnMinimumWidth(0, 3*DialogBase::verticalSpacing());
187
188 item = KookaSettings::self()->saverAskBeforeScanItem();
189 Q_ASSERT(item!=nullptr);
190 mAskBeforeScan = new QRadioButton(item->label(), this);
191 mAskBeforeScan->setEnabled(mAskFileName->isChecked());
192 mAskBeforeScan->setToolTip(item->toolTip());
193 connect(mAskFileName, &QCheckBox::toggled, mAskBeforeScan, &QRadioButton::setEnabled);
194 bg->addButton(mAskBeforeScan);
195 gl->addWidget(mAskBeforeScan, 0, 1);
196
197 item = KookaSettings::self()->saverAskAfterScanItem();
198 Q_ASSERT(item!=nullptr);
199 mAskAfterScan = new QRadioButton(item->label(), this);
200 mAskAfterScan->setEnabled(mAskFileName->isChecked());
201 mAskAfterScan->setToolTip(item->toolTip());
202 connect(mAskFileName, &QCheckBox::toggled, mAskAfterScan, &QRadioButton::setEnabled);
203 bg->addButton(mAskAfterScan);
204 gl->addWidget(mAskAfterScan, 1, 1);
205
206 mLayout->addLayout(gl);
207
208 applySettings();
209 }
210
saveSettings()211 void KookaSavingPage::saveSettings()
212 {
213 KookaSettings::setSaverAskForFormat(mAskSaveFormat->isChecked());
214 KookaSettings::setSaverAskForFilename(mAskFileName->isChecked());
215 KookaSettings::setSaverAskBeforeScan(mAskBeforeScan->isChecked());
216 KookaSettings::self()->save();
217 }
218
defaultSettings()219 void KookaSavingPage::defaultSettings()
220 {
221 KookaSettings::self()->saverAskForFormatItem()->setDefault();
222 KookaSettings::self()->saverAskForFilenameItem()->setDefault();
223 KookaSettings::self()->saverAskBeforeScanItem()->setDefault();
224 applySettings();
225 }
226
227
applySettings()228 void KookaSavingPage::applySettings()
229 {
230 mAskSaveFormat->setChecked(KookaSettings::saverAskForFormat());
231 mAskFileName->setChecked(KookaSettings::saverAskForFilename());
232 bool askBefore = KookaSettings::saverAskBeforeScan();
233 mAskBeforeScan->setChecked(askBefore);
234 mAskAfterScan->setChecked(!askBefore);
235 }
236
237 // "Gallery/Thumbnail" page
238
KookaThumbnailPage(KPageDialog * parent)239 KookaThumbnailPage::KookaThumbnailPage(KPageDialog *parent)
240 : KookaPrefsPage(parent)
241 {
242 // Gallery options
243 QGroupBox *gb = new QGroupBox(i18n("Image Gallery"), this);
244 QGridLayout *gl = new QGridLayout(gb);
245 gl->setColumnStretch(1, 1);
246
247 /* Layout */
248 const KConfigSkeletonItem *item = KookaSettings::self()->galleryLayoutItem();
249 Q_ASSERT(item!=nullptr);
250 QLabel *lab = new QLabel(item->label(), gb);
251 lab->setToolTip(item->toolTip());
252 gl->addWidget(lab, 0, 0, Qt::AlignRight);
253
254 mGalleryLayoutCombo = new QComboBox(gb);
255 mGalleryLayoutCombo->setToolTip(item->toolTip());
256 // TODO: eliminate former enums
257 mGalleryLayoutCombo->addItem(i18n("Not shown"), KookaSettings::RecentNone);
258 mGalleryLayoutCombo->addItem(i18n("At top"), KookaSettings::RecentAtTop);
259 mGalleryLayoutCombo->addItem(i18n("At bottom"), KookaSettings::RecentAtBottom);
260
261 lab->setBuddy(mGalleryLayoutCombo);
262 gl->addWidget(mGalleryLayoutCombo, 0, 1);
263
264 /* Allow renaming */
265 item = KookaSettings::self()->galleryAllowRenameItem();
266 Q_ASSERT(item!=nullptr);
267 mAllowRenameCheck = new QCheckBox(item->label(), gb);
268 mAllowRenameCheck->setToolTip(item->toolTip());
269 gl->addWidget(mAllowRenameCheck, 1, 0, 1, 2);
270
271 mLayout->addWidget(gb);
272
273 // Thumbnail View options
274 gb = new QGroupBox(i18n("Thumbnail View"), this);
275 gl = new QGridLayout(gb);
276 gl->setColumnStretch(1, 1);
277
278 // Do we want a background image?
279 item = KookaSettings::self()->thumbnailCustomBackgroundItem();
280 Q_ASSERT(item!=nullptr);
281 mCustomBackgroundCheck = new QCheckBox(item->label(), this);
282 mCustomBackgroundCheck->setToolTip(item->toolTip());
283 connect(mCustomBackgroundCheck, &QCheckBox::toggled, this, &KookaThumbnailPage::slotCustomThumbBgndToggled);
284 gl->addWidget(mCustomBackgroundCheck, 2, 0, 1, 2);
285
286 /* Background image */
287 item = KookaSettings::self()->thumbnailBackgroundPathItem();
288 Q_ASSERT(item!=nullptr);
289 lab = new QLabel(item->label(), this);
290 lab->setToolTip(item->toolTip());
291 gl->addWidget(lab, 3, 0, Qt::AlignRight);
292
293 /* Image file selector */
294 mTileSelector = new KUrlRequester(this);
295 mTileSelector->setToolTip(item->toolTip());
296 mTileSelector->setMode(KFile::File|KFile::ExistingOnly|KFile::LocalOnly);
297 mTileSelector->setFilter(ImageFilter::kdeFilter(ImageFilter::Reading));
298 gl->addWidget(mTileSelector, 3, 1);
299 lab->setBuddy(mTileSelector);
300
301 gl->setRowMinimumHeight(4, 2*DialogBase::verticalSpacing());
302
303 /* Preview size */
304 item = KookaSettings::self()->thumbnailPreviewSizeItem();
305 Q_ASSERT(item!=nullptr);
306 lab = new QLabel(item->label(), this);
307 lab->setToolTip(item->toolTip());
308 gl->addWidget(lab, 5, 0, Qt::AlignRight);
309
310 mThumbSizeCombo = new QComboBox(this);
311 mThumbSizeCombo->setToolTip(item->toolTip());
312 mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeEnormous), KIconLoader::SizeEnormous);
313 mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeHuge), KIconLoader::SizeHuge);
314 mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeLarge), KIconLoader::SizeLarge);
315 mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeMedium), KIconLoader::SizeMedium);
316 mThumbSizeCombo->addItem(ThumbView::sizeName(KIconLoader::SizeSmallMedium), KIconLoader::SizeSmallMedium);
317 gl->addWidget(mThumbSizeCombo, 5, 1);
318 lab->setBuddy(mThumbSizeCombo);
319
320 mLayout->addWidget(gb);
321
322 applySettings();
323 slotCustomThumbBgndToggled(mCustomBackgroundCheck->isChecked());
324 }
325
saveSettings()326 void KookaThumbnailPage::saveSettings()
327 {
328 KookaSettings::setGalleryAllowRename(mAllowRenameCheck->isChecked());
329 KookaSettings::setGalleryLayout(mGalleryLayoutCombo->itemData(mGalleryLayoutCombo->currentIndex()).toInt());
330
331 KookaSettings::setThumbnailCustomBackground(mCustomBackgroundCheck->isChecked());
332 KookaSettings::setThumbnailBackgroundPath(mTileSelector->url().url(QUrl::PreferLocalFile));
333
334 int size = mThumbSizeCombo->itemData(mThumbSizeCombo->currentIndex()).toInt();
335 if (size>0) KookaSettings::setThumbnailPreviewSize(size);
336
337 KookaSettings::self()->save();
338 }
339
defaultSettings()340 void KookaThumbnailPage::defaultSettings()
341 {
342 KookaSettings::self()->galleryLayoutItem()->setDefault();
343 KookaSettings::self()->galleryAllowRenameItem()->setDefault();
344 KookaSettings::self()->thumbnailCustomBackgroundItem()->setDefault();
345 KookaSettings::self()->thumbnailBackgroundPathItem()->setDefault();
346 KookaSettings::self()->thumbnailPreviewSizeItem()->setDefault();
347
348 applySettings();
349 slotCustomThumbBgndToggled(false);
350 }
351
352
applySettings()353 void KookaThumbnailPage::applySettings()
354 {
355 mGalleryLayoutCombo->setCurrentIndex(KookaSettings::galleryLayout());
356 mAllowRenameCheck->setChecked(KookaSettings::galleryAllowRename());
357 mCustomBackgroundCheck->setChecked(KookaSettings::thumbnailCustomBackground());
358
359 mTileSelector->setUrl(QUrl::fromLocalFile(KookaSettings::thumbnailBackgroundPath()));
360
361 KIconLoader::StdSizes size = static_cast<KIconLoader::StdSizes>(KookaSettings::thumbnailPreviewSize());
362 int sel = mThumbSizeCombo->findData(size, Qt::UserRole, Qt::MatchExactly);
363 if (sel!=-1) mThumbSizeCombo->setCurrentIndex(sel);
364 //else kWarning() << "Cannot find combo index for size" << size;
365 }
366
slotCustomThumbBgndToggled(bool state)367 void KookaThumbnailPage::slotCustomThumbBgndToggled(bool state)
368 {
369 mTileSelector->setEnabled(state);
370 }
371
372 // "OCR" page
373
KookaOcrPage(KPageDialog * parent)374 KookaOcrPage::KookaOcrPage(KPageDialog *parent)
375 : KookaPrefsPage(parent)
376 {
377 QGridLayout *lay = new QGridLayout;
378 lay->setColumnStretch(1, 9);
379
380 const QString configuredEngine = KookaSettings::ocrEngineName();
381 qDebug() << "configured engine" << configuredEngine;
382 int engineIndex = 0;
383
384 mEngineCombo = new QComboBox(this);
385 mOcrPlugins = PluginManager::self()->allPlugins(PluginManager::OcrPlugin);
386 qDebug() << "have" << mOcrPlugins.count() << "OCR plugins";
387
388 mEngineCombo->addItem(i18n("None"), QString());
389 for (QMap<QString,AbstractPluginInfo>::const_iterator it = mOcrPlugins.constBegin();
390 it!=mOcrPlugins.constEnd(); ++it)
391 {
392 const AbstractPluginInfo &info = it.value();
393 if (info.key==configuredEngine) engineIndex = mEngineCombo->count();
394 mEngineCombo->addItem(QIcon::fromTheme(info.icon), info.name, info.key);
395 }
396
397 connect(mEngineCombo, QOverload<int>::of(&QComboBox::activated), this, &KookaOcrPage::slotEngineSelected);
398 lay->addWidget(mEngineCombo, 0, 1);
399
400 QLabel *lab = new QLabel(i18n("OCR Engine:"), this);
401 lab->setBuddy(mEngineCombo);
402 lay->addWidget(lab, 0, 0, Qt::AlignRight);
403
404 lay->setRowMinimumHeight(1, 2*DialogBase::verticalSpacing());
405
406 mOcrAdvancedButton = new QPushButton(i18n("OCR Engine Settings..."), this);
407 connect(mOcrAdvancedButton, &QPushButton::clicked, this, &KookaOcrPage::slotOcrAdvanced);
408 lay->addWidget(mOcrAdvancedButton, 2, 1, Qt::AlignRight);
409
410 lay->setRowMinimumHeight(3, 2*DialogBase::verticalSpacing());
411
412 KSeparator *sep = new KSeparator(Qt::Horizontal, this);
413 lay->addWidget(sep, 4, 0, 1, 2);
414 lay->setRowMinimumHeight(5, 2*DialogBase::verticalSpacing());
415
416 mDescLabel = new QLabel("?", this);
417 mDescLabel->setOpenExternalLinks(true);
418 mDescLabel->setWordWrap(true);
419 lay->addWidget(mDescLabel, 6, 0, 1, 2, Qt::AlignTop);
420 lay->setRowStretch(6, 1);
421
422 mLayout->addLayout(lay);
423
424 mEngineCombo->setCurrentIndex(engineIndex);
425 slotEngineSelected(mEngineCombo->currentIndex());
426 }
427
428
saveSettings()429 void KookaOcrPage::saveSettings()
430 {
431 KookaSettings::setOcrEngineName(mEngineCombo->currentData().toString());
432 }
433
434
defaultSettings()435 void KookaOcrPage::defaultSettings()
436 {
437 mEngineCombo->setCurrentIndex(0);
438 slotEngineSelected(mEngineCombo->currentIndex());
439 }
440
441
slotEngineSelected(int i)442 void KookaOcrPage::slotEngineSelected(int i)
443 {
444 const QString pluginKey = mEngineCombo->currentData().toString();
445 qDebug() << "selected" << pluginKey;
446
447 QString msg; // description message
448 bool enableAdvanced = false; // for the moment, anyway
449
450 if (pluginKey.isEmpty()) // no engine selected
451 {
452 msg = i18n("No OCR engine is selected. Select and configure one to be able to perform OCR.");
453 }
454 else // an engine is selected,
455 { // try to load its plugin
456 const AbstractPlugin *plugin = PluginManager::self()->loadPlugin(PluginManager::OcrPlugin, pluginKey);
457 const AbstractOcrEngine *engine = qobject_cast<const AbstractOcrEngine *>(plugin);
458 if (engine==nullptr) // plugin not found
459 {
460 msg = i18n("Unknown engine '%1'.", pluginKey);
461 }
462 else
463 {
464 msg = engine->pluginInfo()->description;
465 enableAdvanced = engine->hasAdvancedSettings();
466 }
467 }
468
469 mDescLabel->setText(msg); // show description text
470 mOcrAdvancedButton->setEnabled(enableAdvanced); // enable button if applicable
471 }
472
473
slotOcrAdvanced()474 void KookaOcrPage::slotOcrAdvanced()
475 {
476 AbstractPlugin *plugin = PluginManager::self()->currentPlugin(PluginManager::OcrPlugin);
477 AbstractOcrEngine *engine = qobject_cast<AbstractOcrEngine *>(plugin);
478 Q_ASSERT(engine!=nullptr);
479 Q_ASSERT(engine->hasAdvancedSettings());
480
481 engine->openAdvancedSettings();
482 }
483