/** * @RDE_HEADER@ * HMI Plugin for ExerciseManangement - Exercise Overview Dialog * $Id$ * $HeadURL$ * $Author$ * Created by Mike Wille, SLSE, 2016-03-30 */ #include "scm_dialog.h" #include "ui_scm_dialog.h" #include "scm_dialog_group.h" #include "scm_dialog_service.h" #include #include namespace ServiceManagement { //--------------------------------- // ServiceManagementDialog //--------------------------------- ServiceManagementDialog::ServiceManagementDialog(QWidget *parent) : LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly) , m_requestHelper(new LtsUtils::RequestHelper(this)) , m_ui(new Ui::ServiceManagementDialog) , m_dtcExm(nullptr) , m_dtc(nullptr) , m_ftc(nullptr) , m_logger(getLogger("ServiceManagementDialog")) { m_ui->setupUi(this); // unused yet m_ui->lbGroupsIndicator->hide(); m_ui->lbExercise->hide(); m_ui->lbServer->hide(); m_ui->cbServer->hide(); m_ui->cbExercise->hide(); setOnlineHelpFilename(QStringLiteral("Administrator-Service_Management")); } ServiceManagementDialog::~ServiceManagementDialog() { delete m_ui; } void ServiceManagementDialog::retranslate() { translate(m_ui, tr("Service Management")); } bool ServiceManagementDialog::init(const std::shared_ptr &dtc, const std::shared_ptr &ftc, const std::shared_ptr &dtcExm) { m_dtc = dtc; m_ftc = ftc; m_dtcExm = dtcExm; connect(m_dtc.get(), &Interface::Dtc::groupInformationChanged, this, &ServiceManagementDialog::slotGroupInformationChanged); connect(m_dtc.get(), &Interface::Dtc::serviceInformationChanged, this, &ServiceManagementDialog::slotServiceInformationChanged); const QMap groupInfo = m_dtc->groupInformations(); if (groupInfo.isEmpty()) { INFO_LOG(m_logger) << "initModel - no groups!"; return true; } m_ui->lbNoServices->hide(); INFO_LOG(m_logger) << "initModel - #group information: " << groupInfo.size(); // GROUPS QVector servicesList; for (const ServiceManagement::GroupInformation &gi : groupInfo) { // now that all services of that group are represented by a widget, create the group widget which adds all service widgets //const int id = gi.id(); const int server = gi.domainId(); const int exercise = gi.exercisePartitionId(); const int32_t replayPartitionId = gi.replayPartitionId(); const QString groupName = groupEnumToGroupName(gi.type()); // QLatin1String("Group Name"); // TODO: get real group name long long timestamp = gi.timestamp(); servicesList.clear(); servicesList.reserve(gi.services().size()); for (auto service : gi.services()) servicesList.append(service); addGroup(gi.type(), server, exercise, replayPartitionId, groupName, timestamp, servicesList); } // SERVICES auto cbSvc = [this](const ServiceManagement::ServiceInformation & svc) // create widgets for every service in the group { addService(svc); }; m_dtc->serviceInformations(cbSvc); // needed to resolve services for the groups return true; } GroupWidget *ServiceManagementDialog::addGroup(const Core::ServiceGroupType &groupType, int server, int exercise, int32_t replayPartitionId, const QString &groupName, long long timestamp, const QVector &servicesList) { //qWarning() << "ServiceManagementDialog::addGroup: needed services:" << servicesList; QString exName = QString::fromStdString(m_dtcExm.get()->exercise(exercise).name()); GroupWidget *group = new GroupWidget(groupType, server, exercise, replayPartitionId, exName, timestamp, servicesList); // memleak! QString groupObjectName = craftGroupName(server, exercise, groupName); group->setObjectName(groupObjectName); //qWarning() << "Group Object Name =" << groupObjectName; connect(group, &GroupWidget::signalRestartGroup, this, &ServiceManagementDialog::slotRestartGroup); // direct connection for const ref on group type enum connect(group, &GroupWidget::signalStartGroup, this, &ServiceManagementDialog::slotStartGroup); // direct connection for const ref on group type enum connect(group, &GroupWidget::signalStopGroup, this, &ServiceManagementDialog::slotStopGroup); // direct connection for const ref on group type enum QVBoxLayout *l = qobject_cast(m_ui->groupLayoutWidget->layout()); if (!l) WARNING_LOG(m_logger) << "ServiceManagementDialog::addGroup: group layout failed, cannot add group"; else l->addWidget(group, 0, Qt::AlignTop); return group; } void ServiceManagementDialog::slotRestartService(int serviceID) { const RestartServiceRequest req(serviceID); m_requestHelper->startSingleRequest([req, this]() { return m_ftc->restartServiceRequest(req, this); }); } static int s_requestId = 0; void ServiceManagementDialog::slotRestartGroup(const Core::ServiceGroupType &groupType, int exercise, int server, int32_t replayPartitionId) { const GroupRequest req(groupType, exercise, server, replayPartitionId, ++s_requestId, {}); m_requestHelper->startSingleRequest([req, this]() { return m_ftc->restartGroupRequest(req, this); }); } void ServiceManagementDialog::slotStartGroup(const Core::ServiceGroupType &groupType, int exercise, int server, int32_t replayPartitionId) { const GroupRequest req(groupType, exercise, server, replayPartitionId, ++s_requestId, {}); m_requestHelper->startSingleRequest([req, this]() { return m_ftc->startGroupRequest(req, this); }); } void ServiceManagementDialog::slotStopGroup(const Core::ServiceGroupType &groupType, int exercise, int server, int32_t replayPartitionId) { const GroupRequest req(groupType, exercise, server, replayPartitionId, ++s_requestId, {}); m_requestHelper->startSingleRequest([req, this]() { return m_ftc->stopGroupRequest(req, this); }); } // DTC Modifications void ServiceManagementDialog::slotGroupInformationChanged(ServiceManagement::GroupInformation info, DataModification mod) { //qWarning() << "slotGroupInformationChanged"; // find group int server = info.domainId(); int exercise = info.exercisePartitionId(); int32_t replayPartitionId = info.replayPartitionId(); QString groupName = groupEnumToGroupName(info.type()); long long timestamp = info.timestamp(); QString findGroupName = craftGroupName(server, exercise, groupName); GroupWidget *gw = m_ui->groupLayoutWidget->findChild(findGroupName); if (!gw) // group does not exist? create it! { //qWarning() << "slotGroupInformationChanged: group not found, adding it"; QVector servicesList; servicesList.reserve(info.services().size()); for (auto service : info.services()) servicesList << service; m_ui->lbNoServices->hide(); addGroup(info.type(), server, exercise, replayPartitionId, groupName, timestamp, servicesList); } else { switch (mod) { case DataModification::eAdded: // already exists, so it cant be added - but easily change data in existing group case DataModification::eModified: { //qWarning() << "slotGroupInformationChanged: group added or modified"; m_ui->lbNoServices->hide(); // added/modified = there are groups, which show services gw->setType(info.type()); gw->setServer(server); gw->setExercise(exercise); gw->setTimestamp(timestamp); break; } case DataModification::eRemoved: { //qWarning() << "slotGroupInformationChanged: group removed"; if (m_ui->groupLayoutWidget->findChildren().isEmpty()) // no groups to show services in? m_ui->lbNoServices->show(); delete gw; // then delete gw from layout break; } } } } void ServiceManagementDialog::addService(const ServiceManagement::ServiceInformation &svc) { const int id = svc.id(); const long long pid = svc.pid(); const QString name(QString::fromStdString(svc.name())); const Core::RunningState &state = svc.state(); const QString errorString(QString::fromStdString(svc.errorString())); ServiceWidget *service = new ServiceWidget(id, pid, name, state, errorString); service->setObjectName(QLatin1String("service.") + QString::number(id)); connect(service, &ServiceWidget::signalRestartService, this, &ServiceManagementDialog::slotRestartService); const auto groupList = findChildren(); for (GroupWidget *gw : groupList) gw->addService(service); } void ServiceManagementDialog::slotServiceInformationChanged(ServiceManagement::ServiceInformation info, DataModification mod) { //qWarning() << "slotServiceInformationChanged"; // find services (because ONE service can be in MANY groups) int32_t serviceId = info.id(); QString errorString = QString::fromStdString(info.errorString()); QString serviceName = QString::fromStdString(info.name()); long long pid = info.pid(); const Core::RunningState &state = info.state(); long long timestamp = info.timestamp(); QString findServiceName = QLatin1String("service.") + QString::number(serviceId); const auto serviceList = findChildren(findServiceName); if (serviceList.isEmpty() || mod == DataModification::eAdded) // no service found or is going to be added? add it! { //qWarning() << "slotServiceInformationChanged: service not found, adding it"; addService(info); } for (ServiceWidget *serviceWidget : serviceList) { switch (mod) { case DataModification::eModified: { //qWarning() << "slotServiceInformationChanged: service modified"; serviceWidget->setErrorString(errorString); serviceWidget->setName(serviceName); serviceWidget->setPid(pid); serviceWidget->setState(state); serviceWidget->setTimestamp(timestamp); break; } case DataModification::eRemoved: { //qWarning() << "slotServiceInformationChanged: service removed"; delete serviceWidget; serviceWidget = nullptr; break; } default: { //qWarning() << "ServiceManagementDialog::slotServiceInformationChanged: unknown or invalid modification!"; break; } } } // tell all groups to set their new statuses (bcuz service states may have changed) !! const auto groupList = findChildren(); for (GroupWidget *groupWidget : groupList) groupWidget->checkStatus(); } } // namespace ServiceManagement