2017-06-11 09:31:45 +02:00
# include "messages/lazyloadedimage.hpp"
# include "asyncexec.hpp"
# include "emotemanager.hpp"
# include "ircmanager.hpp"
# include "util/urlfetch.hpp"
# include "windowmanager.hpp"
2017-01-11 18:52:09 +01:00
2017-09-28 22:24:03 +02:00
# include <thread>
2017-02-06 17:42:28 +01:00
# include <QBuffer>
# include <QImageReader>
2017-01-11 18:52:09 +01:00
# include <QNetworkAccessManager>
# include <QNetworkReply>
# include <QNetworkRequest>
2017-02-06 17:42:28 +01:00
# include <QTimer>
2017-06-06 21:18:05 +02:00
2017-01-11 18:52:09 +01:00
# include <functional>
2017-01-18 21:30:23 +01:00
namespace chatterino {
namespace messages {
2017-06-13 21:13:58 +02:00
LazyLoadedImage : : LazyLoadedImage ( EmoteManager & _emoteManager , WindowManager & _windowManager ,
const QString & url , qreal scale , const QString & name ,
2017-04-12 17:46:44 +02:00
const QString & tooltip , const QMargins & margin , bool isHat )
2017-06-13 21:13:58 +02:00
: emoteManager ( _emoteManager )
, windowManager ( _windowManager )
2017-09-12 19:06:16 +02:00
, currentPixmap ( nullptr )
, url ( url )
, name ( name )
, tooltip ( tooltip )
, margin ( margin )
, ishat ( isHat )
, scale ( scale )
, isLoading ( false )
2017-01-05 16:07:20 +01:00
{
}
2017-06-13 21:13:58 +02:00
LazyLoadedImage : : LazyLoadedImage ( EmoteManager & _emoteManager , WindowManager & _windowManager ,
QPixmap * image , qreal scale , const QString & name ,
2017-04-12 17:46:44 +02:00
const QString & tooltip , const QMargins & margin , bool isHat )
2017-06-13 21:13:58 +02:00
: emoteManager ( _emoteManager )
, windowManager ( _windowManager )
2017-09-12 19:06:16 +02:00
, currentPixmap ( image )
, name ( name )
, tooltip ( tooltip )
, margin ( margin )
, ishat ( isHat )
, scale ( scale )
, isLoading ( true )
2017-01-11 18:52:09 +01:00
{
}
2017-04-12 17:46:44 +02:00
void LazyLoadedImage : : loadImage ( )
2017-01-04 15:12:31 +01:00
{
2017-09-28 22:24:03 +02:00
std : : thread ( [ = ] ( ) {
QNetworkRequest request ;
request . setUrl ( QUrl ( this - > url ) ) ;
QNetworkAccessManager NaM ;
QEventLoop eventLoop ;
QNetworkReply * reply = NaM . get ( request ) ;
QObject : : connect ( reply , & QNetworkReply : : finished , & eventLoop , & QEventLoop : : quit ) ;
eventLoop . exec ( ) ; // Wait until response is read.
qDebug ( ) < < " Received emote " < < this - > url ;
QByteArray array = reply - > readAll ( ) ;
QBuffer buffer ( & array ) ;
buffer . open ( QIODevice : : ReadOnly ) ;
QImage image ;
QImageReader reader ( & buffer ) ;
bool first = true ;
for ( int index = 0 ; index < reader . imageCount ( ) ; + + index ) {
if ( reader . read ( & image ) ) {
auto pixmap = new QPixmap ( QPixmap : : fromImage ( image ) ) ;
if ( first ) {
first = false ;
this - > currentPixmap = pixmap ;
}
FrameData data ;
data . duration = std : : max ( 20 , reader . nextImageDelay ( ) ) ;
data . image = pixmap ;
this - > allFrames . push_back ( data ) ;
}
}
if ( this - > allFrames . size ( ) > 1 ) {
this - > animated = true ;
}
this - > emoteManager . incGeneration ( ) ;
this - > windowManager . layoutVisibleChatWidgets ( ) ;
delete reply ;
} ) . detach ( ) ;
this - > emoteManager . getGifUpdateSignal ( ) . connect ( [ = ] ( ) { this - > gifUpdateTimout ( ) ; } ) ; // For some reason when Boost signal is in thread scope and thread deletes the signal doesn't work, so this is the fix.
2017-02-06 17:42:28 +01:00
}
2017-04-12 17:46:44 +02:00
void LazyLoadedImage : : gifUpdateTimout ( )
2017-02-06 17:42:28 +01:00
{
2017-09-28 22:24:03 +02:00
if ( animated ) {
this - > currentFrameOffset + = GIF_FRAME_LENGTH ;
while ( true ) {
if ( this - > currentFrameOffset > this - > allFrames . at ( this - > currentFrame ) . duration ) {
this - > currentFrameOffset - = this - > allFrames . at ( this - > currentFrame ) . duration ;
this - > currentFrame = ( this - > currentFrame + 1 ) % this - > allFrames . size ( ) ;
} else {
break ;
}
}
this - > currentPixmap = this - > allFrames [ this - > currentFrame ] . image ;
}
2017-01-04 15:12:31 +01:00
}
2017-09-12 19:06:16 +02:00
const QPixmap * LazyLoadedImage : : getPixmap ( )
{
if ( ! this - > isLoading ) {
this - > isLoading = true ;
loadImage ( ) ;
}
return this - > currentPixmap ;
}
qreal LazyLoadedImage : : getScale ( ) const
{
return this - > scale ;
}
const QString & LazyLoadedImage : : getUrl ( ) const
{
return this - > url ;
}
const QString & LazyLoadedImage : : getName ( ) const
{
return this - > name ;
}
const QString & LazyLoadedImage : : getTooltip ( ) const
{
return this - > tooltip ;
}
const QMargins & LazyLoadedImage : : getMargin ( ) const
{
return this - > margin ;
}
bool LazyLoadedImage : : getAnimated ( ) const
{
return this - > animated ;
}
bool LazyLoadedImage : : isHat ( ) const
{
return this - > ishat ;
}
int LazyLoadedImage : : getWidth ( ) const
{
if ( this - > currentPixmap = = nullptr ) {
return 16 ;
}
return this - > currentPixmap - > width ( ) ;
}
int LazyLoadedImage : : getScaledWidth ( ) const
{
return static_cast < int > ( getWidth ( ) * this - > scale ) ;
}
int LazyLoadedImage : : getHeight ( ) const
{
if ( this - > currentPixmap = = nullptr ) {
return 16 ;
}
return this - > currentPixmap - > height ( ) ;
}
int LazyLoadedImage : : getScaledHeight ( ) const
{
return static_cast < int > ( getHeight ( ) * this - > scale ) ;
}
2017-04-14 17:52:22 +02:00
} // namespace messages
} // namespace chatterino