Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None
diff --git a/src/AvatarLoader.cpp b/src/AvatarLoader.cpp
index 09818c7..01f0398 100644
--- a/src/AvatarLoader.cpp
+++ b/src/AvatarLoader.cpp
@@ -1,189 +1,157 @@
#include "AvatarLoader.h"
#include "BasicMainWindow.h"
#include "MemoryReader.h"
#include "webclient.h"
-
#include <QCryptographicHash>
#include <QDebug>
+#include <QWaitCondition>
namespace {
const int MAX_CACHE_COUNT = 1000;
const int ICON_SIZE = 64;
}
using WebClientPtr = std::shared_ptr<WebClient>;
struct AvatarLoader::Private {
- QMutex data_mutex;
- QMutex thread_mutex;
+ QMutex mutex;
QWaitCondition condition;
- std::map<std::string, std::string> avatar_url_cache;
std::deque<RequestItem> requested;
std::deque<RequestItem> completed;
- std::set<std::string> notfound;
BasicMainWindow *mainwindow = nullptr;
WebClientPtr web;
};
AvatarLoader::AvatarLoader()
: m(new Private)
{
}
AvatarLoader::~AvatarLoader()
{
delete m;
}
void AvatarLoader::start(BasicMainWindow *mainwindow)
{
m->mainwindow = mainwindow;
QThread::start();
}
void AvatarLoader::run()
{
m->web = std::make_shared<WebClient>(m->mainwindow->webContext());
while (1) {
- std::deque<RequestItem> requests;
-
if (isInterruptionRequested()) return;
- m->thread_mutex.lock();
+ std::deque<RequestItem> requests;
{
- QMutexLocker lock(&m->data_mutex);
- requests = std::move(m->requested);
- }
- if (requests.empty()) {
- m->condition.wait(&m->thread_mutex);
- {
- QMutexLocker lock(&m->data_mutex);
- requests = std::move(m->requested);
+ QMutexLocker lock(&m->mutex);
+ if (m->requested.empty()) {
+ m->condition.wait(&m->mutex);
+ }
+ if (!m->requested.empty()) {
+ std::swap(requests, m->requested);
}
}
- m->thread_mutex.unlock();
-
-// if (!m->mainwindow->isRemoteOnline()) continue;
-
- if (isInterruptionRequested()) return;
for (RequestItem &item : requests) {
if (isInterruptionRequested()) return;
if (item.email.empty()) continue;
if (strchr(item.email.c_str(), '@')) {
- QCryptographicHash hash(QCryptographicHash::Md5);
- hash.addData(item.email.c_str(), item.email.size());
- QByteArray ba = hash.result();
- char tmp[100];
- for (int i = 0; i < ba.size(); i++) {
- sprintf(tmp + i * 2, "%02x", ba.data()[i] & 0xff);
+ QString id;
+ {
+ QCryptographicHash hash(QCryptographicHash::Md5);
+ hash.addData(item.email.c_str(), item.email.size());
+ QByteArray ba = hash.result();
+ char tmp[100];
+ for (int i = 0; i < ba.size(); i++) {
+ sprintf(tmp + i * 2, "%02x", ba.data()[i] & 0xff);
+ }
+ id = tmp;
}
- QString id = tmp;
QString url = "https://www.gravatar.com/avatar/%1?s=%2";
url = url.arg(id).arg(ICON_SIZE);
if (m->web->get(WebClient::URL(url.toStdString())) == 200) {
if (!m->web->response().content.empty()) {
MemoryReader reader(m->web->response().content.data(), m->web->response().content.size());
reader.open(MemoryReader::ReadOnly);
QImage image;
image.load(&reader, nullptr);
int w = image.width();
int h = image.height();
if (w > 0 && h > 0) {
- item.icon = QIcon(QPixmap::fromImage(image));
+ item.image = image;
{
- QMutexLocker lock(&m->data_mutex);
+ QMutexLocker lock(&m->mutex);
while (m->completed.size() >= MAX_CACHE_COUNT) {
m->completed.pop_back();
}
m->completed.push_front(item);
}
emit updated();
continue;
}
}
} else {
m->mainwindow->emitWriteLog(QString("Failed to fetch the avatar.\n").toUtf8());
QString msg = QString::fromStdString(m->web->error().message() + '\n');
m->mainwindow->emitWriteLog(msg.toUtf8());
}
}
- { // not found
- QMutexLocker lock(&m->data_mutex);
- m->notfound.insert(m->notfound.end(), item.email);
- }
- }
- }
-}
-
-namespace {
-bool isValidGitHubName(std::string const &name)
-{
- size_t n = name.size();
- if (n < 1 || n > 39) return false;
- char const *begin = name.c_str();
- char const *end = begin + name.size();
- char const *ptr = begin;
- while (ptr < end) {
- int c = (unsigned char)*ptr;
- ptr++;
- if (isalnum(c)) {
- // ok
- } else if (c == '-') {
- if (ptr == begin) return false;
- if (ptr < end && *ptr == '-') return false;
}
}
- return true;
-}
-
}
QIcon AvatarLoader::fetch(std::string const &email, bool request) const
{
+ QMutexLocker lock(&m->mutex);
RequestItem item;
item.email = email;
- if (isValidGitHubName(item.email)) {
- QMutexLocker lock(&m->data_mutex);
-
- auto it = m->notfound.find(item.email);
- if (it == m->notfound.end()) {
- for (size_t i = 0; i < m->completed.size(); i++) {
- if (item.email == m->completed[i].email) {
- item = m->completed[i];
- m->completed.erase(m->completed.begin() + i);
- m->completed.insert(m->completed.begin(), item);
- return item.icon;
- }
- }
- if (request) {
- bool waiting = false;
- for (RequestItem const &r : m->requested) {
- if (item.email == r.email) {
- waiting = true;
- break;
- }
- }
- if (!waiting) {
- m->requested.push_back(item);
- m->condition.wakeOne();
- }
+ for (size_t i = 0; i < m->completed.size(); i++) {
+ if (item.email == m->completed[i].email) {
+ item = m->completed[i];
+ m->completed.erase(m->completed.begin() + i);
+ m->completed.insert(m->completed.begin(), item);
+ return QIcon(QPixmap::fromImage(item.image));
+ }
+ }
+ if (request) {
+ bool waiting = false;
+ for (RequestItem const &r : m->requested) {
+ if (item.email == r.email) {
+ waiting = true;
+ break;
}
}
+ if (!waiting) {
+ m->requested.push_back(item);
+ m->condition.wakeOne();
+ }
}
return QIcon();
}
void AvatarLoader::stop()
{
- requestInterruption();
- if (m->web) m->web->close();
- m->condition.wakeAll();
- wait();
+ {
+ QMutexLocker lock(&m->mutex);
+ requestInterruption();
+ m->requested.clear();
+ m->condition.wakeAll();
+ }
+ if (!wait(3000)) {
+ terminate();
+ }
+ if (m->web) {
+ m->web->close();
+ m->web.reset();
+ }
+ m->completed.clear();
}
diff --git a/src/AvatarLoader.h b/src/AvatarLoader.h
index 95c73b7..b43c433 100644
--- a/src/AvatarLoader.h
+++ b/src/AvatarLoader.h
@@ -1,38 +1,37 @@
#ifndef AVATARLOADER_H
#define AVATARLOADER_H
#include "GitHubAPI.h"
#include <QIcon>
#include <QThread>
#include <QMutex>
#include <deque>
-#include <QWaitCondition>
#include <set>
#include <string>
class BasicMainWindow;
class WebContext;
class AvatarLoader : public QThread {
Q_OBJECT
private:
struct RequestItem {
std::string email;
- QIcon icon;
+ QImage image;
};
struct Private;
Private *m;
protected:
void run() override;
public:
AvatarLoader();
~AvatarLoader() override;
QIcon fetch(std::string const &email, bool request) const;
void stop();
void start(BasicMainWindow *mainwindow);
signals:
void updated();
};
#endif // AVATARLOADER_H

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:20 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71075
Default Alt Text
(6 KB)

Event Timeline