Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F131771
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
R77 Guitar
Attached
Detach File
Event Timeline