layoutbuilder.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. // Copyright (C) 2020 The Qt Company Ltd.
  2. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
  3. #pragma once
  4. #include "builderutils.h"
  5. #include <QString>
  6. #include <initializer_list>
  7. #include <vector>
  8. #if defined(UTILS_LIBRARY)
  9. # define QTCREATOR_UTILS_EXPORT Q_DECL_EXPORT
  10. #elif defined(UTILS_STATIC_LIBRARY)
  11. # define QTCREATOR_UTILS_EXPORT
  12. #else
  13. # define QTCREATOR_UTILS_EXPORT Q_DECL_IMPORT
  14. #endif
  15. QT_BEGIN_NAMESPACE
  16. class QBoxLayout;
  17. class QFormLayout;
  18. class QGridLayout;
  19. class QGroupBox;
  20. class QHBoxLayout;
  21. class QLabel;
  22. class QLayout;
  23. class QObject;
  24. class QPushButton;
  25. class QSpinBox;
  26. class QSplitter;
  27. class QStackedWidget;
  28. class QTabWidget;
  29. class QTextEdit;
  30. class QToolBar;
  31. class QVBoxLayout;
  32. class QWidget;
  33. QT_END_NAMESPACE
  34. namespace Layouting {
  35. //////////////////////////////////////////////
  36. //
  37. // Basic
  38. //
  39. class QTCREATOR_UTILS_EXPORT Thing
  40. {
  41. public:
  42. void *ptr; // The product.
  43. };
  44. class QTCREATOR_UTILS_EXPORT Object : public Thing
  45. {
  46. public:
  47. using Implementation = QObject;
  48. using I = Building::BuilderItem<Object>;
  49. Object() = default;
  50. Object(std::initializer_list<I> ps);
  51. };
  52. //
  53. // Layouts
  54. //
  55. class FlowLayout;
  56. class Layout;
  57. using LayoutModifier = std::function<void(Layout *)>;
  58. class QTCREATOR_UTILS_EXPORT LayoutItem
  59. {
  60. public:
  61. ~LayoutItem();
  62. LayoutItem();
  63. LayoutItem(QLayout *l);
  64. LayoutItem(QWidget *w);
  65. LayoutItem(const QString &t);
  66. QString text;
  67. QLayout *layout = nullptr;
  68. QWidget *widget = nullptr;
  69. int stretch = -1;
  70. int spanCols = 1;
  71. int spanRows = 1;
  72. bool empty = false;
  73. };
  74. class QTCREATOR_UTILS_EXPORT Layout : public Object
  75. {
  76. public:
  77. using Implementation = QLayout;
  78. using I = Building::BuilderItem<Layout>;
  79. Layout() = default;
  80. Layout(Implementation *w) { ptr = w; }
  81. void span(int cols, int rows);
  82. void setNoMargins();
  83. void setNormalMargins();
  84. void setContentsMargins(int left, int top, int right, int bottom);
  85. void setColumnStretch(int cols, int rows);
  86. void setSpacing(int space);
  87. void setFieldGrowthPolicy(int policy);
  88. void attachTo(QWidget *);
  89. void addItem(I item);
  90. void addItems(std::initializer_list<I> items);
  91. void addRow(std::initializer_list<I> items);
  92. void addLayoutItem(const LayoutItem &item);
  93. void flush();
  94. void flush_() const;
  95. QWidget *emerge() const;
  96. void show() const;
  97. QFormLayout *asForm();
  98. QGridLayout *asGrid();
  99. QBoxLayout *asBox();
  100. FlowLayout *asFlow();
  101. // Grid-only
  102. int currentGridColumn = 0;
  103. int currentGridRow = 0;
  104. //Qt::Alignment align = {};
  105. bool useFormAlignment = false;
  106. std::vector<LayoutItem> pendingItems;
  107. };
  108. class QTCREATOR_UTILS_EXPORT Column : public Layout
  109. {
  110. public:
  111. using Implementation = QVBoxLayout;
  112. using I = Building::BuilderItem<Column>;
  113. Column(std::initializer_list<I> ps);
  114. };
  115. class QTCREATOR_UTILS_EXPORT Row : public Layout
  116. {
  117. public:
  118. using Implementation = QHBoxLayout;
  119. using I = Building::BuilderItem<Row>;
  120. Row(std::initializer_list<I> ps);
  121. };
  122. class QTCREATOR_UTILS_EXPORT Form : public Layout
  123. {
  124. public:
  125. using Implementation = QFormLayout;
  126. using I = Building::BuilderItem<Form>;
  127. Form();
  128. Form(std::initializer_list<I> ps);
  129. };
  130. class QTCREATOR_UTILS_EXPORT Grid : public Layout
  131. {
  132. public:
  133. using Implementation = QGridLayout;
  134. using I = Building::BuilderItem<Grid>;
  135. Grid();
  136. Grid(std::initializer_list<I> ps);
  137. };
  138. class QTCREATOR_UTILS_EXPORT Flow : public Layout
  139. {
  140. public:
  141. Flow(std::initializer_list<I> ps);
  142. };
  143. class QTCREATOR_UTILS_EXPORT Stretch
  144. {
  145. public:
  146. explicit Stretch(int stretch) : stretch(stretch) {}
  147. int stretch;
  148. };
  149. class QTCREATOR_UTILS_EXPORT Space
  150. {
  151. public:
  152. explicit Space(int space) : space(space) {}
  153. int space;
  154. };
  155. class QTCREATOR_UTILS_EXPORT Span
  156. {
  157. public:
  158. Span(int cols, const Layout::I &item);
  159. Span(int cols, int rows, const Layout::I &item);
  160. Layout::I item;
  161. int spanCols = 1;
  162. int spanRows = 1;
  163. };
  164. //
  165. // Widgets
  166. //
  167. class QTCREATOR_UTILS_EXPORT Widget : public Object
  168. {
  169. public:
  170. using Implementation = QWidget;
  171. using I = Building::BuilderItem<Widget>;
  172. Widget() = default;
  173. Widget(std::initializer_list<I> ps);
  174. Widget(Implementation *w) { ptr = w; }
  175. QWidget *emerge() const;
  176. void show();
  177. void setLayout(const Layout &layout);
  178. void setSize(int, int);
  179. void setWindowTitle(const QString &);
  180. void setToolTip(const QString &);
  181. void setNoMargins(int = 0);
  182. void setNormalMargins(int = 0);
  183. void setContentsMargins(int left, int top, int right, int bottom);
  184. };
  185. class QTCREATOR_UTILS_EXPORT Label : public Widget
  186. {
  187. public:
  188. using Implementation = QLabel;
  189. using I = Building::BuilderItem<Label>;
  190. Label(std::initializer_list<I> ps);
  191. Label(const QString &text);
  192. void setText(const QString &);
  193. void setTextFormat(Qt::TextFormat);
  194. void setWordWrap(bool);
  195. void setTextInteractionFlags(Qt::TextInteractionFlags);
  196. void setOpenExternalLinks(bool);
  197. void onLinkHovered(const std::function<void(const QString &)> &, QObject *guard);
  198. };
  199. class QTCREATOR_UTILS_EXPORT Group : public Widget
  200. {
  201. public:
  202. using Implementation = QGroupBox;
  203. using I = Building::BuilderItem<Group>;
  204. Group(std::initializer_list<I> ps);
  205. void setTitle(const QString &);
  206. void setGroupChecker(const std::function<void(QObject *)> &);
  207. };
  208. class QTCREATOR_UTILS_EXPORT SpinBox : public Widget
  209. {
  210. public:
  211. using Implementation = QSpinBox;
  212. using I = Building::BuilderItem<SpinBox>;
  213. SpinBox(std::initializer_list<I> ps);
  214. void setValue(int);
  215. void onTextChanged(const std::function<void(QString)> &);
  216. };
  217. class QTCREATOR_UTILS_EXPORT PushButton : public Widget
  218. {
  219. public:
  220. using Implementation = QPushButton;
  221. using I = Building::BuilderItem<PushButton>;
  222. PushButton(std::initializer_list<I> ps);
  223. void setText(const QString &);
  224. void onClicked(const std::function<void()> &, QObject *guard);
  225. };
  226. class QTCREATOR_UTILS_EXPORT TextEdit : public Widget
  227. {
  228. public:
  229. using Implementation = QTextEdit;
  230. using I = Building::BuilderItem<TextEdit>;
  231. using Id = Implementation *;
  232. TextEdit(std::initializer_list<I> ps);
  233. void setText(const QString &);
  234. };
  235. class QTCREATOR_UTILS_EXPORT Splitter : public Widget
  236. {
  237. public:
  238. using Implementation = QSplitter;
  239. using I = Building::BuilderItem<Splitter>;
  240. Splitter(std::initializer_list<I> items);
  241. void setOrientation(Qt::Orientation);
  242. void setStretchFactor(int index, int stretch);
  243. void setChildrenCollapsible(bool collapsible);
  244. };
  245. class QTCREATOR_UTILS_EXPORT Stack : public Widget
  246. {
  247. public:
  248. using Implementation = QStackedWidget;
  249. using I = Building::BuilderItem<Stack>;
  250. Stack() : Stack({}) {}
  251. Stack(std::initializer_list<I> items);
  252. };
  253. class QTCREATOR_UTILS_EXPORT Tab : public Widget
  254. {
  255. public:
  256. using Implementation = QWidget;
  257. Tab(const QString &tabName, const Layout &inner);
  258. const QString tabName;
  259. const Layout inner;
  260. };
  261. class QTCREATOR_UTILS_EXPORT TabWidget : public Widget
  262. {
  263. public:
  264. using Implementation = QTabWidget;
  265. using I = Building::BuilderItem<TabWidget>;
  266. TabWidget(std::initializer_list<I> items);
  267. };
  268. class QTCREATOR_UTILS_EXPORT ToolBar : public Widget
  269. {
  270. public:
  271. using Implementation = QToolBar;
  272. using I = Building::BuilderItem<ToolBar>;
  273. ToolBar(std::initializer_list<I> items);
  274. };
  275. // Special
  276. class QTCREATOR_UTILS_EXPORT If
  277. {
  278. public:
  279. If(bool condition,
  280. const std::initializer_list<Layout::I> ifcase,
  281. const std::initializer_list<Layout::I> thencase = {});
  282. const std::initializer_list<Layout::I> used;
  283. };
  284. //
  285. // Dispatchers
  286. //
  287. // We need one 'Id' (and a corresponding function wrapping arguments into a
  288. // tuple marked by this id) per 'name' of "backend" setter member function,
  289. // i.e. one 'text' is sufficient for QLabel::setText, QLineEdit::setText.
  290. // The name of the Id does not have to match the backend names as it
  291. // is mapped per-backend-type in the respective setter implementation
  292. // but we assume that it generally makes sense to stay close to the
  293. // wrapped API name-wise.
  294. // These are free functions overloaded on the type of builder object
  295. // and setter id. The function implementations are independent, but
  296. // the base expectation is that they will forwards to the backend
  297. // type's setter.
  298. // Special dispatchers
  299. class BindToId {};
  300. template <typename T>
  301. auto bindTo(T **p)
  302. {
  303. return Building::IdAndArg{BindToId{}, p};
  304. }
  305. template <typename Interface, typename P>
  306. void doit(Interface *x, BindToId, P p)
  307. {
  308. *p = static_cast<typename Interface::Implementation *>(x->ptr);
  309. }
  310. class IdId {};
  311. template<typename P>
  312. auto id(P p) { return Building::IdAndArg{IdId{}, p}; }
  313. template <typename Interface, typename P>
  314. void doit(Interface *x, IdId, P p)
  315. {
  316. **p = static_cast<typename Interface::Implementation *>(x->ptr);
  317. }
  318. // Setter dispatchers
  319. QTC_DEFINE_BUILDER_SETTER(childrenCollapsible, setChildrenCollapsible)
  320. QTC_DEFINE_BUILDER_SETTER(columnStretch, setColumnStretch)
  321. QTC_DEFINE_BUILDER_SETTER(customMargins, setContentsMargins)
  322. QTC_DEFINE_BUILDER_SETTER(fieldGrowthPolicy, setFieldGrowthPolicy)
  323. QTC_DEFINE_BUILDER_SETTER(groupChecker, setGroupChecker)
  324. QTC_DEFINE_BUILDER_SETTER(onClicked, onClicked)
  325. QTC_DEFINE_BUILDER_SETTER(onLinkHovered, onLinkHovered)
  326. QTC_DEFINE_BUILDER_SETTER(onTextChanged, onTextChanged)
  327. QTC_DEFINE_BUILDER_SETTER(openExternalLinks, setOpenExternalLinks)
  328. QTC_DEFINE_BUILDER_SETTER(orientation, setOrientation);
  329. QTC_DEFINE_BUILDER_SETTER(size, setSize)
  330. QTC_DEFINE_BUILDER_SETTER(text, setText)
  331. QTC_DEFINE_BUILDER_SETTER(textFormat, setTextFormat)
  332. QTC_DEFINE_BUILDER_SETTER(textInteractionFlags, setTextInteractionFlags)
  333. QTC_DEFINE_BUILDER_SETTER(title, setTitle)
  334. QTC_DEFINE_BUILDER_SETTER(toolTip, setToolTip)
  335. QTC_DEFINE_BUILDER_SETTER(windowTitle, setWindowTitle)
  336. QTC_DEFINE_BUILDER_SETTER(wordWrap, setWordWrap);
  337. // Nesting dispatchers
  338. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Layout &inner);
  339. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Widget &inner);
  340. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, QWidget *inner);
  341. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, QLayout *inner);
  342. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const LayoutModifier &inner);
  343. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const QString &inner);
  344. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Space &inner);
  345. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Stretch &inner);
  346. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const If &inner);
  347. QTCREATOR_UTILS_EXPORT void addToLayout(Layout *layout, const Span &inner);
  348. // ... can be added to anywhere later to support "user types"
  349. QTCREATOR_UTILS_EXPORT void addToWidget(Widget *widget, const Layout &layout);
  350. QTCREATOR_UTILS_EXPORT void addToTabWidget(TabWidget *tabWidget, const Tab &inner);
  351. QTCREATOR_UTILS_EXPORT void addToSplitter(Splitter *splitter, QWidget *inner);
  352. QTCREATOR_UTILS_EXPORT void addToSplitter(Splitter *splitter, const Widget &inner);
  353. QTCREATOR_UTILS_EXPORT void addToSplitter(Splitter *splitter, const Layout &inner);
  354. QTCREATOR_UTILS_EXPORT void addToStack(Stack *stack, QWidget *inner);
  355. QTCREATOR_UTILS_EXPORT void addToStack(Stack *stack, const Widget &inner);
  356. QTCREATOR_UTILS_EXPORT void addToStack(Stack *stack, const Layout &inner);
  357. template <class Inner>
  358. void doit_nested(Layout *outer, Inner && inner)
  359. {
  360. addToLayout(outer, std::forward<Inner>(inner));
  361. }
  362. template<typename Inner>
  363. void doit_nested(Widget *outer, Inner inner)
  364. {
  365. addToWidget(outer, inner);
  366. }
  367. template<typename Inner>
  368. void doit_nested(TabWidget *outer, Inner inner)
  369. {
  370. addToTabWidget(outer, inner);
  371. }
  372. template<typename Inner>
  373. void doit_nested(Stack *outer, Inner inner)
  374. {
  375. addToStack(outer, inner);
  376. }
  377. template<typename Inner>
  378. void doit_nested(Splitter *outer, Inner inner)
  379. {
  380. addToSplitter(outer, inner);
  381. }
  382. template <typename Outer, typename Inner>
  383. void doit(Outer outer, Building::NestId, Inner && inner)
  384. {
  385. doit_nested(outer, std::forward<Inner>(inner));
  386. }
  387. // Special layout items
  388. QTCREATOR_UTILS_EXPORT void empty(Layout *);
  389. QTCREATOR_UTILS_EXPORT void br(Layout *);
  390. QTCREATOR_UTILS_EXPORT void st(Layout *);
  391. QTCREATOR_UTILS_EXPORT void noMargin(Layout *);
  392. QTCREATOR_UTILS_EXPORT void normalMargin(Layout *);
  393. QTCREATOR_UTILS_EXPORT void withFormAlignment(Layout *);
  394. QTCREATOR_UTILS_EXPORT void hr(Layout *);
  395. QTCREATOR_UTILS_EXPORT LayoutModifier spacing(int space);
  396. // Convenience
  397. QTCREATOR_UTILS_EXPORT QWidget *createHr(QWidget *parent = nullptr);
  398. } // Layouting