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 "tableobjectview.h"
20 
21 const QString TableObjectView::TypeSeparator=QString(" ");
22 const QString TableObjectView::ConstrSeparator=QString(" ");
23 const QString TableObjectView::TextUnique=QString("uq");
24 const QString TableObjectView::TextExclude=QString("ex");
25 const QString TableObjectView::TextCheck=QString("ck");
26 const QString TableObjectView::TextPrimaryKey=QString("pk");
27 const QString TableObjectView::TextForeignKey=QString("fk");
28 const QString TableObjectView::TextNotNull=QString("nn");
29 const QString TableObjectView::ConstrDelimStart=QString("«");
30 const QString TableObjectView::ConstrDelimEnd=QString("»");
31 
TableObjectView(TableObject * object)32 TableObjectView::TableObjectView(TableObject *object) : BaseObjectView(object)
33 {
34 	descriptor=nullptr;
35 	fake_selection=false;
36 
37 	for(unsigned i=0; i < 3; i++)
38 		lables[i]=new QGraphicsSimpleTextItem;
39 
40 	if(obj_selection)
41 		delete obj_selection;
42 }
43 
~TableObjectView()44 TableObjectView::~TableObjectView()
45 {
46 	delete descriptor;
47 
48 	for(unsigned i=0; i < 3; i++)
49 		delete lables[i];
50 
51 	delete obj_selection;
52 }
53 
configureDescriptor(ConstraintType constr_type)54 void TableObjectView::configureDescriptor(ConstraintType constr_type)
55 {
56 	ObjectType obj_type=ObjectType::BaseObject;
57 	Column *column=dynamic_cast<Column *>(this->getUnderlyingObject());
58 	bool ellipse_desc=false;
59 	double factor=(font_config[Attributes::Global].font().pointSizeF()/DefaultFontSize) * BaseObjectView::getScreenDpiFactor();
60 	QPen pen;
61 
62 	//Based upon the source object type the descriptor is allocated
63 	if(this->getUnderlyingObject())
64 		obj_type=this->getUnderlyingObject()->getObjectType();
65 
66 	/* Elliptical descriptor is used to columns (with or without not-null constraint),
67 		for other object types, polygonal descriptor is usded */
68 	ellipse_desc=((column && constr_type==BaseType::Null) || (!TableObject::isTableObject(obj_type)));
69 
70 	if(descriptor && ((ellipse_desc && !dynamic_cast<QGraphicsEllipseItem *>(descriptor)) ||
71 										(!ellipse_desc && dynamic_cast<QGraphicsEllipseItem *>(descriptor))))
72 	{
73 		delete descriptor;
74 		descriptor=nullptr;
75 	}
76 
77 	if(!descriptor)
78 	{
79 		if(ellipse_desc)
80 			descriptor=new QGraphicsEllipseItem;
81 		else
82 			descriptor=new QGraphicsPolygonItem;
83 	}
84 
85 	if(column)
86 	{
87 		QString attrib;
88 		QPolygonF pol;
89 
90 		if(constr_type==BaseType::Null)
91 		{
92 			QGraphicsEllipseItem *desc=dynamic_cast<QGraphicsEllipseItem *>(descriptor);
93 
94 			desc->setRect(QRectF(QPointF(0,0), QSizeF(9.0 * factor, 9.0 * factor)));
95 
96 			if(column->isNotNull())
97 				attrib=Attributes::NnColumn;
98 			else
99 				attrib=Attributes::Column;
100 
101 			desc->setBrush(this->getFillStyle(attrib));
102 
103 			pen = this->getBorderStyle(attrib);
104 			pen.setWidthF(ObjectBorderWidth * 1.15);
105 			desc->setPen(pen);
106 		}
107 		else
108 		{
109 			QGraphicsPolygonItem *desc=dynamic_cast<QGraphicsPolygonItem *>(descriptor);
110 
111 			if(constr_type==ConstraintType::PrimaryKey)
112 			{
113 				attrib=Attributes::PkColumn;
114 				pol.append(QPointF(2,0)); pol.append(QPointF(0,2)); pol.append(QPointF(0,7));
115 				pol.append(QPointF(2,9)); pol.append(QPointF(3,8)); pol.append(QPointF(3,6));
116 				pol.append(QPointF(4,6)); pol.append(QPointF(5,7)); pol.append(QPointF(6,6));
117 				pol.append(QPointF(7,5)); pol.append(QPointF(9,7)); pol.append(QPointF(9,3));
118 				pol.append(QPointF(3,3)); pol.append(QPointF(3,1));
119 			}
120 			else if(constr_type==ConstraintType::ForeignKey)
121 			{
122 				attrib=Attributes::FkColumn;
123 				pol.append(QPointF(0,3)); pol.append(QPointF(0,6)); pol.append(QPointF(4,6));
124 				pol.append(QPointF(4,9)); pol.append(QPointF(5,9)); pol.append(QPointF(9,5));
125 				pol.append(QPointF(9,4)); pol.append(QPointF(5,0)); pol.append(QPointF(4,0));
126 				pol.append(QPointF(4,3));
127 			}
128 			else if(constr_type==ConstraintType::Unique)
129 			{
130 				attrib=Attributes::UqColumn;
131 				pol.append(QPointF(4,0)); pol.append(QPointF(0,4)); pol.append(QPointF(0,5));
132 				pol.append(QPointF(4,9)); pol.append(QPointF(5,9)); pol.append(QPointF(9,5));
133 				pol.append(QPointF(9,4)); pol.append(QPointF(5,0));
134 			}
135 
136 			if(factor!=1.0)
137 				TextPolygonItem::resizePolygon(pol, pol.boundingRect().width() * factor,
138 																						pol.boundingRect().height()  * factor);
139 
140 			desc->setPolygon(pol);
141 			desc->setBrush(this->getFillStyle(attrib));
142 
143 			pen = this->getBorderStyle(attrib);
144 			pen.setWidthF(ObjectBorderWidth * 1.15);
145 			desc->setPen(pen);
146 		}
147 	}
148 	else if(obj_type != ObjectType::BaseObject)
149 	{
150 		TableObject *tab_obj=dynamic_cast<TableObject *>(this->getUnderlyingObject());
151 		QGraphicsPolygonItem *desc=dynamic_cast<QGraphicsPolygonItem *>(descriptor);
152 		QPolygonF pol;
153 
154 		pol.append(QPointF(5,0)); pol.append(QPointF(0,5)); pol.append(QPointF(4,9));
155 		pol.append(QPointF(9,9)); pol.append(QPointF(9,4));
156 
157 		if(factor!=1.0)
158 			TextPolygonItem::resizePolygon(pol,	pol.boundingRect().width() * factor ,	pol.boundingRect().height() * factor);
159 
160 		desc->setPolygon(pol);
161 		desc->setBrush(this->getFillStyle(tab_obj->getSchemaName()));
162 
163 		pen = this->getBorderStyle(tab_obj->getSchemaName());
164 		pen.setWidthF(ObjectBorderWidth * 1.15);
165 		desc->setPen(pen);
166 	}
167 	else
168 	{
169 		QGraphicsEllipseItem *desc=dynamic_cast<QGraphicsEllipseItem *>(descriptor);
170 
171 		desc->setRect(QRectF(QPointF(0,0), QSizeF(9.0 * factor, 9.0 * factor)));
172 		desc->setBrush(this->getFillStyle(Attributes::Reference));
173 
174 		pen = this->getBorderStyle(Attributes::Reference);
175 		pen.setWidthF(ObjectBorderWidth * 1.15);
176 		desc->setPen(pen);
177 	}
178 }
179 
configureObject()180 void TableObjectView::configureObject()
181 {
182 	if(this->getUnderlyingObject())
183 	{
184 		QTextCharFormat fmt;
185 		double px = 0;
186 		QString str_constr, tooltip, atribs_tip;
187 		TableObject *tab_obj=dynamic_cast<TableObject *>(this->getUnderlyingObject());
188 		Column *column=dynamic_cast<Column *>(tab_obj);
189 		ConstraintType constr_type=ConstraintType::Null;
190 		bool sql_disabled=false;
191 
192 		tooltip=tab_obj->getName() + QString(" (") + tab_obj->getTypeName() + QString(")");
193 		tooltip+=QString("\nId: %1").arg(tab_obj->getObjectId());
194 		sql_disabled=tab_obj->isSQLDisabled();
195 		fake_selection=false;
196 
197 		if(column)
198 		{
199 			if(column->isAddedByRelationship())
200 				tooltip+=tr("\nRelationship: %1").arg(column->getParentRelationship()->getName());
201 
202 			str_constr=this->getConstraintString(column);
203 
204 			if(str_constr.indexOf(TextPrimaryKey)>=0)
205 			{
206 				fmt=font_config[Attributes::PkColumn];
207 				constr_type=ConstraintType::PrimaryKey;
208 			}
209 			else if(str_constr.indexOf(TextForeignKey)>=0)
210 			{
211 				fmt=font_config[Attributes::FkColumn];
212 				constr_type=ConstraintType::ForeignKey;
213 			}
214 			else if(str_constr.indexOf(TextUnique)>=0)
215 			{
216 				fmt=font_config[Attributes::UqColumn];
217 				constr_type=ConstraintType::Unique;
218 			}
219 			else if(str_constr.indexOf(TextNotNull)>=0)
220 				fmt=font_config[Attributes::NnColumn];
221 			else
222 				fmt=font_config[Attributes::Column];
223 
224 			if(column->isAddedByRelationship())
225 				fmt=font_config[Attributes::InhColumn];
226 			else if(column->isProtected())
227 				fmt=font_config[Attributes::ProtColumn];
228 
229 			if(str_constr.indexOf(TextPrimaryKey)>=0)
230 				atribs_tip+=(~ConstraintType(ConstraintType::PrimaryKey)).toLower() + QString(", ");
231 
232 			if(str_constr.indexOf(TextForeignKey)>=0)
233 				atribs_tip+=(~ConstraintType(ConstraintType::ForeignKey)).toLower() + QString(", ");
234 
235 			if(str_constr.indexOf(TextUnique)>=0)
236 				atribs_tip+=(~ConstraintType(ConstraintType::Unique)).toLower() + QString(", ");
237 
238 			if(str_constr.indexOf(TextExclude)>=0)
239 				atribs_tip+=(~ConstraintType(ConstraintType::Exclude)).toLower() + QString(", ");
240 
241 			if(str_constr.indexOf(TextNotNull)>=0)
242 				atribs_tip+=QString("not null");
243 		}
244 		else
245 		{
246 			if(tab_obj->isAddedByRelationship())
247 				fmt=font_config[Attributes::InhColumn];
248 			else if(tab_obj->isProtected())
249 				fmt=font_config[Attributes::ProtColumn];
250 			else
251 				fmt=font_config[tab_obj->getSchemaName()];
252 		}
253 
254 		configureDescriptor(constr_type);
255 
256 		descriptor->setPos(HorizSpacing, 0);
257 		px=HorizSpacing + descriptor->boundingRect().width() + (2 * HorizSpacing);
258 
259 		//Configuring the labels as follow: [object name] [type] [constraints]
260 		lables[0]->setText(compact_view && !tab_obj->getAlias().isEmpty() ? tab_obj->getAlias() : tab_obj->getName());
261 
262 		//Strikeout the column name when its SQL is disabled
263 		QFont font=fmt.font();
264 		font.setStrikeOut(sql_disabled);
265 		fmt.setFont(font);
266 
267 		lables[0]->setFont(fmt.font());
268 		lables[0]->setBrush(fmt.foreground());
269 		lables[0]->setPos(px, 0);
270 		px+=lables[0]->boundingRect().width();
271 
272 		//Configuring the type label
273 		fmt=font_config[Attributes::ObjectType];
274 
275 		if(compact_view)
276 			lables[1]->setText("");
277 		else
278 		{
279 			if(column)
280 				lables[1]->setText(TypeSeparator + (*column->getType()));
281 			else
282 				lables[1]->setText(TypeSeparator + tab_obj->getSchemaName());
283 		}
284 
285 		lables[1]->setFont(fmt.font());
286 		lables[1]->setBrush(fmt.foreground());
287 		lables[1]->setPos(px, 0);
288 		px+=lables[1]->boundingRect().width() + (3 * HorizSpacing);
289 
290 		//Configuring the constraints label
291 		fmt=font_config[Attributes::Constraints];
292 		if(compact_view)
293 			lables[2]->setText("");
294 		else if(column)
295 			lables[2]->setText(!str_constr.isEmpty() ? str_constr : QString(" "));
296 		else
297 		{
298 			Rule *rule=dynamic_cast<Rule *>(tab_obj);
299 			Trigger *trigger=dynamic_cast<Trigger *>(tab_obj);
300 			Index *index=dynamic_cast<Index *>(tab_obj);
301 			Constraint *constr=dynamic_cast<Constraint *>(tab_obj);
302 			Policy *policy = dynamic_cast<Policy *>(tab_obj);
303 
304 			if(rule)
305 			{
306 				str_constr+=(~rule->getExecutionType()).mid(0,1);
307 				atribs_tip+=(~rule->getExecutionType()).toLower() + QString(", ");
308 
309 				str_constr+=ConstrSeparator;
310 
311 				str_constr+=(~rule->getEventType()).mid(3,1);
312 				atribs_tip+=(~rule->getEventType()).toLower();
313 				str_constr=str_constr.toLower();
314 			}
315 			else if(trigger)
316 			{
317 				str_constr+=(~trigger->getFiringType()).mid(0,1);
318 				str_constr+=ConstrSeparator;
319 
320 				atribs_tip+=(~trigger->getFiringType()).toLower() + QString(", ");
321 
322 				for(unsigned i=EventType::OnInsert; i <= EventType::OnTruncate; i++)
323 				{
324 					if(trigger->isExecuteOnEvent(EventType(i)))
325 					{
326 						str_constr+=(~EventType(i)).mid(3,1);
327 						atribs_tip+=(~EventType(i)).toLower() + QString(", ");
328 					}
329 				}
330 				str_constr=str_constr.toLower();
331 			}
332 			else if(index)
333 			{
334 				if(index->getIndexAttribute(Index::Unique))
335 				{
336 					str_constr+=QString("u");
337 					atribs_tip += QString("unique") + QString(", ");
338 				}
339 
340 				if(index->getIndexAttribute(Index::Concurrent))
341 				{
342 					str_constr+=QString("c");
343 					atribs_tip += QString("concurrent") + QString(", ");
344 				}
345 
346 				if(index->getIndexAttribute(Index::FastUpdate))
347 				{
348 					str_constr+=QString("f");
349 					atribs_tip += QString("fast updated");
350 				}
351 
352 				if(index->getIndexAttribute(Index::Buffering))
353 				{
354 					str_constr+=QString("b");
355 					atribs_tip += QString("buffering");
356 				}
357 			}
358 			else if(constr)
359 			{
360 				ConstraintType type = constr->getConstraintType();
361 
362 				if(type == ConstraintType::PrimaryKey)
363 					str_constr = TextPrimaryKey;
364 				else if(type == ConstraintType::ForeignKey)
365 					str_constr = TextForeignKey;
366 				else if(type == ConstraintType::Unique)
367 					str_constr = TextUnique;
368 				else if(type == ConstraintType::Exclude)
369 					str_constr = TextExclude;
370 				else if(type == ConstraintType::Check)
371 					str_constr = TextCheck;
372 
373 				atribs_tip = (~type).toLower();
374 			}
375 			else if(policy)
376 			{
377 				if(policy->isPermissive())
378 				{
379 					str_constr += QString("p");
380 					atribs_tip += QString("permissive");
381 				}
382 				else
383 				{
384 					str_constr += QString("r");
385 					atribs_tip += QString("restrictive");
386 				}
387 
388 				atribs_tip += QString(", ");
389 				str_constr += (~policy->getPolicyCommand()).toLower().at(0);
390 				atribs_tip += (~policy->getPolicyCommand()).toLower();
391 			}
392 
393 			if(!str_constr.isEmpty())
394 				lables[2]->setText(ConstrDelimStart + QString(" ") +
395 								   str_constr + QString(" ") +
396 								   ConstrDelimEnd);
397 			else
398 				lables[2]->setText("");
399 		}
400 
401 		if(!atribs_tip.isEmpty())
402 		{
403 			if(atribs_tip.at(atribs_tip.length()-1)==' ')
404 				atribs_tip.remove(atribs_tip.length()-2, 2);
405 
406 			atribs_tip=QString("\n") + ConstrDelimStart +
407 								 QString(" ") + atribs_tip + QString(" ") + ConstrDelimEnd;
408 
409 		}
410 
411 		if(!tab_obj->getComment().isEmpty())
412 			atribs_tip += QString("\n---\n%1").arg(tab_obj->getComment());
413 
414 		lables[2]->setFont(fmt.font());
415 		lables[2]->setBrush(fmt.foreground());
416 		lables[2]->setPos(px, 0);
417 
418 		calculateBoundingRect();
419 		this->setToolTip(tooltip + atribs_tip);
420 	}
421 }
422 
configureObject(Reference reference)423 void TableObjectView::configureObject(Reference reference)
424 {
425 	QTextCharFormat fmt;
426 	double px;
427 	QString str_aux;
428 
429 	configureDescriptor();
430 	descriptor->setPos(HorizSpacing, 0);
431 	px=descriptor->pos().x() + descriptor->boundingRect().width() + (2 * HorizSpacing);
432 
433 	if(reference.getReferenceType()==Reference::ReferColumn)
434 	{
435 		//Configures the name label as: [table].[column]
436 		fmt=font_config[Attributes::RefTable];
437 
438 		if(compact_view && !reference.getReferenceAlias().isEmpty())
439 			lables[0]->setText(reference.getReferenceAlias());
440 		else
441 			lables[0]->setText(reference.getTable()->getName() + ".");
442 
443 		lables[0]->setFont(fmt.font());
444 		lables[0]->setBrush(fmt.foreground());
445 		lables[0]->setPos(px, 0);
446 		px+=lables[0]->boundingRect().width();
447 
448 		fmt=font_config[Attributes::RefColumn];
449 		if(compact_view && !reference.getReferenceAlias().isEmpty())
450 			lables[1]->setText("");
451 		else
452 		{
453 			if(reference.getColumn())
454 				lables[1]->setText(reference.getColumn()->getName());
455 			else
456 				lables[1]->setText("*");
457 		}
458 
459 		lables[1]->setFont(fmt.font());
460 		lables[1]->setBrush(fmt.foreground());
461 		lables[1]->setPos(px, 0);
462 		px+=lables[1]->boundingRect().width();
463 	}
464 	else
465 	{
466 		fmt=font_config[Attributes::RefTable];
467 		str_aux = compact_view && !reference.getReferenceAlias().isEmpty() ? reference.getReferenceAlias() : "";
468 
469 		if(str_aux.isEmpty())
470 		{
471 			str_aux=reference.getExpression().simplified().mid(0,25);
472 			if(reference.getExpression().size() > 25) str_aux+=QString("...");
473 			str_aux.replace(QString("\n"), QString(" "));
474 		}
475 
476 		lables[0]->setText(str_aux);
477 		lables[0]->setFont(fmt.font());
478 		lables[0]->setBrush(fmt.foreground());
479 		lables[1]->setText("");
480 		lables[0]->setPos(px, 0);
481 		px+=lables[0]->boundingRect().width();
482 	}
483 
484 	//Configures a label for the alias (if there is one)
485 	if(!compact_view &&
486 		 ((reference.getColumn() && !reference.getColumnAlias().isEmpty()) ||
487 			(!reference.getAlias().isEmpty() && reference.getReferenceType()==Reference::ReferExpression)))
488 	{
489 		if(reference.getReferenceType()==Reference::ReferExpression)
490 			str_aux=reference.getAlias();
491 		else
492 			str_aux=reference.getColumnAlias();
493 
494 		str_aux=QString(" (") + str_aux + QString(") ");
495 		fmt=font_config[Attributes::Alias];
496 		lables[2]->setText(str_aux);
497 		lables[2]->setFont(fmt.font());
498 		lables[2]->setBrush(fmt.foreground());
499 		lables[2]->setPos(px, 0);
500 	}
501 	else
502 		lables[2]->setText("");
503 
504 	calculateBoundingRect();
505 }
506 
configureObject(const SimpleColumn & col)507 void TableObjectView::configureObject(const SimpleColumn &col)
508 {
509 	QTextCharFormat fmt;
510 	double px;
511 
512 	configureDescriptor();
513 	descriptor->setPos(HorizSpacing, 0);
514 	px=descriptor->pos().x() + descriptor->boundingRect().width() + (2 * HorizSpacing);
515 
516 	fmt = font_config[Attributes::Column];
517 
518 	if(compact_view && !col.alias.isEmpty())
519 		lables[0]->setText(col.alias);
520 	else
521 		lables[0]->setText(col.name);
522 
523 	lables[0]->setFont(fmt.font());
524 	lables[0]->setBrush(fmt.foreground());
525 	lables[0]->setPos(px, 0);
526 	px+=lables[0]->boundingRect().width() + (4 * HorizSpacing);
527 
528 	if(!compact_view && !col.type.isEmpty())
529 	{
530 		fmt=font_config[Attributes::ObjectType];
531 		lables[1]->setText(col.type);
532 		lables[1]->setFont(fmt.font());
533 		lables[1]->setBrush(fmt.foreground());
534 		lables[1]->setPos(px, 0);
535 		px+=lables[1]->boundingRect().width() + (4 * HorizSpacing);
536 	}
537 	else
538 		lables[1]->setText("");
539 
540 	lables[2]->setText("");
541 	calculateBoundingRect();
542 }
543 
setChildObjectXPos(unsigned obj_idx,double px)544 void TableObjectView::setChildObjectXPos(unsigned obj_idx, double px)
545 {
546 	if(obj_idx >= 4)
547 		throw Exception(ErrorCode::RefObjectInvalidIndex, __PRETTY_FUNCTION__, __FILE__, __LINE__);
548 
549 	if(obj_idx==0)
550 		descriptor->setPos(px, descriptor->pos().y());
551 	else
552 		lables[obj_idx-1]->setPos(px, lables[obj_idx-1]->pos().y());
553 
554 	calculateBoundingRect();
555 }
556 
calculateBoundingRect()557 void TableObjectView::calculateBoundingRect()
558 {
559 	double width = 0, height = 0, curr_w = 0, py = 0;
560 
561 	width = descriptor->pos().x() + descriptor->boundingRect().width();
562 	height = lables[0]->boundingRect().height();
563 
564 	for(int i = 0; i < 3; i++)
565 	{
566 		if(lables[i]->text().isEmpty())
567 			continue;
568 
569 		curr_w = lables[i]->pos().x() + lables[i]->boundingRect().width();
570 
571 		if(width < curr_w)
572 			width = lables[i]->pos().x() + lables[i]->boundingRect().width();
573 	}
574 
575 	bounding_rect = QRectF(QPointF(0,0), QSizeF(width + (4 * HorizSpacing), height + VertSpacing * 0.80));
576 
577 	//Adjusting the Y position of the objects in order to center them on the new bouding rect
578 	descriptor->setPos(descriptor->pos().x(),
579 										 (bounding_rect.height() - descriptor->boundingRect().height() + (VertSpacing * 0.4))/2);
580 
581 	py = (bounding_rect.height() - lables[0]->boundingRect().height())/2;
582 
583 	for(unsigned i = 0; i < 3; i++)
584 		lables[i]->setPos(lables[i]->pos().x(), py);
585 }
586 
getChildObject(unsigned obj_idx)587 QGraphicsItem *TableObjectView::getChildObject(unsigned obj_idx)
588 {
589 	if(obj_idx > ConstrAliasLabel)
590 		throw Exception(ErrorCode::RefObjectInvalidIndex, __PRETTY_FUNCTION__, __FILE__, __LINE__);
591 
592 	if(obj_idx == ObjDescriptor)
593 		return descriptor;
594 	else
595 		return lables[obj_idx - 1];
596 }
597 
getConstraintString(Column * column)598 QString TableObjectView::getConstraintString(Column *column)
599 {
600 	if(column && column->getParentTable())
601 	{
602 		PhysicalTable *table=dynamic_cast<PhysicalTable *>(column->getParentTable());
603 		QString str_constr;
604 		Constraint *constr=nullptr;
605 		vector<TableObject *>::iterator itr,itr_end;
606 		ConstraintType constr_type;
607 
608 		itr=table->getObjectList(ObjectType::Constraint)->begin();
609 		itr_end=table->getObjectList(ObjectType::Constraint)->end();
610 
611 		while(itr!=itr_end)
612 		{
613 			constr=dynamic_cast<Constraint *>(*itr);
614 			itr++;
615 
616 			//Check if the column is referecend by the constraint
617 			if((constr->getConstraintType()!=ConstraintType::Exclude && constr->isColumnExists(column, Constraint::SourceCols)) ||
618 				 (constr->getConstraintType()==ConstraintType::Exclude && constr->isColumnReferenced(column, false)))
619 			{
620 				constr_type=constr->getConstraintType();
621 
622 				if(constr_type==ConstraintType::PrimaryKey)
623 					str_constr=TextPrimaryKey + ConstrSeparator + str_constr;
624 
625 				if(constr_type==ConstraintType::ForeignKey && str_constr.indexOf(TextForeignKey) < 0)
626 					str_constr+=TextForeignKey + ConstrSeparator;
627 
628 				if(constr_type==ConstraintType::Unique && str_constr.indexOf(TextUnique) < 0)
629 					str_constr+=TextUnique + ConstrSeparator;
630 
631 				if(constr_type==ConstraintType::Exclude && str_constr.indexOf(TextExclude) < 0)
632 					str_constr+=TextExclude + ConstrSeparator;
633 			}
634 		}
635 
636 		if(column->isNotNull() && !str_constr.contains(TextPrimaryKey))
637 			str_constr+=TextNotNull + ConstrSeparator;
638 
639 		if(!str_constr.isEmpty())
640 			str_constr= ConstrDelimStart + ConstrSeparator + str_constr + ConstrDelimEnd;
641 
642 		return str_constr;
643 	}
644 	else return "";
645 }
646 
setFakeSelection(bool value)647 void TableObjectView::setFakeSelection(bool value)
648 {
649 	// Fake selection is used only by instances that own and underlying object (column, constratin, trigger,etc)
650 	if(!this->getUnderlyingObject())
651 		return;
652 
653 	fake_selection = value;
654 
655 	if(value)
656 	{
657 		configureObjectSelection();
658 		sel_order=++BaseObjectView::global_sel_order;
659 	}
660 	else
661 		sel_order = 0;
662 
663 	update();
664 }
665 
hasFakeSelection()666 bool TableObjectView::hasFakeSelection()
667 {
668 	return fake_selection;
669 }
670 
configureObjectSelection()671 void TableObjectView::configureObjectSelection()
672 {
673 	QGraphicsItem *parent = this->parentItem();
674 	RoundedRectItem *rect_item=nullptr;
675 	QRectF rect = this->boundingRect();
676 
677 	/* In order to avoid unnecessary memory usage by items that eventually will
678 	 * get selection we allocate the object selection rectangle only if the object
679 	 * itself is selected by the user, and it'll be allocated until the object's destruction */
680 	if(!obj_selection)
681 		obj_selection=new RoundedRectItem;
682 
683 	rect_item = dynamic_cast<RoundedRectItem *>(obj_selection);
684 	rect.setX(0);
685 	rect.setY(0);
686 	rect.setHeight(rect.height() - VertSpacing);
687 
688 	// An small hack to capture the width of the table in which the item is child of
689 	if(parent->parentItem())
690 		rect.setWidth(parent->parentItem()->boundingRect().width() - (2.5 * HorizSpacing));
691 	else
692 		rect.setWidth(rect.width() - (3.5 * HorizSpacing));
693 
694 	rect_item->setBorderRadius(2);
695 	rect_item->setRect(rect);
696 	rect_item->setPos(0, VertSpacing/2);
697 	rect_item->setBrush(this->getFillStyle(Attributes::ObjSelection));
698 	rect_item->setPen(this->getBorderStyle(Attributes::ObjSelection));
699 }
700 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)701 void TableObjectView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
702 {
703 	painter->save();
704 	painter->translate(descriptor->pos());
705 	descriptor->paint(painter, option, widget);
706 	painter->restore();
707 
708 	for(int i = 0 ; i < 3; i++)
709 	{
710 		if(lables[i]->text().isEmpty())
711 			continue;
712 
713 		painter->save();
714 		painter->translate(lables[i]->pos());
715 		lables[i]->paint(painter, option, widget);
716 		painter->restore();
717 	}
718 
719 	if(fake_selection)
720 	{
721 		painter->translate(obj_selection->pos());
722 		obj_selection->paint(painter, option, widget);
723 	}
724 }
725 
boundingRect() const726 QRectF TableObjectView::boundingRect() const
727 {
728 	return bounding_rect;
729 }
730 
731