File indexing completed on 2024-05-19 05:40:35
0001 /*************************************************************************** 0002 * Copyright (C) 2021 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/imageselectorcontroller.h" 0021 0022 #include <QClipboard> 0023 #include <QGuiApplication> 0024 #include <QMimeData> 0025 #include <QNetworkReply> 0026 #include <QtConcurrent> 0027 0028 #include "utils/iohelper.h" 0029 #include "worker/iohelper.h" 0030 #include "worker/utilshelper.h" 0031 0032 ImageSelectorController::ImageSelectorController(bool askPath, Sources sources, Shape shape, const QString& directory, 0033 QObject* parent) 0034 : QObject(parent), m_sources(sources), m_shape(shape), m_askPath(askPath), m_currentDir(directory) 0035 { 0036 #ifdef HAVE_QT_NETWORK 0037 m_manager.reset(new QNetworkAccessManager()); 0038 connect(m_manager.get(), &QNetworkAccessManager::finished, this, 0039 [this](QNetworkReply* reply) { setImageData(reply->readAll()); }); 0040 #endif 0041 0042 auto updateImage= [this]() 0043 { 0044 helper::utils::setContinuation<std::pair<QPixmap, QPixmap>>( 0045 QtConcurrent::run( 0046 [this]() 0047 { 0048 if(m_data.isEmpty()) 0049 return std::pair<QPixmap, QPixmap>(); 0050 auto main= QImage::fromData(m_data); 0051 return std::make_pair(QPixmap::fromImage(main), 0052 QPixmap::fromImage(main).scaled(m_visualSize, Qt::KeepAspectRatio)); 0053 }), 0054 this, 0055 [this](const std::pair<QPixmap, QPixmap>& imgs) 0056 { 0057 if(m_pixmap.isNull() && imgs.first.isNull()) 0058 return; 0059 0060 m_pixmap= imgs.first; 0061 0062 m_thumbnail= imgs.second; 0063 0064 m_factor= static_cast<qreal>(m_pixmap.width()) / static_cast<qreal>(m_thumbnail.width()); 0065 emit pixmapChanged(); 0066 }); 0067 }; 0068 0069 connect(this, &ImageSelectorController::imageDataChanged, this, updateImage); 0070 connect(this, &ImageSelectorController::visualSizeChanged, this, updateImage); 0071 0072 auto clipboard= QGuiApplication::clipboard(); 0073 connect(clipboard, &QClipboard::dataChanged, this, &ImageSelectorController::contentToPasteChanged); 0074 } 0075 0076 bool ImageSelectorController::canDrop() const 0077 { 0078 return m_sources & DragAndDrop; 0079 } 0080 0081 bool ImageSelectorController::canPaste() const 0082 { 0083 return m_sources & Clipboard; 0084 } 0085 0086 bool ImageSelectorController::canDownload() const 0087 { 0088 #ifdef HAVE_QT_NETWORK 0089 return m_sources & Web; 0090 #else 0091 return false; 0092 #endif 0093 } 0094 0095 bool ImageSelectorController::askPath() const 0096 { 0097 return m_askPath; 0098 } 0099 0100 bool ImageSelectorController::validData() const 0101 { 0102 auto const& validMovie= isMovie(); 0103 auto const& validImg= !pixmap().isNull(); 0104 0105 return (validImg || validMovie); 0106 } 0107 0108 QPixmap ImageSelectorController::pixmap() const 0109 { 0110 return m_pixmap; // QPixmap::fromImage(QImage::fromData(m_data)); 0111 } 0112 0113 QPixmap ImageSelectorController::thumbnail() const 0114 { 0115 return m_thumbnail; // QPixmap::fromImage(); 0116 } 0117 0118 QByteArray ImageSelectorController::imageData() const 0119 { 0120 return m_data; 0121 } 0122 0123 ImageSelectorController::Shape ImageSelectorController::shape() const 0124 { 0125 return m_shape; 0126 } 0127 0128 ImageSelectorController::Sources ImageSelectorController::sources() const 0129 { 0130 return m_sources; 0131 } 0132 0133 QString ImageSelectorController::title() const 0134 { 0135 return m_title; 0136 } 0137 0138 QString ImageSelectorController::address() const 0139 { 0140 return m_address.toString(); 0141 } 0142 0143 QString ImageSelectorController::currentDir() const 0144 { 0145 return m_currentDir; 0146 } 0147 0148 bool ImageSelectorController::hasContentToPaste() const 0149 { 0150 auto clipboard= QGuiApplication::clipboard(); 0151 if(!clipboard) 0152 return false; 0153 const QMimeData* mimeData= clipboard->mimeData(); 0154 if(!mimeData) 0155 return false; 0156 0157 return mimeData->hasImage(); 0158 } 0159 0160 bool ImageSelectorController::dataInShape() const 0161 { 0162 auto dataGeo= computeDataGeometry(); 0163 bool res= dataGeo.isValid(); 0164 if(m_shape == Square) 0165 res&= (dataGeo.height() == dataGeo.width()); 0166 return res; 0167 } 0168 0169 QSize ImageSelectorController::visualSize() const 0170 { 0171 return m_visualSize; 0172 } 0173 0174 bool ImageSelectorController::rectInShape() const 0175 { 0176 bool res= computeDataGeometry().contains(QRect(m_rect.x()*m_factor,m_rect.y()*m_factor,m_rect.width()*m_factor,m_rect.height()*m_factor)); 0177 if(m_shape == Square) 0178 res&= (m_rect.height() == m_rect.width()); 0179 return res; 0180 } 0181 0182 bool ImageSelectorController::isMovie() const 0183 { 0184 return m_movie.isValid() && m_movie.frameCount() > 1; 0185 } 0186 0187 void ImageSelectorController::imageFromClipboard() 0188 { 0189 auto clipboard= QGuiApplication::clipboard(); 0190 0191 if(!clipboard) 0192 return; 0193 const QMimeData* mimeData= clipboard->mimeData(); 0194 if(!mimeData) 0195 return; 0196 0197 if(mimeData->hasImage()) 0198 { 0199 auto pix= qvariant_cast<QPixmap>(mimeData->imageData()); 0200 if(pix.isNull()) 0201 return; 0202 setImageData(IOHelper::pixmapToData(pix)); 0203 } 0204 else if(mimeData->hasUrls()) 0205 { 0206 auto urls= mimeData->urls(); 0207 if(urls.isEmpty()) 0208 return; 0209 auto url= urls.first(); 0210 downloadImageFrom(url); 0211 } 0212 } 0213 0214 void ImageSelectorController::downloadImageFrom(const QUrl& url) 0215 { 0216 setAddressPrivate(url); 0217 if(m_address.isLocalFile()) 0218 { 0219 openImageFromFile(); 0220 } 0221 else 0222 { 0223 #ifdef HAVE_QT_NETWORK 0224 setTitle(url.fileName()); 0225 m_manager->get(QNetworkRequest(m_address)); 0226 #endif 0227 } 0228 } 0229 0230 QMovie* ImageSelectorController::movie() 0231 { 0232 return &m_movie; 0233 } 0234 0235 QRect ImageSelectorController::rect() const 0236 { 0237 return m_rect; 0238 } 0239 0240 void ImageSelectorController::openImageFromFile() 0241 { 0242 auto local= m_address.toLocalFile(); 0243 QFileInfo info(local); 0244 setTitle(info.baseName()); 0245 setImageData(utils::IOHelper::loadFile(local)); 0246 } 0247 0248 QByteArray ImageSelectorController::finalImageData() const 0249 { 0250 auto data= imageData(); 0251 if(m_shape != AnyShape) 0252 { 0253 auto rect= QRect(m_rect.x() * m_factor, m_rect.y() * m_factor, m_rect.width() * m_factor, 0254 m_rect.height() * m_factor); 0255 data= IOHelper::pixmapToData(m_pixmap.copy(rect)); 0256 } 0257 return data; 0258 } 0259 0260 void ImageSelectorController::setTitle(const QString& title) 0261 { 0262 if(title == m_title) 0263 return; 0264 m_title= title; 0265 emit titleChanged(); 0266 } 0267 0268 void ImageSelectorController::setAddressPrivate(const QUrl& url) 0269 { 0270 if(m_address == url) 0271 return; 0272 m_address= url; 0273 emit addressChanged(); 0274 } 0275 0276 QRect ImageSelectorController::computeDataGeometry() const 0277 { 0278 QRect res; 0279 auto pix= pixmap(); 0280 if(!pix.isNull()) 0281 res= pix.rect(); 0282 else if(isMovie()) 0283 res= m_movie.frameRect(); 0284 0285 return res; 0286 } 0287 0288 void ImageSelectorController::setAddress(const QString& address) 0289 { 0290 if(this->address() == QUrl::fromUserInput(address).toString()) 0291 return; 0292 m_address= QUrl::fromUserInput(address); 0293 emit addressChanged(); 0294 } 0295 0296 void ImageSelectorController::setRect(const QRect& rect) 0297 { 0298 if(rect == m_rect) 0299 return; 0300 m_rect= rect; 0301 emit rectChanged(); 0302 } 0303 0304 void ImageSelectorController::setVisualSize(const QSize& visualSize) 0305 { 0306 if(visualSize == m_visualSize) 0307 return; 0308 m_visualSize= visualSize; 0309 emit visualSizeChanged(); 0310 } 0311 0312 void ImageSelectorController::setImageData(const QByteArray& array) 0313 { 0314 if(array == m_data) 0315 return; 0316 m_data= array; 0317 0318 m_buffer.setData(m_data); 0319 m_movie.setDevice(&m_buffer); 0320 emit imageDataChanged(); 0321 }