forked from qt-creator/qt-creator
LayoutBuilder: Update demo
Backport the learnings and simplification from the real use to the demo case. Change-Id: I3f501b03c760484961bfd586735c0db53ba080db Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "lb.h"
|
#include "lb.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
@@ -29,19 +28,20 @@ namespace Layouting {
|
|||||||
#define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_STRING(#cond); action; } do {} while (0)
|
#define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_STRING(#cond); action; } do {} while (0)
|
||||||
#define QTC_CHECK(cond) if (cond) {} else { QTC_STRING(#cond); } do {} while (0)
|
#define QTC_CHECK(cond) if (cond) {} else { QTC_STRING(#cond); } do {} while (0)
|
||||||
|
|
||||||
|
template <typename X>
|
||||||
template <typename XInterface>
|
X::Implementation *access(const X *x)
|
||||||
XInterface::Implementation *access(const XInterface *x)
|
|
||||||
{
|
{
|
||||||
return static_cast<XInterface::Implementation *>(x->ptr);
|
return static_cast<X::Implementation *>(x->ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setter implementation
|
template <typename X>
|
||||||
|
void apply(X *x, std::initializer_list<typename X::I> ps)
|
||||||
|
{
|
||||||
|
for (auto && p : ps)
|
||||||
|
p.apply(x);
|
||||||
|
}
|
||||||
|
|
||||||
// These are free functions overloaded on the type of builder object
|
// FlowLayout
|
||||||
// and setter id. The function implementations are independent, but
|
|
||||||
// the base expectation is that they will forwards to the backend
|
|
||||||
// type's setter.
|
|
||||||
|
|
||||||
class FlowLayout : public QLayout
|
class FlowLayout : public QLayout
|
||||||
{
|
{
|
||||||
@@ -193,37 +193,49 @@ private:
|
|||||||
\namespace Layouting
|
\namespace Layouting
|
||||||
\inmodule QtCreator
|
\inmodule QtCreator
|
||||||
|
|
||||||
\brief The Layouting namespace contains classes for use with layout builders.
|
\brief The Layouting namespace contains classes and functions to conveniently
|
||||||
|
create layouts in code.
|
||||||
|
|
||||||
|
Classes in the namespace help to create create QLayout or QWidget derived class,
|
||||||
|
instances should be used locally within a function and never stored.
|
||||||
|
|
||||||
|
\sa Layouting::Widget, Layouting::Layout
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class Layouting::Layout
|
||||||
|
\inmodule QtCreator
|
||||||
|
|
||||||
|
The Layout class is a base class for more specific builder
|
||||||
|
classes to create QLayout derived objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class Layouting::Widget
|
||||||
|
\inmodule QtCreator
|
||||||
|
|
||||||
|
The Widget class is a base class for more specific builder
|
||||||
|
classes to create QWidget derived objects.
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class Layouting::LayoutItem
|
\class Layouting::LayoutItem
|
||||||
\inmodule QtCreator
|
\inmodule QtCreator
|
||||||
|
|
||||||
\brief The LayoutItem class represents widgets, layouts, and aggregate
|
The LayoutItem class is used for intermediate results
|
||||||
items for use in conjunction with layout builders.
|
while creating layouts with a concept of rows and spans, such
|
||||||
|
as Form and Grid.
|
||||||
Layout items are typically implicitly constructed when adding items to a
|
|
||||||
\c LayoutBuilder instance using \c LayoutBuilder::addItem() or
|
|
||||||
\c LayoutBuilder::addItems() and never stored in user code.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
Layout::LayoutItem::LayoutItem() = default;
|
||||||
Constructs a layout item instance representing an empty cell.
|
|
||||||
*/
|
|
||||||
LayoutItem::LayoutItem() = default;
|
|
||||||
|
|
||||||
LayoutItem::~LayoutItem() = default;
|
Layout::LayoutItem::~LayoutItem() = default;
|
||||||
|
|
||||||
LayoutItem::LayoutItem(const LayoutInterface &inner)
|
|
||||||
: LayoutItem(access(&inner))
|
|
||||||
{}
|
|
||||||
|
|
||||||
LayoutItem::LayoutItem(const WidgetInterface &inner)
|
|
||||||
: LayoutItem(access(&inner))
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
Layout::LayoutItem::LayoutItem(const LayoutModifier &inner)
|
||||||
|
{
|
||||||
|
ownerModifier = inner;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn template <class T> LayoutItem(const T &t)
|
\fn template <class T> LayoutItem(const T &t)
|
||||||
@@ -239,16 +251,12 @@ LayoutItem::LayoutItem(const WidgetInterface &inner)
|
|||||||
\endlist
|
\endlist
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Helpers
|
|
||||||
|
|
||||||
|
|
||||||
// Object
|
// Object
|
||||||
|
|
||||||
Object::Object(std::initializer_list<I> ps)
|
Object::Object(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QWidget *widgetForItem(QLayoutItem *item)
|
static QWidget *widgetForItem(QLayoutItem *item)
|
||||||
@@ -273,6 +281,8 @@ static QLabel *createLabel(const QString &text)
|
|||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using LayoutItem = Layout::LayoutItem;
|
||||||
|
|
||||||
static void addItemToBoxLayout(QBoxLayout *layout, const LayoutItem &item)
|
static void addItemToBoxLayout(QBoxLayout *layout, const LayoutItem &item)
|
||||||
{
|
{
|
||||||
if (QWidget *w = item.widget) {
|
if (QWidget *w = item.widget) {
|
||||||
@@ -281,8 +291,6 @@ static void addItemToBoxLayout(QBoxLayout *layout, const LayoutItem &item)
|
|||||||
layout->addLayout(l);
|
layout->addLayout(l);
|
||||||
} else if (item.stretch != -1) {
|
} else if (item.stretch != -1) {
|
||||||
layout->addStretch(item.stretch);
|
layout->addStretch(item.stretch);
|
||||||
} else if (item.space != -1) {
|
|
||||||
layout->addSpacing(item.space);
|
|
||||||
} else if (!item.text.isEmpty()) {
|
} else if (!item.text.isEmpty()) {
|
||||||
layout->addWidget(createLabel(item.text));
|
layout->addWidget(createLabel(item.text));
|
||||||
} else if (item.empty) {
|
} else if (item.empty) {
|
||||||
@@ -300,8 +308,6 @@ static void addItemToFlowLayout(FlowLayout *layout, const LayoutItem &item)
|
|||||||
layout->addItem(l);
|
layout->addItem(l);
|
||||||
// } else if (item.stretch != -1) {
|
// } else if (item.stretch != -1) {
|
||||||
// layout->addStretch(item.stretch);
|
// layout->addStretch(item.stretch);
|
||||||
// } else if (item.space != -1) {
|
|
||||||
// layout->addSpacing(item.space);
|
|
||||||
} else if (item.empty) {
|
} else if (item.empty) {
|
||||||
// Nothing to do, but no reason to warn, either
|
// Nothing to do, but no reason to warn, either
|
||||||
} else if (!item.text.isEmpty()) {
|
} else if (!item.text.isEmpty()) {
|
||||||
@@ -311,31 +317,6 @@ static void addItemToFlowLayout(FlowLayout *layout, const LayoutItem &item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// void doAddSpace(LayoutBuilder &builder, const Space &space)
|
|
||||||
// {
|
|
||||||
// ResultItem fi;
|
|
||||||
// fi.space = space.space;
|
|
||||||
// builder.stack.last().pendingItems.append(fi);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void doAddStretch(LayoutBuilder &builder, const Stretch &stretch)
|
|
||||||
// {
|
|
||||||
// Item fi;
|
|
||||||
// fi.stretch = stretch.stretch;
|
|
||||||
// builder.stack.last().pendingItems.append(fi);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void doAddLayout(LayoutBuilder &builder, QLayout *layout)
|
|
||||||
// {
|
|
||||||
// builder.stack.last().pendingItems.append(Item(layout));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void doAddWidget(LayoutBuilder &builder, QWidget *widget)
|
|
||||||
// {
|
|
||||||
// builder.stack.last().pendingItems.append(Item(widget));
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class Layouting::Space
|
\class Layouting::Space
|
||||||
\inmodule QtCreator
|
\inmodule QtCreator
|
||||||
@@ -350,26 +331,68 @@ static void addItemToFlowLayout(FlowLayout *layout, const LayoutItem &item)
|
|||||||
\brief The Stretch class represents some stretch in a layout.
|
\brief The Stretch class represents some stretch in a layout.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
|
||||||
\class Layouting::LayoutBuilder
|
|
||||||
\internal
|
|
||||||
\inmodule QtCreator
|
|
||||||
|
|
||||||
\brief The LayoutBuilder class provides a convenient way to fill \c QFormLayout
|
// Layout
|
||||||
and \c QGridLayouts with contents.
|
|
||||||
|
|
||||||
Filling a layout with items happens item-by-item, row-by-row.
|
void Layout::span(int cols, int rows)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!pendingItems.empty(), return);
|
||||||
|
pendingItems.back().spanCols = cols;
|
||||||
|
pendingItems.back().spanRows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
A LayoutBuilder instance is typically used locally within a function and never stored.
|
void Layout::noMargin()
|
||||||
|
{
|
||||||
|
customMargin({});
|
||||||
|
}
|
||||||
|
|
||||||
\sa addItem(), addItems()
|
void Layout::normalMargin()
|
||||||
*/
|
{
|
||||||
|
customMargin({9, 9, 9, 9});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layout::customMargin(const QMargins &margin)
|
||||||
|
{
|
||||||
|
access(this)->setContentsMargins(margin);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
Attaches the constructed layout to the provided QWidget \a w.
|
||||||
Destructs a layout builder.
|
|
||||||
|
This operation can only be performed once per LayoutBuilder instance.
|
||||||
*/
|
*/
|
||||||
|
void Layout::attachTo(QWidget *widget)
|
||||||
|
{
|
||||||
|
flush();
|
||||||
|
widget->setLayout(access(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Adds the layout item \a item as sub items.
|
||||||
|
*/
|
||||||
|
void Layout::addItem(I item)
|
||||||
|
{
|
||||||
|
item.apply(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layout::addItemHelper(const LayoutItem &item)
|
||||||
|
{
|
||||||
|
if (QBoxLayout *lt = asBox())
|
||||||
|
addItemToBoxLayout(lt, item);
|
||||||
|
else if (FlowLayout *lt = asFlow())
|
||||||
|
addItemToFlowLayout(lt, item);
|
||||||
|
else
|
||||||
|
pendingItems.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Adds the layout items \a items as sub items.
|
||||||
|
*/
|
||||||
|
void Layout::addItems(std::initializer_list<I> items)
|
||||||
|
{
|
||||||
|
for (const I &item : items)
|
||||||
|
item.apply(this);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Starts a new row containing \a items. The row can be further extended by
|
Starts a new row containing \a items. The row can be further extended by
|
||||||
@@ -377,160 +400,141 @@ static void addItemToFlowLayout(FlowLayout *layout, const LayoutItem &item)
|
|||||||
|
|
||||||
\sa addItem(), addItems()
|
\sa addItem(), addItems()
|
||||||
*/
|
*/
|
||||||
// void LayoutItem::addRow(const LayoutItems &items)
|
|
||||||
// {
|
|
||||||
// addItem(br);
|
|
||||||
// addItems(items);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /*!
|
void Layout::addRow(std::initializer_list<I> items)
|
||||||
// Adds the layout item \a item as sub items.
|
|
||||||
// */
|
|
||||||
// void LayoutItem::addItem(const LayoutItem &item)
|
|
||||||
// {
|
|
||||||
// subItems.append(item);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /*!
|
|
||||||
// Adds the layout items \a items as sub items.
|
|
||||||
// */
|
|
||||||
// void LayoutItem::addItems(const LayoutItems &items)
|
|
||||||
// {
|
|
||||||
// subItems.append(items);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /*!
|
|
||||||
// Attaches the constructed layout to the provided QWidget \a w.
|
|
||||||
|
|
||||||
// This operation can only be performed once per LayoutBuilder instance.
|
|
||||||
// */
|
|
||||||
|
|
||||||
// void LayoutItem::attachTo(QWidget *w) const
|
|
||||||
// {
|
|
||||||
// LayoutBuilder builder;
|
|
||||||
|
|
||||||
// builder.stack.append(w);
|
|
||||||
// addItemHelper(builder, *this);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// Layout
|
|
||||||
|
|
||||||
void LayoutInterface::span(int cols, int rows)
|
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!pendingItems.empty(), return);
|
for (const I &item : items)
|
||||||
pendingItems.back().spanCols = cols;
|
item.apply(this);
|
||||||
pendingItems.back().spanRows = rows;
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutInterface::noMargin()
|
void Layout::setSpacing(int spacing)
|
||||||
{
|
{
|
||||||
customMargin({});
|
access(this)->setSpacing(spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutInterface::normalMargin()
|
void Layout::setColumnStretch(int column, int stretch)
|
||||||
{
|
{
|
||||||
customMargin({9, 9, 9, 9});
|
if (auto grid = qobject_cast<QGridLayout *>(access(this))) {
|
||||||
|
grid->setColumnStretch(column, stretch);
|
||||||
|
} else {
|
||||||
|
QTC_CHECK(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutInterface::customMargin(const QMargins &margin)
|
void addToWidget(Widget *widget, const Layout &layout)
|
||||||
{
|
{
|
||||||
access(this)->setContentsMargins(margin);
|
layout.flush_();
|
||||||
|
access(widget)->setLayout(access(&layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutInterface::addItem(const LayoutItem &item)
|
void addToLayout(Layout *layout, const Widget &inner)
|
||||||
{
|
|
||||||
if (item.break_)
|
|
||||||
flush();
|
|
||||||
else
|
|
||||||
pendingItems.push_back(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addNestedItem(WidgetInterface *widget, const LayoutInterface &layout)
|
|
||||||
{
|
|
||||||
widget->setLayout(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addNestedItem(LayoutInterface *layout, const WidgetInterface &inner)
|
|
||||||
{
|
{
|
||||||
LayoutItem item;
|
LayoutItem item;
|
||||||
item.widget = access(&inner);
|
item.widget = access(&inner);
|
||||||
layout->addItem(item);
|
layout->addItemHelper(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNestedItem(LayoutInterface *layout, const LayoutItem &inner)
|
void addToLayout(Layout *layout, QWidget *inner)
|
||||||
{
|
|
||||||
layout->addItem(inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addNestedItem(LayoutInterface *layout, const LayoutInterface &inner)
|
|
||||||
{
|
{
|
||||||
LayoutItem item;
|
LayoutItem item;
|
||||||
item.layout = access(&inner);
|
item.widget = inner;
|
||||||
layout->addItem(item);
|
layout->addItemHelper(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNestedItem(LayoutInterface *layout, const std::function<LayoutItem()> &inner)
|
void addToLayout(Layout *layout, QLayout *inner)
|
||||||
{
|
{
|
||||||
LayoutItem item = inner();
|
LayoutItem item;
|
||||||
layout->addItem(item);
|
item.layout = inner;
|
||||||
|
layout->addItemHelper(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNestedItem(LayoutInterface *layout, const QString &inner)
|
void addToLayout(Layout *layout, const Layout &inner)
|
||||||
|
{
|
||||||
|
inner.flush_();
|
||||||
|
LayoutItem item;
|
||||||
|
item.layout = access(&inner);
|
||||||
|
layout->addItemHelper(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToLayout(Layout *layout, const LayoutModifier &inner)
|
||||||
|
{
|
||||||
|
inner(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToLayout(Layout *layout, const QString &inner)
|
||||||
{
|
{
|
||||||
LayoutItem item;
|
LayoutItem item;
|
||||||
item.text = inner;
|
item.text = inner;
|
||||||
layout->addItem(item);
|
layout->addItemHelper(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutItem empty()
|
void empty(Layout *iface)
|
||||||
{
|
{
|
||||||
LayoutItem item;
|
LayoutItem item;
|
||||||
item.empty = true;
|
item.empty = true;
|
||||||
return item;
|
iface->addItemHelper(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutItem hr()
|
void hr(Layout *layout)
|
||||||
{
|
{
|
||||||
LayoutItem item;
|
layout->addItemHelper(createHr());
|
||||||
item.widget = createHr();
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutItem br()
|
void br(Layout *iface)
|
||||||
{
|
{
|
||||||
LayoutItem item;
|
iface->flush();
|
||||||
item.break_ = true;
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutItem st()
|
void st(Layout *iface)
|
||||||
{
|
{
|
||||||
LayoutItem item;
|
LayoutItem item;
|
||||||
item.stretch = 1;
|
item.stretch = 1;
|
||||||
return item;
|
iface->addItemHelper(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
QFormLayout *LayoutInterface::asForm()
|
void noMargin(Layout *iface)
|
||||||
|
{
|
||||||
|
iface->noMargin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalMargin(Layout *iface)
|
||||||
|
{
|
||||||
|
iface->normalMargin();
|
||||||
|
}
|
||||||
|
|
||||||
|
QFormLayout *Layout::asForm()
|
||||||
{
|
{
|
||||||
return qobject_cast<QFormLayout *>(access(this));
|
return qobject_cast<QFormLayout *>(access(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
QGridLayout *LayoutInterface::asGrid()
|
QGridLayout *Layout::asGrid()
|
||||||
{
|
{
|
||||||
return qobject_cast<QGridLayout *>(access(this));
|
return qobject_cast<QGridLayout *>(access(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
QBoxLayout *LayoutInterface::asBox()
|
QBoxLayout *Layout::asBox()
|
||||||
{
|
{
|
||||||
return qobject_cast<QBoxLayout *>(access(this));
|
return qobject_cast<QBoxLayout *>(access(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutInterface::flush()
|
FlowLayout *Layout::asFlow()
|
||||||
{
|
{
|
||||||
|
return dynamic_cast<FlowLayout *>(access(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layout::flush()
|
||||||
|
{
|
||||||
|
if (pendingItems.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
if (QGridLayout *lt = asGrid()) {
|
if (QGridLayout *lt = asGrid()) {
|
||||||
for (const LayoutItem &item : std::as_const(pendingItems)) {
|
for (const LayoutItem &item : std::as_const(pendingItems)) {
|
||||||
Qt::Alignment a = currentGridColumn == 0 ? align : Qt::Alignment();
|
Qt::Alignment a;
|
||||||
|
if (currentGridColumn == 0 && useFormAlignment) {
|
||||||
|
// if (auto widget = builder.stack.at(builder.stack.size() - 2).widget) {
|
||||||
|
// a = widget->style()->styleHint(QStyle::SH_FormLayoutLabelAlignment);
|
||||||
|
}
|
||||||
if (item.widget)
|
if (item.widget)
|
||||||
lt->addWidget(item.widget, currentGridRow, currentGridColumn, item.spanRows, item.spanCols, a);
|
lt->addWidget(item.widget, currentGridRow, currentGridColumn, item.spanRows, item.spanCols, a);
|
||||||
else if (item.layout)
|
else if (item.layout)
|
||||||
@@ -551,11 +555,11 @@ void LayoutInterface::flush()
|
|||||||
if (pendingItems.size() > 2) {
|
if (pendingItems.size() > 2) {
|
||||||
auto hbox = new QHBoxLayout;
|
auto hbox = new QHBoxLayout;
|
||||||
hbox->setContentsMargins(0, 0, 0, 0);
|
hbox->setContentsMargins(0, 0, 0, 0);
|
||||||
for (int i = 1; i < pendingItems.size(); ++i)
|
for (size_t i = 1; i < pendingItems.size(); ++i)
|
||||||
addItemToBoxLayout(hbox, pendingItems.at(i));
|
addItemToBoxLayout(hbox, pendingItems.at(i));
|
||||||
while (pendingItems.size() > 1)
|
while (pendingItems.size() > 1)
|
||||||
pendingItems.pop_back();
|
pendingItems.pop_back();
|
||||||
pendingItems.push_back(LayoutItem(hbox));
|
pendingItems.push_back(hbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pendingItems.size() == 1) { // Only one item given, so this spans both columns.
|
if (pendingItems.size() == 1) { // Only one item given, so this spans both columns.
|
||||||
@@ -601,133 +605,138 @@ void LayoutInterface::flush()
|
|||||||
pendingItems.clear();
|
pendingItems.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTC_CHECK(false); // The other layouts shouldn't use flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LayoutItem withFormAlignment()
|
void Layout::flush_() const
|
||||||
// {
|
{
|
||||||
// LayoutItem item;
|
const_cast<Layout *>(this)->flush();
|
||||||
// item.onAdd = [](LayoutBuilder &builder) {
|
}
|
||||||
// if (builder.stack.size() >= 2) {
|
|
||||||
// if (auto widget = builder.stack.at(builder.stack.size() - 2).widget) {
|
void withFormAlignment(Layout *iface)
|
||||||
// const Qt::Alignment align(widget->style()->styleHint(QStyle::SH_FormLayoutLabelAlignment));
|
{
|
||||||
// builder.stack.last().align = align;
|
iface->useFormAlignment = true;
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// return item;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Flow
|
// Flow
|
||||||
|
|
||||||
Flow::Flow(std::initializer_list<I> ps)
|
Flow::Flow(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
adopt(new FlowLayout);
|
ptr = new FlowLayout;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
flush();
|
||||||
// for (const LayoutItem &item : std::as_const(pendingItems))
|
|
||||||
// addItemToFlowLayout(flowLayout, item);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Row & Column
|
// Row & Column
|
||||||
|
|
||||||
Row::Row(std::initializer_list<I> ps)
|
Row::Row(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
adopt(new QHBoxLayout);
|
ptr = new QHBoxLayout;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
flush();
|
||||||
auto self = asBox();
|
|
||||||
for (const LayoutItem &item : pendingItems)
|
|
||||||
addItemToBoxLayout(self, item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column::Column(std::initializer_list<I> ps)
|
Column::Column(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
adopt(new QVBoxLayout);
|
ptr = new QVBoxLayout;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
flush();
|
||||||
auto self = asBox();
|
|
||||||
for (const LayoutItem &item : pendingItems)
|
|
||||||
addItemToBoxLayout(self, item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grid
|
// Grid
|
||||||
|
|
||||||
|
Grid::Grid()
|
||||||
|
{
|
||||||
|
ptr = new QGridLayout;
|
||||||
|
}
|
||||||
|
|
||||||
Grid::Grid(std::initializer_list<I> ps)
|
Grid::Grid(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
adopt(new QGridLayout);
|
ptr = new QGridLayout;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form
|
// Form
|
||||||
|
|
||||||
|
Form::Form()
|
||||||
|
{
|
||||||
|
ptr = new QFormLayout;
|
||||||
|
}
|
||||||
|
|
||||||
Form::Form(std::initializer_list<I> ps)
|
Form::Form(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
adopt(new QFormLayout);
|
auto lt = new QFormLayout;
|
||||||
fieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
ptr = lt;
|
||||||
for (auto && p : ps)
|
lt->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||||
apply(p);
|
apply(this, ps);
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutInterface::fieldGrowthPolicy(int policy)
|
void Layout::fieldGrowthPolicy(int policy)
|
||||||
{
|
{
|
||||||
if (auto lt = asForm())
|
if (auto lt = asForm())
|
||||||
lt->setFieldGrowthPolicy(QFormLayout::FieldGrowthPolicy(policy));
|
lt->setFieldGrowthPolicy(QFormLayout::FieldGrowthPolicy(policy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget *Layout::emerge() const
|
||||||
|
{
|
||||||
|
const_cast<Layout *>(this)->flush();
|
||||||
|
QWidget *widget = new QWidget;
|
||||||
|
widget->setLayout(access(this));
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
// "Widgets"
|
// "Widgets"
|
||||||
|
|
||||||
Widget::Widget(std::initializer_list<I> ps)
|
Widget::Widget(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::resize(int w, int h)
|
void Widget::resize(int w, int h)
|
||||||
{
|
{
|
||||||
access(this)->resize(w, h);
|
access(this)->resize(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::setLayout(const LayoutInterface &layout)
|
void Widget::setLayout(const Layout &layout)
|
||||||
{
|
{
|
||||||
access(this)->setLayout(access(&layout));
|
access(this)->setLayout(access(&layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::setWindowTitle(const QString &title)
|
void Widget::setWindowTitle(const QString &title)
|
||||||
{
|
{
|
||||||
access(this)->setWindowTitle(title);
|
access(this)->setWindowTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::setToolTip(const QString &title)
|
void Widget::setToolTip(const QString &title)
|
||||||
{
|
{
|
||||||
access(this)->setToolTip(title);
|
access(this)->setToolTip(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::show()
|
void Widget::show()
|
||||||
{
|
{
|
||||||
access(this)->show();
|
access(this)->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::noMargin()
|
void Widget::noMargin(int)
|
||||||
{
|
{
|
||||||
customMargin({});
|
customMargin({});
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::normalMargin()
|
void Widget::normalMargin(int)
|
||||||
{
|
{
|
||||||
customMargin({9, 9, 9, 9});
|
customMargin({9, 9, 9, 9});
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetInterface::customMargin(const QMargins &margin)
|
void Widget::customMargin(const QMargins &margin)
|
||||||
{
|
{
|
||||||
access(this)->setContentsMargins(margin);
|
access(this)->setContentsMargins(margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *WidgetInterface::emerge()
|
QWidget *Widget::emerge() const
|
||||||
{
|
{
|
||||||
return access(this);
|
return access(this);
|
||||||
}
|
}
|
||||||
@@ -736,18 +745,17 @@ QWidget *WidgetInterface::emerge()
|
|||||||
|
|
||||||
Label::Label(std::initializer_list<I> ps)
|
Label::Label(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Label::Label(const QString &text)
|
Label::Label(const QString &text)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
setText(text);
|
setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelInterface::setText(const QString &text)
|
void Label::setText(const QString &text)
|
||||||
{
|
{
|
||||||
access(this)->setText(text);
|
access(this)->setText(text);
|
||||||
}
|
}
|
||||||
@@ -756,32 +764,35 @@ void LabelInterface::setText(const QString &text)
|
|||||||
|
|
||||||
Group::Group(std::initializer_list<I> ps)
|
Group::Group(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupInterface::setTitle(const QString &title)
|
void Group::setTitle(const QString &title)
|
||||||
{
|
{
|
||||||
access(this)->setTitle(title);
|
access(this)->setTitle(title);
|
||||||
access(this)->setObjectName(title);
|
access(this)->setObjectName(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Group::setGroupChecker(const std::function<void (QObject *)> &checker)
|
||||||
|
{
|
||||||
|
checker(access(this));
|
||||||
|
}
|
||||||
|
|
||||||
// SpinBox
|
// SpinBox
|
||||||
|
|
||||||
SpinBox::SpinBox(std::initializer_list<I> ps)
|
SpinBox::SpinBox(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpinBoxInterface::setValue(int val)
|
void SpinBox::setValue(int val)
|
||||||
{
|
{
|
||||||
access(this)->setValue(val);
|
access(this)->setValue(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpinBoxInterface::onTextChanged(const std::function<void (QString)> &func)
|
void SpinBox::onTextChanged(const std::function<void (QString)> &func)
|
||||||
{
|
{
|
||||||
QObject::connect(access(this), &QSpinBox::textChanged, func);
|
QObject::connect(access(this), &QSpinBox::textChanged, func);
|
||||||
}
|
}
|
||||||
@@ -790,12 +801,11 @@ void SpinBoxInterface::onTextChanged(const std::function<void (QString)> &func)
|
|||||||
|
|
||||||
TextEdit::TextEdit(std::initializer_list<I> ps)
|
TextEdit::TextEdit(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditInterface::setText(const QString &text)
|
void TextEdit::setText(const QString &text)
|
||||||
{
|
{
|
||||||
access(this)->setText(text);
|
access(this)->setText(text);
|
||||||
}
|
}
|
||||||
@@ -804,19 +814,18 @@ void TextEditInterface::setText(const QString &text)
|
|||||||
|
|
||||||
PushButton::PushButton(std::initializer_list<I> ps)
|
PushButton::PushButton(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushButtonInterface::setText(const QString &text)
|
void PushButton::setText(const QString &text)
|
||||||
{
|
{
|
||||||
access(this)->setText(text);
|
access(this)->setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushButtonInterface::onClicked(const std::function<void ()> &func)
|
void PushButton::onClicked(const std::function<void ()> &func, QObject *guard)
|
||||||
{
|
{
|
||||||
QObject::connect(access(this), &QAbstractButton::clicked, func);
|
QObject::connect(access(this), &QAbstractButton::clicked, guard, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stack
|
// Stack
|
||||||
@@ -826,88 +835,92 @@ void PushButtonInterface::onClicked(const std::function<void ()> &func)
|
|||||||
// top-level widget. This can lead to the focus shifting away from the main application.
|
// top-level widget. This can lead to the focus shifting away from the main application.
|
||||||
Stack::Stack(std::initializer_list<I> ps)
|
Stack::Stack(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
}
|
||||||
|
|
||||||
|
void addToStack(Stack *stack, const Widget &inner)
|
||||||
|
{
|
||||||
|
access(stack)->addWidget(inner.emerge());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToStack(Stack *stack, const Layout &inner)
|
||||||
|
{
|
||||||
|
inner.flush_();
|
||||||
|
access(stack)->addWidget(inner.emerge());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToStack(Stack *stack, QWidget *inner)
|
||||||
|
{
|
||||||
|
access(stack)->addWidget(inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splitter
|
// Splitter
|
||||||
|
|
||||||
Splitter::Splitter(std::initializer_list<I> ps)
|
Splitter::Splitter(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
access(this)->setOrientation(Qt::Vertical);
|
access(this)->setOrientation(Qt::Vertical);
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
}
|
||||||
|
|
||||||
|
void addToSplitter(Splitter *splitter, QWidget *inner)
|
||||||
|
{
|
||||||
|
access(splitter)->addWidget(inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToSplitter(Splitter *splitter, const Widget &inner)
|
||||||
|
{
|
||||||
|
access(splitter)->addWidget(inner.emerge());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToSplitter(Splitter *splitter, const Layout &inner)
|
||||||
|
{
|
||||||
|
inner.flush_();
|
||||||
|
access(splitter)->addWidget(inner.emerge());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToolBar
|
// ToolBar
|
||||||
|
|
||||||
ToolBar::ToolBar(std::initializer_list<I> ps)
|
ToolBar::ToolBar(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
|
apply(this, ps);
|
||||||
access(this)->setOrientation(Qt::Horizontal);
|
access(this)->setOrientation(Qt::Horizontal);
|
||||||
for (auto && p : ps)
|
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TabWidget
|
// TabWidget
|
||||||
|
|
||||||
TabWidget::TabWidget(std::initializer_list<I> ps)
|
TabWidget::TabWidget(std::initializer_list<I> ps)
|
||||||
{
|
{
|
||||||
create();
|
ptr = new Implementation;
|
||||||
for (auto && p : ps)
|
apply(this, ps);
|
||||||
apply(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Special Tab
|
Tab::Tab(const QString &tabName, const Layout &inner)
|
||||||
|
: tabName(tabName), inner(inner)
|
||||||
|
{}
|
||||||
|
|
||||||
// Tab::Tab(const QString &tabName, const LayoutItem &item)
|
void addToTabWidget(TabWidget *tabWidget, const Tab &tab)
|
||||||
// {
|
{
|
||||||
// onAdd = [item](LayoutBuilder &builder) {
|
access(tabWidget)->addTab(tab.inner.emerge(), tab.tabName);
|
||||||
// auto tab = new QWidget;
|
}
|
||||||
// builder.stack.append(tab);
|
|
||||||
// item.attachTo(tab);
|
|
||||||
// };
|
|
||||||
// onExit = [tabName](LayoutBuilder &builder) {
|
|
||||||
// QWidget *inner = builder.stack.last().widget;
|
|
||||||
// builder.stack.pop_back();
|
|
||||||
// auto tabWidget = qobject_cast<QTabWidget *>(builder.stack.last().widget);
|
|
||||||
// QTC_ASSERT(tabWidget, return);
|
|
||||||
// tabWidget->addTab(inner, tabName);
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Special If
|
// Special If
|
||||||
|
|
||||||
// If::If(bool condition, const LayoutItems &items, const LayoutItems &other)
|
If::If(bool condition,
|
||||||
// {
|
const std::initializer_list<Layout::I> ifcase,
|
||||||
// subItems.append(condition ? items : other);
|
const std::initializer_list<Layout::I> thencase)
|
||||||
// }
|
: used(condition ? ifcase : thencase)
|
||||||
|
{}
|
||||||
|
|
||||||
// "Properties"
|
void addToLayout(Layout *layout, const If &inner)
|
||||||
|
{
|
||||||
|
for (const Layout::I &item : inner.used)
|
||||||
|
item.apply(layout);
|
||||||
|
}
|
||||||
|
|
||||||
// LayoutItem spacing(int spacing)
|
// Specials
|
||||||
// {
|
|
||||||
// return [spacing](QObject *target) {
|
|
||||||
// if (auto layout = qobject_cast<QLayout *>(target)) {
|
|
||||||
// layout->setSpacing(spacing);
|
|
||||||
// } else {
|
|
||||||
// QTC_CHECK(false);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// LayoutItem columnStretch(int column, int stretch)
|
|
||||||
// {
|
|
||||||
// return [column, stretch](QObject *target) {
|
|
||||||
// if (auto grid = qobject_cast<QGridLayout *>(target)) {
|
|
||||||
// grid->setColumnStretch(column, stretch);
|
|
||||||
// } else {
|
|
||||||
// QTC_CHECK(false);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
QWidget *createHr(QWidget *parent)
|
QWidget *createHr(QWidget *parent)
|
||||||
{
|
{
|
||||||
@@ -917,10 +930,34 @@ QWidget *createHr(QWidget *parent)
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span::Span(int n, const LayoutItem &item)
|
Span::Span(int n, const Layout::I &item)
|
||||||
: LayoutItem(item)
|
: item(item), spanCols(n)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void addToLayout(Layout *layout, const Span &inner)
|
||||||
{
|
{
|
||||||
spanCols = n;
|
LayoutItem item;
|
||||||
|
layout->addItem(inner.item);
|
||||||
|
QTC_ASSERT(!layout->pendingItems.empty(), return);
|
||||||
|
layout->pendingItems.back().spanCols = inner.spanCols;
|
||||||
|
layout->pendingItems.back().spanRows = inner.spanRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutModifier spacing(int space)
|
||||||
|
{
|
||||||
|
return [space](Layout *iface) { iface->setSpacing(space); };
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToLayout(Layout *layout, const Space &inner)
|
||||||
|
{
|
||||||
|
if (auto lt = layout->asBox())
|
||||||
|
lt->addSpacing(inner.space);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToLayout(Layout *layout, const Stretch &inner)
|
||||||
|
{
|
||||||
|
if (auto lt = layout->asBox())
|
||||||
|
lt->addStretch(inner.stretch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void createItem(LayoutItem *item, QWidget *t)
|
// void createItem(LayoutItem *item, QWidget *t)
|
||||||
|
@@ -4,11 +4,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QList>
|
#include <QMargins>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include <array>
|
#include <functional>
|
||||||
#include <cstring>
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
#if defined(UTILS_LIBRARY)
|
#if defined(UTILS_LIBRARY)
|
||||||
@@ -24,6 +23,7 @@ class QBoxLayout;
|
|||||||
class QFormLayout;
|
class QFormLayout;
|
||||||
class QGridLayout;
|
class QGridLayout;
|
||||||
class QGroupBox;
|
class QGroupBox;
|
||||||
|
class QHBoxLayout;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QLayout;
|
class QLayout;
|
||||||
class QMargins;
|
class QMargins;
|
||||||
@@ -35,129 +35,67 @@ class QStackedWidget;
|
|||||||
class QTabWidget;
|
class QTabWidget;
|
||||||
class QTextEdit;
|
class QTextEdit;
|
||||||
class QToolBar;
|
class QToolBar;
|
||||||
|
class QVBoxLayout;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Layouting {
|
namespace Layouting {
|
||||||
|
|
||||||
struct LayoutItem;
|
class NestId {};
|
||||||
|
|
||||||
// struct NestId {};
|
|
||||||
struct NestId {};
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
struct IdAndArg
|
class IdAndArg
|
||||||
{
|
|
||||||
IdAndArg(const T1 &id, const T2 &arg) : id(id), arg(arg) {}
|
|
||||||
T1 id;
|
|
||||||
T2 arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The main dispatchers
|
|
||||||
|
|
||||||
void doit(auto x, auto id, auto a);
|
|
||||||
|
|
||||||
// BuilderItem
|
|
||||||
|
|
||||||
template <typename X, typename XInterface>
|
|
||||||
struct BuilderItem : XInterface
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct I
|
IdAndArg(const T1 &id, const T2 &arg) : id(id), arg(arg) {}
|
||||||
|
const T1 id;
|
||||||
|
const T2 arg; // FIXME: Could be const &, but this would currently break bindTo().
|
||||||
|
};
|
||||||
|
|
||||||
|
// The main dispatcher
|
||||||
|
|
||||||
|
void doit(auto x, auto id, auto p);
|
||||||
|
|
||||||
|
template <typename X> class BuilderItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Nested child object
|
||||||
|
template <typename Inner>
|
||||||
|
BuilderItem(Inner && p)
|
||||||
{
|
{
|
||||||
// Nested child object
|
apply = [&p](X *x) { doit(x, NestId{}, std::forward<Inner>(p)); };
|
||||||
template <typename Inner>
|
|
||||||
I(const Inner &p)
|
|
||||||
{
|
|
||||||
apply = [p](XInterface *x) { doit(x, NestId{}, p); };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Property setter
|
|
||||||
template <typename Id, typename Arg1>
|
|
||||||
I(const IdAndArg<Id, Arg1> &p)
|
|
||||||
{
|
|
||||||
apply = [p](XInterface *x) { doit(x, p.id, p.arg); };
|
|
||||||
}
|
|
||||||
|
|
||||||
std::function<void(XInterface *)> apply;
|
|
||||||
};
|
|
||||||
|
|
||||||
void create()
|
|
||||||
{
|
|
||||||
XInterface::ptr = new XInterface::Implementation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void adopt(XInterface::Implementation *ptr)
|
// Property setter
|
||||||
|
template <typename Id, typename Arg>
|
||||||
|
BuilderItem(IdAndArg<Id, Arg> && idarg)
|
||||||
{
|
{
|
||||||
XInterface::ptr = ptr;
|
apply = [&idarg](X *x) { doit(x, idarg.id, idarg.arg); };
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply(const I &init)
|
std::function<void(X *)> apply;
|
||||||
{
|
|
||||||
init.apply(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
using Id = typename XInterface::Implementation *;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
|
|
||||||
struct LayoutInterface;
|
|
||||||
struct WidgetInterface;
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT LayoutItem
|
|
||||||
{
|
|
||||||
LayoutItem();
|
|
||||||
LayoutItem(QLayout *l) : layout(l), empty(!l) {}
|
|
||||||
LayoutItem(QWidget *w) : widget(w), empty(!w) {}
|
|
||||||
LayoutItem(const QString &t) : text(t) {}
|
|
||||||
LayoutItem(const LayoutInterface &inner);
|
|
||||||
LayoutItem(const WidgetInterface &inner);
|
|
||||||
~LayoutItem();
|
|
||||||
|
|
||||||
QString text;
|
|
||||||
QLayout *layout = nullptr;
|
|
||||||
QWidget *widget = nullptr;
|
|
||||||
int space = -1;
|
|
||||||
int stretch = -1;
|
|
||||||
int spanCols = 1;
|
|
||||||
int spanRows = 1;
|
|
||||||
bool empty = false;
|
|
||||||
bool break_ = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using LayoutItems = QList<LayoutItem>;
|
|
||||||
|
|
||||||
|
|
||||||
// We need two classes for each user visible Builder type.
|
|
||||||
// The actual Builder classes derive from BuilderItem with two parameters,
|
|
||||||
// one is the Builder class itself for CRTP and a one "Interface" type.
|
|
||||||
// The "Interface" types act (individually, and as a hierarchy) as interface
|
|
||||||
// members of the real QObject/QWidget/... hierarchy things. This wrapper is not
|
|
||||||
// strictly needed, the Q* hierarchy could be used directly, at the
|
|
||||||
// price of #include'ing the definitions of each participating class,
|
|
||||||
// which does not scale well.
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Basic
|
// Basic
|
||||||
//
|
//
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT ThingInterface
|
class QTCREATOR_UTILS_EXPORT Thing
|
||||||
{
|
{
|
||||||
template <typename T>
|
public:
|
||||||
T *access_() const { return static_cast<T *>(ptr); }
|
|
||||||
|
|
||||||
void *ptr; // The product.
|
void *ptr; // The product.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT ObjectInterface : ThingInterface
|
class QTCREATOR_UTILS_EXPORT Object : public Thing
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QObject;
|
using Implementation = QObject;
|
||||||
};
|
using I = BuilderItem<Object>;
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Object : BuilderItem<Object, ObjectInterface>
|
Object() = default;
|
||||||
{
|
|
||||||
Object(std::initializer_list<I> ps);
|
Object(std::initializer_list<I> ps);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -165,235 +103,288 @@ struct QTCREATOR_UTILS_EXPORT Object : BuilderItem<Object, ObjectInterface>
|
|||||||
// Layouts
|
// Layouts
|
||||||
//
|
//
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT LayoutInterface : ObjectInterface
|
class FlowLayout;
|
||||||
|
class Layout;
|
||||||
|
using LayoutModifier = std::function<void(Layout *)>;
|
||||||
|
// using LayoutModifier = void(*)(Layout *);
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT Layout : public Object
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QLayout;
|
using Implementation = QLayout;
|
||||||
|
using I = BuilderItem<Layout>;
|
||||||
|
|
||||||
|
Layout() = default;
|
||||||
|
Layout(Implementation *w) { ptr = w; }
|
||||||
|
|
||||||
|
class LayoutItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~LayoutItem();
|
||||||
|
LayoutItem();
|
||||||
|
LayoutItem(QLayout *l) : layout(l) {}
|
||||||
|
LayoutItem(QWidget *w) : widget(w) {}
|
||||||
|
LayoutItem(const QString &t) : text(t) {}
|
||||||
|
LayoutItem(const LayoutModifier &inner);
|
||||||
|
|
||||||
|
QString text;
|
||||||
|
QLayout *layout = nullptr;
|
||||||
|
QWidget *widget = nullptr;
|
||||||
|
int stretch = -1;
|
||||||
|
int spanCols = 1;
|
||||||
|
int spanRows = 1;
|
||||||
|
bool empty = false;
|
||||||
|
LayoutModifier ownerModifier;
|
||||||
|
//Qt::Alignment align = {};
|
||||||
|
};
|
||||||
|
|
||||||
void span(int cols, int rows);
|
void span(int cols, int rows);
|
||||||
void noMargin();
|
void noMargin();
|
||||||
void normalMargin();
|
void normalMargin();
|
||||||
void customMargin(const QMargins &margin);
|
void customMargin(const QMargins &margin);
|
||||||
|
void setColumnStretch(int cols, int rows);
|
||||||
|
void setSpacing(int space);
|
||||||
|
|
||||||
void addItem(const LayoutItem &item);
|
void attachTo(QWidget *);
|
||||||
|
void addItemHelper(const LayoutItem &item);
|
||||||
|
void addItem(I item);
|
||||||
|
void addItems(std::initializer_list<I> items);
|
||||||
|
void addRow(std::initializer_list<I> items);
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
|
void flush_() const;
|
||||||
void fieldGrowthPolicy(int policy);
|
void fieldGrowthPolicy(int policy);
|
||||||
|
|
||||||
|
QWidget *emerge() const;
|
||||||
|
|
||||||
QFormLayout *asForm();
|
QFormLayout *asForm();
|
||||||
QGridLayout *asGrid();
|
QGridLayout *asGrid();
|
||||||
QBoxLayout *asBox();
|
QBoxLayout *asBox();
|
||||||
|
FlowLayout *asFlow();
|
||||||
std::vector<LayoutItem> pendingItems;
|
|
||||||
|
|
||||||
// Grid-only
|
// Grid-only
|
||||||
int currentGridColumn = 0;
|
int currentGridColumn = 0;
|
||||||
int currentGridRow = 0;
|
int currentGridRow = 0;
|
||||||
Qt::Alignment align = {};
|
//Qt::Alignment align = {};
|
||||||
|
bool useFormAlignment = false;
|
||||||
|
|
||||||
|
std::vector<LayoutItem> pendingItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Layout : BuilderItem<Layout, LayoutInterface>
|
class QTCREATOR_UTILS_EXPORT Column : public Layout
|
||||||
{
|
{
|
||||||
};
|
public:
|
||||||
|
using Implementation = QVBoxLayout;
|
||||||
|
using I = BuilderItem<Column>;
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Column : BuilderItem<Column, LayoutInterface>
|
|
||||||
{
|
|
||||||
Column(std::initializer_list<I> ps);
|
Column(std::initializer_list<I> ps);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Row : BuilderItem<Row, LayoutInterface>
|
class QTCREATOR_UTILS_EXPORT Row : public Layout
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using Implementation = QHBoxLayout;
|
||||||
|
using I = BuilderItem<Row>;
|
||||||
|
|
||||||
Row(std::initializer_list<I> ps);
|
Row(std::initializer_list<I> ps);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Form : BuilderItem<Form, LayoutInterface>
|
class QTCREATOR_UTILS_EXPORT Form : public Layout
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using Implementation = QFormLayout;
|
||||||
|
using I = BuilderItem<Form>;
|
||||||
|
|
||||||
|
Form();
|
||||||
Form(std::initializer_list<I> ps);
|
Form(std::initializer_list<I> ps);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Grid : BuilderItem<Grid, LayoutInterface>
|
class QTCREATOR_UTILS_EXPORT Grid : public Layout
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using Implementation = QGridLayout;
|
||||||
|
using I = BuilderItem<Grid>;
|
||||||
|
|
||||||
|
Grid();
|
||||||
Grid(std::initializer_list<I> ps);
|
Grid(std::initializer_list<I> ps);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Flow : BuilderItem<Flow, LayoutInterface>
|
class QTCREATOR_UTILS_EXPORT Flow : public Layout
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
Flow(std::initializer_list<I> ps);
|
Flow(std::initializer_list<I> ps);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Stretch : LayoutItem
|
class QTCREATOR_UTILS_EXPORT Stretch
|
||||||
{
|
{
|
||||||
explicit Stretch(int stretch) { this->stretch = stretch; }
|
public:
|
||||||
|
explicit Stretch(int stretch) : stretch(stretch) {}
|
||||||
|
|
||||||
|
int stretch;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Space : LayoutItem
|
class QTCREATOR_UTILS_EXPORT Space
|
||||||
{
|
{
|
||||||
explicit Space(int space) { this->space = space; }
|
public:
|
||||||
|
explicit Space(int space) : space(space) {}
|
||||||
|
|
||||||
|
int space;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Span : LayoutItem
|
class QTCREATOR_UTILS_EXPORT Span
|
||||||
{
|
{
|
||||||
Span(int n, const LayoutItem &item);
|
public:
|
||||||
|
Span(int n, const Layout::I &item);
|
||||||
|
|
||||||
|
Layout::I item;
|
||||||
|
int spanCols = 1;
|
||||||
|
int spanRows = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Widgets
|
// Widgets
|
||||||
//
|
//
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT WidgetInterface : ObjectInterface
|
class QTCREATOR_UTILS_EXPORT Widget : public Object
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QWidget;
|
using Implementation = QWidget;
|
||||||
QWidget *emerge();
|
using I = BuilderItem<Widget>;
|
||||||
|
|
||||||
|
Widget() = default;
|
||||||
|
Widget(std::initializer_list<I> ps);
|
||||||
|
Widget(Implementation *w) { ptr = w; }
|
||||||
|
|
||||||
|
QWidget *emerge() const;
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
void resize(int, int);
|
void resize(int, int);
|
||||||
void setLayout(const LayoutInterface &layout);
|
void setLayout(const Layout &layout);
|
||||||
void setWindowTitle(const QString &);
|
void setWindowTitle(const QString &);
|
||||||
void setToolTip(const QString &);
|
void setToolTip(const QString &);
|
||||||
void noMargin();
|
void noMargin(int = 0);
|
||||||
void normalMargin();
|
void normalMargin(int = 0);
|
||||||
void customMargin(const QMargins &margin);
|
void customMargin(const QMargins &margin);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Widget : BuilderItem<Widget, WidgetInterface>
|
class QTCREATOR_UTILS_EXPORT Label : public Widget
|
||||||
{
|
|
||||||
Widget(std::initializer_list<I> ps);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Label
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT LabelInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QLabel;
|
using Implementation = QLabel;
|
||||||
|
using I = BuilderItem<Label>;
|
||||||
|
|
||||||
|
Label(std::initializer_list<I> ps);
|
||||||
|
Label(const QString &text);
|
||||||
|
|
||||||
void setText(const QString &);
|
void setText(const QString &);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Label : BuilderItem<Label, LabelInterface>
|
class QTCREATOR_UTILS_EXPORT Group : public Widget
|
||||||
{
|
|
||||||
Label(std::initializer_list<I> ps);
|
|
||||||
Label(const QString &text);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Group
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT GroupInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QGroupBox;
|
using Implementation = QGroupBox;
|
||||||
|
using I = BuilderItem<Group>;
|
||||||
|
|
||||||
|
Group(std::initializer_list<I> ps);
|
||||||
|
|
||||||
void setTitle(const QString &);
|
void setTitle(const QString &);
|
||||||
|
void setGroupChecker(const std::function<void(QObject *)> &);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Group : BuilderItem<Group, GroupInterface>
|
class QTCREATOR_UTILS_EXPORT SpinBox : public Widget
|
||||||
{
|
|
||||||
Group(std::initializer_list<I> ps);
|
|
||||||
};
|
|
||||||
|
|
||||||
// SpinBox
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT SpinBoxInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QSpinBox;
|
using Implementation = QSpinBox;
|
||||||
|
using I = BuilderItem<SpinBox>;
|
||||||
|
|
||||||
|
SpinBox(std::initializer_list<I> ps);
|
||||||
|
|
||||||
void setValue(int);
|
void setValue(int);
|
||||||
void onTextChanged(const std::function<void(QString)> &);
|
void onTextChanged(const std::function<void(QString)> &);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT SpinBox : BuilderItem<SpinBox, SpinBoxInterface>
|
class QTCREATOR_UTILS_EXPORT PushButton : public Widget
|
||||||
{
|
|
||||||
SpinBox(std::initializer_list<I> ps);
|
|
||||||
};
|
|
||||||
|
|
||||||
// PushButton
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT PushButtonInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QPushButton;
|
using Implementation = QPushButton;
|
||||||
|
using I = BuilderItem<PushButton>;
|
||||||
|
|
||||||
void setText(const QString &);
|
|
||||||
void onClicked(const std::function<void()> &);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT PushButton : BuilderItem<PushButton, PushButtonInterface>
|
|
||||||
{
|
|
||||||
PushButton(std::initializer_list<I> ps);
|
PushButton(std::initializer_list<I> ps);
|
||||||
|
|
||||||
|
void setText(const QString &);
|
||||||
|
void onClicked(const std::function<void()> &, QObject *guard);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TextEdit
|
class QTCREATOR_UTILS_EXPORT TextEdit : public Widget
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT TextEditInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QTextEdit;
|
using Implementation = QTextEdit;
|
||||||
|
using I = BuilderItem<TextEdit>;
|
||||||
|
using Id = Implementation *;
|
||||||
|
|
||||||
|
TextEdit(std::initializer_list<I> ps);
|
||||||
|
|
||||||
void setText(const QString &);
|
void setText(const QString &);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT TextEdit : BuilderItem<TextEdit, TextEditInterface>
|
class QTCREATOR_UTILS_EXPORT Splitter : public Widget
|
||||||
{
|
|
||||||
TextEdit(std::initializer_list<I> ps);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Splitter
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT SplitterInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QSplitter;
|
using Implementation = QSplitter;
|
||||||
};
|
using I = BuilderItem<Splitter>;
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Splitter : BuilderItem<Splitter, SplitterInterface>
|
|
||||||
{
|
|
||||||
Splitter(std::initializer_list<I> items);
|
Splitter(std::initializer_list<I> items);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stack
|
class QTCREATOR_UTILS_EXPORT Stack : public Widget
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT StackInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
};
|
public:
|
||||||
|
using Implementation = QStackedWidget;
|
||||||
|
using I = BuilderItem<Stack>;
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Stack : BuilderItem<Stack, StackInterface>
|
|
||||||
{
|
|
||||||
Stack() : Stack({}) {}
|
Stack() : Stack({}) {}
|
||||||
Stack(std::initializer_list<I> items);
|
Stack(std::initializer_list<I> items);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TabWidget
|
class QTCREATOR_UTILS_EXPORT Tab : public Widget
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT TabInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using Implementation = QWidget;
|
||||||
|
|
||||||
|
Tab(const QString &tabName, const Layout &inner);
|
||||||
|
|
||||||
|
const QString tabName;
|
||||||
|
const Layout inner;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT TabWidgetInterface : WidgetInterface
|
class QTCREATOR_UTILS_EXPORT TabWidget : public Widget
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QTabWidget;
|
using Implementation = QTabWidget;
|
||||||
};
|
using I = BuilderItem<TabWidget>;
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT Tab : BuilderItem<Tab, TabInterface>
|
|
||||||
{
|
|
||||||
Tab(const QString &tabName, const LayoutItem &item);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT TabWidget : BuilderItem<TabWidget, TabWidgetInterface>
|
|
||||||
{
|
|
||||||
TabWidget(std::initializer_list<I> items);
|
TabWidget(std::initializer_list<I> items);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ToolBar
|
class QTCREATOR_UTILS_EXPORT ToolBar : public Widget
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT ToolBarInterface : WidgetInterface
|
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
using Implementation = QToolBar;
|
using Implementation = QToolBar;
|
||||||
};
|
using I = Layouting::BuilderItem<ToolBar>;
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT ToolBar : BuilderItem<ToolBar, ToolBarInterface>
|
|
||||||
{
|
|
||||||
ToolBar(std::initializer_list<I> items);
|
ToolBar(std::initializer_list<I> items);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
|
|
||||||
struct QTCREATOR_UTILS_EXPORT If : LayoutItem
|
class QTCREATOR_UTILS_EXPORT If
|
||||||
{
|
{
|
||||||
If(bool condition, const LayoutItems &item, const LayoutItems &other = {});
|
public:
|
||||||
|
If(bool condition,
|
||||||
|
const std::initializer_list<Layout::I> ifcase,
|
||||||
|
const std::initializer_list<Layout::I> thencase = {});
|
||||||
|
|
||||||
|
const std::initializer_list<Layout::I> used;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -413,24 +404,15 @@ struct QTCREATOR_UTILS_EXPORT If : LayoutItem
|
|||||||
// the base expectation is that they will forwards to the backend
|
// the base expectation is that they will forwards to the backend
|
||||||
// type's setter.
|
// type's setter.
|
||||||
|
|
||||||
// Special dispatchers :w
|
// Special dispatchers
|
||||||
|
|
||||||
|
|
||||||
struct BindToId {};
|
class BindToId {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto bindTo(T **x)
|
auto bindTo(T **p)
|
||||||
{
|
{
|
||||||
// FIXME: Evil hack to shut up clang-tidy which does not see that the returned tuple will
|
return IdAndArg{BindToId{}, p};
|
||||||
// result in an assignment to *x and complains about every use of the bound value later.
|
|
||||||
// main.cpp:129:5: Called C++ object pointer is null [clang-analyzer-core.CallAndMessage]
|
|
||||||
// 1: Calling 'bindTo<QWidget>' in /data/dev/creator/tests/manual/layoutbuilder/v2/main.cpp:73
|
|
||||||
// 2: Null pointer value stored to 'w' in /data/dev/creator/tests/manual/layoutbuilder/v2/lb.h:518
|
|
||||||
// 3: Returning from 'bindTo<QWidget>' in /data/dev/creator/tests/manual/layoutbuilder/v2/main.cpp:73
|
|
||||||
// 4: Called C++ object pointer is null in /data/dev/creator/tests/manual/layoutbuilder/v2/main.cpp:129
|
|
||||||
*x = reinterpret_cast<T*>(1);
|
|
||||||
|
|
||||||
return IdAndArg{BindToId{}, x};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Interface>
|
template <typename Interface>
|
||||||
@@ -439,8 +421,8 @@ void doit(Interface *x, BindToId, auto p)
|
|||||||
*p = static_cast<Interface::Implementation *>(x->ptr);
|
*p = static_cast<Interface::Implementation *>(x->ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IdId {};
|
class IdId {};
|
||||||
auto id(auto x) { return IdAndArg{IdId{}, x}; }
|
auto id(auto p) { return IdAndArg{IdId{}, p}; }
|
||||||
|
|
||||||
template <typename Interface>
|
template <typename Interface>
|
||||||
void doit(Interface *x, IdId, auto p)
|
void doit(Interface *x, IdId, auto p)
|
||||||
@@ -450,59 +432,119 @@ void doit(Interface *x, IdId, auto p)
|
|||||||
|
|
||||||
// Setter dispatchers
|
// Setter dispatchers
|
||||||
|
|
||||||
struct SizeId {};
|
class SizeId {};
|
||||||
auto size(auto w, auto h) { return IdAndArg{SizeId{}, std::pair{w, h}}; }
|
auto size(auto w, auto h) { return IdAndArg{SizeId{}, std::pair{w, h}}; }
|
||||||
void doit(auto x, SizeId, auto p) { x->resize(p.first, p.second); }
|
void doit(auto x, SizeId, auto p) { x->resize(p.first, p.second); }
|
||||||
|
|
||||||
struct TextId {};
|
class TextId {};
|
||||||
auto text(auto x) { return IdAndArg{TextId{}, x}; }
|
auto text(auto p) { return IdAndArg{TextId{}, p}; }
|
||||||
void doit(auto x, TextId, auto t) { x->setText(t); }
|
void doit(auto x, TextId, auto p) { x->setText(p); }
|
||||||
|
|
||||||
struct TitleId {};
|
class TitleId {};
|
||||||
auto title(auto x) { return IdAndArg{TitleId{}, x}; }
|
auto title(auto p) { return IdAndArg{TitleId{}, p}; }
|
||||||
void doit(auto x, TitleId, auto t) { x->setTitle(t); }
|
void doit(auto x, TitleId, auto p) { x->setTitle(p); }
|
||||||
|
|
||||||
struct ToolTipId {};
|
class GroupCheckerId {};
|
||||||
auto toolTip(auto x) { return IdAndArg{ToolTipId{}, x}; }
|
auto groupChecker(auto p) { return IdAndArg{GroupCheckerId{}, p}; }
|
||||||
void doit(auto x, ToolTipId, auto t) { x->setToolTip(t); }
|
void doit(auto x, GroupCheckerId, auto p) { x->setGroupChecker(p); }
|
||||||
|
|
||||||
struct WindowTitleId {};
|
class ToolTipId {};
|
||||||
auto windowTitle(auto x) { return IdAndArg{WindowTitleId{}, x}; }
|
auto toolTip(auto p) { return IdAndArg{ToolTipId{}, p}; }
|
||||||
void doit(auto x, WindowTitleId, auto t) { x->setWindowTitle(t); }
|
void doit(auto x, ToolTipId, auto p) { x->setToolTip(p); }
|
||||||
|
|
||||||
struct OnTextChangedId {};
|
class WindowTitleId {};
|
||||||
auto onTextChanged(auto x) { return IdAndArg{OnTextChangedId{}, x}; }
|
auto windowTitle(auto p) { return IdAndArg{WindowTitleId{}, p}; }
|
||||||
void doit(auto x, OnTextChangedId, auto func) { x->onTextChanged(func); }
|
void doit(auto x, WindowTitleId, auto p) { x->setWindowTitle(p); }
|
||||||
|
|
||||||
struct OnClickedId {};
|
class OnTextChangedId {};
|
||||||
auto onClicked(auto x) { return IdAndArg{OnClickedId{}, x}; }
|
auto onTextChanged(auto p) { return IdAndArg{OnTextChangedId{}, p}; }
|
||||||
void doit(auto x, OnClickedId, auto func) { x->onClicked(func); }
|
void doit(auto x, OnTextChangedId, auto p) { x->onTextChanged(p); }
|
||||||
|
|
||||||
|
class OnClickedId {};
|
||||||
|
auto onClicked(auto p, auto guard) { return IdAndArg{OnClickedId{}, std::pair{p, guard}}; }
|
||||||
|
void doit(auto x, OnClickedId, auto p) { x->onClicked(p.first, p.second); }
|
||||||
|
|
||||||
|
class CustomMarginId {};
|
||||||
|
inline auto customMargin(const QMargins &p) { return IdAndArg{CustomMarginId{}, p}; }
|
||||||
|
void doit(auto x, CustomMarginId, auto p) { x->customMargin(p); }
|
||||||
|
|
||||||
|
class FieldGrowthPolicyId {};
|
||||||
|
inline auto fieldGrowthPolicy(auto p) { return IdAndArg{FieldGrowthPolicyId{}, p}; }
|
||||||
|
void doit(auto x, FieldGrowthPolicyId, auto p) { x->fieldGrowthPolicy(p); }
|
||||||
|
|
||||||
|
class ColumnStretchId {};
|
||||||
|
inline auto columnStretch(int column, int stretch) { return IdAndArg{ColumnStretchId{}, std::pair{column, stretch}}; }
|
||||||
|
void doit(auto x, ColumnStretchId, auto p) { x->setColumnStretch(p.first, p.second); }
|
||||||
|
|
||||||
// Nesting dispatchers
|
// Nesting dispatchers
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT void addNestedItem(WidgetInterface *widget, const LayoutInterface &layout);
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Layout &inner);
|
||||||
QTCREATOR_UTILS_EXPORT void addNestedItem(LayoutInterface *layout, const LayoutItem &inner);
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Widget &inner);
|
||||||
QTCREATOR_UTILS_EXPORT void addNestedItem(LayoutInterface *layout, const LayoutInterface &inner);
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, QWidget *inner);
|
||||||
QTCREATOR_UTILS_EXPORT void addNestedItem(LayoutInterface *layout, const WidgetInterface &inner);
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, QLayout *inner);
|
||||||
QTCREATOR_UTILS_EXPORT void addNestedItem(LayoutInterface *layout, const QString &inner);
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const LayoutModifier &inner);
|
||||||
QTCREATOR_UTILS_EXPORT void addNestedItem(LayoutInterface *layout, const std::function<LayoutItem()> &inner);
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const QString &inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Space &inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Stretch &inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const If &inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Span &inner);
|
||||||
// ... can be added to anywhere later to support "user types"
|
// ... can be added to anywhere later to support "user types"
|
||||||
|
|
||||||
void doit(auto outer, NestId, auto inner)
|
QTCREATOR_UTILS_EXPORT void addToWidget(Widget *widget, const Layout &layout);
|
||||||
|
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToTabWidget(TabWidget *tabWidget, const Tab &inner);
|
||||||
|
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToSplitter(Splitter *splitter, QWidget *inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToSplitter(Splitter *splitter, const Widget &inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToSplitter(Splitter *splitter, const Layout &inner);
|
||||||
|
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToStack(Stack *stack, QWidget *inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToStack(Stack *stack, const Widget &inner);
|
||||||
|
QTCREATOR_UTILS_EXPORT void addToStack(Stack *stack, const Layout &inner);
|
||||||
|
|
||||||
|
template <class Inner>
|
||||||
|
void doit_nested(Layout *outer, Inner && inner)
|
||||||
{
|
{
|
||||||
addNestedItem(outer, inner);
|
addToLayout(outer, std::forward<Inner>(inner));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doit_nested(Widget *outer, auto inner)
|
||||||
|
{
|
||||||
|
addToWidget(outer, inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doit_nested(TabWidget *outer, auto inner)
|
||||||
|
{
|
||||||
|
addToTabWidget(outer, inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doit_nested(Stack *outer, auto inner)
|
||||||
|
{
|
||||||
|
addToStack(outer, inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doit_nested(Splitter *outer, auto inner)
|
||||||
|
{
|
||||||
|
addToSplitter(outer, inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Inner>
|
||||||
|
void doit(auto outer, NestId, Inner && inner)
|
||||||
|
{
|
||||||
|
doit_nested(outer, std::forward<Inner>(inner));
|
||||||
|
}
|
||||||
|
|
||||||
// Special layout items
|
// Special layout items
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT LayoutItem br();
|
QTCREATOR_UTILS_EXPORT void empty(Layout *);
|
||||||
QTCREATOR_UTILS_EXPORT LayoutItem empty();
|
QTCREATOR_UTILS_EXPORT void br(Layout *);
|
||||||
QTCREATOR_UTILS_EXPORT LayoutItem hr();
|
QTCREATOR_UTILS_EXPORT void st(Layout *);
|
||||||
QTCREATOR_UTILS_EXPORT LayoutItem withFormAlignment();
|
QTCREATOR_UTILS_EXPORT void noMargin(Layout *);
|
||||||
QTCREATOR_UTILS_EXPORT LayoutItem st();
|
QTCREATOR_UTILS_EXPORT void normalMargin(Layout *);
|
||||||
|
QTCREATOR_UTILS_EXPORT void withFormAlignment(Layout *);
|
||||||
|
QTCREATOR_UTILS_EXPORT void hr(Layout *);
|
||||||
|
|
||||||
|
QTCREATOR_UTILS_EXPORT LayoutModifier spacing(int space);
|
||||||
|
|
||||||
// Convenience
|
// Convenience
|
||||||
|
|
||||||
|
@@ -68,7 +68,7 @@ int main(int argc, char *argv[])
|
|||||||
st,
|
st,
|
||||||
PushButton {
|
PushButton {
|
||||||
text("Quit"),
|
text("Quit"),
|
||||||
onClicked(QApplication::quit)
|
onClicked(QApplication::quit, nullptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user