Skip to content

Commit

Permalink
iio-widgets: Add optional runtime reconfiguration
Browse files Browse the repository at this point in the history
Signed-off-by: Andrei-Fabian-Pop <[email protected]>
  • Loading branch information
Andrei-Fabian-Pop committed Aug 23, 2024
1 parent f260ad2 commit c317c79
Show file tree
Hide file tree
Showing 34 changed files with 936 additions and 148 deletions.
3 changes: 2 additions & 1 deletion gr-util/src/grdeviceaddon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ QWidget *GRDeviceAddon::createAttrMenu(QWidget *parent)
MenuSectionWidget *attrContainer = new MenuSectionWidget(parent);
MenuCollapseSection *attr =
new MenuCollapseSection("ATTRIBUTES", MenuCollapseSection::MHCW_NONE, attrContainer);
QList<IIOWidget *> attrWidgets = IIOWidgetBuilder().device(m_src->iioDev()).buildAll();
QList<IIOWidget *> attrWidgets = IIOWidgetBuilder().device(m_src->iioDev()).parent(parent).buildAll();
const struct iio_context *ctx = iio_device_get_context(m_src->iioDev());
attrWidgets.append(IIOWidgetBuilder()
.context(const_cast<iio_context *>(ctx))
.device(m_src->iioDev())
.attribute("Triggers")
.uiStrategy(IIOWidgetBuilder::UIS::ComboUi)
.dataStrategy(IIOWidgetBuilder::DS::TriggerData)
.parent(parent)
.buildSingle());

auto layout = new QVBoxLayout();
Expand Down
2 changes: 1 addition & 1 deletion gr-util/src/grtimechanneladdon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ QWidget *GRTimeChannelAddon::createAttrMenu(QWidget *parent)
MenuSectionWidget *attrcontainer = new MenuSectionWidget(parent);
MenuCollapseSection *attr =
new MenuCollapseSection("ATTRIBUTES", MenuCollapseSection::MHCW_NONE, attrcontainer);
QList<IIOWidget *> attrWidgets = IIOWidgetBuilder().channel(grch()->channel()).buildAll();
QList<IIOWidget *> attrWidgets = IIOWidgetBuilder().channel(grch()->channel()).parent(parent).buildAll();

auto layout = new QVBoxLayout();
layout->setSpacing(10);
Expand Down
1 change: 1 addition & 0 deletions gui/include/gui/widgets/menucombo.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class SCOPY_GUI_EXPORT MenuCombo : public QWidget
MenuCombo(QString title, QWidget *parent = nullptr);
virtual ~MenuCombo();

QLabel *label();
QComboBox *combo();
void applyStylesheet();

Expand Down
2 changes: 2 additions & 0 deletions gui/src/widgets/menucombo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ MenuCombo::MenuCombo(QString title, QWidget *parent)
}

MenuCombo::~MenuCombo() {}

QLabel *MenuCombo::label() { return m_label; }
QComboBox *MenuCombo::combo() { return m_combo; }

void MenuCombo::applyStylesheet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class SCOPY_IIO_WIDGETS_EXPORT ComboAttrUi : public QWidget, public GuiStrategyI

public Q_SLOTS:
void receiveData(QString currentData, QString optionalData) override;
void changeName(QString name) override;

Q_SIGNALS:
void displayedNewData(QString data, QString optionalData) override;
Expand All @@ -58,6 +59,8 @@ public Q_SLOTS:
private:
QWidget *m_ui;
QComboBox *m_comboWidget;
MenuCombo *m_menuCombo;
QLabel *m_compactLabel;
bool m_isCompact;
};
} // namespace scopy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class SCOPY_IIO_WIDGETS_EXPORT EditableGuiStrategy : public QWidget, public GuiS

public Q_SLOTS:
void receiveData(QString currentData, QString optionalData) override;
void changeName(QString name) override;

Q_SIGNALS:
void displayedNewData(QString data, QString optionalData) override;
Expand All @@ -57,6 +58,7 @@ public Q_SLOTS:

private:
QWidget *m_ui;
QLabel *m_titleLabel;
MenuLineEdit *m_lineEdit;
QString m_lastEmittedText;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public Q_SLOTS:
* */
virtual void receiveData(QString currentData, QString optionalData) = 0;

/**
* @brief changeName Changes the title of the UI strategy
* @param name The new name/title of the UI strategy
*/
virtual void changeName(QString name) = 0;

Q_SIGNALS:
/**
* @brief This signal is emitted when the ui strategy receives new data from external sources,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class SCOPY_IIO_WIDGETS_EXPORT RangeAttrUi : public QWidget, public GuiStrategyI

public Q_SLOTS:
void receiveData(QString currentData, QString optionalData) override;
void changeName(QString name) override;

Q_SIGNALS:
void displayedNewData(QString data, QString optionalData) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class SCOPY_IIO_WIDGETS_EXPORT SwitchAttrUi : public QWidget, public GuiStrategy

public Q_SLOTS:
void receiveData(QString currentData, QString optionalData) override;
void changeName(QString name) override;

Q_SIGNALS:
void displayedNewData(QString data, QString optionalData) override;
Expand Down
46 changes: 46 additions & 0 deletions iio-widgets/include/iio-widgets/iioconfigurationpopup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#ifndef IIOCONFIGURATIONPOPUP_H
#define IIOCONFIGURATIONPOPUP_H

#include "iiowidgetselector.h"
#include "scopy-iio-widgets_export.h"
#include <gui/tintedoverlay.h>
#include <iioutil/iioitem.h>
#include <iio.h>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QTreeView>

namespace scopy {
class SCOPY_IIO_WIDGETS_EXPORT IIOConfigurationPopup : public QWidget
{
Q_OBJECT
public:
explicit IIOConfigurationPopup(iio_context *ctx, QWidget *parent = nullptr);
explicit IIOConfigurationPopup(iio_device *dev, QWidget *parent = nullptr);
explicit IIOConfigurationPopup(iio_channel *chnl, QWidget *parent = nullptr);
~IIOConfigurationPopup();

void enableTintedOverlay(bool enable = true);

Q_SIGNALS:
void selectButtonClicked(IIOItem *selected);
void exitButtonClicked();

protected Q_SLOTS:
void modelSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);

protected:
void init();
void initUI();

gui::TintedOverlay *m_tintedOverlay;
QLabel *m_titleLabel;
IIOWidgetSelector *m_widgetSelector;
QPushButton *m_exitButton;
QPushButton *m_selectButton;
IIOItem *m_root;
};
} // namespace scopy

#endif // IIOCONFIGURATIONPOPUP_H
114 changes: 104 additions & 10 deletions iio-widgets/include/iio-widgets/iiowidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
#define SCOPY_IIOWIDGET_H

#include <QWidget>
#include "iioconfigurationpopup.h"
#include "iiowidgetdata.h"
#include "utils.h"
#include <gui/widgets/menucollapsesection.h>
#include <gui/widgets/menusectionwidget.h>
#include <gui/widgets/smallprogressbar.h>
#include <gui/widgets/hoverwidget.h>
#include <gui/widgets/popupwidget.h>
#include "guistrategy/guistrategyinterface.h"
#include "datastrategy/datastrategyinterface.h"
#include "scopy-iio-widgets_export.h"
Expand Down Expand Up @@ -81,16 +84,11 @@ class SCOPY_IIO_WIDGETS_EXPORT IIOWidget : public QWidget
void writeAsync(QString data);

/**
* @brief Returns the UI of the IIOWidget
* @return GuiStrategyInterface
* */
GuiStrategyInterface *getUiStrategy();

/**
* @brief Returns the data save/load strategy
* @return DataStretegyInterface
* */
DataStrategyInterface *getDataStrategy();
* @brief swapDataStrategy Disconnects the current Data Strategy and connects the new Data Strategy.
* @param dataStrategy The new Data Strategy that will be connected to the UIC.
* @return The old Data Strategy.
*/
DataStrategyInterface *swapDataStrategy(DataStrategyInterface *dataStrategy);

/**
* @brief Returns the recipe that this widget is based on. This is optional, currently serves as a way to pass
Expand Down Expand Up @@ -125,13 +123,101 @@ class SCOPY_IIO_WIDGETS_EXPORT IIOWidget : public QWidget
*/
int lastReturnCode();

/**
* @brief setConfigurable A configurable widget will have a wheel button on the right and it will allow the
* use to modify the underlying data strategy at runtime.
* @param isConfigurable If true, the widget is configurable at runtime. The default is false.
*/
void setConfigurable(bool isConfigurable);

/**
* @brief setUIEnabled Enables/Disables the UI.
* @param isEnabled True if the UI should be enabled, false if it should be disabled.
*/
void setUIEnabled(bool isEnabled);

/**
* @brief optionalData Calls the optionalData function from the data strategy.
* @return QString representing the optional data.
*/
QString optionalData() const;

/**
* @brief data Calls the data functipm from the data strategy.
* @return QString represrnting the data.
*/
QString data() const;

/**
* @brief isDSInstanceOf Checks whether the current data strategy is an instance of the specified type.
* @return True if the type specified coincides with the type of the data strategy.
*/
template <typename T>
bool isDSInstanceOf() const
{
return dynamic_cast<T *>(m_dataStrategy) != nullptr;
}

/**
* @brief isUISInstanceO Checks wheter the current UI strategy is an instance of the specified type.
* @return True if the type specified coincides with the type of the UI strategy.
*/
template <typename T>
bool isUISInstanceOf() const
{
return dynamic_cast<T *>(m_uiStrategy) != nullptr;
}

Q_SIGNALS:
/**
* @brief Emits the current state of the IIOWidget system and a string containing a more
* elaborate explanation of the current state
* */
void currentStateChanged(State currentState, QString explanation = "");

/**
* @brief sendData Forwards the sendData signal from the Data Strategy (emits the newly read data).
* @param data The data read.
* @param dataOptions The data from the optional attribute read.
*/
void sendData(QString data, QString dataOptions);

/**
* @brief emitStatus Forwarded signal from the Data Strategy for emitting the status of
* the operation that was just performed.
* @param timestamp QDateTime that holds the timestamp
* @param oldData The data that is present in the iio-widget before the operation
* @param newData The new data that was given to the operation
* @param returnCode int representing the return code of that operation
* @param isReadOp Boolean value set to true if the operation is a read
* operation and false if it is a write operation.
*/
void emitStatus(QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp);

/**
* @brief This signal is emitted before a write operation
* @param oldData String containing the data what is present before the write
* @param newData String containing the data that will be written
* */
void aboutToWrite(QString oldData, QString newData);

/**
* @brief This will be the signal that the user changed the data, it is forwarded from the UI strategy.
* */
void emitData(QString data);

/**
* @brief This signal is emitted when the ui strategy receives new data from external sources,
* not from the user.
* @param data The data that will be displayed.
* @param optionalData The data options, if available. Empty string if the parameter is not
* necessary in this case.
* */
void displayedNewData(QString data, QString optionalData);

public Q_SLOTS:
void changeTitle(QString title);

protected Q_SLOTS:
void saveData(QString data);
void emitDataStatus(QDateTime timestamp, QString oldData, QString newData, int returnCode, bool isReadOp);
Expand All @@ -141,19 +227,27 @@ protected Q_SLOTS:

protected:
void initialize();
void reconfigure();

void setLastOperationTimestamp(QDateTime timestamp);
void setLastOperationState(IIOWidget::State state);

// Core variables
GuiStrategyInterface *m_uiStrategy;
DataStrategyInterface *m_dataStrategy;
IIOWidgetFactoryRecipe m_recipe;

// Logged data
QString m_lastData;
SmallProgressBar *m_progressBar;
QDateTime *m_lastOpTimestamp;
int m_lastReturnCode;
IIOWidget::State *m_lastOpState;

// Optional configuration
QPushButton *m_configBtn;
IIOConfigurationPopup *m_configPopup;
bool m_isConfigurable;
};
} // namespace scopy

Expand Down
12 changes: 12 additions & 0 deletions iio-widgets/include/iio-widgets/iiowidgetbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ class SCOPY_IIO_WIDGETS_EXPORT IIOWidgetBuilder : public QObject
*/
IIOWidgetBuilder &compactMode(bool isCompact);

/**
* @brief configMode Sets the IIOWidget to be configurable. This way, a
* wheel button will be created next to the IIOWidget. Once pressed,
* this button will allow the user to select a new attribute and the
* new data strategy will use that.
* @param isConfigurable If set to true, the IIOWidget will be configurable.
* Default is false.
* @return
*/
IIOWidgetBuilder &configMode(bool isConfigurable);

/**
* @brief Sets the context that will be used, if no iio_device or iio_channel
* is set, the build functions will work with the context.
Expand Down Expand Up @@ -161,6 +172,7 @@ class SCOPY_IIO_WIDGETS_EXPORT IIOWidgetBuilder : public QObject

Connection *m_connection;
bool m_isCompact;
bool m_isConfigurable;
struct iio_context *m_context;
struct iio_device *m_device;
struct iio_channel *m_channel;
Expand Down
30 changes: 30 additions & 0 deletions iio-widgets/include/iio-widgets/iiowidgetselector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef IIOWIDGETSELECTOR_H
#define IIOWIDGETSELECTOR_H

#include <QWidget>
#include <QFrame>
#include <QStandardItemModel>
#include <QItemSelection>
#include <QTreeView>
#include <iioutil/iioitem.h>

namespace scopy {
class IIOWidgetSelector : public QFrame
{
Q_OBJECT
public:
IIOWidgetSelector(IIOItem *root, QWidget *parent = nullptr);
~IIOWidgetSelector();
QTreeView *getTree() const;
QStandardItemModel *getModel() const;

Q_SIGNALS:
void itemSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);

private:
QTreeView *m_treeView;
QStandardItemModel *m_model;
};
} // namespace scopy

#endif // IIOWIDGETSELECTOR_H
Loading

0 comments on commit c317c79

Please sign in to comment.