From 13663ad5f894f035a47efd5704e84f07d68b3df2 Mon Sep 17 00:00:00 2001 From: redsky17 Date: Fri, 8 Feb 2019 01:58:00 +0000 Subject: 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. --- src/timeline/TimelineItem.cpp | 64 +++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 18 deletions(-) (limited to 'src/timeline/TimelineItem.cpp') diff --git a/src/timeline/TimelineItem.cpp b/src/timeline/TimelineItem.cpp index 1c90eade..d23dbf49 100644 --- a/src/timeline/TimelineItem.cpp +++ b/src/timeline/TimelineItem.cpp @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include #include #include @@ -197,6 +198,12 @@ TimelineItem::init() connect(markAsRead_, &QAction::triggered, this, &TimelineItem::sendReadReceipt); connect(viewRawMessage_, &QAction::triggered, this, &TimelineItem::openRawMessageViewer); + colorGenerating_ = new QFutureWatcher(this); + connect(colorGenerating_, + &QFutureWatcher::finished, + this, + &TimelineItem::finishedGeneratingColor); + topLayout_ = new QHBoxLayout(this); mainLayout_ = new QVBoxLayout; messageLayout_ = new QHBoxLayout; @@ -557,6 +564,12 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent adjustMessageLayout(); } +TimelineItem::~TimelineItem() +{ + colorGenerating_->cancel(); + colorGenerating_->waitForFinished(); +} + void TimelineItem::markSent() { @@ -607,16 +620,39 @@ TimelineItem::generateBody(const QString &body) void TimelineItem::refreshAuthorColor() { + // Cancel and wait if we are already generating the color. + if (colorGenerating_->isRunning()) { + colorGenerating_->cancel(); + colorGenerating_->waitForFinished(); + } if (userName_) { + // generate user's unique color. + std::function generate = [this]() { + QString userColor = utils::generateContrastingHexColor( + userName_->toolTip(), backgroundColor().name()); + return userColor; + }; + QString userColor = Cache::userColor(userName_->toolTip()); + + // If the color is empty, then generate it asynchronously if (userColor.isEmpty()) { - // This attempts to refresh this item since it's not drawn - // which allows us to get the background color accurately. - qApp->style()->polish(this); - // generate user's unique color. - auto backCol = backgroundColor().name(); - userColor = - utils::generateContrastingHexColor(userName_->toolTip(), backCol); + colorGenerating_->setFuture(QtConcurrent::run(generate)); + } else { + userName_->setStyleSheet("QLabel { color : " + userColor + "; }"); + } + } +} + +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); } 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_->setFixedWidth(QFontMetrics(userName_->font()).width(userName_->text())); - // TimelineItem isn't displayed. This forces the QSS to get - // loaded. - QString userColor = Cache::userColor(user_id); - 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 + "; }"); + // Set the user color asynchronously if it hasn't been generated yet, + // otherwise this will just set it. + refreshAuthorColor(); auto filter = new UserProfileFilter(user_id, userName_); userName_->installEventFilter(filter); -- cgit 1.5.1