15.1.974. tablet_qt/whisker/whiskercallbackhandler.cpp

/*
    Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
    Created by Rudolf Cardinal (rnc1001@cam.ac.uk).

    This file is part of CamCOPS.

    CamCOPS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CamCOPS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
*/

#include "whiskercallbackhandler.h"

#include "whisker/whiskerinboundmessage.h"

WhiskerCallbackHandler::WhiskerCallbackHandler()
{
}

void WhiskerCallbackHandler::add(
    const QString& event,
    const WhiskerCallbackDefinition::CallbackFunction& callback,
    const QString& name,
    WhiskerCallbackDefinition::ExpiryType how_expires,
    int target_n_calls,
    qint64 lifetime_ms,
    bool swallow_event
)
{
    WhiskerCallbackDefinition cb(
        event,
        callback,
        name,
        how_expires,
        target_n_calls,
        lifetime_ms,
        swallow_event
    );
    m_callbacks.append(cb);
}

void WhiskerCallbackHandler::addSingle(
    const QString& event,
    const WhiskerCallbackDefinition::CallbackFunction& callback,
    const QString& name,
    bool swallow_event
)
{
    // Adds a single-shot callback.
    add(event,
        callback,
        name,
        WhiskerCallbackDefinition::ExpiryType::Count,
        1,
        0,
        swallow_event);
}

void WhiskerCallbackHandler::addPersistent(
    const QString& event,
    const WhiskerCallbackDefinition::CallbackFunction& callback,
    const QString& name,
    bool swallow_event
)
{
    // Adds a persistent callback.
    add(event,
        callback,
        name,
        WhiskerCallbackDefinition::ExpiryType::Infinite,
        0,
        0,
        swallow_event);
}

void WhiskerCallbackHandler::removeByEvent(const QString& event)
{
    if (event.isEmpty()) {
        return;
    }
    QMutableVectorIterator<WhiskerCallbackDefinition> it(m_callbacks);
    while (it.hasNext()) {
        if (it.next().event() == event) {
            it.remove();
        }
    }
}

void WhiskerCallbackHandler::removeByName(const QString& name)
{
    if (name.isEmpty()) {
        return;
    }
    QMutableVectorIterator<WhiskerCallbackDefinition> it(m_callbacks);
    while (it.hasNext()) {
        if (it.next().name() == name) {
            it.remove();
        }
    }
}

void WhiskerCallbackHandler::removeByEventAndName(
    const QString& event, const QString& name
)
{
    if (event.isEmpty() || name.isEmpty()) {
        return;
    }
    QMutableVectorIterator<WhiskerCallbackDefinition> it(m_callbacks);
    while (it.hasNext()) {
        const WhiskerCallbackDefinition& callback = it.next();
        if (callback.event() == event && callback.name() == name) {
            it.remove();
        }
    }
}

void WhiskerCallbackHandler::clearCallbacks()
{
    // Removes all callbacks.
    m_callbacks.clear();
}

bool WhiskerCallbackHandler::processEvent(const WhiskerInboundMessage& msg)
{
    // Calls any callbacks for the event.
    // Returns whether or not the event was swallowed (dealt with).

    // Remove expired callbacks first, as they may have expired by time.
    removeExpiredCallbacks(msg.timestamp());

    const QString& event = msg.event();
    for (WhiskerCallbackDefinition& callback : m_callbacks) {
        if (callback.event() == event) {
            callback.call(msg);
            if (callback.swallowEvent()) {
                return true;
            }
        }
    }
    return false;
}

void WhiskerCallbackHandler::removeExpiredCallbacks(const QDateTime& now)
{
    // Remove any single-shot (or otherwise expired) events.
    // https://doc.qt.io/qt-6.5/containers.html#java-style-iterators
    QMutableVectorIterator<WhiskerCallbackDefinition> it(m_callbacks);
    while (it.hasNext()) {
        if (it.next().hasExpired(now)) {
            it.remove();
        }
    }
}