1 /***************************************************************************
2                           constraintactivitiesoccupymaxtimeslotsfromselectionform.cpp  -  description
3                              -------------------
4     begin                : Sept 26, 2011
5     copyright            : (C) 2011 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 <QMessageBox>
19 
20 #include "longtextmessagebox.h"
21 
22 #include "constraintactivitiesoccupymaxtimeslotsfromselectionform.h"
23 #include "addconstraintactivitiesoccupymaxtimeslotsfromselectionform.h"
24 #include "modifyconstraintactivitiesoccupymaxtimeslotsfromselectionform.h"
25 
26 #include <QListWidget>
27 #include <QScrollBar>
28 #include <QAbstractItemView>
29 
ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm(QWidget * parent)30 ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm(QWidget* parent): QDialog(parent)
31 {
32 	setupUi(this);
33 
34 	currentConstraintTextEdit->setReadOnly(true);
35 
36 	modifyConstraintPushButton->setDefault(true);
37 
38 	constraintsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
39 
40 	connect(constraintsListWidget, SIGNAL(currentRowChanged(int)), this, SLOT(constraintChanged(int)));
41 	connect(addConstraintPushButton, SIGNAL(clicked()), this, SLOT(addConstraint()));
42 	connect(closePushButton, SIGNAL(clicked()), this, SLOT(close()));
43 	connect(removeConstraintPushButton, SIGNAL(clicked()), this, SLOT(removeConstraint()));
44 	connect(modifyConstraintPushButton, SIGNAL(clicked()), this, SLOT(modifyConstraint()));
45 	connect(constraintsListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(modifyConstraint()));
46 
47 	connect(helpPushButton, SIGNAL(clicked()), this, SLOT(help()));
48 
49 	centerWidgetOnScreen(this);
50 	restoreFETDialogGeometry(this);
51 
52 	QSize tmp1=teachersComboBox->minimumSizeHint();
53 	Q_UNUSED(tmp1);
54 	QSize tmp2=studentsComboBox->minimumSizeHint();
55 	Q_UNUSED(tmp2);
56 	QSize tmp3=subjectsComboBox->minimumSizeHint();
57 	Q_UNUSED(tmp3);
58 	QSize tmp4=activityTagsComboBox->minimumSizeHint();
59 	Q_UNUSED(tmp4);
60 
61 /////////////
62 	teachersComboBox->addItem("");
63 	for(int i=0; i<gt.rules.teachersList.size(); i++){
64 		Teacher* tch=gt.rules.teachersList[i];
65 		teachersComboBox->addItem(tch->name);
66 	}
67 	teachersComboBox->setCurrentIndex(0);
68 
69 	subjectsComboBox->addItem("");
70 	for(int i=0; i<gt.rules.subjectsList.size(); i++){
71 		Subject* sb=gt.rules.subjectsList[i];
72 		subjectsComboBox->addItem(sb->name);
73 	}
74 	subjectsComboBox->setCurrentIndex(0);
75 
76 	activityTagsComboBox->addItem("");
77 	for(int i=0; i<gt.rules.activityTagsList.size(); i++){
78 		ActivityTag* st=gt.rules.activityTagsList[i];
79 		activityTagsComboBox->addItem(st->name);
80 	}
81 	activityTagsComboBox->setCurrentIndex(0);
82 
83 	populateStudentsComboBox(studentsComboBox, QString(""), true);
84 	studentsComboBox->setCurrentIndex(0);
85 ///////////////
86 
87 	this->filterChanged();
88 
89 	connect(teachersComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterChanged()));
90 	connect(studentsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterChanged()));
91 	connect(subjectsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterChanged()));
92 	connect(activityTagsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterChanged()));
93 }
94 
~ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm()95 ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::~ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm()
96 {
97 	saveFETDialogGeometry(this);
98 }
99 
filterOk(TimeConstraint * ctr)100 bool ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::filterOk(TimeConstraint* ctr)
101 {
102 	if(ctr->type!=CONSTRAINT_ACTIVITIES_OCCUPY_MAX_TIME_SLOTS_FROM_SELECTION)
103 		return false;
104 
105 	ConstraintActivitiesOccupyMaxTimeSlotsFromSelection* c=(ConstraintActivitiesOccupyMaxTimeSlotsFromSelection*) ctr;
106 
107 	QString tn=teachersComboBox->currentText();
108 	QString sbn=subjectsComboBox->currentText();
109 	QString atn=activityTagsComboBox->currentText();
110 	QString stn=studentsComboBox->currentText();
111 
112 	if(tn=="" && sbn=="" && atn=="" && stn=="")
113 		return true;
114 
115 	bool foundTeacher=false, foundStudents=false, foundSubject=false, foundActivityTag=false;
116 
117 	for(int i=0; i<c->activitiesIds.count(); i++){
118 		int id=c->activitiesIds.at(i);
119 		/*Activity* act=nullptr;
120 		for(Activity* a : qAsConst(gt.rules.activitiesList))
121 			if(a->id==id)
122 				act=a;*/
123 		Activity* act=gt.rules.activitiesPointerHash.value(id, nullptr);
124 
125 		if(act!=nullptr){
126 			//teacher
127 			if(tn!=""){
128 				bool ok2=false;
129 				for(QStringList::const_iterator it=act->teachersNames.constBegin(); it!=act->teachersNames.constEnd(); it++)
130 					if(*it == tn){
131 						ok2=true;
132 						break;
133 					}
134 				if(ok2)
135 					foundTeacher=true;
136 			}
137 			else
138 				foundTeacher=true;
139 
140 			//subject
141 			if(sbn!="" && sbn!=act->subjectName)
142 				;
143 			else
144 				foundSubject=true;
145 
146 			//activity tag
147 			if(atn!="" && !act->activityTagsNames.contains(atn))
148 				;
149 			else
150 				foundActivityTag=true;
151 
152 			//students
153 			if(stn!=""){
154 				bool ok2=false;
155 				for(QStringList::const_iterator it=act->studentsNames.constBegin(); it!=act->studentsNames.constEnd(); it++)
156 					if(*it == stn){
157 						ok2=true;
158 						break;
159 				}
160 				if(ok2)
161 					foundStudents=true;
162 			}
163 			else
164 				foundStudents=true;
165 		}
166 	}
167 
168 	if(foundTeacher && foundStudents && foundSubject && foundActivityTag)
169 		return true;
170 	else
171 		return false;
172 }
173 
filterChanged()174 void ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::filterChanged()
175 {
176 	this->visibleConstraintsList.clear();
177 	constraintsListWidget->clear();
178 	for(int i=0; i<gt.rules.timeConstraintsList.size(); i++){
179 		TimeConstraint* ctr=gt.rules.timeConstraintsList[i];
180 		if(filterOk(ctr)){
181 			visibleConstraintsList.append(ctr);
182 			constraintsListWidget->addItem(ctr->getDescription(gt.rules));
183 		}
184 	}
185 
186 	if(constraintsListWidget->count()>0)
187 		constraintsListWidget->setCurrentRow(0);
188 	else
189 		constraintChanged(-1);
190 }
191 
constraintChanged(int index)192 void ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::constraintChanged(int index)
193 {
194 	if(index<0){
195 		currentConstraintTextEdit->setPlainText("");
196 		return;
197 	}
198 	assert(index<this->visibleConstraintsList.size());
199 	TimeConstraint* ctr=this->visibleConstraintsList.at(index);
200 	assert(ctr!=nullptr);
201 	currentConstraintTextEdit->setPlainText(ctr->getDetailedDescription(gt.rules));
202 }
203 
addConstraint()204 void ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::addConstraint()
205 {
206 	AddConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm form(this);
207 	setParentAndOtherThings(&form, this);
208 	form.exec();
209 
210 	filterChanged();
211 
212 	constraintsListWidget->setCurrentRow(constraintsListWidget->count()-1);
213 }
214 
modifyConstraint()215 void ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::modifyConstraint()
216 {
217 	int valv=constraintsListWidget->verticalScrollBar()->value();
218 	int valh=constraintsListWidget->horizontalScrollBar()->value();
219 
220 	int i=constraintsListWidget->currentRow();
221 	if(i<0){
222 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected constraint"));
223 		return;
224 	}
225 	TimeConstraint* ctr=this->visibleConstraintsList.at(i);
226 
227 	ModifyConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm form(this, (ConstraintActivitiesOccupyMaxTimeSlotsFromSelection*)ctr);
228 	setParentAndOtherThings(&form, this);
229 	form.exec();
230 
231 	filterChanged();
232 
233 	constraintsListWidget->verticalScrollBar()->setValue(valv);
234 	constraintsListWidget->horizontalScrollBar()->setValue(valh);
235 
236 	if(i>=constraintsListWidget->count())
237 		i=constraintsListWidget->count()-1;
238 
239 	if(i>=0)
240 		constraintsListWidget->setCurrentRow(i);
241 	else
242 		this->constraintChanged(-1);
243 }
244 
removeConstraint()245 void ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::removeConstraint()
246 {
247 	int i=constraintsListWidget->currentRow();
248 	if(i<0){
249 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected constraint"));
250 		return;
251 	}
252 	TimeConstraint* ctr=this->visibleConstraintsList.at(i);
253 	QString s;
254 	s=tr("Remove constraint?");
255 	s+="\n\n";
256 	s+=ctr->getDetailedDescription(gt.rules);
257 
258 	QListWidgetItem* item;
259 
260 	switch( LongTextMessageBox::confirmation( this, tr("FET confirmation"),
261 		s, tr("Yes"), tr("No"), 0, 0, 1 ) ){
262 	case 0: // The user clicked the OK button or pressed Enter
263 		gt.rules.removeTimeConstraint(ctr);
264 
265 		visibleConstraintsList.removeAt(i);
266 		constraintsListWidget->setCurrentRow(-1);
267 		item=constraintsListWidget->takeItem(i);
268 		delete item;
269 
270 		break;
271 	case 1: // The user clicked the Cancel button or pressed Escape
272 		break;
273 	}
274 
275 	if(i>=constraintsListWidget->count())
276 		i=constraintsListWidget->count()-1;
277 	if(i>=0)
278 		constraintsListWidget->setCurrentRow(i);
279 	else
280 		this->constraintChanged(-1);
281 }
282 
help()283 void ConstraintActivitiesOccupyMaxTimeSlotsFromSelectionForm::help()
284 {
285 	QString s=QString("");
286 
287 	s+=tr("IMPORTANT NOTE: Please use this constraint ONLY when strictly necessary, when it is really useful, when it has effect, "
288 	 "when it is not implied by the other constraints, and in a non-redundant way. Otherwise it may slow down very much the generation.");
289 	s+=QString("\n\n");
290 	s+=tr("This constraint type was added on 25 September 2011.");
291 	s+=QString("\n\n");
292 	s+=tr("To use this constraint, you need to specify a set of activities, a set of time slots, and a maximum number "
293 	 "of time slots from those selected which can be occupied by the specified activities.");
294 	s+=QString("\n\n");
295 	s+=tr("Uses of this constraint are probably very wide. The main reason it was added was to enable users to specify that a teacher "
296 	 "should have activities in certain time slots. Example: we have a week with 30 hours. Teacher T has 20 hours of activities, and "
297 	 "we would like him to have activities Monday and Tuesday on the first two hours. Add a constraint of this type, with the set of activities "
298 	 "being all the activities of teacher T, selected time slots being the remaining 30-2*2=26 slots of the week, and the maximum number of "
299 	 "selected time slots which can be occupied by these activities being 20-2*2=16.");
300 	s+=QString(" ");
301 	s+=tr("Please note that more recently it was added the constraint of type activities occupy min time slots from selection. This permits to specify "
302 	 "easier/directly the times when a teacher should have activities.");
303 
304 	LongTextMessageBox::largeInformation(this, tr("FET help"), s);
305 }
306