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

+7
View File
@@ -0,0 +1,7 @@
#
# $Id$
# $HeadURL$
# $Author$
#
ADD_SUBDIRECTORY(Messaging)
+47
View File
@@ -0,0 +1,47 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Patric Karwat, SLSE, 2016-10-05
#
SET(msg_messaging_gui_SRCS
msg_messaging_gui_plugin.cpp
msg_messaging_gui_plugin.h
msg_messaging.cpp
msg_messaging.h
msg_messaging_model.cpp
msg_messaging_model.h
msg_show_message_dialog.cpp
msg_show_message_dialog.h
msg_new_message_dialog.cpp
msg_new_message_dialog.h
)
NGL_WRAP_UI(msg_messaging_gui_SRCS
msg_messaging.ui
msg_show_message_dialog.ui
msg_new_message_dialog.ui
)
NGL_ADD_LIBRARY(WS MsgMessageingGuiPlugin MODULE ${msg_messaging_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(MsgMessageingGuiPlugin
LtsPrinting
NGLLogger
LtsNotification
LtsSession
LtsSessionData
LtsUtilsSettings
MsgGuiPluginInterface
MsgDataPluginInterface
OpmGuiComboboxPluginInterface
PpmDataPluginInterface
TabocDataPluginInterface
Qt5::Widgets
LtsWidgets
LtsDataView
LtsUtilsGuiDds
ngltools
)
NGL_INSTALL_TARGET(MsgMessageingGuiPlugin)
+177
View File
@@ -0,0 +1,177 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - Messaging Overview Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#include "msg_messaging.h"
#include "ui_msg_messaging.h"
#include "msg_show_message_dialog.h"
#include "msg_new_message_dialog.h"
#include <LtsSession/lts_session_manager.h>
#include <LtsSession/lts_session_data.h>
#include <LtsPrinting/printing.h>
#include <QTreeView>
namespace Messaging
{
MessagingView::MessagingView(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_menuGroup(menuGroup)
, m_model(nullptr)
, m_box(MessagingModel::Box::InBox)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_opmCbxDtc(nullptr)
, m_uniqueMsgId(0)
, m_session(session)
, m_ui(new Ui::MessagingView)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("MessagingDialog"))
{
m_ui->setupUi(this);
m_ui->widget->setSelectionMode(QAbstractItemView::SingleSelection);
// connects fuer Widgetaenderungen
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &MessagingView::onSelectionChanged);
// Show-Button erzeugen
m_buttonBox->connectButton(LtsWidgets::DialogButton::Show, this, &MessagingView::onShowMessage);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Show, false);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked, this, &MessagingView::onShowMessage);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalEnterPressed, this, &MessagingView::onShowMessage);
// Create Add-Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &MessagingView::onNewMessage);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, true);
m_buttonBox->setText(LtsWidgets::DialogButton::Add, tr("Add"));
// Create Remove-Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &MessagingView::onRemoveMessage);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &MessagingView::onPrint);
} // end of ctor()
//-----------------------------------------------------------------------------
MessagingView::~MessagingView()
{
delete m_ui;
} // end of dtor()
//-----------------------------------------------------------------------------
void MessagingView::retranslate()
{
translate(m_ui, m_box == MessagingModel::Box::InBox ? tr("Inbox") : tr("Outbox"));
}
bool MessagingView::init(const std::shared_ptr<Messaging::Interface::Dtc> &dtc,
const std::shared_ptr<Messaging::Interface::Ftc> &ftc,
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
const std::shared_ptr<TrainingAreaBaseOC::Interface::Dtc> &tabocDtc,
const std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> &opmCbxDtc,
const MessagingModel::Box &box)
{
if (!dtc || !ftc || !opmCbxDtc)
return false;
m_dtc = dtc;
m_ftc = ftc;
m_opmCbxDtc = opmCbxDtc;
m_box = box;
m_model = new MessagingModel(this);
m_model->initModel(m_dtc, ppmDtc, tabocDtc, m_session, m_box);
m_proxyModel = new MessagingProxyModel(this);
m_proxyModel->setSourceModel(m_model);
m_ui->widget->setModel(m_proxyModel);
#ifndef LTS_DEBUG
m_ui->widget->hideColumn(0);
#endif
m_ui->widget->setSortIndicator(1, Qt::AscendingOrder);
setOnlineHelpFilename(QStringLiteral("Situation-Function_Group_Messages"));
/*
if (m_box == MessagingModel::Box::InBox)
setOnlineHelpFilename(QStringLiteral("Situation-Inbox"));
else
setOnlineHelpFilename(QStringLiteral("Situation-Outbox"));
*/
return true;
} // end of init()
//-----------------------------------------------------------------------------
void MessagingView::onSelectionChanged() // aka. enaDisa
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
const int cntSelectedRows = selectedRows.size();
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, cntSelectedRows == 1);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Show, cntSelectedRows == 1);
} // end of onSelectionChanged()
//-----------------------------------------------------------------------------
void MessagingView::onShowMessage()
{
const QModelIndex idx = m_ui->widget->currentIndex();
int row = idx.row();
if (row < 0)
return;
Messaging::OperatorMessage operatorMessage = m_model->getRowData(row);
ShowMessageDialog *dialog = new ShowMessageDialog(m_session, this);
dialog->init(m_dtc, m_ftc, m_opmCbxDtc, m_box, operatorMessage, m_menuGroup);
addDialog(dialog, m_menuGroup, QStringLiteral("msgShowMessage%1").arg(operatorMessage.id()), LtsWidgets::LayoutArea::eDialogTab);
} // end of onShowMessage()
// Window to create and send a new Message
void MessagingView::onNewMessage()
{
NewMessageDialog *dialog = new NewMessageDialog(m_session);
dialog->init(m_dtc, m_ftc, m_opmCbxDtc);
addDialog(dialog, m_menuGroup, QStringLiteral("msgNewMessage%1").arg(m_uniqueMsgId++), LtsWidgets::LayoutArea::eDialogTab);
} // end of onNewMessage()
// Window to remove a Message
void MessagingView::onRemoveMessage()
{
m_requestHelper->startSingleRequest([this]()
{
return m_ftc->modifyOperatorMessageRequest(ModifyOperatorMessageRequest(m_model->getRowData(m_ui->widget->currentIndex().row()).id(), false, false, true), this);
});
// TODO: enaDisa !! or does a view trigger it, because the selection might have changed?
} // end of onRemoveMessage()
void MessagingView::onPrint()
{
LtsPrinting::printView(m_session, this, m_ui->widget->treeView());
}
void MessagingView::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->widget->setColumnsOrganiserEnabled(identifier(), true);
}
} // namespace Messaging
+79
View File
@@ -0,0 +1,79 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - Messaging Overview Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#pragma once
#include "msg_messaging_model.h"
#include <Services/Messaging/msg_dtc.h>
#include <Services/Messaging/msg_ftc.h>
#include <OperatorManagement/opm_gui_combobox_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <Plugins/TrainingAreaBaseOC/taboc_data_plugin_interface.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsSession/lts_session.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace Ui
{
class MessagingView;
}
namespace Messaging
{
class MessagingView : public LtsWidgets::LtsDialog
, protected Messaging::Interface::Ftc::ModifyOperatorMessageReplyHandler
{
Q_OBJECT
public:
explicit MessagingView(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
~MessagingView();
bool init(const std::shared_ptr<Messaging::Interface::Dtc> &dtc,
const std::shared_ptr<Messaging::Interface::Ftc> &ftc,
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
const std::shared_ptr<TrainingAreaBaseOC::Interface::Dtc> &tabocDtc,
const std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> &opmCbxDtc,
const MessagingModel::Box &box);
private:
void retranslate() override;
void onSelectionChanged();
void onShowMessage();
void onNewMessage();
void onRemoveMessage();
void onPrint();
void tableColumnOrganiserSetting() override;
protected:
void onModifyOperatorMessageReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private:
QString m_menuGroup;
MessagingModel *m_model;
MessagingProxyModel *m_proxyModel;
MessagingModel::Box m_box;
std::shared_ptr<Messaging::Interface::Dtc> m_dtc;
std::shared_ptr<Messaging::Interface::Ftc> m_ftc;
std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> m_opmCbxDtc;
int m_uniqueMsgId;
LtsSession::LtsSession *m_session;
Ui::MessagingView *m_ui;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
} // namespace Messaging
+45
View File
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MessagingView</class>
<widget class="QWidget" name="MessagingView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>455</width>
<height>341</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">MessagingView</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="LtsDataView::LtsDataView" name="widget">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>250</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,287 @@
/**
* @RDE_HEADER@
* Gui Plugin for Messaging
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#include "msg_messaging.h"
#include "msg_messaging_gui_plugin.h"
#include "msg_show_message_dialog.h"
#include "msg_new_message_dialog.h"
#include "msg_messaging_model.h"
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsNotification/lts_notification.h>
#include <LtsWidgets/lts_dialog.h> // for noti actions..
#include <LtsWidgets/lts_splash.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <LtsUtilsSettings/settings.h>
#include <Plugins/OperatorManagement/opm_data_plugin_interface.h>
#include <Services/Messaging/msg_operator_rights.h>
#include <QTimer>
namespace Messaging
{
const char s_msgInboxIdentifier[] = "msgInbox";
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
{
return std::make_shared<InterfaceImpl>(session);
}
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
: GuiPluginBase::Interface(session, getLogger("Plugins.Gui.Msg.Messaging"))
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_ppmDtc(nullptr)
, m_tabocDtc(nullptr)
, m_opmCbxDtc(nullptr)
, m_unreadMessages(QVector<int>())
, m_operatorId(-1)
, m_ownParticipantId(-1)
, m_noti(nullptr)
{}
InterfaceImpl::~InterfaceImpl()
{
delete m_noti;
}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<Messaging::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<Messaging::DataInterface>(m_ftc))
return false;
if (!m_session->getForeignGuiInterface<OperatorManagement::ForeignGuiComboboxInterface>(m_opmCbxDtc))
return false;
if (appId() == LtsAppDescriptor::App::OC)
{
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
return false;
if (!m_session->getDtc<TrainingAreaBaseOC::DataInterface>(m_tabocDtc))
return false;
}
return true;
}
void InterfaceImpl::clearInterfaces()
{
if (m_tabocDtc)
m_tabocDtc->disconnect(this);
if (m_dtc)
m_dtc->disconnect(this);
m_dtc = nullptr;
m_ftc = nullptr;
m_ppmDtc = nullptr;
m_tabocDtc = nullptr;
m_opmCbxDtc = nullptr;
}
void InterfaceImpl::initializeMessaging()
{
if (m_noti != nullptr)
return;
m_noti = m_session->createNotification(QStringLiteral("MsgMessages"));
m_noti->setIcon(QIcon(QStringLiteral("icon:messages.svg")));
m_noti->setToolTip(tr("No unread messages"));
m_noti->setAction([this]()
{
m_session->addWidget(onShowInBox(nullptr), menuGroup(), QStringLiteral("msgInbox"), LtsWidgets::LayoutArea::eDialogTab); // TODO: PlData und das hier verbinden..
});
m_operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
connect(m_dtc.get(), &Messaging::Interface::Dtc::operatorMessageChanged,
this, &InterfaceImpl::slotOperatorMessageChanged, Qt::UniqueConnection);
m_dtc->waitForHistoricalDataOperatorMessage(5000);
if (m_session->app() == LtsAppDescriptor::App::OC)
{
m_ppmDtc->enableAll(2000);
connect(m_tabocDtc.get(), &TrainingAreaBaseOC::Interface::Dtc::specificsEquipmentChanged,
this, &InterfaceImpl::slotSpecificsEquipmentChanged);
m_tabocDtc->specificsEquipments([this](const TrainingAreaBaseOC::SpecificsEquipment & data) { slotSpecificsEquipmentChanged(data, DataModification::eAdded); });
}
else
evaluateMessages();
emit signalInitDone();
}
void InterfaceImpl::slotOperatorMessageChanged(const Messaging::OperatorMessage &msg, const DataModification &mod)
{
// TODO: check if messaging enabled?
if (!isMyMessage(msg.recipientId(), msg.recipientType()))
return;
if (!msg.isRead() && mod == DataModification::eAdded)
{
if (!m_unreadMessages.contains(msg.id()))
{
m_unreadMessages.append(msg.id());
const QString openMessageLink(QStringLiteral("OpenMessages"));
int msgCount = m_unreadMessages.count();
m_session->baseLayout()->showMessage(tr("%Ln new message(s)", "", msgCount), tr("You received %Ln new message(s).<br />Click <a href='%1'>here</a> to open the Inbox.", "", msgCount).arg(openMessageLink),
LtsWidgets::LtsNotificationBox::MessageType::Info,
[this, openMessageLink](const QString & link)
{
if (link == openMessageLink)
m_session->baseLayout()->executeAction(QLatin1String(s_msgInboxIdentifier));
}, true, QStringLiteral("msg.NewMessages"));
}
}
if ((msg.isRead() && (mod == DataModification::eModified)) || mod == DataModification::eRemoved)
m_unreadMessages.removeAll(msg.id()); // deletes nothing if there is no message with that id :)
updateUnreadCount();
}
void InterfaceImpl::slotSpecificsEquipmentChanged(const TrainingAreaBaseOC::SpecificsEquipment &data, DataModification mod)
{
if (DataModification::eRemoved == mod)
return;
if (m_session->app() == LtsAppDescriptor::App::OC)
{
int oldParticipantId = m_ownParticipantId;
m_ownParticipantId = m_ppmDtc->participantIdByEquipmentNumber(data.equipmentNumber());
if (m_ownParticipantId <= 0)
WARNING_LOG(m_logger) << "EquipmentNumber " << data.equipmentNumber() << " is not present in current set of PPM-participants.";
if (oldParticipantId != m_ownParticipantId)
evaluateMessages();
}
}
bool InterfaceImpl::isMyMessage(int recipientId, const AddressType &adressType)
{
bool ret = (((adressType == Messaging::AddressType::Operator) && (recipientId == m_operatorId)) ||
((adressType == Messaging::AddressType::ObserverController) && (recipientId == m_ownParticipantId)));
return ret;
}
QString InterfaceImpl::menuGroup() const
{
return tr("Messaging");
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableMassages = ps->value(QStringLiteral("msg"),
QStringLiteral("enableMessages")).toBool();
if (enableMassages)
{
// Action 'Inbox' anlegen
plData.menuText = tr("Inbox");
plData.menuIcon = QIcon(QLatin1String("icon:messages_inbox.svg"));
plData.identifier = QLatin1String(s_msgInboxIdentifier);
plData.operatorRight = OperatorRights::MessagesShow;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return onShowInBox(parent);
};
ret.append(plData);
// Action 'Outbox' anlegen
plData.menuText = tr("Outbox");
plData.menuIcon = QIcon(QLatin1String("icon:messages_outbox.svg"));
plData.identifier = QStringLiteral("msgOutbox");
plData.operatorRight = OperatorRights::MessagesShow;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return onShowOutBox(parent);
};
ret.append(plData);
// Action 'New Message' anlegen
plData.menuText = tr("Add Message");
plData.menuIcon = QIcon(QLatin1String("icon:send_player_message.svg"));
plData.identifier = QStringLiteral("msgNewMessage"); // ident fuer interne Verwaltung (muss nur unique sein)
plData.operatorRight = OperatorRights::MessagesSend;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return onNewMessage(parent);
};
ret.append(plData);
initializeMessaging();
}
return ret;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowInBox(QWidget *parent)
{
MessagingView *dialog = new MessagingView(menuGroup(), m_session, parent);
dialog->init(m_dtc, m_ftc, m_ppmDtc, m_tabocDtc, m_opmCbxDtc, MessagingModel::Box::InBox);
return dialog;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowOutBox(QWidget *parent)
{
MessagingView *dialog = new MessagingView(menuGroup(), m_session, parent);
dialog->init(m_dtc, m_ftc, m_ppmDtc, m_tabocDtc, m_opmCbxDtc, MessagingModel::Box::OutBox);
return dialog;
}
LtsWidgets::LtsDialog *InterfaceImpl::onNewMessage(QWidget *parent)
{
NewMessageDialog *dialog = new NewMessageDialog(m_session, parent);
dialog->init(m_dtc, m_ftc, m_opmCbxDtc);
return dialog;
}
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()));
}
void InterfaceImpl::evaluateMessages()
{
m_unreadMessages.clear();
auto cb = [this](const Messaging::OperatorMessage & msg)
{
if (this->isMyMessage(msg.recipientId(), msg.recipientType())
&& !msg.isRead())
m_unreadMessages.append(msg.id());
};
m_dtc->operatorMessages(cb);
updateUnreadCount();
}
} // namespace Messaging
@@ -0,0 +1,99 @@
/**
* @RDE_HEADER@
* Gui Plugin for Messaging
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#pragma once
#include <Messaging/logger.h>
#include <Messaging/msg_ftc.h>
#include <Messaging/msg_dtc.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/Messaging/msg_data_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <Plugins/TrainingAreaBaseOC/taboc_data_plugin_interface.h>
#include <OperatorManagement/opm_gui_combobox_plugin_interface.h>
namespace LtsNotification
{
class LtsNotification;
}
namespace Messaging
{
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:msg")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QStringLiteral("Messaging.Gui"); }
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return (partition == IDL::PartitionType::Global ||
partition == IDL::PartitionType::Exercise);
}
};
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface
{
Q_OBJECT
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
~InterfaceImpl();
bool fetchInterfaces() override;
void clearInterfaces() override;
QString menuGroup() const override;
QVector<LtsWidgets::PluginData> getActions() override;
void initializeMessaging();
void messageChanged();
bool availableInPartition(IDL::PartitionType partition) const override
{
return (partition == IDL::PartitionType::Global ||
partition == IDL::PartitionType::Exercise);
}
signals:
void signalInitDone();
private slots:
void slotOperatorMessageChanged(const Messaging::OperatorMessage &msg, const DataModification &mod);
void slotSpecificsEquipmentChanged(const TrainingAreaBaseOC::SpecificsEquipment &data, DataModification mod);
private:
void updateUnreadCount();
void evaluateMessages();
bool isMyMessage(int recipientId, const AddressType &adressType);
LtsWidgets::LtsDialog *onShowInBox(QWidget *parent);
LtsWidgets::LtsDialog *onShowOutBox(QWidget *parent);
// unused? LtsWidgets::LtsDialog *onShowMessage(QWidget *parent);
LtsWidgets::LtsDialog *onNewMessage(QWidget *parent);
std::shared_ptr<Messaging::Interface::Dtc> m_dtc;
std::shared_ptr<Messaging::Interface::Ftc> m_ftc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<TrainingAreaBaseOC::Interface::Dtc> m_tabocDtc;
std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> m_opmCbxDtc;
QVector<int> m_unreadMessages;
int m_operatorId;
int m_ownParticipantId;
LtsNotification::LtsNotification *m_noti;
};
} // namespace Messaging
+210
View File
@@ -0,0 +1,210 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - Messaging Model
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10.05
*/
#include "msg_messaging_model.h"
#include <Messaging/msg_translation.h>
#include <LtsSession/lts_session_data.h>
#include <ngltools/ngltools_dtg.h>
namespace Messaging
{
//---------------------------------
// Messaging
//---------------------------------
MessagingModel::MessagingModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<Messaging::OperatorMessage>(
{
tr("Id"),
tr("Time"),
tr("Sender"),
tr("Type"),
tr("Receiver"),
tr("Type"),
tr("Subject")
},
parent)
, m_dtc(nullptr)
, m_box(MessagingModel::Box::InBox)
, m_operatorId(0)
, m_ownParticipantId(-1)
, m_app(LtsAppDescriptor::App::Situation)
, m_logger(getLogger("MessagingModel"))
{}
bool MessagingModel::initModel(const std::shared_ptr<Messaging::Interface::Dtc> &dtc,
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, // only needed if OC-app
const std::shared_ptr<TrainingAreaBaseOC::Interface::Dtc> &tabocDtc, // only needed if OC-app
LtsSession::LtsSession *session,
const MessagingModel::Box &box)
{
m_dtc = dtc;
m_ppmDtc = ppmDtc;
m_tabocDtc = tabocDtc;
m_box = box;
m_operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
m_app = session->app();
connect(m_dtc.get(), &Interface::Dtc::operatorMessageChanged,
this, &MessagingModel::onDataChanged);
if (m_app == LtsAppDescriptor::App::OC)
{
connect(m_tabocDtc.get(), &TrainingAreaBaseOC::Interface::Dtc::specificsEquipmentChanged,
this, &MessagingModel::onSpecificsEquipmentChanged);
m_tabocDtc->specificsEquipments([this](const TrainingAreaBaseOC::SpecificsEquipment & data) { onSpecificsEquipmentChanged(data, DataModification::eAdded); });
}
else
// insert Model
reInitModel();
return true;
}
QVariant MessagingModel::data(const QModelIndex &index, int role) const
{
if (!indexIsValid(index))
return QVariant();
const Messaging::OperatorMessage &operatorMessage = m_vecData.at(index.row());
if (role == Qt::FontRole)
{
bool setBold = false;
if (m_box == Box::InBox)
{
if (!operatorMessage.isRead())
setBold = true;
}
else
{
if (m_app == LtsAppDescriptor::App::OC)
{
const int opMsgId = operatorMessage.id();
std::function<bool(const Messaging::OperatorMessage&)> cb = [&setBold, opMsgId] (const Messaging::OperatorMessage &message) -> bool
{
if (message.correspondingOutboxMessageId() == opMsgId &&
!message.isSend())
{
setBold = true;
return true; // found
}
return false;
};
m_dtc->operatorMessages(cb);
}
}
if (setBold)
{
QFont font;
font.setBold(true);
return font;
}
}
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case MessagingModel::OperatorId:
return operatorMessage.id();
case MessagingModel::TimeStamp:
return QDateTime::fromMSecsSinceEpoch(operatorMessage.timeStamp());
case MessagingModel::SenderText:
return QString::fromStdString(operatorMessage.senderText());
case MessagingModel::SenderType:
return Messaging::toString(operatorMessage.senderType());
case MessagingModel::RecipientText:
return QString::fromStdString(operatorMessage.recipientText());
case MessagingModel::RecipientType:
return Messaging::toString(operatorMessage.recipientType());
case MessagingModel::Subject:
return QString::fromStdString(operatorMessage.subject());
}
}
return QVariant();
}
bool MessagingModel::isFiltered(const OperatorMessage &msg, DataModification modType) const
{
if (modType == DataModification::eRemoved)
return false;
switch (m_box)
{
case Box::InBox:
if (((msg.recipientType() == Messaging::AddressType::Operator) && (m_operatorId != msg.recipientId())) ||
((msg.recipientType() == Messaging::AddressType::ObserverController) && (m_ownParticipantId != msg.recipientId())))
return true;
break;
case Box::OutBox:
return (m_operatorId != msg.senderId() || msg.correspondingOutboxMessageId() > 0);
}
return false;
}
void MessagingModel::onSpecificsEquipmentChanged(const TrainingAreaBaseOC::SpecificsEquipment &data, const DataModification &modType)
{
if (DataModification::eRemoved == modType)
return;
if (m_app == LtsAppDescriptor::App::OC)
{
int oldParticipantId = m_ownParticipantId;
m_ownParticipantId = m_ppmDtc->participantIdByEquipmentNumber(data.equipmentNumber());
if (m_ownParticipantId <= 0)
WARNING_LOG(m_logger) << "EquipmentNumber " << data.equipmentNumber() << " is not present in current set of PPM-participants.";
if (oldParticipantId != m_ownParticipantId)
reInitModel();
}
}
void MessagingModel::reInitModel()
{
beginResetModel();
m_vecData.clear();
// insert Model
m_dtc->operatorMessages([this](const Messaging::OperatorMessage & data) { insertRow(data); });
endResetModel();
}
//
// MessagingProxyModel
//
void MessagingProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<MessagingModel*>(sourceModel);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(sourceModel);
}
bool MessagingProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel ||
source_left.column() != source_right.column() ||
!source_left.isValid() ||
!source_right.isValid())
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
const auto &dataLeft = m_sourceModel->m_vecData.at(source_left.row());
const auto dataRight = m_sourceModel->m_vecData.at(source_right.row());
switch (source_left.column())
{
case MessagingModel::TimeStamp:
return dataLeft.timeStamp() < dataRight.timeStamp();
case MessagingModel::OperatorId:
case MessagingModel::SenderText:
case MessagingModel::SenderType:
case MessagingModel::RecipientText:
case MessagingModel::RecipientType:
case MessagingModel::Subject:
break;
}
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
}
} // namespace Messaging
+91
View File
@@ -0,0 +1,91 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - Messaging Model
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10.05
*/
#pragma once
#include <Messaging/msg_dtc.h>
#include <Messaging/logger.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <Plugins/TrainingAreaBaseOC/taboc_data_plugin_interface.h>
#include <LtsSession/lts_session.h>
#include <LtsWidgets/lts_abstract_table_model.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
namespace Messaging
{
// --------------------------------------------------------
// MessagingModel
// --------------------------------------------------------
class MessagingModel final : public LtsWidgets::LtsAbstractTableModel<Messaging::OperatorMessage>
{
Q_OBJECT
public:
enum class Box
{
InBox,
OutBox
};
enum Columns
{
OperatorId,
TimeStamp,
SenderText,
SenderType,
RecipientText,
RecipientType,
Subject
};
explicit MessagingModel(QObject *parent = nullptr);
bool initModel(const std::shared_ptr<Messaging::Interface::Dtc> &dtc,
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, // only needed if OC-app
const std::shared_ptr<TrainingAreaBaseOC::Interface::Dtc> &tabocDtc, // only needed if OC-app
LtsSession::LtsSession *session,
const MessagingModel::Box &box);
QVariant data(const QModelIndex &, int) const override;
protected:
bool isFiltered(const OperatorMessage &msg, DataModification modType) const override;
private slots:
void onSpecificsEquipmentChanged(const TrainingAreaBaseOC::SpecificsEquipment &data, const DataModification &modType);
private:
void reInitModel();
std::shared_ptr<Messaging::Interface::Dtc> m_dtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<TrainingAreaBaseOC::Interface::Dtc> m_tabocDtc;
MessagingModel::Box m_box;
int m_operatorId;
int m_ownParticipantId;
LtsAppDescriptor::App m_app;
friend class MessagingProxyModel;
LOGGER_T m_logger;
};
class MessagingProxyModel final : public LtsWidgets::LtsColumnFilterProxyModel
{
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel) override;
protected:
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
private:
MessagingModel *m_sourceModel = nullptr;
};
} //namespace Messaging
@@ -0,0 +1,364 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - Show Message Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#include "msg_new_message_dialog.h"
#include "ui_msg_new_message_dialog.h"
#include <LtsSession/lts_session_data.h>
#include <LtsWidgets/ui_requirement.h>
namespace Messaging
{
//
// RecipientModel
//
void RecipientModel::addData(const Recipient &recipient)
{
for (const auto &r : qAsConst(m_data))
{
if (r == recipient)
return;
}
beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
m_data += recipient;
endInsertRows();
}
void RecipientModel::removeData(const QModelIndex &idx)
{
if (idx.column() != 0 || idx.row() < 0 || idx.row() >= m_data.size())
return;
const int row = idx.row();
beginRemoveRows(QModelIndex(), row, row);
m_data.removeAt(row);
endRemoveRows();
}
QVariant RecipientModel::data(const QModelIndex &idx, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (idx.column() != 0 || idx.row() < 0 || idx.row() >= m_data.size())
return QVariant();
const Recipient &r = m_data.at(idx.row());
return r.name;
}
int RecipientModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_data.size();
}
int RecipientModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 1;
}
QVector<RecipientModel::Recipient> RecipientModel::recvOperators() const
{
QVector<RecipientModel::Recipient> ret;
for (const RecipientModel::Recipient &r : m_data)
{
if (r.isOperator)
ret += r;
}
return ret;
}
QVector<RecipientModel::Recipient> RecipientModel::recvOCs() const
{
QVector<RecipientModel::Recipient> ret;
for (const RecipientModel::Recipient &r : m_data)
{
if (!r.isOperator)
ret += r;
}
return ret;
}
//
// NewMessageDialog
//
NewMessageDialog::NewMessageDialog(LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkCancel)
, m_recipientsContainsOc(false)
, m_ui(new Ui::NewMessageDialog)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_opmCbxDtc(nullptr)
, m_recipientModel(new RecipientModel(this))
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_session(session)
, m_logger(getLogger("NewMessageDialog"))
{
INFO_LOG(m_logger) << "NewMessageDialog::Konstruktor";
m_ui->setupUi(this);
m_ui->leSubject->clear();
m_ui->teMessage->clear();
m_ui->addrListView->setModel(m_recipientModel);
// Create Send-Button
m_buttonBox->setText(LtsWidgets::DialogButton::Ok, tr("Send"));
connect(m_ui->cbxAddrType, &QCheckBox::toggled, this, &NewMessageDialog::addrTypeChanged);
connect(m_ui->addrAddButton, &QPushButton::clicked, this, &NewMessageDialog::addAddr);
connect(m_ui->addrRemoveButton, &QPushButton::clicked, this, &NewMessageDialog::removeAddr);
connect(m_ui->teMessage, &QTextEdit::textChanged, this, [this]()
{
if (m_ui->cbxAddrType->isChecked() || m_session->app() == LtsAppDescriptor::App::OC || m_recipientsContainsOc)
limitTextLength();
});
m_ui->addrRemoveButton->setEnabled(false);
if (m_session->app() != LtsAppDescriptor::App::OC)
m_ui->lblCharsLeft->setVisible(false);
m_ui->lblCharsLeft->setText(tr("Characters left: %1").arg(MAX_CHARS));
QFontMetricsF fm(m_ui->lblCharsLeft->font());
m_ui->lblCharsLeft->setFixedWidth(fm.width(m_ui->lblCharsLeft->text()));
// connects fuer ListViewAenderungen
connect(m_ui->addrListView, &QListView::clicked,
this, &NewMessageDialog::onAddrSelectionChanged);
connect(m_recipientModel, &RecipientModel::rowsInserted, this, [this]()
{
m_recipientsContainsOc = !m_recipientModel->recvOCs().isEmpty();
});
connect(m_recipientModel, &RecipientModel::rowsRemoved, this, [this]()
{
m_recipientsContainsOc = !m_recipientModel->recvOCs().isEmpty();
});
m_uiRequirements->addRequirement({ m_ui->lblSubject, [this]() { return !m_ui->leSubject->text().isEmpty(); } });
m_uiRequirements->addRequirement({ m_ui->lblTo, [this]() { return m_recipientModel->rowCount() > 0; } });
m_uiRequirements->addRequirement({ m_ui->lblMessage, [this]() { return !m_ui->teMessage->toPlainText().isEmpty(); } });
setOnlineHelpFilename(QStringLiteral("Situation-Function_Group_Messages"));
} // end of ctor()
//-----------------------------------------------------------------------------
NewMessageDialog::~NewMessageDialog()
{
delete m_ui;
} // end of dtor()
//-----------------------------------------------------------------------------
void NewMessageDialog::retranslate()
{
translate(m_ui, QString(), true, tr("Message"));
}
bool NewMessageDialog::init(const std::shared_ptr<Messaging::Interface::Dtc> &dtc,
const std::shared_ptr<Messaging::Interface::Ftc> &ftc,
const std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> &opmCbxDtc)
{
if (!dtc || !ftc)
return false;
m_dtc = dtc;
m_ftc = ftc;
m_opmCbxDtc = opmCbxDtc;
INFO_LOG(m_logger) << "NewMessageDialog::init";
fillAddressBox();
return true;
} // end of init()
bool NewMessageDialog::initAnswerDialog(const Messaging::OperatorMessage &msg)
{
m_ui->leSubject->setText(tr("Re: %1").arg(QString::fromStdString(msg.subject())));
if (msg.senderType() == Messaging::AddressType_def::ObserverController)
m_ui->cbxAddrType->setChecked(true);
fillAddressBox();
if (msg.senderType() == Messaging::AddressType_def::ObserverController)
{
int idx = m_ui->cmbOperators->findData(0-msg.senderId());
INFO_LOG(m_logger) << "senderId=" << 0-msg.senderId()
<< " idx = " << idx;
m_ui->cmbOperators->setCurrentIndex(idx);
}
else
{
if (msg.correspondingOutboxMessageId() <= 0)
return false;
const Messaging::OperatorMessage &senderMsg = m_dtc->operatorMessage(msg.correspondingOutboxMessageId());
int idx = m_ui->cmbOperators->findData(senderMsg.senderId());
m_ui->cmbOperators->setCurrentIndex(idx);
}
addAddr();
const QString msgStr =
QLatin1String("\n\n\n")
+ QLatin1String("-----------------------------------\n")
+ tr("from: %1").arg(QString::fromStdString(msg.senderText()))
+ QLatin1Char('\n')
+ tr("sent: %1").arg(QDateTime::fromMSecsSinceEpoch(msg.timeStamp()).toString())
+ QLatin1Char('\n')
+ tr("to: %1").arg(QString::fromStdString(msg.recipientText()))
+ QLatin1Char('\n')
+ tr("subject: %1").arg(QString::fromStdString(msg.subject()))
+ QLatin1String("\n\n")
+ QString::fromStdString(msg.message());
m_ui->teMessage->setText(msgStr);
emit m_ui->teMessage->textChanged();
m_ui->teMessage->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
m_ui->teMessage->moveCursor(QTextCursor::Down, QTextCursor::MoveAnchor);
m_ui->teMessage->ensureCursorVisible();
m_ui->teMessage->setFocus();
return true;
} // end of initAnswerDialog()
// Window to create and send a new Message
bool NewMessageDialog::apply()
{
DEBUG_LOG(m_logger) << "--- onSendMessage() ";
QString subject = m_ui->leSubject->text();
QString message = m_ui->teMessage->toPlainText();
DEBUG_LOG(m_logger) << "subject = " << subject
<< ",message = " << message;
const QVector<RecipientModel::Recipient> recvOperators = m_recipientModel->recvOperators();
const QVector<RecipientModel::Recipient> recvOCs = m_recipientModel->recvOCs();
if (!recvOperators.isEmpty())
{
CreateOperatorMessageRequest comr;
// request for Operators
DEBUG_LOG(m_logger) << "request for Operators";
comr.senderId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
comr.subject(subject.toStdString());
comr.senderType(Messaging::AddressType_def::type::Operator);
comr.message(message.toStdString());
comr.recipientType() = Messaging::AddressType_def::type::Operator;
comr.recipientIds().reserve(recvOperators.size());
// Operators are not in an exercise => exerciseId = 0
comr.exerciseId(m_session->exerciseId());
for (const RecipientModel::Recipient &r : recvOperators)
{
comr.recipientIds().push_back(r.recipientId);
DEBUG_LOG(m_logger) << "recipientId =" << r.recipientId;
}
m_requestHelper->addRequest([comr, this]()
{
DEBUG_LOG(m_logger) << "m_ftc->createOperatorMessageRequest ";
return m_ftc->createOperatorMessageRequest(comr, this);
});
}
DEBUG_LOG(m_logger) << " m_recipientModel->countOcMessages=" << recvOCs.size();
// Check OC-messages
if (!recvOCs.isEmpty())
{
CreateOperatorMessageRequest comrOC;
// request for OCs
DEBUG_LOG(m_logger) << "request for OCs";
comrOC.senderId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
comrOC.subject(subject.toStdString());
comrOC.senderType(Messaging::AddressType_def::type::Operator);
comrOC.message(message.toStdString());
comrOC.recipientType() = Messaging::AddressType_def::type::ObserverController;
comrOC.recipientIds().reserve(recvOperators.size());
comrOC.exerciseId(m_session->exerciseId());
for (const RecipientModel::Recipient &r : recvOCs)
{
comrOC.recipientIds().push_back(r.recipientId);
DEBUG_LOG(m_logger) << "recipientId OC =" << r.recipientId;
}
m_requestHelper->addRequest([comrOC, this]()
{
DEBUG_LOG(m_logger) << "m_ftc->createOperatorMessageRequest OC";
return m_ftc->createOperatorMessageRequest(comrOC, this);
});
}
return m_requestHelper->startRequests();
} // end of apply()
void NewMessageDialog::fillAddressBox()
{
m_ui->cmbOperators->clear();
m_opmCbxDtc->fillOperatorComboBox(m_ui->cmbOperators, m_ui->cbxAddrType->isChecked() ? OperatorManagement::ForeignGuiComboboxInterface::eOc : OperatorManagement::ForeignGuiComboboxInterface::eOperators);
} // end of fillAddressBox
void NewMessageDialog::addrTypeChanged()
{
DEBUG_LOG(m_logger) << "************** addrTypeChanged ";
fillAddressBox();
if (m_session->app() != LtsAppDescriptor::App::OC)
m_ui->lblCharsLeft->setVisible(m_ui->cbxAddrType->isChecked() || m_recipientsContainsOc);
limitTextLength();
} // end of addrTypeChanged
void NewMessageDialog::addAddr()
{
RecipientModel::Recipient r;
r.name = m_ui->cmbOperators->currentText();
r.isOperator = m_ui->cmbOperators->currentData().toInt() > 0;
r.recipientId = abs(m_ui->cmbOperators->currentData().toInt());
m_recipientModel->addData(r);
DEBUG_LOG(m_logger) << "************** addAddr: " << m_ui->cmbOperators->currentText()
<< " isOperator:" << r.isOperator;
} // end of addAddr
void NewMessageDialog::removeAddr()
{
DEBUG_LOG(m_logger) << "************** removeAddr ";
QModelIndex modelIndex = m_ui->addrListView->currentIndex();
m_recipientModel->removeData(modelIndex);
m_ui->addrRemoveButton->setEnabled(m_recipientModel->rowCount() > 0);
addrTypeChanged();
} // end of removeAddr
void NewMessageDialog::onAddrSelectionChanged()
{
DEBUG_LOG(m_logger) << "************** onAddrSelectionChanged ";
m_ui->addrRemoveButton->setEnabled(true);
} // end of onAddrSelectionChanged
/**
* @brief NewMessageDialog::limitTextLength
* checks the text length comparing it with the maximum allowed character length and chops the waste
*/
void NewMessageDialog::limitTextLength()
{
QString plainText(m_ui->teMessage->toPlainText());
int currentUsedChars = plainText.toUtf8().size();
bool bNeedSetNew = false;
while (currentUsedChars > MAX_CHARS)
{
plainText.chop(1);
currentUsedChars = plainText.toUtf8().size();
bNeedSetNew = true; // do not set text directly, results in recursion
}
// if text longer than allowed
if (bNeedSetNew)
{
m_ui->teMessage->setPlainText(plainText);
m_ui->teMessage->moveCursor(QTextCursor::End);
}
m_ui->lblCharsLeft->setText(tr("Characters left: %1").arg(QString::number(MAX_CHARS - currentUsedChars)));
} // end of limitTextLength
} // namespace Messaging
@@ -0,0 +1,111 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - New Message Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#pragma once
#include <Messaging/msg_dtc.h>
#include <Messaging/msg_ftc.h>
#include <Messaging/logger.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsSession/lts_session.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <Plugins/OperatorManagement/opm_gui_combobox_plugin_interface.h>
#include <QAbstractListModel>
namespace Ui
{
class NewMessageDialog;
}
namespace Messaging
{
class RecipientModel final : public QAbstractListModel
{
Q_OBJECT
public:
struct Recipient
{
QString name;
int recipientId = 0;
bool isOperator = false;
bool operator==(const Recipient &o) const
{
return name == o.name &&
recipientId == o.recipientId &&
isOperator == o.isOperator;
}
};
using QAbstractListModel::QAbstractListModel;
void addData(const Recipient &recipient);
void removeData(const QModelIndex &idx);
QVariant data(const QModelIndex &idx, int role) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVector<Recipient> recvOperators() const;
QVector<Recipient> recvOCs() const;
private:
QVector<Recipient> m_data;
};
class NewMessageDialog : public LtsWidgets::LtsDialog
, protected Messaging::Interface::Ftc::CreateOperatorMessageReplyHandler
, protected Messaging::Interface::Ftc::ModifyOperatorMessageReplyHandler
{
Q_OBJECT
static constexpr int MAX_CHARS = 1024;
public:
explicit NewMessageDialog(LtsSession::LtsSession *session, QWidget *parent = nullptr);
~NewMessageDialog();
bool init(const std::shared_ptr<Messaging::Interface::Dtc> &dtc,
const std::shared_ptr<Messaging::Interface::Ftc> &ftc,
const std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> &opmCbxDtc);
bool initAnswerDialog(const Messaging::OperatorMessage &msg);
private:
void retranslate() override;
bool apply() override final;
void fillAddressBox();
protected:
void onCreateOperatorMessageReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onModifyOperatorMessageReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void addrTypeChanged();
void addAddr();
void removeAddr();
void onAddrSelectionChanged();
private:
void textChanged();
void limitTextLength();
bool m_recipientsContainsOc;
QString m_menuGroup;
Ui::NewMessageDialog *m_ui;
std::shared_ptr<Messaging::Interface::Dtc> m_dtc;
std::shared_ptr<Messaging::Interface::Ftc> m_ftc;
std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> m_opmCbxDtc;
RecipientModel *m_recipientModel;
LtsUtils::RequestHelper *m_requestHelper;
LtsSession::LtsSession *m_session;
LOGGER_T m_logger;
};
} // namespace Messaging
@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewMessageDialog</class>
<widget class="QWidget" name="NewMessageDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>566</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">New Message</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1,0,0,3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="lblSubject">
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Subject:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="leSubject">
<property name="toolTip">
<string>Subject</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="lblTo">
<property name="text">
<string>To:</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbxAddrType">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>O&amp;C</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsComboBox" name="cmbOperators"/>
</item>
<item>
<widget class="QPushButton" name="addrAddButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
</property>
<property name="autoRepeatInterval">
<number>106</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListView" name="addrListView">
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="addrRemoveButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="lblMessage">
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Message:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lblCharsLeft">
<property name="text">
<string notr="true">Characters left: 1024</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTextEdit" name="teMessage">
<property name="toolTip">
<string>Message</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>leSubject</tabstop>
<tabstop>cbxAddrType</tabstop>
<tabstop>cmbOperators</tabstop>
<tabstop>addrAddButton</tabstop>
<tabstop>addrListView</tabstop>
<tabstop>addrRemoveButton</tabstop>
<tabstop>teMessage</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,176 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - Show Message Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#include "msg_messaging.h"
#include "ui_msg_show_message_dialog.h"
#include "msg_show_message_dialog.h"
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session_manager.h>
#include <LtsSession/lts_session_data.h>
#include <LtsPrinting/printing.h>
#include <QShowEvent>
#include <QDateTime>
#include <QTimer>
namespace Messaging
{
ShowMessageDialog::ShowMessageDialog(LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_ui(new Ui::ShowMessageDialog)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_opmCbxDtc(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_session(session)
, m_logger(getLogger("MessagingDialog"))
{
m_ui->setupUi(this);
setUnchangeable(); // is show only
m_ui->msgContent->clear();
setOnlineHelpFilename(QStringLiteral("Situation-Function_Group_Messages"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &ShowMessageDialog::onPrint);
} // end of ctor()
//-----------------------------------------------------------------------------
ShowMessageDialog::~ShowMessageDialog()
{
delete m_ui;
} // end of dtor()
//-----------------------------------------------------------------------------
void ShowMessageDialog::retranslate()
{
translate(m_ui, QString::fromStdString(m_operatorMessage.subject()), false /* never new */, tr("Message"));
}
bool ShowMessageDialog::init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> &opmCbxDtc,
const MessagingModel::Box &box,
const OperatorMessage &operatorMessage,
const QString &menuGroup)
{
m_dtc = dtc;
m_ftc = ftc;
m_opmCbxDtc = opmCbxDtc;
m_operatorMessage = operatorMessage;
m_menuGroup = menuGroup;
m_ui->from->clear();
m_ui->subject->clear();
m_ui->time->clear();
m_ui->msgContent->clear();
m_ui->from->setText(QString::fromStdString(operatorMessage.senderText()));
m_ui->to->setText(QString::fromStdString(operatorMessage.recipientText()));
m_ui->subject->setText(QString::fromStdString(operatorMessage.subject()));
QDateTime qDateTime;
qDateTime.setMSecsSinceEpoch(operatorMessage.timeStamp());
QString time = qDateTime.toUTC().toString();
INFO_LOG(m_logger) << " time = " << time;
m_ui->time->setText(time);
m_ui->msgContent->append(QString::fromStdString(operatorMessage.message()));
QTextCursor cursor = m_ui->msgContent->textCursor();
cursor.setPosition(0);
m_ui->msgContent->setTextCursor(cursor);
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Add, ((operatorMessage.recipientId() > 0) && (operatorMessage.correspondingOutboxMessageId() > 0))// only if is opened by recipient and the sender is known, we dont want to answer our own msg ...
|| (operatorMessage.recipientId() == Messaging::AddressType_def::ObserverController)); // Message from OC to EXCON
m_buttonBox->setText(LtsWidgets::DialogButton::Add, tr("Answer"));
if (box == MessagingModel::Box::InBox)
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, true);
else if (box == MessagingModel::Box::OutBox)
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, false);
// connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Add), &QPushButton::clicked,
// this, &ShowMessageDialog::onAnswerMessage);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &ShowMessageDialog::onAnswerMessage);
return true;
} // end of init()
void ShowMessageDialog::showEvent(QShowEvent *e)
{
LtsDialog::showEvent(e);
if (m_operatorMessage.recipientId() > 0) // Only mark messages in Inbox as read on opening, we use the read flag in the outbox for the OC-laptop application
QTimer::singleShot(200, this, &ShowMessageDialog::slotMarkMessageAsRead);
} // end of showEvent
//-----------------------------------------------------------------------------
void ShowMessageDialog::slotMarkMessageAsRead()
{
// to avoid wait-dialog only mark, if necessary
if (!m_operatorMessage.isRead())
{
bool isRead = true;
bool isSend = m_operatorMessage.isSend();
bool isDeleted = false;
m_requestHelper->setCustomWaitMessage(tr("Marking message as read"));
m_requestHelper->startSingleRequest([&]()
{
return m_ftc->modifyOperatorMessageRequest(ModifyOperatorMessageRequest(m_operatorMessage.id(), isRead, isSend, isDeleted), this);
});
}
} // end of slotMarkMessageAsRead
void ShowMessageDialog::onAnswerMessage()
{
NewMessageDialog *answerDialog = new NewMessageDialog(m_session, this);
if (!answerDialog->init(m_dtc, m_ftc, m_opmCbxDtc))
{
ERROR_LOG(m_logger) << "Can't initialize NewMessageDialog!";
return;
}
if (!answerDialog->initAnswerDialog(m_operatorMessage))
{
ERROR_LOG(m_logger) << "Can't set values from previous message!";
return;
}
addDialog(answerDialog, m_menuGroup, QStringLiteral("Messages"), LtsWidgets::LayoutArea::eDialogTab, true, true);
}
void ShowMessageDialog::onModifyOperatorMessageReply(const Core::FunctionReplyObject &replyObject)
{
//INFO_LOG(m_logger) << "onModifyOperatorMessageReply, error = " << replyObject.error() << " (" << (this) << ")";
if (!replyObject.error()) // we only use the modifiy to mark as read here
m_operatorMessage.isRead(true);
m_requestHelper->requestReply(replyObject);
} // end of onModifyOperatorMessageReply
void ShowMessageDialog::onPrint()
{
LtsPrinting::printMessage(m_session, this,
m_ui->lbSubject->text(),
m_ui->subject->text(),
m_ui->lbFrom->text(),
m_ui->from->text(),
m_ui->lbTo->text(),
m_ui->to->text(),
m_ui->msgContent->toHtml(),
m_ui->lbTime->text(),
m_ui->time->text());
}
} // namespace Messaging
@@ -0,0 +1,73 @@
/**
* @RDE_HEADER@
* HMI Plugin for Messaging - Show Message Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-05
*/
#pragma once
#include "msg_messaging_model.h"
#include "msg_new_message_dialog.h"
#include <Services/Messaging/msg_ftc.h>
#include <OperatorManagement/opm_gui_combobox_plugin_interface.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsSession/lts_session.h>
namespace LtsUtils
{
class RequestHelper;
}
namespace Ui
{
class ShowMessageDialog;
}
namespace Messaging
{
class ShowMessageDialog : public LtsWidgets::LtsDialog
, protected Messaging::Interface::Ftc::ModifyOperatorMessageReplyHandler
{
Q_OBJECT
public:
explicit ShowMessageDialog(LtsSession::LtsSession *session, QWidget *parent = nullptr);
~ShowMessageDialog();
bool init(const std::shared_ptr<Messaging::Interface::Dtc> &dtc,
const std::shared_ptr<Messaging::Interface::Ftc> &ftc,
const std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> &opmCbxDtc,
const MessagingModel::Box &box,
const Messaging::OperatorMessage &operatorMessage,
const QString &menuGroup);
private:
void retranslate() override;
private slots:
void slotMarkMessageAsRead();
void onAnswerMessage();
void onPrint();
protected:
void onModifyOperatorMessageReply(const Core::FunctionReplyObject &replyObject) override;
void showEvent(QShowEvent *) override;
private:
QString m_menuGroup;
Ui::ShowMessageDialog *m_ui;
std::shared_ptr<Messaging::Interface::Dtc> m_dtc;
std::shared_ptr<Messaging::Interface::Ftc> m_ftc;
std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> m_opmCbxDtc;
Messaging::OperatorMessage m_operatorMessage;
LtsUtils::RequestHelper *m_requestHelper;
LtsSession::LtsSession *m_session;
LOGGER_T m_logger;
};
} // namespace Messaging
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ShowMessageDialog</class>
<widget class="QWidget" name="ShowMessageDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>455</width>
<height>348</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Show Message</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="lbSubject">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Subject:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="subject">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbFrom">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>From:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="from">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbTo">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>To:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="to">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lbTime">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Time:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="time">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="msgContent"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>