| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- /******************************************************************************
- Copyright (C) 2023 by Dennis Sädtler <[email protected]>
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
- 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.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- ******************************************************************************/
- #include <Idian/Row.hpp>
- #include <QApplication>
- #include <QComboBox>
- #include <QSizePolicy>
- #include <QSvgRenderer>
- #include <Idian/moc_Row.cpp>
- namespace idian {
- Row::Row(QWidget *parent) : GenericRow(parent)
- {
- layout = new QGridLayout(this);
- layout->setVerticalSpacing(0);
- layout->setContentsMargins(0, 0, 0, 0);
- labelLayout = new QVBoxLayout();
- labelLayout->setSpacing(0);
- labelLayout->setContentsMargins(0, 0, 0, 0);
- setFocusPolicy(Qt::StrongFocus);
- setLayout(layout);
- layout->setColumnMinimumWidth(0, 0);
- layout->setColumnStretch(0, 0);
- layout->setColumnStretch(1, 40);
- layout->setColumnStretch(2, 55);
- nameLabel = new QLabel();
- nameLabel->setVisible(false);
- Utils::addClass(nameLabel, "title");
- descriptionLabel = new QLabel();
- descriptionLabel->setVisible(false);
- Utils::addClass(descriptionLabel, "description");
- labelLayout->addWidget(nameLabel);
- labelLayout->addWidget(descriptionLabel);
- layout->addLayout(labelLayout, 0, 1, Qt::AlignLeft);
- }
- void Row::setPrefix(QWidget *w, bool auto_connect)
- {
- setSuffixEnabled(false);
- prefix_ = w;
- if (auto_connect)
- this->connectBuddyWidget(w);
- prefix_->setParent(this);
- layout->addWidget(prefix_, 0, 0, Qt::AlignLeft);
- layout->setColumnStretch(0, 3);
- }
- void Row::setSuffix(QWidget *w, bool auto_connect)
- {
- setPrefixEnabled(false);
- suffix_ = w;
- if (auto_connect)
- this->connectBuddyWidget(w);
- suffix_->setParent(this);
- layout->addWidget(suffix_, 0, 2, Qt::AlignRight | Qt::AlignVCenter);
- }
- void Row::setPrefixEnabled(bool enabled)
- {
- if (!prefix_)
- return;
- if (enabled)
- setSuffixEnabled(false);
- if (enabled == prefix_->isEnabled() && enabled == prefix_->isVisible())
- return;
- layout->setColumnStretch(0, enabled ? 3 : 0);
- prefix_->setEnabled(enabled);
- prefix_->setVisible(enabled);
- }
- void Row::setSuffixEnabled(bool enabled)
- {
- if (!suffix_)
- return;
- if (enabled)
- setPrefixEnabled(false);
- if (enabled == suffix_->isEnabled() && enabled == suffix_->isVisible())
- return;
- suffix_->setEnabled(enabled);
- suffix_->setVisible(enabled);
- }
- void Row::setTitle(const QString &name)
- {
- nameLabel->setText(name);
- setAccessibleName(name);
- showTitle(true);
- }
- void Row::setDescription(const QString &description)
- {
- descriptionLabel->setText(description);
- setAccessibleDescription(description);
- showDescription(true);
- }
- void Row::showTitle(bool visible)
- {
- nameLabel->setVisible(visible);
- }
- void Row::showDescription(bool visible)
- {
- descriptionLabel->setVisible(visible);
- }
- void Row::setBuddy(QWidget *widget)
- {
- buddyWidget = widget;
- Utils::addClass(widget, "row-buddy");
- }
- void Row::setChangeCursor(bool change)
- {
- changeCursor = change;
- Utils::toggleClass("cursor-pointer", change);
- }
- void Row::enterEvent(QEnterEvent *event)
- {
- if (!isEnabled())
- return;
- if (changeCursor) {
- setCursor(Qt::PointingHandCursor);
- }
- Utils::addClass("hover");
- if (buddyWidget)
- Utils::repolish(buddyWidget);
- if (hasPrefix() || hasSuffix()) {
- Utils::polishChildren();
- }
- GenericRow::enterEvent(event);
- }
- void Row::leaveEvent(QEvent *event)
- {
- Utils::removeClass("hover");
- if (buddyWidget)
- Utils::repolish(buddyWidget);
- if (hasPrefix() || hasSuffix()) {
- Utils::polishChildren();
- }
- GenericRow::leaveEvent(event);
- }
- void Row::mouseReleaseEvent(QMouseEvent *event)
- {
- if (event->button() & Qt::LeftButton) {
- emit clicked();
- }
- QFrame::mouseReleaseEvent(event);
- }
- void Row::keyReleaseEvent(QKeyEvent *event)
- {
- if (event->key() == Qt::Key_Space || event->key() == Qt::Key_Enter) {
- emit clicked();
- }
- QFrame::keyReleaseEvent(event);
- }
- void Row::connectBuddyWidget(QWidget *widget)
- {
- setAccessibleName(nameLabel->text());
- setFocusProxy(widget);
- setBuddy(widget);
- // If element is a ToggleSwitch and checkable, forward clicks to the widget
- ToggleSwitch *obsToggle = dynamic_cast<ToggleSwitch *>(widget);
- if (obsToggle && obsToggle->isCheckable()) {
- setChangeCursor(true);
- connect(this, &Row::clicked, obsToggle, &ToggleSwitch::click);
- return;
- }
- // If element is any other QAbstractButton subclass, and checkable, forward clicks to the widget.
- QAbstractButton *button = dynamic_cast<QAbstractButton *>(widget);
- if (button && button->isCheckable()) {
- setChangeCursor(true);
- connect(this, &Row::clicked, button, &QAbstractButton::click);
- return;
- }
- // If element is an ComboBox, clicks toggle the dropdown.
- ComboBox *obsCombo = dynamic_cast<ComboBox *>(widget);
- if (obsCombo) {
- setChangeCursor(true);
- connect(this, &Row::clicked, obsCombo, &ComboBox::togglePopup);
- return;
- }
- }
- // Button for expanding a collapsible ActionRow
- ExpandButton::ExpandButton(QWidget *parent) : QAbstractButton(parent), Utils(this)
- {
- setCheckable(true);
- }
- void ExpandButton::paintEvent(QPaintEvent *)
- {
- QStyleOptionButton opt;
- opt.initFrom(this);
- QPainter p(this);
- bool checked = isChecked();
- opt.state.setFlag(QStyle::State_On, checked);
- opt.state.setFlag(QStyle::State_Off, !checked);
- opt.state.setFlag(QStyle::State_Sunken, checked);
- p.setRenderHint(QPainter::Antialiasing, true);
- p.setRenderHint(QPainter::SmoothPixmapTransform, true);
- style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &opt, &p, this);
- style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, &p, this);
- }
- // Row variant that can be expanded to show another properties list
- CollapsibleRow::CollapsibleRow(QWidget *parent) : GenericRow(parent)
- {
- layout = new QVBoxLayout;
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(0);
- setLayout(layout);
- rowWidget = new RowFrame();
- rowLayout = new QHBoxLayout();
- rowLayout->setContentsMargins(0, 0, 0, 0);
- rowLayout->setSpacing(0);
- rowWidget->setLayout(rowLayout);
- actionRow = new Row();
- actionRow->setChangeCursor(false);
- rowLayout->addWidget(actionRow);
- propertyList = new PropertiesList(this);
- propertyList->setVisible(false);
- expandFrame = new QFrame();
- btnLayout = new QHBoxLayout();
- btnLayout->setContentsMargins(0, 0, 0, 0);
- btnLayout->setSpacing(0);
- expandFrame->setLayout(btnLayout);
- Utils::addClass(expandFrame, "btn-frame");
- actionRow->setBuddy(expandFrame);
- expandButton = new ExpandButton(this);
- btnLayout->addWidget(expandButton);
- rowLayout->addWidget(expandFrame);
- layout->addWidget(rowWidget);
- layout->addWidget(propertyList);
- actionRow->setFocusProxy(expandButton);
- connect(expandButton, &QAbstractButton::clicked, this, &CollapsibleRow::toggleVisibility);
- connect(actionRow, &Row::clicked, expandButton, &QAbstractButton::click);
- }
- void CollapsibleRow::setCheckable(bool check)
- {
- checkable = check;
- if (checkable && !toggleSwitch) {
- propertyList->setEnabled(false);
- Utils::polishChildren(propertyList);
- toggleSwitch = new ToggleSwitch(false);
- actionRow->setSuffix(toggleSwitch, false);
- connect(toggleSwitch, &ToggleSwitch::toggled, propertyList, &PropertiesList::setEnabled);
- connect(toggleSwitch, &ToggleSwitch::toggled, this, &CollapsibleRow::toggled);
- }
- if (!checkable && toggleSwitch) {
- propertyList->setEnabled(true);
- Utils::polishChildren(propertyList);
- actionRow->suffix()->deleteLater();
- }
- }
- void CollapsibleRow::setChecked(bool checked)
- {
- if (!isCheckable()) {
- throw std::logic_error("Called setChecked on a non-checkable row.");
- }
- toggleSwitch->setChecked(checked);
- }
- void CollapsibleRow::setTitle(const QString &name)
- {
- actionRow->setTitle(name);
- }
- void CollapsibleRow::setDescription(const QString &description)
- {
- actionRow->setDescription(description);
- }
- void CollapsibleRow::toggleVisibility()
- {
- bool visible = !propertyList->isVisible();
- propertyList->setVisible(visible);
- expandButton->setChecked(visible);
- }
- void CollapsibleRow::addRow(GenericRow *actionRow)
- {
- propertyList->addRow(actionRow);
- }
- RowFrame::RowFrame(QWidget *parent) : QFrame(parent), Utils(this) {}
- void RowFrame::enterEvent(QEnterEvent *event)
- {
- setCursor(Qt::PointingHandCursor);
- Utils::addClass("hover");
- Utils::polishChildren();
- QWidget::enterEvent(event);
- }
- void RowFrame::leaveEvent(QEvent *event)
- {
- Utils::removeClass("hover");
- Utils::polishChildren();
- QWidget::leaveEvent(event);
- }
- } // namespace idian
|