1 /***************************************************************************
2                           allspaceconstraintsform.cpp  -  description
3                              -------------------
4     begin                : Feb 13, 2005
5     copyright            : (C) 2005 by Lalescu Liviu
6     email                : Please see https://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software: you can redistribute it and/or modify  *
12  *   it under the terms of the GNU Affero General Public License as        *
13  *   published by the Free Software Foundation, either version 3 of the    *
14  *   License, or (at your option) any later version.                       *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include <Qt>
19 
20 #include "longtextmessagebox.h"
21 
22 #include "allspaceconstraintsform.h"
23 
24 #include "modifyconstraintbasiccompulsoryspaceform.h"
25 #include "modifyconstraintroomnotavailabletimesform.h"
26 #include "modifyconstraintteacherroomnotavailabletimesform.h"
27 #include "modifyconstraintactivitypreferredroomform.h"
28 #include "modifyconstraintactivitypreferredroomsform.h"
29 
30 #include "modifyconstraintstudentssethomeroomform.h"
31 #include "modifyconstraintstudentssethomeroomsform.h"
32 
33 #include "modifyconstraintteacherhomeroomform.h"
34 #include "modifyconstraintteacherhomeroomsform.h"
35 
36 #include "modifyconstraintstudentssetmaxbuildingchangesperdayform.h"
37 #include "modifyconstraintstudentsmaxbuildingchangesperdayform.h"
38 #include "modifyconstraintstudentssetmaxbuildingchangesperweekform.h"
39 #include "modifyconstraintstudentsmaxbuildingchangesperweekform.h"
40 #include "modifyconstraintstudentssetmingapsbetweenbuildingchangesform.h"
41 #include "modifyconstraintstudentsmingapsbetweenbuildingchangesform.h"
42 
43 #include "modifyconstraintteachermaxbuildingchangesperdayform.h"
44 #include "modifyconstraintteachersmaxbuildingchangesperdayform.h"
45 #include "modifyconstraintteachermaxbuildingchangesperweekform.h"
46 #include "modifyconstraintteachersmaxbuildingchangesperweekform.h"
47 #include "modifyconstraintteachermingapsbetweenbuildingchangesform.h"
48 #include "modifyconstraintteachersmingapsbetweenbuildingchangesform.h"
49 
50 #include "modifyconstraintstudentssetmaxroomchangesperrealdayform.h"
51 #include "modifyconstraintstudentsmaxroomchangesperrealdayform.h"
52 
53 #include "modifyconstraintstudentssetmaxroomchangesperdayform.h"
54 #include "modifyconstraintstudentsmaxroomchangesperdayform.h"
55 #include "modifyconstraintstudentssetmaxroomchangesperweekform.h"
56 #include "modifyconstraintstudentsmaxroomchangesperweekform.h"
57 #include "modifyconstraintstudentssetmingapsbetweenroomchangesform.h"
58 #include "modifyconstraintstudentsmingapsbetweenroomchangesform.h"
59 
60 #include "modifyconstraintteachermaxroomchangesperrealdayform.h"
61 #include "modifyconstraintteachersmaxroomchangesperrealdayform.h"
62 
63 #include "modifyconstraintteachermaxroomchangesperdayform.h"
64 #include "modifyconstraintteachersmaxroomchangesperdayform.h"
65 #include "modifyconstraintteachermaxroomchangesperweekform.h"
66 #include "modifyconstraintteachersmaxroomchangesperweekform.h"
67 #include "modifyconstraintteachermingapsbetweenroomchangesform.h"
68 #include "modifyconstraintteachersmingapsbetweenroomchangesform.h"
69 
70 #include "modifyconstraintsubjectpreferredroomform.h"
71 #include "modifyconstraintsubjectpreferredroomsform.h"
72 #include "modifyconstraintsubjectactivitytagpreferredroomform.h"
73 #include "modifyconstraintsubjectactivitytagpreferredroomsform.h"
74 
75 #include "modifyconstraintactivitytagpreferredroomform.h"
76 #include "modifyconstraintactivitytagpreferredroomsform.h"
77 
78 #include "modifyconstraintactivitiesoccupymaxdifferentroomsform.h"
79 #include "modifyconstraintactivitiessameroomifconsecutiveform.h"
80 
81 #include "lockunlock.h"
82 
83 #include "advancedfilterform.h"
84 
85 #include <QMessageBox>
86 
87 #include <QPlainTextEdit>
88 
89 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
90 #include <QRegularExpression>
91 #include <QRegularExpressionMatch>
92 #else
93 #include <QRegExp>
94 #endif
95 
96 #include <QListWidget>
97 #include <QListWidgetItem>
98 #include <QScrollBar>
99 #include <QAbstractItemView>
100 
101 #include <QSplitter>
102 #include <QSettings>
103 #include <QObject>
104 #include <QMetaObject>
105 
106 #include <QBrush>
107 #include <QPalette>
108 
109 #include <QtAlgorithms>
110 
111 #include <algorithm>
112 //using namespace std;
113 
114 extern const QString COMPANY;
115 extern const QString PROGRAM;
116 
117 const int DESCRIPTION=0;
118 //const int DETDESCRIPTION=1;
119 
120 const int CONTAINS=0;
121 const int DOESNOTCONTAIN=1;
122 const int REGEXP=2;
123 const int NOTREGEXP=3;
124 
AllSpaceConstraintsForm(QWidget * parent)125 AllSpaceConstraintsForm::AllSpaceConstraintsForm(QWidget* parent): QDialog(parent)
126 {
127 	setupUi(this);
128 
129 	filterCheckBox->setChecked(false);
130 	sortedCheckBox->setChecked(false);
131 
132 	currentConstraintTextEdit->setReadOnly(true);
133 
134 	modifyConstraintPushButton->setDefault(true);
135 
136 	constraintsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
137 
138 	connect(constraintsListWidget, SIGNAL(currentRowChanged(int)), this, SLOT(constraintChanged()));
139 	connect(closePushButton, SIGNAL(clicked()), this, SLOT(close()));
140 	connect(removeConstraintPushButton, SIGNAL(clicked()), this, SLOT(removeConstraint()));
141 	connect(modifyConstraintPushButton, SIGNAL(clicked()), this, SLOT(modifyConstraint()));
142 	connect(constraintsListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(modifyConstraint()));
143 	connect(filterCheckBox, SIGNAL(toggled(bool)), this, SLOT(filter(bool)));
144 
145 	connect(moveSpaceConstraintUpPushButton, SIGNAL(clicked()), this, SLOT(moveSpaceConstraintUp()));
146 	connect(moveSpaceConstraintDownPushButton, SIGNAL(clicked()), this, SLOT(moveSpaceConstraintDown()));
147 
148 	connect(sortedCheckBox, SIGNAL(toggled(bool)), this, SLOT(sortedChanged(bool)));
149 	connect(activatePushButton, SIGNAL(clicked()), this, SLOT(activateConstraint()));
150 	connect(deactivatePushButton, SIGNAL(clicked()), this, SLOT(deactivateConstraint()));
151 	//connect(sortByCommentsPushButton, SIGNAL(clicked()), this, SLOT(sortConstraintsByComments()));
152 	connect(commentsPushButton, SIGNAL(clicked()), this, SLOT(constraintComments()));
153 
154 	centerWidgetOnScreen(this);
155 	restoreFETDialogGeometry(this);
156 	//restore splitter state
157 	QSettings settings(COMPANY, PROGRAM);
158 	if(settings.contains(this->metaObject()->className()+QString("/splitter-state")))
159 		splitter->restoreState(settings.value(this->metaObject()->className()+QString("/splitter-state")).toByteArray());
160 
161 	QString settingsName="AllSpaceConstraintsAdvancedFilterForm";
162 
163 	all=settings.value(settingsName+"/all-conditions", "true").toBool();
164 
165 	descrDetDescr.clear();
166 	int n=settings.value(settingsName+"/number-of-descriptions", "1").toInt();
167 	for(int i=0; i<n; i++)
168 		descrDetDescr.append(settings.value(settingsName+"/description/"+CustomFETString::number(i+1), CustomFETString::number(DESCRIPTION)).toInt());
169 
170 	contains.clear();
171 	n=settings.value(settingsName+"/number-of-contains", "1").toInt();
172 	for(int i=0; i<n; i++)
173 		contains.append(settings.value(settingsName+"/contains/"+CustomFETString::number(i+1), CustomFETString::number(CONTAINS)).toInt());
174 
175 	text.clear();
176 	n=settings.value(settingsName+"/number-of-texts", "1").toInt();
177 	for(int i=0; i<n; i++)
178 		text.append(settings.value(settingsName+"/text/"+CustomFETString::number(i+1), QString("")).toString());
179 
180 	caseSensitive=settings.value(settingsName+"/case-sensitive", "false").toBool();
181 
182 	useFilter=false;
183 
184 	assert(filterCheckBox->isChecked()==false);
185 	assert(sortedCheckBox->isChecked()==false);
186 
187 	filterChanged();
188 }
189 
~AllSpaceConstraintsForm()190 AllSpaceConstraintsForm::~AllSpaceConstraintsForm()
191 {
192 	saveFETDialogGeometry(this);
193 	//save splitter state
194 	QSettings settings(COMPANY, PROGRAM);
195 	settings.setValue(this->metaObject()->className()+QString("/splitter-state"), splitter->saveState());
196 
197 	QString settingsName="AllSpaceConstraintsAdvancedFilterForm";
198 
199 	settings.setValue(settingsName+"/all-conditions", all);
200 
201 	settings.setValue(settingsName+"/number-of-descriptions", descrDetDescr.count());
202 	settings.remove(settingsName+"/description");
203 	for(int i=0; i<descrDetDescr.count(); i++)
204 		settings.setValue(settingsName+"/description/"+CustomFETString::number(i+1), descrDetDescr.at(i));
205 
206 	settings.setValue(settingsName+"/number-of-contains", contains.count());
207 	settings.remove(settingsName+"/contains");
208 	for(int i=0; i<contains.count(); i++)
209 		settings.setValue(settingsName+"/contains/"+CustomFETString::number(i+1), contains.at(i));
210 
211 	settings.setValue(settingsName+"/number-of-texts", text.count());
212 	settings.remove(settingsName+"/text");
213 	for(int i=0; i<text.count(); i++)
214 		settings.setValue(settingsName+"/text/"+CustomFETString::number(i+1), text.at(i));
215 
216 	settings.setValue(settingsName+"/case-sensitive", caseSensitive);
217 }
218 
filterOk(SpaceConstraint * ctr)219 bool AllSpaceConstraintsForm::filterOk(SpaceConstraint* ctr)
220 {
221 	if(!useFilter)
222 		return true;
223 
224 	assert(descrDetDescr.count()==contains.count());
225 	assert(contains.count()==text.count());
226 
227 	Qt::CaseSensitivity csens=Qt::CaseSensitive;
228 	if(!caseSensitive)
229 		csens=Qt::CaseInsensitive;
230 
231 	QList<bool> okPartial;
232 
233 	for(int i=0; i<descrDetDescr.count(); i++){
234 		QString s;
235 		if(descrDetDescr.at(i)==DESCRIPTION)
236 			s=ctr->getDescription(gt.rules);
237 		else
238 			s=ctr->getDetailedDescription(gt.rules);
239 
240 		QString t=text.at(i);
241 		if(contains.at(i)==CONTAINS){
242 			okPartial.append(s.contains(t, csens));
243 		}
244 		else if(contains.at(i)==DOESNOTCONTAIN){
245 			okPartial.append(!(s.contains(t, csens)));
246 		}
247 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
248 		else if(contains.at(i)==REGEXP){
249 			QRegularExpression regExp(t);
250 			if(!caseSensitive)
251 				regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
252 			okPartial.append((regExp.match(s)).hasMatch());
253 		}
254 		else if(contains.at(i)==NOTREGEXP){
255 			QRegularExpression regExp(t);
256 			if(!caseSensitive)
257 				regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
258 			okPartial.append(!(regExp.match(s)).hasMatch());
259 		}
260 #else
261 		else if(contains.at(i)==REGEXP){
262 			QRegExp regExp(t);
263 			regExp.setCaseSensitivity(csens);
264 			okPartial.append(regExp.indexIn(s)>=0);
265 		}
266 		else if(contains.at(i)==NOTREGEXP){
267 			QRegExp regExp(t);
268 			regExp.setCaseSensitivity(csens);
269 			okPartial.append(regExp.indexIn(s)<0);
270 		}
271 #endif
272 		else
273 			assert(0);
274 	}
275 
276 	if(all){
277 		bool ok=true;
278 		for(bool b : qAsConst(okPartial))
279 			ok = ok && b;
280 
281 		return ok;
282 	}
283 	else{ //any
284 		bool ok=false;
285 		for(bool b : qAsConst(okPartial))
286 			ok = ok || b;
287 
288 		return ok;
289 	}
290 }
291 
moveSpaceConstraintUp()292 void AllSpaceConstraintsForm::moveSpaceConstraintUp()
293 {
294 	if(filterCheckBox->isChecked()){
295 		QMessageBox::information(this, tr("FET information"), tr("To move a space constraint, the 'Filter' check box must not be checked."));
296 		return;
297 	}
298 	if(sortedCheckBox->isChecked()){
299 		QMessageBox::information(this, tr("FET information"), tr("To move a space constraint, the 'Sorted' check box must not be checked."));
300 		return;
301 	}
302 
303 	if(constraintsListWidget->count()<=1)
304 		return;
305 	int i=constraintsListWidget->currentRow();
306 	if(i<0 || i>=constraintsListWidget->count())
307 		return;
308 	if(i==0)
309 		return;
310 
311 	QString s1=constraintsListWidget->item(i)->text();
312 	QString s2=constraintsListWidget->item(i-1)->text();
313 
314 	assert(gt.rules.spaceConstraintsList.count()==visibleSpaceConstraintsList.count());
315 	SpaceConstraint* sc1=gt.rules.spaceConstraintsList.at(i);
316 	assert(sc1==visibleSpaceConstraintsList.at(i));
317 	SpaceConstraint* sc2=gt.rules.spaceConstraintsList.at(i-1);
318 	assert(sc2==visibleSpaceConstraintsList.at(i-1));
319 
320 	gt.rules.internalStructureComputed=false;
321 	setRulesModifiedAndOtherThings(&gt.rules);
322 
323 	constraintsListWidget->item(i)->setText(s2);
324 	constraintsListWidget->item(i-1)->setText(s1);
325 
326 	gt.rules.spaceConstraintsList[i]=sc2;
327 	gt.rules.spaceConstraintsList[i-1]=sc1;
328 
329 	visibleSpaceConstraintsList[i]=sc2;
330 	visibleSpaceConstraintsList[i-1]=sc1;
331 
332 	if(USE_GUI_COLORS){
333 		if(sc2->active)
334 			constraintsListWidget->item(i)->setBackground(constraintsListWidget->palette().base());
335 		else
336 			constraintsListWidget->item(i)->setBackground(constraintsListWidget->palette().alternateBase());
337 
338 		if(sc1->active)
339 			constraintsListWidget->item(i-1)->setBackground(constraintsListWidget->palette().base());
340 		else
341 			constraintsListWidget->item(i-1)->setBackground(constraintsListWidget->palette().alternateBase());
342 	}
343 
344 	constraintsListWidget->setCurrentRow(i-1);
345 	constraintChanged(/*i-1*/);
346 }
347 
moveSpaceConstraintDown()348 void AllSpaceConstraintsForm::moveSpaceConstraintDown()
349 {
350 	if(filterCheckBox->isChecked()){
351 		QMessageBox::information(this, tr("FET information"), tr("To move a space constraint, the 'Filter' check box must not be checked."));
352 		return;
353 	}
354 	if(sortedCheckBox->isChecked()){
355 		QMessageBox::information(this, tr("FET information"), tr("To move a space constraint, the 'Sorted' check box must not be checked."));
356 		return;
357 	}
358 
359 	if(constraintsListWidget->count()<=1)
360 		return;
361 	int i=constraintsListWidget->currentRow();
362 	if(i<0 || i>=constraintsListWidget->count())
363 		return;
364 	if(i==constraintsListWidget->count()-1)
365 		return;
366 
367 	QString s1=constraintsListWidget->item(i)->text();
368 	QString s2=constraintsListWidget->item(i+1)->text();
369 
370 	assert(gt.rules.spaceConstraintsList.count()==visibleSpaceConstraintsList.count());
371 	SpaceConstraint* sc1=gt.rules.spaceConstraintsList.at(i);
372 	assert(sc1==visibleSpaceConstraintsList.at(i));
373 	SpaceConstraint* sc2=gt.rules.spaceConstraintsList.at(i+1);
374 	assert(sc2==visibleSpaceConstraintsList.at(i+1));
375 
376 	gt.rules.internalStructureComputed=false;
377 	setRulesModifiedAndOtherThings(&gt.rules);
378 
379 	constraintsListWidget->item(i)->setText(s2);
380 	constraintsListWidget->item(i+1)->setText(s1);
381 
382 	gt.rules.spaceConstraintsList[i]=sc2;
383 	gt.rules.spaceConstraintsList[i+1]=sc1;
384 
385 	visibleSpaceConstraintsList[i]=sc2;
386 	visibleSpaceConstraintsList[i+1]=sc1;
387 
388 	if(USE_GUI_COLORS){
389 		if(sc2->active)
390 			constraintsListWidget->item(i)->setBackground(constraintsListWidget->palette().base());
391 		else
392 			constraintsListWidget->item(i)->setBackground(constraintsListWidget->palette().alternateBase());
393 
394 		if(sc1->active)
395 			constraintsListWidget->item(i+1)->setBackground(constraintsListWidget->palette().base());
396 		else
397 			constraintsListWidget->item(i+1)->setBackground(constraintsListWidget->palette().alternateBase());
398 	}
399 
400 	constraintsListWidget->setCurrentRow(i+1);
401 	constraintChanged(/*i+1*/);
402 }
403 
sortedChanged(bool checked)404 void AllSpaceConstraintsForm::sortedChanged(bool checked)
405 {
406 	Q_UNUSED(checked);
407 
408 	filterChanged();
409 }
410 
spaceConstraintsAscendingByDescription(SpaceConstraint * s1,SpaceConstraint * s2)411 static int spaceConstraintsAscendingByDescription(SpaceConstraint* s1, SpaceConstraint* s2)
412 {
413 	//return s1->getDescription(gt.rules) < s2->getDescription(gt.rules);
414 	//by Rodolfo Ribeiro Gomes
415 	return s1->getDescription(gt.rules).localeAwareCompare(s2->getDescription(gt.rules))<0;
416 }
417 
filterChanged()418 void AllSpaceConstraintsForm::filterChanged()
419 {
420 	visibleSpaceConstraintsList.clear();
421 	constraintsListWidget->clear();
422 	int n_active=0;
423 	for(SpaceConstraint* ctr : qAsConst(gt.rules.spaceConstraintsList))
424 		if(filterOk(ctr))
425 			visibleSpaceConstraintsList.append(ctr);
426 
427 	if(sortedCheckBox->isChecked())
428 		std::stable_sort(visibleSpaceConstraintsList.begin(), visibleSpaceConstraintsList.end(), spaceConstraintsAscendingByDescription);
429 
430 	for(SpaceConstraint* ctr : qAsConst(visibleSpaceConstraintsList)){
431 		assert(filterOk(ctr));
432 		constraintsListWidget->addItem(ctr->getDescription(gt.rules));
433 
434 		if(ctr->active)
435 			n_active++;
436 		else if(USE_GUI_COLORS)
437 			constraintsListWidget->item(constraintsListWidget->count()-1)->setBackground(constraintsListWidget->palette().alternateBase());
438 	}
439 
440 	if(constraintsListWidget->count()<=0)
441 		currentConstraintTextEdit->setPlainText("");
442 	else
443 		constraintsListWidget->setCurrentRow(0);
444 
445 	constraintsTextLabel->setText(tr("%1 / %2 space constraints",
446 	 "%1 represents the number of visible active space constraints, %2 represents the total number of visible space constraints")
447 	 .arg(n_active).arg(visibleSpaceConstraintsList.count()));
448 }
449 
constraintChanged()450 void AllSpaceConstraintsForm::constraintChanged()
451 {
452 	int index=constraintsListWidget->currentRow();
453 
454 	if(index<0)
455 		return;
456 
457 	assert(index<visibleSpaceConstraintsList.count());
458 	SpaceConstraint* ctr=visibleSpaceConstraintsList.at(index);
459 	assert(ctr!=nullptr);
460 	QString s=ctr->getDetailedDescription(gt.rules);
461 	currentConstraintTextEdit->setPlainText(s);
462 }
463 
modifyConstraint()464 void AllSpaceConstraintsForm::modifyConstraint()
465 {
466 	int i=constraintsListWidget->currentRow();
467 	if(i<0){
468 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected constraint"));
469 
470 		constraintsListWidget->setFocus();
471 
472 		return;
473 	}
474 
475 	int valv=constraintsListWidget->verticalScrollBar()->value();
476 	int valh=constraintsListWidget->horizontalScrollBar()->value();
477 
478 	assert(i<visibleSpaceConstraintsList.count());
479 	SpaceConstraint* ctr=visibleSpaceConstraintsList.at(i);
480 
481 	//1
482 	if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){
483 		ModifyConstraintBasicCompulsorySpaceForm form(this, (ConstraintBasicCompulsorySpace*)ctr);
484 		setParentAndOtherThings(&form, this);
485 		form.exec();
486 	}
487 	//2
488 	else if(ctr->type==CONSTRAINT_ROOM_NOT_AVAILABLE_TIMES){
489 		ModifyConstraintRoomNotAvailableTimesForm form(this, (ConstraintRoomNotAvailableTimes*)ctr);
490 		setParentAndOtherThings(&form, this);
491 		form.exec();
492 	}
493 	//3
494 	else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
495 		ModifyConstraintActivityPreferredRoomForm form(this, (ConstraintActivityPreferredRoom*)ctr);
496 		setParentAndOtherThings(&form, this);
497 		form.exec();
498 	}
499 	//4
500 	else if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOMS){
501 		ModifyConstraintActivityPreferredRoomsForm form(this, (ConstraintActivityPreferredRooms*)ctr);
502 		setParentAndOtherThings(&form, this);
503 		form.exec();
504 	}
505 	//5
506 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOM){
507 		ModifyConstraintStudentsSetHomeRoomForm form(this, (ConstraintStudentsSetHomeRoom*)ctr);
508 		setParentAndOtherThings(&form, this);
509 		form.exec();
510 	}
511 	//6
512 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_HOME_ROOMS){
513 		ModifyConstraintStudentsSetHomeRoomsForm form(this, (ConstraintStudentsSetHomeRooms*)ctr);
514 		setParentAndOtherThings(&form, this);
515 		form.exec();
516 	}
517 	//7
518 	else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOM){
519 		ModifyConstraintTeacherHomeRoomForm form(this, (ConstraintTeacherHomeRoom*)ctr);
520 		setParentAndOtherThings(&form, this);
521 		form.exec();
522 	}
523 	//8
524 	else if(ctr->type==CONSTRAINT_TEACHER_HOME_ROOMS){
525 		ModifyConstraintTeacherHomeRoomsForm form(this, (ConstraintTeacherHomeRooms*)ctr);
526 		setParentAndOtherThings(&form, this);
527 		form.exec();
528 	}
529 	//9
530 	else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOM){
531 		ModifyConstraintSubjectPreferredRoomForm form(this, (ConstraintSubjectPreferredRoom*)ctr);
532 		setParentAndOtherThings(&form, this);
533 		form.exec();
534 	}
535 	//10
536 	else if(ctr->type==CONSTRAINT_SUBJECT_PREFERRED_ROOMS){
537 		ModifyConstraintSubjectPreferredRoomsForm form(this, (ConstraintSubjectPreferredRooms*)ctr);
538 		setParentAndOtherThings(&form, this);
539 		form.exec();
540 	}
541 	//11
542 	else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOM){
543 		ModifyConstraintSubjectActivityTagPreferredRoomForm form(this, (ConstraintSubjectActivityTagPreferredRoom*)ctr);
544 		setParentAndOtherThings(&form, this);
545 		form.exec();
546 	}
547 	//12
548 	else if(ctr->type==CONSTRAINT_SUBJECT_ACTIVITY_TAG_PREFERRED_ROOMS){
549 		ModifyConstraintSubjectActivityTagPreferredRoomsForm form(this, (ConstraintSubjectActivityTagPreferredRooms*)ctr);
550 		setParentAndOtherThings(&form, this);
551 		form.exec();
552 	}
553 	///6 apr 2009
554 	//13
555 	else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOM){
556 		ModifyConstraintActivityTagPreferredRoomForm form(this, (ConstraintActivityTagPreferredRoom*)ctr);
557 		setParentAndOtherThings(&form, this);
558 		form.exec();
559 	}
560 	//14
561 	else if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
562 		ModifyConstraintActivityTagPreferredRoomsForm form(this, (ConstraintActivityTagPreferredRooms*)ctr);
563 		setParentAndOtherThings(&form, this);
564 		form.exec();
565 	}
566 	///
567 	//15
568 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_DAY){
569 		ModifyConstraintStudentsSetMaxBuildingChangesPerDayForm form(this, (ConstraintStudentsSetMaxBuildingChangesPerDay*)ctr);
570 		setParentAndOtherThings(&form, this);
571 		form.exec();
572 	}
573 	//16
574 	else if(ctr->type==CONSTRAINT_STUDENTS_MAX_BUILDING_CHANGES_PER_DAY){
575 		ModifyConstraintStudentsMaxBuildingChangesPerDayForm form(this, (ConstraintStudentsMaxBuildingChangesPerDay*)ctr);
576 		setParentAndOtherThings(&form, this);
577 		form.exec();
578 	}
579 	//17
580 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_BUILDING_CHANGES_PER_WEEK){
581 		ModifyConstraintStudentsSetMaxBuildingChangesPerWeekForm form(this, (ConstraintStudentsSetMaxBuildingChangesPerWeek*)ctr);
582 		setParentAndOtherThings(&form, this);
583 		form.exec();
584 	}
585 	//18
586 	else if(ctr->type==CONSTRAINT_STUDENTS_MAX_BUILDING_CHANGES_PER_WEEK){
587 		ModifyConstraintStudentsMaxBuildingChangesPerWeekForm form(this, (ConstraintStudentsMaxBuildingChangesPerWeek*)ctr);
588 		setParentAndOtherThings(&form, this);
589 		form.exec();
590 	}
591 	//19
592 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
593 		ModifyConstraintStudentsSetMinGapsBetweenBuildingChangesForm form(this, (ConstraintStudentsSetMinGapsBetweenBuildingChanges*)ctr);
594 		setParentAndOtherThings(&form, this);
595 		form.exec();
596 	}
597 	//20
598 	else if(ctr->type==CONSTRAINT_STUDENTS_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
599 		ModifyConstraintStudentsMinGapsBetweenBuildingChangesForm form(this, (ConstraintStudentsMinGapsBetweenBuildingChanges*)ctr);
600 		setParentAndOtherThings(&form, this);
601 		form.exec();
602 	}
603 	//21
604 	else if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_DAY){
605 		ModifyConstraintTeacherMaxBuildingChangesPerDayForm form(this, (ConstraintTeacherMaxBuildingChangesPerDay*)ctr);
606 		setParentAndOtherThings(&form, this);
607 		form.exec();
608 	}
609 	//22
610 	else if(ctr->type==CONSTRAINT_TEACHERS_MAX_BUILDING_CHANGES_PER_DAY){
611 		ModifyConstraintTeachersMaxBuildingChangesPerDayForm form(this, (ConstraintTeachersMaxBuildingChangesPerDay*)ctr);
612 		setParentAndOtherThings(&form, this);
613 		form.exec();
614 	}
615 	//23
616 	else if(ctr->type==CONSTRAINT_TEACHER_MAX_BUILDING_CHANGES_PER_WEEK){
617 		ModifyConstraintTeacherMaxBuildingChangesPerWeekForm form(this, (ConstraintTeacherMaxBuildingChangesPerWeek*)ctr);
618 		setParentAndOtherThings(&form, this);
619 		form.exec();
620 	}
621 	//24
622 	else if(ctr->type==CONSTRAINT_TEACHERS_MAX_BUILDING_CHANGES_PER_WEEK){
623 		ModifyConstraintTeachersMaxBuildingChangesPerWeekForm form(this, (ConstraintTeachersMaxBuildingChangesPerWeek*)ctr);
624 		setParentAndOtherThings(&form, this);
625 		form.exec();
626 	}
627 	//25
628 	else if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
629 		ModifyConstraintTeacherMinGapsBetweenBuildingChangesForm form(this, (ConstraintTeacherMinGapsBetweenBuildingChanges*)ctr);
630 		setParentAndOtherThings(&form, this);
631 		form.exec();
632 	}
633 	//26
634 	else if(ctr->type==CONSTRAINT_TEACHERS_MIN_GAPS_BETWEEN_BUILDING_CHANGES){
635 		ModifyConstraintTeachersMinGapsBetweenBuildingChangesForm form(this, (ConstraintTeachersMinGapsBetweenBuildingChanges*)ctr);
636 		setParentAndOtherThings(&form, this);
637 		form.exec();
638 	}
639 	//27
640 	else if(ctr->type==CONSTRAINT_ACTIVITIES_OCCUPY_MAX_DIFFERENT_ROOMS){
641 		ModifyConstraintActivitiesOccupyMaxDifferentRoomsForm form(this, (ConstraintActivitiesOccupyMaxDifferentRooms*)ctr);
642 		setParentAndOtherThings(&form, this);
643 		form.exec();
644 	}
645 	//28
646 	else if(ctr->type==CONSTRAINT_ACTIVITIES_SAME_ROOM_IF_CONSECUTIVE){
647 		ModifyConstraintActivitiesSameRoomIfConsecutiveForm form(this, (ConstraintActivitiesSameRoomIfConsecutive*)ctr);
648 		setParentAndOtherThings(&form, this);
649 		form.exec();
650 	}
651 	//2019-11-14
652 	//29
653 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_DAY){
654 		ModifyConstraintStudentsSetMaxRoomChangesPerDayForm form(this, (ConstraintStudentsSetMaxRoomChangesPerDay*)ctr);
655 		setParentAndOtherThings(&form, this);
656 		form.exec();
657 	}
658 	//30
659 	else if(ctr->type==CONSTRAINT_STUDENTS_MAX_ROOM_CHANGES_PER_DAY){
660 		ModifyConstraintStudentsMaxRoomChangesPerDayForm form(this, (ConstraintStudentsMaxRoomChangesPerDay*)ctr);
661 		setParentAndOtherThings(&form, this);
662 		form.exec();
663 	}
664 	//31
665 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_WEEK){
666 		ModifyConstraintStudentsSetMaxRoomChangesPerWeekForm form(this, (ConstraintStudentsSetMaxRoomChangesPerWeek*)ctr);
667 		setParentAndOtherThings(&form, this);
668 		form.exec();
669 	}
670 	//32
671 	else if(ctr->type==CONSTRAINT_STUDENTS_MAX_ROOM_CHANGES_PER_WEEK){
672 		ModifyConstraintStudentsMaxRoomChangesPerWeekForm form(this, (ConstraintStudentsMaxRoomChangesPerWeek*)ctr);
673 		setParentAndOtherThings(&form, this);
674 		form.exec();
675 	}
676 	//33
677 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_MIN_GAPS_BETWEEN_ROOM_CHANGES){
678 		ModifyConstraintStudentsSetMinGapsBetweenRoomChangesForm form(this, (ConstraintStudentsSetMinGapsBetweenRoomChanges*)ctr);
679 		setParentAndOtherThings(&form, this);
680 		form.exec();
681 	}
682 	//34
683 	else if(ctr->type==CONSTRAINT_STUDENTS_MIN_GAPS_BETWEEN_ROOM_CHANGES){
684 		ModifyConstraintStudentsMinGapsBetweenRoomChangesForm form(this, (ConstraintStudentsMinGapsBetweenRoomChanges*)ctr);
685 		setParentAndOtherThings(&form, this);
686 		form.exec();
687 	}
688 	//35
689 	else if(ctr->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_DAY){
690 		ModifyConstraintTeacherMaxRoomChangesPerDayForm form(this, (ConstraintTeacherMaxRoomChangesPerDay*)ctr);
691 		setParentAndOtherThings(&form, this);
692 		form.exec();
693 	}
694 	//36
695 	else if(ctr->type==CONSTRAINT_TEACHERS_MAX_ROOM_CHANGES_PER_DAY){
696 		ModifyConstraintTeachersMaxRoomChangesPerDayForm form(this, (ConstraintTeachersMaxRoomChangesPerDay*)ctr);
697 		setParentAndOtherThings(&form, this);
698 		form.exec();
699 	}
700 	//37
701 	else if(ctr->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_WEEK){
702 		ModifyConstraintTeacherMaxRoomChangesPerWeekForm form(this, (ConstraintTeacherMaxRoomChangesPerWeek*)ctr);
703 		setParentAndOtherThings(&form, this);
704 		form.exec();
705 	}
706 	//38
707 	else if(ctr->type==CONSTRAINT_TEACHERS_MAX_ROOM_CHANGES_PER_WEEK){
708 		ModifyConstraintTeachersMaxRoomChangesPerWeekForm form(this, (ConstraintTeachersMaxRoomChangesPerWeek*)ctr);
709 		setParentAndOtherThings(&form, this);
710 		form.exec();
711 	}
712 	//39
713 	else if(ctr->type==CONSTRAINT_TEACHER_MIN_GAPS_BETWEEN_ROOM_CHANGES){
714 		ModifyConstraintTeacherMinGapsBetweenRoomChangesForm form(this, (ConstraintTeacherMinGapsBetweenRoomChanges*)ctr);
715 		setParentAndOtherThings(&form, this);
716 		form.exec();
717 	}
718 	//40
719 	else if(ctr->type==CONSTRAINT_TEACHERS_MIN_GAPS_BETWEEN_ROOM_CHANGES){
720 		ModifyConstraintTeachersMinGapsBetweenRoomChangesForm form(this, (ConstraintTeachersMinGapsBetweenRoomChanges*)ctr);
721 		setParentAndOtherThings(&form, this);
722 		form.exec();
723 	}
724 	//41
725 	else if(ctr->type==CONSTRAINT_TEACHER_ROOM_NOT_AVAILABLE_TIMES){
726 		ModifyConstraintTeacherRoomNotAvailableTimesForm form(this, (ConstraintTeacherRoomNotAvailableTimes*)ctr);
727 		setParentAndOtherThings(&form, this);
728 		form.exec();
729 	}
730 	//for mornings-afternoons
731 	//42
732 	else if(ctr->type==CONSTRAINT_STUDENTS_SET_MAX_ROOM_CHANGES_PER_REAL_DAY){
733 		ModifyConstraintStudentsSetMaxRoomChangesPerRealDayForm form(this, (ConstraintStudentsSetMaxRoomChangesPerRealDay*)ctr);
734 		setParentAndOtherThings(&form, this);
735 		form.exec();
736 	}
737 	//43
738 	else if(ctr->type==CONSTRAINT_STUDENTS_MAX_ROOM_CHANGES_PER_REAL_DAY){
739 		ModifyConstraintStudentsMaxRoomChangesPerRealDayForm form(this, (ConstraintStudentsMaxRoomChangesPerRealDay*)ctr);
740 		setParentAndOtherThings(&form, this);
741 		form.exec();
742 	}
743 	//44
744 	else if(ctr->type==CONSTRAINT_TEACHER_MAX_ROOM_CHANGES_PER_REAL_DAY){
745 		ModifyConstraintTeacherMaxRoomChangesPerRealDayForm form(this, (ConstraintTeacherMaxRoomChangesPerRealDay*)ctr);
746 		setParentAndOtherThings(&form, this);
747 		form.exec();
748 	}
749 	//45
750 	else if(ctr->type==CONSTRAINT_TEACHERS_MAX_ROOM_CHANGES_PER_REAL_DAY){
751 		ModifyConstraintTeachersMaxRoomChangesPerRealDayForm form(this, (ConstraintTeachersMaxRoomChangesPerRealDay*)ctr);
752 		setParentAndOtherThings(&form, this);
753 		form.exec();
754 	}
755 	else{
756 		QMessageBox::critical(this, tr("FET critical"), tr("You have found a bug in FET. Please report it. This kind of constraint"
757 		 " is not correctly recognized in all space constraints dialog. FET will skip this error, so that you can continue work."
758 		 " Probably the constraint can be modified from the specific constraint dialog."));
759 //		assert(0);
760 //		exit(1);
761 	}
762 
763 	filterChanged();
764 
765 	constraintsListWidget->verticalScrollBar()->setValue(valv);
766 	constraintsListWidget->horizontalScrollBar()->setValue(valh);
767 
768 	if(i>=constraintsListWidget->count())
769 		i=constraintsListWidget->count()-1;
770 
771 	if(i>=0)
772 		constraintsListWidget->setCurrentRow(i);
773 
774 	constraintsListWidget->setFocus();
775 }
776 
removeConstraint()777 void AllSpaceConstraintsForm::removeConstraint()
778 {
779 	int i=constraintsListWidget->currentRow();
780 	if(i<0){
781 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected constraint"));
782 		return;
783 	}
784 	assert(i<visibleSpaceConstraintsList.count());
785 	SpaceConstraint* ctr=visibleSpaceConstraintsList.at(i);
786 
787 	QString s;
788 	s=tr("Remove constraint?");
789 	s+="\n\n";
790 	s+=ctr->getDetailedDescription(gt.rules);
791 
792 	bool recompute, t;
793 
794 	QListWidgetItem* item;
795 
796 	int lres=LongTextMessageBox::confirmation( this, tr("FET confirmation"),
797 		s, tr("Yes"), tr("No"), 0, 0, 1 );
798 
799 	if(lres==0){ //The user clicked the OK button or pressed Enter
800 		QMessageBox::StandardButton wr=QMessageBox::Yes;
801 
802 		if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){ //additional confirmation for this one
803 			QString s=tr("Do you really want to remove the basic compulsory space constraint?");
804 			s+=" ";
805 			s+=tr("You cannot generate a timetable without this constraint.");
806 			s+="\n\n";
807 			s+=tr("Note: you can add again a constraint of this type from the menu Data -> Space constraints -> "
808 				"Miscellaneous -> Basic compulsory space constraints.");
809 
810 			wr=QMessageBox::warning(this, tr("FET warning"), s,
811 				QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
812 		}
813 
814 		if(wr==QMessageBox::Yes){
815 			if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
816 				recompute=true;
817 			}
818 			else{
819 				recompute=false;
820 			}
821 
822 			t=gt.rules.removeSpaceConstraint(ctr);
823 			assert(t);
824 			visibleSpaceConstraintsList.removeAt(i);
825 			constraintsListWidget->setCurrentRow(-1);
826 			item=constraintsListWidget->takeItem(i);
827 			delete item;
828 
829 			int n_active=0;
830 			for(SpaceConstraint* ctr2 : qAsConst(visibleSpaceConstraintsList))
831 				if(ctr2->active)
832 					n_active++;
833 
834 			constraintsTextLabel->setText(tr("%1 / %2 space constraints",
835 			 "%1 represents the number of visible active space constraints, %2 represents the total number of visible space constraints")
836 			 .arg(n_active).arg(visibleSpaceConstraintsList.count()));
837 
838 			//constraintsTextLabel->setText(tr("%1 Space Constraints", "%1 represents the number of constraints").arg(visibleSpaceConstraintsList.count()));
839 
840 			if(recompute){
841 				LockUnlock::computeLockedUnlockedActivitiesOnlySpace();
842 				LockUnlock::increaseCommunicationSpinBox();
843 			}
844 		}
845 	}
846 	//else if(lres==1){ //The user clicked the Cancel button or pressed Escape
847 	//}
848 
849 	if(i>=constraintsListWidget->count())
850 		i=constraintsListWidget->count()-1;
851 	if(i>=0)
852 		constraintsListWidget->setCurrentRow(i);
853 	else
854 		currentConstraintTextEdit->setPlainText(QString(""));
855 }
856 
filter(bool active)857 void AllSpaceConstraintsForm::filter(bool active)
858 {
859 	if(!active){
860 		assert(useFilter==true);
861 		useFilter=false;
862 
863 		filterChanged();
864 
865 		return;
866 	}
867 
868 	assert(active);
869 
870 	filterForm=new AdvancedFilterForm(this, all, descrDetDescr, contains, text, caseSensitive, "AllSpaceConstraintsAdvancedFilterForm");
871 
872 	int t=filterForm->exec();
873 
874 	if(t==QDialog::Accepted){
875 		assert(useFilter==false);
876 		useFilter=true;
877 
878 		if(filterForm->allRadio->isChecked())
879 			all=true;
880 		else if(filterForm->anyRadio->isChecked())
881 			all=false;
882 		else
883 			assert(0);
884 
885 		caseSensitive=filterForm->caseSensitiveCheckBox->isChecked();
886 
887 		descrDetDescr.clear();
888 		contains.clear();
889 		text.clear();
890 
891 		assert(filterForm->descrDetDescrComboBoxList.count()==filterForm->contNContReNReComboBoxList.count());
892 		assert(filterForm->descrDetDescrComboBoxList.count()==filterForm->textLineEditList.count());
893 		for(int i=0; i<filterForm->rows; i++){
894 			QComboBox* cb1=filterForm->descrDetDescrComboBoxList.at(i);
895 			QComboBox* cb2=filterForm->contNContReNReComboBoxList.at(i);
896 			QLineEdit* tl=filterForm->textLineEditList.at(i);
897 
898 			descrDetDescr.append(cb1->currentIndex());
899 			contains.append(cb2->currentIndex());
900 			text.append(tl->text());
901 		}
902 
903 		filterChanged();
904 	}
905 	else{
906 		assert(useFilter==false);
907 		useFilter=false;
908 
909 		disconnect(filterCheckBox, SIGNAL(toggled(bool)), this, SLOT(filter(bool)));
910 		filterCheckBox->setChecked(false);
911 		connect(filterCheckBox, SIGNAL(toggled(bool)), this, SLOT(filter(bool)));
912 	}
913 
914 	delete filterForm;
915 }
916 
activateConstraint()917 void AllSpaceConstraintsForm::activateConstraint()
918 {
919 	int i=constraintsListWidget->currentRow();
920 	if(i<0){
921 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected constraint"));
922 
923 		constraintsListWidget->setFocus();
924 
925 		return;
926 	}
927 
928 	assert(i<visibleSpaceConstraintsList.count());
929 	SpaceConstraint* ctr=visibleSpaceConstraintsList.at(i);
930 
931 	if(!ctr->active){
932 		ctr->active=true;
933 
934 		gt.rules.internalStructureComputed=false;
935 		setRulesModifiedAndOtherThings(&gt.rules);
936 
937 		if(!filterOk(ctr)){ //Maybe the constraint is no longer visible in the list widget, because of the filter.
938 			visibleSpaceConstraintsList.removeAt(i);
939 			constraintsListWidget->setCurrentRow(-1);
940 			QListWidgetItem* item=constraintsListWidget->takeItem(i);
941 			delete item;
942 
943 			if(i>=constraintsListWidget->count())
944 				i=constraintsListWidget->count()-1;
945 			if(i>=0)
946 				constraintsListWidget->setCurrentRow(i);
947 			else
948 				currentConstraintTextEdit->setPlainText(QString(""));
949 		}
950 		else{
951 			constraintsListWidget->currentItem()->setText(ctr->getDescription(gt.rules));
952 			if(USE_GUI_COLORS)
953 				constraintsListWidget->currentItem()->setBackground(constraintsListWidget->palette().base());
954 			constraintChanged();
955 		}
956 
957 		if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
958 			LockUnlock::computeLockedUnlockedActivitiesOnlySpace();
959 			LockUnlock::increaseCommunicationSpinBox();
960 		}
961 
962 		int n_active=0;
963 		for(SpaceConstraint* ctr2 : qAsConst(visibleSpaceConstraintsList))
964 			if(ctr2->active)
965 				n_active++;
966 
967 		constraintsTextLabel->setText(tr("%1 / %2 space constraints",
968 		 "%1 represents the number of visible active space constraints, %2 represents the total number of visible space constraints")
969 		 .arg(n_active).arg(visibleSpaceConstraintsList.count()));
970 	}
971 
972 	constraintsListWidget->setFocus();
973 }
974 
deactivateConstraint()975 void AllSpaceConstraintsForm::deactivateConstraint()
976 {
977 	int i=constraintsListWidget->currentRow();
978 	if(i<0){
979 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected constraint"));
980 
981 		constraintsListWidget->setFocus();
982 
983 		return;
984 	}
985 
986 	assert(i<visibleSpaceConstraintsList.count());
987 	SpaceConstraint* ctr=visibleSpaceConstraintsList.at(i);
988 
989 	if(ctr->active){
990 		if(ctr->type==CONSTRAINT_BASIC_COMPULSORY_SPACE){
991 			QMessageBox::warning(this, tr("FET warning"), tr("You are not allowed to deactivate the basic compulsory space constraints"));
992 			return;
993 		}
994 
995 		ctr->active=false;
996 
997 		gt.rules.internalStructureComputed=false;
998 		setRulesModifiedAndOtherThings(&gt.rules);
999 
1000 		if(!filterOk(ctr)){ //Maybe the constraint is no longer visible in the list widget, because of the filter.
1001 			visibleSpaceConstraintsList.removeAt(i);
1002 			constraintsListWidget->setCurrentRow(-1);
1003 			QListWidgetItem* item=constraintsListWidget->takeItem(i);
1004 			delete item;
1005 
1006 			if(i>=constraintsListWidget->count())
1007 				i=constraintsListWidget->count()-1;
1008 			if(i>=0)
1009 				constraintsListWidget->setCurrentRow(i);
1010 			else
1011 				currentConstraintTextEdit->setPlainText(QString(""));
1012 		}
1013 		else{
1014 			constraintsListWidget->currentItem()->setText(ctr->getDescription(gt.rules));
1015 			if(USE_GUI_COLORS)
1016 				constraintsListWidget->currentItem()->setBackground(constraintsListWidget->palette().alternateBase());
1017 			constraintChanged();
1018 		}
1019 
1020 		if(ctr->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
1021 			LockUnlock::computeLockedUnlockedActivitiesOnlySpace();
1022 			LockUnlock::increaseCommunicationSpinBox();
1023 		}
1024 
1025 		int n_active=0;
1026 		for(SpaceConstraint* ctr2 : qAsConst(visibleSpaceConstraintsList))
1027 			if(ctr2->active)
1028 				n_active++;
1029 
1030 		constraintsTextLabel->setText(tr("%1 / %2 space constraints",
1031 		 "%1 represents the number of visible active space constraints, %2 represents the total number of visible space constraints")
1032 		 .arg(n_active).arg(visibleSpaceConstraintsList.count()));
1033 	}
1034 
1035 	constraintsListWidget->setFocus();
1036 }
1037 
1038 /*static int spaceConstraintsAscendingByComments(const SpaceConstraint* s1, const SpaceConstraint* s2)
1039 {
1040 	return s1->comments < s2->comments;
1041 }
1042 
1043 void AllSpaceConstraintsForm::sortConstraintsByComments()
1044 {
1045 	QMessageBox::StandardButton t=QMessageBox::question(this, tr("Sort constraints?"),
1046 	 tr("This will sort the space constraints list ascending according to their comments. You can obtain "
1047 	 "a custom ordering by adding comments to some or all space constraints, for example 'rank #1 ... other comments', "
1048 	 "'rank #2 ... other different comments'.")
1049 	 +" "+tr("Are you sure you want to continue?"),
1050 	 QMessageBox::Yes|QMessageBox::Cancel);
1051 
1052 	if(t==QMessageBox::Cancel)
1053 		return;
1054 
1055 	std::stable_sort(gt.rules.spaceConstraintsList.begin(), gt.rules.spaceConstraintsList.end(), spaceConstraintsAscendingByComments);
1056 
1057 	gt.rules.internalStructureComputed=false;
1058 	setRulesModifiedAndOtherThings(&gt.rules);
1059 
1060 	filterChanged();
1061 }*/
1062 
constraintComments()1063 void AllSpaceConstraintsForm::constraintComments()
1064 {
1065 	int i=constraintsListWidget->currentRow();
1066 	if(i<0){
1067 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected constraint"));
1068 		return;
1069 	}
1070 
1071 	assert(i<visibleSpaceConstraintsList.count());
1072 	SpaceConstraint* ctr=visibleSpaceConstraintsList.at(i);
1073 
1074 	QDialog getCommentsDialog(this);
1075 
1076 	getCommentsDialog.setWindowTitle(tr("Constraint comments"));
1077 
1078 	QPushButton* okPB=new QPushButton(tr("OK"));
1079 	okPB->setDefault(true);
1080 	QPushButton* cancelPB=new QPushButton(tr("Cancel"));
1081 
1082 	connect(okPB, SIGNAL(clicked()), &getCommentsDialog, SLOT(accept()));
1083 	connect(cancelPB, SIGNAL(clicked()), &getCommentsDialog, SLOT(reject()));
1084 
1085 	QHBoxLayout* hl=new QHBoxLayout();
1086 	hl->addStretch();
1087 	hl->addWidget(okPB);
1088 	hl->addWidget(cancelPB);
1089 
1090 	QVBoxLayout* vl=new QVBoxLayout();
1091 
1092 	QPlainTextEdit* commentsPT=new QPlainTextEdit();
1093 	commentsPT->setPlainText(ctr->comments);
1094 	commentsPT->selectAll();
1095 	commentsPT->setFocus();
1096 
1097 	vl->addWidget(commentsPT);
1098 	vl->addLayout(hl);
1099 
1100 	getCommentsDialog.setLayout(vl);
1101 
1102 	const QString settingsName=QString("SpaceConstraintCommentsDialog");
1103 
1104 	getCommentsDialog.resize(500, 320);
1105 	centerWidgetOnScreen(&getCommentsDialog);
1106 	restoreFETDialogGeometry(&getCommentsDialog, settingsName);
1107 
1108 	int t=getCommentsDialog.exec();
1109 	saveFETDialogGeometry(&getCommentsDialog, settingsName);
1110 
1111 	if(t==QDialog::Accepted){
1112 		ctr->comments=commentsPT->toPlainText();
1113 
1114 		gt.rules.internalStructureComputed=false;
1115 		setRulesModifiedAndOtherThings(&gt.rules);
1116 
1117 		if(!filterOk(ctr)){ //Maybe the constraint is no longer visible in the list widget, because of the filter.
1118 			visibleSpaceConstraintsList.removeAt(i);
1119 			constraintsListWidget->setCurrentRow(-1);
1120 			QListWidgetItem* item=constraintsListWidget->takeItem(i);
1121 			delete item;
1122 
1123 			if(i>=constraintsListWidget->count())
1124 				i=constraintsListWidget->count()-1;
1125 			if(i>=0)
1126 				constraintsListWidget->setCurrentRow(i);
1127 			else
1128 				currentConstraintTextEdit->setPlainText(QString(""));
1129 
1130 			int n_active=0;
1131 			for(SpaceConstraint* ctr2 : qAsConst(visibleSpaceConstraintsList))
1132 				if(ctr2->active)
1133 					n_active++;
1134 
1135 			constraintsTextLabel->setText(tr("%1 / %2 space constraints",
1136 			 "%1 represents the number of visible active space constraints, %2 represents the total number of visible space constraints")
1137 			 .arg(n_active).arg(visibleSpaceConstraintsList.count()));
1138 		}
1139 		else{
1140 			constraintsListWidget->currentItem()->setText(ctr->getDescription(gt.rules));
1141 			constraintChanged();
1142 		}
1143 	}
1144 }
1145