Make it repaint after downloading the image

This commit is contained in:
Mm2PL 2023-12-02 02:32:11 +01:00
parent 6223e3461e
commit a56d6b084c
No known key found for this signature in database
GPG key ID: 94AC9B80EFA15ED9
4 changed files with 50 additions and 5 deletions

View file

@ -24,6 +24,7 @@
#include <functional> #include <functional>
#include <queue> #include <queue>
#include <thread> #include <thread>
#include <utility>
// Duration between each check of every Image instance // Duration between each check of every Image instance
const auto IMAGE_POOL_CLEANUP_INTERVAL = std::chrono::minutes(1); const auto IMAGE_POOL_CLEANUP_INTERVAL = std::chrono::minutes(1);
@ -423,7 +424,7 @@ bool Image::loaded() const
return this->frames_->current().has_value(); return this->frames_->current().has_value();
} }
std::optional<QPixmap> Image::pixmapOrLoad() const std::optional<QPixmap> Image::pixmapOrLoad(std::function<void()> cb)
{ {
assertInGuiThread(); assertInGuiThread();
@ -432,6 +433,10 @@ std::optional<QPixmap> Image::pixmapOrLoad() const
// See src/messages/layouts/MessageLayoutElement.cpp ImageLayoutElement::paint, for example. // See src/messages/layouts/MessageLayoutElement.cpp ImageLayoutElement::paint, for example.
this->lastUsed_ = std::chrono::steady_clock::now(); this->lastUsed_ = std::chrono::steady_clock::now();
if (cb != nullptr)
{
this->finishedLoadingCb_ = std::move(cb);
}
this->load(); this->load();
return this->frames_->current(); return this->frames_->current();
@ -574,6 +579,20 @@ void Image::actuallyLoad()
return true; return true;
}) })
.finally([weak]() {
postToThread([weak]() {
auto shared = weak.lock();
if (!shared)
{
return;
}
if (shared->finishedLoadingCb_ != nullptr)
{
shared->finishedLoadingCb_();
}
});
})
.execute(); .execute();
} }

View file

@ -2,6 +2,7 @@
#include "common/Aliases.hpp" #include "common/Aliases.hpp"
#include "common/Common.hpp" #include "common/Common.hpp"
#include "common/NetworkResult.hpp"
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <pajlada/signals/signal.hpp> #include <pajlada/signals/signal.hpp>
@ -13,6 +14,7 @@
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <functional>
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -80,7 +82,7 @@ public:
const Url &url() const; const Url &url() const;
bool loaded() const; bool loaded() const;
// either returns the current pixmap, or triggers loading it (lazy loading) // either returns the current pixmap, or triggers loading it (lazy loading)
std::optional<QPixmap> pixmapOrLoad() const; std::optional<QPixmap> pixmapOrLoad(std::function<void()> cb = nullptr);
void load() const; void load() const;
qreal scale() const; qreal scale() const;
bool isEmpty() const; bool isEmpty() const;
@ -111,6 +113,8 @@ private:
// gui thread only // gui thread only
std::unique_ptr<detail::Frames> frames_{}; std::unique_ptr<detail::Frames> frames_{};
std::function<void()> finishedLoadingCb_;
friend class ImageExpirationPool; friend class ImageExpirationPool;
}; };

View file

@ -1,19 +1,26 @@
#pragma once #pragma once
#include "common/QLogging.hpp"
#include "messages/Image.hpp" #include "messages/Image.hpp"
#include "messages/ImageSet.hpp" #include "messages/ImageSet.hpp"
#include <QModelIndex> #include <QModelIndex>
#include <qnamespace.h>
#include <QPainter> #include <QPainter>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <Qt>
#include <QTableView>
namespace chatterino { namespace chatterino {
class ImagePtrItemDelegate : public QStyledItemDelegate class ImagePtrItemDelegate : public QStyledItemDelegate
{ {
std::map<QString, ImagePtr> ownedImages_; std::map<QString, ImagePtr> ownedImages_;
QTableView *view_;
public: public:
ImagePtrItemDelegate(QTableView *view)
: view_(view)
{
}
static constexpr auto IMAGE_URL_ROLE = Qt::UserRole + 1; static constexpr auto IMAGE_URL_ROLE = Qt::UserRole + 1;
void paint(QPainter *painter, const QStyleOptionViewItem &option, void paint(QPainter *painter, const QStyleOptionViewItem &option,
@ -27,6 +34,14 @@ public:
auto opt = img->pixmapOrLoad(); auto opt = img->pixmapOrLoad();
if (!opt) // wait for next time if (!opt) // wait for next time
{ {
if (img->isEmpty())
{
painter->drawText(option.rect, "[Error]");
}
else
{
painter->drawText(option.rect, "Loading");
}
return; return;
} }
auto pixmap = *opt; auto pixmap = *opt;
@ -56,7 +71,14 @@ public:
} }
auto img = Image::fromUrl(Url{url}); auto img = Image::fromUrl(Url{url});
img->pixmapOrLoad(); img->pixmapOrLoad([this, index]() {
// wait for it to parse
QTimer::singleShot(100, [this, index]() {
this->view_->repaint();
this->view_->update(index);
});
});
// You cannot stop me, clang-tidy // You cannot stop me, clang-tidy
auto *bleh = const_cast<ImagePtrItemDelegate *>(this); auto *bleh = const_cast<ImagePtrItemDelegate *>(this);
bleh->ownedImages_[url] = img; bleh->ownedImages_[url] = img;

View file

@ -21,7 +21,6 @@
namespace chatterino { namespace chatterino {
ImageUploaderPage::ImageUploaderPage() ImageUploaderPage::ImageUploaderPage()
: imgDelegate_(new ImagePtrItemDelegate())
{ {
LayoutCreator<ImageUploaderPage> layoutCreator(this); LayoutCreator<ImageUploaderPage> layoutCreator(this);
auto tabs = layoutCreator.emplace<QTabWidget>(); auto tabs = layoutCreator.emplace<QTabWidget>();
@ -42,6 +41,7 @@ ImageUploaderPage::ImageUploaderPage()
auto *view = layout.emplace<QTableView>().getElement(); auto *view = layout.emplace<QTableView>().getElement();
view->setModel(model); view->setModel(model);
this->imgDelegate_ = new ImagePtrItemDelegate(view);
view->setItemDelegateForColumn(0, this->imgDelegate_); view->setItemDelegateForColumn(0, this->imgDelegate_);
view->setSelectionMode(QAbstractItemView::SingleSelection); view->setSelectionMode(QAbstractItemView::SingleSelection);