2022-04-21 23:42:53 +02:00
|
|
|
#include "datadragon.h"
|
|
|
|
|
|
|
|
#include <ostream>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
#include <curl/easy.h>
|
|
|
|
#include <Log.h>
|
|
|
|
|
2023-08-27 16:51:02 +02:00
|
|
|
#include <QEventLoop>
|
2022-04-21 23:42:53 +02:00
|
|
|
#include <QJsonArray>
|
|
|
|
#include <QJsonObject>
|
2023-08-27 16:51:02 +02:00
|
|
|
#include <QThread>
|
2022-04-21 23:42:53 +02:00
|
|
|
|
2022-07-02 22:25:20 +02:00
|
|
|
#include <algorithm> // std::max, champ matching
|
2022-04-23 01:53:19 +02:00
|
|
|
|
2022-04-24 01:27:46 +02:00
|
|
|
#include "json.h"
|
2022-04-21 23:42:53 +02:00
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
static const QString BASEURL = "https://ddragon.leagueoflegends.com/";
|
2022-04-23 00:39:45 +02:00
|
|
|
const DataDragon::ChampData DataDragon::EMPTYCHAMP;
|
2022-04-21 23:42:53 +02:00
|
|
|
|
2023-08-29 00:17:40 +02:00
|
|
|
DataDragon::DataDragon(const QString& locale) : RestClient(BASEURL), locale(locale), cache{{"square", ".png"}, {"loading", "_0.jpg"}, {"splash", "_0.jpg"}} {
|
2023-08-27 16:51:02 +02:00
|
|
|
this->setObjectName("DataDragon");
|
2022-04-24 12:15:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DataDragon::~DataDragon() {
|
|
|
|
stopAndJoinThread();
|
2022-04-21 23:42:53 +02:00
|
|
|
}
|
|
|
|
|
2022-04-23 00:39:45 +02:00
|
|
|
DataDragon::ChampData::ChampData() : key(-1) {}
|
|
|
|
|
2022-04-21 23:42:53 +02:00
|
|
|
DataDragon::ChampData::ChampData(const QJsonObject& source) {
|
2023-05-31 22:22:23 +02:00
|
|
|
name = getValue<QString>(source, "name", "");
|
|
|
|
id = getValue<QString>(source, "id", "");
|
2022-04-21 23:42:53 +02:00
|
|
|
key = getValue<int>(source, "key", -1);
|
2023-05-31 22:22:23 +02:00
|
|
|
partype = getValue<QString>(source, "partype", "");
|
|
|
|
title = getValue<QString>(source, "title", "");
|
2022-04-21 23:42:53 +02:00
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
const QString& DataDragon::getVersion() {
|
2022-04-24 12:15:58 +02:00
|
|
|
std::unique_lock lock(cachedatamutex);
|
2023-05-31 22:22:23 +02:00
|
|
|
while(version.isEmpty() && shouldrun) {
|
2022-04-24 12:15:58 +02:00
|
|
|
cachedatacv.wait(lock);
|
2022-04-21 23:42:53 +02:00
|
|
|
}
|
|
|
|
return version;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<DataDragon::ChampData>& DataDragon::getChamps() {
|
2022-04-24 12:15:58 +02:00
|
|
|
std::unique_lock lock(cachedatamutex);
|
|
|
|
while(champs.empty() && shouldrun) {
|
|
|
|
cachedatacv.wait(lock);
|
2022-04-21 23:42:53 +02:00
|
|
|
}
|
|
|
|
return champs;
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
QPixmap DataDragon::getImage(const QString& champid, ImageType imgtype, bool writeMemcache) {
|
|
|
|
if(champid.isEmpty()) return {};
|
2022-04-24 12:15:58 +02:00
|
|
|
|
2022-04-23 22:28:01 +02:00
|
|
|
// query mem cache
|
2022-07-02 17:44:29 +02:00
|
|
|
QPixmap img = memcache.getImage(champid, (int) imgtype);
|
|
|
|
if(!img.isNull()) return img;
|
2022-04-23 22:28:01 +02:00
|
|
|
|
|
|
|
// query HDD cache
|
|
|
|
img = cache[(int) imgtype].getImage(champid);
|
2022-07-02 17:44:29 +02:00
|
|
|
if(!img.isNull()) {
|
2022-04-23 22:28:01 +02:00
|
|
|
// update mem cache
|
|
|
|
memcache.addImage(img, champid, (int) imgtype);
|
2022-04-23 20:33:21 +02:00
|
|
|
return img;
|
2022-04-23 22:28:01 +02:00
|
|
|
}
|
2022-04-23 20:33:21 +02:00
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
const QString url = getImageUrl(champid, imgtype);
|
|
|
|
if(url.isEmpty()) return {};
|
2022-04-22 00:26:10 +02:00
|
|
|
|
2022-07-29 00:05:22 +02:00
|
|
|
|
|
|
|
QByteArray arr;
|
|
|
|
try {
|
|
|
|
arr = requestRaw(url);
|
|
|
|
} catch(RestClient::WebException& e) {}
|
2022-04-22 00:26:10 +02:00
|
|
|
if(arr.isEmpty()) {
|
2023-05-31 22:22:23 +02:00
|
|
|
qCritical() << "image could not be loaded";
|
2022-04-22 00:26:10 +02:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
// propably an error
|
|
|
|
if(arr.size() < 1000) {
|
2023-05-31 22:22:23 +02:00
|
|
|
qInfo() << "small icon url: " << url;
|
|
|
|
qInfo() << "content: " << QString::fromLocal8Bit(arr);
|
2022-04-22 00:26:10 +02:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2022-04-23 22:28:01 +02:00
|
|
|
// store HDD cache
|
2022-04-23 20:33:21 +02:00
|
|
|
cache[(int) imgtype].addImageRaw(arr, champid);
|
|
|
|
|
2022-07-05 19:39:16 +02:00
|
|
|
// remove from notDownloadedList
|
|
|
|
notDownloadedImages.erase(champid);
|
|
|
|
|
2022-07-02 17:44:29 +02:00
|
|
|
QPixmap decodedImage;
|
|
|
|
decodedImage.loadFromData(arr);
|
2022-04-23 22:28:01 +02:00
|
|
|
|
|
|
|
// store mem cache
|
2022-07-05 19:39:16 +02:00
|
|
|
if(writeMemcache) {
|
|
|
|
memcache.addImage(decodedImage, champid, (int) imgtype);
|
|
|
|
}
|
2022-04-23 22:28:01 +02:00
|
|
|
|
2022-04-22 00:26:10 +02:00
|
|
|
return decodedImage;
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
void DataDragon::getImageAsnyc(const QString& champid, notifyImgfunc_t func, ImageType imgtype) {
|
2022-04-24 12:15:58 +02:00
|
|
|
if(!func) return;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::lock_guard lock(tasksmutex);
|
|
|
|
tasks.push_back({champid, func, imgtype});
|
|
|
|
}
|
|
|
|
tasksnotemptycv.notify_one();
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
static int startinglength(const QString& original, const QString& prefix) {
|
|
|
|
int i = 0;
|
2022-04-23 01:53:19 +02:00
|
|
|
for(; i < original.size() && i < prefix.size(); ++i) {
|
2023-05-31 22:22:23 +02:00
|
|
|
if(original.left(i+1) != prefix.left(i+1)) {
|
2022-04-23 01:53:19 +02:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
static size_t matchChamp(const DataDragon::ChampData& champ, const QString& lower) {
|
|
|
|
QString lowerid = champ.id.toLower();
|
|
|
|
QString lowername = champ.name.toLower();
|
2022-04-23 01:53:19 +02:00
|
|
|
if(lowerid == lower || lowername == lower) {
|
|
|
|
return lower.size();
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
int lengtha = startinglength(lowerid, lower);
|
|
|
|
int lengthb = startinglength(lowername, lower);
|
2022-04-23 01:53:19 +02:00
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
return qMax(lengtha, lengthb);
|
2022-04-23 01:53:19 +02:00
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
const DataDragon::ChampData& DataDragon::getBestMatchingChamp(const QString& name, int* count) {
|
2022-04-23 00:39:45 +02:00
|
|
|
getChamps();
|
|
|
|
// for now: just check for a perfect hit
|
2023-05-31 22:22:23 +02:00
|
|
|
QString lower = name.toLower();
|
2022-04-23 01:53:19 +02:00
|
|
|
int bestmatchingoffset = -1;
|
2023-05-31 22:22:23 +02:00
|
|
|
int bestmatchinglength = 0;
|
2022-04-23 01:53:19 +02:00
|
|
|
uint32_t bestmatchingcount = 0;
|
|
|
|
for(size_t offset = 0; offset < champs.size(); ++offset) {
|
|
|
|
const ChampData& it = champs.at(offset);
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
int match = matchChamp(it, lower);
|
2022-04-23 01:53:19 +02:00
|
|
|
if(match > bestmatchinglength) {
|
|
|
|
bestmatchinglength = match;
|
|
|
|
bestmatchingcount = 1;
|
|
|
|
bestmatchingoffset = offset;
|
|
|
|
} else if(match == bestmatchinglength) {
|
|
|
|
bestmatchingcount ++;
|
2022-04-23 00:39:45 +02:00
|
|
|
}
|
|
|
|
}
|
2022-04-23 01:53:19 +02:00
|
|
|
|
|
|
|
if(bestmatchinglength < lower.size()) {
|
|
|
|
if(count) *count = 0;
|
|
|
|
return EMPTYCHAMP;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(count) *count = bestmatchingcount;
|
2022-04-23 16:45:23 +02:00
|
|
|
if(bestmatchingoffset >= 0)
|
2022-04-23 01:53:19 +02:00
|
|
|
return champs.at(bestmatchingoffset);
|
|
|
|
|
2022-04-23 00:39:45 +02:00
|
|
|
return EMPTYCHAMP;
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
std::vector<const DataDragon::ChampData*> DataDragon::getMatchingChamp(const QString& name, uint32_t limit) {
|
2022-07-02 22:25:20 +02:00
|
|
|
if(limit == 0) return {};
|
2023-05-31 22:22:23 +02:00
|
|
|
if(name.isEmpty()) return {};
|
2022-07-02 22:25:20 +02:00
|
|
|
|
|
|
|
getChamps();
|
2023-05-31 22:22:23 +02:00
|
|
|
QString lower = name.toLower();
|
2022-07-02 22:25:20 +02:00
|
|
|
|
|
|
|
std::vector<size_t> matches;
|
|
|
|
matches.resize(champs.size());
|
|
|
|
std::transform(champs.begin(), champs.end(), std::insert_iterator(matches, matches.begin()), std::bind(&matchChamp, std::placeholders::_1, lower));
|
|
|
|
|
|
|
|
// find smallest element
|
|
|
|
std::vector<size_t> matches_sort = matches;
|
2022-07-03 00:31:13 +02:00
|
|
|
std::nth_element(matches_sort.begin(), matches_sort.begin(), matches_sort.end(), std::greater{});
|
2022-07-02 22:25:20 +02:00
|
|
|
size_t border = matches_sort.at(0);
|
|
|
|
Log::trace << "border: " << border;
|
|
|
|
|
|
|
|
std::vector<const ChampData*> out;
|
|
|
|
out.reserve(limit);
|
|
|
|
|
|
|
|
// take all with a match higher than that
|
|
|
|
for(uint32_t i = 0; i < matches.size() && out.size() < limit; ++i) {
|
|
|
|
if(matches[i] >= border) {
|
|
|
|
out.push_back(&champs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2022-07-10 15:19:25 +02:00
|
|
|
const DataDragon::ChampData* DataDragon::getChampByID(uint32_t id) {
|
|
|
|
getChamps();
|
|
|
|
|
2022-08-20 21:46:44 +02:00
|
|
|
auto it = std::find_if(champs.begin(), champs.end(), [id](const ChampData& cd) { return cd.key == (int) id; });
|
2022-07-10 15:19:25 +02:00
|
|
|
|
|
|
|
// nothing found
|
|
|
|
if(it == champs.end()) return nullptr;
|
|
|
|
|
|
|
|
return &*it;
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
std::vector<uint32_t> DataDragon::resolveChampIDs(const std::vector<QString>& champnames) {
|
2022-07-04 22:59:48 +02:00
|
|
|
std::vector<uint32_t> out;
|
|
|
|
out.reserve(champnames.size());
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
std::transform(champnames.begin(), champnames.end(), std::insert_iterator(out, out.begin()), [this](const QString& champname) {
|
2022-07-04 22:59:48 +02:00
|
|
|
auto cd = getBestMatchingChamp(champname);
|
|
|
|
return cd.key; // might be 0 (invalid)
|
|
|
|
});
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2023-08-27 16:51:02 +02:00
|
|
|
void DataDragon::startThread() {
|
|
|
|
shouldrun = true;
|
|
|
|
bgthread = QThread::create(&DataDragon::threadLoop, this);
|
|
|
|
bgthread->setObjectName("DataDragonThread");
|
|
|
|
bgthread->start();
|
|
|
|
this->moveToThread(bgthread);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataDragon::stop() {
|
|
|
|
qDebug() << "stop DataDragon";
|
|
|
|
shouldrun = false;
|
|
|
|
std::unique_lock lock(tasksmutex);
|
|
|
|
|
|
|
|
tasks.clear();
|
|
|
|
notDownloadedImages.clear(); // this is a possible race condition!
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
QString DataDragon::getImageUrl(const QString& champid, ImageType type) {
|
2022-04-24 12:15:58 +02:00
|
|
|
switch(type) {
|
|
|
|
case ImageType::SQUARE: {
|
2023-05-31 22:22:23 +02:00
|
|
|
if(getVersion().isEmpty()) {
|
2022-04-24 12:15:58 +02:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
// with version
|
|
|
|
return getCDNString() + "img/champion/" + champid + ".png";
|
|
|
|
}
|
|
|
|
case ImageType::LOADING:
|
|
|
|
// no version
|
|
|
|
return "cdn/img/champion/loading/" + champid + "_0.jpg";
|
|
|
|
case ImageType::SPLASH:
|
|
|
|
// no version
|
|
|
|
return "cdn/img/champion/splash/" + champid + "_0.jpg";
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
QString DataDragon::getCDNString() const {
|
2022-04-22 00:26:10 +02:00
|
|
|
return "cdn/" + version + "/";
|
|
|
|
}
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
void DataDragon::prefetchChampImage(const QString& champid, ImageType imgtype) {
|
2022-07-05 19:39:16 +02:00
|
|
|
if(!cache[(int) imgtype].hasImage(champid)) {
|
2023-05-31 22:22:23 +02:00
|
|
|
qDebug() << "prefetch " << champid << " type: " << (int) imgtype;
|
2022-07-05 19:39:16 +02:00
|
|
|
getImage(champid, imgtype, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:15:58 +02:00
|
|
|
void DataDragon::getVersionInternal() {
|
|
|
|
std::unique_lock lock(cachedatamutex);
|
|
|
|
|
2023-05-31 22:22:23 +02:00
|
|
|
if(!version.isEmpty()) return;
|
2022-04-24 12:15:58 +02:00
|
|
|
|
2022-07-05 23:45:28 +02:00
|
|
|
version = champCache.getVersion();
|
2023-05-31 22:22:23 +02:00
|
|
|
if(!version.isEmpty()) return;
|
2022-07-05 23:45:28 +02:00
|
|
|
|
2022-07-29 00:05:22 +02:00
|
|
|
try {
|
|
|
|
QJsonDocument jversions = request("api/versions.json");
|
|
|
|
if(jversions.isArray()) {
|
|
|
|
QJsonArray jverarr = jversions.array();
|
|
|
|
if(!jverarr.empty()) {
|
2023-05-31 22:22:23 +02:00
|
|
|
version = jverarr.at(0).toString();
|
|
|
|
qInfo() << "got League version: " << version;
|
2022-07-29 00:05:22 +02:00
|
|
|
|
|
|
|
lock.unlock();
|
|
|
|
cachedatacv.notify_all();
|
|
|
|
return;
|
|
|
|
}
|
2022-04-24 12:15:58 +02:00
|
|
|
}
|
2023-05-31 22:22:23 +02:00
|
|
|
qCritical() << "error parsing version object";
|
2022-07-29 00:05:22 +02:00
|
|
|
} catch(RestClient::WebException& e) {}
|
2022-04-24 12:15:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataDragon::getChampsInternal() {
|
|
|
|
std::unique_lock lock(cachedatamutex);
|
2023-05-31 22:22:23 +02:00
|
|
|
if(!champs.empty() && version.isEmpty()) {
|
2022-04-24 12:15:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-05 23:45:28 +02:00
|
|
|
QJsonDocument jchamps = champCache.getChamps();
|
2022-07-17 01:22:31 +02:00
|
|
|
bool cacheSuccessfull = !jchamps.isEmpty();
|
|
|
|
if(!cacheSuccessfull) {
|
2022-07-29 00:05:22 +02:00
|
|
|
try {
|
2022-07-05 23:45:28 +02:00
|
|
|
jchamps = request(getCDNString() + "data/" + locale + "/champion.json");
|
2022-07-29 00:05:22 +02:00
|
|
|
if(jchamps.isEmpty()) {
|
|
|
|
// try again with default locale
|
|
|
|
locale = "en_US";
|
|
|
|
jchamps = request(getCDNString() + "data/" + locale + "/champion.json");
|
|
|
|
}
|
|
|
|
} catch(RestClient::WebException& e) {}
|
2022-04-24 13:09:28 +02:00
|
|
|
}
|
2022-04-24 12:15:58 +02:00
|
|
|
if(jchamps.isObject()) {
|
2022-07-05 23:45:28 +02:00
|
|
|
// save to cache
|
2022-07-17 01:22:31 +02:00
|
|
|
if(!cacheSuccessfull) {
|
|
|
|
champCache.saveChamps(jchamps, version);
|
|
|
|
}
|
2022-07-05 23:45:28 +02:00
|
|
|
|
2022-04-24 12:15:58 +02:00
|
|
|
QJsonObject obj = jchamps.object();
|
|
|
|
auto it = obj.constFind("data");
|
2023-08-29 00:18:24 +02:00
|
|
|
if(it != obj.constEnd() && it->isObject()) {
|
|
|
|
for(auto&& champdata : it->toObject()) {
|
|
|
|
if(champdata.isObject()) {
|
|
|
|
auto& dataobj = champs.emplace_back(champdata.toObject());
|
|
|
|
notDownloadedImages.insert(dataobj.id);
|
2022-04-24 12:15:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-05-31 22:22:23 +02:00
|
|
|
qInfo() << "loaded " << champs.size() << " champs from cache: " << cacheSuccessfull;
|
2022-04-24 12:15:58 +02:00
|
|
|
lock.unlock();
|
|
|
|
cachedatacv.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataDragon::stopThread() {
|
|
|
|
shouldrun = false;
|
|
|
|
tasksnotemptycv.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataDragon::stopAndJoinThread() {
|
|
|
|
stopThread();
|
|
|
|
|
2023-08-27 16:51:02 +02:00
|
|
|
bgthread->wait();
|
2022-04-24 12:15:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DataDragon::threadLoop() {
|
2023-08-27 16:51:02 +02:00
|
|
|
QEventLoop loop;
|
|
|
|
|
2022-04-24 12:15:58 +02:00
|
|
|
// init version and champ list
|
|
|
|
getVersionInternal();
|
|
|
|
getChampsInternal();
|
|
|
|
|
|
|
|
while(shouldrun) {
|
|
|
|
// wait for a task in the list
|
|
|
|
Task t;
|
|
|
|
{
|
|
|
|
std::unique_lock lock(tasksmutex);
|
|
|
|
if(tasks.empty()) {
|
2022-07-05 19:39:16 +02:00
|
|
|
if(notDownloadedImages.empty()) {
|
|
|
|
tasksnotemptycv.wait(lock);
|
|
|
|
} else {
|
|
|
|
Log::note << "DataDragon background thread is idleing - prefetching champion images TODO: " << notDownloadedImages.size();
|
|
|
|
|
2023-08-27 16:51:02 +02:00
|
|
|
while(shouldrun && !notDownloadedImages.empty() && tasks.empty()) {
|
2022-07-05 19:39:16 +02:00
|
|
|
lock.unlock();
|
|
|
|
|
|
|
|
auto it = notDownloadedImages.begin();
|
2023-08-29 00:18:08 +02:00
|
|
|
auto champid = std::move(notDownloadedImages.extract(it).value());
|
2022-07-05 19:39:16 +02:00
|
|
|
|
|
|
|
prefetchChampImage(champid, ImageType::SQUARE);
|
|
|
|
|
2023-08-27 16:51:02 +02:00
|
|
|
emit this->loading(1.0 - (notDownloadedImages.size() / (float) champs.size()));
|
|
|
|
emit this->fetchingChamp(champid);
|
|
|
|
|
2022-07-05 19:39:16 +02:00
|
|
|
lock.lock();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(notDownloadedImages.empty() && tasks.empty()) {
|
|
|
|
// everything prefetched, but nothing more to do
|
2022-07-17 01:22:31 +02:00
|
|
|
static bool once = false;
|
|
|
|
if(!once) {
|
|
|
|
once = true;
|
|
|
|
Log::note << "all champs are prefetched now";
|
2023-08-27 16:51:02 +02:00
|
|
|
emit this->loading( 1.0 );
|
2022-07-17 01:22:31 +02:00
|
|
|
}
|
|
|
|
|
2022-07-05 19:39:16 +02:00
|
|
|
tasksnotemptycv.wait(lock);
|
|
|
|
}
|
|
|
|
}
|
2022-04-24 12:15:58 +02:00
|
|
|
}
|
2023-08-27 16:51:02 +02:00
|
|
|
|
2022-04-24 12:15:58 +02:00
|
|
|
if(tasks.empty()) continue;
|
|
|
|
|
|
|
|
t = tasks.front();
|
|
|
|
tasks.pop_front();
|
|
|
|
}
|
|
|
|
|
2023-08-27 16:51:02 +02:00
|
|
|
loop.processEvents();
|
|
|
|
|
2022-07-02 17:44:29 +02:00
|
|
|
QPixmap img = getImage(t.champid, t.type);
|
2022-04-24 12:15:58 +02:00
|
|
|
t.func(img);
|
|
|
|
}
|
|
|
|
|
2023-08-27 16:51:02 +02:00
|
|
|
qDebug() << "DataDragon Thread terminated";
|
|
|
|
}
|
2022-04-24 12:15:58 +02:00
|
|
|
|
2022-04-21 23:42:53 +02:00
|
|
|
std::ostream& operator<<(std::ostream& str, const DataDragon::ChampData& cd) {
|
2023-05-31 22:22:23 +02:00
|
|
|
return str << "[n: " << cd.name.toStdString() << " " << " k: " << cd.key << " id: " << cd.id.toStdString() << "]";
|
2022-04-21 23:42:53 +02:00
|
|
|
}
|