mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 12:38:48 +03:00
Improve color generation performance
Colors are generated asynchronously now and the TimelineItem is updated when the color generation finishes. This allows the UI to stay responsive while new colors are being generated.
This commit is contained in:
parent
bb345a9a9f
commit
13663ad5f8
3 changed files with 53 additions and 27 deletions
|
@ -399,7 +399,6 @@ utils::hashQString(const QString &input)
|
||||||
QString
|
QString
|
||||||
utils::generateContrastingHexColor(const QString &input, const QString &background)
|
utils::generateContrastingHexColor(const QString &input, const QString &background)
|
||||||
{
|
{
|
||||||
nhlog::ui()->debug("Background hex {}", background.toStdString());
|
|
||||||
const QColor backgroundCol(background);
|
const QColor backgroundCol(background);
|
||||||
const qreal backgroundLum = luminance(background);
|
const qreal backgroundLum = luminance(background);
|
||||||
|
|
||||||
|
@ -407,8 +406,6 @@ utils::generateContrastingHexColor(const QString &input, const QString &backgrou
|
||||||
auto hash = hashQString(input);
|
auto hash = hashQString(input);
|
||||||
// create a hue value based on the hash of the input.
|
// create a hue value based on the hash of the input.
|
||||||
auto userHue = qAbs(hash % 360);
|
auto userHue = qAbs(hash % 360);
|
||||||
nhlog::ui()->debug(
|
|
||||||
"User Hue {} : {}", input.toStdString(), QString::number(userHue).toStdString());
|
|
||||||
// start with moderate saturation and lightness values.
|
// start with moderate saturation and lightness values.
|
||||||
auto sat = 220;
|
auto sat = 220;
|
||||||
auto lightness = 125;
|
auto lightness = 125;
|
||||||
|
@ -430,7 +427,6 @@ utils::generateContrastingHexColor(const QString &input, const QString &backgrou
|
||||||
// saturation instead.
|
// saturation instead.
|
||||||
if (lightness == 242 || lightness == 13) {
|
if (lightness == 242 || lightness == 13) {
|
||||||
qreal newSat = qBound(26.0, sat * 1.25, 242.0);
|
qreal newSat = qBound(26.0, sat * 1.25, 242.0);
|
||||||
nhlog::ui()->info("newSat {}", QString::number(newSat).toStdString());
|
|
||||||
|
|
||||||
inputColor.setHsl(userHue, qFloor(newSat), lightness);
|
inputColor.setHsl(userHue, qFloor(newSat), lightness);
|
||||||
auto tmpLum = luminance(inputColor);
|
auto tmpLum = luminance(inputColor);
|
||||||
|
@ -477,11 +473,6 @@ utils::generateContrastingHexColor(const QString &input, const QString &backgrou
|
||||||
// get the hex value of the generated color.
|
// get the hex value of the generated color.
|
||||||
auto colorHex = inputColor.name();
|
auto colorHex = inputColor.name();
|
||||||
|
|
||||||
nhlog::ui()->debug("Hex Generated for {}: [hex: {}, contrast: {}, luminance: {}]",
|
|
||||||
input.toStdString(),
|
|
||||||
colorHex.toStdString(),
|
|
||||||
QString::number(contrast).toStdString(),
|
|
||||||
QString::number(lum).toStdString());
|
|
||||||
return colorHex;
|
return colorHex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <QContextMenuEvent>
|
#include <QContextMenuEvent>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
@ -197,6 +198,12 @@ TimelineItem::init()
|
||||||
connect(markAsRead_, &QAction::triggered, this, &TimelineItem::sendReadReceipt);
|
connect(markAsRead_, &QAction::triggered, this, &TimelineItem::sendReadReceipt);
|
||||||
connect(viewRawMessage_, &QAction::triggered, this, &TimelineItem::openRawMessageViewer);
|
connect(viewRawMessage_, &QAction::triggered, this, &TimelineItem::openRawMessageViewer);
|
||||||
|
|
||||||
|
colorGenerating_ = new QFutureWatcher<QString>(this);
|
||||||
|
connect(colorGenerating_,
|
||||||
|
&QFutureWatcher<QString>::finished,
|
||||||
|
this,
|
||||||
|
&TimelineItem::finishedGeneratingColor);
|
||||||
|
|
||||||
topLayout_ = new QHBoxLayout(this);
|
topLayout_ = new QHBoxLayout(this);
|
||||||
mainLayout_ = new QVBoxLayout;
|
mainLayout_ = new QVBoxLayout;
|
||||||
messageLayout_ = new QHBoxLayout;
|
messageLayout_ = new QHBoxLayout;
|
||||||
|
@ -557,6 +564,12 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Text>
|
||||||
adjustMessageLayout();
|
adjustMessageLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimelineItem::~TimelineItem()
|
||||||
|
{
|
||||||
|
colorGenerating_->cancel();
|
||||||
|
colorGenerating_->waitForFinished();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineItem::markSent()
|
TimelineItem::markSent()
|
||||||
{
|
{
|
||||||
|
@ -607,16 +620,39 @@ TimelineItem::generateBody(const QString &body)
|
||||||
void
|
void
|
||||||
TimelineItem::refreshAuthorColor()
|
TimelineItem::refreshAuthorColor()
|
||||||
{
|
{
|
||||||
|
// Cancel and wait if we are already generating the color.
|
||||||
|
if (colorGenerating_->isRunning()) {
|
||||||
|
colorGenerating_->cancel();
|
||||||
|
colorGenerating_->waitForFinished();
|
||||||
|
}
|
||||||
if (userName_) {
|
if (userName_) {
|
||||||
|
// generate user's unique color.
|
||||||
|
std::function<QString()> generate = [this]() {
|
||||||
|
QString userColor = utils::generateContrastingHexColor(
|
||||||
|
userName_->toolTip(), backgroundColor().name());
|
||||||
|
return userColor;
|
||||||
|
};
|
||||||
|
|
||||||
QString userColor = Cache::userColor(userName_->toolTip());
|
QString userColor = Cache::userColor(userName_->toolTip());
|
||||||
|
|
||||||
|
// If the color is empty, then generate it asynchronously
|
||||||
if (userColor.isEmpty()) {
|
if (userColor.isEmpty()) {
|
||||||
// This attempts to refresh this item since it's not drawn
|
colorGenerating_->setFuture(QtConcurrent::run(generate));
|
||||||
// which allows us to get the background color accurately.
|
} else {
|
||||||
qApp->style()->polish(this);
|
userName_->setStyleSheet("QLabel { color : " + userColor + "; }");
|
||||||
// generate user's unique color.
|
}
|
||||||
auto backCol = backgroundColor().name();
|
}
|
||||||
userColor =
|
}
|
||||||
utils::generateContrastingHexColor(userName_->toolTip(), backCol);
|
|
||||||
|
void
|
||||||
|
TimelineItem::finishedGeneratingColor()
|
||||||
|
{
|
||||||
|
nhlog::ui()->debug("finishedGeneratingColor for: {}", userName_->toolTip().toStdString());
|
||||||
|
QString userColor = colorGenerating_->result();
|
||||||
|
|
||||||
|
if (!userColor.isEmpty()) {
|
||||||
|
// another TimelineItem might have inserted in the meantime.
|
||||||
|
if (Cache::userColor(userName_->toolTip()).isEmpty()) {
|
||||||
Cache::insertUserColor(userName_->toolTip(), userColor);
|
Cache::insertUserColor(userName_->toolTip(), userColor);
|
||||||
}
|
}
|
||||||
userName_->setStyleSheet("QLabel { color : " + userColor + "; }");
|
userName_->setStyleSheet("QLabel { color : " + userColor + "; }");
|
||||||
|
@ -656,17 +692,9 @@ TimelineItem::generateUserName(const QString &user_id, const QString &displaynam
|
||||||
userName_->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
userName_->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||||
userName_->setFixedWidth(QFontMetrics(userName_->font()).width(userName_->text()));
|
userName_->setFixedWidth(QFontMetrics(userName_->font()).width(userName_->text()));
|
||||||
|
|
||||||
// TimelineItem isn't displayed. This forces the QSS to get
|
// Set the user color asynchronously if it hasn't been generated yet,
|
||||||
// loaded.
|
// otherwise this will just set it.
|
||||||
QString userColor = Cache::userColor(user_id);
|
refreshAuthorColor();
|
||||||
if (userColor.isEmpty()) {
|
|
||||||
qApp->style()->polish(this);
|
|
||||||
// generate user's unique color.
|
|
||||||
auto backCol = backgroundColor().name();
|
|
||||||
userColor = utils::generateContrastingHexColor(user_id, backCol);
|
|
||||||
Cache::insertUserColor(user_id, userColor);
|
|
||||||
}
|
|
||||||
userName_->setStyleSheet("QLabel { color : " + userColor + "; }");
|
|
||||||
|
|
||||||
auto filter = new UserProfileFilter(user_id, userName_);
|
auto filter = new UserProfileFilter(user_id, userName_);
|
||||||
userName_->installEventFilter(filter);
|
userName_->installEventFilter(filter);
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
#include "AvatarProvider.h"
|
#include "AvatarProvider.h"
|
||||||
#include "RoomInfoListItem.h"
|
#include "RoomInfoListItem.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
@ -204,6 +206,8 @@ public:
|
||||||
const QString &room_id,
|
const QString &room_id,
|
||||||
QWidget *parent);
|
QWidget *parent);
|
||||||
|
|
||||||
|
~TimelineItem();
|
||||||
|
|
||||||
void setBackgroundColor(const QColor &color) { backgroundColor_ = color; }
|
void setBackgroundColor(const QColor &color) { backgroundColor_ = color; }
|
||||||
QColor backgroundColor() const { return backgroundColor_; }
|
QColor backgroundColor() const { return backgroundColor_; }
|
||||||
|
|
||||||
|
@ -229,6 +233,7 @@ signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refreshAuthorColor();
|
void refreshAuthorColor();
|
||||||
|
void finishedGeneratingColor();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
@ -264,6 +269,8 @@ private:
|
||||||
//! has been acknowledged by the server.
|
//! has been acknowledged by the server.
|
||||||
bool isReceived_ = false;
|
bool isReceived_ = false;
|
||||||
|
|
||||||
|
QFutureWatcher<QString> *colorGenerating_;
|
||||||
|
|
||||||
QString replaceEmoji(const QString &body);
|
QString replaceEmoji(const QString &body);
|
||||||
QString event_id_;
|
QString event_id_;
|
||||||
QString room_id_;
|
QString room_id_;
|
||||||
|
|
Loading…
Reference in a new issue