Files
qt5-legatus-legacy/Lts/Plugins/AppStarter/Gui/AppStart/app_gui_plugin.cpp
T
2026-08-13 18:33:10 +02:00

398 lines
14 KiB
C++
Executable File

/**
* @RDE_HEADER@
* GUI Plugin for AppStarter
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2016-11-03
*/
#include "app_gui_plugin.h"
#include <LtsSession/lts_session.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <LtsAppManager/lts_app_manager.h>
#include <LtsAppDescriptor/lts_app_descriptor.h>
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <LtsSession/lts_session_data.h>
#include <LtsUtilsSettings/settings.h>
#include <Services/InfrastructureManagement/ism_operator_rights.h>
#include <QApplication>
namespace AppStarter
{
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
{
return std::make_shared<InterfaceImpl>(session);
}
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
: GuiPluginBase::Interface(session, NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("AppStarter")) // TODO: log name
{}
static inline LtsAppDescriptor::AppDescriptionVector getAvailableApps(LtsAppDescriptor::App curAppId)
{
LtsAppDescriptor::AppDescriptionVector apps = LtsAppManager::LtsAppManager::getInstance()->getAvailableApps();
if (curAppId == LtsAppDescriptor::App::OC)
{
// only online help in O/C mode
apps.erase(std::remove_if(apps.begin(), apps.end(),
[](const LtsAppDescriptor::AppDescription & app)
{
switch (app.id)
{
case LtsAppDescriptor::App::OnlineHelp:
case LtsAppDescriptor::App::Snapshot:
case LtsAppDescriptor::App::BuildingViewer:
case LtsAppDescriptor::App::Login:
case LtsAppDescriptor::App::OC: // should stay in vector to enable re-login for the user
return false;
default:
return true;
}
}), apps.end());
if( strcmp(PROJECTBUILD, "guez") == 0)
{
apps.erase(std::remove_if(apps.begin(), apps.end(),
[](const LtsAppDescriptor::AppDescription & app)
{
switch (app.id)
{
case LtsAppDescriptor::App::OnlineHelp:
return true;
default:
return false;
}
}), apps.end());
}
}
else if (LtsSessionData::LtsSessionData::getInstance()->isTablet())
{
apps.erase(std::remove_if(apps.begin(), apps.end(),
[](const LtsAppDescriptor::AppDescription & app)
{
switch (app.id)
{
if (strcmp(PROJECTBUILD, "commaster") == 0)
{
case LtsAppDescriptor::App::Situation:
case LtsAppDescriptor::App::Scripts:
case LtsAppDescriptor::App::ScriptEditorEssentialsView:
case LtsAppDescriptor::App::SymbolEditor:
case LtsAppDescriptor::App::PlanEditor:
return false;
}
if (strcmp(PROJECTBUILD, "demotablet") == 0)
{
case LtsAppDescriptor::App::BuildingViewer:
return false;
}
case LtsAppDescriptor::App::OnlineHelp:
case LtsAppDescriptor::App::Snapshot:
case LtsAppDescriptor::App::Login:
case LtsAppDescriptor::App::OC: // should stay in vector to enable re-login for the user
return false;
default:
return true;
}
}), apps.end());
if( strcmp(PROJECTBUILD, "guez") == 0)
{
apps.erase(std::remove_if(apps.begin(), apps.end(),
[](const LtsAppDescriptor::AppDescription & app)
{
switch (app.id)
{
case LtsAppDescriptor::App::OnlineHelp:
return true;
default:
return false;
}
}), apps.end());
}
}
else
{
// no O/C app in Workstation mode
apps.erase(std::remove_if(apps.begin(), apps.end(),
[](const LtsAppDescriptor::AppDescription & app)
{
return app.id == LtsAppDescriptor::App::OC;
}), apps.end());
}
// NO!! this is not the right place to do this - or not even the correct way anyways. Just remove them from your own list.
// // make sure they are removed during the whole runtime
// LtsAppManager::LtsAppManager::getInstance()->setAvailableApps(apps);
return apps;
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
const LtsSessionData::LtsSessionData *sessionData = LtsSessionData::LtsSessionData::getInstance();
const LtsAppDescriptor::AppDescriptionVector &apps = getAvailableApps(appId());
for (const LtsAppDescriptor::AppDescription &app : apps)
{
// suppress OC: (required since getAvailableApps(App::OC) returns App::OC
if (app.id == LtsAppDescriptor::App::OC)
continue;
// has right to start app? if not, do not create action for it
const QSet<int> &acls = sessionData->getOperatorRights();
bool hasRight = true; // he has the right to start the app if there are no required rights or if all required rights are given
for (int reqRight : app.requiredAcls)
{
if (!acls.contains(reqRight))
hasRight = false;
}
if (!hasRight)
continue;
if (!app.visible) // ignore invisible apps
continue;
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = LtsSession::LtsSession::appToString(app.id);
plData.menuIcon = LtsSession::LtsSession::appToIcon(app.id);
plData.identifier = QStringLiteral("app%1").arg(int(app.id));
plData.directFunc = [this, app](const LtsWidgets::PluginData &)
{
return startApp(app.id);
};
ret.append(plData);
}
#ifdef Q_OS_UNIX
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Take Screenshot");
plData.identifier = QLatin1String("TakeScreenshot");
plData.menuIcon = QIcon(QLatin1String("icon:create_snapshot.svg"));
//plData.operatorRight = OperatorRights::DatabaseAdministration;
plData.directFunc = [this](const LtsWidgets::PluginData & plData)
{
const QString appPath(QLatin1String("mate-screenshot"));
const QStringList args(QStringLiteral("-i"));
startProcess(appPath, args, plData.menuText, plData.identifier);
};
ret.append(plData);
}
#endif
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableDatabaseAdministrationTools = ps->value(QStringLiteral("dat"),
QStringLiteral("enableDatabaseAdministrationTools")).toBool();
if (enableDatabaseAdministrationTools && m_session->app() != LtsAppDescriptor::App::ResourceManager)
{
#ifndef TABLET_MODE
if (m_session->partitionType() == IDL::PartitionType::Global)
{
{
LtsWidgets::PluginData plData;
plData.menuGroup = tr("Database Administration Tools");
plData.menuText = tr("Database Administration");
plData.identifier = QLatin1String("StartDbAdministration");
plData.menuIcon = QIcon(QLatin1String("icon:plans.svg"));
plData.operatorRight = OperatorRights::DatabaseAdministration;
plData.directFunc = [this](const LtsWidgets::PluginData & plData)
{
#ifdef Q_OS_UNIX
//sshpass -p ctc11de ssh ctc_sv@excadb01 -X -o StrictHostKeyChecking=no dbAdministration
const QStringList args({QStringLiteral("-p"), QStringLiteral("ctc11de"),
QStringLiteral("ssh"), QStringLiteral("ctc_sv@excadb01"),
QStringLiteral("-X"),
//QStringLiteral("-o"), QStringLiteral("UserKnownHostsFile=/dev/null"),
QStringLiteral("-o"), QStringLiteral("StrictHostKeyChecking=no"),
QStringLiteral("dbAdministration")
});
const QString appPath(QLatin1String("sshpass"));
#else
const QStringList args;
//TODO: Windows start on same machine as OperatorApplication ?
const QString appPath(QCoreApplication::applicationDirPath() + QLatin1Char('/') + QLatin1String("dbAdministration"));
#endif
startProcess(appPath, args, plData.menuText, plData.identifier);
};
ret.append(plData);
}
LtsWidgets::PluginData plData;
plData.menuGroup = tr("Database Administration Tools");
plData.menuText = tr("TeamPostgreSQL");
plData.identifier = QLatin1String("TeamPostgresql");
plData.menuIcon = QIcon(QLatin1String("icon:plans.svg"));
plData.operatorRight = OperatorRights::DatabaseAdministration;
plData.directFunc = [this](const LtsWidgets::PluginData & plData)
{
const QStringList args({QLatin1String("excadb01:8082/teampostgresql/")});
startProcess(QLatin1String("firefox"), args, plData.menuText, plData.identifier);
};
ret.append(plData);
}
#endif
}
return ret;
}
void InterfaceImpl::startProcess(const QString &procName, const QStringList &args, const QString &title, const QString &identifier)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
// pre-condition
if (identifier.isEmpty())
return;
QPointer<QProcess> proc = m_ProcMap.value(identifier);
if (proc)
{
DEBUG_LOG(m_logger) << "kill QProcess: "
<< " pid=" << proc->processId()
<< " state=" << proc->state();
if (proc->processId() > 0) // still running
{
proc->kill();
if (!proc->waitForFinished())
{
DEBUG_LOG(m_logger) << "!proc->waitForFinished()";
return;
}
}
}
else
{
// LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait();
DEBUG_LOG(m_logger) << "new QProcess";
proc = new QProcess(this);
m_ProcMap.insert(identifier, proc);
DEBUG_LOG(m_logger) << "Starting process '" << procName << "' with args '" << args.join(QLatin1Char(' ')) << "'";
//connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
// proc, &QProcess::deleteLater);
connect(proc.data(), &QProcess::readyReadStandardError,
this, [this, proc, title]()
{
DEBUG_LOG(m_logger) << "QProcess::readyReadStandardError";
const QString readStdErr = QString::fromLocal8Bit(proc->readAllStandardError());
if (readStdErr.contains(QLatin1String("swrast", Qt::CaseInsensitive)))
return;
WARNING_LOG(m_logger) << QStringLiteral("readAllStandardError: %1 while running process %2 with args %3")
.arg(readStdErr, proc->program(), proc->arguments().join(QLatin1Char(' ')));
// show popup only if some error occurs, rest logged as warning
if (readStdErr.contains(QLatin1String("ERROR", Qt::CaseInsensitive)))
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(),
tr("Error: \"%1\"\nwhile running process %2 with args %3").arg(readStdErr, proc->program(), proc->arguments().join(QLatin1Char(' '))),
title);
});
connect(proc.data(), &QProcess::errorOccurred,
this, [this, proc, title](const QProcess::ProcessError & error)
{
ERROR_LOG(m_logger) << "QProcess::errorOccurred";
const QVariant done(proc->property("properlyStarted"));
if (!done.canConvert(QVariant::Bool) || done.toBool() == false)
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(),
tr("Starting app failed - error id: %1").arg(static_cast<int>(error)),
title);
// LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
}
});
connect(proc.data(), &QProcess::stateChanged,
this, [this](const QProcess::ProcessState & state)
{
DEBUG_LOG(m_logger) << "QProcess::stateChanged" << state;
});
connect(proc.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, [this, proc](int, QProcess::ExitStatus)
{
DEBUG_LOG(m_logger) << "QProcess::finished";
proc->deleteLater();
});
proc->setProgram(procName);
proc->setArguments(args);
proc->start();
if (!proc->waitForStarted())
{
ERROR_LOG(m_logger) << "Could not start process '" << procName << "' with args '" << args.join(QLatin1Char(' ')) << "'";
proc->deleteLater();
}
proc->setProperty("properlyStarted", true);
// LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
void InterfaceImpl::startApp(LtsAppDescriptor::App appId)
{
LtsSession::DdsConnectionParams hackParams(m_session->connParams());
//#ifdef LTS_DEBUG
// if (QApplication::queryKeyboardModifiers() == Qt::ControlModifier)
{
// start every new app in session 0 / global
hackParams.exerciseId = 0; // unterschied?
hackParams.partitionId = 0; // unterschied?
hackParams.partitionType = IDL::PartitionType::Global;
}
//#endif
// use default connection url because we're maybe in a replay session with
// an url to a replay session which will not work here
const LtsSessionData::LtsSessionData *sessionData = LtsSessionData::LtsSessionData::getInstance();
hackParams.tcpConnectionUrl = sessionData->getTcpConnectionUrl();
if (sessionData->getDomainIdPreset() > 0)
hackParams.domainId = sessionData->getDomainIdPreset();
const LtsAppDescriptor::AppDescriptionVector apps = LtsAppManager::LtsAppManager::getInstance()->getAvailableApps();
for (const LtsAppDescriptor::AppDescription &app : apps)
{
if (app.id == appId)
{
LtsAppManager::LtsAppManager::getInstance()->createApp(app.id, hackParams);
return;
}
}
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayoutWidget(), tr("Invalid app"));
}
QString InterfaceImpl::menuGroup() const
{
return tr("Apps");
}
} // namespace AppStarter