398 lines
14 KiB
C++
Executable File
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
|