// Copyright (C) 2023 André Pönitz // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #pragma once #include #include #include #include #if defined(UTILS_LIBRARY) # define QTCREATOR_UTILS_EXPORT Q_DECL_EXPORT #elif defined(UTILS_STATIC_LIBRARY) # define QTCREATOR_UTILS_EXPORT #else # define QTCREATOR_UTILS_EXPORT Q_DECL_IMPORT #endif QT_BEGIN_NAMESPACE class QBoxLayout; class QFormLayout; class QGridLayout; class QGroupBox; class QHBoxLayout; class QLabel; class QLayout; class QMargins; class QObject; class QPushButton; class QSpinBox; class QSplitter; class QStackedWidget; class QTabWidget; class QTextEdit; class QToolBar; class QVBoxLayout; class QWidget; QT_END_NAMESPACE namespace Building { class NestId {}; template class IdAndArg { public: IdAndArg(Id, const Arg &arg) : arg(arg) {} const Arg arg; // FIXME: Could be const &, but this would currently break bindTo(). }; // The main dispatcher void doit(auto x, auto id, auto p); template class BuilderItem { public: // Property setter template BuilderItem(IdAndArg && idarg) { apply = [&idarg](X *x) { doit(x, Id{}, idarg.arg); }; } // Nested child object template BuilderItem(Inner && p) { apply = [&p](X *x) { doit(x, NestId{}, std::forward(p)); }; } std::function apply; }; #define QTC_DEFINE_BUILDER_SETTER(name, setter) \ class name##_TAG {}; \ template \ inline auto name(Args &&...args) { \ return Building::IdAndArg{name##_TAG{}, std::tuple{std::forward(args)...}}; \ } \ template \ inline void doit(L *x, name##_TAG, const std::tuple &arg) { \ std::apply(&L::setter, std::tuple_cat(std::make_tuple(x), arg)); \ } } // Building namespace Layouting { ////////////////////////////////////////////// // // Basic // class QTCREATOR_UTILS_EXPORT Thing { public: void *ptr; // The product. }; class QTCREATOR_UTILS_EXPORT Object : public Thing { public: using Implementation = QObject; using I = Building::BuilderItem; Object() = default; Object(std::initializer_list ps); }; // // Layouts // class FlowLayout; class Layout; using LayoutModifier = std::function; // using LayoutModifier = void(*)(Layout *); class QTCREATOR_UTILS_EXPORT Layout : public Object { public: using Implementation = QLayout; using I = Building::BuilderItem; 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 noMargin(); void normalMargin(); void customMargin(const QMargins &margin); void setColumnStretch(int cols, int rows); void setSpacing(int space); void attachTo(QWidget *); void addItemHelper(const LayoutItem &item); void addItem(I item); void addItems(std::initializer_list items); void addRow(std::initializer_list items); void flush(); void flush_() const; void fieldGrowthPolicy(int policy); QWidget *emerge() const; QFormLayout *asForm(); QGridLayout *asGrid(); QBoxLayout *asBox(); FlowLayout *asFlow(); // Grid-only int currentGridColumn = 0; int currentGridRow = 0; //Qt::Alignment align = {}; bool useFormAlignment = false; std::vector pendingItems; }; class QTCREATOR_UTILS_EXPORT Column : public Layout { public: using Implementation = QVBoxLayout; using I = Building::BuilderItem; Column(std::initializer_list ps); }; class QTCREATOR_UTILS_EXPORT Row : public Layout { public: using Implementation = QHBoxLayout; using I = Building::BuilderItem; Row(std::initializer_list ps); }; class QTCREATOR_UTILS_EXPORT Form : public Layout { public: using Implementation = QFormLayout; using I = Building::BuilderItem
; Form(); Form(std::initializer_list ps); }; class QTCREATOR_UTILS_EXPORT Grid : public Layout { public: using Implementation = QGridLayout; using I = Building::BuilderItem; Grid(); Grid(std::initializer_list ps); }; class QTCREATOR_UTILS_EXPORT Flow : public Layout { public: Flow(std::initializer_list ps); }; class QTCREATOR_UTILS_EXPORT Stretch { public: explicit Stretch(int stretch) : stretch(stretch) {} int stretch; }; class QTCREATOR_UTILS_EXPORT Space { public: explicit Space(int space) : space(space) {} int space; }; class QTCREATOR_UTILS_EXPORT Span { public: Span(int n, const Layout::I &item); Layout::I item; int spanCols = 1; int spanRows = 1; }; // // Widgets // class QTCREATOR_UTILS_EXPORT Widget : public Object { public: using Implementation = QWidget; using I = Building::BuilderItem; Widget() = default; Widget(std::initializer_list ps); Widget(Implementation *w) { ptr = w; } QWidget *emerge() const; void show(); void setSize(int, int); void setLayout(const Layout &layout); void setWindowTitle(const QString &); void setToolTip(const QString &); void noMargin(int = 0); void normalMargin(int = 0); void customMargin(const QMargins &margin); }; class QTCREATOR_UTILS_EXPORT Label : public Widget { public: using Implementation = QLabel; using I = Building::BuilderItem