File indexing completed on 2024-05-05 05:21:41

0001 /*
0002   SPDX-FileCopyrightText: 2012-2024 Laurent Montel <montel@kde.org>
0003 
0004   SPDX-License-Identifier: LGPL-2.0-or-later
0005 
0006 */
0007 #include "insertimagewidget.h"
0008 
0009 #include <KLineEdit>
0010 #include <KLocalizedString>
0011 #include <KSeparator>
0012 #include <KUrlRequester>
0013 
0014 #include <QCheckBox>
0015 #include <QHBoxLayout>
0016 #include <QImageReader>
0017 #include <QLabel>
0018 #include <QMimeDatabase>
0019 #include <QSpinBox>
0020 #include <QVBoxLayout>
0021 
0022 namespace KPIMTextEdit
0023 {
0024 static inline QString resolveAlias(const QString &name)
0025 {
0026     QMimeDatabase db;
0027     const QString str = db.mimeTypeForName(name).name();
0028     return str;
0029 }
0030 
0031 class InsertImageWidgetPrivate
0032 {
0033 public:
0034     explicit InsertImageWidgetPrivate(InsertImageWidget *qq)
0035         : q(qq)
0036     {
0037         auto lay = new QVBoxLayout(q);
0038         lay->setContentsMargins({});
0039         auto hbox = new QHBoxLayout;
0040         auto lab = new QLabel(i18n("Image Location:"));
0041         imageUrlRequester = new KUrlRequester;
0042 
0043         QStringList lstMimeTypes;
0044         const QList<QByteArray> mimetypes = QImageReader::supportedMimeTypes();
0045         lstMimeTypes.reserve(mimetypes.count());
0046         for (const QByteArray &ba : mimetypes) {
0047             const QString resolvedAlias = resolveAlias(QString::fromUtf8(ba));
0048             if (!resolvedAlias.isEmpty()) {
0049                 lstMimeTypes << resolvedAlias;
0050             }
0051         }
0052         imageUrlRequester->setMimeTypeFilters(lstMimeTypes);
0053         imageUrlRequester->setWindowTitle(i18nc("@title:window", "Add Image"));
0054         imageUrlRequester->setMode(KFile::File);
0055         q->connect(imageUrlRequester->lineEdit(), &KLineEdit::textChanged, q, [this](const QString &str) {
0056             _k_slotUrlChanged(str);
0057         });
0058 
0059         hbox->addWidget(lab);
0060         hbox->addWidget(imageUrlRequester);
0061         lab->setBuddy(imageUrlRequester);
0062         lay->addLayout(hbox);
0063 
0064         keepOriginalSize = new QCheckBox(i18n("Keep Original Size"));
0065         q->connect(keepOriginalSize, &QCheckBox::clicked, q, [this](bool b) {
0066             _k_slotKeepOriginalSizeClicked(b);
0067         });
0068         keepOriginalSize->setChecked(true);
0069         lay->addWidget(keepOriginalSize);
0070 
0071         keepImageRatio = new QCheckBox(i18n("Keep Image Ratio"));
0072         keepImageRatio->setChecked(true);
0073         keepImageRatio->setEnabled(false);
0074         lay->addWidget(keepImageRatio);
0075 
0076         hbox = new QHBoxLayout;
0077         lab = new QLabel(i18n("Width:"));
0078         width = new QSpinBox;
0079         width->setMinimum(1);
0080         width->setMaximum(99999);
0081         width->setEnabled(false);
0082         width->setSuffix(i18n(" px"));
0083         lab->setBuddy(width);
0084         q->connect(width, &QSpinBox::valueChanged, q, [this](int val) {
0085             _k_slotImageWidthChanged(val);
0086         });
0087         hbox->addWidget(lab);
0088         hbox->addWidget(width);
0089         lay->addLayout(hbox);
0090 
0091         hbox = new QHBoxLayout;
0092         lab = new QLabel(i18n("Height:"));
0093         height = new QSpinBox;
0094         height->setMinimum(1);
0095         height->setMaximum(99999);
0096         height->setEnabled(false);
0097         height->setSuffix(i18n(" px"));
0098         lab->setBuddy(height);
0099         q->connect(height, &QSpinBox::valueChanged, q, [this](int val) {
0100             _k_slotImageHeightChanged(val);
0101         });
0102         hbox->addWidget(lab);
0103         hbox->addWidget(height);
0104         lay->addLayout(hbox);
0105 
0106         auto sep = new KSeparator;
0107         lay->addWidget(sep);
0108 
0109         hbox = new QHBoxLayout;
0110         lab = new QLabel(i18n("Image Preview:"));
0111         hbox->addWidget(lab);
0112         preview = new QLabel;
0113         preview->setFrameStyle(QFrame::Box);
0114         preview->setFixedSize(50, 50);
0115         hbox->addWidget(preview);
0116         lay->addLayout(hbox);
0117     }
0118 
0119     void _k_slotKeepOriginalSizeClicked(bool);
0120     void _k_slotUrlChanged(const QString &);
0121     void _k_slotImageWidthChanged(int);
0122     void _k_slotImageHeightChanged(int);
0123 
0124     qreal imageRatio = -1;
0125     QCheckBox *keepOriginalSize = nullptr;
0126     QCheckBox *keepImageRatio = nullptr;
0127     QSpinBox *width = nullptr;
0128     QSpinBox *height = nullptr;
0129     KUrlRequester *imageUrlRequester = nullptr;
0130     QLabel *preview = nullptr;
0131     InsertImageWidget *const q;
0132 };
0133 
0134 void InsertImageWidgetPrivate::_k_slotKeepOriginalSizeClicked(bool checked)
0135 {
0136     height->setEnabled(!checked);
0137     width->setEnabled(!checked);
0138     keepImageRatio->setEnabled(!checked);
0139     // Update default size
0140     _k_slotUrlChanged(imageUrlRequester->text());
0141 }
0142 
0143 void InsertImageWidgetPrivate::_k_slotUrlChanged(const QString &text)
0144 {
0145     QImage image(text);
0146     if (!image.isNull()) {
0147         height->setValue(image.height());
0148         width->setValue(image.width());
0149 
0150         imageRatio = (double)((double)image.height() / (double)image.width());
0151         preview->setPixmap(QPixmap::fromImage(image));
0152     } else {
0153         preview->clear();
0154         imageRatio = -1;
0155     }
0156     Q_EMIT q->enableButtonOk(!text.trimmed().isEmpty());
0157 }
0158 
0159 void InsertImageWidgetPrivate::_k_slotImageWidthChanged(int value)
0160 {
0161     if (keepImageRatio->isChecked() && !keepOriginalSize->isChecked()) {
0162         if (imageRatio != -1) {
0163             height->blockSignals(true);
0164             height->setValue(value * imageRatio);
0165             height->blockSignals(false);
0166         }
0167     }
0168 }
0169 
0170 void InsertImageWidgetPrivate::_k_slotImageHeightChanged(int value)
0171 {
0172     if (keepImageRatio->isChecked() && !keepOriginalSize->isChecked()) {
0173         if (imageRatio != -1) {
0174             width->blockSignals(true);
0175             width->setValue(value / imageRatio);
0176             width->blockSignals(false);
0177         }
0178     }
0179 }
0180 
0181 InsertImageWidget::InsertImageWidget(QWidget *parent)
0182     : QWidget(parent)
0183     , d(new InsertImageWidgetPrivate(this))
0184 {
0185 }
0186 
0187 InsertImageWidget::~InsertImageWidget() = default;
0188 
0189 int InsertImageWidget::imageWidth() const
0190 {
0191     return d->width->value();
0192 }
0193 
0194 int InsertImageWidget::imageHeight() const
0195 {
0196     return d->height->value();
0197 }
0198 
0199 void InsertImageWidget::setImageWidth(int value)
0200 {
0201     d->width->setValue(value);
0202 }
0203 
0204 void InsertImageWidget::setImageHeight(int value)
0205 {
0206     d->height->setValue(value);
0207 }
0208 
0209 QUrl InsertImageWidget::imageUrl() const
0210 {
0211     return d->imageUrlRequester->url();
0212 }
0213 
0214 void InsertImageWidget::setImageUrl(const QUrl &url)
0215 {
0216     d->imageUrlRequester->setUrl(url);
0217 }
0218 
0219 bool InsertImageWidget::keepOriginalSize() const
0220 {
0221     return d->keepOriginalSize->isChecked();
0222 }
0223 }
0224 
0225 #include "moc_insertimagewidget.cpp"