C
Telltales: Rendering Safety-Critical UI
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
// This file is part of the Qt Safe Renderer module
/*
Purpose of this example is to enable development of Qt Safe Renderer
in desktop environment (Windows and Linux).
Note that this example is NOT implemented according Misra C++ 2008 nor ISO26262
functional safety standards and it depends on Qt classes.
You should not use this example in production environment.
*/
#include <QtSafeRenderer/qsafelayout.h>
#include <QtSafeRenderer/qsafelayoutresourcereader.h>
#include <QtSafeRenderer/statemanager.h>
#include <QtSafeRenderer/qsafechecksum.h>
#include <QGuiApplication>
#if defined(USE_OUTPUTVERIFIER)
#include <outputverifier.h>
#endif
#include "safewindow.h"
#include <QtSafeEventHandlerAdaptation/eventhandler.h>
using namespace SafeRenderer;
class CustomEventFilter : public QSafeEventFilter {
public:
CustomEventFilter(EventHandler* eventHandler) : m_eventHandlerPtr(eventHandler) {}
// Don't use the ackReplyHandled so that the runtime handles ack reply for this message
bool handleEvent(const QSafeEvent &event, [[maybe_unused]] bool *ackReplyHandled = nullptr) override {
bool eventHandled = false;
// Handle EventHeartbeatTimeout event
if (m_eventHandlerPtr != nullptr && EventId::EventHeartbeatTimeout == event.getEventId()) {
eventHandled = true;
QSafeEventHeartbeatTimeout timeout(event);
bool showNotif = timeout.getValue();
//Show or hide the error notification.
QSafeEventVisibility notification;
notification.setItemId(qsafe_hash_string("safeText"));
notification.setValue(showNotif);
m_eventHandlerPtr->processEvent(notification);
}
return eventHandled;
}
private:
EventHandler *m_eventHandlerPtr = nullptr;
};
static void hideIcons(StateManager &stateManager, QSafeLayout &layout)
{
for (auto& it : layout.getLayoutItems()) {
if (it.id() == qsafe_hash_string("speedText") ) {
continue;
} else if (it.id() == qsafe_hash_string("turnleft") ||
it.id() == qsafe_hash_string("turnright") ) {
QSafeEventChangeState changeState;
changeState.setItemId(it.id());
changeState.setStateId(qsafe_hash_string("hidden"));
stateManager.handleEvent(changeState);
} else {
QSafeEventVisibility hideItem;
hideItem.setItemId(it.id());
hideItem.setValue(0U);
stateManager.handleEvent(hideItem);
}
}
}
int main(int argc, char **argv)
{
#ifdef HOST_BUILD
// In host build when using QtGUI, we need to initialize QApplication before SafeWindow.
QGuiApplication app(argc, argv);
#endif
static QSafeLayoutResourceReader hybrid;
hybrid.readLayout("/layoutData/DashboardForm/DashboardForm.ui.srl");
static QSafeLayoutResourceReader sport;
sport.readLayout("/layoutData/DashboardSportForm/DashboardSportForm.ui.srl");
hybrid.setLayoutId(qsafe_hash_string("hybrid"));
sport.setLayoutId(qsafe_hash_string("sport"));
SafeWindow telltaleWindow(hybrid.size(), QSafePoint(0U, 0U));
static StateManager stateManager(telltaleWindow, hybrid);
stateManager.addLayout(&sport);
hideIcons(stateManager, hybrid);
telltaleWindow.requestUpdate();
#if defined(USE_OUTPUTVERIFIER)
EventHandler msgHandler(stateManager, telltaleWindow, outputVerifier);
#else
EventHandler msgHandler(stateManager, telltaleWindow);
#endif
CustomEventFilter customEventFilter(&msgHandler);
msgHandler.installSafeEventFilter(&customEventFilter);
msgHandler.handleEvents();
return 0;
}