1 /***************************************************************************
2                           modifyconstraintstudentssetnotavailabletimesform.cpp  -  description
3                              -------------------
4     begin                : Feb 10, 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 <QMessageBox>
21 
22 #include "modifyconstraintstudentssetnotavailabletimesform.h"
23 #include "timeconstraint.h"
24 
25 #include <QHeaderView>
26 #include <QTableWidget>
27 #include <QTableWidgetItem>
28 
29 #include <QBrush>
30 #include <QColor>
31 
32 #define YES		(QString("X"))
33 #define NO		(QString(" "))
34 
ModifyConstraintStudentsSetNotAvailableTimesForm(QWidget * parent,ConstraintStudentsSetNotAvailableTimes * ctr)35 ModifyConstraintStudentsSetNotAvailableTimesForm::ModifyConstraintStudentsSetNotAvailableTimesForm(QWidget* parent, ConstraintStudentsSetNotAvailableTimes* ctr): QDialog(parent)
36 {
37 	setupUi(this);
38 
39 	okPushButton->setDefault(true);
40 
41 	connect(okPushButton, SIGNAL(clicked()), this, SLOT(ok()));
42 	connect(cancelPushButton, SIGNAL(clicked()), this, SLOT(cancel()));
43 	connect(notAllowedTimesTable, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(itemClicked(QTableWidgetItem*)));
44 	connect(setAllAvailablePushButton, SIGNAL(clicked()), this, SLOT(setAllAvailable()));
45 	connect(setAllNotAvailablePushButton, SIGNAL(clicked()), this, SLOT(setAllNotAvailable()));
46 
47 	centerWidgetOnScreen(this);
48 	restoreFETDialogGeometry(this);
49 
50 	QSize tmp2=studentsComboBox->minimumSizeHint();
51 	Q_UNUSED(tmp2);
52 
53 	this->_ctr=ctr;
54 
55 	weightLineEdit->setText(CustomFETString::number(ctr->weightPercentage));
56 
57 	updateStudentsComboBox(parent);
58 
59 	notAllowedTimesTable->setRowCount(gt.rules.nHoursPerDay);
60 	notAllowedTimesTable->setColumnCount(gt.rules.nDaysPerWeek);
61 
62 	for(int j=0; j<gt.rules.nDaysPerWeek; j++){
63 		QTableWidgetItem* item=new QTableWidgetItem(gt.rules.daysOfTheWeek[j]);
64 		notAllowedTimesTable->setHorizontalHeaderItem(j, item);
65 	}
66 	for(int i=0; i<gt.rules.nHoursPerDay; i++){
67 		QTableWidgetItem* item=new QTableWidgetItem(gt.rules.hoursOfTheDay[i]);
68 		notAllowedTimesTable->setVerticalHeaderItem(i, item);
69 	}
70 
71 	Matrix2D<bool> currentMatrix;
72 	currentMatrix.resize(gt.rules.nHoursPerDay, gt.rules.nDaysPerWeek);
73 
74 	for(int i=0; i<gt.rules.nHoursPerDay; i++)
75 		for(int j=0; j<gt.rules.nDaysPerWeek; j++)
76 			currentMatrix[i][j]=false;
77 	assert(ctr->days.count()==ctr->hours.count());
78 	for(int k=0; k<ctr->days.count(); k++){
79 		if(ctr->hours.at(k)==-1 || ctr->days.at(k)==-1)
80 			assert(0);
81 		int i=ctr->hours.at(k);
82 		int j=ctr->days.at(k);
83 		if(i>=0 && i<gt.rules.nHoursPerDay && j>=0 && j<gt.rules.nDaysPerWeek)
84 			currentMatrix[i][j]=true;
85 	}
86 
87 	for(int i=0; i<gt.rules.nHoursPerDay; i++)
88 		for(int j=0; j<gt.rules.nDaysPerWeek; j++){
89 			QTableWidgetItem* item= new QTableWidgetItem();
90 			item->setTextAlignment(Qt::AlignCenter);
91 			item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
92 			if(SHOW_TOOLTIPS_FOR_CONSTRAINTS_WITH_TABLES)
93 				item->setToolTip(gt.rules.daysOfTheWeek[j]+QString("\n")+gt.rules.hoursOfTheDay[i]);
94 			notAllowedTimesTable->setItem(i, j, item);
95 
96 			if(!currentMatrix[i][j])
97 				item->setText(NO);
98 			else
99 				item->setText(YES);
100 
101 			colorItem(item);
102 		}
103 
104 	notAllowedTimesTable->resizeRowsToContents();
105 
106 	connect(notAllowedTimesTable->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(horizontalHeaderClicked(int)));
107 	connect(notAllowedTimesTable->verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(verticalHeaderClicked(int)));
108 
109 	notAllowedTimesTable->setSelectionMode(QAbstractItemView::NoSelection);
110 
111 	setStretchAvailabilityTableNicely(notAllowedTimesTable);
112 }
113 
~ModifyConstraintStudentsSetNotAvailableTimesForm()114 ModifyConstraintStudentsSetNotAvailableTimesForm::~ModifyConstraintStudentsSetNotAvailableTimesForm()
115 {
116 	saveFETDialogGeometry(this);
117 }
118 
colorItem(QTableWidgetItem * item)119 void ModifyConstraintStudentsSetNotAvailableTimesForm::colorItem(QTableWidgetItem* item)
120 {
121 	if(USE_GUI_COLORS){
122 #if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
123 		if(item->text()==NO)
124 			item->setBackground(QBrush(QColorConstants::DarkGreen));
125 		else
126 			item->setBackground(QBrush(QColorConstants::DarkRed));
127 		item->setForeground(QBrush(QColorConstants::LightGray));
128 #else
129 		if(item->text()==NO)
130 			item->setBackground(QBrush(Qt::darkGreen));
131 		else
132 			item->setBackground(QBrush(Qt::darkRed));
133 		item->setForeground(QBrush(Qt::lightGray));
134 #endif
135 	}
136 }
137 
horizontalHeaderClicked(int col)138 void ModifyConstraintStudentsSetNotAvailableTimesForm::horizontalHeaderClicked(int col)
139 {
140 	if(col>=0 && col<gt.rules.nDaysPerWeek){
141 		QString s=notAllowedTimesTable->item(0, col)->text();
142 		if(s==YES)
143 			s=NO;
144 		else{
145 			assert(s==NO);
146 			s=YES;
147 		}
148 
149 		for(int row=0; row<gt.rules.nHoursPerDay; row++){
150 			notAllowedTimesTable->item(row, col)->setText(s);
151 			colorItem(notAllowedTimesTable->item(row,col));
152 		}
153 	}
154 }
155 
verticalHeaderClicked(int row)156 void ModifyConstraintStudentsSetNotAvailableTimesForm::verticalHeaderClicked(int row)
157 {
158 	if(row>=0 && row<gt.rules.nHoursPerDay){
159 		QString s=notAllowedTimesTable->item(row, 0)->text();
160 		if(s==YES)
161 			s=NO;
162 		else{
163 			assert(s==NO);
164 			s=YES;
165 		}
166 
167 		for(int col=0; col<gt.rules.nDaysPerWeek; col++){
168 			notAllowedTimesTable->item(row, col)->setText(s);
169 			colorItem(notAllowedTimesTable->item(row,col));
170 		}
171 	}
172 }
173 
setAllAvailable()174 void ModifyConstraintStudentsSetNotAvailableTimesForm::setAllAvailable()
175 {
176 	for(int i=0; i<gt.rules.nHoursPerDay; i++)
177 		for(int j=0; j<gt.rules.nDaysPerWeek; j++){
178 			notAllowedTimesTable->item(i, j)->setText(NO);
179 			colorItem(notAllowedTimesTable->item(i,j));
180 		}
181 }
182 
setAllNotAvailable()183 void ModifyConstraintStudentsSetNotAvailableTimesForm::setAllNotAvailable()
184 {
185 	for(int i=0; i<gt.rules.nHoursPerDay; i++)
186 		for(int j=0; j<gt.rules.nDaysPerWeek; j++){
187 			notAllowedTimesTable->item(i, j)->setText(YES);
188 			colorItem(notAllowedTimesTable->item(i,j));
189 		}
190 }
191 
itemClicked(QTableWidgetItem * item)192 void ModifyConstraintStudentsSetNotAvailableTimesForm::itemClicked(QTableWidgetItem* item)
193 {
194 	QString s=item->text();
195 	if(s==YES)
196 		s=NO;
197 	else{
198 		assert(s==NO);
199 		s=YES;
200 	}
201 	item->setText(s);
202 	colorItem(item);
203 }
204 
updateStudentsComboBox(QWidget * parent)205 void ModifyConstraintStudentsSetNotAvailableTimesForm::updateStudentsComboBox(QWidget* parent){
206 	int j=populateStudentsComboBox(studentsComboBox, this->_ctr->students);
207 	if(j<0)
208 		showWarningForInvisibleSubgroupConstraint(parent, this->_ctr->students);
209 	else
210 		assert(j>=0);
211 	studentsComboBox->setCurrentIndex(j);
212 }
213 
ok()214 void ModifyConstraintStudentsSetNotAvailableTimesForm::ok()
215 {
216 	if(studentsComboBox->currentIndex()<0){
217 		showWarningCannotModifyConstraintInvisibleSubgroupConstraint(this, this->_ctr->students);
218 		return;
219 	}
220 
221 	double weight;
222 	QString tmp=weightLineEdit->text();
223 	weight_sscanf(tmp, "%lf", &weight);
224 	if(weight<100.0 || weight>100.0){
225 		QMessageBox::warning(this, tr("FET information"),
226 			tr("Invalid weight (percentage). It has to be 100"));
227 		return;
228 	}
229 
230 	QString students_name=studentsComboBox->currentText();
231 	StudentsSet* s=gt.rules.searchStudentsSet(students_name);
232 	if(s==nullptr){
233 		QMessageBox::warning(this, tr("FET information"),
234 			tr("Invalid students set"));
235 		return;
236 	}
237 
238 	for(TimeConstraint* c : qAsConst(gt.rules.timeConstraintsList))
239 		if(c!=this->_ctr && c->type==CONSTRAINT_STUDENTS_SET_NOT_AVAILABLE_TIMES){
240 			ConstraintStudentsSetNotAvailableTimes* cc=(ConstraintStudentsSetNotAvailableTimes*)c;
241 			if(cc->students==students_name){
242 				QMessageBox::warning(this, tr("FET information"),
243 				tr("A constraint of this type exists for the same students set - cannot proceed"));
244 				return;
245 			}
246 		}
247 
248 	this->_ctr->weightPercentage=weight;
249 
250 	if(_ctr->students!=students_name){
251 		QString oldName=_ctr->students;
252 		QString newName=students_name;
253 
254 		QSet<ConstraintStudentsSetNotAvailableTimes*> cs=gt.rules.ssnatHash.value(oldName, QSet<ConstraintStudentsSetNotAvailableTimes*>());
255 		assert(cs.contains(_ctr));
256 		cs.remove(_ctr);
257 		gt.rules.ssnatHash.insert(oldName, cs);
258 
259 		cs=gt.rules.ssnatHash.value(newName, QSet<ConstraintStudentsSetNotAvailableTimes*>());
260 		assert(!cs.contains(_ctr));
261 		cs.insert(_ctr);
262 		gt.rules.ssnatHash.insert(newName, cs);
263 
264 		this->_ctr->students=students_name;
265 	}
266 
267 	QList<int> days;
268 	QList<int> hours;
269 	for(int j=0; j<gt.rules.nDaysPerWeek; j++)
270 		for(int i=0; i<gt.rules.nHoursPerDay; i++)
271 			if(notAllowedTimesTable->item(i, j)->text()==YES){
272 				days.append(j);
273 				hours.append(i);
274 			}
275 
276 	this->_ctr->days=days;
277 	this->_ctr->hours=hours;
278 
279 	gt.rules.internalStructureComputed=false;
280 	setRulesModifiedAndOtherThings(&gt.rules);
281 
282 	this->close();
283 }
284 
cancel()285 void ModifyConstraintStudentsSetNotAvailableTimesForm::cancel()
286 {
287 	this->close();
288 }
289