Reworked value handling.

This commit is contained in:
Christoph Holzheuer
2026-01-19 16:44:52 +01:00
parent 4309d2231e
commit 8639529bbe
12 changed files with 95 additions and 80 deletions

View File

@@ -30,29 +30,21 @@ void BCDelightPMWidget::loadWidgetsFromResources()
QString resourcePath = ":/resources/smile"; QString resourcePath = ":/resources/smile";
// 2. Iterator erstellen
// QDir::Files sorgt dafür, dass wir nur echte Dateien finden, keine Ordner wie "." oder ".."
// QDirIterator::Subdirectories würde auch in Unterordnern suchen (falls nötig)
QDirIterator it(resourcePath, QDir::Files); QDirIterator it(resourcePath, QDir::Files);
//QFileInfoList fileList:
// 3. Schleife: Solange es noch Einträge gibt
while (it.hasNext()) while (it.hasNext())
{ {
// Iteriert zum nächsten Eintrag und gibt den kompletten virtuellen Pfad zurück
// z.B. ":/icons/ball_red.png"
QString fullPath = it.next(); QString fullPath = it.next();
// Eine Zufallsfarbe für den Button-Hintergrund generieren // Eine Zufallsfarbe für den Button-Hintergrund generieren
QStringList colors = {"#ff5555", "#50fa7b", "#8be9fd", "#ffb86c"}; QStringList colors = {"#ff5555", "#50fa7b", "#8be9fd", "#ffb86c"};
QString randomColor = colors.at(QRandomGenerator::global()->bounded(colors.size()));
// Ihre Funktion aufrufen und den Pfad übergeben // Ihre Funktion aufrufen und den Pfad übergeben
createFlyingWidget(fullPath, randomColor); createFlyingWidget(fullPath);
} }
} }
void BCDelightPMWidget::createFlyingWidget(const QString& iconPath, const QString &color) void BCDelightPMWidget::createFlyingWidget(const QString& iconPath)
{ {
// 1. Button als Kind des Playground erstellen // 1. Button als Kind des Playground erstellen
QPushButton *btn = new QPushButton(_playGround); QPushButton *btn = new QPushButton(_playGround);
@@ -86,24 +78,16 @@ void BCDelightPMWidget::createFlyingWidget(const QString& iconPath, const QStrin
btn->show(); btn->show();
// --- NEU: Opacity Effekt hinzufügen ---
// 1. Effekt erstellen. 'btn' wird der Parent und kümmert sich ums Löschen.
QGraphicsOpacityEffect *opacityEff = new QGraphicsOpacityEffect(btn); QGraphicsOpacityEffect *opacityEff = new QGraphicsOpacityEffect(btn);
// 2. Startwert setzen (1.0 = voll sichtbar)
opacityEff->setOpacity(1.0); opacityEff->setOpacity(1.0);
// 3. Dem Widget zuweisen. WICHTIG: Das Widget übernimmt den Besitz.
btn->setGraphicsEffect(opacityEff); btn->setGraphicsEffect(opacityEff);
// -------------------------------------- // --------------------------------------
btn->show(); btn->show();
// ... (Rest der Funktion: move und append) ...
btn->move(50 + _flyingWidgets.size() * 60, 50); btn->move(50 + _flyingWidgets.size() * 60, 50);
_flyingWidgets.append(btn); _flyingWidgets.append(btn);
// Startzustand: Unsichtbar in der Mitte
btn->move(_playGround->width()/2, _playGround->height()/2); btn->move(_playGround->width()/2, _playGround->height()/2);
opacityEff->setOpacity(0.0); opacityEff->setOpacity(0.0);

View File

@@ -4,7 +4,8 @@
#include <QObject> #include <QObject>
/** /**
* @brief The BCDelightPMWidget class : Graphische Effekte für unseren Produktmanager Simon. * @brief The BCDelightPMWidget class : Demonstration Graphischer
* Effekte für unseren Produktmanager Simon.
*/ */
class BCDelightPMWidget : public QObject class BCDelightPMWidget : public QObject
@@ -22,10 +23,9 @@ public slots:
protected: protected:
void loadWidgetsFromResources(); void loadWidgetsFromResources();
void createFlyingWidget(const QString& iconPath, const QString &color); void createFlyingWidget(const QString& iconPath);
QWidget *_playGround{};
QWidget* _playGround{};
// Liste der Widgets, die wir bewegen // Liste der Widgets, die wir bewegen
QList<QWidget*> _flyingWidgets; QList<QWidget*> _flyingWidgets;
}; };

View File

@@ -68,7 +68,7 @@ void BCDeviceView::setDeviceID( BCDevice::ID deviceID )
_devideID = deviceID; _devideID = deviceID;
} }
BCDevice::ID BCDeviceView::getDeviceID() const BCDevice::ID BCDeviceView::deviceID() const
{ {
return _devideID; return _devideID;
} }

View File

@@ -49,7 +49,7 @@ public:
explicit BCDeviceView(QWidget *parent = nullptr); explicit BCDeviceView(QWidget *parent = nullptr);
void setDeviceID( BCDevice::ID deviceID ); void setDeviceID( BCDevice::ID deviceID );
BCDevice::ID getDeviceID() const; BCDevice::ID deviceID() const;
const BCValueList& getValueList(); const BCValueList& getValueList();

View File

@@ -144,11 +144,11 @@ void BCTransmitter::onUpdateValue( BCValuePtrConst valuePtr)
// Kosmetik // Kosmetik
const BCValue& value = *(valuePtr.get()); const BCValue& value = *(valuePtr.get());
uint32_t devID = static_cast<uint32_t>(value.getDeviceID()); uint32_t devID = static_cast<uint32_t>(value.deviceID());
uint8_t regID = static_cast<uint8_t> (value.getRegisterID()); uint8_t regID = static_cast<uint8_t> (value.registerID());
// Für den Fehlerfall: Wir senden den alten Wert einfach zurück // Für den Fehlerfall: Wir senden den alten Wert einfach zurück
uint32_t newValue = value.getRawValue(); uint32_t newValue = value.rawValue();
BCValue::Flag newState = BCValue::Flag::Failed; BCValue::Flag newState = BCValue::Flag::Failed;
@@ -170,7 +170,7 @@ void BCTransmitter::onUpdateValue( BCValuePtrConst valuePtr)
} }
} }
emit valueUpdated( value.getDeviceID(), value.getIndexRow(), newState, newValue ); emit valueUpdated( value.deviceID(), value.indexRow(), newState, newValue );
} }
/** /**

View File

@@ -75,17 +75,17 @@ void BCValue::setFlag( BCValue::Flag flag, bool state) const
} }
BCDevice::ID BCValue::getDeviceID() const noexcept BCDevice::ID BCValue::deviceID() const noexcept
{ {
return _deviceID; return _deviceID;
} }
BC::ID BCValue::getRegisterID() const noexcept BC::ID BCValue::registerID() const noexcept
{ {
return _registerID; return _registerID;
} }
uint32_t BCValue::getRawValue() const noexcept uint32_t BCValue::rawValue() const noexcept
{ {
return _rawValue; return _rawValue;
} }
@@ -101,6 +101,12 @@ void BCValue::setRawValue(uint32_t newRawValue) const
// können beliebigen Unsinn enthalten, also müssen wir sie // können beliebigen Unsinn enthalten, also müssen wir sie
// auch skalieren. // auch skalieren.
if( _valueType == ValueType::Bool )
{
_rawValue = newRawValue > 0 ? 1 : 0;
return;
}
double value = newRawValue * _factor; double value = newRawValue * _factor;
if( _optMin.has_value() && _optMax.has_value() ) if( _optMin.has_value() && _optMax.has_value() )
@@ -116,13 +122,13 @@ void BCValue::setRawValue(uint32_t newRawValue) const
} }
BCValue::ValueType BCValue::getValueType() const noexcept BCValue::ValueType BCValue::valueType() const noexcept
{ {
return _valueType; return _valueType;
} }
int BCValue::getIndexRow() const noexcept int BCValue::indexRow() const noexcept
{ {
return _indexRow; return _indexRow;
} }
@@ -132,31 +138,16 @@ void BCValue::setIndexRow(int newIndexRow)
_indexRow = newIndexRow; _indexRow = newIndexRow;
} }
QString BCValue::getLabel() const QString BCValue::label() const
{ {
return _label; return _label;
} }
QString BCValue::getUnitLabel() const QString BCValue::unitLabel() const
{ {
return _unitLabel; return _unitLabel;
} }
double BCValue::getFactor() const noexcept
{
return _factor;
}
const OptDouble BCValue::getOptMin() const
{
return _optMin;
}
const OptDouble BCValue::getOptMax() const
{
return _optMax;
}
void BCValue::setFromDouble( double value ) void BCValue::setFromDouble( double value )
{ {
//if( _isReadOnly) //if( _isReadOnly)
@@ -166,7 +157,7 @@ void BCValue::setFromDouble( double value )
// wir betrachten plain // wir betrachten plain
case ValueType::Bool : case ValueType::Bool :
_rawValue = value >0 ? 1 : 0; _rawValue = value > 0 ? 1 : 0;
break; break;
case ValueType::Plain : case ValueType::Plain :
@@ -207,19 +198,32 @@ double BCValue::calcMinMaxRatio() const
if (std::abs(range) < 1e-9) if (std::abs(range) < 1e-9)
return ratio; return ratio;
double value = _rawValue * _factor;
// Die eigentliche Formel // Die eigentliche Formel
ratio = ((_rawValue - min) / range); ratio = ((value - min) / range);
//ratio = (int) qBound( min,ratio, max);
} }
return ratio; return ratio;
} }
uint32_t BCValue::getScaledValue() const noexcept
{
double value =_rawValue * _factor;
return (uint32_t) value * calcMinMaxRatio();
}
bool BCValue::valuesForSlider( int& value, int& min, int& max ) const
{
// min & max sind vorraussetzung für den slider
if( !_optMin.has_value() || !_optMax.has_value() )
return false;
// wir erwarten hier, das value zwischen min
// und max liegt weil wir das schon bei setRawValue
// überprüft haben.
value = _rawValue * _factor;
min = _optMin.value();
max = _optMax.value();
return true;
}
void BCValue::dumpValue() const void BCValue::dumpValue() const
{ {

View File

@@ -107,22 +107,20 @@ public:
bool testFlag( Flag flag ) const; bool testFlag( Flag flag ) const;
void setFlag( Flag flag, bool state=true ) const; void setFlag( Flag flag, bool state=true ) const;
BCDevice::ID getDeviceID() const noexcept; BCDevice::ID deviceID() const noexcept;
BC::ID getRegisterID() const noexcept; BC::ID registerID() const noexcept;
uint32_t getRawValue() const noexcept; uint32_t rawValue() const noexcept;
uint32_t getScaledValue() const noexcept;
void setRawValue(uint32_t newRawValue) const; void setRawValue(uint32_t newRawValue) const;
void setFromDouble( double value ); void setFromDouble( double value );
ValueType getValueType() const noexcept; ValueType valueType() const noexcept;
int getIndexRow() const noexcept; int indexRow() const noexcept;
void setIndexRow(int newIndexRow); void setIndexRow(int newIndexRow);
QString getLabel() const; QString label() const;
QString getUnitLabel() const; QString unitLabel() const;
double getFactor() const noexcept;
const OptDouble getOptMin() const; bool valuesForSlider( int& value, int& min, int& max ) const;
const OptDouble getOptMax() const;
protected: protected:

View File

@@ -62,9 +62,16 @@ QWidget* BCValueDelegate::createEditor(QWidget *parent, const QStyleOptionViewIt
const BCValue& bcValue = *(_valueList[ index.row()].get()); const BCValue& bcValue = *(_valueList[ index.row()].get());
qDebug() << " --- Create Editor: " << bcValue.getLabel() << " ratio: " << bcValue.calcMinMaxRatio() << " raw: " << bcValue.getRawValue() << " scaled: " << bcValue.getScaledValue(); int value,min,max;
bool hasData = bcValue.valuesForSlider( value, min, max );
if( !hasData )
return nullptr;
auto* valueEditor = new BCValueEditor(bcValue.getScaledValue(), parent); qDebug() << " --- Create Editor: " << bcValue.label() << " value: " << value << " min: " << min << " max: " << max << " ratio:" << bcValue.calcMinMaxRatio()*100.0 << '%';
auto* valueEditor = new BCValueEditor(parent);
valueEditor->setValue( value );
valueEditor->setRange( min, max );
// Signal für sofortige Updates // Signal für sofortige Updates
connect(valueEditor, &BCValueEditor::valueChanged, this, [this, valueEditor]() connect(valueEditor, &BCValueEditor::valueChanged, this, [this, valueEditor]()
@@ -122,8 +129,15 @@ void BCValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem& optio
if( row>-1 && row <= _valueList.size() ) if( row>-1 && row <= _valueList.size() )
{ {
const BCValue& bcValue = *(_valueList[ index.row()].get()); const BCValue& bcValue = *(_valueList[ index.row()].get());
if( !bcValue.isReadOnly()) if( !bcValue.isReadOnly() )
paintSliderIndicator(painter,option,bcValue); {
if( bcValue.valueType() == BCValue::ValueType::Bool )
paintButtonIndicator(painter,option,bcValue);
else
paintSliderIndicator(painter,option,bcValue);
}
} }
if(_rowOpacities.contains(row)) if(_rowOpacities.contains(row))
@@ -175,6 +189,11 @@ void BCValueDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionVi
} }
void BCValueDelegate::paintButtonIndicator(QPainter* painter, const QStyleOptionViewItem& option, const BCValue& bcValue) const
{
}
/** /**
* @brief Zeichnet eine passiven Slider, um den möglichen Wertebereich des übergebenen BCValue anzuzeigen. * @brief Zeichnet eine passiven Slider, um den möglichen Wertebereich des übergebenen BCValue anzuzeigen.
*/ */

View File

@@ -70,6 +70,7 @@ protected:
void updateRow(int row); void updateRow(int row);
void paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, int row) const; void paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, int row) const;
void paintSliderIndicator(QPainter* painter, const QStyleOptionViewItem& option, const BCValue& bcValue) const; void paintSliderIndicator(QPainter* painter, const QStyleOptionViewItem& option, const BCValue& bcValue) const;
void paintButtonIndicator(QPainter* painter, const QStyleOptionViewItem& option, const BCValue& bcValue) const;
// Das ist ein Quickhack, der Delegate sollte // Das ist ein Quickhack, der Delegate sollte
// nichts über die Originaldaten wissen. Die // nichts über die Originaldaten wissen. Die

View File

@@ -4,7 +4,7 @@
#include <bcvalue.h> #include <bcvalue.h>
BCValueEditor::BCValueEditor( int sliderValue, QWidget *parent ) BCValueEditor::BCValueEditor( QWidget *parent )
: QWidget(parent) : QWidget(parent)
{ {
setupUi(this); setupUi(this);
@@ -17,8 +17,7 @@ BCValueEditor::BCValueEditor( int sliderValue, QWidget *parent )
sp.setRetainSizeWhenHidden(true); // <--- Das ist der magische Schalter sp.setRetainSizeWhenHidden(true); // <--- Das ist der magische Schalter
_commitButton->setSizePolicy(sp); _commitButton->setSizePolicy(sp);
_slider->setRange(0, 100);
_slider->setValue( sliderValue );
// Wenn Slider bewegt wird -> Signal nach außen senden // Wenn Slider bewegt wird -> Signal nach außen senden
connect(_slider, &QSlider::valueChanged, this, [this](int val) connect(_slider, &QSlider::valueChanged, this, [this](int val)
@@ -51,3 +50,9 @@ void BCValueEditor::setValue(int val)
} }
} }
void BCValueEditor::setRange( int min, int max )
{
_slider->setRange( min, max);
}

View File

@@ -15,10 +15,11 @@ class BCValueEditor : public QWidget, private Ui::BCValueEditor
public: public:
explicit BCValueEditor(int sliderValue, QWidget *parent = nullptr); explicit BCValueEditor(QWidget *parent = nullptr);
int getValue() const; int getValue() const;
void setValue(int val); void setValue(int val);
void setRange( int min, int max );
signals: signals:

View File

@@ -148,12 +148,12 @@ QVariant BCValueModel::data(const QModelIndex& index, int role) const
const BCValue& value = *(_valueList.at( row ).get()); const BCValue& value = *(_valueList.at( row ).get());
if( col == 0 ) if( col == 0 )
return value.getLabel(); return value.label();
if( col == 1) if( col == 1)
{ {
if( role == Qt::DisplayRole ) if( role == Qt::DisplayRole )
return QString("%1 %2").arg( value.formatValue(), value.getUnitLabel()); return QString("%1 %2").arg( value.formatValue(), value.unitLabel());
return value.formatValue(); return value.formatValue();
} }
@@ -183,6 +183,9 @@ bool BCValueModel::setData(const QModelIndex& index, const QVariant& variant, in
{ {
if (index.isValid() && role == Qt::EditRole) if (index.isValid() && role == Qt::EditRole)
{ {
qDebug() << " --- SetData: at: " << index.row() << " --- set: " << variant.toString();
BCValuePtr value = _valueList[index.row()]; BCValuePtr value = _valueList[index.row()];
// Wir erwarten hier nur den Value-Teil (vom Slider/Editor) // Wir erwarten hier nur den Value-Teil (vom Slider/Editor)