391 lines
13 KiB
C++
Executable File
391 lines
13 KiB
C++
Executable File
/**
|
|
* @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 ¬i, 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 ¬ification)
|
|
{
|
|
|
|
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
|