Index: Vago/trunk/Vago/mainwindow.cpp
===================================================================
--- Vago/trunk/Vago/mainwindow.cpp	(revision 1036)
+++ Vago/trunk/Vago/mainwindow.cpp	(revision 1047)
@@ -10,22 +10,22 @@
     ui->setupUi(this);
 
-    this->myLogger = new Logger(Util::getAppPath()); //start logger
-
-    this->myLogger->writeString("Detected AppDir: "+Util::getAppPath());
+    this->myLogger = new Logger(UtilVago::getAppPath(), GlobalVars::AppLogName); //start logger
+
+    this->myLogger->writeString("Detected AppDir: "+UtilVago::getAppPath());
     this->myLogger->writeString("True app dir: "+QDir::currentPath());
 
-    this->setWindowTitle("Vago v"+GlobalVars::AppVersion);
-
-    if(!QFile::exists(Util::getAppPath()+"/"+GlobalVars::OniSplitString)){
-        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.");
+    setVagoWindowTitle();
+
+    if(!QFile::exists(UtilVago::getOniSplitExeAbsolutePath())){
+        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.");
         exit(1);
     }
 
-    if(!QFile::exists(Util::getAppPath()+"/"+GlobalVars::XmlToolsString)){
-        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.");
+    if(!QFile::exists(UtilVago::getXmlToolsExeAbsolutePath())){
+        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.");
         exit(1);
     }
 
-    this->vagoSettings = new QSettings(Util::getAppPath() + "/" + this->VagoSettingsName, QSettings::IniFormat);
+    this->vagoSettings = new QSettings(UtilVago::getAppPath() + "/" + this->VagoSettingsName, QSettings::IniFormat);
 
     //First Execution? Old configuration? Settings missed?
@@ -36,5 +36,5 @@
     }
     if(!this->vagoSettings->contains("Workspace")){
-        this->vagoSettings->setValue("Workspace", Util::getAppPath()+"/VagoWorkspace");
+        this->vagoSettings->setValue("Workspace", UtilVago::getAppPath()+"/VagoWorkspace");
         iniChanged=true;
     }
@@ -45,5 +45,5 @@
 
         if(aefolder.isEmpty()){
-            Util::showErrorPopUp("AE folder is mandatory. Application will now exit.");
+            UtilVago::showAndLogErrorPopUp(this->myLogger, "AE folder is mandatory. Application will now exit.");
             exit(1);
         }
@@ -75,4 +75,14 @@
         this->vagoSettings->setValue("ConfirmExit", false);
         iniChanged=true;
+    }
+    if(!this->vagoSettings->contains("LastProjectPath")){
+        this->vagoSettings->setValue("LastProjectPath", this->vagoSettings->value("Workspace"));
+        iniChanged=true;
+    }
+    for(int i=0; i<this->recentProjectsMaxSize; i++){
+        if(!this->vagoSettings->contains("RecentProject" + QString::number(i+1))){
+            this->vagoSettings->setValue("RecentProject" + QString::number(i+1), "");
+            iniChanged=true;
+        }
     }
 #ifdef Q_OS_MAC
@@ -118,7 +128,4 @@
     this->listToProccess = new QStringList;
 
-    //Create a thread for do the conversion in background
-    this->myConverter = new Converter(Util::getAppPath(),this->myLogger,this->listToProccess);
-
     // User interface
     ui->mainToolBar->addWidget(ui->tbAE); //add ae installer launch button
@@ -132,5 +139,6 @@
     ui->mainToolBar->setLayoutDirection(Qt::RightToLeft);
 
-    setConverterButtonsSize();
+    ui->pbConvert->setMinimumHeight(ui->pbConvert->sizeHint().height()*1.5); // This is OS indepented. It maintain size ratio over the Windows and Mac.
+
 
 #ifdef Q_OS_MAC
@@ -144,11 +152,13 @@
     // resize(800,600); // Mac OS pcs should be able to render this resolution without any problem. It's also better
     //// because the components on mac use more space
+#endif
+
+    resize(this->startedWindowWidth,this->startedWindowHeight);
+
+#ifdef Q_OS_MAC
+    ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (⌘ + Enter)");
 #else
-    //resize(640,480); // windows stuff
+    ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (Ctrl + Enter)");
 #endif
-
-    resize(this->startedWindowWidth,this->startedWindowHeight);
-
-    connectSlots();
 
     //Commands Mapping
@@ -158,5 +168,5 @@
     updateItemsLoaded(ui->twSourcesXML);
 
-    this->myLogger->writeString("Application started.");
+    loadRecentProjects();
 }
 
@@ -166,4 +176,31 @@
     this->myLogger->writeString("Application Exited.");
 }
+
+
+void MainWindow::showEvent(QShowEvent *e)
+{
+    #ifdef Q_OS_WIN
+    // QProgressBar only works after the windows was shown
+    // http://stackoverflow.com/questions/24840941/qwintaskbarprogress-wont-show (Kervala answer)
+
+    this->win7TaskBarButton = new QWinTaskbarButton();
+
+    this->win7TaskBarButton->setWindow(this->windowHandle());
+
+    this->win7TaskBarProgress = this->win7TaskBarButton->progress();
+
+    //Create a thread for do the conversion in background
+    this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, this->listToProccess, this->win7TaskBarProgress);
+    #else
+    this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, this->listToProccess);
+    #endif
+
+    connectSlots();
+
+    this->myLogger->writeString("Application started.");
+
+    e->accept();
+}
+
 
 void MainWindow::on_actionExit_triggered()
@@ -187,5 +224,5 @@
 void MainWindow::on_actionSound_Wizard_triggered()
 {
-    SoundWizard myWizard (Util::getAppPath(), this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
+    SoundWizard myWizard (UtilVago::getAppPath(), this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
     myWizard.exec();
 }
@@ -283,5 +320,5 @@
     }
     else{
-        Util::showErrorPopUp("An error occurred checking last version:\n\n"+result->errorString());
+        UtilVago::showAndLogErrorPopUp(this->myLogger, "An error occurred checking last version:\n\n"+result->errorString());
     }
     result->deleteLater();
@@ -436,22 +473,5 @@
         }
 
-        if(ui->rbBGR32->isChecked()){
-            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGR32->text());
-        }
-        else if(ui->rbBGRA32->isChecked()){
-            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGRA32->text());
-        }
-        else if(ui->rbBGR555->isChecked()){
-            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGR555->text());
-        }
-        else if(ui->rbBGRA5551->isChecked()){
-            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGRA5551->text());
-        }
-        else if(ui->rbBGRA444->isChecked()){
-            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbBGRA444->text());
-        }
-        else{ //dxt1 checked
-            command+=" "+this->commandMap.value(tabTitle+"->"+ui->rbDxt1->text());
-        }
+        command+=" "+this->commandMap.value(tabTitle+"->"+getTextureRBCheckedTypeTexture()->text());
 
         if(ui->cbEnvMap->isChecked()){
@@ -635,5 +655,5 @@
 }
 
-void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command){
+void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command, bool isToDisabled){
     //Get actual number rows
     int twSize=myTable->rowCount();
@@ -647,4 +667,10 @@
     QTableWidgetItem *newCommand = new QTableWidgetItem(command);
 
+    if(isToDisabled){
+        myTable->setDisableStyleWidgetItem(newFile);
+        myTable->setDisableStyleWidgetItem(newConversion);
+        myTable->setDisableStyleWidgetItem(newCommand);
+    }
+
     myTable->setItem(twSize,0,newFile);
     myTable->setItem(twSize,1,newConversion);
@@ -654,39 +680,16 @@
 }
 
-void MainWindow::on_pbConvertXML_clicked()
-{
-    startConversion(ui->twSourcesXML);
-}
-
-void MainWindow::on_pbConvertTextures_clicked()
-{
-    startConversion(ui->twSourcesTextures);
-}
-
-void MainWindow::on_pbConvertObjects_clicked()
-{
-    startConversion(ui->twSourcesObjects);
-}
-
-void MainWindow::on_pbConvertCharacters_clicked()
-{
-    startConversion(ui->twSourcesCharacters);
-}
-
-void MainWindow::on_pbConvertLevels_clicked()
-{
-    startConversion(ui->twSourcesLevels);
-}
-
-void MainWindow::on_pbConvertMisc_clicked()
-{
-    startConversion(ui->twSourcesMisc);
-}
-
-void MainWindow::startConversion(DropTableWidget *myTable){
+void MainWindow::on_pbConvert_clicked()
+{
+    startConversion();
+}
+
+void MainWindow::startConversion(){
+
+    DropTableWidget* currTable = getCurrentTableWidget();
 
     bool ready=false;
-    for(int i=0; i<myTable->rowCount(); i++){ //There are items to process?
-        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
+    for(int i=0; i<currTable->rowCount(); i++){ //There are items to process?
+        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
             ready=true;
             break;
@@ -704,8 +707,8 @@
     }
 
-    for(int i=0; i<myTable->rowCount(); i++){
+    for(int i=0; i<currTable->rowCount(); i++){
         //Only process enabled items
-        if(myTable->item(i,2)->background()!=myTable->disabledBackStyle){
-            this->listToProccess->append(myTable->item(i,2)->text());
+        if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
+            this->listToProccess->append(currTable->item(i,2)->text());
         }
     }
@@ -733,9 +736,9 @@
         QString sNumErrors=QString::number(numErrors);
         if(numErrors>1){
-            Util::showErrorLogPopUp(result+"\n This is the last of "+sNumErrors+" Errors.");
+            UtilVago::showErrorPopUpLogButton(result+"\n This is the last of "+sNumErrors+" Errors.");
             showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" Errors).");
         }
         else{
-            Util::showErrorLogPopUp(result);
+            UtilVago::showErrorPopUpLogButton(result);
             showErrStatusMessage("Something gone wrong. Check log file.");
         }
@@ -887,12 +890,4 @@
 void MainWindow::on_cbFromTextures_currentIndexChanged(const QString &arg1)
 {
-    //Options are only used for DAT/ONI -> Image
-    if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
-        ui->gbTextures->setEnabled(false);
-    }
-    else{
-        ui->gbTextures->setEnabled(true);
-    }
-
     updateComboBox(arg1, ui->cbToTextures);
 }
@@ -900,16 +895,4 @@
 void MainWindow::on_cbFromObjects_currentIndexChanged(const QString &arg1)
 {
-    ui->cbTexture->setEnabled(false);
-    ui->cbTexture->setChecked(false);
-    ui->cbWithAnimation->setEnabled(false);
-    ui->cbWithAnimation->setChecked(false);
-
-    if(QString::compare(arg1,"M3GM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
-        ui->cbWithAnimation->setEnabled(true);
-    }
-    else if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){
-        ui->cbTexture->setEnabled(true);
-    }
-
     updateComboBox(arg1, ui->cbToObjects);
 }
@@ -917,19 +900,4 @@
 void MainWindow::on_cbFromCharacters_currentIndexChanged(const QString &arg1)
 {
-    ui->cbWithTRBS_ONCC->setEnabled(false);
-    ui->cbWithTRBS_ONCC->setChecked(false);
-    ui->cbCellShading->setEnabled(false);
-    ui->cbCellShading->setChecked(false);
-    ui->cbNormals->setEnabled(false);
-    ui->cbNormals->setChecked(false);
-
-    if(QString::compare(arg1,"TRAM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
-        ui->cbWithTRBS_ONCC->setEnabled(true);
-    }
-    else if(QString::compare(arg1,"TRBS DAE",Qt::CaseSensitive)==0){
-        ui->cbNormals->setEnabled(true);
-        ui->cbCellShading->setEnabled(true);
-    }
-
     updateComboBox(arg1, ui->cbToCharacters);
 }
@@ -937,27 +905,4 @@
 void MainWindow::on_cbFromLevels_currentIndexChanged(const QString &arg1)
 {
-
-    ui->cbSpecificFilesLevels->setEnabled(false);
-    ui->cbSpecificFilesLevels->setChecked(false);
-    ui->cbDatLevels->setEnabled(false);
-    ui->cbDatLevels->setChecked(false);
-    ui->cbBnvLevels->setEnabled(false);
-    ui->cbBnvLevels->setChecked(false);
-    ui->cbAdditionalSourcesLevels->setEnabled(false);
-    ui->cbAdditionalSourcesLevels->setChecked(false);
-    ui->cbGridsLevels->setEnabled(false);
-    ui->cbGridsLevels->setChecked(false);
-
-    if(arg1=="DAT"){ //case sensitive is faster
-        ui->cbSpecificFilesLevels->setEnabled(true);
-    }
-    else if(arg1=="ONI FILES"){ //case sensitive is faster
-        ui->cbDatLevels->setEnabled(true);
-    }
-    else if(arg1=="DAE"){
-        ui->cbBnvLevels->setEnabled(true);
-        ui->cbAdditionalSourcesLevels->setEnabled(true);
-    }
-
     updateComboBox(arg1, ui->cbToLevels);
 }
@@ -969,5 +914,85 @@
 
 void MainWindow::updateComboBox(const QString &arg1, QComboBox *comboBox){
-    QString identifier=ui->tabWidget->tabText(ui->tabWidget->currentIndex()).toLower(); // get current tab title text (lower case)
+
+    QString identifier;
+
+    if(comboBox == ui->cbToXML){
+        identifier = ui->tabWidget->tabText(XMLTabIndex);
+    }
+    else if(comboBox == ui->cbToTextures){
+        identifier = ui->tabWidget->tabText(TexturesTabIndex);
+
+        //Options are only used for DAT/ONI -> Image
+        if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
+            ui->gbTextures->setEnabled(false);
+        }
+        else{
+            ui->gbTextures->setEnabled(true);
+        }
+    }
+    else if(comboBox == ui->cbToCharacters){
+        identifier = ui->tabWidget->tabText(CharactersTabIndex);
+
+        ui->cbWithTRBS_ONCC->setEnabled(false);
+        ui->cbWithTRBS_ONCC->setChecked(false);
+        ui->cbCellShading->setEnabled(false);
+        ui->cbCellShading->setChecked(false);
+        ui->cbNormals->setEnabled(false);
+        ui->cbNormals->setChecked(false);
+
+        if(QString::compare(arg1,"TRAM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
+            ui->cbWithTRBS_ONCC->setEnabled(true);
+        }
+        else if(QString::compare(arg1,"TRBS DAE",Qt::CaseSensitive)==0){
+            ui->cbNormals->setEnabled(true);
+            ui->cbCellShading->setEnabled(true);
+        }
+
+    }
+    else if(comboBox == ui->cbToObjects){
+        identifier = ui->tabWidget->tabText(ObjectsTabIndex);
+
+        ui->cbTexture->setEnabled(false);
+        ui->cbTexture->setChecked(false);
+        ui->cbWithAnimation->setEnabled(false);
+        ui->cbWithAnimation->setChecked(false);
+
+        if(QString::compare(arg1,"M3GM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
+            ui->cbWithAnimation->setEnabled(true);
+        }
+        else if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){
+            ui->cbTexture->setEnabled(true);
+        }
+    }
+    else if(comboBox == ui->cbToLevels){
+        identifier = ui->tabWidget->tabText(LevelsTabIndex);
+
+        ui->cbSpecificFilesLevels->setEnabled(false);
+        ui->cbSpecificFilesLevels->setChecked(false);
+        ui->cbDatLevels->setEnabled(false);
+        ui->cbDatLevels->setChecked(false);
+        ui->cbBnvLevels->setEnabled(false);
+        ui->cbBnvLevels->setChecked(false);
+        ui->cbAdditionalSourcesLevels->setEnabled(false);
+        ui->cbAdditionalSourcesLevels->setChecked(false);
+        ui->cbGridsLevels->setEnabled(false);
+        ui->cbGridsLevels->setChecked(false);
+
+        if(arg1=="DAT"){ //case sensitive is faster
+            ui->cbSpecificFilesLevels->setEnabled(true);
+        }
+        else if(arg1=="ONI FILES"){ //case sensitive is faster
+            ui->cbDatLevels->setEnabled(true);
+        }
+        else if(arg1=="DAE"){
+            ui->cbBnvLevels->setEnabled(true);
+            ui->cbAdditionalSourcesLevels->setEnabled(true);
+        }
+    }
+    else{ // Misc
+        identifier = ui->tabWidget->tabText(MiscTabIndex);
+    }
+
+    identifier = identifier.toLower(); // get current tab title text (lower case)
 
     comboBox->clear();
@@ -1105,10 +1130,13 @@
 
     if(Util::showQuestionPopUp(this,"Are you sure you want to clear the content?",defaultButton)){
-        myTable->clearContents();
-        myTable->setRowCount(0);
+        clearTableNoPrompt(myTable);
     }
     updateItemsLoaded(myTable);
 }
 
+void MainWindow::clearTableNoPrompt(DropTableWidget *myTable){
+    myTable->clearContents();
+    myTable->setRowCount(0);
+}
 
 void MainWindow::on_actionPreferences_triggered()
@@ -1186,22 +1214,23 @@
 void MainWindow::on_actionCheck_OniSplit_version_triggered()
 {
-    QProcess *myProcess = new QProcess();
-    myProcess->setWorkingDirectory(Util::getAppPath());
-    myProcess->start(Util::getOniSplitExeName()+" -version");
-    myProcess->waitForFinished(-1);
-    QString result=myProcess->readAllStandardOutput();
-    delete myProcess;
-    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nActual version is:\n"+result);
+    QProcess myProcess;
+    myProcess.setWorkingDirectory(UtilVago::getAppPath());
+    myProcess.start(UtilVago::getOniSplitExeAbsolutePath()+" -version");
+    myProcess.waitForFinished();
+
+    QString result=myProcess.readAllStandardOutput();
+
+    Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nCurrent version is:\n"+result.trimmed());
 }
 
 void MainWindow::on_actionCheck_xmlTools_version_triggered()
 {
-    QProcess *myProcess = new QProcess();
-    myProcess->setWorkingDirectory(Util::getAppPath());
-    myProcess->start(Util::getXmlToolsExeName()+" version");
-    myProcess->waitForFinished(-1);
-    QString result=myProcess->readLine();
-    delete myProcess;
-    Util::showPopUp("This Vago version was built with base in xmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nActual version is:\n"+result);
+    QProcess myProcess;
+    myProcess.setWorkingDirectory(UtilVago::getAppPath());
+    myProcess.start(UtilVago::getXmlToolsExeAbsolutePath()+" --version");
+    myProcess.waitForFinished();
+    QString result=myProcess.readLine();
+
+    Util::showPopUp("This Vago version was built with base in XmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nCurrent version is:\n"+result.trimmed());
 }
 
@@ -1209,26 +1238,7 @@
   Update items loaded
 **/
-void MainWindow::on_tabWidget_currentChanged(int index)
-{
-    QString tabtext = ui->tabWidget->tabText(index);
-
-    if(tabtext.compare("XML",Qt::CaseSensitive)==0){ //case sentive is faster
-        updateItemsLoaded(ui->twSourcesXML);
-    }
-    else if(tabtext.compare("Textures",Qt::CaseSensitive)==0){
-        updateItemsLoaded(ui->twSourcesTextures);
-    }
-    else if(tabtext.compare("Characters",Qt::CaseSensitive)==0){
-        updateItemsLoaded(ui->twSourcesCharacters);
-    }
-    else if(tabtext.compare("Objects",Qt::CaseSensitive)==0){
-        updateItemsLoaded(ui->twSourcesObjects);
-    }
-    else if(tabtext.compare("Levels",Qt::CaseSensitive)==0){
-        updateItemsLoaded(ui->twSourcesLevels);
-    }
-    else{
-        updateItemsLoaded(ui->twSourcesMisc);
-    }
+void MainWindow::on_tabWidget_currentChanged(int)
+{
+    updateItemsLoaded(getCurrentTableWidget());
 }
 
@@ -1283,5 +1293,5 @@
 void MainWindow::on_actionView_log_triggered()
 {
-    Util::openLogFile();
+    UtilVago::openLogFile();
 }
 
@@ -1289,4 +1299,63 @@
 {
     QDesktopServices::openUrl(QUrl("file:///"+this->AeLocation));
+}
+
+void MainWindow::on_actionSave_Project_triggered()
+{
+
+    QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),
+                                                    this->vagoSettings->value("LastProjectPath").toString(),
+                                                    tr("Vago project files (*.vgp)"));
+
+    if(!filePath.isEmpty()){
+        saveProjectState(filePath);
+    }
+
+}
+
+void MainWindow::on_actionSave_triggered()
+{
+    if(this->lastProjectFilePath.isEmpty()){
+        on_actionSave_Project_triggered();
+        return;
+    }
+
+    saveProjectState(this->lastProjectFilePath);
+}
+
+void MainWindow::on_actionLoad_Project_triggered()
+{
+
+    QString filePath = QFileDialog::getOpenFileName(this, tr("Load File"),
+                                                    this->vagoSettings->value("LastProjectPath").toString(),
+                                                    tr("Vago project files (*.vgp)"));
+    if(!filePath.isEmpty()){
+        loadProjectState(filePath);
+    }
+}
+
+void MainWindow::on_actionProject1_triggered()
+{
+    loadProjectState(this->ui->actionProject1->text());
+}
+
+void MainWindow::on_actionProject2_triggered()
+{
+    loadProjectState(this->ui->actionProject2->text());
+}
+
+void MainWindow::on_actionProject3_triggered()
+{
+    loadProjectState(this->ui->actionProject3->text());
+}
+
+void MainWindow::on_actionProject4_triggered()
+{
+    loadProjectState(this->ui->actionProject4->text());
+}
+
+void MainWindow::on_actionProject5_triggered()
+{
+    loadProjectState(this->ui->actionProject5->text());
 }
 
@@ -1340,24 +1409,24 @@
     }
 
-    QMenu *menu = new QMenu();
-    QAction *copy = new QAction("Copy",myTable);
-    QAction *moveUp = new QAction("Move Up",myTable);
-    QAction *moveDown = new QAction("Move Down",myTable);
-    QAction *changeOptions = new QAction("Change To Current Options",myTable);
-    QMenu *changeOutput = new QMenu("Change Output for:");
-    QAction *outWorkspace = new QAction("Workspace",myTable);
-    QAction *outCurrOutput = new QAction("Current Output Folder",myTable);
-    QAction *outOther = new QAction("Other...",myTable);
-    QAction *edisable = new QAction("Enable/Disable",myTable);
-
-    menu->addAction(copy);
+    std::unique_ptr<QMenu> menu = std::make_unique<QMenu>();
+    std::unique_ptr<QAction> copy =  std::make_unique<QAction>("Copy",myTable);
+    std::unique_ptr<QAction> moveUp = std::make_unique<QAction>("Move Up",myTable);
+    std::unique_ptr<QAction> moveDown = std::make_unique<QAction>("Move Down",myTable);
+    std::unique_ptr<QAction> changeOptions = std::make_unique<QAction>("Change To Current Options",myTable);
+    std::unique_ptr<QMenu> changeOutput = std::make_unique<QMenu>("Change Output for:");
+    std::unique_ptr<QAction> outWorkspace = std::make_unique<QAction>("Workspace",myTable);
+    std::unique_ptr<QAction> outCurrOutput = std::make_unique<QAction>("Current Output Folder",myTable);
+    std::unique_ptr<QAction> outOther = std::make_unique<QAction>("Other...",myTable);
+    std::unique_ptr<QAction> edisable = std::make_unique<QAction>("Enable/Disable",myTable);
+
+    menu->addAction(copy.get());
     menu->addSeparator();
-    menu->addAction(moveUp);
-    menu->addAction(moveDown);
+    menu->addAction(moveUp.get());
+    menu->addAction(moveDown.get());
     menu->addSeparator();
-    menu->addAction(changeOptions);
-    menu->addMenu(changeOutput);
-    changeOutput->addActions(QList<QAction*>() << outWorkspace << outCurrOutput << outOther);
-    menu->addAction(edisable);
+    menu->addAction(changeOptions.get());
+    menu->addMenu(changeOutput.get());
+    changeOutput->addActions(QList<QAction*>() << outWorkspace.get() << outCurrOutput.get() << outOther.get());
+    menu->addAction(edisable.get());
 
 
@@ -1383,5 +1452,5 @@
     QAction* selectedOption = menu->exec(event->globalPos());
 
-    if(selectedOption==copy){
+    if(selectedOption==copy.get()){
         //Let's copy the contents to the clipboard
 
@@ -1406,22 +1475,22 @@
         showSuccessStatusMessage(QString::number(size) + (size==1?" item ":" items ")+ "copied to the clipboard");
     }
-    else if(selectedOption==moveUp){
+    else if(selectedOption==moveUp.get()){
         qSort(selectedRows); //let's order the selections by the row number, so we know exactly how to swap it
         myTable->swapPositions(selectedRows,-1);
     }
-    else if(selectedOption==moveDown){
+    else if(selectedOption==moveDown.get()){
         qSort(selectedRows);
         myTable->swapPositions(selectedRows,+1);
     }
-    else if(selectedOption==changeOptions){
+    else if(selectedOption==changeOptions.get()){
         changeToCurrentSettings(selectedRows,myTable);
     }
-    else if(selectedOption==outWorkspace){
+    else if(selectedOption==outWorkspace.get()){
         changeItemsOutput(myTable,selectedRows,this->workspaceLocation);
     }
-    else if(selectedOption==outCurrOutput){
+    else if(selectedOption==outCurrOutput.get()){
         changeItemsOutput(myTable,selectedRows,this->outputFolder);
     }
-    else if(selectedOption==outOther){
+    else if(selectedOption==outOther.get()){
 
         QString newDir=QFileDialog::getExistingDirectory(this,"Choose the folder for the output of the files selected...",this->AeLocation+"/GameDataFolder");
@@ -1435,5 +1504,5 @@
 
     }
-    else if(selectedOption==edisable){
+    else if(selectedOption==edisable.get()){
 
         int enabledCount=0, disabledCount=0;
@@ -1473,15 +1542,4 @@
         showSuccessStatusMessage(result);
     }
-
-    delete copy;
-    delete moveUp;
-    delete moveDown;
-    delete changeOptions;
-    delete outWorkspace;
-    delete outCurrOutput;
-    delete outOther;
-    delete changeOutput;
-    delete edisable;
-    delete menu;
 }
 
@@ -1558,17 +1616,4 @@
 }
 
-/**
-  This is OS indepented. It maintain size ratio over the Windows and Mac.
-  **/
-void MainWindow::setConverterButtonsSize(){
-    int height=ui->pbConvertXML->sizeHint().height()*1.3;
-    ui->pbConvertXML->setMinimumHeight(height);
-    ui->pbConvertTextures->setMinimumHeight(height);
-    ui->pbConvertObjects->setMinimumHeight(height);
-    ui->pbConvertCharacters->setMinimumHeight(height);
-    ui->pbConvertLevels->setMinimumHeight(height);
-    ui->pbConvertMisc->setMinimumHeight(height);
-}
-
 void MainWindow::connectSlots(){
 
@@ -1624,2 +1669,493 @@
     connect(ui->twSourcesMisc, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
 }
+
+void MainWindow::saveProjectState(const QString &filePath)
+{
+
+    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
+
+    pugi::xml_document doc;
+
+    pugi::xml_node rootNode = doc.append_child("VagoProject");
+    rootNode.append_attribute("vagoVersion").set_value(GlobalVars::AppVersion.toUtf8().constData());
+
+    foreach(DropTableWidget* const &myTable, tableWidgets){
+        saveProjectWidget(rootNode, myTable);
+    }
+
+    if(!doc.save_file(filePath.toUtf8().constData(), PUGIXML_TEXT("\t"), pugi::format_default | pugi::format_write_bom, pugi::xml_encoding::encoding_utf8)){
+        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while trying to save the project file. Please try another path.");
+        return;
+    }
+
+    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
+
+    this->lastProjectFilePath = filePath;
+
+    addNewRecentProject(filePath);
+
+    setVagoWindowTitle();
+}
+
+void MainWindow::saveProjectWidget(pugi::xml_node &rootNode, DropTableWidget* table)
+{
+    QString from;
+    QString to;
+    QString tabName = getTabNameByTableWidget(table);
+
+    pugi::xml_node currentNodeTable = rootNode.append_child("tempName");
+    pugi::xml_node options;
+
+    if(table==ui->twSourcesXML){ //So we only need to parse one command.
+        from = ui->cbFromXML->currentText().toUtf8().constData();
+        to = ui->cbToXML->currentText().toUtf8().constData();
+    }
+    else if(table==ui->twSourcesTextures){
+        from = ui->cbFromTextures->currentText().toUtf8().constData();
+        to = ui->cbToTextures->currentText().toUtf8().constData();
+        options = currentNodeTable.append_child("Options");
+        options.append_attribute("type").set_value(Util::qStrToCstr(getTextureRBCheckedTypeTexture()->text()));
+        options.append_attribute("genMipMaps").set_value(Util::boolToCstr(ui->cbMipMapsTextures->isChecked()));
+        options.append_attribute("noUwrap").set_value(Util::boolToCstr(ui->cbNoUwrap->isChecked()));
+        options.append_attribute("noVwrap").set_value(Util::boolToCstr(ui->cbNoVwrap->isChecked()));
+        options.append_attribute("large").set_value(Util::boolToCstr(ui->cbLarge->isChecked()));
+        options.append_attribute("envMap").set_value(Util::boolToCstr(ui->cbEnvMap->isChecked()));
+        options.append_attribute("envMapValue").set_value(Util::qStrToCstr(ui->leEnvMapTexture->text()));
+    }
+    else if(table==ui->twSourcesCharacters){
+        from = ui->cbFromCharacters->currentText().toUtf8().constData();
+        to = ui->cbToCharacters->currentText().toUtf8().constData();
+        options = currentNodeTable.append_child("Options");
+        options.append_attribute("cellShading").set_value(Util::boolToCstr(ui->cbCellShading->isChecked()));
+        options.append_attribute("normals").set_value(Util::boolToCstr(ui->cbNormals->isChecked()));
+        options.append_attribute("extractTRBSONCC").set_value(Util::boolToCstr(ui->cbWithTRBS_ONCC->isChecked()));
+        options.append_attribute("extractTRBSONCCValue").set_value(Util::qStrToCstr(ui->leTRBS_ONCC->text()));
+    }
+    else if(table==ui->twSourcesObjects){
+        from = ui->cbFromObjects->currentText().toUtf8().constData();
+        to = ui->cbToObjects->currentText().toUtf8().constData();
+        options = currentNodeTable.append_child("Options");
+        options.append_attribute("texture").set_value(Util::boolToCstr(ui->cbTexture->isChecked()));
+        options.append_attribute("textureValue").set_value(Util::qStrToCstr(ui->leTextureName->text()));
+        options.append_attribute("withAnimation").set_value(Util::boolToCstr(ui->cbWithAnimation->isChecked()));
+        options.append_attribute("withAnimationValue").set_value(Util::qStrToCstr(ui->leAnimationName->text()));
+    }
+    else if(table==ui->twSourcesLevels){
+        from = ui->cbFromLevels->currentText().toUtf8().constData();
+        to = ui->cbToLevels->currentText().toUtf8().constData();
+        options = currentNodeTable.append_child("Options");
+        options.append_attribute("extractWithFiles").set_value(Util::boolToCstr(ui->cbSpecificFilesLevels->isChecked()));
+        options.append_attribute("extractWithFilesValue").set_value(Util::qStrToCstr(ui->leSpecificFilesLevels->text()));
+        options.append_attribute("datFilename").set_value(Util::boolToCstr(ui->cbDatLevels->isChecked()));
+        options.append_attribute("datFilenameValue").set_value(Util::qStrToCstr(ui->leTargetDatLevels->text()));
+        options.append_attribute("bnvSource").set_value(Util::boolToCstr(ui->cbBnvLevels->isChecked()));
+        options.append_attribute("bnvSourceValue").set_value(Util::qStrToCstr(ui->leBnvLevels->text()));
+        options.append_attribute("generateGrids").set_value(Util::boolToCstr(ui->cbGridsLevels->isChecked()));
+        options.append_attribute("additionalSources").set_value(Util::boolToCstr(ui->cbAdditionalSourcesLevels->isChecked()));
+        options.append_attribute("additionalSourcesValue").set_value(Util::qStrToCstr(ui->leAdditSourcesLevels->text()));
+    }
+    else{
+        from = ui->cbFromMisc->currentText().toUtf8().constData();
+        to = ui->cbToMisc->currentText().toUtf8().constData();
+    }
+
+    currentNodeTable.set_name(tabName.toUtf8().constData());
+
+    currentNodeTable.append_attribute("from").set_value(from.toUtf8().constData());
+    currentNodeTable.append_attribute("to").set_value(to.toUtf8().constData());
+
+
+    for(int i=0; i<table->rowCount(); i++){
+
+        QString currFileFolder = table->item(i,0)->text();
+        QString currFromTo = table->item(i,1)->text();
+        QString currCommand = table->item(i,2)->text();
+
+        pugi::xml_node currentRow = currentNodeTable.append_child("Row");
+
+
+        currentRow.append_attribute("fileFolder").set_value(Util::qStrToCstr(currFileFolder));
+        currentRow.append_attribute("fromTo").set_value(Util::qStrToCstr(currFromTo));
+        currentRow.append_attribute("command").set_value(Util::qStrToCstr(currCommand));
+
+        if(table->item(i,2)->background()==table->disabledBackStyle){
+            currentRow.append_attribute("disabled").set_value(true);
+        }
+
+    }
+}
+
+QRadioButton* MainWindow::getTextureRBCheckedTypeTexture()
+{
+    if(ui->rbBGR32->isChecked()){
+        return ui->rbBGR32;
+    }
+    else if(ui->rbBGRA32->isChecked()){
+        return ui->rbBGRA32;
+    }
+    else if(ui->rbBGR555->isChecked()){
+        return ui->rbBGR555;
+    }
+    else if(ui->rbBGRA5551->isChecked()){
+        return ui->rbBGRA5551;
+    }
+    else if(ui->rbBGRA444->isChecked()){
+        return ui->rbBGRA444;
+    }
+    else{ //dxt1 checked
+        return ui->rbDxt1;
+    }
+}
+
+QRadioButton* MainWindow::getTextureRBTypeTextureByName(const QString &texType)
+{
+    if(QString::compare(texType,ui->rbBGR32->text(),Qt::CaseSensitive)==0){
+        return ui->rbBGR32;
+    }
+    else if(QString::compare(texType,ui->rbBGRA32->text(),Qt::CaseSensitive)==0){
+        return ui->rbBGRA32;
+    }
+    else if(QString::compare(texType, ui->rbBGR555->text(),Qt::CaseSensitive)==0){
+        return ui->rbBGR555;
+    }
+    else if(QString::compare(texType,ui->rbBGRA5551->text(),Qt::CaseSensitive)==0){
+        return ui->rbBGRA5551;
+    }
+    else if(QString::compare(texType,ui->rbBGRA444->text(),Qt::CaseSensitive)==0){
+        return ui->rbBGRA444;
+    }
+    else{ //dxt1
+        return ui->rbDxt1;
+    }
+
+}
+
+void MainWindow::setVagoWindowTitle(){
+
+    QString vagoTitle = "Vago v"+GlobalVars::AppVersion + " - ";
+
+    if(this->lastProjectFilePath.isEmpty()){
+        vagoTitle += "Untitled";
+    }
+    else{
+        vagoTitle += Util::cutNameWithoutBackSlash(this->lastProjectFilePath);
+    }
+
+    setWindowTitle(vagoTitle);
+}
+
+DropTableWidget* MainWindow::getCurrentTableWidget(){
+
+    return getTableWidgetByTabName(ui->tabWidget->tabText(ui->tabWidget->currentIndex()));
+
+}
+
+DropTableWidget* MainWindow::getTableWidgetByTabName(const QString &tabName){
+
+    if(tabName.compare("XML",Qt::CaseSensitive)==0){ //case sentive is faster
+        return ui->twSourcesXML;
+    }
+    else if(tabName.compare("Textures",Qt::CaseSensitive)==0){
+        return ui->twSourcesTextures;
+    }
+    else if(tabName.compare("Characters",Qt::CaseSensitive)==0){
+        return ui->twSourcesCharacters;
+    }
+    else if(tabName.compare("Objects",Qt::CaseSensitive)==0){
+        return ui->twSourcesObjects;
+    }
+    else if(tabName.compare("Levels",Qt::CaseSensitive)==0){
+        return ui->twSourcesLevels;
+    }
+    else{
+        return ui->twSourcesMisc;
+    }
+
+}
+
+QString MainWindow::getCurrentTabName(){
+    return ui->tabWidget->tabText(ui->tabWidget->currentIndex());
+}
+
+QString MainWindow::getTabNameByTableWidget(DropTableWidget* table){
+
+    if(table == ui->twSourcesXML){
+        return ui->tabWidget->tabText(XMLTabIndex);
+    }
+    else if(table == ui->twSourcesTextures){
+        return ui->tabWidget->tabText(TexturesTabIndex);
+    }
+    else if(table == ui->twSourcesCharacters){
+        return ui->tabWidget->tabText(CharactersTabIndex);
+    }
+    else if(table == ui->twSourcesObjects){
+        return ui->tabWidget->tabText(ObjectsTabIndex);
+    }
+    else if(table == ui->twSourcesLevels){
+        return ui->tabWidget->tabText(LevelsTabIndex);
+    }
+    else{
+        return ui->tabWidget->tabText(MiscTabIndex);
+    }
+
+}
+
+QList<DropTableWidget*> MainWindow::getAllTableWidgets()
+{
+    QList<DropTableWidget*> tableWidgets;
+
+    tableWidgets << ui->twSourcesXML << ui->twSourcesTextures << ui->twSourcesCharacters
+                 << ui->twSourcesObjects << ui->twSourcesLevels << ui->twSourcesMisc;
+
+    return tableWidgets;
+}
+
+void MainWindow::loadProjectState(const QString &filePath)
+{
+
+    QString statusError = "Couldn't load project.";
+
+    pugi::xml_document doc;
+
+    pugi::xml_parse_result result = doc.load_file(Util::qStrToCstr(filePath));
+
+    if(result.status!=pugi::status_ok){
+        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while loading project file.\n" + QString(result.description()));
+        showErrStatusMessage(statusError);
+        return;
+    }
+
+
+    if(QString(doc.root().first_child().name()) != "VagoProject"){
+        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, QString(doc.root().name()) + "The file opened is not a valid VagoProject file. Load aborted.");
+        showErrStatusMessage(statusError);
+        return;
+    }
+
+    QString projVagoVersion;
+
+    try{
+        projVagoVersion = QString(doc.select_node("/VagoProject/@vagoVersion").attribute().value());
+    }
+    catch (const pugi::xpath_exception& e)
+    {
+        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't find the vagoVersion of the current project. Load aborted.\n" + QString(e.what()));
+        showErrStatusMessage(statusError);
+        return;
+    }
+
+    if(!projVagoVersion.startsWith(GlobalVars::LastCompatibleVersion)){
+        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.");
+        showErrStatusMessage(statusError);
+        return;
+    }
+
+    // After the initial validations begin loading the project data
+
+    QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
+
+    try{
+        foreach(DropTableWidget* const &myTable, tableWidgets){
+            loadProjectWidget(doc, myTable);
+        }
+    }
+    catch(const std::exception& e){
+        UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't load the vago project. Error: " + QString(e.what()));
+        showErrStatusMessage(statusError);
+        return;
+    }
+
+    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
+
+    this->lastProjectFilePath = filePath;
+
+    addNewRecentProject(filePath);
+
+    setVagoWindowTitle();
+
+    showSuccessStatusMessage("Project loaded sucessfully.");
+}
+
+
+void MainWindow::loadProjectWidget(pugi::xml_document &doc, DropTableWidget* table)
+{
+    QString tabName = getTabNameByTableWidget(table);
+    QString from (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@from")).attribute().value());
+    QString to (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@to")).attribute().value());
+
+    if(table==ui->twSourcesXML){
+        ui->cbFromXML->setCurrentText(from);
+        on_cbFromXML_currentIndexChanged(from);
+        ui->cbToXML->setCurrentText(to);
+    }
+    else if(table==ui->twSourcesTextures){
+        //ui->cbFromTextures->setCurrentText(from);
+        on_cbFromTextures_currentIndexChanged(from);
+        ui->cbToTextures->setCurrentText(to);
+
+        getTextureRBTypeTextureByName((doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@type")).attribute().value()))->setChecked(true);
+        ui->cbMipMapsTextures->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@genMipMaps")).attribute().as_bool());
+        ui->cbNoUwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noUwrap")).attribute().as_bool());
+        ui->cbNoVwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noVwrap")).attribute().as_bool());
+        ui->cbLarge->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@large")).attribute().as_bool());
+        ui->cbEnvMap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMap")).attribute().as_bool());
+        ui->leEnvMapTexture->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMapValue")).attribute().value()));
+    }
+    else if(table==ui->twSourcesCharacters){
+        ui->cbFromCharacters->setCurrentText(from);
+        on_cbFromCharacters_currentIndexChanged(from);
+        ui->cbToCharacters->setCurrentText(to);
+
+
+        ui->cbCellShading->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@cellShading")).attribute().as_bool());
+        ui->cbNormals->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@normals")).attribute().as_bool());
+        ui->cbWithTRBS_ONCC->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCC")).attribute().as_bool());
+        ui->leTRBS_ONCC->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCCValue")).attribute().value()));
+    }
+    else if(table==ui->twSourcesObjects){
+        ui->cbFromObjects->setCurrentText(from);
+        on_cbFromObjects_currentIndexChanged(from);
+        ui->cbToObjects->setCurrentText(to);
+
+        ui->cbTexture->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@texture")).attribute().as_bool());
+        ui->leTextureName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@textureValue")).attribute().value()));
+        ui->cbWithAnimation->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimation")).attribute().as_bool());
+        ui->leAnimationName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimationValue")).attribute().value()));
+    }
+    else if(table==ui->twSourcesLevels){
+        ui->cbFromLevels->setCurrentText(from);
+        on_cbFromLevels_currentIndexChanged(from);
+        ui->cbToLevels->setCurrentText(to);
+
+        ui->cbSpecificFilesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFiles")).attribute().as_bool());
+        ui->leSpecificFilesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFilesValue")).attribute().value()));
+        ui->cbDatLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilename")).attribute().as_bool());
+        ui->leTargetDatLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilenameValue")).attribute().value()));
+        ui->cbBnvLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSource")).attribute().as_bool());
+        ui->leBnvLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSourceValue")).attribute().value()));
+        ui->cbGridsLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@generateGrids")).attribute().as_bool());
+        ui->cbAdditionalSourcesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSources")).attribute().as_bool());
+        ui->leAdditSourcesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSource")).attribute().value()));
+    }
+    else{
+        ui->cbFromMisc->setCurrentText(from);
+        on_cbFromMisc_currentIndexChanged(from);
+        ui->cbToMisc->setCurrentText(to);
+    }
+
+    // Clean previous rows
+    clearTableNoPrompt(table);
+
+    for(const pugi::xpath_node &xPathNode : doc.select_nodes(Util::qStrToCstr("/VagoProject/"+tabName+"/Row"))){
+        pugi::xml_node currNode = xPathNode.node();
+
+        QString currFileFolder = currNode.attribute("fileFolder").value();
+        QString currFromTo = currNode.attribute("fromTo").value();
+        QString currCommand = currNode.attribute("command").value();
+
+        bool isToDisable = false;
+        pugi::xml_attribute disabledAttr = currNode.attribute("disabled");
+        isToDisable = disabledAttr.empty() ? false : disabledAttr.as_bool();
+
+        addRowTable(table,currFileFolder,currFromTo,currCommand, isToDisable);
+    }
+}
+
+void MainWindow::saveRecentProjects(){
+    for(int i=0; i<this->recentProjectsList.size(); i++){
+        this->vagoSettings->setValue("RecentProject" + QString::number(i+1), recentProjectsList[i]);
+    }
+}
+
+void MainWindow::loadRecentProjects(){
+    for(int i=0; i<this->recentProjectsMaxSize; i++){
+
+        QString currProj = this->vagoSettings->value("RecentProject" + QString::number(i+1)).toString();
+
+        if(!currProj.isEmpty()){
+            recentProjectsList.append(currProj);
+        }
+        else{
+            break;
+        }
+    }
+
+    reloadRecentProjectsMenu();
+
+}
+
+void MainWindow::addNewRecentProject(const QString &filePath){
+
+    // If the new project is equal to the last one simply ignore
+    if(filePath == this->vagoSettings->value("RecentProject1").toString()){
+        return;
+    }
+
+    // If the item already exists in our list remove it, so it can go to the top again
+    for(auto it = this->recentProjectsList.begin(); it != this->recentProjectsList.end();){
+        if(*it == filePath){
+            it = this->recentProjectsList.erase(it);
+        }
+        else{
+            it++;
+        }
+    }
+
+    // if we gonna overflow our list, remove the older item to reserve space to the new one
+    if(this->recentProjectsList.size()==this->recentProjectsMaxSize){
+        this->recentProjectsList.removeLast();
+    }
+
+    this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
+
+    // add new recent file
+    this->recentProjectsList.prepend(filePath);
+
+    reloadRecentProjectsMenu();
+
+    saveRecentProjects();
+}
+
+void MainWindow::reloadRecentProjectsMenu(){
+
+    ui->menuRecent_Projects->setEnabled(false);
+    ui->actionProject1->setVisible(false);
+    ui->actionProject2->setVisible(false);
+    ui->actionProject3->setVisible(false);
+    ui->actionProject4->setVisible(false);
+    ui->actionProject5->setVisible(false);
+
+    {
+        QList<QString>::const_iterator it;
+        int i;
+        for(it = recentProjectsList.cbegin(), i=0; it != recentProjectsList.cend(); it++, i++){
+
+            QAction* currAction = nullptr;
+
+            switch (i){
+            case 0:
+                currAction = ui->actionProject1;
+                break;
+            case 1:
+                currAction = ui->actionProject2;
+                break;
+            case 2:
+                currAction = ui->actionProject3;
+                break;
+            case 3:
+                currAction = ui->actionProject4;
+                break;
+            case 4:
+                currAction = ui->actionProject5;
+                break;
+            }
+
+            if(currAction){
+                ui->menuRecent_Projects->setEnabled(true);
+                currAction->setText(*it);
+                currAction->setVisible(true);
+            }
+        }
+    }
+
+}
