mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-15 05:22:53 +08:00
Add generic widget loader item
This commit is contained in:
parent
230e8809f0
commit
33fecc9ed5
@ -156,10 +156,12 @@ HEADERS += \
|
||||
src/Widgets/Gyroscope.h \
|
||||
src/Widgets/Plot.h \
|
||||
src/Widgets/Terminal.h \
|
||||
src/Widgets/Thermometer.h
|
||||
src/Widgets/Thermometer.h \
|
||||
src/Widgets/WidgetLoader.h
|
||||
|
||||
SOURCES += \
|
||||
src/UI/Dashboard.cpp \
|
||||
src/Widgets/WidgetLoader.cpp \
|
||||
src/main.cpp \
|
||||
src/CSV/Export.cpp \
|
||||
src/CSV/Player.cpp \
|
||||
|
@ -145,9 +145,9 @@ Page {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.maximumHeight: parent.height
|
||||
Layout.minimumHeight: parent.height
|
||||
icon.source: "qrc:/icons/widget.svg"
|
||||
Layout.minimumWidth: root.headerHeight
|
||||
Layout.maximumWidth: root.headerHeight
|
||||
icon.source: "qrc:/icons/equalizer.svg"
|
||||
icon.width: root.headerHeight * 24 / 32
|
||||
icon.height: root.headerHeight * 24 / 32
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
* Copyright (c) 2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -38,7 +38,6 @@ Item {
|
||||
// Main layout
|
||||
//
|
||||
ColumnLayout {
|
||||
x: 2 * app.spacing
|
||||
anchors.fill: parent
|
||||
spacing: app.spacing * 2
|
||||
anchors.margins: app.spacing * 1.5
|
||||
@ -75,6 +74,15 @@ Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.minimumWidth: 240
|
||||
|
||||
WidgetGrid {
|
||||
id: widgetGrid
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Widgets.Shadow {
|
||||
source: widgetGrid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
* Copyright (c) 2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
* Copyright (c) 2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
114
assets/qml/Windows/WidgetGrid.qml
Normal file
114
assets/qml/Windows/WidgetGrid.qml
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import SerialStudio 1.0
|
||||
import "../Widgets" as Widgets
|
||||
|
||||
Widgets.Window {
|
||||
id: root
|
||||
|
||||
//
|
||||
// Window properties
|
||||
//
|
||||
gradient: true
|
||||
title: qsTr("Data")
|
||||
headerDoubleClickEnabled: false
|
||||
icon.source: "qrc:/icons/dataset.svg"
|
||||
backgroundColor: Cpp_ThemeManager.embeddedWindowBackground
|
||||
|
||||
// Hacks for calculating cell width
|
||||
readonly property int columns: Math.floor(grid.width / cWidth)
|
||||
readonly property int cWidth: Math.min(Math.max(356, grid.width / Math.min(3, grid.count)), 480)
|
||||
|
||||
//
|
||||
// Put all items inside a grid view (the column layout in combination with the "clip" property
|
||||
// of the grid is used to inhibit the generated widgets from escaping the window)
|
||||
//
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: 0
|
||||
leftMargin: app.spacing
|
||||
rightMargin: app.spacing
|
||||
}
|
||||
|
||||
GridView {
|
||||
id: grid
|
||||
clip: true
|
||||
contentWidth: -1
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
// Calculate cell size so that cells fill the grid space and heigth < width
|
||||
cellHeight: cellWidth * (2/3)
|
||||
cellWidth: cWidth + (grid.width - cWidth * columns) / columns
|
||||
|
||||
// Model + delegate
|
||||
model: Cpp_UI_Dashboard.totalWidgetCount
|
||||
delegate: Item {
|
||||
width: grid.cellWidth
|
||||
height: grid.cellHeight
|
||||
|
||||
visible: opacity > 0
|
||||
opacity: loader.widgetVisible ? 1 : 0
|
||||
Behavior on opacity {NumberAnimation{}}
|
||||
|
||||
Widgets.Window {
|
||||
id: window
|
||||
title: loader.widgetTitle
|
||||
icon.source: loader.widgetIcon
|
||||
onHeaderDoubleClicked: loader.displayWindow()
|
||||
borderColor: Cpp_ThemeManager.datasetWindowBorder
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: app.spacing
|
||||
bottomMargin: app.spacing
|
||||
topMargin: 2 * app.spacing
|
||||
}
|
||||
|
||||
WidgetLoader {
|
||||
id: loader
|
||||
widgetIndex: index
|
||||
anchors.fill: parent
|
||||
anchors.margins: app.spacing
|
||||
}
|
||||
}
|
||||
|
||||
Widgets.Shadow {
|
||||
source: window
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
height: root.borderWidth
|
||||
}
|
||||
}
|
||||
}
|
@ -28,5 +28,6 @@
|
||||
<file>JSONDropArea.qml</file>
|
||||
<file>Windows/ViewOptions.qml</file>
|
||||
<file>Windows/DashboardTitle.qml</file>
|
||||
<file>Windows/WidgetGrid.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -50,15 +50,8 @@
|
||||
#include <Plugins/Bridge.h>
|
||||
#include <UI/Dashboard.h>
|
||||
|
||||
#include <Widgets/Bar.h>
|
||||
#include <Widgets/Plot.h>
|
||||
#include <Widgets/Gauge.h>
|
||||
#include <Widgets/Compass.h>
|
||||
#include <Widgets/Terminal.h>
|
||||
#include <Widgets/DataGroup.h>
|
||||
#include <Widgets/Gyroscope.h>
|
||||
#include <Widgets/Thermometer.h>
|
||||
#include <Widgets/Accelerometer.h>
|
||||
#include <Widgets/WidgetLoader.h>
|
||||
|
||||
#include <QSimpleUpdater.h>
|
||||
|
||||
@ -126,6 +119,7 @@ void ModuleManager::registerQmlTypes()
|
||||
qmlRegisterType<JSON::Group>("SerialStudio", 1, 0, "Group");
|
||||
qmlRegisterType<JSON::Dataset>("SerialStudio", 1, 0, "Dataset");
|
||||
qmlRegisterType<Widgets::Terminal>("SerialStudio", 1, 0, "Terminal");
|
||||
qmlRegisterType<Widgets::WidgetLoader>("SerialStudio", 1, 0, "WidgetLoader");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,6 +90,12 @@ bool Dashboard::frameValid() const
|
||||
// Widget count functions
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
int Dashboard::totalWidgetCount()
|
||||
{
|
||||
return mapCount() + barCount() + plotCount() + gaugeCount() + groupCount()
|
||||
+ compassCount() + gyroscopeCount() + thermometerCount() + accelerometerCount();
|
||||
}
|
||||
|
||||
int Dashboard::mapCount()
|
||||
{
|
||||
return m_mapWidgets.count();
|
||||
@ -220,6 +226,23 @@ QStringList Dashboard::accelerometerTitles()
|
||||
return list;
|
||||
}
|
||||
|
||||
QStringList Dashboard::widgetTitles()
|
||||
{
|
||||
// Warning: maintain same order as the view option repeaters in ViewOptions.qml!
|
||||
|
||||
// clang-format off
|
||||
return groupTitles() +
|
||||
plotTitles() +
|
||||
barTitles() +
|
||||
gaugeTitles() +
|
||||
thermometerTitles() +
|
||||
compassTitles() +
|
||||
gyroscopeTitles() +
|
||||
accelerometerTitles() +
|
||||
mapTitles();
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Widget visibility access functions
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -304,11 +327,8 @@ void Dashboard::setBarVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_barVisibility.count())
|
||||
{
|
||||
if (barVisible(index) != visible)
|
||||
{
|
||||
m_barVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_barVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,11 +336,8 @@ void Dashboard::setMapVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_mapVisibility.count())
|
||||
{
|
||||
if (mapVisible(index) != visible)
|
||||
{
|
||||
m_mapVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_mapVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,11 +345,8 @@ void Dashboard::setPlotVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_plotVisibility.count())
|
||||
{
|
||||
if (plotVisible(index) != visible)
|
||||
{
|
||||
m_plotVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_plotVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,11 +354,8 @@ void Dashboard::setGroupVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_groupVisibility.count())
|
||||
{
|
||||
if (groupVisible(index) != visible)
|
||||
{
|
||||
m_groupVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_groupVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,11 +363,8 @@ void Dashboard::setGaugeVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_gaugeVisibility.count())
|
||||
{
|
||||
if (gaugeVisible(index) != visible)
|
||||
{
|
||||
m_gaugeVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_gaugeVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,11 +372,8 @@ void Dashboard::setCompassVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_compassVisibility.count())
|
||||
{
|
||||
if (compassVisible(index) != visible)
|
||||
{
|
||||
m_compassVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_compassVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,11 +381,8 @@ void Dashboard::setGyroscopeVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_gyroscopeVisibility.count())
|
||||
{
|
||||
if (gyroscopeVisible(index) != visible)
|
||||
{
|
||||
m_gyroscopeVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_gyroscopeVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,11 +390,8 @@ void Dashboard::setThermometerVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_thermometerVisibility.count())
|
||||
{
|
||||
if (thermometerVisible(index) != visible)
|
||||
{
|
||||
m_thermometerVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_thermometerVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,11 +399,8 @@ void Dashboard::setAccelerometerVisible(const int index, const bool visible)
|
||||
{
|
||||
if (index < m_accelerometerVisibility.count())
|
||||
{
|
||||
if (accelerometerVisible(index) != visible)
|
||||
{
|
||||
m_accelerometerVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
m_accelerometerVisibility.replace(index, visible);
|
||||
emit widgetVisibilityChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,9 @@ class Dashboard : public QObject
|
||||
Q_PROPERTY(bool available
|
||||
READ available
|
||||
NOTIFY widgetCountChanged)
|
||||
Q_PROPERTY(int totalWidgetCount
|
||||
READ totalWidgetCount
|
||||
NOTIFY widgetCountChanged)
|
||||
Q_PROPERTY(int mapCount
|
||||
READ mapCount
|
||||
NOTIFY widgetCountChanged)
|
||||
@ -81,6 +84,8 @@ public:
|
||||
QString title();
|
||||
bool available();
|
||||
|
||||
int totalWidgetCount();
|
||||
|
||||
int mapCount();
|
||||
int barCount();
|
||||
int plotCount();
|
||||
@ -100,6 +105,7 @@ public:
|
||||
Q_INVOKABLE QStringList gyroscopeTitles();
|
||||
Q_INVOKABLE QStringList thermometerTitles();
|
||||
Q_INVOKABLE QStringList accelerometerTitles();
|
||||
Q_INVOKABLE QStringList widgetTitles();
|
||||
|
||||
Q_INVOKABLE bool barVisible(const int index);
|
||||
Q_INVOKABLE bool mapVisible(const int index);
|
||||
|
495
src/Widgets/WidgetLoader.cpp
Normal file
495
src/Widgets/WidgetLoader.cpp
Normal file
@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "WidgetLoader.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QApplication>
|
||||
#include <UI/Dashboard.h>
|
||||
|
||||
using namespace UI;
|
||||
using namespace Widgets;
|
||||
|
||||
/**
|
||||
* Constructor function
|
||||
*/
|
||||
WidgetLoader::WidgetLoader(QQuickItem *parent)
|
||||
: QQuickPaintedItem(parent)
|
||||
, m_index(-1)
|
||||
, m_widget(nullptr)
|
||||
, m_widgetVisible(true)
|
||||
{
|
||||
// Set item flags
|
||||
setFlag(ItemHasContents, true);
|
||||
setFlag(ItemAcceptsInputMethod, true);
|
||||
setFlag(ItemIsFocusScope, true);
|
||||
setAcceptedMouseButtons(Qt::AllButtons);
|
||||
|
||||
// Resize widget to fit QML item size
|
||||
connect(this, &QQuickPaintedItem::widthChanged, this,
|
||||
&WidgetLoader::updateWidgetSize);
|
||||
connect(this, &QQuickPaintedItem::heightChanged, this,
|
||||
&WidgetLoader::updateWidgetSize);
|
||||
|
||||
// Automatically update the widget's visibility
|
||||
connect(Dashboard::getInstance(), &Dashboard::widgetVisibilityChanged, this,
|
||||
&WidgetLoader::updateWidgetVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete widget on class destruction
|
||||
*/
|
||||
WidgetLoader::~WidgetLoader()
|
||||
{
|
||||
if (m_widget)
|
||||
m_widget->deleteLater();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle application events manually
|
||||
*/
|
||||
bool WidgetLoader::event(QEvent *event)
|
||||
{
|
||||
if (!m_widget)
|
||||
return false;
|
||||
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::FocusIn:
|
||||
forceActiveFocus();
|
||||
return QQuickPaintedItem::event(event);
|
||||
break;
|
||||
case QEvent::Wheel:
|
||||
processWheelEvents(static_cast<QWheelEvent *>(event));
|
||||
return true;
|
||||
break;
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::MouseMove:
|
||||
processMouseEvents(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QApplication::sendEvent(m_widget, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the widget on the given @a painter
|
||||
*/
|
||||
void WidgetLoader::paint(QPainter *painter)
|
||||
{
|
||||
if (m_widget && painter)
|
||||
m_widget->render(painter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom event filter to manage redraw requests
|
||||
*/
|
||||
bool WidgetLoader::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (!m_widget)
|
||||
return false;
|
||||
|
||||
if (watched == m_widget)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::Paint:
|
||||
case QEvent::UpdateRequest:
|
||||
update();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QQuickPaintedItem::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
int WidgetLoader::widgetIndex() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
int WidgetLoader::relativeIndex() const
|
||||
{
|
||||
//
|
||||
// Warning: relative widget index should be calculated using the same order as defined
|
||||
// by the
|
||||
// UI::Dashboard::widgetTitles() function.
|
||||
//
|
||||
|
||||
// Get pointer to dashboard module
|
||||
auto dash = Dashboard::getInstance();
|
||||
|
||||
// Check if we should return group widget
|
||||
int index = widgetIndex();
|
||||
if (index < dash->groupCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return plot widget
|
||||
index -= dash->groupCount();
|
||||
if (index < dash->plotCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return bar widget
|
||||
index -= dash->plotCount();
|
||||
if (index < dash->barCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return gauge widget
|
||||
index -= dash->barCount();
|
||||
if (index < dash->gaugeCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return thermometer widget
|
||||
index -= dash->gaugeCount();
|
||||
if (index < dash->thermometerCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return compass widget
|
||||
index -= dash->thermometerCount();
|
||||
if (index < dash->compassCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return gyro widget
|
||||
index -= dash->compassCount();
|
||||
if (index < dash->gyroscopeCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return accelerometer widget
|
||||
index -= dash->gyroscopeCount();
|
||||
if (index < dash->accelerometerCount())
|
||||
return index;
|
||||
|
||||
// Check if we should return map widget
|
||||
index -= dash->accelerometerCount();
|
||||
if (index < dash->mapCount())
|
||||
return index;
|
||||
|
||||
// Return unknown widget
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool WidgetLoader::widgetVisible() const
|
||||
{
|
||||
return m_widgetVisible;
|
||||
}
|
||||
|
||||
QString WidgetLoader::widgetIcon() const
|
||||
{
|
||||
switch (widgetType())
|
||||
{
|
||||
case WidgetType::Group:
|
||||
return "qrc:/icons/group.svg";
|
||||
break;
|
||||
case WidgetType::Plot:
|
||||
return "qrc:/icons/plot.svg";
|
||||
break;
|
||||
case WidgetType::Bar:
|
||||
return "qrc:/icons/bar.svg";
|
||||
break;
|
||||
case WidgetType::Gauge:
|
||||
return "qrc:/icons/gauge.svg";
|
||||
break;
|
||||
case WidgetType::Thermometer:
|
||||
return "qrc:/icons/thermometer.svg";
|
||||
break;
|
||||
case WidgetType::Compass:
|
||||
return "qrc:/icons/compass.svg";
|
||||
break;
|
||||
case WidgetType::Gyroscope:
|
||||
return "qrc:/icons/gyroscope.svg";
|
||||
break;
|
||||
case WidgetType::Accelerometer:
|
||||
return "qrc:/icons/accelerometer.svg";
|
||||
break;
|
||||
case WidgetType::Map:
|
||||
return "qrc:/icons/map.svg";
|
||||
break;
|
||||
default:
|
||||
return "qrc:/icons/close.svg";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropiate window title for the given widget
|
||||
*/
|
||||
QString WidgetLoader::widgetTitle() const
|
||||
{
|
||||
return UI::Dashboard::getInstance()->widgetTitles().at(widgetIndex());
|
||||
}
|
||||
|
||||
WidgetLoader::WidgetType WidgetLoader::widgetType() const
|
||||
{
|
||||
//
|
||||
// Warning: relative widget index should be calculated using the same order as defined
|
||||
// by the
|
||||
// UI::Dashboard::widgetTitles() function.
|
||||
//
|
||||
|
||||
// Unitialized widget loader class
|
||||
if (widgetIndex() < 0)
|
||||
return WidgetType::Unknown;
|
||||
|
||||
// Get pointer to dashboard module
|
||||
auto dash = UI::Dashboard::getInstance();
|
||||
|
||||
// Check if we should return group widget
|
||||
int index = widgetIndex();
|
||||
if (index < dash->groupCount())
|
||||
return WidgetType::Group;
|
||||
|
||||
// Check if we should return plot widget
|
||||
index -= dash->groupCount();
|
||||
if (index < dash->plotCount())
|
||||
return WidgetType::Plot;
|
||||
|
||||
// Check if we should return bar widget
|
||||
index -= dash->plotCount();
|
||||
if (index < dash->barCount())
|
||||
return WidgetType::Bar;
|
||||
|
||||
// Check if we should return gauge widget
|
||||
index -= dash->barCount();
|
||||
if (index < dash->gaugeCount())
|
||||
return WidgetType::Gauge;
|
||||
|
||||
// Check if we should return thermometer widget
|
||||
index -= dash->gaugeCount();
|
||||
if (index < dash->thermometerCount())
|
||||
return WidgetType::Thermometer;
|
||||
|
||||
// Check if we should return compass widget
|
||||
index -= dash->thermometerCount();
|
||||
if (index < dash->compassCount())
|
||||
return WidgetType::Compass;
|
||||
|
||||
// Check if we should return gyro widget
|
||||
index -= dash->compassCount();
|
||||
if (index < dash->gyroscopeCount())
|
||||
return WidgetType::Gyroscope;
|
||||
|
||||
// Check if we should return accelerometer widget
|
||||
index -= dash->gyroscopeCount();
|
||||
if (index < dash->accelerometerCount())
|
||||
return WidgetType::Accelerometer;
|
||||
|
||||
// Check if we should return map widget
|
||||
index -= dash->accelerometerCount();
|
||||
if (index < dash->mapCount())
|
||||
return WidgetType::Map;
|
||||
|
||||
// Return unknown widget
|
||||
return WidgetType::Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a window with the current widget
|
||||
*/
|
||||
void WidgetLoader::displayWindow()
|
||||
{
|
||||
if (m_widget)
|
||||
m_widget->showNormal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects & configures the appropiate widget for the given @a index
|
||||
*/
|
||||
void WidgetLoader::setWidgetIndex(const int index)
|
||||
{
|
||||
if (m_index != index && index < Dashboard::getInstance()->totalWidgetCount()
|
||||
&& index >= 0)
|
||||
{
|
||||
// Update widget index
|
||||
m_index = index;
|
||||
|
||||
// Delete previous widget
|
||||
if (m_widget)
|
||||
{
|
||||
m_widget->deleteLater();
|
||||
m_widget = nullptr;
|
||||
}
|
||||
|
||||
// Construct new widget
|
||||
switch (widgetType())
|
||||
{
|
||||
case WidgetType::Group:
|
||||
m_widget = new QPushButton("Group");
|
||||
break;
|
||||
case WidgetType::Plot:
|
||||
m_widget = new QPushButton("Plot");
|
||||
break;
|
||||
case WidgetType::Bar:
|
||||
m_widget = new QPushButton("Bar");
|
||||
break;
|
||||
case WidgetType::Gauge:
|
||||
m_widget = new QPushButton("Gauge");
|
||||
break;
|
||||
case WidgetType::Thermometer:
|
||||
m_widget = new QPushButton("Thermometer");
|
||||
break;
|
||||
case WidgetType::Compass:
|
||||
m_widget = new QPushButton("Compass");
|
||||
break;
|
||||
case WidgetType::Gyroscope:
|
||||
m_widget = new QPushButton("Gyroscope");
|
||||
break;
|
||||
case WidgetType::Accelerometer:
|
||||
m_widget = new QPushButton("Accelerometer");
|
||||
break;
|
||||
case WidgetType::Map:
|
||||
m_widget = new QPushButton("Map");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Allow widget to receive events from the QML interface
|
||||
if (m_widget)
|
||||
{
|
||||
m_widget->installEventFilter(this);
|
||||
updateWidgetVisible();
|
||||
}
|
||||
|
||||
// Update UI
|
||||
emit widgetIndexChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the widget to fit inside the QML item.
|
||||
*/
|
||||
void WidgetLoader::updateWidgetSize()
|
||||
{
|
||||
if (m_widget && width() > 0 && height() > 0)
|
||||
{
|
||||
m_widget->setFixedSize(width(), height());
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetLoader::updateWidgetVisible()
|
||||
{
|
||||
bool visible = false;
|
||||
auto index = relativeIndex();
|
||||
auto dash = Dashboard::getInstance();
|
||||
|
||||
switch (widgetType())
|
||||
{
|
||||
case WidgetType::Group:
|
||||
visible = dash->groupVisible(index);
|
||||
break;
|
||||
case WidgetType::Plot:
|
||||
visible = dash->plotVisible(index);
|
||||
break;
|
||||
case WidgetType::Bar:
|
||||
visible = dash->barVisible(index);
|
||||
break;
|
||||
case WidgetType::Gauge:
|
||||
visible = dash->gaugeVisible(index);
|
||||
break;
|
||||
case WidgetType::Thermometer:
|
||||
visible = dash->thermometerVisible(index);
|
||||
break;
|
||||
case WidgetType::Compass:
|
||||
visible = dash->compassVisible(index);
|
||||
break;
|
||||
case WidgetType::Gyroscope:
|
||||
visible = dash->gyroscopeVisible(index);
|
||||
break;
|
||||
case WidgetType::Accelerometer:
|
||||
visible = dash->accelerometerVisible(index);
|
||||
break;
|
||||
case WidgetType::Map:
|
||||
visible = dash->mapVisible(index);
|
||||
break;
|
||||
default:
|
||||
visible = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (widgetVisible() != visible)
|
||||
{
|
||||
m_widgetVisible = visible;
|
||||
emit widgetVisibleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack: calls the appropiate protected mouse event handler function of the widget item
|
||||
*/
|
||||
void WidgetLoader::processMouseEvents(QMouseEvent *event)
|
||||
{
|
||||
if (!m_widget)
|
||||
return;
|
||||
|
||||
class Hack : public QWidget
|
||||
{
|
||||
public:
|
||||
using QWidget::mouseDoubleClickEvent;
|
||||
using QWidget::mouseMoveEvent;
|
||||
using QWidget::mousePressEvent;
|
||||
using QWidget::mouseReleaseEvent;
|
||||
};
|
||||
|
||||
auto hack = static_cast<Hack *>(m_widget);
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::MouseButtonPress:
|
||||
hack->mousePressEvent(event);
|
||||
break;
|
||||
case QEvent::MouseMove:
|
||||
hack->mouseMoveEvent(event);
|
||||
break;
|
||||
case QEvent::MouseButtonRelease:
|
||||
hack->mouseReleaseEvent(event);
|
||||
break;
|
||||
case QEvent::MouseButtonDblClick:
|
||||
hack->mouseDoubleClickEvent(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack: calls the appropiate protected wheel event handler function of the widget item
|
||||
*/
|
||||
void WidgetLoader::processWheelEvents(QWheelEvent *event)
|
||||
{
|
||||
if (!m_widget)
|
||||
return;
|
||||
|
||||
class Hack : public QWidget
|
||||
{
|
||||
public:
|
||||
using QWidget::wheelEvent;
|
||||
};
|
||||
|
||||
static_cast<Hack *>(m_widget)->wheelEvent(event);
|
||||
}
|
112
src/Widgets/WidgetLoader.h
Normal file
112
src/Widgets/WidgetLoader.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Alex Spataru <https://github.com/alex-spataru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WIDGETS_LOADER_H
|
||||
#define WIDGETS_LOADER_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QObject>
|
||||
#include <QPainter>
|
||||
#include <QQuickPaintedItem>
|
||||
|
||||
namespace Widgets
|
||||
{
|
||||
class WidgetLoader : public QQuickPaintedItem
|
||||
{
|
||||
// clang-format off
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_PROPERTY(int widgetIndex
|
||||
READ widgetIndex
|
||||
WRITE setWidgetIndex
|
||||
NOTIFY widgetIndexChanged)
|
||||
Q_PROPERTY(int relativeIndex
|
||||
READ relativeIndex
|
||||
NOTIFY widgetIndexChanged)
|
||||
Q_PROPERTY(WidgetType widgetType
|
||||
READ widgetType
|
||||
NOTIFY widgetIndexChanged)
|
||||
Q_PROPERTY(QString widgetIcon
|
||||
READ widgetIcon
|
||||
NOTIFY widgetIndexChanged)
|
||||
Q_PROPERTY(QString widgetTitle
|
||||
READ widgetTitle
|
||||
NOTIFY widgetIndexChanged)
|
||||
Q_PROPERTY(bool widgetVisible
|
||||
READ widgetVisible
|
||||
NOTIFY widgetVisibleChanged)
|
||||
// clang-format on
|
||||
|
||||
signals:
|
||||
void widgetIndexChanged();
|
||||
void widgetVisibleChanged();
|
||||
|
||||
public:
|
||||
enum class WidgetType
|
||||
{
|
||||
Group,
|
||||
Plot,
|
||||
Bar,
|
||||
Gauge,
|
||||
Thermometer,
|
||||
Compass,
|
||||
Gyroscope,
|
||||
Accelerometer,
|
||||
Map,
|
||||
Unknown
|
||||
};
|
||||
Q_ENUM(WidgetType)
|
||||
|
||||
WidgetLoader(QQuickItem *parent = 0);
|
||||
~WidgetLoader();
|
||||
|
||||
virtual bool event(QEvent *event) override;
|
||||
virtual void paint(QPainter *painter) override;
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
int widgetIndex() const;
|
||||
int relativeIndex() const;
|
||||
bool widgetVisible() const;
|
||||
QString widgetIcon() const;
|
||||
QString widgetTitle() const;
|
||||
WidgetType widgetType() const;
|
||||
|
||||
public slots:
|
||||
void displayWindow();
|
||||
void setWidgetIndex(const int index);
|
||||
|
||||
private slots:
|
||||
void updateWidgetSize();
|
||||
void updateWidgetVisible();
|
||||
|
||||
protected:
|
||||
void processMouseEvents(QMouseEvent *event);
|
||||
void processWheelEvents(QWheelEvent *event);
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
QWidget *m_widget;
|
||||
bool m_widgetVisible;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user