Major Changes:
- Merged latest Qt5 devel content from dlbo (292 files changed, 7 new dirs)
- Consolidated forward-declarations and include folders
- Removed unneeded modules per Niklas' repo check list
Build System Fixes:
- Fixed CMake VERSION_GREATER syntax in ParticipantManagement/CMakeLists.txt
- Added VLC packages (libvlc-dev, vlc-plugin-base) to docker_build.sh
- Added PostgreSQL dev packages (libpq-dev, postgresql-server-dev-all) to Dockerfile
- Fixed locale warnings (ANSI_X3.4-1968 → C.UTF-8)
- Fixed ArcGIS SDK path warnings when BUILD_ARCGIS=OFF
Code Generation Fixes:
- Fixed IDL enum collisions (PortType→CorePortType/DdsutPortType, PdmEventType)
- Fixed Grantlee template svc_translation.cpp.grantlee:
- Changed {{ idl_enum.name }}_def:: to {{ idl_enum.name }}::
- Fixed .underlying() calls for C++11 scoped enums (enum class)
- Removed generated files from repo (moc_*, *_dtc.h, *_ftc.h)
Validation:
- BUILD_RTI=ON: SUCCESS
- BUILD_RTI=OFF: SUCCESS
- C++17 standard maintained for RTI 7.7 compatibility
- Ubuntu 26.04 Docker environment verified
Remaining Warnings (expected):
- BgViewer, KDChart, KDReports, Poppler-Qt6 not found (optional features)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
502 lines
15 KiB
C++
502 lines
15 KiB
C++
/*
|
|
* @RDE_HEADER@
|
|
* <short description>
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Malte Schröder, SLSE, 2016-06-08
|
|
*/
|
|
|
|
#include "aar_application.h"
|
|
#include "ui_aarApp.h"
|
|
#include "databases_model.h"
|
|
|
|
#include <ngldb/dbconnection.h>
|
|
#include <ngldb/nsqlquery.h>
|
|
#include <nglsettings/nglsettings_settings.h>
|
|
#include <ngltools/ngltools_filesystem.h>
|
|
|
|
#include <QMessageBox>
|
|
#include <QTimer>
|
|
#include <QMenu>
|
|
#include <QSettings>
|
|
#include <QDir>
|
|
#include <QThread>
|
|
#include <QScreen>
|
|
#include <QSqlError>
|
|
|
|
#define DEFAULT_DB "lts_ets_pro"
|
|
|
|
namespace AARApplication
|
|
{
|
|
|
|
AarApplication::AarApplication(QWidget *parent)
|
|
: QMainWindow(parent)
|
|
, m_ui(new Ui::AarApplication)
|
|
, m_stopping(false)
|
|
, m_proc(nullptr)
|
|
, m_progressDialog(nullptr)
|
|
, m_logger(getLogger("AarApplication"))
|
|
{
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
m_ui->setupUi(this);
|
|
|
|
const QList<QScreen*> &screenList = QGuiApplication::screens();
|
|
m_widgets.reserve(screenList.size());
|
|
for (QScreen *s : qAsConst(screenList))
|
|
{
|
|
QWidget *w = new QWidget(); // no parent
|
|
w->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
|
|
w->setGeometry(s->geometry());
|
|
w->activateWindow();
|
|
w->show();
|
|
m_widgets.append(w);
|
|
}
|
|
|
|
m_databasesModel = new DatabasesModel(this);
|
|
m_proxyModel = new DatabasesProxyModel(this);
|
|
m_proxyModel->setSourceModel(m_databasesModel);
|
|
m_ui->tableViewDatabases->setModel(m_proxyModel);
|
|
|
|
connect(m_ui->pbClose, &QPushButton::clicked, this, &AarApplication::onClosedClicked);
|
|
connect(m_ui->pbRemove, &QPushButton::clicked, this, &AarApplication::onRemoveClicked);
|
|
connect(m_ui->pbActivate, &QPushButton::clicked, this, &AarApplication::onActivateClicked);
|
|
connect(m_ui->pbActivateNetwork, &QPushButton::clicked, this, &AarApplication::onActivateNetworkClicked);
|
|
|
|
connect(m_ui->tableViewDatabases->selectionModel(), &QItemSelectionModel::selectionChanged, this, &AarApplication::enaDisa);
|
|
|
|
setWindowTitle(QLatin1String("AarApplication"));
|
|
|
|
enaDisa();
|
|
|
|
m_progressDialog = new QProgressDialog(this);
|
|
|
|
m_progressDialog->setLabelText(tr("Stopping server software ..."));
|
|
m_progressDialog->setMinimum(0);
|
|
m_progressDialog->setMaximum(0);
|
|
m_progressDialog->show();
|
|
onStopApp();
|
|
|
|
}
|
|
|
|
AarApplication::~AarApplication()
|
|
{
|
|
delete m_ui;
|
|
delete m_databasesModel;
|
|
delete m_progressDialog;
|
|
|
|
for (QSqlDatabase db : qAsConst(m_dbMap))
|
|
db.close();
|
|
|
|
m_dbPostgres.close();
|
|
|
|
if (m_proc)
|
|
m_proc->deleteLater();
|
|
|
|
qDeleteAll(m_widgets);
|
|
}
|
|
|
|
bool AarApplication::init()
|
|
{
|
|
m_ui->lblStatus->setText(tr("No active database"));
|
|
|
|
m_dbPostgres = DBConnection::open(m_logger,
|
|
QStringLiteral("postgres"),
|
|
QStringLiteral("postgres"),
|
|
QStringLiteral("QPSQL"),
|
|
QStringLiteral("localhost"),
|
|
QStringLiteral("postgres"),
|
|
QString(),
|
|
QStringLiteral("localhost_postgres"));
|
|
|
|
if (!m_dbPostgres.open())
|
|
{
|
|
ERROR_LOG(m_logger) << "Error opening postgres database" << m_dbPostgres.lastError().databaseText();
|
|
return false;
|
|
}
|
|
|
|
NSqlQuery q(m_dbPostgres);
|
|
|
|
QString stmt = QStringLiteral("SELECT datname FROM pg_database WHERE datname = '") + QStringLiteral(DEFAULT_DB) + QStringLiteral("'");
|
|
|
|
if (!q.execAndFetch(stmt))
|
|
{
|
|
NOTICE_LOG(m_logger) << "Database does not exist: " << DEFAULT_DB;
|
|
}
|
|
else
|
|
{
|
|
QSqlDatabase db_lts = DBConnection::open(m_logger,
|
|
QStringLiteral("ctc_sv"),
|
|
QStringLiteral("ctc11de"),
|
|
QStringLiteral("QPSQL"),
|
|
QStringLiteral("localhost"),
|
|
QStringLiteral(DEFAULT_DB),
|
|
QString(),
|
|
QStringLiteral("localhost_")+QStringLiteral(DEFAULT_DB));
|
|
|
|
if (!db_lts.open())
|
|
{
|
|
ERROR_LOG(m_logger) << "Error opening database " << DEFAULT_DB << " : "<< db_lts.lastError().databaseText();
|
|
m_dbPostgres.close();
|
|
return false;
|
|
}
|
|
|
|
NSqlQuery ql(db_lts);
|
|
|
|
stmt = QStringLiteral("SELECT id FROM exm.exercise");
|
|
|
|
if (!ql.execAndFetch(stmt))
|
|
{
|
|
ERROR_LOG(m_logger) << "No entry for exercise found in database " << DEFAULT_DB;
|
|
}
|
|
else
|
|
{
|
|
int dbId = ql.value(0).toInt();
|
|
db_lts.close();
|
|
|
|
QString dbName = QStringLiteral("lts_db_") + QString::number(dbId);
|
|
INFO_LOG(m_logger) << "New dbName for " << DEFAULT_DB << ": " << dbName;
|
|
|
|
stmt = QStringLiteral("ALTER DATABASE ") + QStringLiteral(DEFAULT_DB) + QStringLiteral(" RENAME TO ") + dbName;
|
|
|
|
if (!q.exec(stmt))
|
|
{
|
|
ERROR_LOG(m_logger) << "Error renaming database " << DEFAULT_DB << " : " << db_lts.lastError().databaseText();
|
|
m_dbPostgres.close();
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
stmt = QStringLiteral("SELECT datname FROM pg_database WHERE datname ilike 'lts_db_%';");
|
|
|
|
if (!q.exec(stmt))
|
|
{
|
|
ERROR_LOG(m_logger) << "Error while reading dbnames from database";
|
|
return false;
|
|
}
|
|
|
|
while (q.next())
|
|
{
|
|
QString dbName = q.value(0).toString();
|
|
QSqlDatabase db = DBConnection::open(m_logger,
|
|
QStringLiteral("ctc_sv"),
|
|
QStringLiteral("ctc11de"),
|
|
QStringLiteral("QPSQL"),
|
|
QStringLiteral("localhost"),
|
|
dbName,
|
|
QString(),
|
|
QStringLiteral("localhost_") + dbName);
|
|
|
|
if (!db.open())
|
|
{
|
|
ERROR_LOG(m_logger) << "Error while opening database " << dbName << ", error: " << db.lastError().databaseText();
|
|
continue;
|
|
}
|
|
|
|
m_databasesModel->initModel(db);
|
|
m_dbMap.insert(dbName, db);
|
|
}
|
|
|
|
m_ui->tableViewDatabases->resizeColumnsToContents();
|
|
|
|
return true;
|
|
}
|
|
|
|
void AarApplication::onClosedClicked()
|
|
{
|
|
handleProcInit(QStringLiteral("/usr/bin/openbox"), {QStringLiteral("--exit")});
|
|
m_proc->start();
|
|
m_proc->waitForFinished();
|
|
QThread::sleep(2);
|
|
close();
|
|
}
|
|
|
|
void AarApplication::onRemoveClicked()
|
|
{
|
|
disableButtons();
|
|
|
|
m_databaseToRemove = m_databasesModel->getRowData(m_ui->tableViewDatabases->currentIndex().row());
|
|
|
|
QString strMsg = QStringLiteral("Do you really want to remove the database '%1'?").arg (m_databaseToRemove.dbName);
|
|
int result = QMessageBox::question(this, tr("Remove Database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
|
if (result == QMessageBox::No)
|
|
{
|
|
enableButtons();
|
|
return;
|
|
}
|
|
|
|
DEBUG_LOG(m_logger) << "onRemoveClicked: dbName = " << m_databaseToRemove.dbName;
|
|
QSqlDatabase db = m_dbMap.value(m_databaseToRemove.dbName);
|
|
db.close();
|
|
|
|
const QStringList args({QStringLiteral("-U"),
|
|
QStringLiteral("postgres"),
|
|
QStringLiteral("-h"),
|
|
QStringLiteral("localhost"),
|
|
m_databaseToRemove.dbName
|
|
});
|
|
|
|
QString errStr;
|
|
const QString exePath = NGL::postgresExecutablePath(QStringLiteral("dropdb"), errStr);
|
|
if (!errStr.isEmpty())
|
|
WARNING_LOG(m_logger) << errStr;
|
|
|
|
handleProcInit(exePath, args);
|
|
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
this, &AarApplication::onDropDbFinished);
|
|
|
|
// start process
|
|
m_proc->start();
|
|
}
|
|
|
|
void AarApplication::onActivateClicked()
|
|
{
|
|
const QString fileName = QStringLiteral("/shd/CTC/WS/lts-cc.conf.org");
|
|
|
|
WARNING_LOG(m_logger) << "FileName: " << fileName;
|
|
QFile ltsConfig(fileName);
|
|
|
|
if (ltsConfig.exists())
|
|
ltsConfig.rename(QStringLiteral("/shd/CTC/WS/lts-cc.conf.org"), QStringLiteral("/shd/CTC/WS/lts-cc.conf"));
|
|
|
|
Exercise ex = m_databasesModel->getRowData(m_ui->tableViewDatabases->currentIndex().row());
|
|
|
|
QString strMsg = tr("Do you really want to activate database '%1'?").arg(ex.name);
|
|
int result = QMessageBox::question(this, tr("Activate local database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
|
if (result == QMessageBox::No)
|
|
return;
|
|
|
|
INFO_LOG(m_logger) << "onActivateClicked: dbName = " << ex.dbName;
|
|
|
|
QSqlDatabase db = m_dbMap.value(ex.dbName);
|
|
db.close();
|
|
|
|
NSqlQuery q(m_dbPostgres);
|
|
|
|
QString stmt = QStringLiteral("ALTER DATABASE ") + ex.dbName + QStringLiteral(" RENAME TO ") + QStringLiteral(DEFAULT_DB);
|
|
|
|
if (!q.exec(stmt))
|
|
ERROR_LOG(m_logger) << "Error renaming " << ex.dbName << " to " << DEFAULT_DB << " "<< m_dbPostgres.lastError().databaseText();
|
|
else
|
|
INFO_LOG(m_logger) << "Database " << ex.dbName << " renamed to " << DEFAULT_DB;
|
|
|
|
QString status = ex.name + QStringLiteral(" (") + ex.dbName + QStringLiteral(") ") + tr("active");
|
|
m_ui->lblStatus->setText(status);
|
|
onStartApp();
|
|
}
|
|
|
|
void AarApplication::onActivateNetworkClicked()
|
|
{
|
|
onStopApp();
|
|
//const QString fileName = QDir::homePath()+ QStringLiteral("/lts-cc.conf");
|
|
|
|
const QString fileName = QStringLiteral("/shd/CTC/WS") + QStringLiteral("/lts-cc.conf");
|
|
|
|
WARNING_LOG(m_logger) << "FileName: " << fileName;
|
|
QFile ltsConfig(fileName);
|
|
|
|
if (!ltsConfig.exists())
|
|
{
|
|
QMessageBox::critical(this, tr ("Activate network database"), tr("Network database active"), QMessageBox::Ok);
|
|
m_ui->lblStatus->setText(tr("Network database active"));
|
|
return;
|
|
}
|
|
|
|
ltsConfig.rename(QStringLiteral("/shd/CTC/WS/lts-cc.conf"), QStringLiteral("/shd/CTC/WS/lts-cc.conf.org"));
|
|
m_ui->lblStatus->setText(tr("Network database active"));
|
|
}
|
|
|
|
void AarApplication::enaDisa()
|
|
{
|
|
if (!m_ui)
|
|
return;
|
|
int selected = m_ui->tableViewDatabases->selectionModel()->selectedRows().size();
|
|
|
|
m_ui->pbRemove->setEnabled(selected > 0);
|
|
m_ui->pbActivate->setEnabled(selected > 0);
|
|
}
|
|
|
|
void AarApplication::onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
|
{
|
|
INFO_LOG(m_logger) << "onDropDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
|
|
|
|
static const QString s_title = tr("Remove Database");
|
|
static const QString s_msgFailure = tr("Removing database failed.");
|
|
static const QString s_msgSuccess = tr("Removing database successful.");
|
|
|
|
if (exitCode > 0)
|
|
{
|
|
const QString str = QString::fromLocal8Bit(m_proc->readAllStandardError()) + QLatin1Char('\n') +
|
|
QString::fromLocal8Bit(m_proc->readAllStandardOutput());
|
|
ERROR_LOG(m_logger) << "Cannot drop database: " << str;
|
|
QString msg = s_msgFailure;
|
|
QString db0 = QLatin1String("ERROR: database \"") + m_databaseToRemove.dbName + QLatin1String("\" does not exist");
|
|
if (!str.contains(db0))
|
|
msg += tr(" Database cannot be removed:\n%1.").arg(str);
|
|
QMessageBox::critical(this, s_title, msg, QMessageBox::Ok);
|
|
}
|
|
else
|
|
{
|
|
m_databasesModel->onDataChanged(m_databaseToRemove, DataModification::eRemoved);
|
|
QMessageBox::information(this, s_title, s_msgSuccess);
|
|
}
|
|
|
|
enableButtons();
|
|
}
|
|
|
|
void AarApplication::onErrorOccured(QProcess::ProcessError error)
|
|
{
|
|
ERROR_LOG(m_logger) << "error: " << error;
|
|
}
|
|
|
|
void AarApplication::onStartApp()
|
|
{
|
|
handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")});
|
|
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
this, &AarApplication::onPsauxFinished);
|
|
m_proc->start();
|
|
}
|
|
|
|
|
|
void AarApplication::onPsauxFinished()
|
|
{
|
|
enableButtons();
|
|
QByteArray output = m_proc->readAllStandardOutput();
|
|
|
|
if (output.contains("svcServiceManagement"))
|
|
{
|
|
ERROR_LOG(m_logger) << "ServiceManagement already started";
|
|
}
|
|
else
|
|
{
|
|
ERROR_LOG(m_logger) << "Start svcServiceManagement";
|
|
handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-z")});
|
|
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
this, &AarApplication::onStartAppFinished);
|
|
m_proc->start();
|
|
m_proc->waitForFinished();
|
|
}
|
|
}
|
|
|
|
void AarApplication::onStartAppFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
|
{
|
|
handleProcFinished(exitCode, exitStatus);
|
|
}
|
|
|
|
void AarApplication::onStopApp()
|
|
{
|
|
disableButtons();
|
|
handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")});
|
|
m_proc->start();
|
|
if (m_proc->waitForFinished())
|
|
onPsauxStopFinished();
|
|
}
|
|
|
|
void AarApplication::onPsauxStopFinished()
|
|
{
|
|
DEBUG_LOG(m_logger) << "IN onPsauxStopFinished";
|
|
enableButtons();
|
|
QByteArray output = m_proc->readAllStandardOutput();
|
|
|
|
if (output.contains("svcServiceManagement"))
|
|
{
|
|
if (m_stopping)
|
|
{
|
|
QThread::sleep(3);
|
|
onStopApp();
|
|
}
|
|
else
|
|
{
|
|
|
|
ERROR_LOG(m_logger) << "ServiceManagement started - stopping";
|
|
|
|
handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-s")});
|
|
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
this, &AarApplication::onStopAppFinished);
|
|
m_proc->start();
|
|
m_stopping = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
INFO_LOG(m_logger) << "ServiceManagement already stopped";
|
|
m_stopping = false;
|
|
m_progressDialog->hide();
|
|
}
|
|
|
|
m_proc->waitForFinished();
|
|
}
|
|
|
|
void AarApplication::onStopAppFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
|
{
|
|
if (m_stopping)
|
|
onPsauxStopFinished();
|
|
|
|
handleProcFinished(exitCode, exitStatus);
|
|
}
|
|
|
|
void AarApplication::handleProcInit(const QString &program, const QStringList &args)
|
|
{
|
|
if (m_proc)
|
|
{
|
|
m_proc->disconnect(this);
|
|
m_proc->deleteLater();
|
|
}
|
|
m_proc = new QProcess(this);
|
|
NOTICE_LOG(m_logger) << "Starting process '" << program << "' with args '"
|
|
<< args.join(QLatin1Char(' ')) << "'";
|
|
|
|
m_proc->setProgram(program);
|
|
m_proc->setArguments(args);
|
|
connect(m_proc, &QProcess::errorOccurred, this, &AarApplication::onErrorOccured);
|
|
disableButtons();
|
|
}
|
|
|
|
void AarApplication::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
|
{
|
|
enableButtons();
|
|
|
|
if (!m_proc)
|
|
return;
|
|
if (exitCode != 0 || exitStatus != 0)
|
|
{
|
|
QByteArray out = m_proc->readAllStandardError();
|
|
if (!out.isEmpty())
|
|
out += '\n';
|
|
out += m_proc->readAllStandardOutput();
|
|
ERROR_LOG(m_logger) << "Process finished - exitCode: " << exitCode << ", exitStatus = " << exitStatus << ", " << out;
|
|
|
|
QMessageBox::critical(this,
|
|
tr ("Execute process"), tr("Error executing process, exitCode: %1, exitStatus: %2, output: %3")
|
|
.arg(exitCode).arg(exitStatus).arg(QString::fromLocal8Bit(out)),
|
|
QMessageBox::Ok);
|
|
}
|
|
m_proc->disconnect(this);
|
|
m_proc->deleteLater();
|
|
m_proc = nullptr;
|
|
|
|
if (m_progressDialog)
|
|
m_progressDialog->hide();
|
|
}
|
|
|
|
|
|
void AarApplication::enaDisaButtons(bool bEnable)
|
|
{
|
|
{
|
|
const QList<QPushButton*> l = findChildren<QPushButton*>();
|
|
for (QPushButton *pb : l)
|
|
pb->setEnabled(bEnable);
|
|
}
|
|
{
|
|
const QList<QAction*> l = findChildren<QAction*>();
|
|
for (QAction *a : l)
|
|
a->setEnabled(bEnable);
|
|
}
|
|
if (bEnable)
|
|
enaDisa();
|
|
}
|
|
|
|
} // namespace AarApplication
|