Qt6 migration: LtsWidgets API fixes, LtsWebSocket logger init, RTI Docker install

- LtsWidgets: Fixed Qt6 API compatibility issues
  - QWheelEvent::delta() → angleDelta().y()
  - QStyleOption::init() → initFrom()
  - QComboBox activated signal signature change
  - QTextCodec removal (UTF-8 default in Qt6)
  - Missing widget includes added

- LtsWebSocket: Fixed m_logger reference initialization
  - Added NGLLoggerBootstrap includes
  - Proper initialization in constructor initializer lists

- CMake: Added BUILD_LTSWEBSOCKET option for temporary exclusion

- Docker: RTI Connext permanent installation script added
  - ci/install-rti-in-docker.sh for persistent RTI setup
  - Removes need for volume mounting RTI into container

- BUILD options: FilterManagement, RTI, Codification, Grantlee, LtsWebSocket
  can be disabled for partial builds during migration

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
torstenandCopilot committed 2026-08-19 14:04:26 +02:00
1 parent 3bb6e89496
commit bafed3705f
69 files changed
+12600 -14037

No files matched your search

+42 -1
View File
@@ -18,9 +18,50 @@ RUN apt-get update && \
qt6-base-dev \ qt6-base-dev \
qt6-base-dev-tools \ qt6-base-dev-tools \
qt6-tools-dev \ qt6-tools-dev \
qt6-tools-dev-tools && \ qt6-tools-dev-tools \
qt6-svg-dev \
qt6-websockets-dev \
qt6-serialport-dev \
qt6-multimedia-dev \
qt6-declarative-dev \
libpoppler-qt6-dev \
libpq-dev \
libbz2-dev \
libboost-all-dev \
libxml2-dev \
libssl-dev \
libcurl4-openssl-dev && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
# Install Log4Qt for Qt6
RUN git clone --depth 1 https://github.com/MEONMedical/Log4Qt.git /tmp/log4qt && \
cd /tmp/log4qt && \
mkdir -p build && cd build && \
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=20 \
-DCMAKE_CXX_EXTENSIONS=OFF \
-DCMAKE_PREFIX_PATH="/usr" \
-DCMAKE_INSTALL_PREFIX="/usr/local" \
-DBUILD_SHARED_LIBS=ON .. && \
cmake --build . -- -j$(nproc) && \
cmake --install . && \
rm -rf /tmp/log4qt
# Create minimal CMake config for Log4Qt
RUN mkdir -p /usr/local/lib/cmake/Log4Qt && \
cat > /usr/local/lib/cmake/Log4Qt/Log4QtConfig.cmake << 'EOF'
if (NOT TARGET Log4Qt::log4qt)
add_library(Log4Qt::log4qt UNKNOWN IMPORTED)
set_target_properties(Log4Qt::log4qt PROPERTIES
IMPORTED_LOCATION "/usr/local/lib/liblog4qt.so"
INTERFACE_INCLUDE_DIRECTORIES "/usr/local/include"
)
endif()
set(Log4Qt_FOUND TRUE CACHE INTERNAL "Log4Qt found by package config")
set(Log4Qt_INCLUDE_DIRS "/usr/local/include" CACHE INTERNAL "Log4Qt include dir")
set(Log4Qt_LIBRARIES "/usr/local/lib/liblog4qt.so" CACHE INTERNAL "Log4Qt library")
EOF
# Set Qt platform for headless testing # Set Qt platform for headless testing
ENV QT_QPA_PLATFORM=offscreen ENV QT_QPA_PLATFORM=offscreen
+36
View File
@@ -0,0 +1,36 @@
#!/bin/bash
# Install RTI Connext into existing Docker image
set -e
RTI_SOURCE="/home/torsten/swy/sandbox/external/rti_connext_dds-7.7.0"
BASE_IMAGE="lifemaps/ci-cpp:latest"
TARGET_IMAGE="lifemaps/ci-cpp:rti"
echo "Step 1: Create container from base image..."
CONTAINER_ID=$(docker create --name rti-install-temp $BASE_IMAGE /bin/bash)
echo "Step 2: Copy RTI Connext into container..."
docker cp "$RTI_SOURCE" "$CONTAINER_ID:/opt/rti_connext_dds-7.7.0"
echo "Step 3: Commit container as new image..."
docker commit $CONTAINER_ID $TARGET_IMAGE
echo "Step 4: Remove temporary container..."
docker rm $CONTAINER_ID
echo "Step 5: Set environment variables in image..."
docker run --rm $TARGET_IMAGE /bin/bash -c '
echo "RTI Connext installed successfully"
ls -la /opt/rti_connext_dds-7.7.0 | head -10
'
echo ""
echo "RTI Connext installed in image: $TARGET_IMAGE"
echo "To use this image, set environment variables:"
echo " docker run -e RTI_CONNEXT_HOME=/opt/rti_connext_dds-7.7.0 \\"
echo " -e NDDSHOME=/opt/rti_connext_dds-7.7.0 \\"
echo " -e PATH=/opt/rti_connext_dds-7.7.0/bin:\$PATH \\"
echo " -e LD_LIBRARY_PATH=/opt/rti_connext_dds-7.7.0/lib/x64Linux4gcc7.3.0:\$LD_LIBRARY_PATH \\"
echo " -e CMAKE_PREFIX_PATH=/opt/rti_connext_dds-7.7.0/lib/cmake:\$CMAKE_PREFIX_PATH \\"
echo " $TARGET_IMAGE"
+12 -17
View File
@@ -75,6 +75,10 @@ OPTION(BUILD_PLUGINS_PARTICIPANT_ORG_CHART "Build ParticipantOrgChart (requires
OPTION(BUILD_PLUGINS_MSDL "Build MSDL module (requires Qt6 XmlPatterns)" OFF) OPTION(BUILD_PLUGINS_MSDL "Build MSDL module (requires Qt6 XmlPatterns)" OFF)
OPTION(BUILD_PLUGINS_SAAB "Build Saab module (requires Qt6 XmlPatterns)" OFF) OPTION(BUILD_PLUGINS_SAAB "Build Saab module (requires Qt6 XmlPatterns)" OFF)
OPTION(BUILD_RTI "Build RTI Connext DDS dependent modules" OFF) OPTION(BUILD_RTI "Build RTI Connext DDS dependent modules" OFF)
OPTION(BUILD_FILTERMANAGEMENT "Build FilterManagement plugins (temporarily disabled for migration)" OFF)
OPTION(BUILD_CODIFICATION "Build CodificationManagement plugins (requires KDReports)" OFF)
OPTION(BUILD_GRANTLEE "Build CodeGen Grantlee templates (requires Grantlee5/Qt5)" OFF)
OPTION(BUILD_LTSWEBSOCKET "Build LtsWebSocket module (requires NGLLogger)" OFF)
IF(WIN32) IF(WIN32)
SET(EXTERNAL_LIBRARY_DIR "C:/Development/Projekte/SituationMap/ExtFw" CACHE STRING "Library dir with all external dependencies") SET(EXTERNAL_LIBRARY_DIR "C:/Development/Projekte/SituationMap/ExtFw" CACHE STRING "Library dir with all external dependencies")
@@ -113,21 +117,12 @@ SET(CMAKE_AUTOMOC TRUE)
SET(CMAKE_AUTOUIC TRUE) SET(CMAKE_AUTOUIC TRUE)
SET(QT_USE_IMPORTED_TARGETS TRUE) SET(QT_USE_IMPORTED_TARGETS TRUE)
# Prefer Qt6, fallback to Qt5. Create Qt6::*-aliases when Qt6 is found so existing CMakeLists continue to work. # Prefer Qt6, fallback to Qt5. Create Qt6::*-aliases when Qt6 is found so existing CMakeLists continue to work.
# Try to detect Qt6 with a minimal check and then create aliases/placeholders for components used across the project. # Find Qt6 with all required components in one call to ensure all targets are properly created
# Prefer Qt6, fallback to Qt5. Create Qt6::* aliases only when the corresponding find_package(Qt6 6.8 COMPONENTS Concurrent Core Gui Location LinguistTools Network OpenGL PrintSupport
# Qt6:: component target exists. Avoid creating IMPORTED placeholder targets which Sensors Multimedia Sql Svg SerialPort Test UiTools WebSockets WebEngineCore WebEngineWidgets
# have no LOCATION and later inject 'NOTFOUND' into autogen timestamp deps. Widgets Xml XmlPatterns QUIET)
# Find minimal Qt6 Core first, then probe for other components (non-fatal).
find_package(Qt6 6.8 COMPONENTS Core QUIET)
if(Qt6_FOUND) if(Qt6_FOUND)
message(STATUS "Found Qt6: ${Qt6Core_VERSION}") message(STATUS "Found Qt6: ${Qt6Core_VERSION}")
set(_qlist Concurrent Core Gui Location LinguistTools Network OpenGL PrintSupport
Sensors Multimedia Sql Svg SerialPort Test UiTools WebSockets WebEngineCore WebEngineWidgets
Widgets Xml XmlPatterns)
foreach(_comp ${_qlist})
# Probe for each component (non-fatal).
find_package(Qt6 COMPONENTS ${_comp} QUIET)
endforeach()
# Map version variable for compatibility if available # Map version variable for compatibility if available
if(Qt6Core_VERSION) if(Qt6Core_VERSION)
set(Qt5Core_VERSION ${Qt6Core_VERSION} CACHE INTERNAL "Compatibility Qt5Core_VERSION mapped from Qt6") set(Qt5Core_VERSION ${Qt6Core_VERSION} CACHE INTERNAL "Compatibility Qt5Core_VERSION mapped from Qt6")
@@ -146,12 +141,12 @@ if(Qt6_FOUND)
endif() endif()
endif() endif()
else() else()
find_package(Qt6 5.9.0 COMPONENTS Concurrent Core Gui Location LinguistTools find_package(Qt6 5.9.0 COMPONENTS Concurrent Core Gui LinguistTools
Network OpenGL PrintSupport Sensors Multimedia Network OpenGL PrintSupport Multimedia
Sql Svg SerialPort Test UiTools WebSockets Sql Svg SerialPort Test UiTools WebSockets
WebEngineCore WebEngineWidgets Widgets Widgets Xml
Xml XmlPatterns
REQUIRED) REQUIRED)
find_package(Qt6 COMPONENTS Location Sensors WebEngineCore WebEngineWidgets XmlPatterns OPTIONAL)
MESSAGE(STATUS "Qt version is ${Qt6Core_VERSION}") MESSAGE(STATUS "Qt version is ${Qt6Core_VERSION}")
endif() endif()
@@ -36,7 +36,9 @@ ADD_SUBDIRECTORY(LtsTimeline)
ADD_SUBDIRECTORY(LtsPrinting) ADD_SUBDIRECTORY(LtsPrinting)
ADD_SUBDIRECTORY(LtsSerialPortQuerry) ADD_SUBDIRECTORY(LtsSerialPortQuerry)
ADD_SUBDIRECTORY(LtsScriptTimeline) ADD_SUBDIRECTORY(LtsScriptTimeline)
IF(BUILD_LTSWEBSOCKET)
ADD_SUBDIRECTORY(LtsWebSocket) ADD_SUBDIRECTORY(LtsWebSocket)
ENDIF()
ADD_SUBDIRECTORY(LtsProjectionWorkstation) ADD_SUBDIRECTORY(LtsProjectionWorkstation)
ADD_SUBDIRECTORY(LtsVirtualKeyboard) ADD_SUBDIRECTORY(LtsVirtualKeyboard)
ADD_SUBDIRECTORY(PluginInterfaces) ADD_SUBDIRECTORY(PluginInterfaces)
@@ -5,7 +5,11 @@
# #
FIND_PACKAGE(RTI) FIND_PACKAGE(RTI)
FIND_PACKAGE(Grantlee5 REQUIRED COMPONENTS Templates)
# Grantlee5 is Qt5-based and optional for Qt6 migration
IF(BUILD_GRANTLEE)
FIND_PACKAGE(Grantlee5 REQUIRED COMPONENTS Templates)
ENDIF()
NGL_ADD_LIBRARY2(ALL codegen_base SHARED NGL_ADD_LIBRARY2(ALL codegen_base SHARED
codegen_export.h codegen_export.h
@@ -45,7 +49,8 @@ else()
endif() endif()
NGL_INSTALL_TARGET(codegen_base) NGL_INSTALL_TARGET(codegen_base)
if (TARGET Grantlee5::Templates) # Grantlee5 is Qt5-based and optional for Qt6 migration
IF(BUILD_GRANTLEE AND TARGET Grantlee5::Templates)
NGL_ADD_LIBRARY(ALL codegen_grantlee STATIC NGL_ADD_LIBRARY(ALL codegen_grantlee STATIC
CppTopicGeneratorGrantlee.cpp CppTopicGeneratorGrantlee.cpp
CppTopicGeneratorGrantlee.h CppTopicGeneratorGrantlee.h
@@ -111,12 +116,8 @@ if (TARGET Grantlee5::Templates)
PUBLIC PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../
) )
else()
message(STATUS "Grantlee not found; skipping codegen_grantlee target")
endif()
# Smoke-test: parse all .grantlee templates in this directory to detect parse/render regressions # Smoke-test: parse all .grantlee templates in this directory to detect parse/render regressions
if (TARGET Grantlee5::Templates)
find_package(Qt6 COMPONENTS Core QUIET) find_package(Qt6 COMPONENTS Core QUIET)
if (Qt6_FOUND) if (Qt6_FOUND)
set(QTCORE_TARGET Qt6::Core) set(QTCORE_TARGET Qt6::Core)
@@ -128,30 +129,32 @@ if (TARGET Grantlee5::Templates)
add_executable(grantlee_parser_smoke tests/GrantleeParserSmoke.cpp) add_executable(grantlee_parser_smoke tests/GrantleeParserSmoke.cpp)
target_link_libraries(grantlee_parser_smoke PRIVATE Grantlee5::Templates ${QTCORE_TARGET}) target_link_libraries(grantlee_parser_smoke PRIVATE Grantlee5::Templates ${QTCORE_TARGET})
add_test(NAME GrantleeParserSmoke COMMAND grantlee_parser_smoke ${CMAKE_CURRENT_SOURCE_DIR}) add_test(NAME GrantleeParserSmoke COMMAND grantlee_parser_smoke ${CMAKE_CURRENT_SOURCE_DIR})
endif()
NGL_ADD_EXECUTABLE(ALL ngl_codegen NGL_ADD_EXECUTABLE(ALL ngl_codegen
main_grantlee.cpp main_grantlee.cpp
) )
NGL_TARGET_LINK_LIBRARIES(ngl_codegen NGL_TARGET_LINK_LIBRARIES(ngl_codegen
codegen_grantlee codegen_grantlee
LtsCommandLineParser LtsCommandLineParser
nglcoreapplication nglcoreapplication
Qt6::Core Qt6::Core
) )
NGL_WRAP_UI(codegen_gui_uics NGL_WRAP_UI(codegen_gui_uics
main_grantlee_gui.ui
)
NGL_ADD_EXECUTABLE(WS AAR SV NO_TRANSLATION codegen_gui
${codegen_gui_uics}
main_grantlee_gui.cpp
main_grantlee_gui.ui main_grantlee_gui.ui
) )
NGL_ADD_EXECUTABLE(WS AAR SV NO_TRANSLATION codegen_gui NGL_TARGET_LINK_LIBRARIES(codegen_gui
${codegen_gui_uics} codegen_grantlee
main_grantlee_gui.cpp LtsCommandLineParser
main_grantlee_gui.ui nglapplication
) Qt6::Widgets
NGL_TARGET_LINK_LIBRARIES(codegen_gui Grantlee5::Templates
codegen_grantlee )
LtsCommandLineParser ELSE()
nglapplication message(STATUS "BUILD_GRANTLEE disabled or Grantlee not found; skipping codegen_grantlee, ngl_codegen, and codegen_gui targets")
Qt6::Widgets ENDIF()
Grantlee5::Templates
)
@@ -24,6 +24,7 @@ endif()
NGL_TARGET_INCLUDE_DIRECTORIES(LtsCoordTrans NGL_TARGET_INCLUDE_DIRECTORIES(LtsCoordTrans
PUBLIC PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}
) )
SET(ltsCoordWidget_SRCS SET(ltsCoordWidget_SRCS
@@ -48,6 +49,7 @@ NGL_TARGET_INCLUDE_DIRECTORIES(ltsCoordWidget
PUBLIC PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_SOURCE_DIR}/../LtsUtils/LtsUtilsCore ${CMAKE_CURRENT_SOURCE_DIR}/../LtsUtils/LtsUtilsCore
${CMAKE_CURRENT_BINARY_DIR}
) )
IF(TARGET LtsCoordTrans) IF(TARGET LtsCoordTrans)
+46 -58
View File
@@ -1,10 +1,9 @@
#pragma once #pragma once
#include <QObject>
#include "sv_export.h"
#include <LtsCoordTrans/lts_coord_trans.h> #include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsCoordTrans/ltscoordwidget_export.h>
#include <QObject>
#include <QWidget> #include <QWidget>
class QToolButton; class QToolButton;
@@ -12,68 +11,57 @@ class QToolButton;
namespace LtsCoordWidget namespace LtsCoordWidget
{ {
class LtsCoordInputWidgetHandler; class LtsCoordInputWidgetHandler;
class LTSCOORDWIDGET_EXPORT LtsCoordWidget : public QWidget class LTSCOORDWIDGET_EXPORT LtsCoordWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum class DisplayType enum class DisplayType { MGRS5, MGRS7, UTM, WGS84, MGRS = DisplayType::MGRS5 };
{ Q_ENUM(DisplayType)
MGRS5, Q_PROPERTY(DisplayType displayType READ displayType WRITE setDisplayType)
MGRS7, Q_PROPERTY(bool withResetButton READ withResetButton WRITE setWithResetButton)
UTM, Q_PROPERTY(bool showToolTip READ showToolTip WRITE setShowToolTip)
WGS84, Q_PROPERTY(bool mgrsSquareEditable READ mgrsSquareEditable WRITE setMgrsSquareEditable)
MGRS = DisplayType::MGRS5
};
Q_ENUM(DisplayType)
Q_PROPERTY(DisplayType displayType READ displayType WRITE setDisplayType)
Q_PROPERTY(bool withResetButton READ withResetButton WRITE setWithResetButton)
Q_PROPERTY(bool showToolTip READ showToolTip WRITE setShowToolTip)
Q_PROPERTY(bool mgrsSquareEditable READ mgrsSquareEditable WRITE setMgrsSquareEditable)
explicit LtsCoordWidget(QWidget* parent = nullptr) : LtsCoordWidget(LtsCoordWidget::DisplayType::MGRS, parent) {}
explicit LtsCoordWidget(DisplayType dt, QWidget* parent = nullptr);
explicit LtsCoordWidget(QWidget *parent = nullptr) QPointF coordinate() const;
: LtsCoordWidget(LtsCoordWidget::DisplayType::MGRS, parent) DisplayType displayType() const;
{} bool withResetButton() const;
bool showToolTip() const;
bool mgrsSquareEditable() const;
bool event(QEvent* event) override;
public Q_SLOTS:
void setCoordinate(const QPointF& geoCoord, bool bUseAsDefaultValue = true);
void setCoordinate(double lon, double lat, bool bUseAsDefaultValue = true);
void setDisplayType(LtsCoordWidget::DisplayType dt);
void setWithResetButton(bool bWith);
void setShowToolTip(bool bShow);
void setMgrsSquareEditable(bool bEditable);
void setWithSurroundingMgrsSquares(bool bEnable);
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate>& geoCoords);
void clear();
Q_SIGNALS:
void coordinateChanged(const QPointF& newGeoCoord);
void invalidCoordinate();
explicit LtsCoordWidget(DisplayType dt, QWidget *parent = nullptr); private:
void rebuildUi();
void updateToolTip();
private Q_SLOTS:
void onResetToDefaultCoordinate();
QPointF coordinate() const; private:
DisplayType displayType() const; bool m_bWithResetButton = false;
bool withResetButton() const; bool m_bShowToolTip = true;
bool showToolTip() const; bool m_bMgrsSquareEditable = false;
bool mgrsSquareEditable() const; LtsCoordWidget::DisplayType m_displayType = LtsCoordWidget::DisplayType::MGRS;
bool event(QEvent *event) override; LtsCoordInputWidgetHandler* m_inputWidgetHandler = nullptr;
public Q_SLOTS: QPointF m_coordinate;
QPointF m_defaultCoordinate;
void setCoordinate(const QPointF &geoCoord, bool bUseAsDefaultValue = true);
void setCoordinate(double lon, double lat, bool bUseAsDefaultValue = true);
void setDisplayType(LtsCoordWidget::DisplayType dt);
void setWithResetButton(bool bWith);
void setShowToolTip(bool bShow);
void setMgrsSquareEditable(bool bEditable);
void setWithSurroundingMgrsSquares(bool bEnable);
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords);
void clear();
Q_SIGNALS:
void coordinateChanged(const QPointF &newGeoCoord);
void invalidCoordinate();
private:
void rebuildUi();
void updateToolTip();
private Q_SLOTS:
void onResetToDefaultCoordinate();
private:
bool m_bWithResetButton = false;
bool m_bShowToolTip = true;
bool m_bMgrsSquareEditable = false;
LtsCoordWidget::DisplayType m_displayType = LtsCoordWidget::DisplayType::MGRS;
LtsCoordInputWidgetHandler *m_inputWidgetHandler = nullptr;
QPointF m_coordinate;
QPointF m_defaultCoordinate;
}; };
} } // namespace LtsCoordWidget
@@ -15,7 +15,7 @@ SET(SRCS
printing.h printing.h
) )
if (KDReports_FOUND AND BUILD_RTI) if (KDReports_FOUND AND BUILD_CODIFICATION)
NGL_ADD_LIBRARY2(WS LtsPrinting SHARED ${SRCS}) NGL_ADD_LIBRARY2(WS LtsPrinting SHARED ${SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsPrinting NGL_TARGET_INCLUDE_DIRECTORIES(LtsPrinting
PUBLIC PUBLIC
@@ -13,6 +13,7 @@ NGL_ADD_LIBRARY2(ALL LtsUtilsSettings SHARED ${SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsSettings NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsSettings
PUBLIC PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}
) )
NGL_TARGET_LINK_LIBRARIES(LtsUtilsSettings NGL_TARGET_LINK_LIBRARIES(LtsUtilsSettings
+48 -46
View File
@@ -2,82 +2,84 @@
#include "client_connection.h" #include "client_connection.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QWebSocket> #include <QWebSocket>
namespace LtsWebSocket namespace LtsWebSocket
{ {
ClientConnection::ClientConnection(QWebSocket *socket, QObject *parent) ClientConnection::ClientConnection(QWebSocket* socket, QObject* parent)
: QThread(parent) : QThread(parent), m_logger(NGL::NGLLoggerBootstrap::getLogger()), m_socket(socket ? socket : new QWebSocket)
, m_socket(socket ? socket : new QWebSocket)
{ {
} }
ClientConnection::~ClientConnection() ClientConnection::~ClientConnection()
{ {
DEBUG_LOG(m_logger) << "Thread closed" << this; DEBUG_LOG(m_logger) << "Thread closed" << this;
delete m_socket; delete m_socket;
qDeleteAll(m_messageQueue); qDeleteAll(m_messageQueue);
} }
bool ClientConnection::init() bool ClientConnection::init()
{ {
if (m_socket == nullptr) if (m_socket == nullptr)
{ {
ERROR_LOG(m_logger) << "Initialisation failed due to an invalid socket"; ERROR_LOG(m_logger) << "Initialisation failed due to an invalid socket";
return false; return false;
} }
DEBUG_LOG(m_logger) << "Started new thread" << this; DEBUG_LOG(m_logger) << "Started new thread" << this;
connect(m_socket, &QWebSocket::textMessageReceived, this, &ClientConnection::onNewTextMessageFromSocket, Qt::DirectConnection); connect(m_socket, &QWebSocket::textMessageReceived, this, &ClientConnection::onNewTextMessageFromSocket,
connect(m_socket, &QWebSocket::connected, this, &ClientConnection::sendMessagesFromQueue); Qt::DirectConnection);
connect(m_socket, &QWebSocket::disconnected, this, &ClientConnection::onSocketDisconnect); connect(m_socket, &QWebSocket::connected, this, &ClientConnection::sendMessagesFromQueue);
connect(m_socket, &QWebSocket::disconnected, this, &ClientConnection::onSocketDisconnect);
return true; return true;
} }
void ClientConnection::addReply(ReplyMessage *message) void ClientConnection::addReply(ReplyMessage* message)
{ {
if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState) if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState)
{ {
m_messageQueue.enqueue(message); m_messageQueue.enqueue(message);
DEBUG_LOG(m_logger) << "Adding message to queue, size: " << m_messageQueue.size(); DEBUG_LOG(m_logger) << "Adding message to queue, size: " << m_messageQueue.size();
return; return;
} }
const QString msg(message->toJsonString()); const QString msg(message->toJsonString());
DEBUG_LOG(m_logger) << "Sending message: " << msg ; DEBUG_LOG(m_logger) << "Sending message: " << msg;
m_socket->sendTextMessage(msg); m_socket->sendTextMessage(msg);
delete message; delete message;
} }
void ClientConnection::onNewTextMessageFromSocket(const QString &message) void ClientConnection::onNewTextMessageFromSocket(const QString& message)
{ {
DEBUG_LOG(m_logger) << "Recv msg: " << message << this; DEBUG_LOG(m_logger) << "Recv msg: " << message << this;
emit newTextMessage(this, message); emit newTextMessage(this, message);
} }
void ClientConnection::sendMessagesFromQueue() void ClientConnection::sendMessagesFromQueue()
{ {
INFO_LOG(m_logger) << "Client connected ip: " << m_socket->peerAddress().toString() << ":" << m_socket->peerPort(); INFO_LOG(m_logger) << "Client connected ip: " << m_socket->peerAddress().toString() << ":" << m_socket->peerPort();
if (m_socket->state() != QAbstractSocket::ConnectedState) if (m_socket->state() != QAbstractSocket::ConnectedState)
return; return;
while (!m_messageQueue.isEmpty()) while (!m_messageQueue.isEmpty())
{ {
ReplyMessage *message = m_messageQueue.dequeue(); ReplyMessage* message = m_messageQueue.dequeue();
const QString msg(message->toJsonString()); const QString msg(message->toJsonString());
TRACE_LOG(m_logger) << "Send msg: " << msg; TRACE_LOG(m_logger) << "Send msg: " << msg;
m_socket->sendTextMessage(msg); m_socket->sendTextMessage(msg);
delete message; delete message;
DEBUG_LOG(m_logger) << "Sent message from queue, new size: " << m_messageQueue.size(); DEBUG_LOG(m_logger) << "Sent message from queue, new size: " << m_messageQueue.size();
} }
} }
void ClientConnection::onSocketDisconnect() void ClientConnection::onSocketDisconnect()
{ {
DEBUG_LOG(m_logger) << "Client disconnected ip: " << m_socket->peerAddress().toString() << ":" << m_socket->peerPort(); DEBUG_LOG(m_logger) << "Client disconnected ip: " << m_socket->peerAddress().toString() << ":"
exit(0); << m_socket->peerPort();
emit disconnected(this); exit(0);
emit disconnected(this);
} }
} } // namespace LtsWebSocket
+29 -47
View File
@@ -1,69 +1,51 @@
#pragma once #pragma once
#include <QObject>
#include <QtCore/QThread>
#include <QtCore/QQueue>
#include "reply_message.h"
#include "logger.h" #include "logger.h"
#include "ltswebsocketserver_export.h" #include "ltswebsocketserver_export.h"
#include "reply_message.h"
#include <QObject>
#include <QtCore/QQueue>
#include <QtCore/QThread>
class QWebSocket; class QWebSocket;
namespace LtsWebSocket namespace LtsWebSocket
{ {
class LTSWEBSOCKETSERVER_EXPORT ClientConnection : public QThread, public ReplyHandler
class LTSWEBSOCKETSERVER_EXPORT ClientConnection
: public QThread
, public ReplyHandler
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ClientConnection(QWebSocket* socket, QObject* parent = nullptr);
~ClientConnection();
explicit ClientConnection(QWebSocket *socket, QObject *parent = nullptr); bool init();
void addReply(ReplyMessage* message) override;
QWebSocket* webSocket()
{
return m_socket;
}
signals:
~ClientConnection(); void newTextMessage(ClientConnection* client, const QString& message);
void disconnected(ClientConnection* client);
private slots:
void onNewTextMessageFromSocket(const QString& message);
void sendMessagesFromQueue();
void onSocketDisconnect();
bool init(); private:
NGL::INGLLogger& m_logger;
void sendMessages();
QWebSocket* m_socket;
void addReply(ReplyMessage *message) override; QQueue<ReplyMessage*> m_messageQueue;
QWebSocket *webSocket() { return m_socket; }
signals:
void newTextMessage(ClientConnection *client, const QString &message);
void disconnected(ClientConnection *client);
private slots:
void onNewTextMessageFromSocket(const QString &message);
void sendMessagesFromQueue();
void onSocketDisconnect();
private:
NGL::INGLLogger &m_logger;
void sendMessages();
private:
NGL::INGLLogger &m_logger;
QWebSocket *m_socket;
QQueue<ReplyMessage *> m_messageQueue;
}; };
} } // namespace LtsWebSocket
+38 -39
View File
@@ -3,67 +3,66 @@
#pragma once #pragma once
#include "client_message.h" #include "client_message.h"
#include "reply_message.h"
#include "ltswebsocketcommon_export.h" #include "ltswebsocketcommon_export.h"
#include "reply_message.h"
#include <QString>
#include <QJsonParseError> #include <QJsonParseError>
#include <QString>
namespace NGL namespace NGL
{ {
class INGLLogger; class INGLLogger;
} }
namespace LtsWebSocket namespace LtsWebSocket
{ {
class LTSWEBSOCKETCOMMON_EXPORT AbstractClientMessageFactory class LTSWEBSOCKETCOMMON_EXPORT AbstractClientMessageFactory
{ {
public: public:
explicit AbstractClientMessageFactory(NGL::INGLLogger &logger) explicit AbstractClientMessageFactory(NGL::INGLLogger& logger) : m_logger(logger) {}
: m_logger(logger)
{}
virtual ~AbstractClientMessageFactory() {} virtual ~AbstractClientMessageFactory() {}
QJsonParseError parseMessage(const QString& message);
virtual AbstractClientMessage* createMessage(ReplyHandler* client, const QString& message) = 0;
QJsonParseError parseMessage(const QString &message); protected:
AbstractClientMessage* checkAttributes(ReplyHandler* client, const QString& message) const;
AbstractClientMessage* checkResult(ReplyHandler* client, const QString& message,
AbstractClientMessage* result) const;
protected:
NGL::INGLLogger& m_logger;
virtual AbstractClientMessage *createMessage(ReplyHandler *client, const QString &message) = 0; QString m_type;
int m_typeId;
protected: QString m_uuid;
AbstractClientMessage *checkAttributes(ReplyHandler *client, QJsonValue m_data;
const QString &message) const;
AbstractClientMessage *checkResult(ReplyHandler *client,
const QString &message,
AbstractClientMessage *result) const;
protected:
QString m_type;
int m_typeId;
QString m_uuid;
QJsonValue m_data;
}; };
class PongMessage final : public ReplyMessage class PongMessage final : public ReplyMessage
{ {
public: public:
static QString strPong() { return QStringLiteral("pong"); } static QString strPong()
static int idPong() { return 2; } {
explicit PongMessage(const QString &payload) return QStringLiteral("pong");
: ReplyMessage(strPong(), idPong(), QString()) }
, m_payload(payload)
{}
QString toJsonString() const override static int idPong()
{ {
return m_payload.isEmpty() ? strPong() : QStringLiteral("%1 %2").arg(strPong(), m_payload); return 2;
} }
private:
QString m_payload; explicit PongMessage(const QString& payload) : ReplyMessage(strPong(), idPong(), QString()), m_payload(payload) {}
QString toJsonString() const override
{
return m_payload.isEmpty() ? strPong() : QStringLiteral("%1 %2").arg(strPong(), m_payload);
}
private:
QString m_payload;
}; };
} } // namespace LtsWebSocket
+53 -52
View File
@@ -1,88 +1,89 @@
#include "connection_handler.h" #include "connection_handler.h"
#include <utility>
#include "client_connection.h" #include "client_connection.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QtWebSockets/QWebSocket> #include <QtWebSockets/QWebSocket>
#include <utility>
using namespace LtsWebSocket; using namespace LtsWebSocket;
ConnectionHandler::ConnectionHandler(QObject *parent) : QObject(parent) ConnectionHandler::ConnectionHandler(QObject* parent)
, m_server(nullptr), : QObject(parent), m_server(nullptr), m_logger(NGL::NGLLoggerBootstrap::getLogger())
m_logger(NGL::NGLLoggerBootstrap::getLogger()) {} {
}
ConnectionHandler::~ConnectionHandler() ConnectionHandler::~ConnectionHandler()
{ {
for (auto connection : std::as_const(m_connections)) for (auto connection : std::as_const(m_connections))
connection->disconnect(this); connection->disconnect(this);
} }
bool ConnectionHandler::init(const QString &serviceName, unsigned short port) bool ConnectionHandler::init(const QString& serviceName, unsigned short port)
{ {
if (m_server != nullptr) if (m_server != nullptr)
{ {
m_server->disconnect(); m_server->disconnect();
delete m_server; delete m_server;
} }
m_server = new QWebSocketServer(QStringLiteral("RME-") + serviceName, QWebSocketServer::NonSecureMode, this); m_server = new QWebSocketServer(QStringLiteral("RME-") + serviceName, QWebSocketServer::NonSecureMode, this);
connect(m_server, &QWebSocketServer::newConnection, this, &ConnectionHandler::onNewConnection); connect(m_server, &QWebSocketServer::newConnection, this, &ConnectionHandler::onNewConnection);
connect(m_server, &QWebSocketServer::serverError, this, &ConnectionHandler::onServerError); connect(m_server, &QWebSocketServer::serverError, this, &ConnectionHandler::onServerError);
DEBUG_LOG(m_logger) << "Trying to listen "; DEBUG_LOG(m_logger) << "Trying to listen ";
if (!m_server->listen(QHostAddress::Any, port)) if (!m_server->listen(QHostAddress::Any, port))
{ {
ERROR_LOG(m_logger) << "Not possible to listen to port " << port; ERROR_LOG(m_logger) << "Not possible to listen to port " << port;
return false; return false;
} }
DEBUG_LOG(m_logger) << "... ok, port " << m_server->serverPort(); DEBUG_LOG(m_logger) << "... ok, port " << m_server->serverPort();
return true; return true;
} }
void ConnectionHandler::sendToAllClients(ReplyMessage *message) void ConnectionHandler::sendToAllClients(ReplyMessage* message)
{ {
for (auto connection : std::as_const(m_connections)) for (auto connection : std::as_const(m_connections))
connection->addReply(new ReplyMessage(*message)); connection->addReply(new ReplyMessage(*message));
delete message; delete message;
} }
void ConnectionHandler::onServerError(QWebSocketProtocol::CloseCode closeCode) void ConnectionHandler::onServerError(QWebSocketProtocol::CloseCode closeCode)
{ {
ERROR_LOG(m_logger) << "Got server error with close code " << closeCode; ERROR_LOG(m_logger) << "Got server error with close code " << closeCode;
} }
void ConnectionHandler::onNewConnection() void ConnectionHandler::onNewConnection()
{ {
while (m_server->hasPendingConnections()) while (m_server->hasPendingConnections())
{
QWebSocket *socket = m_server->nextPendingConnection();
ClientConnection *newConnection = new ClientConnection(socket, this);
connect(newConnection, &ClientConnection::destroyed, this, [this](QObject* o)
{ {
m_connections.remove(static_cast<ClientConnection*>(o)); QWebSocket* socket = m_server->nextPendingConnection();
});
if (!newConnection->init()) ClientConnection* newConnection = new ClientConnection(socket, this);
{ connect(newConnection, &ClientConnection::destroyed, this,
ERROR_LOG(m_logger) << "Failed to initialise new client"; [this](QObject* o) { m_connections.remove(static_cast<ClientConnection*>(o)); });
delete newConnection;
newConnection = nullptr; if (!newConnection->init())
continue; {
ERROR_LOG(m_logger) << "Failed to initialise new client";
delete newConnection;
newConnection = nullptr;
continue;
}
newConnection->start();
connect(newConnection, &ClientConnection::newTextMessage, this, &ConnectionHandler::newTextMessageFromClient);
connect(newConnection, &ClientConnection::disconnected, this, &ConnectionHandler::clientDisconnected);
connect(newConnection, &ClientConnection::finished, newConnection, &ClientConnection::deleteLater);
m_connections.insert(newConnection);
emit clientConnected(newConnection);
INFO_LOG(m_logger) << "New client connected ip: " << socket->localAddress().toString() << ":"
<< socket->localPort();
} }
newConnection->start();
connect(newConnection, &ClientConnection::newTextMessage, this, &ConnectionHandler::newTextMessageFromClient);
connect(newConnection, &ClientConnection::disconnected, this, &ConnectionHandler::clientDisconnected);
connect(newConnection, &ClientConnection::finished, newConnection, &ClientConnection::deleteLater);
m_connections.insert(newConnection);
emit clientConnected(newConnection);
INFO_LOG(m_logger) << "New client connected ip: " << socket->localAddress().toString() << ":" << socket->localPort();
}
} }
@@ -172,6 +172,7 @@ NGL_TARGET_LINK_LIBRARIES(LtsWidgets
TabBarTabStyle TabBarTabStyle
LtsSessionData LtsSessionData
LtsUtilsSettings LtsUtilsSettings
NGLLogger
PUBLIC PUBLIC
LtsUtilsCore LtsUtilsCore
Qt6::Core Qt6::Core
@@ -2,25 +2,21 @@
#include "lts_abstract_sequence_widget.h" #include "lts_abstract_sequence_widget.h"
#include <QRegularExpression>
#include <QToolButton> #include <QToolButton>
namespace LtsWidgets namespace LtsWidgets
{ {
LtsAbstractSequenceWidget::LtsAbstractSequenceWidget(QWidget *parent, const bool &readOnly) LtsAbstractSequenceWidget::LtsAbstractSequenceWidget(QWidget* parent, const bool& readOnly)
: QGroupBox(parent) : QGroupBox(parent), m_readOnly(readOnly), m_pbAddMember(new QToolButton)
, m_readOnly(readOnly)
, m_pbAddMember(new QToolButton)
{ {
m_pbAddMember->setIcon(QIcon(QLatin1String(":/icons/png/add.png"))); m_pbAddMember->setIcon(QIcon(QLatin1String(":/icons/png/add.png")));
connect(m_pbAddMember, &QToolButton::clicked, this, &LtsAbstractSequenceWidget::addMember); connect(m_pbAddMember, &QToolButton::clicked, this, &LtsAbstractSequenceWidget::addMember);
} }
LtsAbstractSequenceWidget::~LtsAbstractSequenceWidget() LtsAbstractSequenceWidget::~LtsAbstractSequenceWidget() {}
{
}
void LtsAbstractSequenceWidget::addWidget(QWidget* widget, bool isReadOnly, bool isButtonVisible) void LtsAbstractSequenceWidget::addWidget(QWidget* widget, bool isReadOnly, bool isButtonVisible)
{ {
@@ -29,92 +25,91 @@ void LtsAbstractSequenceWidget::addWidget(QWidget* widget, bool isReadOnly, bool
m_pbAddMember->setVisible(isButtonVisible); m_pbAddMember->setVisible(isButtonVisible);
} }
int LtsAbstractSequenceWidget::getMemberlistSize(){ int LtsAbstractSequenceWidget::getMemberlistSize()
return m_memberList.size(); {
return m_memberList.size();
} }
void LtsAbstractSequenceWidget::getValue(QWidget *data, void LtsAbstractSequenceWidget::getValue(QWidget* data, const QString& findObjectName) const
const QString &findObjectName) const
{ {
if(!findChild<QWidget *>(findObjectName)) if (!findChild<QWidget*>(findObjectName))
return; return;
data = findChild<QWidget *>(findObjectName); data = findChild<QWidget*>(findObjectName);
} }
void LtsAbstractSequenceWidget::setMemberCount(int count) void LtsAbstractSequenceWidget::setMemberCount(int count)
{ {
QWidget *child = nullptr; QWidget* child = nullptr;
do do
{ {
child = findChild<QWidget *>(getObjectName(++count)); child = findChild<QWidget*>(getObjectName(++count));
delete child; delete child;
} } while (child);
while (child); m_memberList.removeAll(nullptr);
m_memberList.removeAll(nullptr);
} }
uint32_t LtsAbstractSequenceWidget::getMemberCount() const uint32_t LtsAbstractSequenceWidget::getMemberCount() const
{ {
int count = 0; int count = 0;
QWidget *child = findChild<QWidget *>(getObjectName(count+1)); QWidget* child = findChild<QWidget*>(getObjectName(count + 1));
while(child) while (child)
{ {
count++; count++;
child = findChild<QWidget *>(getObjectName(count+1)); child = findChild<QWidget*>(getObjectName(count + 1));
} }
return count; return count;
} }
QToolButton *LtsAbstractSequenceWidget::pbAddMember() const QToolButton* LtsAbstractSequenceWidget::pbAddMember() const
{ {
return m_pbAddMember; return m_pbAddMember;
} }
QString LtsAbstractSequenceWidget::getObjectName(int index) const QString LtsAbstractSequenceWidget::getObjectName(int index) const
{ {
return QString::number(index); return QString::number(index);
} }
void LtsAbstractSequenceWidget::addMemberWidget(QWidget *member, bool isReadOnly, bool isButtonVisible) void LtsAbstractSequenceWidget::addMemberWidget(QWidget* member, bool isReadOnly, bool isButtonVisible)
{ {
QToolButton *button = new QToolButton(); QToolButton* button = new QToolButton();
button->setIcon(QIcon(QLatin1String(":/icons/png/remove.png"))); button->setIcon(QIcon(QLatin1String(":/icons/png/remove.png")));
button->setDisabled(isReadOnly); button->setDisabled(isReadOnly);
connect(button, &QToolButton::clicked, member, &QWidget::deleteLater); connect(button, &QToolButton::clicked, member, &QWidget::deleteLater);
connect(member, &QWidget::destroyed, this, &LtsAbstractSequenceWidget::deleteMemberWidget); connect(member, &QWidget::destroyed, this, &LtsAbstractSequenceWidget::deleteMemberWidget);
connect(member, &QWidget::destroyed, button, &QToolButton::deleteLater); connect(member, &QWidget::destroyed, button, &QToolButton::deleteLater);
m_memberList.push_back(member); m_memberList.push_back(member);
setupMemberWidget(member, button, member->objectName(), isButtonVisible); setupMemberWidget(member, button, member->objectName(), isButtonVisible);
} }
void LtsAbstractSequenceWidget::deleteMemberWidget(QObject *member) void LtsAbstractSequenceWidget::deleteMemberWidget(QObject* member)
{ {
QWidget *w = qobject_cast<QWidget*>(member); QWidget* w = qobject_cast<QWidget*>(member);
if(!w) if (!w)
return; return;
for(auto child : w->children()) for (auto child : w->children())
child->deleteLater(); child->deleteLater();
m_memberList.removeAll(w); m_memberList.removeAll(w);
for(int i=0; i<m_memberList.size(); i++) for (int i = 0; i < m_memberList.size(); i++)
{
m_memberList[i]->setObjectName(getObjectName(i + 1));
for(auto child : m_memberList[i]->children())
{ {
if(child->objectName().isEmpty()) m_memberList[i]->setObjectName(getObjectName(i + 1));
continue;
QString childName = child->objectName(); for (auto child : m_memberList[i]->children())
QString newId = QString::number(i + 1); {
child->setObjectName(childName.replace(QRegExp(QLatin1String(".([0-9]*)")), newId)); if (child->objectName().isEmpty())
continue;
QString childName = child->objectName();
QString newId = QString::number(i + 1);
child->setObjectName(childName.replace(QRegularExpression(QLatin1String("\\.([0-9]*)")), newId));
}
} }
}
}
} }
} // namespace LtsWidgets
+68 -82
View File
@@ -1,137 +1,123 @@
#include "lts_background_widget.h" #include "lts_background_widget.h"
#include <QDebug>
#include <QFile>
#include <QPaintEvent> #include <QPaintEvent>
#include <QPainter> #include <QPainter>
#include <QDebug>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <QtPlatformHeaders/qwindowswindowfunctions.h> #include <QtPlatformHeaders/qwindowswindowfunctions.h>
#endif #endif
namespace LtsWidgets namespace LtsWidgets
{ {
LtsBackgroundWidget::LtsBackgroundWidget(QWidget *parent) LtsBackgroundWidget::LtsBackgroundWidget(QWidget* parent) : QDialog(parent), m_isUltraWide(false)
: QDialog(parent)
, m_isUltraWide(false)
{ {
setMouseTracking(true); setMouseTracking(true);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint ); setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
setWindowTitle(QStringLiteral("Splash")); setWindowTitle(QStringLiteral("Splash"));
setBackground(); setBackground();
} }
void LtsBackgroundWidget::setBackground() void LtsBackgroundWidget::setBackground()
{ {
static const auto backgroundFiles = static const auto backgroundFiles = {
{ QStringLiteral(":/project/background.png"),
QStringLiteral(":/project/background.png"), QStringLiteral(":/project/background.jpg"),
QStringLiteral(":/project/background.jpg"), };
}; static const auto backgroundFilesWide = {
static const auto backgroundFilesWide = QStringLiteral(":/project/background_wide.png"),
{ QStringLiteral(":/project/background_wide.jpg"),
QStringLiteral(":/project/background_wide.png"), };
QStringLiteral(":/project/background_wide.jpg"),
}; m_pixmap = QPixmap();
for (const QString& f : m_isUltraWide ? backgroundFilesWide : backgroundFiles)
{
if (!QFile::exists(f))
continue;
m_pixmap = QPixmap(f);
if (m_pixmap.isNull())
continue;
break;
}
m_pixmap = QPixmap();
for (const QString &f : m_isUltraWide ? backgroundFilesWide : backgroundFiles)
{
if (!QFile::exists(f))
continue;
m_pixmap = QPixmap(f);
if (m_pixmap.isNull()) if (m_pixmap.isNull())
continue;
break;
}
if (m_pixmap.isNull())
{
if (m_isUltraWide)
{ {
m_isUltraWide = false; if (m_isUltraWide)
setBackground(); {
m_isUltraWide = false;
setBackground();
}
else
{
qWarning() << "BackgroundWidget::c_tor: file missing or is not a valid image ':/project/background.png'";
}
} }
else
{
qWarning() << "BackgroundWidget::c_tor: file missing or is not a valid image ':/project/background.png'";
}
}
} }
void LtsBackgroundWidget::setUltraWide(bool set) void LtsBackgroundWidget::setUltraWide(bool set)
{ {
if (set == m_isUltraWide) if (set == m_isUltraWide)
return; return;
m_isUltraWide = set; m_isUltraWide = set;
setBackground(); setBackground();
update(); update();
} }
void LtsBackgroundWidget::resizeEvent(QResizeEvent* e)
void LtsBackgroundWidget::resizeEvent(QResizeEvent *e)
{ {
setUltraWide(width() > 3000); setUltraWide(width() > 3000);
QDialog::resizeEvent(e); QDialog::resizeEvent(e);
} }
void LtsBackgroundWidget::paintEvent(QPaintEvent* e)
void LtsBackgroundWidget::paintEvent(QPaintEvent *e)
{ {
if (!m_pixmap.isNull()) if (!m_pixmap.isNull())
{ {
QPainter painter(this); QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.drawPixmap(0, 0, width(), height(), m_pixmap); painter.drawPixmap(0, 0, width(), height(), m_pixmap);
} }
QDialog::paintEvent(e); QDialog::paintEvent(e);
} }
bool LtsBackgroundWidget::event(QEvent* e)
bool LtsBackgroundWidget::event(QEvent *e)
{ {
if (e->type() == QEvent::KeyPress || if (e->type() == QEvent::KeyPress || e->type() == QEvent::MouseButtonPress ||
e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove)
e->type() == QEvent::MouseButtonRelease || {
e->type() == QEvent::MouseMove)
{
emit signalOperatorAction(); emit signalOperatorAction();
e->ignore(); e->ignore();
return true; return true;
} }
return QDialog::event(e); return QDialog::event(e);
} }
void LtsBackgroundWidget::showFullScreen() void LtsBackgroundWidget::showFullScreen()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
winId(); winId();
QWindowsWindowFunctions::setHasBorderInFullScreen(windowHandle(), true); QWindowsWindowFunctions::setHasBorderInFullScreen(windowHandle(), true);
#endif #endif
QDialog::showFullScreen(); QDialog::showFullScreen();
raise(); raise();
} }
void LtsBackgroundWidget::closeEvent(QCloseEvent* e)
void LtsBackgroundWidget::closeEvent(QCloseEvent *e)
{ {
#ifdef DEVEL #ifdef DEVEL
deleteLater(); deleteLater();
#else #else
e->ignore(); e->ignore();
#endif #endif
} }
} } // namespace LtsWidgets
File diff suppressed because it is too large. Load diff
@@ -1,123 +1,133 @@
#pragma once #pragma once
#include <QObject>
#include "ltswidgets_export.h" #include "ltswidgets_export.h"
#include <LtsUtilsCore/variant_operators.h>
#include <LtsUtilsCore/variant_operators.h>
#include <QDataStream> #include <QDataStream>
#include <QIODevice>
#include <QIcon> #include <QIcon>
#include <QObject>
#include <QRegularExpression> #include <QRegularExpression>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QVector> #include <QVector>
namespace LtsWidgets namespace LtsWidgets
{ {
struct ComboboxFilterData struct ComboboxFilterData
{ {
QString text; QString text;
QVariant data; QVariant data;
QIcon icon; QIcon icon;
inline bool operator<(const ComboboxFilterData &cfd) inline bool operator<(const ComboboxFilterData& cfd)
{ {
return LtsUtils::lessThan(data, cfd.data); return LtsUtils::lessThan(data, cfd.data);
} }
inline friend QDataStream &operator<<(QDataStream &ds, const ComboboxFilterData &cfd)
{ inline friend QDataStream& operator<<(QDataStream& ds, const ComboboxFilterData& cfd)
ds << cfd.text << cfd.data << cfd.icon; {
return ds; ds << cfd.text << cfd.data << cfd.icon;
} return ds;
inline friend QDataStream &operator>>(QDataStream &ds, ComboboxFilterData &cfd) }
{
ds >> cfd.text >> cfd.data >> cfd.icon; inline friend QDataStream& operator>>(QDataStream& ds, ComboboxFilterData& cfd)
return ds; {
} ds >> cfd.text >> cfd.data >> cfd.icon;
return ds;
}
}; };
struct ComboboxFilterContent struct ComboboxFilterContent
{ {
QVector<ComboboxFilterData> data; QVector<ComboboxFilterData> data;
bool sortItems = false; bool sortItems = false;
bool isValid() const { return m_isValid; }
QVariant toVariant() const bool isValid() const
{ {
if (!isValid()) return m_isValid;
return QVariant(); }
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << (*this);
return ba;
}
static ComboboxFilterContent fromVariant(const QVariant &v) QVariant toVariant() const
{ {
ComboboxFilterContent ret; if (!isValid())
QDataStream ds(v.toByteArray()); return QVariant();
ds.startTransaction(); QByteArray ba;
ds >> ret; QDataStream ds(&ba, QIODevice::WriteOnly);
ds.commitTransaction(); ds << (*this);
ret.m_isValid = ds.status() == QDataStream::Ok; return ba;
}
return ret; static ComboboxFilterContent fromVariant(const QVariant& v)
} {
ComboboxFilterContent ret;
QDataStream ds(v.toByteArray());
ds.startTransaction();
ds >> ret;
ds.commitTransaction();
ret.m_isValid = ds.status() == QDataStream::Ok;
inline friend QDataStream &operator<<(QDataStream &ds, const ComboboxFilterContent &cfc) return ret;
{ }
ds << cfc.data << cfc.sortItems;
return ds;
}
inline friend QDataStream &operator>>(QDataStream &ds, ComboboxFilterContent &cfc)
{
ds >> cfc.data >> cfc.sortItems;
return ds;
}
private: inline friend QDataStream& operator<<(QDataStream& ds, const ComboboxFilterContent& cfc)
bool m_isValid = true; {
ds << cfc.data << cfc.sortItems;
return ds;
}
inline friend QDataStream& operator>>(QDataStream& ds, ComboboxFilterContent& cfc)
{
ds >> cfc.data >> cfc.sortItems;
return ds;
}
private:
bool m_isValid = true;
}; };
class LTSWIDGETS_EXPORT LtsColumnFilterProxyModel : public QSortFilterProxyModel class LTSWIDGETS_EXPORT LtsColumnFilterProxyModel : public QSortFilterProxyModel
{ {
Q_OBJECT Q_OBJECT
public: public:
static constexpr int ComboboxFilterRole = Qt::UserRole + 17; static constexpr int ComboboxFilterRole = Qt::UserRole + 17;
explicit LtsColumnFilterProxyModel(QObject *parent = nullptr); explicit LtsColumnFilterProxyModel(QObject* parent = nullptr);
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
void setRecursiveFilteringEnabled(bool recursive); void setRecursiveFilteringEnabled(bool recursive);
bool recursiveFilteringEnabled() const; bool recursiveFilteringEnabled() const;
#endif #endif
const QHash<int, QRegularExpression> &columnStringFilters() const { return m_columnStringFilters; } const QHash<int, QRegularExpression>& columnStringFilters() const
const QHash<int, QVariant> &columnDataFilters() const { return m_columnDataFilters; } {
return m_columnStringFilters;
}
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; const QHash<int, QVariant>& columnDataFilters() const
{
return m_columnDataFilters;
}
virtual void setColumnStringFilter(const QString &newFilterString, int column); bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
virtual void setColumnDataFilter(const QVariant &newFilterData, int column);
public slots: virtual void setColumnStringFilter(const QString& newFilterString, int column);
void onSetColumnStringFilter(const QString &newFilterString, int column); virtual void setColumnDataFilter(const QVariant& newFilterData, int column);
void onSetColumnDataFilter(const QVariant &newFilterData, int column);
protected: public slots:
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; void onSetColumnStringFilter(const QString& newFilterString, int column);
void onSetColumnDataFilter(const QVariant& newFilterData, int column);
protected:
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
bool checkIfOneChildIsVisible(const QModelIndex &parent) const; bool checkIfOneChildIsVisible(const QModelIndex& parent) const;
#endif #endif
private: private:
QHash<int, QRegularExpression> m_columnStringFilters; QHash<int, QRegularExpression> m_columnStringFilters;
QHash<int, QVariant> m_columnDataFilters; QHash<int, QVariant> m_columnDataFilters;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
bool m_bRecursiveFiltering = false; bool m_bRecursiveFiltering = false;
#endif #endif
}; };
} } // namespace LtsWidgets
+44 -63
View File
@@ -1,16 +1,15 @@
#include "lts_combo_box.h" #include "lts_combo_box.h"
#include "lts_selection_popup.h"
#include "lts_message_dialog.h" #include "lts_message_dialog.h"
#include "lts_selection_popup.h"
#include <QGuiApplication> #include <QGuiApplication>
#include <QShowEvent> #include <QShowEvent>
#ifdef NEVER #ifdef NEVER
# include <QDebug> #include <QDebug>
#endif #endif
namespace LtsWidgets namespace LtsWidgets
@@ -18,101 +17,83 @@ namespace LtsWidgets
bool LtsComboBox::s_useSelectionDialog = false; bool LtsComboBox::s_useSelectionDialog = false;
LtsComboBox::LtsComboBox(QWidget *parent) LtsComboBox::LtsComboBox(QWidget* parent) : QComboBox(parent), m_currentIndex(-1)
: QComboBox(parent)
, m_currentIndex(-1)
{ {
connect(this, &LtsComboBox::signalExternallyChanged, connect(this, &LtsComboBox::signalExternallyChanged, this, &LtsComboBox::signalRefill);
this, &LtsComboBox::signalRefill);
} }
void LtsComboBox::setUseSelectionDialog(bool bUseSelectionDialog) void LtsComboBox::setUseSelectionDialog(bool bUseSelectionDialog)
{ {
s_useSelectionDialog = bUseSelectionDialog; s_useSelectionDialog = bUseSelectionDialog;
} }
void LtsComboBox::showEvent(QShowEvent *e) void LtsComboBox::showEvent(QShowEvent* e)
{ {
QComboBox::showEvent(e); QComboBox::showEvent(e);
m_currentIndex = currentIndex(); m_currentIndex = currentIndex();
} }
void LtsComboBox::enterEvent(QEvent *e) void LtsComboBox::enterEvent(QEnterEvent* e)
{ {
BaseClass::enterEvent(e); BaseClass::enterEvent(e);
emit signalEnterEvent(); emit signalEnterEvent();
} }
void LtsComboBox::leaveEvent(QEvent *e) void LtsComboBox::leaveEvent(QEvent* e)
{ {
BaseClass::leaveEvent(e); BaseClass::leaveEvent(e);
emit signalLeaveEvent(); emit signalLeaveEvent();
} }
void LtsComboBox::showPopup() void LtsComboBox::showPopup()
{ {
bool bUseSelectionDialog = s_useSelectionDialog; bool bUseSelectionDialog = s_useSelectionDialog;
if (QGuiApplication::queryKeyboardModifiers() == Qt::ControlModifier) if (QGuiApplication::queryKeyboardModifiers() == Qt::ControlModifier)
bUseSelectionDialog = !bUseSelectionDialog; bUseSelectionDialog = !bUseSelectionDialog;
if (!bUseSelectionDialog) if (!bUseSelectionDialog)
{ {
QComboBox::showPopup(); QComboBox::showPopup();
return; return;
} }
if (!model()->rowCount()) if (!model()->rowCount())
{ {
LtsWidgets::LtsMessageDialog::showMessage(this, tr("There are no items available!")); LtsWidgets::LtsMessageDialog::showMessage(this, tr("There are no items available!"));
return; return;
} }
LtsSelectionPopup* popup = new LtsSelectionPopup(model(), currentIndex(), this);
LtsSelectionPopup* popup = new LtsSelectionPopup(model(), currentIndex(), this); popup->setAttribute(Qt::WA_DeleteOnClose);
popup->setAttribute(Qt::WA_DeleteOnClose);
#ifdef NEVER #ifdef NEVER
connect(popup, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::currentIndexChanged), this,
[](int idx) { qCritical() << " LtsComboBox: called: currentIndexChanged(int), idx=" << idx; });
connect(popup, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::activated), this,
[](int idx) { qCritical() << " LtsComboBox: called: activated(int), idx=" << idx; });
connect(popup, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::currentIndexChanged), this, [](int idx){
qCritical() << " LtsComboBox: called: currentIndexChanged(int), idx=" << idx;
});
connect(popup, static_cast<void (LtsSelectionPopup::*)(int)>(&LtsSelectionPopup::activated), this, [](int idx){
qCritical() << " LtsComboBox: called: activated(int), idx=" << idx;
});
#endif #endif
connect(popup, &LtsSelectionPopup::currentIndexChanged, this, &LtsComboBox::userChangedIndex);
connect(popup, &LtsSelectionPopup::activated, this,
static_cast<void (LtsComboBox::*)(int)>(&LtsComboBox::activated));
popup->show();
connect(popup, &LtsSelectionPopup::currentIndexChanged,
this, &LtsComboBox::userChangedIndex);
connect(popup, &LtsSelectionPopup::activated,
this, static_cast<void (LtsComboBox::*)(int)>(&LtsComboBox::activated));
popup->show();
} }
void LtsComboBox::userChangedIndex(int index) void LtsComboBox::userChangedIndex(int index)
{ {
m_currentIndex = index; m_currentIndex = index;
setCurrentIndex(index); setCurrentIndex(index);
} }
bool LtsComboBox::hasValueChanged() const bool LtsComboBox::hasValueChanged() const
{ {
if (m_currentIndex == -1) if (m_currentIndex == -1)
return false; return false;
return !(currentIndex() == m_currentIndex); return !(currentIndex() == m_currentIndex);
} }
} } // namespace LtsWidgets
+33 -37
View File
@@ -1,60 +1,56 @@
#pragma once #pragma once
#include <QObject>
#include "ltswidgets_export.h" #include "ltswidgets_export.h"
#include <QComboBox> #include <QComboBox>
#include <QObject>
namespace LtsWidgets namespace LtsWidgets
{ {
class LTSWIDGETS_EXPORT LtsComboBox : public QComboBox class LTSWIDGETS_EXPORT LtsComboBox : public QComboBox
{ {
Q_OBJECT Q_OBJECT
using BaseClass = QComboBox; using BaseClass = QComboBox;
public: public:
explicit LtsComboBox(QWidget *parent = nullptr); explicit LtsComboBox(QWidget* parent = nullptr);
~LtsComboBox() = default; ~LtsComboBox() = default;
static void setUseSelectionDialog(bool bUseSelectionDialog);
bool hasValueChanged() const;
static void setUseSelectionDialog(bool bUseSelectionDialog); void setExternalContentType(int ect)
{
m_externalContentType = ect;
}
int externalContentType() const
{
return m_externalContentType;
}
protected:
void showPopup() override;
bool hasValueChanged() const; void showEvent(QShowEvent* e) override;
void enterEvent(QEnterEvent* e) override;
void leaveEvent(QEvent*) override;
void setExternalContentType(int ect) { m_externalContentType = ect; } protected slots:
int externalContentType() const { return m_externalContentType; } void userChangedIndex(int index);
protected: signals:
void signalExternallyChanged();
void signalRefill();
void signalEnterEvent();
void signalLeaveEvent();
private:
void showPopup() override; int m_currentIndex;
int m_externalContentType;
void showEvent(QShowEvent *e) override; static bool s_useSelectionDialog;
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *) override;
protected slots:
void userChangedIndex(int index);
signals:
void signalExternallyChanged();
void signalRefill();
void signalEnterEvent();
void signalLeaveEvent();
private:
int m_currentIndex;
int m_externalContentType;
static bool s_useSelectionDialog;
}; };
} } // namespace LtsWidgets
File diff suppressed because it is too large. Load diff
+54 -63
View File
@@ -1,118 +1,109 @@
#include "lts_date_time_edit_p.h" #include "lts_date_time_edit_p.h"
#include <QApplication> #include <QApplication>
#include <QKeyEvent>
#include <QRegularExpression> #include <QRegularExpression>
#include <QValidator> #include <QValidator>
#include <QKeyEvent>
namespace LtsWidgets namespace LtsWidgets
{ {
void LineEdit::clear() void LineEdit::clear()
{ {
setStyleSheet(QString()); setStyleSheet(QString());
QLineEdit::clear(); QLineEdit::clear();
} }
bool LineEdit::isEmpty() const bool LineEdit::isEmpty() const
{ {
return text().isEmpty(); return text().isEmpty();
} }
void LineEdit::keyPressEvent(QKeyEvent *event) void LineEdit::keyPressEvent(QKeyEvent* event)
{ {
const bool wasEmpty = isEmpty(); const bool wasEmpty = isEmpty();
QLineEdit::keyPressEvent(event); QLineEdit::keyPressEvent(event);
int keyCode = event->key(); int keyCode = event->key();
if (keyCode == Qt::Key_Backspace && wasEmpty) if (keyCode == Qt::Key_Backspace && wasEmpty)
{ {
emit focusOutBackspace(); emit focusOutBackspace();
focusPreviousChild(); focusPreviousChild();
event->accept(); event->accept();
} }
} }
void LineEdit::contextMenuEvent(QContextMenuEvent *e) void LineEdit::contextMenuEvent(QContextMenuEvent* e)
{ {
Q_UNUSED(e); Q_UNUSED(e);
} }
void LineEdit::focusOutEvent(QFocusEvent *event) void LineEdit::focusOutEvent(QFocusEvent* event)
{ {
QLineEdit::focusOutEvent(event); QLineEdit::focusOutEvent(event);
emit focusOut(); emit focusOut();
} }
DigitsLineEdit::DigitsLineEdit(QWidget* parent) : LineEdit(parent)
DigitsLineEdit::DigitsLineEdit(QWidget *parent)
: LineEdit(parent)
{ {
setAlignment(Qt::AlignRight); setAlignment(Qt::AlignRight);
QRegularExpression rx(QLatin1String("[-]{0,1}[0-9 ]*")); QRegularExpression rx(QLatin1String("[-]{0,1}[0-9 ]*"));
setValidator(new QRegularExpressionValidator(rx, this)); setValidator(new QRegularExpressionValidator(rx, this));
} }
void DigitsLineEdit::setExactNumDigits(int num) void DigitsLineEdit::setExactNumDigits(int num)
{ {
m_exactNumDigits = num; m_exactNumDigits = num;
QRegularExpression rx(QString::asprintf("^[0-9 ]{%d}$", num)); QRegularExpression rx(QString::asprintf("^[0-9 ]{%d}$", num));
setValidator(new QRegularExpressionValidator(rx, this)); setValidator(new QRegularExpressionValidator(rx, this));
} }
void DigitsLineEdit::setValue(int val) void DigitsLineEdit::setValue(int val)
{ {
QString str; QString str;
if (m_exactNumDigits == -1) if (m_exactNumDigits == -1)
str.setNum(val); str.setNum(val);
else else
str = QStringLiteral("%1").arg(val, m_exactNumDigits, 10, QLatin1Char('0')); str = QStringLiteral("%1").arg(val, m_exactNumDigits, 10, QLatin1Char('0'));
setText(str); setText(str);
} }
int DigitsLineEdit::getValue() const int DigitsLineEdit::getValue() const
{ {
if (text().isEmpty()) if (text().isEmpty())
return 0; return 0;
return text().remove(QLatin1Char(' ')).toInt(); return text().remove(QLatin1Char(' ')).toInt();
} }
void DigitsLineEdit::setCursorPosition(int curPos) void DigitsLineEdit::setCursorPosition(int curPos)
{ {
curPos = curPos < 0 ? 1 : curPos; curPos = curPos < 0 ? 1 : curPos;
QLineEdit::setCursorPosition(curPos); QLineEdit::setCursorPosition(curPos);
} }
void DigitsLineEdit::wheelEvent(QWheelEvent *event) void DigitsLineEdit::wheelEvent(QWheelEvent* event)
{ {
LineEdit::wheelEvent(event); LineEdit::wheelEvent(event);
const QString txt = text(); const QString txt = text();
if (m_exactNumDigits > 0 && txt.length() != m_exactNumDigits) if (m_exactNumDigits > 0 && txt.length() != m_exactNumDigits)
return; return;
event->accept(); event->accept();
int cursorPos = cursorPosition(); int cursorPos = cursorPosition();
emit wheelEventReceived(event->delta() > 0, cursorPos); emit wheelEventReceived(event->angleDelta().y() > 0, cursorPos);
} }
void DigitsLineEdit::keyPressEvent(QKeyEvent *event) void DigitsLineEdit::keyPressEvent(QKeyEvent* event)
{ {
LineEdit::keyPressEvent(event); LineEdit::keyPressEvent(event);
if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down)
{ {
const bool bUp = event->key() == Qt::Key_Up; const bool bUp = event->key() == Qt::Key_Up;
const int cursorPos = cursorPosition(); const int cursorPos = cursorPosition();
emit wheelEventReceived(bUp, cursorPos); emit wheelEventReceived(bUp, cursorPos);
} }
} }
} } // namespace LtsWidgets
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+391 -392
View File
@@ -1,57 +1,79 @@
#pragma once #pragma once
#include <QObject>
#include "lts_base.h" #include "lts_base.h"
#include "lts_dialog_button_box.h"
#include "ltswidgets_export.h" #include "ltswidgets_export.h"
#include "requirement_widget.h" #include "requirement_widget.h"
#include "lts_dialog_button_box.h"
#include <NGLLogger/NGLLoggerBootstrap.h> #include <NGLLogger/NGLLoggerBootstrap.h>
#include <QPushButton>
#include <QLineEdit>
#include <QComboBox>
#include <QCheckBox> #include <QCheckBox>
#include <QSpinBox> #include <QComboBox>
#include <QDateTimeEdit> #include <QDateTimeEdit>
#include <QSlider> #include <QDebug>
#include <QLineEdit>
#include <QObject>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QPointer>
#include <QPushButton>
#include <QRadioButton>
#include <QSlider>
#include <QSpinBox>
#include <QTextEdit> #include <QTextEdit>
#include <QWidget> #include <QWidget>
#include <QRadioButton>
#include <QPointer>
#include <QDebug>
namespace LtsWidgets namespace LtsWidgets
{ {
class TopicInfo class TopicInfo
{ {
public: public:
int entityId() const { return m_entityId; } int entityId() const
const QString &topicName() const { return m_topicName; } {
bool isLocked() const { return m_locked; } return m_entityId;
bool isValid() const { return m_valid; } }
void setEntity(int entityId) { m_entityId = entityId; } const QString& topicName() const
void setTopicName(const QString &topicName) { m_topicName = topicName; } {
void setLocked(bool locked = true) { m_locked = locked; } return m_topicName;
void setValid() { m_valid = true; } }
private: bool isLocked() const
{
return m_locked;
}
NGL::INGLLogger &m_logger; bool isValid() const
QString m_topicName; {
int m_entityId{0}; return m_valid;
bool m_locked{false}; }
bool m_valid{false};
void setEntity(int entityId)
{
m_entityId = entityId;
}
void setTopicName(const QString& topicName)
{
m_topicName = topicName;
}
void setLocked(bool locked = true)
{
m_locked = locked;
}
void setValid()
{
m_valid = true;
}
private:
QString m_topicName;
int m_entityId{0};
bool m_locked{false};
bool m_valid{false};
}; };
class LtsBaseLayoutWidget; class LtsBaseLayoutWidget;
class LtsDialogHelper; class LtsDialogHelper;
class LtsProgressDialogHelper; class LtsProgressDialogHelper;
@@ -59,416 +81,393 @@ class LtsDialogButtonBox;
class LtsToolBarArea; class LtsToolBarArea;
class OverlayContainer; class OverlayContainer;
enum class ButtonCombination {
OkApplyCancel,
enum class ButtonCombination OkCancel,
{
OkApplyCancel,
OkCancel, CloseOnly,
SeamlessDialog,
CloseOnly,
SeamlessDialog,
}; };
class LTSWIDGETS_EXPORT LtsDialog : public QWidget class LTSWIDGETS_EXPORT LtsDialog : public QWidget
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool unchangeable READ unchangeable WRITE setUnchangeable) Q_PROPERTY(bool unchangeable READ unchangeable WRITE setUnchangeable)
public: public:
static int s_object_count; static int s_object_count;
explicit LtsDialog(QWidget* parent = nullptr, ButtonCombination buttonCombination = ButtonCombination::CloseOnly,
bool closeable = true);
~LtsDialog();
LtsDialogHelper* getHelper();
explicit LtsDialog(QWidget *parent = nullptr, ButtonCombination buttonCombination = ButtonCombination::CloseOnly, bool closeable = true); bool hasUnsavedChanges() const
~LtsDialog();
LtsDialogHelper *getHelper();
bool hasUnsavedChanges() const { return m_changesMade || m_currentlyBlocking; }
virtual void retranslate() = 0;
void closeRequest();
void setUnchangeable(bool unchangeable = true);
bool unchangeable() const { return m_unchangeableDialog; }
bool addDialog(LtsDialog *dialog, const QString &menuGroup, const QString &identifier, const LayoutArea &layoutArea = LayoutArea::eDialogTab, bool setClosable = true, bool focusNewTab = true);
Q_DECL_DEPRECATED bool addDialogFixed(LtsDialog *dialog, const char *menuGroupUntranslated, const QString &identifier, const LayoutArea &layoutArea = LayoutArea::eDialogTab, bool setClosable = true, bool focusNewTab = true);
bool focusDialog(const QString &menuGroup, const QString &identifier, const LayoutArea &layoutArea);
bool amIFocused() const;
void setBaseLayoutWidget(LtsBaseLayoutWidget *baseLayoutWidget);
void __unchange__() { resetChanges(); }
void setClosable(bool closable) { m_isClosable = closable; }
bool isClosable() const { return m_isClosable; }
virtual void aboutToClose() {}
void setMenuGroup(const QString &menuGroup) { m_menuGroup = menuGroup; }
const QString &menuGroup() const { return m_menuGroup; }
void setIdentifier(const QString &identifier);
virtual void tableColumnOrganiserSetting(){};
const QString &identifier() const { return m_identifier; }
void setOverlay(QWidget *widget);
void unsetOverlay();
static inline void setMinWidthForWidgetHelper(QWidget *w)
{
int width = w->sizeHint().width();
w->setMinimumWidth(width);
}
QString windowTitle() const
{
return m_title;
}
void tryLockTopicNew();
virtual void tryLockTopicNew (const QString &topicName, int entityId = -1);
void triggerTopicLock();
void setOnlineHelpFilename(const QString &fileName);
void setCurrentlyBlocking(bool currentlyBlocking = true) { m_currentlyBlocking = currentlyBlocking; }
signals:
void startMainSelect(LtsWidgets::LayoutArea);
void endMainSelect(LtsWidgets::LayoutArea);
void signalChangesMade();
void signalHide(QObject *object);
void signalChangesReset();
void signalFocused();
void visibilityChanged(bool visible);
void signalLockTopic(const LtsWidgets::TopicInfo &topicInfo);
void signalShowOnlineHelp(const QString &fileName);
protected:
void translate(const QString &title);
template <typename T>
void translate(T *ui, const QString &title)
{
translate(title);
if (ui)
ui->retranslateUi(this);
m_uiRequirements->retranslate();
}
void hideEvent(QHideEvent *event) override
{
QWidget::hideEvent(event);
emit visibilityChanged(false);
}
template <typename T>
void translate(T *ui, const QString &custom, bool isNew, const QString &title)
{
QString newTitle;
if (!isNew)
{ {
if (unchangeable()) return m_changesMade || m_currentlyBlocking;
{ }
if (custom.isEmpty())
newTitle = (tr("Show %1").arg(title)); virtual void retranslate() = 0;
void closeRequest();
void setUnchangeable(bool unchangeable = true);
bool unchangeable() const
{
return m_unchangeableDialog;
}
bool addDialog(LtsDialog* dialog, const QString& menuGroup, const QString& identifier,
const LayoutArea& layoutArea = LayoutArea::eDialogTab, bool setClosable = true,
bool focusNewTab = true);
Q_DECL_DEPRECATED bool addDialogFixed(LtsDialog* dialog, const char* menuGroupUntranslated,
const QString& identifier,
const LayoutArea& layoutArea = LayoutArea::eDialogTab,
bool setClosable = true, bool focusNewTab = true);
bool focusDialog(const QString& menuGroup, const QString& identifier, const LayoutArea& layoutArea);
bool amIFocused() const;
void setBaseLayoutWidget(LtsBaseLayoutWidget* baseLayoutWidget);
void __unchange__()
{
resetChanges();
}
void setClosable(bool closable)
{
m_isClosable = closable;
}
bool isClosable() const
{
return m_isClosable;
}
virtual void aboutToClose() {}
void setMenuGroup(const QString& menuGroup)
{
m_menuGroup = menuGroup;
}
const QString& menuGroup() const
{
return m_menuGroup;
}
void setIdentifier(const QString& identifier);
virtual void tableColumnOrganiserSetting(){};
const QString& identifier() const
{
return m_identifier;
}
void setOverlay(QWidget* widget);
void unsetOverlay();
static inline void setMinWidthForWidgetHelper(QWidget* w)
{
int width = w->sizeHint().width();
w->setMinimumWidth(width);
}
QString windowTitle() const
{
return m_title;
}
void tryLockTopicNew();
virtual void tryLockTopicNew(const QString& topicName, int entityId = -1);
void triggerTopicLock();
void setOnlineHelpFilename(const QString& fileName);
void setCurrentlyBlocking(bool currentlyBlocking = true)
{
m_currentlyBlocking = currentlyBlocking;
}
signals:
void startMainSelect(LtsWidgets::LayoutArea);
void endMainSelect(LtsWidgets::LayoutArea);
void signalChangesMade();
void signalHide(QObject* object);
void signalChangesReset();
void signalFocused();
void visibilityChanged(bool visible);
void signalLockTopic(const LtsWidgets::TopicInfo& topicInfo);
void signalShowOnlineHelp(const QString& fileName);
protected:
void translate(const QString& title);
template <typename T>
void translate(T* ui, const QString& title)
{
translate(title);
if (ui)
ui->retranslateUi(this);
m_uiRequirements->retranslate();
}
void hideEvent(QHideEvent* event) override
{
QWidget::hideEvent(event);
emit visibilityChanged(false);
}
template <typename T>
void translate(T* ui, const QString& custom, bool isNew, const QString& title)
{
QString newTitle;
if (!isNew)
{
if (unchangeable())
{
if (custom.isEmpty())
newTitle = (tr("Show %1").arg(title));
else
newTitle = (tr("Show %1: %2").arg(title, custom));
}
else
{
if (custom.isEmpty())
newTitle = (tr("Edit %1").arg(title));
else
newTitle = (tr("Edit %1: %2").arg(title, custom));
tryLockTopicNew();
}
}
else else
newTitle = (tr("Show %1: %2").arg(title, custom)); {
} newTitle = (tr("New %1").arg(title));
else m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->hide();
{ m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setText(tr("Create"));
if (custom.isEmpty()) }
newTitle = (tr("Edit %1").arg(title));
else
newTitle = (tr("Edit %1: %2").arg(title, custom));
translate(ui, newTitle);
tryLockTopicNew();
}
} }
else
template <typename T>
void translate(T* ui, const QString& customUniqueTopicName, int topicId, const QString& custom,
const QString& title)
{ {
newTitle = (tr("New %1").arg(title)); Q_UNUSED(customUniqueTopicName);
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->hide();
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setText(tr("Create")); initTopicLockHandler(customUniqueTopicName, topicId);
translate(ui, custom, (topicId < 1), title);
} }
translate(ui, newTitle); template <typename T, typename S>
}
void translate(T* ui, const S& data, const QString& custom, const QString& title)
template <typename T>
void translate(T* ui, const QString &customUniqueTopicName, int topicId, const QString &custom, const QString &title)
{
Q_UNUSED(customUniqueTopicName);
initTopicLockHandler(customUniqueTopicName, topicId);
translate(ui, custom ,
(topicId < 1 ),
title);
}
template <typename T, typename S>
void translate(T *ui, const S &data, const QString &custom, const QString &title)
{
translate(ui, QString::fromUtf8(typeid(data).name()), data.id(), custom , title);
}
template <typename T, typename S>
void translate(T *ui, const S &data, const QString &title)
{
translate(ui, data, QString::fromStdString(data.name()), title);
}
virtual void dialogCanceled() {}
LtsBaseLayoutWidget* baseLayoutWidget();
void setNoTopicLock() { m_noLockTopic = true; }
private:
friend class LtsDialogHelper;
bool m_changesMade;
bool m_currentlyBlocking { false };
bool m_firstShow;
QPointer<LtsBaseLayoutWidget> m_baseLayoutWidget;
bool m_isClosable;
TopicInfo m_topicInfo;
public:
QString m_topicLockedBy;
private:
bool m_noLockTopic;
bool m_unchangeableDialog;
QPointer<LtsDialogHelper> m_dialogHelper;
QString m_title;
QString m_onlineHelpFileName;
QString m_menuGroup;
QString m_identifier;
QPointer<OverlayContainer> m_overlayContainer;
QPointer<QWidget> m_overlayWidget;
bool _apply();
void _close();
void _discard();
void _hide();
void resetChanges();
void addDebugMenuButton();
void tryLockTopic();
void initTopicLockHandler(const QString &topicName, int entityId);
void setWindowTitle(const QString &title);
void updateWindowTitle();
void addConnections(QWidget *widget);
template <typename WidgetType, typename SignalFunc>
bool addChangesMadeSignal(QWidget *widget, SignalFunc signal)
{
WidgetType *concreteWidget = qobject_cast<WidgetType *>(widget);
if (!concreteWidget)
return false;
connect(concreteWidget, signal, this, &LtsDialog::slotChangesMade);
return true;
}
template <typename WidgetType>
void setWidgetsReadonly(bool readonly)
{
const auto children = findChildren<WidgetType *>();
for (WidgetType *widget : children )
{ {
widget->setProperty("lastReadOnlyState", widget->isReadOnly()); translate(ui, QString::fromUtf8(typeid(data).name()), data.id(), custom, title);
widget->setReadOnly(readonly);
} }
}
template <typename T, typename S>
template <typename WidgetType> void translate(T* ui, const S& data, const QString& title)
void setWidgetsDisabled(bool disabled)
{
const auto children = findChildren<WidgetType *>();
for (WidgetType *widget : children)
{ {
widget->setProperty("lastEnabledState", widget->isEnabled()); translate(ui, data, QString::fromStdString(data.name()), title);
widget->setEnabled(!disabled);
} }
}
template <typename WidgetType> virtual void dialogCanceled() {}
void restoreReadonly()
{ LtsBaseLayoutWidget* baseLayoutWidget();
const auto children = findChildren<WidgetType *>();
for (WidgetType *widget : children) void setNoTopicLock()
{ {
QVariant lastState = widget->property("lastReadOnlyState"); m_noLockTopic = true;
if (lastState.isValid() && !lastState.isNull() && lastState.canConvert(QMetaType::Bool))
widget->setReadOnly(lastState.toBool());
} }
}
template <typename WidgetType> private:
void restoreEnabled() friend class LtsDialogHelper;
{
const auto children = findChildren<WidgetType *>(); bool m_changesMade;
for (WidgetType *widget : children) bool m_currentlyBlocking{false};
bool m_firstShow;
QPointer<LtsBaseLayoutWidget> m_baseLayoutWidget;
bool m_isClosable;
TopicInfo m_topicInfo;
public:
QString m_topicLockedBy;
private:
bool m_noLockTopic;
bool m_unchangeableDialog;
QPointer<LtsDialogHelper> m_dialogHelper;
NGL::INGLLogger& m_logger;
QString m_title;
QString m_onlineHelpFileName;
QString m_menuGroup;
QString m_identifier;
QPointer<OverlayContainer> m_overlayContainer;
QPointer<QWidget> m_overlayWidget;
bool _apply();
void _close();
void _discard();
void _hide();
void resetChanges();
void addDebugMenuButton();
void tryLockTopic();
void initTopicLockHandler(const QString& topicName, int entityId);
void setWindowTitle(const QString& title);
void updateWindowTitle();
void addConnections(QWidget* widget);
template <typename WidgetType, typename SignalFunc> bool addChangesMadeSignal(QWidget* widget, SignalFunc signal)
{ {
QVariant lastState = widget->property("lastEnabledState"); WidgetType* concreteWidget = qobject_cast<WidgetType*>(widget);
if (lastState.isValid() && !lastState.isNull() && lastState.canConvert(QMetaType::Bool))
widget->setEnabled(lastState.toBool()); if (!concreteWidget)
return false;
connect(concreteWidget, signal, this, &LtsDialog::slotChangesMade);
return true;
} }
}
public slots: template <typename WidgetType> void setWidgetsReadonly(bool readonly)
{
const auto children = findChildren<WidgetType*>();
for (WidgetType* widget : children)
{
widget->setProperty("lastReadOnlyState", widget->isReadOnly());
widget->setReadOnly(readonly);
}
}
template <typename WidgetType> void setWidgetsDisabled(bool disabled)
{
const auto children = findChildren<WidgetType*>();
for (WidgetType* widget : children)
{
widget->setProperty("lastEnabledState", widget->isEnabled());
widget->setEnabled(!disabled);
}
}
void slotChangesMade(); template <typename WidgetType> void restoreReadonly()
{
const auto children = findChildren<WidgetType*>();
for (WidgetType* widget : children)
{
QVariant lastState = widget->property("lastReadOnlyState");
if (lastState.isValid() && !lastState.isNull() && lastState.canConvert(QMetaType::Bool))
widget->setReadOnly(lastState.toBool());
}
}
void slotHide(); template <typename WidgetType> void restoreEnabled()
void slotLock(const QString &lockedBy); {
void slotUnlock(); const auto children = findChildren<WidgetType*>();
for (WidgetType* widget : children)
{
QVariant lastState = widget->property("lastEnabledState");
if (lastState.isValid() && !lastState.isNull() && lastState.canConvert(QMetaType::Bool))
widget->setEnabled(lastState.toBool());
}
}
private slots: public slots:
void slotApply();
void slotOkay();
void slotClose();
void onReadOnlyButtonClicked(); void slotChangesMade();
protected: void slotHide();
virtual void lock(); void slotLock(const QString& lockedBy);
virtual void unlock(); void slotUnlock();
virtual bool apply() { return true; } private slots:
void showEvent(QShowEvent *event) override; void slotApply();
Button askApplyDiscardCancel(); void slotOkay();
void slotClose();
LtsDialogButtonBox *m_buttonBox; void onReadOnlyButtonClicked();
UiRequirementList *m_uiRequirements;
protected:
virtual void lock();
virtual void unlock();
virtual bool apply()
{
return true;
}
void showEvent(QShowEvent* event) override;
Button askApplyDiscardCancel();
LtsDialogButtonBox* m_buttonBox;
UiRequirementList* m_uiRequirements;
}; };
template <typename T> T* initDialog(T* dialog)
template<typename T>
T *initDialog(T *dialog)
{ {
if (!dialog->init()) if (!dialog->init())
{ {
dialog->deleteLater(); dialog->deleteLater();
return nullptr; return nullptr;
} }
return dialog; return dialog;
} }
template <typename T, typename... F> T* initDialog(T* dialog, F&&... f)
template<typename T, typename ... F>
T *initDialog(T *dialog, F&&... f)
{ {
if (!dialog->init(std::forward<F>(f)...)) if (!dialog->init(std::forward<F>(f)...))
{ {
dialog->deleteLater(); dialog->deleteLater();
return nullptr; return nullptr;
} }
return dialog; return dialog;
} }
template <typename T, typename... F> T* createThrowableDialog(F&&... f)
template<typename T, typename ... F>
T *createThrowableDialog(F&&... f)
{ {
T *dlg = nullptr; T* dlg = nullptr;
try try
{ {
dlg = new T(std::forward<F>(f)...); dlg = new T(std::forward<F>(f)...);
} }
catch (const char *s) catch (const char* s)
{ {
fprintf(stderr, "Dialog could not be created: %s\n", s); fprintf(stderr, "Dialog could not be created: %s\n", s);
return nullptr; return nullptr;
} }
catch (const QString &msg) catch (const QString& msg)
{ {
fprintf(stderr, "Dialog could not be created: %s\n", msg.toStdString().c_str()); fprintf(stderr, "Dialog could not be created: %s\n", msg.toStdString().c_str());
return nullptr; return nullptr;
} }
catch (...) catch (...)
{ {
fprintf(stderr, "Dialog could not be created: unknown error\n"); fprintf(stderr, "Dialog could not be created: unknown error\n");
return nullptr; return nullptr;
} }
return dlg; return dlg;
} }
} // namespace LtsWidgets
}
+300 -306
View File
@@ -1,489 +1,483 @@
#include "lts_drag_icon.h" #include "lts_drag_icon.h"
#include <QAction>
#include <QButtonGroup>
#include <QDrag> #include <QDrag>
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QDragLeaveEvent> #include <QDragLeaveEvent>
#include <QDropEvent> #include <QDropEvent>
#include <QMimeData>
#include <QAction>
#include <QVBoxLayout>
#include <QLabel> #include <QLabel>
#include <QMimeData>
#include <QPainter>
#include <QPixmap> #include <QPixmap>
#include <QToolButton> #include <QToolButton>
#include <QButtonGroup> #include <QVBoxLayout>
#include <QPainter>
namespace LtsWidgets namespace LtsWidgets
{ {
class LtsToolButton : public QToolButton class LtsToolButton : public QToolButton
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LtsToolButton(QWidget *parent) explicit LtsToolButton(QWidget* parent)
: QToolButton(parent) : QToolButton(parent), m_sameWidgetDrop(false), m_isDraggable(true), m_startPos(QPoint())
, m_sameWidgetDrop(false) {
, m_isDraggable(true) setAutoFillBackground(false);
, m_startPos(QPoint()) setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
{ }
setAutoFillBackground(false);
setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
}
virtual ~LtsToolButton() = default; virtual ~LtsToolButton() = default;
void mousePressEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent* event) override;
void dragEnterEvent(QDragEnterEvent *event) override; void dragEnterEvent(QDragEnterEvent* event) override;
void setSameWidgetDrop(bool drop) { m_sameWidgetDrop = drop; }
bool sameWidgetDrop() const { return m_sameWidgetDrop; }
void setDraggable(bool isDraggable) { m_isDraggable = isDraggable; }
void dropEvent(QDropEvent *event) override
{
emit newDropEvent(event);
QToolButton::dropEvent(event);
}
void addMimeData(const QString &mimeType, const QByteArray &data);
bool removeMimeData(const QString &mimeType);
void removeAllMimeData() { m_mimeData.clear(); }
protected: void setSameWidgetDrop(bool drop)
void initButton(); {
m_sameWidgetDrop = drop;
}
signals: bool sameWidgetDrop() const
void newDropEvent(QDropEvent *e); {
void dropSuc(); return m_sameWidgetDrop;
}
private: void setDraggable(bool isDraggable)
void performDrag(QMouseEvent *event); {
bool m_sameWidgetDrop; m_isDraggable = isDraggable;
bool m_isDraggable; }
QPoint m_startPos;
QMap<QString, QByteArray> m_mimeData;
void dropEvent(QDropEvent* event) override
{
emit newDropEvent(event);
QToolButton::dropEvent(event);
}
void addMimeData(const QString& mimeType, const QByteArray& data);
bool removeMimeData(const QString& mimeType);
void removeAllMimeData()
{
m_mimeData.clear();
}
protected:
void initButton();
signals:
void newDropEvent(QDropEvent* e);
void dropSuc();
private:
void performDrag(QMouseEvent* event);
bool m_sameWidgetDrop;
bool m_isDraggable;
QPoint m_startPos;
QMap<QString, QByteArray> m_mimeData;
}; };
LtsDragIcon::LtsDragIcon(QWidget* parent)
: QWidget(parent), m_lay(nullptr), m_toolButton(nullptr), m_icon(), m_dragLabel(new QLabel(this)), m_text(),
LtsDragIcon::LtsDragIcon(QWidget *parent) m_style(ButtonStyle::eAll), m_forceFixedSize(false), m_isDraggable(true), m_dropHandlerKey(0L),
: QWidget(parent) m_buttonSize(ButtonSize::eDefault), m_showDragIcon(true)
, m_lay(nullptr)
, m_toolButton(nullptr)
, m_icon()
, m_dragLabel(new QLabel(this))
, m_text()
, m_style(ButtonStyle::eAll)
, m_forceFixedSize(false)
, m_isDraggable(true)
, m_dropHandlerKey(0L)
, m_buttonSize(ButtonSize::eDefault)
, m_showDragIcon(true)
{ {
setAutoFillBackground(false); setAutoFillBackground(false);
initButton(); initButton();
} }
void LtsDragIcon::setStyleToButton() void LtsDragIcon::setStyleToButton()
{ {
if (nullptr == m_toolButton) return; if (nullptr == m_toolButton)
return;
switch (m_style) switch (m_style)
{ {
case ButtonStyle::eIconOnly: case ButtonStyle::eIconOnly: {
{ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); setFixedSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)));
setFixedSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize))); m_toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
m_toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly); }
} break; break;
case ButtonStyle::eTextOnly: case ButtonStyle::eTextOnly: {
{ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); setFixedSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
setFixedSize( QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX) ); m_toolButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
m_toolButton->setToolButtonStyle(Qt::ToolButtonTextOnly); layout()->setSizeConstraint(QLayout::SetDefaultConstraint);
layout()->setSizeConstraint( QLayout::SetDefaultConstraint ); }
} break; break;
case ButtonStyle::eTextNextToIcon: case ButtonStyle::eTextNextToIcon: {
{ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); setFixedSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
setFixedSize( QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX) ); m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); layout()->setSizeConstraint(QLayout::SetDefaultConstraint);
layout()->setSizeConstraint( QLayout::SetDefaultConstraint ); }
} break; break;
default: break;
}
default:
break;
}
} }
void LtsDragIcon::initButton() void LtsDragIcon::initButton()
{ {
setMinimumSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)); setMinimumSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize));
delete m_toolButton; delete m_toolButton;
delete m_lay; delete m_lay;
delete layout(); delete layout();
m_toolButton = new LtsToolButton(this); m_toolButton = new LtsToolButton(this);
m_toolButton->setDraggable(m_isDraggable); m_toolButton->setDraggable(m_isDraggable);
connect(m_toolButton, &LtsToolButton::clicked, this, &LtsDragIcon::clicked); connect(m_toolButton, &LtsToolButton::clicked, this, &LtsDragIcon::clicked);
connect(m_toolButton, &LtsToolButton::toggled, this, &LtsDragIcon::toggled); connect(m_toolButton, &LtsToolButton::toggled, this, &LtsDragIcon::toggled);
connect(m_toolButton, &LtsToolButton::newDropEvent, this, &LtsDragIcon::newDropEvent); connect(m_toolButton, &LtsToolButton::newDropEvent, this, &LtsDragIcon::newDropEvent);
connect(m_toolButton, &LtsToolButton::dropSuc, this, &LtsDragIcon::dropSuc); connect(m_toolButton, &LtsToolButton::dropSuc, this, &LtsDragIcon::dropSuc);
m_toolButton->setIcon(modifyIcon(m_icon)); m_toolButton->setIcon(modifyIcon(m_icon));
m_toolButton->setText(m_text); m_toolButton->setText(m_text);
generateToolTip(); generateToolTip();
m_toolButton->setIconSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize))); m_toolButton->setIconSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)));
QVBoxLayout* box = new QVBoxLayout(this);
box->setContentsMargins(0, 0, 0, 0);
box->setSpacing(0);
box->addWidget(m_toolButton);
QVBoxLayout *box = new QVBoxLayout(this); this->setLayout(box);
box->setMargin(0);
box->setSpacing(0);
box->addWidget(m_toolButton);
this->setLayout(box); m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); if (m_forceFixedSize)
{
m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setFixedSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)));
}
else
{
m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
}
if (m_forceFixedSize) setStyleToButton();
{
m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setFixedSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)));
}
else
{
m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
}
setStyleToButton();
} }
void LtsDragIcon::addToButtonGroup(QButtonGroup *btnGrp, int btnGrpId) void LtsDragIcon::addToButtonGroup(QButtonGroup* btnGrp, int btnGrpId)
{ {
btnGrp->addButton(m_toolButton, btnGrpId); btnGrp->addButton(m_toolButton, btnGrpId);
} }
void LtsDragIcon::setIcon(const QIcon& icon)
void LtsDragIcon::setIcon(const QIcon &icon)
{ {
m_icon = icon; m_icon = icon;
(m_toolButton) ? m_toolButton->setIcon(modifyIcon(m_icon)) : initButton(); (m_toolButton) ? m_toolButton->setIcon(modifyIcon(m_icon)) : initButton();
} }
void LtsDragIcon::setMenu(QMenu* menu)
void LtsDragIcon::setMenu(QMenu *menu)
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
m_toolButton->setMenu(menu); m_toolButton->setMenu(menu);
} }
QMenu *LtsDragIcon::menu() const QMenu* LtsDragIcon::menu() const
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
return nullptr; return nullptr;
return m_toolButton->menu(); return m_toolButton->menu();
} }
void LtsDragIcon::setText(const QString& text)
void LtsDragIcon::setText(const QString &text)
{ {
m_text = text; m_text = text;
(m_toolButton) ? generateToolTip() : initButton(); (m_toolButton) ? generateToolTip() : initButton();
} }
void LtsDragIcon::setContext(const QString &context) void LtsDragIcon::setContext(const QString& context)
{ {
m_context = context; m_context = context;
generateToolTip(); generateToolTip();
} }
void LtsDragIcon::generateToolTip() void LtsDragIcon::generateToolTip()
{ {
if (!m_toolButton || m_text.isEmpty()) if (!m_toolButton || m_text.isEmpty())
return; return;
QString text(m_text); QString text(m_text);
if (!m_context.isEmpty()) if (!m_context.isEmpty())
text.prepend(m_context + QLatin1String(" - ")); text.prepend(m_context + QLatin1String(" - "));
m_toolButton->setText(m_text); m_toolButton->setText(m_text);
m_toolButton->setToolTip(text); m_toolButton->setToolTip(text);
} }
bool LtsDragIcon::isCheckable() bool LtsDragIcon::isCheckable()
{ {
return (m_toolButton) ? m_toolButton->isCheckable() : false; return (m_toolButton) ? m_toolButton->isCheckable() : false;
} }
void LtsDragIcon::setDraggable(bool draggable) void LtsDragIcon::setDraggable(bool draggable)
{ {
m_isDraggable = draggable; m_isDraggable = draggable;
m_toolButton->setDraggable(m_isDraggable); m_toolButton->setDraggable(m_isDraggable);
} }
void LtsDragIcon::setCheckable(bool checkable) void LtsDragIcon::setCheckable(bool checkable)
{ {
m_toolButton->setCheckable(checkable); m_toolButton->setCheckable(checkable);
} }
bool LtsDragIcon::isChecked() const bool LtsDragIcon::isChecked() const
{ {
return (m_toolButton) ? m_toolButton->isChecked() : false; return (m_toolButton) ? m_toolButton->isChecked() : false;
} }
void LtsDragIcon::setChecked(bool checked) void LtsDragIcon::setChecked(bool checked)
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
m_toolButton->setChecked(checked); m_toolButton->setChecked(checked);
} }
void LtsDragIcon::setSameWidgetDrop(bool drop) void LtsDragIcon::setSameWidgetDrop(bool drop)
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
m_toolButton->setSameWidgetDrop(drop); m_toolButton->setSameWidgetDrop(drop);
} }
bool LtsDragIcon::sameWidgetDrop() const bool LtsDragIcon::sameWidgetDrop() const
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
return false; return false;
return m_toolButton->sameWidgetDrop(); return m_toolButton->sameWidgetDrop();
} }
void LtsDragIcon::addMimeData(const QString &mimeType, const QByteArray &data) void LtsDragIcon::addMimeData(const QString& mimeType, const QByteArray& data)
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
m_toolButton->addMimeData(mimeType, data); m_toolButton->addMimeData(mimeType, data);
} }
bool LtsDragIcon::removeMimeData(const QString &mimeType) bool LtsDragIcon::removeMimeData(const QString& mimeType)
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
return m_toolButton->removeMimeData(mimeType); return m_toolButton->removeMimeData(mimeType);
} }
void LtsDragIcon::removeAllMimeData() void LtsDragIcon::removeAllMimeData()
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
m_toolButton->removeAllMimeData(); m_toolButton->removeAllMimeData();
} }
void LtsDragIcon::setAcceptDrops(bool on) void LtsDragIcon::setAcceptDrops(bool on)
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
m_toolButton->setAcceptDrops(on); m_toolButton->setAcceptDrops(on);
} }
void LtsDragIcon::dragEnterEvent(QDragEnterEvent *e) void LtsDragIcon::dragEnterEvent(QDragEnterEvent* e)
{ {
if (m_toolButton) if (m_toolButton)
m_toolButton->dragEnterEvent(e); m_toolButton->dragEnterEvent(e);
} }
void LtsDragIcon::dropEvent(QDropEvent *e)
void LtsDragIcon::dropEvent(QDropEvent* e)
{ {
QWidget::dropEvent(e); QWidget::dropEvent(e);
} }
void LtsDragIcon::setButtonStyle(ButtonStyle style) void LtsDragIcon::setButtonStyle(ButtonStyle style)
{ {
m_style = style; m_style = style;
setStyleToButton(); setStyleToButton();
} }
void LtsDragIcon::setIconSize(ButtonSize buttonSize) void LtsDragIcon::setIconSize(ButtonSize buttonSize)
{ {
m_buttonSize = buttonSize; m_buttonSize = buttonSize;
(m_toolButton) ? m_toolButton->setIconSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize))) : initButton(); (m_toolButton) ? m_toolButton->setIconSize(QSize(static_cast<int>(m_buttonSize), static_cast<int>(m_buttonSize)))
: initButton();
} }
void LtsDragIcon::setForceFixedSize(bool force) void LtsDragIcon::setForceFixedSize(bool force)
{ {
m_forceFixedSize = force; m_forceFixedSize = force;
initButton(); initButton();
} }
void LtsDragIcon::setButtonVisible(bool visible) void LtsDragIcon::setButtonVisible(bool visible)
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
initButton(); initButton();
m_toolButton->setVisible(visible); m_toolButton->setVisible(visible);
} }
bool LtsDragIcon::buttonVisible() const bool LtsDragIcon::buttonVisible() const
{ {
if (nullptr == m_toolButton) if (nullptr == m_toolButton)
return false; return false;
return m_toolButton->isVisible(); return m_toolButton->isVisible();
} }
void LtsDragIcon::setAction(QAction *action) void LtsDragIcon::setAction(QAction* action)
{ {
QIcon icon = action->icon(); QIcon icon = action->icon();
if(!icon.isNull()) if (!icon.isNull())
m_icon = icon; m_icon = icon;
m_toolButton->setDefaultAction(action); m_toolButton->setDefaultAction(action);
this->setObjectName(action->objectName()); this->setObjectName(action->objectName());
} }
void LtsDragIcon::changeEvent(QEvent *event) void LtsDragIcon::changeEvent(QEvent* event)
{ {
if (event->type() == QEvent::EnabledChange) if (event->type() == QEvent::EnabledChange)
emit enabledChanged(isEnabled()); emit enabledChanged(isEnabled());
} }
void LtsToolButton::mousePressEvent(QMouseEvent* event)
void LtsToolButton::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) if (event->button() == Qt::LeftButton)
m_startPos = event->pos(); m_startPos = event->pos();
QToolButton::mousePressEvent(event); QToolButton::mousePressEvent(event);
} }
void LtsToolButton::mouseReleaseEvent(QMouseEvent* event)
void LtsToolButton::mouseReleaseEvent(QMouseEvent *event)
{ {
QToolButton::mouseReleaseEvent(event); QToolButton::mouseReleaseEvent(event);
} }
void LtsToolButton::mouseMoveEvent(QMouseEvent *event) void LtsToolButton::mouseMoveEvent(QMouseEvent* event)
{ {
if (!m_isDraggable) if (!m_isDraggable)
return; return;
if (event->buttons() & Qt::LeftButton) { if (event->buttons() & Qt::LeftButton)
int distance = (event->pos() - m_startPos).manhattanLength();
if (distance >= 5)
{ {
this->setDown(false); int distance = (event->pos() - m_startPos).manhattanLength();
performDrag(event); if (distance >= 5)
return; {
this->setDown(false);
performDrag(event);
return;
}
} }
} QToolButton::mouseMoveEvent(event);
QToolButton::mouseMoveEvent(event);
} }
void LtsToolButton::performDrag(QMouseEvent *) void LtsToolButton::performDrag(QMouseEvent*)
{ {
QWidget *item = this; QWidget* item = this;
if (item) if (item)
{
LtsDragIcon *dragIcon = nullptr;
QString name;
while (dragIcon == nullptr)
{ {
if ((!item->objectName().isEmpty()) && (name.isNull()))
{ LtsDragIcon* dragIcon = nullptr;
name = item->objectName(); QString name;
}
item = item->parentWidget(); while (dragIcon == nullptr)
if (nullptr == item) return; {
dragIcon = dynamic_cast<LtsDragIcon*>(item); if ((!item->objectName().isEmpty()) && (name.isNull()))
{
name = item->objectName();
}
item = item->parentWidget();
if (nullptr == item)
return;
dragIcon = dynamic_cast<LtsDragIcon*>(item);
}
QMimeData* mimeData = new QMimeData();
mimeData->setText(name);
for (auto it = m_mimeData.cbegin(); it != m_mimeData.cend(); ++it)
mimeData->setData(it.key(), it.value());
if (dragIcon->dropHandlerKey() != 0L)
{
QByteArray data = QByteArray(QByteArray::number(dragIcon->dropHandlerKey()));
mimeData->setData(QLatin1String("DropHandlerPtr"), data);
}
QDrag* drag = new QDrag(item);
drag->setMimeData(mimeData);
QAction* action = defaultAction();
if ((action) && (dragIcon->showDragIcon()))
{
drag->setPixmap(action->icon().pixmap(16, 16));
}
else
{
drag->setPixmap(dragIcon->icon().pixmap(16, 16));
}
Qt::DropAction drop = drag->exec(Qt::CopyAction | Qt::MoveAction);
if (drop == Qt::MoveAction || drop == Qt::CopyAction)
emit dropSuc();
} }
QMimeData *mimeData = new QMimeData();
mimeData->setText(name);
for(auto it = m_mimeData.cbegin(); it != m_mimeData.cend(); ++it)
mimeData->setData(it.key(), it.value());
if (dragIcon->dropHandlerKey() != 0L)
{
QByteArray data = QByteArray(QByteArray::number(dragIcon->dropHandlerKey()));
mimeData->setData(QLatin1String("DropHandlerPtr"),data);
}
QDrag *drag = new QDrag(item);
drag->setMimeData(mimeData);
QAction *action = defaultAction();
if ((action) && (dragIcon->showDragIcon()))
{
drag->setPixmap(action->icon().pixmap(16,16) );
}
else
{
drag->setPixmap(dragIcon->icon().pixmap(16, 16));
}
Qt::DropAction drop = drag->exec(Qt::CopyAction | Qt::MoveAction);
if (drop == Qt::MoveAction || drop == Qt::CopyAction )
emit dropSuc();
}
} }
void LtsToolButton::dragEnterEvent(QDragEnterEvent *event) void LtsToolButton::dragEnterEvent(QDragEnterEvent* event)
{ {
QWidget *source = QWidget* source = qobject_cast<QWidget*>(event->source());
qobject_cast<QWidget *>(event->source()); if (source && source != this)
if (source && source != this) { {
event->setDropAction(Qt::MoveAction); event->setDropAction(Qt::MoveAction);
event->accept(); event->accept();
} }
QWidget::dragEnterEvent(event); QWidget::dragEnterEvent(event);
} }
void LtsToolButton::addMimeData(const QString &mimeType, const QByteArray &data) void LtsToolButton::addMimeData(const QString& mimeType, const QByteArray& data)
{ {
m_mimeData.insert(mimeType,data); m_mimeData.insert(mimeType, data);
} }
bool LtsToolButton::removeMimeData(const QString &mimeType) bool LtsToolButton::removeMimeData(const QString& mimeType)
{ {
return (m_mimeData.remove(mimeType) > 0); return (m_mimeData.remove(mimeType) > 0);
} }
#define SIZE 40 #define SIZE 40
QIcon LtsDragIcon::modifyIcon(const QIcon &icon) QIcon LtsDragIcon::modifyIcon(const QIcon& icon)
{ {
if (m_modification.isEmpty()) if (m_modification.isEmpty())
return icon; return icon;
QPixmap iconImage(icon.pixmap(SIZE*0.8, SIZE*0.8)); QPixmap iconImage(icon.pixmap(SIZE * 0.8, SIZE * 0.8));
QPainter painter(&iconImage); QPainter painter(&iconImage);
painter.save(); painter.save();
painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::HighQualityAntialiasing | QPainter::SmoothPixmapTransform); painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.setBrush(QColor("red")); painter.setBrush(QColor("red"));
painter.setPen(QPen(QColor("red"), 3)); painter.setPen(QPen(QColor("red"), 3));
QFont f; QFont f;
f.setFamily(QStringLiteral("Monospace")); f.setFamily(QStringLiteral("Monospace"));
f.setPointSize(12); f.setPointSize(12);
f.setBold(true); f.setBold(true);
painter.setFont(f); painter.setFont(f);
painter.drawText(QRect(0, 0, 28, 28), m_modification); painter.drawText(QRect(0, 0, 28, 28), m_modification);
painter.restore(); painter.restore();
return iconImage;
}
return iconImage;
} }
} // namespace LtsWidgets
#include "lts_drag_icon.moc" #include "lts_drag_icon.moc"
+75 -102
View File
@@ -1,153 +1,126 @@
#include "lts_frameless_dialog.h" #include "lts_frameless_dialog.h"
#include <QApplication> #include <QApplication>
#include <QRect> #include <QRect>
#include <QStyle>
#include <QSize>
#include <QScreen> #include <QScreen>
#include <QScroller>
#include <QScrollArea> #include <QScrollArea>
#include <QDesktopWidget> #include <QScroller>
#include <QShowEvent> #include <QShowEvent>
#include <QSize>
#include <QStyle>
#include <QTimer> #include <QTimer>
namespace LtsWidgets namespace LtsWidgets
{ {
LtsFramelessDialog::LtsFramelessDialog(QWidget *parent, const Behaviour &behaviour) LtsFramelessDialog::LtsFramelessDialog(QWidget* parent, const Behaviour& behaviour) : QDialog(parent)
: QDialog(parent)
{ {
Qt::WindowFlags wf;
Qt::WindowFlags wf; switch (behaviour)
switch (behaviour)
{
case Behaviour::Modal:
{ {
case Behaviour::Modal: {
#ifndef TABLET_MODE #ifndef TABLET_MODE
setModal(true); setModal(true);
wf |= Qt::Dialog; wf |= Qt::Dialog;
#else #else
wf |= Qt::Window; wf |= Qt::Window;
#endif #endif
wf |= Qt::WindowStaysOnTopHint; wf |= Qt::WindowStaysOnTopHint;
break; break;
}
case Behaviour::Popup:
wf |= Qt::Popup;
break;
} }
case Behaviour::Popup: setWindowFlags(wf);
wf |= Qt::Popup;
break;
}
setWindowFlags(wf);
QTimer *t = new QTimer(this);
t->setInterval(250);
connect(t, &QTimer::timeout,
this, [this]()
{
QSize s = size();
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, screenRectFromPoint(QCursor::pos())));
});
QTimer* t = new QTimer(this);
t->setInterval(250);
connect(t, &QTimer::timeout, this, [this]() {
QSize s = size();
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, screenRectFromPoint(QCursor::pos())));
});
} }
LtsFramelessDialog::~LtsFramelessDialog() {}
LtsFramelessDialog::~LtsFramelessDialog() QRect LtsFramelessDialog::screenRectFromPoint(const QPoint& pos) const
{ {
const auto screens = QGuiApplication::screens();
for (QScreen* screen : screens)
{
QRect s = screen->geometry().adjusted(-50, -50, 50, 50);
bool contains = s.contains(pos);
if (contains)
return screen->geometry();
}
return QRect();
} }
void LtsFramelessDialog::showEvent(QShowEvent* event)
QRect LtsFramelessDialog::screenRectFromPoint(const QPoint &pos) const
{ {
const auto screens = QGuiApplication::screens(); QDialog::showEvent(event);
for (QScreen *screen : screens) QTimer::singleShot(0, this, &LtsFramelessDialog::onUpdateGeometry);
{
QRect s = screen->geometry().adjusted(-50, -50, 50, 50);
bool contains = s.contains(pos);
if (contains)
return screen->geometry();
}
return QRect();
}
void LtsFramelessDialog::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
QTimer::singleShot(0, this, &LtsFramelessDialog::onUpdateGeometry);
#ifdef TABLET_MODE #ifdef TABLET_MODE
QList<QWidget *> scrollWidgets = findChildren<QWidget *>(); QList<QWidget*> scrollWidgets = findChildren<QWidget*>();
for (auto i = scrollWidgets.begin(); i != scrollWidgets.end(); ++i) for (auto i = scrollWidgets.begin(); i != scrollWidgets.end(); ++i)
{ {
QWidget *widget = *i; QWidget* widget = *i;
QVariant isConst = widget->property("const"); QVariant isConst = widget->property("const");
if (isConst.isValid() && isConst.toBool()) if (isConst.isValid() && isConst.toBool())
continue; continue;
addTouchScroll(widget); addTouchScroll(widget);
} }
#endif #endif
} }
void LtsFramelessDialog::addTouchScroll(QWidget* widget)
void LtsFramelessDialog::addTouchScroll(QWidget *widget)
{ {
if (!widget) if (!widget)
return; return;
widget->setAttribute(Qt::WA_AcceptTouchEvents); widget->setAttribute(Qt::WA_AcceptTouchEvents);
QScrollArea *sca = qobject_cast<QScrollArea *>(widget); QScrollArea* sca = qobject_cast<QScrollArea*>(widget);
if (sca) if (sca)
{ {
QScroller::grabGesture(sca->viewport(), QScroller::LeftMouseButtonGesture); QScroller::grabGesture(sca->viewport(), QScroller::LeftMouseButtonGesture);
return; return;
} }
} }
void LtsFramelessDialog::onUpdateGeometry() void LtsFramelessDialog::onUpdateGeometry()
{ {
QRect r; QRect r;
QWidget *p = parentWidget(); QWidget* p = parentWidget();
if (p) if (p)
{ {
QWidget *window = p->window(); QWidget* window = p->window();
QPoint global = window->mapToGlobal(QPoint(0,0)); QPoint global = window->mapToGlobal(QPoint(0, 0));
QSize size = window->size(); QSize size = window->size();
r = QRect(global, size); r = QRect(global, size);
} }
else else
{ {
r = QGuiApplication::primaryScreen()->geometry(); r = QGuiApplication::primaryScreen()->geometry();
} }
QSize s = size(); QSize s = size();
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, r)); setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, r));
} }
} } // namespace LtsWidgets
+78 -85
View File
@@ -1,129 +1,122 @@
#include "lts_grid_layout.h" #include "lts_grid_layout.h"
#include <utility>
#include <QResizeEvent> #include <QResizeEvent>
#include <utility>
namespace LtsWidgets namespace LtsWidgets
{ {
LtsGridLayout::LtsGridLayout(LtsWidgets::ButtonSize buttonSize, QWidget *parent, int maxColumn) LtsGridLayout::LtsGridLayout(LtsWidgets::ButtonSize buttonSize, QWidget* parent, int maxColumn)
: QGridLayout(parent) : QGridLayout(parent), m_buttonSize(buttonSize), m_defaultMaxColumn(maxColumn), m_maxColumn(maxColumn),
, m_buttonSize(buttonSize) m_colSize(0), m_autoSize(maxColumn < 0)
, m_defaultMaxColumn(maxColumn)
, m_maxColumn(maxColumn)
, m_colSize(0)
, m_autoSize(maxColumn < 0)
{ {
setSizeConstraint(SizeConstraint::SetNoConstraint); setSizeConstraint(SizeConstraint::SetNoConstraint);
setVerticalSpacing(1); setVerticalSpacing(1);
setMargin(0); setContentsMargins(0, 0, 0, 0);
} }
void LtsGridLayout::add_widget(QWidget *widget) void LtsGridLayout::add_widget(QWidget* widget)
{ {
for (auto it = m_widgetList.cbegin(); it != m_widgetList.cend(); ++it) for (auto it = m_widgetList.cbegin(); it != m_widgetList.cend(); ++it)
{ {
if (*it == widget) if (*it == widget)
return; return;
} }
connect(widget, &QWidget::destroyed, this, &LtsGridLayout::onWidgetDestroyed); connect(widget, &QWidget::destroyed, this, &LtsGridLayout::onWidgetDestroyed);
addWidgetInternal(widget); addWidgetInternal(widget);
m_widgetList.push_back(widget); m_widgetList.push_back(widget);
} }
void LtsGridLayout::setAutoSize(bool enable) void LtsGridLayout::setAutoSize(bool enable)
{ {
m_autoSize = enable; m_autoSize = enable;
if (m_autoSize == false) if (m_autoSize == false)
setMaxColumn(1); setMaxColumn(1);
else else
{ {
m_maxColumn = -1; m_maxColumn = -1;
m_oldSize = QSize(); m_oldSize = QSize();
m_oldGeo = QRect(); m_oldGeo = QRect();
QResizeEvent e(sizeHint(), sizeHint()); QResizeEvent e(sizeHint(), sizeHint());
onParentResize(&e); onParentResize(&e);
setGeometry(QRect(0, 0, sizeHint().width(), sizeHint().height())); setGeometry(QRect(0, 0, sizeHint().width(), sizeHint().height()));
} }
} }
void LtsGridLayout::setMaxColumn(int max) void LtsGridLayout::setMaxColumn(int max)
{ {
m_maxColumn = max; m_maxColumn = max;
m_defaultMaxColumn = max; m_defaultMaxColumn = max;
m_colSize = 0;
m_colSize = 0; for (QWidget* wid : std::as_const(m_widgetList))
removeWidget(wid);
for (QWidget *wid : std::as_const(m_widgetList))
removeWidget(wid);
for (QWidget *wid : std::as_const(m_widgetList))
addWidgetInternal(wid);
for (QWidget* wid : std::as_const(m_widgetList))
addWidgetInternal(wid);
} }
void LtsGridLayout::addWidgetInternal(QWidget *widget) void LtsGridLayout::addWidgetInternal(QWidget* widget)
{ {
int current_row = 0; int current_row = 0;
int current_column = 0; int current_column = 0;
while (QLayoutItem *item = itemAtPosition(current_row, current_column)) while (QLayoutItem* item = itemAtPosition(current_row, current_column))
{
if (!item->widget())
{ {
removeItem(item); if (!item->widget())
continue; {
removeItem(item);
continue;
}
if (current_column == (m_maxColumn - 1))
{
current_column = 0;
++current_row;
}
else
++current_column;
} }
if (current_column == (m_maxColumn - 1)) if (current_row == 0)
{ m_colSize += 1;
current_column = 0;
++current_row;
}
else
++current_column;
}
if (current_row == 0) QGridLayout::addWidget(widget, current_row, current_column);
m_colSize += 1;
QGridLayout::addWidget(widget, current_row, current_column);
} }
void LtsGridLayout::onParentResize(QResizeEvent* e)
void LtsGridLayout::onParentResize(QResizeEvent *e)
{ {
if (m_autoSize && m_oldSize != e->size()) if (m_autoSize && m_oldSize != e->size())
{ {
bool bigger = (e->size().width() > m_oldSize.width()); bool bigger = (e->size().width() > m_oldSize.width());
m_oldSize = e->size(); m_oldSize = e->size();
int newWidth = m_oldSize.width(); int newWidth = m_oldSize.width();
int maxIconsInRow = newWidth / (static_cast<int>(m_buttonSize) + 4); int maxIconsInRow = newWidth / (static_cast<int>(m_buttonSize) + 4);
if (!bigger && newWidth <= (static_cast<int>(m_buttonSize)*m_colSize - static_cast<int>(m_buttonSize) / 2)) if (!bigger && newWidth <= (static_cast<int>(m_buttonSize) * m_colSize - static_cast<int>(m_buttonSize) / 2))
maxIconsInRow--; maxIconsInRow--;
if (m_maxColumn != maxIconsInRow) if (m_maxColumn != maxIconsInRow)
setMaxColumn(maxIconsInRow); setMaxColumn(maxIconsInRow);
} }
} }
void LtsGridLayout::onWidgetDestroyed() void LtsGridLayout::onWidgetDestroyed()
{ {
QWidget *s = qobject_cast<QWidget*>(sender()); QWidget* s = qobject_cast<QWidget*>(sender());
for (auto it = m_widgetList.begin(); it != m_widgetList.end(); ++it) for (auto it = m_widgetList.begin(); it != m_widgetList.end(); ++it)
{
if (*it == s)
{ {
QGridLayout::removeWidget(s); if (*it == s)
m_widgetList.erase(it); {
setMaxColumn(m_maxColumn); QGridLayout::removeWidget(s);
break; m_widgetList.erase(it);
setMaxColumn(m_maxColumn);
break;
}
} }
}
} }
} } // namespace LtsWidgets
File diff suppressed because it is too large. Load diff
+62 -77
View File
@@ -1,116 +1,101 @@
#include "lts_image_editor.h" #include "lts_image_editor.h"
#include <QPainter>
#include <QPaintEvent>
#include <QBrush> #include <QBrush>
#include <QEvent>
#include <QPaintEvent>
#include <QPainter>
#include <QPen> #include <QPen>
#include <QRect> #include <QRect>
#include <QEvent>
using namespace LtsWidgets; using namespace LtsWidgets;
LtsImageEditor::LtsImageEditor(QWidget* parent)
LtsImageEditor::LtsImageEditor(QWidget *parent) : QWidget(parent), m_isHovered(false), m_menuEnabled(true), m_bDrawOuterRect(true)
: QWidget(parent)
, m_isHovered(false)
, m_menuEnabled(true)
, m_bDrawOuterRect(true)
{}
void LtsImageEditor::setPixmap(const QPixmap &pixmap)
{ {
if (pixmap.isNull())
m_pixmap = QPixmap(QStringLiteral(":style/noimage.png"));
else
m_pixmap = pixmap;
update();
emit imageChanged();
} }
void LtsImageEditor::setPixmap(const QPixmap& pixmap)
void LtsImageEditor::enterEvent(QEvent *)
{ {
if (pixmap.isNull())
m_pixmap = QPixmap(QStringLiteral(":style/noimage.png"));
else
m_pixmap = pixmap;
m_isHovered = true; update();
update(); emit imageChanged();
} }
void LtsImageEditor::enterEvent(QEnterEvent*)
void LtsImageEditor::leaveEvent(QEvent *)
{ {
m_isHovered = false; m_isHovered = true;
update(); update();
} }
void LtsImageEditor::leaveEvent(QEvent*)
bool LtsImageEditor::event(QEvent *event)
{ {
if (event->type() == QEvent::MouseButtonPress && m_menuEnabled)
{
emit signalClicked();
event->accept();
m_isHovered = false; m_isHovered = false;
update(); update();
return true;
}
return QWidget::event(event);
} }
bool LtsImageEditor::event(QEvent* event)
{
if (event->type() == QEvent::MouseButtonPress && m_menuEnabled)
{
emit signalClicked();
event->accept();
m_isHovered = false;
update();
return true;
}
return QWidget::event(event);
}
void LtsImageEditor::paintEvent(QPaintEvent* event) void LtsImageEditor::paintEvent(QPaintEvent* event)
{ {
QPainter p(this); QPainter p(this);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
QBrush brush = QColor(QStringLiteral("white"));
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); if (!m_pixmap.isNull())
QBrush brush = QColor(QStringLiteral("white"));
if (!m_pixmap.isNull())
{
if (!(m_isHovered && m_menuEnabled))
{ {
const QSize s(size()); if (!(m_isHovered && m_menuEnabled))
const QPixmap pixmap(m_pixmap.scaled(s, Qt::KeepAspectRatio, Qt::SmoothTransformation)); {
const int x = qRound((s.width() - pixmap.width()) / 2.); const QSize s(size());
const int y = qRound((s.height() - pixmap.height()) / 2.); const QPixmap pixmap(m_pixmap.scaled(s, Qt::KeepAspectRatio, Qt::SmoothTransformation));
if (m_bDrawOuterRect) const int x = qRound((s.width() - pixmap.width()) / 2.);
{ const int y = qRound((s.height() - pixmap.height()) / 2.);
p.setPen(QPen(QColor("gray"), 2)); if (m_bDrawOuterRect)
p.drawRect(rect()); {
} p.setPen(QPen(QColor("gray"), 2));
p.drawPixmap(x, y, pixmap); p.drawRect(rect());
event->accept(); }
return; p.drawPixmap(x, y, pixmap);
event->accept();
return;
}
} }
}
p.setPen(QPen(QColor("gray"), 2));
p.setBrush(brush);
p.drawRect(rect());
if (m_isHovered && m_menuEnabled)
{
p.setPen(QPen(QColor(QStringLiteral("gray")), (size().height() / 48 * 2)));
p.setPen(QPen(QColor("gray"), 2)); double xc = size().width() / 2.012;
p.setBrush(brush); double yc = size().height() / 2.012;
p.drawRect(rect());
p.drawLine(QPointF(xc - (xc / 2.01f), yc - (yc / 3.01f)), QPointF(xc + (xc / 2.02f), yc - (yc / 3.02f)));
p.drawLine(QPointF(xc - (xc / 2.01f), yc - 0.01f), QPointF(xc + (xc / 2.02f), yc - 0));
p.drawLine(QPointF(xc - (xc / 2.01f), yc + (yc / 3.01f)), QPointF(xc + (xc / 2.02f), yc + (yc / 3.02f)));
}
event->accept();
if (m_isHovered && m_menuEnabled)
{
p.setPen(QPen(QColor(QStringLiteral("gray")), (size().height() / 48 * 2)));
double xc = size().width()/2.012;
double yc = size().height()/2.012;
p.drawLine(QPointF(xc - (xc/2.01f), yc - (yc/3.01f)), QPointF(xc + (xc/2.02f), yc - (yc/3.02f)));
p.drawLine(QPointF(xc - (xc/2.01f), yc - 0.01f), QPointF(xc + (xc/2.02f), yc - 0));
p.drawLine(QPointF(xc - (xc/2.01f), yc + (yc/3.01f)), QPointF(xc + (xc/2.02f), yc + (yc/3.02f)));
}
event->accept();
} }
+41 -34
View File
@@ -1,61 +1,68 @@
#pragma once #pragma once
#include <QObject>
#include "ltswidgets_export.h" #include "ltswidgets_export.h"
#include <QObject>
#include <QWidget> #include <QWidget>
namespace LtsWidgets namespace LtsWidgets
{ {
class LTSWIDGETS_EXPORT LtsImageEditor : public QWidget class LTSWIDGETS_EXPORT LtsImageEditor : public QWidget
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap) Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)
Q_PROPERTY(bool menuEnabled READ isMenuEnabled WRITE setMenuEnabled) Q_PROPERTY(bool menuEnabled READ isMenuEnabled WRITE setMenuEnabled)
public: public:
explicit LtsImageEditor(QWidget *parent = nullptr); explicit LtsImageEditor(QWidget* parent = nullptr);
void setPixmap(const QPixmap& pixmap);
QPixmap pixmap() const
{
return m_pixmap;
}
void setPixmap(const QPixmap &pixmap); void setMenuEnabled(bool enabled = true)
{
m_menuEnabled = enabled;
}
bool isMenuEnabled() const
{
return m_menuEnabled;
}
void setDrawOuterRect(bool bDraw)
{
m_bDrawOuterRect = bDraw;
}
QPixmap pixmap() const { return m_pixmap; } bool drawOuterRect() const
{
return m_bDrawOuterRect;
}
protected:
void paintEvent(QPaintEvent* event);
void enterEvent(QEnterEvent*);
void leaveEvent(QEvent*);
bool event(QEvent* event);
private:
QPixmap m_pixmap;
bool m_isHovered;
bool m_menuEnabled;
bool m_bDrawOuterRect;
void setMenuEnabled(bool enabled = true) { m_menuEnabled = enabled; } signals:
bool isMenuEnabled() const { return m_menuEnabled; }
void setDrawOuterRect(bool bDraw) { m_bDrawOuterRect = bDraw; } void signalClicked();
bool drawOuterRect() const { return m_bDrawOuterRect; }
protected: void imageChanged();
void paintEvent(QPaintEvent *event);
void enterEvent(QEvent *);
void leaveEvent(QEvent *);
bool event(QEvent *event);
private:
QPixmap m_pixmap;
bool m_isHovered;
bool m_menuEnabled;
bool m_bDrawOuterRect;
signals:
void signalClicked();
void imageChanged();
}; };
} } // namespace LtsWidgets
+79 -86
View File
@@ -1,133 +1,126 @@
#include "lts_message_dialog.h" #include "lts_message_dialog.h"
#include "lts_message_dialog_helper.h" #include "lts_message_dialog_helper.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QVBoxLayout> #include <QDebug>
#include <QLabel> #include <QLabel>
#include <QPushButton> #include <QPushButton>
#include <QDebug> #include <QVBoxLayout>
namespace LtsWidgets namespace LtsWidgets
{ {
namespace LtsMessageDialog namespace LtsMessageDialog
{ {
Button showMessage(QWidget* parent, Button showMessage(QWidget* parent, const QString& message, const QString& title, const Behaviour behaviour,
const QString& message, const Buttons buttons, const QHash<Button, QString>& buttonTexts)
const QString &title,
const Behaviour behaviour,
const Buttons buttons,
const QHash<Button, QString> &buttonTexts)
{ {
static QAtomicInt s_used = 0; static QAtomicInt s_used = 0;
if (s_used) if (s_used)
qDebug() << "LtsMessageDialog: showMessage called while showMessage is in its Event Loop - do not open more than one Dialog at once !!"; qDebug() << "LtsMessageDialog: showMessage called while showMessage is in its Event Loop - do not open more "
"than one Dialog at once !!";
s_used = 1; s_used = 1;
LtsMessageDialogHelper *dialog = new LtsMessageDialogHelper(); LtsMessageDialogHelper* dialog = new LtsMessageDialogHelper();
Button result = dialog->showMessage(parent, message, title, behaviour, buttons, buttonTexts); Button result = dialog->showMessage(parent, message, title, behaviour, buttons, buttonTexts);
dialog->deleteLater(); dialog->deleteLater();
s_used = 0; s_used = 0;
return result; return result;
} }
Button askApplyDiscardCancel(QWidget *parent) Button askApplyDiscardCancel(QWidget* parent)
{ {
const QString question = QCoreApplication::translate("LtsDialog", const QString question = QCoreApplication::translate("LtsDialog", "<br>"
"<br>" "Apply - apply changes and close.<br>"
"Apply - apply changes and close.<br>" "Discard - discard changes and close.<br>"
"Discard - discard changes and close.<br>" "Cancel - do not close.");
"Cancel - do not close."); const QString title = QCoreApplication::translate("LtsDialog", "Unapplied changes made. Apply the changes?");
const QString title = QCoreApplication::translate("LtsDialog", "Unapplied changes made. Apply the changes?"); return LtsMessageDialog::showMessage(parent, question, title, Behaviour::Modal,
return LtsMessageDialog::showMessage(parent, Button::Apply | Button::Discard | Button::Cancel);
question,
title,
Behaviour::Modal,
Button::Apply | Button::Discard | Button::Cancel);
} }
} // namespace LtsMessageDialog
} LtsMessageDialogNew::LtsMessageDialogNew(QWidget* parent, const QString& message, const QString& title,
const Behaviour behaviour, const Buttons buttons,
const QHash<Button, QString>& buttonTexts, bool deleteOnClose)
LtsMessageDialogNew::LtsMessageDialogNew(QWidget *parent, const QString &message, const QString &title, const Behaviour behaviour, const Buttons buttons, const QHash<Button, QString> &buttonTexts, bool deleteOnClose)
{ {
m_dialog = new LtsFramelessDialog(parent, behaviour); m_dialog = new LtsFramelessDialog(parent, behaviour);
if (deleteOnClose) if (deleteOnClose)
m_dialog->setAttribute(Qt::WA_DeleteOnClose); m_dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(m_dialog, &LtsFramelessDialog::destroyed, connect(m_dialog, &LtsFramelessDialog::destroyed, this, &LtsMessageDialogNew::deleteLater);
this, &LtsMessageDialogNew::deleteLater);
QVBoxLayout *mainLayout = new QVBoxLayout(m_dialog); QVBoxLayout* mainLayout = new QVBoxLayout(m_dialog);
QString text; QString text;
if (!title.isEmpty()) if (!title.isEmpty())
{ {
text = QStringLiteral("<b>%1</b><br><br>").arg(title); text = QStringLiteral("<b>%1</b><br><br>").arg(title);
} }
text += message; text += message;
QLabel *messageLabel = new QLabel(text, m_dialog); QLabel* messageLabel = new QLabel(text, m_dialog);
messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
mainLayout->addWidget(messageLabel); mainLayout->addWidget(messageLabel);
QHBoxLayout *buttonLayout = new QHBoxLayout; QHBoxLayout* buttonLayout = new QHBoxLayout;
buttonLayout->setMargin(0); buttonLayout->setContentsMargins(0, 0, 0, 0);
if (buttons.testFlag(Button::Ok))
connect(addButton(buttonTexts.value(Button::Ok, tr("Ok")), buttonLayout, m_dialog, Button::Ok, parent),
&QPushButton::clicked, this, &LtsMessageDialogNew::ok);
if (buttons.testFlag(Button::Yes))
connect(addButton(buttonTexts.value(Button::Yes, tr("Yes")), buttonLayout, m_dialog, Button::Yes, parent),
&QPushButton::clicked, this, &LtsMessageDialogNew::yes);
if (buttons.testFlag(Button::No))
connect(addButton(buttonTexts.value(Button::No, tr("No")), buttonLayout, m_dialog, Button::No, parent),
&QPushButton::clicked, this, &LtsMessageDialogNew::no);
if (buttons.testFlag(Button::Ok)) if (buttons.testFlag(Button::Apply))
connect(addButton(buttonTexts.value(Button::Ok, tr("Ok")), buttonLayout, m_dialog, Button::Ok, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::ok); connect(addButton(buttonTexts.value(Button::Apply, tr("Apply")), buttonLayout, m_dialog, Button::Apply, parent),
&QPushButton::clicked, this, &LtsMessageDialogNew::apply);
if (buttons.testFlag(Button::Yes)) if (buttons.testFlag(Button::Discard))
connect(addButton(buttonTexts.value(Button::Yes, tr("Yes")), buttonLayout, m_dialog, Button::Yes, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::yes); connect(addButton(buttonTexts.value(Button::Discard, tr("Discard")), buttonLayout, m_dialog, Button::Discard,
parent),
&QPushButton::clicked, this, &LtsMessageDialogNew::discard);
if (buttons.testFlag(Button::No)) if (buttons.testFlag(Button::Cancel))
connect(addButton(buttonTexts.value(Button::No, tr("No")), buttonLayout, m_dialog, Button::No, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::no); connect(
addButton(buttonTexts.value(Button::Cancel, tr("Cancel")), buttonLayout, m_dialog, Button::Cancel, parent),
&QPushButton::clicked, this, &LtsMessageDialogNew::cancel);
if (buttons.testFlag(Button::Apply)) QWidget* buttonLayoutWidget = new QWidget;
connect(addButton(buttonTexts.value(Button::Apply, tr("Apply")), buttonLayout, m_dialog, Button::Apply, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::apply); buttonLayoutWidget->setLayout(buttonLayout);
if (buttons.testFlag(Button::Discard)) mainLayout->addWidget(buttonLayoutWidget);
connect(addButton(buttonTexts.value(Button::Discard, tr("Discard")), buttonLayout, m_dialog, Button::Discard, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::discard);
if (buttons.testFlag(Button::Cancel)) m_dialog->show();
connect(addButton(buttonTexts.value(Button::Cancel, tr("Cancel")), buttonLayout, m_dialog, Button::Cancel, parent), &QPushButton::clicked, this, &LtsMessageDialogNew::cancel); m_dialog->raise();
QWidget *buttonLayoutWidget = new QWidget;
buttonLayoutWidget->setLayout(buttonLayout);
mainLayout->addWidget(buttonLayoutWidget);
m_dialog->show();
m_dialog->raise();
} }
QPushButton* LtsMessageDialogNew::addButton(const QString& text, QHBoxLayout* thatLayout, LtsFramelessDialog* dialog,
QPushButton* LtsMessageDialogNew::addButton(const QString &text, QHBoxLayout *thatLayout, LtsFramelessDialog *dialog, const Button &button, QWidget *parent) const Button& button, QWidget* parent)
{ {
QPushButton* btn = new QPushButton(text, parent); QPushButton* btn = new QPushButton(text, parent);
connect(btn, &QPushButton::clicked, dialog, &LtsFramelessDialog::accept); connect(btn, &QPushButton::clicked, dialog, &LtsFramelessDialog::accept);
thatLayout->addWidget(btn); thatLayout->addWidget(btn);
if (button == Button::Ok || if (button == Button::Ok || button == Button::Cancel)
button == Button::Cancel) {
{ btn->setDefault(true);
btn->setDefault(true); }
}
return btn; return btn;
} }
} // namespace LtsWidgets
}
+101 -114
View File
@@ -1,155 +1,142 @@
#include "lts_message_dialog_helper.h" #include "lts_message_dialog_helper.h"
#include <QPushButton> #include <QEventLoop>
#include <QVBoxLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QEventLoop> #include <QPushButton>
#include <QVBoxLayout>
namespace LtsWidgets namespace LtsWidgets
{ {
LtsMessageDialogHelper::LtsMessageDialogHelper(QObject *parent) LtsMessageDialogHelper::LtsMessageDialogHelper(QObject* parent)
: QObject(parent) : QObject(parent), m_result(Button::Cancel), m_dialog(nullptr)
, m_result(Button::Cancel)
, m_dialog(nullptr)
{}
Button LtsMessageDialogHelper::showMessage(QWidget *parent,
const QString &message,
const QString &title,
Behaviour behaviour,
Buttons buttons,
const QHash<Button, QString> &buttonTexts)
{ {
m_dialog = new LtsFramelessDialog(parent, behaviour);
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout *mainLayout = new QVBoxLayout(m_dialog);
QString text;
if (!title.isEmpty())
{
text = QStringLiteral("<b>%1</b><br><br>").arg(title);
}
text += message;
QLabel *messageLabel = new QLabel(text, m_dialog);
messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
mainLayout->addWidget(messageLabel);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->setMargin(0);
connect(m_dialog, &LtsFramelessDialog::rejected, this, &LtsMessageDialogHelper::slotCancel);
if (buttons.testFlag(Button::Ok))
connect(addButton(buttonTexts.value(Button::Ok, tr("Ok")), buttonLayout, m_dialog, Button::Ok, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotOkay);
if (buttons.testFlag(Button::Yes))
connect(addButton(buttonTexts.value(Button::Yes, tr("Yes")), buttonLayout, m_dialog, Button::Yes, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotYes);
if (buttons.testFlag(Button::No))
connect(addButton(buttonTexts.value(Button::No, tr("No")), buttonLayout, m_dialog, Button::No, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotNo);
if (buttons.testFlag(Button::Apply))
connect(addButton(buttonTexts.value(Button::Apply, tr("Apply")), buttonLayout, m_dialog, Button::Apply, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotApply);
if (buttons.testFlag(Button::Discard))
connect(addButton(buttonTexts.value(Button::Discard, tr("Discard")), buttonLayout, m_dialog, Button::Discard, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotDiscard);
if (buttons.testFlag(Button::Cancel))
connect(addButton(buttonTexts.value(Button::Cancel, tr("Cancel")), buttonLayout, m_dialog, Button::Cancel, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotCancel);
QWidget *buttonLayoutWidget = new QWidget;
buttonLayoutWidget->setLayout(buttonLayout);
mainLayout->addWidget(buttonLayoutWidget);
m_dialog->show();
m_dialog->raise();
QEventLoop loop;
connect(this, &LtsMessageDialogHelper::signalQuitEventLoop, &loop, &QEventLoop::quit, Qt::QueuedConnection);
loop.exec();
return m_result;
} }
Button LtsMessageDialogHelper::showMessage(QWidget* parent, const QString& message, const QString& title,
Behaviour behaviour, Buttons buttons,
const QHash<Button, QString>& buttonTexts)
{
m_dialog = new LtsFramelessDialog(parent, behaviour);
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout* mainLayout = new QVBoxLayout(m_dialog);
QString text;
if (!title.isEmpty())
{
text = QStringLiteral("<b>%1</b><br><br>").arg(title);
}
text += message;
QLabel* messageLabel = new QLabel(text, m_dialog);
messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
mainLayout->addWidget(messageLabel);
QHBoxLayout* buttonLayout = new QHBoxLayout;
buttonLayout->setContentsMargins(0, 0, 0, 0);
connect(m_dialog, &LtsFramelessDialog::rejected, this, &LtsMessageDialogHelper::slotCancel);
if (buttons.testFlag(Button::Ok))
connect(addButton(buttonTexts.value(Button::Ok, tr("Ok")), buttonLayout, m_dialog, Button::Ok, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotOkay);
if (buttons.testFlag(Button::Yes))
connect(addButton(buttonTexts.value(Button::Yes, tr("Yes")), buttonLayout, m_dialog, Button::Yes, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotYes);
if (buttons.testFlag(Button::No))
connect(addButton(buttonTexts.value(Button::No, tr("No")), buttonLayout, m_dialog, Button::No, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotNo);
if (buttons.testFlag(Button::Apply))
connect(addButton(buttonTexts.value(Button::Apply, tr("Apply")), buttonLayout, m_dialog, Button::Apply, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotApply);
if (buttons.testFlag(Button::Discard))
connect(addButton(buttonTexts.value(Button::Discard, tr("Discard")), buttonLayout, m_dialog, Button::Discard,
parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotDiscard);
if (buttons.testFlag(Button::Cancel))
connect(
addButton(buttonTexts.value(Button::Cancel, tr("Cancel")), buttonLayout, m_dialog, Button::Cancel, parent),
&QPushButton::clicked, this, &LtsMessageDialogHelper::slotCancel);
QWidget* buttonLayoutWidget = new QWidget;
buttonLayoutWidget->setLayout(buttonLayout);
mainLayout->addWidget(buttonLayoutWidget);
m_dialog->show();
m_dialog->raise();
QEventLoop loop;
connect(this, &LtsMessageDialogHelper::signalQuitEventLoop, &loop, &QEventLoop::quit, Qt::QueuedConnection);
loop.exec();
return m_result;
}
void LtsMessageDialogHelper::slotOkay() void LtsMessageDialogHelper::slotOkay()
{ {
m_dialog->hide(); m_dialog->hide();
m_result = Button::Ok; m_result = Button::Ok;
emit signalQuitEventLoop(); emit signalQuitEventLoop();
} }
void LtsMessageDialogHelper::slotYes() void LtsMessageDialogHelper::slotYes()
{ {
m_dialog->hide(); m_dialog->hide();
m_result = Button::Yes; m_result = Button::Yes;
emit signalQuitEventLoop(); emit signalQuitEventLoop();
} }
void LtsMessageDialogHelper::slotNo() void LtsMessageDialogHelper::slotNo()
{ {
m_dialog->hide(); m_dialog->hide();
m_result = Button::No; m_result = Button::No;
emit signalQuitEventLoop(); emit signalQuitEventLoop();
} }
void LtsMessageDialogHelper::slotApply() void LtsMessageDialogHelper::slotApply()
{ {
m_dialog->hide(); m_dialog->hide();
m_result = Button::Apply; m_result = Button::Apply;
emit signalQuitEventLoop(); emit signalQuitEventLoop();
} }
void LtsMessageDialogHelper::slotDiscard() void LtsMessageDialogHelper::slotDiscard()
{ {
m_dialog->hide(); m_dialog->hide();
m_result = Button::Discard; m_result = Button::Discard;
emit signalQuitEventLoop(); emit signalQuitEventLoop();
} }
void LtsMessageDialogHelper::slotCancel() void LtsMessageDialogHelper::slotCancel()
{ {
m_dialog->hide(); m_dialog->hide();
m_result = Button::Cancel; m_result = Button::Cancel;
emit signalQuitEventLoop(); emit signalQuitEventLoop();
} }
QPushButton* LtsMessageDialogHelper::addButton(const QString& text, QHBoxLayout* thatLayout, LtsFramelessDialog* dialog,
QPushButton* LtsMessageDialogHelper::addButton(const QString &text, QHBoxLayout *thatLayout, LtsFramelessDialog *dialog, const Button &button, QWidget *parent) const Button& button, QWidget* parent)
{ {
QPushButton* btn = new QPushButton(text, parent); QPushButton* btn = new QPushButton(text, parent);
connect(btn, &QPushButton::clicked, dialog, &LtsFramelessDialog::accept); connect(btn, &QPushButton::clicked, dialog, &LtsFramelessDialog::accept);
thatLayout->addWidget(btn); thatLayout->addWidget(btn);
if (button == Button::Ok || if (button == Button::Ok || button == Button::Cancel)
button == Button::Cancel) {
{ btn->setDefault(true);
btn->setDefault(true); }
}
return btn; return btn;
} }
} } // namespace LtsWidgets
+21 -23
View File
@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <QObject>
#include "ltswidgets_export.h" #include "ltswidgets_export.h"
#include <QObject>
#include <QRegularExpression>
#include <QSet> #include <QSet>
#include <QSpinBox> #include <QSpinBox>
@@ -15,39 +15,37 @@ class LTSWIDGETS_EXPORT LtsMultiRangeSpinBox : public QSpinBox
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LtsMultiRangeSpinBox(QWidget *parent = nullptr); explicit LtsMultiRangeSpinBox(QWidget* parent = nullptr);
~LtsMultiRangeSpinBox() = default; ~LtsMultiRangeSpinBox() = default;
public slots:
public slots: void setRanges(const QVector<QPair<int, int>>& ranges);
void setRanges(const QVector<QPair<int, int>> &ranges);
void setRange(int min, int max); void setRange(int min, int max);
void setMinimum(int min); void setMinimum(int min);
void setMaximum(int max); void setMaximum(int max);
protected: protected:
QValidator::State validate(QString &input, int &pos) const override; QValidator::State validate(QString& input, int& pos) const override;
void fixup(QString &str) const override; void fixup(QString& str) const override;
void focusOutEvent(QFocusEvent *event) override; void focusOutEvent(QFocusEvent* event) override;
void wheelEvent(QWheelEvent *event) override; void wheelEvent(QWheelEvent* event) override;
void mousePressEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent* event) override;
void keyPressEvent(QKeyEvent *event) override; void keyPressEvent(QKeyEvent* event) override;
private: private:
static QVector<QPair<int,int>> sortRanges(const QVector<QPair<int, int> > &ranges); static QVector<QPair<int, int>> sortRanges(const QVector<QPair<int, int>>& ranges);
QValidator::State validateAll(QString &input, int &pos); QValidator::State validateAll(QString& input, int& pos);
int fixupValue(int value) const; int fixupValue(int value) const;
int fixupValue(int value, bool higher) const; int fixupValue(int value, bool higher) const;
private:
private:
QVector<QPair<int, int>> m_rangesList; QVector<QPair<int, int>> m_rangesList;
int m_curVal = minimum(); int m_curVal = minimum();
QRegExp m_regex; QRegularExpression m_regex;
}; };
} // namespace LtsWidgets
}
+129 -151
View File
@@ -1,198 +1,176 @@
#include "lts_notification_box.h" #include "lts_notification_box.h"
#include "ui_lts_notification_box.h" #include "ui_lts_notification_box.h"
#include <QPainter>
#include <QLinearGradient>
#include <QColor> #include <QColor>
#include <QGraphicsDropShadowEffect> #include <QGraphicsDropShadowEffect>
#include <QStyleOption> #include <QLinearGradient>
#include <QPainter>
#include <QStyle> #include <QStyle>
#include <QStyleOption>
#ifdef NOTIBOX_DEBUG #ifdef NOTIBOX_DEBUG
#include <QDebug> #include <QDebug>
#endif #endif
namespace LtsWidgets namespace LtsWidgets
{ {
const int LtsNotificationBox::margin = 14; const int LtsNotificationBox::margin = 14;
LtsNotificationBox::LtsNotificationBox(QWidget *parent) LtsNotificationBox::LtsNotificationBox(QWidget* parent) : QWidget(parent), m_ui(new Ui::NotiBox)
: QWidget(parent)
, m_ui(new Ui::NotiBox)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->lblText->setText({}); m_ui->lblText->setText({});
connect(m_ui->lblText, &QLabel::linkActivated, connect(m_ui->lblText, &QLabel::linkActivated, this, [this](const QString& link) { emit signalLinkClicked(link); });
this, [this](const QString &link)
{
emit signalLinkClicked(link);
});
connect(m_ui->tbClose, &QToolButton::clicked, connect(m_ui->tbClose, &QToolButton::clicked, this, &LtsNotificationBox::signalClose);
this, &LtsNotificationBox::signalClose); connect(m_ui->tbAck, &QToolButton::clicked, this, &LtsNotificationBox::signalAck);
connect(m_ui->tbAck, &QToolButton::clicked,
this, &LtsNotificationBox::signalAck);
setObjectName(QStringLiteral("NotiBox")); setObjectName(QStringLiteral("NotiBox"));
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this); QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect(this);
shadow->setOffset(0, 0); shadow->setOffset(0, 0);
shadow->setBlurRadius(margin*2); shadow->setBlurRadius(margin * 2);
shadow->setColor(QColor(25, 25, 25)); shadow->setColor(QColor(25, 25, 25));
setGraphicsEffect(shadow); setGraphicsEffect(shadow);
} }
void LtsNotificationBox::message(const QString& title, const QString& text, MessageType type)
void LtsNotificationBox::message(const QString &title, const QString &text, MessageType type)
{ {
static QString rgbBaseString(QStringLiteral("%1, %2, %3")); static QString rgbBaseString(QStringLiteral("%1, %2, %3"));
static QString closeDefault(QStringLiteral("close.svg")); static QString closeDefault(QStringLiteral("close.svg"));
static QString closeDark(QStringLiteral("close_dark.svg")); static QString closeDark(QStringLiteral("close_dark.svg"));
static QString ackDefault(QStringLiteral("ack.svg")); static QString ackDefault(QStringLiteral("ack.svg"));
static QString ackDark(QStringLiteral("ack_dark.svg")); static QString ackDark(QStringLiteral("ack_dark.svg"));
static QString lightTextColor(QStringLiteral("fbfbfb")); static QString lightTextColor(QStringLiteral("fbfbfb"));
static QString darkTextColor(QStringLiteral("2c3642")); static QString darkTextColor(QStringLiteral("2c3642"));
static QColor errorStart(254, 45, 102); static QColor errorStart(254, 45, 102);
static QColor errorEnd(255, 92, 61); static QColor errorEnd(255, 92, 61);
static QColor successStart(43, 167, 70); static QColor successStart(43, 167, 70);
static QColor successEnd(130, 180, 45); static QColor successEnd(130, 180, 45);
static QColor infoStart(74, 74, 74); static QColor infoStart(74, 74, 74);
static QColor infoEnd(43, 43, 43); static QColor infoEnd(43, 43, 43);
static QColor warningStart(253, 151, 4); static QColor warningStart(253, 151, 4);
static QColor warningEnd(253, 202, 0); static QColor warningEnd(253, 202, 0);
QColor start;
QColor end;
QString close;
QString closeHover;
QString ack;
QString ackHover;
QString textColor;
QColor start; switch (type)
QColor end;
QString close;
QString closeHover;
QString ack;
QString ackHover;
QString textColor;
switch (type)
{
case MessageType::Error:
{ {
start = errorStart; case MessageType::Error: {
end = errorEnd; start = errorStart;
close = closeDefault; end = errorEnd;
closeHover = closeDark; close = closeDefault;
ack = ackDefault; closeHover = closeDark;
ackHover = ackDark; ack = ackDefault;
textColor = lightTextColor; ackHover = ackDark;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/error.svg"))); textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/error.svg")));
break; break;
}
case MessageType::Success: {
start = successStart;
end = successEnd;
close = closeDefault;
closeHover = closeDark;
ack = ackDefault;
ackHover = ackDark;
textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/success.svg")));
break;
}
case MessageType::Info: {
start = infoStart;
end = infoEnd;
close = closeDefault;
closeHover = closeDark;
ack = ackDefault;
ackHover = ackDark;
textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/info.svg")));
break;
}
case MessageType::Warning: {
start = warningStart;
end = warningEnd;
close = closeDark;
closeHover = closeDefault;
ack = ackDark;
ackHover = ackDefault;
textColor = darkTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/warning.svg")));
break;
}
} }
case MessageType::Success: QStringList css;
{
start = successStart;
end = successEnd;
close = closeDefault;
closeHover = closeDark;
ack = ackDefault;
ackHover = ackDark;
textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/success.svg")));
break; css << QStringLiteral("#NotiBox { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop: 0 rgb(%1), stop: 1 "
} "rgb(%2)); border: 1px solid rgb(%3); border-radius: 8px; margin: %4px }")
.arg(rgbBaseString.arg(start.red()).arg(start.green()).arg(start.blue()),
rgbBaseString.arg(end.red()).arg(end.green()).arg(end.blue()),
rgbBaseString.arg(end.red()).arg(end.green()).arg(end.blue()))
.arg(margin);
case MessageType::Info: css << QStringLiteral("QToolButton#tbClose { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; "
{ "background-color: transparent; }")
start = infoStart; .arg(close);
end = infoEnd; css << QStringLiteral("QToolButton#tbClose:hover { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: "
close = closeDefault; "0px; background-color: transparent; }")
closeHover = closeDark; .arg(closeHover);
ack = ackDefault;
ackHover = ackDark;
textColor = lightTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/info.svg")));
break; css << QStringLiteral("QToolButton#tbAck { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; "
} "background-color: transparent; }")
.arg(ack);
case MessageType::Warning: css << QStringLiteral("QToolButton#tbAck:hover { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: "
{ "0px; background-color: transparent; }")
start = warningStart; .arg(ackHover);
end = warningEnd;
close = closeDark;
closeHover = closeDefault;
ack = ackDark;
ackHover = ackDefault;
textColor = darkTextColor;
m_ui->lblImage->setPixmap(QPixmap(QStringLiteral(":/warning.svg")));
break;
}
}
QStringList css;
css << QStringLiteral("#NotiBox { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop: 0 rgb(%1), stop: 1 rgb(%2)); border: 1px solid rgb(%3); border-radius: 8px; margin: %4px }").
arg(rgbBaseString.arg(start.red()).arg(start.green()).arg(start.blue()),
rgbBaseString.arg(end.red()).arg(end.green()).arg(end.blue()),
rgbBaseString.arg(end.red()).arg(end.green()).arg(end.blue())).
arg(margin);
css << QStringLiteral("QToolButton#tbClose { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(close);
css << QStringLiteral("QToolButton#tbClose:hover { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(closeHover);
css << QStringLiteral("QToolButton#tbAck { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(ack);
css << QStringLiteral("QToolButton#tbAck:hover { border-image: url(:/%1) 0 0 0 0 stretch stretch; border-width: 0px; background-color: transparent; }").arg(ackHover);
#ifdef NOTIBOX_DEBUG #ifdef NOTIBOX_DEBUG
qWarning() << "css" << css; qWarning() << "css" << css;
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/close.svg")); qWarning() << "exists?" << QFile::exists(QStringLiteral(":/close.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/close_dark.svg")); qWarning() << "exists?" << QFile::exists(QStringLiteral(":/close_dark.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/error.svg")); qWarning() << "exists?" << QFile::exists(QStringLiteral(":/error.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/info.svg")); qWarning() << "exists?" << QFile::exists(QStringLiteral(":/info.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/warning.svg")); qWarning() << "exists?" << QFile::exists(QStringLiteral(":/warning.svg"));
qWarning() << "exists?" << QFile::exists(QStringLiteral(":/success.svg")); qWarning() << "exists?" << QFile::exists(QStringLiteral(":/success.svg"));
#endif #endif
m_ui->lblImage->setStyleSheet(QString()); m_ui->lblImage->setStyleSheet(QString());
setStyleSheet(css.join(QStringLiteral(" "))); setStyleSheet(css.join(QStringLiteral(" ")));
m_ui->lblText->setText(QStringLiteral("<p><span style='font-size:14pt; font-weight:600; color:#%1;'>%2</span></p><p><span style='font-size:14pt; color:#%3;'>%4</span></p>").arg(textColor, title, textColor, text)); m_ui->lblText->setText(
QStringLiteral("<p><span style='font-size:14pt; font-weight:600; color:#%1;'>%2</span></p><p><span "
"style='font-size:14pt; color:#%3;'>%4</span></p>")
.arg(textColor, title, textColor, text));
show(); show();
} }
void LtsNotificationBox::paintEvent(QPaintEvent*)
void LtsNotificationBox::paintEvent(QPaintEvent *)
{ {
QStyleOption opt; QStyleOption opt;
opt.init(this); opt.initFrom(this);
QPainter p(this); QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
} }
} } // namespace LtsWidgets
+75 -98
View File
@@ -1,133 +1,110 @@
#include "lts_profile_button.h" #include "lts_profile_button.h"
#include <QBrush>
#include <QEvent>
#include <QPaintEvent>
#include <QPainter> #include <QPainter>
#include <QPainterPath> #include <QPainterPath>
#include <QPaintEvent>
#include <QBrush>
#include <QPen> #include <QPen>
#include <QRect> #include <QRect>
#include <QEvent>
using namespace LtsWidgets; using namespace LtsWidgets;
LtsProfileButton::LtsProfileButton(QWidget* parent) : QWidget(parent), m_isHovered(false), m_menuEnabled(true)
LtsProfileButton::LtsProfileButton(QWidget *parent)
: QWidget(parent)
, m_isHovered(false)
, m_menuEnabled(true)
{ {
QSizePolicy qsp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); QSizePolicy qsp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
qsp.setHeightForWidth(true); qsp.setHeightForWidth(true);
setSizePolicy(qsp); setSizePolicy(qsp);
} }
void LtsProfileButton::setPixmap(const QPixmap& pixmap)
void LtsProfileButton::setPixmap(const QPixmap &pixmap)
{ {
if (pixmap.isNull()) if (pixmap.isNull())
m_pixmap = QPixmap(QStringLiteral("icon:no_pic.svg")); m_pixmap = QPixmap(QStringLiteral("icon:no_pic.svg"));
else else
m_pixmap = pixmap; m_pixmap = pixmap;
update();
}
void LtsProfileButton::enterEvent(QEvent *event)
{
m_isHovered = true;
update();
QWidget::enterEvent(event);
}
void LtsProfileButton::leaveEvent(QEvent *event)
{
m_isHovered = false;
update();
QWidget::leaveEvent(event);
}
bool LtsProfileButton::event(QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress && m_menuEnabled)
{
emit signalClicked();
event->accept();
update(); update();
return true;
}
return QWidget::event(event);
} }
void LtsProfileButton::enterEvent(QEvent* event)
{
m_isHovered = true;
update();
QWidget::enterEvent(static_cast<QEnterEvent*>(event));
}
void LtsProfileButton::leaveEvent(QEvent* event)
{
m_isHovered = false;
update();
QWidget::leaveEvent(event);
}
bool LtsProfileButton::event(QEvent* event)
{
if (event->type() == QEvent::MouseButtonPress && m_menuEnabled)
{
emit signalClicked();
event->accept();
update();
return true;
}
return QWidget::event(event);
}
void LtsProfileButton::paintEvent(QPaintEvent* event) void LtsProfileButton::paintEvent(QPaintEvent* event)
{ {
QPainter p(this); QPainter p(this);
p.save(); p.save();
int minSize; int minSize;
QPointF center; QPointF center;
minSize = height() > width() ? width() : height(); minSize = height() > width() ? width() : height();
center = QPointF(width() / 2.0, height() / 2.0); center = QPointF(width() / 2.0, height() / 2.0);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
QPixmap pixmap(minSize, minSize);
pixmap.fill(Qt::white);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); if (!m_pixmap.isNull())
QPixmap pixmap(minSize, minSize);
pixmap.fill(Qt::white);
if (!m_pixmap.isNull())
{
if (!(m_isHovered && m_menuEnabled))
{ {
pixmap = m_pixmap.scaled(minSize, minSize, Qt::KeepAspectRatioByExpanding); if (!(m_isHovered && m_menuEnabled))
{
pixmap = m_pixmap.scaled(minSize, minSize, Qt::KeepAspectRatioByExpanding);
}
} }
}
QPainterPath path;
path.addEllipse(center, minSize / 2.0 - 4, minSize / 2.0 - 4);
p.setClipPath(path);
p.drawPixmap(center - QPointF(minSize / 2.0, minSize / 2.0), pixmap);
p.setPen(QPen(QColor("gray"), 2));
p.drawEllipse(center, minSize / 2.0 - 4, minSize / 2.0 - 4);
QPainterPath path; if (m_isHovered && m_menuEnabled)
path.addEllipse(center, {
minSize / 2.0 - 4, p.setPen(QPen(QColor(QStringLiteral("gray")), (minSize / 48 * 2)));
minSize / 2.0 - 4);
p.setClipPath(path);
p.drawPixmap(center - QPointF(minSize/2.0,minSize/2.0),pixmap);
double xc = size().width() / 2.012;
double yc = size().height() / 2.012;
double diff = minSize / 2.012;
p.drawLine(QPointF(xc - (diff / 2.01f), yc - (diff / 3.01f)),
QPointF(xc + (diff / 2.02f), yc - (diff / 3.02f)));
p.drawLine(QPointF(xc - (diff / 2.01f), yc - 0.01f), QPointF(xc + (diff / 2.02f), yc - 0));
p.drawLine(QPointF(xc - (diff / 2.01f), yc + (diff / 3.01f)),
QPointF(xc + (diff / 2.02f), yc + (diff / 3.02f)));
}
event->accept();
p.setPen(QPen(QColor("gray"), 2)); p.restore();
p.drawEllipse(center,
minSize / 2.0 - 4,
minSize / 2.0 - 4);
if (m_isHovered && m_menuEnabled)
{
p.setPen(QPen(QColor(QStringLiteral("gray")), (minSize / 48 * 2)));
double xc = size().width()/2.012;
double yc = size().height()/2.012;
double diff = minSize/2.012;
p.drawLine(QPointF(xc - (diff/2.01f), yc - (diff/3.01f)), QPointF(xc + (diff/2.02f), yc - (diff/3.02f)));
p.drawLine(QPointF(xc - (diff/2.01f), yc - 0.01f), QPointF(xc + (diff/2.02f), yc - 0));
p.drawLine(QPointF(xc - (diff/2.01f), yc + (diff/3.01f)), QPointF(xc + (diff/2.02f), yc + (diff/3.02f)));
}
event->accept();
p.restore();
} }
File diff suppressed because it is too large. Load diff
+230 -269
View File
@@ -2,390 +2,351 @@
#include "ui_lts_text_editor.h" #include "ui_lts_text_editor.h"
#include <QColorDialog>
#include <QTextCursor>
#include <QApplication> #include <QApplication>
#include <QClipboard> #include <QClipboard>
#include <QTextCharFormat> #include <QColorDialog>
#include <QMimeData>
#include <QTextList>
#include <QLineEdit>
#include <QDebug> #include <QDebug>
#include <QLineEdit>
#include <QMimeData>
#include <QTextCharFormat>
#include <QTextCursor>
#include <QTextList>
namespace LtsWidgets namespace LtsWidgets
{ {
LtsTextEditor::LtsTextEditor(QWidget *parent) LtsTextEditor::LtsTextEditor(QWidget* parent) : QWidget(parent), m_ui(new Ui::LtsTextEditor)
: QWidget(parent)
, m_ui(new Ui::LtsTextEditor)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->textEdit, &QTextEdit::currentCharFormatChanged, connect(m_ui->textEdit, &QTextEdit::currentCharFormatChanged, this, &LtsTextEditor::slotCurrentCharFormatChanged);
this, &LtsTextEditor::slotCurrentCharFormatChanged); connect(m_ui->textEdit, &QTextEdit::cursorPositionChanged, this, &LtsTextEditor::slotAlignmentChanged);
connect(m_ui->textEdit, &QTextEdit::cursorPositionChanged,
this, &LtsTextEditor::slotAlignmentChanged);
connect(m_ui->textEdit->document(), &QTextDocument::undoAvailable, connect(m_ui->textEdit->document(), &QTextDocument::undoAvailable, m_ui->pbUndo, &QToolButton::setEnabled);
m_ui->pbUndo, &QToolButton::setEnabled); connect(m_ui->textEdit->document(), &QTextDocument::redoAvailable, m_ui->pbRedo, &QToolButton::setEnabled);
connect(m_ui->textEdit->document(), &QTextDocument::redoAvailable,
m_ui->pbRedo, &QToolButton::setEnabled);
m_ui->pbUndo->setEnabled(m_ui->textEdit->document()->isUndoAvailable()); m_ui->pbUndo->setEnabled(m_ui->textEdit->document()->isUndoAvailable());
m_ui->pbRedo->setEnabled(m_ui->textEdit->document()->isRedoAvailable()); m_ui->pbRedo->setEnabled(m_ui->textEdit->document()->isRedoAvailable());
connect(QApplication::clipboard(), &QClipboard::dataChanged, connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &LtsTextEditor::slotClipboardDataChanged);
this, &LtsTextEditor::slotClipboardDataChanged);
connect(m_ui->pbCut, &QToolButton::clicked, m_ui->textEdit, &QTextEdit::cut);
connect(m_ui->pbCopy, &QToolButton::clicked, m_ui->textEdit, &QTextEdit::copy);
connect(m_ui->pbPaste, &QToolButton::clicked, m_ui->textEdit, &QTextEdit::paste);
connect(m_ui->pbCut, &QToolButton::clicked, connect(m_ui->pbUndo, &QToolButton::clicked, m_ui->textEdit, &QTextEdit::undo);
m_ui->textEdit, &QTextEdit::cut); connect(m_ui->pbRedo, &QToolButton::clicked, m_ui->textEdit, &QTextEdit::redo);
connect(m_ui->pbCopy, &QToolButton::clicked,
m_ui->textEdit, &QTextEdit::copy);
connect(m_ui->pbPaste, &QToolButton::clicked,
m_ui->textEdit, &QTextEdit::paste);
connect(m_ui->pbUndo, &QToolButton::clicked, connect(m_ui->pbBold, &QToolButton::clicked, this, &LtsTextEditor::slotTextBold);
m_ui->textEdit, &QTextEdit::undo); connect(m_ui->pbItalic, &QToolButton::clicked, this, &LtsTextEditor::slotTextItalic);
connect(m_ui->pbRedo, &QToolButton::clicked, connect(m_ui->pbUnderline, &QToolButton::clicked, this, &LtsTextEditor::slotTextUnderline);
m_ui->textEdit, &QTextEdit::redo);
connect(m_ui->pbBold, &QToolButton::clicked, connect(m_ui->pbTextColor, &QToolButton::clicked, this, &LtsTextEditor::slotTextColor);
this, &LtsTextEditor::slotTextBold); connect(m_ui->pbBackgroundColor, &QToolButton::clicked, this, &LtsTextEditor::slotBackgroundColor);
connect(m_ui->pbItalic, &QToolButton::clicked,
this, &LtsTextEditor::slotTextItalic);
connect(m_ui->pbUnderline, &QToolButton::clicked,
this, &LtsTextEditor::slotTextUnderline);
connect(m_ui->pbTextColor, &QToolButton::clicked, connect(m_ui->pbAlignLeft, &QToolButton::toggled, this, &LtsTextEditor::slotTextAlign);
this, &LtsTextEditor::slotTextColor); connect(m_ui->pbAlignCenter, &QToolButton::toggled, this, &LtsTextEditor::slotTextAlign);
connect(m_ui->pbBackgroundColor, &QToolButton::clicked, connect(m_ui->pbAlignRight, &QToolButton::toggled, this, &LtsTextEditor::slotTextAlign);
this, &LtsTextEditor::slotBackgroundColor); connect(m_ui->pbAlignJustify, &QToolButton::toggled, this, &LtsTextEditor::slotTextAlign);
connect(m_ui->pbAlignLeft, &QToolButton::toggled, QFont textFont(QStringLiteral("Sans Serif"));
this, &LtsTextEditor::slotTextAlign); textFont.setStyleHint(QFont::SansSerif);
connect(m_ui->pbAlignCenter, &QToolButton::toggled, m_ui->textEdit->setFont(textFont);
this, &LtsTextEditor::slotTextAlign); slotFontChanged(m_ui->textEdit->font());
connect(m_ui->pbAlignRight, &QToolButton::toggled, slotTextColorChanged(m_ui->textEdit->textColor());
this, &LtsTextEditor::slotTextAlign); slotAlignmentChanged();
connect(m_ui->pbAlignJustify, &QToolButton::toggled,
this, &LtsTextEditor::slotTextAlign);
slotBackgroundColorChanged(m_backgroundColor);
QFont textFont(QStringLiteral("Sans Serif")); connect(m_ui->cbFonts, &QComboBox::currentTextChanged, this, &LtsTextEditor::slotTextFamily);
textFont.setStyleHint(QFont::SansSerif);
m_ui->textEdit->setFont(textFont);
slotFontChanged(m_ui->textEdit->font());
slotTextColorChanged(m_ui->textEdit->textColor());
slotAlignmentChanged();
slotBackgroundColorChanged(m_backgroundColor); const QList<int> standardSizes = QFontDatabase::standardSizes();
for (int size : standardSizes)
m_ui->cbFontSize->addItem(QString::number(size));
m_ui->cbFontSize->setCurrentIndex(standardSizes.indexOf(QApplication::font().pointSize()));
connect(m_ui->cbFontSize, &QComboBox::currentTextChanged, this, &LtsTextEditor::slotTextSize);
connect(m_ui->cbFonts, QOverload<const QString &>::of(&QComboBox::activated), connect(m_ui->cbFontSize->lineEdit(), &QLineEdit::editingFinished, this,
this, &LtsTextEditor::slotTextFamily); &LtsTextEditor::slotTextSizeEditingFinished);
const QList<int> standardSizes = QFontDatabase::standardSizes(); m_ui->textEdit->setFocus();
for (int size : standardSizes)
m_ui->cbFontSize->addItem(QString::number(size));
m_ui->cbFontSize->setCurrentIndex(standardSizes.indexOf(QApplication::font().pointSize()));
connect(m_ui->cbFontSize, QOverload<const QString &>::of(&QComboBox::activated),
this, &LtsTextEditor::slotTextSize);
connect(m_ui->cbFontSize->lineEdit(), &QLineEdit::editingFinished,
this, &LtsTextEditor::slotTextSizeEditingFinished);
m_ui->textEdit->setFocus();
} }
LtsTextEditor::~LtsTextEditor() LtsTextEditor::~LtsTextEditor()
{ {
delete m_ui; delete m_ui;
} }
QTextEdit* LtsTextEditor::textEdit()
QTextEdit *LtsTextEditor::textEdit()
{ {
return m_ui->textEdit; return m_ui->textEdit;
} }
QColor LtsTextEditor::backgroundColor() const QColor LtsTextEditor::backgroundColor() const
{ {
return m_backgroundColor; return m_backgroundColor;
} }
void LtsTextEditor::enableBackgroundColor(bool onOff) void LtsTextEditor::enableBackgroundColor(bool onOff)
{ {
m_ui->pbBackgroundColor->setVisible(onOff); m_ui->pbBackgroundColor->setVisible(onOff);
} }
void LtsTextEditor::setInitialBackgroundColor(const QColor &bgColor) void LtsTextEditor::setInitialBackgroundColor(const QColor& bgColor)
{ {
if (bgColor.isValid()) if (bgColor.isValid())
m_backgroundColor = bgColor; m_backgroundColor = bgColor;
slotBackgroundColorChanged(m_backgroundColor); slotBackgroundColorChanged(m_backgroundColor);
} }
void LtsTextEditor::slotTextBold() void LtsTextEditor::slotTextBold()
{ {
QTextCharFormat fmt; QTextCharFormat fmt;
fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
if (m_ui->textEdit->document()->isEmpty())
{
const QString &f = m_ui->cbFonts->currentText();
fmt.setFontFamily(f);
fmt.setFontFamilies({f});
fmt.setForeground(m_foregroundColor);
const qreal pointSize = (m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
fmt.setFontPointSize(pointSize);
}
slotMergeFormatOnWordOrSelection(fmt);
}
void LtsTextEditor::slotTextUnderline()
{
QTextCharFormat fmt;
fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
if (m_ui->textEdit->document()->isEmpty())
{
const QString &f = m_ui->cbFonts->currentText();
fmt.setFontFamily(f);
fmt.setFontFamilies({f});
fmt.setForeground(m_foregroundColor);
const qreal pointSize = (m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
fmt.setFontPointSize(pointSize);
}
slotMergeFormatOnWordOrSelection(fmt);
}
void LtsTextEditor::slotTextItalic()
{
QTextCharFormat fmt;
fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
if (m_ui->textEdit->document()->isEmpty())
{
const QString &f = m_ui->cbFonts->currentText();
fmt.setFontFamily(f);
fmt.setFontFamilies({f});
fmt.setForeground(m_foregroundColor);
const qreal pointSize = (m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
fmt.setFontPointSize(pointSize);
}
slotMergeFormatOnWordOrSelection(fmt);
}
void LtsTextEditor::slotTextFamily(const QString &f)
{
QTextCharFormat fmt;
if (m_ui->textEdit->document()->isEmpty())
{
fmt.setFontItalic(m_ui->pbItalic->isChecked()); fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked()); fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal); fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
if (m_ui->textEdit->document()->isEmpty())
const qreal pointSize = (m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11); {
fmt.setFontPointSize(pointSize); const QString& f = m_ui->cbFonts->currentText();
fmt.setForeground(m_foregroundColor); fmt.setFontFamily(f);
} fmt.setFontFamilies({f});
fmt.setFontFamily(f); fmt.setForeground(m_foregroundColor);
fmt.setFontFamilies({f}); const qreal pointSize =
slotMergeFormatOnWordOrSelection(fmt); (m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
fmt.setFontPointSize(pointSize);
}
slotMergeFormatOnWordOrSelection(fmt);
} }
void LtsTextEditor::slotTextUnderline()
void LtsTextEditor::slotTextSize(const QString &p)
{ {
qreal pointSize = p.toFloat(); QTextCharFormat fmt;
fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
if (m_ui->textEdit->document()->isEmpty())
{
const QString& f = m_ui->cbFonts->currentText();
fmt.setFontFamily(f);
fmt.setFontFamilies({f});
fmt.setForeground(m_foregroundColor);
const qreal pointSize =
(m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
fmt.setFontPointSize(pointSize);
}
slotMergeFormatOnWordOrSelection(fmt);
}
if (p.toFloat() > 0) void LtsTextEditor::slotTextItalic()
{ {
QSignalBlocker signalBlocker(m_ui->cbFontSize->lineEdit()); QTextCharFormat fmt;
m_ui->cbFontSize->clearFocus(); fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
if (m_ui->textEdit->document()->isEmpty())
{
const QString& f = m_ui->cbFonts->currentText();
fmt.setFontFamily(f);
fmt.setFontFamilies({f});
fmt.setForeground(m_foregroundColor);
const qreal pointSize =
(m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
fmt.setFontPointSize(pointSize);
}
slotMergeFormatOnWordOrSelection(fmt);
}
void LtsTextEditor::slotTextFamily(const QString& f)
{
QTextCharFormat fmt; QTextCharFormat fmt;
if (m_ui->textEdit->document()->isEmpty()) if (m_ui->textEdit->document()->isEmpty())
{ {
const QString &f = m_ui->cbFonts->currentText(); fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontFamily(f); fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontFamilies({f}); fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
fmt.setForeground(m_foregroundColor);
fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
const qreal pointSize =
(m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
fmt.setFontPointSize(pointSize);
fmt.setForeground(m_foregroundColor);
} }
fmt.setFontPointSize(pointSize); fmt.setFontFamily(f);
fmt.setFontFamilies({f});
slotMergeFormatOnWordOrSelection(fmt); slotMergeFormatOnWordOrSelection(fmt);
} }
void LtsTextEditor::slotTextSize(const QString& p)
{
qreal pointSize = p.toFloat();
if (p.toFloat() > 0)
{
QSignalBlocker signalBlocker(m_ui->cbFontSize->lineEdit());
m_ui->cbFontSize->clearFocus();
QTextCharFormat fmt;
if (m_ui->textEdit->document()->isEmpty())
{
const QString& f = m_ui->cbFonts->currentText();
fmt.setFontFamily(f);
fmt.setFontFamilies({f});
fmt.setForeground(m_foregroundColor);
fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
}
fmt.setFontPointSize(pointSize);
slotMergeFormatOnWordOrSelection(fmt);
}
} }
void LtsTextEditor::slotTextSizeEditingFinished() void LtsTextEditor::slotTextSizeEditingFinished()
{ {
qreal pointSize = m_ui->cbFontSize->currentText().toFloat(); qreal pointSize = m_ui->cbFontSize->currentText().toFloat();
if (pointSize > 0) if (pointSize > 0)
{ {
QTextCharFormat textCharFormat; QTextCharFormat textCharFormat;
textCharFormat.setFontPointSize(pointSize); textCharFormat.setFontPointSize(pointSize);
QTextCursor cursor = m_ui->textEdit->textCursor(); QTextCursor cursor = m_ui->textEdit->textCursor();
if (cursor.charFormat().font().pointSizeF() == pointSize) if (cursor.charFormat().font().pointSizeF() == pointSize)
return; return;
if (!cursor.hasSelection()) if (!cursor.hasSelection())
cursor.select(QTextCursor::WordUnderCursor); cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeCharFormat(textCharFormat); cursor.mergeCharFormat(textCharFormat);
} }
} }
void LtsTextEditor::slotTextColor() void LtsTextEditor::slotTextColor()
{ {
QColor col = QColorDialog::getColor(m_ui->textEdit->textColor(), this); QColor col = QColorDialog::getColor(m_ui->textEdit->textColor(), this);
if (!col.isValid()) if (!col.isValid())
return; return;
QTextCharFormat fmt; QTextCharFormat fmt;
if (m_ui->textEdit->document()->isEmpty()) if (m_ui->textEdit->document()->isEmpty())
{ {
fmt.setFontItalic(m_ui->pbItalic->isChecked()); fmt.setFontItalic(m_ui->pbItalic->isChecked());
fmt.setFontUnderline(m_ui->pbUnderline->isChecked()); fmt.setFontUnderline(m_ui->pbUnderline->isChecked());
fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal); fmt.setFontWeight(m_ui->pbBold->isChecked() ? QFont::Bold : QFont::Normal);
const QString &f = m_ui->cbFonts->currentText(); const QString& f = m_ui->cbFonts->currentText();
fmt.setFontFamily(f); fmt.setFontFamily(f);
fmt.setFontFamilies({f}); fmt.setFontFamilies({f});
const qreal pointSize = (m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11); const qreal pointSize =
fmt.setFontPointSize(pointSize); (m_ui->cbFontSize->currentText().toFloat() > 0 ? m_ui->cbFontSize->currentText().toFloat() : 11);
} fmt.setFontPointSize(pointSize);
fmt.setForeground(col); }
slotMergeFormatOnWordOrSelection(fmt); fmt.setForeground(col);
slotTextColorChanged(col); slotMergeFormatOnWordOrSelection(fmt);
slotTextColorChanged(col);
} }
void LtsTextEditor::slotBackgroundColor() void LtsTextEditor::slotBackgroundColor()
{ {
QColor col = QColorDialog::getColor(m_backgroundColor.isValid() ? m_backgroundColor : Qt::white, this); QColor col = QColorDialog::getColor(m_backgroundColor.isValid() ? m_backgroundColor : Qt::white, this);
if (!col.isValid()) if (!col.isValid())
return; return;
m_backgroundColor = col; m_backgroundColor = col;
slotBackgroundColorChanged(m_backgroundColor); slotBackgroundColorChanged(m_backgroundColor);
emit backgroundColorChanged(m_backgroundColor); emit backgroundColorChanged(m_backgroundColor);
} }
void LtsTextEditor::slotCurrentCharFormatChanged(const QTextCharFormat& format)
void LtsTextEditor::slotCurrentCharFormatChanged(const QTextCharFormat &format)
{ {
slotFontChanged(format.font()); slotFontChanged(format.font());
slotTextColorChanged(format.foreground().color()); slotTextColorChanged(format.foreground().color());
} }
void LtsTextEditor::slotFontChanged(const QFont& f)
void LtsTextEditor::slotFontChanged(const QFont &f)
{ {
m_ui->cbFonts->setCurrentIndex(m_ui->cbFonts->findText(f.family())); m_ui->cbFonts->setCurrentIndex(m_ui->cbFonts->findText(f.family()));
QSignalBlocker comboBoxsignalBlocker(m_ui->cbFontSize); QSignalBlocker comboBoxsignalBlocker(m_ui->cbFontSize);
QSignalBlocker lineEditSignalBlocker(m_ui->cbFontSize->lineEdit()); QSignalBlocker lineEditSignalBlocker(m_ui->cbFontSize->lineEdit());
QString fontSizeString = QString::number(f.pointSize()); QString fontSizeString = QString::number(f.pointSize());
int32_t fontSizeIndex = m_ui->cbFontSize->findText(fontSizeString); int32_t fontSizeIndex = m_ui->cbFontSize->findText(fontSizeString);
if (fontSizeIndex >= 0) if (fontSizeIndex >= 0)
m_ui->cbFontSize->setCurrentIndex(fontSizeIndex); m_ui->cbFontSize->setCurrentIndex(fontSizeIndex);
else if (m_ui->cbFontSize->currentText() != fontSizeString) else if (m_ui->cbFontSize->currentText() != fontSizeString)
m_ui->cbFontSize->setCurrentText(fontSizeString); m_ui->cbFontSize->setCurrentText(fontSizeString);
m_ui->pbBold->setChecked(f.bold()); m_ui->pbBold->setChecked(f.bold());
m_ui->pbItalic->setChecked(f.italic()); m_ui->pbItalic->setChecked(f.italic());
m_ui->pbUnderline->setChecked(f.underline()); m_ui->pbUnderline->setChecked(f.underline());
} }
void LtsTextEditor::slotMergeFormatOnWordOrSelection(const QTextCharFormat& format)
void LtsTextEditor::slotMergeFormatOnWordOrSelection(const QTextCharFormat &format)
{ {
QTextCursor cursor = m_ui->textEdit->textCursor(); QTextCursor cursor = m_ui->textEdit->textCursor();
if (!cursor.hasSelection()) if (!cursor.hasSelection())
cursor.select(QTextCursor::WordUnderCursor); cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeCharFormat(format); cursor.mergeCharFormat(format);
if (m_ui->textEdit->document()->isEmpty())
if (m_ui->textEdit->document()->isEmpty()) m_ui->textEdit->setTextCursor(cursor);
m_ui->textEdit->setTextCursor(cursor);
} }
void LtsTextEditor::slotTextColorChanged(const QColor& c)
void LtsTextEditor::slotTextColorChanged(const QColor &c)
{ {
QPixmap pix(32, 32); QPixmap pix(32, 32);
pix.fill(c); pix.fill(c);
m_ui->pbTextColor->setIcon(pix); m_ui->pbTextColor->setIcon(pix);
m_foregroundColor = c; m_foregroundColor = c;
} }
void LtsTextEditor::slotBackgroundColorChanged(const QColor& bgColor)
void LtsTextEditor::slotBackgroundColorChanged(const QColor &bgColor)
{ {
QPixmap pix(32, 32); QPixmap pix(32, 32);
pix.fill(bgColor); pix.fill(bgColor);
m_ui->pbBackgroundColor->setIcon(pix); m_ui->pbBackgroundColor->setIcon(pix);
} }
void LtsTextEditor::slotTextAlign() void LtsTextEditor::slotTextAlign()
{ {
QToolButton *b = qobject_cast<QToolButton *>(sender()); QToolButton* b = qobject_cast<QToolButton*>(sender());
if (b == nullptr) if (b == nullptr)
return; return;
if (b == m_ui->pbAlignLeft) if (b == m_ui->pbAlignLeft)
m_ui->textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute); m_ui->textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
else if (b == m_ui->pbAlignCenter) else if (b == m_ui->pbAlignCenter)
m_ui->textEdit->setAlignment(Qt::AlignHCenter); m_ui->textEdit->setAlignment(Qt::AlignHCenter);
else if (b == m_ui->pbAlignRight) else if (b == m_ui->pbAlignRight)
m_ui->textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute); m_ui->textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
else if (b == m_ui->pbAlignJustify) else if (b == m_ui->pbAlignJustify)
m_ui->textEdit->setAlignment(Qt::AlignJustify); m_ui->textEdit->setAlignment(Qt::AlignJustify);
} }
void LtsTextEditor::slotAlignmentChanged() void LtsTextEditor::slotAlignmentChanged()
{ {
auto a = m_ui->textEdit->alignment(); auto a = m_ui->textEdit->alignment();
if (a & Qt::AlignLeft) if (a & Qt::AlignLeft)
m_ui->pbAlignLeft->setChecked(true); m_ui->pbAlignLeft->setChecked(true);
if (a & Qt::AlignHCenter) if (a & Qt::AlignHCenter)
m_ui->pbAlignCenter->setChecked(true); m_ui->pbAlignCenter->setChecked(true);
if (a & Qt::AlignRight) if (a & Qt::AlignRight)
m_ui->pbAlignRight->setChecked(true); m_ui->pbAlignRight->setChecked(true);
if (a & Qt::AlignJustify) if (a & Qt::AlignJustify)
m_ui->pbAlignJustify->setChecked(true); m_ui->pbAlignJustify->setChecked(true);
} }
void LtsTextEditor::slotClipboardDataChanged() void LtsTextEditor::slotClipboardDataChanged()
{ {
if (const QMimeData *md = QApplication::clipboard()->mimeData()) if (const QMimeData* md = QApplication::clipboard()->mimeData())
m_ui->pbPaste->setEnabled(md->hasText()); m_ui->pbPaste->setEnabled(md->hasText());
} }
} } // namespace LtsWidgets
File diff suppressed because it is too large. Load diff
+13 -17
View File
@@ -1,31 +1,27 @@
#include "lts_tool_bar.h" #include "lts_tool_bar.h"
using namespace LtsWidgets; using namespace LtsWidgets;
LtsToolBar::LtsToolBar(QWidget *parent) LtsToolBar::LtsToolBar(QWidget* parent) : QToolBar(parent)
: QToolBar(parent)
{ {
setMaximumHeight(1); setMaximumHeight(1);
setMinimumHeight(1); setMinimumHeight(1);
} }
LtsToolBar::~LtsToolBar() LtsToolBar::~LtsToolBar() {}
void LtsToolBar::enterEvent(QEnterEvent* e)
{ {
setMaximumHeight(50);
setMinimumHeight(50);
QToolBar::enterEvent(e);
} }
void LtsToolBar::enterEvent(QEvent *e) void LtsToolBar::leaveEvent(QEvent* e)
{ {
setMaximumHeight(50); setMaximumHeight(1);
setMinimumHeight(50); setMinimumHeight(1);
QToolBar::enterEvent(e); QToolBar::leaveEvent(e);
}
void LtsToolBar::leaveEvent(QEvent *e)
{
setMaximumHeight(1);
setMinimumHeight(1);
QToolBar::leaveEvent(e);
} }
+11 -14
View File
@@ -1,28 +1,25 @@
#pragma once #pragma once
#include <QObject>
#include <QToolBar>
#include "ltswidgets_export.h" #include "ltswidgets_export.h"
#include <QObject>
#include <QToolBar>
namespace LtsWidgets namespace LtsWidgets
{ {
class LTSWIDGETS_EXPORT LtsToolBar : public QToolBar class LTSWIDGETS_EXPORT LtsToolBar : public QToolBar
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LtsToolBar(QWidget *parent = nullptr); explicit LtsToolBar(QWidget* parent = nullptr);
~LtsToolBar(); ~LtsToolBar();
protected:
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *e) override;
protected:
void enterEvent(QEnterEvent* e) override;
void leaveEvent(QEvent* e) override;
}; };
} } // namespace LtsWidgets
+240 -280
View File
@@ -1,385 +1,345 @@
#include "lts_tool_bar_area.h" #include "lts_tool_bar_area.h"
#include <utility>
#include "ui_lts_tool_bar_area.h"
#include "lts_drag_icon.h" #include "lts_drag_icon.h"
#include "ui_lts_tool_bar_area.h"
#include <LtsUtilsSettings/settings.h> #include <LtsUtilsSettings/settings.h>
#include <QDebug>
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QDropEvent> #include <QDropEvent>
#include <QLabel> #include <QLabel>
#include <QDebug>
#include <QMenu> #include <QMenu>
#include <QShortcut>
#include <QPointer> #include <QPointer>
#include <QShortcut>
#include <QVariant>
#include <utility>
namespace LtsWidgets namespace LtsWidgets
{ {
void ShortCut::clear() void ShortCut::clear()
{ {
name.clear(); name.clear();
identifier.clear(); identifier.clear();
icon = nullptr; icon = nullptr;
shortcut->disconnect(icon); shortcut->disconnect(icon);
} }
LtsToolBarArea::LtsToolBarArea(QWidget* parent) : QWidget(parent), m_dummyLabel(nullptr), m_ui(new Ui::LtsToolBarArea)
LtsToolBarArea::LtsToolBarArea(QWidget *parent)
: QWidget(parent)
, m_dummyLabel(nullptr)
, m_ui(new Ui::LtsToolBarArea)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
setAcceptDrops(true); setAcceptDrops(true);
clearToolBarArea(); clearToolBarArea();
for (int i = Qt::Key_F5; i <= Qt::Key_F12; ++i)
for(int i=Qt::Key_F5; i<=Qt::Key_F12; ++i) {
{ ShortCut sc(this);
ShortCut sc(this); sc.shortcut->setKey(QKeySequence(i));
sc.shortcut->setKey(QKeySequence(i)); sc.key = i;
sc.key = i; m_functionKeys.insert(i, sc);
m_functionKeys.insert(i, sc); }
}
} }
LtsToolBarArea::~LtsToolBarArea() LtsToolBarArea::~LtsToolBarArea()
{ {
delete m_ui; delete m_ui;
} }
void LtsToolBarArea::addMenuEntry(LtsDragIcon *entry, LtsDragIcon *after) void LtsToolBarArea::addMenuEntry(LtsDragIcon* entry, LtsDragIcon* after)
{ {
if (!entry) if (!entry)
return;
if (m_foreignButtonMap.contains(entry))
return;
delete m_dummyLabel;
m_dummyLabel = nullptr;
bool isInternalMove = false;
LtsDragIcon *foreignDragIcon = entry;
for (int i = 0; i < m_buttonMap.size(); ++i)
{
if (m_buttonMap.at(i) == entry)
{
isInternalMove = true;
if (after == nullptr)
return; return;
m_buttonMap.removeAt(i);
foreignDragIcon = m_foreignButtonMap.at(i);
m_foreignButtonMap.removeAt(i);
m_ui->layToolbar->removeWidget(entry);
break;
}
}
if (m_foreignButtonMap.contains(entry))
return;
int index = m_buttonMap.size(); delete m_dummyLabel;
for(int i = 0; i < m_buttonMap.size(); ++i) m_dummyLabel = nullptr;
{
if (m_buttonMap.at(i) == after || bool isInternalMove = false;
m_foreignButtonMap.at(i) == after) LtsDragIcon* foreignDragIcon = entry;
for (int i = 0; i < m_buttonMap.size(); ++i)
{ {
index = i + 1; if (m_buttonMap.at(i) == entry)
break; {
isInternalMove = true;
if (after == nullptr)
return;
m_buttonMap.removeAt(i);
foreignDragIcon = m_foreignButtonMap.at(i);
m_foreignButtonMap.removeAt(i);
m_ui->layToolbar->removeWidget(entry);
break;
}
} }
}
int index = m_buttonMap.size();
for (int i = 0; i < m_buttonMap.size(); ++i)
{
if (m_buttonMap.at(i) == after || m_foreignButtonMap.at(i) == after)
{
index = i + 1;
break;
}
}
LtsDragIcon *newAction = entry; LtsDragIcon* newAction = entry;
if (!isInternalMove) if (!isInternalMove)
{ {
newAction = new LtsDragIcon(this); newAction = new LtsDragIcon(this);
newAction->setIcon(entry->icon()); newAction->setIcon(entry->icon());
newAction->setText(entry->text()); newAction->setText(entry->text());
newAction->setContext(entry->context()); newAction->setContext(entry->context());
if (!entry->toolTip().isEmpty()) if (!entry->toolTip().isEmpty())
newAction->setToolTip(entry->toolTip()); newAction->setToolTip(entry->toolTip());
newAction->setIconSize(ButtonSize::eDefault); newAction->setIconSize(ButtonSize::eDefault);
newAction->setButtonStyle(ButtonStyle::eIconOnly); newAction->setButtonStyle(ButtonStyle::eIconOnly);
newAction->setIdentifier(entry->identifier()); newAction->setIdentifier(entry->identifier());
connect(newAction, &LtsDragIcon::clicked, entry, &LtsDragIcon::clicked); connect(newAction, &LtsDragIcon::clicked, entry, &LtsDragIcon::clicked);
connect(entry, &LtsDragIcon::destroyed, newAction, connect(entry, &LtsDragIcon::destroyed, newAction, [this, newAction]() {
[this, newAction]() { m_buttonMap.removeAll(newAction); newAction->deleteLater(); }); m_buttonMap.removeAll(newAction);
newAction->setVisible(!entry->text().isEmpty()); newAction->deleteLater();
} });
newAction->setContextMenuPolicy(Qt::CustomContextMenu); newAction->setVisible(!entry->text().isEmpty());
connect(newAction, &LtsDragIcon::customContextMenuRequested, }
this, &LtsToolBarArea::showContextMenu); newAction->setContextMenuPolicy(Qt::CustomContextMenu);
connect(newAction, &LtsDragIcon::customContextMenuRequested, this, &LtsToolBarArea::showContextMenu);
m_foreignButtonMap.insert(index, foreignDragIcon); m_foreignButtonMap.insert(index, foreignDragIcon);
m_buttonMap.insert(index, newAction); m_buttonMap.insert(index, newAction);
connect(foreignDragIcon, &LtsDragIcon::enabledChanged, newAction, &LtsDragIcon::setEnabled); connect(foreignDragIcon, &LtsDragIcon::enabledChanged, newAction, &LtsDragIcon::setEnabled);
m_ui->layToolbar->insertWidget(index + 1, newAction);
m_ui->layToolbar->insertWidget(index + 1, newAction); saveSettings();
saveSettings();
} }
void LtsToolBarArea::clearToolBarArea() void LtsToolBarArea::clearToolBarArea()
{ {
qDeleteAll(m_buttonMap); qDeleteAll(m_buttonMap);
m_buttonMap.clear(); m_buttonMap.clear();
m_foreignButtonMap.clear(); m_foreignButtonMap.clear();
for(ShortCut &item : m_functionKeys) for (ShortCut& item : m_functionKeys)
item.clear(); item.clear();
delete m_dummyLabel; delete m_dummyLabel;
m_dummyLabel = new QLabel(tr("Drop menu entry here"), this); m_dummyLabel = new QLabel(tr("Drop menu entry here"), this);
m_ui->layToolbar->addWidget(m_dummyLabel); m_ui->layToolbar->addWidget(m_dummyLabel);
} }
void LtsToolBarArea::setMenuEntries(const QVector<LtsDragIcon *> &actions) void LtsToolBarArea::setMenuEntries(const QVector<LtsDragIcon*>& actions)
{ {
clearToolBarArea(); clearToolBarArea();
for (LtsDragIcon* ico : actions) for (LtsDragIcon* ico : actions)
addMenuEntry(ico); addMenuEntry(ico);
} }
QStringList LtsToolBarArea::menuEntries() const QStringList LtsToolBarArea::menuEntries() const
{ {
QStringList ret; QStringList ret;
ret.reserve(m_foreignButtonMap.size()); ret.reserve(m_foreignButtonMap.size());
for (LtsDragIcon *dragIcon : m_foreignButtonMap) for (LtsDragIcon* dragIcon : m_foreignButtonMap)
ret << dragIcon->identifier(); ret << dragIcon->identifier();
return ret; return ret;
} }
void LtsToolBarArea::dragEnterEvent(QDragEnterEvent* event)
void LtsToolBarArea::dragEnterEvent(QDragEnterEvent *event)
{ {
LtsDragIcon *source = LtsDragIcon* source = qobject_cast<LtsDragIcon*>(event->source());
qobject_cast<LtsDragIcon *>(event->source()); if (source)
if (source)
{
if (!m_foreignButtonMap.contains(source))
{ {
event->setDropAction(Qt::MoveAction); if (!m_foreignButtonMap.contains(source))
event->accept(); {
event->setDropAction(Qt::MoveAction);
event->accept();
}
} }
}
} }
void LtsToolBarArea::dropEvent(QDropEvent *event) void LtsToolBarArea::dropEvent(QDropEvent* event)
{ {
LtsDragIcon *source = qobject_cast<LtsDragIcon *>(event->source()); LtsDragIcon* source = qobject_cast<LtsDragIcon*>(event->source());
LtsDragIcon *after = nullptr; LtsDragIcon* after = nullptr;
QWidget *w = childAt(event->pos()); QWidget* w = childAt(event->pos());
while (w) while (w)
{ {
after = qobject_cast<LtsDragIcon *>(w); after = qobject_cast<LtsDragIcon*>(w);
if (after) if (after)
break; break;
w = w->parentWidget(); w = w->parentWidget();
} }
addMenuEntry(source, after); addMenuEntry(source, after);
} }
QMenu *LtsToolBarArea::functionKeyMenu(QWidget *parent) QMenu* LtsToolBarArea::functionKeyMenu(QWidget* parent)
{ {
QMenu* menu = new QMenu(parent); QMenu* menu = new QMenu(parent);
menu->setTitle(tr("Function Key")); menu->setTitle(tr("Function Key"));
QAction *act; QAction* act;
for(auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val) for (auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
{ {
ShortCut &shorty = val.value(); ShortCut& shorty = val.value();
act = menu->addAction(QStringLiteral("%1%2").arg(shorty.keyName(), !shorty.name.isEmpty() ? QStringLiteral(" - %1").arg(shorty.name) : QString())); act = menu->addAction(QStringLiteral("%1%2").arg(
act->setData(shorty.shortcut->key()[0]); shorty.keyName(), !shorty.name.isEmpty() ? QStringLiteral(" - %1").arg(shorty.name) : QString()));
act->setData(QVariant::fromValue(shorty.shortcut->key()[0]));
connect(act, &QAction::triggered, this, &LtsToolBarArea::functionKeyMenuTriggered);
}
menu->addSeparator();
act = menu->addAction(tr("Remove Function Key"));
act->setData(-1);
connect(act, &QAction::triggered, this, &LtsToolBarArea::functionKeyMenuTriggered); connect(act, &QAction::triggered, this, &LtsToolBarArea::functionKeyMenuTriggered);
} return menu;
menu->addSeparator();
act = menu->addAction(tr("Remove Function Key"));
act->setData(-1);
connect(act, &QAction::triggered, this, &LtsToolBarArea::functionKeyMenuTriggered);
return menu;
} }
void LtsToolBarArea::functionKeyMenuTriggered() void LtsToolBarArea::functionKeyMenuTriggered()
{ {
QAction* act = qobject_cast<QAction*>(sender()); QAction* act = qobject_cast<QAction*>(sender());
if (!act) if (!act)
return; return;
int fkey = act->data().toInt(); int fkey = act->data().toInt();
if (fkey == -1) if (fkey == -1)
removeFunctionKey(m_currentIdentifierForContextMenue); removeFunctionKey(m_currentIdentifierForContextMenue);
else if (fkey > 0) else if (fkey > 0)
setFunctionKey(fkey, m_currentIdentifierForContextMenue); setFunctionKey(fkey, m_currentIdentifierForContextMenue);
} }
bool LtsToolBarArea::removeFunctionKey(const QString& action)
bool LtsToolBarArea::removeFunctionKey(const QString &action)
{ {
if (action.isEmpty()) if (action.isEmpty())
return true;
for (auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
{
ShortCut& itShortcut = val.value();
if (itShortcut.identifier == action)
{
itShortcut.icon->removeModification();
itShortcut.clear();
break;
}
}
saveSettings();
return true; return true;
for(auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
{
ShortCut &itShortcut = val.value();
if (itShortcut.identifier == action)
{
itShortcut.icon->removeModification();
itShortcut.clear();
break;
}
}
saveSettings();
return true;
} }
bool LtsToolBarArea::setFunctionKey(int fkey, const QString &action) bool LtsToolBarArea::setFunctionKey(int fkey, const QString& action)
{ {
if (fkey < Qt::Key_F5 || fkey > Qt::Key_F12) if (fkey < Qt::Key_F5 || fkey > Qt::Key_F12)
return false; return false;
LtsDragIcon* icon = nullptr;
LtsDragIcon *icon = nullptr; for (LtsDragIcon* ic : std::as_const(m_buttonMap))
for (LtsDragIcon *ic : std::as_const(m_buttonMap))
{
if (ic->identifier() == action)
{ {
icon = ic; if (ic->identifier() == action)
break; {
icon = ic;
break;
}
} }
}
if (!icon) if (!icon)
return false; return false;
ShortCut& shorty = m_functionKeys[fkey];
ShortCut &shorty = m_functionKeys[fkey]; for (LtsDragIcon* ic : std::as_const(m_buttonMap))
if (ic->identifier() == shorty.identifier)
ic->removeModification();
for (auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
for (LtsDragIcon *ic : std::as_const(m_buttonMap))
if (ic->identifier() == shorty.identifier)
ic->removeModification();
for(auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
{
ShortCut &itShortcut = val.value();
if (itShortcut.identifier == action)
{ {
itShortcut.clear(); ShortCut& itShortcut = val.value();
break; if (itShortcut.identifier == action)
{
itShortcut.clear();
break;
}
} }
}
shorty.clear();
shorty.clear(); shorty.identifier = icon->identifier();
shorty.identifier = icon->identifier(); shorty.name = icon->text();
shorty.name = icon->text(); shorty.icon = icon;
shorty.icon = icon; shorty.icon->setModification(shorty.keyName());
shorty.icon->setModification(shorty.keyName()); connect(shorty.shortcut, &QShortcut::activated, icon, &LtsDragIcon::clicked);
connect(shorty.shortcut, &QShortcut::activated, icon, &LtsDragIcon::clicked); saveSettings();
saveSettings(); return true;
return true;
} }
QMap<int, QString> LtsToolBarArea::functionKeys() const QMap<int, QString> LtsToolBarArea::functionKeys() const
{ {
QMap<int, QString> retVal; QMap<int, QString> retVal;
for(auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val) for (auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
{
const ShortCut &itShortcut = val.value();
if (!itShortcut.identifier.isEmpty())
retVal[itShortcut.key] = itShortcut.identifier;
}
return retVal;
}
void LtsToolBarArea::removeMenuAction(LtsDragIcon *icon)
{
for(auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
{
ShortCut &itShortcut = val.value();
if (itShortcut.identifier == icon->identifier())
itShortcut.clear();
}
for (LtsDragIcon *ic : std::as_const(m_foreignButtonMap))
{
if(ic->identifier() == icon->identifier())
{ {
m_foreignButtonMap.removeAll(ic); const ShortCut& itShortcut = val.value();
break; if (!itShortcut.identifier.isEmpty())
retVal[itShortcut.key] = itShortcut.identifier;
} }
} return retVal;
m_buttonMap.removeAll(icon);
m_ui->layToolbar->removeWidget(icon);
delete icon;
saveSettings();
} }
void LtsToolBarArea::showContextMenu(const QPoint &pos) void LtsToolBarArea::removeMenuAction(LtsDragIcon* icon)
{
QPointer<LtsDragIcon> icon = qobject_cast<LtsDragIcon*>(sender());
if (!icon)
return;
const QPoint &globalPos = icon->mapToGlobal(pos);
QMenu *contextMenu = new QMenu(this);
contextMenu->setAttribute(Qt::WA_DeleteOnClose);
m_currentIdentifierForContextMenue = icon->identifier();
connect(contextMenu, &QObject::destroyed, this, [this](){
m_currentIdentifierForContextMenue.clear();
});
QAction *delAction = contextMenu->addAction(tr("Remove"));
connect(delAction, &QAction::triggered, this, [this, icon] () {
if (icon)
removeMenuAction(icon);
});
QMenu *fkeyMenu = functionKeyMenu(contextMenu);
contextMenu->addMenu(fkeyMenu);
contextMenu->popup(globalPos);
}
void LtsToolBarArea::saveSettings()
{ {
for (auto val = m_functionKeys.begin(); val != m_functionKeys.end(); ++val)
{
ShortCut& itShortcut = val.value();
if (itShortcut.identifier == icon->identifier())
itShortcut.clear();
}
for (LtsDragIcon* ic : std::as_const(m_foreignButtonMap))
{
if (ic->identifier() == icon->identifier())
{
m_foreignButtonMap.removeAll(ic);
break;
}
}
m_buttonMap.removeAll(icon);
m_ui->layToolbar->removeWidget(icon);
delete icon;
saveSettings();
} }
void LtsToolBarArea::showContextMenu(const QPoint& pos)
{
QPointer<LtsDragIcon> icon = qobject_cast<LtsDragIcon*>(sender());
if (!icon)
return;
const QPoint& globalPos = icon->mapToGlobal(pos);
QMenu* contextMenu = new QMenu(this);
contextMenu->setAttribute(Qt::WA_DeleteOnClose);
m_currentIdentifierForContextMenue = icon->identifier();
connect(contextMenu, &QObject::destroyed, this, [this]() { m_currentIdentifierForContextMenue.clear(); });
QAction* delAction = contextMenu->addAction(tr("Remove"));
connect(delAction, &QAction::triggered, this, [this, icon]() {
if (icon)
removeMenuAction(icon);
});
QMenu* fkeyMenu = functionKeyMenu(contextMenu);
contextMenu->addMenu(fkeyMenu);
contextMenu->popup(globalPos);
} }
void LtsToolBarArea::saveSettings() {}
} // namespace LtsWidgets
@@ -13,8 +13,10 @@ ADD_SUBDIRECTORY(Battery)
ADD_SUBDIRECTORY(Buildings) ADD_SUBDIRECTORY(Buildings)
ADD_SUBDIRECTORY(BuildingViewer) # uses ZW connections (uses sql, ace, ..) ADD_SUBDIRECTORY(BuildingViewer) # uses ZW connections (uses sql, ace, ..)
ADD_SUBDIRECTORY(CentralEffectSimulation) ADD_SUBDIRECTORY(CentralEffectSimulation)
ADD_SUBDIRECTORY(CodificationManagement) IF(BUILD_CODIFICATION)
ADD_SUBDIRECTORY(CodificationManagement/Test) ADD_SUBDIRECTORY(CodificationManagement)
ADD_SUBDIRECTORY(CodificationManagement/Test)
ENDIF()
ADD_SUBDIRECTORY(CollateralDamageSimulation) ADD_SUBDIRECTORY(CollateralDamageSimulation)
ADD_SUBDIRECTORY(EffectManagement) ADD_SUBDIRECTORY(EffectManagement)
ADD_SUBDIRECTORY(EffectShowClient) ADD_SUBDIRECTORY(EffectShowClient)
@@ -22,7 +24,9 @@ ADD_SUBDIRECTORY(EffectShowManagement)
ADD_SUBDIRECTORY(Evaluations) ADD_SUBDIRECTORY(Evaluations)
ADD_SUBDIRECTORY(ExerciseManagement) ADD_SUBDIRECTORY(ExerciseManagement)
ADD_SUBDIRECTORY(FileManagement) ADD_SUBDIRECTORY(FileManagement)
ADD_SUBDIRECTORY(FilterManagement) IF(BUILD_FILTERMANAGEMENT)
ADD_SUBDIRECTORY(FilterManagement)
ENDIF()
ADD_SUBDIRECTORY(FreeSpace) ADD_SUBDIRECTORY(FreeSpace)
ADD_SUBDIRECTORY(GuezIedManagement) ADD_SUBDIRECTORY(GuezIedManagement)
ADD_SUBDIRECTORY(GuezNasat) ADD_SUBDIRECTORY(GuezNasat)
@@ -5,7 +5,12 @@
# Created by Hannes Fritsche, ESZS, 2024-08-05 # Created by Hannes Fritsche, ESZS, 2024-08-05
# #
FIND_PACKAGE(KDReports REQUIRED) FIND_PACKAGE(KDReports)
IF(NOT KDReports_FOUND)
MESSAGE(STATUS "KDReports not found; skipping CdsSimulationGuiPlugin")
RETURN()
ENDIF()
SET(cds_gui_SRCS SET(cds_gui_SRCS
cds_building_model.cpp cds_building_model.cpp
@@ -37,11 +37,18 @@ ADD_INTERFACE_LIBRARY(
# #
# need top be shared due to signals/slots # need top be shared due to signals/slots
NGL_ADD_LIBRARY2(WS IsmDataPluginInterface SHARED ism_data_plugin_interface.h) NGL_ADD_LIBRARY2(WS IsmDataPluginInterface SHARED ism_data_plugin_interface.h)
IF(BUILD_RTI)
NGL_TARGET_LINK_LIBRARIES(IsmDataPluginInterface NGL_TARGET_LINK_LIBRARIES(IsmDataPluginInterface
Qt6::Core Qt6::Core
svcIsmCommon svcIsmCommon
DataPluginInterface DataPluginInterface
) )
ELSE()
NGL_TARGET_LINK_LIBRARIES(IsmDataPluginInterface
Qt6::Core
DataPluginInterface
)
ENDIF(BUILD_RTI)
NGL_INSTALL_TARGET(IsmDataPluginInterface) NGL_INSTALL_TARGET(IsmDataPluginInterface)
# #
@@ -7,8 +7,8 @@
FIND_PACKAGE(KDReports) FIND_PACKAGE(KDReports)
FIND_PACKAGE(KDChart) FIND_PACKAGE(KDChart)
IF (NOT KDReports_FOUND OR NOT KDChart_FOUND) IF ((NOT KDReports_FOUND OR NOT KDChart_FOUND) OR NOT BUILD_CODIFICATION)
MESSAGE(WARNING "KDReports or KDChart not found; skipping ReportViewer") MESSAGE(WARNING "KDReports, KDChart not found or BUILD_CODIFICATION disabled; skipping ReportViewer")
RETURN() RETURN()
ENDIF() ENDIF()
+210 -194
View File
@@ -1,289 +1,305 @@
#pragma once #pragma once
#include "sv_export.h"
#include <QByteArray> #include <QByteArray>
#include <WirelessLocationSystem/sfmconverter_export.h>
namespace WirelessLocationSystem namespace WirelessLocationSystem
{ {
class SfmMessage class SfmMessage
{ {
public: public:
enum class MsgId enum class MsgId {
{ TacticalState = 37,
TacticalState = 37, SfmRestartNotification = 76,
SfmRestartNotification = 76, GpsControl = 79,
GpsControl = 79, RequestGpsControl = 79 | 0x8000,
RequestGpsControl = 79 | 0x8000, EquipmentId = 478,
EquipmentId = 478, RequestEquipmentId = 478 | 0x8000,
RequestEquipmentId = 478 | 0x8000, Acknowledge = 1098,
Acknowledge = 1098, LicenseState = 1099,
LicenseState = 1099, TetraMessage = 1100
TetraMessage = 1100 };
};
protected: protected:
explicit SfmMessage(MsgId id) explicit SfmMessage(MsgId id) : m_id(id) {}
: m_id(id)
{}
public: public:
virtual ~SfmMessage() = default; virtual ~SfmMessage() = default;
MsgId getId() const { return m_id; } MsgId getId() const
private: {
MsgId m_id; return m_id;
}
private:
MsgId m_id;
}; };
class SfmMessage_tx : public SfmMessage class SfmMessage_tx : public SfmMessage
{ {
public: public:
using SfmMessage::SfmMessage; using SfmMessage::SfmMessage;
virtual QByteArray getPayload() const = 0;
virtual QByteArray getPayload() const = 0;
}; };
class SfmMessage_rx : public SfmMessage class SfmMessage_rx : public SfmMessage
{ {
public: public:
using SfmMessage::SfmMessage; using SfmMessage::SfmMessage;
virtual bool setPayload(const QByteArray& payload) = 0;
virtual bool setPayload(const QByteArray &payload) = 0;
}; };
class SfmMsgGpsControl_tx final : public SfmMessage_tx class SfmMsgGpsControl_tx final : public SfmMessage_tx
{ {
public: public:
explicit SfmMsgGpsControl_tx(bool gpsOn = false) explicit SfmMsgGpsControl_tx(bool gpsOn = false) : SfmMessage_tx(SfmMessage::MsgId::GpsControl), m_gpsOn(gpsOn) {}
: SfmMessage_tx(SfmMessage::MsgId::GpsControl)
, m_gpsOn(gpsOn)
{}
QByteArray getPayload() const override; QByteArray getPayload() const override;
void setGpsOn(bool bOn) { m_gpsOn = bOn; } void setGpsOn(bool bOn)
bool isGpsOn() const { return m_gpsOn; } {
m_gpsOn = bOn;
}
private: bool isGpsOn() const
bool m_gpsOn; {
return m_gpsOn;
}
private:
bool m_gpsOn;
}; };
class SfmMsgRequestGpsControl_rx final : public SfmMessage_rx class SfmMsgRequestGpsControl_rx final : public SfmMessage_rx
{ {
public: public:
SfmMsgRequestGpsControl_rx() SfmMsgRequestGpsControl_rx() : SfmMessage_rx(SfmMessage::MsgId::RequestGpsControl) {}
: SfmMessage_rx(SfmMessage::MsgId::RequestGpsControl)
{}
bool setPayload(const QByteArray &payload) override bool setPayload(const QByteArray& payload) override
{ {
return (payload.size() == 0); return (payload.size() == 0);
} }
}; };
class SfmMsgRequestEquipmentId_tx final : public SfmMessage_tx class SfmMsgRequestEquipmentId_tx final : public SfmMessage_tx
{ {
public: public:
SfmMsgRequestEquipmentId_tx() SfmMsgRequestEquipmentId_tx() : SfmMessage_tx(SfmMessage::MsgId::RequestEquipmentId) {}
: SfmMessage_tx(SfmMessage::MsgId::RequestEquipmentId)
{}
QByteArray getPayload() const override QByteArray getPayload() const override
{ {
return QByteArray(); return QByteArray();
} }
}; };
class SFMCONVERTER_EXPORT SfmMsgEquipmentId final : public SfmMessage_rx, public SfmMessage_tx class SFMCONVERTER_EXPORT SfmMsgEquipmentId final : public SfmMessage_rx, public SfmMessage_tx
{ {
public: public:
SfmMsgEquipmentId() SfmMsgEquipmentId() : SfmMessage_rx(SfmMessage::MsgId::EquipmentId), SfmMessage_tx(SfmMessage::MsgId::EquipmentId)
: SfmMessage_rx(SfmMessage::MsgId::EquipmentId) {
, SfmMessage_tx(SfmMessage::MsgId::EquipmentId) }
{}
bool setPayload(const QByteArray &) override; bool setPayload(const QByteArray&) override;
QByteArray getPayload() const override; QByteArray getPayload() const override;
static constexpr int s_payloadSize = 3; static constexpr int s_payloadSize = 3;
unsigned short getEquipmentNumber() const unsigned short getEquipmentNumber() const
{ {
return m_equipmentNumber; return m_equipmentNumber;
} }
void setEquipmentNumber(quint16 equipmentNumber) { m_equipmentNumber = equipmentNumber; }
private: void setEquipmentNumber(quint16 equipmentNumber)
unsigned short m_equipmentNumber = 0; {
m_equipmentNumber = equipmentNumber;
}
private:
unsigned short m_equipmentNumber = 0;
}; };
class SfmMsgSfmRestart_rx final : public SfmMessage_rx class SfmMsgSfmRestart_rx final : public SfmMessage_rx
{ {
public: public:
SfmMsgSfmRestart_rx() SfmMsgSfmRestart_rx() : SfmMessage_rx(SfmMessage::MsgId::SfmRestartNotification) {}
: SfmMessage_rx(SfmMessage::MsgId::SfmRestartNotification)
{} bool setPayload(const QByteArray& payload) override
bool setPayload(const QByteArray &payload) override {
{ return (payload.size() == 0);
return (payload.size() == 0); }
}
}; };
class SfmMsgTacticalState_rx final : public SfmMessage_rx class SfmMsgTacticalState_rx final : public SfmMessage_rx
{ {
public: public:
SfmMsgTacticalState_rx() SfmMsgTacticalState_rx() : SfmMessage_rx(SfmMessage::MsgId::TacticalState) {}
: SfmMessage_rx(SfmMessage::MsgId::TacticalState)
{}
static constexpr int s_payloadSize = 1; static constexpr int s_payloadSize = 1;
bool setPayload(const QByteArray &) override; bool setPayload(const QByteArray&) override;
unsigned char getTacticalState() const { return m_tacticalState; } unsigned char getTacticalState() const
{
return m_tacticalState;
}
private: private:
unsigned char m_tacticalState = 0; unsigned char m_tacticalState = 0;
}; };
class SfmMsgTetra_rx final : public SfmMessage_rx class SfmMsgTetra_rx final : public SfmMessage_rx
{ {
public: public:
SfmMsgTetra_rx() SfmMsgTetra_rx() : SfmMessage_rx(SfmMessage::MsgId::TetraMessage) {}
: SfmMessage_rx(SfmMessage::MsgId::TetraMessage)
{}
bool setPayload(const QByteArray &p_data) override; bool setPayload(const QByteArray& p_data) override;
uint8_t sendCounter() const { return m_sendCounter; } uint8_t sendCounter() const
bool isFragmented() const { return fragmentCount() > 1; } {
uint8_t fragmentNumber() const { return m_fragmentByte & 0x0f; } return m_sendCounter;
uint8_t fragmentCount() const { return (m_fragmentByte & 0xf0) >> 4;} }
const QByteArray &payload() const { return m_payload; } bool isFragmented() const
{
return fragmentCount() > 1;
}
private: uint8_t fragmentNumber() const
QByteArray m_payload; {
uint8_t m_sendCounter = 0; return m_fragmentByte & 0x0f;
uint8_t m_fragmentByte = 0; }
uint8_t fragmentCount() const
{
return (m_fragmentByte & 0xf0) >> 4;
}
const QByteArray& payload() const
{
return m_payload;
}
private:
QByteArray m_payload;
uint8_t m_sendCounter = 0;
uint8_t m_fragmentByte = 0;
}; };
class SfmMsgTetra_tx final : public SfmMessage_tx class SfmMsgTetra_tx final : public SfmMessage_tx
{ {
public: public:
explicit SfmMsgTetra_tx(uint8_t sendCounter, int fragmentCount, int fragmentNumber, const QByteArray &data) explicit SfmMsgTetra_tx(uint8_t sendCounter, int fragmentCount, int fragmentNumber, const QByteArray& data)
: SfmMessage_tx(SfmMessage::MsgId::TetraMessage) : SfmMessage_tx(SfmMessage::MsgId::TetraMessage)
{ {
m_data.reserve(data.size() + 2); m_data.reserve(data.size() + 2);
m_data += sendCounter; m_data += sendCounter;
m_data += fragmentByte(fragmentCount, fragmentNumber); m_data += fragmentByte(fragmentCount, fragmentNumber);
m_data += data; m_data += data;
} }
static char fragmentByte(int fragmentCount, int fragmentNumber) static char fragmentByte(int fragmentCount, int fragmentNumber)
{ {
Q_ASSERT(fragmentCount >= 0 && fragmentCount < 16); Q_ASSERT(fragmentCount >= 0 && fragmentCount < 16);
Q_ASSERT(fragmentNumber >= 0 && fragmentNumber <= fragmentCount); Q_ASSERT(fragmentNumber >= 0 && fragmentNumber <= fragmentCount);
return ((fragmentCount & 0x0f) << 4 ) | (fragmentNumber & 0x0f); return ((fragmentCount & 0x0f) << 4) | (fragmentNumber & 0x0f);
} }
QByteArray getPayload() const override { return m_data; }
private: QByteArray getPayload() const override
QByteArray m_data; {
return m_data;
}
private:
QByteArray m_data;
}; };
class Acknowledge_rx final : public SfmMessage_rx class Acknowledge_rx final : public SfmMessage_rx
{ {
public: public:
Acknowledge_rx() Acknowledge_rx() : SfmMessage_rx(SfmMessage::MsgId::Acknowledge) {}
: SfmMessage_rx(SfmMessage::MsgId::Acknowledge)
{}
static constexpr int s_payloadSize = 2; static constexpr int s_payloadSize = 2;
bool setPayload(const QByteArray &p_data) override; bool setPayload(const QByteArray& p_data) override;
uint8_t recvCounter() const { return m_recvCounter; }
bool isOk() const { return m_ackState == 0; } uint8_t recvCounter() const
bool isCrcError() const { return (m_ackState & 0x20) == 0x20; } {
bool isFragmentError() const { return (m_ackState & 0x10) == 0x10; } return m_recvCounter;
uint8_t missingFragment() const { return (m_ackState & 0x0f)!= 0; } }
private:
uint8_t m_recvCounter = 0; bool isOk() const
uint8_t m_ackState = 0; {
return m_ackState == 0;
}
bool isCrcError() const
{
return (m_ackState & 0x20) == 0x20;
}
bool isFragmentError() const
{
return (m_ackState & 0x10) == 0x10;
}
uint8_t missingFragment() const
{
return (m_ackState & 0x0f) != 0;
}
private:
uint8_t m_recvCounter = 0;
uint8_t m_ackState = 0;
}; };
class Acknowledge_tx final : public SfmMessage_tx class Acknowledge_tx final : public SfmMessage_tx
{ {
public: public:
explicit Acknowledge_tx() explicit Acknowledge_tx() : SfmMessage_tx(SfmMessage::MsgId::Acknowledge) {}
: SfmMessage_tx(SfmMessage::MsgId::Acknowledge)
{}
QByteArray getPayload() const override; QByteArray getPayload() const override;
void setRecvCounter(uint8_t recvCounter) { m_recvCounter = recvCounter; } void setRecvCounter(uint8_t recvCounter)
void setCrcError() { m_ackState |= 0x20; } {
void setFragmentError(uint8_t missingFrag) { m_ackState |= (0x10 | (0x0f & missingFrag)); } m_recvCounter = recvCounter;
private: }
uint8_t m_recvCounter = 0;
uint8_t m_ackState = 0; void setCrcError()
{
m_ackState |= 0x20;
}
void setFragmentError(uint8_t missingFrag)
{
m_ackState |= (0x10 | (0x0f & missingFrag));
}
private:
uint8_t m_recvCounter = 0;
uint8_t m_ackState = 0;
}; };
class SfmMsgLicenseState_rx final : public SfmMessage_rx class SfmMsgLicenseState_rx final : public SfmMessage_rx
{ {
public: public:
SfmMsgLicenseState_rx() SfmMsgLicenseState_rx() : SfmMessage_rx(SfmMessage::MsgId::LicenseState) {}
: SfmMessage_rx(SfmMessage::MsgId::LicenseState)
{}
static constexpr int s_payloadSize = 1; static constexpr int s_payloadSize = 1;
bool setPayload(const QByteArray &p_data) override; bool setPayload(const QByteArray& p_data) override;
bool isLicensed() const { return m_isLicensed; }
private: bool isLicensed() const
bool m_isLicensed = false; {
return m_isLicensed;
}
private:
bool m_isLicensed = false;
}; };
} } // namespace WirelessLocationSystem
@@ -18,7 +18,9 @@ ADD_SUBDIRECTORY(Evaluations)
ADD_SUBDIRECTORY(ExerciseManagement) ADD_SUBDIRECTORY(ExerciseManagement)
ADD_SUBDIRECTORY(ExerciseEventManagement) ADD_SUBDIRECTORY(ExerciseEventManagement)
ADD_SUBDIRECTORY(FileManagement) ADD_SUBDIRECTORY(FileManagement)
ADD_SUBDIRECTORY(FilterManagement) IF(BUILD_FILTERMANAGEMENT)
ADD_SUBDIRECTORY(FilterManagement)
ENDIF()
ADD_SUBDIRECTORY(GuezIedManagement) ADD_SUBDIRECTORY(GuezIedManagement)
ADD_SUBDIRECTORY(GuezMinelayerProcessing) ADD_SUBDIRECTORY(GuezMinelayerProcessing)
IF(BUILD_RTI) IF(BUILD_RTI)
File diff suppressed because it is too large. Load diff
@@ -595,6 +595,10 @@ protected:
static void setDestISSI_Internal(QByteArray &data, const uint32_t issi); static void setDestISSI_Internal(QByteArray &data, const uint32_t issi);
private: private:
/**
* The logger object
*/
NGL::INGLLogger &m_logger;
}; };
} }
File diff suppressed because it is too large. Load diff
@@ -19,7 +19,7 @@ SET(NGLLogger_HDRS
ADD_DEFINITIONS(-DBUILDING_NGLLOGGER) ADD_DEFINITIONS(-DBUILDING_NGLLOGGER)
NGL_ADD_LIBRARY2(ALL NGLLogger SHARED ${NGLLogger_SRCS} ${NGLLogger_HDRS}) NGL_ADD_LIBRARY2(ALL NGLLogger SHARED ${NGLLogger_SRCS} ${NGLLogger_HDRS})
NGL_TARGET_INCLUDE_DIRECTORIES(NGLLogger NGL_TARGET_INCLUDE_DIRECTORIES(NGLLogger
INTERFACE PUBLIC
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
+172 -187
View File
@@ -1,59 +1,56 @@
/** /**
* Logger interface * Logger interface
* $Id$ * $Id$
* $HeadURL$ * $HeadURL$
* $Author$ * $Author$
*/ */
#pragma once #pragma once
#include <string> #include <QList>
#include <sstream>
#include <QString>
#include <QPointF> #include <QPointF>
#include <QSize>
#include <QRect> #include <QRect>
#include <QRectF> #include <QRectF>
#include <QList> #include <QSize>
#include "ngllogger_export.h" #include <QString>
#include <ngllogger_export.h>
#include <sstream>
#include <string>
namespace NGL namespace NGL
{ {
class INGLLogger; class INGLLogger;
// keep in sync with log4qt/level.h // keep in sync with log4qt/level.h
enum class LogLevel enum class LogLevel {
{ Undefined = 0,
Undefined = 0, Trace = 64,
Trace = 64, Debug = 96,
Debug = 96, Info = 128,
Info = 128, Warning = 150,
Warning = 150, Error = 182,
Error = 182, Fatal = 214,
Fatal = 214,
}; };
class LogStreamHelper class LogStreamHelper
{ {
public: public:
inline LogStreamHelper(INGLLogger &logger, LogLevel level, const char *const file, int line, const char *const function) inline LogStreamHelper(INGLLogger& logger, LogLevel level, const char* const file, int line,
: m_logger(logger) const char* const function)
, m_level(level) : m_logger(logger), m_level(level), m_line(line), m_file(file), m_func(function)
, m_line(line) {
, m_file(file) }
, m_func(function)
{}
inline ~LogStreamHelper(); // after INGLLogger class definition
template<typename T> inline ~LogStreamHelper(); // after INGLLogger class definition
inline LogStreamHelper &operator<<(const T &val);
private: template <typename T> inline LogStreamHelper& operator<<(const T& val);
std::ostringstream m_buffer;
NGL::INGLLogger &m_logger; private:
const LogLevel m_level; std::ostringstream m_buffer;
const int m_line; NGL::INGLLogger& m_logger;
const char *const m_file; const LogLevel m_level;
const char *const m_func; const int m_line;
const char* const m_file;
const char* const m_func;
}; };
// Interface class for source code logging. // Interface class for source code logging.
@@ -64,58 +61,64 @@ private:
// information on logger-hierarchies, logging-levels, and configuration files. // information on logger-hierarchies, logging-levels, and configuration files.
class INGLLogger class INGLLogger
{ {
public: public:
INGLLogger(const INGLLogger &) = delete; INGLLogger(const INGLLogger&) = delete;
INGLLogger &operator=(const INGLLogger &) = delete; INGLLogger& operator=(const INGLLogger&) = delete;
INGLLogger() = default; INGLLogger() = default;
virtual ~INGLLogger() = default; virtual ~INGLLogger() = default;
using String = std::string; using String = std::string;
// Creates an instance of an INGLLogger interface. The fullqualifiedname is // Creates an instance of an INGLLogger interface. The fullqualifiedname is
// a dottet sequence (i.e. "NGL.thisandthat.mylogger"). The same name will // a dottet sequence (i.e. "NGL.thisandthat.mylogger"). The same name will
// always return the same interface-instance. It is not required to create // always return the same interface-instance. It is not required to create
// the parent nodes. // the parent nodes.
virtual INGLLogger &getNGLLogger(const char *fullqualifiedname) = 0; virtual INGLLogger& getNGLLogger(const char* fullqualifiedname) = 0;
virtual INGLLogger &getNGLLogger(const std::string &fullqualifiedname) = 0; virtual INGLLogger& getNGLLogger(const std::string& fullqualifiedname) = 0;
// True if this level is enabled.
virtual bool isTraceEnabled() const = 0;
virtual bool isDebugEnabled() const = 0;
virtual bool isInfoEnabled() const = 0;
virtual bool isWarningEnabled() const = 0;
virtual bool isErrorEnabled() const = 0;
virtual bool isFatalEnabled() const = 0;
virtual bool isLevelEnabled(LogLevel level) const = 0;
// True if this level is enabled. // Submit a LOG message.
virtual bool isTraceEnabled() const = 0; // Use __FILE__ and __NAME__ macros.
virtual bool isDebugEnabled() const = 0; virtual void log(LogLevel level, const INGLLogger::String& message, const char* file = nullptr, int line = -1,
virtual bool isInfoEnabled() const = 0; const char* function = nullptr) = 0;
virtual bool isWarningEnabled() const = 0;
virtual bool isErrorEnabled() const = 0;
virtual bool isFatalEnabled() const = 0;
virtual bool isLevelEnabled(LogLevel level) const = 0;
// Submit a LOG message. // Submit an TRACE message.
// Use __FILE__ and __NAME__ macros. virtual void logTrace(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
virtual void log(LogLevel level, const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0; const char* function = nullptr) = 0;
// Submit an DEBUG message.
virtual void logDebug(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit an INFO message.
virtual void logInfo(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit a WARNING message.
virtual void logWarning(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit an ERROR message.
virtual void logError(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit a FATAL message.
virtual void logFatal(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit an TRACE message. // Writes a startup message into the logfile
virtual void logTrace(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0; virtual void logStartup(const char* file, int line, const char* function = nullptr) = 0;
// Submit an DEBUG message. // Writes a shutdown message into the logfile
virtual void logDebug(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0; virtual void logShutdown(const char* file, int line, const char* function = nullptr) = 0;
// Submit an INFO message.
virtual void logInfo(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Submit a WARNING message.
virtual void logWarning(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Submit an ERROR message.
virtual void logError(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Submit a FATAL message.
virtual void logFatal(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Writes a startup message into the logfile // Get this loggers fullqualified name.
virtual void logStartup(const char *file, int line, const char *function = nullptr) = 0; virtual std::string getLoggerName() const = 0;
// Writes a shutdown message into the logfile
virtual void logShutdown(const char *file, int line, const char *function = nullptr) = 0;
// Get this loggers fullqualified name. virtual void setNoSpace(bool bNoSpace) = 0;
virtual std::string getLoggerName() const = 0; virtual bool noSpace() const = 0;
virtual void setNoSpace(bool bNoSpace) = 0;
virtual bool noSpace() const = 0;
}; };
// //
@@ -123,112 +126,90 @@ public:
// //
inline LogStreamHelper::~LogStreamHelper() inline LogStreamHelper::~LogStreamHelper()
{ {
m_logger.log(m_level, m_buffer.str(), m_file, m_line, m_func); m_logger.log(m_level, m_buffer.str(), m_file, m_line, m_func);
} }
template<typename T> template <typename T> inline LogStreamHelper& LogStreamHelper::operator<<(const T& val)
inline LogStreamHelper &LogStreamHelper::operator<<(const T &val)
{ {
m_buffer << val; m_buffer << val;
if (!m_logger.noSpace()) if (!m_logger.noSpace())
m_buffer << " "; m_buffer << " ";
return *this; return *this;
} }
} // namespace NGL
} //namespace NGL inline std::ostream& operator<<(std::ostream& stream, const QByteArray& str)
inline std::ostream &operator<<(std::ostream &stream, const QByteArray &str)
{ {
stream << std::string(str.data(), str.size()); stream << std::string(str.data(), str.size());
return stream; return stream;
} }
// //
// operator to ease logging (at least via NglLogging) // operator to ease logging (at least via NglLogging)
// //
inline std::ostream &operator<<(std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QPointF& value)
const QPointF &value)
{ {
stream << "QPointF(" << QString::number(value.x(), 'f', 6).toStdString() << "#" << QString::number(value.y(), 'f', 6).toStdString() << ")"; stream << "QPointF(" << QString::number(value.x(), 'f', 6).toStdString() << "#"
return stream; << QString::number(value.y(), 'f', 6).toStdString() << ")";
return stream;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline std::ostream &operator<< (std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QPoint& value)
const QPoint &value)
{ {
stream << "QPoint(" << value.x() << "#" << value.y() << ")"; stream << "QPoint(" << value.x() << "#" << value.y() << ")";
return stream; return stream;
} }
inline std::ostream &operator<< (std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QSize& value)
const QSize &value)
{ {
stream << "QSize(w=" << value.width() << ";h=" << value.height() << ")"; stream << "QSize(w=" << value.width() << ";h=" << value.height() << ")";
return stream; return stream;
}
inline std::ostream &operator<< (std::ostream &stream,
const QSizeF &value)
{
stream << "QSize(w="
<< QString::number(value.width(), 'f', 6).toStdString() << ";h="
<< QString::number(value.height(), 'f', 6).toStdString()
<< ")";
return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QSizeF& value)
inline std::ostream &operator<< (std::ostream &stream,
const QRect &value)
{ {
stream << "QRect(center=" << value.center() stream << "QSize(w=" << QString::number(value.width(), 'f', 6).toStdString()
<< " w=" << value.width() << ";h=" << QString::number(value.height(), 'f', 6).toStdString() << ")";
<< ";h=" << value.height() return stream;
<< " bottomLeft=" << value.bottomLeft()
<< " topRight=" << value.topRight()
<< ")";
return stream;
} }
inline std::ostream &operator<< (std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QRect& value)
const QRectF &value)
{ {
stream << "QRectF(center=" << value.center() stream << "QRect(center=" << value.center() << " w=" << value.width() << ";h=" << value.height()
<< " w=" << QString::number(value.width(), 'f', 3).toStdString() << " bottomLeft=" << value.bottomLeft() << " topRight=" << value.topRight() << ")";
<< ";h=" << QString::number(value.height(), 'f', 3).toStdString() return stream;
<< " bottomLeft=" << value.bottomLeft()
<< " topRight=" << value.topRight()
<< ")";
return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QRectF& value)
inline std::ostream &operator<< (std::ostream &stream,
const QList<int> &value)
{ {
stream << "QList<int>(" << value.size() << "): "; stream << "QRectF(center=" << value.center() << " w=" << QString::number(value.width(), 'f', 3).toStdString()
for (int i : value) << ";h=" << QString::number(value.height(), 'f', 3).toStdString() << " bottomLeft=" << value.bottomLeft()
stream << i << ";"; << " topRight=" << value.topRight() << ")";
return stream; return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QList<int>& value)
inline std::ostream &operator<< (std::ostream &stream,
const QList<QPointF> &value)
{ {
stream << "QList<QPointF>(" << value.size() << "): "; stream << "QList<int>(" << value.size() << "): ";
for (const QPointF &item : value) for (int i : value)
stream << item << ";"; stream << i << ";";
return stream; return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QList<QPointF>& value)
inline std::ostream &operator<<(std::ostream &stream, const QString &str)
{ {
return stream << str.toUtf8(); stream << "QList<QPointF>(" << value.size() << "): ";
for (const QPointF& item : value)
stream << item << ";";
return stream;
}
inline std::ostream& operator<<(std::ostream& stream, const QString& str)
{
return stream << str.toUtf8();
} }
namespace NGL namespace NGL
@@ -236,15 +217,12 @@ namespace NGL
namespace NGLLoggerHelper namespace NGLLoggerHelper
{ {
NGLLOGGER_EXPORT void hexDumpHelper(NGL::INGLLogger &logger, NGLLOGGER_EXPORT void hexDumpHelper(NGL::INGLLogger& logger, NGL::LogLevel level, const void* a_data,
NGL::LogLevel level,
const void *a_data,
const unsigned int a_size); const unsigned int a_size);
inline void hexDumpHelper(NGL::INGLLogger &logger,
NGL::LogLevel level, inline void hexDumpHelper(NGL::INGLLogger& logger, NGL::LogLevel level, const QByteArray& data)
const QByteArray &data)
{ {
return hexDumpHelper(logger, level, data.data(), data.size()); return hexDumpHelper(logger, level, data.data(), data.size());
} }
} // namespace NGLLoggerHelper } // namespace NGLLoggerHelper
@@ -260,41 +238,46 @@ NGLLOGGER_EXPORT std::string getMemoryData();
#define LOGFUNCTION Q_FUNC_INFO #define LOGFUNCTION Q_FUNC_INFO
// log this output every time, no matter what log level is enabled // log this output every time, no matter what log level is enabled
#define NOTICE_LOG(logger) \ #define NOTICE_LOG(logger) NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__, __LINE__, Q_FUNC_INFO)
NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO)
#ifdef LTS_DEBUG #ifdef LTS_DEBUG
#define TRACE_LOG(logger) \ #define TRACE_LOG(logger) \
for (bool log_level_enabled = (logger).isTraceEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isTraceEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__, __LINE__, Q_FUNC_INFO)
#else #else
#define TRACE_LOG(logger) \ #define TRACE_LOG(logger) \
for ( ; false; ) \ for (; false;) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__, __LINE__, Q_FUNC_INFO)
#endif #endif
#define DEBUG_LOG(logger) \ #define DEBUG_LOG(logger) \
for (bool log_level_enabled = (logger).isDebugEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isDebugEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Debug, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Debug, __FILE__, __LINE__, Q_FUNC_INFO)
#define INFO_LOG(logger) \ #define INFO_LOG(logger) \
for (bool log_level_enabled = (logger).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__, __LINE__, Q_FUNC_INFO)
#define WARNING_LOG(logger) \ #define WARNING_LOG(logger) \
for (bool log_level_enabled = (logger).isWarningEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isWarningEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Warning, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Warning, __FILE__, __LINE__, Q_FUNC_INFO)
#define ERROR_LOG(logger) \ #define ERROR_LOG(logger) \
for (bool log_level_enabled = (logger).isErrorEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isErrorEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Error, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Error, __FILE__, __LINE__, Q_FUNC_INFO)
#define FATAL_LOG(logger) \ #define FATAL_LOG(logger) \
for (bool log_level_enabled = (logger).isFatalEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isFatalEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Fatal, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Fatal, __FILE__, __LINE__, Q_FUNC_INFO)
#define STARTUP_LOG(logger) { (logger).logStartup(__FILE__, __LINE__, Q_FUNC_INFO); } #define STARTUP_LOG(logger) \
#define SHUTDOWN_LOG(logger) { (logger).logShutdown(__FILE__, __LINE__, Q_FUNC_INFO); } { \
(logger).logStartup(__FILE__, __LINE__, Q_FUNC_INFO); \
}
#define SHUTDOWN_LOG(logger) \
{ \
(logger).logShutdown(__FILE__, __LINE__, Q_FUNC_INFO); \
}
//============================================================================== //==============================================================================
@@ -303,8 +286,10 @@ NGLLOGGER_EXPORT std::string getMemoryData();
// do something nasty // do something nasty
// MEMORY_LOG() << " after something nasty"; // MEMORY_LOG() << " after something nasty";
#define MEMORY_LOG() \ #define MEMORY_LOG() \
for (bool log_level_enabled = (NGL::getMemoryLogger()).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (NGL::getMemoryLogger()).isInfoEnabled(); log_level_enabled; \
NGL::LogStreamHelper(NGL::getMemoryLogger(), NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO) << NGL::getMemoryData() log_level_enabled = false) \
NGL::LogStreamHelper(NGL::getMemoryLogger(), NGL::LogLevel::Info, __FILE__, __LINE__, Q_FUNC_INFO) \
<< NGL::getMemoryData()
//============================================================================== //==============================================================================
+17 -31
View File
@@ -1,11 +1,10 @@
#ifndef NGLLOGGERBOOTSTRAP_H #ifndef NGLLOGGERBOOTSTRAP_H
#define NGLLOGGERBOOTSTRAP_H #define NGLLOGGERBOOTSTRAP_H
#include <NGLLogger/INGLLogger.h> #include <NGLLogger/INGLLogger.h>
#include "ngllogger_export.h" #include <ngllogger_export.h>
namespace NGL namespace NGL
{ {
@@ -14,46 +13,33 @@ namespace NGLLoggerBootstrap
{ {
class AlreadyCreatedError final : public std::exception class AlreadyCreatedError final : public std::exception
{ {
const char* what() const noexcept override const char* what() const noexcept override
{ {
return "NGLLogger rootlogger already created!"; return "NGLLogger rootlogger already created!";
} }
}; };
class NotCreatedError final : public std::exception class NotCreatedError final : public std::exception
{ {
const char* what() const noexcept override const char* what() const noexcept override
{ {
return "NGLLogger rootlogger not yet created!"; return "NGLLogger rootlogger not yet created!";
} }
}; };
NGLLOGGER_EXPORT INGLLogger& getNGLRootLogger();
NGLLOGGER_EXPORT INGLLogger& createNGLRootLogger(const QString& configfilename, bool ignorealreadycreated,
const QString& logOutputName = QString(), bool quiet = false);
inline INGLLogger& createNGLRootLogger(const char* configfilename, bool ignorealreadycreated,
NGLLOGGER_EXPORT INGLLogger &getNGLRootLogger(); const QString& logOutputName = QString())
NGLLOGGER_EXPORT INGLLogger &createNGLRootLogger(const QString &configfilename,
bool ignorealreadycreated,
const QString &logOutputName = QString(),
bool quiet = false);
inline INGLLogger &createNGLRootLogger(const char *configfilename,
bool ignorealreadycreated,
const QString &logOutputName = QString())
{ {
return createNGLRootLogger(QString::fromUtf8(configfilename), ignorealreadycreated, logOutputName); return createNGLRootLogger(QString::fromUtf8(configfilename), ignorealreadycreated, logOutputName);
} }
} } // namespace NGLLoggerBootstrap
}
} // namespace NGL
#endif #endif
+242 -261
View File
@@ -1,360 +1,341 @@
#include "nglcomp_bzip2iodevice.h" #include "nglcomp_bzip2iodevice.h"
#include <QIODevice> #include <QIODevice>
#include <QString> #include <QString>
#include <bzlib.h> #include <bzlib.h>
class BZip2IODevice::Private class BZip2IODevice::Private
{ {
public: public:
Private(BZip2IODevice *parent_, QIODevice *dev, int bs) Private(BZip2IODevice* parent_, QIODevice* dev, int bs)
: parent(parent_) : parent(parent_), device(dev), iCurPos(0), iMaxBufSize(1024 * 1024), blocksize(bs), initialized(false),
, device(dev) decomressStreamEnd(false)
, iCurPos(0) {
, iMaxBufSize(1024 * 1024) buffer.resize(iMaxBufSize);
, blocksize(bs) }
, initialized(false)
, decomressStreamEnd(false)
{
buffer.resize(iMaxBufSize);
}
bool initializeCompress(); bool initializeCompress();
qint64 doCompress(const char *in, qint64 iMaxLen); qint64 doCompress(const char* in, qint64 iMaxLen);
bool finishCompress(); bool finishCompress();
bool initializeDecompress(); bool initializeDecompress();
qint64 doDecompress(char *out, qint64 iMaxLen); qint64 doDecompress(char* out, qint64 iMaxLen);
bool finishDecompress(); bool finishDecompress();
static QString bzipError2String(int errCode); static QString bzipError2String(int errCode);
QAtomicInt aborted { 0 }; QAtomicInt aborted{0};
BZip2IODevice *parent; BZip2IODevice* parent;
QIODevice *device; QIODevice* device;
unsigned int iCurPos; unsigned int iCurPos;
unsigned int iMaxBufSize; unsigned int iMaxBufSize;
unsigned int blocksize; unsigned int blocksize;
bool initialized; bool initialized;
bool decomressStreamEnd; bool decomressStreamEnd;
QByteArray buffer; QByteArray buffer;
bz_stream stream; bz_stream stream;
}; };
bool BZip2IODevice::Private::initializeCompress() bool BZip2IODevice::Private::initializeCompress()
{ {
if (initialized) if (initialized)
return true; return true;
memset(&stream, 0, sizeof(stream)); memset(&stream, 0, sizeof(stream));
int blockSize = (blocksize > 0 && blocksize < 10) ? blocksize : 10; int blockSize = (blocksize > 0 && blocksize < 10) ? blocksize : 10;
int ret = BZ2_bzCompressInit(&stream, blockSize, 0, 0); int ret = BZ2_bzCompressInit(&stream, blockSize, 0, 0);
if (ret != BZ_OK) if (ret != BZ_OK)
{ {
parent->setErrorString(QStringLiteral("Error initializing bzip2 %1").arg(bzipError2String(ret))); parent->setErrorString(QStringLiteral("Error initializing bzip2 %1").arg(bzipError2String(ret)));
initialized = false; initialized = false;
} }
else else
initialized = true; initialized = true;
return initialized; return initialized;
} }
qint64 BZip2IODevice::Private::doCompress(const char *in, qint64 iMaxLen) qint64 BZip2IODevice::Private::doCompress(const char* in, qint64 iMaxLen)
{ {
if (!initialized) if (!initialized)
{
if (parent->errorString().isEmpty())
parent->setErrorString(QLatin1String("Internal Error - bzip not initialized"));
finishCompress();
return -1;
}
if (iMaxLen > 2 * 1024 * 1024 * 1024LL)
{
finishCompress();
parent->setErrorString(QLatin1String("Currently can't handle more than 2GB!"));
return -1;
}
stream.next_in = const_cast<char *>(in);
stream.avail_in = iMaxLen;
do
{
if (aborted) return 0;
stream.next_out = buffer.data();
stream.avail_out = buffer.size();
const int ret = BZ2_bzCompress(&stream, BZ_RUN);
if (ret != BZ_RUN_OK)
{ {
finishCompress(); if (parent->errorString().isEmpty())
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret))); parent->setErrorString(QLatin1String("Internal Error - bzip not initialized"));
return -1;
}
int iBytesToWrite = buffer.size() - stream.avail_out;
if (iBytesToWrite)
{
if (device->write(buffer.constData(), iBytesToWrite) != iBytesToWrite)
{
finishCompress(); finishCompress();
parent->setErrorString(QLatin1String("Error writing to QIODevice"));
return -1; return -1;
}
} }
} if (iMaxLen > 2 * 1024 * 1024 * 1024LL)
while (stream.avail_in != 0); {
finishCompress();
parent->setErrorString(QLatin1String("Currently can't handle more than 2GB!"));
return -1;
}
return stream.next_in - in; stream.next_in = const_cast<char*>(in);
stream.avail_in = iMaxLen;
do
{
if (aborted)
return 0;
stream.next_out = buffer.data();
stream.avail_out = buffer.size();
const int ret = BZ2_bzCompress(&stream, BZ_RUN);
if (ret != BZ_RUN_OK)
{
finishCompress();
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret)));
return -1;
}
int iBytesToWrite = buffer.size() - stream.avail_out;
if (iBytesToWrite)
{
if (device->write(buffer.constData(), iBytesToWrite) != iBytesToWrite)
{
finishCompress();
parent->setErrorString(QLatin1String("Error writing to QIODevice"));
return -1;
}
}
} while (stream.avail_in != 0);
return stream.next_in - in;
} }
bool BZip2IODevice::Private::finishCompress() bool BZip2IODevice::Private::finishCompress()
{ {
if (!initialized || aborted) if (!initialized || aborted)
return true;
int ret = -1;
do
{
stream.next_out = buffer.data();
stream.avail_out = buffer.size();
ret = BZ2_bzCompress(&stream, BZ_FINISH);
if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
{
finishCompress();
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret)));
return false;
}
int iBytesToWrite = buffer.size() - stream.avail_out;
if (device->write(buffer.constData(), iBytesToWrite) != iBytesToWrite)
{
finishCompress();
parent->setErrorString(QLatin1String("Error writing to QIODevice"));
return false;
}
} while (ret != BZ_STREAM_END);
BZ2_bzCompressEnd(&stream);
initialized = false;
return true; return true;
int ret = -1;
do
{
stream.next_out = buffer.data();
stream.avail_out = buffer.size();
ret = BZ2_bzCompress(&stream, BZ_FINISH);
if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
{
finishCompress();
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret)));
return false;
}
int iBytesToWrite = buffer.size() - stream.avail_out;
if (device->write(buffer.constData(), iBytesToWrite) != iBytesToWrite)
{
finishCompress();
parent->setErrorString(QLatin1String("Error writing to QIODevice"));
return false;
}
}
while (ret != BZ_STREAM_END);
BZ2_bzCompressEnd(&stream);
initialized = false;
return true;
} }
bool BZip2IODevice::Private::initializeDecompress() bool BZip2IODevice::Private::initializeDecompress()
{ {
if (initialized) if (initialized)
return true; return true;
memset(&stream, 0, sizeof(stream)); memset(&stream, 0, sizeof(stream));
int ret = BZ2_bzDecompressInit(&stream, 0, 0); int ret = BZ2_bzDecompressInit(&stream, 0, 0);
if (ret != BZ_OK) if (ret != BZ_OK)
{ {
parent->setErrorString(QStringLiteral("Error initializing bzip2: %1").arg(bzipError2String(ret))); parent->setErrorString(QStringLiteral("Error initializing bzip2: %1").arg(bzipError2String(ret)));
initialized = false; initialized = false;
} }
else else
initialized = true; initialized = true;
decomressStreamEnd = false; decomressStreamEnd = false;
return initialized; return initialized;
} }
qint64 BZip2IODevice::Private::doDecompress(char *out, qint64 iMaxLen) qint64 BZip2IODevice::Private::doDecompress(char* out, qint64 iMaxLen)
{ {
int ret = -1; int ret = -1;
if (!initialized) if (!initialized)
{
if (parent->errorString().isEmpty())
parent->setErrorString(QLatin1String("Internal Error - bzip not initialized"));
finishDecompress();
return -1;
}
if (decomressStreamEnd)
return 0;
if (iMaxLen > 2 * 1024 * 1024 * 1024LL)
{
finishCompress();
parent->setErrorString(QLatin1String("Currently can't handle more than 2GB!"));
return -1;
}
stream.next_out = out;
stream.avail_out = iMaxLen;
do
{
if (ret != BZ_STREAM_END && stream.avail_in == 0)
{ {
qint64 iReadCnt = device->read(buffer.data(), buffer.size()); if (parent->errorString().isEmpty())
if (iReadCnt <= 0) parent->setErrorString(QLatin1String("Internal Error - bzip not initialized"));
finishDecompress();
return -1;
}
if (decomressStreamEnd)
return 0;
if (iMaxLen > 2 * 1024 * 1024 * 1024LL)
{
finishCompress();
parent->setErrorString(QLatin1String("Currently can't handle more than 2GB!"));
return -1; return -1;
stream.next_in = buffer.data();
stream.avail_in = iReadCnt;
} }
ret = BZ2_bzDecompress(&stream); stream.next_out = out;
if (ret != BZ_OK && ret != BZ_STREAM_END) stream.avail_out = iMaxLen;
do
{ {
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret))); if (ret != BZ_STREAM_END && stream.avail_in == 0)
finishDecompress(); {
return -1; qint64 iReadCnt = device->read(buffer.data(), buffer.size());
} if (iReadCnt <= 0)
} return -1;
while (stream.avail_out != 0 && ret != BZ_STREAM_END); stream.next_in = buffer.data();
decomressStreamEnd = (ret == BZ_STREAM_END); stream.avail_in = iReadCnt;
return stream.next_out - out; }
ret = BZ2_bzDecompress(&stream);
if (ret != BZ_OK && ret != BZ_STREAM_END)
{
parent->setErrorString(QStringLiteral("Error executing BZ2_bzCompress: %1").arg(bzipError2String(ret)));
finishDecompress();
return -1;
}
} while (stream.avail_out != 0 && ret != BZ_STREAM_END);
decomressStreamEnd = (ret == BZ_STREAM_END);
return stream.next_out - out;
} }
bool BZip2IODevice::Private::finishDecompress() bool BZip2IODevice::Private::finishDecompress()
{ {
if (!initialized) if (!initialized)
return true; return true;
BZ2_bzDecompressEnd(&stream); BZ2_bzDecompressEnd(&stream);
initialized = false; initialized = false;
return true; return true;
} }
QString BZip2IODevice::Private::bzipError2String(int errCode) QString BZip2IODevice::Private::bzipError2String(int errCode)
{ {
switch (errCode) switch (errCode)
{ {
case BZ_SEQUENCE_ERROR: case BZ_SEQUENCE_ERROR:
return QLatin1String("Sequence error"); return QLatin1String("Sequence error");
case BZ_PARAM_ERROR: case BZ_PARAM_ERROR:
return QLatin1String("Parameter not correct"); return QLatin1String("Parameter not correct");
case BZ_MEM_ERROR: case BZ_MEM_ERROR:
return QLatin1String("Memory allocation error"); return QLatin1String("Memory allocation error");
case BZ_DATA_ERROR: case BZ_DATA_ERROR:
return QLatin1String("Invalid input data"); return QLatin1String("Invalid input data");
case BZ_DATA_ERROR_MAGIC: case BZ_DATA_ERROR_MAGIC:
return QLatin1String("Not a bzip2 file"); return QLatin1String("Not a bzip2 file");
case BZ_IO_ERROR: case BZ_IO_ERROR:
return QLatin1String("I/O error"); return QLatin1String("I/O error");
case BZ_UNEXPECTED_EOF: case BZ_UNEXPECTED_EOF:
return QLatin1String("Unexpected end of file"); return QLatin1String("Unexpected end of file");
case BZ_OUTBUFF_FULL: case BZ_OUTBUFF_FULL:
return QLatin1String("Output buffer full"); return QLatin1String("Output buffer full");
case BZ_CONFIG_ERROR: case BZ_CONFIG_ERROR:
return QLatin1String("Wrong config parameter"); return QLatin1String("Wrong config parameter");
}; };
return QString::number(errCode); return QString::number(errCode);
} }
BZip2IODevice::BZip2IODevice(QIODevice* dev, int blocksize) : d(new Private(this, dev, blocksize)) {}
BZip2IODevice::BZip2IODevice(QIODevice *dev, int blocksize)
: d(new Private(this, dev, blocksize))
{}
BZip2IODevice::~BZip2IODevice() BZip2IODevice::~BZip2IODevice()
{ {
close(); close();
delete d; delete d;
} }
void BZip2IODevice::setBufferSize(unsigned int size) void BZip2IODevice::setBufferSize(unsigned int size)
{ {
d->iMaxBufSize = size > 1024 ? size : 1024; d->iMaxBufSize = size > 1024 ? size : 1024;
d->buffer.resize(d->iMaxBufSize); d->buffer.resize(d->iMaxBufSize);
} }
void BZip2IODevice::setBlockSize(unsigned int size) void BZip2IODevice::setBlockSize(unsigned int size)
{ {
if (isOpen()) if (isOpen())
return; return;
d->blocksize = size; d->blocksize = size;
} }
bool BZip2IODevice::isSequential() const bool BZip2IODevice::isSequential() const
{ {
return true; return true;
} }
bool BZip2IODevice::open(OpenMode mode) bool BZip2IODevice::open(OpenMode mode)
{ {
if ((mode & QIODevice::ReadWrite) == 0) if ((mode & QIODevice::ReadWrite) == 0)
{
setErrorString(QStringLiteral("Unsupported OpenMode %1").arg(mode));
return false;
}
if ((mode & QIODevice::ReadWrite) == QIODevice::ReadWrite)
{
setErrorString(QLatin1String("Can't read and write simultaniously"));
return false;
}
if ((mode & QIODevice::ReadOnly) == QIODevice::ReadOnly)
{
if (!d->device)
{ {
setErrorString(QLatin1String("No QIODevice for reading available")); setErrorString(QStringLiteral("Unsupported OpenMode %1").arg(static_cast<int>(mode)));
return false; return false;
} }
if ((d->device->openMode() & QIODevice::ReadOnly) == 0) if ((mode & QIODevice::ReadWrite) == QIODevice::ReadWrite)
{ {
setErrorString(QLatin1String("QIODevice not opened for reading")); setErrorString(QLatin1String("Can't read and write simultaniously"));
return false; return false;
} }
if (!d->initializeDecompress()) if ((mode & QIODevice::ReadOnly) == QIODevice::ReadOnly)
return false;
}
else
{
if (!d->device)
{ {
setErrorString(QLatin1String("No QIODevice for writing available")); if (!d->device)
return false; {
setErrorString(QLatin1String("No QIODevice for reading available"));
return false;
}
if ((d->device->openMode() & QIODevice::ReadOnly) == 0)
{
setErrorString(QLatin1String("QIODevice not opened for reading"));
return false;
}
if (!d->initializeDecompress())
return false;
} }
if ((d->device->openMode() & QIODevice::WriteOnly) == 0) else
{ {
setErrorString(QLatin1String("QIODevice not opened for writing")); if (!d->device)
return false; {
setErrorString(QLatin1String("No QIODevice for writing available"));
return false;
}
if ((d->device->openMode() & QIODevice::WriteOnly) == 0)
{
setErrorString(QLatin1String("QIODevice not opened for writing"));
return false;
}
if (!d->initializeCompress())
return false;
} }
if (!d->initializeCompress()) setErrorString(QString());
return false; setOpenMode(mode);
} return QIODevice::open(mode);
setErrorString(QString());
setOpenMode(mode);
return QIODevice::open(mode);
} }
void BZip2IODevice::abort() void BZip2IODevice::abort()
{ {
d->aborted = 1; d->aborted = 1;
} }
void BZip2IODevice::close() void BZip2IODevice::close()
{ {
if (!isOpen()) if (!isOpen())
return; return;
if ((openMode() & QIODevice::ReadOnly) == QIODevice::ReadOnly) if ((openMode() & QIODevice::ReadOnly) == QIODevice::ReadOnly)
d->finishDecompress(); d->finishDecompress();
else else
d->finishCompress(); d->finishCompress();
QIODevice::close(); QIODevice::close();
} }
bool BZip2IODevice::atEnd() const bool BZip2IODevice::atEnd() const
{ {
if (!d->device) if (!d->device)
return true; return true;
return d->device->atEnd() && d->decomressStreamEnd && QIODevice::atEnd(); return d->device->atEnd() && d->decomressStreamEnd && QIODevice::atEnd();
} }
qint64 BZip2IODevice::readData(char *data, qint64 maxSize) qint64 BZip2IODevice::readData(char* data, qint64 maxSize)
{ {
return d->doDecompress(data, maxSize); return d->doDecompress(data, maxSize);
} }
qint64 BZip2IODevice::writeData(const char *data, qint64 maxSize) qint64 BZip2IODevice::writeData(const char* data, qint64 maxSize)
{ {
return d->doCompress(data, maxSize); return d->doCompress(data, maxSize);
} }
+390 -430
View File
@@ -1,569 +1,529 @@
#include "nglcomp_compress.h" #include "nglcomp_compress.h"
#include "nglcomp_bzip2iodevice.h" #include "nglcomp_bzip2iodevice.h"
#include "nglcomp_tarfilter.h" #include "nglcomp_tarfilter.h"
#include <NGLLogger/NGLLoggerBootstrap.h> #include <NGLLogger/NGLLoggerBootstrap.h>
#include <QBuffer> #include <QBuffer>
#include <QtConcurrent>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QIODevice> #include <QIODevice>
#include <QStringList> #include <QStringList>
#include <QtConcurrent>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <QDebug>
namespace NGL namespace NGL
{ {
Compress::Compress(QObject *parent) Compress::Compress(QObject* parent)
: QObject(parent) : QObject(parent), m_u2_memFiles(), m_aborted(0),
, m_u2_memFiles() m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("nglcompress"))
, m_aborted(0)
{ {
DEBUG_LOG(m_logger) << "c_tor"; DEBUG_LOG(m_logger) << "c_tor";
QTimer* t = new QTimer(this);
t->setInterval(1000);
connect(t, &QTimer::timeout, this, []() { qWarning() << "still alive ..."; });
t->start();
QTimer *t = new QTimer(this);
t->setInterval(1000);
connect(t, &QTimer::timeout, this, [](){qWarning() << "still alive ...";});
t->start();
} }
Compress::~Compress() Compress::~Compress()
{ {
qWarning() << "## COMPRESS DTOR!!!!"; qWarning() << "## COMPRESS DTOR!!!!";
DEBUG_LOG(m_logger) << "~";
DEBUG_LOG(m_logger) << "~"; abort();
m_future.waitForFinished();
abort(); DEBUG_LOG(m_logger) << "~ finished";
m_future.waitForFinished();
DEBUG_LOG(m_logger) << "~ finished";
} }
void Compress::abort() void Compress::abort()
{ {
DEBUG_LOG(m_logger) << "ABORT"; DEBUG_LOG(m_logger) << "ABORT";
m_aborted = 1; m_aborted = 1;
m_lastError = tr("Aborted"); m_lastError = tr("Aborted");
if (m_currentTarFilter != nullptr) if (m_currentTarFilter != nullptr)
{ {
DEBUG_LOG(m_logger) << "aborting tar"; DEBUG_LOG(m_logger) << "aborting tar";
m_currentTarFilter->abort(); m_currentTarFilter->abort();
} }
if (m_currentBzipDevice != nullptr) if (m_currentBzipDevice != nullptr)
{ {
DEBUG_LOG(m_logger) << "aborting bzip"; DEBUG_LOG(m_logger) << "aborting bzip";
m_currentBzipDevice->abort(); m_currentBzipDevice->abort();
} }
} }
void Compress::compress(QIODevice *out, void Compress::compress(QIODevice* out, const QString& filesRootDir, const QVector<FileInformations>& files,
const QString &filesRootDir, const QVector<FileInformations>& memFiles, const QString& destRootDir)
const QVector<FileInformations> &files,
const QVector<FileInformations> &memFiles,
const QString &destRootDir)
{ {
DEBUG_LOG(m_logger) << "compress #2"; DEBUG_LOG(m_logger) << "compress #2";
reset(); reset();
setupFutureWatcher(QtConcurrent::run([this, out, filesRootDir, files, memFiles, destRootDir]() { setupFutureWatcher(QtConcurrent::run([this, out, filesRootDir, files, memFiles, destRootDir]() {
return this->_compress(out, filesRootDir, files, memFiles, destRootDir); return this->_compress(out, filesRootDir, files, memFiles, destRootDir);
})); }));
} }
void Compress::compress(QIODevice *out, const QString &sourceDir, const QString &destRootDir) void Compress::compress(QIODevice* out, const QString& sourceDir, const QString& destRootDir)
{ {
DEBUG_LOG(m_logger) << "compress #1 source dir: " << sourceDir << ", destRootDir: " << destRootDir; DEBUG_LOG(m_logger) << "compress #1 source dir: " << sourceDir << ", destRootDir: " << destRootDir;
reset(); reset();
QVector<Compress::FileInformations> inFiles = directoryFileList(sourceDir, true); QVector<Compress::FileInformations> inFiles = directoryFileList(sourceDir, true);
int len = sourceDir.length();
if (!sourceDir.endsWith(QLatin1Char('/')))
len += 1;
for (auto& fi : inFiles)
{
fi.inputFileName = fi.inputFileName.mid(len);
fi.bAbsInputPath = false;
DEBUG_LOG(m_logger) << "fi: ifm = " << fi.inputFileName << ", abs = " << fi.bAbsInputPath;
}
int len = sourceDir.length(); DEBUG_LOG(m_logger) << "FI list size: " << inFiles.count();
if (!sourceDir.endsWith(QLatin1Char('/')))
len += 1;
for (auto &fi : inFiles)
{
fi.inputFileName = fi.inputFileName.mid(len);
fi.bAbsInputPath = false;
DEBUG_LOG(m_logger) << "fi: ifm = " << fi.inputFileName << ", abs = " << fi.bAbsInputPath;
}
DEBUG_LOG(m_logger) << "FI list size: " << inFiles.count(); compress(out, sourceDir, inFiles, {}, destRootDir);
compress(out, sourceDir, inFiles, {}, destRootDir);
} }
bool Compress::_compress(QIODevice *output, bool Compress::_compress(QIODevice* output, const QString& filesRootDir, const QVector<FileInformations>& files,
const QString &filesRootDir, const QVector<FileInformations>& memFiles, const QString& _destRootDir)
const QVector<FileInformations> &files,
const QVector<FileInformations> &memFiles,
const QString &_destRootDir)
{ {
std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int *) std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int*) {
{ DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #1";
DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #1"; m_currentTarFilter = nullptr;
m_currentTarFilter = nullptr; m_currentBzipDevice = nullptr;
m_currentBzipDevice = nullptr; });
}); (void)invalidatePointersOnScopeLeave;
(void)invalidatePointersOnScopeLeave;
if (!output || !output->isWritable())
if (!output || !output->isWritable())
{
m_lastError = tr("Device is not writeable");
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;;
return false;
}
const QString destRootDir = _destRootDir.endsWith(QLatin1Char('/')) ?
_destRootDir : _destRootDir + QLatin1Char('/');
const qint64 maxCount = files.count() + memFiles.count();
qint64 count = 0;
DEBUG_LOG(m_logger) << "destRootDir = " << destRootDir << ", maxCount = " << maxCount << ", count = " << count;
BZip2IODevice bzip2(output, 9);
m_currentBzipDevice = &bzip2;
if (!bzip2.open(QIODevice::WriteOnly))
{
m_lastError = bzip2.errorString();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
qint64 bytesTotal = 0;
for (const FileInformations &file : std::as_const(files))
{
if (m_aborted) return false;
const QString in = file.bAbsInputPath ? file.inputFileName : filesRootDir + QLatin1Char('/') + file.inputFileName;
const QFileInfo fi(in);
bytesTotal += fi.size();
}
qint64 currentFileSize = 0;
QString currentFileName;
auto readCallback = [this, &maxCount, &count, &currentFileSize, &currentFileName, &bytesTotal](const qint64 iSize)
{
DEBUG_LOG(m_logger) << "readCallback: maxCount = " << maxCount << ", count = " << count
<< ", currentFileSize = " << currentFileSize << ", currentFileName = " << currentFileName << ", iSize = " << iSize;
emit compressInfoEx(maxCount, count, currentFileSize, (currentFileSize - iSize), currentFileName, bytesTotal);
};
TarFilter tf(&bzip2, readCallback);
m_currentTarFilter = &tf;
const QStringList paths = destRootDir.split(QLatin1Char('/'), Qt::SkipEmptyParts);
QString curPath;
DEBUG_LOG(m_logger) << "prepairing tar filter";
for (const QString &path : paths)
{
DEBUG_LOG(m_logger) << "path = " << path;
if (m_aborted) return false;
if (curPath.isEmpty())
curPath = path + QLatin1Char('/');
else
curPath += path + QLatin1Char('/');
DEBUG_LOG(m_logger) << "curPath = " << curPath << ", filesRootDir.isEmpty() = " << filesRootDir.isEmpty();
if (filesRootDir.isEmpty())
{ {
if (!tf.addData(curPath, QByteArray(), true)) m_lastError = tr("Device is not writeable");
{ ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
m_lastError = tf.lastError(); ;
return false;
}
const QString destRootDir =
_destRootDir.endsWith(QLatin1Char('/')) ? _destRootDir : _destRootDir + QLatin1Char('/');
const qint64 maxCount = files.count() + memFiles.count();
qint64 count = 0;
DEBUG_LOG(m_logger) << "destRootDir = " << destRootDir << ", maxCount = " << maxCount << ", count = " << count;
BZip2IODevice bzip2(output, 9);
m_currentBzipDevice = &bzip2;
if (!bzip2.open(QIODevice::WriteOnly))
{
m_lastError = bzip2.errorString();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError; ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false; return false;
}
} }
else
qint64 bytesTotal = 0;
for (const FileInformations& file : std::as_const(files))
{ {
if (!tf.addFile(filesRootDir, curPath)) if (m_aborted)
{ return false;
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false; const QString in =
} file.bAbsInputPath ? file.inputFileName : filesRootDir + QLatin1Char('/') + file.inputFileName;
const QFileInfo fi(in);
bytesTotal += fi.size();
} }
}
m_c_sizeInfo.realSize = 0; qint64 currentFileSize = 0;
for (const FileInformations &file : std::as_const(files)) QString currentFileName;
{ auto readCallback = [this, &maxCount, &count, &currentFileSize, &currentFileName, &bytesTotal](const qint64 iSize) {
DEBUG_LOG(m_logger) << "file = " << file.inputFileName; DEBUG_LOG(m_logger) << "readCallback: maxCount = " << maxCount << ", count = " << count
emit compressInfo(maxCount, ++count, file.inputFileName); << ", currentFileSize = " << currentFileSize << ", currentFileName = " << currentFileName
<< ", iSize = " << iSize;
emit compressInfoEx(maxCount, count, currentFileSize, (currentFileSize - iSize), currentFileName, bytesTotal);
};
if (m_aborted) return false; TarFilter tf(&bzip2, readCallback);
m_currentTarFilter = &tf;
const QStringList paths = destRootDir.split(QLatin1Char('/'), Qt::SkipEmptyParts);
QString curPath;
QString in = file.bAbsInputPath ? file.inputFileName : filesRootDir + QLatin1Char('/') + file.inputFileName; DEBUG_LOG(m_logger) << "prepairing tar filter";
QString out = destRootDir + (file.outputFileName.isEmpty() ? file.inputFileName : file.outputFileName); for (const QString& path : paths)
DEBUG_LOG(m_logger) << "in = " << in << ", out = " << out;
QFileInfo fi(in);
currentFileName = fi.fileName();
currentFileSize = fi.size();
m_c_sizeInfo.realSize += currentFileSize;
DEBUG_LOG(m_logger) << "currentFileName = " << currentFileName << ", currentFileSize = " << currentFileSize << "m_c_sizeInfo.realSize" << m_c_sizeInfo.realSize;
if (!tf.addFile(in, out))
{ {
m_lastError = tf.lastError(); DEBUG_LOG(m_logger) << "path = " << path;
ERROR_LOG(m_logger) << "compress failed: " << m_lastError; if (m_aborted)
return false;
return false; if (curPath.isEmpty())
curPath = path + QLatin1Char('/');
else
curPath += path + QLatin1Char('/');
DEBUG_LOG(m_logger) << "curPath = " << curPath << ", filesRootDir.isEmpty() = " << filesRootDir.isEmpty();
if (filesRootDir.isEmpty())
{
if (!tf.addData(curPath, QByteArray(), true))
{
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
}
else
{
if (!tf.addFile(filesRootDir, curPath))
{
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
}
} }
}
for (const FileInformations &file : std::as_const(memFiles)) m_c_sizeInfo.realSize = 0;
{ for (const FileInformations& file : std::as_const(files))
DEBUG_LOG(m_logger) << "(mem) file = " << file.inputFileName;
emit compressInfo(maxCount, ++count, file.inputFileName);
if (m_aborted) return false;
currentFileName = file.inputFileName;
currentFileSize = file.fileData.size();
m_c_sizeInfo.compressedSize += currentFileSize;
DEBUG_LOG(m_logger) << "(mem) currentFileName = " << currentFileName << ", currentFileSize = " << currentFileSize << "m_c_sizeInfo.realSize" << m_c_sizeInfo.realSize;
if (!tf.addData(file.inputFileName, file.fileData))
{ {
m_lastError = tf.lastError(); DEBUG_LOG(m_logger) << "file = " << file.inputFileName;
ERROR_LOG(m_logger) << "compress failed: " << m_lastError; emit compressInfo(maxCount, ++count, file.inputFileName);
return false; if (m_aborted)
return false;
QString in = file.bAbsInputPath ? file.inputFileName : filesRootDir + QLatin1Char('/') + file.inputFileName;
QString out = destRootDir + (file.outputFileName.isEmpty() ? file.inputFileName : file.outputFileName);
DEBUG_LOG(m_logger) << "in = " << in << ", out = " << out;
QFileInfo fi(in);
currentFileName = fi.fileName();
currentFileSize = fi.size();
m_c_sizeInfo.realSize += currentFileSize;
DEBUG_LOG(m_logger) << "currentFileName = " << currentFileName << ", currentFileSize = " << currentFileSize
<< "m_c_sizeInfo.realSize" << m_c_sizeInfo.realSize;
if (!tf.addFile(in, out))
{
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
} }
}
for (const FileInformations& file : std::as_const(memFiles))
{
DEBUG_LOG(m_logger) << "(mem) file = " << file.inputFileName;
emit compressInfo(maxCount, ++count, file.inputFileName);
DEBUG_LOG(m_logger) << "writing eos"; if (m_aborted)
tf.writeEOS(); return false;
DEBUG_LOG(m_logger) << "closing bzip"; currentFileName = file.inputFileName;
bzip2.close(); currentFileSize = file.fileData.size();
m_c_sizeInfo.compressedSize += currentFileSize;
m_c_sizeInfo.compressedSize = output->size(); DEBUG_LOG(m_logger) << "(mem) currentFileName = " << currentFileName
DEBUG_LOG(m_logger) << "m_c_sizeInfo.compressedSize = " << m_c_sizeInfo.compressedSize; << ", currentFileSize = " << currentFileSize << "m_c_sizeInfo.realSize"
<< m_c_sizeInfo.realSize;
m_success = true; if (!tf.addData(file.inputFileName, file.fileData))
{
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
DEBUG_LOG(m_logger) << "DONE!"; return false;
}
}
return true; DEBUG_LOG(m_logger) << "writing eos";
tf.writeEOS();
DEBUG_LOG(m_logger) << "closing bzip";
bzip2.close();
m_c_sizeInfo.compressedSize = output->size();
DEBUG_LOG(m_logger) << "m_c_sizeInfo.compressedSize = " << m_c_sizeInfo.compressedSize;
m_success = true;
DEBUG_LOG(m_logger) << "DONE!";
return true;
} }
void Compress::uncompress(QIODevice *in, const QString &outDir) void Compress::uncompress(QIODevice* in, const QString& outDir)
{ {
DEBUG_LOG(m_logger) << "uncompress #1"; DEBUG_LOG(m_logger) << "uncompress #1";
reset(); reset();
setupFutureWatcher(QtConcurrent::run([this, in, outDir](){ return this->_uncompressDirectory(in, outDir); })); setupFutureWatcher(QtConcurrent::run([this, in, outDir]() { return this->_uncompressDirectory(in, outDir); }));
} }
bool Compress::_uncompressDirectory(QIODevice *input, const QString &outDir) bool Compress::_uncompressDirectory(QIODevice* input, const QString& outDir)
{ {
DEBUG_LOG(m_logger) << "_uncompressDirectory"; DEBUG_LOG(m_logger) << "_uncompressDirectory";
std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int *) std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int*) {
{ DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #2";
DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #2"; m_currentTarFilter = nullptr;
m_currentTarFilter = nullptr; m_currentBzipDevice = nullptr;
m_currentBzipDevice = nullptr; });
}); (void)invalidatePointersOnScopeLeave;
(void)invalidatePointersOnScopeLeave;
if (!input || !input->isReadable())
if (!input || !input->isReadable())
{
m_lastError = tr("Device is not readable");
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
BZip2IODevice bzip2(input, 9);
m_currentBzipDevice = &bzip2;
if (!bzip2.open(QIODevice::ReadOnly))
{
m_lastError = bzip2.errorString();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
TarFilter tf(&bzip2);
m_currentTarFilter = &tf;
TarFilter::FileInformations tfi;
QDir dir(outDir);
DEBUG_LOG(m_logger) << "dir = " << dir.path();
while (tf.getData(tfi))
{
DEBUG_LOG(m_logger) << "tfi.fileName = " << tfi.fileName;
emit uncompressInfo(input->size(), input->pos(), tfi.fileName);
if (m_aborted) return false;
QString path = outDir + QLatin1Char('/') + tfi.fileName;
DEBUG_LOG(m_logger) << "path = " << path;
if (tfi.fileType == TarFilter::directory)
{ {
DEBUG_LOG(m_logger) << "tfi.fileType == TarFilter::directory"; m_lastError = tr("Device is not readable");
if (!dir.exists(path) && !dir.mkpath(path))
{
m_lastError = tr("Error creating directory %1").arg(outDir);
ERROR_LOG(m_logger) << "compress failed: " << m_lastError; ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false; return false;
}
} }
else
BZip2IODevice bzip2(input, 9);
m_currentBzipDevice = &bzip2;
if (!bzip2.open(QIODevice::ReadOnly))
{ {
m_lastError = bzip2.errorString();
QString pathName = QFileInfo(path).absolutePath();
if (!dir.exists(pathName) && !dir.mkpath(pathName))
{
m_lastError = tr("Error creating directory %1").arg(pathName);
ERROR_LOG(m_logger) << "compress failed: " << m_lastError; ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false; return false;
}
QFile f(path);
if (!f.open(QIODevice::WriteOnly))
{
m_lastError = tr("Error opening %1 for writing (%2)").arg(path, f.errorString());
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
if (!tf.getData(&f))
{
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
} }
}
DEBUG_LOG(m_logger) << "uncompress done!"; TarFilter tf(&bzip2);
m_success = true; m_currentTarFilter = &tf;
return true; TarFilter::FileInformations tfi;
QDir dir(outDir);
DEBUG_LOG(m_logger) << "dir = " << dir.path();
while (tf.getData(tfi))
{
DEBUG_LOG(m_logger) << "tfi.fileName = " << tfi.fileName;
emit uncompressInfo(input->size(), input->pos(), tfi.fileName);
if (m_aborted)
return false;
QString path = outDir + QLatin1Char('/') + tfi.fileName;
DEBUG_LOG(m_logger) << "path = " << path;
if (tfi.fileType == TarFilter::directory)
{
DEBUG_LOG(m_logger) << "tfi.fileType == TarFilter::directory";
if (!dir.exists(path) && !dir.mkpath(path))
{
m_lastError = tr("Error creating directory %1").arg(outDir);
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
}
else
{
QString pathName = QFileInfo(path).absolutePath();
if (!dir.exists(pathName) && !dir.mkpath(pathName))
{
m_lastError = tr("Error creating directory %1").arg(pathName);
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
QFile f(path);
if (!f.open(QIODevice::WriteOnly))
{
m_lastError = tr("Error opening %1 for writing (%2)").arg(path, f.errorString());
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
if (!tf.getData(&f))
{
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
}
}
DEBUG_LOG(m_logger) << "uncompress done!";
m_success = true;
return true;
} }
void Compress::uncompress(QIODevice *in) void Compress::uncompress(QIODevice* in)
{ {
DEBUG_LOG(m_logger) << "uncompress #2!"; DEBUG_LOG(m_logger) << "uncompress #2!";
reset(); reset();
setupFutureWatcher(QtConcurrent::run([this, in](){ return this->_uncompressBuffer(in); })); setupFutureWatcher(QtConcurrent::run([this, in]() { return this->_uncompressBuffer(in); }));
} }
bool Compress::_uncompressBuffer(QIODevice *input) bool Compress::_uncompressBuffer(QIODevice* input)
{ {
DEBUG_LOG(m_logger) << "uncompressBuffer"; DEBUG_LOG(m_logger) << "uncompressBuffer";
std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int *) std::shared_ptr<int> invalidatePointersOnScopeLeave(nullptr, [this](int*) {
{ DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #2";
DEBUG_LOG(m_logger) << "invalidatePointersOnScopeLeave #2"; m_currentTarFilter = nullptr;
m_currentTarFilter = nullptr; m_currentBzipDevice = nullptr;
m_currentBzipDevice = nullptr; });
}); (void)invalidatePointersOnScopeLeave;
(void)invalidatePointersOnScopeLeave;
if (!input->isReadable())
if (!input->isReadable())
{
m_lastError = tr("Device is not readable");
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
BZip2IODevice bzip2(input, 9);
m_currentBzipDevice = &bzip2;
if (!bzip2.open(QIODevice::ReadOnly))
{
m_lastError = bzip2.errorString();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
TarFilter tf(&bzip2);
m_currentTarFilter = &tf;
TarFilter::FileInformations tfi;
while (tf.getData(tfi))
{
DEBUG_LOG(m_logger) << "tfi.fileName = " << tfi.fileName;
emit uncompressInfo(input->size(), input->pos(), tfi.fileName);
if (m_aborted) return false;
FileInformations fi;
fi.outputFileName = tfi.fileName;
DEBUG_LOG(m_logger) << "fi.outputFileName = " << fi.outputFileName;
if (tfi.fileType == TarFilter::directory)
{ {
fi.outputFileName += QLatin1Char('/'); m_lastError = tr("Device is not readable");
DEBUG_LOG(m_logger) << "> fi.outputFileName = " << fi.outputFileName;
}
else
{
DEBUG_LOG(m_logger) << "stuff";
QBuffer buf(&fi.fileData);
if (!buf.open(QIODevice::WriteOnly))
{
m_lastError = tr("Error opening buffer for writing (%1)").arg(buf.errorString());
ERROR_LOG(m_logger) << "compress failed: " << m_lastError; ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false; return false;
} }
if (!tf.getData(&buf))
{ BZip2IODevice bzip2(input, 9);
m_lastError = tf.lastError(); m_currentBzipDevice = &bzip2;
if (!bzip2.open(QIODevice::ReadOnly))
{
m_lastError = bzip2.errorString();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError; ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false; return false;
}
} }
fi.bAbsInputPath = fi.outputFileName.startsWith(QLatin1Char('/')); TarFilter tf(&bzip2);
DEBUG_LOG(m_logger) << "added fi.bAbsInputPath = " << fi.bAbsInputPath; m_currentTarFilter = &tf;
m_u2_memFiles += fi; TarFilter::FileInformations tfi;
} while (tf.getData(tfi))
{
DEBUG_LOG(m_logger) << "tfi.fileName = " << tfi.fileName;
emit uncompressInfo(input->size(), input->pos(), tfi.fileName);
if (m_aborted)
return false;
m_success = true; FileInformations fi;
return true; fi.outputFileName = tfi.fileName;
DEBUG_LOG(m_logger) << "fi.outputFileName = " << fi.outputFileName;
if (tfi.fileType == TarFilter::directory)
{
fi.outputFileName += QLatin1Char('/');
DEBUG_LOG(m_logger) << "> fi.outputFileName = " << fi.outputFileName;
}
else
{
DEBUG_LOG(m_logger) << "stuff";
QBuffer buf(&fi.fileData);
if (!buf.open(QIODevice::WriteOnly))
{
m_lastError = tr("Error opening buffer for writing (%1)").arg(buf.errorString());
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
if (!tf.getData(&buf))
{
m_lastError = tf.lastError();
ERROR_LOG(m_logger) << "compress failed: " << m_lastError;
return false;
}
}
fi.bAbsInputPath = fi.outputFileName.startsWith(QLatin1Char('/'));
DEBUG_LOG(m_logger) << "added fi.bAbsInputPath = " << fi.bAbsInputPath;
m_u2_memFiles += fi;
}
m_success = true;
return true;
} }
bool Compress::success() const bool Compress::success() const
{ {
ERROR_LOG(m_logger) << "success? " << (m_future.isFinished() && !m_future.isCanceled() && m_success); ERROR_LOG(m_logger) << "success? " << (m_future.isFinished() && !m_future.isCanceled() && m_success);
ERROR_LOG(m_logger) << "success details: " ERROR_LOG(m_logger) << "success details: "
<< "success m_future.isFinished() = " << (m_future.isFinished()) << "success m_future.isFinished() = " << (m_future.isFinished())
<< " !m_future.isCanceled() = " << !m_future.isCanceled() << " !m_future.isCanceled() = " << !m_future.isCanceled() << " m_success = " << m_success;
<< " m_success = " << m_success; return (m_future.isFinished() && !m_future.isCanceled() && m_success);
return (m_future.isFinished() && !m_future.isCanceled() && m_success);
} }
bool Compress::waitForFinished() bool Compress::waitForFinished()
{ {
DEBUG_LOG(m_logger) << "waitForFinished..."; DEBUG_LOG(m_logger) << "waitForFinished...";
m_future.waitForFinished(); m_future.waitForFinished();
DEBUG_LOG(m_logger) << "waitForFinished... done!"; DEBUG_LOG(m_logger) << "waitForFinished... done!";
return success(); return success();
} }
QVector<Compress::FileInformations> Compress::directoryFileList(const QString &dir, bool recursive) QVector<Compress::FileInformations> Compress::directoryFileList(const QString& dir, bool recursive)
{ {
DEBUG_LOG(m_logger) << "directoryFileList"; DEBUG_LOG(m_logger) << "directoryFileList";
QVector<FileInformations> sl_absolute; QVector<FileInformations> sl_absolute;
QDir d(dir); QDir d(dir);
if (d.exists()) if (d.exists())
{ {
DEBUG_LOG(m_logger) << "exists"; DEBUG_LOG(m_logger) << "exists";
const auto entries = d.entryList(QDir::Files); const auto entries = d.entryList(QDir::Files);
sl_absolute.reserve(sl_absolute.size() + entries.size()); sl_absolute.reserve(sl_absolute.size() + entries.size());
for (const QString &entry : entries) for (const QString& entry : entries)
sl_absolute << FileInformations(QFileInfo(d, entry).absoluteFilePath(), true); sl_absolute << FileInformations(QFileInfo(d, entry).absoluteFilePath(), true);
} }
if (recursive) if (recursive)
{ {
DEBUG_LOG(m_logger) << "recursive"; DEBUG_LOG(m_logger) << "recursive";
const auto entries = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot); const auto entries = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
sl_absolute.reserve(sl_absolute.size() + entries.size()); sl_absolute.reserve(sl_absolute.size() + entries.size());
for (const QString &s : entries) for (const QString& s : entries)
sl_absolute << directoryFileList(dir + QLatin1Char('/') + s, true); sl_absolute << directoryFileList(dir + QLatin1Char('/') + s, true);
} }
DEBUG_LOG(m_logger) << "done"; DEBUG_LOG(m_logger) << "done";
return sl_absolute; return sl_absolute;
} }
void Compress::reset() void Compress::reset()
{ {
DEBUG_LOG(m_logger) << "reset"; DEBUG_LOG(m_logger) << "reset";
m_u2_memFiles.clear(); m_u2_memFiles.clear();
m_lastError.clear(); m_lastError.clear();
m_c_sizeInfo.realSize = 0; m_c_sizeInfo.realSize = 0;
m_c_sizeInfo.compressedSize = 0; m_c_sizeInfo.compressedSize = 0;
m_success = false; m_success = false;
} }
void Compress::setupFutureWatcher(const QFuture<bool> &future) void Compress::setupFutureWatcher(const QFuture<bool>& future)
{ {
DEBUG_LOG(m_logger) << "setupFutureWatcher"; DEBUG_LOG(m_logger) << "setupFutureWatcher";
m_future = future; m_future = future;
QFutureWatcher<bool> *fw = new QFutureWatcher<bool>(this); QFutureWatcher<bool>* fw = new QFutureWatcher<bool>(this);
QObject::connect(fw, &QObject::destroyed, this, [this]() { DEBUG_LOG(m_logger) << "Future Watcher destroyed"; }); QObject::connect(fw, &QObject::destroyed, this, [this]() { DEBUG_LOG(m_logger) << "Future Watcher destroyed"; });
QObject::connect(fw, &QFutureWatcher<bool>::finished, this, &Compress::finished); QObject::connect(fw, &QFutureWatcher<bool>::finished, this, &Compress::finished);
QObject::connect(fw, &QFutureWatcher<bool>::finished, fw, &QObject::deleteLater); QObject::connect(fw, &QFutureWatcher<bool>::finished, fw, &QObject::deleteLater);
QObject::connect(fw, &QFutureWatcher<bool>::finished, fw, [this]() { DEBUG_LOG(m_logger) << "Future Watcher about to be deleted"; }); QObject::connect(fw, &QFutureWatcher<bool>::finished, fw,
fw->setFuture(m_future); [this]() { DEBUG_LOG(m_logger) << "Future Watcher about to be deleted"; });
fw->setFuture(m_future);
} }
} } // namespace NGL
+6 -9
View File
@@ -1,19 +1,16 @@
#pragma once #pragma once
#include "commandinterface.h" #include "commandinterface.h"
#include "sv_export.h" #include "tcpserver_export.h"
class TCPSERVER_EXPORT CBI_Help : public CommandInterface class TCPSERVER_EXPORT CBI_Help : public CommandInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CBI_Help(unsigned short port); explicit CBI_Help(unsigned short port);
void handleCommandInternal(const QVector<QByteArray> &args) override; void handleCommandInternal(const QVector<QByteArray>& args) override;
QString help() const override; QString help() const override;
}; };
+6 -9
View File
@@ -1,19 +1,16 @@
#pragma once #pragma once
#include "commandinterface.h" #include "commandinterface.h"
#include "sv_export.h" #include "tcpserver_export.h"
class CBI_PingPong : public CommandInterface class CBI_PingPong : public CommandInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CBI_PingPong(unsigned short port); explicit CBI_PingPong(unsigned short port);
void handleCommandInternal(const QVector<QByteArray> &args) override; void handleCommandInternal(const QVector<QByteArray>& args) override;
QString help() const override; QString help() const override;
}; };
+6 -9
View File
@@ -1,19 +1,16 @@
#pragma once #pragma once
#include "commandinterface.h" #include "commandinterface.h"
#include "sv_export.h" #include "tcpserver_export.h"
class TCPSERVER_EXPORT CBI_Quit : public CommandInterface class TCPSERVER_EXPORT CBI_Quit : public CommandInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CBI_Quit(unsigned short port); explicit CBI_Quit(unsigned short port);
void handleCommandInternal(const QVector<QByteArray> &args) override; void handleCommandInternal(const QVector<QByteArray>& args) override;
QString help() const override; QString help() const override;
}; };
+12 -10
View File
@@ -1,23 +1,25 @@
#pragma once #pragma once
#include "commandinterface.h" #include "commandinterface.h"
#include "sv_export.h" #include "tcpserver_export.h"
#include <QMap> #include <QMap>
#include <QPair> #include <QPair>
class QIODevice; class QIODevice;
class CBI_Recvfile : public CommandInterface class CBI_Recvfile : public CommandInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CBI_Recvfile(unsigned short port); explicit CBI_Recvfile(unsigned short port);
void handleCommandInternal(const QVector<QByteArray> &args) override; void handleCommandInternal(const QVector<QByteArray>& args) override;
QString help() const override; QString help() const override;
void newPlainData() override; void newPlainData() override;
protected:
QMap<WorkerBase*, QPair<QIODevice*, int> > m_wbMap; protected:
QMap<WorkerBase*, QPair<QIODevice*, int>> m_wbMap;
}; };
+6 -7
View File
@@ -1,17 +1,16 @@
#pragma once #pragma once
#include "commandinterface.h" #include "commandinterface.h"
#include "sv_export.h" #include "tcpserver_export.h"
class CBI_Sendfile : public CommandInterface class CBI_Sendfile : public CommandInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CBI_Sendfile(unsigned short port); explicit CBI_Sendfile(unsigned short port);
void handleCommandInternal(const QVector<QByteArray> &args) override; void handleCommandInternal(const QVector<QByteArray>& args) override;
QString help() const override; QString help() const override;
}; };
+9 -12
View File
@@ -1,25 +1,22 @@
#pragma once #pragma once
#include "commandinterface.h" #include "commandinterface.h"
#include "sv_export.h" #include "tcpserver_export.h"
class TCPSERVER_EXPORT CBI_Shutdown : public CommandInterface class TCPSERVER_EXPORT CBI_Shutdown : public CommandInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CBI_Shutdown(unsigned short port); explicit CBI_Shutdown(unsigned short port);
void handleCommandInternal(const QVector<QByteArray> &args) override; void handleCommandInternal(const QVector<QByteArray>& args) override;
QString help() const override; QString help() const override;
Q_SIGNALS: Q_SIGNALS:
void shutdownRequest();
void shutdownRequest(); private:
private:
}; };
+51 -102
View File
@@ -1,158 +1,107 @@
#pragma once #pragma once
#include "tcpserver_export.h"
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QVector> #include <QVector>
#include "sv_export.h"
class QAbstractSocket; class QAbstractSocket;
class QByteArray; class QByteArray;
class WorkerBase; class WorkerBase;
class TCPSERVER_EXPORT CommandInterface : public QObject class TCPSERVER_EXPORT CommandInterface : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CommandInterface(unsigned short port, const QByteArray& command = QByteArray());
virtual ~CommandInterface();
explicit CommandInterface(unsigned short port, const QByteArray &command = QByteArray()); void handleCommand(const QVector<QByteArray>& args);
virtual void newPlainData();
virtual QString help() const = 0;
virtual ~CommandInterface(); QByteArray command() const;
void setAutoWriteEOL(bool newAutoWriteEOL);
void handleCommand(const QVector<QByteArray> &args); bool autoWriteEOL() const;
bool errorOccured() const;
virtual void newPlainData(); static void setDefaultSuccessMessage(const QString& msg);
static void setDefaultErrorMessage(const QString& msg);
virtual QString help() const = 0; template <class T> static CommandInterface* factory(unsigned short port)
{
return new T(port);
}
virtual void aboutToDestroy() {}
QByteArray command() const; protected:
virtual void handleCommandInternal(const QVector<QByteArray>& args) = 0;
void setWriteTimeout(int iMS);
void writeData(const QByteArray& payload);
void setAutoWriteEOL(bool newAutoWriteEOL); void writeData(const char* payload);
void writeData(const QString& payload);
void writeData(const QStringList& payload);
bool autoWriteEOL() const; void writeData(const QList<QByteArray>& payload);
void writeOk(const QString& additionalMsg = QString());
void writeError(const QString& additionalMsg = QString());
bool errorOccured() const; void writeEOL();
QByteArray quote(const QByteArray& payload);
QAbstractSocket* socket();
static void setDefaultSuccessMessage(const QString &msg); void setSocket(QAbstractSocket* socket);
WorkerBase* workerBase();
void setWorkerBase(WorkerBase* wb);
static void setDefaultErrorMessage(const QString &msg); void conversionError(const QByteArray& arg, const QByteArray& type);
template<class T> bool getValue(const QByteArray& arg, bool& value);
static CommandInterface *factory(unsigned short port) { return new T(port); }
bool getValue(const QByteArray& arg, long& value);
bool getValue(const QByteArray& arg, unsigned long& value);
virtual void aboutToDestroy() {} bool getValue(const QByteArray& arg, int& value);
protected:
bool getValue(const QByteArray& arg, unsigned int& value);
virtual void handleCommandInternal(const QVector<QByteArray> &args) = 0; bool getValue(const QByteArray& arg, float& value);
bool getValue(const QByteArray& arg, double& value);
void setWriteTimeout(int iMS); unsigned short port() const;
void closeConnection();
void writeData(const QByteArray &payload); bool socketIsOpen() const;
private:
friend class WorkerBase;
void writeData(const char *payload); class Private;
Private* const d;
void writeData(const QString &payload);
void writeData(const QStringList &payload);
void writeData(const QList<QByteArray> &payload);
void writeOk(const QString &additionalMsg = QString());
void writeError(const QString &additionalMsg = QString());
void writeEOL();
QByteArray quote(const QByteArray &payload);
QAbstractSocket *socket();
void setSocket(QAbstractSocket *socket);
WorkerBase *workerBase();
void setWorkerBase(WorkerBase *wb);
void conversionError(const QByteArray &arg, const QByteArray &type);
bool getValue(const QByteArray &arg, bool &value);
bool getValue(const QByteArray &arg, long &value);
bool getValue(const QByteArray &arg, unsigned long &value);
bool getValue(const QByteArray &arg, int &value);
bool getValue(const QByteArray &arg, unsigned int &value);
bool getValue(const QByteArray &arg, float &value);
bool getValue(const QByteArray &arg, double &value);
unsigned short port() const;
void closeConnection();
bool socketIsOpen() const;
private:
friend class WorkerBase;
class Private;
Private *const d;
}; };
+30 -62
View File
@@ -1,96 +1,64 @@
#pragma once #pragma once
#include <QTcpServer> #include "tcpserver_export.h"
#include "sv_export.h" #include <QTcpServer>
class WorkerInstance; class WorkerInstance;
class CommandInterface; class CommandInterface;
class TCPSERVER_EXPORT TcpServer : public QTcpServer class TCPSERVER_EXPORT TcpServer : public QTcpServer
{ {
Q_OBJECT Q_OBJECT
public: public:
typedef QVector<CommandInterface*(*)(unsigned short) > CommandInterfaceList; typedef QVector<CommandInterface* (*)(unsigned short)> CommandInterfaceList;
public:
public:
virtual ~TcpServer();
virtual ~TcpServer(); static TcpServer* instance(unsigned short port);
bool listen(const QHostAddress& address = QHostAddress::Any);
static TcpServer *instance(unsigned short port); void setUseWorkerThreads(bool bEnable);
bool useWorkerThreads() const;
QVector<WorkerInstance*> workers() const;
bool listen(const QHostAddress &address = QHostAddress::Any); unsigned short getListenPort() const;
static bool registerCommand(unsigned short port, CommandInterface* (*factory)(unsigned short));
static bool unregisterCommand(unsigned short port, CommandInterface* (*factory)(unsigned short));
void setUseWorkerThreads(bool bEnable); static CommandInterfaceList registeredCommands(unsigned short port);
void setUserData(void* userData);
void* userData() const;
bool useWorkerThreads() const; Q_SIGNALS:
void aboutToQuit(unsigned short port);
public Q_SLOTS:
QVector<WorkerInstance *> workers() const; void shutdownRequest();
void workerFinished();
protected:
void incomingConnection(qintptr socketDescriptor);
unsigned short getListenPort() const; private:
class Private;
Private* const d;
explicit TcpServer(unsigned short port);
static bool registerCommand(unsigned short port, CommandInterface * (*factory)(unsigned short)); bool listen(const QHostAddress& address, quint16 port);
static bool unregisterCommand(unsigned short port, CommandInterface * (*factory)(unsigned short));
static CommandInterfaceList registeredCommands(unsigned short port);
void setUserData(void *userData);
void *userData() const;
Q_SIGNALS:
void aboutToQuit(unsigned short port);
public Q_SLOTS:
void shutdownRequest();
void workerFinished();
protected:
void incomingConnection(qintptr socketDescriptor);
private:
class Private;
Private *const d;
explicit TcpServer(unsigned short port);
bool listen(const QHostAddress &address, quint16 port);
}; };
+41 -82
View File
@@ -1,128 +1,87 @@
#pragma once #pragma once
#include "tcpserver_export.h"
#include <QByteArray> #include <QByteArray>
#include <QMap> #include <QMap>
#include <QPointer>
#include <QObject> #include <QObject>
#include <QPointer>
#include "sv_export.h"
class QAbstractSocket; class QAbstractSocket;
class CommandInterface; class CommandInterface;
class TCPSERVER_EXPORT WorkerBase class TCPSERVER_EXPORT WorkerBase
{ {
public: public:
typedef QMap< QByteArray, CommandInterface *> CommandMap; typedef QMap<QByteArray, CommandInterface*> CommandMap;
public:
public:
WorkerBase(qintptr sd, unsigned short port);
WorkerBase(qintptr sd, unsigned short port); virtual ~WorkerBase() = default;
QAbstractSocket* connection();
virtual ~WorkerBase() = default; const QAbstractSocket* connection() const;
void redirectDataHandling(bool bDoRedirect, CommandInterface* newDataHandler = nullptr);
QAbstractSocket *connection(); static QByteArray formatForDebug(const QByteArray& data);
static QByteArray formatForDebug(const QAbstractSocket* dev);
CommandMap getCommands() const;
const QAbstractSocket *connection() const; protected:
void newDataInternal();
int initCommands(unsigned short port);
void cleanupCommands();
void redirectDataHandling(bool bDoRedirect, CommandInterface *newDataHandler = nullptr); qintptr m_socketDescriptor;
QPointer<QAbstractSocket> m_connection;
unsigned short m_port;
static QByteArray formatForDebug(const QByteArray &data); QByteArray m_connString;
bool m_bRedirectIncomingData;
CommandInterface* m_bRedirectDataHandler;
static QByteArray formatForDebug(const QAbstractSocket *dev); CommandMap m_registeredCommands;
CommandMap getCommands() const;
protected:
void newDataInternal();
int initCommands(unsigned short port);
void cleanupCommands();
qintptr m_socketDescriptor;
QPointer<QAbstractSocket> m_connection;
unsigned short m_port;
QByteArray m_connString;
bool m_bRedirectIncomingData;
CommandInterface *m_bRedirectDataHandler;
CommandMap m_registeredCommands;
}; };
class WorkerInstance final : public QObject, public WorkerBase class WorkerInstance final : public QObject, public WorkerBase
{ {
Q_OBJECT Q_OBJECT
public: public:
WorkerInstance(qintptr sd, unsigned short port, QObject *parent = nullptr); WorkerInstance(qintptr sd, unsigned short port, QObject* parent = nullptr);
virtual ~WorkerInstance(); virtual ~WorkerInstance();
bool isRunning() const;
bool isFinished() const;
bool isRunning() const; public Q_SLOTS:
void quit();
bool isFinished() const; void doWork();
public Q_SLOTS: protected Q_SLOTS:
void newData();
void quit(); void connectionDisconnected();
Q_SIGNALS:
void finished();
private:
void doWork(); bool m_bFinished;
protected Q_SLOTS:
void newData();
void connectionDisconnected();
Q_SIGNALS:
void finished();
private:
bool m_bFinished;
}; };
@@ -163,25 +163,31 @@ MACRO(INSTALL_SHARED_FILES srcList)
ENDMACRO() ENDMACRO()
MACRO(CODEGEN_SQL srcList xmlFile_in) MACRO(CODEGEN_SQL srcList xmlFile_in)
_GET_SERVICENAME( "${xmlFile_in}" svcNameOut ) IF(BUILD_GRANTLEE)
SET(out_dir_sql "${CMAKE_BINARY_DIR}/share/Lts/sql/") _GET_SERVICENAME( "${xmlFile_in}" svcNameOut )
SET(out_file_sql "${out_dir_sql}/${svcNameOut}.sql") SET(out_dir_sql "${CMAKE_BINARY_DIR}/share/Lts/sql/")
SET(action "SQL") SET(out_file_sql "${out_dir_sql}/${svcNameOut}.sql")
ADD_CUSTOM_COMMAND(OUTPUT ${out_file_sql} SET(action "SQL")
COMMAND ${CMAKE_COMMAND} ADD_CUSTOM_COMMAND(OUTPUT ${out_file_sql}
ARGS -E make_directory ${out_dir_sql} COMMAND ${CMAKE_COMMAND}
COMMAND ngl_codegen ARGS -E make_directory ${out_dir_sql}
ARGS -s ${xmlFile_in} COMMAND ngl_codegen
-a ${action} ARGS -s ${xmlFile_in}
-o ${out_dir_sql} -a ${action}
-i ${CMAKE_BINARY_DIR}/service_idl_files.txt -o ${out_dir_sql}
DEPENDS ngl_codegen ${xmlFile_in} -i ${CMAKE_BINARY_DIR}/service_idl_files.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ngl_codegen ${xmlFile_in}
) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
LIST(APPEND ${srcList} ${out_file_sql}) )
LIST(APPEND ${srcList} ${out_file_sql})
NGL_INSTALL(SV AAR FILES ${out_file_sql} DESTINATION share/Lts/sql) NGL_INSTALL(SV AAR FILES ${out_file_sql} DESTINATION share/Lts/sql)
ELSE()
# BUILD_GRANTLEE disabled: skip SQL generation
# SQL files will not be generated; modules may need pre-generated SQL files
MESSAGE(STATUS "BUILD_GRANTLEE disabled: skipping SQL generation for ${xmlFile_in}")
ENDIF()
ENDMACRO() ENDMACRO()
MACRO(CODEGEN_HANDLE_SVC_XML srcList xmlFile_in) MACRO(CODEGEN_HANDLE_SVC_XML srcList xmlFile_in)
+172 -187
View File
@@ -1,59 +1,56 @@
/** /**
* Logger interface * Logger interface
* $Id$ * $Id$
* $HeadURL$ * $HeadURL$
* $Author$ * $Author$
*/ */
#pragma once #pragma once
#include <string> #include <QList>
#include <sstream>
#include <QString>
#include <QPointF> #include <QPointF>
#include <QSize>
#include <QRect> #include <QRect>
#include <QRectF> #include <QRectF>
#include <QList> #include <QSize>
#include "ngllogger_export.h" #include <QString>
#include <ngllogger_export.h>
#include <sstream>
#include <string>
namespace NGL namespace NGL
{ {
class INGLLogger; class INGLLogger;
// keep in sync with log4qt/level.h // keep in sync with log4qt/level.h
enum class LogLevel enum class LogLevel {
{ Undefined = 0,
Undefined = 0, Trace = 64,
Trace = 64, Debug = 96,
Debug = 96, Info = 128,
Info = 128, Warning = 150,
Warning = 150, Error = 182,
Error = 182, Fatal = 214,
Fatal = 214,
}; };
class LogStreamHelper class LogStreamHelper
{ {
public: public:
inline LogStreamHelper(INGLLogger &logger, LogLevel level, const char *const file, int line, const char *const function) inline LogStreamHelper(INGLLogger& logger, LogLevel level, const char* const file, int line,
: m_logger(logger) const char* const function)
, m_level(level) : m_logger(logger), m_level(level), m_line(line), m_file(file), m_func(function)
, m_line(line) {
, m_file(file) }
, m_func(function)
{}
inline ~LogStreamHelper(); // after INGLLogger class definition
template<typename T> inline ~LogStreamHelper(); // after INGLLogger class definition
inline LogStreamHelper &operator<<(const T &val);
private: template <typename T> inline LogStreamHelper& operator<<(const T& val);
std::ostringstream m_buffer;
NGL::INGLLogger &m_logger; private:
const LogLevel m_level; std::ostringstream m_buffer;
const int m_line; NGL::INGLLogger& m_logger;
const char *const m_file; const LogLevel m_level;
const char *const m_func; const int m_line;
const char* const m_file;
const char* const m_func;
}; };
// Interface class for source code logging. // Interface class for source code logging.
@@ -64,58 +61,64 @@ private:
// information on logger-hierarchies, logging-levels, and configuration files. // information on logger-hierarchies, logging-levels, and configuration files.
class INGLLogger class INGLLogger
{ {
public: public:
INGLLogger(const INGLLogger &) = delete; INGLLogger(const INGLLogger&) = delete;
INGLLogger &operator=(const INGLLogger &) = delete; INGLLogger& operator=(const INGLLogger&) = delete;
INGLLogger() = default; INGLLogger() = default;
virtual ~INGLLogger() = default; virtual ~INGLLogger() = default;
using String = std::string; using String = std::string;
// Creates an instance of an INGLLogger interface. The fullqualifiedname is // Creates an instance of an INGLLogger interface. The fullqualifiedname is
// a dottet sequence (i.e. "NGL.thisandthat.mylogger"). The same name will // a dottet sequence (i.e. "NGL.thisandthat.mylogger"). The same name will
// always return the same interface-instance. It is not required to create // always return the same interface-instance. It is not required to create
// the parent nodes. // the parent nodes.
virtual INGLLogger &getNGLLogger(const char *fullqualifiedname) = 0; virtual INGLLogger& getNGLLogger(const char* fullqualifiedname) = 0;
virtual INGLLogger &getNGLLogger(const std::string &fullqualifiedname) = 0; virtual INGLLogger& getNGLLogger(const std::string& fullqualifiedname) = 0;
// True if this level is enabled.
virtual bool isTraceEnabled() const = 0;
virtual bool isDebugEnabled() const = 0;
virtual bool isInfoEnabled() const = 0;
virtual bool isWarningEnabled() const = 0;
virtual bool isErrorEnabled() const = 0;
virtual bool isFatalEnabled() const = 0;
virtual bool isLevelEnabled(LogLevel level) const = 0;
// True if this level is enabled. // Submit a LOG message.
virtual bool isTraceEnabled() const = 0; // Use __FILE__ and __NAME__ macros.
virtual bool isDebugEnabled() const = 0; virtual void log(LogLevel level, const INGLLogger::String& message, const char* file = nullptr, int line = -1,
virtual bool isInfoEnabled() const = 0; const char* function = nullptr) = 0;
virtual bool isWarningEnabled() const = 0;
virtual bool isErrorEnabled() const = 0;
virtual bool isFatalEnabled() const = 0;
virtual bool isLevelEnabled(LogLevel level) const = 0;
// Submit a LOG message. // Submit an TRACE message.
// Use __FILE__ and __NAME__ macros. virtual void logTrace(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
virtual void log(LogLevel level, const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0; const char* function = nullptr) = 0;
// Submit an DEBUG message.
virtual void logDebug(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit an INFO message.
virtual void logInfo(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit a WARNING message.
virtual void logWarning(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit an ERROR message.
virtual void logError(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit a FATAL message.
virtual void logFatal(const INGLLogger::String& message, const char* file = nullptr, int line = -1,
const char* function = nullptr) = 0;
// Submit an TRACE message. // Writes a startup message into the logfile
virtual void logTrace(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0; virtual void logStartup(const char* file, int line, const char* function = nullptr) = 0;
// Submit an DEBUG message. // Writes a shutdown message into the logfile
virtual void logDebug(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0; virtual void logShutdown(const char* file, int line, const char* function = nullptr) = 0;
// Submit an INFO message.
virtual void logInfo(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Submit a WARNING message.
virtual void logWarning(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Submit an ERROR message.
virtual void logError(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Submit a FATAL message.
virtual void logFatal(const INGLLogger::String &message, const char *file = nullptr, int line = -1, const char *function = nullptr) = 0;
// Writes a startup message into the logfile // Get this loggers fullqualified name.
virtual void logStartup(const char *file, int line, const char *function = nullptr) = 0; virtual std::string getLoggerName() const = 0;
// Writes a shutdown message into the logfile
virtual void logShutdown(const char *file, int line, const char *function = nullptr) = 0;
// Get this loggers fullqualified name. virtual void setNoSpace(bool bNoSpace) = 0;
virtual std::string getLoggerName() const = 0; virtual bool noSpace() const = 0;
virtual void setNoSpace(bool bNoSpace) = 0;
virtual bool noSpace() const = 0;
}; };
// //
@@ -123,112 +126,90 @@ public:
// //
inline LogStreamHelper::~LogStreamHelper() inline LogStreamHelper::~LogStreamHelper()
{ {
m_logger.log(m_level, m_buffer.str(), m_file, m_line, m_func); m_logger.log(m_level, m_buffer.str(), m_file, m_line, m_func);
} }
template<typename T> template <typename T> inline LogStreamHelper& LogStreamHelper::operator<<(const T& val)
inline LogStreamHelper &LogStreamHelper::operator<<(const T &val)
{ {
m_buffer << val; m_buffer << val;
if (!m_logger.noSpace()) if (!m_logger.noSpace())
m_buffer << " "; m_buffer << " ";
return *this; return *this;
} }
} // namespace NGL
} //namespace NGL inline std::ostream& operator<<(std::ostream& stream, const QByteArray& str)
inline std::ostream &operator<<(std::ostream &stream, const QByteArray &str)
{ {
stream << std::string(str.data(), str.size()); stream << std::string(str.data(), str.size());
return stream; return stream;
} }
// //
// operator to ease logging (at least via NglLogging) // operator to ease logging (at least via NglLogging)
// //
inline std::ostream &operator<<(std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QPointF& value)
const QPointF &value)
{ {
stream << "QPointF(" << QString::number(value.x(), 'f', 6).toStdString() << "#" << QString::number(value.y(), 'f', 6).toStdString() << ")"; stream << "QPointF(" << QString::number(value.x(), 'f', 6).toStdString() << "#"
return stream; << QString::number(value.y(), 'f', 6).toStdString() << ")";
return stream;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline std::ostream &operator<< (std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QPoint& value)
const QPoint &value)
{ {
stream << "QPoint(" << value.x() << "#" << value.y() << ")"; stream << "QPoint(" << value.x() << "#" << value.y() << ")";
return stream; return stream;
} }
inline std::ostream &operator<< (std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QSize& value)
const QSize &value)
{ {
stream << "QSize(w=" << value.width() << ";h=" << value.height() << ")"; stream << "QSize(w=" << value.width() << ";h=" << value.height() << ")";
return stream; return stream;
}
inline std::ostream &operator<< (std::ostream &stream,
const QSizeF &value)
{
stream << "QSize(w="
<< QString::number(value.width(), 'f', 6).toStdString() << ";h="
<< QString::number(value.height(), 'f', 6).toStdString()
<< ")";
return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QSizeF& value)
inline std::ostream &operator<< (std::ostream &stream,
const QRect &value)
{ {
stream << "QRect(center=" << value.center() stream << "QSize(w=" << QString::number(value.width(), 'f', 6).toStdString()
<< " w=" << value.width() << ";h=" << QString::number(value.height(), 'f', 6).toStdString() << ")";
<< ";h=" << value.height() return stream;
<< " bottomLeft=" << value.bottomLeft()
<< " topRight=" << value.topRight()
<< ")";
return stream;
} }
inline std::ostream &operator<< (std::ostream &stream, inline std::ostream& operator<<(std::ostream& stream, const QRect& value)
const QRectF &value)
{ {
stream << "QRectF(center=" << value.center() stream << "QRect(center=" << value.center() << " w=" << value.width() << ";h=" << value.height()
<< " w=" << QString::number(value.width(), 'f', 3).toStdString() << " bottomLeft=" << value.bottomLeft() << " topRight=" << value.topRight() << ")";
<< ";h=" << QString::number(value.height(), 'f', 3).toStdString() return stream;
<< " bottomLeft=" << value.bottomLeft()
<< " topRight=" << value.topRight()
<< ")";
return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QRectF& value)
inline std::ostream &operator<< (std::ostream &stream,
const QList<int> &value)
{ {
stream << "QList<int>(" << value.size() << "): "; stream << "QRectF(center=" << value.center() << " w=" << QString::number(value.width(), 'f', 3).toStdString()
for (int i : value) << ";h=" << QString::number(value.height(), 'f', 3).toStdString() << " bottomLeft=" << value.bottomLeft()
stream << i << ";"; << " topRight=" << value.topRight() << ")";
return stream; return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QList<int>& value)
inline std::ostream &operator<< (std::ostream &stream,
const QList<QPointF> &value)
{ {
stream << "QList<QPointF>(" << value.size() << "): "; stream << "QList<int>(" << value.size() << "): ";
for (const QPointF &item : value) for (int i : value)
stream << item << ";"; stream << i << ";";
return stream; return stream;
} }
inline std::ostream& operator<<(std::ostream& stream, const QList<QPointF>& value)
inline std::ostream &operator<<(std::ostream &stream, const QString &str)
{ {
return stream << str.toUtf8(); stream << "QList<QPointF>(" << value.size() << "): ";
for (const QPointF& item : value)
stream << item << ";";
return stream;
}
inline std::ostream& operator<<(std::ostream& stream, const QString& str)
{
return stream << str.toUtf8();
} }
namespace NGL namespace NGL
@@ -236,15 +217,12 @@ namespace NGL
namespace NGLLoggerHelper namespace NGLLoggerHelper
{ {
NGLLOGGER_EXPORT void hexDumpHelper(NGL::INGLLogger &logger, NGLLOGGER_EXPORT void hexDumpHelper(NGL::INGLLogger& logger, NGL::LogLevel level, const void* a_data,
NGL::LogLevel level,
const void *a_data,
const unsigned int a_size); const unsigned int a_size);
inline void hexDumpHelper(NGL::INGLLogger &logger,
NGL::LogLevel level, inline void hexDumpHelper(NGL::INGLLogger& logger, NGL::LogLevel level, const QByteArray& data)
const QByteArray &data)
{ {
return hexDumpHelper(logger, level, data.data(), data.size()); return hexDumpHelper(logger, level, data.data(), data.size());
} }
} // namespace NGLLoggerHelper } // namespace NGLLoggerHelper
@@ -260,41 +238,46 @@ NGLLOGGER_EXPORT std::string getMemoryData();
#define LOGFUNCTION Q_FUNC_INFO #define LOGFUNCTION Q_FUNC_INFO
// log this output every time, no matter what log level is enabled // log this output every time, no matter what log level is enabled
#define NOTICE_LOG(logger) \ #define NOTICE_LOG(logger) NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__, __LINE__, Q_FUNC_INFO)
NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO)
#ifdef LTS_DEBUG #ifdef LTS_DEBUG
#define TRACE_LOG(logger) \ #define TRACE_LOG(logger) \
for (bool log_level_enabled = (logger).isTraceEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isTraceEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__, __LINE__, Q_FUNC_INFO)
#else #else
#define TRACE_LOG(logger) \ #define TRACE_LOG(logger) \
for ( ; false; ) \ for (; false;) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Trace, __FILE__, __LINE__, Q_FUNC_INFO)
#endif #endif
#define DEBUG_LOG(logger) \ #define DEBUG_LOG(logger) \
for (bool log_level_enabled = (logger).isDebugEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isDebugEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Debug, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Debug, __FILE__, __LINE__, Q_FUNC_INFO)
#define INFO_LOG(logger) \ #define INFO_LOG(logger) \
for (bool log_level_enabled = (logger).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Info, __FILE__, __LINE__, Q_FUNC_INFO)
#define WARNING_LOG(logger) \ #define WARNING_LOG(logger) \
for (bool log_level_enabled = (logger).isWarningEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isWarningEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Warning, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Warning, __FILE__, __LINE__, Q_FUNC_INFO)
#define ERROR_LOG(logger) \ #define ERROR_LOG(logger) \
for (bool log_level_enabled = (logger).isErrorEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isErrorEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Error, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Error, __FILE__, __LINE__, Q_FUNC_INFO)
#define FATAL_LOG(logger) \ #define FATAL_LOG(logger) \
for (bool log_level_enabled = (logger).isFatalEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (logger).isFatalEnabled(); log_level_enabled; log_level_enabled = false) \
NGL::LogStreamHelper(logger, NGL::LogLevel::Fatal, __FILE__,__LINE__, Q_FUNC_INFO) NGL::LogStreamHelper(logger, NGL::LogLevel::Fatal, __FILE__, __LINE__, Q_FUNC_INFO)
#define STARTUP_LOG(logger) { (logger).logStartup(__FILE__, __LINE__, Q_FUNC_INFO); } #define STARTUP_LOG(logger) \
#define SHUTDOWN_LOG(logger) { (logger).logShutdown(__FILE__, __LINE__, Q_FUNC_INFO); } { \
(logger).logStartup(__FILE__, __LINE__, Q_FUNC_INFO); \
}
#define SHUTDOWN_LOG(logger) \
{ \
(logger).logShutdown(__FILE__, __LINE__, Q_FUNC_INFO); \
}
//============================================================================== //==============================================================================
@@ -303,8 +286,10 @@ NGLLOGGER_EXPORT std::string getMemoryData();
// do something nasty // do something nasty
// MEMORY_LOG() << " after something nasty"; // MEMORY_LOG() << " after something nasty";
#define MEMORY_LOG() \ #define MEMORY_LOG() \
for (bool log_level_enabled = (NGL::getMemoryLogger()).isInfoEnabled(); log_level_enabled; log_level_enabled = false) \ for (bool log_level_enabled = (NGL::getMemoryLogger()).isInfoEnabled(); log_level_enabled; \
NGL::LogStreamHelper(NGL::getMemoryLogger(), NGL::LogLevel::Info, __FILE__,__LINE__, Q_FUNC_INFO) << NGL::getMemoryData() log_level_enabled = false) \
NGL::LogStreamHelper(NGL::getMemoryLogger(), NGL::LogLevel::Info, __FILE__, __LINE__, Q_FUNC_INFO) \
<< NGL::getMemoryData()
//============================================================================== //==============================================================================
@@ -13,7 +13,7 @@ if(NOT TARGET GTest::gtest_main)
FetchContent_Declare( FetchContent_Declare(
googletest googletest
GIT_REPOSITORY https://github.com/google/googletest.git GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.13.0 GIT_TAG v1.13.0
) )
# For Windows: Prevent overriding the parent project's compiler/linker settings # For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
@@ -31,6 +31,7 @@ if(BUILD_TESTING)
test_symbology_xml.cpp test_symbology_xml.cpp
test_saa_telegrams.cpp test_saa_telegrams.cpp
test_rti_integration.cpp test_rti_integration.cpp
test_ltswidgets_qt6.cpp
) )
# Check which files actually exist # Check which files actually exist
@@ -0,0 +1,224 @@
/**
* @file test_ltswidgets_qt6.cpp
* @brief Tests für LtsWidgets Qt6-Migration
*
* Tests verify Qt6 API compatibility changes:
* 1. QRandomGenerator usage (replacing qrand())
* 2. Signal/slot connections with Qt6 signatures
* 3. QWheelEvent angleDelta() usage
* 4. QStyleOption::initFrom() usage
*/
#include <gtest/gtest.h>
#include <QRandomGenerator>
#include <QComboBox>
#include <QWheelEvent>
#include <QStyleOption>
#include <QPushButton>
#include <QApplication>
// Ensure QApplication is initialized for widget tests
static bool appInitialized = false;
static void ensureAppInitialized() {
if (!appInitialized) {
static int argc = 1;
static char* argv[] = { (char*)"test_ltswidgets_qt6", nullptr };
static QApplication app(argc, argv);
appInitialized = true;
}
}
// Test 1: QRandomGenerator bounded generation (used in lts_tab_widget.cpp)
TEST(LtsWidgetsQt6, QRandomGeneratorBounded) {
auto* generator = QRandomGenerator::global();
ASSERT_NE(generator, nullptr);
// Test multiple bounded calls to ensure stability
for (int i = 0; i < 100; ++i) {
int value = generator->bounded(10);
EXPECT_GE(value, 0);
EXPECT_LT(value, 10);
}
}
// Test 2: QRandomGenerator produces different values
TEST(LtsWidgetsQt6, QRandomGeneratorVariation) {
auto* generator = QRandomGenerator::global();
QVector<int> values;
for (int i = 0; i < 50; ++i) {
values.append(generator->bounded(1000));
}
// Check that we get some variation (not all same value)
bool hasDifferent = false;
for (int i = 1; i < values.size(); ++i) {
if (values[i] != values[0]) {
hasDifferent = true;
break;
}
}
EXPECT_TRUE(hasDifferent);
}
// Test 3: QRandomGenerator seeded reproducibility
TEST(LtsWidgetsQt6, QRandomGeneratorSeeded) {
QRandomGenerator gen1(12345);
QRandomGenerator gen2(12345);
// Same seed should produce same sequence
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(gen1.bounded(1000), gen2.bounded(1000));
}
}
// Test 4: QComboBox currentTextChanged signal (Qt6 compatible)
// This tests the signal used in lts_text_editor.cpp
TEST(LtsWidgetsQt6, QComboBoxCurrentTextChangedSignal) {
ensureAppInitialized();
QComboBox comboBox;
comboBox.addItem("Option1");
comboBox.addItem("Option2");
comboBox.addItem("Option3");
bool signalReceived = false;
QString receivedText;
QObject::connect(&comboBox, &QComboBox::currentTextChanged,
[&signalReceived, &receivedText](const QString& text) {
signalReceived = true;
receivedText = text;
});
comboBox.setCurrentIndex(1);
EXPECT_TRUE(signalReceived);
EXPECT_EQ(receivedText, "Option2");
}
// Test 5: QComboBox activated signal with int parameter (Qt6)
// Note: activated signal is only emitted on user interaction, not on setCurrentIndex
TEST(LtsWidgetsQt6, QComboBoxActivatedIntSignal) {
ensureAppInitialized();
QComboBox comboBox;
comboBox.addItem("First");
comboBox.addItem("Second");
comboBox.addItem("Third");
bool signalReceived = false;
int receivedIndex = -1;
// Connect using Qt6 syntax - activated emits int index
QObject::connect(&comboBox, QOverload<int>::of(&QComboBox::activated),
[&signalReceived, &receivedIndex](int index) {
signalReceived = true;
receivedIndex = index;
});
// Simulate user interaction by emitting the signal manually
// (setCurrentIndex does not trigger activated signal)
QMetaObject::invokeMethod(&comboBox, "activated", Qt::QueuedConnection, Q_ARG(int, 2));
QCoreApplication::processEvents();
// Verify the connection works with int parameter
EXPECT_TRUE(signalReceived);
EXPECT_EQ(receivedIndex, 2);
}
// Test 6: QStyleOption::initFrom() (Qt6 replacement for init())
// This tests the API used in lts_notification_box.cpp
TEST(LtsWidgetsQt6, QStyleOptionInitFrom) {
ensureAppInitialized();
QPushButton button("Test");
button.resize(100, 30);
button.setEnabled(true);
QStyleOption opt;
opt.initFrom(&button);
// Verify initFrom sets up the option correctly
// State_Enabled should be set (among other states)
EXPECT_TRUE(opt.state & QStyle::State_Enabled);
EXPECT_FALSE(opt.rect.isNull());
}
// Test 7: QStyleOption multiple widgets
TEST(LtsWidgetsQt6, QStyleOptionInitFromMultipleWidgets) {
ensureAppInitialized();
QPushButton button1("Btn1");
QPushButton button2("Btn2");
button1.setEnabled(true);
button2.setEnabled(false);
QStyleOption opt1;
opt1.initFrom(&button1);
QStyleOption opt2;
opt2.initFrom(&button2);
// Verify different widget states are captured
EXPECT_TRUE(opt1.state & QStyle::State_Enabled);
EXPECT_FALSE(opt2.state & QStyle::State_Enabled);
}
// Test 8: QWheelEvent angleDelta() availability
// This verifies the API used in lts_date_time_edit_p.cpp
TEST(LtsWidgetsQt6, QWheelEventAngleDelta) {
ensureAppInitialized();
QPoint pos(100, 100);
QPoint globalPos(200, 200);
QPoint pixelDelta(0, 0);
QPoint angleDelta(0, 120); // Standard wheel step
QWheelEvent wheelEvent(pos, globalPos, pixelDelta, angleDelta,
Qt::NoButton, Qt::NoModifier,
Qt::NoScrollPhase, false);
// Verify angleDelta() is accessible and returns correct value
QPoint delta = wheelEvent.angleDelta();
EXPECT_EQ(delta.y(), 120);
EXPECT_EQ(delta.x(), 0);
}
// Test 9: QWheelEvent negative angleDelta
TEST(LtsWidgetsQt6, QWheelEventNegativeAngleDelta) {
ensureAppInitialized();
QPoint pos(100, 100);
QPoint globalPos(200, 200);
QPoint pixelDelta(0, 0);
QPoint angleDelta(0, -120); // Scroll down
QWheelEvent wheelEvent(pos, globalPos, pixelDelta, angleDelta,
Qt::NoButton, Qt::NoModifier,
Qt::NoScrollPhase, false);
QPoint delta = wheelEvent.angleDelta();
EXPECT_EQ(delta.y(), -120);
// Test the logic used in lts_date_time_edit_p.cpp
bool isUp = delta.y() > 0;
EXPECT_FALSE(isUp);
}
// Test 10: QWheelEvent angleDelta direction detection
TEST(LtsWidgetsQt6, QWheelEventDirectionDetection) {
ensureAppInitialized();
// Simulate wheel up (positive delta)
QPoint angleDeltaUp(0, 120);
QWheelEvent wheelUp(QPoint(0, 0), QPoint(0, 0), QPoint(0, 0), angleDeltaUp,
Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
EXPECT_TRUE(wheelUp.angleDelta().y() > 0);
// Simulate wheel down (negative delta)
QPoint angleDeltaDown(0, -120);
QWheelEvent wheelDown(QPoint(0, 0), QPoint(0, 0), QPoint(0, 0), angleDeltaDown,
Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
EXPECT_FALSE(wheelDown.angleDelta().y() > 0);
}