Back to index

fet  5.18.0
timetableviewstudentsform.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           timetableviewstudentsform.cpp  -  description
00003                              -------------------
00004     begin                : Tue Apr 22 2003
00005     copyright            : (C) 2003 by Lalescu Liviu
00006     email                : Please see http://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "tablewidgetupdatebug.h"
00019 
00020 #include "longtextmessagebox.h"
00021 
00022 #include "fetmainform.h"
00023 #include "timetableviewstudentsform.h"
00024 #include "timetable_defs.h"
00025 #include "timetable.h"
00026 #include "fet.h"
00027 #include "solution.h"
00028 
00029 #include "matrix.h"
00030 
00031 #include "lockunlock.h"
00032 
00033 #include <QSplitter>
00034 #include <QList>
00035 
00036 #include <QMessageBox>
00037 
00038 #include <QTableWidget>
00039 #include <QTableWidgetItem>
00040 #include <QHeaderView>
00041 
00042 #include <QAbstractItemView>
00043 
00044 #include <QCoreApplication>
00045 #include <QApplication>
00046 
00047 #include <QString>
00048 #include <QStringList>
00049 
00050 #include <QSplitter>
00051 #include <QSettings>
00052 #include <QObject>
00053 #include <QMetaObject>
00054 
00055 extern const QString COMPANY;
00056 extern const QString PROGRAM;
00057 
00058 extern bool students_schedule_ready;
00059 extern bool teachers_schedule_ready;
00060 
00061 extern bool simulation_running;
00062 
00063 extern Solution best_solution;
00064 
00065 extern Matrix3D<bool> subgroupNotAvailableDayHour;
00066 extern Matrix2D<bool> breakDayHour;
00067 
00068 extern QSet <int> idsOfLockedTime;        //care about locked activities in view forms
00069 extern QSet <int> idsOfLockedSpace;              //care about locked activities in view forms
00070 extern QSet <int> idsOfPermanentlyLockedTime;    //care about locked activities in view forms
00071 extern QSet <int> idsOfPermanentlyLockedSpace;   //care about locked activities in view forms
00072 
00073 extern CommunicationSpinBox communicationSpinBox;       //small hint to sync the forms
00074 
00075 TimetableViewStudentsForm::TimetableViewStudentsForm(QWidget* parent): QDialog(parent)
00076 {
00077        setupUi(this);
00078        
00079        closePushButton->setDefault(true);
00080        
00081        detailsTextEdit->setReadOnly(true);
00082 
00083        //columnResizeModeInitialized=false;
00084 
00085        QList<int> tmpList2;
00086        tmpList2<<10000<<2500;
00087        verticalStudentsTableDetailsSplitter->setSizes(tmpList2);
00088        
00089        QList<int> tmpList3;
00090        tmpList3<<3000<<10000;
00091        horizontalSplitter->setSizes(tmpList3);
00092        
00093        studentsTimetableTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
00094        
00095        yearsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
00096        groupsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
00097        subgroupsListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
00098 
00099        groupsListWidget->clear();
00100        subgroupsListWidget->clear();
00101        
00102        connect(yearsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(yearChanged(const QString&)));
00103        connect(groupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(groupChanged(const QString&)));
00104        connect(subgroupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(subgroupChanged(const QString&)));
00105        connect(closePushButton, SIGNAL(clicked()), this, SLOT(close()));
00106        connect(studentsTimetableTable, SIGNAL(currentItemChanged(QTableWidgetItem*, QTableWidgetItem*)), this, SLOT(currentItemChanged(QTableWidgetItem*, QTableWidgetItem*)));
00107        connect(lockTimePushButton, SIGNAL(clicked()), this, SLOT(lockTime()));
00108        connect(lockSpacePushButton, SIGNAL(clicked()), this, SLOT(lockSpace()));
00109        connect(lockTimeSpacePushButton, SIGNAL(clicked()), this, SLOT(lockTimeSpace()));
00110        connect(helpPushButton, SIGNAL(clicked()), this, SLOT(help()));
00111 
00112        centerWidgetOnScreen(this);
00113        restoreFETDialogGeometry(this);
00114 
00115        //restore vertical students list splitter state
00116        QSettings settings(COMPANY, PROGRAM);
00117        if(settings.contains(this->metaObject()->className()+QString("/vertical-students-list-splitter-state")))
00118               verticalStudentsListSplitter->restoreState(settings.value(this->metaObject()->className()+QString("/vertical-students-list-splitter-state")).toByteArray());
00119 
00120        //restore vertical students table details splitter state
00121        //QSettings settings(COMPANY, PROGRAM);
00122        if(settings.contains(this->metaObject()->className()+QString("/vertical-students-table-details-splitter-state")))
00123               verticalStudentsTableDetailsSplitter->restoreState(settings.value(this->metaObject()->className()+QString("/vertical-students-table-details-splitter-state")).toByteArray());
00124 
00125        //restore horizontal splitter state
00126        //QSettings settings(COMPANY, PROGRAM);
00127        if(settings.contains(this->metaObject()->className()+QString("/horizontal-splitter-state")))
00128               horizontalSplitter->restoreState(settings.value(this->metaObject()->className()+QString("/horizontal-splitter-state")).toByteArray());
00129 
00131        QSet<int> backupLockedTime;
00132        QSet<int> backupPermanentlyLockedTime;
00133        QSet<int> backupLockedSpace;
00134        QSet<int> backupPermanentlyLockedSpace;
00135 
00136        backupLockedTime=idsOfLockedTime;
00137        backupPermanentlyLockedTime=idsOfPermanentlyLockedTime;
00138        backupLockedSpace=idsOfLockedSpace;
00139        backupPermanentlyLockedSpace=idsOfPermanentlyLockedSpace;
00140 
00141        //added by Volker Dirr
00142        //these lines are not really needed - just to be safer
00143        LockUnlock::computeLockedUnlockedActivitiesTimeSpace();
00144        
00145        assert(backupLockedTime==idsOfLockedTime);
00146        assert(backupPermanentlyLockedTime==idsOfPermanentlyLockedTime);
00147        assert(backupLockedSpace==idsOfLockedSpace);
00148        assert(backupPermanentlyLockedSpace==idsOfPermanentlyLockedSpace);
00150 
00151        LockUnlock::increaseCommunicationSpinBox();
00152 
00153        studentsTimetableTable->setRowCount(gt.rules.nHoursPerDay);
00154        studentsTimetableTable->setColumnCount(gt.rules.nDaysPerWeek);
00155        for(int j=0; j<gt.rules.nDaysPerWeek; j++){
00156               QTableWidgetItem* item=new QTableWidgetItem(gt.rules.daysOfTheWeek[j]);
00157               studentsTimetableTable->setHorizontalHeaderItem(j, item);
00158        }
00159        for(int i=0; i<gt.rules.nHoursPerDay; i++){
00160               QTableWidgetItem* item=new QTableWidgetItem(gt.rules.hoursOfTheDay[i]);
00161               studentsTimetableTable->setVerticalHeaderItem(i, item);
00162        }
00163        for(int j=0; j<gt.rules.nHoursPerDay; j++){
00164               for(int k=0; k<gt.rules.nDaysPerWeek; k++){
00165                      QTableWidgetItem* item= new QTableWidgetItem();
00166                      item->setTextAlignment(Qt::AlignCenter);
00167                      item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
00168 
00169                      studentsTimetableTable->setItem(j, k, item);
00170 
00171                      //if(j==0 && k==0)
00172                      //     teachersTimetableTable->setCurrentItem(item);
00173               }
00174        }
00175        
00176        //resize columns
00177        //if(!columnResizeModeInitialized){
00178        studentsTimetableTable->horizontalHeader()->setMinimumSectionSize(studentsTimetableTable->horizontalHeader()->defaultSectionSize());
00179        //     columnResizeModeInitialized=true;
00180        studentsTimetableTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
00181        //}
00183        
00184        yearsListWidget->clear();
00185        for(int i=0; i<gt.rules.augmentedYearsList.size(); i++){
00186               StudentsYear* sty=gt.rules.augmentedYearsList[i];
00187               yearsListWidget->addItem(sty->name);
00188        }
00189        if(yearsListWidget->count()>0)
00190               yearsListWidget->setCurrentRow(0);
00191 
00192        //added by Volker Dirr
00193        connect(&communicationSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateStudentsTimetableTable()));
00194 }
00195 
00196 TimetableViewStudentsForm::~TimetableViewStudentsForm()
00197 {
00198        saveFETDialogGeometry(this);
00199 
00200        //save vertical students list splitter state
00201        QSettings settings(COMPANY, PROGRAM);
00202        settings.setValue(this->metaObject()->className()+QString("/vertical-students-list-splitter-state"), verticalStudentsListSplitter->saveState());
00203 
00204        //save vertical students table details splitter state
00205        //QSettings settings(COMPANY, PROGRAM);
00206        settings.setValue(this->metaObject()->className()+QString("/vertical-students-table-details-splitter-state"), verticalStudentsTableDetailsSplitter->saveState());
00207 
00208        //save horizontal splitter state
00209        //QSettings settings(COMPANY, PROGRAM);
00210        settings.setValue(this->metaObject()->className()+QString("/horizontal-splitter-state"), horizontalSplitter->saveState());
00211 }
00212 
00213 void TimetableViewStudentsForm::resizeRowsAfterShow()
00214 {
00215        studentsTimetableTable->resizeRowsToContents();
00216 //     tableWidgetUpdateBug(studentsTimetableTable);
00217 }
00218 
00219 void TimetableViewStudentsForm::yearChanged(const QString &yearName)
00220 {
00221        if(!(students_schedule_ready && teachers_schedule_ready)){
00222               QMessageBox::warning(this, tr("FET warning"), tr("Timetable not available in view students timetable dialog - please generate a new timetable"));
00223               return;
00224        }
00225        assert(students_schedule_ready && teachers_schedule_ready);
00226 
00227        if(yearName==QString())
00228               return;
00229        int yearIndex=gt.rules.searchAugmentedYear(yearName);
00230        if(yearIndex<0){
00231               QMessageBox::warning(this, tr("FET warning"), tr("Invalid year - please close this dialog and open a new students view timetable dialog"));
00232               return;
00233        }
00234 
00235        disconnect(groupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(groupChanged(const QString&)));
00236 
00237        groupsListWidget->clear();
00238        StudentsYear* sty=gt.rules.augmentedYearsList.at(yearIndex);
00239        for(int i=0; i<sty->groupsList.size(); i++){
00240               StudentsGroup* stg=sty->groupsList[i];
00241               groupsListWidget->addItem(stg->name);
00242        }
00243 
00244        connect(groupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(groupChanged(const QString&)));
00245 
00246        if(groupsListWidget->count()>0)
00247               groupsListWidget->setCurrentRow(0);
00248 }
00249 
00250 void TimetableViewStudentsForm::groupChanged(const QString &groupName)
00251 {
00252        if(!(students_schedule_ready && teachers_schedule_ready)){
00253               QMessageBox::warning(this, tr("FET warning"), tr("Timetable not available in view students timetable dialog - please generate a new timetable"));
00254               return;
00255        }
00256        assert(students_schedule_ready && teachers_schedule_ready);
00257 
00258        if(groupName==QString())
00259               return;
00260 
00261        QString yearName=yearsListWidget->currentItem()->text();
00262        int yearIndex=gt.rules.searchAugmentedYear(yearName);
00263        if(yearIndex<0){
00264               QMessageBox::warning(this, tr("FET warning"), tr("Invalid year - please close this dialog and open a new students view timetable dialog"));
00265               return;
00266        }
00267 
00268        StudentsYear* sty=gt.rules.augmentedYearsList.at(yearIndex);
00269        int groupIndex=gt.rules.searchAugmentedGroup(yearName, groupName);
00270        if(groupIndex<0){
00271               QMessageBox::warning(this, tr("FET warning"),
00272                tr("Invalid group in the selected year, or the groups of the current year are not updated")+
00273                "\n\n"+
00274                tr("Solution: please try to select a different year and after that select the current year again, "
00275                "to refresh the groups list, or close this dialog and open again the students view timetable dialog"));
00276               return;
00277        }
00278        
00279        disconnect(subgroupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(subgroupChanged(const QString&)));
00280 
00281        subgroupsListWidget->clear();
00282        
00283        StudentsGroup* stg=sty->groupsList.at(groupIndex);
00284        for(int i=0; i<stg->subgroupsList.size(); i++){
00285               StudentsSubgroup* sts=stg->subgroupsList[i];
00286               subgroupsListWidget->addItem(sts->name);
00287        }
00288 
00289        connect(subgroupsListWidget, SIGNAL(currentTextChanged(const QString&)), this, SLOT(subgroupChanged(const QString&)));
00290 
00291        if(subgroupsListWidget->count()>0)
00292               subgroupsListWidget->setCurrentRow(0);
00293 }
00294 
00295 void TimetableViewStudentsForm::subgroupChanged(const QString &subgroupName)
00296 {
00297        Q_UNUSED(subgroupName);
00298        
00299        updateStudentsTimetableTable();
00300 }
00301 
00302 void TimetableViewStudentsForm::updateStudentsTimetableTable(){
00303        if(!(students_schedule_ready && teachers_schedule_ready)){
00304               QMessageBox::warning(this, tr("FET warning"), tr("Timetable not available in view students timetable dialog - please generate a new timetable "
00305               "or close the timetable view students dialog"));
00306               return;
00307        }
00308        assert(students_schedule_ready && teachers_schedule_ready);
00309        
00310        if(gt.rules.nInternalRooms!=gt.rules.roomsList.count()){
00311               QMessageBox::warning(this, tr("FET warning"), tr("Cannot display the timetable, because you added or removed some rooms. Please regenerate the timetable and then view it"));
00312               return;
00313        }
00314 
00315        QString s;
00316        QString yearname;
00317        QString groupname;
00318        QString subgroupname;
00319 
00320        if(yearsListWidget->currentRow()<0 || yearsListWidget->currentRow()>=yearsListWidget->count())
00321               return;
00322        if(groupsListWidget->currentRow()<0 || groupsListWidget->currentRow()>=groupsListWidget->count())
00323               return;
00324        if(subgroupsListWidget->currentRow()<0 || subgroupsListWidget->currentRow()>=subgroupsListWidget->count())
00325               return;
00326 
00327        yearname = yearsListWidget->currentItem()->text();
00328        groupname = groupsListWidget->currentItem()->text();
00329        subgroupname = subgroupsListWidget->currentItem()->text();
00330 
00331        if( ! ((StudentsSubgroup*)gt.rules.searchAugmentedStudentsSet(subgroupname)) ){
00332               QMessageBox::information(this, tr("FET warning"), tr("You have an old timetable view students dialog opened - please close it"));
00333               return;
00334        }
00335 
00336        s="";
00337 /*     s = tr("Students");
00338        s += ": ";*/
00339        //s += yearname;
00340        //s += ", ";
00341        //s += groupname;
00342        //s += ", ";
00343        s += subgroupname;
00344 
00345        classNameTextLabel->setText(s);
00346 
00347        assert(gt.rules.initialized);
00348 
00349        StudentsSubgroup* sts=(StudentsSubgroup*)gt.rules.searchAugmentedStudentsSet(subgroupname);
00350        assert(sts);
00351        int i;
00352        for(i=0; i<gt.rules.nInternalSubgroups; i++)
00353               if(gt.rules.internalSubgroupsList[i]==sts)
00354                      break;
00355        assert(i<gt.rules.nInternalSubgroups);
00356        for(int j=0; j<gt.rules.nHoursPerDay && j<studentsTimetableTable->rowCount(); j++){
00357               for(int k=0; k<gt.rules.nDaysPerWeek && k<studentsTimetableTable->columnCount(); k++){
00358                      s="";
00359                      int ai=students_timetable_weekly[i][k][j]; //activity index
00360                      if(ai!=UNALLOCATED_ACTIVITY){
00361                             Activity* act=&gt.rules.internalActivitiesList[ai];
00362                             assert(act!=NULL);
00363                             
00364                             QString ats=act->activityTagsNames.join(", ");
00365                             s+=act->subjectName +" "+ ats;
00366                             
00367                             if(act->teachersNames.count()>0){
00368                                    s+="\n";
00369                                    s+=act->teachersNames.join(", ");
00370                             }
00371                             
00372                             int r=best_solution.rooms[ai];
00373                             if(r!=UNALLOCATED_SPACE && r!=UNSPECIFIED_ROOM){
00374                                    //s+=" ";
00375                                    //s+=tr("R:%1", "Room").arg(gt.rules.internalRoomsList[r]->name);
00376                                    s+="\n";
00377                                    s+=gt.rules.internalRoomsList[r]->name;
00378                             }
00379 
00380                             //added by Volker Dirr (start)
00381                             QString descr="";
00382                             QString t="";
00383                             if(idsOfPermanentlyLockedTime.contains(act->id)){
00384                                    descr+=QCoreApplication::translate("TimetableViewForm", "PLT", "Abbreviation for permanently locked time. There are 4 string: permanently locked time, permanently locked space, "
00385                                           "locked time, locked space. Make sure their abbreviations contain different letters and are visually different, so user can easily differentiate between them."
00386                                           " These abbreviations may appear also in other places, please use the same abbreviations.");
00387                                    t=", ";
00388                             }
00389                             else if(idsOfLockedTime.contains(act->id)){
00390                                    descr+=QCoreApplication::translate("TimetableViewForm", "LT", "Abbreviation for locked time. There are 4 string: permanently locked time, permanently locked space, "
00391                                           "locked time, locked space. Make sure their abbreviations contain different letters and are visually different, so user can easily differentiate between them."
00392                                           " These abbreviations may appear also in other places, please use the same abbreviations.");
00393                                    t=", ";
00394                             }
00395                             if(idsOfPermanentlyLockedSpace.contains(act->id)){
00396                                    descr+=t+QCoreApplication::translate("TimetableViewForm", "PLS", "Abbreviation for permanently locked space. There are 4 string: permanently locked time, permanently locked space, "
00397                                           "locked time, locked space. Make sure their abbreviations contain different letters and are visually different, so user can easily differentiate between them."
00398                                           " These abbreviations may appear also in other places, please use the same abbreviations.");
00399                             }
00400                             else if(idsOfLockedSpace.contains(act->id)){
00401                                    descr+=t+QCoreApplication::translate("TimetableViewForm", "LS", "Abbreviation for locked space. There are 4 string: permanently locked time, permanently locked space, "
00402                                           "locked time, locked space. Make sure their abbreviations contain different letters and are visually different, so user can easily differentiate between them."
00403                                           " These abbreviations may appear also in other places, please use the same abbreviations.");
00404                             }
00405                             if(descr!=""){
00406                                    descr.prepend("\n(");
00407                                    descr.append(")");
00408                             }
00409                             s+=descr;
00410                             //added by Volker Dirr (end)
00411                      }
00412                      else{
00413                             if(subgroupNotAvailableDayHour[i][k][j] && PRINT_NOT_AVAILABLE_TIME_SLOTS)
00414                                    s+="-x-";
00415                             else if(breakDayHour[k][j] && PRINT_BREAK_TIME_SLOTS)
00416                                    s+="-X-";
00417                      }
00418                      studentsTimetableTable->item(j, k)->setText(s);
00419               }
00420        }
00421 
00422        studentsTimetableTable->resizeRowsToContents();
00423        
00424        tableWidgetUpdateBug(studentsTimetableTable);
00425        
00426        detailActivity(studentsTimetableTable->currentItem());
00427 }
00428 
00429 void TimetableViewStudentsForm::resizeEvent(QResizeEvent* event)
00430 {
00431        QDialog::resizeEvent(event);
00432 
00433        studentsTimetableTable->resizeRowsToContents();
00434 }
00435 
00436 void TimetableViewStudentsForm::currentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
00437 {
00438        Q_UNUSED(previous);
00439        
00440        detailActivity(current);
00441 }
00442 
00443 void TimetableViewStudentsForm::detailActivity(QTableWidgetItem* item)
00444 {
00445        if(item==NULL){
00446               detailsTextEdit->setPlainText(QString(""));
00447               return;
00448        }
00449        
00450        if(item->row()>=gt.rules.nHoursPerDay || item->column()>=gt.rules.nDaysPerWeek){
00451               QMessageBox::warning(this, tr("FET warning"), tr("Timetable not available in view students timetable dialog - please generate a new timetable "
00452               "or close the timetable view students dialog"));
00453               return;
00454        }
00455 
00456        if(!(students_schedule_ready && teachers_schedule_ready)){
00457               QMessageBox::warning(this, tr("FET warning"), tr("Timetable not available in view students timetable dialog - please generate a new timetable"));
00458               return;
00459        }
00460        assert(students_schedule_ready && teachers_schedule_ready);
00461 
00462        if(gt.rules.nInternalRooms!=gt.rules.roomsList.count()){
00463               QMessageBox::warning(this, tr("FET warning"), tr("Cannot display the timetable, because you added or removed some rooms. Please regenerate the timetable and then view it"));
00464               return;
00465        }
00466 
00467        QString s;
00468        QString yearname;
00469        QString groupname;
00470        QString subgroupname;
00471 
00472        if(yearsListWidget->currentRow()<0 || yearsListWidget->currentRow()>=yearsListWidget->count())
00473               return;
00474        if(groupsListWidget->currentRow()<0 || groupsListWidget->currentRow()>=groupsListWidget->count())
00475               return;
00476        if(subgroupsListWidget->currentRow()<0 || subgroupsListWidget->currentRow()>=subgroupsListWidget->count())
00477               return;
00478 
00479        yearname = yearsListWidget->currentItem()->text();
00480        groupname = groupsListWidget->currentItem()->text();
00481        subgroupname = subgroupsListWidget->currentItem()->text();
00482 
00483        StudentsSubgroup* sts=(StudentsSubgroup*)gt.rules.searchAugmentedStudentsSet(subgroupname);
00484        if(!sts){
00485               QMessageBox::warning(this, tr("FET warning"), tr("Invalid students set - please close this dialog and open a new view students timetable dialog"));
00486               return;
00487        }
00488        assert(sts);
00489        int i;
00490        for(i=0; i<gt.rules.nInternalSubgroups; i++)
00491               if(gt.rules.internalSubgroupsList[i]==sts)
00492                      break;
00493 /*     if(!(i<gt.rules.nInternalSubgroups)){
00494               QMessageBox::warning(this, tr("FET warning"), tr("Invalid students set - please close this dialog and open a new view students dialog"));
00495               return;
00496        }*/
00497        assert(i<gt.rules.nInternalSubgroups);
00498        int j=item->row();
00499        int k=item->column();
00500        s="";
00501        if(j>=0 && k>=0){
00502               int ai=students_timetable_weekly[i][k][j]; //activity index
00503               //Activity* act=gt.rules.activitiesList.at(ai);
00504               if(ai!=UNALLOCATED_ACTIVITY){
00505                      Activity* act=&gt.rules.internalActivitiesList[ai];
00506                      assert(act!=NULL);
00507                      //s+=act->getDetailedDescriptionWithConstraints(gt.rules);
00508                      s+=act->getDetailedDescription(gt.rules);
00509 
00510                      //int r=rooms_timetable_weekly[i][k][j];
00511                      int r=best_solution.rooms[ai];
00512                      if(r!=UNALLOCATED_SPACE && r!=UNSPECIFIED_ROOM){
00513                             s+="\n";
00514                             s+=tr("Room: %1").arg(gt.rules.internalRoomsList[r]->name);
00515                      }
00516                      //added by Volker Dirr (start)
00517                      QString descr="";
00518                      QString t="";
00519                      if(idsOfPermanentlyLockedTime.contains(act->id)){
00520                             descr+=QCoreApplication::translate("TimetableViewForm", "permanently locked time", "refers to activity");
00521                             t=", ";
00522                      }
00523                      else if(idsOfLockedTime.contains(act->id)){
00524                             descr+=QCoreApplication::translate("TimetableViewForm", "locked time", "refers to activity");
00525                             t=", ";
00526                      }
00527                      if(idsOfPermanentlyLockedSpace.contains(act->id)){
00528                             descr+=t+QCoreApplication::translate("TimetableViewForm", "permanently locked space", "refers to activity");
00529                      }
00530                      else if(idsOfLockedSpace.contains(act->id)){
00531                             descr+=t+QCoreApplication::translate("TimetableViewForm", "locked space", "refers to activity");
00532                      }
00533                      if(descr!=""){
00534                             descr.prepend("\n(");
00535                             descr.append(")");
00536                      }
00537                      s+=descr;
00538                      //added by Volker Dirr (end)
00539               }
00540               else{
00541                      if(subgroupNotAvailableDayHour[i][k][j]){
00542                             s+=tr("Students subgroup is not available 100% in this slot");
00543                             s+="\n";
00544                      }
00545                      if(breakDayHour[k][j]){
00546                             s+=tr("Break with weight 100% in this slot");
00547                             s+="\n";
00548                      }
00549               }
00550        }
00551        detailsTextEdit->setPlainText(s);
00552 }
00553 
00554 void TimetableViewStudentsForm::lockTime()
00555 {
00556        lock(true, false);
00557 }
00558 
00559 void TimetableViewStudentsForm::lockSpace()
00560 {
00561        lock(false, true);
00562 }
00563 
00564 void TimetableViewStudentsForm::lockTimeSpace()
00565 {
00566        lock(true, true);
00567 }
00568 
00569 void TimetableViewStudentsForm::lock(bool lockTime, bool lockSpace)
00570 {
00571        if(simulation_running){
00572               QMessageBox::information(this, tr("FET information"),
00573                      tr("Allocation in course.\nPlease stop simulation before this."));
00574               return;
00575        }
00576 
00577        //find subgroup index
00578        if(!(students_schedule_ready && teachers_schedule_ready)){
00579               QMessageBox::warning(this, tr("FET warning"), tr("Timetable not available in view students timetable dialog - please generate a new timetable"));
00580               return;
00581        }
00582        assert(students_schedule_ready && teachers_schedule_ready);
00583 
00584        if(gt.rules.nInternalRooms!=gt.rules.roomsList.count()){
00585               QMessageBox::warning(this, tr("FET warning"), tr("Cannot display the timetable, because you added or removed some rooms. Please regenerate the timetable and then view it"));
00586               return;
00587        }
00588 
00589        QString yearname;
00590        QString groupname;
00591        QString subgroupname;
00592        
00593        if(yearsListWidget->currentRow()<0 || yearsListWidget->currentRow()>=yearsListWidget->count()){
00594               QMessageBox::information(this, tr("FET information"), tr("Please select a year"));
00595               return;
00596        }
00597        if(groupsListWidget->currentRow()<0 || groupsListWidget->currentRow()>=groupsListWidget->count()){
00598               QMessageBox::information(this, tr("FET information"), tr("Please select a group"));
00599               return;
00600        }
00601        if(subgroupsListWidget->currentRow()<0 || subgroupsListWidget->currentRow()>=subgroupsListWidget->count()){
00602               QMessageBox::information(this, tr("FET information"), tr("Please select a subgroup"));
00603               return;
00604        }
00605 
00606        yearname = yearsListWidget->currentItem()->text();
00607        groupname = groupsListWidget->currentItem()->text();
00608        subgroupname = subgroupsListWidget->currentItem()->text();
00609 
00610        Solution* tc=&best_solution;
00611 
00612        StudentsSubgroup* sts=(StudentsSubgroup*)gt.rules.searchAugmentedStudentsSet(subgroupname);
00613        if(!sts){
00614               QMessageBox::warning(this, tr("FET warning"), tr("Invalid students set - please close this dialog and open a new view students timetable dialog"));
00615               return;
00616        }
00617        assert(sts);
00618        int i;
00619        for(i=0; i<gt.rules.nInternalSubgroups; i++)
00620               if(gt.rules.internalSubgroupsList[i]==sts)
00621                      break;
00622        assert(i<gt.rules.nInternalSubgroups);
00623 
00624        bool report=false; //the messages are annoying
00625        
00626        int addedT=0, unlockedT=0;
00627        int addedS=0, unlockedS=0;
00628 
00629        //lock selected activities
00630        QSet <int> careAboutIndex;         //added by Volker Dirr. Needed, because of activities with duration > 1
00631        careAboutIndex.clear();
00632        for(int j=0; j<gt.rules.nHoursPerDay && j<studentsTimetableTable->rowCount(); j++){
00633               for(int k=0; k<gt.rules.nDaysPerWeek && k<studentsTimetableTable->columnCount(); k++){
00634                      if(studentsTimetableTable->item(j, k)->isSelected()){
00635                             int ai=students_timetable_weekly[i][k][j];
00636                             if(ai!=UNALLOCATED_ACTIVITY && !careAboutIndex.contains(ai)){  //modified, because of activities with duration > 1
00637                                    careAboutIndex.insert(ai);                              //Needed, because of activities with duration > 1
00638                                    int a_tim=tc->times[ai];
00639                                    int hour=a_tim/gt.rules.nDaysPerWeek;
00640                                    int day=a_tim%gt.rules.nDaysPerWeek;
00641                                    //Activity* act=gt.rules.activitiesList.at(ai);
00642                                    Activity* act=&gt.rules.internalActivitiesList[ai];
00643                                    
00644                                    if(lockTime){
00645                                           ConstraintActivityPreferredStartingTime* ctr=new ConstraintActivityPreferredStartingTime(100.0, act->id, day, hour, false);
00646                                           bool t=gt.rules.addTimeConstraint(ctr);
00647                                           QString s;
00648                                           if(t){ //modified by Volker Dirr, so you can also unlock (start)
00649                                                  addedT++;
00650                                                  idsOfLockedTime.insert(act->id);
00651                                                  s+=tr("Added the following constraint:")+"\n"+ctr->getDetailedDescription(gt.rules);
00652                                           }
00653                                           else{
00654                                                  delete ctr;
00655                                           
00656                                                  QList<TimeConstraint*> tmptc;
00657                                                  tmptc.clear();
00658                                                  int count=0;
00659                                                  foreach(TimeConstraint* tc, gt.rules.timeConstraintsList){
00660                                                         if(tc->type==CONSTRAINT_ACTIVITY_PREFERRED_STARTING_TIME){
00661                                                                ConstraintActivityPreferredStartingTime* c=(ConstraintActivityPreferredStartingTime*) tc;
00662                                                                if(c->activityId==act->id && c->weightPercentage==100.0 && c->active && c->day>=0 && c->hour>=0){
00663                                                                       count++;
00664                                                                       if(c->permanentlyLocked){
00665                                                                              if(idsOfLockedTime.contains(c->activityId) || !idsOfPermanentlyLockedTime.contains(c->activityId)){
00666                                                                                     QMessageBox::warning(this, tr("FET warning"), tr("Small problem detected")
00667                                                                                      +"\n\n"+tr("A possible problem might be that you have 2 or more constraints of type activity preferred starting time with weight 100% related to activity id %1, please leave only one of them").arg(act->id)
00668                                                                                      +"\n\n"+tr("A possible problem might be synchronization - so maybe try to close the timetable view dialog and open it again")
00669                                                                                      +"\n\n"+tr("Please report possible bug")
00670                                                                                     );
00671                                                                              }
00672                                                                              else{
00673                                                                                     s+=tr("Constraint %1 will not be removed, because it is permanently locked. If you want to unlock it you must go to the constraints menu.").arg("\n"+c->getDetailedDescription(gt.rules)+"\n");
00674                                                                              }
00675                                                                       }
00676                                                                       else{
00677                                                                              if(!idsOfLockedTime.contains(c->activityId) || idsOfPermanentlyLockedTime.contains(c->activityId)){
00678                                                                                     QMessageBox::warning(this, tr("FET warning"), tr("Small problem detected")
00679                                                                                      +"\n\n"+tr("A possible problem might be that you have 2 or more constraints of type activity preferred starting time with weight 100% related to activity id %1, please leave only one of them").arg(act->id)
00680                                                                                      +"\n\n"+tr("A possible problem might be synchronization - so maybe try to close the timetable view dialog and open it again")
00681                                                                                      +"\n\n"+tr("Please report possible bug")
00682                                                                                     );
00683                                                                              }
00684                                                                              else{
00685                                                                                     tmptc.append(tc);
00686                                                                              }
00687                                                                       }
00688                                                                }
00689                                                         }
00690                                                  }
00691                                                  if(count!=1)
00692                                                         QMessageBox::warning(this, tr("FET warning"), tr("You may have a problem, because FET expected to delete 1 constraint, but will delete %1 constraints").arg(tmptc.size()));
00693 
00694                                                  foreach(TimeConstraint* deltc, tmptc){
00695                                                         s+=tr("The following constraint will be deleted:")+"\n"+deltc->getDetailedDescription(gt.rules)+"\n";
00696                                                         gt.rules.removeTimeConstraint(deltc);
00697                                                         //delete deltc; - this is done by rules.remove...
00698                                                         idsOfLockedTime.remove(act->id);
00699                                                         unlockedT++;
00700                                                  }
00701                                                  tmptc.clear();
00702                                                  //gt.rules.internalStructureComputed=false;
00703                                           }  //modified by Volker Dirr, so you can also unlock (end)
00704                                           
00705                                           if(report){
00706                                                  int k;
00707                                                  if(t)
00708                                                         k=QMessageBox::information(this, tr("FET information"), s,
00709                                                          tr("Skip information"), tr("See next"), QString(), 1, 0 );
00710                                                  else
00711                                                         k=QMessageBox::information(this, tr("FET information"), s,
00712                                                          tr("Skip information"), tr("See next"), QString(), 1, 0 );
00713                                                  if(k==0)
00714                                                         report=false;
00715                                           }
00716                                    }
00717 
00718                                    int ri=tc->rooms[ai];
00719                                    if(ri!=UNALLOCATED_SPACE && ri!=UNSPECIFIED_ROOM && lockSpace){
00720                                           ConstraintActivityPreferredRoom* ctr=new ConstraintActivityPreferredRoom(100, act->id, (gt.rules.internalRoomsList[ri])->name, false);
00721                                           bool t=gt.rules.addSpaceConstraint(ctr);
00722 
00723                                           QString s;
00724                                           
00725                                           if(t){ //modified by Volker Dirr, so you can also unlock (start)
00726                                                  addedS++;
00727                                                  idsOfLockedSpace.insert(act->id);
00728                                                  s+=tr("Added the following constraint:")+"\n"+ctr->getDetailedDescription(gt.rules);
00729                                           }
00730                                           else{
00731                                                  delete ctr;
00732                                           
00733                                                  QList<SpaceConstraint*> tmpsc;
00734                                                  tmpsc.clear();
00735                                                  int count=0;
00736                                                  foreach(SpaceConstraint* sc, gt.rules.spaceConstraintsList){
00737                                                         if(sc->type==CONSTRAINT_ACTIVITY_PREFERRED_ROOM){
00738                                                                ConstraintActivityPreferredRoom* c=(ConstraintActivityPreferredRoom*) sc;
00739                                                                if(c->activityId==act->id && c->weightPercentage==100.0 && c->active){
00740                                                                       count++;
00741                                                                       if(c->permanentlyLocked){
00742                                                                              if(idsOfLockedSpace.contains(c->activityId) || !idsOfPermanentlyLockedSpace.contains(c->activityId)){
00743                                                                                     QMessageBox::warning(this, tr("FET warning"), tr("Small problem detected")
00744                                                                                      +"\n\n"+tr("A possible problem might be that you have 2 or more constraints of type activity preferred room with weight 100% related to activity id %1, please leave only one of them").arg(act->id)
00745                                                                                      +"\n\n"+tr("A possible problem might be synchronization - so maybe try to close the timetable view dialog and open it again")
00746                                                                                      +"\n\n"+tr("Please report possible bug")
00747                                                                                     );
00748                                                                              }
00749                                                                              else{
00750                                                                                     s+=tr("Constraint %1 will not be removed, because it is permanently locked. If you want to unlock it you must go to the constraints menu.").arg("\n"+c->getDetailedDescription(gt.rules)+"\n");
00751                                                                              }
00752                                                                       }
00753                                                                       else{
00754                                                                              if(!idsOfLockedSpace.contains(c->activityId) || idsOfPermanentlyLockedSpace.contains(c->activityId)){
00755                                                                                     QMessageBox::warning(this, tr("FET warning"), tr("Small problem detected")
00756                                                                                      +"\n\n"+tr("A possible problem might be that you have 2 or more constraints of type activity preferred room with weight 100% related to activity id %1, please leave only one of them").arg(act->id)
00757                                                                                      +"\n\n"+tr("A possible problem might be synchronization - so maybe try to close the timetable view dialog and open it again")
00758                                                                                      +"\n\n"+tr("Please report possible bug")
00759                                                                                     );
00760                                                                              }
00761                                                                              else{
00762                                                                                     tmpsc.append(sc);
00763                                                                              }
00764                                                                       }
00765                                                                }
00766                                                         }
00767                                                  }
00768                                                  if(count!=1)
00769                                                         QMessageBox::warning(this, tr("FET warning"), tr("You may have a problem, because FET expected to delete 1 constraint, but will delete %1 constraints").arg(tmpsc.size()));
00770 
00771                                                  foreach(SpaceConstraint* delsc, tmpsc){
00772                                                         s+=tr("The following constraint will be deleted:")+"\n"+delsc->getDetailedDescription(gt.rules)+"\n";
00773                                                         gt.rules.removeSpaceConstraint(delsc);
00774                                                         idsOfLockedSpace.remove(act->id);
00775                                                         unlockedS++;
00776                                                         //delete delsc; done by rules.remove...
00777                                                  }
00778                                                  tmpsc.clear();
00779                                                  //gt.rules.internalStructureComputed=false;
00780                                           }  //modified by Volker Dirr, so you can also unlock (end)
00781                                           
00782                                           if(report){
00783                                                  int k;
00784                                                  if(t)
00785                                                         k=QMessageBox::information(this, tr("FET information"), s,
00786                                                          tr("Skip information"), tr("See next"), QString(), 1, 0 );
00787                                                  else
00788                                                         k=QMessageBox::information(this, tr("FET information"), s,
00789                                                          tr("Skip information"), tr("See next"), QString(), 1, 0 );
00790                                                  
00791                                                  if(k==0)
00792                                                         report=false;
00793                                           }
00794                                    }
00795                             }
00796                      }
00797               }
00798        }
00799        
00800        QStringList added;
00801        QStringList removed;
00802        if(addedT>0){
00803               if(addedT==1)
00804                      added << QCoreApplication::translate("TimetableViewForm", "Added 1 locking time constraint.", "constraint is singular (only 1 constraint)");
00805               else
00806                      added << QCoreApplication::translate("TimetableViewForm", "Added %1 locking time constraints.", "%1 is >= 2, so constraints is plural").arg(addedT);
00807        }
00808        if(addedS>0){
00809               if(addedS==1)
00810                      added << QCoreApplication::translate("TimetableViewForm", "Added 1 locking space constraint.", "constraint is singular (only 1 constraint)");
00811               else
00812                      added << QCoreApplication::translate("TimetableViewForm", "Added %1 locking space constraints.", "%1 is >= 2, so constraints is plural").arg(addedS);
00813        }
00814        if(unlockedT>0){
00815               if(unlockedT==1)
00816                      removed << QCoreApplication::translate("TimetableViewForm", "Removed 1 locking time constraint.", "constraint is singular (only 1 constraint)");
00817               else
00818                      removed << QCoreApplication::translate("TimetableViewForm", "Removed %1 locking time constraints.", "%1 is >= 2, so constraints is plural").arg(unlockedT);
00819        }
00820        if(unlockedS>0){
00821               if(unlockedS==1)
00822                      removed << QCoreApplication::translate("TimetableViewForm", "Removed 1 locking space constraint.", "constraint is singular (only 1 constraint)");
00823               else
00824                      removed << QCoreApplication::translate("TimetableViewForm", "Removed %1 locking space constraints.", "%1 is >= 2, so constraints is plural").arg(unlockedS);
00825        }
00826        QString ad=added.join("\n");
00827        QString re=removed.join("\n");
00828        QStringList all;
00829        if(!ad.isEmpty())
00830               all<<ad;
00831        if(!re.isEmpty())
00832               all<<re;
00833        QString s=all.join("\n\n");
00834        if(s.isEmpty())
00835               s=QCoreApplication::translate("TimetableViewForm", "No locking constraints added or removed.");
00836        QMessageBox::information(this, tr("FET information"), s);
00837 
00839        QSet<int> backupLockedTime;
00840        QSet<int> backupPermanentlyLockedTime;
00841        QSet<int> backupLockedSpace;
00842        QSet<int> backupPermanentlyLockedSpace;
00843        
00844        backupLockedTime=idsOfLockedTime;
00845        backupPermanentlyLockedTime=idsOfPermanentlyLockedTime;
00846        backupLockedSpace=idsOfLockedSpace;
00847        backupPermanentlyLockedSpace=idsOfPermanentlyLockedSpace;
00848        
00849        LockUnlock::computeLockedUnlockedActivitiesTimeSpace(); //just to make sure, not really needed, but to test better
00850        
00851        assert(backupLockedTime==idsOfLockedTime);
00852        assert(backupPermanentlyLockedTime==idsOfPermanentlyLockedTime);
00853        assert(backupLockedSpace==idsOfLockedSpace);
00854        assert(backupPermanentlyLockedSpace==idsOfPermanentlyLockedSpace);
00856 
00857        LockUnlock::increaseCommunicationSpinBox(); //this is needed
00858        
00859        //cout<<"students end, isc="<<gt.rules.internalStructureComputed<<endl;
00860        //cout<<endl;
00861 }
00862 
00863 void TimetableViewStudentsForm::help()
00864 {
00865        QString s="";
00866        //s+=QCoreApplication::translate("TimetableViewForm", "You can drag sections to increase/decrease them.");
00867        //s+="\n\n";
00868        s+=QCoreApplication::translate("TimetableViewForm", "Lock/unlock: you can select one or more activities in the table and toggle lock/unlock in time, space or both.");
00869        s+=" ";
00870        s+=QCoreApplication::translate("TimetableViewForm", "There will be added or removed locking constraints for the selected activities (they can be unlocked only if they are not permanently locked).");
00871        s+="\n\n";
00872        s+=QCoreApplication::translate("TimetableViewForm", "Locking time constraints are constraints of type activity preferred starting time. Locking space constraints are constraints of type"
00873               " activity preferred room. You can see these constraints in the corresponding constraints dialogs. New locking constraints are added at the end of the list of constraints.");
00874        s+="\n\n";
00875        s+=QCoreApplication::translate("TimetableViewForm", "If a cell is (permanently) locked in time or space, it contains abbreviations to show that: PLT (permanently locked time), LT (locked time), "
00876               "PLS (permanently locked space) or LS (locked space).", "Translate the abbreviations also. Make sure the abbreviations in your language are different between themselves "
00877               "and the user can differentiate easily between them. These abbreviations may appear also in other places, please use the same abbreviations.");
00878 
00879        LongTextMessageBox::largeInformation(this, tr("FET help"), s);
00880 }