[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwidgetsaddons] /: New class: KColumnResizer
From:       Aurélien Gâteau <agateau () kde ! org>
Date:       2014-08-05 7:50:56
Message-ID: E1XEZWK-0005fa-Dc () scm ! kde ! org
[Download RAW message or body]

Git commit 909d74d8c683c6b632352d7179d36a8f6a79578a by Aurélien Gâteau.
Committed on 05/08/2014 at 07:50.
Pushed by gateau into branch 'master'.

New class: KColumnResizer

Makes it easy to vertically align widgets across groups

REVIEW: 118514

M  +7    -1    autotests/CMakeLists.txt
A  +59   -0    autotests/kcolumnresizertest-forms.ui
A  +75   -0    autotests/kcolumnresizertest-grid-and-form.ui
A  +61   -0    autotests/kcolumnresizertest-grids.ui
A  +87   -0    autotests/kcolumnresizertest.cpp     [License: LGPL (v2.1+)]
A  +34   -0    autotests/kcolumnresizertest.h     [License: LGPL (v2.1+)]
A  +-    --    docs/pics/kcolumnresizer.png
M  +2    -0    src/CMakeLists.txt
A  +248  -0    src/kcolumnresizer.cpp     [License: LGPL (v2.1+)]
A  +126  -0    src/kcolumnresizer.h     [License: LGPL (v2.1+)]
M  +6    -0    tests/CMakeLists.txt
A  +64   -0    tests/kcolumnresizertestapp.cpp     [License: LGPL (v2.1+)]
A  +41   -0    tests/kcolumnresizertestapp.h     [License: LGPL (v2.1+)]
A  +188  -0    tests/kcolumnresizertestapp.ui

http://commits.kde.org/kwidgetsaddons/909d74d8c683c6b632352d7179d36a8f6a79578a

diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 7ba9cfe..26c479f 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -1,7 +1,7 @@
 
 include(ECMAddTests)
 
-find_package(Qt5 5.2.0 CONFIG REQUIRED Test)
+find_package(Qt5 5.2.0 CONFIG REQUIRED Test UiTools)
 
 ecm_add_tests(
   kcolorbuttontest.cpp
@@ -14,3 +14,9 @@ ecm_add_tests(
   kpagedialogautotest.cpp
   LINK_LIBRARIES Qt5::Test KF5::WidgetsAddons
 )
+
+ecm_add_tests(
+  kcolumnresizertest.cpp
+  NAME_PREFIX "kwidgetsaddons-"
+  LINK_LIBRARIES Qt5::Test KF5::WidgetsAddons Qt5::UiTools
+)
diff --git a/autotests/kcolumnresizertest-forms.ui \
b/autotests/kcolumnresizertest-forms.ui new file mode 100644
index 0000000..16a0808
--- /dev/null
+++ b/autotests/kcolumnresizertest-forms.ui
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>GroupBox</string>
+     </property>
+     <layout class="QFormLayout" name="layout1">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label1">
+        <property name="text">
+         <string>Short:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="widget1"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>GroupBox</string>
+     </property>
+     <layout class="QFormLayout" name="layout2">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label2">
+        <property name="text">
+         <string>Some long label:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="widget2"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/autotests/kcolumnresizertest-grid-and-form.ui \
b/autotests/kcolumnresizertest-grid-and-form.ui new file mode 100644
index 0000000..d035098
--- /dev/null
+++ b/autotests/kcolumnresizertest-grid-and-form.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>GroupBox</string>
+     </property>
+     <layout class="QGridLayout" name="layout1">
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="widget1"/>
+      </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label1">
+        <property name="text">
+         <string>Short:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QCheckBox" name="checkBox">
+        <property name="text">
+         <string>CheckBox</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QPushButton" name="pushButton">
+        <property name="text">
+         <string>PushButton</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>GroupBox</string>
+     </property>
+     <layout class="QFormLayout" name="layout2">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label2">
+        <property name="text">
+         <string>Some long label:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="widget2"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+  <zorder>groupBox_2</zorder>
+  <zorder>groupBox</zorder>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/autotests/kcolumnresizertest-grids.ui \
b/autotests/kcolumnresizertest-grids.ui new file mode 100644
index 0000000..d204b24
--- /dev/null
+++ b/autotests/kcolumnresizertest-grids.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>GroupBox</string>
+     </property>
+     <layout class="QGridLayout" name="layout1">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label1">
+        <property name="text">
+         <string>Short:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="widget1"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>GroupBox</string>
+     </property>
+     <layout class="QFormLayout" name="layout2">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label2">
+        <property name="text">
+         <string>Some long label:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="widget2"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+  <zorder>groupBox_2</zorder>
+  <zorder>groupBox</zorder>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/autotests/kcolumnresizertest.cpp b/autotests/kcolumnresizertest.cpp
new file mode 100644
index 0000000..817ff57
--- /dev/null
+++ b/autotests/kcolumnresizertest.cpp
@@ -0,0 +1,87 @@
+/* This file is part of the KDE frameworks
+ *
+ * Copyright (c) 2014 Aurélien Gâteau <agateau@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <kcolumnresizertest.h>
+
+#include <KColumnResizer>
+
+#include <QFile>
+#include <QFormLayout>
+#include <QLabel>
+#include <QScopedPointer>
+#include <QUiLoader>
+#include <QtTest>
+
+QTEST_MAIN(KColumnResizerTest)
+
+static QWidget *loadUi(const QString &name)
+{
+    QUiLoader loader;
+    QFile file(name);
+    file.open(QFile::ReadOnly);
+    return loader.load(&file);
+}
+
+void KColumnResizerTest::test_data()
+{
+    QTest::addColumn<QString>("uiFilePath");
+    QTest::newRow("forms") << QFINDTESTDATA("kcolumnresizertest-forms.ui");
+    QTest::newRow("grids") << QFINDTESTDATA("kcolumnresizertest-grids.ui");
+    QTest::newRow("grid-and-form") << \
QFINDTESTDATA("kcolumnresizertest-grid-and-form.ui"); +}
+
+void KColumnResizerTest::test()
+{
+    // This test checks the x coordinate of the widgets from the column
+    // immediately after the resized column, rather than checking the width of
+    // the resized column itself because checking the width of the column cannot
+    // be done the same way for all layout types.
+    QFETCH(QString, uiFilePath);
+    QScopedPointer<QWidget> parent(loadUi(uiFilePath));
+    QVERIFY(parent.data());
+
+    auto layout1 = parent->findChild<QLayout *>(QStringLiteral("layout1"));
+    auto layout2 = parent->findChild<QLayout *>(QStringLiteral("layout2"));
+    auto widget1 = parent->findChild<QWidget *>(QStringLiteral("widget1"));
+    auto widget2 = parent->findChild<QWidget *>(QStringLiteral("widget2"));
+    QVERIFY(layout1);
+    QVERIFY(layout2);
+    QVERIFY(widget1);
+    QVERIFY(widget2);
+
+    // Show the widget so that geometries are updated
+    parent->show();
+
+    int widget1x = widget1->x();
+    int widget2x = widget2->x();
+    QVERIFY(widget1x < widget2x);
+
+    auto resizer = new KColumnResizer(parent.data());
+    resizer->addWidgetsFromLayout(layout1);
+    resizer->addWidgetsFromLayout(layout2);
+
+    // Wait for resizer to do the work
+    QCoreApplication::processEvents();
+    // Now wait for the layout change to propagate
+    QCoreApplication::processEvents();
+
+    QCOMPARE(widget1->x(), widget2x);
+    QCOMPARE(widget2->x(), widget2x);
+}
diff --git a/autotests/kcolumnresizertest.h b/autotests/kcolumnresizertest.h
new file mode 100644
index 0000000..a96fa6a
--- /dev/null
+++ b/autotests/kcolumnresizertest.h
@@ -0,0 +1,34 @@
+/* This file is part of the KDE frameworks
+ *
+ * Copyright (c) 2014 Aurélien Gâteau <agateau@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+#ifndef KCOLUMNRESIZERTEST_H
+#define KCOLUMNRESIZERTEST_H
+
+#include <QObject>
+
+class KColumnResizerTest : public QObject
+{
+    Q_OBJECT
+
+private Q_SLOTS:
+    void test_data();
+    void test();
+};
+
+#endif /* KCOLUMNRESIZERTEST_H */
diff --git a/docs/pics/kcolumnresizer.png b/docs/pics/kcolumnresizer.png
new file mode 100644
index 0000000..81c27ee
Binary files /dev/null and b/docs/pics/kcolumnresizer.png differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 27b9084..d5d3db0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -7,6 +7,7 @@ set(kwidgetsaddons_SRCS
   kcharselect.cpp
   kcharselectdata.cpp
   kcolorbutton.cpp
+  kcolumnresizer.cpp
   kdatecombobox.cpp
   kdatepicker.cpp
   kdatetable.cpp
@@ -96,6 +97,7 @@ ecm_generate_headers(KWidgetsAddons_HEADERS
   KAnimatedButton
   KCharSelect
   KColorButton
+  KColumnResizer
   KDateComboBox
   KDatePicker
   KDateTimeEdit
diff --git a/src/kcolumnresizer.cpp b/src/kcolumnresizer.cpp
new file mode 100644
index 0000000..6316bff
--- /dev/null
+++ b/src/kcolumnresizer.cpp
@@ -0,0 +1,248 @@
+/* This file is part of the KDE frameworks
+ *
+ * Copyright (c) 2014 Aurélien Gâteau <agateau@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+#include <kcolumnresizer.h>
+
+#include <QDebug>
+#include <QEvent>
+#include <QFormLayout>
+#include <QGridLayout>
+#include <QSet>
+#include <QTimer>
+#include <QWidget>
+
+class FormLayoutWidgetItem : public QWidgetItem
+{
+public:
+    FormLayoutWidgetItem(QWidget *widget, QFormLayout *formLayout, \
QFormLayout::ItemRole itemRole) +        : QWidgetItem(widget)
+        , m_width(-1)
+        , m_formLayout(formLayout)
+        , m_itemRole(itemRole)
+    {}
+
+    void setWidth(int width)
+    {
+        if (width != m_width) {
+            m_width = width;
+            invalidate();
+        }
+    }
+
+    QFormLayout *formLayout() const
+    {
+        return m_formLayout;
+    }
+
+    QSize sizeHint() const Q_DECL_OVERRIDE
+    {
+        QSize size = QWidgetItem::sizeHint();
+        if (m_width != -1) {
+            size.setWidth(m_width);
+        }
+        return size;
+    }
+
+    QSize minimumSize() const Q_DECL_OVERRIDE
+    {
+        QSize size = QWidgetItem::minimumSize();
+        if (m_width != -1) {
+            size.setWidth(m_width);
+        }
+        return size;
+    }
+
+    QSize maximumSize() const Q_DECL_OVERRIDE
+    {
+        QSize size = QWidgetItem::maximumSize();
+        if (m_width != -1) {
+            size.setWidth(m_width);
+        }
+        return size;
+    }
+
+    void setGeometry(const QRect &_rect) Q_DECL_OVERRIDE
+    {
+        QRect rect = _rect;
+        int width = widget()->sizeHint().width();
+        if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & \
Qt::AlignRight) { +            rect.setLeft(rect.right() - width);
+        }
+        QWidgetItem::setGeometry(rect);
+    }
+
+private:
+    int m_width;
+    QFormLayout *m_formLayout;
+    QFormLayout::ItemRole m_itemRole;
+};
+
+struct GridColumnInfo
+{
+    GridColumnInfo(QGridLayout *layout_, int column_)
+        : layout(layout_)
+        , column(column_)
+    {}
+    QGridLayout *layout;
+    int column;
+};
+
+class KColumnResizerPrivate
+{
+public:
+    KColumnResizerPrivate(KColumnResizer *q_ptr)
+        : q(q_ptr)
+        , m_updateTimer(new QTimer(q))
+    {
+        m_updateTimer->setSingleShot(true);
+        m_updateTimer->setInterval(0);
+        QObject::connect(m_updateTimer, SIGNAL(timeout()), q, SLOT(updateWidth()));
+    }
+
+    void scheduleWidthUpdate()
+    {
+        m_updateTimer->start();
+    }
+
+    void updateWidth()
+    {
+        int width = 0;
+        Q_FOREACH(QWidget *widget, m_widgets) {
+            width = qMax(widget->sizeHint().width(), width);
+        }
+        Q_FOREACH(FormLayoutWidgetItem *item, m_formWidgetItemList) {
+            item->setWidth(width);
+            item->formLayout()->update();
+        }
+        Q_FOREACH(const GridColumnInfo &info, m_gridColumnInfoList) {
+            info.layout->setColumnMinimumWidth(info.column, width);
+        }
+    }
+
+    void addWidgetsFromGridLayout(QGridLayout *layout, int column)
+    {
+        for (int row = 0; row < layout->rowCount(); ++row) {
+            QLayoutItem *item = layout->itemAtPosition(row, column);
+            if (!item) {
+                continue;
+            }
+            QWidget *widget = item->widget();
+            if (!widget) {
+                continue;
+            }
+            q->addWidget(widget);
+        }
+        m_gridColumnInfoList << GridColumnInfo(layout, column);
+    }
+
+    void addWidgetsFromFormLayout(QFormLayout *layout, QFormLayout::ItemRole role)
+    {
+        for (int row = 0; row < layout->rowCount(); ++row) {
+            QLayoutItem *item = layout->itemAt(row, role);
+            if (!item) {
+                continue;
+            }
+            QWidget *widget = item->widget();
+            if (!widget) {
+                continue;
+            }
+            // Replace the QWidgetItem with our own
+            layout->removeItem(item);
+            delete item;
+            FormLayoutWidgetItem *newItem = new FormLayoutWidgetItem(widget, layout, \
role); +            layout->setItem(row, role, newItem);
+            m_formWidgetItemList << newItem;
+
+            q->addWidget(widget);
+        }
+    }
+
+    KColumnResizer *q;
+    QTimer *m_updateTimer;
+    QSet<QWidget *> m_widgets;
+    QList<FormLayoutWidgetItem *> m_formWidgetItemList;
+    QList<GridColumnInfo> m_gridColumnInfoList;
+};
+
+KColumnResizer::KColumnResizer(QObject *parent)
+    : QObject(parent)
+    , d(new KColumnResizerPrivate(this))
+{}
+
+KColumnResizer::~KColumnResizer()
+{
+    delete d;
+}
+
+void KColumnResizer::addWidget(QWidget *widget)
+{
+    if (d->m_widgets.contains(widget)) {
+        return;
+    }
+    d->m_widgets.insert(widget);
+    widget->installEventFilter(this);
+    d->scheduleWidthUpdate();
+}
+
+void KColumnResizer::removeWidget(QWidget *widget)
+{
+    if (!d->m_widgets.remove(widget)) {
+        return;
+    }
+    widget->removeEventFilter(this);
+    d->scheduleWidthUpdate();
+}
+
+bool KColumnResizer::eventFilter(QObject *, QEvent *event)
+{
+    if (event->type() == QEvent::Resize) {
+        d->scheduleWidthUpdate();
+    }
+    return false;
+}
+
+void KColumnResizer::addWidgetsFromLayout(QLayout *layout, int column)
+{
+    Q_ASSERT(column >= 0);
+    if (column < 0) {
+        qWarning() << "column must be >= 0";
+        return;
+    }
+    QGridLayout *gridLayout = qobject_cast<QGridLayout *>(layout);
+    if (gridLayout) {
+        d->addWidgetsFromGridLayout(gridLayout, column);
+        return;
+    }
+    QFormLayout *formLayout = qobject_cast<QFormLayout *>(layout);
+    if (formLayout) {
+        Q_ASSERT(column <= QFormLayout::SpanningRole);
+        if (column > QFormLayout::SpanningRole) {
+            qWarning() << "column should not be more than" << \
QFormLayout::SpanningRole << "for QFormLayout"; +            return;
+        }
+        QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column);
+        d->addWidgetsFromFormLayout(formLayout, role);
+    } else {
+        qWarning() << "Don't know how to handle layout" << layout;
+        Q_ASSERT(0);
+    }
+}
+
+#include <moc_kcolumnresizer.cpp>
+// vi: ts=4 sw=4 et
diff --git a/src/kcolumnresizer.h b/src/kcolumnresizer.h
new file mode 100644
index 0000000..6855f57
--- /dev/null
+++ b/src/kcolumnresizer.h
@@ -0,0 +1,126 @@
+/* This file is part of the KDE frameworks
+ *
+ * Copyright (c) 2014 Aurélien Gâteau <agateau@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+#ifndef KCOLUMNRESIZER_H
+#define KCOLUMNRESIZER_H
+
+#include <kwidgetsaddons_export.h>
+
+#include <QFormLayout>
+#include <QObject>
+
+class QEvent;
+class QGridLayout;
+class QLayout;
+class QWidget;
+
+class KColumnResizerPrivate;
+
+/**
+ * @short Maintains consistent column sizes across layouts
+ *
+ * KColumnResizer is a helper class which can force columns of different layouts
+ * to keep the same width. It is useful to keep label columns consistent.
+ *
+ * It works with QGridLayout and QFormLayout.
+ *
+ * @image html kcolumnresizer.png "left: without KColumnResizer - right: with \
KColumnResizer" + *
+ * Here is a typical example:
+ *
+ * @code
+ *  void Window::createWidgets()
+ *  {
+ *      QVBoxLayout *layout = new QVBoxLayout(this);
+ *
+ *      QGroupBox *box1 = new QGroupBox();
+ *      // Fill box1
+ *      // ...
+ *      layout->addWidget(box1);
+ *
+ *      QGroupBox *box2 = new QGroupBox();
+ *      // Fill box2
+ *      // ...
+ *      layout->addWidget(box2);
+ *
+ *      KColumnResizer *resizer = new KColumnResizer(this);
+ *      resizer->addWidgetsFromLayout(box1->layout(), 0);
+ *      resizer->addWidgetsFromLayout(box2->layout(), 0);
+ *  }
+ * @endcode
+ *
+ * In this example box1 and box2 children can be organized using QGridLayout or
+ * QFormLayout, resizer will ensure the first columns of the two QGroupBox stay
+ * the same width.
+ *
+ * @author Aurélien Gâteau <agateau@kde.org>
+ *
+ * @since 5.1
+ */
+class KWIDGETSADDONS_EXPORT KColumnResizer : public QObject
+{
+    Q_OBJECT
+public:
+    /**
+     * Constructs a KColumnResizer.
+     */
+    explicit KColumnResizer(QObject *parent = 0);
+
+    ~KColumnResizer();
+
+    /**
+     * Add all widgets from @p layout which are in column @p column to the list
+     * of widgets to manage.
+     *
+     * @param layout The layout containing the widgets to add. KColumnResizer
+     * supports QGridLayout and QFormLayout.
+     * @param column The column number which contains the widgets. If layout is
+     * a QFormLayout, column should not be higher than QFormLayout::SpanningRole
+     */
+    void addWidgetsFromLayout(QLayout *layout, int column = 0);
+
+    /**
+     * Add a single widget to the list of widgets whose width is monitored.
+     *
+     * It is more common to use addWidgetsFromLayout(), but adding single
+     * widgets can be useful if you want to keep a single button the same width
+     * as a column in a layout.
+     *
+     * @param widget The widget to add
+     */
+    void addWidget(QWidget *widget);
+
+    /**
+     * Remove a widget previously added by addWidget or addWidgetsFromLayout.
+     *
+     * @param widget The widget to remove
+     */
+    void removeWidget(QWidget *widget);
+
+protected:
+    bool eventFilter(QObject *, QEvent *event) Q_DECL_OVERRIDE;
+
+private:
+    KColumnResizerPrivate *const d;
+    Q_DISABLE_COPY(KColumnResizer)
+
+    Q_PRIVATE_SLOT(d, void updateWidth())
+};
+
+#endif /* KCOLUMNRESIZER_H */
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index eccf887..5086ac0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -44,3 +44,9 @@ add_executable(kdatetabletest kdatetabletest.cpp \
../src/kdatetable.cpp)  target_include_directories(kdatetabletest PRIVATE ../src)
 target_link_libraries(kdatetabletest Qt5::Widgets)
 ecm_mark_as_test(kdatetabletest)
+
+set(kcolumnresizertestapp_SRCS kcolumnresizertestapp.cpp)
+qt5_wrap_ui(kcolumnresizertestapp_SRCS kcolumnresizertestapp.ui)
+add_executable(kcolumnresizertestapp ${kcolumnresizertestapp_SRCS})
+target_link_libraries(kcolumnresizertestapp KF5::WidgetsAddons Qt5::Widgets)
+ecm_mark_as_test(kcolumnresizertestapp)
diff --git a/tests/kcolumnresizertestapp.cpp b/tests/kcolumnresizertestapp.cpp
new file mode 100644
index 0000000..a750cfd
--- /dev/null
+++ b/tests/kcolumnresizertestapp.cpp
@@ -0,0 +1,64 @@
+/* This file is part of the KDE frameworks
+ *
+ * Copyright (c) 2011-2014 Aurélien Gâteau <agateau@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+#include <QApplication>
+#include <kcolumnresizer.h>
+
+#include <QtGui>
+
+#include <kcolumnresizertestapp.h>
+
+#include <ui_kcolumnresizertestapp.h>
+
+Window::Window()
+{
+    m_ui = new Ui_ColumnResizerTestWidget;
+    m_ui->setupUi(this);
+
+    KColumnResizer *resizer = new KColumnResizer(this);
+    resizer->addWidgetsFromLayout(m_ui->gridGroupBox1->layout(), 0);
+    resizer->addWidgetsFromLayout(m_ui->formGroupBox1->layout(), 0);
+    resizer->addWidgetsFromLayout(m_ui->formGroupBox2->layout(), 0);
+    resizer->addWidgetsFromLayout(m_ui->gridGroupBox2->layout(), 0);
+
+    connect(m_ui->spinBox, SIGNAL(valueChanged(int)), \
SLOT(updateAdjustableLabel())); +    updateAdjustableLabel();
+}
+
+Window::~Window()
+{
+    delete m_ui;
+}
+
+void Window::updateAdjustableLabel()
+{
+    QString txt;
+    txt.fill(QLatin1Char('#'), m_ui->spinBox->value());
+    m_ui->adjustableLabel->setText(QStringLiteral("Spin me %1:").arg(txt));
+}
+
+int main(int argc, char **argv)
+{
+    QApplication app(argc, argv);
+    Window window;
+    window.show();
+    return app.exec();
+}
+
+#include <kcolumnresizertestapp.moc>
diff --git a/tests/kcolumnresizertestapp.h b/tests/kcolumnresizertestapp.h
new file mode 100644
index 0000000..d71dac9
--- /dev/null
+++ b/tests/kcolumnresizertestapp.h
@@ -0,0 +1,41 @@
+/* This file is part of the KDE frameworks
+ *
+ * Copyright (c) 2011-2014 Aurélien Gâteau <agateau@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+#ifndef KCOLUMNRESIZERTESTAPP_H
+#define KCOLUMNRESIZERTESTAPP_H
+
+#include <QWidget>
+
+class Ui_ColumnResizerTestWidget;
+
+class Window : public QWidget
+{
+    Q_OBJECT
+public:
+    Window();
+    ~Window();
+
+public Q_SLOTS:
+    void updateAdjustableLabel();
+
+private:
+    Ui_ColumnResizerTestWidget *m_ui;
+};
+
+#endif /* KCOLUMNRESIZERTESTAPP_H */
diff --git a/tests/kcolumnresizertestapp.ui b/tests/kcolumnresizertestapp.ui
new file mode 100644
index 0000000..4100824
--- /dev/null
+++ b/tests/kcolumnresizertestapp.ui
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ColumnResizerTestWidget</class>
+ <widget class="QWidget" name="Co&amp;lumnResizerDemoWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>376</width>
+    <height>580</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>ColumnResizer Test</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="gridGroupBox1">
+     <property name="title">
+      <string>GridLayout</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>A line edit:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="lineEdit"/>
+      </item>
+      <item row="1" column="1">
+       <widget class="QSpinBox" name="spinBox"/>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="adjustableLabel">
+        <property name="text">
+         <string>Spin me:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QCheckBox" name="checkBox">
+        <property name="text">
+         <string>A check box</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="formGroupBox1">
+     <property name="title">
+      <string>FormLayout</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout">
+      <property name="fieldGrowthPolicy">
+       <enum>QFormLayout::ExpandingFieldsGrow</enum>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>One line:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="lineEdit_2"/>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_4">
+        <property name="text">
+         <string>A much bigger text area:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QListWidget" name="listWidget"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="formGroupBox2">
+     <property name="title">
+      <string>FormLayout2</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout_2">
+      <item row="2" column="1">
+       <widget class="QTimeEdit" name="timeEdit"/>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="label_5">
+        <property name="text">
+         <string>Time:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QCheckBox" name="checkBox_2">
+        <property name="text">
+         <string>Show seconds</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="label_6">
+        <property name="text">
+         <string>Details:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QRadioButton" name="radioButton">
+        <property name="text">
+         <string>Option &amp;1</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="5" column="1">
+       <widget class="QRadioButton" name="radioButton_2">
+        <property name="text">
+         <string>Option &amp;2</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="gridGroupBox2">
+     <property name="title">
+      <string>Crazy QGridLayout</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <widget class="QPushButton" name="pushButton_2">
+        <property name="text">
+         <string>PushButton</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QPushButton" name="pushButton_3">
+        <property name="text">
+         <string>PushButton</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0" colspan="2">
+       <widget class="QPushButton" name="pushButton_4">
+        <property name="text">
+         <string>PushButton</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2" rowspan="2">
+       <widget class="QPushButton" name="pushButton_5">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>PushButton</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic