Qt6 Migration: Merge latest Qt5 devel content and apply migration fixes

- Merged 292 changed files from dlbo snapshot
- Fixed IDL enum collisions (PortType, PdmEventType)
- Fixed Grantlee template for C++11 scoped enums
- Fixed CMake VERSION_GREATER syntax
- Added missing directories (THP, LtsRestClient, etc.)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
torstenandCopilot committed 2026-09-15 18:20:51 +00:00
1 parent c9e245a211
commit 3028302f7b
310 files changed
+2823 -740

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
#
# Tool for sending http-requests to a REST API
# $Id$
# $HeadURL$
# $Author$
# Created by Hannes Fritsche, ESZS, 2026-08-25
#
SET(SRCS
main_window.cpp
main_window.h
main.cpp
)
NGL_WRAP_UI(SRCS main_window.ui)
NGL_ADD_EXECUTABLE(TOOLSWS RestClientUi ${SRCS})
NGL_INSTALL(WS DIRECTORY rest_templates/ DESTINATION bin/updates/)
NGL_TARGET_LINK_LIBRARIES(RestClientUi
Qt5::Widgets
Qt5::Gui
LtsRestClient
)
NGL_INSTALL_TARGET(RestClientUi)
IF (BUILD_TOOLSWS)
SET(TEMPLATES_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/rest_templates")
SET(TEMPLATES_DESTINATION "${CMAKE_BINARY_DIR}/bin/rest_templates")
ADD_CUSTOM_COMMAND(
TARGET RestClientUi POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${TEMPLATES_SOURCE}" "${TEMPLATES_DESTINATION}"
COMMENT "Copy ${TEMPLATES_SOURCE} to ${TEMPLATES_DESTINATION}"
)
ENDIF()
+22
View File
@@ -0,0 +1,22 @@
/*
* main for RestClientUi
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, ESZS, 2026-08-25
*/
#include <QApplication>
#include "main_window.h"
// Documentation on how to use it can be found at https://confluence-classified.rh-int.de/spaces/LEG/pages/207919552/HOWTO+RestClientUi+Tool
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
+301
View File
@@ -0,0 +1,301 @@
#include "main_window.h"
#include "LtsRestClient/lts_rest_client.h"
#include "ui_main_window.h"
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QMessageBox>
#include <QPushButton>
// Documentation on how to use it can be found at https://confluence-classified.rh-int.de/spaces/LEG/pages/207919552/HOWTO+RestClientUi+Tool
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Connect core HTTP actions
connect(ui->m_getBtn, &QPushButton::clicked, this, &MainWindow::onGetClicked);
connect(ui->m_postBtn, &QPushButton::clicked, this, &MainWindow::onPostClicked);
connect(ui->m_putBtn, &QPushButton::clicked, this, &MainWindow::onPutClicked);
connect(ui->m_deleteBtn, &QPushButton::clicked, this, &MainWindow::onDeleteClicked);
// Connect logging output actions
connect(ui->m_clearResponseBtn, &QPushButton::clicked, this, &MainWindow::onClearResponseClicked);
connect(ui->m_exportResponseBtn, &QPushButton::clicked, this, &MainWindow::onExportResponseClicked);
loadRequestTemplates();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onClearResponseClicked()
{
ui->m_responseOutput->clear();
}
void MainWindow::onExportResponseClicked()
{
const QString content = ui->m_responseOutput->toPlainText().trimmed();
if (content.isEmpty())
{
QMessageBox::warning(this, QStringLiteral("Export Failed"), QStringLiteral("There is no response data available to export."));
return;
}
const QString fileName = QFileDialog::getSaveFileName(this,
QStringLiteral("Save Response as JSON"),
QDir::homePath() + QStringLiteral("/response.json"),
QStringLiteral("JSON Files (*.json);;All Files (*)"));
if (fileName.isEmpty())
return;
QJsonParseError parseError;
const QJsonDocument jsonDoc = QJsonDocument::fromJson(content.toUtf8(), &parseError);
QByteArray dataToWrite;
if (parseError.error == QJsonParseError::NoError)
dataToWrite = jsonDoc.toJson(QJsonDocument::Indented);
else
dataToWrite = content.toUtf8();
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text))
{
file.write(dataToWrite);
file.close();
QMessageBox::information(this, QStringLiteral("Success"), QStringLiteral("File saved successfully."));
}
else
QMessageBox::critical(this, QStringLiteral("Error"), QStringLiteral("Could not write to file:\n") + file.errorString());
}
void MainWindow::highlightMethodButton(const QString &method)
{
// Reset stylesheets for all HTTP method buttons back to default
ui->m_getBtn->setStyleSheet(QString());
ui->m_postBtn->setStyleSheet(QString());
ui->m_putBtn->setStyleSheet(QString());
ui->m_deleteBtn->setStyleSheet(QString());
// Modern green border highlight style string
const QString highlightStyle = QStringLiteral("border: 2px solid #2ecc71; font-weight: bold; background-color: #e8f8f5;");
// Apply style based on the uppercase method string
const QString upperMethod = method.toUpper().trimmed();
if (upperMethod == QStringLiteral("GET"))
ui->m_getBtn->setStyleSheet(highlightStyle);
else if (upperMethod == QStringLiteral("POST"))
ui->m_postBtn->setStyleSheet(highlightStyle);
else if (upperMethod == QStringLiteral("PUT"))
ui->m_putBtn->setStyleSheet(highlightStyle);
else if (upperMethod == QStringLiteral("DELETE")
|| upperMethod == QStringLiteral("DEL"))
ui->m_deleteBtn->setStyleSheet(highlightStyle);
}
void MainWindow::loadRequestTemplates()
{
const QString templatePath = QCoreApplication::applicationDirPath() + QStringLiteral("/templates");
QDir directory(templatePath);
if (!directory.exists())
directory.mkpath(QStringLiteral("."));
QStringList filters;
filters << QStringLiteral("*.json");
directory.setNameFilters(filters);
const QFileInfoList fileList = directory.entryInfoList(QDir::Files);
int insertIndex = 0;
for (const QFileInfo &fileInfo : fileList)
{
const QString absolutePath = fileInfo.absoluteFilePath();
QFile file(absolutePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
continue;
}
const QByteArray fileContent = file.readAll();
file.close();
QJsonParseError parseError;
const QJsonDocument metaDoc = QJsonDocument::fromJson(fileContent, &parseError);
if (parseError.error != QJsonParseError::NoError
|| !metaDoc.isObject())
continue;
const QJsonObject metaObj = metaDoc.object();
QString displayName = metaObj.value(QStringLiteral("name")).toString();
if (displayName.isEmpty())
displayName = fileInfo.fileName();
const QString targetEndpoint = metaObj.value(QStringLiteral("endpoint")).toString();
const QString targetMethod = metaObj.value(QStringLiteral("method")).toString().toUpper().trimmed();
QPushButton *templateBtn = new QPushButton(displayName, this);
connect(templateBtn, &QPushButton::clicked, this, [this, metaObj, targetEndpoint, targetMethod]()
{
// 1. Fill values into fields
ui->m_endpointInput->setText(targetEndpoint);
ui->m_jsonInput->clear();
if (metaObj.contains(QStringLiteral("payload")))
{
const QJsonValue payloadValue = metaObj.value(QStringLiteral("payload"));
if (payloadValue.isObject())
{
const QJsonDocument doc(payloadValue.toObject());
ui->m_jsonInput->setPlainText(QString::fromUtf8(doc.toJson(QJsonDocument::Indented)));
}
else if (payloadValue.isArray())
{
const QJsonDocument doc(payloadValue.toArray());
ui->m_jsonInput->setPlainText(QString::fromUtf8(doc.toJson(QJsonDocument::Indented)));
}
else
{
ui->m_jsonInput->setPlainText(payloadValue.toVariant().toString());
}
}
// 2. Visually focus the matching HTTP button
highlightMethodButton(targetMethod);
// 3. NEW: Optional Auto-Submit trigger chain execution
if (ui->m_autoSubmitCheck->isChecked())
{
if (targetMethod == QStringLiteral("GET"))
ui->m_getBtn->animateClick(); // animateClick provides nice visual feedback
else if (targetMethod == QStringLiteral("POST"))
ui->m_postBtn->animateClick();
else if (targetMethod == QStringLiteral("PUT"))
ui->m_putBtn->animateClick();
else if (targetMethod == QStringLiteral("DELETE")
|| targetMethod == QStringLiteral("DEL"))
ui->m_deleteBtn->animateClick();
}
});
ui->templateButtonContainer->insertWidget(insertIndex++, templateBtn);
}
}
LtsCommon::LtsRestClient *MainWindow::createClient()
{
return new LtsCommon::LtsRestClient(ui->m_urlInput->text(), this);
}
void MainWindow::showSuccess(const QJsonDocument &json)
{
ui->m_responseOutput->setTextColor(QColor(Qt::darkGreen));
ui->m_responseOutput->setText(QString::fromLatin1(json.toJson(QJsonDocument::Indented)));
}
void MainWindow::showError(const QString &error)
{
ui->m_responseOutput->setTextColor(QColor(Qt::red));
ui->m_responseOutput->setText(QStringLiteral("Error: ") + error);
}
void MainWindow::onGetClicked()
{
ui->m_responseOutput->clear();
LtsCommon::LtsRestClient *client = createClient();
client->get(
ui->m_endpointInput->text(),
[this](const QJsonDocument &json)
{
showSuccess(json);
},
[this](const QString &err)
{
showError(err);
});
}
void MainWindow::onPostClicked()
{
ui->m_responseOutput->clear();
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(ui->m_jsonInput->toPlainText().toUtf8(), &parseError);
if (parseError.error != QJsonParseError::NoError)
{
showError(QStringLiteral("Invalid JSON input syntax: ") + parseError.errorString());
return;
}
LtsCommon::LtsRestClient *client = createClient();
client->post(
ui->m_endpointInput->text(), jsonDoc,
[this](const QJsonDocument &json)
{
showSuccess(json);
},
[this](const QString &err)
{
showError(err);
});
}
void MainWindow::onPutClicked()
{
ui->m_responseOutput->clear();
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(ui->m_jsonInput->toPlainText().toUtf8(), &parseError);
if (parseError.error != QJsonParseError::NoError)
{
showError(QStringLiteral("Invalid JSON input syntax: ") + parseError.errorString());
return;
}
LtsCommon::LtsRestClient *client = createClient();
client->put(
ui->m_endpointInput->text(), jsonDoc,
[this](const QJsonDocument &json)
{
showSuccess(json);
},
[this](const QString &err)
{
showError(err);
});
}
void MainWindow::onDeleteClicked()
{
ui->m_responseOutput->clear();
LtsCommon::LtsRestClient *client = createClient();
client->del(
ui->m_endpointInput->text(),
[this](const QJsonDocument &json)
{
showSuccess(json);
},
[this](const QString &err)
{
showError(err);
});
}
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include "LtsRestClient/lts_rest_client.h"
#include <QJsonDocument>
#include <QMainWindow>
// Documentation on how to use it can be found at https://confluence-classified.rh-int.de/spaces/LEG/pages/207919552/HOWTO+RestClientUi+Tool
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onGetClicked();
void onPostClicked();
void onPutClicked();
void onDeleteClicked();
void onClearResponseClicked();
void onExportResponseClicked();
private:
void loadRequestTemplates();
LtsCommon::LtsRestClient *createClient();
void showSuccess(const QJsonDocument &json);
void showError(const QString &error);
void highlightMethodButton(const QString &method);
Ui::MainWindow *ui;
}; // class MainWindow
+215
View File
@@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>750</width>
<height>580</height>
</rect>
</property>
<property name="windowTitle">
<string>Qt REST Client GUI</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QFrame" name="leftFrame">
<property name="minimumSize">
<size>
<width>180</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>220</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="leftLayout">
<item>
<widget class="QLabel" name="labelTemplates">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>JSON Templates:</string>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>520</height>
</rect>
</property>
<layout class="QVBoxLayout" name="templateButtonContainer">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="mainVerticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelUrl">
<property name="text">
<string>Basis URL:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="m_urlInput">
<property name="text">
<string>http://localhost:8080</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelEndpoint">
<property name="text">
<string>Endpunkt:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_endpointInput">
<property name="text">
<string>/posts</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelJson">
<property name="text">
<string>JSON Input (for POST / PUT):</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="m_jsonInput"/>
</item>
<item>
<widget class="QCheckBox" name="m_autoSubmitCheck">
<property name="text">
<string>Submit automatically on template click</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="buttonLayout">
<item>
<widget class="QPushButton" name="m_getBtn">
<property name="text">
<string>GET</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_postBtn">
<property name="text">
<string>POST</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_putBtn">
<property name="text">
<string>PUT</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_deleteBtn">
<property name="text">
<string>DELETE</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelResponse">
<property name="text">
<string>Server Response / Error Log:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="m_responseOutput">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="responseActionLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_clearResponseBtn">
<property name="text">
<string>Clear Log</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_exportResponseBtn">
<property name="text">
<string>Export as JSON...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,5 @@
{
"name": "itemsKeys",
"method": "GET",
"endpoint": "/uncat/itemsKeys"
}