From 48fec55c02d41f313fb9e2aa68d0ed5b3b5efb34 Mon Sep 17 00:00:00 2001 From: Marco Randazzo Date: Tue, 16 Nov 2021 12:36:50 +0100 Subject: [PATCH] yarpmotorgui: improved slider graphics, with displayed reference value (optional, enabled from the menu, default off) --- doc/release/master/yarpmotogui_slider.md | 9 ++++ src/yarpmotorgui/jointitem.cpp | 55 ++++++++++--------- src/yarpmotorgui/jointitem.h | 3 +- src/yarpmotorgui/mainwindow.cpp | 30 ++++++++--- src/yarpmotorgui/mainwindow.h | 6 ++- src/yarpmotorgui/partitem.cpp | 13 ++++- src/yarpmotorgui/partitem.h | 3 +- src/yarpmotorgui/sliderWithTarget.cpp | 67 ++++++++++++++++-------- src/yarpmotorgui/sliderWithTarget.h | 15 +++--- 9 files changed, 131 insertions(+), 70 deletions(-) create mode 100644 doc/release/master/yarpmotogui_slider.md diff --git a/doc/release/master/yarpmotogui_slider.md b/doc/release/master/yarpmotogui_slider.md new file mode 100644 index 00000000000..36b7f89a3cf --- /dev/null +++ b/doc/release/master/yarpmotogui_slider.md @@ -0,0 +1,9 @@ +yarpmotorgui_slider {#master} +----------------------- + +### GUIs + +#### yarpmotorgui + +* Improved slider graphics, with displayed reference value (optional, enabled from the menu, default off) + diff --git a/src/yarpmotorgui/jointitem.cpp b/src/yarpmotorgui/jointitem.cpp index b8bfacc2838..2a1528763bc 100644 --- a/src/yarpmotorgui/jointitem.cpp +++ b/src/yarpmotorgui/jointitem.cpp @@ -24,24 +24,12 @@ void JointItem::resetTarget() void JointItem::updateTrajectoryPositionTarget(double val) { - int w = ui->sliderTrajectoryPosition->width()- 30; - double mmin = this->min_position; - double mmax = this->max_position; - double totValues = fabs(mmax - mmin); - double cursor = fabs(val - mmin); - double newX = cursor * (double)w / (double)totValues; - ui->sliderTrajectoryPosition->updateSliderTarget(newX); + ui->sliderTrajectoryPosition->updateSliderTarget(val); } void JointItem::updateMixedPositionTarget(double val) { - int w = ui->sliderMixedPosition->width() - 30; - double mmin = this->min_position; - double mmax = this->max_position; - double totValues = fabs(mmax - mmin); - double cursor = fabs(val - mmin); - double newX = cursor * (double)w / (double)totValues; - ui->sliderMixedPosition->updateSliderTarget(newX); + ui->sliderMixedPosition->updateSliderTarget(val); } JointItem::JointItem(int index,QWidget *parent) : @@ -101,55 +89,64 @@ JointItem::JointItem(int index,QWidget *parent) : connect(ui->sliderTrajectoryPosition,SIGNAL(sliderPressed()),this,SLOT(onSliderTrajectoryPositionPressed())); connect(ui->sliderTrajectoryPosition, SIGNAL(sliderReleased()), this, SLOT(onSliderTrajectoryPositionReleased())); ui->sliderTrajectoryPosition->disableClickOutOfHandle=true; - ui->sliderTrajectoryPosition->enableViewTarget = true; + ui->sliderTrajectoryPosition->enableViewTargetBox = true; + ui->sliderTrajectoryPosition->enableViewTargetValue = false; ui->sliderTorqueTorque->installEventFilter(this); connect(ui->sliderTorqueTorque,SIGNAL(sliderPressed()),this,SLOT(onSliderTorquePressed())); connect(ui->sliderTorqueTorque,SIGNAL(sliderReleased()),this,SLOT(onSliderTorqueReleased())); ui->sliderTorqueTorque->disableClickOutOfHandle = true; - ui->sliderTorqueTorque->enableViewTarget = false; + ui->sliderTorqueTorque->enableViewTargetBox = false; + ui->sliderTorqueTorque->enableViewTargetValue = false; ui->sliderPWMOutput->installEventFilter(this); connect(ui->sliderPWMOutput, SIGNAL(sliderPressed()), this, SLOT(onSliderPWMPressed())); connect(ui->sliderPWMOutput, SIGNAL(sliderReleased()), this, SLOT(onSliderPWMReleased())); ui->sliderPWMOutput->disableClickOutOfHandle = true; - ui->sliderPWMOutput->enableViewTarget = false; + ui->sliderPWMOutput->enableViewTargetBox = false; + ui->sliderPWMOutput->enableViewTargetValue = false; ui->sliderCurrentOutput->installEventFilter(this); connect(ui->sliderCurrentOutput, SIGNAL(sliderPressed()), this, SLOT(onSliderCurrentPressed())); connect(ui->sliderCurrentOutput, SIGNAL(sliderReleased()), this, SLOT(onSliderCurrentReleased())); ui->sliderCurrentOutput->disableClickOutOfHandle = true; - ui->sliderCurrentOutput->enableViewTarget = false; + ui->sliderCurrentOutput->enableViewTargetBox = false; + ui->sliderCurrentOutput->enableViewTargetValue = false; ui->sliderDirectPosition->installEventFilter(this); connect(ui->sliderDirectPosition, SIGNAL(sliderPressed()), this, SLOT(onSliderDirectPositionPressed())); connect(ui->sliderDirectPosition, SIGNAL(sliderReleased()), this, SLOT(onSliderDirectPositionReleased())); ui->sliderDirectPosition->disableClickOutOfHandle = true; - ui->sliderDirectPosition->enableViewTarget = false; + ui->sliderDirectPosition->enableViewTargetBox = false; + ui->sliderDirectPosition->enableViewTargetValue = false; ui->sliderMixedPosition->installEventFilter(this); connect(ui->sliderMixedPosition, SIGNAL(sliderPressed()), this, SLOT(onSliderMixedPositionPressed())); connect(ui->sliderMixedPosition, SIGNAL(sliderReleased()), this, SLOT(onSliderMixedPositionReleased())); ui->sliderMixedPosition->disableClickOutOfHandle = true; - ui->sliderMixedPosition->enableViewTarget = true; + ui->sliderMixedPosition->enableViewTargetBox = true; + ui->sliderMixedPosition->enableViewTargetValue = false; ui->sliderVelocityVelocity->installEventFilter(this); connect(ui->sliderVelocityVelocity,SIGNAL(sliderPressed()),this,SLOT(onSliderVelocityPressed())); connect(ui->sliderVelocityVelocity,SIGNAL(sliderReleased()),this,SLOT(onSliderVelocityReleased())); ui->sliderVelocityVelocity->disableClickOutOfHandle = true; - ui->sliderVelocityVelocity->enableViewTarget = false; + ui->sliderVelocityVelocity->enableViewTargetBox = false; + ui->sliderVelocityVelocity->enableViewTargetValue = false; ui->sliderTrajectoryVelocity->installEventFilter(this); connect(ui->sliderTrajectoryVelocity, SIGNAL(sliderPressed()), this, SLOT(onSliderTrajectoryVelocityPressed())); connect(ui->sliderTrajectoryVelocity, SIGNAL(sliderReleased()), this, SLOT(onSliderTrajectoryVelocityReleased())); ui->sliderTrajectoryVelocity->disableClickOutOfHandle = true; - ui->sliderTrajectoryVelocity->enableViewTarget = false; + ui->sliderTrajectoryVelocity->enableViewTargetBox = false; + ui->sliderTrajectoryVelocity->enableViewTargetValue = false; ui->sliderMixedVelocity->installEventFilter(this); connect(ui->sliderMixedVelocity, SIGNAL(sliderPressed()), this, SLOT(onSliderMixedVelocityPressed())); connect(ui->sliderMixedVelocity, SIGNAL(sliderReleased()), this, SLOT(onSliderMixedVelocityReleased())); ui->sliderMixedVelocity->disableClickOutOfHandle = true; - ui->sliderMixedVelocity->enableViewTarget = false; + ui->sliderMixedVelocity->enableViewTargetBox = false; + ui->sliderMixedVelocity->enableViewTargetValue = false; connect(ui->buttonHome,SIGNAL(clicked()),this,SLOT(onHomeClicked())); connect(ui->buttonIdle,SIGNAL(clicked()),this,SLOT(onIdleClicked())); @@ -379,10 +376,16 @@ void JointItem::enableControlCurrent(bool control) ui->stackedWidget->widget(CURRENT)->setEnabled(control); } -void JointItem::viewPositionTarget(bool visible) +void JointItem::viewPositionTargetBox(bool visible) { - ui->sliderTrajectoryPosition->enableViewTarget = visible; - ui->sliderMixedPosition->enableViewTarget = visible; + ui->sliderTrajectoryPosition->enableViewTargetBox = visible; + ui->sliderMixedPosition->enableViewTargetBox = visible; +} + +void JointItem::viewPositionTargetValue(bool visible) +{ + ui->sliderTrajectoryPosition->enableViewTargetValue = visible; + ui->sliderMixedPosition->enableViewTargetValue = visible; } void JointItem::setUnits(yarp::dev::JointTypeEnum t) diff --git a/src/yarpmotorgui/jointitem.h b/src/yarpmotorgui/jointitem.h index 98f2233df32..21de6b51cd3 100644 --- a/src/yarpmotorgui/jointitem.h +++ b/src/yarpmotorgui/jointitem.h @@ -70,7 +70,8 @@ class JointItem : public QWidget void setDutyVisible(bool); void setCurrentsVisible(bool); void setUnits(yarp::dev::JointTypeEnum t); - void viewPositionTarget(bool); + void viewPositionTargetBox(bool); + void viewPositionTargetValue(bool); void enableControlVelocity(bool control); void enableControlMixed(bool control); void enableControlPositionDirect(bool control); diff --git a/src/yarpmotorgui/mainwindow.cpp b/src/yarpmotorgui/mainwindow.cpp index 0560fde0d5a..de8fa3d23f8 100644 --- a/src/yarpmotorgui/mainwindow.cpp +++ b/src/yarpmotorgui/mainwindow.cpp @@ -250,7 +250,8 @@ MainWindow::MainWindow(QWidget *parent) : QAction *viewCurrentValues = windows->addAction("View Current Values"); QAction *viewMotorPosition = windows->addAction("View Motor Position"); QAction *viewDutyCycles = windows->addAction("View Duty Cycles"); - QAction *viewPositionTarget = windows->addAction("View Position Target"); + QAction *viewPositionTargetBox = windows->addAction("View Position Target Box"); + QAction* viewPositionTargetValue = windows->addAction("View Position Target Value"); QAction *enableControlVelocity = windows->addAction("Enable Velocity Control"); QAction *enableControlMixed = windows->addAction("Enable Mixed Control"); QAction *enableControlPositionDirect = windows->addAction("Enable Position Direct Control"); @@ -269,13 +270,15 @@ MainWindow::MainWindow(QWidget *parent) : enableControlPositionDirect->setCheckable(true); enableControlPWM->setCheckable(true); enableControlCurrent->setCheckable(true); - viewPositionTarget->setCheckable(true); + viewPositionTargetBox->setCheckable(true); + viewPositionTargetValue->setCheckable(true); QSettings settings("YARP","yarpmotorgui"); bool bViewGlobalToolbar = settings.value("GlobalToolVisible",true).toBool(); bool bViewPartToolbar = settings.value("PartToolVisible",true).toBool(); bool bSpeedValues = settings.value("SpeedValuesVisible",false).toBool(); - bool bViewPositionTarget = settings.value("ViewPositionTarget", true).toBool(); + bool bViewPositionTargetBox = settings.value("ViewPositionTargetBox", true).toBool(); + bool bViewPositionTargetValue = settings.value("ViewPositionTargetValue", false).toBool(); bool bviewMotorPosition = settings.value("MotorPositionVisible", false).toBool(); bool bviewDutyCycles = settings.value("DutyCycleVisible", false).toBool(); bool bCurrentValues = settings.value("CurrentsVisible", false).toBool(); @@ -286,7 +289,8 @@ MainWindow::MainWindow(QWidget *parent) : viewCurrentValues->setChecked(bCurrentValues); viewMotorPosition->setChecked(bviewMotorPosition); viewDutyCycles->setChecked(bviewDutyCycles); - viewPositionTarget->setChecked(bViewPositionTarget); + viewPositionTargetBox->setChecked(bViewPositionTargetBox); + viewPositionTargetValue->setChecked(bViewPositionTargetValue); enableControlVelocity->setChecked(false); enableControlMixed->setChecked(false); enableControlPositionDirect->setChecked(false); @@ -302,7 +306,8 @@ MainWindow::MainWindow(QWidget *parent) : connect(viewCurrentValues, SIGNAL(triggered(bool)), this, SLOT(onViewCurrents(bool))); connect(viewMotorPosition, SIGNAL(triggered(bool)), this, SLOT(onViewMotorPositions(bool))); connect(viewDutyCycles, SIGNAL(triggered(bool)), this, SLOT(onViewDutyCycles(bool))); - connect(viewPositionTarget, SIGNAL(triggered(bool)), this, SLOT(onViewPositionTarget(bool))); + connect(viewPositionTargetBox, SIGNAL(triggered(bool)), this, SLOT(onViewPositionTargetBox(bool))); + connect(viewPositionTargetValue, SIGNAL(triggered(bool)), this, SLOT(onViewPositionTargetValue(bool))); connect(enableControlVelocity, SIGNAL(triggered(bool)), this, SLOT(onEnableControlVelocity(bool))); connect(enableControlMixed, SIGNAL(triggered(bool)), this, SLOT(onEnableControlMixed(bool))); connect(enableControlPositionDirect, SIGNAL(triggered(bool)), this, SLOT(onEnableControlPositionDirect(bool))); @@ -477,12 +482,20 @@ void MainWindow::onViewDutyCycles(bool val) emit sig_viewDutyCycles(val); } -void MainWindow::onViewPositionTarget(bool val) +void MainWindow::onViewPositionTargetBox(bool val) { QSettings settings("YARP", "yarpmotorgui"); settings.setValue("ViewPositionTarget", val); - emit sig_viewPositionTarget(val); + emit sig_viewPositionTargetBox(val); +} + +void MainWindow::onViewPositionTargetValue(bool val) +{ + QSettings settings("YARP", "yarpmotorgui"); + settings.setValue("ViewPositionTarget", val); + + emit sig_viewPositionTargetValue(val); } void MainWindow::onSetPosSliderOptionMW(int choice, double val) @@ -632,7 +645,8 @@ bool MainWindow::init(QStringList enabledParts, connect(this, SIGNAL(sig_setPosSliderOptionMW(int, double)), part, SLOT(onSetPosSliderOptionPI(int, double))); connect(this, SIGNAL(sig_setVelSliderOptionMW(int, double)), part, SLOT(onSetVelSliderOptionPI(int, double))); connect(this, SIGNAL(sig_setTrqSliderOptionMW(int, double)), part, SLOT(onSetTrqSliderOptionPI(int, double))); - connect(this,SIGNAL(sig_viewPositionTarget(bool)), part, SLOT(onViewPositionTarget(bool))); + connect(this, SIGNAL(sig_viewPositionTargetBox(bool)), part, SLOT(onViewPositionTargetBox(bool))); + connect(this, SIGNAL(sig_viewPositionTargetValue(bool)), part, SLOT(onViewPositionTargetValue(bool))); connect(this, SIGNAL(sig_enableControlVelocity(bool)), part, SLOT(onEnableControlVelocity(bool))); connect(this, SIGNAL(sig_enableControlMixed(bool)), part, SLOT(onEnableControlMixed(bool))); connect(this, SIGNAL(sig_enableControlPositionDirect(bool)), part, SLOT(onEnableControlPositionDirect(bool))); diff --git a/src/yarpmotorgui/mainwindow.h b/src/yarpmotorgui/mainwindow.h index 4496275d45d..dcc58f5268a 100644 --- a/src/yarpmotorgui/mainwindow.h +++ b/src/yarpmotorgui/mainwindow.h @@ -116,7 +116,8 @@ private slots: void onViewCurrents(bool); void onViewMotorPositions(bool); void onViewDutyCycles(bool); - void onViewPositionTarget(bool); + void onViewPositionTargetBox(bool); + void onViewPositionTargetValue(bool); void onEnableControlVelocity(bool val); void onEnableControlMixed(bool val); void onEnableControlPositionDirect(bool val); @@ -140,7 +141,8 @@ private slots: void sig_setPosSliderOptionMW(int, double); void sig_setVelSliderOptionMW(int, double); void sig_setTrqSliderOptionMW(int, double); - void sig_viewPositionTarget(bool); + void sig_viewPositionTargetBox(bool); + void sig_viewPositionTargetValue(bool); void sig_internalClose(); }; diff --git a/src/yarpmotorgui/partitem.cpp b/src/yarpmotorgui/partitem.cpp index fc0442efd7b..bef173c65ca 100644 --- a/src/yarpmotorgui/partitem.cpp +++ b/src/yarpmotorgui/partitem.cpp @@ -1959,12 +1959,21 @@ void PartItem::onViewCurrentValues(bool view) } } -void PartItem::onViewPositionTarget(bool ena) +void PartItem::onViewPositionTargetBox(bool ena) { for (int i = 0; icount(); i++) { auto* joint = (JointItem*)m_layout->itemAt(i)->widget(); - joint->viewPositionTarget(ena); + joint->viewPositionTargetBox(ena); + } +} + +void PartItem::onViewPositionTargetValue(bool ena) +{ + for (int i = 0; i < m_layout->count(); i++) + { + auto* joint = (JointItem*)m_layout->itemAt(i)->widget(); + joint->viewPositionTargetValue(ena); } } diff --git a/src/yarpmotorgui/partitem.h b/src/yarpmotorgui/partitem.h index da920bf03de..452b3c0859c 100644 --- a/src/yarpmotorgui/partitem.h +++ b/src/yarpmotorgui/partitem.h @@ -174,7 +174,8 @@ public slots: void onSetVelSliderOptionPI(int mode, double step); void onSetTrqSliderOptionPI(int mode, double step); void onSetCurSliderOptionPI(int mode, double step); - void onViewPositionTarget(bool); + void onViewPositionTargetBox(bool); + void onViewPositionTargetValue(bool); void onEnableControlVelocity(bool control); void onEnableControlMixed(bool control); void onEnableControlPositionDirect(bool control); diff --git a/src/yarpmotorgui/sliderWithTarget.cpp b/src/yarpmotorgui/sliderWithTarget.cpp index 648f63b0999..eda9579a0ab 100644 --- a/src/yarpmotorgui/sliderWithTarget.cpp +++ b/src/yarpmotorgui/sliderWithTarget.cpp @@ -16,23 +16,27 @@ double my_round(double number) return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5); } -SliderWithTarget::SliderWithTarget(QWidget * parent, bool _hasTargetOption) : QSlider(Qt::Horizontal, nullptr) +SliderWithTarget::SliderWithTarget(QWidget * parent) : QSlider(Qt::Horizontal, nullptr) { - sliderLabel = new QLabel(this); - sliderLabel->setObjectName(QStringLiteral("sliderLabel")); - sliderLabel->setGeometry(QRect(0, 0, 41, 20)); - sliderLabel->setMinimumSize(QSize(40, 20)); - sliderLabel->setMaximumSize(QSize(16777215, 20)); - sliderLabel->setAlignment(Qt::AlignCenter); - sliderLabel->setStyleSheet("background-color: rgba(0,0,0,0%)"); - - hasTargetOption = _hasTargetOption; - enableViewTarget = true; - enableViewLabel = true; + sliderCurrentLabel = new QLabel(this); + sliderCurrentLabel->setObjectName(QStringLiteral("sliderLabel")); + sliderCurrentLabel->setGeometry(QRect(0, 0, 100, 20)); + sliderCurrentLabel->setMinimumSize(QSize(40, 20)); + sliderCurrentLabel->setMaximumSize(QSize(16777215, 20)); + sliderCurrentLabel->setAlignment(Qt::AlignCenter); + sliderCurrentLabel->setStyleSheet("background-color: rgba(0,0,0,0%)"); + + sliderTargetLabel = new QLabel(this); + sliderTargetLabel->setObjectName(QStringLiteral("sliderTargetLabel")); + sliderTargetLabel->setGeometry(QRect(0, 0, 100, 20)); + sliderTargetLabel->setMinimumSize(QSize(40, 20)); + sliderTargetLabel->setMaximumSize(QSize(16777215, 20)); + sliderTargetLabel->setAlignment(Qt::AlignCenter); + sliderTargetLabel->setStyleSheet("background-color: rgba(0,0,0,0%)"); + disableClickOutOfHandle = true; target=-1e50; //default value is intensionally set out of the slider width_at_target = this->width() - 30; - sliderStep=1; isDouble = false; } @@ -73,35 +77,46 @@ void SliderWithTarget::updateSliderTarget(double t) { target = t; width_at_target= this->width()-30; - this->update(); //force the reapint of the widget + this->update(); //force the repaint of the widget } void SliderWithTarget::resetTarget() { target = -1e50; width_at_target = this->width() - 30; - this->update(); //force the reapint of the widget + this->update(); //force the repaint of the widget } void SliderWithTarget::paintEvent(QPaintEvent *e) { QSlider::paintEvent(e); - if (hasTargetOption && enableViewTarget) + double w = this->width() - 30; + int totValues = this->maximum() + abs(this->minimum()); + + if (enableViewTargetBox) { QPainter p(this); - double current_width = this->width()-30; - QRect r(target / width_at_target * current_width, 17, 30, 15); + double newX = ((double)w / (double)totValues) * ((double)target + abs(this->minimum())); + QRect r(newX, 17, 30, 15); p.fillRect(r, QBrush(QColor(128, 128, 255, 128))); p.drawRect(r); } if (enableViewLabel) { - double value = this->value(); - int w = this->width() - 30; - int totValues = this->maximum() + abs(this->minimum()); + double value = this->value(); double newX = ((double)w / (double)totValues) * ((double)value + abs(this->minimum())); - sliderLabel->setGeometry(newX, -10, 40, 20); - sliderLabel->setText(QString("%L1").arg((double)value / sliderStep, 0, 'f', 3)); + sliderCurrentLabel->setGeometry(newX, -10, 40, 20); + sliderCurrentLabel->setText(QString("%L1").arg((double)value / sliderStep, 0, 'f', 3)); + } + if (enableViewTargetValue) + { + double newX = ((double)w / (double)totValues) * ((double)target + abs(this->minimum())); + sliderTargetLabel->setGeometry(newX, +10, 80, 20); + sliderTargetLabel->setText(QString("Ref:%L1").arg((double)target, 0, 'f', 3)); + } + else + { + sliderTargetLabel->setText(""); } } @@ -128,3 +143,9 @@ void SliderWithTarget::mousePressEvent(QMouseEvent * event) } QSlider::mousePressEvent(event); } + +SliderWithTarget::~SliderWithTarget() +{ + if (sliderCurrentLabel) { delete sliderCurrentLabel; sliderCurrentLabel = nullptr; } + if (sliderTargetLabel) { delete sliderTargetLabel; sliderTargetLabel = nullptr; } +} diff --git a/src/yarpmotorgui/sliderWithTarget.h b/src/yarpmotorgui/sliderWithTarget.h index 1b583616974..dad2f80c7e1 100644 --- a/src/yarpmotorgui/sliderWithTarget.h +++ b/src/yarpmotorgui/sliderWithTarget.h @@ -17,11 +17,12 @@ class SliderWithTarget : public QSlider { public: - bool enableViewLabel; - bool enableViewTarget; + bool enableViewLabel = true; + bool enableViewTargetBox = true; + bool enableViewTargetValue = false; bool disableClickOutOfHandle; - SliderWithTarget(QWidget * parent = 0, bool _hasTargetOption = true); - ~SliderWithTarget() { if (sliderLabel) { delete sliderLabel; sliderLabel = 0; } } + SliderWithTarget(QWidget * parent = 0); + ~SliderWithTarget(); void updateSliderTarget(double val); void resetTarget(); void setSliderStep(double val); @@ -32,11 +33,11 @@ class SliderWithTarget : public QSlider protected: bool isDouble; - QLabel* sliderLabel; + QLabel* sliderCurrentLabel = nullptr; + QLabel* sliderTargetLabel = nullptr; double target; double width_at_target; - double sliderStep; - bool hasTargetOption; + double sliderStep = 1; void paintEvent(QPaintEvent *ev) override; void mousePressEvent(QMouseEvent * event) override; };