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 801 by s10k, Sun Apr 7 15:36:17 2013 UTC vs.
Revision 1058 by s10k, Sun Oct 30 14:42:39 2016 UTC

# Line 9 | Line 9 | MainWindow::MainWindow(QWidget *parent)
9   {
10      ui->setupUi(this);
11  
12 <    this->AppDir=getOSIndependentAppPath();
12 >    this->myLogger = new Logger(UtilVago::getAppPath(), GlobalVars::AppLogName); //start logger
13  
14 <    this->setWindowTitle("Vago v"+GlobalVars::AppVersion);
14 >    this->myLogger->writeString("Detected AppDir: "+UtilVago::getAppPath());
15 >    this->myLogger->writeString("True app dir: "+QDir::currentPath());
16  
17 <    if(!QFile::exists(this->AppDir+"/"+GlobalVars::OniSplitString)){
18 <        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.");
17 >    setVagoWindowTitle();
18 >
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(this->AppDir+"/"+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(this->AppDir + "/" + 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 32 | Line 35 | MainWindow::MainWindow(QWidget *parent)
35          iniChanged=true;
36      }
37      if(!this->vagoSettings->contains("Workspace")){
38 <        this->vagoSettings->setValue("Workspace", this->AppDir+"/VagoWorkspace");
38 >        this->vagoSettings->setValue("Workspace", UtilVago::getAppPath()+"/VagoWorkspace");
39          iniChanged=true;
40      }
41      if(!this->vagoSettings->contains("AeFolder")){
# Line 41 | 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 52 | Line 55 | MainWindow::MainWindow(QWidget *parent)
55          this->vagoSettings->setValue("AeFolder", aefolder);
56          iniChanged=true;
57      }
58 +    if(!this->vagoSettings->contains("WindowWidth")){
59 +        this->vagoSettings->setValue("WindowWidth", GlobalVars::DefaultWindowWidth);
60 +        iniChanged=true;
61 +    }
62 +    if(!this->vagoSettings->contains("WindowHeight")){
63 +        this->vagoSettings->setValue("WindowHeight", GlobalVars::DefaultWindowHeight);
64 +        iniChanged=true;
65 +    }
66      if(!this->vagoSettings->contains("OniWindow")){
67          this->vagoSettings->setValue("OniWindow", true);
68          iniChanged=true;
# Line 60 | 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);
95 +        iniChanged=true;
96 +    }
97 + #endif
98  
99      if(iniChanged){
100          this->vagoSettings->sync();
# Line 74 | Line 105 | MainWindow::MainWindow(QWidget *parent)
105      this->workspaceWizardsLocation=this->workspaceLocation+"/Wizards";
106      this->AeLocation=this->vagoSettings->value("AeFolder").toString();
107      this->outputFolder=this->workspaceLocation;
108 +    this->startedWindowWidth=this->vagoSettings->value("WindowWidth").toInt();
109 +    this->startedWindowHeight=this->vagoSettings->value("WindowHeight").toInt();
110 + #ifdef Q_OS_MAC
111 +    this->useYesAsDefaultWhenRemovingItems=this->vagoSettings->value("useYesAsDefaultWhenRemovingItems").toBool();
112 + #endif
113  
114      //Create our workspace if it doesn't exists yet
115      if(!QDir(this->workspaceLocation).exists()){
# Line 87 | Line 123 | MainWindow::MainWindow(QWidget *parent)
123      this->myBar->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Fixed);
124      this->myBar->setMinimumWidth(150);
125      this->myBar->hide(); //hide while not being used
126 +    ui->tbAbortConversion->hide(); //hide while not being used
127  
128 <    ui->statusBar->addPermanentWidget(myBar); //this adds automatically in right
129 <
93 <    this->myLogger = new Logger(); //start logger
94 <
95 <    //Initialize list pointers
96 <    this->listToProccess = new QStringList;
97 <
98 <    //Create a thread for do the conversion in background
99 <    this->myConverter = new Converter(this->myLogger,this->listToProccess);
128 >    ui->statusBar->addPermanentWidget(this->myBar); //this adds automatically in right
129 >    ui->statusBar->addPermanentWidget(ui->tbAbortConversion);
130  
131      // User interface
132      ui->mainToolBar->addWidget(ui->tbAE); //add ae installer launch button
# Line 105 | 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 < #ifdef Q_WS_MAC
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
149      ui->tbOni->setIcon(QIcon(":/new/icons/oni_icon_mac.png")); // Oni executable on mac have a different icon than windows
150      // Set mac platform the first one in the menu, and also make it checkable by default
# Line 119 | Line 152 | MainWindow::MainWindow(QWidget *parent)
152      ui->menuTarget_Platform->addAction(ui->actionWindows);
153      ui->actionWindows->setChecked(false);
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
124 < #else
125 <    resize(640,480);
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
157   #endif
158  
159 <    connectSlots();
159 >    resize(this->startedWindowWidth,this->startedWindowHeight);
160 >
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>();
169      mapCommands();
170  
171 <    updateItemsLoaded(ui->twSourcesGeneral);
171 >    updateItemsLoaded(ui->twSourcesXML);
172  
173 <    this->myLogger->writeString("Application started.");
173 >    loadRecentProjects();
174   }
175  
176   MainWindow::~MainWindow()
# Line 142 | 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 162 | Line 247 | void MainWindow::on_actionAE_Package_Cre
247  
248   void MainWindow::on_actionSound_Wizard_triggered()
249   {
250 <    SoundWizard myWizard (this->AppDir, this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
250 >    SoundWizard myWizard (UtilVago::getAppPath(), this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
251 >    myWizard.exec();
252 > }
253 >
254 > void MainWindow::on_actionBackground_Image_Wizard_triggered()
255 > {
256 >    BGImageWizard myWizard (UtilVago::getAppPath(), this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
257      myWizard.exec();
258   }
259  
# Line 173 | Line 264 | void MainWindow::on_tbOni_clicked()
264      if(this->vagoSettings->value("OniWindow").toBool()){ // Run in a window?
265          arguments << "-noswitch";
266      }
267 < #ifdef Q_WS_WIN
267 > #ifdef Q_OS_WIN
268      else{
269          arguments << "-switch"; // only supported on windows. Was added by daodan dll.
270      }
# Line 200 | Line 291 | void MainWindow::on_tbOpenFolder_clicked
291      QDesktopServices::openUrl(QUrl("file:///"+this->outputFolder));
292   }
293  
294 +
295 + void MainWindow::on_tbXmlToolsInterface_clicked()
296 + {
297 +    //We pass no parent because we want to have an independent window for XmlToolsInterface,
298 +    //so we can minimize it or maximize indepently from the MainWindow
299 +    XmlToolsInterface *xmlToolsWindow = new XmlToolsInterface(this->myLogger);
300 +    xmlToolsWindow->show(); //it destroys itself when finished.
301 + }
302 +
303 + void MainWindow::on_tbAbortConversion_clicked()
304 + {
305 +    if(Util::showQuestionPopUp(this,"Are you sure you want to abort the current conversion?")){
306 +        emit terminateCurrProcess();
307 +    }
308 + }
309 +
310   void MainWindow::on_cbEnvMap_toggled(bool checked)
311   {
312      ui->leEnvMapTexture->setEnabled(checked);
# Line 215 | Line 322 | void MainWindow::on_cbWithAnimation_togg
322      ui->leAnimationName->setEnabled(checked);
323   }
324  
325 < void MainWindow::on_cbCamera_toggled(bool checked)
325 > void MainWindow::on_cbSpecificFilesLevels_toggled(bool checked)
326   {
327 <    if(checked){
221 <        ui->cbGeometry->setChecked(false);
222 <    }
223 < }
224 <
225 < void MainWindow::on_cbGeometry_toggled(bool checked)
226 < {
227 <    ui->leGeometryName->setEnabled(checked);
228 <    if(checked){
229 <        ui->cbCamera->setChecked(false);
230 <    }
327 >    ui->leSpecificFilesLevels->setEnabled(checked);
328   }
329  
330   void MainWindow::on_actionCheck_For_Updates_triggered()
# Line 261 | Line 358 | void MainWindow::checkVagoLastVersion(QN
358          }
359      }
360      else{
361 <        Util::showErrorPopUp("An error occurred checking last version:\n\n"+result->errorString());
361 >        UtilVago::showAndLogErrorPopUp(this->myLogger, "An error occurred checking last version:\n\n"+result->errorString());
362      }
363      result->deleteLater();
364   }
365  
366 < void MainWindow::on_pbAddSourceGeneral_clicked()
366 > void MainWindow::on_pbAddSourceXML_clicked()
367   {
368 <    if(QString::compare(ui->cbFromGeneral->currentText(),"ONI",Qt::CaseSensitive)==0 && QString::compare(ui->cbToGeneral->currentText(),"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster)
272 <        addFilesSource(ui->twSourcesGeneral,Util::multipleDirDialog("Choose folders with ONIs..."));
273 <    }
274 <    else{
275 <        addFilesSource( ui->twSourcesGeneral,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
276 <    }
368 >    addFilesSource( ui->twSourcesXML,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
369   }
370  
371   void MainWindow::on_pbAddSourceTextures_clicked()
# Line 281 | Line 373 | void MainWindow::on_pbAddSourceTextures_
373      addFilesSource( ui->twSourcesTextures, QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
374   }
375  
376 < void MainWindow::on_pbAddSourceModels_clicked()
376 > void MainWindow::on_pbAddSourceObjects_clicked()
377   {
378 <    addFilesSource( ui->twSourcesModels,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
378 >    addFilesSource( ui->twSourcesObjects,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
379   }
380  
381 < void MainWindow::on_pbAddSourceAnimations_clicked()
381 > void MainWindow::on_pbAddSourceCharacters_clicked()
382   {
383 <    addFilesSource( ui->twSourcesAnimations,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
383 >    addFilesSource( ui->twSourcesCharacters,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
384   }
385  
386   void MainWindow::on_pbAddSourceLevels_clicked()
387   {
388 <    addFilesSource( ui->twSourcesLevels,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
388 >    if(QString::compare(ui->cbFromLevels->currentText(),"ONI FILES",Qt::CaseSensitive)==0 && QString::compare(ui->cbToLevels->currentText(),"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster)
389 >        addFilesSource(ui->twSourcesLevels,Util::multipleDirDialog("Choose folders with ONIs..."));
390 >    }
391 >    else{
392 >        addFilesSource(ui->twSourcesLevels,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
393 >    }
394   }
395  
396   void MainWindow::on_pbAddSourceMisc_clicked()
# Line 325 | Line 422 | void MainWindow::addFilesSource(DropTabl
422      to = QString(fromTo).remove(0,fromTo.lastIndexOf("> ")+2); //+2 to start after "> "
423  
424      //Pre-processing (check if the files/folders received are valid), e.g. check for ONI->DAT if are only given folders and not files
425 <    if(QString::compare(from,"ONI",Qt::CaseSensitive)==0 && QString::compare(to,"DAT",Qt::CaseSensitive)==0){
425 >    if(from=="ONI FILES" && to=="DAT"){
426          //check if it's a folder
427          foreach(QString myFile, files){
428              if(!QDir(myFile).exists()){
# Line 375 | Line 472 | void MainWindow::addFilesSource(DropTabl
472          addRowTable(myTable,lastFileName,fromTo,command);
473      }
474      updateItemsLoaded(myTable);
475 +    rowsWereChangedInDropTableWidget();
476   }
477  
478 < QString MainWindow::fileParsingGeneral(QString myOutputFolder, QString from, QString to , QString file){
478 > QString MainWindow::fileParsingXML(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
479  
480      QString command;
481  
482 <    if(QString::compare(from,"ONI",Qt::CaseSensitive)==0 && QString::compare(to,"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster
483 <
386 <        QString datName;
387 <
388 <        if(ui->cbDatGeneral->isChecked()){
389 <            if(ui->leTargetDatGeneral->text().isEmpty()){
390 <                showErrStatusMessage("Checkbox '"+ui->cbDatGeneral->text()+"' is selected. The name cannot be empty.");
391 <                return "";
392 <            }
393 <            datName+=QString(myOutputFolder).insert(myOutputFolder.size()-1,ui->leTargetDatGeneral->text()); //set name inputted by user
394 <            if(!ui->leTargetDatGeneral->text().toUpper().endsWith(".DAT")){
395 <                datName.insert(datName.size()-1,".dat"); //append extension if necessary (-1 to maintain final quote)
396 <            }
397 <        }
398 <        else{
399 <            datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/")+".dat"); //if none iputted set the same name of input file
400 <        }
401 <
402 <        if(ui->actionWindows->isChecked()){ //is target plataform select windows?
403 <            return command=this->commandMap.value("general->"+from+"->"+to+"(PC)")+" "+ file + " "+datName;
404 <        }
405 <        else{
406 <            return command=this->commandMap.value("general->"+from+"->"+to+"(demoPCMAC)")+" "+ file + " "+datName;
407 <        }
408 <    }
409 <    else if(QString::compare(from,"ONI",Qt::CaseSensitive)==0 && QString::compare(to,"XML",Qt::CaseSensitive)==0 && ui->cbTRAMGeneral->isChecked()){
410 <        if(ui->leTRAMGeneral->text().isEmpty()){
411 <            showErrStatusMessage("Checkbox '"+ui->cbTRAMGeneral->text()+"' is selected. The source cannot be empty.");
412 <            return "";
413 <        }
414 <        return command=this->commandMap.value("general->"+from+"->"+to)+" "+myOutputFolder+" "+this->commandMap.value("general->"+ui->cbTRAMGeneral->text())+file + " "+ Util::normalizeAndQuote(ui->leTRAMGeneral->text());
482 >    if(from=="ONI" && to=="XML"){
483 >        return command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder+" "+file;
484      }
485 <    else{
486 <        return command=this->commandMap.value("general->"+from+"->"+to)+" "+myOutputFolder+" "+file;
485 >    else if(from=="XML" && to=="ONI"){
486 >        return command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder+" "+file;
487      }
488  
489 +    return "";
490 +
491   }
492  
493 < QString MainWindow::fileParsingTextures(QString myOutputFolder, QString from, QString to , QString file){
493 > QString MainWindow::fileParsingTextures(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
494  
495 <    QString command=this->commandMap.value("textures->"+from+"->"+to)+" "+myOutputFolder;
495 >    QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder;
496  
497      if(ui->gbTextures->isEnabled()){ //faster than compare strings (if is DAT/ONI)
498  
499          if(ui->cbMipMapsTextures->isChecked()){
500 <            command+=" "+this->commandMap.value("textures->"+ui->cbMipMapsTextures->text());
500 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbMipMapsTextures->text());
501          }
502  
503          if(ui->cbNoUwrap->isChecked()){
504 <            command+=" "+this->commandMap.value("textures->"+ui->cbNoUwrap->text());
504 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNoUwrap->text());
505          }
506  
507          if(ui->cbNoVwrap->isChecked()){
508 <            command+=" "+this->commandMap.value("textures->"+ui->cbNoVwrap->text());
508 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNoVwrap->text());
509          }
510  
511          if(ui->cbLarge->isChecked()){
512 <            command+=" "+this->commandMap.value("textures->"+ui->cbLarge->text());
512 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbLarge->text());
513          }
514  
515 <        if(ui->rbBGR32->isChecked()){
445 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGR32->text());
446 <        }
447 <        else if(ui->rbBGRA32->isChecked()){
448 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGRA32->text());
449 <        }
450 <        else if(ui->rbBGR555->isChecked()){
451 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGR555->text());
452 <        }
453 <        else if(ui->rbBGRA5551->isChecked()){
454 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGRA5551->text());
455 <        }
456 <        else if(ui->rbBGRA444->isChecked()){
457 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGRA444->text());
458 <        }
459 <        else{ //dxt1 checked
460 <            command+=" "+this->commandMap.value("textures->"+ui->rbDxt1->text());
461 <        }
515 >        command+=" "+this->commandMap.value(tabTitle+"->"+getTextureRBCheckedTypeTexture()->text());
516  
517          if(ui->cbEnvMap->isChecked()){
518              if(ui->leEnvMapTexture->text().isEmpty()){
519                  showErrStatusMessage("Checkbox '"+ui->cbEnvMap->text()+"' is selected. The name texture name cannot be empty.");
520                  return "";
521              }
522 <            command+=" "+this->commandMap.value("textures->"+ui->cbEnvMap->text()) + ui->leEnvMapTexture->text().remove(".oni",Qt::CaseInsensitive);
522 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbEnvMap->text()) + ui->leEnvMapTexture->text().remove(".oni",Qt::CaseInsensitive);
523          }
524      }
525  
526      return command+=" "+file; //add source
527   }
528  
529 < QString MainWindow::fileParsingModels(QString myOutputFolder, QString from, QString to , QString file){
529 > QString MainWindow::fileParsingCharacters(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
530  
531 <    QString command=this->commandMap.value("models->"+from+"->"+to)+" "+myOutputFolder;
531 >    QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder + " " + file ;
532  
479    //TODO: This can be optimized. When some are not enable others are.
480    if(ui->cbTexture->isChecked()){
481        if(ui->leTextureName->text().isEmpty()){
482            showErrStatusMessage("Checkbox '"+ui->cbTexture->text()+"' is selected. The name cannot be empty.");
483            return "";
484        }
485        command+=" "+this->commandMap.value("models->"+ui->cbTexture->text()) + ui->leTextureName->text().remove(".oni",Qt::CaseInsensitive);
486    }
533  
534      if(ui->cbCellShading->isChecked()){
535 <        command+=" "+this->commandMap.value("models->"+ui->cbCellShading->text());
535 >        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbCellShading->text());
536      }
537  
538      if(ui->cbNormals->isChecked()){
539 <        command+=" "+this->commandMap.value("models->"+ui->cbNormals->text());
539 >        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNormals->text());
540      }
541  
542 <    if(ui->cbWithAnimation->isEnabled()){
543 <        if(ui->cbWithAnimation->isChecked()){
544 <            command+=" "+this->commandMap.value("models->"+ui->cbWithAnimation->text())+ui->leAnimationName->text().remove(".oni",Qt::CaseInsensitive);
545 <        }
500 <        else{
501 <            command+=" "+this->commandMap.value("models->No Animation");
542 >    if(ui->cbWithTRBS_ONCC->isChecked()){
543 >        if(ui->leTRBS_ONCC->text().isEmpty()){
544 >            showErrStatusMessage("Checkbox '"+ui->cbWithTRBS_ONCC->text()+"' is selected. The name cannot be empty.");
545 >            return "";
546          }
503    }
547  
548 +        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbWithTRBS_ONCC->text())+Util::normalizeAndQuote(ui->leTRBS_ONCC->text());
549 +    }
550  
551 <    return command+=" "+file; //add source
551 >    return command;
552   }
553  
509 QString MainWindow::fileParsingAnimations(QString myOutputFolder, QString from, QString to , QString file){
554  
555 <    QString command=this->commandMap.value("animations->"+from+"->"+to)+" "+myOutputFolder + " " + file ;
555 > QString MainWindow::fileParsingObjects(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
556 >
557 >    QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder;
558  
559 <    if(ui->cbCamera->isChecked()){
560 <        command+=" "+this->commandMap.value("animations->"+ui->cbCamera->text());
559 >    //TODO: This can be optimized. When some are not enable others are.
560 >    if(ui->cbTexture->isChecked()){
561 >        if(ui->leTextureName->text().isEmpty()){
562 >            showErrStatusMessage("Checkbox '"+ui->cbTexture->text()+"' is selected. The file source cannot be empty.");
563 >            return "";
564 >        }
565 >        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbTexture->text()) + ui->leTextureName->text();
566      }
567 <    else if(ui->cbGeometry->isChecked()){
568 <        if(ui->leGeometryName->text().isEmpty()){
569 <            showErrStatusMessage("Checkbox '"+ui->cbGeometry->text()+"' is selected. The geometry file path cannot be empty.");
567 >    else if(ui->cbWithAnimation->isChecked()){
568 >        if(ui->leAnimationName->text().isEmpty()){
569 >            showErrStatusMessage("Checkbox '"+ui->cbWithAnimation->text()+"' is selected. The file source cannot be empty.");
570              return "";
571          }
572 <        command+=" "+this->commandMap.value("animations->"+ui->cbGeometry->text()) + (ui->leGeometryName->text().startsWith('"')?ui->leGeometryName->text():Util::insertQuotes(ui->leGeometryName->text()));
572 >        command+=" "+Util::normalizeAndQuote(ui->leAnimationName->text()) + " " + this->commandMap.value(tabTitle+"->"+ui->cbWithAnimation->text()) + file;
573 >        return command;
574      }
575  
576 <    return command;
576 >    if(from=="OBAN ONI (cam)"){
577 >        command+=" -geom:camera";
578 >    }
579 >
580 >    return command+=" "+file; //add source
581   }
582  
583 < QString MainWindow::fileParsingLevels(QString myOutputFolder, QString from, QString to , QString file){
583 > QString MainWindow::fileParsingLevels(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
584  
585      QString datName, command;
586  
587 <    command=this->commandMap.value("levels->"+from+"->"+to)+" "+myOutputFolder+" "+file;
587 >    if(!(from=="ONI FILES" && to=="DAT")){ // to all except this one
588 >
589 >        command=this->commandMap.value(tabTitle+"->"+from+"->"+to);
590  
591 <    if(from=="MASTER XML" && to=="DAT"){
534 <        command+=GlobalVars::OniSplitProcSeparator; //insert mark so we know this action will take 2 commands
591 >        if(ui->cbSpecificFilesLevels->isChecked()){
592  
593 +            if(ui->leSpecificFilesLevels->text().isEmpty()){
594 +                showErrStatusMessage("Checkbox '"+ui->cbSpecificFilesLevels->text()+"' is selected. The files pattern cannot be empty.");
595 +                return "";
596 +            }
597 +
598 +            command+=":"+ui->leSpecificFilesLevels->text();
599 +        }
600 +
601 +        if(from=="DAT" && to=="ONI FILES"){ // extract files to a subdir with the files name ex: level0_Final
602 +            command += " " + myOutputFolder.insert(myOutputFolder.size()-2,QString(Util::cutName(file)).replace(".dat","")) + " " + file;
603 +        }
604 +        else{
605 +            command+=" "+myOutputFolder+" "+file;
606 +        }
607 +
608 +    }
609 +
610 +    if((from=="ONI FILES" || from=="MASTER XML") && to=="DAT"){ // almost the same command for both
611          QString datName;
612 +
613 +        if(from=="MASTER XML"){
614 +            command+=GlobalVars::OniSplitProcSeparator; //insert mark so we know this action will take 2 commands
615 +        }
616 +
617          if(ui->cbDatLevels->isChecked()){
618              if(ui->leTargetDatLevels->text().isEmpty()){
619                  showErrStatusMessage("Checkbox '"+ui->cbDatLevels->text()+"' is selected. The name cannot be empty.");
# Line 545 | Line 625 | QString MainWindow::fileParsingLevels(QS
625              }
626          }
627          else{
628 <            datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/").replace(".xml",".dat",Qt::CaseInsensitive)); //if none iputted set the same name of input file
628 >            if(from=="ONI FILES"){
629 >                datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/")+".dat"); //if none iputted set the same name of input file
630 >            }
631 >            else if(from=="MASTER XML"){
632 >                datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/").replace(".xml",".dat",Qt::CaseInsensitive)); //if none iputted set the same name of input file
633 >            }
634          }
635 <
636 <        if(ui->actionWindows->isChecked()){ //is target plataform select windows?
637 <            command+=this->commandMap.value("general->ONI->"+to+"(PC)")+" "+myOutputFolder+" "+datName; //add second command
635 >        if(from=="ONI FILES"){
636 >            if(ui->actionWindows->isChecked()){ //is target plataform select windows?
637 >                return command=this->commandMap.value(tabTitle+"->"+from+"->"+to+"(PC)")+" "+ file + " "+datName;
638 >            }
639 >            else{
640 >                return command=this->commandMap.value(tabTitle+"->"+from+"->"+to+"(demoPCMAC)")+" "+ file + " "+datName;
641 >            }
642          }
643 <        else{
644 <            command+=this->commandMap.value("general->ONI->"+to+"(demoPCMAC)")+" "+myOutputFolder+" "+datName; //add second command
643 >        else if(from=="MASTER XML"){
644 >            if(ui->actionWindows->isChecked()){ //is target plataform select windows?
645 >                command+=this->commandMap.value(tabTitle+"->ONI FILES->"+to+"(PC)")+" "+myOutputFolder+" "+datName; //add second command
646 >            }
647 >            else{
648 >                command+=this->commandMap.value(tabTitle+"->ONI FILES->"+to+"(demoPCMAC)")+" "+myOutputFolder+" "+datName; //add second command
649 >            }
650          }
651      }
652  
# Line 578 | Line 672 | QString MainWindow::fileParsingLevels(QS
672  
673          //parse all files (separated by spaces)
674          while(true){
675 <            nextIndex=additionalFiles.indexOf(" ",currentIndex+1);
675 >            nextIndex=additionalFiles.indexOf(";",currentIndex+1);
676  
677              command += " "+Util::normalizeAndQuote(additionalFiles.mid(currentIndex,(nextIndex-currentIndex)));
678  
# Line 590 | Line 684 | QString MainWindow::fileParsingLevels(QS
684      }
685  
686      if(ui->cbGridsLevels->isChecked()){
687 <        command+=GlobalVars::OniSplitProcSeparator+this->commandMap.value("levels->"+ui->cbGridsLevels->text())+" "+Util::normalizeAndQuote(ui->leBnvLevels->text())+" "+file+" -out:"+myOutputFolder;
687 >        command+=GlobalVars::OniSplitProcSeparator+this->commandMap.value(tabTitle+"->"+ui->cbGridsLevels->text())+" "+Util::normalizeAndQuote(ui->leBnvLevels->text())+" "+file+" -out:"+myOutputFolder;
688      }
689  
690      return command;
# Line 600 | Line 694 | QString MainWindow::fileParsingMisc(QStr
694      return this->commandMap.value("misc->"+from+"->"+to)+" "+myOutputFolder+" "+file;
695   }
696  
697 < void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command){
697 > void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command, bool isToDisabled){
698      //Get actual number rows
699      int twSize=myTable->rowCount();
700  
# Line 612 | Line 706 | void MainWindow::addRowTable(DropTableWi
706      QTableWidgetItem *newConversion = new QTableWidgetItem(fromTo);
707      QTableWidgetItem *newCommand = new QTableWidgetItem(command);
708  
709 +    if(isToDisabled){
710 +        myTable->setDisableStyleWidgetItem(newFile);
711 +        myTable->setDisableStyleWidgetItem(newConversion);
712 +        myTable->setDisableStyleWidgetItem(newCommand);
713 +    }
714 +
715      myTable->setItem(twSize,0,newFile);
716      myTable->setItem(twSize,1,newConversion);
717      myTable->setItem(twSize,2,newCommand);
# Line 619 | Line 719 | void MainWindow::addRowTable(DropTableWi
719      myTable->updateTableToolTips(twSize); //Update tool tips
720   }
721  
722 < void MainWindow::on_pbConvertGeneral_clicked()
722 > void MainWindow::on_pbConvert_clicked()
723   {
724 <    startConversion(ui->twSourcesGeneral);
724 >    startConversion();
725   }
726  
727 < void MainWindow::on_pbConvertTextures_clicked()
628 < {
629 <    startConversion(ui->twSourcesTextures);
630 < }
631 <
632 < void MainWindow::on_pbConvertModels_clicked()
633 < {
634 <    startConversion(ui->twSourcesModels);
635 < }
636 <
637 < void MainWindow::on_pbConvertAnimations_clicked()
638 < {
639 <    startConversion(ui->twSourcesAnimations);
640 < }
641 <
642 < void MainWindow::on_pbConvertLevels_clicked()
643 < {
644 <    startConversion(ui->twSourcesLevels);
645 < }
646 <
647 < void MainWindow::on_pbConvertMisc_clicked()
648 < {
649 <    startConversion(ui->twSourcesMisc);
650 < }
727 > void MainWindow::startConversion(){
728  
729 < void MainWindow::startConversion(DropTableWidget *myTable){
729 >    DropTableWidget* currTable = getCurrentTableWidget();
730  
731      bool ready=false;
732 <    for(int i=0; i<myTable->rowCount(); i++){ //There are items to process?
733 <        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
732 >    for(int i=0; i<currTable->rowCount(); i++){ //There are items to process?
733 >        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
734              ready=true;
735              break;
736          }
# Line 664 | Line 741 | void MainWindow::startConversion(DropTab
741          return;
742      }
743  
744 <    if(myBar->isVisible()){
744 >    if(this->myBar->isVisible()){
745          Util::showErrorPopUp("Another conversion is progress. Please wait until it finishes.");
746          return;
747      }
748  
749 <    for(int i=0; i<myTable->rowCount(); i++){
749 >    for(int i=0; i<currTable->rowCount(); i++){
750          //Only process enabled items
751 <        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
752 <            this->listToProccess->append(myTable->item(i,2)->text());
751 >        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
752 >            this->listToProccess.append(currTable->item(i,2)->text());
753          }
754      }
755  
# Line 683 | Line 760 | void MainWindow::TsetupProgressBar(int m
760      this->myBar->setValue(0);
761      this->myBar->show();
762      this->myBar->setMaximum(max);
763 +    ui->tbAbortConversion->show();
764   }
765  
766   void  MainWindow::TupdateProgressBar(){
# Line 692 | Line 770 | void  MainWindow::TupdateProgressBar(){
770   void MainWindow::TresultConversion(QString result, int numErrors){
771      QApplication::alert(this); //Show a notification if window is not active
772      this->myBar->hide();
773 +    ui->tbAbortConversion->hide();
774  
775      if(numErrors!=0){
776          QString sNumErrors=QString::number(numErrors);
777          if(numErrors>1){
778 <            Util::showErrorLogPopUp(result+"\n This is the last of "+sNumErrors+" Errors.");
779 <            showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" Errors).");
778 >            UtilVago::showErrorPopUpLogButton(result+"\n This is the last of "+sNumErrors+" errors.");
779 >            showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" errors).");
780          }
781          else{
782 <            Util::showErrorLogPopUp(result);
782 >            UtilVago::showErrorPopUpLogButton(result);
783              showErrStatusMessage("Something gone wrong. Check log file.");
784          }
706
785      }
786      else{
787          showSuccessStatusMessage("Everything went well!");
788      }
789   }
790  
791 + void MainWindow::TconversionAborted(){
792 +    this->myBar->hide();
793 +    ui->tbAbortConversion->hide();
794 +
795 +    showErrStatusMessage("Conversion was aborted.");
796 + }
797 +
798   void MainWindow::showErrStatusMessage(QString message){
799  
800      QPalette myPalete = QPalette();
# Line 729 | Line 814 | void MainWindow::showSuccessStatusMessag
814   }
815  
816   void MainWindow::mapCommands(){
817 <    ////////////////////////////////////////////////////////////////////////General Commands
818 <    this->commandMap.insert("general->DAT->ONI","-export");
819 <    //this->commandMap.insert("general->ONI->DAT","-import"); //Not used.
735 <    this->commandMap.insert("general->ONI->DAT(PC)","-import:nosep");
736 <    this->commandMap.insert("general->ONI->DAT(demoPCMAC)","-import:sep");
737 <    this->commandMap.insert("general->ONI->XML","-extract:xml");
738 <    this->commandMap.insert("general->XML->ONI","-create");
817 >    ////////////////////////////////////////////////////////////////////////XML Commands
818 >    this->commandMap.insert("xml->ONI->XML","-extract:xml");
819 >    this->commandMap.insert("xml->XML->ONI","-create");
820      //######################General Options
821 <    this->commandMap.insert("general->"+ui->cbTRAMGeneral->text(),"-anim-body:");
821 >
822      //Possible Combinations
823 <    this->commandMap.insertMulti("general->DAT","ONI");
824 <    this->commandMap.insertMulti("general->ONI","DAT");
744 <    this->commandMap.insertMulti("general->ONI","XML");
745 <    this->commandMap.insertMulti("general->XML","ONI");
823 >    this->commandMap.insertMulti("xml->ONI","XML");
824 >    this->commandMap.insertMulti("xml->XML","ONI");
825  
826      ////////////////////////////////////////////////////////////////////////Textures Commands
827 <    this->commandMap.insert("textures->DAT / ONI->DDS","-extract:dds");
828 <    this->commandMap.insert("textures->DAT / ONI->TGA","-extract:tga");
829 <    this->commandMap.insert("textures->DAT / ONI->PNG","-extract:png");
830 <    this->commandMap.insert("textures->DAT / ONI->JPG","-extract:jpg");
831 <    this->commandMap.insert("textures->DDS / TGA / PNG / JPG->ONI","-create:txmp");
827 >    this->commandMap.insert("textures->DAT / TXMP ONI->DDS","-extract:dds");
828 >    this->commandMap.insert("textures->DAT / TXMP ONI->TGA","-extract:tga");
829 >    this->commandMap.insert("textures->DAT / TXMP ONI->PNG","-extract:png");
830 >    this->commandMap.insert("textures->DAT / TXMP ONI->JPG","-extract:jpg");
831 >    this->commandMap.insert("textures->TGA / DDS / PNG / JPG->TXMP ONI","-create:txmp");
832      //######################Textures Options
833      this->commandMap.insert("textures->"+ui->rbBGR32->text(),"-format:bgr32");
834      this->commandMap.insert("textures->"+ui->rbBGRA32->text(),"-format:bgra32");
# Line 763 | Line 842 | void MainWindow::mapCommands(){
842      this->commandMap.insert("textures->"+ui->cbLarge->text(),"-large");
843      this->commandMap.insert("textures->"+ui->cbEnvMap->text(),"-envmap:");
844      //Possible Combinations
845 <    this->commandMap.insertMulti("textures->DAT / ONI","DDS");
846 <    this->commandMap.insertMulti("textures->DAT / ONI","TGA");
847 <    this->commandMap.insertMulti("textures->DAT / ONI","PNG");
848 <    this->commandMap.insertMulti("textures->DAT / ONI","JPG");
849 <    this->commandMap.insertMulti("textures->DDS / TGA / PNG / JPG","ONI");
850 <
851 <    ////////////////////////////////////////////////////////////////////////Models Commands
852 <    this->commandMap.insert("models->ONI->OBJ","-extract:obj");
853 <    this->commandMap.insert("models->ONI->DAE","-extract:dae -search "+Util::insertQuotes(this->AeLocation+"/GameDataFolder/level0_Final"));
854 <    this->commandMap.insert("models->OBJ->ONI","-create:m3gm");
855 <    this->commandMap.insert("models->DAE->ONI","-create:trbs");
856 <    //######################Models Options
857 <    this->commandMap.insert("models->"+ui->cbCellShading->text(),"-cel");
858 <    this->commandMap.insert("models->"+ui->cbNormals->text(),"-normals");
859 <    this->commandMap.insert("models->"+ui->cbTexture->text(),"-tex:");
860 <    this->commandMap.insert("models->"+ui->cbWithAnimation->text(),"-anim:");
861 <    this->commandMap.insert("models->No Animation","-noanim"); //No label with this name so can't be dynamic
845 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","TGA");
846 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","DDS");
847 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","PNG");
848 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","JPG");
849 >    this->commandMap.insertMulti("textures->TGA / DDS / PNG / JPG","TXMP ONI");
850 >
851 >    ////////////////////////////////////////////////////////////////////////Characters Commands
852 >    this->commandMap.insert("characters->TRAM ONI->XML / XML & DAE","-extract:xml");
853 >    this->commandMap.insert("characters->TRBS / ONCC ONI->DAE","-extract:dae");
854 >    this->commandMap.insert("characters->TRBS XML->TRBS ONI","-create");
855 >    this->commandMap.insert("characters->TRBS DAE->TRBS ONI","-create:trbs");
856 >    this->commandMap.insert("characters->FILM DAT->XML","film2xml");
857 >
858 >    //######################Characters Options
859 >    this->commandMap.insert("characters->"+ui->cbWithTRBS_ONCC->text(),"-anim-body:");
860 >    this->commandMap.insert("characters->"+ui->cbCellShading->text(),"-cel");
861 >    this->commandMap.insert("characters->"+ui->cbNormals->text(),"-normals");
862      //Possible Combinations
863 <    this->commandMap.insertMulti("models->ONI","OBJ");
864 <    this->commandMap.insertMulti("models->ONI","DAE");
865 <    this->commandMap.insertMulti("models->OBJ","ONI");
866 <    this->commandMap.insertMulti("models->DAE","ONI");
867 <
868 <    ////////////////////////////////////////////////////////////////////////Animations Commands
869 <    this->commandMap.insert("animations->ONI->DAE","-extract:dae");
870 <    this->commandMap.insert("animations->FILM DAT->XML","film2xml");
871 <    //######################Animations Options
872 <    this->commandMap.insert("animations->"+ui->cbCamera->text(),"-geom:camera");
873 <    this->commandMap.insert("animations->"+ui->cbGeometry->text(),"-geom:");
863 >    this->commandMap.insertMulti("characters->TRAM ONI","XML / XML & DAE");
864 >    this->commandMap.insertMulti("characters->TRBS / ONCC ONI","DAE");
865 >    this->commandMap.insertMulti("characters->DAE","TRBS ONI");
866 >    this->commandMap.insertMulti("characters->TRBS DAE","TRBS ONI");
867 >    this->commandMap.insertMulti("characters->TRBS XML","TRBS ONI");
868 >    this->commandMap.insertMulti("characters->FILM DAT","XML");
869 >
870 >    ////////////////////////////////////////////////////////////////////////Objects Commands
871 >    this->commandMap.insert("objects->M3GM ONI->OBJ","-extract:obj");
872 >    this->commandMap.insert("objects->M3GM ONI->DAE","-extract:dae");
873 >    this->commandMap.insert("objects->ONWC ONI->OBJ","-extract:obj");
874 >    this->commandMap.insert("objects->ONWC ONI->DAE","-extract:dae");
875 >    this->commandMap.insert("objects->OBAN ONI (cam)->DAE","-extract:dae");
876 >    this->commandMap.insert("objects->OBJ->M3GM ONI","-create:m3gm");
877 >    //######################Characters Options
878 >    this->commandMap.insert("objects->"+ui->cbTexture->text(),"-tex:");
879 >    this->commandMap.insert("objects->"+ui->cbWithAnimation->text(),"-geom:");
880      //Possible Combinations
881 <    this->commandMap.insertMulti("animations->ONI","DAE");
882 <    this->commandMap.insertMulti("animations->DAE","ONI");
883 <    this->commandMap.insertMulti("animations->FILM DAT","XML");
881 >    this->commandMap.insertMulti("objects->M3GM ONI","OBJ");
882 >    this->commandMap.insertMulti("objects->M3GM ONI","DAE");
883 >    this->commandMap.insertMulti("objects->ONWC ONI","OBJ");
884 >    this->commandMap.insertMulti("objects->ONWC ONI","DAE");
885 >    this->commandMap.insertMulti("objects->OBAN ONI (cam)","DAE");
886 >    this->commandMap.insertMulti("objects->OBJ","M3GM ONI");
887 >
888  
889      ////////////////////////////////////////////////////////////////////////Levels Commands
890 <    this->commandMap.insert("levels->ONI->DAE","-extract:dae -search "+Util::insertQuotes(this->AeLocation+"/GameDataFolder/level0_Final"));
891 <    this->commandMap.insert("levels->DAE->ONI","-create:akev");
890 >    this->commandMap.insert("levels->DAT->ONI FILES","-export");
891 >    //this->commandMap.insert("levels->ONI FILES->DAT","-import"); //Not used.
892 >    this->commandMap.insert("levels->ONI FILES->DAT(PC)","-import:nosep");
893 >    this->commandMap.insert("levels->ONI FILES->DAT(demoPCMAC)","-import:sep");
894 >    this->commandMap.insert("levels->AKEV ONI->DAE","-extract:dae");
895 >    this->commandMap.insert("levels->DAE->AKEV ONI","-create:akev");
896      this->commandMap.insert("levels->MASTER XML->DAT","-create:level");
897      this->commandMap.insert("levels->MASTER XML->ONI FILES","-create:level");
898      //######################Levels Options
899      this->commandMap.insert("levels->"+ui->cbGridsLevels->text(),"-grid:create");
900      //Possible Combinations
901 <    this->commandMap.insertMulti("levels->ONI","DAE");
902 <    this->commandMap.insertMulti("levels->DAE","ONI");
901 >    this->commandMap.insertMulti("levels->DAT","ONI FILES");
902 >    this->commandMap.insertMulti("levels->ONI FILES","DAT");
903 >    this->commandMap.insertMulti("levels->AKEV ONI","DAE");
904 >    this->commandMap.insertMulti("levels->DAE","AKEV ONI");
905      this->commandMap.insertMulti("levels->MASTER XML","DAT");
906      this->commandMap.insertMulti("levels->MASTER XML","ONI FILES");
907  
908      ////////////////////////////////////////////////////////////////////////Misc Commands
909 <    this->commandMap.insert("misc->DAT / ONI->WAV","-extract:wav");
910 <    this->commandMap.insert("misc->DAT / ONI->AIF","-extract:aif");
911 <    this->commandMap.insert("misc->DAT / ONI->TXT","-extract:txt");
912 <    this->commandMap.insert("misc->WAV / AIF->ONI","-create");
913 <    this->commandMap.insert("misc->TXT->ONI","-create:subt");
909 >    this->commandMap.insert("misc->DAT / SNDD ONI->WAV","-extract:wav");
910 >    this->commandMap.insert("misc->DAT / SNDD ONI->AIF","-extract:aif");
911 >    this->commandMap.insert("misc->DAT / SUBT ONI->TXT","-extract:txt");
912 >    this->commandMap.insert("misc->WAV / AIF->SNDD ONI","-create");
913 >    this->commandMap.insert("misc->TXT->SUBT ONI","-create:subt");
914      //Possible Combinations
915 <    this->commandMap.insertMulti("misc->DAT / ONI","WAV");
916 <    this->commandMap.insertMulti("misc->DAT / ONI","AIF");
917 <    this->commandMap.insertMulti("misc->DAT / ONI","TXT");
918 <    this->commandMap.insertMulti("misc->WAV / AIF","ONI");
919 <    this->commandMap.insertMulti("misc->TXT","ONI");
915 >    this->commandMap.insertMulti("misc->DAT / SNDD ONI","WAV");
916 >    this->commandMap.insertMulti("misc->DAT / SNDD ONI","AIF");
917 >    this->commandMap.insertMulti("misc->DAT / SUBT ONI","TXT");
918 >    this->commandMap.insertMulti("misc->WAV / AIF","SNDD ONI");
919 >    this->commandMap.insertMulti("misc->TXT","SUBT ONI");
920  
921   }
922  
923 < void MainWindow::on_cbFromGeneral_currentIndexChanged(const QString &arg1)
923 > void MainWindow::on_cbFromXML_currentIndexChanged(const QString &arg1)
924   {
925 <    updateComboBox(arg1, ui->cbToGeneral, "general");
925 >    updateComboBox(arg1, ui->cbToXML);
926   }
927  
928 +
929   void MainWindow::on_cbFromTextures_currentIndexChanged(const QString &arg1)
930   {
931 <    //Options are only used for DAT/ONI -> Image
836 <    if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
837 <        ui->gbTextures->setEnabled(false);
838 <    }
839 <    else{
840 <        ui->gbTextures->setEnabled(true);
841 <    }
842 <
843 <    updateComboBox(arg1, ui->cbToTextures, "textures");
931 >    updateComboBox(arg1, ui->cbToTextures);
932   }
933  
934 < void MainWindow::on_cbFromModels_currentIndexChanged(const QString &arg1)
934 > void MainWindow::on_cbFromObjects_currentIndexChanged(const QString &arg1)
935   {
936 <
849 <    ui->cbCellShading->setEnabled(false);
850 <    ui->cbCellShading->setChecked(false);
851 <    ui->cbNormals->setEnabled(false);
852 <    ui->cbNormals->setChecked(false);
853 <    ui->cbTexture->setEnabled(false);
854 <    ui->cbTexture->setChecked(false);
855 <    ui->cbWithAnimation->setEnabled(false);
856 <    ui->cbWithAnimation->setChecked(false);
857 <
858 <    if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){ //case sensitive is faster
859 <        ui->cbTexture->setEnabled(true);
860 <    }
861 <    else if(QString::compare(arg1,"DAE",Qt::CaseSensitive)==0){
862 <        ui->cbCellShading->setEnabled(true);
863 <        ui->cbNormals->setEnabled(true);
864 <    }
865 <
866 <    updateComboBox(arg1, ui->cbToModels, "models");
936 >    updateComboBox(arg1, ui->cbToObjects);
937   }
938  
939 < void MainWindow::on_cbFromAnimations_currentIndexChanged(const QString &arg1)
939 > void MainWindow::on_cbFromCharacters_currentIndexChanged(const QString &arg1)
940   {
941 <    ui->cbCamera->setEnabled(false);
872 <    ui->cbCamera->setChecked(false);
873 <    ui->cbGeometry->setEnabled(false);
874 <    ui->cbGeometry->setChecked(false);
875 <
876 <    if(QString::compare(arg1,"ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
877 <        ui->cbCamera->setEnabled(true);
878 <        ui->cbGeometry->setEnabled(true);
879 <    }
880 <
881 <    updateComboBox(arg1, ui->cbToAnimations, "animations");
941 >    updateComboBox(arg1, ui->cbToCharacters);
942   }
943  
944   void MainWindow::on_cbFromLevels_currentIndexChanged(const QString &arg1)
945   {
946 <    updateComboBox(arg1, ui->cbToLevels, "levels");
946 >    updateComboBox(arg1, ui->cbToLevels);
947   }
948  
949   void MainWindow::on_cbFromMisc_currentIndexChanged(const QString &arg1)
950   {
951 <    updateComboBox(arg1, ui->cbToMisc, "misc");
951 >    updateComboBox(arg1, ui->cbToMisc);
952   }
953  
954 < void MainWindow::updateComboBox(const QString &arg1, QComboBox *comboBox, const QString &identifier){
954 > void MainWindow::updateComboBox(const QString &arg1, QComboBox *comboBox){
955 >
956 >    QString identifier;
957 >
958 >    if(comboBox == ui->cbToXML){
959 >        identifier = ui->tabWidget->tabText(XMLTabIndex);
960 >    }
961 >    else if(comboBox == ui->cbToTextures){
962 >        identifier = ui->tabWidget->tabText(TexturesTabIndex);
963 >
964 >        //Options are only used for DAT/ONI -> Image
965 >        if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
966 >            ui->gbTextures->setEnabled(false);
967 >        }
968 >        else{
969 >            ui->gbTextures->setEnabled(true);
970 >        }
971 >    }
972 >    else if(comboBox == ui->cbToCharacters){
973 >        identifier = ui->tabWidget->tabText(CharactersTabIndex);
974 >
975 >        ui->cbWithTRBS_ONCC->setEnabled(false);
976 >        ui->cbWithTRBS_ONCC->setChecked(false);
977 >        ui->cbCellShading->setEnabled(false);
978 >        ui->cbCellShading->setChecked(false);
979 >        ui->cbNormals->setEnabled(false);
980 >        ui->cbNormals->setChecked(false);
981 >
982 >        if(QString::compare(arg1,"TRAM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
983 >            ui->cbWithTRBS_ONCC->setEnabled(true);
984 >        }
985 >        else if(QString::compare(arg1,"TRBS DAE",Qt::CaseSensitive)==0){
986 >            ui->cbNormals->setEnabled(true);
987 >            ui->cbCellShading->setEnabled(true);
988 >        }
989 >
990 >    }
991 >    else if(comboBox == ui->cbToObjects){
992 >        identifier = ui->tabWidget->tabText(ObjectsTabIndex);
993 >
994 >        ui->cbTexture->setEnabled(false);
995 >        ui->cbTexture->setChecked(false);
996 >        ui->cbWithAnimation->setEnabled(false);
997 >        ui->cbWithAnimation->setChecked(false);
998 >
999 >        if(QString::compare(arg1,"M3GM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
1000 >            ui->cbWithAnimation->setEnabled(true);
1001 >        }
1002 >        else if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){
1003 >            ui->cbTexture->setEnabled(true);
1004 >        }
1005 >    }
1006 >    else if(comboBox == ui->cbToLevels){
1007 >        identifier = ui->tabWidget->tabText(LevelsTabIndex);
1008 >
1009 >        ui->cbSpecificFilesLevels->setEnabled(false);
1010 >        ui->cbSpecificFilesLevels->setChecked(false);
1011 >        ui->cbDatLevels->setEnabled(false);
1012 >        ui->cbDatLevels->setChecked(false);
1013 >        ui->cbBnvLevels->setEnabled(false);
1014 >        ui->cbBnvLevels->setChecked(false);
1015 >        ui->cbAdditionalSourcesLevels->setEnabled(false);
1016 >        ui->cbAdditionalSourcesLevels->setChecked(false);
1017 >        ui->cbGridsLevels->setEnabled(false);
1018 >        ui->cbGridsLevels->setChecked(false);
1019 >
1020 >        if(arg1=="DAT"){ //case sensitive is faster
1021 >            ui->cbSpecificFilesLevels->setEnabled(true);
1022 >        }
1023 >        else if(arg1=="ONI FILES"){ //case sensitive is faster
1024 >            ui->cbDatLevels->setEnabled(true);
1025 >        }
1026 >        else if(arg1=="DAE"){
1027 >            ui->cbBnvLevels->setEnabled(true);
1028 >            ui->cbAdditionalSourcesLevels->setEnabled(true);
1029 >        }
1030 >    }
1031 >    else{ // Misc
1032 >        identifier = ui->tabWidget->tabText(MiscTabIndex);
1033 >    }
1034 >
1035 >    identifier = identifier.toLower(); // get current tab title text (lower case)
1036 >
1037      comboBox->clear();
1038  
1039      QStringList toUpdate=QStringList();
# Line 918 | Line 1060 | void MainWindow::on_actionMac_Windows_de
1060      ui->actionWindows->setChecked(false);
1061   }
1062  
1063 < void MainWindow::on_pbRemoveSourceGeneral_clicked()
1063 > void MainWindow::on_pbRemoveSourceXML_clicked()
1064   {
1065 <    removeTableContents( ui->twSourcesGeneral);
1065 >    removeTableContents( ui->twSourcesXML);
1066   }
1067  
1068   void MainWindow::on_pbRemoveSourceTextures_clicked()
# Line 928 | Line 1070 | void MainWindow::on_pbRemoveSourceTextur
1070      removeTableContents(ui->twSourcesTextures);
1071   }
1072  
1073 < void MainWindow::on_pbRemoveSourceModels_clicked()
1073 > void MainWindow::on_pbRemoveSourceObjects_clicked()
1074   {
1075 <    removeTableContents(ui->twSourcesModels);
1075 >    removeTableContents(ui->twSourcesObjects);
1076   }
1077  
1078 < void MainWindow::on_pbRemoveSourceAnimations_clicked()
1078 > void MainWindow::on_pbRemoveSourceCharacters_clicked()
1079   {
1080 <    removeTableContents(ui->twSourcesAnimations);
1080 >    removeTableContents(ui->twSourcesCharacters);
1081   }
1082  
1083   void MainWindow::on_pbRemoveSourceLevels_clicked()
# Line 948 | Line 1090 | void MainWindow::on_pbRemoveSourceMisc_c
1090      removeTableContents(ui->twSourcesMisc);
1091   }
1092  
1093 < void MainWindow::on_pbClearSourcesGeneral_clicked()
1093 > void MainWindow::on_pbClearSourcesXML_clicked()
1094   {
1095 <    clearTableContents(ui->twSourcesGeneral);
1095 >    clearTableContents(ui->twSourcesXML);
1096   }
1097  
1098   void MainWindow::on_pbClearSourcesTextures_clicked()
# Line 958 | Line 1100 | void MainWindow::on_pbClearSourcesTextur
1100      clearTableContents(ui->twSourcesTextures);
1101   }
1102  
1103 < void MainWindow::on_pbClearSourcesModels_clicked()
1103 > void MainWindow::on_pbClearSourcesObjects_clicked()
1104   {
1105 <    clearTableContents(ui->twSourcesModels);
1105 >    clearTableContents(ui->twSourcesObjects);
1106   }
1107  
1108 < void MainWindow::on_pbClearSourcesAnimations_clicked()
1108 > void MainWindow::on_pbClearSourcesCharacters_clicked()
1109   {
1110 <    clearTableContents(ui->twSourcesAnimations);
1110 >    clearTableContents(ui->twSourcesCharacters);
1111   }
1112  
1113   void MainWindow::on_pbClearSourcesLevels_clicked()
# Line 981 | Line 1123 | void MainWindow::on_pbClearSourcesMisc_c
1123   void MainWindow::removeTableContents(DropTableWidget *myTable){
1124      int size = myTable->selectionModel()->selectedRows().size();
1125  
1126 +    QMessageBox::StandardButton defaultButton = QMessageBox::NoButton; // default button for clear asking question, only customizable in mac os
1127 +
1128      if(size==0){
1129          Util::showPopUp("Select a row first.");
1130          return;
1131      }
1132  
1133 <    if(Util::showQuestionPopUp(this,"Are you sure you want to delete the selected rows?")){
1133 > #ifdef Q_OS_MAC
1134 >    if(this->useYesAsDefaultWhenRemovingItems){
1135 >        defaultButton = QMessageBox::Yes;
1136 >    }
1137 >    else{
1138 >        defaultButton = QMessageBox::No;
1139 >    }
1140 > #endif
1141 >
1142 >
1143 >    if(Util::showQuestionPopUp(this,"Are you sure you want to delete the selected rows?",defaultButton)){
1144          for(int i=0; i<size; i++){
1145              //myTable->removeRow(myTable->selectedItems().at(size-i-1)->row());
1146              myTable->removeRow(myTable->selectionModel()->selectedRows().at(size-i-1).row());
1147          }
1148          updateItemsLoaded(myTable);
1149 +        rowsWereChangedInDropTableWidget();
1150      }
1151   }
1152  
1153   void MainWindow::clearTableContents(DropTableWidget *myTable){
1154 +
1155 +    QMessageBox::StandardButton defaultButton = QMessageBox::NoButton; // default button for clear asking question, only customizable in mac os
1156 +
1157      if(myTable->rowCount()==0){
1158          Util::showPopUp("Nothing to clear.");
1159          return;
1160      }
1161  
1162 <    if(Util::showQuestionPopUp(this,"Are you sure you want to clear the content?")){
1163 <        myTable->clearContents();
1164 <        myTable->setRowCount(0);
1162 > #ifdef Q_OS_MAC
1163 >    if(this->useYesAsDefaultWhenRemovingItems){
1164 >        defaultButton = QMessageBox::Yes;
1165      }
1166 <    updateItemsLoaded(myTable);
1166 >    else{
1167 >        defaultButton = QMessageBox::No;
1168 >    }
1169 > #endif
1170 >
1171 >    if(Util::showQuestionPopUp(this,"Are you sure you want to clear the content?",defaultButton)){
1172 >        clearTableNoPrompt(myTable);
1173 >        updateItemsLoaded(myTable);
1174 >        rowsWereChangedInDropTableWidget();
1175 >    }
1176 >
1177   }
1178  
1179 + void MainWindow::clearTableNoPrompt(DropTableWidget *myTable){
1180 +    myTable->clearContents();
1181 +    myTable->setRowCount(0);
1182 + }
1183  
1184   void MainWindow::on_actionPreferences_triggered()
1185   {
# Line 1018 | Line 1190 | void MainWindow::on_actionPreferences_tr
1190  
1191  
1192   void MainWindow::closeEvent(QCloseEvent *event){
1193 <    if(this->vagoSettings->value("ConfirmExit").toBool()){
1194 <        if(!Util::showQuestionPopUp(this,"Exit Vago?")){
1193 >    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1194 >        QMessageBox::StandardButton result = askToSaveCurrentProject();
1195 >        if(result == QMessageBox::StandardButton::Cancel){
1196              event->ignore();
1197 <        }
1025 <    }
1026 < }
1027 <
1028 < void MainWindow::on_cbToGeneral_currentIndexChanged(const QString &arg1)
1029 < {
1030 <
1031 <    ui->cbDatGeneral->setEnabled(false);
1032 <    ui->cbDatGeneral->setChecked(false);
1033 <    ui->cbTRAMGeneral->setEnabled(false);
1034 <    ui->cbTRAMGeneral->setChecked(false);
1035 <
1036 <    if(QString::compare(ui->cbFromGeneral->currentText(),"ONI",Qt::CaseSensitive)==0){
1037 <        if(QString::compare(arg1,"DAT",Qt::CaseSensitive)==0){
1038 <            ui->cbDatGeneral->setEnabled(true);
1039 <        }
1040 <        else{
1041 <            ui->cbTRAMGeneral->setEnabled(true);
1197 >            return;
1198          }
1199      }
1200  
1201 +    // Exit application (this will also close all other windows which don't have parent, for instance ManualCommands)
1202 +    QApplication::quit();
1203   }
1204  
1205 < void MainWindow::on_cbToModels_currentIndexChanged(const QString &arg1)
1206 < {
1207 <    ui->cbWithAnimation->setEnabled(false);
1050 <    ui->cbWithAnimation->setChecked(false);
1205 > QMessageBox::StandardButton MainWindow::askToSaveCurrentProject(){
1206 >    QMessageBox::StandardButton result =
1207 >            Util::showQuestionPopUpWithCancel(this,"There are unsaved changes. Do you want to save the current project?", QMessageBox::StandardButton::Yes);
1208  
1209 <    if(arg1=="DAE"){
1210 <        ui->cbWithAnimation->setEnabled(true);
1209 >    if(result == QMessageBox::StandardButton::Yes){
1210 >        on_actionSave_triggered();
1211      }
1212 +
1213 +    return result;
1214   }
1215  
1216   void MainWindow::on_cbToLevels_currentIndexChanged(const QString &arg1)
1217   {
1218  
1060    ui->cbDatLevels->setEnabled(false);
1061    ui->cbDatLevels->setChecked(false);
1062    ui->cbBnvLevels->setEnabled(false);
1063    ui->cbBnvLevels->setChecked(false);
1064    ui->cbAdditionalSourcesLevels->setEnabled(false);
1065    ui->cbAdditionalSourcesLevels->setChecked(false);
1066    ui->cbGridsLevels->setEnabled(false);
1067    ui->cbGridsLevels->setChecked(false);
1068
1219      if(ui->cbFromLevels->currentText()=="MASTER XML" && arg1=="DAT"){
1220          ui->cbDatLevels->setEnabled(true);
1221      }
1222 <    else if(ui->cbFromLevels->currentText()=="DAE" && arg1=="ONI"){
1223 <        ui->cbBnvLevels->setEnabled(true);
1224 <        ui->cbAdditionalSourcesLevels->setEnabled(true);
1222 >    else if(ui->cbFromLevels->currentText()=="MASTER XML" && arg1=="ONI FILES"){
1223 >        ui->cbDatLevels->setEnabled(false);
1224 >        ui->cbDatLevels->setChecked(false);
1225      }
1076 }
1077
1078 void MainWindow::on_cbDatGeneral_toggled(bool checked)
1079 {
1080    ui->leTargetDatGeneral->setEnabled(checked);
1081 }
1226  
1083 void MainWindow::on_cbTRAMGeneral_toggled(bool checked)
1084 {
1085    ui->leTRAMGeneral->setEnabled(checked);
1086    if(checked){
1087        QString file=QFileDialog::getOpenFileName(this,"Choose the TRAM.oni file...","./" , "All Files (*.*)");
1088        if(!file.isEmpty()){
1089            ui->leTRAMGeneral->setText(file);
1090        }
1091    }
1227   }
1228  
1229   void MainWindow::on_cbDatLevels_toggled(bool checked)
# Line 1101 | Line 1236 | void MainWindow::on_cbBnvLevels_toggled(
1236      ui->leBnvLevels->setEnabled(checked);
1237      ui->cbGridsLevels->setEnabled(checked);
1238      ui->cbGridsLevels->setChecked(checked);
1239 <    if(checked){
1239 >    if(checked && !projectIsLoading){
1240          QString file=QFileDialog::getOpenFileName(this,"Choose the BNV.dae file...","./" , "All Files (*.*)");
1241          if(!file.isEmpty()){
1242              ui->leBnvLevels->setText(file);
# Line 1113 | Line 1248 | void MainWindow::on_cbAdditionalSourcesL
1248   {
1249      ui->leAdditSourcesLevels->setEnabled(checked);
1250  
1251 <    if(checked){
1251 >    if(checked && !projectIsLoading){
1252          QStringList filesSelected=QFileDialog::getOpenFileNames(this,"Choose the additional .dae files...","./" , "All Files (*.*)");
1253          QString filesJoined;
1254          int size=filesSelected.size();
# Line 1129 | Line 1264 | void MainWindow::on_cbAdditionalSourcesL
1264      }
1265   }
1266  
1267 + void MainWindow::on_cbWithTRBS_ONCC_toggled(bool checked)
1268 + {
1269 +    ui->leTRBS_ONCC->setEnabled(checked);
1270 + }
1271 +
1272   void MainWindow::on_actionCheck_OniSplit_version_triggered()
1273   {
1274 <    QProcess *myProcess = new QProcess();
1275 <    myProcess->start(GlobalVars::OniSplitExeName+" -version");
1276 <    myProcess->waitForFinished(-1);
1277 <    QString result=myProcess->readAllStandardOutput();
1278 <    delete myProcess;
1279 <    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nActual version is:\n"+result);
1274 >    QProcess myProcess;
1275 >    myProcess.setWorkingDirectory(UtilVago::getAppPath());
1276 >    myProcess.start(UtilVago::getOniSplitExecutable()+" -version");
1277 >    myProcess.waitForFinished();
1278 >
1279 >    QString result=myProcess.readAllStandardOutput();
1280 >
1281 >    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nCurrent version is:\n"+result.trimmed());
1282   }
1283  
1284   void MainWindow::on_actionCheck_xmlTools_version_triggered()
1285   {
1286 <    QProcess *myProcess = new QProcess();
1287 <    myProcess->start(GlobalVars::XmlToolsExeName+" version");
1288 <    myProcess->waitForFinished(-1);
1289 <    QString result=myProcess->readLine();
1290 <    delete myProcess;
1291 <    Util::showPopUp("This Vago version was built with base in xmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nActual version is:\n"+result);
1286 >    QProcess myProcess;
1287 >    myProcess.setWorkingDirectory(UtilVago::getAppPath());
1288 >    myProcess.start(UtilVago::getXmlToolsExecutable()+" --version");
1289 >    myProcess.waitForFinished();
1290 >    QString result=myProcess.readLine();
1291 >
1292 >    Util::showPopUp("This Vago version was built with base in XmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nCurrent version is:\n"+result.trimmed());
1293   }
1294  
1295   /**
1296    Update items loaded
1297 <  **/
1298 < void MainWindow::on_tabWidget_selected(const QString &arg1)
1297 > **/
1298 > void MainWindow::on_tabWidget_currentChanged(int)
1299   {
1300 <    if(arg1.compare("General",Qt::CaseSensitive)==0){ //case sentive is faster
1158 <        updateItemsLoaded(ui->twSourcesGeneral);
1159 <    }
1160 <    else if(arg1.compare("Textures",Qt::CaseSensitive)==0){
1161 <        updateItemsLoaded(ui->twSourcesTextures);
1162 <    }
1163 <    else if(arg1.compare("Models",Qt::CaseSensitive)==0){
1164 <        updateItemsLoaded(ui->twSourcesModels);
1165 <    }
1166 <    else if(arg1.compare("Levels",Qt::CaseSensitive)==0){
1167 <        updateItemsLoaded(ui->twSourcesLevels);
1168 <    }
1169 <    else{
1170 <        updateItemsLoaded(ui->twSourcesMisc);
1171 <    }
1300 >    updateItemsLoaded(getCurrentTableWidget());
1301   }
1302  
1303   void MainWindow::updateItemsLoaded(DropTableWidget *currentTable){
# Line 1178 | Line 1307 | void MainWindow::updateItemsLoaded(DropT
1307      this->itemsLoaded->setText(QString().setNum(numItems)+ (numItems==1?" item ":" items ") +"loaded");
1308   }
1309  
1310 + void MainWindow::rowsWereChangedInDropTableWidget(){
1311 +    // We have changed rows, we have now unsaved changes.
1312 +    if(!this->unsavedChangesExist){
1313 +        this->unsavedChangesExist = true;
1314 +        setVagoWindowTitle();
1315 +    }
1316 + }
1317 +
1318   void MainWindow::on_tbCommand_clicked()
1319   {
1320 <    //Show preferences
1321 <    ManualCommands *commandsWindow = new ManualCommands(this);
1320 >    //We pass no parent because we want to have an independent window for ManualCommands,
1321 >    //so we can minimize it or maximize indepently from the MainWindow
1322 >    ManualCommands *commandsWindow = new ManualCommands();
1323      commandsWindow->show(); //it destroys itself when finished.
1324   }
1325  
# Line 1221 | Line 1359 | void MainWindow::on_actionOther_triggere
1359  
1360   void MainWindow::on_actionView_log_triggered()
1361   {
1362 <    Util::openLogFile();
1362 >    UtilVago::openLogFile();
1363 > }
1364 >
1365 > void MainWindow::on_actionOpen_AE_folder_triggered()
1366 > {
1367 >    QDesktopServices::openUrl(QUrl("file:///"+this->AeLocation));
1368 > }
1369 >
1370 > void MainWindow::on_actionSave_Project_triggered()
1371 > {
1372 >
1373 >    QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),
1374 >                                                    this->vagoSettings->value("LastProjectPath").toString(),
1375 >                                                    tr("Vago project files (*.vgp)"));
1376 >
1377 >    if(!filePath.isEmpty()){
1378 >        saveProjectState(filePath);
1379 >    }
1380 >
1381 > }
1382 >
1383 > // New Project
1384 > void MainWindow::on_actionNew_Project_triggered()
1385 > {
1386 >    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1387 >        QMessageBox::StandardButton result = askToSaveCurrentProject();
1388 >        if(result == QMessageBox::StandardButton::Cancel){
1389 >            return;
1390 >        }
1391 >    }
1392 >
1393 >    QList<DropTableWidget*> myTables = getAllTableWidgets();
1394 >
1395 >    for(DropTableWidget* const currTable : myTables){
1396 >        clearTableNoPrompt(currTable);
1397 >    }
1398 >
1399 >    this->lastProjectFilePath=""; // clear last project file path
1400 >    this->unsavedChangesExist = false;
1401 >
1402 >    setVagoWindowTitle(); // update vago title
1403 > }
1404 >
1405 > void MainWindow::on_actionSave_triggered()
1406 > {
1407 >    if(this->lastProjectFilePath.isEmpty()){
1408 >        on_actionSave_Project_triggered();
1409 >        return;
1410 >    }
1411 >
1412 >    saveProjectState(this->lastProjectFilePath);
1413 > }
1414 >
1415 > void MainWindow::on_actionLoad_Project_triggered()
1416 > {
1417 >
1418 >    QString filePath = QFileDialog::getOpenFileName(this, tr("Load File"),
1419 >                                                    this->vagoSettings->value("LastProjectPath").toString(),
1420 >                                                    tr("Vago project files (*.vgp)"));
1421 >    if(!filePath.isEmpty()){
1422 >        loadProjectState(filePath);
1423 >    }
1424 > }
1425 >
1426 > void MainWindow::on_actionProject1_triggered()
1427 > {
1428 >    loadProjectState(this->ui->actionProject1->text());
1429 > }
1430 >
1431 > void MainWindow::on_actionProject2_triggered()
1432 > {
1433 >    loadProjectState(this->ui->actionProject2->text());
1434 > }
1435 >
1436 > void MainWindow::on_actionProject3_triggered()
1437 > {
1438 >    loadProjectState(this->ui->actionProject3->text());
1439 > }
1440 >
1441 > void MainWindow::on_actionProject4_triggered()
1442 > {
1443 >    loadProjectState(this->ui->actionProject4->text());
1444 > }
1445 >
1446 > void MainWindow::on_actionProject5_triggered()
1447 > {
1448 >    loadProjectState(this->ui->actionProject5->text());
1449   }
1450  
1451   QString MainWindow::getTypeConversion(DropTableWidget *myTable){
1452      QString from,to;
1453  
1454 <    if(myTable==ui->twSourcesGeneral){
1455 <        from=ui->cbFromGeneral->currentText();
1456 <        to=ui->cbToGeneral->currentText();
1454 >    if(myTable==ui->twSourcesXML){
1455 >        from=ui->cbFromXML->currentText();
1456 >        to=ui->cbToXML->currentText();
1457      }
1458      else if(myTable==ui->twSourcesTextures){
1459          from=ui->cbFromTextures->currentText();
1460          to=ui->cbToTextures->currentText();
1461      }
1462 <    else if(myTable==ui->twSourcesModels){
1463 <        from=ui->cbFromModels->currentText();
1464 <        to=ui->cbToModels->currentText();
1465 <    }
1466 <    else if(myTable==ui->twSourcesAnimations){
1467 <        from=ui->cbFromAnimations->currentText();
1468 <        to=ui->cbToAnimations->currentText();
1462 >    else if(myTable==ui->twSourcesObjects){
1463 >        from=ui->cbFromObjects->currentText();
1464 >        to=ui->cbToObjects->currentText();
1465 >    }
1466 >    else if(myTable==ui->twSourcesCharacters){
1467 >        from=ui->cbFromCharacters->currentText();
1468 >        to=ui->cbToCharacters->currentText();
1469      }
1470      else if(myTable==ui->twSourcesLevels){
1471          from=ui->cbFromLevels->currentText();
# Line 1273 | Line 1497 | void MainWindow::dtContextMenu(DropTable
1497          selectedRows << rowItem.row();
1498      }
1499  
1500 <    QMenu *menu = new QMenu();
1501 <    QAction *copy = new QAction("Copy",myTable);
1502 <    QAction *moveUp = new QAction("Move Up",myTable);
1503 <    QAction *moveDown = new QAction("Move Down",myTable);
1504 <    QAction *changeOptions = new QAction("Change To Current Options",myTable);
1505 <    QMenu *changeOutput = new QMenu("Change Output for:");
1506 <    QAction *outWorkspace = new QAction("Workspace",myTable);
1507 <    QAction *outCurrOutput = new QAction("Current Output Folder",myTable);
1508 <    QAction *outOther = new QAction("Other...",myTable);
1509 <    QAction *edisable = new QAction("Enable/Disable",myTable);
1500 >    std::unique_ptr<QMenu> menu = std::make_unique<QMenu>();
1501 >    std::unique_ptr<QAction> copy =  std::make_unique<QAction>("Copy",myTable);
1502 >    std::unique_ptr<QAction> moveUp = std::make_unique<QAction>("Move Up",myTable);
1503 >    std::unique_ptr<QAction> moveDown = std::make_unique<QAction>("Move Down",myTable);
1504 >    std::unique_ptr<QAction> changeOptions = std::make_unique<QAction>("Change To Current Options",myTable);
1505 >    std::unique_ptr<QMenu> changeOutput = std::make_unique<QMenu>("Change Output for:");
1506 >    std::unique_ptr<QAction> outWorkspace = std::make_unique<QAction>("Workspace",myTable);
1507 >    std::unique_ptr<QAction> outCurrOutput = std::make_unique<QAction>("Current Output Folder",myTable);
1508 >    std::unique_ptr<QAction> outOther = std::make_unique<QAction>("Other...",myTable);
1509 >    std::unique_ptr<QAction> edisable = std::make_unique<QAction>("Enable/Disable",myTable);
1510  
1511 <    menu->addAction(copy);
1511 >    menu->addAction(copy.get());
1512      menu->addSeparator();
1513 <    menu->addAction(moveUp);
1514 <    menu->addAction(moveDown);
1513 >    menu->addAction(moveUp.get());
1514 >    menu->addAction(moveDown.get());
1515      menu->addSeparator();
1516 <    menu->addAction(changeOptions);
1517 <    menu->addMenu(changeOutput);
1518 <    changeOutput->addActions(QList<QAction*>() << outWorkspace << outCurrOutput << outOther);
1519 <    menu->addAction(edisable);
1516 >    menu->addAction(changeOptions.get());
1517 >    menu->addMenu(changeOutput.get());
1518 >    changeOutput->addActions(QList<QAction*>() << outWorkspace.get() << outCurrOutput.get() << outOther.get());
1519 >    menu->addAction(edisable.get());
1520  
1521  
1522      //if it's in the first row it can't be setted up
# Line 1316 | Line 1540 | void MainWindow::dtContextMenu(DropTable
1540  
1541      QAction* selectedOption = menu->exec(event->globalPos());
1542  
1543 <    if(selectedOption==copy){
1543 >    if(selectedOption==copy.get()){
1544          //Let's copy the contents to the clipboard
1545  
1546          QString toCopy;
# Line 1339 | Line 1563 | void MainWindow::dtContextMenu(DropTable
1563          QApplication::clipboard()->setText(toCopy);
1564          showSuccessStatusMessage(QString::number(size) + (size==1?" item ":" items ")+ "copied to the clipboard");
1565      }
1566 <    else if(selectedOption==moveUp){
1566 >    else if(selectedOption==moveUp.get()){
1567          qSort(selectedRows); //let's order the selections by the row number, so we know exactly how to swap it
1568          myTable->swapPositions(selectedRows,-1);
1569 +        rowsWereChangedInDropTableWidget();
1570      }
1571 <    else if(selectedOption==moveDown){
1571 >    else if(selectedOption==moveDown.get()){
1572          qSort(selectedRows);
1573          myTable->swapPositions(selectedRows,+1);
1574 +        rowsWereChangedInDropTableWidget();
1575      }
1576 <    else if(selectedOption==changeOptions){
1576 >    else if(selectedOption==changeOptions.get()){
1577          changeToCurrentSettings(selectedRows,myTable);
1578      }
1579 <    else if(selectedOption==outWorkspace){
1579 >    else if(selectedOption==outWorkspace.get()){
1580          changeItemsOutput(myTable,selectedRows,this->workspaceLocation);
1581      }
1582 <    else if(selectedOption==outCurrOutput){
1582 >    else if(selectedOption==outCurrOutput.get()){
1583          changeItemsOutput(myTable,selectedRows,this->outputFolder);
1584      }
1585 <    else if(selectedOption==outOther){
1585 >    else if(selectedOption==outOther.get()){
1586  
1587          QString newDir=QFileDialog::getExistingDirectory(this,"Choose the folder for the output of the files selected...",this->AeLocation+"/GameDataFolder");
1588          newDir=Util::normalizePath(newDir);
# Line 1368 | Line 1594 | void MainWindow::dtContextMenu(DropTable
1594          changeItemsOutput(myTable,selectedRows,newDir);
1595  
1596      }
1597 <    else if(selectedOption==edisable){
1597 >    else if(selectedOption==edisable.get()){
1598  
1599          int enabledCount=0, disabledCount=0;
1600  
# Line 1404 | Line 1630 | void MainWindow::dtContextMenu(DropTable
1630              result+=QString::number(disabledCount) + (disabledCount==1?" item ":" items ") + "Disabled";
1631          }
1632  
1633 +        rowsWereChangedInDropTableWidget();
1634          showSuccessStatusMessage(result);
1635      }
1409
1410    delete copy;
1411    delete moveUp;
1412    delete moveDown;
1413    delete changeOptions;
1414    delete outWorkspace;
1415    delete outCurrOutput;
1416    delete outOther;
1417    delete changeOutput;
1418    delete edisable;
1419    delete menu;
1636   }
1637  
1638   void MainWindow::changeToCurrentSettings(QList<int> rows, DropTableWidget* myTable){
# Line 1440 | Line 1656 | void MainWindow::changeToCurrentSettings
1656          myTable->updateTableToolTips(row);
1657      }
1658  
1659 +    rowsWereChangedInDropTableWidget();
1660      showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed to the current settings");
1661   }
1662  
# Line 1463 | Line 1680 | void MainWindow::changeItemsOutput(DropT
1680          myTable->updateTableToolTips(row);
1681      }
1682  
1683 +    rowsWereChangedInDropTableWidget();
1684      showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed the output to "+(newOutput!=this->workspaceLocation?Util::cutName(newOutput):"Vago workspace"));
1685   }
1686  
1687   QString MainWindow::getCommand(DropTableWidget* myTable, QString myOutputFolder, QString from, QString to , QString file){
1688 <    if(myTable==ui->twSourcesGeneral){ //So we only need to parse one command.
1689 <        return fileParsingGeneral(myOutputFolder,from,to,file);
1688 >
1689 >    QString tabTitle=ui->tabWidget->tabText(ui->tabWidget->currentIndex()).toLower(); // get current tab title
1690 >
1691 >    if(myTable==ui->twSourcesXML){ //So we only need to parse one command.
1692 >        return fileParsingXML(tabTitle, myOutputFolder,from,to,file);
1693      }
1694      else if(myTable==ui->twSourcesTextures){
1695 <        return fileParsingTextures(myOutputFolder,from,to,file);
1695 >        return fileParsingTextures(tabTitle, myOutputFolder,from,to,file);
1696      }
1697 <    else if(myTable==ui->twSourcesModels){
1698 <        return fileParsingModels(myOutputFolder,from,to,file);
1697 >    else if(myTable==ui->twSourcesObjects){
1698 >        return fileParsingObjects(tabTitle, myOutputFolder,from,to,file);
1699      }
1700 <    else if(myTable==ui->twSourcesAnimations){
1701 <        return fileParsingAnimations(myOutputFolder,from,to,file);
1700 >    else if(myTable==ui->twSourcesCharacters){
1701 >        return fileParsingCharacters(tabTitle, myOutputFolder,from,to,file);
1702      }
1703      else if(myTable==ui->twSourcesLevels){
1704 <        return fileParsingLevels(myOutputFolder,from,to,file);
1704 >        return fileParsingLevels(tabTitle, myOutputFolder,from,to,file);
1705      }
1706      else{
1707          return fileParsingMisc(myOutputFolder,from,to,file);
# Line 1488 | Line 1709 | QString MainWindow::getCommand(DropTable
1709  
1710   }
1711  
1491 /**
1492  This is OS indepented. It maintain size ratio over the Windows and Mac.
1493  **/
1494 void MainWindow::setConverterButtonsSize(){
1495    int height=ui->pbConvertGeneral->sizeHint().height()*1.3;
1496    ui->pbConvertGeneral->setMinimumHeight(height);
1497    ui->pbConvertTextures->setMinimumHeight(height);
1498    ui->pbConvertModels->setMinimumHeight(height);
1499    ui->pbConvertAnimations->setMinimumHeight(height);
1500    ui->pbConvertLevels->setMinimumHeight(height);
1501    ui->pbConvertMisc->setMinimumHeight(height);
1502 }
1503
1504 /**
1505  Gets application directory. In mac os gets the .app directory
1506  **/
1507 QString MainWindow::getOSIndependentAppPath(){
1508 #ifdef Q_WS_MAC
1509    QDir dir = QDir::current();
1510    if(dir.absolutePath().contains(".app")){ // include bundle, but we don't want it
1511        dir.cdUp();
1512        dir.cdUp();
1513    }
1514    return dir.absolutePath();
1515 #else
1516    return  QDir::currentPath();
1517 #endif
1518 }
1519
1712   void MainWindow::connectSlots(){
1713  
1714      //This signal is for thread that is working setup the progress bar (make it visible and set it's min-max)
# Line 1528 | Line 1720 | void MainWindow::connectSlots(){
1720      //This signal is for thread that is working can show the result of a conversion
1721      connect(myConverter, SIGNAL(resultConversion(QString,int)), this, SLOT(TresultConversion(QString,int)));
1722  
1723 +    //This signal is for thread that is working notify the gui thread that the conversion was aborted with sucess
1724 +    connect(myConverter, SIGNAL(conversionAborted()), this, SLOT(TconversionAborted()));
1725 +
1726 +    // This signal is to the user be able to terminate a conversion (OniSplit process in class myConverter will be terminated)
1727 +    connect(this, SIGNAL(terminateCurrProcess()), myConverter, SLOT(terminateCurrProcess()));
1728 +
1729      //Drop signal for General table
1730 <    connect(ui->twSourcesGeneral, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1730 >    connect(ui->twSourcesXML, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1731  
1732      //Drop signal for Textures table
1733      connect(ui->twSourcesTextures, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1734  
1735 <    //Drop signal for Models table
1736 <    connect(ui->twSourcesModels, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1735 >    //Drop signal for Objects table
1736 >    connect(ui->twSourcesObjects, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1737  
1738 <    //Drop signal for Animations table
1739 <    connect(ui->twSourcesAnimations, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1738 >    //Drop signal for Characters table
1739 >    connect(ui->twSourcesCharacters, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1740  
1741      //Drop signal for Levels table
1742      connect(ui->twSourcesLevels, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
# Line 1547 | Line 1745 | void MainWindow::connectSlots(){
1745      connect(ui->twSourcesMisc, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1746  
1747      //Context menu for General table
1748 <    connect(ui->twSourcesGeneral, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1748 >    connect(ui->twSourcesXML, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1749  
1750      //Context menu for Textures table
1751      connect(ui->twSourcesTextures, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1752  
1753 <    //Context menu for Models table
1754 <    connect(ui->twSourcesModels, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1753 >    //Context menu for Objects table
1754 >    connect(ui->twSourcesObjects, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1755  
1756 <    //Context menu for Animations table
1757 <    connect(ui->twSourcesAnimations, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1756 >    //Context menu for Characters table
1757 >    connect(ui->twSourcesCharacters, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1758  
1759      //Context menu for Levels table
1760      connect(ui->twSourcesLevels, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
# Line 1565 | Line 1763 | void MainWindow::connectSlots(){
1763      connect(ui->twSourcesMisc, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1764   }
1765  
1766 + void MainWindow::saveProjectState(const QString &filePath)
1767 + {
1768 +
1769 +    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
1770 +
1771 +    pugi::xml_document doc;
1772 +
1773 +    pugi::xml_node rootNode = doc.append_child("VagoProject");
1774 +    rootNode.append_attribute("vagoVersion").set_value(GlobalVars::LastCompatibleVersion.toUtf8().constData());
1775  
1776 +    foreach(DropTableWidget* const &myTable, tableWidgets){
1777 +        saveProjectWidget(rootNode, myTable);
1778 +    }
1779 +
1780 +    if(!doc.save_file(filePath.toUtf8().constData(), PUGIXML_TEXT("\t"), pugi::format_default | pugi::format_write_bom, pugi::xml_encoding::encoding_utf8)){
1781 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while trying to save the project file. Please try another path.");
1782 +        return;
1783 +    }
1784 +
1785 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
1786 +
1787 +    this->lastProjectFilePath = filePath;
1788 +    this->unsavedChangesExist = false;
1789 +
1790 +    addNewRecentProject(filePath);
1791 +
1792 +    setVagoWindowTitle();
1793 +
1794 +    showSuccessStatusMessage("Project saved sucessfully.");
1795 + }
1796 +
1797 + void MainWindow::saveProjectWidget(pugi::xml_node &rootNode, DropTableWidget* table)
1798 + {
1799 +    QString from;
1800 +    QString to;
1801 +    QString tabName = getTabNameByTableWidget(table);
1802 +
1803 +    pugi::xml_node currentNodeTable = rootNode.append_child("tempName");
1804 +    pugi::xml_node options;
1805 +
1806 +    if(table==ui->twSourcesXML){ //So we only need to parse one command.
1807 +        from = ui->cbFromXML->currentText().toUtf8().constData();
1808 +        to = ui->cbToXML->currentText().toUtf8().constData();
1809 +    }
1810 +    else if(table==ui->twSourcesTextures){
1811 +        from = ui->cbFromTextures->currentText().toUtf8().constData();
1812 +        to = ui->cbToTextures->currentText().toUtf8().constData();
1813 +        options = currentNodeTable.append_child("Options");
1814 +        options.append_attribute("type").set_value(Util::qStrToCstr(getTextureRBCheckedTypeTexture()->text()));
1815 +        options.append_attribute("genMipMaps").set_value(Util::boolToCstr(ui->cbMipMapsTextures->isChecked()));
1816 +        options.append_attribute("noUwrap").set_value(Util::boolToCstr(ui->cbNoUwrap->isChecked()));
1817 +        options.append_attribute("noVwrap").set_value(Util::boolToCstr(ui->cbNoVwrap->isChecked()));
1818 +        options.append_attribute("large").set_value(Util::boolToCstr(ui->cbLarge->isChecked()));
1819 +        options.append_attribute("envMap").set_value(Util::boolToCstr(ui->cbEnvMap->isChecked()));
1820 +        options.append_attribute("envMapValue").set_value(Util::qStrToCstr(ui->leEnvMapTexture->text()));
1821 +    }
1822 +    else if(table==ui->twSourcesCharacters){
1823 +        from = ui->cbFromCharacters->currentText().toUtf8().constData();
1824 +        to = ui->cbToCharacters->currentText().toUtf8().constData();
1825 +        options = currentNodeTable.append_child("Options");
1826 +        options.append_attribute("cellShading").set_value(Util::boolToCstr(ui->cbCellShading->isChecked()));
1827 +        options.append_attribute("normals").set_value(Util::boolToCstr(ui->cbNormals->isChecked()));
1828 +        options.append_attribute("extractTRBSONCC").set_value(Util::boolToCstr(ui->cbWithTRBS_ONCC->isChecked()));
1829 +        options.append_attribute("extractTRBSONCCValue").set_value(Util::qStrToCstr(ui->leTRBS_ONCC->text()));
1830 +    }
1831 +    else if(table==ui->twSourcesObjects){
1832 +        from = ui->cbFromObjects->currentText().toUtf8().constData();
1833 +        to = ui->cbToObjects->currentText().toUtf8().constData();
1834 +        options = currentNodeTable.append_child("Options");
1835 +        options.append_attribute("texture").set_value(Util::boolToCstr(ui->cbTexture->isChecked()));
1836 +        options.append_attribute("textureValue").set_value(Util::qStrToCstr(ui->leTextureName->text()));
1837 +        options.append_attribute("withAnimation").set_value(Util::boolToCstr(ui->cbWithAnimation->isChecked()));
1838 +        options.append_attribute("withAnimationValue").set_value(Util::qStrToCstr(ui->leAnimationName->text()));
1839 +    }
1840 +    else if(table==ui->twSourcesLevels){
1841 +        from = ui->cbFromLevels->currentText().toUtf8().constData();
1842 +        to = ui->cbToLevels->currentText().toUtf8().constData();
1843 +        options = currentNodeTable.append_child("Options");
1844 +        options.append_attribute("extractWithFiles").set_value(Util::boolToCstr(ui->cbSpecificFilesLevels->isChecked()));
1845 +        options.append_attribute("extractWithFilesValue").set_value(Util::qStrToCstr(ui->leSpecificFilesLevels->text()));
1846 +        options.append_attribute("datFilename").set_value(Util::boolToCstr(ui->cbDatLevels->isChecked()));
1847 +        options.append_attribute("datFilenameValue").set_value(Util::qStrToCstr(ui->leTargetDatLevels->text()));
1848 +        options.append_attribute("bnvSource").set_value(Util::boolToCstr(ui->cbBnvLevels->isChecked()));
1849 +        options.append_attribute("bnvSourceValue").set_value(Util::qStrToCstr(ui->leBnvLevels->text()));
1850 +        options.append_attribute("generateGrids").set_value(Util::boolToCstr(ui->cbGridsLevels->isChecked()));
1851 +        options.append_attribute("additionalSources").set_value(Util::boolToCstr(ui->cbAdditionalSourcesLevels->isChecked()));
1852 +        options.append_attribute("additionalSourcesValue").set_value(Util::qStrToCstr(ui->leAdditSourcesLevels->text()));
1853 +    }
1854 +    else{
1855 +        from = ui->cbFromMisc->currentText().toUtf8().constData();
1856 +        to = ui->cbToMisc->currentText().toUtf8().constData();
1857 +    }
1858 +
1859 +    currentNodeTable.set_name(tabName.toUtf8().constData());
1860 +
1861 +    currentNodeTable.append_attribute("from").set_value(from.toUtf8().constData());
1862 +    currentNodeTable.append_attribute("to").set_value(to.toUtf8().constData());
1863 +
1864 +
1865 +    for(int i=0; i<table->rowCount(); i++){
1866 +
1867 +        QString currFileFolder = table->item(i,0)->text();
1868 +        QString currFromTo = table->item(i,1)->text();
1869 +        QString currCommand = table->item(i,2)->text();
1870 +
1871 +        pugi::xml_node currentRow = currentNodeTable.append_child("Row");
1872 +
1873 +
1874 +        currentRow.append_attribute("fileFolder").set_value(Util::qStrToCstr(currFileFolder));
1875 +        currentRow.append_attribute("fromTo").set_value(Util::qStrToCstr(currFromTo));
1876 +        currentRow.append_attribute("command").set_value(Util::qStrToCstr(currCommand));
1877 +
1878 +        if(table->item(i,2)->background()==table->disabledBackStyle){
1879 +            currentRow.append_attribute("disabled").set_value(true);
1880 +        }
1881 +
1882 +    }
1883 + }
1884 +
1885 + QRadioButton* MainWindow::getTextureRBCheckedTypeTexture()
1886 + {
1887 +    if(ui->rbBGR32->isChecked()){
1888 +        return ui->rbBGR32;
1889 +    }
1890 +    else if(ui->rbBGRA32->isChecked()){
1891 +        return ui->rbBGRA32;
1892 +    }
1893 +    else if(ui->rbBGR555->isChecked()){
1894 +        return ui->rbBGR555;
1895 +    }
1896 +    else if(ui->rbBGRA5551->isChecked()){
1897 +        return ui->rbBGRA5551;
1898 +    }
1899 +    else if(ui->rbBGRA444->isChecked()){
1900 +        return ui->rbBGRA444;
1901 +    }
1902 +    else{ //dxt1 checked
1903 +        return ui->rbDxt1;
1904 +    }
1905 + }
1906 +
1907 + QRadioButton* MainWindow::getTextureRBTypeTextureByName(const QString &texType)
1908 + {
1909 +    if(QString::compare(texType,ui->rbBGR32->text(),Qt::CaseSensitive)==0){
1910 +        return ui->rbBGR32;
1911 +    }
1912 +    else if(QString::compare(texType,ui->rbBGRA32->text(),Qt::CaseSensitive)==0){
1913 +        return ui->rbBGRA32;
1914 +    }
1915 +    else if(QString::compare(texType, ui->rbBGR555->text(),Qt::CaseSensitive)==0){
1916 +        return ui->rbBGR555;
1917 +    }
1918 +    else if(QString::compare(texType,ui->rbBGRA5551->text(),Qt::CaseSensitive)==0){
1919 +        return ui->rbBGRA5551;
1920 +    }
1921 +    else if(QString::compare(texType,ui->rbBGRA444->text(),Qt::CaseSensitive)==0){
1922 +        return ui->rbBGRA444;
1923 +    }
1924 +    else{ //dxt1
1925 +        return ui->rbDxt1;
1926 +    }
1927 +
1928 + }
1929 +
1930 + void MainWindow::setVagoWindowTitle(){
1931 +
1932 +    QString vagoTitle = "Vago v"+GlobalVars::AppVersion + " - ";
1933 +
1934 +    if(this->lastProjectFilePath.isEmpty()){
1935 +        vagoTitle += "Untitled";
1936 +    }
1937 +    else{
1938 +        vagoTitle += Util::cutNameWithoutBackSlash(this->lastProjectFilePath);
1939 +    }
1940 +
1941 +    if(this->unsavedChangesExist){
1942 +        vagoTitle += "*";
1943 +    }
1944 +
1945 +    setWindowTitle(vagoTitle);
1946 + }
1947 +
1948 + DropTableWidget* MainWindow::getCurrentTableWidget(){
1949 +
1950 +    return getTableWidgetByTabName(ui->tabWidget->tabText(ui->tabWidget->currentIndex()));
1951 +
1952 + }
1953 +
1954 + DropTableWidget* MainWindow::getTableWidgetByTabName(const QString &tabName){
1955 +
1956 +    if(tabName.compare("XML",Qt::CaseSensitive)==0){ //case sentive is faster
1957 +        return ui->twSourcesXML;
1958 +    }
1959 +    else if(tabName.compare("Textures",Qt::CaseSensitive)==0){
1960 +        return ui->twSourcesTextures;
1961 +    }
1962 +    else if(tabName.compare("Characters",Qt::CaseSensitive)==0){
1963 +        return ui->twSourcesCharacters;
1964 +    }
1965 +    else if(tabName.compare("Objects",Qt::CaseSensitive)==0){
1966 +        return ui->twSourcesObjects;
1967 +    }
1968 +    else if(tabName.compare("Levels",Qt::CaseSensitive)==0){
1969 +        return ui->twSourcesLevels;
1970 +    }
1971 +    else{
1972 +        return ui->twSourcesMisc;
1973 +    }
1974 +
1975 + }
1976 +
1977 + QString MainWindow::getCurrentTabName(){
1978 +    return ui->tabWidget->tabText(ui->tabWidget->currentIndex());
1979 + }
1980 +
1981 + QString MainWindow::getTabNameByTableWidget(DropTableWidget* table){
1982 +
1983 +    if(table == ui->twSourcesXML){
1984 +        return ui->tabWidget->tabText(XMLTabIndex);
1985 +    }
1986 +    else if(table == ui->twSourcesTextures){
1987 +        return ui->tabWidget->tabText(TexturesTabIndex);
1988 +    }
1989 +    else if(table == ui->twSourcesCharacters){
1990 +        return ui->tabWidget->tabText(CharactersTabIndex);
1991 +    }
1992 +    else if(table == ui->twSourcesObjects){
1993 +        return ui->tabWidget->tabText(ObjectsTabIndex);
1994 +    }
1995 +    else if(table == ui->twSourcesLevels){
1996 +        return ui->tabWidget->tabText(LevelsTabIndex);
1997 +    }
1998 +    else{
1999 +        return ui->tabWidget->tabText(MiscTabIndex);
2000 +    }
2001 +
2002 + }
2003 +
2004 + QList<DropTableWidget*> MainWindow::getAllTableWidgets()
2005 + {
2006 +    QList<DropTableWidget*> tableWidgets;
2007 +
2008 +    tableWidgets << ui->twSourcesXML << ui->twSourcesTextures << ui->twSourcesCharacters
2009 +                 << ui->twSourcesObjects << ui->twSourcesLevels << ui->twSourcesMisc;
2010 +
2011 +    return tableWidgets;
2012 + }
2013 +
2014 + void MainWindow::loadProjectState(const QString &filePath)
2015 + {
2016 +
2017 +    this->projectIsLoading = true;
2018 +
2019 +    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
2020 +        QMessageBox::StandardButton result = askToSaveCurrentProject();
2021 +        if(result == QMessageBox::StandardButton::Cancel){
2022 +            this->projectIsLoading = false;
2023 +            return;
2024 +        }
2025 +    }
2026 +
2027 +    QString statusError = "Couldn't load project.";
2028 +
2029 +    pugi::xml_document doc;
2030 +
2031 +    pugi::xml_parse_result result = doc.load_file(Util::qStrToCstr(filePath));
2032 +
2033 +    if(result.status!=pugi::status_ok){
2034 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while loading project file.\n" + QString(result.description()));
2035 +        showErrStatusMessage(statusError);
2036 +        this->projectIsLoading = false;
2037 +        return;
2038 +    }
2039 +
2040 +
2041 +    if(QString(doc.root().first_child().name()) != "VagoProject"){
2042 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, QString(doc.root().name()) + "The file opened is not a valid VagoProject file. Load aborted.");
2043 +        showErrStatusMessage(statusError);
2044 +        this->projectIsLoading = false;
2045 +        return;
2046 +    }
2047 +
2048 +    QString projVagoVersion;
2049 +
2050 +    try{
2051 +        projVagoVersion = QString(doc.select_node("/VagoProject/@vagoVersion").attribute().value());
2052 +    }
2053 +    catch (const pugi::xpath_exception& e)
2054 +    {
2055 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't find the vagoVersion of the current project. Load aborted.\n" + QString(e.what()));
2056 +        showErrStatusMessage(statusError);
2057 +        this->projectIsLoading = false;
2058 +        return;
2059 +    }
2060 +
2061 +    if(!projVagoVersion.startsWith(GlobalVars::LastCompatibleVersion)){
2062 +        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.");
2063 +        showErrStatusMessage(statusError);
2064 +        this->projectIsLoading = false;
2065 +        return;
2066 +    }
2067 +
2068 +    // After the initial validations begin loading the project data
2069 +
2070 +    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
2071 +
2072 +    try{
2073 +        foreach(DropTableWidget* const &myTable, tableWidgets){
2074 +            loadProjectWidget(doc, myTable);
2075 +        }
2076 +    }
2077 +    catch(const std::exception& e){
2078 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't load the vago project. Error: " + QString(e.what()));
2079 +        showErrStatusMessage(statusError);
2080 +        this->projectIsLoading = false;
2081 +        return;
2082 +    }
2083 +
2084 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2085 +
2086 +    this->lastProjectFilePath = filePath;
2087 +    this->unsavedChangesExist = false;
2088 +
2089 +    addNewRecentProject(filePath);
2090 +
2091 +    setVagoWindowTitle();
2092 +
2093 +    this->projectIsLoading = false;
2094 +
2095 +    showSuccessStatusMessage("Project loaded sucessfully.");
2096 + }
2097 +
2098 +
2099 + void MainWindow::loadProjectWidget(pugi::xml_document &doc, DropTableWidget* table)
2100 + {
2101 +    QString tabName = getTabNameByTableWidget(table);
2102 +    QString from (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@from")).attribute().value());
2103 +    QString to (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@to")).attribute().value());
2104 +
2105 +    if(table==ui->twSourcesXML){
2106 +        ui->cbFromXML->setCurrentText(from);
2107 +        on_cbFromXML_currentIndexChanged(from);
2108 +        ui->cbToXML->setCurrentText(to);
2109 +    }
2110 +    else if(table==ui->twSourcesTextures){
2111 +        //ui->cbFromTextures->setCurrentText(from);
2112 +        on_cbFromTextures_currentIndexChanged(from);
2113 +        ui->cbToTextures->setCurrentText(to);
2114 +
2115 +        getTextureRBTypeTextureByName((doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@type")).attribute().value()))->setChecked(true);
2116 +        ui->cbMipMapsTextures->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@genMipMaps")).attribute().as_bool());
2117 +        ui->cbNoUwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noUwrap")).attribute().as_bool());
2118 +        ui->cbNoVwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noVwrap")).attribute().as_bool());
2119 +        ui->cbLarge->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@large")).attribute().as_bool());
2120 +        ui->cbEnvMap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMap")).attribute().as_bool());
2121 +        ui->leEnvMapTexture->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMapValue")).attribute().value()));
2122 +    }
2123 +    else if(table==ui->twSourcesCharacters){
2124 +        ui->cbFromCharacters->setCurrentText(from);
2125 +        on_cbFromCharacters_currentIndexChanged(from);
2126 +        ui->cbToCharacters->setCurrentText(to);
2127 +
2128 +
2129 +        ui->cbCellShading->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@cellShading")).attribute().as_bool());
2130 +        ui->cbNormals->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@normals")).attribute().as_bool());
2131 +        ui->cbWithTRBS_ONCC->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCC")).attribute().as_bool());
2132 +        ui->leTRBS_ONCC->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCCValue")).attribute().value()));
2133 +    }
2134 +    else if(table==ui->twSourcesObjects){
2135 +        ui->cbFromObjects->setCurrentText(from);
2136 +        on_cbFromObjects_currentIndexChanged(from);
2137 +        ui->cbToObjects->setCurrentText(to);
2138 +
2139 +        ui->cbTexture->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@texture")).attribute().as_bool());
2140 +        ui->leTextureName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@textureValue")).attribute().value()));
2141 +        ui->cbWithAnimation->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimation")).attribute().as_bool());
2142 +        ui->leAnimationName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimationValue")).attribute().value()));
2143 +    }
2144 +    else if(table==ui->twSourcesLevels){
2145 +        ui->cbFromLevels->setCurrentText(from);
2146 +        on_cbFromLevels_currentIndexChanged(from);
2147 +        ui->cbToLevels->setCurrentText(to);
2148 +
2149 +        ui->cbSpecificFilesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFiles")).attribute().as_bool());
2150 +        ui->leSpecificFilesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFilesValue")).attribute().value()));
2151 +        ui->cbDatLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilename")).attribute().as_bool());
2152 +        ui->leTargetDatLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilenameValue")).attribute().value()));
2153 +        ui->cbBnvLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSource")).attribute().as_bool());
2154 +        ui->leBnvLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSourceValue")).attribute().value()));
2155 +        ui->cbGridsLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@generateGrids")).attribute().as_bool());
2156 +        ui->cbAdditionalSourcesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSources")).attribute().as_bool());
2157 +        ui->leAdditSourcesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSourcesValue")).attribute().value()));
2158 +    }
2159 +    else{
2160 +        ui->cbFromMisc->setCurrentText(from);
2161 +        on_cbFromMisc_currentIndexChanged(from);
2162 +        ui->cbToMisc->setCurrentText(to);
2163 +    }
2164 +
2165 +    // Clean previous rows
2166 +    clearTableNoPrompt(table);
2167 +
2168 +    for(const pugi::xpath_node &xPathNode : doc.select_nodes(Util::qStrToCstr("/VagoProject/"+tabName+"/Row"))){
2169 +        pugi::xml_node currNode = xPathNode.node();
2170 +
2171 +        QString currFileFolder = currNode.attribute("fileFolder").value();
2172 +        QString currFromTo = currNode.attribute("fromTo").value();
2173 +        QString currCommand = currNode.attribute("command").value();
2174 +
2175 +        bool isToDisable = false;
2176 +        pugi::xml_attribute disabledAttr = currNode.attribute("disabled");
2177 +        isToDisable = disabledAttr.empty() ? false : disabledAttr.as_bool();
2178 +
2179 +        addRowTable(table,currFileFolder,currFromTo,currCommand, isToDisable);
2180 +    }
2181 + }
2182 +
2183 + void MainWindow::saveRecentProjects(){
2184 +    for(int i=0; i<this->recentProjectsList.size(); i++){
2185 +        this->vagoSettings->setValue("RecentProject" + QString::number(i+1), recentProjectsList[i]);
2186 +    }
2187 + }
2188 +
2189 + void MainWindow::loadRecentProjects(){
2190 +    for(int i=0; i<this->recentProjectsMaxSize; i++){
2191 +
2192 +        QString currProj = this->vagoSettings->value("RecentProject" + QString::number(i+1)).toString();
2193 +
2194 +        if(!currProj.isEmpty()){
2195 +            recentProjectsList.append(currProj);
2196 +        }
2197 +        else{
2198 +            break;
2199 +        }
2200 +    }
2201 +
2202 +    reloadRecentProjectsMenu();
2203 +
2204 + }
2205 +
2206 + void MainWindow::addNewRecentProject(const QString &filePath){
2207 +
2208 +    // If the new project is equal to the last one simply ignore
2209 +    if(filePath == this->vagoSettings->value("RecentProject1").toString()){
2210 +        return;
2211 +    }
2212 +
2213 +    // If the item already exists in our list remove it, so it can go to the top again
2214 +    for(auto it = this->recentProjectsList.begin(); it != this->recentProjectsList.end();){
2215 +        if(*it == filePath){
2216 +            it = this->recentProjectsList.erase(it);
2217 +        }
2218 +        else{
2219 +            it++;
2220 +        }
2221 +    }
2222 +
2223 +    // if we gonna overflow our list, remove the older item to reserve space to the new one
2224 +    if(this->recentProjectsList.size()==this->recentProjectsMaxSize){
2225 +        this->recentProjectsList.removeLast();
2226 +    }
2227 +
2228 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2229 +
2230 +    // add new recent file
2231 +    this->recentProjectsList.prepend(filePath);
2232 +
2233 +    reloadRecentProjectsMenu();
2234 +
2235 +    saveRecentProjects();
2236 + }
2237 +
2238 + void MainWindow::reloadRecentProjectsMenu(){
2239 +
2240 +    ui->menuRecent_Projects->setEnabled(false);
2241 +    ui->actionProject1->setVisible(false);
2242 +    ui->actionProject2->setVisible(false);
2243 +    ui->actionProject3->setVisible(false);
2244 +    ui->actionProject4->setVisible(false);
2245 +    ui->actionProject5->setVisible(false);
2246 +
2247 +    {
2248 +        QList<QString>::const_iterator it;
2249 +        int i;
2250 +        for(it = recentProjectsList.cbegin(), i=0; it != recentProjectsList.cend(); it++, i++){
2251 +
2252 +            QAction* currAction = nullptr;
2253 +
2254 +            switch (i){
2255 +            case 0:
2256 +                currAction = ui->actionProject1;
2257 +                break;
2258 +            case 1:
2259 +                currAction = ui->actionProject2;
2260 +                break;
2261 +            case 2:
2262 +                currAction = ui->actionProject3;
2263 +                break;
2264 +            case 3:
2265 +                currAction = ui->actionProject4;
2266 +                break;
2267 +            case 4:
2268 +                currAction = ui->actionProject5;
2269 +                break;
2270 +            }
2271 +
2272 +            if(currAction){
2273 +                ui->menuRecent_Projects->setEnabled(true);
2274 +                currAction->setText(*it);
2275 +                currAction->setVisible(true);
2276 +            }
2277 +        }
2278 +    }
2279 +
2280 + }

Diff Legend

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