Continues migration with DDS, Common

This commit is contained in:
torsten committed 2026-07-17 12:41:42 +02:00
1 parent 9b15cee841
commit fa48db111e
668 files changed
+111841 -2

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, SLSE, 2016-05-20
#
# LtsPluginLoader
NGL_ADD_LIBRARY(ALL LtsPluginLoader SHARED lts_plugin_loader.cpp lts_plugin_loader.h)
NGL_TARGET_INCLUDE_DIRECTORIES(LtsPluginLoader
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsPluginLoader
PRIVATE
NGLLogger
PUBLIC
Qt5::Core
)
# LtsPluginManager
SET(ltspluginmanager_SRCS
lts_plugin_manager.h
lts_plugin_manager.cpp
Ui/lts_plugin_manager_dialog.h
Ui/lts_plugin_manager_dialog.cpp
Ui/lts_plugin_manager_widget.h
Ui/lts_plugin_manager_widget.cpp
lts_plugin_manager_export.h
)
NGL_WRAP_UI(ltspluginmanager_SRCS
Ui/lts_plugin_manager_dialog.ui
Ui/lts_plugin_manager_widget.ui
)
NGL_ADD_LIBRARY(WS LtsPluginManager SHARED ${ltspluginmanager_SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsPluginManager
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(LtsPluginManager
PRIVATE
NGLLogger
LtsPluginLoader
GuiPluginInterface
DataPluginInterface
LtsWidgets
LtsSession
LtsSessionData
Qt5::Widgets
PUBLIC
ProjectConfig
LtsAppDescriptor
Qt5::Core
)
NGL_INSTALL_TARGET(LtsPluginManager)
NGL_INSTALL_TARGET(LtsPluginLoader)
@@ -0,0 +1,102 @@
#include "lts_plugin_manager_dialog.h"
#include "lts_plugin_manager_widget.h"
#include "ui_lts_plugin_manager_dialog.h"
#include "../lts_plugin_manager.h"
#include <QCoreApplication>
#include <QString>
#include <QDebug>
namespace LtsPluginManager
{
LtsPluginManagerDialog::LtsPluginManagerDialog(QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::LtsPluginManagerDialog)
{
m_ui->setupUi(this);
m_ui->masterSplitter->setStretchFactor(m_ui->masterSplitter->indexOf(m_ui->pluginsWidget), 20);
m_ui->masterSplitter->setStretchFactor(m_ui->masterSplitter->indexOf(m_ui->lwErrorLog), 0);
}
LtsPluginManagerDialog::~LtsPluginManagerDialog()
{
delete m_ui;
}
void LtsPluginManagerDialog::setServiceMissing(const QString &newPluginFilename, const QString &missingPluginName)
{
m_ui->lwErrorLog->addItem(tr("ERROR: Plugin '%1' needs the plugin '%2', which is not available!").arg(newPluginFilename, missingPluginName));
getPluginWidget(newPluginFilename)->setStatus(LtsPluginWidget::MISSING_SERVICE);
if (!isVisible())
show();
QCoreApplication::processEvents();
}
void LtsPluginManagerDialog::setOptionalServiceMissing(const QString &newPluginFilename, const QString &missingPluginName)
{
m_ui->lwErrorLog->addItem(tr("INFO: Plugin %1 asked for plugin %2, which is not available!").arg(newPluginFilename, missingPluginName));
if (!isVisible())
show();
QCoreApplication::processEvents();
}
void LtsPluginManagerDialog::setInvalidPlugin(const QString &newPluginFilename)
{
m_ui->lwErrorLog->addItem(tr("INFO: Invalid plugin '%1'").arg(newPluginFilename));
}
LtsPluginWidget *LtsPluginManagerDialog::getPluginWidget(const QString &filename)
{
LtsPluginWidget *pluginWidget = findChild<LtsPluginWidget *>(filename);
if (!pluginWidget)
{
pluginWidget = new LtsPluginWidget(filename);
pluginWidget->setObjectName(filename);
qobject_cast<QHBoxLayout *>(m_ui->pluginsWidget->layout())->insertWidget(0, pluginWidget);
}
return pluginWidget;
}
void LtsPluginManagerDialog::setPluginLogStatus(const QString &filename, const LtsPluginWidget::Status &status)
{
getPluginWidget(filename)->setStatus(status);
QCoreApplication::processEvents();
}
void LtsPluginManagerDialog::setPluginLogType(const QString &filename, const QString &type)
{
getPluginWidget(filename)->setType(type);
QCoreApplication::processEvents();
}
void LtsPluginManagerDialog::setPluginLogIdent(const QString &filename, const QString &ident)
{
getPluginWidget(filename)->setIdent(ident);
QCoreApplication::processEvents();
}
}
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <LtsPluginManager/lts_plugin_manager_export.h>
#include "lts_plugin_manager_widget.h"
#include <QDialog>
namespace Ui
{
class LtsPluginManagerDialog;
}
namespace LtsPluginManager
{
class LTSPLUGINMANAGER_EXPORT LtsPluginManagerDialog : public QDialog
{
Q_OBJECT
public:
explicit LtsPluginManagerDialog(QWidget *parent = nullptr);
~LtsPluginManagerDialog();
void setServiceMissing(const QString &newPluginFilename, const QString &missingPluginName);
void setOptionalServiceMissing(const QString &newPluginFilename, const QString &missingPluginName);
void setInvalidPlugin(const QString &newPluginFilename);
void setPluginLogStatus(const QString &filename, const LtsPluginWidget::Status &status);
void setPluginLogType(const QString &filename, const QString &type);
void setPluginLogIdent(const QString &filename, const QString &ident);
private:
Ui::LtsPluginManagerDialog *m_ui;
LtsPluginWidget *getPluginWidget(const QString &filename);
};
}
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsPluginManagerDialog</class>
<widget class="QWidget" name="LtsPluginManagerDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>492</width>
<height>342</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="masterSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="pluginsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>250</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>493</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QListWidget" name="lwErrorLog">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,130 @@
#include "lts_plugin_manager_widget.h"
#include "ui_lts_plugin_manager_widget.h"
using namespace LtsPluginManager;
LtsPluginWidget::LtsPluginWidget(const QString &filename, QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::LtsPluginWidget)
{
m_ui->setupUi(this);
m_ui->leFilename->setText(filename);
setStatus(UNKNOWN);
setType();
setIdent();
m_ui->lbGuiPlugins->hide();
m_ui->lbDtc->hide();
m_ui->lwDtcs->hide();
m_ui->lbFtc->hide();
m_ui->lwFtcs->hide();
}
LtsPluginWidget::~LtsPluginWidget()
{
delete m_ui;
}
void LtsPluginWidget::setStatus(Status status)
{
QString statusText;
switch (status)
{
case INVALID:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(189, 106, 98);"));
statusText = tr("Invalid");
break;
}
case LOADED:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(124, 189, 124);"));
statusText = tr("Loaded");
break;
}
case CONFLICT:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(189, 106, 98);"));
statusText = tr("CONFLICT!");
break;
}
case UNLOADED:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(100, 100, 100);"));
statusText = tr("Unloaded");
break;
}
case INIT_FAILED:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(189, 106, 98);"));
statusText = tr("INIT FAILED!");
break;
}
case MISSING_SERVICE:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(189, 106, 98);"));
statusText = tr("MISSING SERVICE!");
break;
}
case OBLIBATORY_INTERFACES_MISSING:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(189, 106, 98);"));
statusText = tr("OBLIGATORY INTERFACES MISSING!");
break;
}
case INVALID_PLUGIN_VERSION:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(189, 106, 98);"));
statusText = tr("INVALID PLUGIN VERSION!");
break;
}
default:
{
m_ui->frStatus->setStyleSheet(QLatin1String("background-color: rgb(100, 100, 100);"));
statusText = tr("Unknown (%1)").arg(status);
break;
}
}
m_ui->leStatus->setText(statusText);
}
void LtsPluginWidget::setType(const QString &type)
{
if (type.isEmpty())
{
m_ui->leType->hide();
m_ui->lbType->hide();
}
else
{
m_ui->leType->show();
m_ui->lbType->show();
m_ui->leType->setText(type);
}
}
void LtsPluginWidget::setIdent(const QString &ident)
{
if (ident.isEmpty())
{
m_ui->leIdent->hide();
m_ui->lbIdent->hide();
}
else
{
m_ui->leIdent->show();
m_ui->lbIdent->show();
m_ui->leIdent->setText(ident);
}
}
+45
View File
@@ -0,0 +1,45 @@
#pragma once
#include <lts_plugin_manager.h>
#include <QWidget>
namespace Ui
{
class LtsPluginWidget;
}
namespace LtsPluginManager
{
class LtsPluginWidget : public QWidget
{
Q_OBJECT
public:
enum Status
{
UNKNOWN = 0,
INVALID,
LOADED,
CONFLICT,
UNLOADED,
INIT_FAILED,
MISSING_SERVICE,
OBLIBATORY_INTERFACES_MISSING,
INVALID_PLUGIN_VERSION,
};
explicit LtsPluginWidget(const QString &filename, QWidget *parent = nullptr);
~LtsPluginWidget();
void setStatus(Status status);
void setType(const QString &type = QString());
void setIdent(const QString &ident = QString());
private:
Ui::LtsPluginWidget *m_ui;
};
}
+196
View File
@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LtsPluginWidget</class>
<widget class="QWidget" name="LtsPluginWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>481</width>
<height>580</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QFrame" name="frStatus">
<property name="minimumSize">
<size>
<width>15</width>
<height>60</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>15</width>
<height>60</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="1">
<widget class="QLineEdit" name="leFilename">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lbFilename">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbType">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbStatus">
<property name="text">
<string>Status:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lbIdent">
<property name="text">
<string>Ident:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lbGuiPlugins">
<property name="text">
<string>Gui Plugins:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QWidget" name="guiPluginsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leStatus">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="leType">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="leIdent">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lbDtc">
<property name="text">
<string>Foreign Data Topic Clients:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lbFtc">
<property name="text">
<string>Foreign Function Topic Clients:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QListWidget" name="lwDtcs">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QListWidget" name="lwFtcs">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+449
View File
@@ -0,0 +1,449 @@
#include "lts_plugin_loader.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <LtsAppDescriptor/lts_app_descriptor.h>
#include <QCoreApplication>
#include <QDirIterator>
#include <QFileInfo>
#include <QJsonObject>
#include <QPluginLoader>
#include <QMutableListIterator>
#include <QDebug>
namespace LtsPluginManager
{
struct LtsPluginLoaderHandler
{
LtsPluginLoader ltsPluginLoader;
static NGL::INGLLogger &logger() { return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsPluginLoader"); }
static void cleanupPluginLoader();
};
Q_GLOBAL_STATIC(LtsPluginLoaderHandler, s_ltsPluginLoader)
void LtsPluginLoaderHandler::cleanupPluginLoader()
{
if (s_ltsPluginLoader.exists())
s_ltsPluginLoader->ltsPluginLoader.unloadAllPlugins();
}
LtsPluginLoader *LtsPluginLoader::getInstance()
{
if (!s_ltsPluginLoader.exists())
qAddPostRoutine(&LtsPluginLoaderHandler::cleanupPluginLoader);
return &s_ltsPluginLoader->ltsPluginLoader;
}
LtsPluginLoader::~LtsPluginLoader()
{
unloadAllPlugins();
}
void LtsPluginLoader::unloadAllPlugins()
{
for (auto &pi : qAsConst(m_loadedPlugins))
{
QPluginLoader *pluginLoader = pi.pluginLoader;
delete pluginLoader->instance();
if (!pluginLoader->unload())
qWarning() << "~LtsPluginLoader: could not unload" << pi.pluginName << pluginLoader->errorString();
delete pluginLoader;
}
m_loadedPlugins.clear();
}
void LtsPluginLoader::checkPlugins(const QVector<LtsAppDescriptor::AppDescription> &appVector,
QStringList &errors )
{
NGL::INGLLogger &logger = LtsPluginLoaderHandler::logger();
if (appVector.isEmpty())
{
errors += QStringLiteral("No Apps available");
return;
}
QVector<PluginInstance> dataPlugins;
QVector<PluginInstance> guiPlugins;
auto addDataPluginFn = [&](const PluginInstance &pi)
{
dataPlugins.append(pi);
return true;
};
auto addGuiPluginFn = [&](const PluginInstance &pi)
{
guiPlugins.append(pi);
return true;
};
if (!loadPlugins(PluginType::DATA, addDataPluginFn))
{
errors += QStringLiteral("failed to load data plugins");
return;
}
if (!loadPlugins(PluginType::GUI, addGuiPluginFn))
{
errors += QStringLiteral("failed to load gui plugins");
return;
}
auto checkDuplicateIidsFn = [&](const QVector<PluginInstance> &plugins, const QString &pluginType)
{
typedef QMap<QString , QString > IidMap;
IidMap iids;
for (auto i3 = plugins.constBegin(); i3 != plugins.constEnd(); ++i3)
{
const PluginInstance &pin = *i3;
auto iidFound = iids.constFind(pin.pluginName);
if (iidFound != iids.constEnd())
errors += QStringLiteral("Iid duplicate for %1 plugin '%2'").arg(pluginType, pin.pluginName);
else
iids.insert(pin.pluginName, pin.fullFileName);
}
};
checkDuplicateIidsFn(dataPlugins, QStringLiteral("data"));
checkDuplicateIidsFn(guiPlugins, QStringLiteral("gui"));
QVector<PluginInstance> plugins(dataPlugins + guiPlugins);
for (auto i1 = appVector.constBegin(); i1 != appVector.constEnd(); ++i1)
{
const LtsAppDescriptor::AppDescription &app = *i1;
const QVector<LtsAppDescriptor::PluginInfo> &piVector = app.pluginInfos;
for (auto i2 = piVector.constBegin(); i2 != piVector.constEnd(); i2++)
{
const LtsAppDescriptor::PluginInfo &pi = *i2;
bool found = false;
for (auto i3 = plugins.constBegin(); i3 != plugins.constEnd(); ++i3)
{
const PluginInstance &pin = *i3;
if (pi.iid == pin.pluginName)
{
found = true;
break;
}
}
if (!found)
{
ERROR_LOG(logger) << "Plugin with iid '" << pi.iid << "' was requested but was not loaded!";
errors += QStringLiteral("App '%1' requires plugin '%2' that could not be found.").arg(app.appName, pi.iid);
}
}
}
return;
}
bool LtsPluginLoader::loadPlugins(PluginType requestedPluginType,
const std::function<bool(const PluginInstance &)> &loadPlugin,
const QStringList &requiredPlugins,
const QString &specialTopicTypeFilter,
const QStringList &optionalPlugins)
{
NGL::INGLLogger &logger = LtsPluginLoaderHandler::logger();
Q_ASSERT(requestedPluginType != PluginType::UNKNOWN);
QStringList requiredPluginsList = requiredPlugins;
QStringList optionalPluginsList = optionalPlugins;
bool checkPluginsLists = (!requiredPluginsList.isEmpty()) || (!optionalPluginsList.isEmpty());
if (checkPluginsLists && !m_loadedPlugins.isEmpty())
{
{
QMutableListIterator<QString> i1(requiredPluginsList);
while (i1.hasNext())
{
const QString pluginName = i1.next().toLower();
QMap<PluginKey, PluginInstance>::iterator i2 = m_loadedPlugins.find(PluginKey(requestedPluginType, pluginName));
if (i2 != m_loadedPlugins.end())
{
DEBUG_LOG(logger) << "Plugin " << pluginName << " already loaded, using that instance";
if (loadPlugin)
loadPlugin(i2.value());
i1.remove();
}
}
}
{
QMutableListIterator<QString> i1(optionalPluginsList);
while (i1.hasNext())
{
const QString pluginName = i1.next().toLower();
QMap<PluginKey, PluginInstance>::iterator i2 = m_loadedPlugins.find(PluginKey(requestedPluginType, pluginName));
if (i2 != m_loadedPlugins.end())
{
DEBUG_LOG(logger) << "Plugin " << pluginName << " already loaded, using that instance";
if (loadPlugin)
loadPlugin(i2.value());
i1.remove();
}
}
}
}
QFileInfo libPathInfo(QCoreApplication::applicationDirPath() + QStringLiteral("/../lib/"));
QString libPath(libPathInfo.absolutePath());
if (!libPathInfo.exists())
{
libPathInfo.setFile(QCoreApplication::applicationFilePath());
libPath = libPathInfo.absolutePath();
}
#ifdef Q_OS_WIN
const QStringList nameFilter = QStringList(QStringLiteral("*Plugin*.dll"));
#else
const QStringList nameFilter = QStringList(QStringLiteral("*Plugin*.so"));
#endif
static const QStringList pluginTypes({QStringLiteral("data"),
QStringLiteral("gui"),
QStringLiteral("topic_type"),
QStringLiteral("project"),
QStringLiteral("style"),
QStringLiteral("special")});
QDirIterator pluginDir(libPath, nameFilter, QDir::Files);
while (pluginDir.hasNext())
{
pluginDir.next();
const QString filename = pluginDir.fileName();
if (filename.contains(QStringLiteral("PluginInterface"), Qt::CaseSensitive))
continue;
const QString absoluteFilePath = pluginDir.filePath();
DEBUG_LOG(logger) << "File Path: " << absoluteFilePath;
QScopedPointer<QPluginLoader> pluginLoader(new QPluginLoader);
pluginLoader->setFileName(absoluteFilePath);
const QJsonObject jObj = pluginLoader->metaData();
QJsonObject::const_iterator iid = jObj.find(QStringLiteral("IID"));
if (iid == jObj.end())
{
DEBUG_LOG(logger) << "Plugin '" << filename << "' has no IID !";
continue;
}
const QString jsonIid = iid.value().toString().toLower();
const QVector<QStringRef> iidParameters = jsonIid.splitRef(QLatin1Char(':'));
DEBUG_LOG(logger) << "Plugin " << absoluteFilePath << " provides iid '" << jsonIid;
if (iidParameters.count() != 3)
{
WARNING_LOG(logger) << "Invalid iid "<<jsonIid<<" for plugin " << filename;
continue;
}
bool ok = false;
int pluginLoaderVersion = iidParameters.at(1).toInt(&ok);
if (!ok || pluginLoaderVersion != PLUGIN_LOADER_VERSION)
{
WARNING_LOG(logger) << "Invalid plugin loader version" << pluginLoaderVersion << "for plugin:" << filename;
continue;
}
PluginType pluginType = PluginType::UNKNOWN;
const QString pluginName = iidParameters.at(2).toString();
const QString pluginTypeString = iidParameters.at(0).toString();
switch (pluginTypes.indexOf(pluginTypeString))
{
case 0:
pluginType = PluginType::DATA;
break;
case 1:
pluginType = PluginType::GUI;
break;
case 2:
pluginType = PluginType::TOPIC_TYPE;
break;
case 3:
pluginType = PluginType::PROJECT;
break;
case 4:
pluginType = PluginType::STYLE;
break;
case 5:
pluginType = PluginType::SPECIAL;
break;
default:
break;
}
if (pluginType != requestedPluginType)
{
DEBUG_LOG(logger) << "Plugin provides not the requested type " << (int)requestedPluginType << " is: " << (int)pluginType;
continue;
}
if (pluginType == PluginType::SPECIAL && !specialTopicTypeFilter.isEmpty())
{
if (!pluginName.startsWith(specialTopicTypeFilter))
{
DEBUG_LOG(logger) << "Special plugin, but filter does not match: " << pluginName << " - " << specialTopicTypeFilter;
continue;
}
}
if (checkPluginsLists)
{
bool found = false;
{
QMutableListIterator<QString> i (requiredPluginsList);
while (i.hasNext())
{
const QString requiredPlugin = i.next().toLower();
if (pluginName == requiredPlugin)
{
found = true;
i.remove();
break;
}
}
}
if (!found)
{
for (auto i = optionalPluginsList.constBegin(); i != optionalPluginsList.constEnd(); i++)
{
const QString optionalPlugin = (*i).toLower();
if (pluginName == optionalPlugin)
{
found = true;
break;
}
}
}
if (!found)
{
DEBUG_LOG(logger) << "Plugin " << pluginName << " was not requested";
continue;
}
}
if (loadPlugin && !m_loadedPlugins.isEmpty())
{
QMap<PluginKey, PluginInstance>::iterator i = m_loadedPlugins.find(PluginKey(requestedPluginType, pluginName));
if (i != m_loadedPlugins.end())
{
DEBUG_LOG(logger) << "Plugin " << pluginName << " already loaded, using that instance ("<<i.value().plugin->metaObject()->className()<<")";
loadPlugin(i.value());
continue;
}
}
QObject *plugin = pluginLoader->instance();
if (!plugin)
{
ERROR_LOG(logger) << "Failed to load " << filename << " - " << pluginLoader->errorString();
continue;
}
PluginInstance pi;
pi.pluginName = pluginName;
pi.fileName = filename;
pi.fullFileName = absoluteFilePath;
pi.plugin = plugin;
pi.pluginLoader = pluginLoader.data();
if (loadPlugin && !loadPlugin(pi))
{
DEBUG_LOG(logger) << "Plugin " << pluginName << " unloaded";
delete pluginLoader->instance();
pluginLoader->unload();
continue;
}
pi.pluginLoader = pluginLoader.take();
m_loadedPlugins.insert(PluginKey(requestedPluginType, pluginName), pi);
DEBUG_LOG(logger) << "Loaded " << jsonIid << " - File: " << filename;
}
if (checkPluginsLists && !requiredPluginsList.isEmpty())
{
WARNING_LOG(logger) << "These plugins could not be found for Plugin Type " << (int)requestedPluginType << ": " << requiredPluginsList.join(QStringLiteral(", "));
return false;
}
return true;
}
}
+85
View File
@@ -0,0 +1,85 @@
#pragma once
#define PLUGIN_LOADER_VERSION 3
#include <qglobal.h>
#include <functional>
#include <QMap>
#include <QPair>
#ifndef LTSPLUGINLOADER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define LTSPLUGINLOADER_EXPORT
# else
# if defined(MAKE_LTSPLUGINLOADER_LIB)
# define LTSPLUGINLOADER_EXPORT Q_DECL_EXPORT
# else
# define LTSPLUGINLOADER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
class QObject;
class QPluginLoader;
namespace LtsAppDescriptor
{
struct AppDescription;
}
namespace LtsPluginManager
{
enum class PluginType
{
UNKNOWN = 0,
DATA,
GUI,
TOPIC_TYPE,
PROJECT,
STYLE,
SPECIAL,
};
struct PluginInstance
{
QString pluginName;
QString fullFileName;
QString fileName;
QObject *plugin = nullptr;
QPluginLoader *pluginLoader = nullptr;
};
class LTSPLUGINLOADER_EXPORT LtsPluginLoader
{
public:
static LtsPluginLoader *getInstance();
void unloadAllPlugins();
void checkPlugins(const QVector<LtsAppDescriptor::AppDescription> &appVector,
QStringList &errors );
bool loadPlugins(PluginType requestedPluginType,
const std::function<bool(const PluginInstance &pluginInstance)> &loadPlugin,
const QStringList &requiredPlugins = QStringList(),
const QString &specialTopicTypeFilter = QString(),
const QStringList &optionalPlugins = QStringList());
typedef QPair<PluginType, QString> PluginKey;
private:
friend struct LtsPluginLoaderHandler;
LtsPluginLoader() = default;
~LtsPluginLoader();
QMap<PluginKey, PluginInstance> m_loadedPlugins;
};
}
+286
View File
@@ -0,0 +1,286 @@
#include "lts_plugin_manager.h"
#include "Ui/lts_plugin_manager_dialog.h"
#include <LtsSession/lts_session_data_dds.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <LtsWidgets/lts_wait_dialog.h>
#include <LtsPluginManager/lts_plugin_loader.h>
#include <LtsSession/lts_session_manager.h>
#include <LtsSession/lts_session_data.h>
#include <PluginInterfaces/data_plugin_interface.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <QTimer>
#include <QDebug>
namespace LtsPluginManager
{
LtsPluginManager::LtsPluginManager()
: m_sessionManager(new LtsSession::LtsSessionManager)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsPluginManager"))
, m_markedForDeletion(false)
{
connect(m_sessionManager, &LtsSession::LtsSessionManager::signalQuit,
this, &LtsPluginManager::signalQuit);
connect(m_sessionManager, &LtsSession::LtsSessionManager::signalLogout,
this, &LtsPluginManager::signalLogout);
connect(m_sessionManager, &LtsSession::LtsSessionManager::signalInitializationFinished,
this, &LtsPluginManager::signalInitializationFinished);
connect(m_sessionManager, &LtsSession::LtsSessionManager::signalInitializationAborted,
this, &LtsPluginManager::signalInitializationAborted);
connect(m_sessionManager, &LtsSession::LtsSessionManager::signalInitializationFinished,
this, &LtsPluginManager::slotInitializationFinished);
connect(m_sessionManager, &LtsSession::LtsSessionManager::taskSwitch,
this, &LtsPluginManager::taskSwitch);
connect(m_sessionManager, &LtsSession::LtsSessionManager::hideAllOtherBLWs,
this, &LtsPluginManager::hideAllOtherBLWs);
QTimer *t = new QTimer(this);
t->setInterval(1000);
connect(t, &QTimer::timeout,
this, &LtsPluginManager::signalStillAlive);
t->start();
}
LtsPluginManager::~LtsPluginManager()
{
delete m_sessionManager;
}
void LtsPluginManager::softQuit()
{
emit signalSoftQuit();
}
void LtsPluginManager::_softQuit()
{
m_sessionManager->softQuit();
}
QVector<LtsSession::LtsSession *> LtsPluginManager::sessions() const
{
return m_sessionManager->sessions();
}
bool LtsPluginManager::hasSituationMapInstance(const LtsAppDescriptor::AppDescription &appDescription, bool alsoTestForScriptApp)
{
if (alsoTestForScriptApp && appDescription.id == LtsAppDescriptor::App::Scripts)
return true;
for (const LtsAppDescriptor::PluginInfo &pluginInfo : qAsConst(appDescription.pluginInfos))
{
if (pluginInfo.flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::ACTIONS) &&
(pluginInfo.iid == QStringLiteral("sitmap")))
return true;
}
return false;
}
bool LtsPluginManager::hasSituationMapInstance() const
{
return hasSituationMapInstance(m_app);
}
LtsSession::LtsSession *LtsPluginManager::getSession(IDL::PartitionType partitionType, int partitionId)
{
return m_sessionManager->getSession(partitionType, partitionId);
}
bool LtsPluginManager::startApp(const LtsAppDescriptor::AppDescription &app, bool headless,
const LtsSession::DdsConnectionParams &connParams, const QString &workspaceId,
bool hidden)
{
LtsWidgets::LtsWaitDialogContainer wait;
m_app = app;
LtsPluginLoader *pluginLoader = LtsPluginLoader::getInstance();
QVector<PluginInstance> dataPlugins;
auto cb = [&](const PluginInstance &pi)
{
dataPlugins.append(pi);
return true;
};
if (!pluginLoader->loadPlugins(PluginType::DATA, cb))
{
WARNING_LOG(m_logger) << "PluginLoader failed to load data plugins - abort!";
return false;
}
QVector<PluginInstance> guiPlugins;
auto cbLoadPlugins = [&](const PluginInstance &pi)
{
guiPlugins.append(pi);
return true;
};
if (!pluginLoader->loadPlugins(PluginType::GUI, cbLoadPlugins))
{
WARNING_LOG(m_logger) << "PluginLoader failed to load gui plugins - abort!";
return false;
}
QVector<AppPluginInstance> dataApiList;
for (auto i = dataPlugins.constBegin(); i != dataPlugins.constEnd(); ++i)
{
const PluginInstance &pi = *i;
AppPluginInstance api;
api.pluginInstance = pi;
api.m_appName = m_app.appName;
api.m_appId = m_app.id;
dataApiList.append(api);
}
QVector<AppPluginInstance> guiApiList;
for (auto i = guiPlugins.constBegin(); i != guiPlugins.constEnd(); ++i)
{
const PluginInstance &pi = *i;
AppPluginInstance api;
api.pluginInstance = pi;
api.m_appName = m_app.appName;
api.m_appId = m_app.id;
for (auto i2 = app.pluginInfos.constBegin(); i2 != app.pluginInfos.constEnd(); ++i2)
{
const LtsAppDescriptor::PluginInfo &rp = *i2;
if (rp.type == LtsAppDescriptor::PluginInfo::PluginType::GUI
&& rp.iid == pi.pluginName)
{
api.m_flags = rp.flags;
api.m_options = rp.options;
break;
}
}
guiApiList.append(api);
}
LtsSession::DdsConnectionParams connParamsNew(connParams);
if (!connParamsNew.isValid())
{
INFO_LOG(m_logger) << "Invalid connection params given - using default parameter";
connParamsNew.domainId = LtsSessionData::LtsSessionData::getInstance()->getDomainIdPreset();
connParamsNew.partitionId = 0;
connParamsNew.exerciseId = 0;
connParamsNew.partitionType = IDL::PartitionType::Global;
connParamsNew.tcpConnectionUrl = LtsSessionData::LtsSessionData::getInstance()->getTcpConnectionUrl();
}
if (LtsSessionData::LtsSessionData::getInstance()->getQosFile().size() > 0 && LtsSessionData::LtsSessionData::getInstance()->getQosFile().at(0).size() > 0)
connParamsNew.qos_file = LtsSessionData::LtsSessionData::getInstance()->getQosFile();
else
connParamsNew.qos_file = QStringList();
if (!m_sessionManager->init(connParamsNew,
dataApiList,
guiApiList,
m_app.id,
workspaceId,
headless,
hidden))
{
ERROR_LOG(m_logger) << "Could not create Global Session - abort.";
return false;
}
return true;
}
}
+110
View File
@@ -0,0 +1,110 @@
#pragma once
#include "lts_plugin_manager_export.h"
#include <LtsPluginManager/lts_plugin_loader.h>
#include <LtsAppDescriptor/lts_app_descriptor.h>
#include <ProjectConfig/project_defines.h>
#include <QObject>
#include <QString>
#include <QMap>
#include <QVector>
#include <QFlags>
namespace NGL
{
class INGLLogger;
}
namespace DataPluginBase
{
class Plugin;
}
namespace GuiPluginBase
{
class Plugin;
}
namespace ProjectPlugin
{
class Plugin;
}
namespace LtsSession
{
class LtsSession;
class LtsSessionManager;
struct DdsConnectionParams;
}
namespace DeveloperTools
{
class DevDialog;
}
namespace LtsPluginManager
{
struct AppPluginInstance
{
PluginInstance pluginInstance;
QFlags<LtsAppDescriptor::PluginInfo::Flag> m_flags;
QStringList m_options;
QString m_appName;
LtsAppDescriptor::App m_appId = LtsAppDescriptor::App::Login;
};
class LTSPLUGINMANAGER_EXPORT LtsPluginManager : public QObject
{
Q_OBJECT
public:
LtsPluginManager();
~LtsPluginManager();
bool startApp(const LtsAppDescriptor::AppDescription &app, bool headless,
const LtsSession::DdsConnectionParams &connParams,
const QString &workspaceId = QString(), bool hidden = false);
LtsSession::LtsSession *getSession(IDL::PartitionType partitionType, int partitionId);
bool isInitialized() const { return m_initialized; }
const LtsAppDescriptor::AppDescription &appDescription() const { return m_app; }
QVector<LtsSession::LtsSession *> sessions() const;
Q_DECL_DEPRECATED void setMarkedForDeletion() { m_markedForDeletion = true; }
Q_DECL_DEPRECATED bool markedForDeletion() const { return m_markedForDeletion; }
const QString &description() const { return m_description; }
void setDescription(const QString &description) { m_description = description; }
static bool hasSituationMapInstance(const LtsAppDescriptor::AppDescription &appDescription, bool alsoTestFOrScriptApp = false);
bool hasSituationMapInstance() const;
void softQuit();
void _softQuit();
LtsSession::LtsSessionManager *m_sessionManager;
private:
friend class DeveloperTools::DevDialog;
LtsAppDescriptor::AppDescription m_app;
NGL::INGLLogger &m_logger;
bool m_initialized = false;
bool m_markedForDeletion;
QString m_description;
private slots:
void slotInitializationFinished() { m_initialized = true; }
signals:
void signalQuit();
void signalSoftQuit();
void signalLogout();
void signalInitializationFinished();
void signalInitializationAborted();
void signalStillAlive();
void hideAllOtherBLWs(QObject *caller);
void taskSwitch(QObject *caller);
};
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <QtCore/qglobal.h>
#ifndef LTSPLUGINMANAGER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define LTSPLUGINMANAGER_EXPORT
# else
# if defined(MAKE_LTSPLUGINMANAGER_LIB)
# define LTSPLUGINMANAGER_EXPORT Q_DECL_EXPORT
# else
# define LTSPLUGINMANAGER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif