/** * @RDE_HEADER@ * GUI Plugin for AppStarter * $Id$ * $HeadURL$ * $Author$ * * Created by Mike Wille, SLSE, 2016-11-03 */ #include "app_gui_plugin.h" #include #include #include #include #include #include #include #include #include #include namespace AppStarter { std::shared_ptr GuiPlugin::createGuiInterface(LtsSession::LtsSession *session) { return std::make_shared(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 InterfaceImpl::getActions() { QVector 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 &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 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::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(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::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