From 316a2508a576021c543efe0088f854d94eec13d5 Mon Sep 17 00:00:00 2001 From: Max Paperno Date: Thu, 28 Jun 2018 04:44:48 -0400 Subject: [PATCH] [Companion] Add AutoBitsetCheckBox --- companion/src/shared/CMakeLists.txt | 1 + companion/src/shared/autobitsetcheckbox.h | 178 ++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 companion/src/shared/autobitsetcheckbox.h diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt index 1692c70dc..81df9dd67 100644 --- a/companion/src/shared/CMakeLists.txt +++ b/companion/src/shared/CMakeLists.txt @@ -7,6 +7,7 @@ set(shared_SRCS ) set(shared_HDRS + autobitsetcheckbox.h autocheckbox.h autocombobox.h autodoublespinbox.h diff --git a/companion/src/shared/autobitsetcheckbox.h b/companion/src/shared/autobitsetcheckbox.h new file mode 100644 index 000000000..6274e0117 --- /dev/null +++ b/companion/src/shared/autobitsetcheckbox.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef AUTOBITSETCHECKBOX_H +#define AUTOBITSETCHECKBOX_H + +#include +#include "genericpanel.h" + +class AutoBitsetCheckBox: public QCheckBox +{ + Q_OBJECT + //! \property bitmask The value (shifted bit(s)) to set/clear based on checked state. + Q_PROPERTY(int bitmask READ bitmask WRITE setBitmask) + //! \property inverted If \e true, then the \p bitmask is cleared when the checkbox is checked, and vice versa. Default behavior is to set the bitmask when checked. + Q_PROPERTY(bool inverted READ inverted WRITE setInverted) + //! \property toggleMask If > 0, then set this value when clearing the \p bitmask value (toggles between the two masks being set). \p inverted is ignored if \p toggleMask is set. + Q_PROPERTY(int toggleMask READ toggleMask WRITE setToggleMask) + + public: + explicit AutoBitsetCheckBox(QWidget *parent = nullptr) : AutoBitsetCheckBox(QString(), parent) {} + explicit AutoBitsetCheckBox(const QString &text, QWidget *parent = nullptr) : + QCheckBox(text, parent) + { + init(); + } + + // int field constructors + explicit AutoBitsetCheckBox(int & field, int bitmask, const QString &text = QString(), QWidget *parent = nullptr) : AutoBitsetCheckBox(field, bitmask, false, text, parent) {} + explicit AutoBitsetCheckBox(int & field, int bitmask, bool invert, const QString &text = QString(), QWidget *parent = nullptr) : QCheckBox(text, parent) + { + setField(field, bitmask, invert); + init(); + } + explicit AutoBitsetCheckBox(int & field, int bitmask, int toggleMask, const QString &text = QString(), QWidget *parent = nullptr) : QCheckBox(text, parent) + { + setField(field, bitmask, false, toggleMask); + init(); + } + + // unsigned field constructors + explicit AutoBitsetCheckBox(unsigned & field, int bitmask, const QString &text = QString(), QWidget *parent = nullptr) : AutoBitsetCheckBox(field, bitmask, false, text, parent) {} + explicit AutoBitsetCheckBox(unsigned & field, int bitmask, bool invert, const QString &text = QString(), QWidget *parent = nullptr) : QCheckBox(text, parent) + { + setField(field, bitmask, invert); + init(); + } + explicit AutoBitsetCheckBox(unsigned & field, int bitmask, int toggleMask, const QString &text = QString(), QWidget *parent = nullptr) : QCheckBox(text, parent) + { + setField(field, bitmask, false, toggleMask); + init(); + } + + inline int bitmask() const { return m_bitmask; } + inline int toggleMask() const { return m_toggleMask; } + inline bool inverted() const { return m_toggleMask ? false : m_invert; } + + public slots: + void setField(int & field, int bitmask = 0, bool invert = false, int toggleMask = 0) + { + m_field = &field; + initField(bitmask, invert, toggleMask); + } + + void setField(unsigned & field, int bitmask = 0, bool invert = false, int toggleMask = 0) + { + m_field = reinterpret_cast(&field); + initField(bitmask, invert, toggleMask); + } + + void setBitmask(int bitmask) + { + m_bitmask = bitmask; + updateValue(); + } + + void setToggleMask(int toggleMask) + { + m_toggleMask = toggleMask; + updateValue(); + } + + void setInverted(bool invert) + { + m_invert = invert; + updateValue(); + } + + void updateValue() + { + if (!m_field) + return; + const bool oldLock = setLocked(true); + setChecked((m_invert && !m_toggleMask) != bool(*m_field & m_bitmask)); + setLocked(oldLock); + } + + void setPanel(GenericPanel * panel) + { + m_panel = panel; + } + + protected slots: + void init() + { + connect(this, &AutoBitsetCheckBox::toggled, this, &AutoBitsetCheckBox::onToggled); + } + + void initField(int bitmask, bool invert, int toggleMask) + { + m_bitmask = bitmask; + m_toggleMask = toggleMask; + m_invert = toggleMask ? false : invert; + updateValue(); + } + + void onToggled(bool checked) + { + if (!m_field) + return; + + if (m_toggleMask) { + if (checked) { + *m_field &= ~m_toggleMask; + *m_field |= m_bitmask; + } + else { + *m_field &= ~m_bitmask; + *m_field |= m_toggleMask; + } + } + else { + if (m_invert) + checked = !checked; + if (checked) + *m_field |= m_bitmask; + else + *m_field &= ~m_bitmask; + } + + if (m_panel && !m_lock) + emit m_panel->modified(); + } + + bool setLocked(bool lock) + { + const bool ret = m_lock; + m_lock = lock; + return ret; + } + + protected: + int * m_field = nullptr; + int m_bitmask = 0; + int m_toggleMask = 0; + bool m_invert = false; + bool m_lock = false; + GenericPanel * m_panel = nullptr; +}; + +#endif // AUTOBITSETCHECKBOX_H