diff --git a/.qtcreator/BionxControl.pro.user b/.qtcreator/BionxControl.pro.user index 8176cf2..fbb27f9 100644 --- a/.qtcreator/BionxControl.pro.user +++ b/.qtcreator/BionxControl.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/BionxControl.qrc b/BionxControl.qrc index b5728e7..ec486b3 100644 --- a/BionxControl.qrc +++ b/BionxControl.qrc @@ -2,6 +2,5 @@ data/bikeinfo.xml bionxcontrol.qss - data/typeinfo.xml diff --git a/bcdatamodel.cpp b/bcdatamodel.cpp index 369ffcf..69bf55c 100644 --- a/bcdatamodel.cpp +++ b/bcdatamodel.cpp @@ -50,22 +50,30 @@ void BCValueModel::setValueList(const BCValueList& valueList) endResetModel(); } +BCValueList& BCValueModel::getValueList() +{ + return _valueList; +} + int BCValueModel::rowCount(const QModelIndex &parent) const { - if (parent.isValid()) return 0; + if (parent.isValid()) + return 0; return _valueList.size(); } -QVariant BCValueModel::data(const QModelIndex &index, int role) const +QVariant BCValueModel::data(const QModelIndex& index, int role) const { - if (!index.isValid() || index.row() >= _valueList.size()) + int row = index.row(); + if (!index.isValid() || row >= _valueList.size()) return QVariant(); - const BCValue &item = _valueList.at(index.row()); + BCValue& value = const_cast(_valueList.at( row )); + value.rowInModel = row; + + if (role == Qt::DisplayRole || role == Qt::EditRole) + return QVariant::fromValue(value); - if (role == Qt::DisplayRole || role == Qt::EditRole) { - return QVariant::fromValue(item); - } return QVariant(); } diff --git a/bcdatamodel.h b/bcdatamodel.h index 1d86e72..78da93b 100644 --- a/bcdatamodel.h +++ b/bcdatamodel.h @@ -46,6 +46,8 @@ public: void addValue(const BCValue &val); void setValueList(const BCValueList& valueList); + BCValueList& getValueList(); + int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/bcitemdelegate.cpp b/bcitemdelegate.cpp index 31bcd98..ae45af4 100644 --- a/bcitemdelegate.cpp +++ b/bcitemdelegate.cpp @@ -3,14 +3,17 @@ #include #include #include +#include +#include +#include #include "bcitemdelegate.h" #include "bcvalue.h" #include "qapplication.h" -BCItemDelegate::BCItemDelegate(QObject *parent) - : QStyledItemDelegate(parent) +BCItemDelegate::BCItemDelegate(QListView *view) + : QStyledItemDelegate(view), _view{view} { } @@ -26,7 +29,7 @@ QString BCItemDelegate::displayText(const QVariant& dataValue, const QLocale& lo // 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(), "mm1"); + return QString("%1: %2 %3").arg(bc.label, bc.value.toString(), "mmX"); } // Fallback für normale Strings/Zahlen @@ -132,6 +135,51 @@ QSize BCItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelI */ } + +void BCItemDelegate::onHighlightRow(int row) +{ + qDebug() << " --- should highlight: " << row; + _highlightedRow = row; + + // Trigger Repaint der View (damit der Rahmen sofort erscheint) + _view->viewport()->update(); + + // Timer: Nach 1 Sekunde wieder ausschalten (Temporär) + QTimer::singleShot(1000, this, [=, this]() + { + if(_highlightedRow == row) + { // Nur zurücksetzen, wenn es noch dieselbe Zeile ist + _highlightedRow = -1; + if (_view) + _view->viewport()->update(); + } + }); +} + +void BCItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + // 1. Standard-Zeichnen (Text, Hintergrund, Selection) durchführen + QStyledItemDelegate::paint(painter, option, index); + + // 2. Unser Custom-Overly: Oranger Rahmen, wenn Zeile passt + if (index.row() == _highlightedRow) + { + painter->save(); + + qDebug() << " --- is highlight: " << index.row(); + + // Setup Stift + QPen pen(QColor(255, 165, 0)); // Orange + pen.setWidth(2); + painter->setPen(pen); + + // Rechteck zeichnen (leicht eingezogen, damit es nicht abgeschnitten wird) + QRect rect = option.rect.adjusted(1, 1, -1, -1); + painter->drawRect(rect); + + painter->restore(); + } +} QString BCItemDelegate::formatDisplayString(const QModelIndex &index) const { if (!index.isValid()) diff --git a/bcitemdelegate.h b/bcitemdelegate.h index d47a355..de7726a 100644 --- a/bcitemdelegate.h +++ b/bcitemdelegate.h @@ -2,18 +2,18 @@ #ifndef BCITEMDELEGATE_H #define BCITEMDELEGATE_H - #include +class QListView; + class BCItemDelegate : public QStyledItemDelegate { Q_OBJECT public: - explicit BCItemDelegate(QObject *parent = nullptr); + explicit BCItemDelegate(QListView *view ); - // WICHTIG: Zuständig für die normale Anzeige (ohne Editor) QString displayText(const QVariant& dataValue, const QLocale& locale) const override; // Zuständig für den Edit-Modus (Doppelklick) @@ -23,9 +23,19 @@ public: void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const override; + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +public slots: + + void onHighlightRow(int row); private: + QString formatDisplayString(const QModelIndex &index) const; + + int _highlightedRow{-1}; + QListView* _view{nullptr}; + }; diff --git a/bcmainwindow.cpp b/bcmainwindow.cpp index f7cfc34..4b090da 100644 --- a/bcmainwindow.cpp +++ b/bcmainwindow.cpp @@ -36,12 +36,16 @@ BCMainWindow::BCMainWindow(QWidget *parent) { setupUi(this); _valueManager.loadBikeData(); - auto model = _valueManager.getModel( "Console"_L1 ); + auto model = _valueManager.getModel( BCDevice::ID::Console ); if( model) _valueView->setModel( *model ); - _valueView->setItemDelegate( new BCItemDelegate( _valueView) ); + BCItemDelegate* delegate = new BCItemDelegate( _valueView); + _valueView->setItemDelegate( delegate ); + + connect( &_valueManager, &BCValueManager::valueTouched, delegate, &BCItemDelegate::onHighlightRow ); connect( _connectButton, &QPushButton::clicked, &_valueManager, &BCValueManager::onToggleConnectionState ); + connect( _syncButton, &QPushButton::clicked, &_valueManager, &BCValueManager::onSyncFromDevice ); } BCMainWindow::~BCMainWindow() diff --git a/bcmainwindow.ui b/bcmainwindow.ui index 0f3fac0..b532a57 100644 --- a/bcmainwindow.ui +++ b/bcmainwindow.ui @@ -27,7 +27,7 @@ QFrame::Shadow::Raised - + 30 @@ -37,7 +37,7 @@ - PushButton + Sync diff --git a/bcvalue.h b/bcvalue.h index e7dbf44..b2a3771 100644 --- a/bcvalue.h +++ b/bcvalue.h @@ -106,9 +106,8 @@ public: BCDevice::ID deviceID{BCDevice::ID::Invalid}; BC::ID targetID{BC::ID::Invalid}; - BCValueType::TypeID typeID{BCValueType::TypeID::Invalid};; - + int rowInModel{-1}; QString label; QVariant value; QVariant defaultValue; diff --git a/bcvaluemanager.cpp b/bcvaluemanager.cpp index 96751c0..d79f3ea 100644 --- a/bcvaluemanager.cpp +++ b/bcvaluemanager.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -53,7 +54,7 @@ BCValueManager::BCValueManager(QObject *parent) // 4. Verbindungen herstellen (Signal/Slot über Thread-Grenzen) // A) Befehl senden (Manager -> Runner) - connect(this, &BCValueManager::newCommandArrived, &_transmitter, &BCTransmitter::addCommand); + connect(this, &BCValueManager::newCommandArrived, &_transmitter, &BCTransmitter::enqueueValue); // B) Ergebnisse empfangen (Runner -> Manager) connect(&_transmitter, &BCTransmitter::commandFinished, this, &BCValueManager::onCommandFinished); @@ -136,11 +137,31 @@ void BCValueManager::onToggleConnectionState( bool connect ) } - -std::optional BCValueManager::getModel(const QString& key ) +void BCValueManager::onSyncFromDevice() { - if( _valueModels.contains( key) ) - return _valueModels[key]; + qDebug() << " ---Syncing"; + if( _currentDeviceID != BCDevice::ID::Invalid) + { + + BCValueList& currentList = _valueModels[_currentDeviceID]->getValueList(); + for( BCValue& value : currentList ) + { + qDebug() << " --- value: " << value.label; + _transmitter.enqueueValue( value ); + emit valueTouched( value.rowInModel ); + QApplication::processEvents(); + // Thread schlafen lassen (Simulation einer blockierenden Operation) + QThread::msleep(500); + + } + + } +} + +std::optional BCValueManager::getModel(BCDevice::ID deviceID ) +{ + if( _valueModels.contains( deviceID) ) + return _valueModels[deviceID]; return std::nullopt; } @@ -185,25 +206,28 @@ void BCValueManager::loadBikeData() if (token == QXmlStreamReader::StartElement) { QString deviceType = _xml.attributes().value("Type"_L1).toString(); - qDebug() << " --- Device: " << _xml.name() << ": " << deviceType; printAttrs (_xml); const char* deviceKey = _xml.attributes().value("Type"_L1).toLatin1().constData(); auto deviceID = _bcDeviceEnum.keyToValue64(deviceKey); //_currentDeviceID = BCDevice::ID( deviceID.value_or( BCDevice::ID::Invalid ) ); - _currentDeviceID = deviceID.has_value() ? BCDevice::ID( deviceID.value() ) : BCDevice::ID::Invalid; if(deviceID.has_value()) { - BCValueList parsedValues; + qDebug() << " --- Device: " << _xml.name() << ": " << deviceType << " : " << deviceID; + + _currentDeviceID = BCDevice::ID( deviceID.value() ); + BCValueList parsedValues; loadDeviceData( parsedValues ); if( parsedValues.count() ) { BCValueModel* valueModel = new BCValueModel( this ); valueModel->setValueList(parsedValues); - _valueModels.insert( deviceType, valueModel ); + _valueModels.insert( _currentDeviceID, valueModel ); } } } + + _currentDeviceID = BCDevice::ID::Console; } /* diff --git a/bcvaluemanager.h b/bcvaluemanager.h index 672eb3a..1014784 100644 --- a/bcvaluemanager.h +++ b/bcvaluemanager.h @@ -50,7 +50,7 @@ public: BCValueManager( QObject* parent = nullptr); virtual ~BCValueManager(); - std::optional getModel(const QString& key ); + std::optional getModel(BCDevice::ID deviceID ); BCValue makeValue(BCDevice::ID deviceID, const BCValueParams& params ); @@ -62,11 +62,14 @@ public slots: void loadBikeData(); void saveBikeData(); void onToggleConnectionState( bool connect ); + void onSyncFromDevice(); signals: // Internes Signal, um Daten an den Worker Thread zu senden - void newCommandArrived(BCValue cmd); + void newCommandArrived(const BCValue& cmd); + //void valuedTouched(const BCValue& cmd); + void valueTouched(int rowInModel ); private slots: @@ -79,16 +82,19 @@ protected: void loadTypeData(); void loadDeviceData( BCValueList& parsedValues ); - QXmlStreamReader _xml; - QMap _valueTypes; - QMap _valueModels; - BCDevice::ID _currentDeviceID{BCDevice::ID::Invalid}; - QMetaEnum _bcDeviceEnum{QMetaEnum::fromType()}; + using BCDeviceModels = QMap; + using BCValueTypes = QMap; - BCCanDriverTinyCan _canDriver; + QXmlStreamReader _xml; + BCValueTypes _valueTypes; + BCDeviceModels _valueModels; + BCDevice::ID _currentDeviceID{BCDevice::ID::Invalid}; + QMetaEnum _bcDeviceEnum{QMetaEnum::fromType()}; - QThread _worker; - BCTransmitter _transmitter; + BCCanDriverTinyCan _canDriver; + + QThread _worker; + BCTransmitter _transmitter; };