diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-10-08 20:14:13 +0200 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-10-08 20:14:13 +0200 |
commit | 6c6370c83fab2140a81f431b8909746a0b6833dc (patch) | |
tree | 9c0aeaece5cdb461fdbc0863ea276e259b86137b /src | |
parent | Reimplement mention highlight and scroll to highlight (diff) | |
download | nheko-6c6370c83fab2140a81f431b8909746a0b6833dc.tar.xz |
Switch to manual polishing of event delegates
Diffstat (limited to 'src')
-rw-r--r-- | src/timeline/EventDelegateChooser.cpp | 78 | ||||
-rw-r--r-- | src/timeline/EventDelegateChooser.h | 60 | ||||
-rw-r--r-- | src/timeline/TimelineModel.cpp | 8 |
3 files changed, 128 insertions, 18 deletions
diff --git a/src/timeline/EventDelegateChooser.cpp b/src/timeline/EventDelegateChooser.cpp index 2218d9ee..0060907d 100644 --- a/src/timeline/EventDelegateChooser.cpp +++ b/src/timeline/EventDelegateChooser.cpp @@ -131,7 +131,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) roleToPropIdx.insert(*role, i); roles.emplace_back(*role); - nhlog::ui()->critical("Found prop {}, idx {}, role {}", prop.name(), i, *role); + // nhlog::ui()->critical("Found prop {}, idx {}, role {}", prop.name(), i, *role); } else { nhlog::ui()->critical("Required property {} not found in model!", prop.name()); } @@ -140,14 +140,15 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) nhlog::ui()->debug("Querying data for id {}", currentId.toStdString()); chooser.room_->multiData(currentId, forReply ? chooser.eventId_ : QString(), roles); + Qt::beginPropertyUpdateGroup(); for (const auto &role : roles) { const auto &roleName = roleNames[role.role()]; - nhlog::ui()->critical("Setting role {}, {} to {}", - role.role(), - roleName.toStdString(), - role.data().toString().toStdString()); + // nhlog::ui()->critical("Setting role {}, {} to {}", + // role.role(), + // roleName.toStdString(), + // role.data().toString().toStdString()); - nhlog::ui()->critical("Setting {}", mo->property(roleToPropIdx[role.role()]).name()); + // nhlog::ui()->critical("Setting {}", mo->property(roleToPropIdx[role.role()]).name()); mo->property(roleToPropIdx[role.role()]).write(obj, role.data()); if (const auto &req = requiredProperties.find(roleName); req != requiredProperties.end()) @@ -156,14 +157,15 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) if (isReplyNeeded) { const auto roleName = QByteArray("isReply"); - nhlog::ui()->critical("Setting role {} to {}", roleName.toStdString(), forReply); + // nhlog::ui()->critical("Setting role {} to {}", roleName.toStdString(), forReply); - nhlog::ui()->critical("Setting {}", mo->property(roleToPropIdx[-1]).name()); + // nhlog::ui()->critical("Setting {}", mo->property(roleToPropIdx[-1]).name()); mo->property(roleToPropIdx[-1]).write(obj, forReply); if (const auto &req = requiredProperties.find(roleName); req != requiredProperties.end()) QQmlIncubatorPrivate::get(this)->requiredProperties()->remove(*req); } + Qt::endPropertyUpdateGroup(); // setInitialProperties(rolesToSet); @@ -188,9 +190,12 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) auto mo = obj->metaObject(); chooser.room_->multiData( currentId, forReply ? chooser.eventId_ : QString(), rolesToRequest); + + Qt::beginPropertyUpdateGroup(); for (const auto &role : rolesToRequest) { mo->property(roleToPropIdx[role.role()]).write(obj, role.data()); } + Qt::endPropertyUpdateGroup(); }; if (!forReply) { @@ -257,11 +262,22 @@ EventDelegateChooser::DelegateIncubator::statusChanged(QQmlIncubator::Status sta child->setParentItem(&chooser); QQmlEngine::setObjectOwnership(child, QQmlEngine::ObjectOwnership::JavaScriptOwnership); + + // connect(child, &QQuickItem::parentChanged, child, [child](QQuickItem *) { + // // QTBUG-115687 + // if (child->flags().testFlag(QQuickItem::ItemObservesViewport)) { + // nhlog::ui()->critical("SETTING OBSERVES VIEWPORT"); + // // Re-trigger the parent traversal to get subtreeTransformChangedEnabled turned + // on child->setFlag(QQuickItem::ItemObservesViewport); + // } + // }); + if (forReply) emit chooser.replyChanged(); else emit chooser.mainChanged(); + chooser.polish(); } else if (status == QQmlIncubator::Error) { auto errors_ = errors(); for (const auto &e : qAsConst(errors_)) @@ -269,3 +285,49 @@ EventDelegateChooser::DelegateIncubator::statusChanged(QQmlIncubator::Status sta } } +void +EventDelegateChooser::updatePolish() +{ + auto mainChild = qobject_cast<QQuickItem *>(eventIncubator.object()); + auto replyChild = qobject_cast<QQuickItem *>(replyIncubator.object()); + + nhlog::ui()->critical("POLISHING {}", (void *)this); + + if (mainChild) { + auto attached = qobject_cast<EventDelegateChooserAttachedType *>( + qmlAttachedPropertiesObject<EventDelegateChooser>(mainChild)); + Q_ASSERT(attached != nullptr); + + // in theory we could also reset the width, but that doesn't seem to work nicely for text + // areas because of how they cache it. + mainChild->setWidth(maxWidth_); + mainChild->ensurePolished(); + auto width = mainChild->implicitWidth(); + + if (width > maxWidth_ || attached->fillWidth()) + width = maxWidth_; + + nhlog::ui()->debug( + "Made event delegate width: {}, {}", width, mainChild->metaObject()->className()); + mainChild->setWidth(width); + mainChild->ensurePolished(); + } + + if (replyChild) { + auto attached = qobject_cast<EventDelegateChooserAttachedType *>( + qmlAttachedPropertiesObject<EventDelegateChooser>(replyChild)); + Q_ASSERT(attached != nullptr); + + // in theory we could also reset the width, but that doesn't seem to work nicely for text + // areas because of how they cache it. + replyChild->setWidth(maxWidth_); + replyChild->ensurePolished(); + auto width = replyChild->implicitWidth(); + + if (width > maxWidth_ || attached->fillWidth()) + width = maxWidth_; + + replyChild->setWidth(width); + replyChild->ensurePolished(); + } +} diff --git a/src/timeline/EventDelegateChooser.h b/src/timeline/EventDelegateChooser.h index 1cd2d65a..ff67ccd8 100644 --- a/src/timeline/EventDelegateChooser.h +++ b/src/timeline/EventDelegateChooser.h @@ -2,9 +2,6 @@ // // SPDX-License-Identifier: GPL-3.0-or-later -// A DelegateChooser like the one, that was added to Qt5.12 (in labs), but compatible with older Qt -// versions see KDE/kquickitemviews see qtdeclarative/qqmldelagatecomponent - #pragma once #include <QAbstractItemModel> @@ -17,6 +14,32 @@ #include "TimelineModel.h" +class EventDelegateChooserAttachedType : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged) + QML_ANONYMOUS +public: + EventDelegateChooserAttachedType(QObject *parent) + : QObject(parent) + { + } + bool fillWidth() const { return fillWidth_; } + void setFillWidth(bool fill) + { + fillWidth_ = fill; + emit fillWidthChanged(); + } +signals: + void fillWidthChanged(); + +private: + bool fillWidth_ = false, keepAspectRatio = false; + double aspectRatio = 1.; + int maxWidth = -1; + int maxHeight = -1; +}; + class EventDelegateChoice : public QObject { Q_OBJECT @@ -51,14 +74,18 @@ class EventDelegateChooser : public QQuickItem QML_ELEMENT Q_CLASSINFO("DefaultProperty", "choices") -public: + QML_ATTACHED(EventDelegateChooserAttachedType) + Q_PROPERTY(QQmlListProperty<EventDelegateChoice> choices READ choices CONSTANT FINAL) Q_PROPERTY(QQuickItem *main READ main NOTIFY mainChanged FINAL) Q_PROPERTY(QQuickItem *reply READ reply NOTIFY replyChanged FINAL) Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged REQUIRED FINAL) Q_PROPERTY(QString replyTo READ replyTo WRITE setReplyTo NOTIFY replyToChanged REQUIRED FINAL) Q_PROPERTY(TimelineModel *room READ room WRITE setRoom NOTIFY roomChanged REQUIRED FINAL) + Q_PROPERTY(bool sameWidth READ sameWidth WRITE setSameWidth NOTIFY sameWidthChanged) + Q_PROPERTY(int maxWidth READ maxWidth WRITE setMaxWidth NOTIFY maxWidthChanged) +public: QQmlListProperty<EventDelegateChoice> choices(); [[nodiscard]] QQuickItem *main() const @@ -70,6 +97,20 @@ public: return qobject_cast<QQuickItem *>(replyIncubator.object()); } + bool sameWidth() const { return sameWidth_; } + void setSameWidth(bool width) + { + sameWidth_ = width; + emit sameWidthChanged(); + } + bool maxWidth() const { return maxWidth_; } + void setMaxWidth(int width) + { + maxWidth_ = width; + emit maxWidthChanged(); + polish(); + } + void setRoom(TimelineModel *m) { if (m != room_) { @@ -105,12 +146,21 @@ public: void componentComplete() override; + static EventDelegateChooserAttachedType *qmlAttachedProperties(QObject *object) + { + return new EventDelegateChooserAttachedType(object); + } + + void updatePolish() override; + signals: void mainChanged(); void replyChanged(); void roomChanged(); void eventIdChanged(); void replyToChanged(); + void sameWidthChanged(); + void maxWidthChanged(); private: struct DelegateIncubator final : public QQmlIncubator @@ -142,6 +192,8 @@ private: TimelineModel *room_{nullptr}; QString eventId_; QString replyId; + bool sameWidth_ = false; + int maxWidth_ = 400; static void appendChoice(QQmlListProperty<EventDelegateChoice> *, EventDelegateChoice *); static qsizetype choiceCount(QQmlListProperty<EventDelegateChoice> *); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 3e0c6688..f5b9e142 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -601,12 +601,8 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r case UserName: return QVariant(displayName(QString::fromStdString(acc::sender(event)))); case UserPowerlevel: { - return static_cast<qlonglong>(mtx::events::state::PowerLevels{ - cache::client() - ->getStateEvent<mtx::events::state::PowerLevels>(room_id_.toStdString()) - .value_or(mtx::events::StateEvent<mtx::events::state::PowerLevels>{}) - .content} - .user_level(acc::sender(event))); + return static_cast<qlonglong>( + permissions_.powerlevelEvent().user_level(acc::sender(event))); } case Day: { |