diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-10-08 23:52:23 +0200 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-10-08 23:52:23 +0200 |
commit | c4d2ec875dfce9c29adab0ec85e4317277b5509d (patch) | |
tree | 24a8e3cb996769f3fcf2e96faea8d88365be3269 /src | |
parent | Switch to manual polishing of event delegates (diff) | |
download | nheko-c4d2ec875dfce9c29adab0ec85e4317277b5509d.tar.xz |
Fixup reply and state event rendering
Diffstat (limited to 'src')
-rw-r--r-- | src/timeline/EventDelegateChooser.cpp | 120 | ||||
-rw-r--r-- | src/timeline/EventDelegateChooser.h | 96 |
2 files changed, 156 insertions, 60 deletions
diff --git a/src/timeline/EventDelegateChooser.cpp b/src/timeline/EventDelegateChooser.cpp index 0060907d..a8629b3e 100644 --- a/src/timeline/EventDelegateChooser.cpp +++ b/src/timeline/EventDelegateChooser.cpp @@ -97,6 +97,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) return; item->setParentItem(&chooser); + item->setParent(&chooser); auto roleNames = chooser.room_->roleNames(); QHash<QByteArray, int> nameToRole; @@ -106,8 +107,6 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) QHash<int, int> roleToPropIdx; std::vector<QModelRoleData> roles; - bool isReplyNeeded = false; - // Workaround for https://bugreports.qt.io/browse/QTBUG-98846 QHash<QString, RequiredPropertyKey> requiredProperties; for (const auto &[propKey, prop] : @@ -124,10 +123,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) if (!prop.isRequired() && !requiredProperties.contains(prop.name())) continue; - if (prop.name() == std::string_view("isReply")) { - isReplyNeeded = true; - roleToPropIdx.insert(-1, i); - } else if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) { + if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) { roleToPropIdx.insert(*role, i); roles.emplace_back(*role); @@ -141,6 +137,11 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) chooser.room_->multiData(currentId, forReply ? chooser.eventId_ : QString(), roles); Qt::beginPropertyUpdateGroup(); + auto attached = qobject_cast<EventDelegateChooserAttachedType *>( + qmlAttachedPropertiesObject<EventDelegateChooser>(obj)); + Q_ASSERT(attached != nullptr); + attached->setIsReply(this->forReply); + for (const auto &role : roles) { const auto &roleName = roleNames[role.role()]; // nhlog::ui()->critical("Setting role {}, {} to {}", @@ -155,22 +156,25 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj) QQmlIncubatorPrivate::get(this)->requiredProperties()->remove(*req); } - if (isReplyNeeded) { - const auto roleName = QByteArray("isReply"); - // nhlog::ui()->critical("Setting role {} to {}", roleName.toStdString(), forReply); - - // 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); auto update = [this, obj, roleToPropIdx = std::move(roleToPropIdx)](const QList<int> &changedRoles) { + if (changedRoles.empty() || changedRoles.contains(TimelineModel::Roles::Type)) { + int type = chooser.room_ + ->dataById(currentId, + TimelineModel::Roles::Type, + forReply ? chooser.eventId_ : QString()) + .toInt(); + if (type != oldType) { + nhlog::ui()->debug("Type changed!"); + reset(currentId); + return; + } + } + std::vector<QModelRoleData> rolesToRequest; if (changedRoles.empty()) { @@ -233,6 +237,7 @@ EventDelegateChooser::DelegateIncubator::reset(QString id) chooser.room_ ->dataById(id, TimelineModel::Roles::Type, forReply ? chooser.eventId_ : QString()) .toInt(); + this->oldType = role; for (const auto choice : qAsConst(chooser.choices_)) { const auto &choiceValue = choice->roleValues(); @@ -293,41 +298,58 @@ EventDelegateChooser::updatePolish() 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); + auto layoutItem = [this](QQuickItem *item, int inset) { + if (item) { + auto attached = qobject_cast<EventDelegateChooserAttachedType *>( + qmlAttachedPropertiesObject<EventDelegateChooser>(item)); + Q_ASSERT(attached != nullptr); + + int maxWidth = maxWidth_ - inset; + + // 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. + if (attached->maxWidth() > 0) + item->setWidth(attached->maxWidth()); + else + item->setWidth(maxWidth); + item->ensurePolished(); + auto width = item->implicitWidth(); + + if (width < 1 || width > maxWidth) + width = maxWidth; + + if (attached->maxWidth() > 0 && width > attached->maxWidth()) + width = attached->maxWidth(); + + if (attached->keepAspectRatio()) { + auto height = width * attached->aspectRatio(); + if (attached->maxHeight() && height > attached->maxHeight()) { + height = attached->maxHeight(); + width = height / attached->aspectRatio(); + } + + item->setHeight(height); + } - // 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(); + nhlog::ui()->debug( + "Made event delegate width: {}, {}", width, item->metaObject()->className()); + item->setWidth(width); + item->ensurePolished(); + } + }; - if (width > maxWidth_ || attached->fillWidth()) - width = maxWidth_; + layoutItem(mainChild, mainInset_); + layoutItem(replyChild, replyInset_); +} - replyChild->setWidth(width); - replyChild->ensurePolished(); +void +EventDelegateChooserAttachedType::polishChooser() +{ + auto p = parent(); + if (p) { + auto chooser = qobject_cast<EventDelegateChooser *>(p->parent()); + if (chooser) { + chooser->polish(); + } } } diff --git a/src/timeline/EventDelegateChooser.h b/src/timeline/EventDelegateChooser.h index ff67ccd8..ce79444a 100644 --- a/src/timeline/EventDelegateChooser.h +++ b/src/timeline/EventDelegateChooser.h @@ -17,27 +17,78 @@ class EventDelegateChooserAttachedType : public QObject { Q_OBJECT - Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged) + Q_PROPERTY(bool keepAspectRatio READ keepAspectRatio WRITE setKeepAspectRatio NOTIFY + keepAspectRatioChanged) + Q_PROPERTY(double aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged) + Q_PROPERTY(int maxWidth READ maxWidth WRITE setMaxWidth NOTIFY maxWidthChanged) + Q_PROPERTY(int maxHeight READ maxHeight WRITE setMaxHeight NOTIFY maxHeightChanged) + Q_PROPERTY(bool isReply READ isReply WRITE setIsReply NOTIFY isReplyChanged) + QML_ANONYMOUS public: EventDelegateChooserAttachedType(QObject *parent) : QObject(parent) { } - bool fillWidth() const { return fillWidth_; } - void setFillWidth(bool fill) + + bool keepAspectRatio() const { return keepAspectRatio_; } + void setKeepAspectRatio(bool fill) + { + if (fill != keepAspectRatio_) { + keepAspectRatio_ = fill; + emit keepAspectRatioChanged(); + polishChooser(); + } + } + + double aspectRatio() const { return aspectRatio_; } + void setAspectRatio(double fill) { - fillWidth_ = fill; - emit fillWidthChanged(); + aspectRatio_ = fill; + emit aspectRatioChanged(); + polishChooser(); } + + int maxWidth() const { return maxWidth_; } + void setMaxWidth(int fill) + { + maxWidth_ = fill; + emit maxWidthChanged(); + polishChooser(); + } + + int maxHeight() const { return maxHeight_; } + void setMaxHeight(int fill) + { + maxHeight_ = fill; + emit maxHeightChanged(); + } + + bool isReply() const { return isReply_; } + void setIsReply(bool fill) + { + if (fill != isReply_) { + isReply_ = fill; + emit isReplyChanged(); + polishChooser(); + } + } + signals: - void fillWidthChanged(); + void keepAspectRatioChanged(); + void aspectRatioChanged(); + void maxWidthChanged(); + void maxHeightChanged(); + void isReplyChanged(); private: - bool fillWidth_ = false, keepAspectRatio = false; - double aspectRatio = 1.; - int maxWidth = -1; - int maxHeight = -1; + void polishChooser(); + + double aspectRatio_ = 1.; + int maxWidth_ = -1; + int maxHeight_ = -1; + bool keepAspectRatio_ = false; + bool isReply_ = false; }; class EventDelegateChoice : public QObject @@ -84,6 +135,8 @@ class EventDelegateChooser : public QQuickItem 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) + Q_PROPERTY(int replyInset READ replyInset WRITE setReplyInset NOTIFY replyInsetChanged) + Q_PROPERTY(int mainInset READ mainInset WRITE setMainInset NOTIFY mainInsetChanged) public: QQmlListProperty<EventDelegateChoice> choices(); @@ -103,7 +156,7 @@ public: sameWidth_ = width; emit sameWidthChanged(); } - bool maxWidth() const { return maxWidth_; } + int maxWidth() const { return maxWidth_; } void setMaxWidth(int width) { maxWidth_ = width; @@ -111,6 +164,22 @@ public: polish(); } + int replyInset() const { return replyInset_; } + void setReplyInset(int width) + { + replyInset_ = width; + emit replyInsetChanged(); + polish(); + } + + int mainInset() const { return mainInset_; } + void setMainInset(int width) + { + mainInset_ = width; + emit mainInsetChanged(); + polish(); + } + void setRoom(TimelineModel *m) { if (m != room_) { @@ -161,6 +230,8 @@ signals: void replyToChanged(); void sameWidthChanged(); void maxWidthChanged(); + void replyInsetChanged(); + void mainInsetChanged(); private: struct DelegateIncubator final : public QQmlIncubator @@ -183,6 +254,7 @@ private: QString instantiatedId; int instantiatedRole = -1; QAbstractItemModel *instantiatedModel = nullptr; + int oldType = -1; }; QVariant roleValue_; @@ -194,6 +266,8 @@ private: QString replyId; bool sameWidth_ = false; int maxWidth_ = 400; + int replyInset_ = 0; + int mainInset_ = 0; static void appendChoice(QQmlListProperty<EventDelegateChoice> *, EventDelegateChoice *); static qsizetype choiceCount(QQmlListProperty<EventDelegateChoice> *); |