1 #include "swapobjectsidswidget.h"
2 #include "pgmodeleruins.h"
3 
4 const QString SwapObjectsIdsWidget::IdLabel("ID: <strong>%1</strong>");
5 
SwapObjectsIdsWidget(QWidget * parent,Qt::WindowFlags f)6 SwapObjectsIdsWidget::SwapObjectsIdsWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f)
7 {
8 	try
9 	{
10 		QGridLayout *swap_objs_grid=new QGridLayout(this);
11 		vector<ObjectType> types=BaseObject::getObjectTypes(true, {ObjectType::Permission,
12 																															 ObjectType::Role, ObjectType::Textbox,
13 																															 ObjectType::Column, ObjectType::Constraint });
14 		setupUi(this);
15 
16 		PgModelerUiNs::configureWidgetFont(message_lbl, PgModelerUiNs::MediumFontFactor);
17 
18 		selector_idx = 0;
19 		src_object_sel=nullptr;
20 		dst_object_sel=nullptr;
21 
22 		src_object_sel=new ObjectSelectorWidget(types, true, this);
23 		src_object_sel->enableObjectCreation(false);
24 
25 		dst_object_sel=new ObjectSelectorWidget(types, true, this);
26 		dst_object_sel->enableObjectCreation(false);
27 
28 		swap_objs_grid->setContentsMargins(4,4,4,4);
29 		swap_objs_grid->setSpacing(6);
30 
31 		swap_objs_grid->addWidget(create_lbl, 0, 0);
32 		swap_objs_grid->addWidget(src_object_sel, 0, 1);
33 		swap_objs_grid->addWidget(swap_values_tb, 0, 2, 2, 1);
34 		swap_objs_grid->addWidget(src_id_lbl, 0, 3);
35 		swap_objs_grid->addWidget(src_ico_lbl, 0, 4);
36 
37 		swap_objs_grid->addWidget(before_lbl, 1, 0);
38 		swap_objs_grid->addWidget(dst_object_sel, 1, 1);
39 		swap_objs_grid->addWidget(dst_id_lbl, 1, 3);
40 		swap_objs_grid->addWidget(dst_ico_lbl, 1, 4);
41 
42 		swap_objs_grid->addWidget(filter_btn, 2, 0, 1, 1);
43 		swap_objs_grid->addWidget(filter_wgt, 2, 1, 1, 4);
44 
45 		swap_objs_grid->addWidget(objects_tbw, 3, 0, 1, 5);
46 		swap_objs_grid->addWidget(alert_frm, 4, 0, 1, 5);
47 
48 		setModel(nullptr);
49 		filter_wgt->setVisible(false);
50 
51 		connect(filter_btn, SIGNAL(toggled(bool)), filter_wgt, SLOT(setVisible(bool)));
52 		connect(src_object_sel, SIGNAL(s_objectSelected()), this, SLOT(showObjectId()));
53 		connect(dst_object_sel, SIGNAL(s_objectSelected()), this, SLOT(showObjectId()));
54 		connect(src_object_sel, SIGNAL(s_selectorCleared()), this, SLOT(showObjectId()));
55 		connect(dst_object_sel, SIGNAL(s_selectorCleared()), this, SLOT(showObjectId()));
56 
57 		connect(swap_values_tb, &QToolButton::clicked,
58 		[&](){
59 			BaseObject *obj=src_object_sel->getSelectedObject();
60 			src_object_sel->setSelectedObject(dst_object_sel->getSelectedObject());
61 			dst_object_sel->setSelectedObject(obj);
62 		});
63 
64 		connect(objects_tbw, &QTableWidget::itemDoubleClicked,
65 		[&](QTableWidgetItem *item){
66 			if(QApplication::mouseButtons() == Qt::LeftButton)
67 				selectItem(item);
68 		});
69 
70 		setMinimumSize(640,480);
71 
72 		//connect(swap_ids_tb, SIGNAL(clicked(bool)), this, SLOT(swapObjectsIds()));
73 		connect(filter_edt, SIGNAL(textChanged(QString)), this, SLOT(filterObjects()));
74 		connect(hide_rels_chk, SIGNAL(toggled(bool)), this, SLOT(filterObjects()));
75 		connect(hide_sys_objs_chk, SIGNAL(toggled(bool)), this, SLOT(filterObjects()));
76 
77 		objects_tbw->installEventFilter(this);
78 	}
79 	catch(Exception &e)
80 	{
81 		throw Exception(e.getErrorMessage(),e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
82 	}
83 }
84 
~SwapObjectsIdsWidget()85 SwapObjectsIdsWidget::~SwapObjectsIdsWidget()
86 {
87 
88 }
89 
setModel(DatabaseModel * model)90 void SwapObjectsIdsWidget::setModel(DatabaseModel *model)
91 {
92 	this->model=model;
93 
94 	src_object_sel->setModel(model);
95 	dst_object_sel->setModel(model);
96 
97 	src_object_sel->clearSelector();
98 	dst_object_sel->clearSelector();
99 
100 	fillCreationOrderGrid();
101 }
102 
setSelectedObjects(BaseObject * src_object,BaseObject * dst_objct)103 void SwapObjectsIdsWidget::setSelectedObjects(BaseObject *src_object, BaseObject *dst_objct)
104 {
105 	src_object_sel->setSelectedObject(src_object);
106 	dst_object_sel->setSelectedObject(dst_objct);
107 	selector_idx = (src_object && !dst_objct ? 1 : 0);
108 }
109 
fillCreationOrderGrid()110 void SwapObjectsIdsWidget::fillCreationOrderGrid()
111 {
112 	objects_tbw->clearContents();
113 	objects_tbw->setRowCount(0);
114 
115 	if(!model)
116 		return;
117 
118 	map<unsigned, BaseObject *> creation_order = model->getCreationOrder(SchemaParser::SqlDefinition);
119 	vector<BaseObject *> objects;
120 
121 	//Using an stl function to extract all the values (objects) from the map and put them into a list
122 	std::for_each(creation_order.begin(), creation_order.end(), [&](const std::pair<unsigned, BaseObject *> &itr) {
123 		if(itr.second->getObjectType() != ObjectType::Constraint) {
124 			objects.push_back(itr.second);
125 		}
126 	});
127 
128 	ObjectFinderWidget::updateObjectTable(objects_tbw, objects);
129 	objects_tbw->resizeColumnsToContents();
130 
131 	if(!filter_edt->text().isEmpty() || hide_rels_chk->isChecked() || hide_sys_objs_chk->isChecked())
132 		filterObjects();
133 }
134 
eventFilter(QObject * object,QEvent * event)135 bool SwapObjectsIdsWidget::eventFilter(QObject *object, QEvent *event)
136 {
137 	if(object == objects_tbw && event->type() == QEvent::KeyPress)
138 	{
139 		QKeyEvent *k_event = dynamic_cast<QKeyEvent *>(event);
140 		QTableWidgetItem *item = objects_tbw->currentItem();
141 		int row = item->row();
142 
143 		if(k_event->key() == Qt::Key_Space)
144 			selectItem(item);
145 		else if((k_event->key() == Qt::Key_Down || k_event->key() == Qt::Key_Up) && k_event->modifiers() == Qt::ControlModifier)
146 		{
147 			QTableWidgetItem *aux_item = nullptr;
148 			int key_code = k_event->key();
149 
150 			clearSelectors();
151 			selectItem(item);
152 
153 			while(!aux_item)
154 			{
155 				// If user presses down we get the next item below
156 				if(key_code == Qt::Key_Down && row < objects_tbw->rowCount() - 1)
157 					aux_item = objects_tbw->item(row + 1, 0);
158 				// If user presses up we get the next item above
159 				else if(key_code == Qt::Key_Up && row > 1)
160 					aux_item =  objects_tbw->item(row - 1, 0);
161 
162 				// If we reach a hidden row we need to jump to the next one that is not hidden
163 				if(aux_item && objects_tbw->isRowHidden(aux_item->row()))
164 				{
165 					aux_item = nullptr;
166 					row += (key_code == Qt::Key_Down ? 1 : -1);
167 				}
168 
169 				// Breaking if we've reached the top or down limits (avoiding swap ids with null objects)
170 				if((key_code == Qt::Key_Down && row >= objects_tbw->rowCount() - 1) ||
171 					 (key_code == Qt::Key_Up && row <= 0))
172 					break;
173 			}
174 
175 			if(aux_item)
176 			{
177 				selectItem(aux_item);
178 				swapObjectsIds();
179 				clearSelectors();
180 				objects_tbw->setCurrentItem(objects_tbw->item(row , 0));
181 			}
182 		}
183 	}
184 
185 	return QWidget::eventFilter(object, event);
186 }
187 
showObjectId()188 void SwapObjectsIdsWidget::showObjectId()
189 {
190 	QLabel *ico_lbl=nullptr, *id_lbl=nullptr;
191 	BaseObject *sel_obj=nullptr;
192 
193 	if(sender()==src_object_sel)
194 	{
195 		ico_lbl=src_ico_lbl;
196 		id_lbl=src_id_lbl;
197 		sel_obj=src_object_sel->getSelectedObject();
198 	}
199 	else
200 	{
201 		ico_lbl=dst_ico_lbl;
202 		id_lbl=dst_id_lbl;
203 		sel_obj=dst_object_sel->getSelectedObject();
204 	}
205 
206 	id_lbl->clear();
207 	if(sel_obj)
208 	{
209 		id_lbl->setText(IdLabel.arg(sel_obj->getObjectId()));
210 		ico_lbl->setPixmap(QPixmap(PgModelerUiNs::getIconPath(sel_obj->getObjectType())));
211 		ico_lbl->setToolTip(sel_obj->getTypeName());
212 
213 		id_lbl->setVisible(true);
214 		ico_lbl->setVisible(true);
215 	}
216 	else
217 	{
218 		id_lbl->setVisible(false);
219 		ico_lbl->setVisible(false);
220 	}
221 
222 	swap_values_tb->setEnabled(src_object_sel->getSelectedObject() &&
223 														 dst_object_sel->getSelectedObject());
224 
225 	emit s_objectsIdsSwapReady(src_object_sel->getSelectedObject() &&
226 														 dst_object_sel->getSelectedObject());
227 }
228 
swapObjectsIds()229 void SwapObjectsIdsWidget::swapObjectsIds()
230 {
231 	BaseObject *src_obj=src_object_sel->getSelectedObject(),
232 			*dst_obj=dst_object_sel->getSelectedObject();
233 	BaseGraphicObject *graph_src_obj=dynamic_cast<BaseGraphicObject *>(src_obj),
234 			*graph_dst_obj=dynamic_cast<BaseGraphicObject *>(dst_obj);
235 
236 	if(!src_obj && !dst_obj)
237 		throw Exception(ErrorCode::OprNotAllocatedObject,__PRETTY_FUNCTION__,__FILE__,__LINE__);
238 	//Raise an exception if the user try to swap an id of relationship by other object of different kind
239 	else if((src_obj->getObjectType()==ObjectType::Relationship || dst_obj->getObjectType()==ObjectType::Relationship) &&
240 					(src_obj->getObjectType() != dst_obj->getObjectType()))
241 		throw Exception(ErrorCode::InvRelationshipIdSwap,__PRETTY_FUNCTION__,__FILE__,__LINE__);
242 
243 	try
244 	{
245 		BaseObject::swapObjectsIds(src_obj, dst_obj, false);
246 
247 		//Special id swap for relationship
248 		if(src_obj->getObjectType()==ObjectType::Relationship)
249 		{
250 			vector<BaseObject *>::iterator itr, itr1;
251 			vector<BaseObject *> *list=model->getObjectList(ObjectType::Relationship);
252 
253 			//Find the relationships in the list and swap the memory position too
254 			itr=std::find(list->begin(), list->end(), src_obj);
255 			itr1=std::find(list->begin(), list->end(), dst_obj);
256 			(*itr)=dst_obj;
257 			(*itr1)=src_obj;
258 
259 			model->validateRelationships();
260 		}
261 		else
262 		{
263 			if(graph_src_obj)
264 				graph_src_obj->setModified(true);
265 
266 			if(graph_dst_obj)
267 				graph_dst_obj->setModified(true);
268 		}
269 
270 		model->setInvalidated(true);
271 		fillCreationOrderGrid();
272 
273 		src_id_lbl->setText(IdLabel.arg(src_object_sel->getSelectedObject()->getObjectId()));
274 		dst_id_lbl->setText(IdLabel.arg(dst_object_sel->getSelectedObject()->getObjectId()));
275 
276 		emit s_objectsIdsSwapped();
277 	}
278 	catch(Exception &e)
279 	{
280 		throw Exception(e.getErrorMessage(), e.getErrorCode(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
281 	}
282 }
283 
filterObjects()284 void SwapObjectsIdsWidget::filterObjects()
285 {
286 	BaseObject *object = nullptr;
287 	bool is_rel = false, is_sys_obj = false;
288 	QList<QTableWidgetItem*> items=objects_tbw->findItems(filter_edt->text(), Qt::MatchStartsWith | Qt::MatchRecursive);
289 	QTableWidgetItem *item = nullptr;
290 
291 	for(int row=0; row < objects_tbw->rowCount(); row++)
292 		objects_tbw->setRowHidden(row, true);
293 
294 	while(!items.isEmpty())
295 	{
296 		item = items.front();
297 		object = reinterpret_cast<BaseObject *>(objects_tbw->item(item->row(), 0)->data(Qt::UserRole).value<void *>());
298 		is_rel = (object->getObjectType() == ObjectType::BaseRelationship || object->getObjectType() == ObjectType::Relationship);
299 		is_sys_obj = object->isSystemObject();
300 
301 		if((!is_rel && !is_sys_obj) ||
302 			 (!hide_rels_chk->isChecked() && is_rel) ||
303 			 (!hide_sys_objs_chk->isChecked() && is_sys_obj))
304 			objects_tbw->setRowHidden(items.front()->row(), false);
305 
306 		items.pop_front();
307 	}
308 }
309 
selectItem(QTableWidgetItem * item)310 void SwapObjectsIdsWidget::selectItem(QTableWidgetItem *item)
311 {
312 	QTableWidgetItem *item_aux = (item->column() == 0 ? item : objects_tbw->item(item->row(), 0));
313 	BaseObject *obj = reinterpret_cast<BaseObject *>(item_aux->data(Qt::UserRole).value<void *>());
314 
315 	if(selector_idx == 0)
316 	{
317 		src_object_sel->setSelectedObject(obj);
318 		selector_idx = 1;
319 	}
320 	else
321 	{
322 		dst_object_sel->setSelectedObject(obj);
323 		selector_idx = 0;
324 	}
325 }
326 
clearSelectors()327 void SwapObjectsIdsWidget::clearSelectors()
328 {
329 	selector_idx = 0;
330 	src_object_sel->clearSelector();
331 	dst_object_sel->clearSelector();
332 }
333