Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,390 @@
/**
* @RDE_HEADER@
* Gui Plugin for NotificationManangement
*
* Created by Mike Lennart Wille, ESZS, 2025-06-17
*/
#include "nom_edit_gui_plugin.h"
#include "nom_dialog.h"
#include <LtsNotification/lts_notification.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <LtsWidgets/lts_events.h>
#include <NotificationManagement/nom_dtc.h>
#include <Services/AreaEffectSimulation/aes_operator_rights.h>
#include <QApplication>
#include <QDebug>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
namespace NotificationManagement
{
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session) { return std::make_shared<InterfaceImpl>(session); }
const QString InterfaceImpl::s_nomEditGuiPlugin = QStringLiteral("nomEditGuiPlugin");
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
: GuiPluginBase::Interface(session, getLogger("Plugins.Gui.Nom.Edit"))
, m_noti(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
{
qApp->installEventFilter(this);
}
InterfaceImpl::~InterfaceImpl() {}
int InterfaceImpl::isDeleted(const NomNotification &data) const
{
int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
for (const auto &addr : data.recipientIds())
{
if (addr.addressType() == AddressType_def::Operator)
{
if (addr.addressId() != operatorId)
continue;
if (addr.isDeleted())
return true;
}
}
return false;
}
void InterfaceImpl::showNotificationList(int notificationId)
{
DEBUG_LOG(m_logger) << "showNotificationList notificationId=" << notificationId;
initNotificationSystem();
}
bool InterfaceImpl::eventFilter(QObject *watched, QEvent *event)
{
// DEBUG_LOG(m_logger) << "event->type()" << event->type();
if (watched == qApp && !event->isAccepted() && event->type() == LtsWidgets::LtsLinkEvent::eventTypeId())
{
DEBUG_LOG(m_logger) << "0 event->type()" << event->type();
}
auto ev = static_cast<LtsWidgets::LtsLinkEvent *>(event);
if (event->type() == LtsWidgets::LtsLinkEvent::eventTypeId())
{
DEBUG_LOG(m_logger) << "event->type() == LtsWidgets::LinkEvent::eventId()";
DEBUG_LOG(m_logger) << "ev->url()=" << ev->url().toString();
const auto ev = static_cast<LtsWidgets::LtsLinkEvent *>(event);
const auto identifier = ev->url().path().mid(1);
int id = 0;
QRegularExpression re(QStringLiteral("(\\d+)$"));
QRegularExpressionMatch match = re.match(identifier);
if (match.hasMatch())
{
id = match.captured(1).toInt();
}
DEBUG_LOG(m_logger) << "identifier=" << identifier << ", id=" << id;
if(ev->url().host().toLower() == QStringLiteral("notificationack") && id > 0)
{
DEBUG_LOG(m_logger) << "ack";
ack(m_nomNotifications.value(m_nomNotifications.value(id).id())); //hier eigentlich nicht
}
DEBUG_LOG(m_logger) << "ev->url().host()=" << ev->url().host();
if (ev->url().host().toLower() == s_nomEditGuiPlugin.toLower())
{
DEBUG_LOG(m_logger) << "ev->url().host()=" << ev->url().host();
m_session->addWidget(onShowNotificationManagementDialog(nullptr), menuGroup(), QStringLiteral("NotificationEdit"), LtsWidgets::LayoutArea::eDialogTab);
return true;
}
}
return QObject::eventFilter(watched, event);
}
void InterfaceImpl::onNotificationChanged(const NotificationManagement::NomNotification &noti, DataModification modType)
{
DEBUG_LOG(m_logger) << "onNotificationChanged title=" << noti.title()
<< ", content =" << noti.content()
<< ", args.size=" << noti.contentArgs().size()
<< ", modType=" << modType;
if (noti.exerciseId() != m_session->exerciseId())
return;
if (!isMyMessage(noti.recipientIds()))
return;
const QString notiIdent = QCoreApplication::translate("Notification", noti.title().c_str()) + QString::number(noti.id());
if (isDeleted(noti))
{
m_unreadMessages.remove(noti.id());
updateUnreadCount();
if (m_session->baseLayout()->messageIdentifierExists(notiIdent))
{
m_session->baseLayout()->removeQueuedMessage(notiIdent);
}
return;
}
NomNotification localNoti = noti;
QString content = QCoreApplication::translate("Notification", localNoti.content().c_str());
for (const std::string& arg : noti.contentArgs())
{
// .arg() ersetzt immer den kleinsten freien Platzhalter (z. B. zuerst %1, dann %2)
content = content.arg(QString::fromStdString(arg));
DEBUG_LOG(m_logger) << ".arg() ersetzt immer den kleinsten freien Platzhalter"
<< ", arg=" << arg
<< ", content=" << content;
}
localNoti.content(content.toStdString());
m_nomNotifications.insert(noti.id(), localNoti);
// When it's low, dont add it to the unread_message
if (noti.processed() <= 0 && (modType == DataModification::eAdded || modType == DataModification::eModified))
{
if (m_unreadMessages.contains(noti.id()) && noti.priority() < Priority::Normal)
{
m_unreadMessages.remove(noti.id());
}
if (!m_unreadMessages.contains(noti.id()))
{
m_unreadMessages.insert(noti.id());
QString content = QString::fromStdString(localNoti.content());
for (const std::string& arg : noti.contentArgs()) {
content = content.arg(QString::fromStdString(arg));
}
QMap<QString, QString> linkMap;
parseContent(content, linkMap);
// now replace the strings
QMapIterator<QString, QString> it(linkMap);
while (it.hasNext())
{
it.next();
content = content.replace(QStringLiteral("[%1](%2)").arg(it.value(), it.key()), QStringLiteral("<a href='%1'>%2</a>").arg(it.key(), it.value()));
}
const QString openMessageLink(QStringLiteral("OpenMessages"));
const LtsWidgets::LtsNotificationBox::MessageType messageType = static_cast<LtsWidgets::LtsNotificationBox::MessageType>(noti.messageType().underlying());
// If Priority is High add Notification for every user
if (noti.priority() == Priority::High)
{
m_session->baseLayout()->showMessage(
QCoreApplication::translate("Notification", noti.title().c_str()),
content,
messageType,
[this, linkMap, noti](const QString &link)
{
Q_UNUSED(link)
// Nothing to do here for now as links are already taken care of inside the Message see: LtsBaseLayoutWidget::showMessage
// do not try to ack already acked notification
if (!noti.processed())
{
DEBUG_LOG(m_logger) << "ack";
ack(noti); //hier nach neustart?
}
},
true,
notiIdent);
m_session->baseLayout()->installEventFilter(this);
}
else if (noti.priority() == Priority::Highest)
{
// if the proirity is highest parse the links and send them directly without user input
for (const auto &link : linkMap.keys())
{
auto *event = new LtsWidgets::LtsLinkEvent(QUrl(link), m_session->baseLayout());
event->setAccepted(false);
DEBUG_LOG(m_logger) << "Post event" << event << " " << event->url().toString();
QApplication::postEvent(qApp, event); // receive link events by overriding eventFilter of your *parented* QObject class
}
// do not try to ack already acked notification
if (!noti.processed())
{
DEBUG_LOG(m_logger) << "ack";
ack(noti); //oder hier?
}
}
}
}
if ((noti.processed() && (modType == DataModification::eModified)) || modType == DataModification::eRemoved)
{
m_unreadMessages.remove(noti.id()); // deletes nothing if there is no message with that id :)
// remove notification from user
if (m_session->baseLayout()->messageIdentifierExists(notiIdent))
{
m_session->baseLayout()->removeQueuedMessage(notiIdent);
}
}
updateUnreadCount();
// recalc notification icon counter
}
void InterfaceImpl::onReadReceiptReply(const Core::FunctionReplyObject &replyObject)
{
DEBUG_LOG(m_logger) << "Got ReadReceiptReply " << replyObject.translated() << " add info: " << replyObject.additionalInfo();
}
void InterfaceImpl::initNotificationSystem()
{
if (m_noti != nullptr)
return;
m_noti = m_session->createNotification(QStringLiteral("nom.Notifications"));
m_noti->setIcon(QIcon(QStringLiteral("icon:messages_notif.svg")));
m_noti->setToolTip(tr("No unread notifications"));
m_noti->setAction(
[this]()
{ m_session->addWidget(onShowNotificationManagementDialog(nullptr), menuGroup(), QStringLiteral("NotificationEdit"), LtsWidgets::LayoutArea::eDialogTab); });
connect(m_dtc.get(), &NotificationManagement::Interface::Dtc::nomNotificationChanged, this, &InterfaceImpl::onNotificationChanged, Qt::UniqueConnection);
m_dtc->enableNomNotification();
}
void InterfaceImpl::updateUnreadCount()
{
if (m_noti == nullptr)
return;
m_noti->setCount(m_unreadMessages.count());
m_noti->setToolTip(tr("%Ln unread message(s)", "", m_unreadMessages.count()));
}
bool InterfaceImpl::parseContent(const QString &contentString, QMap<QString, QString> &retMap)
{
if (contentString.isEmpty())
return false;
// Mark Down Regex lookig for String between ]( and ) eg: TestLingk "[LinkName](http::blahblah)"
QRegularExpression regLink(QStringLiteral("(?<=\\]\\()(.*?)(?=\\))"));
QRegularExpressionMatch matchLink = regLink.match(contentString);
QRegularExpression regDesc(QStringLiteral("(?<=\\[)(.*?)(?=\\]\\()"));
QRegularExpressionMatch matchDesc = regDesc.match(contentString);
QRegularExpressionMatchIterator itLink = regLink.globalMatch(contentString);
QRegularExpressionMatchIterator itDesc = regDesc.globalMatch(contentString);
while (itLink.hasNext() && itDesc.hasNext())
{
QString linkRef = itLink.next().captured();
QString linkDesc = itDesc.next().captured();
if (!linkRef.isEmpty() && !linkDesc.isEmpty())
{
retMap.insert(linkRef, linkDesc);
}
}
return retMap.size();
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Notifications");
plData.menuIcon = QIcon(QLatin1String("icon:messages_notif.svg"));
plData.identifier = QLatin1String("NotificationEdit");
plData.operatorRight = OperatorRights::NotificationEdit;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget *parent) { return onShowNotificationManagementDialog(parent); };
ret.append(plData);
}
// Init System without button
initNotificationSystem();
return ret;
}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<NotificationManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<NotificationManagement::DataInterface>(m_ftc))
return false;
return true;
}
void InterfaceImpl::clearInterfaces()
{
m_dtc = nullptr;
m_ftc = nullptr;
m_dtcOpm = nullptr;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowNotificationManagementDialog(QWidget *parent)
{
auto *dialog = new NotificationManagementDialog(m_session, menuGroup(), parent);
return dialog;
}
void InterfaceImpl::ack(const NotificationManagement::NomNotification &notification)
{
ReadReceipt request;
int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
int workstationId = LtsSessionData::LtsSessionData::getInstance()->getWorkstationId();
for (const auto &addr : notification.recipientIds())
{
if ((addr.addressType() == AddressType_def::Operator && addr.addressId() == operatorId)
|| (addr.addressType() == AddressType_def::Workstation && addr.addressId() == workstationId))
{
request.addressId(addr.id());
break;
}
}
request.operatorId(operatorId);
request.workstationId(workstationId);
request.notificationIds({notification.id()});
request.processed(!notification.processed());
DEBUG_LOG(m_logger) << "m_ftc->readReceipt ";
m_ftc->readReceiptRequest(request, this);
}
bool InterfaceImpl::isMyMessage(const std::vector<Address> &recipents)
{
if (recipents.empty())
return false;
using Iter = std::vector<Address>::const_iterator;
Iter it = recipents.begin();
while (it != recipents.end())
{
if (it->addressType() == AddressType::Operator && it->addressId() == LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
{
return true;
}
else if (it->addressType() == AddressType::Workstation && it->addressId() == LtsSessionData::LtsSessionData::getInstance()->getWorkstationId())
{
return true;
}
++it;
}
return false;
}
} // namespace NotificationManagement