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 "graphicalview.h"
20
GraphicalView(View * view)21 GraphicalView::GraphicalView(View *view) : BaseTableView(view)
22 {
23 connect(view, SIGNAL(s_objectModified()), this, SLOT(configureObject()));
24
25 columns=new QGraphicsItemGroup;
26 columns->setZValue(1);
27 this->addToGroup(columns);
28 configurePlaceholder();
29 this->configureObject();
30 }
31
configureObject()32 void GraphicalView::configureObject()
33 {
34 /* If the table isn't visible we abort the current configuration
35 * and mark its geometry update as pending so in the next call to
36 * setVisible(true) the geometry can be updated (see BaseObjectView::itemChange()) */
37 if(!this->isVisible())
38 {
39 pending_geom_update = true;
40 return;
41 }
42
43 View *view=dynamic_cast<View *>(this->getUnderlyingObject());
44 int i = 0, count = 0;
45 unsigned start_col = 0, end_col = 0, start_ext = 0, end_ext = 0;
46 QPen pen;
47 TableObjectView *graph_ref=nullptr;
48 QList<QGraphicsItem *> subitems;
49 vector<TableObject *> tab_objs, ext_tab_objs;
50 vector<SimpleColumn> view_cols;
51 QGraphicsItemGroup *groups[]={ columns, ext_attribs };
52 RoundedRectItem *bodies[]={ body, ext_attribs_body };
53 QString attribs[]={ Attributes::ViewBody, Attributes::ViewExtBody },
54 tag_attribs[]={ Attributes::TableBody, Attributes::TableExtBody };
55 double width, type_width=0, px=0;
56 TableObjectView *col_item=nullptr;
57 QList<TableObjectView *> col_items;
58 TableObject *tab_obj=nullptr;
59 Tag *tag=view->getTag();
60 CollapseMode collapse_mode = view->getCollapseMode();
61 bool has_col_pag = false, has_ext_pag = false;
62
63 // Clear the selected children objects vector since we'll (re)configure the whole view
64 sel_child_objs.clear();
65
66 //Configures the view's title
67 title->configureObject(view);
68
69 for(auto &obj : view->getObjects())
70 ext_tab_objs.push_back(dynamic_cast<TableObject *>(obj));
71
72 attribs_toggler->setHasExtAttributes(!hide_ext_attribs && !ext_tab_objs.empty());
73
74 view_cols = view->getColumns();
75 has_col_pag = configurePaginationParams(BaseTable::AttribsSection, view_cols.size(), start_col, end_col);
76 has_ext_pag = configurePaginationParams(BaseTable::ExtAttribsSection,
77 collapse_mode != CollapseMode::ExtAttribsCollapsed ? ext_tab_objs.size() : 0,
78 start_ext, end_ext);
79
80 //Moves the references group to the origin to be moved latter
81 columns->moveBy(-columns->scenePos().x(), -columns->scenePos().y());
82 columns->setVisible(view->getCollapseMode() != CollapseMode::AllAttribsCollapsed && start_col < static_cast<unsigned>(view_cols.size()));
83 body->setVisible(columns->isVisible());
84
85 if(!columns->isVisible())
86 {
87 for(auto &item : columns->childItems())
88 {
89 columns->removeFromGroup(item);
90 delete item;
91 }
92 }
93 else
94 {
95 vector<SimpleColumn> aux_view_cols;
96
97 if(has_col_pag)
98 aux_view_cols.assign(view_cols.begin() + start_col, view_cols.begin() + end_col);
99 else
100 aux_view_cols = view_cols;
101
102 count = aux_view_cols.size();
103 subitems=columns->childItems();
104
105 for(i=0; i < count; i++)
106 {
107 //Reuses the subitem if it was allocated before
108 if(!subitems.isEmpty() && i < subitems.size())
109 {
110 graph_ref=dynamic_cast<TableObjectView *>(subitems[i]);
111
112 //Moves the reference to the origin to be moved latter
113 graph_ref->moveBy(-graph_ref->scenePos().x(),
114 -graph_ref->scenePos().y());
115 }
116 else
117 graph_ref=new TableObjectView;
118
119 graph_ref->configureObject(aux_view_cols[i]);
120 graph_ref->moveBy(HorizSpacing, (i * graph_ref->boundingRect().height()) + VertSpacing);
121
122 /* Calculates the width of the name + type of the object. This is used to align all
123 the constraint labels on table */
124 width=graph_ref->getChildObject(TableObjectView::ObjDescriptor)->boundingRect().width() +
125 graph_ref->getChildObject(TableObjectView::NameLabel)->boundingRect().width() + (8 * HorizSpacing);
126 if(px < width) px=width;
127
128 //Gets the maximum width of the column type label to align all at same horizontal position
129 if(type_width < graph_ref->getChildObject(TableObjectView::TypeLabel)->boundingRect().width())
130 type_width=graph_ref->getChildObject(TableObjectView::TypeLabel)->boundingRect().width() + (3 * HorizSpacing);
131
132 col_items.push_back(graph_ref);
133 }
134
135 //Destroy the graphical references not used
136 i=subitems.size()-1;
137 while(i > count-1)
138 {
139 graph_ref=dynamic_cast<TableObjectView *>(subitems[i]);
140 columns->removeFromGroup(graph_ref);
141 delete graph_ref;
142 i--;
143 }
144
145 //Set all items position
146 while(!col_items.isEmpty())
147 {
148 col_item=dynamic_cast<TableObjectView *>(col_items.front());
149 columns->removeFromGroup(col_item);
150 col_items.pop_front();
151
152 //Positioning the type label
153 col_item->setChildObjectXPos(TableObjectView::TypeLabel, px);
154
155 //Positioning the constraints label
156 col_item->setChildObjectXPos(TableObjectView::ConstrAliasLabel, px + type_width);
157 columns->addToGroup(col_item);
158 }
159 }
160
161 if(!hide_ext_attribs && view->getCollapseMode() == CollapseMode::NotCollapsed)
162 {
163 if(view->isPaginationEnabled() && has_ext_pag)
164 tab_objs.assign(ext_tab_objs.begin() + start_ext, ext_tab_objs.begin() + end_ext);
165 else
166 tab_objs.assign(ext_tab_objs.begin(), ext_tab_objs.end());
167 }
168
169 ext_attribs->setVisible(!tab_objs.empty() && view->getCollapseMode() == CollapseMode::NotCollapsed);
170 ext_attribs_body->setVisible(ext_attribs->isVisible());
171
172 if(tab_objs.empty())
173 {
174 for(auto &item : ext_attribs->childItems())
175 {
176 ext_attribs->removeFromGroup(item);
177 delete item;
178 }
179 }
180 else
181 {
182 count=tab_objs.size();
183
184 //Gets the subitems of the current group
185 subitems=ext_attribs->childItems();
186 ext_attribs->moveBy(-ext_attribs->scenePos().x(), -ext_attribs->scenePos().y());
187 for(i=0; i < count; i++)
188 {
189 tab_obj=tab_objs.at(i);
190
191 //Reusing the subitem if it was allocated before
192 if(!subitems.isEmpty() && i < subitems.size())
193 {
194 col_item=dynamic_cast<TableObjectView *>(subitems[i]);
195 col_item->setSourceObject(tab_obj);
196 col_item->configureObject();
197 col_item->moveBy(-col_item->scenePos().x(),
198 -col_item->scenePos().y());
199 }
200 else
201 col_item=new TableObjectView(tab_obj);
202
203 //Configures the item and set its position
204 col_item->configureObject();
205 col_item->moveBy(HorizSpacing, (i * col_item->boundingRect().height()) + VertSpacing);
206
207 /* Calculates the width of the name + type of the object. This is used to align all
208 the constraint labels on table */
209 width=col_item->getChildObject(TableObjectView::ObjDescriptor)->boundingRect().width() +
210 col_item->getChildObject(TableObjectView::NameLabel)->boundingRect().width() + (3 * HorizSpacing);
211 if(px < width) px=width;
212
213 //Gets the maximum width of the column type label to align all at same horizontal position
214 if(type_width < col_item->getChildObject(TableObjectView::TypeLabel)->boundingRect().width())
215 type_width=col_item->getChildObject(TableObjectView::TypeLabel)->boundingRect().width() + (3 * HorizSpacing);
216
217 col_items.push_back(col_item);
218 }
219
220 //Destroy the unused items
221 i=subitems.size()-1;
222 while(i > count-1)
223 {
224 col_item=dynamic_cast<TableObjectView *>(subitems[i]);
225 ext_attribs->removeFromGroup(col_item);
226 delete col_item;
227 i--;
228 }
229
230 //Set all items position
231 while(!col_items.isEmpty())
232 {
233 col_item=dynamic_cast<TableObjectView *>(col_items.front());
234 ext_attribs->removeFromGroup(col_item);
235 col_items.pop_front();
236
237 //Positioning the type label
238 col_item->setChildObjectXPos(TableObjectView::TypeLabel, px);
239
240 //Positioning the constraints label
241 col_item->setChildObjectXPos(TableObjectView::ConstrAliasLabel, px + type_width);
242 ext_attribs->addToGroup(col_item);
243 }
244 }
245
246 width = calculateWidth();
247
248 //Resizes the title using the new width
249 title->resizeTitle(width, title->boundingRect().height());
250
251 //Resizes the columns/extended attributes using the new width
252 for(int idx=0; idx < 2; idx++)
253 {
254 /* Configuring the brush and pen of the bodies even if they aren't visible
255 * the attributes toggler at the bottom of the view uses the color of the attributes body
256 * this will avoid the creation of a transparent toggler */
257 if(!tag)
258 {
259 bodies[idx]->setBrush(this->getFillStyle(attribs[idx]));
260 pen=this->getBorderStyle(attribs[idx]);
261 }
262 else
263 {
264 bodies[idx]->setBrush(tag->getFillStyle(tag_attribs[idx]));
265 pen.setColor(tag->getElementColor(tag_attribs[idx], Tag::BorderColor));
266 }
267
268 pen.setStyle(Qt::DashLine);
269 bodies[idx]->setPen(pen);
270
271 // We avoid the construction of the rect related to the current body item if the related group isn't visible
272 if(!groups[idx]->isVisible())
273 continue;
274
275 bodies[idx]->setRect(QRectF(0,0, width, groups[idx]->boundingRect().height() + (2 * VertSpacing)));
276
277 if(idx==0)
278 bodies[idx]->setPos(title->pos().x(), title->boundingRect().height() - 1);
279 else
280 {
281 if(bodies[0]->isVisible())
282 bodies[idx]->setPos(title->pos().x(),
283 title->boundingRect().height() +
284 bodies[0]->boundingRect().height() - 2);
285 else
286 bodies[idx]->setPos(title->pos().x(), title->boundingRect().height()-1);
287 }
288
289 groups[idx]->setPos(bodies[idx]->pos());
290
291 subitems=groups[idx]->childItems();
292 while(!subitems.isEmpty())
293 {
294 col_item=dynamic_cast<TableObjectView *>(subitems.front());
295 subitems.pop_front();
296 col_item->setChildObjectXPos(TableObjectView::ConstrAliasLabel,
297 width - col_item->getChildObject(3)->boundingRect().width() - (2 * HorizSpacing));
298 }
299 }
300
301 this->bounding_rect.setTopLeft(title->boundingRect().topLeft());
302 this->bounding_rect.setWidth(title->boundingRect().width());
303
304 BaseTableView::__configureObject(width);
305
306 if(!view->getAlias().isEmpty())
307 table_tooltip += QString("\nAlias: %1").arg(view->getAlias());
308
309 if(!view->getComment().isEmpty())
310 table_tooltip += QString("\n---\n%1").arg(view->getComment());
311
312 BaseObjectView::__configureObject();
313 BaseObjectView::configureObjectShadow();
314 BaseObjectView::configureObjectSelection();
315 configureTag();
316 configureSQLDisabledInfo();
317 requestRelationshipsUpdate();
318 }
319
320