// SPDX-FileCopyrightText: 2022 Tobias Fella // SPDX-License-Identifier: LGPL-2.0-or-later #pragma once #include #include #include #include #include #include #include "events/pollevent.h" #include "models/pollanswermodel.h" namespace Quotient { class PollResponseEvent; } class NeoChatRoom; /** * @class PollHandler * * A class to help manage a poll in a room. * * A poll is made up of a start event that poses the question and possible answers, * and is followed by a series of response events as users in the room select * their choice. This purpose of the poll handler is to keep track of all this as * the poll is displayed as a single event in the timeline which merges all this * information. */ class PollHandler : public QObject { Q_OBJECT QML_ELEMENT QML_UNCREATABLE("Use NeoChatRoom::poll") /** * @brief The kind of the poll. */ Q_PROPERTY(PollKind::Kind kind READ kind CONSTANT) /** * @brief The question for the poll. */ Q_PROPERTY(QString question READ question NOTIFY questionChanged) /** * @brief Whether the poll has ended. */ Q_PROPERTY(bool hasEnded READ hasEnded NOTIFY hasEndedChanged) /** * @brief The model to visualize the answers to this poll. */ Q_PROPERTY(PollAnswerModel *answerModel READ answerModel CONSTANT) /** * @brief The total number of vote responses to the poll. */ Q_PROPERTY(int totalCount READ totalCount NOTIFY totalCountChanged) public: PollHandler() = default; PollHandler(NeoChatRoom *room, const QString &pollStartId); NeoChatRoom *room() const; PollKind::Kind kind() const; QString question() const; bool hasEnded() const; PollAnswerModel *answerModel(); /** * @brief The total number of answer options. */ int numAnswers() const; /** * @brief The answer at the given row. */ Quotient::EventContent::Answer answerAtRow(int row) const; /** * @brief The number of responders who gave the answer ID. */ int answerCountAtId(const QString &id) const; /** * @brief Check whether the given member has selected the given ID in their response. */ bool checkMemberSelectedId(const QString &memberId, const QString &id) const; int totalCount() const; /** * @brief The current answer IDs with the most votes. */ QStringList winningAnswerIds() const; /** * @brief Send an answer to the poll. */ Q_INVOKABLE void sendPollAnswer(const QString &eventId, const QString &answerId); /** * @brief Send the PollEndEvent. */ Q_INVOKABLE void endPoll() const; Q_SIGNALS: void questionChanged(); void hasEndedChanged(); void answersChanged(); void totalCountChanged(); /** * @brief Emitted when the selected answers to the poll change. */ void selectionsChanged(); private: QString m_pollStartId; void updatePoll(Quotient::RoomEventsRange events); void checkLoadRelations(); void handleEvent(Quotient::RoomEvent *event); void handleResponse(const Quotient::PollResponseEvent *event); QHash m_selectionTimestamps; QHash m_selections; bool m_hasEnded = false; QDateTime m_endedTimestamp; QString endText() const; QPointer m_answerModel; };