diff --git a/src/tuxclocker-qt/Utils.cpp b/src/tuxclocker-qt/Utils.cpp index d576e6c..7ec5f5b 100644 --- a/src/tuxclocker-qt/Utils.cpp +++ b/src/tuxclocker-qt/Utils.cpp @@ -20,9 +20,11 @@ QVariant fromAssignmentArgument(TuxClocker::Device::AssignmentArgument arg) { return QVariant{}; } -using ModelTraverseCallback = std::function; +using ModelTraverseCallback = + std::function; -void traverseModel(const ModelTraverseCallback &cb, QAbstractItemModel *model, QModelIndex parent) { +void traverseModel( + const ModelTraverseCallback &cb, QAbstractItemModel *model, const QModelIndex &parent) { for (int i = 0; i < model->rowCount(parent); i++) { // We get the next index we should traverse, and the funtion does // its thing with the model and index diff --git a/src/tuxclocker-qt/Utils.hpp b/src/tuxclocker-qt/Utils.hpp index 2044298..789f66b 100644 --- a/src/tuxclocker-qt/Utils.hpp +++ b/src/tuxclocker-qt/Utils.hpp @@ -4,10 +4,11 @@ namespace Utils { -using ModelTraverseCallback = std::function; +using ModelTraverseCallback = + std::function; void traverseModel( - const ModelTraverseCallback &, QAbstractItemModel *, QModelIndex parent = QModelIndex()); + const ModelTraverseCallback &, QAbstractItemModel *, const QModelIndex &parent = QModelIndex()); void writeAssignableDefaults(DeviceModel &model); } // namespace Utils diff --git a/src/tuxclocker-qt/data/DeviceModelDelegate.cpp b/src/tuxclocker-qt/data/DeviceModelDelegate.cpp index 28a2027..60e4bd5 100644 --- a/src/tuxclocker-qt/data/DeviceModelDelegate.cpp +++ b/src/tuxclocker-qt/data/DeviceModelDelegate.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include using namespace TuxClocker::Device; using namespace mpark::patterns; @@ -19,8 +21,8 @@ Q_DECLARE_METATYPE(AssignableItemData) DeviceModelDelegate::DeviceModelDelegate(QObject *parent) : QStyledItemDelegate(parent) { m_parametrize = new QAction{"Parametrize...", this}; + m_resetAssignable = new QAction{"Reset to default", this}; - m_menu.addAction(m_parametrize); m_functionEditor = nullptr; } @@ -98,8 +100,17 @@ bool DeviceModelDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &item, const QModelIndex &index) { // Context menu handling if (event->type() == QEvent::MouseButtonRelease) { + // TODO: remove menu connections + m_menu.clear(); + auto mouse = dynamic_cast(event); + // Check if any children have saved default assignable values + if (mouse->button() == Qt::RightButton && + subtreeHasAssignableDefaults(model, index)) { + m_menu.addAction(m_resetAssignable); + } + auto data = index.data(DeviceModel::AssignableRole); auto assInfo = data.value(); // TODO: need a different check for future 'Reset assignable' action @@ -116,10 +127,11 @@ bool DeviceModelDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, m_functionEditor->setAssignableName( index.data(DeviceModel::NodeNameRole).toString()); + m_menu.addAction(m_parametrize); + // TODO: show in main window as a page connect(m_parametrize, &QAction::triggered, [=](auto) { m_functionEditor->show(); }); - m_menu.exec(mouse->globalPos()); // TODO: not handled in AssignableProxy connect(m_functionEditor, &FunctionEditor::connectionDataChanged, @@ -127,6 +139,8 @@ bool DeviceModelDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, setAssignableData(model, index, "(Parametrized)", data); }); } + if (!m_menu.actions().empty()) + m_menu.exec(mouse->globalPos()); } return QStyledItemDelegate::editorEvent(event, model, item, index); @@ -147,6 +161,33 @@ void DeviceModelDelegate::setAssignableData( model->setData(index, v, DeviceModel::AssignableRole); } +bool DeviceModelDelegate::subtreeHasAssignableDefaults( + QAbstractItemModel *model, const QModelIndex &item) { + QSettings settings{"tuxclocker"}; + settings.beginGroup("assignableDefaults"); + bool hasDefaults = false; + + auto cb = [&settings, &hasDefaults]( + QAbstractItemModel *model, const QModelIndex &index, int row) { + auto ifaceIndex = model->index(row, DeviceModel::InterfaceColumn, index); + auto assProxyV = ifaceIndex.data(DeviceModel::AssignableProxyRole); + + qDebug() << model->index(row, DeviceModel::NameColumn, index).data(); + if (assProxyV.isValid()) { + auto nodePath = qvariant_cast(assProxyV)->dbusPath(); + if (settings.contains(nodePath.replace('/', '-'))) { + // TODO: break out of the function here + hasDefaults = true; + } + } + + return model->index(row, DeviceModel::NameColumn, index); + }; + Utils::traverseModel(cb, model); + + return hasDefaults; +} + QColor alphaBlend(QColor top, QColor background) { auto alpha = top.alphaF(); auto factor = 1 - alpha; diff --git a/src/tuxclocker-qt/data/DeviceModelDelegate.hpp b/src/tuxclocker-qt/data/DeviceModelDelegate.hpp index 45ce8da..33a0838 100644 --- a/src/tuxclocker-qt/data/DeviceModelDelegate.hpp +++ b/src/tuxclocker-qt/data/DeviceModelDelegate.hpp @@ -5,6 +5,7 @@ class AssignableItemData; class FunctionEditor; +class QStandardItemModel; // TODO: align checkbox to the right class DeviceModelDelegate : public QStyledItemDelegate { @@ -28,8 +29,11 @@ private: template static void setAssignableData( QAbstractItemModel *, const QModelIndex &, QString text, T data); + // Whether to show reset action for a node + bool subtreeHasAssignableDefaults(QAbstractItemModel *, const QModelIndex &); FunctionEditor *m_functionEditor; QAction *m_parametrize; + QAction *m_resetAssignable; QMenu m_menu; };