443 lines
12 KiB
C++
Executable File
443 lines
12 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*
|
|
* Created by Mike Wille, SLSE, 2017-11-15
|
|
*/
|
|
|
|
#include "dev_gui_plugin.h"
|
|
#include "dev_dialog.h"
|
|
#include "dev_permissions_dialog.h"
|
|
#include "dev_debug_flags_dialog.h"
|
|
#include "dev_ftcmock.h"
|
|
|
|
#include <NGLLogger/NGLLoggerBootstrap.h>
|
|
#include <ngltranslator/ngltranslator.h>
|
|
#include <LtsNotification/lts_notification.h>
|
|
#include <LtsSession/lts_session.h>
|
|
#include <LtsSession/lts_session_data.h>
|
|
#include <LtsAppManager/lts_app_manager.h>
|
|
#include <LtsAppDescriptor/lts_app_descriptor.h>
|
|
#include <LtsPluginManager/lts_plugin_manager.h>
|
|
#include <LtsWidgets/lts_base_layout_widget.h>
|
|
#include <LtsWidgets/lts_notification_box.h>
|
|
|
|
#include <QGuiApplication>
|
|
#include <QInputDialog>
|
|
#include <QMessageBox>
|
|
#include <QTimer>
|
|
#include <QTime>
|
|
#include <QDebug>
|
|
#include <QThread>
|
|
#include <QShortcut>
|
|
#include <QTcpSocket>
|
|
|
|
|
|
namespace DeveloperTools
|
|
{
|
|
|
|
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
|
{
|
|
return std::make_shared<InterfaceImpl>(session);
|
|
}
|
|
|
|
|
|
bool InterfaceImpl::s_devDialogVisible = false;
|
|
|
|
|
|
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
|
: GuiPluginBase::Interface(session, NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Plugins.Gui.Dev"))
|
|
{
|
|
#ifdef LTS_DEBUG
|
|
if (QGuiApplication::queryKeyboardModifiers() == Qt::ControlModifier)
|
|
showDevTools();
|
|
#endif
|
|
|
|
auto *t1 = new QTimer(this);
|
|
t1->setInterval(1000);
|
|
connect(t1, &QTimer::timeout,
|
|
this, &InterfaceImpl::slotCheckFlags);
|
|
t1->start();
|
|
|
|
connect(LtsAppManager::LtsAppManager::getInstance(), &LtsAppManager::LtsAppManager::signalCommand,
|
|
this, &InterfaceImpl::slotCommand, Qt::UniqueConnection);
|
|
}
|
|
|
|
|
|
InterfaceImpl::~InterfaceImpl()
|
|
{
|
|
delete m_noti;
|
|
if (m_ftcMock != nullptr)
|
|
{
|
|
m_ftcMock->deleteLater();
|
|
m_ftcMock = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void InterfaceImpl::slotCommand(QTcpSocket *client, const QStringList &argList)
|
|
{
|
|
if (argList.at(0) != QStringLiteral("ftcmock"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool k = false;
|
|
const int sessionId = argList.at(2).toInt(&k);
|
|
if (!k || sessionId != m_session->id())
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (QStringList({QStringLiteral("start"), QStringLiteral("stop")}).indexOf(argList.at(1)))
|
|
{
|
|
case 0: // start
|
|
{
|
|
if (m_ftcMock != nullptr)
|
|
{
|
|
client->write("ftcmock already running for this session");
|
|
return;
|
|
}
|
|
|
|
const int min = argList.at(3).toInt(&k);
|
|
if (!k || min < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const int max = argList.at(4).toInt(&k);
|
|
if (!k || max < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const int timers = argList.at(5).toInt(&k);
|
|
if (!k || timers < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_ftcMock = new FtcMock(m_session, min, max, timers);
|
|
client->write("ftcmock now running");
|
|
return;
|
|
}
|
|
|
|
case 1: // stop
|
|
{
|
|
if (m_ftcMock == nullptr)
|
|
{
|
|
client->write("ftcmock not running for this session");
|
|
return;
|
|
}
|
|
|
|
m_ftcMock->deleteLater();
|
|
m_ftcMock = nullptr;
|
|
return;
|
|
}
|
|
}
|
|
|
|
client->write("Usage: ftcmock <start / stop> <sessionId>");
|
|
}
|
|
|
|
|
|
void InterfaceImpl::slotCheckFlags()
|
|
{
|
|
LtsSessionData::LtsSessionData *sessionData = LtsSessionData::LtsSessionData::getInstance();
|
|
|
|
if (sessionData->debugFlagValue(QStringLiteral("DeveloperTools.ShowSessionsOnce")) == QVariant(true)) // first DevGuiPlugin wins!
|
|
{
|
|
if (!m_processedFlags.contains(QStringLiteral("DeveloperTools.ShowSessionsOnce")))
|
|
{
|
|
m_processedFlags.append(QStringLiteral("DeveloperTools.ShowSessionsOnce"));
|
|
showDevTools();
|
|
}
|
|
}
|
|
|
|
if (sessionData->debugFlagValue(QStringLiteral("LanguageChangeViaKey")) == QVariant(true)) // first DevGuiPlugin wins!
|
|
{
|
|
if (!m_processedFlags.contains(QStringLiteral("LanguageChangeViaKey")))
|
|
{
|
|
if (m_session->baseLayout() != nullptr)
|
|
{
|
|
m_processedFlags.append(QStringLiteral("LanguageChangeViaKey"));
|
|
|
|
QShortcut *shortcutGer = new QShortcut(QKeySequence(QStringLiteral("F1"), QKeySequence::SequenceFormat::NativeText), m_session->baseLayout(),
|
|
nullptr, nullptr, Qt::ShortcutContext::WindowShortcut);
|
|
|
|
connect(shortcutGer, &QShortcut::activated,
|
|
this, []()
|
|
{
|
|
#ifdef AFTER_FAT
|
|
LtsTranslator::LtsTranslator::getInstance()->setLocale(QLocale::German, QLocale::Germany);
|
|
#else
|
|
NGL::setTranslationLocale(QByteArray("de_DE"));
|
|
#endif
|
|
});
|
|
|
|
|
|
|
|
QShortcut *shortcutEng = new QShortcut(QKeySequence(QStringLiteral("F3"), QKeySequence::SequenceFormat::NativeText), m_session->baseLayout(),
|
|
nullptr, nullptr, Qt::ShortcutContext::WindowShortcut);
|
|
|
|
connect(shortcutEng, &QShortcut::activated,
|
|
this, []()
|
|
{
|
|
#ifdef AFTER_FAT
|
|
LtsTranslator::LtsTranslator::getInstance()->setLocale(QLocale::English, QLocale::UnitedKingdom);
|
|
#else
|
|
NGL::setTranslationLocale(QByteArray("en_GB"));
|
|
#endif
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef LTS_DEBUG
|
|
if (!LtsSessionData::LtsSessionData::getInstance()->hasDebugFlag(QStringLiteral("DeveloperTools.Active")))
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (m_noti != nullptr)
|
|
{
|
|
delete m_noti;
|
|
m_noti = nullptr;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int count = m_session->missingRightActions().count();
|
|
|
|
if (count > 0)
|
|
{
|
|
if (m_noti == nullptr)
|
|
{
|
|
m_noti = m_session->createNotification(QStringLiteral("DevPermissions"));
|
|
|
|
m_noti->setIcon(QIcon(QStringLiteral("icon:lock.svg")));
|
|
m_noti->setAction([this]()
|
|
{
|
|
m_session->addWidget(LtsWidgets::initDialog(new PermissionsDialog(), m_session), menuGroup(), QStringLiteral("devPermissions"));
|
|
});
|
|
}
|
|
|
|
m_noti->setCount(count);
|
|
}
|
|
else
|
|
{
|
|
delete m_noti;
|
|
m_noti = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void InterfaceImpl::showAutoRestart()
|
|
{
|
|
QMessageBox::warning(nullptr, QStringLiteral("DEV"), QStringLiteral("Warning: Auto restart can not be stopped (not yet implemented), hard kill required!"));
|
|
|
|
const LtsAppDescriptor::AppDescriptionVector apps = LtsAppManager::LtsAppManager::getInstance()->getAvailableApps();
|
|
|
|
QStringList listApps;
|
|
listApps.reserve(apps.count());
|
|
QMap<QString, LtsAppDescriptor::App> mapApp2Id;
|
|
|
|
for (const LtsAppDescriptor::AppDescription &app : apps)
|
|
{
|
|
listApps.append(app.appName);
|
|
mapApp2Id[app.appName] = app.id;
|
|
}
|
|
|
|
QInputDialog dialog;
|
|
dialog.setComboBoxItems(listApps);
|
|
dialog.setLabelText(QStringLiteral("Select app to debug: "));
|
|
dialog.setWindowTitle(QStringLiteral("Select app to debug: "));
|
|
|
|
if (!dialog.exec())
|
|
return;
|
|
|
|
QString strApp = dialog.textValue();
|
|
|
|
QInputDialog dialogInt;
|
|
dialogInt.setLabelText(QStringLiteral("Select restart timeout value: "));
|
|
dialogInt.setInputMode(QInputDialog::InputMode::IntInput);
|
|
dialogInt.setIntMinimum(1000);
|
|
dialogInt.setIntMaximum(600000);
|
|
dialogInt.setIntStep(1000);
|
|
dialogInt.setIntValue(4000);
|
|
|
|
if (!dialogInt.exec())
|
|
return;
|
|
|
|
int timeoutValue = dialogInt.intValue();
|
|
|
|
|
|
LtsSession::DdsConnectionParams hackParams(m_session->connParams());
|
|
|
|
QTimer *t = new QTimer(this);
|
|
connect(t, &QTimer::timeout,
|
|
this, [=]
|
|
{
|
|
LtsPluginManager::LtsPluginManager *pApp = LtsAppManager::LtsAppManager::getInstance()->createApp(mapApp2Id.value(strApp), hackParams);
|
|
if (pApp == nullptr)
|
|
{
|
|
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayoutWidget(), tr("App not could not be started"));
|
|
return;
|
|
}
|
|
|
|
connect(pApp, &LtsPluginManager::LtsPluginManager::signalInitializationFinished,
|
|
this, [this, pApp, timeoutValue]()
|
|
{
|
|
QTimer *k = new QTimer(this);
|
|
connect(pApp, &LtsPluginManager::LtsPluginManager::destroyed,
|
|
k, &QTimer::deleteLater);
|
|
connect(k, &QTimer::timeout, pApp,
|
|
&LtsPluginManager::LtsPluginManager::deleteLater);
|
|
k->setSingleShot(true);
|
|
k->setInterval(timeoutValue);
|
|
k->start();
|
|
});
|
|
|
|
});
|
|
t->setInterval(timeoutValue);
|
|
t->start();
|
|
}
|
|
|
|
|
|
void InterfaceImpl::showDevTools()
|
|
{
|
|
if (!s_devDialogVisible)
|
|
{
|
|
QDialog *d = new DevDialog();
|
|
|
|
connect(d, &QDialog::destroyed,
|
|
this, []()
|
|
{
|
|
qWarning() << "Developer Tools destroyed";
|
|
s_devDialogVisible = false;
|
|
});
|
|
|
|
d->setWindowFlags(Qt::Dialog | /*Qt::X11BypassWindowManagerHint |*/ Qt::WindowStaysOnTopHint);
|
|
d->show();
|
|
|
|
qWarning() << "Developer Tools started";
|
|
s_devDialogVisible = true;
|
|
}
|
|
}
|
|
|
|
|
|
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
|
{
|
|
#ifdef LTS_DEBUG
|
|
bool actions = true;
|
|
#else
|
|
bool actions = false;
|
|
#endif
|
|
|
|
if (LtsSessionData::LtsSessionData::getInstance()->hasDebugFlag(QStringLiteral("DeveloperTools.Actions")))
|
|
actions = true;
|
|
|
|
QVector<LtsWidgets::PluginData> ret;
|
|
|
|
if (!actions)
|
|
return ret;
|
|
|
|
{
|
|
LtsWidgets::PluginData plData;
|
|
plData.menuGroup = menuGroup();
|
|
plData.menuText = tr("Show Debug Dialog");
|
|
plData.identifier = QStringLiteral("devTools");
|
|
plData.directFunc = [this](const LtsWidgets::PluginData &)
|
|
{
|
|
showDevTools();
|
|
};
|
|
ret.append(plData);
|
|
}
|
|
|
|
{
|
|
LtsWidgets::PluginData plData;
|
|
plData.menuGroup = menuGroup();
|
|
plData.menuText = tr("Show Debug Flags");
|
|
plData.identifier = QStringLiteral("devFlags");
|
|
plData.createWidgetFunc = [this](QWidget *)
|
|
{
|
|
return LtsWidgets::initDialog(new DebugFlagsDialog(menuGroup()));
|
|
};
|
|
ret.append(plData);
|
|
}
|
|
|
|
{
|
|
LtsWidgets::PluginData plData;
|
|
plData.menuGroup = menuGroup();
|
|
plData.menuText = tr("App Auto Restart");
|
|
plData.identifier = QStringLiteral("devAutoRestart");
|
|
plData.directFunc = [this](const LtsWidgets::PluginData &)
|
|
{
|
|
showAutoRestart();
|
|
};
|
|
ret.append(plData);
|
|
}
|
|
|
|
{
|
|
LtsWidgets::PluginData plData;
|
|
plData.menuGroup = menuGroup();
|
|
plData.menuText = tr("Start App ...");
|
|
plData.identifier = QStringLiteral("devStartAppByAppId");
|
|
plData.directFunc = [this](const LtsWidgets::PluginData &)
|
|
{
|
|
bool k = false;
|
|
|
|
int appId = QInputDialog::getInt(m_session->baseLayout(), QStringLiteral("Start App - AppId"), QStringLiteral("AppId"), (int)m_session->app(), 0, 999, 1, &k);
|
|
if (!k) return;
|
|
|
|
int dId = QInputDialog::getInt(m_session->baseLayout(), QStringLiteral("Start App - Domain Id"), QStringLiteral("Domain Id"), m_session->domainId(), 0, 999, 1, &k);
|
|
if (!k) return;
|
|
|
|
int exId = QInputDialog::getInt(m_session->baseLayout(), QStringLiteral("Start App - Exercise Id"), QStringLiteral("Exercise Id"), m_session->exerciseId(), 0, 999, 1, &k);
|
|
if (!k) return;
|
|
|
|
int pId = QInputDialog::getInt(m_session->baseLayout(), QStringLiteral("Start App - Partition Id"), QStringLiteral("Partition Id"), m_session->exerciseId(), 0, 999, 1, &k);
|
|
if (!k) return;
|
|
|
|
|
|
LtsSession::DdsConnectionParams params(m_session->connParams());
|
|
params.domainId = dId;
|
|
params.exerciseId = exId;
|
|
params.partitionId = pId;
|
|
|
|
if (pId != exId)
|
|
params.partitionType = IDL::PartitionType::Replay;
|
|
else if (pId == exId && exId != 0)
|
|
params.partitionType = IDL::PartitionType::Exercise;
|
|
else
|
|
params.partitionType = IDL::PartitionType::Global;
|
|
|
|
|
|
LtsAppManager::LtsAppManager::getInstance()->createApp(LtsAppDescriptor::LtsAppDescriptor::appFromInteger(appId), params);
|
|
};
|
|
ret.append(plData);
|
|
}
|
|
|
|
{
|
|
LtsWidgets::PluginData plData;
|
|
plData.menuGroup = menuGroup();
|
|
plData.menuText = tr("Show Notification Box");
|
|
plData.identifier = QStringLiteral("devShowNotiBox");
|
|
plData.directFunc = [this](const LtsWidgets::PluginData &)
|
|
{
|
|
m_session->baseLayout()->showMessage(QStringLiteral("Test Title"), QStringLiteral("A long test text that notifies the user about <a href='Test'>something</a><br />that spreads over two lines to fit even more text."), LtsWidgets::LtsNotificationBox::MessageType::Info,
|
|
[this](const QString &)
|
|
{
|
|
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), QStringLiteral("You clicked the link!"));
|
|
});
|
|
};
|
|
ret.append(plData);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
} // namespace DeveloperTools
|