Threaded picture caching
This commit is contained in:
parent
9ece3cb789
commit
dc0f21cce4
9 changed files with 139 additions and 78 deletions
|
@ -28,7 +28,6 @@ HEADERS += src/abstractcounter.h \
|
|||
src/handcounter.h \
|
||||
src/carddatabase.h \
|
||||
src/gameview.h \
|
||||
src/deck_picturecacher.h \
|
||||
src/decklistmodel.h \
|
||||
src/dlg_load_deck_from_clipboard.h \
|
||||
src/dlg_load_remote_deck.h \
|
||||
|
@ -111,7 +110,6 @@ SOURCES += src/abstractcounter.cpp \
|
|||
src/handcounter.cpp \
|
||||
src/carddatabase.cpp \
|
||||
src/gameview.cpp \
|
||||
src/deck_picturecacher.cpp \
|
||||
src/decklistmodel.cpp \
|
||||
src/dlg_load_deck_from_clipboard.cpp \
|
||||
src/dlg_load_remote_deck.cpp \
|
||||
|
|
|
@ -60,6 +60,62 @@ void SetList::sortByKey()
|
|||
qSort(begin(), end(), CompareFunctor());
|
||||
}
|
||||
|
||||
PictureLoadingThread::PictureLoadingThread(QObject *parent)
|
||||
: QThread(parent)
|
||||
{
|
||||
}
|
||||
|
||||
PictureLoadingThread::~PictureLoadingThread()
|
||||
{
|
||||
quit();
|
||||
wait();
|
||||
}
|
||||
|
||||
void PictureLoadingThread::run()
|
||||
{
|
||||
forever {
|
||||
mutex.lock();
|
||||
if (loadQueue.isEmpty()) {
|
||||
mutex.unlock();
|
||||
return;
|
||||
}
|
||||
CardInfo *card = loadQueue.takeFirst();
|
||||
QString correctedName = card->getCorrectedName();
|
||||
QString picsPath = _picsPath;
|
||||
SetList sortedSets = card->getSets();
|
||||
mutex.unlock();
|
||||
|
||||
sortedSets.sortByKey();
|
||||
|
||||
QImage image;
|
||||
for (int i = 0; i < sortedSets.size(); i++) {
|
||||
if (image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName)))
|
||||
break;
|
||||
if (image.load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName).arg(1)))
|
||||
break;
|
||||
}
|
||||
if (image.isNull())
|
||||
image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg("downloadedPics").arg(correctedName));
|
||||
|
||||
emit imageLoaded(card, image);
|
||||
}
|
||||
}
|
||||
|
||||
void PictureLoadingThread::loadImage(CardInfo *card)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
loadQueue.append(card);
|
||||
|
||||
if (!isRunning())
|
||||
start(LowPriority);
|
||||
}
|
||||
|
||||
void PictureLoadingThread::setPicsPath(const QString &path)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
_picsPath = path;
|
||||
}
|
||||
|
||||
CardInfo::CardInfo(CardDatabase *_db, const QString &_name, const QString &_manacost, const QString &_cardtype, const QString &_powtough, const QString &_text, const QStringList &_colors, bool _cipt, int _tableRow, const SetList &_sets, const QString &_picURL)
|
||||
: db(_db), name(_name), sets(_sets), manacost(_manacost), cardtype(_cardtype), powtough(_powtough), text(_text), colors(_colors), picURL(_picURL), cipt(_cipt), tableRow(_tableRow), pixmap(NULL)
|
||||
{
|
||||
|
@ -119,36 +175,24 @@ QPixmap *CardInfo::loadPixmap()
|
|||
if (pixmap)
|
||||
return pixmap;
|
||||
pixmap = new QPixmap();
|
||||
QString picsPath = settingsCache->getPicsPath();
|
||||
if (!QDir(picsPath).exists())
|
||||
return pixmap;
|
||||
|
||||
if (getName().isEmpty()) {
|
||||
pixmap->load(settingsCache->getCardBackPicturePath());
|
||||
return pixmap;
|
||||
}
|
||||
SetList sortedSets = sets;
|
||||
sortedSets.sortByKey();
|
||||
|
||||
QString debugOutput = QString("CardDatabase: loading pixmap for '%1' from ").arg(getName());
|
||||
for (int i = 0; i < sortedSets.size(); i++)
|
||||
debugOutput.append(QString("%1, ").arg(sortedSets[i]->getShortName()));
|
||||
qDebug(debugOutput.toLatin1());
|
||||
|
||||
QString correctedName = getCorrectedName();
|
||||
for (int i = 0; i < sortedSets.size(); i++) {
|
||||
if (pixmap->load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName)))
|
||||
return pixmap;
|
||||
if (pixmap->load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName).arg(1)))
|
||||
return pixmap;
|
||||
}
|
||||
if (pixmap->load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg("downloadedPics").arg(correctedName)))
|
||||
return pixmap;
|
||||
if (settingsCache->getPicDownload())
|
||||
db->startPicDownload(this);
|
||||
db->loadImage(this);
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
void CardInfo::imageLoaded(const QImage &image)
|
||||
{
|
||||
if (!image.isNull()) {
|
||||
*pixmap = QPixmap::fromImage(image);
|
||||
emit pixmapUpdated();
|
||||
} else if (settingsCache->getPicDownload())
|
||||
db->startPicDownload(this);
|
||||
}
|
||||
|
||||
QPixmap *CardInfo::getPixmap(QSize size)
|
||||
{
|
||||
qDebug(QString("CardInfo::getPixmap(%1, %2) for %3").arg(size.width()).arg(size.height()).arg(getName()).toLatin1());
|
||||
|
@ -243,6 +287,11 @@ CardDatabase::CardDatabase(QObject *parent)
|
|||
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *)));
|
||||
|
||||
loadCardDatabase();
|
||||
|
||||
loadingThread = new PictureLoadingThread(this);
|
||||
loadingThread->setPicsPath(settingsCache->getPicsPath());
|
||||
connect(loadingThread, SIGNAL(imageLoaded(CardInfo *, QImage)), this, SLOT(imageLoaded(CardInfo *, QImage)));
|
||||
loadingThread->start();
|
||||
|
||||
noCard = new CardInfo(this);
|
||||
noCard->loadPixmap(); // cache pixmap for card back
|
||||
|
@ -532,3 +581,21 @@ QStringList CardDatabase::getAllMainCardTypes() const
|
|||
types.insert(cardIterator.next().value()->getMainCardType());
|
||||
return types.toList();
|
||||
}
|
||||
|
||||
void CardDatabase::cacheCardPixmaps(const QStringList &cardNames)
|
||||
{
|
||||
qDebug("pixmapCache started");
|
||||
for (int i = 0; i < cardNames.size(); ++i)
|
||||
getCard(cardNames[i])->loadPixmap();
|
||||
qDebug("pixmapCache finished");
|
||||
}
|
||||
|
||||
void CardDatabase::loadImage(CardInfo *card)
|
||||
{
|
||||
loadingThread->loadImage(card);
|
||||
}
|
||||
|
||||
void CardDatabase::imageLoaded(CardInfo *card, QImage image)
|
||||
{
|
||||
card->imageLoaded(image);
|
||||
}
|
|
@ -8,6 +8,8 @@
|
|||
#include <QList>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QNetworkRequest>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
|
||||
class CardDatabase;
|
||||
class CardInfo;
|
||||
|
@ -35,6 +37,23 @@ public:
|
|||
void sortByKey();
|
||||
};
|
||||
|
||||
class PictureLoadingThread : public QThread {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QString _picsPath;
|
||||
QList<CardInfo *> loadQueue;
|
||||
QMutex mutex;
|
||||
protected:
|
||||
void run();
|
||||
public:
|
||||
PictureLoadingThread(QObject *parent);
|
||||
~PictureLoadingThread();
|
||||
void setPicsPath(const QString &path);
|
||||
void loadImage(CardInfo *card);
|
||||
signals:
|
||||
void imageLoaded(CardInfo *card, const QImage &image);
|
||||
};
|
||||
|
||||
class CardInfo : public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
@ -85,6 +104,7 @@ public:
|
|||
QPixmap *getPixmap(QSize size);
|
||||
void clearPixmapCache();
|
||||
void clearPixmapCacheMiss();
|
||||
void imageLoaded(const QImage &image);
|
||||
public slots:
|
||||
void updatePixmapCache();
|
||||
signals:
|
||||
|
@ -102,6 +122,7 @@ protected:
|
|||
bool downloadRunning;
|
||||
bool loadSuccess;
|
||||
CardInfo *noCard;
|
||||
PictureLoadingThread *loadingThread;
|
||||
private:
|
||||
void loadCardsFromXml(QXmlStreamReader &xml);
|
||||
void loadSetsFromXml(QXmlStreamReader &xml);
|
||||
|
@ -120,6 +141,8 @@ public:
|
|||
QStringList getAllColors() const;
|
||||
QStringList getAllMainCardTypes() const;
|
||||
bool getLoadSuccess() const { return loadSuccess; }
|
||||
void cacheCardPixmaps(const QStringList &cardNames);
|
||||
void loadImage(CardInfo *card);
|
||||
public slots:
|
||||
void clearPixmapCache();
|
||||
bool loadCardDatabase(const QString &path);
|
||||
|
@ -127,6 +150,7 @@ public slots:
|
|||
private slots:
|
||||
void picDownloadFinished(QNetworkReply *reply);
|
||||
void picDownloadChanged();
|
||||
void imageLoaded(CardInfo *card, QImage image);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
#include <QProgressDialog>
|
||||
#include "deck_picturecacher.h"
|
||||
#include "decklist.h"
|
||||
#include "carddatabase.h"
|
||||
#include "main.h"
|
||||
|
||||
void Deck_PictureCacher::cacheHelper(InnerDecklistNode *item, QProgressDialog *progress)
|
||||
{
|
||||
for (int i = 0; i < item->size(); i++) {
|
||||
DecklistCardNode *node = dynamic_cast<DecklistCardNode *>(item->at(i));
|
||||
if (node) {
|
||||
db->getCard(node->getName())->loadPixmap();
|
||||
progress->setValue(progress->value() + 1);
|
||||
} else
|
||||
cacheHelper(dynamic_cast<InnerDecklistNode *>(item->at(i)), progress);
|
||||
}
|
||||
}
|
||||
|
||||
void Deck_PictureCacher::cachePictures(DeckList *deck, QWidget *parent)
|
||||
{
|
||||
int totalCards = deck->getRoot()->recursiveCount();
|
||||
|
||||
QProgressDialog progress(tr("Caching card pictures..."), QString(), 0, totalCards, parent);
|
||||
progress.setMinimumDuration(1000);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
|
||||
cacheHelper(deck->getRoot(), &progress);
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef DECK_PICTURECACHER_H
|
||||
#define DECK_PICTURECACHER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class InnerDecklistNode;
|
||||
class QProgressDialog;
|
||||
class DeckList;
|
||||
class QWidget;
|
||||
|
||||
class Deck_PictureCacher : public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
static void cacheHelper(InnerDecklistNode *item, QProgressDialog *progress);
|
||||
public:
|
||||
static void cachePictures(DeckList *deck, QWidget *parent);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -18,7 +18,6 @@
|
|||
#include "zoneviewwidget.h"
|
||||
#include "deckview.h"
|
||||
#include "decklist.h"
|
||||
#include "deck_picturecacher.h"
|
||||
#include "protocol_items.h"
|
||||
#include "dlg_load_remote_deck.h"
|
||||
#include "abstractclient.h"
|
||||
|
@ -26,6 +25,7 @@
|
|||
#include "arrowitem.h"
|
||||
#include "main.h"
|
||||
#include "settingscache.h"
|
||||
#include "carddatabase.h"
|
||||
|
||||
ReadyStartButton::ReadyStartButton(QWidget *parent)
|
||||
: QPushButton(parent), readyStart(false)
|
||||
|
@ -131,7 +131,7 @@ void DeckViewContainer::deckSelectFinished(ProtocolResponse *r)
|
|||
if (!resp)
|
||||
return;
|
||||
|
||||
Deck_PictureCacher::cachePictures(resp->getDeck(), this);
|
||||
db->cacheCardPixmaps(resp->getDeck()->getCardList());
|
||||
deckView->setDeck(new DeckList(resp->getDeck()));
|
||||
readyStartButton->setEnabled(true);
|
||||
}
|
||||
|
@ -508,7 +508,7 @@ void TabGame::eventGameStateChanged(Event_GameStateChanged *event, GameEventCont
|
|||
}
|
||||
player->processPlayerInfo(pl);
|
||||
if (player->getLocal() && !pl->getDeck()->isEmpty()) {
|
||||
Deck_PictureCacher::cachePictures(pl->getDeck(), this);
|
||||
db->cacheCardPixmaps(pl->getDeck()->getCardList());
|
||||
deckViewContainers.value(player->getId())->setDeck(new DeckList(pl->getDeck()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "carddatabasemodel.h"
|
||||
#include "decklistmodel.h"
|
||||
#include "cardinfowidget.h"
|
||||
#include "deck_picturecacher.h"
|
||||
#include "dlg_cardsearch.h"
|
||||
#include "dlg_load_deck_from_clipboard.h"
|
||||
#include "main.h"
|
||||
|
@ -466,8 +465,8 @@ void WndDeckEditor::setDeck(DeckList *_deck, const QString &_lastFileName, DeckL
|
|||
deckModel->sort(1);
|
||||
deckView->expandAll();
|
||||
setWindowModified(false);
|
||||
|
||||
Deck_PictureCacher::cachePictures(_deck, this);
|
||||
|
||||
db->cacheCardPixmaps(_deck->getCardList());
|
||||
deckView->expandAll();
|
||||
setWindowModified(false);
|
||||
}
|
||||
|
|
|
@ -468,6 +468,24 @@ void DeckList::cleanList()
|
|||
setComments();
|
||||
}
|
||||
|
||||
void DeckList::getCardListHelper(InnerDecklistNode *item, QSet<QString> &result) const
|
||||
{
|
||||
for (int i = 0; i < item->size(); ++i) {
|
||||
DecklistCardNode *node = dynamic_cast<DecklistCardNode *>(item->at(i));
|
||||
if (node)
|
||||
result.insert(node->getName());
|
||||
else
|
||||
getCardListHelper(dynamic_cast<InnerDecklistNode *>(item->at(i)), result);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DeckList::getCardList() const
|
||||
{
|
||||
QSet<QString> result;
|
||||
getCardListHelper(root, result);
|
||||
return result.toList();
|
||||
}
|
||||
|
||||
DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zoneName)
|
||||
{
|
||||
InnerDecklistNode *zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <QPair>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QSet>
|
||||
#include "serializable_item.h"
|
||||
|
||||
class CardDatabase;
|
||||
|
@ -115,6 +116,7 @@ private:
|
|||
InnerDecklistNode *currentZone;
|
||||
SideboardPlan *currentSideboardPlan;
|
||||
QString currentElementText;
|
||||
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
|
||||
signals:
|
||||
void deckLoaded();
|
||||
public slots:
|
||||
|
@ -149,6 +151,7 @@ public:
|
|||
|
||||
void cleanList();
|
||||
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
|
||||
QStringList getCardList() const;
|
||||
|
||||
InnerDecklistNode *getRoot() const { return root; }
|
||||
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
|
||||
|
|
Loading…
Reference in a new issue