#ifndef CVVISUAL_ACCORDION_HPP #define CVVISUAL_ACCORDION_HPP // STD #include <memory> #include <stdexcept> #include <map> #include <limits> // QT #include <QWidget> #include <QString> #include <QVBoxLayout> // CVV #include "collapsable.hpp" #include "../util/util.hpp" #include "../util/observer_ptr.hpp" namespace cvv { namespace qtutil { /** * @brief The Accordion class. * * Contains multiple widgets and their title. These get stored in collapsables. * The collapsables are stored in a collumn. */ class Accordion : public QWidget { Q_OBJECT public: /** * @brief The handle type to access elements */ using Handle = QWidget *; /** * @brief Constructs an empty accordion. * @param parent The parent widget */ explicit Accordion(QWidget *parent = nullptr); ~Accordion() { } /** * @brief Returns the element corrsponding to handle * @throw std::out_of_range If there is no element corresponding to * handle * @return The element corrsponding to handle */ Collapsable &element(Handle handle) { return *elements_.at(handle); } const Collapsable &element(Handle handle) const { return *elements_.at(handle); } /** * @brief Sets the title above the element. * @param handle The element * @param title The new title. * @throw std::out_of_range If there is no element corresponding to * handle */ void setTitle(Handle handle, const QString &title) { element(handle).setTitle(title); } /** * @brief Returns the current title above the element. * @param handle The element * @throw std::out_of_range If there is no element corresponding to * handle * @return The current title above the element. */ QString title(Handle handle) const { return element(handle).title(); } /** * @brief Collapses an element * @param handle The element to collapse * @param b * @parblock * true: collapses the widget * false: expands the widget * @endparblock * @throw std::out_of_range If there is no element corresponding to * handle */ void collapse(Handle handle, bool b = true) { element(handle).collapse(b); } /** * @brief Expands an element * @param handle Element to expand * @param b * @parblock * true: expands the widget * false: collapses the widget * @endparblock * @throw std::out_of_range If there is no element corresponding to * handle */ void expand(Handle handle, bool b = true) { collapse(handle, !b); } /** * @brief Collapses all elements * @param b * @parblock * true: collapses all elements * false: expands all elements * @endparblock */ void collapseAll(bool b = true); /** * @brief Expands all elements * @param b * @parblock * true: expands all elements * false: collapses all elements * @endparblock */ void expandAll(bool b = true) { collapseAll(!b); } /** * @brief Makes the element invisible * @param handle The element * @param b * @parblock * true: makes the element invisible * false: makes the element visible * @endparblock * @throw std::out_of_range If there is no element corresponding to * handle */ void hide(Handle handle, bool b = true) { element(handle).setVisible(!b); } /** * @brief Makes the element visible * @param handle The element * @param b * @parblock * true: makes the element visible * false: makes the element invisible * @endparblock * @throw std::out_of_range If there is no element corresponding to * handle */ void show(Handle handle, bool b = true) { hide(handle, !b); } /** * @brief Sets all elements' visibility to !b * @param b * @parblock * true: makes all elements invisible * false: makes all elements visible * @endparblock */ void hideAll(bool b = true); /** * @brief Sets all elements' visibility to b * @param b * @parblock * true: makes all elements visible * false: makes all elements invisible * @endparblock */ void showAll(bool b = true) { hideAll(!b); } /** * @brief Inserts a widget at the given position * @param title The title to display * @param widget The widget to display * @param isCollapsed Whether the widget is collapsed after creation * @param position The position. If it is greater than the number of *elements the widget * will be added to the end * @return The handle to access the element */ Handle insert(const QString &title, std::unique_ptr<QWidget> widget, bool isCollapsed = true, std::size_t position = std::numeric_limits<std::size_t>::max()); /** * @brief Adds a widget to the end of the Accordion * @param title The title to display * @param widget The widget to display * @param isCollapsed Whether the widget is collapsed after creation * @return The handle to access the element */ Handle push_back(const QString &title, std::unique_ptr<QWidget> widget, bool isCollapsed = true) { return insert(title, std::move(widget), isCollapsed); } /** * @brief Adds a widget to the front of the Accordion * @param title The title to display * @param widget The widget to display * @param isCollapsed Whether the widget is collapsed after creation * @return The handle to access the element */ Handle push_front(const QString &title, std::unique_ptr<QWidget> widget, bool isCollapsed = true) { return insert(title, std::move(widget), isCollapsed, 0); } /** * @brief Removes the element and deletes it immediately. * @param handle Handle of the element * @param del * @throw std::out_of_range If there is no element corresponding to * handle */ void remove(Handle handle); /** * @brief Removes all elements and deletes them immediately. * @param del */ void clear(); /** * @brief Removes an element and returns its title and Collapsable. * (ownership remains) * @param handle Handle of the element * @throw std::out_of_range If there is no element corresponding to * handle * @return Title and reference */ std::pair<QString, Collapsable *> pop(Handle handle); /** * @brief Removes all elements from the Accordion and returns their *titles * and Collapsables (ownership remains) * @return A vector containing all titles and references */ std::vector<std::pair<QString, Collapsable *>> popAll(); /** * @brief Returns the number of elements * @return The number of elements */ std::size_t size() const { return elements_.size(); } private: /** * @brief Storage for all elements */ std::map<Handle, Collapsable *> elements_; /** * @brief Layout for all elements */ util::ObserverPtr<QVBoxLayout> layout_; }; // Accordion } } // end namespaces qtutil, cvv #endif // CVVISUAL_ACCORDION_HPP