File indexing completed on 2024-04-21 15:12:07
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) 2008-2016 Jonathan Marten <jjm@keelhaul.me.uk> * 0007 * * 0008 * Kooka is free software; you can redistribute it and/or modify it * 0009 * under the terms of the GNU Library General Public License as * 0010 * published by the Free Software Foundation and appearing in the * 0011 * file COPYING included in the packaging of this file; either * 0012 * version 2 of the License, or (at your option) any later version. * 0013 * * 0014 * As a special exception, permission is given to link this program * 0015 * with any version of the KADMOS OCR/ICR engine (a product of * 0016 * reRecognition GmbH, Kreuzlingen), and distribute the resulting * 0017 * executable without including the source code for KADMOS in the * 0018 * source distribution. * 0019 * * 0020 * This program is distributed in the hope that it will be useful, * 0021 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0023 * GNU General Public License for more details. * 0024 * * 0025 * You should have received a copy of the GNU General Public * 0026 * License along with this program; see the file COPYING. If * 0027 * not, see <http://www.gnu.org/licenses/>. * 0028 * * 0029 ************************************************************************/ 0030 0031 #include "scanpresetsdialog.h" 0032 0033 #include <qlabel.h> 0034 #include <qlayout.h> 0035 #include <qpushbutton.h> 0036 #include <qlistwidget.h> 0037 0038 #include <klocalizedstring.h> 0039 #include <kmessagebox.h> 0040 #include <kstandardguiitem.h> 0041 0042 extern "C" { 0043 #include <sane/saneopts.h> 0044 } 0045 0046 #include "kscandevice.h" 0047 #include "kscanoption.h" 0048 #include "kscanoptset.h" 0049 #include "kscancontrols.h" 0050 #include "scanicons.h" 0051 #include "newscanpresetdialog.h" 0052 #include "kooka_logging.h" 0053 0054 0055 // TODO: also associate an icon, default the "color"/"grey" etc 0056 0057 ScanPresetsDialog::ScanPresetsDialog(KScanDevice *scandev, QWidget *pnt) 0058 : DialogBase(pnt) 0059 { 0060 setObjectName("ScanPresetsDialog"); 0061 0062 setButtons(QDialogButtonBox::Close); 0063 setWindowTitle(i18n("Scan Presets")); 0064 0065 QWidget *w = new QWidget(this); 0066 QGridLayout *gl = new QGridLayout(w); 0067 0068 mParamsList = new QListWidget(w); 0069 mParamsList->setSelectionMode(QAbstractItemView::SingleSelection); 0070 mParamsList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 0071 mParamsList->setMinimumWidth(200); 0072 connect(mParamsList, &QListWidget::itemSelectionChanged, this, &ScanPresetsDialog::slotSelectionChanged); 0073 connect(mParamsList, &QListWidget::itemDoubleClicked, this, &ScanPresetsDialog::slotLoadAndClose); 0074 gl->addWidget(mParamsList, 1, 0, 5, 1); 0075 0076 QLabel *l = new QLabel(i18n("Saved scan preset sets:"), w); 0077 gl->addWidget(l, 0, 0, Qt::AlignLeft); 0078 l->setBuddy(mParamsList); 0079 0080 mLoadButton = new QPushButton(i18n("Select"), w); 0081 mLoadButton->setIcon(QIcon::fromTheme("dialog-ok-apply")); 0082 mLoadButton->setToolTip(i18n("Load the selected scan preset set to use as scanner settings")); 0083 connect(mLoadButton, &QPushButton::clicked, this, &ScanPresetsDialog::slotLoad); 0084 gl->addWidget(mLoadButton, 1, 2); 0085 0086 mSaveButton = new QPushButton(i18n("Save..."), w); 0087 mSaveButton->setIcon(QIcon::fromTheme("bookmark-new")); 0088 mSaveButton->setToolTip(i18n("Save the current scanner settings as a new scan preset set")); 0089 connect(mSaveButton, &QPushButton::clicked, this, &ScanPresetsDialog::slotSave); 0090 gl->addWidget(mSaveButton, 2, 2); 0091 0092 mDeleteButton = new QPushButton(w); 0093 KGuiItem::assign(mDeleteButton, KStandardGuiItem::del()); 0094 mDeleteButton->setToolTip(i18n("Delete the selected scan preset set")); 0095 connect(mDeleteButton, &QPushButton::clicked, this, &ScanPresetsDialog::slotDelete); 0096 gl->addWidget(mDeleteButton, 3, 2); 0097 0098 mEditButton = new QPushButton(i18n("Edit..."), w); 0099 mEditButton->setIcon(QIcon::fromTheme("document-edit")); 0100 mEditButton->setToolTip(i18n("Change the name or description of the selected scan preset set")); 0101 connect(mEditButton, &QPushButton::clicked, this, &ScanPresetsDialog::slotEdit); 0102 gl->addWidget(mEditButton, 4, 2); 0103 0104 gl->setRowStretch(5, 9); 0105 gl->setRowMinimumHeight(6, 2*DialogBase::verticalSpacing()); 0106 0107 gl->setColumnStretch(0, 9); 0108 gl->setColumnMinimumWidth(1, 2*DialogBase::horizontalSpacing()); 0109 0110 mDescLabel = new QLabel(w); 0111 gl->addWidget(mDescLabel, 7, 0, 1, 3); 0112 0113 mScanDevice = scandev; 0114 0115 setMainWidget(w); 0116 populateList(); 0117 slotSelectionChanged(); 0118 } 0119 0120 0121 void ScanPresetsDialog::populateList() 0122 { 0123 mParamsList->clear(); 0124 mSets = KScanOptSet::readList(); 0125 0126 for (KScanOptSet::StringMap::const_iterator it = mSets.constBegin(); it != mSets.constEnd(); ++it) 0127 { 0128 const QString &setName = it.key(); 0129 qCDebug(KOOKA_LOG) << "saveset" << setName; 0130 0131 KScanOptSet optSet(setName); 0132 optSet.loadConfig(); 0133 const QByteArray scanMode = optSet.value(SANE_NAME_SCAN_MODE); 0134 0135 mParamsList->addItem(new QListWidgetItem(ScanIcons::self()->icon(scanMode), setName)); 0136 } 0137 } 0138 0139 0140 void ScanPresetsDialog::slotSelectionChanged() 0141 { 0142 QString desc; 0143 bool enable = false; 0144 0145 QListWidgetItem *item = mParamsList->currentItem(); 0146 if (item == nullptr) desc = i18n("No preset set selected."); 0147 else // something getting selected 0148 { 0149 desc = mSets[item->text()]; 0150 enable = true; 0151 } 0152 0153 mDescLabel->setText(desc); 0154 mLoadButton->setEnabled(enable); 0155 mDeleteButton->setEnabled(enable); 0156 mEditButton->setEnabled(enable); 0157 0158 mLoadButton->setDefault(enable); 0159 buttonBox()->button(QDialogButtonBox::Close)->setDefault(!enable); 0160 } 0161 0162 0163 void ScanPresetsDialog::slotLoad() 0164 { 0165 QListWidgetItem *item = mParamsList->currentItem(); 0166 if (item == nullptr) return; 0167 0168 QString name = item->text(); 0169 qCDebug(KOOKA_LOG) << "set" << name; 0170 0171 KScanOptSet optSet(name); 0172 if (!optSet.loadConfig()) 0173 { 0174 qCWarning(KOOKA_LOG) << "Failed to load set" << name; 0175 return; 0176 } 0177 0178 mScanDevice->loadOptionSet(&optSet); 0179 mScanDevice->reloadAllOptions(); 0180 } 0181 0182 0183 void ScanPresetsDialog::slotLoadAndClose(QListWidgetItem *item) 0184 { 0185 if (item == nullptr) return; 0186 0187 qCDebug(KOOKA_LOG) << "set" << item->text(); 0188 mParamsList->setCurrentItem(item); 0189 slotLoad(); 0190 accept(); 0191 } 0192 0193 0194 void ScanPresetsDialog::slotSave() 0195 { 0196 QString name; 0197 QListWidgetItem *item = mParamsList->currentItem(); 0198 if (item != nullptr) name = item->text(); 0199 qCDebug(KOOKA_LOG) << "selected set" << name; 0200 0201 QString newdesc; 0202 if (mSets.contains(name)) newdesc = mSets[name]; 0203 else 0204 { 0205 const KScanOption *sm = mScanDevice->getExistingGuiElement(SANE_NAME_SCAN_MODE); 0206 const KScanOption *sr = mScanDevice->getExistingGuiElement(SANE_NAME_SCAN_RESOLUTION); 0207 if (sm != nullptr && sr != nullptr) 0208 { 0209 // See KScanCombo for explanation of how the translation works. 0210 QString scanMode = ki18n(sm->widget()->text().toLocal8Bit().constData()).toString("sane-backends"); 0211 if (scanMode.isEmpty()) scanMode = sm->get(); 0212 newdesc = i18nc("New set name, %1=scan mode, %2=resolution", "%1, %2 dpi", 0213 scanMode, sr->get().constData()); 0214 } 0215 } 0216 0217 NewScanPresetDialog d(name, newdesc, false, this); 0218 if (!d.exec()) return; 0219 0220 const QString newName = d.getName(); 0221 const QString newDesc = d.getDescription(); 0222 qCDebug(KOOKA_LOG) << "name" << newName << "desc" << newDesc; 0223 0224 KScanOptSet optSet(newName); 0225 mScanDevice->getCurrentOptions(&optSet); 0226 0227 optSet.saveConfig(mScanDevice->scannerBackendName(), newDesc); 0228 mSets[newName] = newDesc; 0229 0230 // TODO: why? 0231 mParamsList->setCurrentItem(nullptr); 0232 QList<QListWidgetItem *> found = mParamsList->findItems(newName, Qt::MatchFixedString | Qt::MatchCaseSensitive); 0233 if (found.isEmpty()) 0234 { 0235 const QByteArray scanMode = optSet.value(SANE_NAME_SCAN_MODE); 0236 mParamsList->addItem(new QListWidgetItem(ScanIcons::self()->icon(scanMode), newName)); 0237 item = mParamsList->item(mParamsList->count() - 1); 0238 } 0239 else item = found.first(); 0240 0241 mParamsList->setCurrentItem(item); 0242 slotSelectionChanged(); 0243 } 0244 0245 0246 void ScanPresetsDialog::slotEdit() 0247 { 0248 QListWidgetItem *item = mParamsList->currentItem(); 0249 if (item == nullptr) { 0250 return; 0251 } 0252 QString oldName = item->text(); 0253 qCDebug(KOOKA_LOG) << "selected set" << oldName; 0254 0255 NewScanPresetDialog d(oldName, mSets[oldName], true, this); 0256 if (!d.exec()) return; 0257 0258 const QString newName = d.getName(); 0259 const QString newDesc = d.getDescription(); 0260 if (newName==oldName && newDesc==mSets[oldName]) return; 0261 qCDebug(KOOKA_LOG) << "new name" << newName << "desc" << newDesc; 0262 0263 KScanOptSet optSet(oldName.toLocal8Bit()); 0264 if (!optSet.loadConfig()) { 0265 qCWarning(KOOKA_LOG) << "Failed to load set" << oldName; 0266 return; 0267 } 0268 0269 KScanOptSet::deleteSet(oldName); // do first, in case name not changed 0270 optSet.setSetName(newName); 0271 optSet.saveConfig(mScanDevice->scannerBackendName(), newDesc); 0272 0273 mSets.remove(oldName); // do first, ditto 0274 mSets[newName] = newDesc; 0275 0276 item->setText(newName); 0277 slotSelectionChanged(); // recalculate 'item', it may change 0278 } 0279 0280 0281 void ScanPresetsDialog::slotDelete() 0282 { 0283 QListWidgetItem *item = mParamsList->currentItem(); 0284 if (item == nullptr) return; 0285 0286 QString name = item->text(); 0287 qCDebug(KOOKA_LOG) << "set" << name; 0288 if (KMessageBox::warningContinueCancel(this, 0289 xi18nc("@info", "Do you really want to delete the set <resource>%1</resource>?", name), 0290 i18n("Delete Scan Preset Set"), 0291 KStandardGuiItem::del(), 0292 KStandardGuiItem::cancel(), 0293 "deleteSaveSet") != KMessageBox::Continue) return; 0294 0295 KScanOptSet::deleteSet(name); 0296 delete mParamsList->takeItem(mParamsList->row(item)); 0297 mParamsList->setCurrentItem(nullptr); // clear selection 0298 }