File indexing completed on 2024-07-14 05:32:31

0001 /***************************************************************************
0002  *   Copyright (C) 2006 by David Saxton                                    *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #include "dpimage.h"
0012 #include "itemdocument.h"
0013 #include "libraryitem.h"
0014 #include "resizeoverlay.h"
0015 
0016 #include <KLocalizedString>
0017 
0018 #include <QPainter>
0019 #include <QTimer>
0020 
0021 #include <ktechlab_debug.h>
0022 
0023 // BEGIN class ImageScaleThread
0024 ImageScaleThread::ImageScaleThread()
0025 {
0026     // Start with a blank (grey) image
0027     QPixmap pm(1, 1);
0028     pm.fill(Qt::gray);
0029     m_image = pm.toImage();
0030 
0031     m_width = -1;
0032     m_height = -1;
0033     m_bDoneNormalScale = false;
0034     m_bDoneSmoothScale = false;
0035     m_bSettingsChanged = false;
0036 }
0037 
0038 bool ImageScaleThread::updateSettings(const QString &imageURL, int width, int height)
0039 {
0040     if (isRunning()) {
0041         qCWarning(KTL_LOG) << "Cannot update settings while running.";
0042         return false;
0043     }
0044 
0045     bool changed = false;
0046 
0047     if (m_width != width) {
0048         m_width = width;
0049         changed = true;
0050     }
0051 
0052     if (m_height != height) {
0053         m_height = height;
0054         changed = true;
0055     }
0056 
0057     if (m_imageURL != imageURL) {
0058         m_imageURL = imageURL;
0059         m_image.load(m_imageURL);
0060         if (m_image.isNull()) {
0061             QPixmap pm(1, 1);
0062             pm.fill(Qt::gray);
0063             m_image = pm.toImage();
0064         }
0065         changed = true;
0066     }
0067 
0068     if (changed) {
0069         m_bSettingsChanged = true;
0070         m_bDoneNormalScale = false;
0071         m_bDoneSmoothScale = false;
0072     }
0073 
0074     return changed;
0075 }
0076 
0077 QImage ImageScaleThread::bestScaling(BestScaling *scaling) const
0078 {
0079     BestScaling temp;
0080     if (!scaling)
0081         scaling = &temp;
0082 
0083     if (m_bDoneSmoothScale) {
0084         *scaling = SmoothScaled;
0085         return m_smoothScaled;
0086     }
0087 
0088     else if (m_bDoneNormalScale) {
0089         *scaling = NormalScaled;
0090         return m_normalScaled;
0091     }
0092 
0093     else {
0094         *scaling = Unscaled;
0095         return m_image;
0096     }
0097 }
0098 
0099 void ImageScaleThread::run()
0100 {
0101     do {
0102         m_bSettingsChanged = false;
0103         if (!m_bDoneNormalScale) {
0104             m_normalScaled = m_image.scaled(m_width, m_height);
0105             m_bDoneNormalScale = true;
0106         }
0107     } while (m_bSettingsChanged);
0108 
0109     // If m_bSettingsChanged is true, then another thread called updateSettings
0110     // while we were doing normal scaling, so don't both doing smooth scaling
0111     // just yet.
0112 
0113     if (!m_bDoneSmoothScale) {
0114         // m_smoothScaled = m_image.smoothScale( m_width, m_height ); // 2018.12.01
0115         m_smoothScaled = m_image.scaled(QSize(m_width, m_height), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
0116         m_bDoneSmoothScale = true;
0117     }
0118 }
0119 // END class ImageScaleThread
0120 
0121 // BEGIN class DPImage
0122 Item *DPImage::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0123 {
0124     return new DPImage(itemDocument, newItem, id);
0125 }
0126 
0127 LibraryItem *DPImage::libraryItem()
0128 {
0129     return new LibraryItem(QStringList(QString("dp/image")), i18n("Image"), i18n("Other"), QIcon::fromTheme("text"), LibraryItem::lit_drawpart, DPImage::construct);
0130 }
0131 
0132 DPImage::DPImage(ItemDocument *itemDocument, bool newItem, const char *id)
0133     : DrawPart(itemDocument, newItem, id ? id : "image")
0134 {
0135     m_bSettingsChanged = false;
0136     m_bResizeToImage = newItem;
0137     m_imageScaling = ImageScaleThread::Unscaled;
0138 
0139     m_pRectangularOverlay = new RectangularOverlay(this);
0140 
0141     m_pCheckImageScalingTimer = new QTimer(this);
0142     connect(m_pCheckImageScalingTimer, &QTimer::timeout, this, &DPImage::checkImageScaling);
0143     m_pCheckImageScalingTimer->start(100);
0144 
0145     m_name = i18n("Image");
0146 
0147     Variant *v = createProperty("image", Variant::Type::FileName);
0148     v->setCaption(i18n("Image File"));
0149     dataChanged();
0150 }
0151 
0152 DPImage::~DPImage()
0153 {
0154     m_imageScaleThread.wait();
0155 }
0156 
0157 void DPImage::setSelected(bool yes)
0158 {
0159     if (yes == isSelected())
0160         return;
0161 
0162     DrawPart::setSelected(yes);
0163     m_pRectangularOverlay->showResizeHandles(yes);
0164 }
0165 
0166 void DPImage::postResize()
0167 {
0168     setItemPoints(QPolygon(m_sizeRect), false);
0169     m_bSettingsChanged = true;
0170 }
0171 
0172 void DPImage::dataChanged()
0173 {
0174     m_imageURL = dataString("image");
0175     m_image.load(m_imageURL);
0176 
0177     if (m_image.isNull()) {
0178         // Make a grey image
0179         // m_image.resize( width(), height() ); // 2018.12.01
0180         m_image = m_image.copy(0, 0, width(), height());
0181         m_image.fill(Qt::gray);
0182 
0183         m_imageScaling = ImageScaleThread::SmoothScaled;
0184     } else {
0185         if (m_bResizeToImage) {
0186             int w = m_image.width();
0187             int h = m_image.height();
0188             setSize(0, 0, w, h);
0189             m_imageScaling = ImageScaleThread::SmoothScaled;
0190         } else {
0191             m_bResizeToImage = true;
0192             m_bSettingsChanged = true;
0193         }
0194     }
0195 }
0196 
0197 void DPImage::checkImageScaling()
0198 {
0199     if (!m_bSettingsChanged && (m_imageScaling == ImageScaleThread::SmoothScaled)) {
0200         // Image scaling is already at its best, so return
0201         return;
0202     }
0203 
0204     ImageScaleThread::BestScaling bs;
0205     QImage im = m_imageScaleThread.bestScaling(&bs);
0206     if (bs > m_imageScaling) {
0207         m_imageScaling = bs;
0208         m_image = QPixmap::fromImage(im);
0209         setChanged();
0210     }
0211 
0212     if (!m_imageScaleThread.isRunning()) {
0213         if (m_imageScaleThread.updateSettings(m_imageURL, width(), height())) {
0214             m_bSettingsChanged = false;
0215             m_imageScaling = ImageScaleThread::Unscaled;
0216             m_imageScaleThread.start();
0217         }
0218     }
0219 }
0220 
0221 void DPImage::drawShape(QPainter &p)
0222 {
0223     p.drawPixmap(int(x() + offsetX()), int(y() + offsetY()), m_image, 0, 0, width(), height());
0224 }
0225 // END class DPImage
0226 
0227 #include "moc_dpimage.cpp"