1 #pragma once
2
3 #include <QHBoxLayout>
4 #include <QScrollArea>
5 #include <QTabWidget>
6 #include <QWidget>
7
8 #include <cassert>
9 #include <type_traits>
10
11 namespace chatterino {
12
13 template <class T>
14 class LayoutCreator
15 {
16 public:
LayoutCreator(T * _item)17 LayoutCreator(T *_item)
18 : item_(_item)
19 {
20 }
21
operator ->()22 T *operator->()
23 {
24 return this->item_;
25 }
26
operator *()27 T &operator*()
28 {
29 return *this->item_;
30 }
31
getElement()32 T *getElement()
33 {
34 return this->item_;
35 }
36
37 template <typename T2>
append(T2 * _item)38 LayoutCreator<T2> append(T2 *_item)
39 {
40 this->addItem(this->getOrCreateLayout(), _item);
41
42 return LayoutCreator<T2>(_item);
43 }
44
45 template <typename T2, typename... Args>
emplace(Args &&...args)46 LayoutCreator<T2> emplace(Args &&... args)
47 {
48 T2 *t = new T2(std::forward<Args>(args)...);
49
50 this->addItem(this->getOrCreateLayout(), t);
51
52 return LayoutCreator<T2>(t);
53 }
54
55 template <typename Q = T,
56 typename std::enable_if<std::is_base_of<QScrollArea, Q>::value,
57 int>::type = 0>
emplaceScrollAreaWidget()58 LayoutCreator<QWidget> emplaceScrollAreaWidget()
59 {
60 QWidget *widget = new QWidget;
61 this->item_->setWidget(widget);
62 return LayoutCreator<QWidget>(widget);
63 }
64
65 template <typename T2, typename Q = T,
66 typename std::enable_if<std::is_base_of<QWidget, Q>::value,
67 int>::type = 0,
68 typename std::enable_if<std::is_base_of<QLayout, T2>::value,
69 int>::type = 0>
setLayoutType()70 LayoutCreator<T2> setLayoutType()
71 {
72 T2 *layout = new T2;
73
74 this->item_->setLayout(layout);
75
76 return LayoutCreator<T2>(layout);
77 }
78
assign(T ** ptr)79 LayoutCreator<T> assign(T **ptr)
80 {
81 *ptr = this->item_;
82
83 return *this;
84 }
85
86 template <typename Q = T,
87 typename std::enable_if<std::is_base_of<QLayout, Q>::value,
88 int>::type = 0>
withoutMargin()89 LayoutCreator<T> withoutMargin()
90 {
91 this->item_->setContentsMargins(0, 0, 0, 0);
92
93 return *this;
94 }
95
withoutSpacing()96 LayoutCreator<T> withoutSpacing()
97 {
98 this->item_->setSpacing(0);
99
100 return *this;
101 }
102
103 template <typename Q = T,
104 typename std::enable_if<std::is_base_of<QWidget, Q>::value,
105 int>::type = 0>
hidden()106 LayoutCreator<T> hidden()
107 {
108 this->item_->setVisible(false);
109
110 return *this;
111 }
112
113 template <typename Q = T, typename T2,
114 typename std::enable_if<std::is_same<QTabWidget, Q>::value,
115 int>::type = 0>
appendTab(T2 * item,const QString & title)116 LayoutCreator<T2> appendTab(T2 *item, const QString &title)
117 {
118 static_assert(std::is_base_of<QLayout, T2>::value,
119 "needs to be QLayout");
120
121 QWidget *widget = new QWidget;
122 widget->setLayout(item);
123
124 this->item_->addTab(widget, title);
125
126 return LayoutCreator<T2>(item);
127 }
128
129 template <typename Slot, typename Func>
connect(Slot slot,QObject * receiver,Func func)130 LayoutCreator<T> connect(Slot slot, QObject *receiver, Func func)
131 {
132 QObject::connect(this->getElement(), slot, receiver, func);
133 return *this;
134 }
135
136 template <typename Func>
onClick(QObject * receiver,Func func)137 LayoutCreator<T> onClick(QObject *receiver, Func func)
138 {
139 QObject::connect(this->getElement(), &T::clicked, receiver, func);
140 return *this;
141 }
142
143 private:
144 T *item_;
145
146 template <typename T2,
147 typename std::enable_if<std::is_base_of<QWidget, T2>::value,
148 int>::type = 0>
addItem(QLayout * layout,T2 * item)149 void addItem(QLayout *layout, T2 *item)
150 {
151 layout->addWidget(item);
152 }
153
154 template <typename T2,
155 typename std::enable_if<std::is_base_of<QLayout, T2>::value,
156 int>::type = 0>
addItem(QLayout * layout,T2 * item)157 void addItem(QLayout *layout, T2 *item)
158 {
159 QWidget *widget = new QWidget();
160 widget->setLayout(item);
161 layout->addWidget(widget);
162 }
163
164 template <typename Q = T,
165 typename std::enable_if<std::is_base_of<QLayout, Q>::value,
166 int>::type = 0>
getOrCreateLayout()167 QLayout *getOrCreateLayout()
168 {
169 return this->item_;
170 }
171
172 template <typename Q = T,
173 typename std::enable_if<std::is_base_of<QWidget, Q>::value,
174 int>::type = 0>
getOrCreateLayout()175 QLayout *getOrCreateLayout()
176 {
177 if (!this->item_->layout())
178 {
179 this->item_->setLayout(new QHBoxLayout());
180 }
181
182 return this->item_->layout();
183 }
184 };
185
186 template <typename T, typename... Args>
makeDialog(Args &&...args)187 LayoutCreator<T> makeDialog(Args &&... args)
188 {
189 T *t = new T(std::forward<Args>(args)...);
190 t->setAttribute(Qt::WA_DeleteOnClose);
191 return LayoutCreator<T>(t);
192 }
193
194 } // namespace chatterino
195