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 791 by s10k, Sat Apr 6 21:08:35 2013 UTC vs.
Revision 1054 by s10k, Wed Oct 12 21:35:13 2016 UTC

# Line 9 | Line 9 | MainWindow::MainWindow(QWidget *parent)
9   {
10      ui->setupUi(this);
11  
12 <    ui->pbConvertGeneral->setMinimumSize(ui->pbConvertGeneral->minimumSizeHint());
13 <    ui->pbConvertGeneral->setMinimumWidth(50);
14 <    ui->pbConvertGeneral->setMinimumHeight(ui->pbConvertGeneral->minimumHeight()*1.4);
12 >    this->myLogger = new Logger(UtilVago::getAppPath(), GlobalVars::AppLogName); //start logger
13  
14 <    qDebug() << ui->pbConvertGeneral->minimumHeight() << ui->pbConvertGeneral->minimumHeight();
14 >    this->myLogger->writeString("Detected AppDir: "+UtilVago::getAppPath());
15 >    this->myLogger->writeString("True app dir: "+QDir::currentPath());
16  
17 <    this->setWindowTitle("Vago v"+GlobalVars::AppVersion);
17 >    setVagoWindowTitle();
18  
19 <    if(!QFile::exists(QDir::currentPath()+"/"+GlobalVars::OniSplitString)){
20 <        Util::showErrorPopUp("OniSplit not found. Please download it at "+GlobalVars::ModsDomain+" and put it in the same folder of Vago. \n\nProgram will now exit.");
19 >    if(!QFile::exists(UtilVago::getOniSplitExecutableAbsolutePath())){
20 >        UtilVago::showAndLogErrorPopUp(this->myLogger, "OniSplit not found. Please download it at "+GlobalVars::ModsDomain+" and put it the Vago's tools folder. \n\nProgram will now exit.");
21          exit(1);
22      }
23  
24 <    if(!QFile::exists(QDir::currentPath()+"/"+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(QDir::currentPath() + "/" + 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 36 | Line 35 | MainWindow::MainWindow(QWidget *parent)
35          iniChanged=true;
36      }
37      if(!this->vagoSettings->contains("Workspace")){
38 <        this->vagoSettings->setValue("Workspace", QDir::currentPath()+"/VagoWorkspace");
38 >        this->vagoSettings->setValue("Workspace", UtilVago::getAppPath()+"/VagoWorkspace");
39          iniChanged=true;
40      }
41      if(!this->vagoSettings->contains("AeFolder")){
# Line 45 | 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 56 | 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 64 | 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 78 | 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 91 | 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 <
97 <    this->myLogger = new Logger(); //start logger
128 >    ui->statusBar->addPermanentWidget(this->myBar); //this adds automatically in right
129 >    ui->statusBar->addPermanentWidget(ui->tbAbortConversion);
130  
131      //Initialize list pointers
132      this->listToProccess = new QStringList;
133  
102    //Create a thread for do the conversion in background
103    this->myConverter = new Converter(this->myLogger,this->listToProccess);
104
134      // User interface
135      ui->mainToolBar->addWidget(ui->tbAE); //add ae installer launch button
136      ui->mainToolBar->addWidget(ui->emptySpacerLabel); //trick, we can't add directly a space so we add an empty
# Line 113 | Line 142 | MainWindow::MainWindow(QWidget *parent)
142  
143      ui->mainToolBar->setLayoutDirection(Qt::RightToLeft);
144  
145 < #ifdef Q_WS_MAC
145 >    ui->pbConvert->setMinimumHeight(ui->pbConvert->sizeHint().height()*1.5); // This is OS indepented. It maintain size ratio over the Windows and Mac.
146 >
147 >
148 > #ifdef Q_OS_MAC
149      // 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
150      ui->tbOni->setIcon(QIcon(":/new/icons/oni_icon_mac.png")); // Oni executable on mac have a different icon than windows
151      // Set mac platform the first one in the menu, and also make it checkable by default
# Line 121 | Line 153 | MainWindow::MainWindow(QWidget *parent)
153      ui->menuTarget_Platform->addAction(ui->actionWindows);
154      ui->actionWindows->setChecked(false);
155      ui->actionMac_Windows_demo->setChecked(true);
156 <    // Hide file menu on mac (not needed)
157 <    ui->menuFile->hide();
126 <    ui->menuFile->close();
127 <    //ui->menuBar->macMenu();
156 >    // resize(800,600); // Mac OS pcs should be able to render this resolution without any problem. It's also better
157 >    //// because the components on mac use more space
158   #endif
159  
160 <    connectSlots();
160 >    resize(this->startedWindowWidth,this->startedWindowHeight);
161 >
162 > #ifdef Q_OS_MAC
163 >    ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (⌘ + Enter)");
164 > #else
165 >    ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (Ctrl + Enter)");
166 > #endif
167  
168      //Commands Mapping
169      this->commandMap = QHash<QString, QString>();
170      mapCommands();
171  
172 <    updateItemsLoaded(ui->twSourcesGeneral);
172 >    updateItemsLoaded(ui->twSourcesXML);
173  
174 <    this->myLogger->writeString("Application started.");
174 >    loadRecentProjects();
175   }
176  
177   MainWindow::~MainWindow()
# Line 144 | Line 180 | MainWindow::~MainWindow()
180      this->myLogger->writeString("Application Exited.");
181   }
182  
183 +
184 + void MainWindow::showEvent(QShowEvent *e)
185 + {
186 +    // If we don't have a converter yet, application wasn't started.
187 +    if(!this->applicationIsFullyLoaded)
188 +    {
189 +        // Apparently Qt doesn't contains a slot to when the application was fully load (mainwindow). So we do our own implementation instead.
190 +        connect(this, SIGNAL(signalAppIsLoaded()), this, SLOT(applicationWasLoaded()), Qt::ConnectionType::QueuedConnection);
191 +        emit signalAppIsLoaded();
192 +    }
193 +
194 +    e->accept();
195 + }
196 +
197 + // Called only when the MainWindow was fully loaded and painted on the screen. This slot is only called once.
198 + void MainWindow::applicationWasLoaded(){
199 + #ifdef Q_OS_WIN
200 +    // QProgressBar only works after the windows was shown
201 +    // http://stackoverflow.com/questions/24840941/qwintaskbarprogress-wont-show (Kervala answer)
202 +
203 +    this->win7TaskBarButton = new QWinTaskbarButton();
204 +
205 +    this->win7TaskBarButton->setWindow(this->windowHandle());
206 +
207 +    this->win7TaskBarProgress = this->win7TaskBarButton->progress();
208 +
209 +    //Create a thread for do the conversion in background
210 +    this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, this->listToProccess, this->win7TaskBarProgress);
211 + #else
212 +    this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, this->listToProccess);
213 + #endif
214 +
215 +    connectSlots();
216 +
217 +    this->myLogger->writeString("Application started.");
218 +
219 +    this->applicationIsFullyLoaded = true;
220 +
221 +    QString lastSavedProject = this->vagoSettings->value("RecentProject1").toString();
222 +
223 +    if(!lastSavedProject.isEmpty() && this->vagoSettings->value("AskToOpenLastProject").toBool()){
224 +        if(Util::showQuestionPopUp(this,"Do you want to load latest project?\n\nLatest project was '" + Util::cutNameWithoutBackSlash(lastSavedProject) + "'.")){
225 +            loadProjectState(lastSavedProject);
226 +        }
227 +    }
228 + }
229 +
230 +
231   void MainWindow::on_actionExit_triggered()
232   {
233      close();
# Line 164 | Line 248 | void MainWindow::on_actionAE_Package_Cre
248  
249   void MainWindow::on_actionSound_Wizard_triggered()
250   {
251 <    SoundWizard myWizard (this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
251 >    SoundWizard myWizard (UtilVago::getAppPath(), this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
252 >    myWizard.exec();
253 > }
254 >
255 > void MainWindow::on_actionBackground_Image_Wizard_triggered()
256 > {
257 >    BGImageWizard myWizard (UtilVago::getAppPath(), this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
258      myWizard.exec();
259   }
260  
# Line 175 | Line 265 | void MainWindow::on_tbOni_clicked()
265      if(this->vagoSettings->value("OniWindow").toBool()){ // Run in a window?
266          arguments << "-noswitch";
267      }
268 < #ifdef Q_WS_WIN
268 > #ifdef Q_OS_WIN
269      else{
270          arguments << "-switch"; // only supported on windows. Was added by daodan dll.
271      }
# Line 202 | Line 292 | void MainWindow::on_tbOpenFolder_clicked
292      QDesktopServices::openUrl(QUrl("file:///"+this->outputFolder));
293   }
294  
295 + void MainWindow::on_tbAbortConversion_clicked()
296 + {
297 +    if(Util::showQuestionPopUp(this,"Are you sure you want to abort the current conversion?")){
298 +        emit terminateCurrProcess();
299 +    }
300 + }
301 +
302   void MainWindow::on_cbEnvMap_toggled(bool checked)
303   {
304      ui->leEnvMapTexture->setEnabled(checked);
# Line 217 | Line 314 | void MainWindow::on_cbWithAnimation_togg
314      ui->leAnimationName->setEnabled(checked);
315   }
316  
317 < void MainWindow::on_cbCamera_toggled(bool checked)
317 > void MainWindow::on_cbSpecificFilesLevels_toggled(bool checked)
318   {
319 <    if(checked){
223 <        ui->cbGeometry->setChecked(false);
224 <    }
225 < }
226 <
227 < void MainWindow::on_cbGeometry_toggled(bool checked)
228 < {
229 <    ui->leGeometryName->setEnabled(checked);
230 <    if(checked){
231 <        ui->cbCamera->setChecked(false);
232 <    }
319 >    ui->leSpecificFilesLevels->setEnabled(checked);
320   }
321  
322   void MainWindow::on_actionCheck_For_Updates_triggered()
# Line 263 | Line 350 | void MainWindow::checkVagoLastVersion(QN
350          }
351      }
352      else{
353 <        Util::showErrorPopUp("An error occurred checking last version:\n\n"+result->errorString());
353 >        UtilVago::showAndLogErrorPopUp(this->myLogger, "An error occurred checking last version:\n\n"+result->errorString());
354      }
355      result->deleteLater();
356   }
357  
358 < void MainWindow::on_pbAddSourceGeneral_clicked()
358 > void MainWindow::on_pbAddSourceXML_clicked()
359   {
360 <    if(QString::compare(ui->cbFromGeneral->currentText(),"ONI",Qt::CaseSensitive)==0 && QString::compare(ui->cbToGeneral->currentText(),"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster)
274 <        addFilesSource(ui->twSourcesGeneral,Util::multipleDirDialog("Choose folders with ONIs..."));
275 <    }
276 <    else{
277 <        addFilesSource( ui->twSourcesGeneral,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
278 <    }
360 >    addFilesSource( ui->twSourcesXML,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
361   }
362  
363   void MainWindow::on_pbAddSourceTextures_clicked()
# Line 283 | Line 365 | void MainWindow::on_pbAddSourceTextures_
365      addFilesSource( ui->twSourcesTextures, QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
366   }
367  
368 < void MainWindow::on_pbAddSourceModels_clicked()
368 > void MainWindow::on_pbAddSourceObjects_clicked()
369   {
370 <    addFilesSource( ui->twSourcesModels,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
370 >    addFilesSource( ui->twSourcesObjects,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
371   }
372  
373 < void MainWindow::on_pbAddSourceAnimations_clicked()
373 > void MainWindow::on_pbAddSourceCharacters_clicked()
374   {
375 <    addFilesSource( ui->twSourcesAnimations,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
375 >    addFilesSource( ui->twSourcesCharacters,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
376   }
377  
378   void MainWindow::on_pbAddSourceLevels_clicked()
379   {
380 <    addFilesSource( ui->twSourcesLevels,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
380 >    if(QString::compare(ui->cbFromLevels->currentText(),"ONI FILES",Qt::CaseSensitive)==0 && QString::compare(ui->cbToLevels->currentText(),"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster)
381 >        addFilesSource(ui->twSourcesLevels,Util::multipleDirDialog("Choose folders with ONIs..."));
382 >    }
383 >    else{
384 >        addFilesSource(ui->twSourcesLevels,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
385 >    }
386   }
387  
388   void MainWindow::on_pbAddSourceMisc_clicked()
# Line 327 | Line 414 | void MainWindow::addFilesSource(DropTabl
414      to = QString(fromTo).remove(0,fromTo.lastIndexOf("> ")+2); //+2 to start after "> "
415  
416      //Pre-processing (check if the files/folders received are valid), e.g. check for ONI->DAT if are only given folders and not files
417 <    if(QString::compare(from,"ONI",Qt::CaseSensitive)==0 && QString::compare(to,"DAT",Qt::CaseSensitive)==0){
417 >    if(from=="ONI FILES" && to=="DAT"){
418          //check if it's a folder
419          foreach(QString myFile, files){
420              if(!QDir(myFile).exists()){
# Line 377 | Line 464 | void MainWindow::addFilesSource(DropTabl
464          addRowTable(myTable,lastFileName,fromTo,command);
465      }
466      updateItemsLoaded(myTable);
467 +    rowsWereChangedInDropTableWidget();
468   }
469  
470 < QString MainWindow::fileParsingGeneral(QString myOutputFolder, QString from, QString to , QString file){
470 > QString MainWindow::fileParsingXML(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
471  
472      QString command;
473  
474 <    if(QString::compare(from,"ONI",Qt::CaseSensitive)==0 && QString::compare(to,"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster
475 <
388 <        QString datName;
389 <
390 <        if(ui->cbDatGeneral->isChecked()){
391 <            if(ui->leTargetDatGeneral->text().isEmpty()){
392 <                showErrStatusMessage("Checkbox '"+ui->cbDatGeneral->text()+"' is selected. The name cannot be empty.");
393 <                return "";
394 <            }
395 <            datName+=QString(myOutputFolder).insert(myOutputFolder.size()-1,ui->leTargetDatGeneral->text()); //set name inputted by user
396 <            if(!ui->leTargetDatGeneral->text().toUpper().endsWith(".DAT")){
397 <                datName.insert(datName.size()-1,".dat"); //append extension if necessary (-1 to maintain final quote)
398 <            }
399 <        }
400 <        else{
401 <            datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/")+".dat"); //if none iputted set the same name of input file
402 <        }
403 <
404 <        if(ui->actionWindows->isChecked()){ //is target plataform select windows?
405 <            return command=this->commandMap.value("general->"+from+"->"+to+"(PC)")+" "+ file + " "+datName;
406 <        }
407 <        else{
408 <            return command=this->commandMap.value("general->"+from+"->"+to+"(demoPCMAC)")+" "+ file + " "+datName;
409 <        }
474 >    if(from=="ONI" && to=="XML"){
475 >        return command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder+" "+file;
476      }
477 <    else if(QString::compare(from,"ONI",Qt::CaseSensitive)==0 && QString::compare(to,"XML",Qt::CaseSensitive)==0 && ui->cbTRAMGeneral->isChecked()){
478 <        if(ui->leTRAMGeneral->text().isEmpty()){
413 <            showErrStatusMessage("Checkbox '"+ui->cbTRAMGeneral->text()+"' is selected. The source cannot be empty.");
414 <            return "";
415 <        }
416 <        return command=this->commandMap.value("general->"+from+"->"+to)+" "+myOutputFolder+" "+this->commandMap.value("general->"+ui->cbTRAMGeneral->text())+file + " "+ Util::normalizeAndQuote(ui->leTRAMGeneral->text());
417 <    }
418 <    else{
419 <        return command=this->commandMap.value("general->"+from+"->"+to)+" "+myOutputFolder+" "+file;
477 >    else if(from=="XML" && to=="ONI"){
478 >        return command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder+" "+file;
479      }
480  
481 +    return "";
482 +
483   }
484  
485 < QString MainWindow::fileParsingTextures(QString myOutputFolder, QString from, QString to , QString file){
485 > QString MainWindow::fileParsingTextures(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
486  
487 <    QString command=this->commandMap.value("textures->"+from+"->"+to)+" "+myOutputFolder;
487 >    QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder;
488  
489      if(ui->gbTextures->isEnabled()){ //faster than compare strings (if is DAT/ONI)
490  
491          if(ui->cbMipMapsTextures->isChecked()){
492 <            command+=" "+this->commandMap.value("textures->"+ui->cbMipMapsTextures->text());
492 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbMipMapsTextures->text());
493          }
494  
495          if(ui->cbNoUwrap->isChecked()){
496 <            command+=" "+this->commandMap.value("textures->"+ui->cbNoUwrap->text());
496 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNoUwrap->text());
497          }
498  
499          if(ui->cbNoVwrap->isChecked()){
500 <            command+=" "+this->commandMap.value("textures->"+ui->cbNoVwrap->text());
500 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNoVwrap->text());
501          }
502  
503          if(ui->cbLarge->isChecked()){
504 <            command+=" "+this->commandMap.value("textures->"+ui->cbLarge->text());
504 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbLarge->text());
505          }
506  
507 <        if(ui->rbBGR32->isChecked()){
447 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGR32->text());
448 <        }
449 <        else if(ui->rbBGRA32->isChecked()){
450 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGRA32->text());
451 <        }
452 <        else if(ui->rbBGR555->isChecked()){
453 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGR555->text());
454 <        }
455 <        else if(ui->rbBGRA5551->isChecked()){
456 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGRA5551->text());
457 <        }
458 <        else if(ui->rbBGRA444->isChecked()){
459 <            command+=" "+this->commandMap.value("textures->"+ui->rbBGRA444->text());
460 <        }
461 <        else{ //dxt1 checked
462 <            command+=" "+this->commandMap.value("textures->"+ui->rbDxt1->text());
463 <        }
507 >        command+=" "+this->commandMap.value(tabTitle+"->"+getTextureRBCheckedTypeTexture()->text());
508  
509          if(ui->cbEnvMap->isChecked()){
510              if(ui->leEnvMapTexture->text().isEmpty()){
511                  showErrStatusMessage("Checkbox '"+ui->cbEnvMap->text()+"' is selected. The name texture name cannot be empty.");
512                  return "";
513              }
514 <            command+=" "+this->commandMap.value("textures->"+ui->cbEnvMap->text()) + ui->leEnvMapTexture->text().remove(".oni",Qt::CaseInsensitive);
514 >            command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbEnvMap->text()) + ui->leEnvMapTexture->text().remove(".oni",Qt::CaseInsensitive);
515          }
516      }
517  
518      return command+=" "+file; //add source
519   }
520  
521 < QString MainWindow::fileParsingModels(QString myOutputFolder, QString from, QString to , QString file){
521 > QString MainWindow::fileParsingCharacters(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
522  
523 <    QString command=this->commandMap.value("models->"+from+"->"+to)+" "+myOutputFolder;
523 >    QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder + " " + file ;
524  
481    //TODO: This can be optimized. When some are not enable others are.
482    if(ui->cbTexture->isChecked()){
483        if(ui->leTextureName->text().isEmpty()){
484            showErrStatusMessage("Checkbox '"+ui->cbTexture->text()+"' is selected. The name cannot be empty.");
485            return "";
486        }
487        command+=" "+this->commandMap.value("models->"+ui->cbTexture->text()) + ui->leTextureName->text().remove(".oni",Qt::CaseInsensitive);
488    }
525  
526      if(ui->cbCellShading->isChecked()){
527 <        command+=" "+this->commandMap.value("models->"+ui->cbCellShading->text());
527 >        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbCellShading->text());
528      }
529  
530      if(ui->cbNormals->isChecked()){
531 <        command+=" "+this->commandMap.value("models->"+ui->cbNormals->text());
531 >        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNormals->text());
532      }
533  
534 <    if(ui->cbWithAnimation->isEnabled()){
535 <        if(ui->cbWithAnimation->isChecked()){
536 <            command+=" "+this->commandMap.value("models->"+ui->cbWithAnimation->text())+ui->leAnimationName->text().remove(".oni",Qt::CaseInsensitive);
537 <        }
502 <        else{
503 <            command+=" "+this->commandMap.value("models->No Animation");
534 >    if(ui->cbWithTRBS_ONCC->isChecked()){
535 >        if(ui->leTRBS_ONCC->text().isEmpty()){
536 >            showErrStatusMessage("Checkbox '"+ui->cbWithTRBS_ONCC->text()+"' is selected. The name cannot be empty.");
537 >            return "";
538          }
505    }
539  
540 +        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbWithTRBS_ONCC->text())+Util::normalizeAndQuote(ui->leTRBS_ONCC->text());
541 +    }
542  
543 <    return command+=" "+file; //add source
543 >    return command;
544   }
545  
511 QString MainWindow::fileParsingAnimations(QString myOutputFolder, QString from, QString to , QString file){
546  
547 <    QString command=this->commandMap.value("animations->"+from+"->"+to)+" "+myOutputFolder + " " + file ;
547 > QString MainWindow::fileParsingObjects(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
548 >
549 >    QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder;
550  
551 <    if(ui->cbCamera->isChecked()){
552 <        command+=" "+this->commandMap.value("animations->"+ui->cbCamera->text());
551 >    //TODO: This can be optimized. When some are not enable others are.
552 >    if(ui->cbTexture->isChecked()){
553 >        if(ui->leTextureName->text().isEmpty()){
554 >            showErrStatusMessage("Checkbox '"+ui->cbTexture->text()+"' is selected. The file source cannot be empty.");
555 >            return "";
556 >        }
557 >        command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbTexture->text()) + ui->leTextureName->text();
558      }
559 <    else if(ui->cbGeometry->isChecked()){
560 <        if(ui->leGeometryName->text().isEmpty()){
561 <            showErrStatusMessage("Checkbox '"+ui->cbGeometry->text()+"' is selected. The geometry file path cannot be empty.");
559 >    else if(ui->cbWithAnimation->isChecked()){
560 >        if(ui->leAnimationName->text().isEmpty()){
561 >            showErrStatusMessage("Checkbox '"+ui->cbWithAnimation->text()+"' is selected. The file source cannot be empty.");
562              return "";
563          }
564 <        command+=" "+this->commandMap.value("animations->"+ui->cbGeometry->text()) + (ui->leGeometryName->text().startsWith('"')?ui->leGeometryName->text():Util::insertQuotes(ui->leGeometryName->text()));
564 >        command+=" "+Util::normalizeAndQuote(ui->leAnimationName->text()) + " " + this->commandMap.value(tabTitle+"->"+ui->cbWithAnimation->text()) + file;
565 >        return command;
566      }
567  
568 <    return command;
568 >    if(from=="OBAN ONI (cam)"){
569 >        command+=" -geom:camera";
570 >    }
571 >
572 >    return command+=" "+file; //add source
573   }
574  
575 < QString MainWindow::fileParsingLevels(QString myOutputFolder, QString from, QString to , QString file){
575 > QString MainWindow::fileParsingLevels(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
576  
577      QString datName, command;
578  
579 <    command=this->commandMap.value("levels->"+from+"->"+to)+" "+myOutputFolder+" "+file;
579 >    if(!(from=="ONI FILES" && to=="DAT")){ // to all except this one
580  
581 <    if(from=="MASTER XML" && to=="DAT"){
536 <        command+=GlobalVars::OniSplitProcSeparator; //insert mark so we know this action will take 2 commands
581 >        command=this->commandMap.value(tabTitle+"->"+from+"->"+to);
582  
583 +        if(ui->cbSpecificFilesLevels->isChecked()){
584 +
585 +            if(ui->leSpecificFilesLevels->text().isEmpty()){
586 +                showErrStatusMessage("Checkbox '"+ui->cbSpecificFilesLevels->text()+"' is selected. The files pattern cannot be empty.");
587 +                return "";
588 +            }
589 +
590 +            command+=":"+ui->leSpecificFilesLevels->text();
591 +        }
592 +
593 +        if(from=="DAT" && to=="ONI FILES"){ // extract files to a subdir with the files name ex: level0_Final
594 +            command += " " + myOutputFolder.insert(myOutputFolder.size()-2,QString(Util::cutName(file)).replace(".dat","")) + " " + file;
595 +        }
596 +        else{
597 +            command+=" "+myOutputFolder+" "+file;
598 +        }
599 +
600 +    }
601 +
602 +    if((from=="ONI FILES" || from=="MASTER XML") && to=="DAT"){ // almost the same command for both
603          QString datName;
604 +
605 +        if(from=="MASTER XML"){
606 +            command+=GlobalVars::OniSplitProcSeparator; //insert mark so we know this action will take 2 commands
607 +        }
608 +
609          if(ui->cbDatLevels->isChecked()){
610              if(ui->leTargetDatLevels->text().isEmpty()){
611                  showErrStatusMessage("Checkbox '"+ui->cbDatLevels->text()+"' is selected. The name cannot be empty.");
# Line 547 | Line 617 | QString MainWindow::fileParsingLevels(QS
617              }
618          }
619          else{
620 <            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
620 >            if(from=="ONI FILES"){
621 >                datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/")+".dat"); //if none iputted set the same name of input file
622 >            }
623 >            else if(from=="MASTER XML"){
624 >                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
625 >            }
626          }
627 <
628 <        if(ui->actionWindows->isChecked()){ //is target plataform select windows?
629 <            command+=this->commandMap.value("general->ONI->"+to+"(PC)")+" "+myOutputFolder+" "+datName; //add second command
627 >        if(from=="ONI FILES"){
628 >            if(ui->actionWindows->isChecked()){ //is target plataform select windows?
629 >                return command=this->commandMap.value(tabTitle+"->"+from+"->"+to+"(PC)")+" "+ file + " "+datName;
630 >            }
631 >            else{
632 >                return command=this->commandMap.value(tabTitle+"->"+from+"->"+to+"(demoPCMAC)")+" "+ file + " "+datName;
633 >            }
634          }
635 <        else{
636 <            command+=this->commandMap.value("general->ONI->"+to+"(demoPCMAC)")+" "+myOutputFolder+" "+datName; //add second command
635 >        else if(from=="MASTER XML"){
636 >            if(ui->actionWindows->isChecked()){ //is target plataform select windows?
637 >                command+=this->commandMap.value(tabTitle+"->ONI FILES->"+to+"(PC)")+" "+myOutputFolder+" "+datName; //add second command
638 >            }
639 >            else{
640 >                command+=this->commandMap.value(tabTitle+"->ONI FILES->"+to+"(demoPCMAC)")+" "+myOutputFolder+" "+datName; //add second command
641 >            }
642          }
643      }
644  
# Line 580 | Line 664 | QString MainWindow::fileParsingLevels(QS
664  
665          //parse all files (separated by spaces)
666          while(true){
667 <            nextIndex=additionalFiles.indexOf(" ",currentIndex+1);
667 >            nextIndex=additionalFiles.indexOf(";",currentIndex+1);
668  
669              command += " "+Util::normalizeAndQuote(additionalFiles.mid(currentIndex,(nextIndex-currentIndex)));
670  
# Line 592 | Line 676 | QString MainWindow::fileParsingLevels(QS
676      }
677  
678      if(ui->cbGridsLevels->isChecked()){
679 <        command+=GlobalVars::OniSplitProcSeparator+this->commandMap.value("levels->"+ui->cbGridsLevels->text())+" "+Util::normalizeAndQuote(ui->leBnvLevels->text())+" "+file+" -out:"+myOutputFolder;
679 >        command+=GlobalVars::OniSplitProcSeparator+this->commandMap.value(tabTitle+"->"+ui->cbGridsLevels->text())+" "+Util::normalizeAndQuote(ui->leBnvLevels->text())+" "+file+" -out:"+myOutputFolder;
680      }
681  
682      return command;
# Line 602 | Line 686 | QString MainWindow::fileParsingMisc(QStr
686      return this->commandMap.value("misc->"+from+"->"+to)+" "+myOutputFolder+" "+file;
687   }
688  
689 < void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command){
689 > void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command, bool isToDisabled){
690      //Get actual number rows
691      int twSize=myTable->rowCount();
692  
# Line 614 | Line 698 | void MainWindow::addRowTable(DropTableWi
698      QTableWidgetItem *newConversion = new QTableWidgetItem(fromTo);
699      QTableWidgetItem *newCommand = new QTableWidgetItem(command);
700  
701 +    if(isToDisabled){
702 +        myTable->setDisableStyleWidgetItem(newFile);
703 +        myTable->setDisableStyleWidgetItem(newConversion);
704 +        myTable->setDisableStyleWidgetItem(newCommand);
705 +    }
706 +
707      myTable->setItem(twSize,0,newFile);
708      myTable->setItem(twSize,1,newConversion);
709      myTable->setItem(twSize,2,newCommand);
# Line 621 | Line 711 | void MainWindow::addRowTable(DropTableWi
711      myTable->updateTableToolTips(twSize); //Update tool tips
712   }
713  
714 < void MainWindow::on_pbConvertGeneral_clicked()
625 < {
626 <    startConversion(ui->twSourcesGeneral);
627 < }
628 <
629 < void MainWindow::on_pbConvertTextures_clicked()
714 > void MainWindow::on_pbConvert_clicked()
715   {
716 <    startConversion(ui->twSourcesTextures);
716 >    startConversion();
717   }
718  
719 < void MainWindow::on_pbConvertModels_clicked()
635 < {
636 <    startConversion(ui->twSourcesModels);
637 < }
719 > void MainWindow::startConversion(){
720  
721 < void MainWindow::on_pbConvertAnimations_clicked()
640 < {
641 <    startConversion(ui->twSourcesAnimations);
642 < }
643 <
644 < void MainWindow::on_pbConvertLevels_clicked()
645 < {
646 <    startConversion(ui->twSourcesLevels);
647 < }
648 <
649 < void MainWindow::on_pbConvertMisc_clicked()
650 < {
651 <    startConversion(ui->twSourcesMisc);
652 < }
653 <
654 < void MainWindow::startConversion(DropTableWidget *myTable){
721 >    DropTableWidget* currTable = getCurrentTableWidget();
722  
723      bool ready=false;
724 <    for(int i=0; i<myTable->rowCount(); i++){ //There are items to process?
725 <        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
724 >    for(int i=0; i<currTable->rowCount(); i++){ //There are items to process?
725 >        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
726              ready=true;
727              break;
728          }
# Line 666 | Line 733 | void MainWindow::startConversion(DropTab
733          return;
734      }
735  
736 <    if(myBar->isVisible()){
736 >    if(this->myBar->isVisible()){
737          Util::showErrorPopUp("Another conversion is progress. Please wait until it finishes.");
738          return;
739      }
740  
741 <    for(int i=0; i<myTable->rowCount(); i++){
741 >    for(int i=0; i<currTable->rowCount(); i++){
742          //Only process enabled items
743 <        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
744 <            this->listToProccess->append(myTable->item(i,2)->text());
743 >        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
744 >            this->listToProccess->append(currTable->item(i,2)->text());
745          }
746      }
747  
# Line 685 | Line 752 | void MainWindow::TsetupProgressBar(int m
752      this->myBar->setValue(0);
753      this->myBar->show();
754      this->myBar->setMaximum(max);
755 +    ui->tbAbortConversion->show();
756   }
757  
758   void  MainWindow::TupdateProgressBar(){
# Line 694 | Line 762 | void  MainWindow::TupdateProgressBar(){
762   void MainWindow::TresultConversion(QString result, int numErrors){
763      QApplication::alert(this); //Show a notification if window is not active
764      this->myBar->hide();
765 +    ui->tbAbortConversion->hide();
766  
767      if(numErrors!=0){
768          QString sNumErrors=QString::number(numErrors);
769          if(numErrors>1){
770 <            Util::showErrorLogPopUp(result+"\n This is the last of "+sNumErrors+" Errors.");
771 <            showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" Errors).");
770 >            UtilVago::showErrorPopUpLogButton(result+"\n This is the last of "+sNumErrors+" errors.");
771 >            showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" errors).");
772          }
773          else{
774 <            Util::showErrorLogPopUp(result);
774 >            UtilVago::showErrorPopUpLogButton(result);
775              showErrStatusMessage("Something gone wrong. Check log file.");
776          }
708
777      }
778      else{
779          showSuccessStatusMessage("Everything went well!");
780      }
781   }
782  
783 + void MainWindow::TconversionAborted(){
784 +    this->myBar->hide();
785 +    ui->tbAbortConversion->hide();
786 +
787 +    showErrStatusMessage("Conversion was aborted.");
788 + }
789 +
790   void MainWindow::showErrStatusMessage(QString message){
791  
792      QPalette myPalete = QPalette();
# Line 731 | Line 806 | void MainWindow::showSuccessStatusMessag
806   }
807  
808   void MainWindow::mapCommands(){
809 <    ////////////////////////////////////////////////////////////////////////General Commands
810 <    this->commandMap.insert("general->DAT->ONI","-export");
811 <    //this->commandMap.insert("general->ONI->DAT","-import"); //Not used.
737 <    this->commandMap.insert("general->ONI->DAT(PC)","-import:nosep");
738 <    this->commandMap.insert("general->ONI->DAT(demoPCMAC)","-import:sep");
739 <    this->commandMap.insert("general->ONI->XML","-extract:xml");
740 <    this->commandMap.insert("general->XML->ONI","-create");
809 >    ////////////////////////////////////////////////////////////////////////XML Commands
810 >    this->commandMap.insert("xml->ONI->XML","-extract:xml");
811 >    this->commandMap.insert("xml->XML->ONI","-create");
812      //######################General Options
813 <    this->commandMap.insert("general->"+ui->cbTRAMGeneral->text(),"-anim-body:");
813 >
814      //Possible Combinations
815 <    this->commandMap.insertMulti("general->DAT","ONI");
816 <    this->commandMap.insertMulti("general->ONI","DAT");
746 <    this->commandMap.insertMulti("general->ONI","XML");
747 <    this->commandMap.insertMulti("general->XML","ONI");
815 >    this->commandMap.insertMulti("xml->ONI","XML");
816 >    this->commandMap.insertMulti("xml->XML","ONI");
817  
818      ////////////////////////////////////////////////////////////////////////Textures Commands
819 <    this->commandMap.insert("textures->DAT / ONI->DDS","-extract:dds");
820 <    this->commandMap.insert("textures->DAT / ONI->TGA","-extract:tga");
821 <    this->commandMap.insert("textures->DAT / ONI->PNG","-extract:png");
822 <    this->commandMap.insert("textures->DAT / ONI->JPG","-extract:jpg");
823 <    this->commandMap.insert("textures->DDS / TGA / PNG / JPG->ONI","-create:txmp");
819 >    this->commandMap.insert("textures->DAT / TXMP ONI->DDS","-extract:dds");
820 >    this->commandMap.insert("textures->DAT / TXMP ONI->TGA","-extract:tga");
821 >    this->commandMap.insert("textures->DAT / TXMP ONI->PNG","-extract:png");
822 >    this->commandMap.insert("textures->DAT / TXMP ONI->JPG","-extract:jpg");
823 >    this->commandMap.insert("textures->TGA / DDS / PNG / JPG->TXMP ONI","-create:txmp");
824      //######################Textures Options
825      this->commandMap.insert("textures->"+ui->rbBGR32->text(),"-format:bgr32");
826      this->commandMap.insert("textures->"+ui->rbBGRA32->text(),"-format:bgra32");
# Line 765 | Line 834 | void MainWindow::mapCommands(){
834      this->commandMap.insert("textures->"+ui->cbLarge->text(),"-large");
835      this->commandMap.insert("textures->"+ui->cbEnvMap->text(),"-envmap:");
836      //Possible Combinations
837 <    this->commandMap.insertMulti("textures->DAT / ONI","DDS");
838 <    this->commandMap.insertMulti("textures->DAT / ONI","TGA");
839 <    this->commandMap.insertMulti("textures->DAT / ONI","PNG");
840 <    this->commandMap.insertMulti("textures->DAT / ONI","JPG");
841 <    this->commandMap.insertMulti("textures->DDS / TGA / PNG / JPG","ONI");
842 <
843 <    ////////////////////////////////////////////////////////////////////////Models Commands
844 <    this->commandMap.insert("models->ONI->OBJ","-extract:obj");
845 <    this->commandMap.insert("models->ONI->DAE","-extract:dae -search "+Util::insertQuotes(this->AeLocation+"/GameDataFolder/level0_Final"));
846 <    this->commandMap.insert("models->OBJ->ONI","-create:m3gm");
847 <    this->commandMap.insert("models->DAE->ONI","-create:trbs");
848 <    //######################Models Options
849 <    this->commandMap.insert("models->"+ui->cbCellShading->text(),"-cel");
850 <    this->commandMap.insert("models->"+ui->cbNormals->text(),"-normals");
851 <    this->commandMap.insert("models->"+ui->cbTexture->text(),"-tex:");
852 <    this->commandMap.insert("models->"+ui->cbWithAnimation->text(),"-anim:");
853 <    this->commandMap.insert("models->No Animation","-noanim"); //No label with this name so can't be dynamic
837 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","TGA");
838 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","DDS");
839 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","PNG");
840 >    this->commandMap.insertMulti("textures->DAT / TXMP ONI","JPG");
841 >    this->commandMap.insertMulti("textures->TGA / DDS / PNG / JPG","TXMP ONI");
842 >
843 >    ////////////////////////////////////////////////////////////////////////Characters Commands
844 >    this->commandMap.insert("characters->TRAM ONI->XML / XML & DAE","-extract:xml");
845 >    this->commandMap.insert("characters->TRBS / ONCC ONI->DAE","-extract:dae");
846 >    this->commandMap.insert("characters->TRBS XML->TRBS ONI","-create");
847 >    this->commandMap.insert("characters->TRBS DAE->TRBS ONI","-create:trbs");
848 >    this->commandMap.insert("characters->FILM DAT->XML","film2xml");
849 >
850 >    //######################Characters Options
851 >    this->commandMap.insert("characters->"+ui->cbWithTRBS_ONCC->text(),"-anim-body:");
852 >    this->commandMap.insert("characters->"+ui->cbCellShading->text(),"-cel");
853 >    this->commandMap.insert("characters->"+ui->cbNormals->text(),"-normals");
854      //Possible Combinations
855 <    this->commandMap.insertMulti("models->ONI","OBJ");
856 <    this->commandMap.insertMulti("models->ONI","DAE");
857 <    this->commandMap.insertMulti("models->OBJ","ONI");
858 <    this->commandMap.insertMulti("models->DAE","ONI");
859 <
860 <    ////////////////////////////////////////////////////////////////////////Animations Commands
861 <    this->commandMap.insert("animations->ONI->DAE","-extract:dae");
862 <    this->commandMap.insert("animations->FILM DAT->XML","film2xml");
863 <    //######################Animations Options
864 <    this->commandMap.insert("animations->"+ui->cbCamera->text(),"-geom:camera");
865 <    this->commandMap.insert("animations->"+ui->cbGeometry->text(),"-geom:");
855 >    this->commandMap.insertMulti("characters->TRAM ONI","XML / XML & DAE");
856 >    this->commandMap.insertMulti("characters->TRBS / ONCC ONI","DAE");
857 >    this->commandMap.insertMulti("characters->DAE","TRBS ONI");
858 >    this->commandMap.insertMulti("characters->TRBS DAE","TRBS ONI");
859 >    this->commandMap.insertMulti("characters->TRBS XML","TRBS ONI");
860 >    this->commandMap.insertMulti("characters->FILM DAT","XML");
861 >
862 >    ////////////////////////////////////////////////////////////////////////Objects Commands
863 >    this->commandMap.insert("objects->M3GM ONI->OBJ","-extract:obj");
864 >    this->commandMap.insert("objects->M3GM ONI->DAE","-extract:dae");
865 >    this->commandMap.insert("objects->ONWC ONI->OBJ","-extract:obj");
866 >    this->commandMap.insert("objects->ONWC ONI->DAE","-extract:dae");
867 >    this->commandMap.insert("objects->OBAN ONI (cam)->DAE","-extract:dae");
868 >    this->commandMap.insert("objects->OBJ->M3GM ONI","-create:m3gm");
869 >    //######################Characters Options
870 >    this->commandMap.insert("objects->"+ui->cbTexture->text(),"-tex:");
871 >    this->commandMap.insert("objects->"+ui->cbWithAnimation->text(),"-geom:");
872      //Possible Combinations
873 <    this->commandMap.insertMulti("animations->ONI","DAE");
874 <    this->commandMap.insertMulti("animations->DAE","ONI");
875 <    this->commandMap.insertMulti("animations->FILM DAT","XML");
873 >    this->commandMap.insertMulti("objects->M3GM ONI","OBJ");
874 >    this->commandMap.insertMulti("objects->M3GM ONI","DAE");
875 >    this->commandMap.insertMulti("objects->ONWC ONI","OBJ");
876 >    this->commandMap.insertMulti("objects->ONWC ONI","DAE");
877 >    this->commandMap.insertMulti("objects->OBAN ONI (cam)","DAE");
878 >    this->commandMap.insertMulti("objects->OBJ","M3GM ONI");
879 >
880  
881      ////////////////////////////////////////////////////////////////////////Levels Commands
882 <    this->commandMap.insert("levels->ONI->DAE","-extract:dae -search "+Util::insertQuotes(this->AeLocation+"/GameDataFolder/level0_Final"));
883 <    this->commandMap.insert("levels->DAE->ONI","-create:akev");
882 >    this->commandMap.insert("levels->DAT->ONI FILES","-export");
883 >    //this->commandMap.insert("levels->ONI FILES->DAT","-import"); //Not used.
884 >    this->commandMap.insert("levels->ONI FILES->DAT(PC)","-import:nosep");
885 >    this->commandMap.insert("levels->ONI FILES->DAT(demoPCMAC)","-import:sep");
886 >    this->commandMap.insert("levels->AKEV ONI->DAE","-extract:dae");
887 >    this->commandMap.insert("levels->DAE->AKEV ONI","-create:akev");
888      this->commandMap.insert("levels->MASTER XML->DAT","-create:level");
889      this->commandMap.insert("levels->MASTER XML->ONI FILES","-create:level");
890      //######################Levels Options
891      this->commandMap.insert("levels->"+ui->cbGridsLevels->text(),"-grid:create");
892      //Possible Combinations
893 <    this->commandMap.insertMulti("levels->ONI","DAE");
894 <    this->commandMap.insertMulti("levels->DAE","ONI");
893 >    this->commandMap.insertMulti("levels->DAT","ONI FILES");
894 >    this->commandMap.insertMulti("levels->ONI FILES","DAT");
895 >    this->commandMap.insertMulti("levels->AKEV ONI","DAE");
896 >    this->commandMap.insertMulti("levels->DAE","AKEV ONI");
897      this->commandMap.insertMulti("levels->MASTER XML","DAT");
898      this->commandMap.insertMulti("levels->MASTER XML","ONI FILES");
899  
900      ////////////////////////////////////////////////////////////////////////Misc Commands
901 <    this->commandMap.insert("misc->DAT / ONI->WAV","-extract:wav");
902 <    this->commandMap.insert("misc->DAT / ONI->AIF","-extract:aif");
903 <    this->commandMap.insert("misc->DAT / ONI->TXT","-extract:txt");
904 <    this->commandMap.insert("misc->WAV / AIF->ONI","-create");
905 <    this->commandMap.insert("misc->TXT->ONI","-create:subt");
901 >    this->commandMap.insert("misc->DAT / SNDD ONI->WAV","-extract:wav");
902 >    this->commandMap.insert("misc->DAT / SNDD ONI->AIF","-extract:aif");
903 >    this->commandMap.insert("misc->DAT / SUBT ONI->TXT","-extract:txt");
904 >    this->commandMap.insert("misc->WAV / AIF->SNDD ONI","-create");
905 >    this->commandMap.insert("misc->TXT->SUBT ONI","-create:subt");
906      //Possible Combinations
907 <    this->commandMap.insertMulti("misc->DAT / ONI","WAV");
908 <    this->commandMap.insertMulti("misc->DAT / ONI","AIF");
909 <    this->commandMap.insertMulti("misc->DAT / ONI","TXT");
910 <    this->commandMap.insertMulti("misc->WAV / AIF","ONI");
911 <    this->commandMap.insertMulti("misc->TXT","ONI");
907 >    this->commandMap.insertMulti("misc->DAT / SNDD ONI","WAV");
908 >    this->commandMap.insertMulti("misc->DAT / SNDD ONI","AIF");
909 >    this->commandMap.insertMulti("misc->DAT / SUBT ONI","TXT");
910 >    this->commandMap.insertMulti("misc->WAV / AIF","SNDD ONI");
911 >    this->commandMap.insertMulti("misc->TXT","SUBT ONI");
912  
913   }
914  
915 < void MainWindow::on_cbFromGeneral_currentIndexChanged(const QString &arg1)
915 > void MainWindow::on_cbFromXML_currentIndexChanged(const QString &arg1)
916   {
917 <    updateComboBox(arg1, ui->cbToGeneral, "general");
917 >    updateComboBox(arg1, ui->cbToXML);
918   }
919  
920 +
921   void MainWindow::on_cbFromTextures_currentIndexChanged(const QString &arg1)
922   {
923 <    //Options are only used for DAT/ONI -> Image
838 <    if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
839 <        ui->gbTextures->setEnabled(false);
840 <    }
841 <    else{
842 <        ui->gbTextures->setEnabled(true);
843 <    }
844 <
845 <    updateComboBox(arg1, ui->cbToTextures, "textures");
923 >    updateComboBox(arg1, ui->cbToTextures);
924   }
925  
926 < void MainWindow::on_cbFromModels_currentIndexChanged(const QString &arg1)
926 > void MainWindow::on_cbFromObjects_currentIndexChanged(const QString &arg1)
927   {
928 <
851 <    ui->cbCellShading->setEnabled(false);
852 <    ui->cbCellShading->setChecked(false);
853 <    ui->cbNormals->setEnabled(false);
854 <    ui->cbNormals->setChecked(false);
855 <    ui->cbTexture->setEnabled(false);
856 <    ui->cbTexture->setChecked(false);
857 <    ui->cbWithAnimation->setEnabled(false);
858 <    ui->cbWithAnimation->setChecked(false);
859 <
860 <    if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){ //case sensitive is faster
861 <        ui->cbTexture->setEnabled(true);
862 <    }
863 <    else if(QString::compare(arg1,"DAE",Qt::CaseSensitive)==0){
864 <        ui->cbCellShading->setEnabled(true);
865 <        ui->cbNormals->setEnabled(true);
866 <    }
867 <
868 <    updateComboBox(arg1, ui->cbToModels, "models");
928 >    updateComboBox(arg1, ui->cbToObjects);
929   }
930  
931 < void MainWindow::on_cbFromAnimations_currentIndexChanged(const QString &arg1)
931 > void MainWindow::on_cbFromCharacters_currentIndexChanged(const QString &arg1)
932   {
933 <    ui->cbCamera->setEnabled(false);
874 <    ui->cbCamera->setChecked(false);
875 <    ui->cbGeometry->setEnabled(false);
876 <    ui->cbGeometry->setChecked(false);
877 <
878 <    if(QString::compare(arg1,"ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
879 <        ui->cbCamera->setEnabled(true);
880 <        ui->cbGeometry->setEnabled(true);
881 <    }
882 <
883 <    updateComboBox(arg1, ui->cbToAnimations, "animations");
933 >    updateComboBox(arg1, ui->cbToCharacters);
934   }
935  
936   void MainWindow::on_cbFromLevels_currentIndexChanged(const QString &arg1)
937   {
938 <    updateComboBox(arg1, ui->cbToLevels, "levels");
938 >    updateComboBox(arg1, ui->cbToLevels);
939   }
940  
941   void MainWindow::on_cbFromMisc_currentIndexChanged(const QString &arg1)
942   {
943 <    updateComboBox(arg1, ui->cbToMisc, "misc");
943 >    updateComboBox(arg1, ui->cbToMisc);
944   }
945  
946 < void MainWindow::updateComboBox(const QString &arg1, QComboBox *comboBox, const QString &identifier){
946 > void MainWindow::updateComboBox(const QString &arg1, QComboBox *comboBox){
947 >
948 >    QString identifier;
949 >
950 >    if(comboBox == ui->cbToXML){
951 >        identifier = ui->tabWidget->tabText(XMLTabIndex);
952 >    }
953 >    else if(comboBox == ui->cbToTextures){
954 >        identifier = ui->tabWidget->tabText(TexturesTabIndex);
955 >
956 >        //Options are only used for DAT/ONI -> Image
957 >        if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
958 >            ui->gbTextures->setEnabled(false);
959 >        }
960 >        else{
961 >            ui->gbTextures->setEnabled(true);
962 >        }
963 >    }
964 >    else if(comboBox == ui->cbToCharacters){
965 >        identifier = ui->tabWidget->tabText(CharactersTabIndex);
966 >
967 >        ui->cbWithTRBS_ONCC->setEnabled(false);
968 >        ui->cbWithTRBS_ONCC->setChecked(false);
969 >        ui->cbCellShading->setEnabled(false);
970 >        ui->cbCellShading->setChecked(false);
971 >        ui->cbNormals->setEnabled(false);
972 >        ui->cbNormals->setChecked(false);
973 >
974 >        if(QString::compare(arg1,"TRAM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
975 >            ui->cbWithTRBS_ONCC->setEnabled(true);
976 >        }
977 >        else if(QString::compare(arg1,"TRBS DAE",Qt::CaseSensitive)==0){
978 >            ui->cbNormals->setEnabled(true);
979 >            ui->cbCellShading->setEnabled(true);
980 >        }
981 >
982 >    }
983 >    else if(comboBox == ui->cbToObjects){
984 >        identifier = ui->tabWidget->tabText(ObjectsTabIndex);
985 >
986 >        ui->cbTexture->setEnabled(false);
987 >        ui->cbTexture->setChecked(false);
988 >        ui->cbWithAnimation->setEnabled(false);
989 >        ui->cbWithAnimation->setChecked(false);
990 >
991 >        if(QString::compare(arg1,"M3GM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
992 >            ui->cbWithAnimation->setEnabled(true);
993 >        }
994 >        else if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){
995 >            ui->cbTexture->setEnabled(true);
996 >        }
997 >    }
998 >    else if(comboBox == ui->cbToLevels){
999 >        identifier = ui->tabWidget->tabText(LevelsTabIndex);
1000 >
1001 >        ui->cbSpecificFilesLevels->setEnabled(false);
1002 >        ui->cbSpecificFilesLevels->setChecked(false);
1003 >        ui->cbDatLevels->setEnabled(false);
1004 >        ui->cbDatLevels->setChecked(false);
1005 >        ui->cbBnvLevels->setEnabled(false);
1006 >        ui->cbBnvLevels->setChecked(false);
1007 >        ui->cbAdditionalSourcesLevels->setEnabled(false);
1008 >        ui->cbAdditionalSourcesLevels->setChecked(false);
1009 >        ui->cbGridsLevels->setEnabled(false);
1010 >        ui->cbGridsLevels->setChecked(false);
1011 >
1012 >        if(arg1=="DAT"){ //case sensitive is faster
1013 >            ui->cbSpecificFilesLevels->setEnabled(true);
1014 >        }
1015 >        else if(arg1=="ONI FILES"){ //case sensitive is faster
1016 >            ui->cbDatLevels->setEnabled(true);
1017 >        }
1018 >        else if(arg1=="DAE"){
1019 >            ui->cbBnvLevels->setEnabled(true);
1020 >            ui->cbAdditionalSourcesLevels->setEnabled(true);
1021 >        }
1022 >    }
1023 >    else{ // Misc
1024 >        identifier = ui->tabWidget->tabText(MiscTabIndex);
1025 >    }
1026 >
1027 >    identifier = identifier.toLower(); // get current tab title text (lower case)
1028 >
1029      comboBox->clear();
1030  
1031      QStringList toUpdate=QStringList();
# Line 920 | Line 1052 | void MainWindow::on_actionMac_Windows_de
1052      ui->actionWindows->setChecked(false);
1053   }
1054  
1055 < void MainWindow::on_pbRemoveSourceGeneral_clicked()
1055 > void MainWindow::on_pbRemoveSourceXML_clicked()
1056   {
1057 <    removeTableContents( ui->twSourcesGeneral);
1057 >    removeTableContents( ui->twSourcesXML);
1058   }
1059  
1060   void MainWindow::on_pbRemoveSourceTextures_clicked()
# Line 930 | Line 1062 | void MainWindow::on_pbRemoveSourceTextur
1062      removeTableContents(ui->twSourcesTextures);
1063   }
1064  
1065 < void MainWindow::on_pbRemoveSourceModels_clicked()
1065 > void MainWindow::on_pbRemoveSourceObjects_clicked()
1066   {
1067 <    removeTableContents(ui->twSourcesModels);
1067 >    removeTableContents(ui->twSourcesObjects);
1068   }
1069  
1070 < void MainWindow::on_pbRemoveSourceAnimations_clicked()
1070 > void MainWindow::on_pbRemoveSourceCharacters_clicked()
1071   {
1072 <    removeTableContents(ui->twSourcesAnimations);
1072 >    removeTableContents(ui->twSourcesCharacters);
1073   }
1074  
1075   void MainWindow::on_pbRemoveSourceLevels_clicked()
# Line 950 | Line 1082 | void MainWindow::on_pbRemoveSourceMisc_c
1082      removeTableContents(ui->twSourcesMisc);
1083   }
1084  
1085 < void MainWindow::on_pbClearSourcesGeneral_clicked()
1085 > void MainWindow::on_pbClearSourcesXML_clicked()
1086   {
1087 <    clearTableContents(ui->twSourcesGeneral);
1087 >    clearTableContents(ui->twSourcesXML);
1088   }
1089  
1090   void MainWindow::on_pbClearSourcesTextures_clicked()
# Line 960 | Line 1092 | void MainWindow::on_pbClearSourcesTextur
1092      clearTableContents(ui->twSourcesTextures);
1093   }
1094  
1095 < void MainWindow::on_pbClearSourcesModels_clicked()
1095 > void MainWindow::on_pbClearSourcesObjects_clicked()
1096   {
1097 <    clearTableContents(ui->twSourcesModels);
1097 >    clearTableContents(ui->twSourcesObjects);
1098   }
1099  
1100 < void MainWindow::on_pbClearSourcesAnimations_clicked()
1100 > void MainWindow::on_pbClearSourcesCharacters_clicked()
1101   {
1102 <    clearTableContents(ui->twSourcesAnimations);
1102 >    clearTableContents(ui->twSourcesCharacters);
1103   }
1104  
1105   void MainWindow::on_pbClearSourcesLevels_clicked()
# Line 983 | Line 1115 | void MainWindow::on_pbClearSourcesMisc_c
1115   void MainWindow::removeTableContents(DropTableWidget *myTable){
1116      int size = myTable->selectionModel()->selectedRows().size();
1117  
1118 +    QMessageBox::StandardButton defaultButton = QMessageBox::NoButton; // default button for clear asking question, only customizable in mac os
1119 +
1120      if(size==0){
1121          Util::showPopUp("Select a row first.");
1122          return;
1123      }
1124  
1125 <    if(Util::showQuestionPopUp(this,"Are you sure you want to delete the selected rows?")){
1125 > #ifdef Q_OS_MAC
1126 >    if(this->useYesAsDefaultWhenRemovingItems){
1127 >        defaultButton = QMessageBox::Yes;
1128 >    }
1129 >    else{
1130 >        defaultButton = QMessageBox::No;
1131 >    }
1132 > #endif
1133 >
1134 >
1135 >    if(Util::showQuestionPopUp(this,"Are you sure you want to delete the selected rows?",defaultButton)){
1136          for(int i=0; i<size; i++){
1137              //myTable->removeRow(myTable->selectedItems().at(size-i-1)->row());
1138              myTable->removeRow(myTable->selectionModel()->selectedRows().at(size-i-1).row());
1139          }
1140          updateItemsLoaded(myTable);
1141 +        rowsWereChangedInDropTableWidget();
1142      }
1143   }
1144  
1145   void MainWindow::clearTableContents(DropTableWidget *myTable){
1146 +
1147 +    QMessageBox::StandardButton defaultButton = QMessageBox::NoButton; // default button for clear asking question, only customizable in mac os
1148 +
1149      if(myTable->rowCount()==0){
1150          Util::showPopUp("Nothing to clear.");
1151          return;
1152      }
1153  
1154 <    if(Util::showQuestionPopUp(this,"Are you sure you want to clear the content?")){
1155 <        myTable->clearContents();
1156 <        myTable->setRowCount(0);
1154 > #ifdef Q_OS_MAC
1155 >    if(this->useYesAsDefaultWhenRemovingItems){
1156 >        defaultButton = QMessageBox::Yes;
1157      }
1158 <    updateItemsLoaded(myTable);
1158 >    else{
1159 >        defaultButton = QMessageBox::No;
1160 >    }
1161 > #endif
1162 >
1163 >    if(Util::showQuestionPopUp(this,"Are you sure you want to clear the content?",defaultButton)){
1164 >        clearTableNoPrompt(myTable);
1165 >        updateItemsLoaded(myTable);
1166 >        rowsWereChangedInDropTableWidget();
1167 >    }
1168 >
1169   }
1170  
1171 + void MainWindow::clearTableNoPrompt(DropTableWidget *myTable){
1172 +    myTable->clearContents();
1173 +    myTable->setRowCount(0);
1174 + }
1175  
1176   void MainWindow::on_actionPreferences_triggered()
1177   {
# Line 1020 | Line 1182 | void MainWindow::on_actionPreferences_tr
1182  
1183  
1184   void MainWindow::closeEvent(QCloseEvent *event){
1185 <    if(this->vagoSettings->value("ConfirmExit").toBool()){
1186 <        if(!Util::showQuestionPopUp(this,"Exit Vago?")){
1185 >    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1186 >        QMessageBox::StandardButton result = askToSaveCurrentProject();
1187 >        if(result == QMessageBox::StandardButton::Cancel){
1188              event->ignore();
1189          }
1190      }
1191   }
1192  
1193 < void MainWindow::on_cbToGeneral_currentIndexChanged(const QString &arg1)
1194 < {
1195 <
1033 <    ui->cbDatGeneral->setEnabled(false);
1034 <    ui->cbDatGeneral->setChecked(false);
1035 <    ui->cbTRAMGeneral->setEnabled(false);
1036 <    ui->cbTRAMGeneral->setChecked(false);
1193 > QMessageBox::StandardButton MainWindow::askToSaveCurrentProject(){
1194 >    QMessageBox::StandardButton result =
1195 >            Util::showQuestionPopUpWithCancel(this,"There are unsaved changes. Do you want to save the current project?", QMessageBox::StandardButton::Yes);
1196  
1197 <    if(QString::compare(ui->cbFromGeneral->currentText(),"ONI",Qt::CaseSensitive)==0){
1198 <        if(QString::compare(arg1,"DAT",Qt::CaseSensitive)==0){
1040 <            ui->cbDatGeneral->setEnabled(true);
1041 <        }
1042 <        else{
1043 <            ui->cbTRAMGeneral->setEnabled(true);
1044 <        }
1197 >    if(result == QMessageBox::StandardButton::Yes){
1198 >        on_actionSave_triggered();
1199      }
1200  
1201 < }
1048 <
1049 < void MainWindow::on_cbToModels_currentIndexChanged(const QString &arg1)
1050 < {
1051 <    ui->cbWithAnimation->setEnabled(false);
1052 <    ui->cbWithAnimation->setChecked(false);
1053 <
1054 <    if(arg1=="DAE"){
1055 <        ui->cbWithAnimation->setEnabled(true);
1056 <    }
1201 >    return result;
1202   }
1203  
1204   void MainWindow::on_cbToLevels_currentIndexChanged(const QString &arg1)
1205   {
1206  
1062    ui->cbDatLevels->setEnabled(false);
1063    ui->cbDatLevels->setChecked(false);
1064    ui->cbBnvLevels->setEnabled(false);
1065    ui->cbBnvLevels->setChecked(false);
1066    ui->cbAdditionalSourcesLevels->setEnabled(false);
1067    ui->cbAdditionalSourcesLevels->setChecked(false);
1068    ui->cbGridsLevels->setEnabled(false);
1069    ui->cbGridsLevels->setChecked(false);
1070
1207      if(ui->cbFromLevels->currentText()=="MASTER XML" && arg1=="DAT"){
1208          ui->cbDatLevels->setEnabled(true);
1209      }
1210 <    else if(ui->cbFromLevels->currentText()=="DAE" && arg1=="ONI"){
1211 <        ui->cbBnvLevels->setEnabled(true);
1212 <        ui->cbAdditionalSourcesLevels->setEnabled(true);
1210 >    else if(ui->cbFromLevels->currentText()=="MASTER XML" && arg1=="ONI FILES"){
1211 >        ui->cbDatLevels->setEnabled(false);
1212 >        ui->cbDatLevels->setChecked(false);
1213      }
1078 }
1214  
1080 void MainWindow::on_cbDatGeneral_toggled(bool checked)
1081 {
1082    ui->leTargetDatGeneral->setEnabled(checked);
1083 }
1084
1085 void MainWindow::on_cbTRAMGeneral_toggled(bool checked)
1086 {
1087    ui->leTRAMGeneral->setEnabled(checked);
1088    if(checked){
1089        QString file=QFileDialog::getOpenFileName(this,"Choose the TRAM.oni file...","./" , "All Files (*.*)");
1090        if(!file.isEmpty()){
1091            ui->leTRAMGeneral->setText(file);
1092        }
1093    }
1215   }
1216  
1217   void MainWindow::on_cbDatLevels_toggled(bool checked)
# Line 1131 | Line 1252 | void MainWindow::on_cbAdditionalSourcesL
1252      }
1253   }
1254  
1255 + void MainWindow::on_cbWithTRBS_ONCC_toggled(bool checked)
1256 + {
1257 +    ui->leTRBS_ONCC->setEnabled(checked);
1258 + }
1259 +
1260   void MainWindow::on_actionCheck_OniSplit_version_triggered()
1261   {
1262 <    QProcess *myProcess = new QProcess();
1263 <    myProcess->start(GlobalVars::OniSplitExeName+" -version");
1264 <    myProcess->waitForFinished(-1);
1265 <    QString result=myProcess->readAllStandardOutput();
1266 <    delete myProcess;
1267 <    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nActual version is:\n"+result);
1262 >    QProcess myProcess;
1263 >    myProcess.setWorkingDirectory(UtilVago::getAppPath());
1264 >    myProcess.start(UtilVago::getOniSplitExecutable()+" -version");
1265 >    myProcess.waitForFinished();
1266 >
1267 >    QString result=myProcess.readAllStandardOutput();
1268 >
1269 >    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nCurrent version is:\n"+result.trimmed());
1270   }
1271  
1272   void MainWindow::on_actionCheck_xmlTools_version_triggered()
1273   {
1274 <    QProcess *myProcess = new QProcess();
1275 <    myProcess->start(GlobalVars::XmlToolsExeName+" version");
1276 <    myProcess->waitForFinished(-1);
1277 <    QString result=myProcess->readLine();
1278 <    delete myProcess;
1279 <    Util::showPopUp("This Vago version was built with base in xmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nActual version is:\n"+result);
1274 >    QProcess myProcess;
1275 >    myProcess.setWorkingDirectory(UtilVago::getAppPath());
1276 >    myProcess.start(UtilVago::getXmlToolsExecutable()+" --version");
1277 >    myProcess.waitForFinished();
1278 >    QString result=myProcess.readLine();
1279 >
1280 >    Util::showPopUp("This Vago version was built with base in XmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nCurrent version is:\n"+result.trimmed());
1281   }
1282  
1283   /**
1284    Update items loaded
1285 <  **/
1286 < void MainWindow::on_tabWidget_selected(const QString &arg1)
1285 > **/
1286 > void MainWindow::on_tabWidget_currentChanged(int)
1287   {
1288 <    if(arg1.compare("General",Qt::CaseSensitive)==0){ //case sentive is faster
1160 <        updateItemsLoaded(ui->twSourcesGeneral);
1161 <    }
1162 <    else if(arg1.compare("Textures",Qt::CaseSensitive)==0){
1163 <        updateItemsLoaded(ui->twSourcesTextures);
1164 <    }
1165 <    else if(arg1.compare("Models",Qt::CaseSensitive)==0){
1166 <        updateItemsLoaded(ui->twSourcesModels);
1167 <    }
1168 <    else if(arg1.compare("Levels",Qt::CaseSensitive)==0){
1169 <        updateItemsLoaded(ui->twSourcesLevels);
1170 <    }
1171 <    else{
1172 <        updateItemsLoaded(ui->twSourcesMisc);
1173 <    }
1288 >    updateItemsLoaded(getCurrentTableWidget());
1289   }
1290  
1291   void MainWindow::updateItemsLoaded(DropTableWidget *currentTable){
# Line 1180 | Line 1295 | void MainWindow::updateItemsLoaded(DropT
1295      this->itemsLoaded->setText(QString().setNum(numItems)+ (numItems==1?" item ":" items ") +"loaded");
1296   }
1297  
1298 + void MainWindow::rowsWereChangedInDropTableWidget(){
1299 +    // We have changed rows, we have now unsaved changes.
1300 +    if(!this->unsavedChangesExist){
1301 +        this->unsavedChangesExist = true;
1302 +        setVagoWindowTitle();
1303 +    }
1304 + }
1305 +
1306   void MainWindow::on_tbCommand_clicked()
1307   {
1308      //Show preferences
# Line 1223 | Line 1346 | void MainWindow::on_actionOther_triggere
1346  
1347   void MainWindow::on_actionView_log_triggered()
1348   {
1349 <    Util::openLogFile();
1349 >    UtilVago::openLogFile();
1350 > }
1351 >
1352 > void MainWindow::on_actionOpen_AE_folder_triggered()
1353 > {
1354 >    QDesktopServices::openUrl(QUrl("file:///"+this->AeLocation));
1355 > }
1356 >
1357 > void MainWindow::on_actionSave_Project_triggered()
1358 > {
1359 >
1360 >    QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),
1361 >                                                    this->vagoSettings->value("LastProjectPath").toString(),
1362 >                                                    tr("Vago project files (*.vgp)"));
1363 >
1364 >    if(!filePath.isEmpty()){
1365 >        saveProjectState(filePath);
1366 >    }
1367 >
1368 > }
1369 >
1370 > // New Project
1371 > void MainWindow::on_actionNew_Project_triggered()
1372 > {
1373 >    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1374 >        QMessageBox::StandardButton result = askToSaveCurrentProject();
1375 >        if(result == QMessageBox::StandardButton::Cancel){
1376 >            return;
1377 >        }
1378 >    }
1379 >
1380 >    QList<DropTableWidget*> myTables = getAllTableWidgets();
1381 >
1382 >    for(DropTableWidget* const currTable : myTables){
1383 >        clearTableNoPrompt(currTable);
1384 >    }
1385 >
1386 >    this->lastProjectFilePath=""; // clear last project file path
1387 >    this->unsavedChangesExist = false;
1388 >
1389 >    setVagoWindowTitle(); // update vago title
1390 > }
1391 >
1392 > void MainWindow::on_actionSave_triggered()
1393 > {
1394 >    if(this->lastProjectFilePath.isEmpty()){
1395 >        on_actionSave_Project_triggered();
1396 >        return;
1397 >    }
1398 >
1399 >    saveProjectState(this->lastProjectFilePath);
1400 > }
1401 >
1402 > void MainWindow::on_actionLoad_Project_triggered()
1403 > {
1404 >
1405 >    QString filePath = QFileDialog::getOpenFileName(this, tr("Load File"),
1406 >                                                    this->vagoSettings->value("LastProjectPath").toString(),
1407 >                                                    tr("Vago project files (*.vgp)"));
1408 >    if(!filePath.isEmpty()){
1409 >        loadProjectState(filePath);
1410 >    }
1411 > }
1412 >
1413 > void MainWindow::on_actionProject1_triggered()
1414 > {
1415 >    loadProjectState(this->ui->actionProject1->text());
1416 > }
1417 >
1418 > void MainWindow::on_actionProject2_triggered()
1419 > {
1420 >    loadProjectState(this->ui->actionProject2->text());
1421 > }
1422 >
1423 > void MainWindow::on_actionProject3_triggered()
1424 > {
1425 >    loadProjectState(this->ui->actionProject3->text());
1426 > }
1427 >
1428 > void MainWindow::on_actionProject4_triggered()
1429 > {
1430 >    loadProjectState(this->ui->actionProject4->text());
1431 > }
1432 >
1433 > void MainWindow::on_actionProject5_triggered()
1434 > {
1435 >    loadProjectState(this->ui->actionProject5->text());
1436   }
1437  
1438   QString MainWindow::getTypeConversion(DropTableWidget *myTable){
1439      QString from,to;
1440  
1441 <    if(myTable==ui->twSourcesGeneral){
1442 <        from=ui->cbFromGeneral->currentText();
1443 <        to=ui->cbToGeneral->currentText();
1441 >    if(myTable==ui->twSourcesXML){
1442 >        from=ui->cbFromXML->currentText();
1443 >        to=ui->cbToXML->currentText();
1444      }
1445      else if(myTable==ui->twSourcesTextures){
1446          from=ui->cbFromTextures->currentText();
1447          to=ui->cbToTextures->currentText();
1448      }
1449 <    else if(myTable==ui->twSourcesModels){
1450 <        from=ui->cbFromModels->currentText();
1451 <        to=ui->cbToModels->currentText();
1452 <    }
1453 <    else if(myTable==ui->twSourcesAnimations){
1454 <        from=ui->cbFromAnimations->currentText();
1455 <        to=ui->cbToAnimations->currentText();
1449 >    else if(myTable==ui->twSourcesObjects){
1450 >        from=ui->cbFromObjects->currentText();
1451 >        to=ui->cbToObjects->currentText();
1452 >    }
1453 >    else if(myTable==ui->twSourcesCharacters){
1454 >        from=ui->cbFromCharacters->currentText();
1455 >        to=ui->cbToCharacters->currentText();
1456      }
1457      else if(myTable==ui->twSourcesLevels){
1458          from=ui->cbFromLevels->currentText();
# Line 1275 | Line 1484 | void MainWindow::dtContextMenu(DropTable
1484          selectedRows << rowItem.row();
1485      }
1486  
1487 <    QMenu *menu = new QMenu();
1488 <    QAction *copy = new QAction("Copy",myTable);
1489 <    QAction *moveUp = new QAction("Move Up",myTable);
1490 <    QAction *moveDown = new QAction("Move Down",myTable);
1491 <    QAction *changeOptions = new QAction("Change To Current Options",myTable);
1492 <    QMenu *changeOutput = new QMenu("Change Output for:");
1493 <    QAction *outWorkspace = new QAction("Workspace",myTable);
1494 <    QAction *outCurrOutput = new QAction("Current Output Folder",myTable);
1495 <    QAction *outOther = new QAction("Other...",myTable);
1496 <    QAction *edisable = new QAction("Enable/Disable",myTable);
1487 >    std::unique_ptr<QMenu> menu = std::make_unique<QMenu>();
1488 >    std::unique_ptr<QAction> copy =  std::make_unique<QAction>("Copy",myTable);
1489 >    std::unique_ptr<QAction> moveUp = std::make_unique<QAction>("Move Up",myTable);
1490 >    std::unique_ptr<QAction> moveDown = std::make_unique<QAction>("Move Down",myTable);
1491 >    std::unique_ptr<QAction> changeOptions = std::make_unique<QAction>("Change To Current Options",myTable);
1492 >    std::unique_ptr<QMenu> changeOutput = std::make_unique<QMenu>("Change Output for:");
1493 >    std::unique_ptr<QAction> outWorkspace = std::make_unique<QAction>("Workspace",myTable);
1494 >    std::unique_ptr<QAction> outCurrOutput = std::make_unique<QAction>("Current Output Folder",myTable);
1495 >    std::unique_ptr<QAction> outOther = std::make_unique<QAction>("Other...",myTable);
1496 >    std::unique_ptr<QAction> edisable = std::make_unique<QAction>("Enable/Disable",myTable);
1497  
1498 <    menu->addAction(copy);
1498 >    menu->addAction(copy.get());
1499      menu->addSeparator();
1500 <    menu->addAction(moveUp);
1501 <    menu->addAction(moveDown);
1500 >    menu->addAction(moveUp.get());
1501 >    menu->addAction(moveDown.get());
1502      menu->addSeparator();
1503 <    menu->addAction(changeOptions);
1504 <    menu->addMenu(changeOutput);
1505 <    changeOutput->addActions(QList<QAction*>() << outWorkspace << outCurrOutput << outOther);
1506 <    menu->addAction(edisable);
1503 >    menu->addAction(changeOptions.get());
1504 >    menu->addMenu(changeOutput.get());
1505 >    changeOutput->addActions(QList<QAction*>() << outWorkspace.get() << outCurrOutput.get() << outOther.get());
1506 >    menu->addAction(edisable.get());
1507  
1508  
1509      //if it's in the first row it can't be setted up
# Line 1318 | Line 1527 | void MainWindow::dtContextMenu(DropTable
1527  
1528      QAction* selectedOption = menu->exec(event->globalPos());
1529  
1530 <    if(selectedOption==copy){
1530 >    if(selectedOption==copy.get()){
1531          //Let's copy the contents to the clipboard
1532  
1533          QString toCopy;
# Line 1341 | Line 1550 | void MainWindow::dtContextMenu(DropTable
1550          QApplication::clipboard()->setText(toCopy);
1551          showSuccessStatusMessage(QString::number(size) + (size==1?" item ":" items ")+ "copied to the clipboard");
1552      }
1553 <    else if(selectedOption==moveUp){
1553 >    else if(selectedOption==moveUp.get()){
1554          qSort(selectedRows); //let's order the selections by the row number, so we know exactly how to swap it
1555          myTable->swapPositions(selectedRows,-1);
1556 +        rowsWereChangedInDropTableWidget();
1557      }
1558 <    else if(selectedOption==moveDown){
1558 >    else if(selectedOption==moveDown.get()){
1559          qSort(selectedRows);
1560          myTable->swapPositions(selectedRows,+1);
1561 +        rowsWereChangedInDropTableWidget();
1562      }
1563 <    else if(selectedOption==changeOptions){
1563 >    else if(selectedOption==changeOptions.get()){
1564          changeToCurrentSettings(selectedRows,myTable);
1565      }
1566 <    else if(selectedOption==outWorkspace){
1566 >    else if(selectedOption==outWorkspace.get()){
1567          changeItemsOutput(myTable,selectedRows,this->workspaceLocation);
1568      }
1569 <    else if(selectedOption==outCurrOutput){
1569 >    else if(selectedOption==outCurrOutput.get()){
1570          changeItemsOutput(myTable,selectedRows,this->outputFolder);
1571      }
1572 <    else if(selectedOption==outOther){
1572 >    else if(selectedOption==outOther.get()){
1573  
1574          QString newDir=QFileDialog::getExistingDirectory(this,"Choose the folder for the output of the files selected...",this->AeLocation+"/GameDataFolder");
1575          newDir=Util::normalizePath(newDir);
# Line 1370 | Line 1581 | void MainWindow::dtContextMenu(DropTable
1581          changeItemsOutput(myTable,selectedRows,newDir);
1582  
1583      }
1584 <    else if(selectedOption==edisable){
1584 >    else if(selectedOption==edisable.get()){
1585  
1586          int enabledCount=0, disabledCount=0;
1587  
# Line 1406 | Line 1617 | void MainWindow::dtContextMenu(DropTable
1617              result+=QString::number(disabledCount) + (disabledCount==1?" item ":" items ") + "Disabled";
1618          }
1619  
1620 +        rowsWereChangedInDropTableWidget();
1621          showSuccessStatusMessage(result);
1622      }
1411
1412    delete copy;
1413    delete moveUp;
1414    delete moveDown;
1415    delete changeOptions;
1416    delete outWorkspace;
1417    delete outCurrOutput;
1418    delete outOther;
1419    delete changeOutput;
1420    delete edisable;
1421    delete menu;
1623   }
1624  
1625   void MainWindow::changeToCurrentSettings(QList<int> rows, DropTableWidget* myTable){
# Line 1442 | Line 1643 | void MainWindow::changeToCurrentSettings
1643          myTable->updateTableToolTips(row);
1644      }
1645  
1646 +    rowsWereChangedInDropTableWidget();
1647      showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed to the current settings");
1648   }
1649  
# Line 1465 | Line 1667 | void MainWindow::changeItemsOutput(DropT
1667          myTable->updateTableToolTips(row);
1668      }
1669  
1670 +    rowsWereChangedInDropTableWidget();
1671      showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed the output to "+(newOutput!=this->workspaceLocation?Util::cutName(newOutput):"Vago workspace"));
1672   }
1673  
1674   QString MainWindow::getCommand(DropTableWidget* myTable, QString myOutputFolder, QString from, QString to , QString file){
1675 <    if(myTable==ui->twSourcesGeneral){ //So we only need to parse one command.
1676 <        return fileParsingGeneral(myOutputFolder,from,to,file);
1675 >
1676 >    QString tabTitle=ui->tabWidget->tabText(ui->tabWidget->currentIndex()).toLower(); // get current tab title
1677 >
1678 >    if(myTable==ui->twSourcesXML){ //So we only need to parse one command.
1679 >        return fileParsingXML(tabTitle, myOutputFolder,from,to,file);
1680      }
1681      else if(myTable==ui->twSourcesTextures){
1682 <        return fileParsingTextures(myOutputFolder,from,to,file);
1682 >        return fileParsingTextures(tabTitle, myOutputFolder,from,to,file);
1683      }
1684 <    else if(myTable==ui->twSourcesModels){
1685 <        return fileParsingModels(myOutputFolder,from,to,file);
1684 >    else if(myTable==ui->twSourcesObjects){
1685 >        return fileParsingObjects(tabTitle, myOutputFolder,from,to,file);
1686      }
1687 <    else if(myTable==ui->twSourcesAnimations){
1688 <        return fileParsingAnimations(myOutputFolder,from,to,file);
1687 >    else if(myTable==ui->twSourcesCharacters){
1688 >        return fileParsingCharacters(tabTitle, myOutputFolder,from,to,file);
1689      }
1690      else if(myTable==ui->twSourcesLevels){
1691 <        return fileParsingLevels(myOutputFolder,from,to,file);
1691 >        return fileParsingLevels(tabTitle, myOutputFolder,from,to,file);
1692      }
1693      else{
1694          return fileParsingMisc(myOutputFolder,from,to,file);
# Line 1501 | Line 1707 | void MainWindow::connectSlots(){
1707      //This signal is for thread that is working can show the result of a conversion
1708      connect(myConverter, SIGNAL(resultConversion(QString,int)), this, SLOT(TresultConversion(QString,int)));
1709  
1710 +    //This signal is for thread that is working notify the gui thread that the conversion was aborted with sucess
1711 +    connect(myConverter, SIGNAL(conversionAborted()), this, SLOT(TconversionAborted()));
1712 +
1713 +    // This signal is to the user be able to terminate a conversion (OniSplit process in class myConverter will be terminated)
1714 +    connect(this, SIGNAL(terminateCurrProcess()), myConverter, SLOT(terminateCurrProcess()));
1715 +
1716      //Drop signal for General table
1717 <    connect(ui->twSourcesGeneral, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1717 >    connect(ui->twSourcesXML, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1718  
1719      //Drop signal for Textures table
1720      connect(ui->twSourcesTextures, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1721  
1722 <    //Drop signal for Models table
1723 <    connect(ui->twSourcesModels, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1722 >    //Drop signal for Objects table
1723 >    connect(ui->twSourcesObjects, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1724  
1725 <    //Drop signal for Animations table
1726 <    connect(ui->twSourcesAnimations, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1725 >    //Drop signal for Characters table
1726 >    connect(ui->twSourcesCharacters, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1727  
1728      //Drop signal for Levels table
1729      connect(ui->twSourcesLevels, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
# Line 1520 | Line 1732 | void MainWindow::connectSlots(){
1732      connect(ui->twSourcesMisc, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1733  
1734      //Context menu for General table
1735 <    connect(ui->twSourcesGeneral, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1735 >    connect(ui->twSourcesXML, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1736  
1737      //Context menu for Textures table
1738      connect(ui->twSourcesTextures, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1739  
1740 <    //Context menu for Models table
1741 <    connect(ui->twSourcesModels, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1740 >    //Context menu for Objects table
1741 >    connect(ui->twSourcesObjects, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1742  
1743 <    //Context menu for Animations table
1744 <    connect(ui->twSourcesAnimations, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1743 >    //Context menu for Characters table
1744 >    connect(ui->twSourcesCharacters, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1745  
1746      //Context menu for Levels table
1747      connect(ui->twSourcesLevels, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
# Line 1538 | Line 1750 | void MainWindow::connectSlots(){
1750      connect(ui->twSourcesMisc, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1751   }
1752  
1753 + void MainWindow::saveProjectState(const QString &filePath)
1754 + {
1755 +
1756 +    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
1757 +
1758 +    pugi::xml_document doc;
1759 +
1760 +    pugi::xml_node rootNode = doc.append_child("VagoProject");
1761 +    rootNode.append_attribute("vagoVersion").set_value(GlobalVars::LastCompatibleVersion.toUtf8().constData());
1762 +
1763 +    foreach(DropTableWidget* const &myTable, tableWidgets){
1764 +        saveProjectWidget(rootNode, myTable);
1765 +    }
1766 +
1767 +    if(!doc.save_file(filePath.toUtf8().constData(), PUGIXML_TEXT("\t"), pugi::format_default | pugi::format_write_bom, pugi::xml_encoding::encoding_utf8)){
1768 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while trying to save the project file. Please try another path.");
1769 +        return;
1770 +    }
1771 +
1772 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
1773 +
1774 +    this->lastProjectFilePath = filePath;
1775 +    this->unsavedChangesExist = false;
1776 +
1777 +    addNewRecentProject(filePath);
1778 +
1779 +    setVagoWindowTitle();
1780 +
1781 +    showSuccessStatusMessage("Project saved sucessfully.");
1782 + }
1783 +
1784 + void MainWindow::saveProjectWidget(pugi::xml_node &rootNode, DropTableWidget* table)
1785 + {
1786 +    QString from;
1787 +    QString to;
1788 +    QString tabName = getTabNameByTableWidget(table);
1789 +
1790 +    pugi::xml_node currentNodeTable = rootNode.append_child("tempName");
1791 +    pugi::xml_node options;
1792 +
1793 +    if(table==ui->twSourcesXML){ //So we only need to parse one command.
1794 +        from = ui->cbFromXML->currentText().toUtf8().constData();
1795 +        to = ui->cbToXML->currentText().toUtf8().constData();
1796 +    }
1797 +    else if(table==ui->twSourcesTextures){
1798 +        from = ui->cbFromTextures->currentText().toUtf8().constData();
1799 +        to = ui->cbToTextures->currentText().toUtf8().constData();
1800 +        options = currentNodeTable.append_child("Options");
1801 +        options.append_attribute("type").set_value(Util::qStrToCstr(getTextureRBCheckedTypeTexture()->text()));
1802 +        options.append_attribute("genMipMaps").set_value(Util::boolToCstr(ui->cbMipMapsTextures->isChecked()));
1803 +        options.append_attribute("noUwrap").set_value(Util::boolToCstr(ui->cbNoUwrap->isChecked()));
1804 +        options.append_attribute("noVwrap").set_value(Util::boolToCstr(ui->cbNoVwrap->isChecked()));
1805 +        options.append_attribute("large").set_value(Util::boolToCstr(ui->cbLarge->isChecked()));
1806 +        options.append_attribute("envMap").set_value(Util::boolToCstr(ui->cbEnvMap->isChecked()));
1807 +        options.append_attribute("envMapValue").set_value(Util::qStrToCstr(ui->leEnvMapTexture->text()));
1808 +    }
1809 +    else if(table==ui->twSourcesCharacters){
1810 +        from = ui->cbFromCharacters->currentText().toUtf8().constData();
1811 +        to = ui->cbToCharacters->currentText().toUtf8().constData();
1812 +        options = currentNodeTable.append_child("Options");
1813 +        options.append_attribute("cellShading").set_value(Util::boolToCstr(ui->cbCellShading->isChecked()));
1814 +        options.append_attribute("normals").set_value(Util::boolToCstr(ui->cbNormals->isChecked()));
1815 +        options.append_attribute("extractTRBSONCC").set_value(Util::boolToCstr(ui->cbWithTRBS_ONCC->isChecked()));
1816 +        options.append_attribute("extractTRBSONCCValue").set_value(Util::qStrToCstr(ui->leTRBS_ONCC->text()));
1817 +    }
1818 +    else if(table==ui->twSourcesObjects){
1819 +        from = ui->cbFromObjects->currentText().toUtf8().constData();
1820 +        to = ui->cbToObjects->currentText().toUtf8().constData();
1821 +        options = currentNodeTable.append_child("Options");
1822 +        options.append_attribute("texture").set_value(Util::boolToCstr(ui->cbTexture->isChecked()));
1823 +        options.append_attribute("textureValue").set_value(Util::qStrToCstr(ui->leTextureName->text()));
1824 +        options.append_attribute("withAnimation").set_value(Util::boolToCstr(ui->cbWithAnimation->isChecked()));
1825 +        options.append_attribute("withAnimationValue").set_value(Util::qStrToCstr(ui->leAnimationName->text()));
1826 +    }
1827 +    else if(table==ui->twSourcesLevels){
1828 +        from = ui->cbFromLevels->currentText().toUtf8().constData();
1829 +        to = ui->cbToLevels->currentText().toUtf8().constData();
1830 +        options = currentNodeTable.append_child("Options");
1831 +        options.append_attribute("extractWithFiles").set_value(Util::boolToCstr(ui->cbSpecificFilesLevels->isChecked()));
1832 +        options.append_attribute("extractWithFilesValue").set_value(Util::qStrToCstr(ui->leSpecificFilesLevels->text()));
1833 +        options.append_attribute("datFilename").set_value(Util::boolToCstr(ui->cbDatLevels->isChecked()));
1834 +        options.append_attribute("datFilenameValue").set_value(Util::qStrToCstr(ui->leTargetDatLevels->text()));
1835 +        options.append_attribute("bnvSource").set_value(Util::boolToCstr(ui->cbBnvLevels->isChecked()));
1836 +        options.append_attribute("bnvSourceValue").set_value(Util::qStrToCstr(ui->leBnvLevels->text()));
1837 +        options.append_attribute("generateGrids").set_value(Util::boolToCstr(ui->cbGridsLevels->isChecked()));
1838 +        options.append_attribute("additionalSources").set_value(Util::boolToCstr(ui->cbAdditionalSourcesLevels->isChecked()));
1839 +        options.append_attribute("additionalSourcesValue").set_value(Util::qStrToCstr(ui->leAdditSourcesLevels->text()));
1840 +    }
1841 +    else{
1842 +        from = ui->cbFromMisc->currentText().toUtf8().constData();
1843 +        to = ui->cbToMisc->currentText().toUtf8().constData();
1844 +    }
1845 +
1846 +    currentNodeTable.set_name(tabName.toUtf8().constData());
1847 +
1848 +    currentNodeTable.append_attribute("from").set_value(from.toUtf8().constData());
1849 +    currentNodeTable.append_attribute("to").set_value(to.toUtf8().constData());
1850 +
1851 +
1852 +    for(int i=0; i<table->rowCount(); i++){
1853 +
1854 +        QString currFileFolder = table->item(i,0)->text();
1855 +        QString currFromTo = table->item(i,1)->text();
1856 +        QString currCommand = table->item(i,2)->text();
1857 +
1858 +        pugi::xml_node currentRow = currentNodeTable.append_child("Row");
1859 +
1860 +
1861 +        currentRow.append_attribute("fileFolder").set_value(Util::qStrToCstr(currFileFolder));
1862 +        currentRow.append_attribute("fromTo").set_value(Util::qStrToCstr(currFromTo));
1863 +        currentRow.append_attribute("command").set_value(Util::qStrToCstr(currCommand));
1864 +
1865 +        if(table->item(i,2)->background()==table->disabledBackStyle){
1866 +            currentRow.append_attribute("disabled").set_value(true);
1867 +        }
1868 +
1869 +    }
1870 + }
1871 +
1872 + QRadioButton* MainWindow::getTextureRBCheckedTypeTexture()
1873 + {
1874 +    if(ui->rbBGR32->isChecked()){
1875 +        return ui->rbBGR32;
1876 +    }
1877 +    else if(ui->rbBGRA32->isChecked()){
1878 +        return ui->rbBGRA32;
1879 +    }
1880 +    else if(ui->rbBGR555->isChecked()){
1881 +        return ui->rbBGR555;
1882 +    }
1883 +    else if(ui->rbBGRA5551->isChecked()){
1884 +        return ui->rbBGRA5551;
1885 +    }
1886 +    else if(ui->rbBGRA444->isChecked()){
1887 +        return ui->rbBGRA444;
1888 +    }
1889 +    else{ //dxt1 checked
1890 +        return ui->rbDxt1;
1891 +    }
1892 + }
1893 +
1894 + QRadioButton* MainWindow::getTextureRBTypeTextureByName(const QString &texType)
1895 + {
1896 +    if(QString::compare(texType,ui->rbBGR32->text(),Qt::CaseSensitive)==0){
1897 +        return ui->rbBGR32;
1898 +    }
1899 +    else if(QString::compare(texType,ui->rbBGRA32->text(),Qt::CaseSensitive)==0){
1900 +        return ui->rbBGRA32;
1901 +    }
1902 +    else if(QString::compare(texType, ui->rbBGR555->text(),Qt::CaseSensitive)==0){
1903 +        return ui->rbBGR555;
1904 +    }
1905 +    else if(QString::compare(texType,ui->rbBGRA5551->text(),Qt::CaseSensitive)==0){
1906 +        return ui->rbBGRA5551;
1907 +    }
1908 +    else if(QString::compare(texType,ui->rbBGRA444->text(),Qt::CaseSensitive)==0){
1909 +        return ui->rbBGRA444;
1910 +    }
1911 +    else{ //dxt1
1912 +        return ui->rbDxt1;
1913 +    }
1914 +
1915 + }
1916 +
1917 + void MainWindow::setVagoWindowTitle(){
1918 +
1919 +    QString vagoTitle = "Vago v"+GlobalVars::AppVersion + " - ";
1920 +
1921 +    if(this->lastProjectFilePath.isEmpty()){
1922 +        vagoTitle += "Untitled";
1923 +    }
1924 +    else{
1925 +        vagoTitle += Util::cutNameWithoutBackSlash(this->lastProjectFilePath);
1926 +    }
1927 +
1928 +    if(this->unsavedChangesExist){
1929 +        vagoTitle += "*";
1930 +    }
1931 +
1932 +    setWindowTitle(vagoTitle);
1933 + }
1934 +
1935 + DropTableWidget* MainWindow::getCurrentTableWidget(){
1936 +
1937 +    return getTableWidgetByTabName(ui->tabWidget->tabText(ui->tabWidget->currentIndex()));
1938  
1939 + }
1940 +
1941 + DropTableWidget* MainWindow::getTableWidgetByTabName(const QString &tabName){
1942 +
1943 +    if(tabName.compare("XML",Qt::CaseSensitive)==0){ //case sentive is faster
1944 +        return ui->twSourcesXML;
1945 +    }
1946 +    else if(tabName.compare("Textures",Qt::CaseSensitive)==0){
1947 +        return ui->twSourcesTextures;
1948 +    }
1949 +    else if(tabName.compare("Characters",Qt::CaseSensitive)==0){
1950 +        return ui->twSourcesCharacters;
1951 +    }
1952 +    else if(tabName.compare("Objects",Qt::CaseSensitive)==0){
1953 +        return ui->twSourcesObjects;
1954 +    }
1955 +    else if(tabName.compare("Levels",Qt::CaseSensitive)==0){
1956 +        return ui->twSourcesLevels;
1957 +    }
1958 +    else{
1959 +        return ui->twSourcesMisc;
1960 +    }
1961 +
1962 + }
1963 +
1964 + QString MainWindow::getCurrentTabName(){
1965 +    return ui->tabWidget->tabText(ui->tabWidget->currentIndex());
1966 + }
1967 +
1968 + QString MainWindow::getTabNameByTableWidget(DropTableWidget* table){
1969 +
1970 +    if(table == ui->twSourcesXML){
1971 +        return ui->tabWidget->tabText(XMLTabIndex);
1972 +    }
1973 +    else if(table == ui->twSourcesTextures){
1974 +        return ui->tabWidget->tabText(TexturesTabIndex);
1975 +    }
1976 +    else if(table == ui->twSourcesCharacters){
1977 +        return ui->tabWidget->tabText(CharactersTabIndex);
1978 +    }
1979 +    else if(table == ui->twSourcesObjects){
1980 +        return ui->tabWidget->tabText(ObjectsTabIndex);
1981 +    }
1982 +    else if(table == ui->twSourcesLevels){
1983 +        return ui->tabWidget->tabText(LevelsTabIndex);
1984 +    }
1985 +    else{
1986 +        return ui->tabWidget->tabText(MiscTabIndex);
1987 +    }
1988 +
1989 + }
1990 +
1991 + QList<DropTableWidget*> MainWindow::getAllTableWidgets()
1992 + {
1993 +    QList<DropTableWidget*> tableWidgets;
1994 +
1995 +    tableWidgets << ui->twSourcesXML << ui->twSourcesTextures << ui->twSourcesCharacters
1996 +                 << ui->twSourcesObjects << ui->twSourcesLevels << ui->twSourcesMisc;
1997 +
1998 +    return tableWidgets;
1999 + }
2000 +
2001 + void MainWindow::loadProjectState(const QString &filePath)
2002 + {
2003 +
2004 +    if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
2005 +        QMessageBox::StandardButton result = askToSaveCurrentProject();
2006 +        if(result == QMessageBox::StandardButton::Cancel){
2007 +            return;
2008 +        }
2009 +    }
2010 +
2011 +    QString statusError = "Couldn't load project.";
2012 +
2013 +    pugi::xml_document doc;
2014 +
2015 +    pugi::xml_parse_result result = doc.load_file(Util::qStrToCstr(filePath));
2016 +
2017 +    if(result.status!=pugi::status_ok){
2018 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while loading project file.\n" + QString(result.description()));
2019 +        showErrStatusMessage(statusError);
2020 +        return;
2021 +    }
2022 +
2023 +
2024 +    if(QString(doc.root().first_child().name()) != "VagoProject"){
2025 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, QString(doc.root().name()) + "The file opened is not a valid VagoProject file. Load aborted.");
2026 +        showErrStatusMessage(statusError);
2027 +        return;
2028 +    }
2029 +
2030 +    QString projVagoVersion;
2031 +
2032 +    try{
2033 +        projVagoVersion = QString(doc.select_node("/VagoProject/@vagoVersion").attribute().value());
2034 +    }
2035 +    catch (const pugi::xpath_exception& e)
2036 +    {
2037 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't find the vagoVersion of the current project. Load aborted.\n" + QString(e.what()));
2038 +        showErrStatusMessage(statusError);
2039 +        return;
2040 +    }
2041 +
2042 +    if(!projVagoVersion.startsWith(GlobalVars::LastCompatibleVersion)){
2043 +        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.");
2044 +        showErrStatusMessage(statusError);
2045 +        return;
2046 +    }
2047 +
2048 +    // After the initial validations begin loading the project data
2049 +
2050 +    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
2051 +
2052 +    try{
2053 +        foreach(DropTableWidget* const &myTable, tableWidgets){
2054 +            loadProjectWidget(doc, myTable);
2055 +        }
2056 +    }
2057 +    catch(const std::exception& e){
2058 +        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't load the vago project. Error: " + QString(e.what()));
2059 +        showErrStatusMessage(statusError);
2060 +        return;
2061 +    }
2062 +
2063 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2064 +
2065 +    this->lastProjectFilePath = filePath;
2066 +    this->unsavedChangesExist = false;
2067 +
2068 +    addNewRecentProject(filePath);
2069 +
2070 +    setVagoWindowTitle();
2071 +
2072 +    showSuccessStatusMessage("Project loaded sucessfully.");
2073 + }
2074 +
2075 +
2076 + void MainWindow::loadProjectWidget(pugi::xml_document &doc, DropTableWidget* table)
2077 + {
2078 +    QString tabName = getTabNameByTableWidget(table);
2079 +    QString from (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@from")).attribute().value());
2080 +    QString to (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@to")).attribute().value());
2081 +
2082 +    if(table==ui->twSourcesXML){
2083 +        ui->cbFromXML->setCurrentText(from);
2084 +        on_cbFromXML_currentIndexChanged(from);
2085 +        ui->cbToXML->setCurrentText(to);
2086 +    }
2087 +    else if(table==ui->twSourcesTextures){
2088 +        //ui->cbFromTextures->setCurrentText(from);
2089 +        on_cbFromTextures_currentIndexChanged(from);
2090 +        ui->cbToTextures->setCurrentText(to);
2091 +
2092 +        getTextureRBTypeTextureByName((doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@type")).attribute().value()))->setChecked(true);
2093 +        ui->cbMipMapsTextures->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@genMipMaps")).attribute().as_bool());
2094 +        ui->cbNoUwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noUwrap")).attribute().as_bool());
2095 +        ui->cbNoVwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noVwrap")).attribute().as_bool());
2096 +        ui->cbLarge->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@large")).attribute().as_bool());
2097 +        ui->cbEnvMap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMap")).attribute().as_bool());
2098 +        ui->leEnvMapTexture->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMapValue")).attribute().value()));
2099 +    }
2100 +    else if(table==ui->twSourcesCharacters){
2101 +        ui->cbFromCharacters->setCurrentText(from);
2102 +        on_cbFromCharacters_currentIndexChanged(from);
2103 +        ui->cbToCharacters->setCurrentText(to);
2104 +
2105 +
2106 +        ui->cbCellShading->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@cellShading")).attribute().as_bool());
2107 +        ui->cbNormals->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@normals")).attribute().as_bool());
2108 +        ui->cbWithTRBS_ONCC->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCC")).attribute().as_bool());
2109 +        ui->leTRBS_ONCC->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCCValue")).attribute().value()));
2110 +    }
2111 +    else if(table==ui->twSourcesObjects){
2112 +        ui->cbFromObjects->setCurrentText(from);
2113 +        on_cbFromObjects_currentIndexChanged(from);
2114 +        ui->cbToObjects->setCurrentText(to);
2115 +
2116 +        ui->cbTexture->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@texture")).attribute().as_bool());
2117 +        ui->leTextureName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@textureValue")).attribute().value()));
2118 +        ui->cbWithAnimation->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimation")).attribute().as_bool());
2119 +        ui->leAnimationName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimationValue")).attribute().value()));
2120 +    }
2121 +    else if(table==ui->twSourcesLevels){
2122 +        ui->cbFromLevels->setCurrentText(from);
2123 +        on_cbFromLevels_currentIndexChanged(from);
2124 +        ui->cbToLevels->setCurrentText(to);
2125 +
2126 +        ui->cbSpecificFilesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFiles")).attribute().as_bool());
2127 +        ui->leSpecificFilesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFilesValue")).attribute().value()));
2128 +        ui->cbDatLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilename")).attribute().as_bool());
2129 +        ui->leTargetDatLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilenameValue")).attribute().value()));
2130 +        ui->cbBnvLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSource")).attribute().as_bool());
2131 +        ui->leBnvLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSourceValue")).attribute().value()));
2132 +        ui->cbGridsLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@generateGrids")).attribute().as_bool());
2133 +        ui->cbAdditionalSourcesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSources")).attribute().as_bool());
2134 +        ui->leAdditSourcesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSource")).attribute().value()));
2135 +    }
2136 +    else{
2137 +        ui->cbFromMisc->setCurrentText(from);
2138 +        on_cbFromMisc_currentIndexChanged(from);
2139 +        ui->cbToMisc->setCurrentText(to);
2140 +    }
2141 +
2142 +    // Clean previous rows
2143 +    clearTableNoPrompt(table);
2144 +
2145 +    for(const pugi::xpath_node &xPathNode : doc.select_nodes(Util::qStrToCstr("/VagoProject/"+tabName+"/Row"))){
2146 +        pugi::xml_node currNode = xPathNode.node();
2147 +
2148 +        QString currFileFolder = currNode.attribute("fileFolder").value();
2149 +        QString currFromTo = currNode.attribute("fromTo").value();
2150 +        QString currCommand = currNode.attribute("command").value();
2151 +
2152 +        bool isToDisable = false;
2153 +        pugi::xml_attribute disabledAttr = currNode.attribute("disabled");
2154 +        isToDisable = disabledAttr.empty() ? false : disabledAttr.as_bool();
2155 +
2156 +        addRowTable(table,currFileFolder,currFromTo,currCommand, isToDisable);
2157 +    }
2158 + }
2159 +
2160 + void MainWindow::saveRecentProjects(){
2161 +    for(int i=0; i<this->recentProjectsList.size(); i++){
2162 +        this->vagoSettings->setValue("RecentProject" + QString::number(i+1), recentProjectsList[i]);
2163 +    }
2164 + }
2165 +
2166 + void MainWindow::loadRecentProjects(){
2167 +    for(int i=0; i<this->recentProjectsMaxSize; i++){
2168 +
2169 +        QString currProj = this->vagoSettings->value("RecentProject" + QString::number(i+1)).toString();
2170 +
2171 +        if(!currProj.isEmpty()){
2172 +            recentProjectsList.append(currProj);
2173 +        }
2174 +        else{
2175 +            break;
2176 +        }
2177 +    }
2178 +
2179 +    reloadRecentProjectsMenu();
2180 +
2181 + }
2182 +
2183 + void MainWindow::addNewRecentProject(const QString &filePath){
2184 +
2185 +    // If the new project is equal to the last one simply ignore
2186 +    if(filePath == this->vagoSettings->value("RecentProject1").toString()){
2187 +        return;
2188 +    }
2189 +
2190 +    // If the item already exists in our list remove it, so it can go to the top again
2191 +    for(auto it = this->recentProjectsList.begin(); it != this->recentProjectsList.end();){
2192 +        if(*it == filePath){
2193 +            it = this->recentProjectsList.erase(it);
2194 +        }
2195 +        else{
2196 +            it++;
2197 +        }
2198 +    }
2199 +
2200 +    // if we gonna overflow our list, remove the older item to reserve space to the new one
2201 +    if(this->recentProjectsList.size()==this->recentProjectsMaxSize){
2202 +        this->recentProjectsList.removeLast();
2203 +    }
2204 +
2205 +    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2206 +
2207 +    // add new recent file
2208 +    this->recentProjectsList.prepend(filePath);
2209 +
2210 +    reloadRecentProjectsMenu();
2211 +
2212 +    saveRecentProjects();
2213 + }
2214 +
2215 + void MainWindow::reloadRecentProjectsMenu(){
2216 +
2217 +    ui->menuRecent_Projects->setEnabled(false);
2218 +    ui->actionProject1->setVisible(false);
2219 +    ui->actionProject2->setVisible(false);
2220 +    ui->actionProject3->setVisible(false);
2221 +    ui->actionProject4->setVisible(false);
2222 +    ui->actionProject5->setVisible(false);
2223 +
2224 +    {
2225 +        QList<QString>::const_iterator it;
2226 +        int i;
2227 +        for(it = recentProjectsList.cbegin(), i=0; it != recentProjectsList.cend(); it++, i++){
2228 +
2229 +            QAction* currAction = nullptr;
2230 +
2231 +            switch (i){
2232 +            case 0:
2233 +                currAction = ui->actionProject1;
2234 +                break;
2235 +            case 1:
2236 +                currAction = ui->actionProject2;
2237 +                break;
2238 +            case 2:
2239 +                currAction = ui->actionProject3;
2240 +                break;
2241 +            case 3:
2242 +                currAction = ui->actionProject4;
2243 +                break;
2244 +            case 4:
2245 +                currAction = ui->actionProject5;
2246 +                break;
2247 +            }
2248 +
2249 +            if(currAction){
2250 +                ui->menuRecent_Projects->setEnabled(true);
2251 +                currAction->setText(*it);
2252 +                currAction->setVisible(true);
2253 +            }
2254 +        }
2255 +    }
2256 +
2257 + }

Diff Legend

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