File indexing completed on 2024-05-19 05:40:35

0001 /***************************************************************************
0002  *  Copyright (C) 2019 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software 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  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "controller/view_controller/imagecontroller.h"
0021 
0022 #include <QBuffer>
0023 #include <QDebug>
0024 #include <QFile>
0025 #include <QMovie>
0026 
0027 #include "utils/iohelper.h"
0028 
0029 constexpr char const* RESOURCE_SCHEME{"qrc"};
0030 ImageController::ImageController(const QString& id, const QString& name, const QUrl& url, const QByteArray& data,
0031                                  QObject* parent)
0032     : MediaControllerBase(id, Core::ContentType::PICTURE, parent), m_data(data)
0033 {
0034     setName(name);
0035     setUrl(url);
0036     if(m_data.isEmpty() && !url.isEmpty() && (url.isLocalFile() || url.scheme() == RESOURCE_SCHEME))
0037     {
0038         QString path
0039             = url.isLocalFile() ? url.toLocalFile() : QString(":%1").arg(url.toDisplayString(QUrl::RemoveScheme));
0040 
0041         m_data= utils::IOHelper::loadFile(path);
0042     }
0043     checkMovie();
0044 }
0045 
0046 ImageController::~ImageController()= default;
0047 
0048 bool ImageController::fitWindow() const
0049 {
0050     return m_fitWindow;
0051 }
0052 
0053 QByteArray ImageController::data() const
0054 {
0055     return m_data;
0056 }
0057 
0058 qreal ImageController::zoomLevel() const
0059 {
0060     return m_zoomLevel;
0061 }
0062 
0063 const QPixmap& ImageController::pixmap() const
0064 {
0065     return m_image;
0066 }
0067 
0068 Qt::CursorShape ImageController::cursor() const
0069 {
0070     return m_fitWindow ? Qt::ArrowCursor : Qt::OpenHandCursor;
0071 }
0072 
0073 bool ImageController::isMovie() const
0074 {
0075     if(!m_movie)
0076         return false;
0077     return m_movie->isValid();
0078 }
0079 
0080 ImageController::Status ImageController::status() const
0081 {
0082     return m_status;
0083 }
0084 
0085 qreal ImageController::ratioV() const
0086 {
0087     if(m_image.isNull())
0088         return 0;
0089     return static_cast<qreal>(m_image.size().width()) / m_image.size().height();
0090 }
0091 
0092 qreal ImageController::ratioH() const
0093 {
0094     if(m_image.isNull())
0095         return 0;
0096     return static_cast<qreal>(m_image.size().height()) / m_image.size().width();
0097 }
0098 
0099 void ImageController::setZoomLevel(qreal lvl)
0100 {
0101     lvl= qBound(0.2, lvl, 4.0);
0102     if(qFuzzyCompare(lvl, m_zoomLevel))
0103         return;
0104 
0105     m_zoomLevel= lvl;
0106     emit zoomLevelChanged();
0107 }
0108 
0109 void ImageController::setFitWindow(bool b)
0110 {
0111 
0112     if(m_fitWindow == b)
0113         return;
0114     m_fitWindow= b;
0115     emit fitWindowChanged();
0116     emit cursorChanged();
0117 }
0118 
0119 void ImageController::setStatus(Status status)
0120 {
0121     if(m_status == status)
0122         return;
0123     m_status= status;
0124     emit statusChanged(m_status);
0125 }
0126 
0127 void ImageController::zoomIn(qreal step)
0128 {
0129     setZoomLevel(m_zoomLevel + step);
0130 }
0131 
0132 void ImageController::zoomOut(qreal step)
0133 {
0134     setZoomLevel(m_zoomLevel - step);
0135 }
0136 
0137 void ImageController::play()
0138 {
0139     if(!m_movie)
0140         return;
0141     if(m_status == Playing)
0142         m_movie->setPaused(true);
0143     else if(m_status == Paused)
0144         m_movie->start();
0145 }
0146 
0147 void ImageController::stop()
0148 {
0149     if(!m_movie)
0150         return;
0151     m_movie->stop();
0152 }
0153 
0154 void ImageController::setPixmap(const QPixmap& pix)
0155 {
0156     m_image= pix;
0157     emit pixmapChanged();
0158 }
0159 
0160 void ImageController::checkMovie()
0161 {
0162     auto buf= new QBuffer(&m_data);
0163     buf->open(QIODevice::ReadOnly);
0164 
0165     m_movie.reset(new QMovie(buf, QByteArray(), this));
0166     if((m_movie->isValid()) && (m_movie->frameCount() > 1))
0167     {
0168         connect(m_movie.get(), &QMovie::updated, this, [this]() { setPixmap(m_movie->currentPixmap()); });
0169         connect(m_movie.get(), &QMovie::stateChanged, this, [this](const QMovie::MovieState& state) {
0170             switch(state)
0171             {
0172             case QMovie::NotRunning:
0173                 setStatus(ImageController::Stopped);
0174                 break;
0175             case QMovie::Paused:
0176                 setStatus(ImageController::Paused);
0177                 break;
0178             case QMovie::Running:
0179                 setStatus(ImageController::Playing);
0180                 break;
0181             }
0182         });
0183         m_movie->start();
0184     }
0185     else
0186     {
0187         m_movie.reset();
0188         QPixmap img;
0189         img.loadFromData(m_data);
0190         setPixmap(img);
0191     }
0192 }
0193 
0194 void ImageController::setData(QByteArray& array)
0195 {
0196     if(m_data == array)
0197         return;
0198     m_data= array;
0199     emit dataChanged();
0200     checkMovie();
0201 }
0202 
0203 const QPixmap ImageController::scaledPixmap() const
0204 {
0205     return m_image.scaled(static_cast<int>(m_image.width() * m_zoomLevel),
0206                           static_cast<int>(m_image.height() * m_zoomLevel));
0207 }