Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelVoelkel committed Oct 7, 2016
0 parents commit 5ad5cf3
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.autosave
22 changes: 22 additions & 0 deletions CollapsibleSection.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#-------------------------------------------------
#
# Project created by QtCreator 2016-10-04T22:23:10
#
#-------------------------------------------------

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = CollapsibleSection
TEMPLATE = app


SOURCES += main.cpp\
mainwindow.cpp \
Section.cpp

HEADERS += mainwindow.h \
Section.h

FORMS += mainwindow.ui
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# QT-collapsable-section

This is a simple collapsable section for QT. It has been tested with QT5.6.

Special thanks to "x squared" who has posted the original code for this idea at StackOverflow: http://stackoverflow.com/a/37119983/2573127
66 changes: 66 additions & 0 deletions Section.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <QPropertyAnimation>

#include "Section.h"

Section::Section(const QString & title, const int animationDuration, QWidget* parent)
: QWidget(parent), animationDuration(animationDuration)
{
toggleButton.setStyleSheet("QToolButton {border: none;}");
toggleButton.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toggleButton.setArrowType(Qt::ArrowType::RightArrow);
toggleButton.setText(title);
toggleButton.setCheckable(true);
toggleButton.setChecked(false);

headerLine.setFrameShape(QFrame::HLine);
headerLine.setFrameShadow(QFrame::Sunken);
headerLine.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);

contentArea.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

// start out collapsed
contentArea.setMaximumHeight(0);
contentArea.setMinimumHeight(0);

// let the entire widget grow and shrink with its content
toggleAnimation.addAnimation(new QPropertyAnimation(this, "minimumHeight"));
toggleAnimation.addAnimation(new QPropertyAnimation(this, "maximumHeight"));
toggleAnimation.addAnimation(new QPropertyAnimation(&contentArea, "maximumHeight"));

mainLayout.setVerticalSpacing(0);
mainLayout.setContentsMargins(0, 0, 0, 0);

int row = 0;
mainLayout.addWidget(&toggleButton, row, 0, 1, 1, Qt::AlignLeft);
mainLayout.addWidget(&headerLine, row++, 2, 1, 1);
mainLayout.addWidget(&contentArea, row, 0, 1, 3);
setLayout(&mainLayout);

QObject::connect(&toggleButton, &QToolButton::clicked, [this](const bool checked)
{
toggleButton.setArrowType(checked ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow);
toggleAnimation.setDirection(checked ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
toggleAnimation.start();
});
}

void Section::setContentLayout(QLayout & contentLayout)
{
delete contentArea.layout();
contentArea.setLayout(&contentLayout);
const auto collapsedHeight = sizeHint().height() - contentArea.maximumHeight();
auto contentHeight = contentLayout.sizeHint().height();

for (int i = 0; i < toggleAnimation.animationCount() - 1; ++i)
{
QPropertyAnimation* SectionAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(i));
SectionAnimation->setDuration(animationDuration);
SectionAnimation->setStartValue(collapsedHeight);
SectionAnimation->setEndValue(collapsedHeight + contentHeight);
}

QPropertyAnimation* contentAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(toggleAnimation.animationCount() - 1));
contentAnimation->setDuration(animationDuration);
contentAnimation->setStartValue(0);
contentAnimation->setEndValue(contentHeight);
}
28 changes: 28 additions & 0 deletions Section.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef SECTION_H
#define SECTION_H

#include <QFrame>
#include <QGridLayout>
#include <QParallelAnimationGroup>
#include <QScrollArea>
#include <QToolButton>
#include <QWidget>

class Section : public QWidget {
Q_OBJECT
private:

QGridLayout mainLayout;
QToolButton toggleButton;
QFrame headerLine;
QParallelAnimationGroup toggleAnimation;
QScrollArea contentArea;
int animationDuration;

public:
explicit Section(const QString & title = "", const int animationDuration = 100, QWidget* parent = 0);

void setContentLayout(QLayout & contentLayout);
};

#endif // SECTION_H
Binary file added example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}
28 changes: 28 additions & 0 deletions mainwindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "Section.h"

#include <QBoxLayout>
#include <QLabel>
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

Section* section = new Section("Section", 300, ui->centralWidget);
ui->centralWidget->layout()->addWidget(section);

auto* anyLayout = new QVBoxLayout();
anyLayout->addWidget(new QLabel("Some Text in Section", section));
anyLayout->addWidget(new QPushButton("Button in Section", section));

section->setContentLayout(*anyLayout);
}

MainWindow::~MainWindow()
{
delete ui;
}
22 changes: 22 additions & 0 deletions mainwindow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
74 changes: 74 additions & 0 deletions mainwindow.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
<string>Test Window</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="listWidget">
<item>
<property name="text">
<string>some</string>
</property>
</item>
<item>
<property name="text">
<string>list</string>
</property>
</item>
<item>
<property name="text">
<string>with</string>
</property>
</item>
<item>
<property name="text">
<string>items</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>SomeButton</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>17</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

0 comments on commit 5ad5cf3

Please sign in to comment.