1 /*
2 * Copyright 2011 Aurélien Gâteau <agateau@kde.org>
3 * License: BSD-3-Clause
4 */
5 #include "ColumnResizer.h"
6
7 #include <QDebug>
8 #include <QEvent>
9 #include <QGridLayout>
10 #include <QTimer>
11 #include <QWidget>
12
13 class FormLayoutWidgetItem : public QWidgetItem
14 {
15 public:
FormLayoutWidgetItem(QWidget * widget,QFormLayout * formLayout,QFormLayout::ItemRole itemRole)16 FormLayoutWidgetItem(QWidget* widget, QFormLayout* formLayout, QFormLayout::ItemRole itemRole)
17 : QWidgetItem(widget)
18 , m_width(-1)
19 , m_formLayout(formLayout)
20 , m_itemRole(itemRole)
21 {}
22
sizeHint() const23 QSize sizeHint() const
24 {
25 QSize size = QWidgetItem::sizeHint();
26 if (m_width != -1) {
27 size.setWidth(m_width);
28 }
29 return size;
30 }
31
minimumSize() const32 QSize minimumSize() const
33 {
34 QSize size = QWidgetItem::minimumSize();
35 if (m_width != -1) {
36 size.setWidth(m_width);
37 }
38 return size;
39 }
40
maximumSize() const41 QSize maximumSize() const
42 {
43 QSize size = QWidgetItem::maximumSize();
44 if (m_width != -1) {
45 size.setWidth(m_width);
46 }
47 return size;
48 }
49
setWidth(int width)50 void setWidth(int width)
51 {
52 if (width != m_width) {
53 m_width = width;
54 invalidate();
55 }
56 }
57
setGeometry(const QRect & _rect)58 void setGeometry(const QRect& _rect)
59 {
60 QRect rect = _rect;
61 int width = widget()->sizeHint().width();
62 if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & Qt::AlignRight) {
63 rect.setLeft(rect.right() - width);
64 }
65 QWidgetItem::setGeometry(rect);
66 }
67
formLayout() const68 QFormLayout* formLayout() const
69 {
70 return m_formLayout;
71 }
72
73 private:
74 int m_width;
75 QFormLayout* m_formLayout;
76 QFormLayout::ItemRole m_itemRole;
77 };
78
79 typedef QPair<QGridLayout*, int> GridColumnInfo;
80
81 class ColumnResizerPrivate
82 {
83 public:
ColumnResizerPrivate(ColumnResizer * q_ptr)84 ColumnResizerPrivate(ColumnResizer* q_ptr)
85 : q(q_ptr)
86 , m_updateTimer(new QTimer(q))
87 {
88 m_updateTimer->setSingleShot(true);
89 m_updateTimer->setInterval(0);
90 QObject::connect(m_updateTimer, SIGNAL(timeout()), q, SLOT(updateWidth()));
91 }
92
scheduleWidthUpdate()93 void scheduleWidthUpdate()
94 {
95 m_updateTimer->start();
96 }
97
98 ColumnResizer* q;
99 QTimer* m_updateTimer;
100 QList<QWidget*> m_widgets;
101 QList<FormLayoutWidgetItem*> m_wrWidgetItemList;
102 QList<GridColumnInfo> m_gridColumnInfoList;
103 };
104
ColumnResizer(QObject * parent)105 ColumnResizer::ColumnResizer(QObject* parent)
106 : QObject(parent)
107 , d(new ColumnResizerPrivate(this))
108 {}
109
~ColumnResizer()110 ColumnResizer::~ColumnResizer()
111 {
112 delete d;
113 }
114
addWidget(QWidget * widget)115 void ColumnResizer::addWidget(QWidget* widget)
116 {
117 d->m_widgets.append(widget);
118 widget->installEventFilter(this);
119 d->scheduleWidthUpdate();
120 }
121
updateWidth()122 void ColumnResizer::updateWidth()
123 {
124 int width = 0;
125 Q_FOREACH(QWidget* widget, d->m_widgets) {
126 width = qMax(widget->sizeHint().width(), width);
127 }
128 Q_FOREACH(FormLayoutWidgetItem* item, d->m_wrWidgetItemList) {
129 item->setWidth(width);
130 item->formLayout()->update();
131 }
132 Q_FOREACH(GridColumnInfo info, d->m_gridColumnInfoList) {
133 info.first->setColumnMinimumWidth(info.second, width);
134 }
135 }
136
eventFilter(QObject *,QEvent * event)137 bool ColumnResizer::eventFilter(QObject*, QEvent* event)
138 {
139 if (event->type() == QEvent::Resize) {
140 d->scheduleWidthUpdate();
141 }
142 return false;
143 }
144
addWidgetsFromLayout(QLayout * layout,int column)145 void ColumnResizer::addWidgetsFromLayout(QLayout* layout, int column)
146 {
147 Q_ASSERT(column >= 0);
148 QGridLayout* gridLayout = qobject_cast<QGridLayout*>(layout);
149 QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
150 if (gridLayout) {
151 addWidgetsFromGridLayout(gridLayout, column);
152 } else if (formLayout) {
153 if (column > QFormLayout::SpanningRole) {
154 qCritical() << "column should not be more than" << QFormLayout::SpanningRole << "for QFormLayout";
155 return;
156 }
157 QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column);
158 addWidgetsFromFormLayout(formLayout, role);
159 } else {
160 qCritical() << "Don't know how to handle layout" << layout;
161 }
162 }
163
addWidgetsFromGridLayout(QGridLayout * layout,int column)164 void ColumnResizer::addWidgetsFromGridLayout(QGridLayout* layout, int column)
165 {
166 for (int row = 0; row < layout->rowCount(); ++row) {
167 QLayoutItem* item = layout->itemAtPosition(row, column);
168 if (!item) {
169 continue;
170 }
171 QWidget* widget = item->widget();
172 if (!widget) {
173 continue;
174 }
175 addWidget(widget);
176 }
177 d->m_gridColumnInfoList << GridColumnInfo(layout, column);
178 }
179
addWidgetsFromFormLayout(QFormLayout * layout,QFormLayout::ItemRole role)180 void ColumnResizer::addWidgetsFromFormLayout(QFormLayout* layout, QFormLayout::ItemRole role)
181 {
182 for (int row = 0; row < layout->rowCount(); ++row) {
183 QLayoutItem* item = layout->itemAt(row, role);
184 if (!item) {
185 continue;
186 }
187 QWidget* widget = item->widget();
188 if (!widget) {
189 continue;
190 }
191 layout->removeItem(item);
192 delete item;
193 FormLayoutWidgetItem* newItem = new FormLayoutWidgetItem(widget, layout, role);
194 layout->setItem(row, role, newItem);
195 addWidget(widget);
196 d->m_wrWidgetItemList << newItem;
197 }
198 }
199
200 // vi: ts=4 sw=4 et
201