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 Sep 25, 2024
1 parent 63baeb3 commit b47bb78
Show file tree
Hide file tree
Showing 33 changed files with 904 additions and 134 deletions.
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 QObject, 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 QObject, 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 QObject, 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 QObject, 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 @@ -82,16 +85,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 @@ -129,13 +127,101 @@ class SCOPY_IIO_WIDGETS_EXPORT IIOWidget : public QWidget
void setUItoDataConversion(std::function<QString(QString)> func);
void setDataToUIConversion(std::function<QString(QString)> func);

/**
* @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 @@ -148,14 +234,17 @@ 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;
Expand All @@ -165,6 +254,11 @@ protected Q_SLOTS:
/* Conversion functions */
std::function<QString(QString)> m_UItoDS;
std::function<QString(QString)> m_DStoUI;

// 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 @@ -98,6 +98,17 @@ class SCOPY_IIO_WIDGETS_EXPORT IIOWidgetBuilder : public QObject
*/
IIOWidgetBuilder &includeDebugAttributes(bool isIncluded);

/**
* @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 @@ -170,6 +181,7 @@ class SCOPY_IIO_WIDGETS_EXPORT IIOWidgetBuilder : public QObject
Connection *m_connection;
bool m_isCompact;
bool m_includeDebugAttrs;
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
21 changes: 15 additions & 6 deletions iio-widgets/src/guistrategy/comboguistrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,26 @@ ComboAttrUi::ComboAttrUi(IIOWidgetFactoryRecipe recipe, bool isCompact, QObject
m_ui->setLayout(new QHBoxLayout(m_ui));
m_ui->layout()->setContentsMargins(0, 0, 0, 0);

auto label = new QLabel(recipe.data, m_ui);
StyleHelper::IIOCompactLabel(label, "IIOTitleLabel");
m_compactLabel = new QLabel(recipe.data, m_ui);
StyleHelper::IIOCompactLabel(m_compactLabel, "IIOTitleLabel");
m_comboWidget = new QComboBox(m_ui);
m_comboWidget->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents);

StyleHelper::IIOComboBox(m_comboWidget, "IIOComboBox");
m_comboWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);

m_ui->layout()->addWidget(label);
m_ui->layout()->addWidget(m_compactLabel);
m_ui->layout()->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Preferred));
m_ui->layout()->addWidget(m_comboWidget);
} else {
m_ui->setLayout(new QVBoxLayout(m_ui));
m_ui->layout()->setContentsMargins(0, 0, 0, 0);

auto comboMenuWidget = new MenuCombo(recipe.data, m_ui);
m_comboWidget = comboMenuWidget->combo();
m_menuCombo = new MenuCombo(recipe.data, m_ui);
m_comboWidget = m_menuCombo->combo();
StyleHelper::IIOComboBox(m_comboWidget, "IIOComboBox");

m_ui->layout()->addWidget(comboMenuWidget);
m_ui->layout()->addWidget(m_menuCombo);
}

connect(m_comboWidget, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
Expand Down Expand Up @@ -97,4 +97,13 @@ void ComboAttrUi::receiveData(QString currentData, QString optionalData)
Q_EMIT displayedNewData(currentData, optionalData);
}

void ComboAttrUi::changeName(QString name)
{
if(m_isCompact) {
m_compactLabel->setText(name);
} else {
m_menuCombo->label()->setText(name);
}
}

#include "moc_comboguistrategy.cpp"
Loading

0 comments on commit b47bb78

Please sign in to comment.