File indexing completed on 2025-04-27 03:58:30

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-03-14
0007  * Description : A widget to host settings as expander box
0008  *
0009  * SPDX-FileCopyrightText: 2008-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText:      2010 by Manuel Viet <contact at 13zenrv dot fr>
0012  * SPDX-FileCopyrightText: 2001      by Frerich Raabe <raabe at kde dot org>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "dexpanderbox.h"
0019 
0020 // Qt includes
0021 
0022 #include <QApplication>
0023 #include <QMouseEvent>
0024 #include <QPainter>
0025 #include <QStyle>
0026 #include <QStyleOption>
0027 #include <QToolButton>
0028 #include <QGridLayout>
0029 #include <QHBoxLayout>
0030 #include <QCheckBox>
0031 #include <QScreen>
0032 #include <QWindow>
0033 
0034 // KDE includes
0035 
0036 #include <kconfiggroup.h>
0037 
0038 // Local includes
0039 
0040 #include "dlayoutbox.h"
0041 
0042 namespace Digikam
0043 {
0044 
0045 DLineWidget::DLineWidget(Qt::Orientation orientation, QWidget* const parent)
0046     : QFrame(parent)
0047 {
0048     setLineWidth(1);
0049     setMidLineWidth(0);
0050     setFrameShadow(QFrame::Sunken);
0051 
0052     if (orientation == Qt::Vertical)
0053     {
0054         setFrameShape(QFrame::VLine);
0055         setMinimumSize(2, 0);
0056     }
0057     else
0058     {
0059         setFrameShape(QFrame::HLine);
0060         setMinimumSize(0, 2);
0061     }
0062 
0063     updateGeometry();
0064 }
0065 
0066 DLineWidget::~DLineWidget()
0067 {
0068 }
0069 
0070 // ------------------------------------------------------------------------------------
0071 
0072 class Q_DECL_HIDDEN DAdjustableLabel::Private
0073 {
0074 public:
0075 
0076     explicit Private()
0077       : emode(Qt::ElideMiddle)
0078     {
0079     }
0080 
0081     QString           ajdText;
0082     Qt::TextElideMode emode;
0083 };
0084 
0085 DAdjustableLabel::DAdjustableLabel(QWidget* const parent)
0086     : QLabel(parent),
0087       d     (new Private)
0088 {
0089     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
0090 }
0091 
0092 DAdjustableLabel::~DAdjustableLabel()
0093 {
0094     delete d;
0095 }
0096 
0097 void DAdjustableLabel::resizeEvent(QResizeEvent*)
0098 {
0099     adjustTextToLabel();
0100 }
0101 
0102 QSize DAdjustableLabel::minimumSizeHint() const
0103 {
0104     QSize sh = QLabel::minimumSizeHint();
0105     sh.setWidth(-1);
0106     return sh;
0107 }
0108 
0109 QSize DAdjustableLabel::sizeHint() const
0110 {
0111     QScreen* screen = qApp->primaryScreen();
0112 
0113     if (QWidget* const widget = nativeParentWidget())
0114     {
0115         if (QWindow* const window = widget->windowHandle())
0116         {
0117             screen = window->screen();
0118         }
0119     }
0120 
0121     QFontMetrics fm(fontMetrics());
0122     int maxW     = screen->geometry().width() * 3 / 4;
0123     int currentW = fm.horizontalAdvance(d->ajdText);
0124 
0125     return (QSize(currentW > maxW ? maxW : currentW, QLabel::sizeHint().height()));
0126 }
0127 
0128 void DAdjustableLabel::setAdjustedText(const QString& text)
0129 {
0130     d->ajdText = text;
0131 
0132     if (d->ajdText.isNull())
0133     {
0134         QLabel::clear();
0135     }
0136 
0137     adjustTextToLabel();
0138 }
0139 
0140 QString DAdjustableLabel::adjustedText() const
0141 {
0142     return d->ajdText;
0143 }
0144 
0145 void DAdjustableLabel::setAlignment(Qt::Alignment alignment)
0146 {
0147     QString tmp(d->ajdText);
0148     QLabel::setAlignment(alignment);
0149     d->ajdText = tmp;
0150 }
0151 
0152 void DAdjustableLabel::setElideMode(Qt::TextElideMode mode)
0153 {
0154     d->emode = mode;
0155     adjustTextToLabel();
0156 }
0157 
0158 void DAdjustableLabel::adjustTextToLabel()
0159 {
0160     QFontMetrics fm(fontMetrics());
0161     QStringList adjustedLines;
0162     int lblW      = size().width();
0163     bool adjusted = false;
0164 
0165     Q_FOREACH (const QString& line, d->ajdText.split(QLatin1Char('\n')))
0166     {
0167         int lineW = fm.horizontalAdvance(line);
0168 
0169         if (lineW > lblW)
0170         {
0171             adjusted = true;
0172             adjustedLines << fm.elidedText(line, d->emode, lblW);
0173         }
0174         else
0175         {
0176             adjustedLines << line;
0177         }
0178     }
0179 
0180     if (adjusted)
0181     {
0182         QLabel::setText(adjustedLines.join(QLatin1Char('\n')));
0183         setToolTip(d->ajdText);
0184     }
0185     else
0186     {
0187         QLabel::setText(d->ajdText);
0188         setToolTip(QString());
0189     }
0190 }
0191 
0192 // ------------------------------------------------------------------------------------
0193 
0194 DClickLabel::DClickLabel(QWidget* const parent)
0195     : QLabel(parent)
0196 {
0197     setCursor(Qt::PointingHandCursor);
0198 }
0199 
0200 DClickLabel::DClickLabel(const QString& text, QWidget* const parent)
0201     : QLabel(text, parent)
0202 {
0203     setCursor(Qt::PointingHandCursor);
0204 }
0205 
0206 DClickLabel::~DClickLabel()
0207 {
0208 }
0209 
0210 void DClickLabel::mousePressEvent(QMouseEvent* event)
0211 {
0212     QLabel::mousePressEvent(event);
0213 
0214     /*
0215      * In some contexts, like QGraphicsView, there will be no
0216      * release event if the press event was not accepted.
0217      */
0218     if (event->button() == Qt::LeftButton)
0219     {
0220         event->accept();
0221     }
0222 }
0223 
0224 void DClickLabel::mouseReleaseEvent(QMouseEvent* event)
0225 {
0226     QLabel::mouseReleaseEvent(event);
0227 
0228     if (event->button() == Qt::LeftButton)
0229     {
0230         Q_EMIT leftClicked();
0231         Q_EMIT activated();
0232         event->accept();
0233     }
0234 }
0235 
0236 void DClickLabel::keyPressEvent(QKeyEvent* e)
0237 {
0238     switch (e->key())
0239     {
0240         case Qt::Key_Down:
0241         case Qt::Key_Right:
0242         case Qt::Key_Space:
0243             Q_EMIT activated();
0244             return;
0245 
0246         default:
0247             break;
0248     }
0249 
0250     QLabel::keyPressEvent(e);
0251 }
0252 
0253 // ------------------------------------------------------------------------
0254 
0255 DSqueezedClickLabel::DSqueezedClickLabel(QWidget* const parent)
0256     : DAdjustableLabel(parent)
0257 {
0258     setCursor(Qt::PointingHandCursor);
0259 }
0260 
0261 DSqueezedClickLabel::DSqueezedClickLabel(const QString& text, QWidget* const parent)
0262     : DAdjustableLabel(parent)
0263 {
0264     setAdjustedText(text);
0265     setCursor(Qt::PointingHandCursor);
0266 }
0267 
0268 DSqueezedClickLabel::~DSqueezedClickLabel()
0269 {
0270 }
0271 
0272 void DSqueezedClickLabel::mouseReleaseEvent(QMouseEvent* event)
0273 {
0274     QLabel::mouseReleaseEvent(event);
0275 
0276     if (event->button() == Qt::LeftButton)
0277     {
0278         Q_EMIT leftClicked();
0279         Q_EMIT activated();
0280         event->accept();
0281     }
0282 }
0283 
0284 void DSqueezedClickLabel::mousePressEvent(QMouseEvent* event)
0285 {
0286     QLabel::mousePressEvent(event);
0287 
0288     /*
0289      * In some contexts, like QGraphicsView, there will be no
0290      * release event if the press event was not accepted.
0291      */
0292     if (event->button() == Qt::LeftButton)
0293     {
0294         event->accept();
0295     }
0296 }
0297 
0298 void DSqueezedClickLabel::keyPressEvent(QKeyEvent* e)
0299 {
0300     switch (e->key())
0301     {
0302         case Qt::Key_Down:
0303         case Qt::Key_Right:
0304         case Qt::Key_Space:
0305             Q_EMIT activated();
0306             return;
0307 
0308         default:
0309             break;
0310     }
0311 
0312     QLabel::keyPressEvent(e);
0313 }
0314 
0315 // ------------------------------------------------------------------------
0316 
0317 DArrowClickLabel::DArrowClickLabel(QWidget* const parent)
0318     : QWidget(parent),
0319       m_arrowType(Qt::DownArrow)
0320 {
0321     setCursor(Qt::PointingHandCursor);
0322     setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
0323     m_size   = 8;
0324     m_margin = 2;
0325 }
0326 
0327 void DArrowClickLabel::setArrowType(Qt::ArrowType type)
0328 {
0329     m_arrowType = type;
0330     update();
0331 }
0332 
0333 DArrowClickLabel::~DArrowClickLabel()
0334 {
0335 }
0336 
0337 Qt::ArrowType DArrowClickLabel::arrowType() const
0338 {
0339     return m_arrowType;
0340 }
0341 
0342 void DArrowClickLabel::mousePressEvent(QMouseEvent* event)
0343 {
0344     /*
0345      * In some contexts, like QGraphicsView, there will be no
0346      * release event if the press event was not accepted.
0347      */
0348     if (event->button() == Qt::LeftButton)
0349     {
0350         event->accept();
0351     }
0352 }
0353 
0354 void DArrowClickLabel::mouseReleaseEvent(QMouseEvent* event)
0355 {
0356     if (event->button() == Qt::LeftButton)
0357     {
0358         Q_EMIT leftClicked();
0359     }
0360 }
0361 
0362 void DArrowClickLabel::paintEvent(QPaintEvent*)
0363 {
0364     QPainter p(this);
0365 
0366     QStyleOptionFrame opt;
0367     opt.initFrom(this);
0368     opt.lineWidth    = 2;
0369     opt.midLineWidth = 0;
0370 
0371 /*
0372     p.fillRect( rect(), palette().brush( QPalette::Window ) );
0373     style()->drawPrimitive( QStyle::PE_Frame, &opt, &p, this);
0374 */
0375 
0376     if (m_arrowType == Qt::NoArrow)
0377     {
0378         return;
0379     }
0380 
0381     if ((width() < (m_size + m_margin)) || (height() < (m_size + m_margin)))
0382     {
0383         return; // don't draw arrows if we are too small
0384     }
0385 
0386     unsigned int x = 0;
0387     unsigned int y = 0;
0388 
0389     if      (m_arrowType == Qt::DownArrow)
0390     {
0391         x = (width() - m_size) / 2;
0392         y = height() - (m_size + m_margin);
0393     }
0394     else if (m_arrowType == Qt::UpArrow)
0395     {
0396         x = (width() - m_size) / 2;
0397         y = m_margin;
0398     }
0399     else if (m_arrowType == Qt::RightArrow)
0400     {
0401         x = width() - (m_size + m_margin);
0402         y = (height() - m_size) / 2;
0403     }
0404     else // arrowType == LeftArrow
0405     {
0406         x = m_margin;
0407         y = (height() - m_size) / 2;
0408     }
0409 
0410 /*
0411     if (isDown())
0412     {
0413         ++x;
0414         ++y;
0415     }
0416 */
0417 
0418     QStyle::PrimitiveElement e = QStyle::PE_IndicatorArrowLeft;
0419 
0420     switch (m_arrowType)
0421     {
0422         case Qt::LeftArrow:
0423             e = QStyle::PE_IndicatorArrowLeft;
0424             break;
0425 
0426         case Qt::RightArrow:
0427             e = QStyle::PE_IndicatorArrowRight;
0428             break;
0429 
0430         case Qt::UpArrow:
0431             e = QStyle::PE_IndicatorArrowUp;
0432             break;
0433 
0434         case Qt::DownArrow:
0435             e = QStyle::PE_IndicatorArrowDown;
0436             break;
0437 
0438         case Qt::NoArrow:
0439             break;
0440     }
0441 
0442     opt.state |= QStyle::State_Enabled;
0443     opt.rect   = QRect( x, y, m_size, m_size);
0444 
0445     style()->drawPrimitive( e, &opt, &p, this );
0446 }
0447 
0448 QSize DArrowClickLabel::sizeHint() const
0449 {
0450     return QSize(m_size + 2*m_margin, m_size + 2*m_margin);
0451 }
0452 
0453 // ------------------------------------------------------------------------
0454 
0455 class Q_DECL_HIDDEN DLabelExpander::Private
0456 {
0457 
0458 public:
0459 
0460     explicit Private()
0461       : expandByDefault (true),
0462         checkBox        (nullptr),
0463         pixmapLabel     (nullptr),
0464         btn             (nullptr),
0465         containerWidget (nullptr),
0466         grid            (nullptr),
0467         line            (nullptr),
0468         hbox            (nullptr),
0469         arrow           (nullptr),
0470         clickLabel      (nullptr)
0471     {
0472     }
0473 
0474     bool              expandByDefault;
0475 
0476     QCheckBox*        checkBox;
0477     QLabel*           pixmapLabel;
0478     QToolButton*      btn;
0479     QWidget*          containerWidget;
0480     QGridLayout*      grid;
0481 
0482     DLineWidget*      line;
0483     QWidget*          hbox;
0484 
0485     DArrowClickLabel* arrow;
0486     DClickLabel*      clickLabel;
0487 };
0488 
0489 DLabelExpander::DLabelExpander(QWidget* const parent)
0490     : QWidget(parent),
0491       d      (new Private)
0492 {
0493     const int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0494                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0495 
0496     d->grid        = new QGridLayout(this);
0497     d->line        = new DLineWidget(Qt::Horizontal, this);
0498     d->hbox        = new QWidget(this);
0499     d->arrow       = new DArrowClickLabel(d->hbox);
0500     d->checkBox    = new QCheckBox(d->hbox);
0501     d->pixmapLabel = new QLabel(d->hbox);
0502     d->clickLabel  = new DClickLabel(d->hbox);
0503     d->btn         = new QToolButton(d->hbox);
0504 
0505     QHBoxLayout* const hlay = new QHBoxLayout(d->hbox);
0506     hlay->addWidget(d->arrow);
0507     hlay->addWidget(d->checkBox);
0508     hlay->addWidget(d->pixmapLabel);
0509     hlay->addWidget(d->clickLabel, 10);
0510     hlay->addWidget(d->btn);
0511     hlay->setContentsMargins(QMargins());
0512     hlay->setSpacing(spacing);
0513 
0514     d->pixmapLabel->installEventFilter(this);
0515     d->pixmapLabel->setCursor(Qt::PointingHandCursor);
0516 
0517     d->hbox->setCursor(Qt::PointingHandCursor);
0518     setCheckBoxVisible(false);
0519     setButtonVisible(false);
0520 
0521     d->grid->addWidget(d->line, 0, 0, 1, 3);
0522     d->grid->addWidget(d->hbox, 1, 0, 1, 3);
0523     d->grid->setColumnStretch(2, 10);
0524     d->grid->setContentsMargins(spacing, spacing, spacing, spacing);
0525     d->grid->setSpacing(spacing);
0526 
0527     connect(d->arrow, &DArrowClickLabel::leftClicked,
0528             this, &DLabelExpander::slotToggleContainer);
0529 
0530     connect(d->clickLabel, &DClickLabel::activated,
0531             this, &DLabelExpander::slotToggleContainer);
0532 
0533     connect(d->checkBox, &QCheckBox::toggled,
0534             this, &DLabelExpander::signalToggled);
0535 
0536     connect(d->btn, &QToolButton::pressed,
0537             this, &DLabelExpander::signalButtonPressed);
0538 }
0539 
0540 DLabelExpander::~DLabelExpander()
0541 {
0542     delete d;
0543 }
0544 
0545 void DLabelExpander::setCheckBoxVisible(bool b)
0546 {
0547     d->checkBox->setVisible(b);
0548 }
0549 
0550 bool DLabelExpander::checkBoxIsVisible() const
0551 {
0552     return d->checkBox->isVisible();
0553 }
0554 
0555 void DLabelExpander::setChecked(bool b)
0556 {
0557     d->checkBox->setChecked(b);
0558 }
0559 
0560 bool DLabelExpander::isChecked() const
0561 {
0562     return d->checkBox->isChecked();
0563 }
0564 
0565 void DLabelExpander::setLineVisible(bool b)
0566 {
0567     d->line->setVisible(b);
0568 }
0569 
0570 bool DLabelExpander::lineIsVisible() const
0571 {
0572     return d->line->isVisible();
0573 }
0574 
0575 void DLabelExpander::setText(const QString& txt)
0576 {
0577     d->clickLabel->setText(QString::fromUtf8("<qt><b>%1</b></qt>").arg(txt));
0578 }
0579 
0580 QString DLabelExpander::text() const
0581 {
0582     return d->clickLabel->text();
0583 }
0584 
0585 void DLabelExpander::setIcon(const QIcon& icon)
0586 {
0587     d->pixmapLabel->setPixmap(icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize)));
0588 }
0589 
0590 QIcon DLabelExpander::icon() const
0591 {
0592 
0593 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
0594 
0595     return QIcon(d->pixmapLabel->pixmap(Qt::ReturnByValue));
0596 
0597 #else
0598 
0599     return QIcon(*d->pixmapLabel->pixmap());
0600 
0601 #endif
0602 
0603 }
0604 
0605 void DLabelExpander::setButtonVisible(bool b)
0606 {
0607     d->btn->setVisible(b);
0608 }
0609 
0610 bool DLabelExpander::buttonIsVisible() const
0611 {
0612     return d->btn->isVisible();
0613 }
0614 
0615 void DLabelExpander::setButtonIcon(const QIcon& icon)
0616 {
0617     d->btn->setIcon(icon);
0618     d->btn->setIconSize(QSize(style()->pixelMetric(QStyle::PM_SmallIconSize), style()->pixelMetric(QStyle::PM_SmallIconSize)));
0619 }
0620 
0621 void DLabelExpander::setWidget(QWidget* const widget)
0622 {
0623     if (widget)
0624     {
0625         d->containerWidget = widget;
0626         d->containerWidget->setParent(this);
0627         d->grid->addWidget(d->containerWidget, 2, 0, 1, 3);
0628     }
0629 }
0630 
0631 QWidget* DLabelExpander::widget() const
0632 {
0633     return d->containerWidget;
0634 }
0635 
0636 void DLabelExpander::setExpandByDefault(bool b)
0637 {
0638     d->expandByDefault = b;
0639 }
0640 
0641 bool DLabelExpander::isExpandByDefault() const
0642 {
0643     return d->expandByDefault;
0644 }
0645 
0646 void DLabelExpander::setExpanded(bool b)
0647 {
0648     if (d->containerWidget)
0649     {
0650         d->containerWidget->setVisible(b);
0651 
0652         if (b)
0653         {
0654            d->arrow->setArrowType(Qt::DownArrow);
0655         }
0656         else
0657         {
0658            d->arrow->setArrowType(Qt::RightArrow);
0659         }
0660     }
0661 
0662     Q_EMIT signalExpanded(b);
0663 }
0664 
0665 bool DLabelExpander::isExpanded() const
0666 {
0667     return (d->arrow->arrowType() == Qt::DownArrow);
0668 }
0669 
0670 void DLabelExpander::slotToggleContainer()
0671 {
0672     if (d->containerWidget)
0673     {
0674         setExpanded(!d->containerWidget->isVisible());
0675     }
0676 }
0677 
0678 bool DLabelExpander::eventFilter(QObject* obj, QEvent* ev)
0679 {
0680     if (obj == d->pixmapLabel)
0681     {
0682         if (ev->type() == QEvent::MouseButtonRelease)
0683         {
0684             slotToggleContainer();
0685             return false;
0686         }
0687         else
0688         {
0689             return false;
0690         }
0691     }
0692     else
0693     {
0694         // pass the event on to the parent class
0695 
0696         return QWidget::eventFilter(obj, ev);
0697     }
0698 }
0699 
0700 // ------------------------------------------------------------------------
0701 
0702 class Q_DECL_HIDDEN DExpanderBox::Private
0703 {
0704 public:
0705 
0706     explicit Private(DExpanderBox* const box)
0707       : vbox  (nullptr),
0708         parent(box)
0709     {
0710     }
0711 
0712     void createItem(int index, QWidget* const w, const QIcon& icon, const QString& txt,
0713                     const QString& objName, bool expandBydefault)
0714     {
0715         DLabelExpander* const exp = new DLabelExpander(parent->viewport());
0716         exp->setText(txt);
0717         exp->setIcon(icon.pixmap(QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize)));
0718         exp->setWidget(w);
0719         exp->setLineVisible(!wList.isEmpty());
0720         exp->setObjectName(objName);
0721         exp->setExpandByDefault(expandBydefault);
0722 
0723         if (index >= 0)
0724         {
0725             vbox->insertWidget(index, exp);
0726             wList.insert(index, exp);
0727         }
0728         else
0729         {
0730             vbox->addWidget(exp);
0731             wList.append(exp);
0732         }
0733 
0734         parent->connect(exp, SIGNAL(signalExpanded(bool)),
0735                         parent, SLOT(slotItemExpanded(bool)));
0736 
0737         parent->connect(exp, SIGNAL(signalToggled(bool)),
0738                         parent, SLOT(slotItemToggled(bool)));
0739 
0740         parent->connect(exp, SIGNAL(signalButtonPressed()),
0741                         parent, SLOT(slotItemButtonPressed()));
0742     }
0743 
0744 public:
0745 
0746     QList<DLabelExpander*> wList;
0747 
0748     QVBoxLayout*           vbox;
0749 
0750     DExpanderBox*          parent;
0751 };
0752 
0753 DExpanderBox::DExpanderBox(QWidget* const parent)
0754     : QScrollArea(parent),
0755       d          (new Private(this))
0756 {
0757     setFrameStyle(QFrame::NoFrame);
0758     setWidgetResizable(true);
0759     QWidget* const main = new QWidget(viewport());
0760     d->vbox             = new QVBoxLayout(main);
0761     d->vbox->setSpacing(qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0762                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)));
0763     d->vbox->setContentsMargins(QMargins());
0764     setWidget(main);
0765 
0766     setAutoFillBackground(false);
0767     viewport()->setAutoFillBackground(false);
0768     main->setAutoFillBackground(false);
0769 }
0770 
0771 DExpanderBox::~DExpanderBox()
0772 {
0773     d->wList.clear();
0774     delete d;
0775 }
0776 
0777 void DExpanderBox::setCheckBoxVisible(int index, bool b)
0778 {
0779     if ((index > d->wList.count()) || (index < 0))
0780     {
0781         return;
0782     }
0783 
0784     d->wList[index]->setCheckBoxVisible(b);
0785 }
0786 
0787 bool DExpanderBox::checkBoxIsVisible(int index) const
0788 {
0789     if ((index > d->wList.count()) || (index < 0))
0790     {
0791         return false;
0792     }
0793 
0794     return d->wList[index]->checkBoxIsVisible();
0795 }
0796 
0797 void DExpanderBox::setChecked(int index, bool b)
0798 {
0799     if ((index > d->wList.count()) || (index < 0))
0800     {
0801         return;
0802     }
0803 
0804     d->wList[index]->setChecked(b);
0805 }
0806 
0807 bool DExpanderBox::isChecked(int index) const
0808 {
0809     if ((index > d->wList.count()) || (index < 0))
0810     {
0811         return false;
0812     }
0813 
0814     return d->wList[index]->isChecked();
0815 }
0816 
0817 void DExpanderBox::addItem(QWidget* const w, const QIcon& icon, const QString& txt,
0818                            const QString& objName, bool expandBydefault)
0819 {
0820     d->createItem(-1, w, icon, txt, objName, expandBydefault);
0821 }
0822 
0823 void DExpanderBox::addItem(QWidget* const w, const QString& txt,
0824                            const QString& objName, bool expandBydefault)
0825 {
0826     addItem(w, QIcon(), txt, objName, expandBydefault);
0827 }
0828 
0829 void DExpanderBox::addStretch()
0830 {
0831     d->vbox->addStretch(10);
0832 }
0833 
0834 void DExpanderBox::insertItem(int index, QWidget* const w, const QIcon& icon, const QString& txt,
0835                               const QString& objName, bool expandBydefault)
0836 {
0837     d->createItem(index, w, icon, txt, objName, expandBydefault);
0838 }
0839 
0840 void DExpanderBox::slotItemExpanded(bool b)
0841 {
0842     DLabelExpander* const exp = dynamic_cast<DLabelExpander*>(sender());
0843  
0844     if (exp)
0845     {
0846         int index = indexOf(exp);
0847         Q_EMIT signalItemExpanded(index, b);
0848     }
0849 }
0850 
0851 void DExpanderBox::slotItemButtonPressed()
0852 {
0853     DLabelExpander* const exp = dynamic_cast<DLabelExpander*>(sender());
0854 
0855     if (exp)
0856     {
0857         int index = indexOf(exp);
0858         Q_EMIT signalItemButtonPressed(index);
0859     }
0860 }
0861 
0862 void DExpanderBox::slotItemToggled(bool b)
0863 {
0864     DLabelExpander* const exp = dynamic_cast<DLabelExpander*>(sender());
0865 
0866     if (exp)
0867     {
0868         int index = indexOf(exp);
0869         Q_EMIT signalItemToggled(index, b);
0870     }
0871 }
0872 
0873 void DExpanderBox::insertItem(int index, QWidget* const w, const QString& txt,
0874                               const QString& objName, bool expandBydefault)
0875 {
0876     insertItem(index, w, QIcon(), txt, objName, expandBydefault);
0877 }
0878 
0879 void DExpanderBox::insertStretch(int index)
0880 {
0881     d->vbox->insertStretch(index, 10);
0882 }
0883 
0884 void DExpanderBox::removeItem(int index)
0885 {
0886     if ((index > d->wList.count()) || (index < 0))
0887     {
0888         return;
0889     }
0890 
0891     d->wList[index]->hide();
0892     d->wList.removeAt(index);
0893 }
0894 
0895 void DExpanderBox::setItemText(int index, const QString& txt)
0896 {
0897     if ((index > d->wList.count()) || (index < 0))
0898     {
0899         return;
0900     }
0901 
0902     d->wList[index]->setText(txt);
0903 }
0904 
0905 QString DExpanderBox::itemText(int index) const
0906 {
0907     if ((index > d->wList.count()) || (index < 0))
0908     {
0909         return QString();
0910     }
0911 
0912     return d->wList[index]->text();
0913 }
0914 
0915 void DExpanderBox::setItemIcon(int index, const QIcon& icon)
0916 {
0917     if ((index > d->wList.count()) || (index < 0))
0918     {
0919         return;
0920     }
0921 
0922     d->wList[index]->setIcon(icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize)));
0923 }
0924 
0925 QIcon DExpanderBox::itemIcon(int index) const
0926 {
0927     if ((index > d->wList.count()) || (index < 0))
0928     {
0929         return QIcon();
0930     }
0931 
0932     return d->wList[index]->icon();
0933 }
0934 
0935 void DExpanderBox::setButtonVisible(int index, bool b)
0936 {
0937     if ((index > d->wList.count()) || (index < 0))
0938     {
0939         return;
0940     }
0941 
0942     d->wList[index]->setButtonVisible(b);
0943 }
0944 
0945 bool DExpanderBox::buttonIsVisible(int index) const
0946 {
0947     if ((index > d->wList.count()) || (index < 0))
0948     {
0949         return false;
0950     }
0951 
0952     return d->wList[index]->buttonIsVisible();
0953 }
0954 
0955 void DExpanderBox::setButtonIcon(int index, const QIcon& icon)
0956 {
0957     if ((index > d->wList.count()) || (index < 0))
0958     {
0959         return;
0960     }
0961 
0962     d->wList[index]->setButtonIcon(icon);
0963 }
0964 
0965 int DExpanderBox::count() const
0966 {
0967     return d->wList.count();
0968 }
0969 
0970 void DExpanderBox::setItemToolTip(int index, const QString& tip)
0971 {
0972     if ((index > d->wList.count()) || (index < 0))
0973     {
0974         return;
0975     }
0976 
0977     d->wList[index]->setToolTip(tip);
0978 }
0979 
0980 QString DExpanderBox::itemToolTip(int index) const
0981 {
0982     if ((index > d->wList.count()) || (index < 0))
0983     {
0984         return QString();
0985     }
0986 
0987     return d->wList[index]->toolTip();
0988 }
0989 
0990 void DExpanderBox::setItemEnabled(int index, bool enabled)
0991 {
0992     if ((index > d->wList.count()) || (index < 0))
0993     {
0994         return;
0995     }
0996 
0997     d->wList[index]->setEnabled(enabled);
0998 }
0999 
1000 bool DExpanderBox::isItemEnabled(int index) const
1001 {
1002     if ((index > d->wList.count()) || (index < 0))
1003     {
1004         return false;
1005     }
1006 
1007     return d->wList[index]->isEnabled();
1008 }
1009 
1010 DLabelExpander* DExpanderBox::widget(int index) const
1011 {
1012     if ((index > d->wList.count()) || (index < 0))
1013     {
1014         return nullptr;
1015     }
1016 
1017     return d->wList[index];
1018 }
1019 
1020 int DExpanderBox::indexOf(DLabelExpander* const widget) const
1021 {
1022     for (int i = 0 ; i < count() ; ++i)
1023     {
1024         DLabelExpander* const exp = d->wList[i];
1025 
1026         if (widget == exp)
1027         {
1028             return i;
1029         }
1030     }
1031 
1032     return -1;
1033 }
1034 
1035 void DExpanderBox::setItemExpanded(int index, bool b)
1036 {
1037     if ((index > d->wList.count()) || (index < 0))
1038     {
1039         return;
1040     }
1041 
1042     DLabelExpander* const exp = d->wList[index];
1043 
1044     if (!exp) return;
1045 
1046     exp->setExpanded(b);
1047 }
1048 
1049 bool DExpanderBox::isItemExpanded(int index) const
1050 {
1051     if ((index > d->wList.count()) || (index < 0))
1052     {
1053         return false;
1054     }
1055 
1056     DLabelExpander* const exp = d->wList[index];
1057 
1058     if (!exp)
1059     {
1060         return false;
1061     }
1062 
1063     return (exp->isExpanded());
1064 }
1065 
1066 void DExpanderBox::readSettings(KConfigGroup& group)
1067 {
1068     for (int i = 0 ; i < count() ; ++i)
1069     {
1070         DLabelExpander* const exp = d->wList[i];
1071 
1072         if (exp)
1073         {
1074             exp->setExpanded(group.readEntry(QString::fromUtf8("%1 Expanded").arg(exp->objectName()),
1075                                              exp->isExpandByDefault()));
1076         }
1077     }
1078 }
1079 
1080 void DExpanderBox::writeSettings(KConfigGroup& group)
1081 {
1082     for (int i = 0 ; i < count() ; ++i)
1083     {
1084         DLabelExpander* const exp = d->wList[i];
1085 
1086         if (exp)
1087         {
1088             group.writeEntry(QString::fromUtf8("%1 Expanded").arg(exp->objectName()),
1089                              exp->isExpanded());
1090         }
1091     }
1092 }
1093 
1094 // ------------------------------------------------------------------------
1095 
1096 DExpanderBoxExclusive::DExpanderBoxExclusive(QWidget* const parent)
1097     : DExpanderBox(parent)
1098 {
1099     setIsToolBox(true);
1100 }
1101 
1102 DExpanderBoxExclusive::~DExpanderBoxExclusive()
1103 {
1104 }
1105 
1106 void DExpanderBoxExclusive::slotItemExpanded(bool b)
1107 {
1108     DLabelExpander* const exp = dynamic_cast<DLabelExpander*>(sender());
1109 
1110     if (!exp)
1111     {
1112         return;
1113     }
1114 
1115     if (isToolBox() && b)
1116     {
1117         int item = 0;
1118 
1119         while (item < count())
1120         {
1121             if (isItemExpanded(item) && (item != indexOf(exp)))
1122             {
1123                 setItemExpanded(item, false);
1124             }
1125 
1126             item++;
1127         }
1128     }
1129 
1130     Q_EMIT signalItemExpanded(indexOf(exp), b);
1131 }
1132 
1133 void DExpanderBoxExclusive::setIsToolBox(bool b)
1134 {
1135     m_toolbox = b;
1136 }
1137 
1138 bool DExpanderBoxExclusive::isToolBox() const
1139 {
1140     return (m_toolbox);
1141 }
1142 
1143 } // namespace Digikam
1144 
1145 #include "moc_dexpanderbox.cpp"