File indexing completed on 2024-06-23 05:16:27

0001 /*  -*- c++ -*-
0002 
0003   kwidgetlister.cpp
0004 
0005   This file is part of libkdepim.
0006   SPDX-FileCopyrightText: 2001 Marc Mutz <mutz@kde.org>
0007 
0008   SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "kwidgetlister.h"
0012 
0013 #include <KGuiItem>
0014 #include <KLocalizedString>
0015 #include <QHBoxLayout>
0016 
0017 #include <QPushButton>
0018 #include <QVBoxLayout>
0019 
0020 #include <KStandardGuiItem>
0021 #include <cassert>
0022 
0023 using namespace KPIM;
0024 
0025 class Q_DECL_HIDDEN KWidgetLister::KWidgetListerPrivate
0026 {
0027 public:
0028     KWidgetListerPrivate(KWidgetLister *qq)
0029         : q(qq)
0030     {
0031     }
0032 
0033     ~KWidgetListerPrivate()
0034     {
0035         qDeleteAll(mWidgetList);
0036         mWidgetList.clear();
0037     }
0038 
0039     void enableControls();
0040 
0041     KWidgetLister *q = nullptr;
0042     QPushButton *mBtnMore = nullptr;
0043     QPushButton *mBtnFewer = nullptr;
0044     QPushButton *mBtnClear = nullptr;
0045     QVBoxLayout *mLayout = nullptr;
0046     QWidget *mButtonBox = nullptr;
0047     QList<QWidget *> mWidgetList;
0048     int mMinWidgets = 0;
0049     int mMaxWidgets = 0;
0050 };
0051 
0052 void KWidgetLister::KWidgetListerPrivate::enableControls()
0053 {
0054     const int count = mWidgetList.count();
0055     const bool isMaxWidgets = (count >= mMaxWidgets);
0056     const bool isMinWidgets = (count <= mMinWidgets);
0057     if (mBtnMore) {
0058         mBtnMore->setEnabled(!isMaxWidgets);
0059     }
0060     if (mBtnFewer) {
0061         mBtnFewer->setEnabled(!isMinWidgets);
0062     }
0063 }
0064 
0065 KWidgetLister::KWidgetLister(bool fewerMoreButton, int minWidgets, int maxWidgets, QWidget *parent)
0066     : QWidget(parent)
0067     , d(new KWidgetListerPrivate(this))
0068 {
0069     d->mMinWidgets = qMax(minWidgets, 1);
0070     d->mMaxWidgets = qMax(maxWidgets, d->mMinWidgets + 1);
0071     init(fewerMoreButton);
0072 }
0073 
0074 KWidgetLister::~KWidgetLister() = default;
0075 
0076 void KWidgetLister::init(bool fewerMoreButton)
0077 {
0078     //--------- the button box
0079     d->mLayout = new QVBoxLayout(this);
0080     d->mLayout->setContentsMargins({});
0081     d->mLayout->setSpacing(4);
0082     d->mLayout->setAlignment(Qt::AlignTop);
0083 
0084     d->mButtonBox = new QWidget(this);
0085     auto mButtonBoxHBoxLayout = new QHBoxLayout(d->mButtonBox);
0086     mButtonBoxHBoxLayout->setContentsMargins({});
0087     d->mLayout->addWidget(d->mButtonBox);
0088 
0089     if (fewerMoreButton) {
0090         d->mBtnMore = new QPushButton(d->mButtonBox);
0091         mButtonBoxHBoxLayout->addWidget(d->mBtnMore);
0092         KGuiItem::assign(d->mBtnMore, KGuiItem(i18nc("more widgets", "More"), QStringLiteral("list-add")));
0093         mButtonBoxHBoxLayout->setStretchFactor(d->mBtnMore, 0);
0094 
0095         d->mBtnFewer = new QPushButton(d->mButtonBox);
0096         mButtonBoxHBoxLayout->addWidget(d->mBtnFewer);
0097         KGuiItem::assign(d->mBtnFewer, KGuiItem(i18nc("fewer widgets", "Fewer"), QStringLiteral("list-remove")));
0098         mButtonBoxHBoxLayout->setStretchFactor(d->mBtnFewer, 0);
0099     }
0100     auto spacer = new QWidget(d->mButtonBox);
0101     mButtonBoxHBoxLayout->addWidget(spacer);
0102     mButtonBoxHBoxLayout->setStretchFactor(spacer, 1);
0103 
0104     d->mBtnClear = new QPushButton(d->mButtonBox);
0105     mButtonBoxHBoxLayout->addWidget(d->mBtnClear);
0106     KGuiItem::assign(d->mBtnClear, KStandardGuiItem::clear());
0107     // FIXME a useful what's this. KStandardGuiItem::clear() returns a text with an edit box
0108     d->mBtnClear->setWhatsThis(QString());
0109     mButtonBoxHBoxLayout->setStretchFactor(d->mBtnClear, 0);
0110 
0111     //---------- connect everything
0112     if (fewerMoreButton) {
0113         connect(d->mBtnMore, &QPushButton::clicked, this, &KWidgetLister::slotMore);
0114         connect(d->mBtnFewer, &QPushButton::clicked, this, &KWidgetLister::slotFewer);
0115     }
0116 
0117     connect(d->mBtnClear, &QPushButton::clicked, this, &KWidgetLister::slotClear);
0118 
0119     d->enableControls();
0120 }
0121 
0122 void KWidgetLister::slotMore()
0123 {
0124     // the class should make certain that slotMore can't
0125     // be called when mMaxWidgets are on screen.
0126     assert(d->mWidgetList.count() < d->mMaxWidgets);
0127 
0128     addWidgetAtEnd();
0129     //  adjustSize();
0130     d->enableControls();
0131 }
0132 
0133 void KWidgetLister::slotFewer()
0134 {
0135     // the class should make certain that slotFewer can't
0136     // be called when mMinWidgets are on screen.
0137     assert(d->mWidgetList.count() > d->mMinWidgets);
0138 
0139     removeLastWidget();
0140     //  adjustSize();
0141     d->enableControls();
0142 }
0143 
0144 void KWidgetLister::slotClear()
0145 {
0146     setNumberOfShownWidgetsTo(d->mMinWidgets);
0147 
0148     // clear remaining widgets
0149     for (QWidget *widget : std::as_const(d->mWidgetList)) {
0150         clearWidget(widget);
0151     }
0152 
0153     //  adjustSize();
0154     d->enableControls();
0155     Q_EMIT clearWidgets();
0156 }
0157 
0158 void KWidgetLister::addWidgetAtEnd(QWidget *widget)
0159 {
0160     if (!widget) {
0161         widget = this->createWidget(this);
0162     }
0163 
0164     d->mLayout->insertWidget(d->mLayout->indexOf(d->mButtonBox), widget);
0165     d->mWidgetList.append(widget);
0166     widget->show();
0167 
0168     d->enableControls();
0169     Q_EMIT widgetAdded();
0170     Q_EMIT widgetAdded(widget);
0171 }
0172 
0173 void KWidgetLister::removeLastWidget()
0174 {
0175     // The layout will take care that the
0176     // widget is removed from screen, too.
0177     delete d->mWidgetList.takeLast();
0178     d->enableControls();
0179     Q_EMIT widgetRemoved();
0180 }
0181 
0182 void KWidgetLister::clearWidget(QWidget *widget)
0183 {
0184     Q_UNUSED(widget)
0185 }
0186 
0187 QWidget *KWidgetLister::createWidget(QWidget *parent)
0188 {
0189     return new QWidget(parent);
0190 }
0191 
0192 void KWidgetLister::setNumberOfShownWidgetsTo(int aNum)
0193 {
0194     int superfluousWidgets = qMax(d->mWidgetList.count() - aNum, 0);
0195     int missingWidgets = qMax(aNum - d->mWidgetList.count(), 0);
0196 
0197     // remove superfluous widgets
0198     for (; superfluousWidgets; superfluousWidgets--) {
0199         removeLastWidget();
0200     }
0201 
0202     // add missing widgets
0203     for (; missingWidgets; missingWidgets--) {
0204         addWidgetAtEnd();
0205     }
0206 }
0207 
0208 QList<QWidget *> KWidgetLister::widgets() const
0209 {
0210     return d->mWidgetList;
0211 }
0212 
0213 int KWidgetLister::widgetsMinimum() const
0214 {
0215     return d->mMinWidgets;
0216 }
0217 
0218 int KWidgetLister::widgetsMaximum() const
0219 {
0220     return d->mMaxWidgets;
0221 }
0222 
0223 void KWidgetLister::removeWidget(QWidget *widget)
0224 {
0225     // The layout will take care that the
0226     // widget is removed from screen, too.
0227 
0228     if (d->mWidgetList.count() <= widgetsMinimum()) {
0229         return;
0230     }
0231 
0232     const int index = d->mWidgetList.indexOf(widget);
0233     QWidget *w = d->mWidgetList.takeAt(index);
0234     w->deleteLater();
0235     w = nullptr;
0236     d->enableControls();
0237     Q_EMIT widgetRemoved(widget);
0238     Q_EMIT widgetRemoved();
0239 }
0240 
0241 void KWidgetLister::addWidgetAfterThisWidget(QWidget *currentWidget, QWidget *widget)
0242 {
0243     if (!widget) {
0244         widget = this->createWidget(this);
0245     }
0246 
0247     int index = d->mLayout->indexOf(currentWidget ? currentWidget : d->mButtonBox) + 1;
0248     d->mLayout->insertWidget(index, widget);
0249     if (currentWidget) {
0250         index = d->mWidgetList.indexOf(currentWidget);
0251         d->mWidgetList.insert(index + 1, widget);
0252     } else {
0253         d->mWidgetList.append(widget);
0254     }
0255     widget->show();
0256 
0257     d->enableControls();
0258     Q_EMIT widgetAdded();
0259     Q_EMIT widgetAdded(widget);
0260 }
0261 
0262 #include "moc_kwidgetlister.cpp"