From 5d1e66f5faa3efa71f078fb73df2eada00d3afbb Mon Sep 17 00:00:00 2001 From: "PANIK\\chris" Date: Mon, 5 Jan 2026 23:39:45 +0100 Subject: [PATCH] Ongoing GUI updates. --- BionxControl.pro | 5 +- bcdeviceview.cpp | 4 ++ bcdriver.cpp | 11 ++++ bcdriver.h | 30 ---------- bcdrivertinycan.cpp | 61 ++++++++++++++----- bcguihelpers.cpp | 139 ++++++++++++++++++++++++++++++++------------ bcguihelpers.h | 24 ++++++-- bcmainwindow.cpp | 68 ++++++++++++++++++++-- bcmainwindow.h | 7 ++- bcmainwindow.ui | 16 ++--- bctransmitter.cpp | 8 ++- bctransmitter.h | 2 +- doc/Challenges.docx | Bin 17353 -> 17650 bytes main.cpp | 19 +----- 14 files changed, 271 insertions(+), 123 deletions(-) diff --git a/BionxControl.pro b/BionxControl.pro index 0bc7ece..3706654 100644 --- a/BionxControl.pro +++ b/BionxControl.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui svg greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -12,7 +12,8 @@ QMAKE_CXXFLAGS += -std=c++23 INCLUDEPATH += . libwin -linux:contains(QT_ARCH, arm.*) { +linux:contains(QT_ARCH, arm.*) +{ message("Konfiguration für Raspberry Pi (ARM) erkannt.") # 1. Header-Dateien (z.B. für bcm2835.h oder eigene Treiber) diff --git a/bcdeviceview.cpp b/bcdeviceview.cpp index c3b1d29..790f1be 100644 --- a/bcdeviceview.cpp +++ b/bcdeviceview.cpp @@ -45,12 +45,16 @@ BCDeviceView::BCDeviceView(QWidget *parent) _itemDelegate = new BCAnimatedDelegate( _valueModel.getValueList(), this); setItemDelegate( _itemDelegate ); + qDebug() << " --- View size I: " << this->size(); + } void BCDeviceView::setDeviceID( BCDevice::ID deviceID ) { + qDebug() << " --- View size II: " << this->size(); + _devideID = deviceID; } diff --git a/bcdriver.cpp b/bcdriver.cpp index b3662ff..4e3c8c1 100644 --- a/bcdriver.cpp +++ b/bcdriver.cpp @@ -36,6 +36,9 @@ #include +/** + * @brief Gibt den Treiberstatus zurück. + */ BCDriver::DriverState BCDriver::getDriverState() const { @@ -63,6 +66,9 @@ BCDriver::DriverStateResult BCDriverDummy::loadAndStartDriver() /// ----------------------------------------------------------------------------------- /// ----------------------------------------------------------------------------------- +/** + * @brief Gibt ein Zufallsbyte zurück. + */ TransmitResult BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID ) const { @@ -73,6 +79,11 @@ TransmitResult BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID return myRandomByte; } + +/** + * @brief Simuliert erfolgreiches scheiben. Tut nix. + */ + TransmitResult BCDriverDummy::writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const { Q_UNUSED(deviceID) diff --git a/bcdriver.h b/bcdriver.h index 0d24f3e..81415d6 100644 --- a/bcdriver.h +++ b/bcdriver.h @@ -37,36 +37,6 @@ #include #include -/* -int32_t CanInitDriver(char *options); -void CanDownDriver(void); -int32_t CanSetOptions(char *options); -int32_t CanDeviceOpen(uint32_t index, char *parameter); -int32_t CanDeviceClose(uint32_t index); - -int32_t CanSetMode(uint32_t index, unsigned char can_op_mode, uint16_t can_command); - -int32_t CanTransmit(uint32_t index, struct TCanMsg *msg, int32_t count); -void CanTransmitClear(uint32_t index); -uint32_t CanTransmitGetCount(uint32_t index); -int32_t CanTransmitSet(uint32_t index, uint16_t cmd, uint32_t time); -int32_t CanReceive(uint32_t index, struct TCanMsg *msg, int32_t count); -void CanReceiveClear(uint32_t index); -uint32_t CanReceiveGetCount(uint32_t index); - -int32_t CanSetSpeed(uint32_t index, uint16_t speed); -int32_t CanSetSpeedUser(uint32_t index, uint32_t value); -char* CanDrvInfo(void); -char* CanDrvHwInfo(uint32_t index); -int32_t CanSetFilter(uint32_t index, struct TMsgFilter *msg_filter); -int32_t CanGetDeviceStatus(uint32_t index, struct TDeviceStatus *status); -void CanSetPnPEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, int32_t status)); -void CanSetStatusEventCallback(void (DRV_CALLBACK_TYPE *event) (uint32_t index, struct TDeviceStatus *device_status) ); -void CanSetRxEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, struct TCanMsg *msg, int32_t count) ); - -void CanSetEvents( uint16_t events ); -uint32_t CanEventStatus(void); -*/ struct CBCItem; class BCDriverStatus; diff --git a/bcdrivertinycan.cpp b/bcdrivertinycan.cpp index 4461173..33e4179 100644 --- a/bcdrivertinycan.cpp +++ b/bcdrivertinycan.cpp @@ -37,12 +37,48 @@ #if defined(Q_OS_WIN) + // Unter Windows steht der Treibername in der registry static const char* cMHS_DRIVERNAME = NULL; #elif defined(Q_OS_LINUX) -// Linux-spezifischer Code (z.B. /proc Filesystem, D-Bus) + // Unter linux(artigen) muss der Treibername explizit mit übergeben werden static const char* cMHS_DRIVERNAME = "libmhstcan.so"; #endif +/* + + // TinyCan C-Api + // ------------- + +int32_t CanInitDriver(char *options); +void CanDownDriver(void); +int32_t CanSetOptions(char *options); +int32_t CanDeviceOpen(uint32_t index, char *parameter); +int32_t CanDeviceClose(uint32_t index); + +int32_t CanSetMode(uint32_t index, unsigned char can_op_mode, uint16_t can_command); + +int32_t CanTransmit(uint32_t index, struct TCanMsg *msg, int32_t count); +void CanTransmitClear(uint32_t index); +uint32_t CanTransmitGetCount(uint32_t index); +int32_t CanTransmitSet(uint32_t index, uint16_t cmd, uint32_t time); +int32_t CanReceive(uint32_t index, struct TCanMsg *msg, int32_t count); +void CanReceiveClear(uint32_t index); +uint32_t CanReceiveGetCount(uint32_t index); + +int32_t CanSetSpeed(uint32_t index, uint16_t speed); +int32_t CanSetSpeedUser(uint32_t index, uint32_t value); +char* CanDrvInfo(void); +char* CanDrvHwInfo(uint32_t index); +int32_t CanSetFilter(uint32_t index, struct TMsgFilter *msg_filter); +int32_t CanGetDeviceStatus(uint32_t index, struct TDeviceStatus *status); +void CanSetPnPEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, int32_t status)); +void CanSetStatusEventCallback(void (DRV_CALLBACK_TYPE *event) (uint32_t index, struct TDeviceStatus *device_status) ); +void CanSetRxEventCallback(void (DRV_CALLBACK_TYPE *event)(uint32_t index, struct TCanMsg *msg, int32_t count) ); + +void CanSetEvents( uint16_t events ); +uint32_t CanEventStatus(void); +*/ + /** * @brief Destruktor. Entlädt den CAN-Bus Treiber wieder. */ @@ -76,8 +112,6 @@ BCDriver::DriverStateResult BCDriverTinyCan::loadDriver() { auto callLoadDriver = [&]() -> DriverStateResult { - qDebug() << " -- Hier!"; - //if( ::LoadDriver( NULL ) < 0 ) if( ::LoadDriver( cMHS_DRIVERNAME ) < 0 ) return std::unexpected(QString("Driver Error: 'LoadDriver'")); _driverState = DriverState::Loaded; @@ -126,19 +160,20 @@ BCDriver::DriverStateResult BCDriverTinyCan::loadDriver() .and_then( callInitDriver ) .and_then( callOpenDevice ); - // success: - if(newDriverState) - { - // return 'DriverState::Opened' - return _driverState; - } - // return driver error message, - // _driverState ist irgendwo unter DriverState::Opened + // in Fehlerfall ist der Errorstring gesetzt, + // der interne _driverstate ist + // irgendwo unter DriverState::Opened return newDriverState; } -// __fix + +/** + * @brief Um mit dem Bionx eBike reden zu können, müssen wir + * die Console in den Slave-Mode setzen. + * @return Fehlerstring oder DriverState::DeviceReady + */ + BCDriver::DriverStateResult BCDriverTinyCan::setConsoleSlaveMode() { @@ -164,7 +199,6 @@ BCDriver::DriverStateResult BCDriverTinyCan::setConsoleSlaveMode() unsigned int retry = cTimeOuts; - do { writeRawByte( console, slaveFlag, 1 ); @@ -192,6 +226,7 @@ void BCDriverTinyCan::resetDriver() } } + /** * @brief BCDriverTinyCan::readRawByte * Kapselt den Treiberzugiff über die legacy C-Api. Liest ein byte, gibt dieses im std::expected aber diff --git a/bcguihelpers.cpp b/bcguihelpers.cpp index 5894ca5..59358e8 100644 --- a/bcguihelpers.cpp +++ b/bcguihelpers.cpp @@ -32,16 +32,18 @@ #include + BCThemeSwitchButton::BCThemeSwitchButton(QWidget *parent ) - : QPushButton(parent), _isDarkMode(true) + : QPushButton(parent) { - // 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor + // Visuelles Setup: Flach, keine Ränder, Hand-Cursor setFlat(true); setCursor(Qt::PointingHandCursor); setFixedSize(24, 24); // Kleiner Footprint im StatusBar // CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt // Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind + /* setStyleSheet(R"( QPushButton { border: none; @@ -53,17 +55,30 @@ BCThemeSwitchButton::BCThemeSwitchButton(QWidget *parent ) border-radius: 24px; } )"); - - // 2. Initialer Status (Startet im Dark Mode -> zeigt Mond) + */ + // Initialer Status (Startet im Dark Mode -> zeigt Mond) updateIcon(); - // 3. Klick verbinden connect(this, &QPushButton::clicked, this, &BCThemeSwitchButton::toggle); } +/** + * @brief Setzt den DarkMode + */ -void BCThemeSwitchButton::toggle() +void BCThemeSwitchButton::setDarkMode( bool isDark ) +{ + _isDarkMode = !isDark; + toggleMode(); +} + + +/** + * @brief Schaltet den akutellen Mode um. + */ + +void BCThemeSwitchButton::toggleMode() { _isDarkMode = !_isDarkMode; updateIcon(); @@ -71,13 +86,17 @@ void BCThemeSwitchButton::toggle() } +/** + * @brief Icon & Tooltip anpassen + */ + void BCThemeSwitchButton::updateIcon() { // Logik: // Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack). // Hier: Zeige das Symbol des AKTUELLEN Modus. setText(_isDarkMode ? "🌙" : "☀️"); - setToolTip(_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode"); + setToolTip(_isDarkMode ? "Zum LightMode wechseln" : "Zum DarkMode wechseln"); } @@ -85,22 +104,20 @@ void BCThemeSwitchButton::updateIcon() /// ----------------------------------------------------------------------------------- - +/** + * @brief Hilfswidget: Zeigt den DriverState als Icon an. + */ BCDriverStateWidget::BCDriverStateWidget(QWidget* parent) : QWidget(parent) { QHBoxLayout* layout = new QHBoxLayout(this); layout->setContentsMargins(10, 2, 10, 2); - layout->setSpacing(8); - - _label = new QLabel(this); - _label->setStyleSheet("font-weight: 500;"); // Medium weight + //layout->setSpacing(8); _led = new QLabel(this); _led->setFixedSize(12, 12); - layout->addWidget(_label); layout->addWidget(_led); // Startzustand @@ -115,31 +132,11 @@ void BCDriverStateWidget::onDriverStateChanged(BCDriver::DriverState state, cons { _state = state; qDebug() << " --- StateWidget: " << state << " - " << customMessage; - // Standard-Texte, falls keine Nachricht übergeben wurde - QString text = customMessage; - if (text.isEmpty()) - { - switch (_state) - { - case BCDriver::DriverState::DeviceReady: - text = "Device Ready"; - break; - - case BCDriver::DriverState::Error: - text = "Driver Error"; - break; - - default: - text = "Not Present"; - break; - } - } - _label->setText(text); updateStyle(); } - +/* void BCDriverStateWidget::updateStyle() { QString ledStyle; @@ -181,8 +178,76 @@ void BCDriverStateWidget::updateStyle() setToolTip(toolTipText); } - - - +*/ + +void BCDriverStateWidget::updateStyle() +{ + QString ledStyle; + QString toolTipText; + /* + NotPresent, + Error, + Loaded, + Initialized, + Opened, // bis hierher: dll vorhanden, Treiber geladen + DeviceReady + */ + switch (_state) + { + case BCDriver::DriverState::NotPresent: + // FLUENT GRAY (Neutral) + // Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look + ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;"; + toolTipText = "Treiber nicht geladen."; + break; + + case BCDriver::DriverState::Error: + // FLUENT RED (Critical) + ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;"; + toolTipText = "Fehler beim Laden des Treibers."; + break; + + // hier: dll vorhanden, Treiber geladen + case BCDriver::DriverState::Loaded: + case BCDriver::DriverState::Initialized: + case BCDriver::DriverState::Opened: + // FLUENT RED (Critical) + ledStyle = "background-color: #FF8C00; border: 1px solid #A80000;"; + toolTipText = "Fehler beim Laden des Treibers."; + break; + + case BCDriver::DriverState::DeviceReady: + // FLUENT GREEN (Success) + ledStyle = "background-color: #107C10; border: 1px solid #0E600E;"; + toolTipText = "Verbindung erfolgreich hergestellt."; + break; + + } + + // Styles anwenden (immer rund machen) + _led->setStyleSheet(ledStyle + "border-radius: 6px;"); + + /* + // Textfarbe setzen + _setStyleSheet(QString("color: %1; font-weight: %2;") + .arg(labelColor) + .arg(_state == BCDriver::DriverState::DeviceReady ? "bold" : "normal")); + */ + setToolTip(toolTipText); +} + +void BCDriverStateWidget::mouseReleaseEvent(QMouseEvent* event) +{ + qDebug() << " --- RELAASE!"; + + if (event->button() == Qt::LeftButton) + { + qDebug() << " --- MOO?!"; + + emit clicked(); + } + + QWidget::mouseReleaseEvent(event); +} diff --git a/bcguihelpers.h b/bcguihelpers.h index 4b2d480..8caca4a 100644 --- a/bcguihelpers.h +++ b/bcguihelpers.h @@ -36,10 +36,16 @@ #include #include #include +#include #include +/** + * @brief Einfaches Buttonwidget, um zwischen Dark- und Lightmode + * zu wechseln + */ + class BCThemeSwitchButton : public QPushButton { Q_OBJECT @@ -47,6 +53,7 @@ class BCThemeSwitchButton : public QPushButton public: explicit BCThemeSwitchButton(QWidget *parent = nullptr); + void setDarkMode( bool isDark ); signals: @@ -54,13 +61,13 @@ signals: private slots: - void toggle(); + void toggleMode(); private: void updateIcon(); - bool _isDarkMode; + bool _isDarkMode{false}; }; @@ -70,6 +77,11 @@ private: /// ----------------------------------------------------------------------------------- +/** + * @brief Einfaches Widget, um den Zustand des TinyCan Native + * Drivers anzuzeigen. + */ + class BCDriverStateWidget : public QWidget { Q_OBJECT @@ -84,12 +96,16 @@ public slots: // 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen. void onDriverStateChanged(BCDriver::DriverState state, const QString& customMessage = QString()); -private: +signals: + + void clicked(); + +protected: void updateStyle(); + void mouseReleaseEvent(QMouseEvent* event) override; QLabel* _led; - QLabel* _label; BCDriver::DriverState _state; }; diff --git a/bcmainwindow.cpp b/bcmainwindow.cpp index 5f7353f..356effa 100644 --- a/bcmainwindow.cpp +++ b/bcmainwindow.cpp @@ -29,7 +29,7 @@ ***************************************************************************/ - +#include #include #include "qassert.h" @@ -119,6 +119,7 @@ void BCMainWindow::initMainWindow() configureAction(_batteryButton, _batteryAction, BCDevice::ID::Battery ); //configureAction(_pimpButton, _pimpAction, BCDevice::ID::Pimp ); + /* bool m_isDarkMode = false; QString icon = m_isDarkMode ? "☀️" : "🌙"; @@ -165,23 +166,74 @@ void BCMainWindow::initMainWindow() } +/* +// 2. Bild für den Zustand UNCHECKED (Off) hinzufügen +// Das ist das Symbol, wenn NICHT verbunden ist (z.B. ein Stecker) +connectIcon.addFile(":/icons/plug_disconnected.svg", QSize(), QIcon::Normal, QIcon::Off); + +// 3. Bild für den Zustand CHECKED (On) hinzufügen +// Das ist das Symbol, wenn verbunden IST (z.B. Stecker in Dose) +connectIcon.addFile(":/icons/plug_connected.svg", QSize(), QIcon::Normal, QIcon::On); +*/ void BCMainWindow::initStatusBar() { QStatusBar *statBar = statusBar(); - BCDriverStateWidget* connector = new BCDriverStateWidget(this); - connect( &_transmitter, &BCTransmitter::driverStateChanged, connector, &BCDriverStateWidget::onDriverStateChanged ); - statBar->addPermanentWidget(connector); + BCDriverStateWidget* conState = new BCDriverStateWidget(this); + connect( &_transmitter, &BCTransmitter::driverStateChanged, conState, &BCDriverStateWidget::onDriverStateChanged ); + connect( conState, &BCDriverStateWidget::clicked, _connectAction, &QAction::trigger ); - statBar->showMessage("Ready"); - BCThemeSwitchButton *themeBtn = new BCThemeSwitchButton(this); + statBar->addPermanentWidget(conState); + conState->installEventFilter(this); + + BCThemeSwitchButton* themeBtn = new BCThemeSwitchButton(this); statBar->addPermanentWidget(themeBtn); connect(themeBtn, &BCThemeSwitchButton::themeChanged, this, [this](bool isDark) { QString message = isDark ? "Dark Mode Activated" : "Light Mode Activated"; statusBar()->showMessage( message, 3000); + setApplicationStyleSheet( isDark ? ":/claude_dark_mode.qss"_L1 : ":/claude_light_mode.qss"_L1 ); }); + + // Wir starten im light mode + //themeBtn->setDarkMode( false ); + + statBar->showMessage("Ready"); +} + +/* +bool BCMainWindow::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == myWidget && event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->button() == Qt::LeftButton) { + myAction->trigger(); + return true; // Event wurde verarbeitet + } + } + return QObject::eventFilter(obj, event); +} +*/ + +/** + * @brief Setzt das Stylesheet, hier: Dark- oder Lightmode + * @param path Der Pfad zuum Stylesheet + * @return + */ + +bool BCMainWindow::setApplicationStyleSheet( QAnyStringView path ) +{ + QFile styleFile( path.toString() ); + if (styleFile.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QString style = styleFile.readAll(); + qApp->setStyleSheet(style); + styleFile.close(); + return false; + } + qWarning() << "Konnte Stylesheet nicht laden:" << styleFile.errorString(); + return true; } @@ -195,6 +247,10 @@ void BCMainWindow::setHeaderLabel( const QString& headerText) _headerLabel->setText( " BionxControl: " + headerText ); } +void BCMainWindow::onShowMessage( const QString& message, int timeOut ) +{ + _statusbar->showMessage( message, timeOut ); +} void BCMainWindow::autoConnect() { diff --git a/bcmainwindow.h b/bcmainwindow.h index 4dda74c..3b0bddc 100644 --- a/bcmainwindow.h +++ b/bcmainwindow.h @@ -60,10 +60,12 @@ public slots: void onConnectButtonToggled(bool active ); void onDriverStateChanged( BCDriver::DriverState state, const QString& message="" ); - // Slots für Rückmeldungen vom Runner + // Slots für Rückmeldungen vom Transmitter void onValueUpdated( BCDevice::ID deviceID, int index, BCValue::State state, const QString& newValue="" ); void onSyncDeviceView(); + void onShowMessage( const QString& message, int timeOut=3000); + signals: // Internes Signal, um Daten an den Worker Thread zu senden @@ -71,10 +73,13 @@ signals: protected: + bool setApplicationStyleSheet( QAnyStringView path ); void initMainWindow(); void initStatusBar(); void autoConnect(); + //bool eventFilter(QObject *obj, QEvent *event) override; + BCXmlLoader _dataManager; // Wir brauchen eine Verbindung zwischen den Views diff --git a/bcmainwindow.ui b/bcmainwindow.ui index c2af381..71e4ac3 100644 --- a/bcmainwindow.ui +++ b/bcmainwindow.ui @@ -19,6 +19,9 @@ + + + @@ -169,13 +172,6 @@ - - - - Fitze - - - @@ -318,7 +314,11 @@ - + + + background-color: #DADADA + + true diff --git a/bctransmitter.cpp b/bctransmitter.cpp index af9150b..b2c473c 100644 --- a/bctransmitter.cpp +++ b/bctransmitter.cpp @@ -44,11 +44,9 @@ BCTransmitter::BCTransmitter(QObject *parent) { //_canDriver = new BCDriverTinyCan{this}; _canDriver = &_dummyDriver; - } - /** * @brief Steuert die Verbindung mit dem 'echten' CAN-Bus Treiber. * @param connect true: Vesuche den CAN-Bus Treiber zu laden und zu verbinden @@ -59,6 +57,10 @@ void BCTransmitter::onToggleDriverConnection( bool connect ) { qDebug() << " --- onToggleDriverConnection: " << connect; // FIX! Ende der current op abwarten! + BCDriver::DriverState state = connect ? BCDriver::DriverState::DeviceReady : BCDriver::DriverState::NotPresent; + const QString& message = connect ? "Trying to connect" : " FAILED"; + emit driverStateChanged(state, message); + return; // Hier sind wir noch in GUI Thread QMutexLocker locker(&_mutex); @@ -69,7 +71,7 @@ void BCTransmitter::onToggleDriverConnection( bool connect ) } -void BCTransmitter::onStartNativeDirver() +void BCTransmitter::onStartNativeDriver() { } diff --git a/bctransmitter.h b/bctransmitter.h index f47e58c..8eb0265 100644 --- a/bctransmitter.h +++ b/bctransmitter.h @@ -65,7 +65,7 @@ public slots: void onToggleDriverConnection( bool connect ); void onEnqueueValue(BCValuePtrConst value ); void onProcessValue(); - void onStartNativeDirver(); + void onStartNativeDriver(); signals: diff --git a/doc/Challenges.docx b/doc/Challenges.docx index b0c3d6f32e2901ec669806258cf33170f7d2e028..32177f2ee8c7fb79fb8bb3512bc8f323e88fbe4d 100644 GIT binary patch delta 6754 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 MDH`NeiT{iJ2iM`-v;Y7A delta 6397 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 diff --git a/main.cpp b/main.cpp index 14005cb..55f1a37 100644 --- a/main.cpp +++ b/main.cpp @@ -39,32 +39,15 @@ #include -#include -#include -bool setApplicationStyleSheet( QAnyStringView path ) -{ - QFile styleFile( path.toString() ); - if (styleFile.open(QIODevice::ReadOnly | QIODevice::Text)) - { - QString style = styleFile.readAll(); - qApp->setStyleSheet(style); - styleFile.close(); - return true; - } - qWarning() << "Konnte Stylesheet nicht laden:" << styleFile.errorString(); - return true; -} - int main(int argc, char *argv[]) { QApplication app(argc, argv); - //setApplicationStyleSheet( ":/claude_light_mode.qss"_L1 ); - /* + /* app.setStyleSheet(R"( QWidget { background-color: #F3F3F3;