1 /*
2 # PostgreSQL Database Modeler (pgModeler)
3 #
4 # Copyright 2006-2020 - Raphael Araújo e Silva <raphael@pgmodeler.io>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation version 3.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # The complete text of GPLv3 is at LICENSE file on source code root directory.
16 # Also, you can get the complete GNU General Public License at <http://www.gnu.org/licenses/>
17 */
18
19 #include "attributestoggleritem.h"
20 #include <QApplication>
21 #include <QDesktopWidget>
22 #include <QScreen>
23 #include "baseobjectview.h"
24
25 QPolygonF AttributesTogglerItem::btn_polygons[7];
26
AttributesTogglerItem(QGraphicsItem * parent)27 AttributesTogglerItem::AttributesTogglerItem(QGraphicsItem *parent) : RoundedRectItem(parent)
28 {
29 createButtonPolygons();
30 this->setRoundedCorners(RoundedRectItem::BottomLeftCorner | RoundedRectItem::BottomRightCorner);
31 sel_rect = new QGraphicsRectItem;
32
33 for(unsigned arr_id = 0; arr_id < 7; arr_id++)
34 {
35 buttons[arr_id] = new QGraphicsPolygonItem;
36 buttons[arr_id]->setPolygon(btn_polygons[arr_id]);
37 btns_selected[arr_id] = false;
38 }
39
40 buttons[AttribsExpandBtn]->setToolTip(tr("Expands the currently collapsed section of the object"));
41 buttons[AttribsCollapseBtn]->setToolTip(tr("Collapses the currently expanded section of the object"));
42 buttons[NextAttribsPageBtn]->setToolTip(tr("Displays the next attributes page"));
43 buttons[PrevAttribsPageBtn]->setToolTip(tr("Displays the previous attributes page"));
44 buttons[NextExtAttribsPageBtn]->setToolTip(tr("Displays the next extended attributes page"));
45 buttons[PrevExtAttribsPageBtn]->setToolTip(tr("Displays the previous extended attributes page"));
46 buttons[PaginationTogglerBtn]->setToolTip(tr("Toggles the attributes pagination on the object"));
47
48 has_ext_attribs = false;
49 pagination_enabled = false;
50 collapse_mode = CollapseMode::NotCollapsed;
51 btns_width = btns_height = 0;
52
53 for(unsigned idx = 0; idx < 2; idx++)
54 current_page[idx] = max_pages[idx] = 0;
55
56 configureButtonsState();
57 }
58
~AttributesTogglerItem()59 AttributesTogglerItem::~AttributesTogglerItem()
60 {
61 for(unsigned arr_id = 0; arr_id < 7; arr_id++)
62 delete buttons[arr_id];
63
64 delete sel_rect;
65 }
66
setButtonsBrush(const QBrush & brush)67 void AttributesTogglerItem::setButtonsBrush(const QBrush &brush)
68 {
69 for(unsigned arr_id = 0; arr_id < 7; arr_id++)
70 buttons[arr_id]->setBrush(brush);
71 }
72
setButtonsPen(const QPen & pen)73 void AttributesTogglerItem::setButtonsPen(const QPen &pen)
74 {
75 for(unsigned arr_id = 0; arr_id < 7; arr_id++)
76 buttons[arr_id]->setPen(pen);
77 }
78
setRect(const QRectF & rect)79 void AttributesTogglerItem::setRect(const QRectF &rect)
80 {
81 configureButtons(rect);
82 }
83
setCollapseMode(CollapseMode coll_mode)84 void AttributesTogglerItem::setCollapseMode(CollapseMode coll_mode)
85 {
86 //Avoiding setting up extended attributes collapsed when the toggler is configured to not having extended attribs
87 if(!has_ext_attribs && coll_mode == CollapseMode::ExtAttribsCollapsed)
88 collapse_mode = CollapseMode::NotCollapsed;
89 else
90 collapse_mode = coll_mode;
91
92 configureButtonsState();
93 }
94
setButtonSelected(const QPointF & pnt,bool clicked)95 void AttributesTogglerItem::setButtonSelected(const QPointF &pnt, bool clicked)
96 {
97 QRectF rect;
98 double h_spacing = 4 * BaseObjectView::HorizSpacing;
99 unsigned coll_mode = static_cast<unsigned>(collapse_mode), section_id = 0;
100
101 this->setToolTip("");
102 clearButtonsSelection();
103
104 for(unsigned arr_id = 0; arr_id < 7; arr_id++)
105 {
106 rect.setSize(QSizeF(buttons[arr_id]->boundingRect().width() + h_spacing, this->boundingRect().height()));
107 rect.moveTo(buttons[arr_id]->pos().x() - (h_spacing/2), 0);
108 btns_selected[arr_id] = rect.contains(pnt) && buttons[arr_id]->isVisible();
109
110 if(btns_selected[arr_id])
111 {
112 this->setToolTip(buttons[arr_id]->toolTip());
113
114 if(clicked)
115 {
116 if(arr_id == AttribsExpandBtn || arr_id == AttribsCollapseBtn)
117 {
118 if(arr_id == AttribsExpandBtn)
119 coll_mode++;
120 else if(arr_id == AttribsCollapseBtn)
121 coll_mode--;
122
123 if(!has_ext_attribs && static_cast<CollapseMode>(coll_mode) == CollapseMode::ExtAttribsCollapsed)
124 coll_mode += (arr_id == AttribsExpandBtn ? 1 : -1);
125
126 if(coll_mode > enum_cast(CollapseMode::NotCollapsed))
127 collapse_mode = (arr_id == AttribsExpandBtn ? CollapseMode::NotCollapsed : CollapseMode::AllAttribsCollapsed);
128 else
129 collapse_mode = static_cast<CollapseMode>(coll_mode);
130 }
131 else if(arr_id == PaginationTogglerBtn)
132 {
133 pagination_enabled = !pagination_enabled;
134 }
135 else
136 {
137 if(arr_id == PrevAttribsPageBtn || arr_id == NextAttribsPageBtn)
138 section_id = BaseTable::AttribsSection;
139 else
140 section_id = BaseTable::ExtAttribsSection;
141
142 if(max_pages[section_id] != 0)
143 {
144 if(arr_id == PrevAttribsPageBtn || arr_id == PrevExtAttribsPageBtn)
145 current_page[section_id]--;
146 else
147 current_page[section_id]++;
148
149 if(current_page[section_id] >= max_pages[section_id])
150 current_page[section_id] = (arr_id == PrevAttribsPageBtn || arr_id == PrevExtAttribsPageBtn ? 0 : max_pages[section_id] - 1);
151 }
152 }
153
154 configureButtons(this->rect());
155 clearButtonsSelection();
156 configureButtonsState();
157
158 if(arr_id == PaginationTogglerBtn)
159 emit s_paginationToggled(pagination_enabled);
160 else if(arr_id == AttribsExpandBtn || arr_id == AttribsCollapseBtn)
161 emit s_collapseModeChanged(collapse_mode);
162 else
163 emit s_currentPageChanged(section_id, current_page[section_id]);
164 }
165 else
166 {
167 //Configuring the selection rectangle if the arrows isn't clicked
168 QRectF rect;
169 QSizeF size = QSizeF(buttons[AttribsExpandBtn]->boundingRect().size().width() + (2 * BaseObjectView::HorizSpacing),
170 btns_height + BaseObjectView::VertSpacing);
171 double px = 0, py = 0, arr_x = buttons[arr_id]->pos().x();
172
173 rect.setSize(size);
174 px = arr_x - (((arr_x + size.width()) - (arr_x + buttons[arr_id]->boundingRect().width()))/2);
175 py = (this->boundingRect().size().height() - size.height())/2.5;
176
177 sel_rect->setBrush(BaseObjectView::getFillStyle(Attributes::ObjSelection));
178 sel_rect->setPen(BaseObjectView::getBorderStyle(Attributes::ObjSelection));
179 sel_rect->setRect(rect);
180 sel_rect->setPos(px, py);
181 }
182
183 break;
184 }
185 }
186 }
187
configureButtonsState()188 void AttributesTogglerItem::configureButtonsState()
189 {
190 buttons[AttribsExpandBtn]->setOpacity(collapse_mode == CollapseMode::ExtAttribsCollapsed ||
191 collapse_mode == CollapseMode::AllAttribsCollapsed? 1 : ButtonMinOpacity);
192
193 buttons[AttribsCollapseBtn]->setOpacity(collapse_mode == CollapseMode::ExtAttribsCollapsed ||
194 collapse_mode == CollapseMode::NotCollapsed ? 1 : ButtonMinOpacity);
195
196 buttons[PrevAttribsPageBtn]->setOpacity(max_pages[BaseTable::AttribsSection] != 0 && current_page[BaseTable::AttribsSection] > 0 ? 1 : ButtonMinOpacity);
197 buttons[NextAttribsPageBtn]->setOpacity(max_pages[BaseTable::AttribsSection] != 0 &&
198 current_page[BaseTable::AttribsSection] < max_pages[BaseTable::AttribsSection] - 1 ? 1 : ButtonMinOpacity);
199
200 buttons[PrevExtAttribsPageBtn]->setOpacity(has_ext_attribs && max_pages[BaseTable::ExtAttribsSection] != 0 && current_page[BaseTable::ExtAttribsSection] > 0 ? 1 : ButtonMinOpacity);
201 buttons[NextExtAttribsPageBtn]->setOpacity(has_ext_attribs && max_pages[BaseTable::ExtAttribsSection] != 0 &&
202 current_page[BaseTable::ExtAttribsSection] < max_pages[BaseTable::ExtAttribsSection] - 1 ? 1 : ButtonMinOpacity);
203
204 buttons[PrevAttribsPageBtn]->setVisible(pagination_enabled);
205 buttons[NextAttribsPageBtn]->setVisible(pagination_enabled);
206 buttons[PrevExtAttribsPageBtn]->setVisible(pagination_enabled);
207 buttons[NextExtAttribsPageBtn]->setVisible(pagination_enabled);
208 }
209
setHasExtAttributes(bool value)210 void AttributesTogglerItem::setHasExtAttributes(bool value)
211 {
212 has_ext_attribs = value;
213 configureButtonsState();
214 }
215
setPaginationEnabled(bool value,bool hide_pag_toggler)216 void AttributesTogglerItem::setPaginationEnabled(bool value, bool hide_pag_toggler)
217 {
218 buttons[PaginationTogglerBtn]->setVisible(!hide_pag_toggler);
219 pagination_enabled = value;
220 configureButtons(this->boundingRect());
221 configureButtonsState();
222 }
223
setPaginationValues(unsigned section_id,unsigned curr_page,unsigned max_page)224 void AttributesTogglerItem::setPaginationValues(unsigned section_id, unsigned curr_page, unsigned max_page)
225 {
226 if(!pagination_enabled || section_id > BaseTable::ExtAttribsSection)
227 return;
228
229 if(curr_page > max_page)
230 current_page[section_id] = max_pages[section_id] = max_page;
231 else
232 {
233 current_page[section_id] = curr_page;
234 max_pages[section_id] = max_page;
235 }
236 }
237
clearButtonsSelection()238 void AttributesTogglerItem::clearButtonsSelection()
239 {
240 for(unsigned arr_id = 0; arr_id < 7; arr_id++)
241 btns_selected[arr_id] = false;
242
243 this->update();
244 }
245
getButtonsWidth()246 double AttributesTogglerItem::getButtonsWidth()
247 {
248 return btns_width;
249 }
250
getButtonsHeight()251 double AttributesTogglerItem::getButtonsHeight()
252 {
253 return btns_height;
254 }
255
configureButtons(const QRectF & rect)256 void AttributesTogglerItem::configureButtons(const QRectF &rect)
257 {
258 double arr_width = 0, px = 0,
259 h_spacing = 6 * BaseObjectView::HorizSpacing,
260 height = 4 * BaseObjectView::VertSpacing;
261 QRectF new_rect = rect;
262
263 btns_height = btn_polygons[PrevAttribsPageBtn].boundingRect().height();
264 height += btns_height;
265
266 if(pagination_enabled)
267 {
268 arr_width = btn_polygons[PrevAttribsPageBtn].boundingRect().width() +
269 btn_polygons[NextAttribsPageBtn].boundingRect().width() +
270 btn_polygons[PrevExtAttribsPageBtn].boundingRect().width() +
271 btn_polygons[NextExtAttribsPageBtn].boundingRect().width() +
272 (4 * h_spacing);
273 }
274
275 arr_width += btn_polygons[AttribsCollapseBtn].boundingRect().width() +
276 btn_polygons[AttribsExpandBtn].boundingRect().width() + (2 * h_spacing);
277
278 if(buttons[PaginationTogglerBtn]->isVisible())
279 arr_width += btn_polygons[AttribsExpandBtn].boundingRect().width() + h_spacing;
280
281 btns_width = arr_width;
282 new_rect.setHeight(height);
283 RoundedRectItem::setRect(new_rect);
284
285 px = (new_rect.width() - arr_width + h_spacing)/2;
286
287 if(buttons[PaginationTogglerBtn]->isVisible())
288 {
289 buttons[PaginationTogglerBtn]->setPos(px, (new_rect.height() - buttons[PaginationTogglerBtn]->boundingRect().height())/2);
290 px += buttons[PaginationTogglerBtn]->boundingRect().width() + h_spacing;
291
292 if(pagination_enabled)
293 {
294 buttons[PrevExtAttribsPageBtn]->setPos(px, (new_rect.height() - buttons[PrevExtAttribsPageBtn]->boundingRect().height())/2);
295 px += buttons[PrevExtAttribsPageBtn]->boundingRect().width() + h_spacing;
296
297 buttons[PrevAttribsPageBtn]->setPos(px, (new_rect.height() - buttons[PrevAttribsPageBtn]->boundingRect().height())/2);
298 px += buttons[PrevAttribsPageBtn]->boundingRect().width() + h_spacing;
299
300 buttons[NextAttribsPageBtn]->setPos(px, (new_rect.height() - buttons[NextAttribsPageBtn]->boundingRect().height())/2);
301 px += buttons[PrevExtAttribsPageBtn]->boundingRect().width() + h_spacing;
302
303 buttons[NextExtAttribsPageBtn]->setPos(px, (new_rect.height() - buttons[NextExtAttribsPageBtn]->boundingRect().height())/2);
304 px += buttons[NextExtAttribsPageBtn]->boundingRect().width() + h_spacing;
305 }
306 }
307
308 buttons[AttribsCollapseBtn]->setPos(px, (new_rect.height() - buttons[AttribsCollapseBtn]->boundingRect().height())/2);
309 px += buttons[AttribsCollapseBtn]->boundingRect().width() + h_spacing * 0.80;
310
311 buttons[AttribsExpandBtn]->setPos(px, (new_rect.height() - buttons[AttribsExpandBtn]->boundingRect().height())/2);
312 }
313
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)314 void AttributesTogglerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
315 {
316 QGraphicsItem *parent = this->parentItem();
317 RoundedRectItem::paint(painter, option, widget);
318
319 for(unsigned arr_id = 0; arr_id < 7; arr_id++)
320 {
321 if(!buttons[arr_id]->isVisible())
322 continue;
323
324 painter->save();
325 painter->translate(buttons[arr_id]->pos());
326 painter->setOpacity(buttons[arr_id]->opacity() * (parent ? parent->opacity() : 1));
327 buttons[arr_id]->paint(painter, option, widget);
328 painter->restore();
329
330 // Drawing the selection rectangle over the button if it isn't faded
331 if(btns_selected[arr_id] && buttons[arr_id]->opacity() > ButtonMinOpacity)
332 {
333 painter->save();
334 painter->translate(sel_rect->pos());
335 sel_rect->paint(painter, option, widget);
336 painter->restore();
337 }
338 }
339 }
340
createButtonPolygons()341 void AttributesTogglerItem::createButtonPolygons()
342 {
343 if(!btn_polygons[0].isEmpty())
344 return;
345
346 QPolygonF *pol = nullptr;
347 double fnt_factor = qApp->screens().at(qApp->desktop()->screenNumber(qApp->activeWindow()))->logicalDotsPerInch() / 96.0,
348 pixel_ratio = qApp->screens().at(qApp->desktop()->screenNumber(qApp->activeWindow()))->devicePixelRatio(),
349 factor = fnt_factor * pixel_ratio;
350
351 pol = &btn_polygons[PrevAttribsPageBtn];
352 pol->append(QPointF(0, 5 * factor));
353 pol->append(QPointF(8 * factor, 0));
354 pol->append(QPointF(8 * factor, 10 * factor));
355
356 pol = &btn_polygons[NextAttribsPageBtn];
357 pol->append(QPointF(0, 0));
358 pol->append(QPointF(8 * factor, 5 * factor));
359 pol->append(QPointF(0, 10 * factor));
360
361 pol = &btn_polygons[PrevExtAttribsPageBtn];
362 pol->append(QPointF(0, 0));
363 pol->append(QPointF(2 * factor, 0));
364 pol->append(QPointF(2 * factor, 4 * factor));
365 pol->append(QPointF(8 * factor, 0));
366 pol->append(QPointF(8 * factor, 10 * factor));
367 pol->append(QPointF(2 * factor, 6 * factor));
368 pol->append(QPointF(2 * factor, 10 * factor));
369 pol->append(QPointF(0, 10 * factor));
370
371 pol = &btn_polygons[NextExtAttribsPageBtn];
372 pol->append(QPointF(0, 0));
373 pol->append(QPointF(6 * factor, 4 * factor));
374 pol->append(QPointF(6 * factor, 0 * factor));
375 pol->append(QPointF(8 * factor, 0));
376 pol->append(QPointF(8 * factor, 10 * factor));
377 pol->append(QPointF(6 * factor, 10 * factor));
378 pol->append(QPointF(6 * factor, 6 * factor));
379 pol->append(QPointF(0, 10 * factor));
380
381 pol = &btn_polygons[AttribsCollapseBtn];
382 pol->append(QPointF(5 * factor, 0));
383 pol->append(QPointF(0, 8 * factor));
384 pol->append(QPointF(10 * factor, 8 * factor));
385
386 pol = &btn_polygons[AttribsExpandBtn];
387 pol->append(QPointF(0, 0));
388 pol->append(QPointF(10 * factor, 0));
389 pol->append(QPointF(5 * factor, 8 * factor));
390
391 pol = &btn_polygons[PaginationTogglerBtn];
392 pol->append(QPointF(4 * factor, 0));
393 pol->append(QPointF(8 * factor, 4 * factor));
394 pol->append(QPointF(4 * factor, 8 * factor));
395 pol->append(QPointF(0, 4 * factor));
396 }
397