Poll Updates and Send Polls
Fix showing polls and update the events and PollHandler to make them easier to work with. Add a PollAnswerModel to visualise poll answers. Enable sending polls.
This commit is contained in:
@@ -121,7 +121,7 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const
|
||||
}
|
||||
|
||||
if (role == ContentModelRole) {
|
||||
if (event->get().is<EncryptedEvent>()) {
|
||||
if (event->get().is<EncryptedEvent>() || event->get().is<PollStartEvent>()) {
|
||||
return QVariant::fromValue<MessageContentModel *>(m_room->contentModelForEvent(event->get().id()));
|
||||
}
|
||||
|
||||
@@ -401,18 +401,12 @@ void MessageModel::refreshLastUserEvents(int baseTimelineRow)
|
||||
}
|
||||
}
|
||||
|
||||
void MessageModel::createEventObjects(const Quotient::RoomEvent *event, bool isPending)
|
||||
void MessageModel::createEventObjects(const Quotient::RoomEvent *event)
|
||||
{
|
||||
if (event == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only create the poll handler for event acknowledged by the server as we need
|
||||
// an ID
|
||||
if (!event->id().isEmpty() && event->is<PollStartEvent>()) {
|
||||
m_room->createPollHandler(eventCast<const PollStartEvent>(event));
|
||||
}
|
||||
|
||||
auto eventId = event->id();
|
||||
auto senderId = event->senderId();
|
||||
if (eventId.isEmpty()) {
|
||||
|
||||
@@ -129,7 +129,7 @@ Q_SIGNALS:
|
||||
* Any model inheriting from MessageModel needs to emit this signal for every
|
||||
* new event it adds.
|
||||
*/
|
||||
void newEventAdded(const Quotient::RoomEvent *event, bool isPending = false);
|
||||
void newEventAdded(const Quotient::RoomEvent *event);
|
||||
|
||||
protected:
|
||||
QPointer<NeoChatRoom> m_room;
|
||||
@@ -154,5 +154,5 @@ private:
|
||||
|
||||
QMap<QString, QSharedPointer<ReadMarkerModel>> m_readMarkerModels;
|
||||
|
||||
void createEventObjects(const Quotient::RoomEvent *event, bool isPending = false);
|
||||
void createEventObjects(const Quotient::RoomEvent *event);
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ void PinnedMessageModel::fill()
|
||||
connect(job, &BaseJob::success, this, [this, job] {
|
||||
beginInsertRows({}, m_pinnedEvents.size(), m_pinnedEvents.size());
|
||||
m_pinnedEvents.push_back(std::move(fromJson<event_ptr_tt<RoomEvent>>(job->jsonData())));
|
||||
Q_EMIT newEventAdded(m_pinnedEvents.back().get(), false);
|
||||
Q_EMIT newEventAdded(m_pinnedEvents.back().get());
|
||||
endInsertRows();
|
||||
});
|
||||
}
|
||||
|
||||
76
src/models/pollanswermodel.cpp
Normal file
76
src/models/pollanswermodel.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
// SPDX-FileCopyrightText: 2025 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "pollanswermodel.h"
|
||||
|
||||
#include "neochatroom.h"
|
||||
#include "pollhandler.h"
|
||||
|
||||
PollAnswerModel::PollAnswerModel(PollHandler *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
Q_ASSERT(parent != nullptr);
|
||||
|
||||
connect(parent, &PollHandler::selectionsChanged, this, [this]() {
|
||||
dataChanged(index(0), index(rowCount() - 1), {CountRole, LocalChoiceRole});
|
||||
});
|
||||
connect(parent, &PollHandler::answersChanged, this, [this]() {
|
||||
dataChanged(index(0), index(rowCount() - 1), {TextRole});
|
||||
});
|
||||
}
|
||||
|
||||
QVariant PollAnswerModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid));
|
||||
|
||||
const auto row = index.row();
|
||||
if (row < 0 || row >= rowCount()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto pollHandler = dynamic_cast<PollHandler *>(this->parent());
|
||||
if (pollHandler == nullptr) {
|
||||
qWarning() << "PollAnswerModel created with nullptr parent.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (role == IdRole) {
|
||||
return pollHandler->answerAtRow(row).id;
|
||||
}
|
||||
if (role == TextRole) {
|
||||
return pollHandler->answerAtRow(row).text;
|
||||
}
|
||||
if (role == CountRole) {
|
||||
return pollHandler->answerCountAtId(pollHandler->answerAtRow(row).id);
|
||||
}
|
||||
if (role == LocalChoiceRole) {
|
||||
const auto room = pollHandler->room();
|
||||
if (room == nullptr) {
|
||||
return {};
|
||||
}
|
||||
return pollHandler->checkMemberSelectedId(room->localMember().id(), pollHandler->answerAtRow(row).id);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int PollAnswerModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
const auto pollHandler = dynamic_cast<PollHandler *>(this->parent());
|
||||
if (pollHandler == nullptr) {
|
||||
qWarning() << "PollAnswerModel created with nullptr parent.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pollHandler->numAnswers();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> PollAnswerModel::roleNames() const
|
||||
{
|
||||
return {
|
||||
{IdRole, "id"},
|
||||
{TextRole, "answerText"},
|
||||
{CountRole, "count"},
|
||||
{LocalChoiceRole, "localChoice"},
|
||||
};
|
||||
}
|
||||
56
src/models/pollanswermodel.h
Normal file
56
src/models/pollanswermodel.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// SPDX-FileCopyrightText: 2025 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QQmlEngine>
|
||||
|
||||
class PollHandler;
|
||||
|
||||
/**
|
||||
* @class PollAnswerModel
|
||||
*
|
||||
* This class defines the model for visualising a list of answer to a poll.
|
||||
*/
|
||||
class PollAnswerModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the model roles.
|
||||
*/
|
||||
enum Roles {
|
||||
IdRole, /**< The ID of the answer. */
|
||||
TextRole, /**< The answer text. */
|
||||
CountRole, /**< The number of people who gave this answer. */
|
||||
LocalChoiceRole, /**< Whether this option was selected by the local user */
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit PollAnswerModel(PollHandler *parent);
|
||||
|
||||
/**
|
||||
* @brief Get the given role value at the given index.
|
||||
*
|
||||
* @sa QAbstractItemModel::data
|
||||
*/
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
/**
|
||||
* @brief Number of rows in the model.
|
||||
*
|
||||
* @sa QAbstractItemModel::rowCount
|
||||
*/
|
||||
int rowCount(const QModelIndex &parent = {}) const override;
|
||||
|
||||
/**
|
||||
* @brief Returns a mapping from Role enum values to role names.
|
||||
*
|
||||
* @sa Roles, QAbstractItemModel::roleNames()
|
||||
*/
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#include "timelinemessagemodel.h"
|
||||
#include "events/pollevent.h"
|
||||
#include "messagemodel_logging.h"
|
||||
|
||||
using namespace Quotient;
|
||||
@@ -36,7 +37,7 @@ void TimelineMessageModel::connectNewRoom()
|
||||
});
|
||||
connect(m_room, &Room::addedMessages, this, [this](int lowest, int biggest) {
|
||||
if (m_initialized) {
|
||||
for (int i = lowest; i == biggest; ++i) {
|
||||
for (int i = lowest; i <= biggest; ++i) {
|
||||
const auto event = m_room->findInTimeline(i)->event();
|
||||
Q_EMIT newEventAdded(event);
|
||||
}
|
||||
@@ -58,14 +59,14 @@ void TimelineMessageModel::connectNewRoom()
|
||||
#if Quotient_VERSION_MINOR > 9 || (Quotient_VERSION_MINOR == 9 && Quotient_VERSION_PATCH > 0)
|
||||
connect(m_room, &Room::pendingEventAdded, this, [this](const Quotient::RoomEvent *event) {
|
||||
m_initialized = true;
|
||||
Q_EMIT newEventAdded(event, true);
|
||||
Q_EMIT newEventAdded(event);
|
||||
beginInsertRows({}, 0, 0);
|
||||
endInsertRows();
|
||||
});
|
||||
#else
|
||||
connect(m_room, &Room::pendingEventAboutToAdd, this, [this](Quotient::RoomEvent *event) {
|
||||
m_initialized = true;
|
||||
Q_EMIT newEventAdded(event, true);
|
||||
Q_EMIT newEventAdded(event);
|
||||
beginInsertRows({}, 0, 0);
|
||||
});
|
||||
connect(m_room, &Room::pendingEventAdded, this, &TimelineMessageModel::endInsertRows);
|
||||
@@ -111,9 +112,6 @@ void TimelineMessageModel::connectNewRoom()
|
||||
const auto eventIt = m_room->findInTimeline(eventId);
|
||||
if (eventIt != m_room->historyEdge()) {
|
||||
Q_EMIT newEventAdded(eventIt->event());
|
||||
if (eventIt->event()->is<PollStartEvent>()) {
|
||||
m_room->createPollHandler(eventCast<const PollStartEvent>(eventIt->event()));
|
||||
}
|
||||
}
|
||||
refreshEventRoles(eventId, {Qt::DisplayRole});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user