#include "comic_flow.h" #include "qnaturalsorting.h" #include "yacreader_global.h" #include #include #include #include ComicFlow::ComicFlow(QWidget* parent,FlowType flowType) :YACReaderFlow(parent,flowType) { updateTimer = new QTimer; connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData())); worker = new ImageLoader; connect(this, SIGNAL(centerIndexChanged(int)), this, SLOT(preload())); connect(this, SIGNAL(centerIndexChangedSilent(int)), this, SLOT(preload())); setReflectionEffect(PlainReflection); } ComicFlow::~ComicFlow() { worker->terminate(); delete worker; delete updateTimer; } void ComicFlow::setImagePaths(const QStringList& paths) { clear(); //imagePath = path; imageFiles = paths; imagesLoaded.clear(); imagesLoaded.fill(false,imageFiles.size()); numImagesLoaded = 0; imagesSetted.clear(); imagesSetted.fill(false,imageFiles.size()); // populate with empty images QImage img; //TODO remove QString s; for(int i = 0; i < (int)imageFiles.size(); i++) { addSlide(img); s = imageFiles.at(i); s.remove(s.size()-4,4); if(QFileInfo(s+".r").exists()) markSlide(i); } setCenterIndex(0); worker->reset(); preload(); } void ComicFlow::preload() { if(numImagesLoaded < imagesLoaded.size()) updateTimer->start(30); //TODO comprobar rendimiento, originalmente era 70 } void ComicFlow::updateImageData() { // can't do anything, wait for the next possibility if(worker->busy()) return; // set image of last one int idx = worker->index(); if( idx >= 0 && !worker->result().isNull()) { if(!imagesSetted[idx]) { setSlide(idx, worker->result()); imagesSetted[idx] = true; numImagesLoaded++; imagesLoaded[idx]=true; } } // try to load only few images on the left and right side // i.e. all visible ones plus some extra #define COUNT 8 int indexes[2*COUNT+1]; int center = centerIndex(); indexes[0] = center; for(int j = 0; j < COUNT; j++) { indexes[j*2+1] = center+j+1; indexes[j*2+2] = center-j-1; } for(int c = 0; c < 2*COUNT+1; c++) { int i = indexes[c]; if((i >= 0) && (i < slideCount())) if(!imagesLoaded[i])//slide(i).isNull()) { // schedule thumbnail generation QString fname = imageFiles[i]; worker->generate(i, fname, slideSize()); return; } } // no need to generate anything? stop polling... updateTimer->stop(); } void ComicFlow::keyPressEvent(QKeyEvent* event) { PictureFlow::keyPressEvent(event); } void ComicFlow::wheelEvent(QWheelEvent * event) { if(event->delta()<0) showNext(); else showPrevious(); event->accept(); } void ComicFlow::removeSlide(int cover) { worker->lock(); worker->reset(); imageFiles.removeAt(cover); if(imagesLoaded[cover]) numImagesLoaded--; imagesLoaded.remove(cover); imagesSetted.remove(cover); YACReaderFlow::removeSlide(cover); worker->unlock(); preload(); } void ComicFlow::resortCovers(QList newOrder) { worker->lock(); worker->reset(); YACReaderFlow::resortCovers(newOrder); QStringList imageFilesNew; QVector imagesLoadedNew; QVector imagesSettedNew; foreach(int index, newOrder) { imageFilesNew << imageFiles.at(index); imagesLoadedNew << imagesLoaded.at(index); imagesSettedNew << imagesSetted.at(index); } imageFiles = imageFilesNew; imagesLoaded = imagesLoadedNew; imagesSetted = imagesSettedNew; worker->unlock(); } //----------------------------------------------------------------------------- //ImageLoader //----------------------------------------------------------------------------- static QImage loadImage(const QString& fileName) { QImage image; bool result = image.load(fileName); if(!result) return QImage(); return image; } ImageLoader::ImageLoader(): QThread(), restart(false), working(false), idx(-1) { } ImageLoader::~ImageLoader() { mutex.lock(); condition.wakeOne(); mutex.unlock(); wait(); } bool ImageLoader::busy() const { return isRunning() ? working : false; } void ImageLoader::generate(int index, const QString& fileName, QSize size) { mutex.lock(); this->idx = index; this->fileName = fileName; this->size = size; this->img = QImage(); mutex.unlock(); if (!isRunning()) start(); else { // already running, wake up whenever ready restart = true; condition.wakeOne(); } } void ImageLoader::lock() { mutex.lock(); } void ImageLoader::unlock() { mutex.unlock(); } void ImageLoader::run() { for(;;) { // copy necessary data mutex.lock(); this->working = true; QString fileName = this->fileName; mutex.unlock(); QImage image = loadImage(fileName); // let everyone knows it is ready mutex.lock(); this->working = false; this->img = image; mutex.unlock(); // put to sleep mutex.lock(); if (!this->restart) condition.wait(&mutex); restart = false; mutex.unlock(); } } QImage ImageLoader::result() { return img; }