Warning, file /frameworks/kwidgetsaddons/src/kcolumnresizer.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE frameworks 0003 SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 #include <kcolumnresizer.h> 0008 0009 #include "loggingcategory.h" 0010 0011 #include <QEvent> 0012 #include <QGridLayout> 0013 #include <QSet> 0014 #include <QTimer> 0015 #include <QWidget> 0016 0017 class FormLayoutWidgetItem : public QWidgetItem 0018 { 0019 public: 0020 FormLayoutWidgetItem(QWidget *widget, QFormLayout *formLayout, QFormLayout::ItemRole itemRole) 0021 : QWidgetItem(widget) 0022 , m_formLayout(formLayout) 0023 , m_itemRole(itemRole) 0024 { 0025 } 0026 0027 void setWidth(int width) 0028 { 0029 if (width != m_width) { 0030 m_width = width; 0031 invalidate(); 0032 } 0033 } 0034 0035 QFormLayout *formLayout() const 0036 { 0037 return m_formLayout; 0038 } 0039 0040 QSize sizeHint() const override 0041 { 0042 QSize size = QWidgetItem::sizeHint(); 0043 if (m_width != -1) { 0044 size.setWidth(m_width); 0045 } 0046 return size; 0047 } 0048 0049 QSize minimumSize() const override 0050 { 0051 QSize size = QWidgetItem::minimumSize(); 0052 if (m_width != -1) { 0053 size.setWidth(m_width); 0054 } 0055 return size; 0056 } 0057 0058 QSize maximumSize() const override 0059 { 0060 QSize size = QWidgetItem::maximumSize(); 0061 if (m_width != -1) { 0062 size.setWidth(m_width); 0063 } 0064 return size; 0065 } 0066 0067 void setGeometry(const QRect &_rect) override 0068 { 0069 QRect rect = _rect; 0070 int width = widget()->sizeHint().width(); 0071 if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & Qt::AlignRight) { 0072 rect.setLeft(rect.right() - width); 0073 } 0074 QWidgetItem::setGeometry(rect); 0075 } 0076 0077 private: 0078 QFormLayout *const m_formLayout; 0079 int m_width = -1; 0080 const QFormLayout::ItemRole m_itemRole; 0081 }; 0082 0083 struct GridColumnInfo { 0084 GridColumnInfo(QGridLayout *layout_, int column_) 0085 : layout(layout_) 0086 , column(column_) 0087 { 0088 } 0089 QGridLayout *layout; 0090 int column; 0091 }; 0092 0093 Q_DECLARE_TYPEINFO(GridColumnInfo, Q_PRIMITIVE_TYPE); 0094 0095 class KColumnResizerPrivate 0096 { 0097 public: 0098 KColumnResizerPrivate(KColumnResizer *q_ptr) 0099 : q(q_ptr) 0100 , m_updateTimer(new QTimer(q)) 0101 { 0102 m_updateTimer->setSingleShot(true); 0103 m_updateTimer->setInterval(0); 0104 QObject::connect(m_updateTimer, &QTimer::timeout, q, [this]() { 0105 updateWidth(); 0106 }); 0107 } 0108 0109 void scheduleWidthUpdate() 0110 { 0111 m_updateTimer->start(); 0112 } 0113 0114 void updateWidth() 0115 { 0116 int width = 0; 0117 for (QWidget *widget : std::as_const(m_widgets)) { 0118 width = qMax(widget->sizeHint().width(), width); 0119 } 0120 for (FormLayoutWidgetItem *item : std::as_const(m_formWidgetItemList)) { 0121 item->setWidth(width); 0122 item->formLayout()->update(); 0123 } 0124 for (const GridColumnInfo &info : std::as_const(m_gridColumnInfoList)) { 0125 info.layout->setColumnMinimumWidth(info.column, width); 0126 } 0127 } 0128 0129 void addWidgetsFromGridLayout(QGridLayout *layout, int column) 0130 { 0131 for (int row = 0; row < layout->rowCount(); ++row) { 0132 QLayoutItem *item = layout->itemAtPosition(row, column); 0133 if (!item) { 0134 continue; 0135 } 0136 QWidget *widget = item->widget(); 0137 if (!widget) { 0138 continue; 0139 } 0140 q->addWidget(widget); 0141 } 0142 m_gridColumnInfoList << GridColumnInfo(layout, column); 0143 } 0144 0145 void addWidgetsFromFormLayout(QFormLayout *layout, QFormLayout::ItemRole role) 0146 { 0147 for (int row = 0; row < layout->rowCount(); ++row) { 0148 QLayoutItem *item = layout->itemAt(row, role); 0149 if (!item) { 0150 continue; 0151 } 0152 QWidget *widget = item->widget(); 0153 if (!widget) { 0154 continue; 0155 } 0156 // Replace the QWidgetItem with our own 0157 layout->removeItem(item); 0158 delete item; 0159 FormLayoutWidgetItem *newItem = new FormLayoutWidgetItem(widget, layout, role); 0160 layout->setItem(row, role, newItem); 0161 m_formWidgetItemList << newItem; 0162 0163 q->addWidget(widget); 0164 } 0165 } 0166 0167 KColumnResizer *q; 0168 QTimer *m_updateTimer; 0169 QSet<QWidget *> m_widgets; 0170 QList<FormLayoutWidgetItem *> m_formWidgetItemList; 0171 QList<GridColumnInfo> m_gridColumnInfoList; 0172 }; 0173 0174 KColumnResizer::KColumnResizer(QObject *parent) 0175 : QObject(parent) 0176 , d(new KColumnResizerPrivate(this)) 0177 { 0178 } 0179 0180 KColumnResizer::~KColumnResizer() = default; 0181 0182 void KColumnResizer::addWidget(QWidget *widget) 0183 { 0184 if (d->m_widgets.contains(widget)) { 0185 return; 0186 } 0187 d->m_widgets.insert(widget); 0188 widget->installEventFilter(this); 0189 d->scheduleWidthUpdate(); 0190 } 0191 0192 void KColumnResizer::removeWidget(QWidget *widget) 0193 { 0194 if (!d->m_widgets.remove(widget)) { 0195 return; 0196 } 0197 widget->removeEventFilter(this); 0198 d->scheduleWidthUpdate(); 0199 } 0200 0201 bool KColumnResizer::eventFilter(QObject *, QEvent *event) 0202 { 0203 if (event->type() == QEvent::Resize) { 0204 d->scheduleWidthUpdate(); 0205 } 0206 return false; 0207 } 0208 0209 void KColumnResizer::addWidgetsFromLayout(QLayout *layout, int column) 0210 { 0211 Q_ASSERT(column >= 0); 0212 if (column < 0) { 0213 qCWarning(KWidgetsAddonsLog) << "column must be >= 0"; 0214 return; 0215 } 0216 QGridLayout *gridLayout = qobject_cast<QGridLayout *>(layout); 0217 if (gridLayout) { 0218 d->addWidgetsFromGridLayout(gridLayout, column); 0219 return; 0220 } 0221 QFormLayout *formLayout = qobject_cast<QFormLayout *>(layout); 0222 if (formLayout) { 0223 Q_ASSERT(column <= QFormLayout::SpanningRole); 0224 if (column > QFormLayout::SpanningRole) { 0225 qCWarning(KWidgetsAddonsLog) << "column should not be more than" << QFormLayout::SpanningRole << "for QFormLayout"; 0226 return; 0227 } 0228 QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column); 0229 d->addWidgetsFromFormLayout(formLayout, role); 0230 } else { 0231 qCWarning(KWidgetsAddonsLog) << "Don't know how to handle layout" << layout; 0232 Q_ASSERT(0); 0233 } 0234 } 0235 0236 #include "moc_kcolumnresizer.cpp" 0237 0238 // vi: ts=4 sw=4 et