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"