1 //
2 //
3 // Description: This file is part of FET
4 //
5 //
6 // Author: Lalescu Liviu <Please see https://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)>
7 // Copyright (C) 2003 Liviu Lalescu <https://lalescu.ro/liviu/>
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 "addstudentssubgroupform.h"
19 #include "addexistingstudentssubgroupsform.h"
20 #include "modifystudentssubgroupform.h"
21 #include "subgroupsform.h"
22 #include "timetable_defs.h"
23 #include "timetable.h"
24 #include "fet.h"
25 
26 #include "longtextmessagebox.h"
27 
28 #include <QMessageBox>
29 
30 #include <QListWidget>
31 #include <QScrollBar>
32 #include <QAbstractItemView>
33 
34 #include <QSplitter>
35 #include <QSettings>
36 #include <QObject>
37 #include <QMetaObject>
38 
39 #include <QSet>
40 #include <QList>
41 #include <QPair>
42 
43 extern const QString COMPANY;
44 extern const QString PROGRAM;
45 
46 extern bool students_schedule_ready;
47 extern bool rooms_schedule_ready;
48 extern bool teachers_schedule_ready;
49 
SubgroupsForm(QWidget * parent)50 SubgroupsForm::SubgroupsForm(QWidget* parent): QDialog(parent)
51 {
52 	setupUi(this);
53 
54 	subgroupTextEdit->setReadOnly(true);
55 
56 	modifySubgroupPushButton->setDefault(true);
57 
58 	yearsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
59 	groupsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
60 	subgroupsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
61 
62 	connect(yearsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(yearChanged(const QString&)));
63 	connect(groupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(groupChanged(const QString&)));
64 	connect(addSubgroupPushButton, SIGNAL(clicked()), this, SLOT(addSubgroup()));
65 	connect(addExistingSubgroupsPushButton, SIGNAL(clicked()), this, SLOT(addExistingSubgroups()));
66 	connect(removeSubgroupPushButton, SIGNAL(clicked()), this, SLOT(removeSubgroup()));
67 	connect(purgeSubgroupPushButton, SIGNAL(clicked()), this, SLOT(purgeSubgroup()));
68 	connect(closePushButton, SIGNAL(clicked()), this, SLOT(close()));
69 	connect(subgroupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(subgroupChanged(const QString&)));
70 	connect(modifySubgroupPushButton, SIGNAL(clicked()), this, SLOT(modifySubgroup()));
71 
72 	connect(moveSubgroupUpPushButton, SIGNAL(clicked()), this, SLOT(moveSubgroupUp()));
73 	connect(moveSubgroupDownPushButton, SIGNAL(clicked()), this, SLOT(moveSubgroupDown()));
74 
75 	connect(sortSubgroupsPushButton, SIGNAL(clicked()), this, SLOT(sortSubgroups()));
76 	connect(activateStudentsPushButton, SIGNAL(clicked()), this, SLOT(activateStudents()));
77 	connect(deactivateStudentsPushButton, SIGNAL(clicked()), this, SLOT(deactivateStudents()));
78 	connect(subgroupsListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(modifySubgroup()));
79 
80 	connect(commentsPushButton, SIGNAL(clicked()), this, SLOT(comments()));
81 
82 	centerWidgetOnScreen(this);
83 	restoreFETDialogGeometry(this);
84 	//restore splitter state
85 	QSettings settings(COMPANY, PROGRAM);
86 	if(settings.contains(this->metaObject()->className()+QString("/splitter-state")))
87 		splitter->restoreState(settings.value(this->metaObject()->className()+QString("/splitter-state")).toByteArray());
88 
89 	yearsListWidget->clear();
90 	for(int i=0; i<gt.rules.yearsList.size(); i++){
91 		StudentsYear* year=gt.rules.yearsList[i];
92 		yearsListWidget->addItem(year->name);
93 	}
94 
95 	if(yearsListWidget->count()>0)
96 		yearsListWidget->setCurrentRow(0);
97 	else{
98 		groupsListWidget->clear();
99 		subgroupsListWidget->clear();
100 	}
101 }
102 
~SubgroupsForm()103 SubgroupsForm::~SubgroupsForm()
104 {
105 	saveFETDialogGeometry(this);
106 	//save splitter state
107 	QSettings settings(COMPANY, PROGRAM);
108 	settings.setValue(this->metaObject()->className()+QString("/splitter-state"), splitter->saveState());
109 }
110 
addSubgroup()111 void SubgroupsForm::addSubgroup()
112 {
113 	if(yearsListWidget->currentRow()<0){
114 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
115 		return;
116 	}
117 	QString yearName=yearsListWidget->currentItem()->text();
118 	int yearIndex=gt.rules.searchYear(yearName);
119 	assert(yearIndex>=0);
120 
121 	if(groupsListWidget->currentRow()<0){
122 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
123 		return;
124 	}
125 	QString groupName=groupsListWidget->currentItem()->text();
126 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
127 	assert(groupIndex>=0);
128 
129 	AddStudentsSubgroupForm form(this, yearName, groupName);
130 	setParentAndOtherThings(&form, this);
131 	form.exec();
132 
133 	groupChanged(groupsListWidget->currentItem()->text());
134 
135 	int i=subgroupsListWidget->count()-1;
136 	if(i>=0)
137 		subgroupsListWidget->setCurrentRow(i);
138 }
139 
addExistingSubgroups()140 void SubgroupsForm::addExistingSubgroups()
141 {
142 	if(yearsListWidget->currentRow()<0){
143 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
144 		return;
145 	}
146 	QString yearName=yearsListWidget->currentItem()->text();
147 
148 	StudentsYear* year=nullptr;
149 
150 	for(StudentsYear* sty : qAsConst(gt.rules.yearsList))
151 		if(sty->name==yearName){
152 			year=sty;
153 			break;
154 		}
155 
156 	assert(year!=nullptr);
157 
158 	if(groupsListWidget->currentRow()<0){
159 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
160 		return;
161 	}
162 	QString groupName=groupsListWidget->currentItem()->text();
163 
164 	StudentsGroup* group=nullptr;
165 
166 	for(StudentsGroup* stg : qAsConst(year->groupsList))
167 		if(stg->name==groupName){
168 			group=stg;
169 			break;
170 		}
171 
172 	assert(group!=nullptr);
173 
174 	AddExistingStudentsSubgroupsForm form(this, year, group);
175 	setParentAndOtherThings(&form, this);
176 	int t=form.exec();
177 
178 	if(t==QDialog::Accepted){
179 		groupChanged(groupsListWidget->currentItem()->text());
180 
181 		int i=subgroupsListWidget->count()-1;
182 		if(i>=0)
183 			subgroupsListWidget->setCurrentRow(i);
184 	}
185 	else{
186 		assert(t==QDialog::Rejected);
187 	}
188 }
189 
removeSubgroup()190 void SubgroupsForm::removeSubgroup()
191 {
192 	if(yearsListWidget->currentRow()<0){
193 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
194 		return;
195 	}
196 	QString yearName=yearsListWidget->currentItem()->text();
197 	int yearIndex=gt.rules.searchYear(yearName);
198 	assert(yearIndex>=0);
199 
200 	if(groupsListWidget->currentRow()<0){
201 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
202 		return;
203 	}
204 	QString groupName=groupsListWidget->currentItem()->text();
205 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
206 	assert(groupIndex>=0);
207 
208 	if(subgroupsListWidget->currentRow()<0){
209 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected subgroup"));
210 		return;
211 	}
212 
213 	QString subgroupName=subgroupsListWidget->currentItem()->text();
214 	int subgroupIndex=gt.rules.searchSubgroup(yearName, groupName, subgroupName);
215 	assert(subgroupIndex>=0);
216 
217 	QList<QPair<QString, QString>> yearsGroupsContainingSubgroup_List;
218 	//QSet<QPair<QString, QString>> yearsGroupsContainingSubgroup_Set;
219 	for(StudentsYear* year : qAsConst(gt.rules.yearsList))
220 		for(StudentsGroup* group : qAsConst(year->groupsList))
221 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
222 				if(subgroup->name==subgroupName)
223 					yearsGroupsContainingSubgroup_List.append(QPair<QString, QString>(year->name, group->name));
224 
225 	assert(yearsGroupsContainingSubgroup_List.count()>=1);
226 	QString s;
227 	if(yearsGroupsContainingSubgroup_List.count()==1)
228 		s=tr("This subgroup exists only in year %1, group %2. This means that"
229 		 " all the related activities and constraints will be removed. Do you want to continue?").arg(yearName).arg(groupName);
230 	else{
231 		s=tr("This subgroup exists in more places, listed below. It will only be removed from the current year/group,"
232 		 " and the related activities and constraints will not be removed. Do you want to continue?");
233 		s+="\n";
234 		for(const QPair<QString, QString>& pair : qAsConst(yearsGroupsContainingSubgroup_List))
235 			s+=QString("\n")+pair.first+QString(", ")+pair.second;
236 	}
237 
238 	int t=LongTextMessageBox::mediumConfirmation(this, tr("FET confirmation"), s,
239 		tr("Yes"), tr("No"), QString(), 0, 1);
240 	if(t==1)
241 		return;
242 
243 	/*if(QMessageBox::warning( this, tr("FET"),
244 		tr("Are you sure you want to delete subgroup %1 and all related activities and constraints?").arg(subgroupName),
245 		tr("Yes"), tr("No"), 0, 0, 1 ) == 1)
246 		return;*/
247 
248 	bool tmp=gt.rules.removeSubgroup(yearName, groupName, subgroupName);
249 	assert(tmp);
250 	if(tmp){
251 		int q=subgroupsListWidget->currentRow();
252 
253 		subgroupsListWidget->setCurrentRow(-1);
254 		QListWidgetItem* item;
255 		item=subgroupsListWidget->takeItem(q);
256 		delete item;
257 
258 		if(q>=subgroupsListWidget->count())
259 			q=subgroupsListWidget->count()-1;
260 		if(q>=0)
261 			subgroupsListWidget->setCurrentRow(q);
262 		else
263 			subgroupTextEdit->setPlainText(QString(""));
264 	}
265 
266 	/*if(gt.rules.searchStudentsSet(subgroupName)!=nullptr)
267 		QMessageBox::information( this, tr("FET"), tr("This subgroup still exists into another group. "
268 		"The related activities and constraints were not removed"));*/
269 }
270 
purgeSubgroup()271 void SubgroupsForm::purgeSubgroup()
272 {
273 	if(yearsListWidget->currentRow()<0){
274 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
275 		return;
276 	}
277 	QString yearName=yearsListWidget->currentItem()->text();
278 	int yearIndex=gt.rules.searchYear(yearName);
279 	assert(yearIndex>=0);
280 
281 	if(groupsListWidget->currentRow()<0){
282 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
283 		return;
284 	}
285 	QString groupName=groupsListWidget->currentItem()->text();
286 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
287 	assert(groupIndex>=0);
288 
289 	if(subgroupsListWidget->currentRow()<0){
290 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected subgroup"));
291 		return;
292 	}
293 
294 	QString subgroupName=subgroupsListWidget->currentItem()->text();
295 	int subgroupIndex=gt.rules.searchSubgroup(yearName, groupName, subgroupName);
296 	assert(subgroupIndex>=0);
297 
298 	QList<QPair<QString, QString>> yearsGroupsContainingSubgroup_List;
299 	//QSet<QPair<QString, QString>> yearsGroupsContainingSubgroup_Set;
300 	for(StudentsYear* year : qAsConst(gt.rules.yearsList))
301 		for(StudentsGroup* group : qAsConst(year->groupsList))
302 			for(StudentsSubgroup* subgroup : qAsConst(group->subgroupsList))
303 				if(subgroup->name==subgroupName)
304 					yearsGroupsContainingSubgroup_List.append(QPair<QString, QString>(year->name, group->name));
305 
306 	assert(yearsGroupsContainingSubgroup_List.count()>=1);
307 	QString s;
308 	if(yearsGroupsContainingSubgroup_List.count()==1)
309 		s=tr("This subgroup exists only in year %1, group %2. All the related activities and constraints "
310 		 "will be removed. Do you want to continue?").arg(yearName).arg(groupName);
311 	else{
312 		s=tr("This subgroup exists in more places, listed below. It will be removed from all these places."
313 		 " All the related activities and constraints will be removed. Do you want to continue?");
314 		s+="\n";
315 		for(const QPair<QString, QString>& pair : qAsConst(yearsGroupsContainingSubgroup_List))
316 			s+=QString("\n")+pair.first+QString(", ")+pair.second;
317 	}
318 
319 	int t=LongTextMessageBox::mediumConfirmation(this, tr("FET confirmation"), s,
320 		tr("Yes"), tr("No"), QString(), 0, 1);
321 	if(t==1)
322 		return;
323 
324 	/*if(QMessageBox::warning( this, tr("FET"),
325 		tr("Are you sure you want to delete subgroup %1 and all related activities and constraints?").arg(subgroupName),
326 		tr("Yes"), tr("No"), 0, 0, 1 ) == 1)
327 		return;*/
328 
329 	bool tmp=gt.rules.purgeSubgroup(subgroupName);
330 	assert(tmp);
331 	if(tmp){
332 		int q=subgroupsListWidget->currentRow();
333 
334 		subgroupsListWidget->setCurrentRow(-1);
335 		QListWidgetItem* item;
336 		item=subgroupsListWidget->takeItem(q);
337 		delete item;
338 
339 		if(q>=subgroupsListWidget->count())
340 			q=subgroupsListWidget->count()-1;
341 		if(q>=0)
342 			subgroupsListWidget->setCurrentRow(q);
343 		else
344 			subgroupTextEdit->setPlainText(QString(""));
345 	}
346 
347 	/*if(gt.rules.searchStudentsSet(subgroupName)!=nullptr)
348 		QMessageBox::information( this, tr("FET"), tr("This subgroup still exists into another group. "
349 		"The related activities and constraints were not removed"));*/
350 }
351 
yearChanged(const QString & yearName)352 void SubgroupsForm::yearChanged(const QString &yearName)
353 {
354 	int yearIndex=gt.rules.searchYear(yearName);
355 	if(yearIndex<0){
356 		groupsListWidget->clear();
357 		subgroupsListWidget->clear();
358 		subgroupTextEdit->setPlainText(QString(""));
359 		return;
360 	}
361 	StudentsYear* sty=gt.rules.yearsList.at(yearIndex);
362 
363 	groupsListWidget->clear();
364 	for(int i=0; i<sty->groupsList.size(); i++){
365 		StudentsGroup* stg=sty->groupsList[i];
366 		groupsListWidget->addItem(stg->name);
367 	}
368 
369 	if(groupsListWidget->count()>0)
370 		groupsListWidget->setCurrentRow(0);
371 	else{
372 		subgroupsListWidget->clear();
373 		subgroupTextEdit->setPlainText(QString(""));
374 	}
375 }
376 
groupChanged(const QString & groupName)377 void SubgroupsForm::groupChanged(const QString &groupName)
378 {
379 	QString yearName=yearsListWidget->currentItem()->text();
380 	int yearIndex=gt.rules.searchYear(yearName);
381 	if(yearIndex<0){
382 		return;
383 	}
384 	StudentsYear* sty=gt.rules.yearsList.at(yearIndex);
385 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
386 	if(groupIndex<0){
387 		subgroupsListWidget->clear();
388 		subgroupTextEdit->setPlainText(QString(""));
389 		return;
390 	}
391 
392 	StudentsGroup* stg=sty->groupsList.at(groupIndex);
393 
394 	subgroupsListWidget->clear();
395 	for(int i=0; i<stg->subgroupsList.size(); i++){
396 		StudentsSubgroup* sts=stg->subgroupsList[i];
397 		subgroupsListWidget->addItem(sts->name);
398 	}
399 
400 	if(subgroupsListWidget->count()>0)
401 		subgroupsListWidget->setCurrentRow(0);
402 	else
403 		subgroupTextEdit->setPlainText(QString(""));
404 }
405 
subgroupChanged(const QString & subgroupName)406 void SubgroupsForm::subgroupChanged(const QString &subgroupName)
407 {
408 	StudentsSet* ss=gt.rules.searchStudentsSet(subgroupName);
409 	if(ss==nullptr){
410 		subgroupTextEdit->setPlainText(QString(""));
411 		return;
412 	}
413 	StudentsSubgroup* s=(StudentsSubgroup*)ss;
414 	subgroupTextEdit->setPlainText(s->getDetailedDescriptionWithConstraints(gt.rules));
415 }
416 
moveSubgroupUp()417 void SubgroupsForm::moveSubgroupUp()
418 {
419 	if(subgroupsListWidget->count()<=1)
420 		return;
421 	int i=subgroupsListWidget->currentRow();
422 	if(i<0 || i>=subgroupsListWidget->count())
423 		return;
424 	if(i==0)
425 		return;
426 
427 	QString s1=subgroupsListWidget->item(i)->text();
428 	QString s2=subgroupsListWidget->item(i-1)->text();
429 
430 	assert(yearsListWidget->currentRow()>=0);
431 	assert(yearsListWidget->currentRow()<gt.rules.yearsList.count());
432 	StudentsYear* sy=gt.rules.yearsList.at(yearsListWidget->currentRow());
433 
434 	assert(groupsListWidget->currentRow()>=0);
435 	assert(groupsListWidget->currentRow()<sy->groupsList.count());
436 	StudentsGroup* sg=sy->groupsList.at(groupsListWidget->currentRow());
437 
438 	StudentsSubgroup* ss1=sg->subgroupsList.at(i);
439 	StudentsSubgroup* ss2=sg->subgroupsList.at(i-1);
440 
441 	gt.rules.internalStructureComputed=false;
442 	setRulesModifiedAndOtherThings(&gt.rules);
443 
444 	teachers_schedule_ready=false;
445 	students_schedule_ready=false;
446 	rooms_schedule_ready=false;
447 
448 	subgroupsListWidget->item(i)->setText(s2);
449 	subgroupsListWidget->item(i-1)->setText(s1);
450 
451 	sg->subgroupsList[i]=ss2;
452 	sg->subgroupsList[i-1]=ss1;
453 
454 	subgroupsListWidget->setCurrentRow(i-1);
455 	subgroupChanged(/*i-1*/s1);
456 }
457 
moveSubgroupDown()458 void SubgroupsForm::moveSubgroupDown()
459 {
460 	if(subgroupsListWidget->count()<=1)
461 		return;
462 	int i=subgroupsListWidget->currentRow();
463 	if(i<0 || i>=subgroupsListWidget->count())
464 		return;
465 	if(i==subgroupsListWidget->count()-1)
466 		return;
467 
468 	QString s1=subgroupsListWidget->item(i)->text();
469 	QString s2=subgroupsListWidget->item(i+1)->text();
470 
471 	assert(yearsListWidget->currentRow()>=0);
472 	assert(yearsListWidget->currentRow()<gt.rules.yearsList.count());
473 	StudentsYear* sy=gt.rules.yearsList.at(yearsListWidget->currentRow());
474 
475 	assert(groupsListWidget->currentRow()>=0);
476 	assert(groupsListWidget->currentRow()<sy->groupsList.count());
477 	StudentsGroup* sg=sy->groupsList.at(groupsListWidget->currentRow());
478 
479 	StudentsSubgroup* ss1=sg->subgroupsList.at(i);
480 	StudentsSubgroup* ss2=sg->subgroupsList.at(i+1);
481 
482 	gt.rules.internalStructureComputed=false;
483 	setRulesModifiedAndOtherThings(&gt.rules);
484 
485 	teachers_schedule_ready=false;
486 	students_schedule_ready=false;
487 	rooms_schedule_ready=false;
488 
489 	subgroupsListWidget->item(i)->setText(s2);
490 	subgroupsListWidget->item(i+1)->setText(s1);
491 
492 	sg->subgroupsList[i]=ss2;
493 	sg->subgroupsList[i+1]=ss1;
494 
495 	subgroupsListWidget->setCurrentRow(i+1);
496 	subgroupChanged(/*i+1*/s1);
497 }
498 
sortSubgroups()499 void SubgroupsForm::sortSubgroups()
500 {
501 	if(yearsListWidget->currentRow()<0){
502 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
503 		return;
504 	}
505 	QString yearName=yearsListWidget->currentItem()->text();
506 	int yearIndex=gt.rules.searchYear(yearName);
507 	assert(yearIndex>=0);
508 
509 	if(groupsListWidget->currentRow()<0){
510 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
511 		return;
512 	}
513 	QString groupName=groupsListWidget->currentItem()->text();
514 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
515 	assert(groupIndex>=0);
516 
517 	gt.rules.sortSubgroupsAlphabetically(yearName, groupName);
518 
519 	groupChanged(groupName);
520 }
521 
modifySubgroup()522 void SubgroupsForm::modifySubgroup()
523 {
524 	if(yearsListWidget->currentRow()<0){
525 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
526 		return;
527 	}
528 	QString yearName=yearsListWidget->currentItem()->text();
529 	int yearIndex=gt.rules.searchYear(yearName);
530 	assert(yearIndex>=0);
531 
532 	if(groupsListWidget->currentRow()<0){
533 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
534 		return;
535 	}
536 	QString groupName=groupsListWidget->currentItem()->text();
537 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
538 	assert(groupIndex>=0);
539 
540 	int q=subgroupsListWidget->currentRow();
541 	int valv=subgroupsListWidget->verticalScrollBar()->value();
542 	int valh=subgroupsListWidget->horizontalScrollBar()->value();
543 
544 	if(subgroupsListWidget->currentRow()<0){
545 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected subgroup"));
546 		return;
547 	}
548 	QString subgroupName=subgroupsListWidget->currentItem()->text();
549 	int subgroupIndex=gt.rules.searchSubgroup(yearName, groupName, subgroupName);
550 	assert(subgroupIndex>=0);
551 
552 	StudentsSet* studentsSet=gt.rules.searchStudentsSet(subgroupName);
553 	assert(studentsSet!=nullptr);
554 	int numberOfStudents=studentsSet->numberOfStudents;
555 
556 	ModifyStudentsSubgroupForm form(this, yearName, groupName, subgroupName, numberOfStudents);
557 	setParentAndOtherThings(&form, this);
558 	form.exec();
559 
560 	groupChanged(groupName);
561 
562 	subgroupsListWidget->verticalScrollBar()->setValue(valv);
563 	subgroupsListWidget->horizontalScrollBar()->setValue(valh);
564 
565 	if(q>=subgroupsListWidget->count())
566 		q=subgroupsListWidget->count()-1;
567 	if(q>=0)
568 		subgroupsListWidget->setCurrentRow(q);
569 	else
570 		subgroupTextEdit->setPlainText(QString(""));
571 }
572 
activateStudents()573 void SubgroupsForm::activateStudents()
574 {
575 	if(yearsListWidget->currentRow()<0){
576 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
577 		return;
578 	}
579 	QString yearName=yearsListWidget->currentItem()->text();
580 	int yearIndex=gt.rules.searchYear(yearName);
581 	assert(yearIndex>=0);
582 
583 	if(groupsListWidget->currentRow()<0){
584 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
585 		return;
586 	}
587 	QString groupName=groupsListWidget->currentItem()->text();
588 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
589 	assert(groupIndex>=0);
590 
591 	if(subgroupsListWidget->currentRow()<0){
592 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected subgroup"));
593 		return;
594 	}
595 
596 	QString subgroupName=subgroupsListWidget->currentItem()->text();
597 	int count=gt.rules.activateStudents(subgroupName);
598 	QMessageBox::information(this, tr("FET information"), tr("Activated a number of %1 activities").arg(count));
599 }
600 
deactivateStudents()601 void SubgroupsForm::deactivateStudents()
602 {
603 	if(yearsListWidget->currentRow()<0){
604 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected year"));
605 		return;
606 	}
607 	QString yearName=yearsListWidget->currentItem()->text();
608 	int yearIndex=gt.rules.searchYear(yearName);
609 	assert(yearIndex>=0);
610 
611 	if(groupsListWidget->currentRow()<0){
612 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected group"));
613 		return;
614 	}
615 	QString groupName=groupsListWidget->currentItem()->text();
616 	int groupIndex=gt.rules.searchGroup(yearName, groupName);
617 	assert(groupIndex>=0);
618 
619 	if(subgroupsListWidget->currentRow()<0){
620 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected subgroup"));
621 		return;
622 	}
623 
624 	QString subgroupName=subgroupsListWidget->currentItem()->text();
625 	int count=gt.rules.deactivateStudents(subgroupName);
626 	QMessageBox::information(this, tr("FET information"), tr("De-activated a number of %1 activities").arg(count));
627 }
628 
comments()629 void SubgroupsForm::comments()
630 {
631 	int ind=subgroupsListWidget->currentRow();
632 	if(ind<0){
633 		QMessageBox::information(this, tr("FET information"), tr("Invalid selected subgroup"));
634 		return;
635 	}
636 
637 	QString subgroupName=subgroupsListWidget->currentItem()->text();
638 
639 	StudentsSet* studentsSet=gt.rules.searchStudentsSet(subgroupName);
640 	assert(studentsSet!=nullptr);
641 
642 	QDialog getCommentsDialog(this);
643 
644 	getCommentsDialog.setWindowTitle(tr("Students subgroup comments"));
645 
646 	QPushButton* okPB=new QPushButton(tr("OK"));
647 	okPB->setDefault(true);
648 	QPushButton* cancelPB=new QPushButton(tr("Cancel"));
649 
650 	connect(okPB, SIGNAL(clicked()), &getCommentsDialog, SLOT(accept()));
651 	connect(cancelPB, SIGNAL(clicked()), &getCommentsDialog, SLOT(reject()));
652 
653 	QHBoxLayout* hl=new QHBoxLayout();
654 	hl->addStretch();
655 	hl->addWidget(okPB);
656 	hl->addWidget(cancelPB);
657 
658 	QVBoxLayout* vl=new QVBoxLayout();
659 
660 	QPlainTextEdit* commentsPT=new QPlainTextEdit();
661 	commentsPT->setPlainText(studentsSet->comments);
662 	commentsPT->selectAll();
663 	commentsPT->setFocus();
664 
665 	vl->addWidget(commentsPT);
666 	vl->addLayout(hl);
667 
668 	getCommentsDialog.setLayout(vl);
669 
670 	const QString settingsName=QString("StudentsSubgroupCommentsDialog");
671 
672 	getCommentsDialog.resize(500, 320);
673 	centerWidgetOnScreen(&getCommentsDialog);
674 	restoreFETDialogGeometry(&getCommentsDialog, settingsName);
675 
676 	int t=getCommentsDialog.exec();
677 	saveFETDialogGeometry(&getCommentsDialog, settingsName);
678 
679 	if(t==QDialog::Accepted){
680 		studentsSet->comments=commentsPT->toPlainText();
681 
682 		gt.rules.internalStructureComputed=false;
683 		setRulesModifiedAndOtherThings(&gt.rules);
684 
685 		subgroupChanged(subgroupName);
686 	}
687 }
688