mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-15 05:22:53 +08:00
Implement accelerometer widget
This commit is contained in:
parent
a4737c81f9
commit
6f22e48b75
@ -38,7 +38,10 @@ ApplicationWindow {
|
||||
//
|
||||
// Quit application on close
|
||||
//
|
||||
onClosing: Cpp_ModuleManager.quit()
|
||||
onClosing: {
|
||||
if (Cpp_JSON_Editor.askSave())
|
||||
Cpp_ModuleManager.quit()
|
||||
}
|
||||
|
||||
//
|
||||
// Global properties
|
||||
|
@ -840,12 +840,23 @@ bool Editor::setGroupWidget(const int group, const int widgetId)
|
||||
{
|
||||
// Set widget title
|
||||
grp->m_widget = "accelerometer";
|
||||
grp->m_title = tr("Accelerometer");
|
||||
|
||||
// Create datasets
|
||||
auto x = new Dataset;
|
||||
auto y = new Dataset;
|
||||
auto z = new Dataset;
|
||||
|
||||
// Set dataset indexes
|
||||
x->m_index = nextDatasetIndex();
|
||||
y->m_index = nextDatasetIndex() + 1;
|
||||
z->m_index = nextDatasetIndex() + 2;
|
||||
|
||||
// Set measurement units
|
||||
x->m_units = "m/s²";
|
||||
y->m_units = "m/s²";
|
||||
z->m_units = "m/s²";
|
||||
|
||||
// Set dataset properties
|
||||
x->m_widget = "x";
|
||||
y->m_widget = "y";
|
||||
@ -865,12 +876,23 @@ bool Editor::setGroupWidget(const int group, const int widgetId)
|
||||
{
|
||||
// Set widget title
|
||||
grp->m_widget = "gyro";
|
||||
grp->m_title = tr("Gyroscope");
|
||||
|
||||
// Create datasets
|
||||
auto x = new Dataset;
|
||||
auto y = new Dataset;
|
||||
auto z = new Dataset;
|
||||
|
||||
// Set dataset indexes
|
||||
x->m_index = nextDatasetIndex();
|
||||
y->m_index = nextDatasetIndex() + 1;
|
||||
z->m_index = nextDatasetIndex() + 2;
|
||||
|
||||
// Set measurement units
|
||||
x->m_units = "°";
|
||||
y->m_units = "°";
|
||||
z->m_units = "°";
|
||||
|
||||
// Set dataset properties
|
||||
x->m_widget = "x";
|
||||
y->m_widget = "y";
|
||||
@ -890,11 +912,20 @@ bool Editor::setGroupWidget(const int group, const int widgetId)
|
||||
{
|
||||
// Set widget title
|
||||
grp->m_widget = "map";
|
||||
grp->m_title = tr("GPS Map");
|
||||
|
||||
// Create datasets
|
||||
auto lat = new Dataset;
|
||||
auto lon = new Dataset;
|
||||
|
||||
// Set dataset indexes
|
||||
lat->m_index = nextDatasetIndex();
|
||||
lon->m_index = nextDatasetIndex() + 1;
|
||||
|
||||
// Set measurement units
|
||||
lat->m_units = "°";
|
||||
lon->m_units = "°";
|
||||
|
||||
// Set dataset properties
|
||||
lat->m_widget = "lat";
|
||||
lon->m_widget = "lon";
|
||||
@ -950,27 +981,9 @@ void Editor::addDataset(const int group)
|
||||
auto grp = getGroup(group);
|
||||
if (grp)
|
||||
{
|
||||
// Calculate frame index for dataset
|
||||
int maxIndex = 1;
|
||||
for (int i = 0; i < groupCount(); ++i)
|
||||
{
|
||||
for (int j = 0; j < datasetCount(i); ++j)
|
||||
{
|
||||
auto dataset = getDataset(i, j);
|
||||
if (dataset)
|
||||
{
|
||||
if (dataset->m_index >= maxIndex)
|
||||
maxIndex = dataset->m_index + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add dataset
|
||||
grp->m_datasets.append(new Dataset);
|
||||
setDatasetIndex(group, grp->m_datasets.count() - 1, maxIndex);
|
||||
setDatasetIndex(group, grp->m_datasets.count() - 1, nextDatasetIndex());
|
||||
setDatasetTitle(group, grp->m_datasets.count() - 1, tr("New dataset"));
|
||||
|
||||
// Update UI
|
||||
emit groupChanged(group);
|
||||
}
|
||||
}
|
||||
@ -1217,3 +1230,29 @@ void Editor::onDatasetChanged(const int group, const int dataset)
|
||||
(void)dataset;
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of datasets registered in the projects and
|
||||
* adds 1 to the result.
|
||||
*
|
||||
* This function is used when registering new datasets, so that
|
||||
* the user does not need to manually specify dataset indexes.
|
||||
*/
|
||||
int Editor::nextDatasetIndex()
|
||||
{
|
||||
int maxIndex = 1;
|
||||
for (int i = 0; i < groupCount(); ++i)
|
||||
{
|
||||
for (int j = 0; j < datasetCount(i); ++j)
|
||||
{
|
||||
auto dataset = getDataset(i, j);
|
||||
if (dataset)
|
||||
{
|
||||
if (dataset->m_index >= maxIndex)
|
||||
maxIndex = dataset->m_index + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxIndex;
|
||||
}
|
||||
|
@ -157,6 +157,8 @@ private:
|
||||
Editor();
|
||||
~Editor();
|
||||
|
||||
int nextDatasetIndex();
|
||||
|
||||
private:
|
||||
QString m_title;
|
||||
QString m_separator;
|
||||
|
@ -19,3 +19,137 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "UI/Dashboard.h"
|
||||
#include "Accelerometer.h"
|
||||
#include "Misc/ThemeManager.h"
|
||||
|
||||
#include <QtMath>
|
||||
#include <QResizeEvent>
|
||||
|
||||
using namespace Widgets;
|
||||
|
||||
Accelerometer::Accelerometer(const int index)
|
||||
: m_index(index)
|
||||
{
|
||||
// Get pointers to Serial Studio modules
|
||||
auto dash = UI::Dashboard::getInstance();
|
||||
auto theme = Misc::ThemeManager::getInstance();
|
||||
|
||||
// Invalid index, abort initialization
|
||||
if (m_index < 0 || m_index >= dash->accelerometerCount())
|
||||
return;
|
||||
|
||||
// Get needle & knob color
|
||||
QString needleColor;
|
||||
auto colors = theme->widgetColors();
|
||||
auto knobColor = theme->widgetControlBackground();
|
||||
if (colors.count() > m_index)
|
||||
needleColor = colors.at(m_index);
|
||||
else
|
||||
needleColor = colors.at(colors.count() % m_index);
|
||||
|
||||
// Configure gauge needle
|
||||
auto needle = new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Arrow, true,
|
||||
QColor(needleColor), knobColor);
|
||||
m_gauge.setNeedle(needle);
|
||||
m_gauge.setFont(dash->monoFont());
|
||||
|
||||
// Set gauge scale & display angles
|
||||
m_gauge.setScale(0, 12);
|
||||
m_gauge.setScaleArc(90, 360);
|
||||
m_gauge.setLabelEnabled(false);
|
||||
|
||||
// Set gauge palette
|
||||
QPalette gaugePalette;
|
||||
gaugePalette.setColor(QPalette::WindowText, theme->base());
|
||||
gaugePalette.setColor(QPalette::Text, theme->widgetIndicator1());
|
||||
m_gauge.setPalette(gaugePalette);
|
||||
|
||||
// Set window palette
|
||||
QPalette windowPalette;
|
||||
windowPalette.setColor(QPalette::Base, theme->datasetWindowBackground());
|
||||
windowPalette.setColor(QPalette::Window, theme->datasetWindowBackground());
|
||||
setPalette(windowPalette);
|
||||
|
||||
// Configure label style
|
||||
QFont font = dash->monoFont();
|
||||
font.setPixelSize(24);
|
||||
m_label.setFont(font);
|
||||
m_label.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
// Configure layout
|
||||
m_layout.addWidget(&m_gauge);
|
||||
m_layout.addWidget(&m_label);
|
||||
m_layout.setSpacing(24);
|
||||
m_layout.setStretch(0, 0);
|
||||
m_layout.setStretch(1, 1);
|
||||
m_layout.setContentsMargins(24, 24, 24, 24);
|
||||
setLayout(&m_layout);
|
||||
|
||||
// Set stylesheets
|
||||
// clang-format off
|
||||
auto valueQSS = QSS("background-color:%1; color:%2; border:1px solid %3;",
|
||||
theme->base(),
|
||||
theme->widgetForegroundPrimary(),
|
||||
theme->widgetIndicator1());
|
||||
m_label.setStyleSheet(valueQSS);
|
||||
// clang-format on
|
||||
|
||||
// React to dashboard events
|
||||
connect(dash, SIGNAL(updated()), this, SLOT(update()));
|
||||
}
|
||||
|
||||
void Accelerometer::update()
|
||||
{
|
||||
// Widget not enabled, do nothing
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
// Update accelerometer values
|
||||
auto accelerometer = UI::Dashboard::getInstance()->getAccelerometer(m_index);
|
||||
if (accelerometer)
|
||||
{
|
||||
if (accelerometer->datasetCount() != 3)
|
||||
return;
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
|
||||
JSON::Dataset *dataset;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
dataset = accelerometer->getDataset(i);
|
||||
if (dataset->widget() == "x")
|
||||
x = dataset->value().toDouble();
|
||||
if (dataset->widget() == "y")
|
||||
y = dataset->value().toDouble();
|
||||
if (dataset->widget() == "z")
|
||||
z = dataset->value().toDouble();
|
||||
}
|
||||
|
||||
x /= 9.18;
|
||||
y /= 9.18;
|
||||
z /= 9.18;
|
||||
|
||||
const double G = qSqrt(qPow(x, 2) + qPow(y, 2) + qPow(z, 2));
|
||||
|
||||
m_gauge.setValue(G);
|
||||
m_label.setText(QString("%1 G").arg(QString::number(G, 'f', 2)));
|
||||
}
|
||||
}
|
||||
|
||||
void Accelerometer::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
auto labelFont = UI::Dashboard::getInstance()->monoFont();
|
||||
auto gaugeFont = UI::Dashboard::getInstance()->monoFont();
|
||||
labelFont.setPixelSize(event->size().width() / 18);
|
||||
gaugeFont.setPixelSize(event->size().width() / 24);
|
||||
m_label.setFont(labelFont);
|
||||
m_gauge.setFont(gaugeFont);
|
||||
m_label.setMinimumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumHeight(event->size().height() * 0.4);
|
||||
event->accept();
|
||||
}
|
||||
|
@ -23,6 +23,33 @@
|
||||
#ifndef WIDGETS_ACCELEROMETER_H
|
||||
#define WIDGETS_ACCELEROMETER_H
|
||||
|
||||
#include
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "AnalogGauge.h"
|
||||
|
||||
namespace Widgets
|
||||
{
|
||||
class Accelerometer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Accelerometer(const int index = -1);
|
||||
|
||||
private slots:
|
||||
void update();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
QLabel m_label;
|
||||
AnalogGauge m_gauge;
|
||||
QHBoxLayout m_layout;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -34,6 +34,8 @@ using namespace Widgets;
|
||||
*/
|
||||
AnalogGauge::AnalogGauge(QWidget *parent)
|
||||
: QwtDial(parent)
|
||||
, m_label("")
|
||||
, m_labelEnabled(true)
|
||||
{
|
||||
// Disable controling the gauge with the mouse or keyboard
|
||||
setReadOnly(true);
|
||||
@ -63,18 +65,33 @@ void AnalogGauge::setLabel(const QString &label)
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the label that displays the current
|
||||
* value. For example, the normal gauge widget enables the
|
||||
* label, while the accelerometer does not.
|
||||
*/
|
||||
void AnalogGauge::setLabelEnabled(const bool enabled)
|
||||
{
|
||||
m_labelEnabled = enabled;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-draws the label that displays the current value & units.
|
||||
*/
|
||||
void AnalogGauge::drawScaleContents(QPainter *painter, const QPointF ¢er,
|
||||
double radius) const
|
||||
{
|
||||
// Label disabled, abort
|
||||
if (!m_labelEnabled)
|
||||
return;
|
||||
|
||||
// Get label font
|
||||
auto labelFont = font();
|
||||
labelFont.setPixelSize(1.4 * font().pixelSize());
|
||||
labelFont.setPixelSize(1.2 * font().pixelSize());
|
||||
|
||||
// Create draw rectangle
|
||||
QRectF rect(0.0, 0.0, 2.0 * radius, 2.0 * radius - labelFont.pixelSize() * 2);
|
||||
QRectF rect(0.0, 0.0, 2.0 * radius, 2.0 * radius - labelFont.pixelSize() * 6);
|
||||
rect.moveCenter(center);
|
||||
|
||||
// Set text alignment flags
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
|
||||
QString label() const;
|
||||
void setLabel(const QString &label);
|
||||
void setLabelEnabled(const bool enabled);
|
||||
|
||||
protected:
|
||||
virtual void drawScaleContents(QPainter *painter, const QPointF ¢er,
|
||||
@ -42,6 +43,7 @@ protected:
|
||||
|
||||
private:
|
||||
QString m_label;
|
||||
bool m_labelEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -149,8 +149,10 @@ void Bar::resizeEvent(QResizeEvent *event)
|
||||
auto width = event->size().width();
|
||||
m_thermo.setPipeWidth(width / 4);
|
||||
QFont font = m_label.font();
|
||||
font.setPixelSize(width / 16);
|
||||
font.setPixelSize(width / 18);
|
||||
m_label.setFont(font);
|
||||
m_label.setMinimumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumHeight(event->size().height() * 0.4);
|
||||
event->accept();
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
private slots:
|
||||
void update();
|
||||
|
||||
private:
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
|
@ -140,7 +140,8 @@ void Compass::resizeEvent(QResizeEvent *event)
|
||||
compassFont.setPixelSize(event->size().width() / 24);
|
||||
m_label.setFont(labelFont);
|
||||
m_compass.setFont(compassFont);
|
||||
m_label.setMaximumWidth(event->size().width() * 0.3);
|
||||
m_label.setMinimumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumHeight(event->size().height() * 0.4);
|
||||
event->accept();
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
private slots:
|
||||
void update();
|
||||
|
||||
private:
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
private slots:
|
||||
void update();
|
||||
|
||||
private:
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
|
@ -55,17 +55,14 @@ Gauge::Gauge(const int index)
|
||||
auto needle = new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Arrow, true,
|
||||
QColor(needleColor), knobColor);
|
||||
m_gauge.setNeedle(needle);
|
||||
m_gauge.setLabelEnabled(false);
|
||||
m_gauge.setFont(dash->monoFont());
|
||||
|
||||
// Set gauge scale & label
|
||||
// Set gauge scale
|
||||
#ifdef LAZY_WIDGETS
|
||||
auto dataset = dash->getGauge(m_index);
|
||||
if (dataset)
|
||||
{
|
||||
m_gauge.setScale(dataset->min(), dataset->max());
|
||||
if (!dataset->units().isEmpty())
|
||||
m_gauge.setLabel(dataset->units());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set gauge palette
|
||||
@ -80,11 +77,30 @@ Gauge::Gauge(const int index)
|
||||
windowPalette.setColor(QPalette::Window, theme->datasetWindowBackground());
|
||||
setPalette(windowPalette);
|
||||
|
||||
// Add gauge to layout
|
||||
// Configure label style
|
||||
QFont font = dash->monoFont();
|
||||
font.setPixelSize(24);
|
||||
m_label.setFont(font);
|
||||
m_label.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
// Configure layout
|
||||
m_layout.addWidget(&m_gauge);
|
||||
m_layout.setContentsMargins(8, 8, 8, 8);
|
||||
m_layout.addWidget(&m_label);
|
||||
m_layout.setSpacing(24);
|
||||
m_layout.setStretch(0, 0);
|
||||
m_layout.setStretch(1, 1);
|
||||
m_layout.setContentsMargins(24, 24, 24, 24);
|
||||
setLayout(&m_layout);
|
||||
|
||||
// Set stylesheets
|
||||
// clang-format off
|
||||
auto valueQSS = QSS("background-color:%1; color:%2; border:1px solid %3;",
|
||||
theme->base(),
|
||||
theme->widgetForegroundPrimary(),
|
||||
theme->widgetIndicator1());
|
||||
m_label.setStyleSheet(valueQSS);
|
||||
// clang-format on
|
||||
|
||||
// React to dashboard events
|
||||
connect(dash, SIGNAL(updated()), this, SLOT(update()));
|
||||
}
|
||||
@ -108,10 +124,11 @@ void Gauge::update()
|
||||
{
|
||||
#ifndef LAZY_WIDGETS
|
||||
m_gauge.setScale(dataset->min(), dataset->max());
|
||||
if (!dataset->units().isEmpty())
|
||||
m_gauge.setLabel(dataset->units());
|
||||
#endif
|
||||
auto value = dataset->value().toDouble();
|
||||
m_gauge.setValue(dataset->value().toDouble());
|
||||
m_label.setText(
|
||||
QString("%1 %2").arg(QString::number(value, 'f', 2), dataset->units()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,8 +137,14 @@ void Gauge::update()
|
||||
*/
|
||||
void Gauge::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
auto font = UI::Dashboard::getInstance()->monoFont();
|
||||
font.setPixelSize(event->size().width() / 32);
|
||||
m_gauge.setFont(font);
|
||||
auto labelFont = UI::Dashboard::getInstance()->monoFont();
|
||||
auto gaugeFont = UI::Dashboard::getInstance()->monoFont();
|
||||
labelFont.setPixelSize(event->size().width() / 18);
|
||||
gaugeFont.setPixelSize(event->size().width() / 24);
|
||||
m_label.setFont(labelFont);
|
||||
m_gauge.setFont(gaugeFont);
|
||||
m_label.setMinimumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumWidth(event->size().width() * 0.4);
|
||||
m_label.setMaximumHeight(event->size().height() * 0.4);
|
||||
event->accept();
|
||||
}
|
||||
|
@ -23,8 +23,9 @@
|
||||
#ifndef WIDGETS_GAUGE_H
|
||||
#define WIDGETS_GAUGE_H
|
||||
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "AnalogGauge.h"
|
||||
|
||||
@ -40,13 +41,14 @@ public:
|
||||
private slots:
|
||||
void update();
|
||||
|
||||
private:
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
QLabel m_label;
|
||||
AnalogGauge m_gauge;
|
||||
QVBoxLayout m_layout;
|
||||
QHBoxLayout m_layout;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "DataGroup.h"
|
||||
#include "Gyroscope.h"
|
||||
#include "Thermometer.h"
|
||||
#include "Accelerometer.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QApplication>
|
||||
@ -263,7 +264,8 @@ void WidgetLoader::setWidgetIndex(const int index)
|
||||
m_widget = new QPushButton("Gyroscope");
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Accelerometer:
|
||||
m_widget = new QPushButton("Accelerometer");
|
||||
m_widget = new Accelerometer(relativeIndex());
|
||||
m_window.setCentralWidget(new Accelerometer(relativeIndex()));
|
||||
break;
|
||||
case UI::Dashboard::WidgetType::Map:
|
||||
m_widget = new QPushButton("Map");
|
||||
|
Loading…
x
Reference in New Issue
Block a user