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> *);
|