File indexing completed on 2024-04-21 15:12:02
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 "formatdialog.h" 0032 0033 #include <qlayout.h> 0034 #include <qlabel.h> 0035 #include <qcheckbox.h> 0036 #include <qcombobox.h> 0037 #include <qpushbutton.h> 0038 #include <qlineedit.h> 0039 #include <qlistwidget.h> 0040 #include <qicon.h> 0041 #include <qmimetype.h> 0042 #include <qmimedatabase.h> 0043 #include <qimagewriter.h> 0044 0045 #include <kseparator.h> 0046 #include <klocalizedstring.h> 0047 #include <kconfigskeleton.h> 0048 0049 #include "imageformat.h" 0050 #include "kookasettings.h" 0051 #include "kooka_logging.h" 0052 0053 0054 // The ImageType can be OR-ed here to make a set of possible formats 0055 Q_DECLARE_OPERATORS_FOR_FLAGS(ScanImage::ImageTypes) 0056 0057 // Information for a format. Static, so only POD allowed. 0058 struct FormatInfo { 0059 // A semicolon-separated list of MIME types that make up this format. 0060 const char *mime; 0061 // An I18N_NOOP()'ed help string for the format. 0062 const char *helpString; 0063 // An OR-ed set of image types that this format is recommended for. 0064 // ScanImage::None means that it is not recommended for any image type. 0065 ScanImage::ImageTypes recForTypes; 0066 // An OR-ed set of image types that this format can be used for. 0067 // ScanImage::None means that it can be used for any image type. 0068 ScanImage::ImageTypes okForTypes; 0069 }; 0070 0071 // Known formats with help text and compatibility recommendations 0072 static struct FormatInfo formats[] = 0073 { 0074 { 0075 "image/bmp", // BMP 0076 I18N_NOOP( 0077 "<b>Bitmap Picture</b> is a widely used format for images under MS Windows. \ 0078 It is suitable for color, grayscale and line art images.\ 0079 <p>This format is widely supported but is not recommended, use an open format \ 0080 instead."), 0081 ScanImage::None, 0082 ScanImage::None 0083 }, 0084 0085 { 0086 "image/x-portable-bitmap", // PBM 0087 I18N_NOOP( 0088 "<b>Portable Bitmap</b>, as used by Netpbm, is an uncompressed format for line art \ 0089 (bitmap) images. Only 1 bit per pixel depth is supported."), 0090 ScanImage::BlackWhite, 0091 ScanImage::BlackWhite 0092 }, 0093 0094 { 0095 "image/x-portable-graymap", // PGM 0096 I18N_NOOP( 0097 "<b>Portable Greymap</b>, as used by Netpbm, is an uncompressed format for grayscale \ 0098 images. Only 8 bit per pixel depth is supported."), 0099 ScanImage::Greyscale, 0100 ScanImage::Greyscale 0101 }, 0102 0103 { 0104 "image/x-portable-pixmap", // PPM 0105 I18N_NOOP( 0106 "<b>Portable Pixmap</b>, as used by Netpbm, is an uncompressed format for full color \ 0107 images. Only 24 bit per pixel RGB is supported."), 0108 ScanImage::LowColour | ScanImage::HighColour, 0109 ScanImage::LowColour | ScanImage::HighColour 0110 }, 0111 0112 { 0113 "image/x-pcx;image/vnd.zbrush.pcx", // PCX 0114 I18N_NOOP( 0115 "<b>PCX</b> is a lossless compressed format which is often supported by PC imaging \ 0116 applications, although it is rather old and unsophisticated. It is suitable for \ 0117 color and grayscale images.\ 0118 <p>This format is not recommended, use an open format instead."), 0119 ScanImage::None, 0120 ScanImage::None 0121 }, 0122 0123 { 0124 "image/x-xbitmap", // XBM 0125 I18N_NOOP( 0126 "<b>X Bitmap</b> is often used by the X Window System to store cursor and icon bitmaps.\ 0127 <p>Unless required for this purpose, use a general purpose format instead."), 0128 ScanImage::None, 0129 ScanImage::BlackWhite 0130 }, 0131 0132 { 0133 "image/x-xpixmap", // XPM 0134 I18N_NOOP( 0135 "<b>X Pixmap</b> is often used by the X Window System for color icons and other images.\ 0136 <p>Unless required for this purpose, use a general purpose format instead."), 0137 ScanImage::None, 0138 ScanImage::LowColour | ScanImage::HighColour 0139 }, 0140 0141 { 0142 "image/png", // PNG 0143 I18N_NOOP( 0144 "<b>Portable Network Graphics</b> is a lossless compressed format designed to be \ 0145 portable and extensible. It is suitable for any type of color or grayscale images, \ 0146 indexed or true color.\ 0147 <p>PNG is an open format which is widely supported."), 0148 ScanImage::BlackWhite | ScanImage::LowColour | ScanImage::Greyscale | ScanImage::HighColour, 0149 ScanImage::None 0150 }, 0151 0152 { 0153 "image/jpeg", // JPEG JPG 0154 I18N_NOOP( 0155 "<b>JPEG</b> is a compressed format suitable for true color or grayscale images. \ 0156 It is a lossy format, so it is not recommended for archiving or for repeated loading \ 0157 and saving.\ 0158 <p>This is an open format which is widely supported."), 0159 ScanImage::HighColour | ScanImage::Greyscale, 0160 ScanImage::LowColour | ScanImage::Greyscale | ScanImage::HighColour 0161 }, 0162 0163 { 0164 "image/jp2", // JP2 0165 I18N_NOOP( 0166 "<b>JPEG 2000</b> was intended as an update to the JPEG format, with the option of \ 0167 lossless compression, but so far is not widely supported. It is suitable for true \ 0168 color or grayscale images."), 0169 ScanImage::None, 0170 ScanImage::LowColour | ScanImage::Greyscale | ScanImage::HighColour 0171 }, 0172 0173 { 0174 "image/x-eps", // EPS EPSF EPSI 0175 I18N_NOOP( 0176 "<b>Encapsulated PostScript</b> is derived from the PostScript™ \ 0177 page description language. Use this format for importing into other \ 0178 applications, or to use with (e.g.) TeX."), 0179 ScanImage::None, 0180 ScanImage::None 0181 }, 0182 0183 { 0184 "image/x-tga", // TGA 0185 I18N_NOOP( 0186 "<b>Truevision Targa</b> can store full color images with an alpha channel, and is \ 0187 used extensively by animation and video applications.\ 0188 <p>This format is not recommended, use an open format instead."), 0189 ScanImage::None, 0190 ScanImage::LowColour | ScanImage::Greyscale | ScanImage::HighColour 0191 }, 0192 0193 { 0194 "image/gif", // GIF 0195 I18N_NOOP( // writing may not be supported 0196 "<b>Graphics Interchange Format</b> is a popular but patent-encumbered format often \ 0197 used for web graphics. It uses lossless compression with up to 256 colors and \ 0198 optional transparency.\ 0199 <p>For legal reasons this format is not recommended, use an open format instead."), 0200 ScanImage::None, 0201 ScanImage::LowColour | ScanImage::Greyscale 0202 }, 0203 0204 { 0205 "image/tiff", // TIF TIFF 0206 I18N_NOOP( // writing may not be supported 0207 "<b>Tagged Image File Format</b> is a versatile and extensible file format widely \ 0208 supported by imaging and publishing applications. It supports indexed and true color \ 0209 images with alpha transparency.\ 0210 <p>Because there are many variations, there may sometimes be compatibility problems. \ 0211 Unless required for use with other applications, use an open format instead."), 0212 ScanImage::BlackWhite | ScanImage::LowColour | ScanImage::Greyscale | ScanImage::HighColour, 0213 ScanImage::None 0214 }, 0215 0216 { 0217 "video/x-mng", // MNG 0218 I18N_NOOP( 0219 "<b>Multiple-image Network Graphics</b> is derived from the PNG standard and is \ 0220 intended for animated images. It is an open format suitable for all types of \ 0221 images.\ 0222 <p>Images produced by a scanner will not be animated, so unless specifically \ 0223 required for use with other applications use PNG instead."), 0224 ScanImage::None, 0225 ScanImage::None 0226 }, 0227 0228 { 0229 "image/x-sgi", // SGI 0230 I18N_NOOP( 0231 "This is the <b>Silicon Graphics</b> native image file format, supporting 24 bit \ 0232 true color images with optional lossless compression.\ 0233 <p>Unless specifically required, use an open format instead."), 0234 ScanImage::None, 0235 ScanImage::LowColour | ScanImage::HighColour 0236 }, 0237 0238 { 0239 "image/vnd.wap.wbmp", // WBMP 0240 I18N_NOOP( 0241 "<b>Wireless Bitmap</b> is a monochrome bitmap format optimised \ 0242 for WAP mobile devices. It supports black and white bitmaps only.\ 0243 <p>Unless specifically required, use an general purpose format instead."), 0244 ScanImage::None, 0245 ScanImage::BlackWhite 0246 }, 0247 0248 { 0249 "image/webp", // WEBP 0250 I18N_NOOP( 0251 "<b>WebP</b> is intended to be an open standard for true colour \ 0252 images with optional transparency. It is widely supported by modern \ 0253 web browsers and graphics software.\ 0254 <p>Various compression methods, both lossy and lossless, are supported. \ 0255 Lossy compression is not recommended for archiving or for repeated loading \ 0256 and saving."), 0257 ScanImage::HighColour | ScanImage::Greyscale, 0258 ScanImage::LowColour | ScanImage::Greyscale | ScanImage::HighColour 0259 }, 0260 0261 { nullptr, nullptr, ScanImage::None, ScanImage::None } 0262 }; 0263 0264 static QString sLastFormat; // format last used, whether 0265 // remembered or not 0266 0267 FormatDialog::FormatDialog(QWidget *parent, ScanImage::ImageType type, 0268 bool askForFormat, const ImageFormat &format, 0269 bool askForFilename, const QString &filename) 0270 : DialogBase(parent), 0271 mFormat(format), // save these to return, if 0272 mFilename(filename) // they are not requested 0273 { 0274 setObjectName("FormatDialog"); 0275 0276 setModal(true); 0277 // KDE4 buttons: Ok Cancel User1=SelectFormat 0278 // KF5 buttons: Ok Cancel Yes=SelectFormat 0279 setButtons(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Yes); 0280 setWindowTitle(askForFormat ? i18n("Save Assistant") : i18n("Save Scan")); 0281 0282 QWidget *page = new QWidget(this); 0283 setMainWidget(page); 0284 0285 mHelpLabel = nullptr; 0286 mSubformatCombo = nullptr; 0287 mFormatList = nullptr; 0288 mSubformatLabel = nullptr; 0289 mDontAskCheck = nullptr; 0290 mRecOnlyCheck = nullptr; 0291 mExtensionLabel = nullptr; 0292 mFilenameEdit = nullptr; 0293 0294 if (!mFormat.isValid()) askForFormat = true; // must ask if none 0295 mWantAssistant = false; 0296 0297 QGridLayout *gl = new QGridLayout(page); 0298 gl->setMargin(0); 0299 int row = 0; 0300 0301 QLabel *l1; 0302 KSeparator *sep; 0303 0304 if (askForFormat) // format selector section 0305 { 0306 l1 = new QLabel(xi18nc("@info", "Select a format to save the scanned image.<nl/>This is a <emphasis strong=\"1\">%1</emphasis>.", 0307 ImgSaver::picTypeAsString(type)), page); 0308 gl->addWidget(l1, row, 0, 1, 3); 0309 ++row; 0310 0311 sep = new KSeparator(Qt::Horizontal, page); 0312 gl->addWidget(sep, row, 0, 1, 3); 0313 ++row; 0314 0315 // Insert scrolled list for formats 0316 l1 = new QLabel(i18n("File format:"), page); 0317 gl->addWidget(l1, row, 0, Qt::AlignLeft); 0318 0319 mFormatList = new QListWidget(page); 0320 // The list box is filled later. 0321 0322 mImageType = type; 0323 connect(mFormatList, &QListWidget::currentItemChanged, this, &FormatDialog::formatSelected); 0324 l1->setBuddy(mFormatList); 0325 gl->addWidget(mFormatList, row + 1, 0); 0326 gl->setRowStretch(row + 1, 1); 0327 0328 // Insert label for help text 0329 mHelpLabel = new QLabel(page); 0330 mHelpLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); 0331 mHelpLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); 0332 mHelpLabel->setMinimumSize(230, 200); 0333 mHelpLabel->setWordWrap(true); 0334 mHelpLabel->setMargin(4); 0335 gl->addWidget(mHelpLabel, row, 1, 4, 2); 0336 0337 // Insert selection box for subformat 0338 mSubformatLabel = new QLabel(i18n("Image sub-format:"), page); 0339 mSubformatLabel->setEnabled(false); 0340 gl->addWidget(mSubformatLabel, row + 2, 0, Qt::AlignLeft); 0341 0342 mSubformatCombo = new QComboBox(page); 0343 mSubformatCombo->setEnabled(false); // not yet implemented 0344 gl->addWidget(mSubformatCombo, row + 3, 0); 0345 mSubformatLabel->setBuddy(mSubformatCombo); 0346 row += 4; 0347 0348 sep = new KSeparator(Qt::Horizontal, page); 0349 gl->addWidget(sep, row, 0, 1, 3); 0350 ++row; 0351 0352 // Checkbox to store setting 0353 const KConfigSkeletonItem *ski = KookaSettings::self()->saverOnlyRecommendedTypesItem(); 0354 Q_ASSERT(ski!=nullptr); 0355 mRecOnlyCheck = new QCheckBox(ski->label(), page); 0356 mRecOnlyCheck->setToolTip(ski->toolTip()); 0357 mRecOnlyCheck->setChecked(KookaSettings::saverOnlyRecommendedTypes()); 0358 connect(mRecOnlyCheck, &QCheckBox::toggled, this, &FormatDialog::buildFormatList); 0359 gl->addWidget(mRecOnlyCheck, row, 0, 1, 3, Qt::AlignLeft); 0360 ++row; 0361 0362 ski = KookaSettings::self()->saverAlwaysUseFormatItem(); 0363 Q_ASSERT(ski!=nullptr); 0364 mDontAskCheck = new QCheckBox(ski->label(), page); 0365 mDontAskCheck->setToolTip(ski->toolTip()); 0366 gl->addWidget(mDontAskCheck, row, 0, 1, 3, Qt::AlignLeft); 0367 ++row; 0368 0369 buildFormatList(mRecOnlyCheck->isChecked()); // now have this setting 0370 // don't want this button 0371 buttonBox()->button(QDialogButtonBox::Yes)->setVisible(false); 0372 } 0373 0374 gl->setColumnStretch(1, 1); 0375 gl->setColumnMinimumWidth(1, horizontalSpacing()); 0376 0377 if (askForFormat && askForFilename) { 0378 sep = new KSeparator(Qt::Horizontal, page); 0379 gl->addWidget(sep, row, 0, 1, 3); 0380 ++row; 0381 } 0382 0383 if (askForFilename) { // file name section 0384 l1 = new QLabel(i18n("File name:"), page); 0385 gl->addWidget(l1, row, 0, 1, 3); 0386 ++row; 0387 0388 mFilenameEdit = new QLineEdit(filename, page); 0389 connect(mFilenameEdit, &QLineEdit::textChanged, this, &FormatDialog::checkValid); 0390 l1->setBuddy(mFilenameEdit); 0391 gl->addWidget(mFilenameEdit, row, 0, 1, 2); 0392 0393 mExtensionLabel = new QLabel("", page); 0394 gl->addWidget(mExtensionLabel, row, 2, Qt::AlignLeft); 0395 ++row; 0396 0397 if (!askForFormat) { 0398 buttonBox()->button(QDialogButtonBox::Yes)->setText(i18n("Select Format...")); 0399 } 0400 } 0401 0402 if (mFormatList != nullptr) // have the format selector 0403 { 0404 setSelectedFormat(format); // preselect the remembered format 0405 } 0406 else // no format selector, but 0407 { // asking for a file name 0408 showExtension(format); // show extension it will have 0409 } 0410 0411 connect(buttonBox()->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormatDialog::slotOk); 0412 connect(buttonBox()->button(QDialogButtonBox::Yes), &QPushButton::clicked, this, &FormatDialog::slotUser1); 0413 } 0414 0415 void FormatDialog::showEvent(QShowEvent *ev) 0416 { 0417 DialogBase::showEvent(ev); 0418 0419 if (mFilenameEdit != nullptr) { // asking for a file name 0420 mFilenameEdit->setFocus(); // set focus to that 0421 mFilenameEdit->selectAll(); // highlight for editing 0422 } 0423 } 0424 0425 void FormatDialog::showExtension(const ImageFormat &format) 0426 { 0427 if (mExtensionLabel == nullptr) return; // not showing this 0428 mExtensionLabel->setText("." + format.extension()); // show extension it will have 0429 } 0430 0431 void FormatDialog::formatSelected(QListWidgetItem *item) 0432 { 0433 if (mHelpLabel == nullptr) return; // not showing this 0434 0435 if (item == nullptr) { // nothing is selected 0436 mHelpLabel->setText(i18n("No format selected.")); 0437 setButtonEnabled(QDialogButtonBox::Ok, false); 0438 0439 mFormatList->clearSelection(); 0440 if (mExtensionLabel != nullptr) { 0441 mExtensionLabel->setText(".???"); 0442 } 0443 return; 0444 } 0445 0446 mFormatList->setCurrentItem(item); // focus highlight -> select 0447 0448 // Locate the help text for the format 0449 const char *helptxt = nullptr; 0450 const QByteArray mimename = item->data(Qt::UserRole).toByteArray(); 0451 for (const FormatInfo *ip = &formats[0]; ip->mime!=nullptr; ++ip) 0452 { 0453 const QList<QByteArray> mimetypes = QByteArray(ip->mime).split(';'); 0454 if (mimetypes.contains(mimename)) 0455 { 0456 helptxt = ip->helpString; 0457 break; 0458 } 0459 } 0460 0461 QMimeDatabase db; 0462 QMimeType mime = db.mimeTypeForName(mimename); 0463 ImageFormat format = ImageFormat::formatForMime(mime); 0464 qCDebug(KOOKA_LOG) << "MIME" << mimename << "format" << format; 0465 0466 if (helptxt != nullptr) { // found some help text 0467 mHelpLabel->setText(i18n(helptxt)); // set the hint 0468 check_subformat(format); // and check subformats 0469 } else { 0470 mHelpLabel->setText(i18n("No information is available for this format.")); 0471 } 0472 0473 if (mDontAskCheck != nullptr) { 0474 mDontAskCheck->setChecked(ImgSaver::isRememberedFormat(mImageType, format)); 0475 } 0476 0477 showExtension(format); 0478 checkValid(); 0479 } 0480 0481 // TODO: implement subtypes 0482 void FormatDialog::check_subformat(const ImageFormat &format) 0483 { 0484 if (mSubformatCombo == nullptr) return; // not showing this 0485 0486 mSubformatCombo->setEnabled(false); // not yet implemented 0487 mSubformatLabel->setEnabled(false); 0488 } 0489 0490 void FormatDialog::setSelectedFormat(const ImageFormat &format) 0491 { 0492 if (mFormatList == nullptr) return; // not showing this 0493 0494 if (format.isValid()) // valid format to select 0495 { 0496 const QMimeType mime = format.mime(); 0497 if (!mime.isValid()) return; 0498 0499 for (int i = 0; i < mFormatList->count(); ++i) { 0500 QListWidgetItem *item = mFormatList->item(i); 0501 if (item == nullptr) { 0502 continue; 0503 } 0504 QString mimename = item->data(Qt::UserRole).toString(); 0505 if (mime.inherits(mimename)) { 0506 mFormatList->setCurrentItem(item); 0507 return; 0508 } 0509 } 0510 } 0511 0512 // If that selected nothing, then select the last-used format (regardless 0513 // of the "always use" option setting). The last-used format is saved 0514 // in getFormat() for that purpose. This helps when scanning a series of 0515 // similar images yet where the user doesn't want to permanently save the 0516 // format for some reason. 0517 // 0518 // This is safe if the last-used format is not applicable to and so is not 0519 // displayed for the current image type - it just does nothing. 0520 if (!sLastFormat.isEmpty()) { 0521 for (int i = 0; i < mFormatList->count(); ++i) { 0522 QListWidgetItem *item = mFormatList->item(i); 0523 if (item == nullptr) { 0524 continue; 0525 } 0526 QString mimename = item->data(Qt::UserRole).toString(); 0527 // We know the MIME name is canonical here, so can use string compare 0528 if (mimename == sLastFormat) { 0529 mFormatList->setCurrentItem(item); 0530 return; 0531 } 0532 } 0533 } 0534 } 0535 0536 ImageFormat FormatDialog::getFormat() const 0537 { 0538 if (mFormatList == nullptr) return (mFormat); // no UI for this 0539 0540 QMimeDatabase db; 0541 const QListWidgetItem *item = mFormatList->currentItem(); 0542 if (item != nullptr) { 0543 QString mimename = item->data(Qt::UserRole).toString(); 0544 const QMimeType mime = db.mimeTypeForName(mimename); 0545 if (mime.isValid()) { 0546 sLastFormat = mime.name(); 0547 return (ImageFormat::formatForMime(mime)); 0548 } 0549 } 0550 0551 return (ImageFormat("PNG")); // a sensible default 0552 } 0553 0554 QString FormatDialog::getFilename() const 0555 { 0556 if (mFilenameEdit == nullptr) return (mFilename); // no UI for this 0557 return (mFilenameEdit->text()); 0558 } 0559 0560 QByteArray FormatDialog::getSubFormat() const 0561 { 0562 return (""); // Not supported yet... 0563 } 0564 0565 void FormatDialog::checkValid() 0566 { 0567 bool ok = true; // so far, anyway 0568 0569 if (mFormatList != nullptr && mFormatList->selectedItems().count() == 0) ok = false; 0570 if (mFilenameEdit != nullptr && mFilenameEdit->text().isEmpty()) ok = false; 0571 setButtonEnabled(QDialogButtonBox::Ok, ok); 0572 } 0573 0574 0575 static const FormatInfo *findKnownFormat(const QMimeType &mime) 0576 { 0577 for (const FormatInfo *fi = &formats[0]; fi->mime!=nullptr; ++fi) 0578 { // search for format info 0579 const QList<QByteArray> mimetypes = QByteArray(fi->mime).split(';'); 0580 for (const QByteArray &mimetype : mimetypes) 0581 { 0582 if (mime.inherits(mimetype)) return (fi); // matching that MIME type 0583 } 0584 } 0585 0586 return (nullptr); // nothing found 0587 } 0588 0589 0590 void FormatDialog::buildFormatList(bool recOnly) 0591 { 0592 if (mFormatList == nullptr) return; // not showing this 0593 qCDebug(KOOKA_LOG) << "recOnly" << recOnly << "for type" << mImageType; 0594 0595 mFormatList->clear(); 0596 const QList<QMimeType> *mimeTypes = ImageFormat::mimeTypes(); 0597 for (const QMimeType &mime : qAsConst(*mimeTypes)) // for all known MIME types 0598 { 0599 const FormatInfo *fi = findKnownFormat(mime); // look for format information 0600 if (fi==nullptr) // nothing for that MIME type 0601 { 0602 if (recOnly) continue; // never show for recommended 0603 } // but always show otherwise 0604 else 0605 { 0606 ScanImage::ImageTypes okTypes = fi->okForTypes; 0607 if (okTypes!=0) // format has allowed types 0608 { 0609 if (!(okTypes & mImageType)) continue; // but not for this image type 0610 } 0611 0612 if (recOnly) // want only recommended types 0613 { 0614 if (!(fi->recForTypes & mImageType)) // check for recommended format 0615 { 0616 continue; // not for this image type 0617 } 0618 } 0619 } 0620 0621 // add format to list 0622 QListWidgetItem *item = new QListWidgetItem(QIcon::fromTheme(mime.iconName()), 0623 mime.comment(), mFormatList); 0624 // Not sure whether a QMimeType can safely be stored in a 0625 // QVariant, so storing the MIME type name instead. 0626 item->setData(Qt::UserRole, mime.name()); 0627 mFormatList->addItem(item); 0628 } 0629 0630 formatSelected(nullptr); // selection has been cleared 0631 } 0632 0633 void FormatDialog::slotOk() 0634 { 0635 if (mRecOnlyCheck != nullptr) { // have UI for this 0636 KookaSettings::setSaverOnlyRecommendedTypes(mRecOnlyCheck->isChecked()); 0637 KookaSettings::self()->save(); // save state of this option 0638 } 0639 } 0640 0641 void FormatDialog::slotUser1() 0642 { 0643 mWantAssistant = true; 0644 accept(); 0645 } 0646 0647 0648 /* static */ void FormatDialog::forgetRemembered() 0649 { 0650 const KConfigSkeletonItem *ski = KookaSettings::self()->saverAlwaysUseFormatItem(); 0651 Q_ASSERT(ski!=nullptr); 0652 KConfigGroup grp = KookaSettings::self()->config()->group(ski->group()); 0653 grp.deleteGroup(); 0654 0655 KookaSettings::self()->save(); // ensure the config is saved 0656 KookaSettings::self()->read(); // and internal values are up to date 0657 } 0658 0659 0660 bool FormatDialog::alwaysUseFormat() const 0661 { 0662 return (mDontAskCheck != nullptr ? mDontAskCheck->isChecked() : false); 0663 } 0664 0665 0666 /* static */ bool FormatDialog::isCompatible(const QMimeType &mime, ScanImage::ImageType type, bool recOnly) 0667 { 0668 //qCDebug(KOOKA_LOG) << "mime" << mime << "type" << type << "recOnly" << recOnly; 0669 for (const FormatInfo *ip = &formats[0]; ip->mime!=nullptr; ++ip) 0670 { // scan the format descriptions 0671 if (mime.inherits(ip->mime)) // found format for the MIME type 0672 { 0673 const ScanImage::ImageTypes types = (recOnly ? ip->recForTypes : ip->okForTypes); 0674 if (!recOnly && types==ScanImage::None) return (true); 0675 // allowed for all formats 0676 return (types & type); // check image type mask 0677 } 0678 } 0679 0680 return (false); 0681 }