ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/s10k/Vago/mainwindow.cpp
(Generate patch)

Comparing:
Vago/trunk/Vago/mainwindow.cpp (file contents), Revision 1035 by s10k, Thu Mar 24 22:28:41 2016 UTC vs.
s10k/Vago/mainwindow.cpp (file contents), Revision 1092 by s10k, Sat Dec 30 13:43:28 2017 UTC

# Line 9 | Line 9 | MainWindow::MainWindow(QWidget *parent)
9   {
10      ui->setupUi(this);
11  
12 <    this->myLogger = new Logger(Util::getAppPath()); //start logger
12 >    this->myLogger = new Logger(UtilVago::getAppPath(), GlobalVars::AppLogName); //start logger
13  
14 <    this->myLogger->writeString("Detected AppDir: "+Util::getAppPath());
14 >    this->myLogger->writeString("Detected AppDir: "+UtilVago::getAppPath());
15      this->myLogger->writeString("True app dir: "+QDir::currentPath());
16  
17 <    this->setWindowTitle("Vago v"+GlobalVars::AppVersion);
17 >    setVagoWindowTitle();
18  
19 <    if(!QFile::exists(Util::getAppPath()+"/"+GlobalVars::OniSplitString)){
20 <        Util::showErrorPopUp("OniSplit not found. Please download it at "+GlobalVars::ModsDomain+" and put it in the same folder of Vago. \n\nProgram will now exit.");
19 >    if(!QFile::exists(UtilVago::getOniSplitExecutableAbsolutePath())){
20 >        UtilVago::showAndLogErrorPopUp(this->myLogger, "OniSplit not found. Please download it at "+GlobalVars::ModsDomain+" and put it the Vago's tools folder. \n\nProgram will now exit.");
21          exit(1);
22      }
23  
24 <    if(!QFile::exists(Util::getAppPath()+"/"+GlobalVars::XmlToolsString)){
25 <        Util::showErrorPopUp("xmlTools not found. Please download it at "+GlobalVars::ModsDomain+" and put it in the same folder of Vago. \n\nProgram will now exit.");
24 >    if(!QFile::exists(UtilVago::getXmlToolsExecutableAbsolutePath())){
25 >        UtilVago::showAndLogErrorPopUp(this->myLogger, "XmlTools not found. Please download it at "+GlobalVars::ModsDomain+" and put it the Vago's tools folder. \n\nProgram will now exit.");
26          exit(1);
27      }
28  
29 <    this->vagoSettings = new QSettings(Util::getAppPath() + "/" + this->VagoSettingsName, QSettings::IniFormat);
29 >    this->vagoSettings = new QSettings(UtilVago::getAppPath() + "/" + this->VagoSettingsName, QSettings::IniFormat);
30  
31      //First Execution? Old configuration? Settings missed?
32      bool iniChanged=false;
# Line 35 | Line 35 | MainWindow::MainWindow(QWidget *parent)
35          iniChanged=true;
36      }
37      if(!this->vagoSettings->contains("Workspace")){
38 <        this->vagoSettings->setValue("Workspace", Util::getAppPath()+"/VagoWorkspace");
38 >        this->vagoSettings->setValue("Workspace", UtilVago::getAppPath()+"/VagoWorkspace");
39          iniChanged=true;
40      }
41      if(!this->vagoSettings->contains("AeFolder")){
# Line 44 | Line 44 | MainWindow::MainWindow(QWidget *parent)
44          QString aefolder=Util::normalizePath(QFileDialog::getExistingDirectory(this,"Choose Anniversary Edition (AE) folder..."));
45  
46          if(aefolder.isEmpty()){
47 <            Util::showErrorPopUp("AE folder is mandatory. Application will now exit.");
47 >            UtilVago::showAndLogErrorPopUp(this->myLogger, "AE folder is mandatory. Application will now exit.");
48              exit(1);
49          }
50  
# Line 71 | Line 71 | MainWindow::MainWindow(QWidget *parent)
71          this->vagoSettings->setValue("SeparateInWorkspace",true);
72          iniChanged=true;
73      }
74 <    if(!this->vagoSettings->contains("ConfirmExit")){
75 <        this->vagoSettings->setValue("ConfirmExit", false);
74 >    if(!this->vagoSettings->contains("AskSaveProject")){
75 >        this->vagoSettings->setValue("AskSaveProject", true);
76          iniChanged=true;
77      }
78 +    if(!this->vagoSettings->contains("AskToOpenLastProject")){
79 +        this->vagoSettings->setValue("AskToOpenLastProject", false);
80 +        iniChanged=true;
81 +    }
82 +    if(!this->vagoSettings->contains("LastProjectPath")){
83 +        this->vagoSettings->setValue("LastProjectPath", this->vagoSettings->value("Workspace"));
84 +        iniChanged=true;
85 +    }
86 +    for(int i=0; i<this->recentProjectsMaxSize; i++){
87 +        if(!this->vagoSettings->contains("RecentProject" + QString::number(i+1))){
88 +            this->vagoSettings->setValue("RecentProject" + QString::number(i+1), "");
89 +            iniChanged=true;
90 +        }
91 +    }
92   #ifdef Q_OS_MAC
93      if(!this->vagoSettings->contains("useYesAsDefaultWhenRemovingItems")){
94          this->vagoSettings->setValue("useYesAsDefaultWhenRemovingItems", false);
# Line 114 | Line 128 | MainWindow::MainWindow(QWidget *parent)
128      ui->statusBar->addPermanentWidget(this->myBar); //this adds automatically in right
129      ui->statusBar->addPermanentWidget(ui->tbAbortConversion);
130  
117    //Initialize list pointers
118    this->listToProccess = new QStringList;
119
120    //Create a thread for do the conversion in background
121    this->myConverter = new Converter(Util::getAppPath(),this->myLogger,this->listToProccess);
122
131      // User interface
132      ui->mainToolBar->addWidget(ui->tbAE); //add ae installer launch button
133      ui->mainToolBar->addWidget(ui->emptySpacerLabel); //trick, we can't add directly a space so we add an empty
# Line 127 | Line 135 | MainWindow::MainWindow(QWidget *parent)
135      ui->mainToolBar->addWidget(ui->emptySpacerLabel2); //same as before
136      ui->mainToolBar->addWidget(ui->tbCommand); //add option to manual onisplit commands
137      ui->mainToolBar->addWidget(ui->emptySpacerLabel3); //same as before
138 +    ui->mainToolBar->addWidget(ui->tbXmlToolsInterface); //add option to manual onisplit commands
139 +    ui->mainToolBar->addWidget(ui->emptySpacerLabel4); //same as before
140      ui->mainToolBar->addWidget(ui->tbOpenFolder); //add option to open folder with files converted etc
141  
142      ui->mainToolBar->setLayoutDirection(Qt::RightToLeft);
143  
144 <    setConverterButtonsSize();
144 >    ui->pbConvert->setMinimumHeight(ui->pbConvert->sizeHint().height()*1.5); // This is OS indepented. It maintain size ratio over the Windows and Mac.
145 >
146  
147   #ifdef Q_OS_MAC
148      // setUnifiedTitleAndToolBarOnMac(true); // Qt suggests to use it on mac | http://www.slideshare.net/qtbynokia/how-to-make-your-qt-app-look-native // align on left doesn't work if active
# Line 143 | Line 154 | MainWindow::MainWindow(QWidget *parent)
154      ui->actionMac_Windows_demo->setChecked(true);
155      // resize(800,600); // Mac OS pcs should be able to render this resolution without any problem. It's also better
156      //// because the components on mac use more space
146 #else
147    //resize(640,480); // windows stuff
157   #endif
158  
159      resize(this->startedWindowWidth,this->startedWindowHeight);
160  
161 <    connectSlots();
161 > #ifdef Q_OS_MAC
162 >    ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (⌘ + Enter)");
163 > #else
164 >    ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (Ctrl + Enter)");
165 > #endif
166  
167      //Commands Mapping
168      this->commandMap = QHash<QString, QString>();
# Line 157 | Line 170 | MainWindow::MainWindow(QWidget *parent)
170  
171      updateItemsLoaded(ui->twSourcesXML);
172  
173 <    this->myLogger->writeString("Application started.");
173 >    loadRecentProjects();
174   }
175  
176   MainWindow::~MainWindow()
# Line 166 | Line 179 | MainWindow::~MainWindow()
179      this->myLogger->writeString("Application Exited.");
180   }
181  
182 +
183 + void MainWindow::showEvent(QShowEvent *e)
184 + {
185 +    // If we don't have a converter yet, application wasn't started.
186 +    if(!this->applicationIsFullyLoaded)
187 +    {
188 +        // Apparently Qt doesn't contains a slot to when the application was fully load (mainwindow). So we do our own implementation instead.
189 +        connect(this, SIGNAL(signalAppIsLoaded()), this, SLOT(applicationWasLoaded()), Qt::ConnectionType::QueuedConnection);
190 +        emit signalAppIsLoaded();
191 +    }
192 +
193 +    e->accept();
194 + }
195 +
196 + // Called only when the MainWindow was fully loaded and painted on the screen. This slot is only called once.
197 + void MainWindow::applicationWasLoaded(){
198 + #ifdef Q_OS_WIN
199 +    // QProgressBar only works after the windows was shown
200 +    // http://stackoverflow.com/questions/24840941/qwintaskbarprogress-wont-show (Kervala answer)
201 +
202 +    this->win7TaskBarButton = new QWinTaskbarButton();
203 +
204 +    this->win7TaskBarButton->setWindow(this->windowHandle());
205 +
206 +    this->win7TaskBarProgress = this->win7TaskBarButton->progress();
207 +
208 +    //Create a thread for do the conversion in background
209 +    this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, &this->listToProccess, this->win7TaskBarProgress);
210 + #else
211 +    this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, &this->listToProccess);
212 + #endif
213 +
214 +    connectSlots();
215 +
216 +    this->myLogger->writeString("Application started.");
217 +
218 +    this->applicationIsFullyLoaded = true;
219 +
220 +    QString lastSavedProject = this->vagoSettings->value("RecentProject1").toString();
221 +
222 +    if(!lastSavedProject.isEmpty() && this->vagoSettings->value("AskToOpenLastProject").toBool()){
223 +        if(Util::showQuestionPopUp(this,"Do you want to load latest project?\n\nLatest project was '" + Util::cutNameWithoutBackSlash(lastSavedProject) + "'.")){
224 +            loadProjectState(lastSavedProject);
225 +        }
226 +    }
227 + }
228 +
229 +
230   void MainWindow::on_actionExit_triggered()
231   {
232      close();
# Line 180 | Line 241 | void MainWindow::on_actionAbout_triggere
241  
242   void MainWindow::on_actionAE_Package_Creator_triggered()
243   {
244 <    PackageWizard myWizard = PackageWizard(this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
245 <    myWizard.exec();
244 >    // it deletes itself once closed
245 >    WizardFactory<PackageWizard>::startInstance(UtilVago::getAppPath(), this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
246   }
247  
248   void MainWindow::on_actionSound_Wizard_triggered()
249   {
250 <    SoundWizard myWizard (Util::getAppPath(), this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
251 <    myWizard.exec();
250 >    // it deletes itself once closed
251 >    WizardFactory<SoundWizard>::startInstance(UtilVago::getAppPath(), this->workspaceWizardsLocation, this->vagoSettings, this->myLogger, &this->commandMap);
252 > }
253 >
254 > void MainWindow::on_actionBackground_Image_Wizard_triggered()
255 > {
256 >    // it deletes itself once closed
257 >    WizardFactory<BGImageWizard>::startInstance(UtilVago::getAppPath(), this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
258 > }
259 >
260 > void MainWindow::on_actionWindow_Messages_Wizard_triggered()
261 > {
262 >    // it deletes itself once closed
263 >    WizardFactory<WmWizard>::startInstance(UtilVago::getAppPath(), this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
264   }
265  
266   void MainWindow::on_tbOni_clicked()
# Line 224 | Line 297 | void MainWindow::on_tbOpenFolder_clicked
297      QDesktopServices::openUrl(QUrl("file:///"+this->outputFolder));
298   }
299  
300 +
301 + void MainWindow::on_tbXmlToolsInterface_clicked()
302 + {
303 +    //We pass no parent because we want to have an independent window for XmlToolsInterface,
304 +    //so we can minimize it or maximize indepently from the MainWindow
305 +    XmlToolsInterface *xmlToolsWindow = new XmlToolsInterface(this->myLogger);
306 +    xmlToolsWindow->show(); //it destroys itself when finished.
307 + }
308 +
309   void MainWindow::on_tbAbortConversion_clicked()
310   {
311      if(Util::showQuestionPopUp(this,"Are you sure you want to abort the current conversion?")){
# Line 282 | Line 364 | void MainWindow::checkVagoLastVersion(QN
364          }
365      }
366      else{
367 <        Util::showErrorPopUp("An error occurred checking last version:\n\n"+result->errorString());
367 >        UtilVago::showAndLogErrorPopUp(this->myLogger, "An error occurred checking last version:\n\n"+result->errorString());
368      }
369      result->deleteLater();
370   }
# Line 309 | Line 391 | void MainWindow::on_pbAddSourceCharacter
391  
392   void MainWindow::on_pbAddSourceLevels_clicked()
393   {
394 <    if(QString::compare(ui->cbFromXML->currentText(),"ONI FILES",Qt::CaseSensitive)==0 && QString::compare(ui->cbToXML->currentText(),"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster)
394 >    if(QString::compare(ui->cbFromLevels->currentText(),"ONI FILES",Qt::CaseSensitive)==0 && QString::compare(ui->cbToLevels->currentText(),"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster)
395          addFilesSource(ui->twSourcesLevels,Util::multipleDirDialog("Choose folders with ONIs..."));
396      }
397      else{
# Line 396 | Line 478 | void MainWindow::addFilesSource(DropTabl
478          addRowTable(myTable,lastFileName,fromTo,command);
479      }
480      updateItemsLoaded(myTable);
481 +    rowsWereChangedInDropTableWidget();
482   }
483  
484   QString MainWindow::fileParsingXML(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
# Line 435 | Line 518 | QString MainWindow::fileParsingTextures(
518              command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbLarge->text());
519          }
520  
521 <        if(ui->rbBGR32->isChecked()){
439 <            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGR32->text());
440 <        }
441 <        else if(ui->rbBGRA32->isChecked()){
442 <            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGRA32->text());
443 <        }
444 <        else if(ui->rbBGR555->isChecked()){
445 <            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGR555->text());
446 <        }
447 <        else if(ui->rbBGRA5551->isChecked()){
448 <            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGRA5551->text());
449 <        }
450 <        else if(ui->rbBGRA444->isChecked()){
451 <            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGRA444->text());
452 <        }
453 <        else{ //dxt1 checked
454 <            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbDxt1->text());
455 <        }
521 >        command+=" "+this->commandMap.value(tabTitle+"->"+getTextureRBCheckedTypeTexture()->text());
522  
523          if(ui->cbEnvMap->isChecked()){
524              if(ui->leEnvMapTexture->text().isEmpty()){
# Line 496 | Line 562 | QString MainWindow::fileParsingObjects(Q
562  
563      QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder;
564  
499    //TODO: This can be optimized. When some are not enable others are.
565      if(ui->cbTexture->isChecked()){
566          if(ui->leTextureName->text().isEmpty()){
567              showErrStatusMessage("Checkbox '"+ui->cbTexture->text()+"' is selected. The file source cannot be empty.");
# Line 634 | Line 699 | QString MainWindow::fileParsingMisc(QStr
699      return this->commandMap.value("misc->"+from+"->"+to)+" "+myOutputFolder+" "+file;
700   }
701  
702 < void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command){
702 > void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command, bool isToDisabled){
703      //Get actual number rows
704      int twSize=myTable->rowCount();
705  
# Line 646 | Line 711 | void MainWindow::addRowTable(DropTableWi
711      QTableWidgetItem *newConversion = new QTableWidgetItem(fromTo);
712      QTableWidgetItem *newCommand = new QTableWidgetItem(command);
713  
714 +    if(isToDisabled){
715 +        myTable->setDisableStyleWidgetItem(newFile);
716 +        myTable->setDisableStyleWidgetItem(newConversion);
717 +        myTable->setDisableStyleWidgetItem(newCommand);
718 +    }
719 +
720      myTable->setItem(twSize,0,newFile);
721      myTable->setItem(twSize,1,newConversion);
722      myTable->setItem(twSize,2,newCommand);
# Line 653 | Line 724 | void MainWindow::addRowTable(DropTableWi
724      myTable->updateTableToolTips(twSize); //Update tool tips
725   }
726  
727 < void MainWindow::on_pbConvertXML_clicked()
727 > void MainWindow::on_pbConvert_clicked()
728   {
729 <    startConversion(ui->twSourcesXML);
729 >    startConversion();
730   }
731  
732 < void MainWindow::on_pbConvertTextures_clicked()
662 < {
663 <    startConversion(ui->twSourcesTextures);
664 < }
732 > void MainWindow::startConversion(){
733  
734 < void MainWindow::on_pbConvertObjects_clicked()
667 < {
668 <    startConversion(ui->twSourcesObjects);
669 < }
670 <
671 < void MainWindow::on_pbConvertCharacters_clicked()
672 < {
673 <    startConversion(ui->twSourcesCharacters);
674 < }
675 <
676 < void MainWindow::on_pbConvertLevels_clicked()
677 < {
678 <    startConversion(ui->twSourcesLevels);
679 < }
680 <
681 < void MainWindow::on_pbConvertMisc_clicked()
682 < {
683 <    startConversion(ui->twSourcesMisc);
684 < }
685 <
686 < void MainWindow::startConversion(DropTableWidget *myTable){
734 >    DropTableWidget* currTable = getCurrentTableWidget();
735  
736      bool ready=false;
737 <    for(int i=0; i<myTable->rowCount(); i++){ //There are items to process?
738 <        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
737 >    for(int i=0; i<currTable->rowCount(); i++){ //There are items to process?
738 >        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
739              ready=true;
740              break;
741          }
# Line 703 | Line 751 | void MainWindow::startConversion(DropTab
751          return;
752      }
753  
754 <    for(int i=0; i<myTable->rowCount(); i++){
754 >    for(int i=0; i<currTable->rowCount(); i++){
755          //Only process enabled items
756 <        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
757 <            this->listToProccess->append(myTable->item(i,2)->text());
756 >        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
757 >            this->listToProccess.append(currTable->item(i,2)->text());
758          }
759      }
760  
# Line 732 | Line 780 | void MainWindow::TresultConversion(QStri
780      if(numErrors!=0){
781          QString sNumErrors=QString::number(numErrors);
782          if(numErrors>1){
783 <            Util::showErrorLogPopUp(result+"\n This is the last of "+sNumErrors+" Errors.");
784 <            showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" Errors).");
783 >            UtilVago::showErrorPopUpLogButton(result+"\n This is the last of "+sNumErrors+" errors.");
784 >            showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" errors).");
785          }
786          else{
787 <            Util::showErrorLogPopUp(result);
787 >            UtilVago::showErrorPopUpLogButton(result);
788              showErrStatusMessage("Something gone wrong. Check log file.");
789          }
742
790      }
791      else{
792          showSuccessStatusMessage("Everything went well!");
# Line 886 | Line 933 | void MainWindow::on_cbFromXML_currentInd
933  
934   void MainWindow::on_cbFromTextures_currentIndexChanged(const QString &arg1)
935   {
889    //Options are only used for DAT/ONI -> Image
890    if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
891        ui->gbTextures->setEnabled(false);
892    }
893    else{
894        ui->gbTextures->setEnabled(true);
895    }
896
936      updateComboBox(arg1, ui->cbToTextures);
937   }
938  
939   void MainWindow::on_cbFromObjects_currentIndexChanged(const QString &arg1)
940   {
902    ui->cbTexture->setEnabled(false);
903    ui->cbTexture->setChecked(false);
904    ui->cbWithAnimation->setEnabled(false);
905    ui->cbWithAnimation->setChecked(false);
906
907    if(QString::compare(arg1,"M3GM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
908        ui->cbWithAnimation->setEnabled(true);
909    }
910    else if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){
911        ui->cbTexture->setEnabled(true);
912    }
913
941      updateComboBox(arg1, ui->cbToObjects);
942   }
943  
944   void MainWindow::on_cbFromCharacters_currentIndexChanged(const QString &arg1)
945   {
919    ui->cbWithTRBS_ONCC->setEnabled(false);
920    ui->cbWithTRBS_ONCC->setChecked(false);
921    ui->cbCellShading->setEnabled(false);
922    ui->cbCellShading->setChecked(false);
923    ui->cbNormals->setEnabled(false);
924    ui->cbNormals->setChecked(false);
925
926    if(QString::compare(arg1,"TRAM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
927        ui->cbWithTRBS_ONCC->setEnabled(true);
928    }
929    else if(QString::compare(arg1,"TRBS DAE",Qt::CaseSensitive)==0){
930        ui->cbNormals->setEnabled(true);
931        ui->cbCellShading->setEnabled(true);
932    }
933
946      updateComboBox(arg1, ui->cbToCharacters);
947   }
948  
949   void MainWindow::on_cbFromLevels_currentIndexChanged(const QString &arg1)
950   {
939
940    ui->cbSpecificFilesLevels->setEnabled(false);
941    ui->cbSpecificFilesLevels->setChecked(false);
942    ui->cbDatLevels->setEnabled(false);
943    ui->cbDatLevels->setChecked(false);
944    ui->cbBnvLevels->setEnabled(false);
945    ui->cbBnvLevels->setChecked(false);
946    ui->cbAdditionalSourcesLevels->setEnabled(false);
947    ui->cbAdditionalSourcesLevels->setChecked(false);
948    ui->cbGridsLevels->setEnabled(false);
949    ui->cbGridsLevels->setChecked(false);
950
951    if(arg1=="DAT"){ //case sensitive is faster
952        ui->cbSpecificFilesLevels->setEnabled(true);
953    }
954    else if(arg1=="ONI FILES"){ //case sensitive is faster
955        ui->cbDatLevels->setEnabled(true);
956    }
957    else if(arg1=="DAE"){
958        ui->cbBnvLevels->setEnabled(true);
959        ui->cbAdditionalSourcesLevels->setEnabled(true);
960    }
961
951      updateComboBox(arg1, ui->cbToLevels);
952   }
953  
# Line 968 | Line 957 | void MainWindow::on_cbFromMisc_currentIn
957   }
958  
959   void MainWindow::updateComboBox(const QString &arg1, QComboBox *comboBox){
960 <    QString identifier=ui->tabWidget->tabText(ui->tabWidget->currentIndex()).toLower(); // get current tab title text (lower case)
960 >
961 >    QString identifier;
962 >
963 >    if(comboBox == ui->cbToXML){
964 >        identifier = ui->tabWidget->tabText(XMLTabIndex);
965 >    }
966 >    else if(comboBox == ui->cbToTextures){
967 >        identifier = ui->tabWidget->tabText(TexturesTabIndex);
968 >
969 >        //Options are only used for DAT/ONI -> Image
970 >        if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
971 >            ui->gbTextures->setEnabled(false);
972 >        }
973 >        else{
974 >            ui->gbTextures->setEnabled(true);
975 >        }
976 >    }
977 >    else if(comboBox == ui->cbToCharacters){
978 >        identifier = ui->tabWidget->tabText(CharactersTabIndex);
979 >
980 >        ui->cbWithTRBS_ONCC->setEnabled(false);
981 >        ui->cbWithTRBS_ONCC->setChecked(false);
982 >        ui->cbCellShading->setEnabled(false);
983 >        ui->cbCellShading->setChecked(false);
984 >        ui->cbNormals->setEnabled(false);
985 >        ui->cbNormals->setChecked(false);
986 > //#error add drag and drop to Extract TRAM with TRBS/ONCC
987 >        if(QString::compare(arg1,"TRAM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
988 >            ui->cbWithTRBS_ONCC->setEnabled(true);
989 >        }
990 >        else if(QString::compare(arg1,"TRBS DAE",Qt::CaseSensitive)==0){
991 >            ui->cbNormals->setEnabled(true);
992 >            ui->cbCellShading->setEnabled(true);
993 >        }
994 >
995 >    }
996 >    else if(comboBox == ui->cbToObjects){
997 >        identifier = ui->tabWidget->tabText(ObjectsTabIndex);
998 >
999 >        ui->cbTexture->setEnabled(false);
1000 >        ui->cbTexture->setChecked(false);
1001 >        ui->cbWithAnimation->setEnabled(false);
1002 >        ui->cbWithAnimation->setChecked(false);
1003 >
1004 >        if(QString::compare(arg1,"M3GM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
1005 >            ui->cbWithAnimation->setEnabled(true);
1006 >        }
1007 >        else if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){
1008 >            ui->cbTexture->setEnabled(true);
1009 >        }
1010 >    }
1011 >    else if(comboBox == ui->cbToLevels){
1012 >        identifier = ui->tabWidget->tabText(LevelsTabIndex);
1013 >
1014 >        ui->cbSpecificFilesLevels->setEnabled(false);
1015 >        ui->cbSpecificFilesLevels->setChecked(false);
1016 >        ui->cbDatLevels->setEnabled(false);
1017 >        ui->cbDatLevels->setChecked(false);
1018 >        ui->cbBnvLevels->setEnabled(false);
1019 >        ui->cbBnvLevels->setChecked(false);
1020 >        ui->cbAdditionalSourcesLevels->setEnabled(false);
1021 >        ui->cbAdditionalSourcesLevels->setChecked(false);
1022 >        ui->cbGridsLevels->setEnabled(false);
1023 >        ui->cbGridsLevels->setChecked(false);
1024 >
1025 >        if(arg1=="DAT"){ //case sensitive is faster
1026 >            ui->cbSpecificFilesLevels->setEnabled(true);
1027 >        }
1028 >        else if(arg1=="ONI FILES"){ //case sensitive is faster
1029 >            ui->cbDatLevels->setEnabled(true);
1030 >        }
1031 >        else if(arg1=="DAE"){
1032 >            ui->cbBnvLevels->setEnabled(true);
1033 >            ui->cbAdditionalSourcesLevels->setEnabled(true);
1034 >        }
1035 >    }
1036 >    else{ // Misc
1037 >        identifier = ui->tabWidget->tabText(MiscTabIndex);
1038 >    }
1039 >
1040 >    identifier = identifier.toLower(); // get current tab title text (lower case)
1041  
1042      comboBox->clear();
1043  
# Line 1082 | Line 1151 | void MainWindow::removeTableContents(Dro
1151              myTable->removeRow(myTable->selectionModel()->selectedRows().at(size-i-1).row());
1152          }
1153          updateItemsLoaded(myTable);
1154 +        rowsWereChangedInDropTableWidget();
1155      }
1156   }
1157  
# Line 1104 | Line 1174 | void MainWindow::clearTableContents(Drop
1174   #endif
1175  
1176      if(Util::showQuestionPopUp(this,"Are you sure you want to clear the content?",defaultButton)){
1177 <        myTable->clearContents();
1178 <        myTable->setRowCount(0);
1177 >        clearTableNoPrompt(myTable);
1178 >        updateItemsLoaded(myTable);
1179 >        rowsWereChangedInDropTableWidget();
1180      }
1181 <    updateItemsLoaded(myTable);
1181 >
1182   }
1183  
1184 + void MainWindow::clearTableNoPrompt(DropTableWidget *myTable){
1185 +    myTable->clearContents();
1186 +    myTable->setRowCount(0);
1187 + }
1188  
1189   void MainWindow::on_actionPreferences_triggered()
1190   {
# Line 1120 | Line 1195 | void MainWindow::on_actionPreferences_tr
1195  
1196  
1197   void MainWindow::closeEvent(QCloseEvent *event){
1198 <    if(this->vagoSettings->value("ConfirmExit").toBool()){
1199 <        if(!Util::showQuestionPopUp(this,"Exit Vago?")){
1198 >    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1199 >        QMessageBox::StandardButton result = askToSaveCurrentProject();
1200 >        if(result == QMessageBox::StandardButton::Cancel){
1201              event->ignore();
1202 +            return;
1203          }
1204      }
1205 +
1206 +    // Exit application (this will also close all other windows which don't have parent, for instance ManualCommands)
1207 +    QApplication::quit();
1208 + }
1209 +
1210 + QMessageBox::StandardButton MainWindow::askToSaveCurrentProject(){
1211 +    QMessageBox::StandardButton result =
1212 +            Util::showQuestionPopUpWithCancel(this,"There are unsaved changes. Do you want to save the current project?", QMessageBox::StandardButton::Yes);
1213 +
1214 +    if(result == QMessageBox::StandardButton::Yes){
1215 +        on_actionSave_triggered();
1216 +    }
1217 +
1218 +    return result;
1219   }
1220  
1221   void MainWindow::on_cbToLevels_currentIndexChanged(const QString &arg1)
# Line 1150 | Line 1241 | void MainWindow::on_cbBnvLevels_toggled(
1241      ui->leBnvLevels->setEnabled(checked);
1242      ui->cbGridsLevels->setEnabled(checked);
1243      ui->cbGridsLevels->setChecked(checked);
1244 <    if(checked){
1244 >    if(checked && !projectIsLoading){
1245          QString file=QFileDialog::getOpenFileName(this,"Choose the BNV.dae file...","./" , "All Files (*.*)");
1246          if(!file.isEmpty()){
1247              ui->leBnvLevels->setText(file);
# Line 1162 | Line 1253 | void MainWindow::on_cbAdditionalSourcesL
1253   {
1254      ui->leAdditSourcesLevels->setEnabled(checked);
1255  
1256 <    if(checked){
1256 >    if(checked && !projectIsLoading){
1257          QStringList filesSelected=QFileDialog::getOpenFileNames(this,"Choose the additional .dae files...","./" , "All Files (*.*)");
1258          QString filesJoined;
1259          int size=filesSelected.size();
# Line 1185 | Line 1276 | void MainWindow::on_cbWithTRBS_ONCC_togg
1276  
1277   void MainWindow::on_actionCheck_OniSplit_version_triggered()
1278   {
1279 <    QProcess *myProcess = new QProcess();
1280 <    myProcess->setWorkingDirectory(Util::getAppPath());
1281 <    myProcess->start(Util::getOniSplitExeName()+" -version");
1282 <    myProcess->waitForFinished(-1);
1283 <    QString result=myProcess->readAllStandardOutput();
1284 <    delete myProcess;
1285 <    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nActual version is:\n"+result);
1279 >    QProcess myProcess;
1280 >    myProcess.setWorkingDirectory(UtilVago::getAppPath());
1281 >    myProcess.start(UtilVago::getOniSplitExecutable()+" -version");
1282 >    myProcess.waitForFinished();
1283 >
1284 >    QString result=myProcess.readAllStandardOutput();
1285 >
1286 >    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nCurrent version is:\n"+result.trimmed());
1287   }
1288  
1289   void MainWindow::on_actionCheck_xmlTools_version_triggered()
1290   {
1291 <    QProcess *myProcess = new QProcess();
1292 <    myProcess->setWorkingDirectory(Util::getAppPath());
1293 <    myProcess->start(Util::getXmlToolsExeName()+" version");
1294 <    myProcess->waitForFinished(-1);
1295 <    QString result=myProcess->readLine();
1296 <    delete myProcess;
1297 <    Util::showPopUp("This Vago version was built with base in xmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nActual version is:\n"+result);
1291 >    QProcess myProcess;
1292 >    myProcess.setWorkingDirectory(UtilVago::getAppPath());
1293 >    myProcess.start(UtilVago::getXmlToolsExecutable()+" --version");
1294 >    myProcess.waitForFinished();
1295 >    QString result=myProcess.readLine();
1296 >
1297 >    Util::showPopUp("This Vago version was built with base in XmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nCurrent version is:\n"+result.trimmed());
1298   }
1299  
1300   /**
1301    Update items loaded
1302   **/
1303 < void MainWindow::on_tabWidget_currentChanged(int index)
1303 > void MainWindow::on_tabWidget_currentChanged(int)
1304   {
1305 <    QString tabtext = ui->tabWidget->tabText(index);
1214 <
1215 <    if(tabtext.compare("XML",Qt::CaseSensitive)==0){ //case sentive is faster
1216 <        updateItemsLoaded(ui->twSourcesXML);
1217 <    }
1218 <    else if(tabtext.compare("Textures",Qt::CaseSensitive)==0){
1219 <        updateItemsLoaded(ui->twSourcesTextures);
1220 <    }
1221 <    else if(tabtext.compare("Characters",Qt::CaseSensitive)==0){
1222 <        updateItemsLoaded(ui->twSourcesCharacters);
1223 <    }
1224 <    else if(tabtext.compare("Objects",Qt::CaseSensitive)==0){
1225 <        updateItemsLoaded(ui->twSourcesObjects);
1226 <    }
1227 <    else if(tabtext.compare("Levels",Qt::CaseSensitive)==0){
1228 <        updateItemsLoaded(ui->twSourcesLevels);
1229 <    }
1230 <    else{
1231 <        updateItemsLoaded(ui->twSourcesMisc);
1232 <    }
1305 >    updateItemsLoaded(getCurrentTableWidget());
1306   }
1307  
1308   void MainWindow::updateItemsLoaded(DropTableWidget *currentTable){
# Line 1239 | Line 1312 | void MainWindow::updateItemsLoaded(DropT
1312      this->itemsLoaded->setText(QString().setNum(numItems)+ (numItems==1?" item ":" items ") +"loaded");
1313   }
1314  
1315 + void MainWindow::rowsWereChangedInDropTableWidget(){
1316 +    // We have changed rows, we have now unsaved changes.
1317 +    if(!this->unsavedChangesExist){
1318 +        this->unsavedChangesExist = true;
1319 +        setVagoWindowTitle();
1320 +    }
1321 + }
1322 +
1323   void MainWindow::on_tbCommand_clicked()
1324   {
1325 <    //Show preferences
1326 <    ManualCommands *commandsWindow = new ManualCommands(this);
1325 >    //We pass no parent because we want to have an independent window for ManualCommands,
1326 >    //so we can minimize it or maximize indepently from the MainWindow
1327 >    ManualCommands *commandsWindow = new ManualCommands();
1328      commandsWindow->show(); //it destroys itself when finished.
1329   }
1330  
# Line 1282 | Line 1364 | void MainWindow::on_actionOther_triggere
1364  
1365   void MainWindow::on_actionView_log_triggered()
1366   {
1367 <    Util::openLogFile();
1367 >    UtilVago::openLogFile();
1368   }
1369  
1370   void MainWindow::on_actionOpen_AE_folder_triggered()
# Line 1290 | Line 1372 | void MainWindow::on_actionOpen_AE_folder
1372      QDesktopServices::openUrl(QUrl("file:///"+this->AeLocation));
1373   }
1374  
1375 + void MainWindow::on_actionSave_Project_triggered()
1376 + {
1377 +
1378 +    QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),
1379 +                                                    this->vagoSettings->value("LastProjectPath").toString(),
1380 +                                                    tr("Vago project files (*.vgp)"));
1381 +
1382 +    if(!filePath.isEmpty()){
1383 +        saveProjectState(filePath);
1384 +    }
1385 +
1386 + }
1387 +
1388 + // New Project
1389 + void MainWindow::on_actionNew_Project_triggered()
1390 + {
1391 +    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1392 +        QMessageBox::StandardButton result = askToSaveCurrentProject();
1393 +        if(result == QMessageBox::StandardButton::Cancel){
1394 +            return;
1395 +        }
1396 +    }
1397 +
1398 +    QList<DropTableWidget*> myTables = getAllTableWidgets();
1399 +
1400 +    for(DropTableWidget* const currTable : myTables){
1401 +        clearTableNoPrompt(currTable);
1402 +    }
1403 +
1404 +    this->lastProjectFilePath=""; // clear last project file path
1405 +    this->unsavedChangesExist = false;
1406 +
1407 +    setVagoWindowTitle(); // update vago title
1408 + }
1409 +
1410 + void MainWindow::on_actionSave_triggered()
1411 + {
1412 +    if(this->lastProjectFilePath.isEmpty()){
1413 +        on_actionSave_Project_triggered();
1414 +        return;
1415 +    }
1416 +
1417 +    saveProjectState(this->lastProjectFilePath);
1418 + }
1419 +
1420 + void MainWindow::on_actionLoad_Project_triggered()
1421 + {
1422 +
1423 +    QString filePath = QFileDialog::getOpenFileName(this, tr("Load File"),
1424 +                                                    this->vagoSettings->value("LastProjectPath").toString(),
1425 +                                                    tr("Vago project files (*.vgp)"));
1426 +    if(!filePath.isEmpty()){
1427 +        loadProjectState(filePath);
1428 +    }
1429 + }
1430 +
1431 + void MainWindow::on_actionProject1_triggered()
1432 + {
1433 +    loadProjectState(this->ui->actionProject1->text());
1434 + }
1435 +
1436 + void MainWindow::on_actionProject2_triggered()
1437 + {
1438 +    loadProjectState(this->ui->actionProject2->text());
1439 + }
1440 +
1441 + void MainWindow::on_actionProject3_triggered()
1442 + {
1443 +    loadProjectState(this->ui->actionProject3->text());
1444 + }
1445 +
1446 + void MainWindow::on_actionProject4_triggered()
1447 + {
1448 +    loadProjectState(this->ui->actionProject4->text());
1449 + }
1450 +
1451 + void MainWindow::on_actionProject5_triggered()
1452 + {
1453 +    loadProjectState(this->ui->actionProject5->text());
1454 + }
1455 +
1456   QString MainWindow::getTypeConversion(DropTableWidget *myTable){
1457      QString from,to;
1458  
# Line 1339 | Line 1502 | void MainWindow::dtContextMenu(DropTable
1502          selectedRows << rowItem.row();
1503      }
1504  
1505 <    QMenu *menu = new QMenu();
1506 <    QAction *copy = new QAction("Copy",myTable);
1507 <    QAction *moveUp = new QAction("Move Up",myTable);
1508 <    QAction *moveDown = new QAction("Move Down",myTable);
1509 <    QAction *changeOptions = new QAction("Change To Current Options",myTable);
1510 <    QMenu *changeOutput = new QMenu("Change Output for:");
1511 <    QAction *outWorkspace = new QAction("Workspace",myTable);
1512 <    QAction *outCurrOutput = new QAction("Current Output Folder",myTable);
1513 <    QAction *outOther = new QAction("Other...",myTable);
1514 <    QAction *edisable = new QAction("Enable/Disable",myTable);
1505 >    std::unique_ptr<QMenu> menu = std::make_unique<QMenu>();
1506 >    std::unique_ptr<QAction> copy =  std::make_unique<QAction>("Copy",myTable);
1507 >    std::unique_ptr<QAction> moveUp = std::make_unique<QAction>("Move Up",myTable);
1508 >    std::unique_ptr<QAction> moveDown = std::make_unique<QAction>("Move Down",myTable);
1509 >    std::unique_ptr<QAction> changeOptions = std::make_unique<QAction>("Change To Current Options",myTable);
1510 >    std::unique_ptr<QMenu> changeOutput = std::make_unique<QMenu>("Change Output for:");
1511 >    std::unique_ptr<QAction> outWorkspace = std::make_unique<QAction>("Workspace",myTable);
1512 >    std::unique_ptr<QAction> outCurrOutput = std::make_unique<QAction>("Current Output Folder",myTable);
1513 >    std::unique_ptr<QAction> outOther = std::make_unique<QAction>("Other...",myTable);
1514 >    std::unique_ptr<QAction> edisable = std::make_unique<QAction>("Enable/Disable",myTable);
1515  
1516 <    menu->addAction(copy);
1516 >    menu->addAction(copy.get());
1517      menu->addSeparator();
1518 <    menu->addAction(moveUp);
1519 <    menu->addAction(moveDown);
1518 >    menu->addAction(moveUp.get());
1519 >    menu->addAction(moveDown.get());
1520      menu->addSeparator();
1521 <    menu->addAction(changeOptions);
1522 <    menu->addMenu(changeOutput);
1523 <    changeOutput->addActions(QList<QAction*>() << outWorkspace << outCurrOutput << outOther);
1524 <    menu->addAction(edisable);
1521 >    menu->addAction(changeOptions.get());
1522 >    menu->addMenu(changeOutput.get());
1523 >    changeOutput->addActions(QList<QAction*>() << outWorkspace.get() << outCurrOutput.get() << outOther.get());
1524 >    menu->addAction(edisable.get());
1525  
1526  
1527      //if it's in the first row it can't be setted up
# Line 1382 | Line 1545 | void MainWindow::dtContextMenu(DropTable
1545  
1546      QAction* selectedOption = menu->exec(event->globalPos());
1547  
1548 <    if(selectedOption==copy){
1548 >    if(selectedOption==copy.get()){
1549          //Let's copy the contents to the clipboard
1550  
1551          QString toCopy;
# Line 1405 | Line 1568 | void MainWindow::dtContextMenu(DropTable
1568          QApplication::clipboard()->setText(toCopy);
1569          showSuccessStatusMessage(QString::number(size) + (size==1?" item ":" items ")+ "copied to the clipboard");
1570      }
1571 <    else if(selectedOption==moveUp){
1571 >    else if(selectedOption==moveUp.get()){
1572          qSort(selectedRows); //let's order the selections by the row number, so we know exactly how to swap it
1573          myTable->swapPositions(selectedRows,-1);
1574 +        rowsWereChangedInDropTableWidget();
1575      }
1576 <    else if(selectedOption==moveDown){
1576 >    else if(selectedOption==moveDown.get()){
1577          qSort(selectedRows);
1578          myTable->swapPositions(selectedRows,+1);
1579 +        rowsWereChangedInDropTableWidget();
1580      }
1581 <    else if(selectedOption==changeOptions){
1581 >    else if(selectedOption==changeOptions.get()){
1582          changeToCurrentSettings(selectedRows,myTable);
1583      }
1584 <    else if(selectedOption==outWorkspace){
1584 >    else if(selectedOption==outWorkspace.get()){
1585          changeItemsOutput(myTable,selectedRows,this->workspaceLocation);
1586      }
1587 <    else if(selectedOption==outCurrOutput){
1587 >    else if(selectedOption==outCurrOutput.get()){
1588          changeItemsOutput(myTable,selectedRows,this->outputFolder);
1589      }
1590 <    else if(selectedOption==outOther){
1590 >    else if(selectedOption==outOther.get()){
1591  
1592          QString newDir=QFileDialog::getExistingDirectory(this,"Choose the folder for the output of the files selected...",this->AeLocation+"/GameDataFolder");
1593          newDir=Util::normalizePath(newDir);
# Line 1434 | Line 1599 | void MainWindow::dtContextMenu(DropTable
1599          changeItemsOutput(myTable,selectedRows,newDir);
1600  
1601      }
1602 <    else if(selectedOption==edisable){
1602 >    else if(selectedOption==edisable.get()){
1603  
1604          int enabledCount=0, disabledCount=0;
1605  
# Line 1470 | Line 1635 | void MainWindow::dtContextMenu(DropTable
1635              result+=QString::number(disabledCount) + (disabledCount==1?" item ":" items ") + "Disabled";
1636          }
1637  
1638 +        rowsWereChangedInDropTableWidget();
1639          showSuccessStatusMessage(result);
1640      }
1475
1476    delete copy;
1477    delete moveUp;
1478    delete moveDown;
1479    delete changeOptions;
1480    delete outWorkspace;
1481    delete outCurrOutput;
1482    delete outOther;
1483    delete changeOutput;
1484    delete edisable;
1485    delete menu;
1641   }
1642  
1643   void MainWindow::changeToCurrentSettings(QList<int> rows, DropTableWidget* myTable){
# Line 1506 | Line 1661 | void MainWindow::changeToCurrentSettings
1661          myTable->updateTableToolTips(row);
1662      }
1663  
1664 +    rowsWereChangedInDropTableWidget();
1665      showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed to the current settings");
1666   }
1667  
# Line 1529 | Line 1685 | void MainWindow::changeItemsOutput(DropT
1685          myTable->updateTableToolTips(row);
1686      }
1687  
1688 +    rowsWereChangedInDropTableWidget();
1689      showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed the output to "+(newOutput!=this->workspaceLocation?Util::cutName(newOutput):"Vago workspace"));
1690   }
1691  
# Line 1557 | Line 1714 | QString MainWindow::getCommand(DropTable
1714  
1715   }
1716  
1560 /**
1561  This is OS indepented. It maintain size ratio over the Windows and Mac.
1562  **/
1563 void MainWindow::setConverterButtonsSize(){
1564    int height=ui->pbConvertXML->sizeHint().height()*1.3;
1565    ui->pbConvertXML->setMinimumHeight(height);
1566    ui->pbConvertTextures->setMinimumHeight(height);
1567    ui->pbConvertObjects->setMinimumHeight(height);
1568    ui->pbConvertCharacters->setMinimumHeight(height);
1569    ui->pbConvertLevels->setMinimumHeight(height);
1570    ui->pbConvertMisc->setMinimumHeight(height);
1571 }
1572
1717   void MainWindow::connectSlots(){
1718  
1719      //This signal is for thread that is working setup the progress bar (make it visible and set it's min-max)
# Line 1623 | Line 1767 | void MainWindow::connectSlots(){
1767      //Context menu for Misc table
1768      connect(ui->twSourcesMisc, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1769   }
1770 +
1771 + void MainWindow::saveProjectState(const QString &filePath)
1772 + {
1773 +
1774 +    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
1775 +
1776 +    pugi::xml_document doc;
1777 +
1778 +    pugi::xml_node rootNode = doc.append_child("VagoProject");
1779 +    rootNode.append_attribute("vagoVersion").set_value(GlobalVars::LastCompatibleVersion.toUtf8().constData());
1780 +
1781 +    foreach(DropTableWidget* const &myTable, tableWidgets){
1782 +        saveProjectWidget(rootNode, myTable);
1783 +    }
1784 +
1785 +    if(!doc.save_file(filePath.toUtf8().constData(), PUGIXML_TEXT("\t"), pugi::format_default | pugi::format_write_bom, pugi::xml_encoding::encoding_utf8)){
1786 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while trying to save the project file. Please try another path.");
1787 +        return;
1788 +    }
1789 +
1790 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
1791 +
1792 +    this->lastProjectFilePath = filePath;
1793 +    this->unsavedChangesExist = false;
1794 +
1795 +    addNewRecentProject(filePath);
1796 +
1797 +    setVagoWindowTitle();
1798 +
1799 +    showSuccessStatusMessage("Project saved sucessfully.");
1800 + }
1801 +
1802 + void MainWindow::saveProjectWidget(pugi::xml_node &rootNode, DropTableWidget* table)
1803 + {
1804 +    QString from;
1805 +    QString to;
1806 +    QString tabName = getTabNameByTableWidget(table);
1807 +
1808 +    pugi::xml_node currentNodeTable = rootNode.append_child("tempName");
1809 +    pugi::xml_node options;
1810 +
1811 +    if(table==ui->twSourcesXML){ //So we only need to parse one command.
1812 +        from = ui->cbFromXML->currentText().toUtf8().constData();
1813 +        to = ui->cbToXML->currentText().toUtf8().constData();
1814 +    }
1815 +    else if(table==ui->twSourcesTextures){
1816 +        from = ui->cbFromTextures->currentText().toUtf8().constData();
1817 +        to = ui->cbToTextures->currentText().toUtf8().constData();
1818 +        options = currentNodeTable.append_child("Options");
1819 +        options.append_attribute("type").set_value(Util::qStrToCstr(getTextureRBCheckedTypeTexture()->text()));
1820 +        options.append_attribute("genMipMaps").set_value(Util::boolToCstr(ui->cbMipMapsTextures->isChecked()));
1821 +        options.append_attribute("noUwrap").set_value(Util::boolToCstr(ui->cbNoUwrap->isChecked()));
1822 +        options.append_attribute("noVwrap").set_value(Util::boolToCstr(ui->cbNoVwrap->isChecked()));
1823 +        options.append_attribute("large").set_value(Util::boolToCstr(ui->cbLarge->isChecked()));
1824 +        options.append_attribute("envMap").set_value(Util::boolToCstr(ui->cbEnvMap->isChecked()));
1825 +        options.append_attribute("envMapValue").set_value(Util::qStrToCstr(ui->leEnvMapTexture->text()));
1826 +    }
1827 +    else if(table==ui->twSourcesCharacters){
1828 +        from = ui->cbFromCharacters->currentText().toUtf8().constData();
1829 +        to = ui->cbToCharacters->currentText().toUtf8().constData();
1830 +        options = currentNodeTable.append_child("Options");
1831 +        options.append_attribute("cellShading").set_value(Util::boolToCstr(ui->cbCellShading->isChecked()));
1832 +        options.append_attribute("normals").set_value(Util::boolToCstr(ui->cbNormals->isChecked()));
1833 +        options.append_attribute("extractTRBSONCC").set_value(Util::boolToCstr(ui->cbWithTRBS_ONCC->isChecked()));
1834 +        options.append_attribute("extractTRBSONCCValue").set_value(Util::qStrToCstr(ui->leTRBS_ONCC->text()));
1835 +    }
1836 +    else if(table==ui->twSourcesObjects){
1837 +        from = ui->cbFromObjects->currentText().toUtf8().constData();
1838 +        to = ui->cbToObjects->currentText().toUtf8().constData();
1839 +        options = currentNodeTable.append_child("Options");
1840 +        options.append_attribute("texture").set_value(Util::boolToCstr(ui->cbTexture->isChecked()));
1841 +        options.append_attribute("textureValue").set_value(Util::qStrToCstr(ui->leTextureName->text()));
1842 +        options.append_attribute("withAnimation").set_value(Util::boolToCstr(ui->cbWithAnimation->isChecked()));
1843 +        options.append_attribute("withAnimationValue").set_value(Util::qStrToCstr(ui->leAnimationName->text()));
1844 +    }
1845 +    else if(table==ui->twSourcesLevels){
1846 +        from = ui->cbFromLevels->currentText().toUtf8().constData();
1847 +        to = ui->cbToLevels->currentText().toUtf8().constData();
1848 +        options = currentNodeTable.append_child("Options");
1849 +        options.append_attribute("extractWithFiles").set_value(Util::boolToCstr(ui->cbSpecificFilesLevels->isChecked()));
1850 +        options.append_attribute("extractWithFilesValue").set_value(Util::qStrToCstr(ui->leSpecificFilesLevels->text()));
1851 +        options.append_attribute("datFilename").set_value(Util::boolToCstr(ui->cbDatLevels->isChecked()));
1852 +        options.append_attribute("datFilenameValue").set_value(Util::qStrToCstr(ui->leTargetDatLevels->text()));
1853 +        options.append_attribute("bnvSource").set_value(Util::boolToCstr(ui->cbBnvLevels->isChecked()));
1854 +        options.append_attribute("bnvSourceValue").set_value(Util::qStrToCstr(ui->leBnvLevels->text()));
1855 +        options.append_attribute("generateGrids").set_value(Util::boolToCstr(ui->cbGridsLevels->isChecked()));
1856 +        options.append_attribute("additionalSources").set_value(Util::boolToCstr(ui->cbAdditionalSourcesLevels->isChecked()));
1857 +        options.append_attribute("additionalSourcesValue").set_value(Util::qStrToCstr(ui->leAdditSourcesLevels->text()));
1858 +    }
1859 +    else{
1860 +        from = ui->cbFromMisc->currentText().toUtf8().constData();
1861 +        to = ui->cbToMisc->currentText().toUtf8().constData();
1862 +    }
1863 +
1864 +    currentNodeTable.set_name(tabName.toUtf8().constData());
1865 +
1866 +    currentNodeTable.append_attribute("from").set_value(from.toUtf8().constData());
1867 +    currentNodeTable.append_attribute("to").set_value(to.toUtf8().constData());
1868 +
1869 +
1870 +    for(int i=0; i<table->rowCount(); i++){
1871 +
1872 +        QString currFileFolder = table->item(i,0)->text();
1873 +        QString currFromTo = table->item(i,1)->text();
1874 +        QString currCommand = table->item(i,2)->text();
1875 +
1876 +        pugi::xml_node currentRow = currentNodeTable.append_child("Row");
1877 +
1878 +
1879 +        currentRow.append_attribute("fileFolder").set_value(Util::qStrToCstr(currFileFolder));
1880 +        currentRow.append_attribute("fromTo").set_value(Util::qStrToCstr(currFromTo));
1881 +        currentRow.append_attribute("command").set_value(Util::qStrToCstr(currCommand));
1882 +
1883 +        if(table->item(i,2)->background()==table->disabledBackStyle){
1884 +            currentRow.append_attribute("disabled").set_value(true);
1885 +        }
1886 +
1887 +    }
1888 + }
1889 +
1890 + QRadioButton* MainWindow::getTextureRBCheckedTypeTexture()
1891 + {
1892 +    if(ui->rbBGR32->isChecked()){
1893 +        return ui->rbBGR32;
1894 +    }
1895 +    else if(ui->rbBGRA32->isChecked()){
1896 +        return ui->rbBGRA32;
1897 +    }
1898 +    else if(ui->rbBGR555->isChecked()){
1899 +        return ui->rbBGR555;
1900 +    }
1901 +    else if(ui->rbBGRA5551->isChecked()){
1902 +        return ui->rbBGRA5551;
1903 +    }
1904 +    else if(ui->rbBGRA444->isChecked()){
1905 +        return ui->rbBGRA444;
1906 +    }
1907 +    else{ //dxt1 checked
1908 +        return ui->rbDxt1;
1909 +    }
1910 + }
1911 +
1912 + QRadioButton* MainWindow::getTextureRBTypeTextureByName(const QString &texType)
1913 + {
1914 +    if(QString::compare(texType,ui->rbBGR32->text(),Qt::CaseSensitive)==0){
1915 +        return ui->rbBGR32;
1916 +    }
1917 +    else if(QString::compare(texType,ui->rbBGRA32->text(),Qt::CaseSensitive)==0){
1918 +        return ui->rbBGRA32;
1919 +    }
1920 +    else if(QString::compare(texType, ui->rbBGR555->text(),Qt::CaseSensitive)==0){
1921 +        return ui->rbBGR555;
1922 +    }
1923 +    else if(QString::compare(texType,ui->rbBGRA5551->text(),Qt::CaseSensitive)==0){
1924 +        return ui->rbBGRA5551;
1925 +    }
1926 +    else if(QString::compare(texType,ui->rbBGRA444->text(),Qt::CaseSensitive)==0){
1927 +        return ui->rbBGRA444;
1928 +    }
1929 +    else{ //dxt1
1930 +        return ui->rbDxt1;
1931 +    }
1932 +
1933 + }
1934 +
1935 + void MainWindow::setVagoWindowTitle(){
1936 +
1937 +    QString vagoTitle = "Vago v"+GlobalVars::AppVersion + " - ";
1938 +
1939 +    if(this->lastProjectFilePath.isEmpty()){
1940 +        vagoTitle += "Untitled";
1941 +    }
1942 +    else{
1943 +        vagoTitle += Util::cutNameWithoutBackSlash(this->lastProjectFilePath);
1944 +    }
1945 +
1946 +    if(this->unsavedChangesExist){
1947 +        vagoTitle += "*";
1948 +    }
1949 +
1950 +    setWindowTitle(vagoTitle);
1951 + }
1952 +
1953 + DropTableWidget* MainWindow::getCurrentTableWidget(){
1954 +
1955 +    return getTableWidgetByTabName(ui->tabWidget->tabText(ui->tabWidget->currentIndex()));
1956 +
1957 + }
1958 +
1959 + DropTableWidget* MainWindow::getTableWidgetByTabName(const QString &tabName){
1960 +
1961 +    if(tabName.compare("XML",Qt::CaseSensitive)==0){ //case sentive is faster
1962 +        return ui->twSourcesXML;
1963 +    }
1964 +    else if(tabName.compare("Textures",Qt::CaseSensitive)==0){
1965 +        return ui->twSourcesTextures;
1966 +    }
1967 +    else if(tabName.compare("Characters",Qt::CaseSensitive)==0){
1968 +        return ui->twSourcesCharacters;
1969 +    }
1970 +    else if(tabName.compare("Objects",Qt::CaseSensitive)==0){
1971 +        return ui->twSourcesObjects;
1972 +    }
1973 +    else if(tabName.compare("Levels",Qt::CaseSensitive)==0){
1974 +        return ui->twSourcesLevels;
1975 +    }
1976 +    else{
1977 +        return ui->twSourcesMisc;
1978 +    }
1979 +
1980 + }
1981 +
1982 + QString MainWindow::getCurrentTabName(){
1983 +    return ui->tabWidget->tabText(ui->tabWidget->currentIndex());
1984 + }
1985 +
1986 + QString MainWindow::getTabNameByTableWidget(DropTableWidget* table){
1987 +
1988 +    if(table == ui->twSourcesXML){
1989 +        return ui->tabWidget->tabText(XMLTabIndex);
1990 +    }
1991 +    else if(table == ui->twSourcesTextures){
1992 +        return ui->tabWidget->tabText(TexturesTabIndex);
1993 +    }
1994 +    else if(table == ui->twSourcesCharacters){
1995 +        return ui->tabWidget->tabText(CharactersTabIndex);
1996 +    }
1997 +    else if(table == ui->twSourcesObjects){
1998 +        return ui->tabWidget->tabText(ObjectsTabIndex);
1999 +    }
2000 +    else if(table == ui->twSourcesLevels){
2001 +        return ui->tabWidget->tabText(LevelsTabIndex);
2002 +    }
2003 +    else{
2004 +        return ui->tabWidget->tabText(MiscTabIndex);
2005 +    }
2006 +
2007 + }
2008 +
2009 + QList<DropTableWidget*> MainWindow::getAllTableWidgets()
2010 + {
2011 +    QList<DropTableWidget*> tableWidgets;
2012 +
2013 +    tableWidgets << ui->twSourcesXML << ui->twSourcesTextures << ui->twSourcesCharacters
2014 +                 << ui->twSourcesObjects << ui->twSourcesLevels << ui->twSourcesMisc;
2015 +
2016 +    return tableWidgets;
2017 + }
2018 +
2019 + void MainWindow::loadProjectState(const QString &filePath)
2020 + {
2021 +
2022 +    this->projectIsLoading = true;
2023 +
2024 +    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
2025 +        QMessageBox::StandardButton result = askToSaveCurrentProject();
2026 +        if(result == QMessageBox::StandardButton::Cancel){
2027 +            this->projectIsLoading = false;
2028 +            return;
2029 +        }
2030 +    }
2031 +
2032 +    QString statusError = "Couldn't load project.";
2033 +
2034 +    pugi::xml_document doc;
2035 +
2036 +    pugi::xml_parse_result result = doc.load_file(Util::qStrToCstr(filePath));
2037 +
2038 +    if(result.status!=pugi::status_ok){
2039 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while loading project file.\n" + QString(result.description()));
2040 +        showErrStatusMessage(statusError);
2041 +        this->projectIsLoading = false;
2042 +        return;
2043 +    }
2044 +
2045 +
2046 +    if(QString(doc.root().first_child().name()) != "VagoProject"){
2047 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, QString(doc.root().name()) + "The file opened is not a valid VagoProject file. Load aborted.");
2048 +        showErrStatusMessage(statusError);
2049 +        this->projectIsLoading = false;
2050 +        return;
2051 +    }
2052 +
2053 +    QString projVagoVersion;
2054 +
2055 +    try{
2056 +        projVagoVersion = QString(doc.select_node("/VagoProject/@vagoVersion").attribute().value());
2057 +    }
2058 +    catch (const pugi::xpath_exception& e)
2059 +    {
2060 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't find the vagoVersion of the current project. Load aborted.\n" + QString(e.what()));
2061 +        showErrStatusMessage(statusError);
2062 +        this->projectIsLoading = false;
2063 +        return;
2064 +    }
2065 +
2066 +    if(!projVagoVersion.startsWith(GlobalVars::LastCompatibleVersion)){
2067 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "The project that you are trying to load seems it is not compatible with your Vago Version. Please update Vago and try again.");
2068 +        showErrStatusMessage(statusError);
2069 +        this->projectIsLoading = false;
2070 +        return;
2071 +    }
2072 +
2073 +    // After the initial validations begin loading the project data
2074 +
2075 +    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
2076 +
2077 +    try{
2078 +        foreach(DropTableWidget* const &myTable, tableWidgets){
2079 +            loadProjectWidget(doc, myTable);
2080 +        }
2081 +    }
2082 +    catch(const std::exception& e){
2083 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't load the vago project. Error: " + QString(e.what()));
2084 +        showErrStatusMessage(statusError);
2085 +        this->projectIsLoading = false;
2086 +        return;
2087 +    }
2088 +
2089 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2090 +
2091 +    this->lastProjectFilePath = filePath;
2092 +    this->unsavedChangesExist = false;
2093 +
2094 +    addNewRecentProject(filePath);
2095 +
2096 +    setVagoWindowTitle();
2097 +
2098 +    this->projectIsLoading = false;
2099 +
2100 +    showSuccessStatusMessage("Project loaded sucessfully.");
2101 + }
2102 +
2103 +
2104 + void MainWindow::loadProjectWidget(pugi::xml_document &doc, DropTableWidget* table)
2105 + {
2106 +    QString tabName = getTabNameByTableWidget(table);
2107 +    QString from (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@from")).attribute().value());
2108 +    QString to (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@to")).attribute().value());
2109 +
2110 +    if(table==ui->twSourcesXML){
2111 +        ui->cbFromXML->setCurrentText(from);
2112 +        on_cbFromXML_currentIndexChanged(from);
2113 +        ui->cbToXML->setCurrentText(to);
2114 +    }
2115 +    else if(table==ui->twSourcesTextures){
2116 +        //ui->cbFromTextures->setCurrentText(from);
2117 +        on_cbFromTextures_currentIndexChanged(from);
2118 +        ui->cbToTextures->setCurrentText(to);
2119 +
2120 +        getTextureRBTypeTextureByName((doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@type")).attribute().value()))->setChecked(true);
2121 +        ui->cbMipMapsTextures->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@genMipMaps")).attribute().as_bool());
2122 +        ui->cbNoUwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noUwrap")).attribute().as_bool());
2123 +        ui->cbNoVwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noVwrap")).attribute().as_bool());
2124 +        ui->cbLarge->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@large")).attribute().as_bool());
2125 +        ui->cbEnvMap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMap")).attribute().as_bool());
2126 +        ui->leEnvMapTexture->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMapValue")).attribute().value()));
2127 +    }
2128 +    else if(table==ui->twSourcesCharacters){
2129 +        ui->cbFromCharacters->setCurrentText(from);
2130 +        on_cbFromCharacters_currentIndexChanged(from);
2131 +        ui->cbToCharacters->setCurrentText(to);
2132 +
2133 +
2134 +        ui->cbCellShading->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@cellShading")).attribute().as_bool());
2135 +        ui->cbNormals->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@normals")).attribute().as_bool());
2136 +        ui->cbWithTRBS_ONCC->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCC")).attribute().as_bool());
2137 +        ui->leTRBS_ONCC->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCCValue")).attribute().value()));
2138 +    }
2139 +    else if(table==ui->twSourcesObjects){
2140 +        ui->cbFromObjects->setCurrentText(from);
2141 +        on_cbFromObjects_currentIndexChanged(from);
2142 +        ui->cbToObjects->setCurrentText(to);
2143 +
2144 +        ui->cbTexture->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@texture")).attribute().as_bool());
2145 +        ui->leTextureName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@textureValue")).attribute().value()));
2146 +        ui->cbWithAnimation->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimation")).attribute().as_bool());
2147 +        ui->leAnimationName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimationValue")).attribute().value()));
2148 +    }
2149 +    else if(table==ui->twSourcesLevels){
2150 +        ui->cbFromLevels->setCurrentText(from);
2151 +        on_cbFromLevels_currentIndexChanged(from);
2152 +        ui->cbToLevels->setCurrentText(to);
2153 +
2154 +        ui->cbSpecificFilesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFiles")).attribute().as_bool());
2155 +        ui->leSpecificFilesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFilesValue")).attribute().value()));
2156 +        ui->cbDatLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilename")).attribute().as_bool());
2157 +        ui->leTargetDatLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilenameValue")).attribute().value()));
2158 +        ui->cbBnvLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSource")).attribute().as_bool());
2159 +        ui->leBnvLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSourceValue")).attribute().value()));
2160 +        ui->cbGridsLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@generateGrids")).attribute().as_bool());
2161 +        ui->cbAdditionalSourcesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSources")).attribute().as_bool());
2162 +        ui->leAdditSourcesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSourcesValue")).attribute().value()));
2163 +    }
2164 +    else{
2165 +        ui->cbFromMisc->setCurrentText(from);
2166 +        on_cbFromMisc_currentIndexChanged(from);
2167 +        ui->cbToMisc->setCurrentText(to);
2168 +    }
2169 +
2170 +    // Clean previous rows
2171 +    clearTableNoPrompt(table);
2172 +
2173 +    for(const pugi::xpath_node &xPathNode : doc.select_nodes(Util::qStrToCstr("/VagoProject/"+tabName+"/Row"))){
2174 +        pugi::xml_node currNode = xPathNode.node();
2175 +
2176 +        QString currFileFolder = currNode.attribute("fileFolder").value();
2177 +        QString currFromTo = currNode.attribute("fromTo").value();
2178 +        QString currCommand = currNode.attribute("command").value();
2179 +
2180 +        bool isToDisable = false;
2181 +        pugi::xml_attribute disabledAttr = currNode.attribute("disabled");
2182 +        isToDisable = disabledAttr.empty() ? false : disabledAttr.as_bool();
2183 +
2184 +        addRowTable(table,currFileFolder,currFromTo,currCommand, isToDisable);
2185 +    }
2186 + }
2187 +
2188 + void MainWindow::saveRecentProjects(){
2189 +    for(int i=0; i<this->recentProjectsList.size(); i++){
2190 +        this->vagoSettings->setValue("RecentProject" + QString::number(i+1), recentProjectsList[i]);
2191 +    }
2192 + }
2193 +
2194 + void MainWindow::loadRecentProjects(){
2195 +    for(int i=0; i<this->recentProjectsMaxSize; i++){
2196 +
2197 +        QString currProj = this->vagoSettings->value("RecentProject" + QString::number(i+1)).toString();
2198 +
2199 +        if(!currProj.isEmpty()){
2200 +            recentProjectsList.append(currProj);
2201 +        }
2202 +        else{
2203 +            break;
2204 +        }
2205 +    }
2206 +
2207 +    reloadRecentProjectsMenu();
2208 +
2209 + }
2210 +
2211 + void MainWindow::addNewRecentProject(const QString &filePath){
2212 +
2213 +    // If the new project is equal to the last one simply ignore
2214 +    if(filePath == this->vagoSettings->value("RecentProject1").toString()){
2215 +        return;
2216 +    }
2217 +
2218 +    // If the item already exists in our list remove it, so it can go to the top again
2219 +    for(auto it = this->recentProjectsList.begin(); it != this->recentProjectsList.end();){
2220 +        if(*it == filePath){
2221 +            it = this->recentProjectsList.erase(it);
2222 +        }
2223 +        else{
2224 +            it++;
2225 +        }
2226 +    }
2227 +
2228 +    // if we gonna overflow our list, remove the older item to reserve space to the new one
2229 +    if(this->recentProjectsList.size()==this->recentProjectsMaxSize){
2230 +        this->recentProjectsList.removeLast();
2231 +    }
2232 +
2233 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2234 +
2235 +    // add new recent file
2236 +    this->recentProjectsList.prepend(filePath);
2237 +
2238 +    reloadRecentProjectsMenu();
2239 +
2240 +    saveRecentProjects();
2241 + }
2242 +
2243 + void MainWindow::reloadRecentProjectsMenu(){
2244 +
2245 +    ui->menuRecent_Projects->setEnabled(false);
2246 +    ui->actionProject1->setVisible(false);
2247 +    ui->actionProject2->setVisible(false);
2248 +    ui->actionProject3->setVisible(false);
2249 +    ui->actionProject4->setVisible(false);
2250 +    ui->actionProject5->setVisible(false);
2251 +
2252 +    {
2253 +        QList<QString>::const_iterator it;
2254 +        int i;
2255 +        for(it = recentProjectsList.cbegin(), i=0; it != recentProjectsList.cend(); it++, i++){
2256 +
2257 +            QAction* currAction = nullptr;
2258 +
2259 +            switch (i){
2260 +            case 0:
2261 +                currAction = ui->actionProject1;
2262 +                break;
2263 +            case 1:
2264 +                currAction = ui->actionProject2;
2265 +                break;
2266 +            case 2:
2267 +                currAction = ui->actionProject3;
2268 +                break;
2269 +            case 3:
2270 +                currAction = ui->actionProject4;
2271 +                break;
2272 +            case 4:
2273 +                currAction = ui->actionProject5;
2274 +                break;
2275 +            }
2276 +
2277 +            if(currAction){
2278 +                ui->menuRecent_Projects->setEnabled(true);
2279 +                currAction->setText(*it);
2280 +                currAction->setVisible(true);
2281 +            }
2282 +        }
2283 +    }
2284 +
2285 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)