Add design prototype, some renamings.

This commit is contained in:
2025-12-22 21:27:20 +01:00
parent 4bd8f30a09
commit 03381ea705
20 changed files with 1219 additions and 159 deletions

View File

@@ -26,14 +26,14 @@ windows
SOURCES += \
bc.cpp \
bcdata.cpp \
bcdatamodel.cpp \
bcitemdelegate.cpp \
bctransmitter.cpp \
bcvaluemodel.cpp \
bcvdatamanager.cpp \
lib/can_drv_win.c \
bccandriver.cpp \
bccandrivertinycan.cpp \
bcvalue.cpp \
bcvaluemanager.cpp \
main.cpp \
bcmainwindow.cpp
@@ -41,12 +41,12 @@ HEADERS += \
bc.h \
bccandriver.h \
bccandrivertinycan.h \
bcdata.h \
bcdatamodel.h \
bcitemdelegate.h \
bcmainwindow.h \
bctransmitter.h \
bcvalue.h \
bcvaluemanager.h \
bcvaluemodel.h
bcvdatamanager.h
FORMS += \
bcmainwindow.ui

View File

@@ -30,14 +30,14 @@
#include <QMetaEnum>
#include <bcvalue.h>
#include <bcdata.h>
BCValueType::BCValueType()
BCDataType::BCDataType()
{
}
BCValueType::BCValueType( TypeID ID_, QString unitLabel_, optDouble factor_, optDouble min_, optDouble max_ )
BCDataType::BCDataType( TypeID ID_, QString unitLabel_, optDouble factor_, optDouble min_, optDouble max_ )
: ID{ID_}, unitLabel{unitLabel_}, factor{factor_}, min{min_}, max{max_}
{
@@ -46,25 +46,18 @@ BCValueType::BCValueType( TypeID ID_, QString unitLabel_, optDouble factor_, opt
///-------------------------------
/*
BCValue::BCValue()
{
}
*/
BCValue::BCValue(const BCValueType& valueType_, BCDevice::ID deviceID_, BC::ID registerID_)
BCData::BCData(const BCDataType& valueType_, BCDevice::ID deviceID_, BC::ID registerID_)
: valueType{valueType_}, deviceID{deviceID_}, registerID{registerID_}
{
value = "--";
}
void BCValue::readRawValue( const BCAbstractTransmitter& transmitter ) const
{
}
void BCValue::writeRawValue( const BCAbstractTransmitter& transmitter ) const
void BCData::readRawValue( const BCAbstractTransmitter& transmitter ) const
{
bcdata_t rawValue = transmitter.readRawValue( deviceID, registerID );
}
void BCData::writeRawValue( const BCAbstractTransmitter& transmitter ) const
{
}

View File

@@ -28,8 +28,8 @@
***************************************************************************/
#ifndef BCVALUE_H
#define BCVALUE_H
#ifndef BCDATA_H
#define BCDATA_H
#include <QObject>
#include <QString>
@@ -68,7 +68,7 @@ public:
using optDouble = std::optional<double>;
struct BCValueType
struct BCDataType
{
Q_GADGET
@@ -99,8 +99,8 @@ public:
};
Q_ENUM(TypeID)
BCValueType();
BCValueType( TypeID ID_, QString unitLabel_="", optDouble factor_=std::nullopt, optDouble min_=std::nullopt, optDouble max_= std::nullopt );
BCDataType();
BCDataType( TypeID ID_, QString unitLabel_="", optDouble factor_=std::nullopt, optDouble min_=std::nullopt, optDouble max_= std::nullopt );
TypeID ID{TypeID::Invalid};
QString unitLabel;
@@ -111,41 +111,40 @@ public:
};
// really needed?
using BCValueTypeCRef = std::optional<std::reference_wrapper<const BCValueType>>;
using BCDataTypeCRef = std::optional<std::reference_wrapper<const BCDataType>>;
class BCValue
class BCData
{
public:
//BCValue();
BCValue( const BCValueType& valueType_, BCDevice::ID deviceID_, BC::ID registerID_ );
BCData( const BCDataType& valueType_, BCDevice::ID deviceID_, BC::ID registerID_ );
void readRawValue( const BCAbstractTransmitter& transmitter ) const;
void writeRawValue( const BCAbstractTransmitter& transmitter ) const;
// void reset()
BCValueTypeCRef valueType;
BCDevice::ID deviceID{BCDevice::ID::Invalid};
BC::ID registerID{BC::ID::Invalid};
int rowInModel{-1};
QString label;
QVariant value;
QVariant defaultValue;
BCDataTypeCRef valueType;
BCDevice::ID deviceID{BCDevice::ID::Invalid};
BC::ID registerID{BC::ID::Invalid};
int rowInModel{-1};
QString label;
QVariant value;
QVariant defaultValue;
bool inSync{false};
bool readOnly{false};
bool inSync{false};
bool readOnly{false};
mutable std::optional<bcdata_t> rawValue;
};
Q_DECLARE_METATYPE(BCValue*)
Q_DECLARE_METATYPE(BCData*)
struct BCValueParams
struct BCDataParams
{
QString ID;
QString Label;
@@ -169,7 +168,7 @@ constexpr auto to_u(E e) noexcept {
}
*/
using BCValueList = QVector<BCValue>;
using BCDataList = QVector<BCData>;
#endif // BCVALUE_H
#endif // BCDATA_H

View File

@@ -28,14 +28,14 @@
***************************************************************************/
#include <bcvaluemodel.h>
#include <bcdatamodel.h>
BCValueModel::BCValueModel(QObject *parent) : QAbstractListModel(parent) {}
BCDataModel::BCDataModel(QObject *parent) : QAbstractListModel(parent) {}
void BCValueModel::addValue(const BCValue &val)
void BCDataModel::addValue(const BCData &val)
{
int row = _valueList.size();
beginInsertRows(QModelIndex(), row, row);
@@ -43,42 +43,42 @@ void BCValueModel::addValue(const BCValue &val)
endInsertRows();
}
void BCValueModel::setValueList(const BCValueList& valueList)
void BCDataModel::setValueList(const BCDataList& valueList)
{
beginResetModel();
_valueList = valueList;
endResetModel();
}
BCValueList& BCValueModel::getValueList()
BCDataList& BCDataModel::getValueList()
{
return _valueList;
}
int BCValueModel::rowCount(const QModelIndex &parent) const
int BCDataModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return _valueList.size();
}
QVariant BCValueModel::data(const QModelIndex& index, int role) const
QVariant BCDataModel::data(const QModelIndex& index, int role) const
{
int row = index.row();
if (!index.isValid() || row >= _valueList.size())
return QVariant();
BCValue& value = const_cast<BCValue&>(_valueList.at( row ));
value.rowInModel = row;
BCData& entry = const_cast<BCData&>(_valueList.at( row ));
entry.rowInModel = row;
if (role == Qt::DisplayRole || role == Qt::EditRole)
return QVariant::fromValue(value);
return entry.value;
return QVariant();
}
Qt::ItemFlags BCValueModel::flags(const QModelIndex &index) const
Qt::ItemFlags BCDataModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
@@ -87,11 +87,11 @@ Qt::ItemFlags BCValueModel::flags(const QModelIndex &index) const
}
bool BCValueModel::setData(const QModelIndex &index, const QVariant &value, int role)
bool BCDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole)
{
BCValue item = _valueList[index.row()];
BCData item = _valueList[index.row()];
// Wir erwarten hier nur den Value-Teil (vom Slider/Editor)
// Checken ob Int oder Double

View File

@@ -28,26 +28,25 @@
***************************************************************************/
#ifndef BCVALUEMODEL_H
#define BCVALUEMODEL_H
#ifndef BCDATAMODEL_H
#define BCDATAMODEL_H
#include <QAbstractTableModel>
#include <bcvalue.h>
#include <bcdata.h>
class BCValueModel : public QAbstractListModel
class BCDataModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit BCValueModel(QObject *parent = nullptr);
void addValue(const BCValue &val);
void setValueList(const BCValueList& valueList);
BCValueList& getValueList();
explicit BCDataModel(QObject *parent = nullptr);
void addValue(const BCData &val);
void setValueList(const BCDataList& valueList);
BCDataList& getValueList();
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@@ -58,8 +57,8 @@ public:
private:
BCValueList _valueList;
BCDataList _valueList;
};
#endif // BCVALUEMODEL_H
#endif // BCDATAMODEL_H

View File

@@ -12,7 +12,7 @@
#include <QPainter>
#include "bcitemdelegate.h"
#include "bcvalue.h"
#include "bcdata.h"
#include "qapplication.h"
@@ -27,15 +27,19 @@ BCItemDelegate::BCItemDelegate(QListView *view)
QString BCItemDelegate::displayText(const QVariant& dataValue, const QLocale& locale) const
{
// Wir prüfen, ob im Variant unser Struct steckt
if (dataValue.canConvert<BCValue*>())
if (dataValue.canConvert<BCData*>())
{
BCValue& bc = *dataValue.value<BCValue*>();
//qDebug() << " --- YES: " << bc.label;
BCData& bc = *dataValue.value<BCData*>();
qDebug() << " --- YES: " << bc.label;
// Hier bauen wir den String zusammen, den man sieht,
// wenn KEIN Editor offen ist.
// Format: "Label: Wert Einheit"
return QString("%1: %2 %3").arg(bc.label, bc.value.toString(), "mmX");
}
else
{
qDebug() << " --- Nö!";
}
// Fallback für normale Strings/Zahlen
return QStyledItemDelegate::displayText(dataValue, locale);
@@ -45,10 +49,10 @@ QString BCItemDelegate::displayText(const QVariant& dataValue, const QLocale& lo
QWidget *BCItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QVariant rawData = index.data(Qt::EditRole);
if (!rawData.canConvert<BCValue*>())
if (!rawData.canConvert<BCData*>())
return QStyledItemDelegate::createEditor(parent, option, index);
const BCValue& bc = *rawData.value<BCValue*>();
const BCData& bc = *rawData.value<BCData*>();
// Nur bei Integern den Slider-Editor bauen
if (bc.value.typeId() == QMetaType::Int)
@@ -93,7 +97,7 @@ QWidget *BCItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewIte
void BCItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
// Daten vom Model in den Editor laden
const BCValue& bc = *index.data(Qt::EditRole).value<BCValue*>();
const BCData& bc = *index.data(Qt::EditRole).value<BCData*>();
QSlider *slider = editor->findChild<QSlider*>("slider");
QLabel *lblUnit = editor->findChild<QLabel*>("lblUnit");
@@ -330,9 +334,9 @@ QString BCItemDelegate::formatDisplayString(const QModelIndex &index) const
QString displayStr;
/*
QString label = index.data(BCValueListModel::LabelRole).toString();
QVariant value = index.data(BCValueListModel::ValueRole);
QString unit = index.data(BCValueListModel::UnitRole).toString();
QString label = index.data(BCDataListModel::LabelRole).toString();
QVariant value = index.data(BCDataListModel::ValueRole);
QString unit = index.data(BCDataListModel::UnitRole).toString();
QString valueStr = value.toString();

View File

@@ -62,9 +62,9 @@ BCMainWindow::BCMainWindow(QWidget *parent)
// besser: model::emit dataChanged
// also: emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, ValueRole});
connect( &_valueManager, &BCValueManager::valueTouched, _delegate, &BCItemDelegate::onHighlightRow );
connect( &_valueManager, &BCDataManager::valueTouched, _delegate, &BCItemDelegate::onHighlightRow );
connect( _connectButton, &QPushButton::clicked, transmitter, &BCTransmitter::onToggleConnectionState );
connect( _syncButton, &QPushButton::clicked, &_valueManager, &BCValueManager::onSyncFromDevice );
connect( _syncButton, &QPushButton::clicked, &_valueManager, &BCDataManager::onSyncFromDevice );
}

View File

@@ -33,7 +33,7 @@
#include <QMainWindow>
#include <ui_bcmainwindow.h>
#include <bcvaluemanager.h>
#include <bcvdatamanager.h>
class AnimatedDelegate;
@@ -53,7 +53,7 @@ public slots:
protected:
BCValueManager _valueManager;
BCDataManager _valueManager;
AnimatedDelegate* _delegate;

View File

@@ -50,7 +50,7 @@ void BCTransmitter::onToggleConnectionState( bool connect )
}
void BCTransmitter::enqueueValueOp(BC::OpID opID, const BCValue* value)
void BCTransmitter::enqueueValueOp(BC::OpID opID, const BCData* value)
{
QMutexLocker locker(&_mutex);
_valueQueue.enqueue( value );
@@ -83,7 +83,7 @@ void BCTransmitter::processValueOp( BC::OpID opID )
while (true)
{
const BCValue* currentValue{};
const BCData* currentValue{};
{
QMutexLocker locker(&_mutex);
if (_valueQueue.isEmpty())

View File

@@ -6,9 +6,10 @@
#include <QMutex>
#include <atomic>
#include <bcvalue.h>
#include <bcdata.h>
#include <bccandrivertinycan.h>
// template ...
class BCTransmitter : public QObject, public BCAbstractTransmitter
{
Q_OBJECT
@@ -23,7 +24,7 @@ public:
public slots:
void onToggleConnectionState( bool connect );
void enqueueValueOp(BC::OpID opID, const BCValue* value );
void enqueueValueOp(BC::OpID opID, const BCData* value );
void processValueOp(BC::OpID opID);
signals:
@@ -33,9 +34,9 @@ signals:
private:
using BCValueQueue = QQueue<const BCValue*>;
using BCDataQueue = QQueue<const BCData*>;
BCValueQueue _valueQueue;
BCDataQueue _valueQueue;
QMutex _mutex;
std::atomic<bool> _isBusy{ false };

View File

@@ -37,28 +37,28 @@
#include <QApplication>
#include <QElapsedTimer>
#include <bcvaluemanager.h>
#include <bcvdatamanager.h>
using namespace Qt::StringLiterals;
BCValueManager::BCValueManager(QObject *parent)
BCDataManager::BCDataManager(QObject *parent)
: QObject(parent)
{
createValueTypes();
//qRegisterMetaType<BCValue*>("BCValue*");
qRegisterMetaType<BCValue*>();
//qRegisterMetaType<BCData*>("BCData*");
qRegisterMetaType<BCData*>();
_transmitter.moveToThread(&_worker);
connect(this, &BCValueManager::sendValueCommand, &_transmitter, &BCTransmitter::enqueueValueOp);
connect(this, &BCDataManager::sendValueCommand, &_transmitter, &BCTransmitter::enqueueValueOp);
// B) Ergebnisse empfangen (Runner -> Manager)
//connect(&_transmitter, &BCTransmitter::commandFinished, this, &BCValueManager::onCommandFinished);
//connect(&_transmitter, &BCTransmitter::messageLogged, this, &BCValueManager::onRunnerMessage);
//connect(&_transmitter, &BCTransmitter::commandFinished, this, &BCDataManager::onCommandFinished);
//connect(&_transmitter, &BCTransmitter::messageLogged, this, &BCDataManager::onRunnerMessage);
// C) Aufräumen: Wenn Thread endet, lösche den Runner
connect(&_worker, &QThread::finished, &_transmitter, &QObject::deleteLater);
@@ -67,7 +67,7 @@ BCValueManager::BCValueManager(QObject *parent)
_worker.start();
}
BCValueManager::~BCValueManager()
BCDataManager::~BCDataManager()
{
// nothing to do here for now,
// our models are autokilled.
@@ -77,7 +77,7 @@ BCValueManager::~BCValueManager()
}
void BCValueManager::createValueTypes()
void BCDataManager::createValueTypes()
{
/*
Invalid = 0x0,
@@ -96,44 +96,44 @@ void BCValueManager::createValueTypes()
"Date"
*/
//_valueTypes.insert( { BCValueType::TypeID::Invalid, "Invalid" } );
//_valueTypes.insert( { BCDataType::TypeID::Invalid, "Invalid" } );
_valueTypes.insert( "Invalid", { BCValueType::TypeID::Invalid, "Invalid" } );
_valueTypes.insert( "Text", { BCValueType::TypeID::Text } );
_valueTypes.insert( "Number", { BCValueType::TypeID::Number } );
_valueTypes.insert( "Invalid", { BCDataType::TypeID::Invalid, "Invalid" } );
_valueTypes.insert( "Text", { BCDataType::TypeID::Text } );
_valueTypes.insert( "Number", { BCDataType::TypeID::Number } );
_valueTypes.insert( "Byte", { BCValueType::TypeID::Byte } );
_valueTypes.insert( "Word", { BCValueType::TypeID::Word } );
_valueTypes.insert( "Quad", { BCValueType::TypeID::Quad } );
_valueTypes.insert( "Byte", { BCDataType::TypeID::Byte } );
_valueTypes.insert( "Word", { BCDataType::TypeID::Word } );
_valueTypes.insert( "Quad", { BCDataType::TypeID::Quad } );
_valueTypes.insert( "Float", { BCValueType::TypeID::Float, "", 1.5625} );
_valueTypes.insert( "Percent",{ BCValueType::TypeID::Percent, "%", 1.5625 } );
_valueTypes.insert( "KWh", { BCValueType::TypeID::KWh, "kwh", 1.5625 } );
_valueTypes.insert( "Watt", { BCValueType::TypeID::Watt, "w", 1.5625 } );
_valueTypes.insert( "Km", { BCValueType::TypeID::Km, "km", 1.5625 } );
_valueTypes.insert( "Kmh", { BCValueType::TypeID::Kmh, "km/h", 0.1 } );
_valueTypes.insert( "Mm", { BCValueType::TypeID::Mm, "mm", 1.5625 } );
_valueTypes.insert( "Sec", { BCValueType::TypeID::Sec, "s", 1.5625 } );
_valueTypes.insert( "SoC", { BCValueType::TypeID::SoC, "%", 1.5625 } );
_valueTypes.insert( "Odo", { BCValueType::TypeID::Odo, "km", 1.5625 } );
_valueTypes.insert( "Assist", { BCValueType::TypeID::Assist, "", 0 ,4 } );
_valueTypes.insert( "Assist", { BCValueType::TypeID::AssistFac, "%" } );
_valueTypes.insert( "Date", { BCValueType::TypeID::Date } );
_valueTypes.insert( "Float", { BCDataType::TypeID::Float, "", 1.5625} );
_valueTypes.insert( "Percent",{ BCDataType::TypeID::Percent, "%", 1.5625 } );
_valueTypes.insert( "KWh", { BCDataType::TypeID::KWh, "kwh", 1.5625 } );
_valueTypes.insert( "Watt", { BCDataType::TypeID::Watt, "w", 1.5625 } );
_valueTypes.insert( "Km", { BCDataType::TypeID::Km, "km", 1.5625 } );
_valueTypes.insert( "Kmh", { BCDataType::TypeID::Kmh, "km/h", 0.1 } );
_valueTypes.insert( "Mm", { BCDataType::TypeID::Mm, "mm", 1.5625 } );
_valueTypes.insert( "Sec", { BCDataType::TypeID::Sec, "s", 1.5625 } );
_valueTypes.insert( "SoC", { BCDataType::TypeID::SoC, "%", 1.5625 } );
_valueTypes.insert( "Odo", { BCDataType::TypeID::Odo, "km", 1.5625 } );
_valueTypes.insert( "Assist", { BCDataType::TypeID::Assist, "", 0 ,4 } );
_valueTypes.insert( "Assist", { BCDataType::TypeID::AssistFac, "%" } );
_valueTypes.insert( "Date", { BCDataType::TypeID::Date } );
}
void BCValueManager::onCommandFinished(int id, bool success)
void BCDataManager::onCommandFinished(int id, bool success)
{
qDebug() << "[Manager] Command" << id << "finished. Success:" << success;
}
void BCValueManager::onRunnerMessage(const QString &msg)
void BCDataManager::onRunnerMessage(const QString &msg)
{
qDebug() << "[Worker says]:" << msg;
}
void BCValueManager::onSyncFromDevice()
void BCDataManager::onSyncFromDevice()
{
qDebug() << " ---Syncing";
if( _currentDeviceID != BCDevice::ID::Invalid )
@@ -141,12 +141,12 @@ void BCValueManager::onSyncFromDevice()
if( _valueModels.contains(_currentDeviceID) )
{
BCValueModel* model = _valueModels[_currentDeviceID];
BCValueList& currentList = model->getValueList();
BCDataModel* model = _valueModels[_currentDeviceID];
BCDataList& currentList = model->getValueList();
//BCValue& value = currentList[4];
//BCData& value = currentList[4];
for( const BCValue& value : currentList )
for( const BCData& value : currentList )
{
qDebug() << " --- value: " << value.label;
@@ -169,19 +169,19 @@ void BCValueManager::onSyncFromDevice()
}
}
std::optional<BCValueModel*> BCValueManager::getModel(BCDevice::ID deviceID )
std::optional<BCDataModel*> BCDataManager::getModel(BCDevice::ID deviceID )
{
if( _valueModels.contains( deviceID) )
return _valueModels[deviceID];
return std::nullopt;
}
BCTransmitter* BCValueManager::getTransmitter()
BCTransmitter* BCDataManager::getTransmitter()
{
return &_transmitter;
};
void BCValueManager::loadBikeData()
void BCDataManager::loadBikeData()
{
auto printAttrs = [](const QXmlStreamReader& xml)
{
@@ -231,11 +231,11 @@ void BCValueManager::loadBikeData()
qDebug() << " --- Device: " << _xml.name() << ": " << deviceType << " : " << deviceID;
_currentDeviceID = BCDevice::ID( deviceID.value() );
BCValueList parsedValues;
BCDataList parsedValues;
loadDeviceData( parsedValues );
if( parsedValues.count() )
{
BCValueModel* valueModel = new BCValueModel( this );
BCDataModel* valueModel = new BCDataModel( this );
valueModel->setValueList(parsedValues);
_valueModels.insert( _currentDeviceID, valueModel );
}
@@ -261,7 +261,7 @@ void BCValueManager::loadBikeData()
}
void BCValueManager::loadDeviceData( BCValueList& parsedValues )
void BCDataManager::loadDeviceData( BCDataList& parsedValues )
{
auto printAttrs = [](const QXmlStreamReader& xml)
{
@@ -285,7 +285,7 @@ void BCValueManager::loadDeviceData( BCValueList& parsedValues )
//qDebug() << " --- found: " << _xml.name() << " : " << _xml.attributes().value(BCTags::ID);
QString id = _xml.attributes().value(BCTags::ID).toString();
BCValueParams params
BCDataParams params
{
.ID = id,
.Label = _xml.attributes().value(BCTags::Label).toString(),
@@ -294,10 +294,10 @@ void BCValueManager::loadDeviceData( BCValueList& parsedValues )
};
// __fix! können ungültige werte erzeugt werden ?
//BCValue newValue = BCValue::makeValue( _currentDeviceID, params );
//BCData newValue = BCData::makeValue( _currentDeviceID, params );
//if(newValue)
// parsedValues.push_back( newValue );
std::optional<BCValue> newValue = makeValue( _currentDeviceID, params );
std::optional<BCData> newValue = makeValue( _currentDeviceID, params );
if(newValue)
parsedValues.push_back( *newValue );
}
@@ -307,7 +307,7 @@ void BCValueManager::loadDeviceData( BCValueList& parsedValues )
}
}
std::optional<BCValue> BCValueManager::makeValue( BCDevice::ID deviceID, const BCValueParams& params )
std::optional<BCData> BCDataManager::makeValue( BCDevice::ID deviceID, const BCDataParams& params )
{
/*
@@ -332,7 +332,7 @@ std::optional<BCValue> BCValueManager::makeValue( BCDevice::ID deviceID, const B
*/
std::optional<BCValue> newValue;
std::optional<BCData> newValue;
std::optional<quint64> IDVal = s_bcValueEnum.keyToValue64( params.ID.toLatin1().constData() );
if( IDVal.has_value() )
@@ -340,8 +340,8 @@ std::optional<BCValue> BCValueManager::makeValue( BCDevice::ID deviceID, const B
if( _valueTypes.contains( params.UnitType ) )
{
const BCValueType& valueType = _valueTypes[params.UnitType];
newValue = BCValue( valueType, deviceID, static_cast<BC::ID>(IDVal.value()) );
const BCDataType& valueType = _valueTypes[params.UnitType];
newValue = BCData( valueType, deviceID, static_cast<BC::ID>(IDVal.value()) );
/*
setIfExists( params.Factor, newValue.factor );
@@ -361,7 +361,7 @@ std::optional<BCValue> BCValueManager::makeValue( BCDevice::ID deviceID, const B
}
// --- NEU: Speichern mit QXmlStreamWriter ---
void BCValueManager::saveBikeData()
void BCDataManager::saveBikeData()
{
/*
QString fileName = QFileDialog::getSaveFileName(this, "XML speichern", "", "XML Files (*.xml)");

View File

@@ -28,8 +28,8 @@
***************************************************************************/
#ifndef BCVALUEMANAGER_H
#define BCVALUEMANAGER_H
#ifndef BCVDATAMANAGER_H
#define BCVDATAMANAGER_H
#include <QMap>
#include <QXmlStreamReader>
@@ -37,23 +37,23 @@
#include <QMetaEnum>
#include <QThread>
#include <bcvaluemodel.h>
#include <bcdatamodel.h>
#include <bctransmitter.h>
class BCValueManager : public QObject
class BCDataManager : public QObject
{
Q_OBJECT
public:
BCValueManager( QObject* parent = nullptr);
virtual ~BCValueManager();
BCDataManager( QObject* parent = nullptr);
virtual ~BCDataManager();
std::optional<BCValueModel*> getModel(BCDevice::ID deviceID );
std::optional<BCDataModel*> getModel(BCDevice::ID deviceID );
BCTransmitter* getTransmitter();
std::optional<BCValue> makeValue( BCDevice::ID deviceID, const BCValueParams& params );
std::optional<BCData> makeValue( BCDevice::ID deviceID, const BCDataParams& params );
public slots:
@@ -64,8 +64,8 @@ public slots:
signals:
// Internes Signal, um Daten an den Worker Thread zu senden
void sendValueCommand( BC::OpID, const BCValue* cmd);
//void valuedTouched(const BCValue& cmd);
void sendValueCommand( BC::OpID, const BCData* cmd);
//void valuedTouched(const BCData& cmd);
void valueTouched(int rowInModel );
private slots:
@@ -77,13 +77,13 @@ private slots:
protected:
void createValueTypes();
void loadDeviceData( BCValueList& parsedValues );
void loadDeviceData( BCDataList& parsedValues );
using BCDeviceModels = QMap<BCDevice::ID, BCValueModel*>;
using BCValueTypes = QMap<QString,BCValueType>;
using BCDeviceModels = QMap<BCDevice::ID, BCDataModel*>;
using BCDataTypes = QMap<QString,BCDataType>;
QXmlStreamReader _xml;
BCValueTypes _valueTypes;
BCDataTypes _valueTypes;
BCDeviceModels _valueModels;
BCDevice::ID _currentDeviceID{BCDevice::ID::Invalid};
QMetaEnum _bcDeviceEnum{QMetaEnum::fromType<BCDevice::ID>()};
@@ -93,4 +93,4 @@ protected:
};
#endif // BCVALUEMANAGER_H
#endif // BCVDATAMANAGER_H

View File

@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 18.0.1, 2025-12-22T19:04:55. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{350f6538-4791-42f9-b43d-6ea1a7b22b7b}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="qlonglong">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<value type="int" key="RcSync">0</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="bool" key="HasPerBcDcs">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.10.1 MinGW 64-bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.10.1 MinGW 64-bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.6101.win64_mingw_kit</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\syncMePlease\projects.now\material_dummy\build\Desktop_Qt_6_10_1_MinGW_64_bit-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/syncMePlease/projects.now/material_dummy/build/Desktop_Qt_6_10_1_MinGW_64_bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="qlonglong">1</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>

305
doc/material_dummy/main.cpp Normal file
View File

@@ -0,0 +1,305 @@
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QSlider>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QProxyStyle>
#include <QPainter>
#include <QStyleOptionSlider>
#include <QGraphicsDropShadowEffect>
#include "mainwindow.h"
// Fluent Design Demo Widget
class FluentWidgetDemo : public QWidget {
public:
FluentWidgetDemo() {
setWindowTitle("Fluent Design System - Windows 11");
resize(600, 500);
// Acrylic-like background
setStyleSheet(R"(
QWidget {
background-color: #F3F3F3;
font-family: 'Segoe UI Variable', 'Segoe UI', sans-serif;
}
)");
auto* mainLayout = new QVBoxLayout(this);
mainLayout->setSpacing(20);
mainLayout->setContentsMargins(32, 32, 32, 32);
// Title
auto* title = new QLabel("Fluent Design System");
title->setStyleSheet(R"(
font-size: 28px;
font-weight: 600;
color: #201F1E;
margin-bottom: 8px;
)");
mainLayout->addWidget(title);
auto* subtitle = new QLabel("Windows 11 Style Components");
subtitle->setStyleSheet("font-size: 14px; color: #605E5C;");
mainLayout->addWidget(subtitle);
// Text Input
auto* inputLabel = new QLabel("Text Input");
inputLabel->setStyleSheet("font-size: 12px; color: #323130; font-weight: 600;");
mainLayout->addWidget(inputLabel);
auto* input = new QLineEdit();
input->setPlaceholderText("Enter text here...");
applyFluentInput(input);
mainLayout->addWidget(input);
// Slider Section
auto* sliderLabel = new QLabel("Sliders");
sliderLabel->setStyleSheet("font-size: 12px; color: #323130; font-weight: 600; margin-top: 8px;");
mainLayout->addWidget(sliderLabel);
auto* valueLabel = new QLabel("Volume: 50");
valueLabel->setStyleSheet("font-size: 14px; color: #605E5C;");
mainLayout->addWidget(valueLabel);
auto* hSlider = new QSlider(Qt::Horizontal);
hSlider->setRange(0, 100);
hSlider->setValue(50);
hSlider->setStyle(new FluentSliderStyle());
hSlider->setMinimumHeight(32); // Genug Platz für Handle
mainLayout->addWidget(hSlider);
connect(hSlider, &QSlider::valueChanged, [valueLabel](int value) {
valueLabel->setText(QString("Volume: %1").arg(value));
});
// Checkbox
auto* checkLabel = new QLabel("Checkbox");
checkLabel->setStyleSheet("font-size: 12px; color: #323130; font-weight: 600; margin-top: 8px;");
mainLayout->addWidget(checkLabel);
auto* checkbox = new QCheckBox("Enable feature");
applyFluentCheckbox(checkbox);
mainLayout->addWidget(checkbox);
// Buttons Section
auto* btnLabel = new QLabel("Buttons");
btnLabel->setStyleSheet("font-size: 12px; color: #323130; font-weight: 600; margin-top: 8px;");
mainLayout->addWidget(btnLabel);
auto* btnLayout = new QHBoxLayout();
btnLayout->setSpacing(12);
auto* primaryBtn = new QPushButton("Primary");
applyFluentButton(primaryBtn, ButtonType::Primary);
btnLayout->addWidget(primaryBtn);
auto* secondaryBtn = new QPushButton("Secondary");
applyFluentButton(secondaryBtn, ButtonType::Secondary);
btnLayout->addWidget(secondaryBtn);
auto* subtleBtn = new QPushButton("Subtle");
applyFluentButton(subtleBtn, ButtonType::Subtle);
btnLayout->addWidget(subtleBtn);
btnLayout->addStretch();
mainLayout->addLayout(btnLayout);
// Vertical Sliders
auto* vLabel = new QLabel("Equalizer");
vLabel->setStyleSheet("font-size: 12px; color: #323130; font-weight: 600; margin-top: 8px;");
mainLayout->addWidget(vLabel);
auto* vLayout = new QHBoxLayout();
vLayout->setSpacing(24);
for (int i = 0; i < 5; ++i) {
auto* vSlider = new QSlider(Qt::Vertical);
vSlider->setRange(0, 100);
vSlider->setValue(20 + i * 15);
vSlider->setStyle(new FluentSliderStyle());
vSlider->setMinimumHeight(120);
vSlider->setMinimumWidth(32); // Genug Platz für Handle
vLayout->addWidget(vSlider);
}
vLayout->addStretch();
mainLayout->addLayout(vLayout);
mainLayout->addStretch();
}
private:
enum class ButtonType {
Primary,
Secondary,
Subtle
};
void applyFluentButton(QPushButton* btn, ButtonType type) {
QString baseStyle = R"(
QPushButton {
background-color: %1;
color: %2;
border: %3;
border-radius: 4px;
padding: 5px 12px;
font-size: 14px;
min-height: 32px;
}
QPushButton:hover {
background-color: %4;
border: %5;
}
QPushButton:pressed {
background-color: %6;
border: %7;
}
QPushButton:disabled {
background-color: #F3F2F1;
color: #A19F9D;
border: 1px solid #EDEBE9;
}
)";
switch (type) {
case ButtonType::Primary:
btn->setStyleSheet(baseStyle
.arg("#0078D4") // bg
.arg("white") // text
.arg("none") // border
.arg("#106EBE") // hover bg
.arg("none") // hover border
.arg("#005A9E") // pressed bg
.arg("none") // pressed border
);
break;
case ButtonType::Secondary:
btn->setStyleSheet(baseStyle
.arg("white") // bg
.arg("#201F1E") // text
.arg("1px solid #8A8886") // border
.arg("#F3F2F1") // hover bg
.arg("1px solid #323130") // hover border
.arg("#EDEBE9") // pressed bg
.arg("1px solid #201F1E") // pressed border
);
break;
case ButtonType::Subtle:
btn->setStyleSheet(baseStyle
.arg("transparent") // bg
.arg("#201F1E") // text
.arg("none") // border
.arg("#F3F2F1") // hover bg
.arg("none") // hover border
.arg("#EDEBE9") // pressed bg
.arg("none") // pressed border
);
break;
}
// Subtle shadow for elevation
if (type == ButtonType::Primary) {
auto* shadow = new QGraphicsDropShadowEffect();
shadow->setBlurRadius(4);
shadow->setColor(QColor(0, 0, 0, 40));
shadow->setOffset(0, 1);
btn->setGraphicsEffect(shadow);
}
}
void applyFluentInput(QLineEdit* input) {
input->setStyleSheet(R"(
QLineEdit {
border: 1px solid #8A8886;
border-radius: 4px;
padding: 6px 10px;
background-color: white;
font-size: 14px;
color: #201F1E;
min-height: 32px;
}
QLineEdit:hover {
border: 1px solid #323130;
}
QLineEdit:focus {
border: 2px solid #0078D4;
padding: 5px 9px;
}
QLineEdit:disabled {
background-color: #F3F2F1;
border: 1px solid #EDEBE9;
color: #A19F9D;
}
)");
}
void applyFluentCheckbox(QCheckBox* checkbox) {
checkbox->setStyleSheet(R"(
QCheckBox {
spacing: 8px;
font-size: 14px;
color: #201F1E;
}
QCheckBox::indicator {
width: 20px;
height: 20px;
border: 1px solid #8A8886;
border-radius: 4px;
background-color: white;
}
QCheckBox::indicator:hover {
border: 1px solid #323130;
background-color: #F3F2F1;
}
QCheckBox::indicator:checked {
background-color: #0078D4;
border: 1px solid #0078D4;
}
QCheckBox::indicator:checked:hover {
background-color: #106EBE;
border: 1px solid #106EBE;
}
QCheckBox::indicator:disabled {
background-color: #F3F2F1;
border: 1px solid #C8C6C4;
}
)");
}
};
//#include "main.moc" // Wichtig für Q_OBJECT in .cpp Datei
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Segoe UI is default on Windows
#ifdef Q_OS_WIN
QFont font("Segoe UI Variable", 10);
#else
QFont font("Segoe UI", 10);
#endif
app.setFont(font);
TableViewDemo demo;
demo.show();
FluentWidgetDemo fdemo;
fdemo.show();
return app.exec();
}

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,148 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QApplication>
#include <QWidget>
#include <QTableView>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QSlider>
#include <QPainter>
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QSlider>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QProxyStyle>
#include <QPainter>
#include <QStyleOptionSlider>
#include <QGraphicsDropShadowEffect>
#include "sliderdelegate.h"
class TableViewDemo : public QWidget
{
public:
TableViewDemo()
{
setWindowTitle("QTableView mit QSlider Editor");
resize(700, 400);
auto* layout = new QVBoxLayout(this);
// Model erstellen (3 Spalten, 10 Zeilen)
auto* model = new QStandardItemModel(10, 2, this);
// Header setzen
model->setHorizontalHeaderLabels({"Name", "Wert"});
// Daten einfügen
for (int row = 0; row < 10; ++row) {
auto* nameItem = new QStandardItem(QString("Eintrag %1").arg(row + 1));
auto* valueItem = new QStandardItem();
// Wert-Item editierbar machen
valueItem->setData(row * 10, Qt::EditRole); // Startwert 0-90
valueItem->setEditable(true);
// Andere nicht editierbar
nameItem->setEditable(false);
model->setItem(row, 0, nameItem);
model->setItem(row, 1, valueItem);
}
// TableView erstellen
auto* tableView = new QTableView();
tableView->setModel(model);
// === SLIDER DELEGATE für Spalte 2 ===
//auto* sliderDelegate = new SliderDelegate(this);
//tableView->setItemDelegateForColumn(1, sliderDelegate);
tableView->setAlternatingRowColors(false);
// === LINIEN ENTFERNEN ===
tableView->setShowGrid(false);
// Header Style
tableView->horizontalHeader()->setStyleSheet(R"(
QHeaderView::section {
background-color: #F5F5F5;
padding: 10px;
border: none;
font-weight: bold;
color: #333;
}
)");
// Vertikaler Header ausblenden
tableView->verticalHeader()->setVisible(false);
// Alternating Row Colors
//tableView->setAlternatingRowColors(true);
// Style für TableView
tableView->setStyleSheet(R"(
QTableView
{
background-color: white;
border: none;
selection-background-color: #E3F2FD;
selection-color: black;
}
QTableView::item
{
padding: 10px;
border: none;
}
QTableView::item:selected {
background-color: #E3F2FD;
border: 1px solid #0078D4; /* Rahmen um JEDE Zelle */
}
}
)");
// Spaltenbreite
tableView->setColumnWidth(0, 50);
tableView->setColumnWidth(1, 150);
tableView->horizontalHeader()->setStretchLastSection(true);
// Row Height für bessere Slider-Darstellung
tableView->verticalHeader()->setDefaultSectionSize(40);
// Selection
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
//tableView->setSelectionMode(QAbstractItemView::SingleSelection);
// Edit Trigger - Klick zum Editieren
tableView->setEditTriggers(QAbstractItemView::DoubleClicked |
QAbstractItemView::SelectedClicked);
layout->addWidget(tableView);
// Signal für Änderungen
connect(model, &QStandardItemModel::dataChanged, this,
[](const QModelIndex& topLeft, const QModelIndex& bottomRight) {
if (topLeft.column() ==1) {
int row = topLeft.row();
int value = topLeft.data(Qt::DisplayRole).toInt();
qDebug() << "Zeile" << row << "wurde auf" << value << "gesetzt";
}
});
}
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>18</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,25 @@
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h \
sliderdelegate.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

View File

@@ -0,0 +1,355 @@
#ifndef SLIDERDELEGATE_H
#define SLIDERDELEGATE_H
#include <QStyledItemDelegate>
#include <QApplication>
#include <QWidget>
#include <QTableView>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QSlider>
#include <QPainter>
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QSlider>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QProxyStyle>
#include <QPainter>
#include <QStyleOptionSlider>
#include <QGraphicsDropShadowEffect>
// Custom Delegate für QSlider in Spalte 3
// Fluent Design Slider Style
class FluentSliderStyle : public QProxyStyle
{
public:
FluentSliderStyle()
: QProxyStyle()
{}
// Wichtig: Genug Platz für Handle reservieren
int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override
{
switch (metric)
{
case PM_SliderThickness:
return 32; // Höhe für horizontalen Slider
case PM_SliderLength:
return 20; // Handle-Größe
case PM_SliderControlThickness:
return 20;
case PM_SliderSpaceAvailable:
if (option)
{
if (const QStyleOptionSlider* sliderOpt = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
if (sliderOpt->orientation == Qt::Horizontal) {
return sliderOpt->rect.width() - 20;
} else {
return sliderOpt->rect.height() - 20;
}
}
}
return QProxyStyle::pixelMetric(metric, option, widget);
default:
return QProxyStyle::pixelMetric(metric, option, widget);
}
}
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt,SubControl sc, const QWidget* widget) const override
{
if (cc == CC_Slider) {
if (const QStyleOptionSlider* slider = qstyleoption_cast<const QStyleOptionSlider*>(opt)) {
QRect rect = slider->rect;
int handleSize = 20;
if (sc == SC_SliderHandle) {
// Handle Position korrekt berechnen
if (slider->orientation == Qt::Horizontal) {
int range = slider->maximum - slider->minimum;
int pos = slider->sliderPosition - slider->minimum;
int pixelRange = rect.width() - handleSize;
int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0;
return QRect(rect.x() + pixelPos,
rect.center().y() - handleSize / 2,
handleSize, handleSize);
} else {
int range = slider->maximum - slider->minimum;
int pos = slider->sliderPosition - slider->minimum;
int pixelRange = rect.height() - handleSize;
int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0;
return QRect(rect.center().x() - handleSize / 2,
rect.bottom() - pixelPos - handleSize,
handleSize, handleSize);
}
}
}
}
return QProxyStyle::subControlRect(cc, opt, sc, widget);
}
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override
{
if (control == CC_Slider)
{
if (const QStyleOptionSlider* slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
painter->setRenderHint(QPainter::Antialiasing);
// Fluent Colors
QColor accentColor(0, 120, 212); // #0078D4
QColor inactiveColor(138, 136, 134); // #8A8886
QColor bgColor(255, 255, 255); // White background
if (slider->orientation == Qt::Horizontal) {
drawHorizontalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor);
} else {
drawVerticalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor);
}
return;
}
}
QProxyStyle::drawComplexControl(control, option, painter, widget);
}
private:
void drawHorizontalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider,
const QColor& activeColor, const QColor& inactiveColor,
const QColor& bgColor) const {
QRect groove = slider->rect;
QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr);
int grooveHeight = 4;
// Track sollte im Widget-Zentrum sein, nicht im groove-Zentrum
int grooveY = slider->rect.center().y() - grooveHeight / 2;
// Full background track
QRect fullTrack(groove.left(), grooveY, groove.width(), grooveHeight);
painter->setPen(Qt::NoPen);
painter->setBrush(inactiveColor.lighter(150));
painter->drawRoundedRect(fullTrack, grooveHeight / 2, grooveHeight / 2);
// Active track (filled portion)
int activeWidth = handle.center().x() - groove.left();
QRect activeTrack(groove.left(), grooveY, activeWidth, grooveHeight);
painter->setBrush(activeColor);
painter->drawRoundedRect(activeTrack, grooveHeight / 2, grooveHeight / 2);
// Handle (Thumb) - Fluent style is more subtle
int handleSize = 20;
QRect thumbRect(handle.center().x() - handleSize / 2,
handle.center().y() - handleSize / 2,
handleSize, handleSize);
// Hover effect - subtle glow
if (slider->state & State_MouseOver) {
painter->setBrush(QColor(activeColor.red(), activeColor.green(),
activeColor.blue(), 30));
int glowSize = 32;
QRect glow(handle.center().x() - glowSize / 2,
handle.center().y() - glowSize / 2,
glowSize, glowSize);
painter->drawEllipse(glow);
}
// Thumb
painter->setBrush(bgColor);
painter->setPen(QPen(activeColor, 2));
painter->drawEllipse(thumbRect);
// Inner circle for pressed state
if (slider->state & State_Sunken) {
int innerSize = 8;
QRect inner(handle.center().x() - innerSize / 2,
handle.center().y() - innerSize / 2,
innerSize, innerSize);
painter->setPen(Qt::NoPen);
painter->setBrush(activeColor);
painter->drawEllipse(inner);
}
}
void drawVerticalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider,
const QColor& activeColor, const QColor& inactiveColor,
const QColor& bgColor) const {
QRect groove = slider->rect;
QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr);
int grooveWidth = 4;
// Track sollte im Widget-Zentrum sein
int grooveX = slider->rect.center().x() - grooveWidth / 2;
// Full background track
QRect fullTrack(grooveX, groove.top(), grooveWidth, groove.height());
painter->setPen(Qt::NoPen);
painter->setBrush(inactiveColor.lighter(150));
painter->drawRoundedRect(fullTrack, grooveWidth / 2, grooveWidth / 2);
// Active track
int activeHeight = groove.bottom() - handle.center().y();
QRect activeTrack(grooveX, handle.center().y(), grooveWidth, activeHeight);
painter->setBrush(activeColor);
painter->drawRoundedRect(activeTrack, grooveWidth / 2, grooveWidth / 2);
// Handle
int handleSize = 20;
QRect thumbRect(handle.center().x() - handleSize / 2,
handle.center().y() - handleSize / 2,
handleSize, handleSize);
if (slider->state & State_MouseOver) {
painter->setBrush(QColor(activeColor.red(), activeColor.green(),
activeColor.blue(), 30));
int glowSize = 32;
QRect glow(handle.center().x() - glowSize / 2,
handle.center().y() - glowSize / 2,
glowSize, glowSize);
painter->drawEllipse(glow);
}
painter->setBrush(bgColor);
painter->setPen(QPen(activeColor, 2));
painter->drawEllipse(thumbRect);
if (slider->state & State_Sunken) {
int innerSize = 8;
QRect inner(handle.center().x() - innerSize / 2,
handle.center().y() - innerSize / 2,
innerSize, innerSize);
painter->setPen(Qt::NoPen);
painter->setBrush(activeColor);
painter->drawEllipse(inner);
}
}
};
class SliderDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SliderDelegate(QObject* parent = nullptr)
: QStyledItemDelegate(parent)
{}
// Editor erstellen (QSlider)
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,const QModelIndex& index) const override
{
Q_UNUSED(option)
Q_UNUSED(index)
auto* slider = new QSlider(Qt::Horizontal, parent);
slider->setRange(0, 100);
slider->setSingleStep(1);
slider->setPageStep(10);
slider->setStyle(new FluentSliderStyle());
// Signal für sofortige Updates
connect(slider, &QSlider::valueChanged, this, [this, slider]() {
// Commit data sofort bei Änderung
emit const_cast<SliderDelegate*>(this)->commitData(slider);
});
return slider;
}
// Editor mit aktuellem Wert füllen
void setEditorData(QWidget* editor, const QModelIndex& index) const override {
int value = index.model()->data(index, Qt::EditRole).toInt();
auto* slider = static_cast<QSlider*>(editor);
slider->setValue(value);
}
// Wert vom Editor ins Model schreiben
void setModelData(QWidget* editor, QAbstractItemModel* model,
const QModelIndex& index) const override {
auto* slider = static_cast<QSlider*>(editor);
int value = slider->value();
model->setData(index, value, Qt::EditRole);
}
// Editor-Geometrie (wichtig für korrekte Positionierung)
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option,
const QModelIndex& index) const override {
Q_UNUSED(index)
/*
QRect barRect = option.rect.adjusted(option.rect.width() - 55,
option.rect.height() / 2 - 2,
-8,
-option.rect.height() / 2 + 2);
*/
QRect sliderRect = option.rect.adjusted(
option.rect.width() - 115, // Von rechts: 115px (Breite der Progress Bar)
0, // Oben: kein Offset
-8, // Rechts: 8px Padding
0 // Unten: kein Offset
);
editor->setGeometry(sliderRect); // Slider nur über Progress Bar
//editor->setGeometry(option.rect);
}
// Anzeige wenn NICHT editiert wird
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
{
if (index.column() == 1)
{ // Nur für Wert-Spalte
// Wert holen
int value = index.model()->data(index, Qt::DisplayRole).toInt();
// Hintergrund
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
} else if (index.row() % 2 == 1) {
painter->fillRect(option.rect, QColor(0xFAFAFA));
} else {
painter->fillRect(option.rect, Qt::white);
}
// Text und kleiner Slider-Indikator zeichnen
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
QRect textRect = option.rect.adjusted(8, 0, -120, 0);
QRect barRect = option.rect.adjusted(option.rect.width() - 115,
option.rect.height() / 2 - 2,
-8,
-option.rect.height() / 2 + 2);
// Text
painter->setPen(option.state & QStyle::State_Selected ?
option.palette.highlightedText().color() : Qt::black);
painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft,
QString::number(value));
// Mini Progress Bar
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(0xE0E0E0));
painter->drawRoundedRect(barRect, 2, 2);
QRect fillRect = barRect;
fillRect.setWidth(barRect.width() * value / 100);
painter->setBrush(QColor(0x0078D4));
painter->drawRoundedRect(fillRect, 2, 2);
painter->restore();
} else {
// Standard-Zeichnung für andere Spalten
QStyledItemDelegate::paint(painter, option, index);
}
}
};
#endif // SLIDERDELEGATE_H

View File

@@ -38,21 +38,21 @@
#include <QDebug>
#include <bcmainwindow.h>
#include <bcvalue.h>
#include <bcvaluemanager.h>
#include <bcdata.h>
#include <bcvdatamanager.h>
/*
#include <QMetaEnum>
void parseString(const QString &inputString) {
QMetaEnum metaEnum = QMetaEnum::fromType<BCValue::ID>();
QMetaEnum metaEnum = QMetaEnum::fromType<BCData::ID>();
bool ok = false;
// keyToValue parst den String ("x1") und liefert den int-Wert
int intVal = metaEnum.keyToValue(inputString.toLatin1().constData(), &ok);
if (ok) {
BCValue::ID id = static_cast<BCValue::ID>(intVal);
BCData::ID id = static_cast<BCData::ID>(intVal);
// Erfolg!
} else {
// Fehler: String existiert nicht im Enum