ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/s10k/Vago/mainwindow.cpp
Revision: 1058
Committed: Sun Oct 30 14:42:39 2016 UTC (8 years, 11 months ago) by s10k
Content type: text/x-c++src
Original Path: Vago/trunk/Vago/mainwindow.cpp
File size: 89700 byte(s)
Log Message:
Vago 1.2

File Contents

# Content
1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3
4 const QString MainWindow::VagoSettingsName = "settingsVago.ini";
5
6 MainWindow::MainWindow(QWidget *parent) :
7 QMainWindow(parent),
8 ui(new Ui::MainWindow)
9 {
10 ui->setupUi(this);
11
12 this->myLogger = new Logger(UtilVago::getAppPath(), GlobalVars::AppLogName); //start logger
13
14 this->myLogger->writeString("Detected AppDir: "+UtilVago::getAppPath());
15 this->myLogger->writeString("True app dir: "+QDir::currentPath());
16
17 setVagoWindowTitle();
18
19 if(!QFile::exists(UtilVago::getOniSplitExecutableAbsolutePath())){
20 UtilVago::showAndLogErrorPopUp(this->myLogger, "OniSplit not found. Please download it at "+GlobalVars::ModsDomain+" and put it the Vago's tools folder. \n\nProgram will now exit.");
21 exit(1);
22 }
23
24 if(!QFile::exists(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(UtilVago::getAppPath() + "/" + this->VagoSettingsName, QSettings::IniFormat);
30
31 //First Execution? Old configuration? Settings missed?
32 bool iniChanged=false;
33 if(!this->vagoSettings->contains("VagoVersion") || this->vagoSettings->value("VagoVersion")!=GlobalVars::AppVersion){
34 this->vagoSettings->setValue("VagoVersion", GlobalVars::AppVersion);
35 iniChanged=true;
36 }
37 if(!this->vagoSettings->contains("Workspace")){
38 this->vagoSettings->setValue("Workspace", UtilVago::getAppPath()+"/VagoWorkspace");
39 iniChanged=true;
40 }
41 if(!this->vagoSettings->contains("AeFolder")){
42
43 Util::showPopUp("Seems it's the first time you are executing Vago. \n\nPlease input your Anniversary Edition (AE) Folder.");
44 QString aefolder=Util::normalizePath(QFileDialog::getExistingDirectory(this,"Choose Anniversary Edition (AE) folder..."));
45
46 if(aefolder.isEmpty()){
47 UtilVago::showAndLogErrorPopUp(this->myLogger, "AE folder is mandatory. Application will now exit.");
48 exit(1);
49 }
50
51 if(!aefolder.endsWith("AE")){
52 Util::showWarningPopUp("Seems the folder you selected isn't called 'AE'. \n\nIf you run in any problems you can always change it in Vago preferences window.");
53 }
54
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;
69 }
70 if(!this->vagoSettings->contains("SeparateInWorkspace")){
71 this->vagoSettings->setValue("SeparateInWorkspace",true);
72 iniChanged=true;
73 }
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();
101 }
102 ///
103
104 this->workspaceLocation=this->vagoSettings->value("Workspace").toString();
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()){
116 QDir().mkdir(this->workspaceLocation);
117 }
118 this->itemsLoaded=new QLabel(this);
119 ui->statusBar->addWidget(this->itemsLoaded);
120 this->myBar = new QProgressBar(this);
121 this->myBar->setTextVisible(false); //hides text
122
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(this->myBar); //this adds automatically in right
129 ui->statusBar->addPermanentWidget(ui->tbAbortConversion);
130
131 // User interface
132 ui->mainToolBar->addWidget(ui->tbAE); //add ae installer launch button
133 ui->mainToolBar->addWidget(ui->emptySpacerLabel); //trick, we can't add directly a space so we add an empty
134 ui->mainToolBar->addWidget(ui->tbOni); //add oni launch buttonlabel
135 ui->mainToolBar->addWidget(ui->emptySpacerLabel2); //same as before
136 ui->mainToolBar->addWidget(ui->tbCommand); //add option to manual onisplit commands
137 ui->mainToolBar->addWidget(ui->emptySpacerLabel3); //same as before
138 ui->mainToolBar->addWidget(ui->tbXmlToolsInterface); //add option to manual onisplit commands
139 ui->mainToolBar->addWidget(ui->emptySpacerLabel4); //same as before
140 ui->mainToolBar->addWidget(ui->tbOpenFolder); //add option to open folder with files converted etc
141
142 ui->mainToolBar->setLayoutDirection(Qt::RightToLeft);
143
144 ui->pbConvert->setMinimumHeight(ui->pbConvert->sizeHint().height()*1.5); // This is OS indepented. It maintain size ratio over the Windows and Mac.
145
146
147 #ifdef Q_OS_MAC
148 // setUnifiedTitleAndToolBarOnMac(true); // Qt suggests to use it on mac | http://www.slideshare.net/qtbynokia/how-to-make-your-qt-app-look-native // align on left doesn't work if active
149 ui->tbOni->setIcon(QIcon(":/new/icons/oni_icon_mac.png")); // Oni executable on mac have a different icon than windows
150 // Set mac platform the first one in the menu, and also make it checkable by default
151 ui->menuTarget_Platform->removeAction(ui->actionWindows);
152 ui->menuTarget_Platform->addAction(ui->actionWindows);
153 ui->actionWindows->setChecked(false);
154 ui->actionMac_Windows_demo->setChecked(true);
155 // resize(800,600); // Mac OS pcs should be able to render this resolution without any problem. It's also better
156 //// because the components on mac use more space
157 #endif
158
159 resize(this->startedWindowWidth,this->startedWindowHeight);
160
161 #ifdef Q_OS_MAC
162 ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (⌘ + Enter)");
163 #else
164 ui->pbConvert->setToolTip(ui->pbConvert->toolTip() + " (Ctrl + Enter)");
165 #endif
166
167 //Commands Mapping
168 this->commandMap = QHash<QString, QString>();
169 mapCommands();
170
171 updateItemsLoaded(ui->twSourcesXML);
172
173 loadRecentProjects();
174 }
175
176 MainWindow::~MainWindow()
177 {
178 delete ui;
179 this->myLogger->writeString("Application Exited.");
180 }
181
182
183 void MainWindow::showEvent(QShowEvent *e)
184 {
185 // If we don't have a converter yet, application wasn't started.
186 if(!this->applicationIsFullyLoaded)
187 {
188 // Apparently Qt doesn't contains a slot to when the application was fully load (mainwindow). So we do our own implementation instead.
189 connect(this, SIGNAL(signalAppIsLoaded()), this, SLOT(applicationWasLoaded()), Qt::ConnectionType::QueuedConnection);
190 emit signalAppIsLoaded();
191 }
192
193 e->accept();
194 }
195
196 // Called only when the MainWindow was fully loaded and painted on the screen. This slot is only called once.
197 void MainWindow::applicationWasLoaded(){
198 #ifdef Q_OS_WIN
199 // QProgressBar only works after the windows was shown
200 // http://stackoverflow.com/questions/24840941/qwintaskbarprogress-wont-show (Kervala answer)
201
202 this->win7TaskBarButton = new QWinTaskbarButton();
203
204 this->win7TaskBarButton->setWindow(this->windowHandle());
205
206 this->win7TaskBarProgress = this->win7TaskBarButton->progress();
207
208 //Create a thread for do the conversion in background
209 this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, &this->listToProccess, this->win7TaskBarProgress);
210 #else
211 this->myConverter = new Converter(UtilVago::getAppPath(), this->myLogger, &this->listToProccess);
212 #endif
213
214 connectSlots();
215
216 this->myLogger->writeString("Application started.");
217
218 this->applicationIsFullyLoaded = true;
219
220 QString lastSavedProject = this->vagoSettings->value("RecentProject1").toString();
221
222 if(!lastSavedProject.isEmpty() && this->vagoSettings->value("AskToOpenLastProject").toBool()){
223 if(Util::showQuestionPopUp(this,"Do you want to load latest project?\n\nLatest project was '" + Util::cutNameWithoutBackSlash(lastSavedProject) + "'.")){
224 loadProjectState(lastSavedProject);
225 }
226 }
227 }
228
229
230 void MainWindow::on_actionExit_triggered()
231 {
232 close();
233 }
234
235 void MainWindow::on_actionAbout_triggered()
236 {
237 //Show preferences
238 About *aboutWindow = new About(this);
239 aboutWindow->show(); //it destroys itself when finished.
240 }
241
242 void MainWindow::on_actionAE_Package_Creator_triggered()
243 {
244 PackageWizard myWizard = PackageWizard(this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
245 myWizard.exec();
246 }
247
248 void MainWindow::on_actionSound_Wizard_triggered()
249 {
250 SoundWizard myWizard (UtilVago::getAppPath(), this->workspaceWizardsLocation, this->myLogger, &this->commandMap);
251 myWizard.exec();
252 }
253
254 void MainWindow::on_actionBackground_Image_Wizard_triggered()
255 {
256 BGImageWizard myWizard (UtilVago::getAppPath(), this->workspaceWizardsLocation, this->vagoSettings, this->myLogger);
257 myWizard.exec();
258 }
259
260 void MainWindow::on_tbOni_clicked()
261 {
262 QStringList arguments;
263
264 if(this->vagoSettings->value("OniWindow").toBool()){ // Run in a window?
265 arguments << "-noswitch";
266 }
267 #ifdef Q_OS_WIN
268 else{
269 arguments << "-switch"; // only supported on windows. Was added by daodan dll.
270 }
271 #endif
272
273 arguments << "-debugfiles";
274
275 if(!QProcess::startDetached(this->AeLocation+"/"+GlobalVars::OniExe,arguments,this->AeLocation)){
276 showErrStatusMessage("Oni could not be started!");
277 }
278 }
279
280 void MainWindow::on_tbAE_clicked()
281 {
282 // If the app turn out someday to a native app use QProcess::startDetached instead...
283
284 if(!QDesktopServices::openUrl("file:///"+this->AeLocation+"/AEInstaller/bin/AEInstaller2.jar")){
285 showErrStatusMessage("Could not start AE Installer!");
286 }
287 }
288
289 void MainWindow::on_tbOpenFolder_clicked()
290 {
291 QDesktopServices::openUrl(QUrl("file:///"+this->outputFolder));
292 }
293
294
295 void MainWindow::on_tbXmlToolsInterface_clicked()
296 {
297 //We pass no parent because we want to have an independent window for XmlToolsInterface,
298 //so we can minimize it or maximize indepently from the MainWindow
299 XmlToolsInterface *xmlToolsWindow = new XmlToolsInterface(this->myLogger);
300 xmlToolsWindow->show(); //it destroys itself when finished.
301 }
302
303 void MainWindow::on_tbAbortConversion_clicked()
304 {
305 if(Util::showQuestionPopUp(this,"Are you sure you want to abort the current conversion?")){
306 emit terminateCurrProcess();
307 }
308 }
309
310 void MainWindow::on_cbEnvMap_toggled(bool checked)
311 {
312 ui->leEnvMapTexture->setEnabled(checked);
313 }
314
315 void MainWindow::on_cbTexture_toggled(bool checked)
316 {
317 ui->leTextureName->setEnabled(checked);
318 }
319
320 void MainWindow::on_cbWithAnimation_toggled(bool checked)
321 {
322 ui->leAnimationName->setEnabled(checked);
323 }
324
325 void MainWindow::on_cbSpecificFilesLevels_toggled(bool checked)
326 {
327 ui->leSpecificFilesLevels->setEnabled(checked);
328 }
329
330 void MainWindow::on_actionCheck_For_Updates_triggered()
331 {
332
333 //let's check in the web if this version is the latest
334 QNetworkAccessManager *manager = new QNetworkAccessManager(this);
335 connect(manager, SIGNAL(finished(QNetworkReply*)),
336 this, SLOT(checkVagoLastVersion(QNetworkReply*)));
337
338 manager->get(QNetworkRequest(QUrl(GlobalVars::VagoCheckUpdatesUrl)));
339
340 }
341
342 void MainWindow::checkVagoLastVersion(QNetworkReply *result){
343
344 if(result->error()==QNetworkReply::NoError){
345 QScriptEngine engine;
346 QScriptValue sc = engine.evaluate("(" + QString(result->readAll()) + ")");
347
348 // "field_version":{"und":[{"value":"0.6a","format":null,"safe_value":"0.6a"}]} //Note the use of [{}] which means it's a array of 1 element with one object inside (so the use of [0] bellow
349
350 QString newVersion = sc.property("field_version").toObject().property("und").toObject().property("0").toObject().property("value").toString();
351
352 if(newVersion!=GlobalVars::AppVersion){
353 Util::showRichPopUp("There's a new version of Vago! (v"+newVersion+")<br/><br/>"+
354 "You can download it <a href='"+GlobalVars::VagoWebUrl+"'>here</a>.");
355 }
356 else{
357 Util::showPopUp("You are using last version.");
358 }
359 }
360 else{
361 UtilVago::showAndLogErrorPopUp(this->myLogger, "An error occurred checking last version:\n\n"+result->errorString());
362 }
363 result->deleteLater();
364 }
365
366 void MainWindow::on_pbAddSourceXML_clicked()
367 {
368 addFilesSource( ui->twSourcesXML,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
369 }
370
371 void MainWindow::on_pbAddSourceTextures_clicked()
372 {
373 addFilesSource( ui->twSourcesTextures, QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
374 }
375
376 void MainWindow::on_pbAddSourceObjects_clicked()
377 {
378 addFilesSource( ui->twSourcesObjects,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
379 }
380
381 void MainWindow::on_pbAddSourceCharacters_clicked()
382 {
383 addFilesSource( ui->twSourcesCharacters,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
384 }
385
386 void MainWindow::on_pbAddSourceLevels_clicked()
387 {
388 if(QString::compare(ui->cbFromLevels->currentText(),"ONI FILES",Qt::CaseSensitive)==0 && QString::compare(ui->cbToLevels->currentText(),"DAT",Qt::CaseSensitive)==0){ //CaseSensitive is faster)
389 addFilesSource(ui->twSourcesLevels,Util::multipleDirDialog("Choose folders with ONIs..."));
390 }
391 else{
392 addFilesSource(ui->twSourcesLevels,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
393 }
394 }
395
396 void MainWindow::on_pbAddSourceMisc_clicked()
397 {
398 addFilesSource( ui->twSourcesMisc,QFileDialog::getOpenFileNames(this,"Choose the files...","./" , "All Files (*.*)"));
399 }
400
401 QString MainWindow::getFileOutputFolder(QString fromTo, QString myOutputFolder){
402
403 if(myOutputFolder==""){ //We may want to change to a non standart location with context menu
404 myOutputFolder=this->outputFolder;
405 }
406
407 if(this->vagoSettings->value("SeparateInWorkspace").toBool() && myOutputFolder==this->workspaceLocation){
408 myOutputFolder+="/"+ui->tabWidget->tabText(ui->tabWidget->currentIndex());
409 myOutputFolder+="/"+QString(fromTo).replace(" / ","_").replace(" > "," - ");
410 }
411 return Util::insertQuotes(myOutputFolder+"/");
412 }
413
414 void MainWindow::addFilesSource(DropTableWidget *myTable, QStringList files){
415
416 //Get Conversion pretended
417 QString from,to;
418
419 QString fromTo = getTypeConversion(myTable);
420
421 from = QString(fromTo).remove(fromTo.indexOf(" >"),fromTo.size()-1); //parse the string to get the from, only 1 time parsed by each group of files = very fast
422 to = QString(fromTo).remove(0,fromTo.lastIndexOf("> ")+2); //+2 to start after "> "
423
424 //Pre-processing (check if the files/folders received are valid), e.g. check for ONI->DAT if are only given folders and not files
425 if(from=="ONI FILES" && to=="DAT"){
426 //check if it's a folder
427 foreach(QString myFile, files){
428 if(!QDir(myFile).exists()){
429 showErrStatusMessage("Only folders are allowed for this operation.");
430 return;
431 }
432 }
433
434 }
435 else{
436 foreach(QString myFile, files){
437 //check if it's a file
438 if(QDir(myFile).exists()){
439 showErrStatusMessage("Only files are allowed for this operation.");
440 return;
441 }
442 }
443 }
444
445 //Build command
446 QString command, lastFileName;
447
448 QString myOutputFolder=getFileOutputFolder(fromTo);
449
450 //if folder doesn't exist onisplit will create it for us :)
451 foreach(QString currentFile, files){
452
453 currentFile=Util::normalizeAndQuote(currentFile); //insert quotes ("") in file
454
455 if(lastFileName.isEmpty()){ //Optimization: all commands are the same for each file, just replace the filename
456
457 command=getCommand(myTable,myOutputFolder,from,to,currentFile);
458
459 if(command.isEmpty()){ //something wrong was happening (not inputted a texture name?)
460 return; //stop adding files
461 }
462 currentFile=Util::cutName(currentFile);
463 }else{ //one parsing was already made just replace the filename by the old one in the command
464
465 currentFile=Util::cutName(currentFile);
466
467 command.replace(lastFileName,currentFile,Qt::CaseSensitive); //case sentive is faster
468 }
469
470 lastFileName=currentFile;
471
472 addRowTable(myTable,lastFileName,fromTo,command);
473 }
474 updateItemsLoaded(myTable);
475 rowsWereChangedInDropTableWidget();
476 }
477
478 QString MainWindow::fileParsingXML(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
479
480 QString command;
481
482 if(from=="ONI" && to=="XML"){
483 return command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder+" "+file;
484 }
485 else if(from=="XML" && to=="ONI"){
486 return command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder+" "+file;
487 }
488
489 return "";
490
491 }
492
493 QString MainWindow::fileParsingTextures(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
494
495 QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder;
496
497 if(ui->gbTextures->isEnabled()){ //faster than compare strings (if is DAT/ONI)
498
499 if(ui->cbMipMapsTextures->isChecked()){
500 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbMipMapsTextures->text());
501 }
502
503 if(ui->cbNoUwrap->isChecked()){
504 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNoUwrap->text());
505 }
506
507 if(ui->cbNoVwrap->isChecked()){
508 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNoVwrap->text());
509 }
510
511 if(ui->cbLarge->isChecked()){
512 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbLarge->text());
513 }
514
515 command+=" "+this->commandMap.value(tabTitle+"->"+getTextureRBCheckedTypeTexture()->text());
516
517 if(ui->cbEnvMap->isChecked()){
518 if(ui->leEnvMapTexture->text().isEmpty()){
519 showErrStatusMessage("Checkbox '"+ui->cbEnvMap->text()+"' is selected. The name texture name cannot be empty.");
520 return "";
521 }
522 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbEnvMap->text()) + ui->leEnvMapTexture->text().remove(".oni",Qt::CaseInsensitive);
523 }
524 }
525
526 return command+=" "+file; //add source
527 }
528
529 QString MainWindow::fileParsingCharacters(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
530
531 QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder + " " + file ;
532
533
534 if(ui->cbCellShading->isChecked()){
535 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbCellShading->text());
536 }
537
538 if(ui->cbNormals->isChecked()){
539 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbNormals->text());
540 }
541
542 if(ui->cbWithTRBS_ONCC->isChecked()){
543 if(ui->leTRBS_ONCC->text().isEmpty()){
544 showErrStatusMessage("Checkbox '"+ui->cbWithTRBS_ONCC->text()+"' is selected. The name cannot be empty.");
545 return "";
546 }
547
548 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbWithTRBS_ONCC->text())+Util::normalizeAndQuote(ui->leTRBS_ONCC->text());
549 }
550
551 return command;
552 }
553
554
555 QString MainWindow::fileParsingObjects(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
556
557 QString command=this->commandMap.value(tabTitle+"->"+from+"->"+to)+" "+myOutputFolder;
558
559 //TODO: This can be optimized. When some are not enable others are.
560 if(ui->cbTexture->isChecked()){
561 if(ui->leTextureName->text().isEmpty()){
562 showErrStatusMessage("Checkbox '"+ui->cbTexture->text()+"' is selected. The file source cannot be empty.");
563 return "";
564 }
565 command+=" "+this->commandMap.value(tabTitle+"->"+ui->cbTexture->text()) + ui->leTextureName->text();
566 }
567 else if(ui->cbWithAnimation->isChecked()){
568 if(ui->leAnimationName->text().isEmpty()){
569 showErrStatusMessage("Checkbox '"+ui->cbWithAnimation->text()+"' is selected. The file source cannot be empty.");
570 return "";
571 }
572 command+=" "+Util::normalizeAndQuote(ui->leAnimationName->text()) + " " + this->commandMap.value(tabTitle+"->"+ui->cbWithAnimation->text()) + file;
573 return command;
574 }
575
576 if(from=="OBAN ONI (cam)"){
577 command+=" -geom:camera";
578 }
579
580 return command+=" "+file; //add source
581 }
582
583 QString MainWindow::fileParsingLevels(QString tabTitle, QString myOutputFolder, QString from, QString to , QString file){
584
585 QString datName, command;
586
587 if(!(from=="ONI FILES" && to=="DAT")){ // to all except this one
588
589 command=this->commandMap.value(tabTitle+"->"+from+"->"+to);
590
591 if(ui->cbSpecificFilesLevels->isChecked()){
592
593 if(ui->leSpecificFilesLevels->text().isEmpty()){
594 showErrStatusMessage("Checkbox '"+ui->cbSpecificFilesLevels->text()+"' is selected. The files pattern cannot be empty.");
595 return "";
596 }
597
598 command+=":"+ui->leSpecificFilesLevels->text();
599 }
600
601 if(from=="DAT" && to=="ONI FILES"){ // extract files to a subdir with the files name ex: level0_Final
602 command += " " + myOutputFolder.insert(myOutputFolder.size()-2,QString(Util::cutName(file)).replace(".dat","")) + " " + file;
603 }
604 else{
605 command+=" "+myOutputFolder+" "+file;
606 }
607
608 }
609
610 if((from=="ONI FILES" || from=="MASTER XML") && to=="DAT"){ // almost the same command for both
611 QString datName;
612
613 if(from=="MASTER XML"){
614 command+=GlobalVars::OniSplitProcSeparator; //insert mark so we know this action will take 2 commands
615 }
616
617 if(ui->cbDatLevels->isChecked()){
618 if(ui->leTargetDatLevels->text().isEmpty()){
619 showErrStatusMessage("Checkbox '"+ui->cbDatLevels->text()+"' is selected. The name cannot be empty.");
620 return "";
621 }
622 datName+=QString(myOutputFolder).insert(myOutputFolder.size()-1,ui->leTargetDatLevels->text()); //set name inputted by user
623 if(!ui->leTargetDatLevels->text().toUpper().endsWith(".DAT")){
624 datName.insert(datName.size()-1,".dat"); //append extension if necessary (-1 to maintain final quote)
625 }
626 }
627 else{
628 if(from=="ONI FILES"){
629 datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/")+".dat"); //if none iputted set the same name of input file
630 }
631 else if(from=="MASTER XML"){
632 datName=QString(myOutputFolder).insert(myOutputFolder.size()-1,Util::cutName(file).remove("/").replace(".xml",".dat",Qt::CaseInsensitive)); //if none iputted set the same name of input file
633 }
634 }
635 if(from=="ONI FILES"){
636 if(ui->actionWindows->isChecked()){ //is target plataform select windows?
637 return command=this->commandMap.value(tabTitle+"->"+from+"->"+to+"(PC)")+" "+ file + " "+datName;
638 }
639 else{
640 return command=this->commandMap.value(tabTitle+"->"+from+"->"+to+"(demoPCMAC)")+" "+ file + " "+datName;
641 }
642 }
643 else if(from=="MASTER XML"){
644 if(ui->actionWindows->isChecked()){ //is target plataform select windows?
645 command+=this->commandMap.value(tabTitle+"->ONI FILES->"+to+"(PC)")+" "+myOutputFolder+" "+datName; //add second command
646 }
647 else{
648 command+=this->commandMap.value(tabTitle+"->ONI FILES->"+to+"(demoPCMAC)")+" "+myOutputFolder+" "+datName; //add second command
649 }
650 }
651 }
652
653 if(ui->cbBnvLevels->isChecked()){
654
655 if(ui->leBnvLevels->text().isEmpty()){
656 showErrStatusMessage("Checkbox '"+ui->cbBnvLevels->text()+"' is selected. The BNV file cannot be empty.");
657 return "";
658 }
659 command+=" "+Util::normalizeAndQuote(ui->leBnvLevels->text());
660 }
661
662 if(ui->cbAdditionalSourcesLevels->isChecked()){
663
664 if(ui->leAdditSourcesLevels->text().isEmpty()){
665 showErrStatusMessage("Checkbox '"+ui->cbAdditionalSourcesLevels->text()+"' is selected. The source files cannot be empty.");
666 return "";
667 }
668
669 QString additionalFiles=ui->leAdditSourcesLevels->text();
670
671 int currentIndex=0, nextIndex=0;
672
673 //parse all files (separated by spaces)
674 while(true){
675 nextIndex=additionalFiles.indexOf(";",currentIndex+1);
676
677 command += " "+Util::normalizeAndQuote(additionalFiles.mid(currentIndex,(nextIndex-currentIndex)));
678
679 if(nextIndex==-1){ //we got to the end, stop parsing
680 break;
681 }
682 currentIndex=nextIndex+1; //update currentIndex +1 for start after the separator
683 }
684 }
685
686 if(ui->cbGridsLevels->isChecked()){
687 command+=GlobalVars::OniSplitProcSeparator+this->commandMap.value(tabTitle+"->"+ui->cbGridsLevels->text())+" "+Util::normalizeAndQuote(ui->leBnvLevels->text())+" "+file+" -out:"+myOutputFolder;
688 }
689
690 return command;
691 }
692
693 QString MainWindow::fileParsingMisc(QString myOutputFolder, QString from, QString to , QString file){
694 return this->commandMap.value("misc->"+from+"->"+to)+" "+myOutputFolder+" "+file;
695 }
696
697 void MainWindow::addRowTable(DropTableWidget *myTable, QString fileName, QString fromTo, QString command, bool isToDisabled){
698 //Get actual number rows
699 int twSize=myTable->rowCount();
700
701 //increase the rows for the new item
702 myTable->setRowCount(twSize+1);
703
704 //Add to table and list to
705 QTableWidgetItem *newFile = new QTableWidgetItem(fileName);
706 QTableWidgetItem *newConversion = new QTableWidgetItem(fromTo);
707 QTableWidgetItem *newCommand = new QTableWidgetItem(command);
708
709 if(isToDisabled){
710 myTable->setDisableStyleWidgetItem(newFile);
711 myTable->setDisableStyleWidgetItem(newConversion);
712 myTable->setDisableStyleWidgetItem(newCommand);
713 }
714
715 myTable->setItem(twSize,0,newFile);
716 myTable->setItem(twSize,1,newConversion);
717 myTable->setItem(twSize,2,newCommand);
718
719 myTable->updateTableToolTips(twSize); //Update tool tips
720 }
721
722 void MainWindow::on_pbConvert_clicked()
723 {
724 startConversion();
725 }
726
727 void MainWindow::startConversion(){
728
729 DropTableWidget* currTable = getCurrentTableWidget();
730
731 bool ready=false;
732 for(int i=0; i<currTable->rowCount(); i++){ //There are items to process?
733 if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
734 ready=true;
735 break;
736 }
737 }
738
739 if(!ready){
740 showErrStatusMessage("Please add sources to convert first.");
741 return;
742 }
743
744 if(this->myBar->isVisible()){
745 Util::showErrorPopUp("Another conversion is progress. Please wait until it finishes.");
746 return;
747 }
748
749 for(int i=0; i<currTable->rowCount(); i++){
750 //Only process enabled items
751 if(currTable->item(i,2)->background()!=currTable->disabledBackStyle){
752 this->listToProccess.append(currTable->item(i,2)->text());
753 }
754 }
755
756 this->myConverter->start();
757 }
758
759 void MainWindow::TsetupProgressBar(int max){
760 this->myBar->setValue(0);
761 this->myBar->show();
762 this->myBar->setMaximum(max);
763 ui->tbAbortConversion->show();
764 }
765
766 void MainWindow::TupdateProgressBar(){
767 this->myBar->setValue(this->myBar->value()+1); //more one task done
768 }
769
770 void MainWindow::TresultConversion(QString result, int numErrors){
771 QApplication::alert(this); //Show a notification if window is not active
772 this->myBar->hide();
773 ui->tbAbortConversion->hide();
774
775 if(numErrors!=0){
776 QString sNumErrors=QString::number(numErrors);
777 if(numErrors>1){
778 UtilVago::showErrorPopUpLogButton(result+"\n This is the last of "+sNumErrors+" errors.");
779 showErrStatusMessage("Something gone wrong. Check log file ("+sNumErrors+" errors).");
780 }
781 else{
782 UtilVago::showErrorPopUpLogButton(result);
783 showErrStatusMessage("Something gone wrong. Check log file.");
784 }
785 }
786 else{
787 showSuccessStatusMessage("Everything went well!");
788 }
789 }
790
791 void MainWindow::TconversionAborted(){
792 this->myBar->hide();
793 ui->tbAbortConversion->hide();
794
795 showErrStatusMessage("Conversion was aborted.");
796 }
797
798 void MainWindow::showErrStatusMessage(QString message){
799
800 QPalette myPalete = QPalette();
801 myPalete.setColor( QPalette::WindowText, QColor(255,0,0));
802 statusBar()->setPalette( myPalete );
803 ui->statusBar->showMessage(message,10000); //display by 10 seconds
804
805 }
806
807 void MainWindow::showSuccessStatusMessage(QString message){
808
809 QPalette myPalete = QPalette();
810 myPalete.setColor( QPalette::WindowText, QColor(0,150,0));
811 statusBar()->setPalette( myPalete );
812 ui->statusBar->showMessage(message,10000); //display by 10 seconds
813
814 }
815
816 void MainWindow::mapCommands(){
817 ////////////////////////////////////////////////////////////////////////XML Commands
818 this->commandMap.insert("xml->ONI->XML","-extract:xml");
819 this->commandMap.insert("xml->XML->ONI","-create");
820 //######################General Options
821
822 //Possible Combinations
823 this->commandMap.insertMulti("xml->ONI","XML");
824 this->commandMap.insertMulti("xml->XML","ONI");
825
826 ////////////////////////////////////////////////////////////////////////Textures Commands
827 this->commandMap.insert("textures->DAT / TXMP ONI->DDS","-extract:dds");
828 this->commandMap.insert("textures->DAT / TXMP ONI->TGA","-extract:tga");
829 this->commandMap.insert("textures->DAT / TXMP ONI->PNG","-extract:png");
830 this->commandMap.insert("textures->DAT / TXMP ONI->JPG","-extract:jpg");
831 this->commandMap.insert("textures->TGA / DDS / PNG / JPG->TXMP ONI","-create:txmp");
832 //######################Textures Options
833 this->commandMap.insert("textures->"+ui->rbBGR32->text(),"-format:bgr32");
834 this->commandMap.insert("textures->"+ui->rbBGRA32->text(),"-format:bgra32");
835 this->commandMap.insert("textures->"+ui->rbBGR555->text(),"-format:bgr555");
836 this->commandMap.insert("textures->"+ui->rbBGRA5551->text(),"-format:bgra5551");
837 this->commandMap.insert("textures->"+ui->rbBGRA444->text(),"-format:bgra4444");
838 this->commandMap.insert("textures->"+ui->rbDxt1->text(),"-format:dxt1");
839 this->commandMap.insert("textures->"+ui->cbMipMapsTextures->text(),"-genmipmaps");
840 this->commandMap.insert("textures->"+ui->cbNoUwrap->text(),"-nouwrap");
841 this->commandMap.insert("textures->"+ui->cbNoVwrap->text(),"-novwrap");
842 this->commandMap.insert("textures->"+ui->cbLarge->text(),"-large");
843 this->commandMap.insert("textures->"+ui->cbEnvMap->text(),"-envmap:");
844 //Possible Combinations
845 this->commandMap.insertMulti("textures->DAT / TXMP ONI","TGA");
846 this->commandMap.insertMulti("textures->DAT / TXMP ONI","DDS");
847 this->commandMap.insertMulti("textures->DAT / TXMP ONI","PNG");
848 this->commandMap.insertMulti("textures->DAT / TXMP ONI","JPG");
849 this->commandMap.insertMulti("textures->TGA / DDS / PNG / JPG","TXMP ONI");
850
851 ////////////////////////////////////////////////////////////////////////Characters Commands
852 this->commandMap.insert("characters->TRAM ONI->XML / XML & DAE","-extract:xml");
853 this->commandMap.insert("characters->TRBS / ONCC ONI->DAE","-extract:dae");
854 this->commandMap.insert("characters->TRBS XML->TRBS ONI","-create");
855 this->commandMap.insert("characters->TRBS DAE->TRBS ONI","-create:trbs");
856 this->commandMap.insert("characters->FILM DAT->XML","film2xml");
857
858 //######################Characters Options
859 this->commandMap.insert("characters->"+ui->cbWithTRBS_ONCC->text(),"-anim-body:");
860 this->commandMap.insert("characters->"+ui->cbCellShading->text(),"-cel");
861 this->commandMap.insert("characters->"+ui->cbNormals->text(),"-normals");
862 //Possible Combinations
863 this->commandMap.insertMulti("characters->TRAM ONI","XML / XML & DAE");
864 this->commandMap.insertMulti("characters->TRBS / ONCC ONI","DAE");
865 this->commandMap.insertMulti("characters->DAE","TRBS ONI");
866 this->commandMap.insertMulti("characters->TRBS DAE","TRBS ONI");
867 this->commandMap.insertMulti("characters->TRBS XML","TRBS ONI");
868 this->commandMap.insertMulti("characters->FILM DAT","XML");
869
870 ////////////////////////////////////////////////////////////////////////Objects Commands
871 this->commandMap.insert("objects->M3GM ONI->OBJ","-extract:obj");
872 this->commandMap.insert("objects->M3GM ONI->DAE","-extract:dae");
873 this->commandMap.insert("objects->ONWC ONI->OBJ","-extract:obj");
874 this->commandMap.insert("objects->ONWC ONI->DAE","-extract:dae");
875 this->commandMap.insert("objects->OBAN ONI (cam)->DAE","-extract:dae");
876 this->commandMap.insert("objects->OBJ->M3GM ONI","-create:m3gm");
877 //######################Characters Options
878 this->commandMap.insert("objects->"+ui->cbTexture->text(),"-tex:");
879 this->commandMap.insert("objects->"+ui->cbWithAnimation->text(),"-geom:");
880 //Possible Combinations
881 this->commandMap.insertMulti("objects->M3GM ONI","OBJ");
882 this->commandMap.insertMulti("objects->M3GM ONI","DAE");
883 this->commandMap.insertMulti("objects->ONWC ONI","OBJ");
884 this->commandMap.insertMulti("objects->ONWC ONI","DAE");
885 this->commandMap.insertMulti("objects->OBAN ONI (cam)","DAE");
886 this->commandMap.insertMulti("objects->OBJ","M3GM ONI");
887
888
889 ////////////////////////////////////////////////////////////////////////Levels Commands
890 this->commandMap.insert("levels->DAT->ONI FILES","-export");
891 //this->commandMap.insert("levels->ONI FILES->DAT","-import"); //Not used.
892 this->commandMap.insert("levels->ONI FILES->DAT(PC)","-import:nosep");
893 this->commandMap.insert("levels->ONI FILES->DAT(demoPCMAC)","-import:sep");
894 this->commandMap.insert("levels->AKEV ONI->DAE","-extract:dae");
895 this->commandMap.insert("levels->DAE->AKEV ONI","-create:akev");
896 this->commandMap.insert("levels->MASTER XML->DAT","-create:level");
897 this->commandMap.insert("levels->MASTER XML->ONI FILES","-create:level");
898 //######################Levels Options
899 this->commandMap.insert("levels->"+ui->cbGridsLevels->text(),"-grid:create");
900 //Possible Combinations
901 this->commandMap.insertMulti("levels->DAT","ONI FILES");
902 this->commandMap.insertMulti("levels->ONI FILES","DAT");
903 this->commandMap.insertMulti("levels->AKEV ONI","DAE");
904 this->commandMap.insertMulti("levels->DAE","AKEV ONI");
905 this->commandMap.insertMulti("levels->MASTER XML","DAT");
906 this->commandMap.insertMulti("levels->MASTER XML","ONI FILES");
907
908 ////////////////////////////////////////////////////////////////////////Misc Commands
909 this->commandMap.insert("misc->DAT / SNDD ONI->WAV","-extract:wav");
910 this->commandMap.insert("misc->DAT / SNDD ONI->AIF","-extract:aif");
911 this->commandMap.insert("misc->DAT / SUBT ONI->TXT","-extract:txt");
912 this->commandMap.insert("misc->WAV / AIF->SNDD ONI","-create");
913 this->commandMap.insert("misc->TXT->SUBT ONI","-create:subt");
914 //Possible Combinations
915 this->commandMap.insertMulti("misc->DAT / SNDD ONI","WAV");
916 this->commandMap.insertMulti("misc->DAT / SNDD ONI","AIF");
917 this->commandMap.insertMulti("misc->DAT / SUBT ONI","TXT");
918 this->commandMap.insertMulti("misc->WAV / AIF","SNDD ONI");
919 this->commandMap.insertMulti("misc->TXT","SUBT ONI");
920
921 }
922
923 void MainWindow::on_cbFromXML_currentIndexChanged(const QString &arg1)
924 {
925 updateComboBox(arg1, ui->cbToXML);
926 }
927
928
929 void MainWindow::on_cbFromTextures_currentIndexChanged(const QString &arg1)
930 {
931 updateComboBox(arg1, ui->cbToTextures);
932 }
933
934 void MainWindow::on_cbFromObjects_currentIndexChanged(const QString &arg1)
935 {
936 updateComboBox(arg1, ui->cbToObjects);
937 }
938
939 void MainWindow::on_cbFromCharacters_currentIndexChanged(const QString &arg1)
940 {
941 updateComboBox(arg1, ui->cbToCharacters);
942 }
943
944 void MainWindow::on_cbFromLevels_currentIndexChanged(const QString &arg1)
945 {
946 updateComboBox(arg1, ui->cbToLevels);
947 }
948
949 void MainWindow::on_cbFromMisc_currentIndexChanged(const QString &arg1)
950 {
951 updateComboBox(arg1, ui->cbToMisc);
952 }
953
954 void MainWindow::updateComboBox(const QString &arg1, QComboBox *comboBox){
955
956 QString identifier;
957
958 if(comboBox == ui->cbToXML){
959 identifier = ui->tabWidget->tabText(XMLTabIndex);
960 }
961 else if(comboBox == ui->cbToTextures){
962 identifier = ui->tabWidget->tabText(TexturesTabIndex);
963
964 //Options are only used for DAT/ONI -> Image
965 if(QString::compare(arg1,"DAT / ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
966 ui->gbTextures->setEnabled(false);
967 }
968 else{
969 ui->gbTextures->setEnabled(true);
970 }
971 }
972 else if(comboBox == ui->cbToCharacters){
973 identifier = ui->tabWidget->tabText(CharactersTabIndex);
974
975 ui->cbWithTRBS_ONCC->setEnabled(false);
976 ui->cbWithTRBS_ONCC->setChecked(false);
977 ui->cbCellShading->setEnabled(false);
978 ui->cbCellShading->setChecked(false);
979 ui->cbNormals->setEnabled(false);
980 ui->cbNormals->setChecked(false);
981
982 if(QString::compare(arg1,"TRAM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
983 ui->cbWithTRBS_ONCC->setEnabled(true);
984 }
985 else if(QString::compare(arg1,"TRBS DAE",Qt::CaseSensitive)==0){
986 ui->cbNormals->setEnabled(true);
987 ui->cbCellShading->setEnabled(true);
988 }
989
990 }
991 else if(comboBox == ui->cbToObjects){
992 identifier = ui->tabWidget->tabText(ObjectsTabIndex);
993
994 ui->cbTexture->setEnabled(false);
995 ui->cbTexture->setChecked(false);
996 ui->cbWithAnimation->setEnabled(false);
997 ui->cbWithAnimation->setChecked(false);
998
999 if(QString::compare(arg1,"M3GM ONI",Qt::CaseSensitive)==0){ //case sensitive is faster
1000 ui->cbWithAnimation->setEnabled(true);
1001 }
1002 else if(QString::compare(arg1,"OBJ",Qt::CaseSensitive)==0){
1003 ui->cbTexture->setEnabled(true);
1004 }
1005 }
1006 else if(comboBox == ui->cbToLevels){
1007 identifier = ui->tabWidget->tabText(LevelsTabIndex);
1008
1009 ui->cbSpecificFilesLevels->setEnabled(false);
1010 ui->cbSpecificFilesLevels->setChecked(false);
1011 ui->cbDatLevels->setEnabled(false);
1012 ui->cbDatLevels->setChecked(false);
1013 ui->cbBnvLevels->setEnabled(false);
1014 ui->cbBnvLevels->setChecked(false);
1015 ui->cbAdditionalSourcesLevels->setEnabled(false);
1016 ui->cbAdditionalSourcesLevels->setChecked(false);
1017 ui->cbGridsLevels->setEnabled(false);
1018 ui->cbGridsLevels->setChecked(false);
1019
1020 if(arg1=="DAT"){ //case sensitive is faster
1021 ui->cbSpecificFilesLevels->setEnabled(true);
1022 }
1023 else if(arg1=="ONI FILES"){ //case sensitive is faster
1024 ui->cbDatLevels->setEnabled(true);
1025 }
1026 else if(arg1=="DAE"){
1027 ui->cbBnvLevels->setEnabled(true);
1028 ui->cbAdditionalSourcesLevels->setEnabled(true);
1029 }
1030 }
1031 else{ // Misc
1032 identifier = ui->tabWidget->tabText(MiscTabIndex);
1033 }
1034
1035 identifier = identifier.toLower(); // get current tab title text (lower case)
1036
1037 comboBox->clear();
1038
1039 QStringList toUpdate=QStringList();
1040
1041 QStringList values=commandMap.values(identifier+"->"+arg1);
1042
1043 for (int i = values.size()-1; i >= 0; i--){ //By defaut MultiItems have the inversed order (http://qt-project.org/doc/qt-4.8/qhash.html#insertMulti)
1044 toUpdate << values.at(i);
1045 }
1046
1047 comboBox->addItems(toUpdate);
1048 }
1049
1050
1051 void MainWindow::on_actionWindows_triggered()
1052 {
1053 ui->actionWindows->setChecked(true);
1054 ui->actionMac_Windows_demo->setChecked(false);
1055 }
1056
1057 void MainWindow::on_actionMac_Windows_demo_triggered()
1058 {
1059 ui->actionMac_Windows_demo->setChecked(true);
1060 ui->actionWindows->setChecked(false);
1061 }
1062
1063 void MainWindow::on_pbRemoveSourceXML_clicked()
1064 {
1065 removeTableContents( ui->twSourcesXML);
1066 }
1067
1068 void MainWindow::on_pbRemoveSourceTextures_clicked()
1069 {
1070 removeTableContents(ui->twSourcesTextures);
1071 }
1072
1073 void MainWindow::on_pbRemoveSourceObjects_clicked()
1074 {
1075 removeTableContents(ui->twSourcesObjects);
1076 }
1077
1078 void MainWindow::on_pbRemoveSourceCharacters_clicked()
1079 {
1080 removeTableContents(ui->twSourcesCharacters);
1081 }
1082
1083 void MainWindow::on_pbRemoveSourceLevels_clicked()
1084 {
1085 removeTableContents(ui->twSourcesLevels);
1086 }
1087
1088 void MainWindow::on_pbRemoveSourceMisc_clicked()
1089 {
1090 removeTableContents(ui->twSourcesMisc);
1091 }
1092
1093 void MainWindow::on_pbClearSourcesXML_clicked()
1094 {
1095 clearTableContents(ui->twSourcesXML);
1096 }
1097
1098 void MainWindow::on_pbClearSourcesTextures_clicked()
1099 {
1100 clearTableContents(ui->twSourcesTextures);
1101 }
1102
1103 void MainWindow::on_pbClearSourcesObjects_clicked()
1104 {
1105 clearTableContents(ui->twSourcesObjects);
1106 }
1107
1108 void MainWindow::on_pbClearSourcesCharacters_clicked()
1109 {
1110 clearTableContents(ui->twSourcesCharacters);
1111 }
1112
1113 void MainWindow::on_pbClearSourcesLevels_clicked()
1114 {
1115 clearTableContents(ui->twSourcesLevels);
1116 }
1117
1118 void MainWindow::on_pbClearSourcesMisc_clicked()
1119 {
1120 clearTableContents(ui->twSourcesMisc);
1121 }
1122
1123 void MainWindow::removeTableContents(DropTableWidget *myTable){
1124 int size = myTable->selectionModel()->selectedRows().size();
1125
1126 QMessageBox::StandardButton defaultButton = QMessageBox::NoButton; // default button for clear asking question, only customizable in mac os
1127
1128 if(size==0){
1129 Util::showPopUp("Select a row first.");
1130 return;
1131 }
1132
1133 #ifdef Q_OS_MAC
1134 if(this->useYesAsDefaultWhenRemovingItems){
1135 defaultButton = QMessageBox::Yes;
1136 }
1137 else{
1138 defaultButton = QMessageBox::No;
1139 }
1140 #endif
1141
1142
1143 if(Util::showQuestionPopUp(this,"Are you sure you want to delete the selected rows?",defaultButton)){
1144 for(int i=0; i<size; i++){
1145 //myTable->removeRow(myTable->selectedItems().at(size-i-1)->row());
1146 myTable->removeRow(myTable->selectionModel()->selectedRows().at(size-i-1).row());
1147 }
1148 updateItemsLoaded(myTable);
1149 rowsWereChangedInDropTableWidget();
1150 }
1151 }
1152
1153 void MainWindow::clearTableContents(DropTableWidget *myTable){
1154
1155 QMessageBox::StandardButton defaultButton = QMessageBox::NoButton; // default button for clear asking question, only customizable in mac os
1156
1157 if(myTable->rowCount()==0){
1158 Util::showPopUp("Nothing to clear.");
1159 return;
1160 }
1161
1162 #ifdef Q_OS_MAC
1163 if(this->useYesAsDefaultWhenRemovingItems){
1164 defaultButton = QMessageBox::Yes;
1165 }
1166 else{
1167 defaultButton = QMessageBox::No;
1168 }
1169 #endif
1170
1171 if(Util::showQuestionPopUp(this,"Are you sure you want to clear the content?",defaultButton)){
1172 clearTableNoPrompt(myTable);
1173 updateItemsLoaded(myTable);
1174 rowsWereChangedInDropTableWidget();
1175 }
1176
1177 }
1178
1179 void MainWindow::clearTableNoPrompt(DropTableWidget *myTable){
1180 myTable->clearContents();
1181 myTable->setRowCount(0);
1182 }
1183
1184 void MainWindow::on_actionPreferences_triggered()
1185 {
1186 //Show preferences
1187 Preferences *preferencesWindow = new Preferences(this,this->vagoSettings);
1188 preferencesWindow->exec(); //it destroys itself when finished.
1189 }
1190
1191
1192 void MainWindow::closeEvent(QCloseEvent *event){
1193 if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1194 QMessageBox::StandardButton result = askToSaveCurrentProject();
1195 if(result == QMessageBox::StandardButton::Cancel){
1196 event->ignore();
1197 return;
1198 }
1199 }
1200
1201 // Exit application (this will also close all other windows which don't have parent, for instance ManualCommands)
1202 QApplication::quit();
1203 }
1204
1205 QMessageBox::StandardButton MainWindow::askToSaveCurrentProject(){
1206 QMessageBox::StandardButton result =
1207 Util::showQuestionPopUpWithCancel(this,"There are unsaved changes. Do you want to save the current project?", QMessageBox::StandardButton::Yes);
1208
1209 if(result == QMessageBox::StandardButton::Yes){
1210 on_actionSave_triggered();
1211 }
1212
1213 return result;
1214 }
1215
1216 void MainWindow::on_cbToLevels_currentIndexChanged(const QString &arg1)
1217 {
1218
1219 if(ui->cbFromLevels->currentText()=="MASTER XML" && arg1=="DAT"){
1220 ui->cbDatLevels->setEnabled(true);
1221 }
1222 else if(ui->cbFromLevels->currentText()=="MASTER XML" && arg1=="ONI FILES"){
1223 ui->cbDatLevels->setEnabled(false);
1224 ui->cbDatLevels->setChecked(false);
1225 }
1226
1227 }
1228
1229 void MainWindow::on_cbDatLevels_toggled(bool checked)
1230 {
1231 ui->leTargetDatLevels->setEnabled(checked);
1232 }
1233
1234 void MainWindow::on_cbBnvLevels_toggled(bool checked)
1235 {
1236 ui->leBnvLevels->setEnabled(checked);
1237 ui->cbGridsLevels->setEnabled(checked);
1238 ui->cbGridsLevels->setChecked(checked);
1239 if(checked && !projectIsLoading){
1240 QString file=QFileDialog::getOpenFileName(this,"Choose the BNV.dae file...","./" , "All Files (*.*)");
1241 if(!file.isEmpty()){
1242 ui->leBnvLevels->setText(file);
1243 }
1244 }
1245 }
1246
1247 void MainWindow::on_cbAdditionalSourcesLevels_toggled(bool checked)
1248 {
1249 ui->leAdditSourcesLevels->setEnabled(checked);
1250
1251 if(checked && !projectIsLoading){
1252 QStringList filesSelected=QFileDialog::getOpenFileNames(this,"Choose the additional .dae files...","./" , "All Files (*.*)");
1253 QString filesJoined;
1254 int size=filesSelected.size();
1255
1256 if(!filesSelected.isEmpty()){
1257 for(int i=0; i<size-1; i++){
1258 filesJoined+=filesSelected.at(i)+" ";
1259 }
1260 filesJoined+=filesSelected.at(size-1); //last doesn't have space after
1261 ui->leAdditSourcesLevels->setText(filesJoined);
1262 }
1263
1264 }
1265 }
1266
1267 void MainWindow::on_cbWithTRBS_ONCC_toggled(bool checked)
1268 {
1269 ui->leTRBS_ONCC->setEnabled(checked);
1270 }
1271
1272 void MainWindow::on_actionCheck_OniSplit_version_triggered()
1273 {
1274 QProcess myProcess;
1275 myProcess.setWorkingDirectory(UtilVago::getAppPath());
1276 myProcess.start(UtilVago::getOniSplitExecutable()+" -version");
1277 myProcess.waitForFinished();
1278
1279 QString result=myProcess.readAllStandardOutput();
1280
1281 Util::showPopUp("This Vago version was built with base in OniSplit version "+GlobalVars::BuiltOniSplitVersion+"\n\nCurrent version is:\n"+result.trimmed());
1282 }
1283
1284 void MainWindow::on_actionCheck_xmlTools_version_triggered()
1285 {
1286 QProcess myProcess;
1287 myProcess.setWorkingDirectory(UtilVago::getAppPath());
1288 myProcess.start(UtilVago::getXmlToolsExecutable()+" --version");
1289 myProcess.waitForFinished();
1290 QString result=myProcess.readLine();
1291
1292 Util::showPopUp("This Vago version was built with base in XmlTools version "+GlobalVars::BuiltXmlToolsVersion+"\n\nCurrent version is:\n"+result.trimmed());
1293 }
1294
1295 /**
1296 Update items loaded
1297 **/
1298 void MainWindow::on_tabWidget_currentChanged(int)
1299 {
1300 updateItemsLoaded(getCurrentTableWidget());
1301 }
1302
1303 void MainWindow::updateItemsLoaded(DropTableWidget *currentTable){
1304
1305 int numItems=currentTable->rowCount();
1306
1307 this->itemsLoaded->setText(QString().setNum(numItems)+ (numItems==1?" item ":" items ") +"loaded");
1308 }
1309
1310 void MainWindow::rowsWereChangedInDropTableWidget(){
1311 // We have changed rows, we have now unsaved changes.
1312 if(!this->unsavedChangesExist){
1313 this->unsavedChangesExist = true;
1314 setVagoWindowTitle();
1315 }
1316 }
1317
1318 void MainWindow::on_tbCommand_clicked()
1319 {
1320 //We pass no parent because we want to have an independent window for ManualCommands,
1321 //so we can minimize it or maximize indepently from the MainWindow
1322 ManualCommands *commandsWindow = new ManualCommands();
1323 commandsWindow->show(); //it destroys itself when finished.
1324 }
1325
1326 void MainWindow::on_actionWorkspace_triggered()
1327 {
1328 ui->actionWorkspace->setChecked(true);
1329 ui->actionOther->setChecked(false);
1330 this->outputFolder=this->workspaceLocation;
1331 ui->tbOpenFolder->setToolTip("Open Vago workspace");
1332 showSuccessStatusMessage("Vago is now outputting the NEW items for Vago workspace.");
1333 }
1334
1335 void MainWindow::on_actionOther_triggered()
1336 {
1337 QString newDir=QFileDialog::getExistingDirectory(this,"Choose the folder for output NEW files directly...",this->AeLocation+"/GameDataFolder");
1338 newDir=Util::normalizePath(newDir);
1339
1340 if(newDir.isEmpty()){
1341 ui->actionOther->setChecked(false);
1342 return; //do nothing
1343 }
1344
1345 if(newDir==this->workspaceLocation){
1346 on_actionWorkspace_triggered(); //set it to vago workspace
1347 return;
1348 }
1349
1350 ui->actionOther->setChecked(true);
1351 ui->actionWorkspace->setChecked(false);
1352
1353 this->outputFolder=newDir;
1354
1355 QString newDirName=Util::cutName(newDir);
1356 ui->tbOpenFolder->setToolTip("Open "+newDirName+" output folder");
1357 showSuccessStatusMessage("Vago is now outputting the NEW items for "+newDirName+".");
1358 }
1359
1360 void MainWindow::on_actionView_log_triggered()
1361 {
1362 UtilVago::openLogFile();
1363 }
1364
1365 void MainWindow::on_actionOpen_AE_folder_triggered()
1366 {
1367 QDesktopServices::openUrl(QUrl("file:///"+this->AeLocation));
1368 }
1369
1370 void MainWindow::on_actionSave_Project_triggered()
1371 {
1372
1373 QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),
1374 this->vagoSettings->value("LastProjectPath").toString(),
1375 tr("Vago project files (*.vgp)"));
1376
1377 if(!filePath.isEmpty()){
1378 saveProjectState(filePath);
1379 }
1380
1381 }
1382
1383 // New Project
1384 void MainWindow::on_actionNew_Project_triggered()
1385 {
1386 if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
1387 QMessageBox::StandardButton result = askToSaveCurrentProject();
1388 if(result == QMessageBox::StandardButton::Cancel){
1389 return;
1390 }
1391 }
1392
1393 QList<DropTableWidget*> myTables = getAllTableWidgets();
1394
1395 for(DropTableWidget* const currTable : myTables){
1396 clearTableNoPrompt(currTable);
1397 }
1398
1399 this->lastProjectFilePath=""; // clear last project file path
1400 this->unsavedChangesExist = false;
1401
1402 setVagoWindowTitle(); // update vago title
1403 }
1404
1405 void MainWindow::on_actionSave_triggered()
1406 {
1407 if(this->lastProjectFilePath.isEmpty()){
1408 on_actionSave_Project_triggered();
1409 return;
1410 }
1411
1412 saveProjectState(this->lastProjectFilePath);
1413 }
1414
1415 void MainWindow::on_actionLoad_Project_triggered()
1416 {
1417
1418 QString filePath = QFileDialog::getOpenFileName(this, tr("Load File"),
1419 this->vagoSettings->value("LastProjectPath").toString(),
1420 tr("Vago project files (*.vgp)"));
1421 if(!filePath.isEmpty()){
1422 loadProjectState(filePath);
1423 }
1424 }
1425
1426 void MainWindow::on_actionProject1_triggered()
1427 {
1428 loadProjectState(this->ui->actionProject1->text());
1429 }
1430
1431 void MainWindow::on_actionProject2_triggered()
1432 {
1433 loadProjectState(this->ui->actionProject2->text());
1434 }
1435
1436 void MainWindow::on_actionProject3_triggered()
1437 {
1438 loadProjectState(this->ui->actionProject3->text());
1439 }
1440
1441 void MainWindow::on_actionProject4_triggered()
1442 {
1443 loadProjectState(this->ui->actionProject4->text());
1444 }
1445
1446 void MainWindow::on_actionProject5_triggered()
1447 {
1448 loadProjectState(this->ui->actionProject5->text());
1449 }
1450
1451 QString MainWindow::getTypeConversion(DropTableWidget *myTable){
1452 QString from,to;
1453
1454 if(myTable==ui->twSourcesXML){
1455 from=ui->cbFromXML->currentText();
1456 to=ui->cbToXML->currentText();
1457 }
1458 else if(myTable==ui->twSourcesTextures){
1459 from=ui->cbFromTextures->currentText();
1460 to=ui->cbToTextures->currentText();
1461 }
1462 else if(myTable==ui->twSourcesObjects){
1463 from=ui->cbFromObjects->currentText();
1464 to=ui->cbToObjects->currentText();
1465 }
1466 else if(myTable==ui->twSourcesCharacters){
1467 from=ui->cbFromCharacters->currentText();
1468 to=ui->cbToCharacters->currentText();
1469 }
1470 else if(myTable==ui->twSourcesLevels){
1471 from=ui->cbFromLevels->currentText();
1472 to=ui->cbToLevels->currentText();
1473 }
1474 else{
1475 from=ui->cbFromMisc->currentText();
1476 to=ui->cbToMisc->currentText();
1477 }
1478
1479 return from + " > " + to;
1480 }
1481
1482 //Drop table widget context menu
1483 void MainWindow::dtContextMenu(DropTableWidget* myTable, QContextMenuEvent *event){
1484 QModelIndex index = myTable->indexAt(event->pos());
1485
1486 //item exists?
1487 if(!index.isValid())
1488 return;
1489
1490 if(myTable->selectionModel()->selectedRows().size()==0){ //No multiple rows selected
1491 myTable->selectRow(myTable->itemAt(event->pos())->row()); //select all the row of the item clicked
1492 }
1493
1494 QList<int> selectedRows = QList<int>();
1495
1496 foreach(QModelIndex rowItem, myTable->selectionModel()->selectedRows()){
1497 selectedRows << rowItem.row();
1498 }
1499
1500 std::unique_ptr<QMenu> menu = std::make_unique<QMenu>();
1501 std::unique_ptr<QAction> copy = std::make_unique<QAction>("Copy",myTable);
1502 std::unique_ptr<QAction> moveUp = std::make_unique<QAction>("Move Up",myTable);
1503 std::unique_ptr<QAction> moveDown = std::make_unique<QAction>("Move Down",myTable);
1504 std::unique_ptr<QAction> changeOptions = std::make_unique<QAction>("Change To Current Options",myTable);
1505 std::unique_ptr<QMenu> changeOutput = std::make_unique<QMenu>("Change Output for:");
1506 std::unique_ptr<QAction> outWorkspace = std::make_unique<QAction>("Workspace",myTable);
1507 std::unique_ptr<QAction> outCurrOutput = std::make_unique<QAction>("Current Output Folder",myTable);
1508 std::unique_ptr<QAction> outOther = std::make_unique<QAction>("Other...",myTable);
1509 std::unique_ptr<QAction> edisable = std::make_unique<QAction>("Enable/Disable",myTable);
1510
1511 menu->addAction(copy.get());
1512 menu->addSeparator();
1513 menu->addAction(moveUp.get());
1514 menu->addAction(moveDown.get());
1515 menu->addSeparator();
1516 menu->addAction(changeOptions.get());
1517 menu->addMenu(changeOutput.get());
1518 changeOutput->addActions(QList<QAction*>() << outWorkspace.get() << outCurrOutput.get() << outOther.get());
1519 menu->addAction(edisable.get());
1520
1521
1522 //if it's in the first row it can't be setted up
1523 if(selectedRows.at(0)==0){
1524 moveUp->setEnabled(false);
1525 }
1526
1527 //if we are at bottom we can't go down
1528 if(selectedRows.at(selectedRows.size()-1)==myTable->rowCount()-1){
1529 moveDown->setEnabled(false);
1530 }
1531
1532 //Can we change the settings? (the conversion must be the same)
1533 QString currentSettings = (getTypeConversion(myTable)); //call function at the mainWindow with a signal (different threads?)
1534 foreach(int row, selectedRows){
1535 if( myTable->item(row,1)->text() != currentSettings){ //If we find out any of the selected items can't be convert disable operation
1536 changeOptions->setEnabled(false);
1537 break;
1538 }
1539 }
1540
1541 QAction* selectedOption = menu->exec(event->globalPos());
1542
1543 if(selectedOption==copy.get()){
1544 //Let's copy the contents to the clipboard
1545
1546 QString toCopy;
1547
1548 int size=selectedRows.size();
1549
1550 //Let's format it a bit...
1551 for(int i=0; i<size; i++){
1552 for(int j=0; j<myTable->columnCount(); j++){
1553 toCopy+=myTable->item(selectedRows.at(i),j)->text();
1554 if(j!=myTable->columnCount()-1){
1555 toCopy+="\t";
1556 }
1557 }
1558 if(i!=size-1){
1559 toCopy+="\n";
1560 }
1561 }
1562
1563 QApplication::clipboard()->setText(toCopy);
1564 showSuccessStatusMessage(QString::number(size) + (size==1?" item ":" items ")+ "copied to the clipboard");
1565 }
1566 else if(selectedOption==moveUp.get()){
1567 qSort(selectedRows); //let's order the selections by the row number, so we know exactly how to swap it
1568 myTable->swapPositions(selectedRows,-1);
1569 rowsWereChangedInDropTableWidget();
1570 }
1571 else if(selectedOption==moveDown.get()){
1572 qSort(selectedRows);
1573 myTable->swapPositions(selectedRows,+1);
1574 rowsWereChangedInDropTableWidget();
1575 }
1576 else if(selectedOption==changeOptions.get()){
1577 changeToCurrentSettings(selectedRows,myTable);
1578 }
1579 else if(selectedOption==outWorkspace.get()){
1580 changeItemsOutput(myTable,selectedRows,this->workspaceLocation);
1581 }
1582 else if(selectedOption==outCurrOutput.get()){
1583 changeItemsOutput(myTable,selectedRows,this->outputFolder);
1584 }
1585 else if(selectedOption==outOther.get()){
1586
1587 QString newDir=QFileDialog::getExistingDirectory(this,"Choose the folder for the output of the files selected...",this->AeLocation+"/GameDataFolder");
1588 newDir=Util::normalizePath(newDir);
1589
1590 if(newDir.isEmpty()){
1591 return; //do nothing
1592 }
1593
1594 changeItemsOutput(myTable,selectedRows,newDir);
1595
1596 }
1597 else if(selectedOption==edisable.get()){
1598
1599 int enabledCount=0, disabledCount=0;
1600
1601 for(int i=0; i<selectedRows.size(); i++){
1602
1603 for(int j=0; j<myTable->columnCount(); j++){
1604 QTableWidgetItem *currentItem=myTable->item(selectedRows.at(i),j);
1605
1606 if(currentItem->background()!=myTable->disabledBackStyle){
1607 myTable->setDisableStyleWidgetItem(currentItem);
1608 if(j==0){ //Only count the row, not the columns
1609 disabledCount++;
1610 }
1611 }
1612 else{ //reset to initial state (enable)
1613 myTable->resetStyleWidgetItem(currentItem);
1614 if(j==0){
1615 enabledCount++;
1616 }
1617 }
1618 }
1619 }
1620
1621 QString result;
1622
1623 if(enabledCount!=0){
1624 result+=QString::number(enabledCount) + (enabledCount==1?" item ":" items ") + "Enabled";
1625 }
1626 if(enabledCount!=0 && disabledCount!=0){
1627 result+=" and ";
1628 }
1629 if(disabledCount!=0){
1630 result+=QString::number(disabledCount) + (disabledCount==1?" item ":" items ") + "Disabled";
1631 }
1632
1633 rowsWereChangedInDropTableWidget();
1634 showSuccessStatusMessage(result);
1635 }
1636 }
1637
1638 void MainWindow::changeToCurrentSettings(QList<int> rows, DropTableWidget* myTable){
1639 //construct a command for each one
1640 //Output a status message saying the number of changed files
1641 QString fromTo=getTypeConversion(myTable);
1642 QString from = QString(fromTo).remove(fromTo.indexOf(" >"),fromTo.size()-1); //parse the string to get the from, only 1 time parsed by each group of files = very fast
1643 QString to = QString(fromTo).remove(0,fromTo.lastIndexOf("> ")+2); //+2 to start after "> "
1644
1645 QString command;
1646
1647 foreach(int row, rows){
1648
1649 command=getCommand(myTable,getFileOutputFolder(fromTo,myTable->getOutputAbsolute(row)),from,to,myTable->getFileAbsolute(row));
1650
1651 if(command.isEmpty()){ //something wrong was happening (not inputted a texture name?)
1652 return; //stop changing settings
1653 }
1654
1655 myTable->item(row,2)->setText(command); //update settings to the current row
1656 myTable->updateTableToolTips(row);
1657 }
1658
1659 rowsWereChangedInDropTableWidget();
1660 showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed to the current settings");
1661 }
1662
1663 void MainWindow::changeItemsOutput(DropTableWidget* myTable, QList<int> rows, QString newOutput){
1664
1665 QString command, currentAbsoluteFile, fromTo, from, to;
1666
1667 foreach(int row, rows){ //No optimization possible here, commands may be different
1668 fromTo=myTable->item(row,1)->text();
1669 from = QString(fromTo).remove(fromTo.indexOf(" >"),fromTo.size()-1); //parse the string to get the from
1670 to = QString(fromTo).remove(0,fromTo.lastIndexOf("> ")+2); //+2 to start after "> "
1671
1672 currentAbsoluteFile=myTable->getFileAbsolute(row);
1673 command=getCommand(myTable,getFileOutputFolder(fromTo,newOutput),from,to,currentAbsoluteFile);
1674
1675 if(command.isEmpty()){ //something wrong was happening (not inputted a texture name?)
1676 return; //stop changing output
1677 }
1678
1679 myTable->item(row,2)->setText(command); //update command to the current row
1680 myTable->updateTableToolTips(row);
1681 }
1682
1683 rowsWereChangedInDropTableWidget();
1684 showSuccessStatusMessage(QString::number(rows.size()) + (rows.size()==1?" item ":" items ")+ "changed the output to "+(newOutput!=this->workspaceLocation?Util::cutName(newOutput):"Vago workspace"));
1685 }
1686
1687 QString MainWindow::getCommand(DropTableWidget* myTable, QString myOutputFolder, QString from, QString to , QString file){
1688
1689 QString tabTitle=ui->tabWidget->tabText(ui->tabWidget->currentIndex()).toLower(); // get current tab title
1690
1691 if(myTable==ui->twSourcesXML){ //So we only need to parse one command.
1692 return fileParsingXML(tabTitle, myOutputFolder,from,to,file);
1693 }
1694 else if(myTable==ui->twSourcesTextures){
1695 return fileParsingTextures(tabTitle, myOutputFolder,from,to,file);
1696 }
1697 else if(myTable==ui->twSourcesObjects){
1698 return fileParsingObjects(tabTitle, myOutputFolder,from,to,file);
1699 }
1700 else if(myTable==ui->twSourcesCharacters){
1701 return fileParsingCharacters(tabTitle, myOutputFolder,from,to,file);
1702 }
1703 else if(myTable==ui->twSourcesLevels){
1704 return fileParsingLevels(tabTitle, myOutputFolder,from,to,file);
1705 }
1706 else{
1707 return fileParsingMisc(myOutputFolder,from,to,file);
1708 }
1709
1710 }
1711
1712 void MainWindow::connectSlots(){
1713
1714 //This signal is for thread that is working setup the progress bar (make it visible and set it's min-max)
1715 connect(myConverter, SIGNAL(setupPB(int)), this, SLOT(TsetupProgressBar(int)), Qt::BlockingQueuedConnection);
1716
1717 //This signal is for thread that is working can update the progress bar of the gui
1718 connect(myConverter, SIGNAL(taskDone()), this, SLOT(TupdateProgressBar()),Qt::BlockingQueuedConnection);
1719
1720 //This signal is for thread that is working can show the result of a conversion
1721 connect(myConverter, SIGNAL(resultConversion(QString,int)), this, SLOT(TresultConversion(QString,int)));
1722
1723 //This signal is for thread that is working notify the gui thread that the conversion was aborted with sucess
1724 connect(myConverter, SIGNAL(conversionAborted()), this, SLOT(TconversionAborted()));
1725
1726 // This signal is to the user be able to terminate a conversion (OniSplit process in class myConverter will be terminated)
1727 connect(this, SIGNAL(terminateCurrProcess()), myConverter, SLOT(terminateCurrProcess()));
1728
1729 //Drop signal for General table
1730 connect(ui->twSourcesXML, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1731
1732 //Drop signal for Textures table
1733 connect(ui->twSourcesTextures, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1734
1735 //Drop signal for Objects table
1736 connect(ui->twSourcesObjects, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1737
1738 //Drop signal for Characters table
1739 connect(ui->twSourcesCharacters, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1740
1741 //Drop signal for Levels table
1742 connect(ui->twSourcesLevels, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1743
1744 //Drop signal for Misc table
1745 connect(ui->twSourcesMisc, SIGNAL(dropped(DropTableWidget*,QStringList)), this, SLOT(addFilesSource(DropTableWidget*,QStringList)));
1746
1747 //Context menu for General table
1748 connect(ui->twSourcesXML, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1749
1750 //Context menu for Textures table
1751 connect(ui->twSourcesTextures, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1752
1753 //Context menu for Objects table
1754 connect(ui->twSourcesObjects, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1755
1756 //Context menu for Characters table
1757 connect(ui->twSourcesCharacters, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1758
1759 //Context menu for Levels table
1760 connect(ui->twSourcesLevels, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1761
1762 //Context menu for Misc table
1763 connect(ui->twSourcesMisc, SIGNAL(dtContextMenu(DropTableWidget*,QContextMenuEvent*)), this, SLOT(dtContextMenu(DropTableWidget*,QContextMenuEvent*)));
1764 }
1765
1766 void MainWindow::saveProjectState(const QString &filePath)
1767 {
1768
1769 QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
1770
1771 pugi::xml_document doc;
1772
1773 pugi::xml_node rootNode = doc.append_child("VagoProject");
1774 rootNode.append_attribute("vagoVersion").set_value(GlobalVars::LastCompatibleVersion.toUtf8().constData());
1775
1776 foreach(DropTableWidget* const &myTable, tableWidgets){
1777 saveProjectWidget(rootNode, myTable);
1778 }
1779
1780 if(!doc.save_file(filePath.toUtf8().constData(), PUGIXML_TEXT("\t"), pugi::format_default | pugi::format_write_bom, pugi::xml_encoding::encoding_utf8)){
1781 UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while trying to save the project file. Please try another path.");
1782 return;
1783 }
1784
1785 this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
1786
1787 this->lastProjectFilePath = filePath;
1788 this->unsavedChangesExist = false;
1789
1790 addNewRecentProject(filePath);
1791
1792 setVagoWindowTitle();
1793
1794 showSuccessStatusMessage("Project saved sucessfully.");
1795 }
1796
1797 void MainWindow::saveProjectWidget(pugi::xml_node &rootNode, DropTableWidget* table)
1798 {
1799 QString from;
1800 QString to;
1801 QString tabName = getTabNameByTableWidget(table);
1802
1803 pugi::xml_node currentNodeTable = rootNode.append_child("tempName");
1804 pugi::xml_node options;
1805
1806 if(table==ui->twSourcesXML){ //So we only need to parse one command.
1807 from = ui->cbFromXML->currentText().toUtf8().constData();
1808 to = ui->cbToXML->currentText().toUtf8().constData();
1809 }
1810 else if(table==ui->twSourcesTextures){
1811 from = ui->cbFromTextures->currentText().toUtf8().constData();
1812 to = ui->cbToTextures->currentText().toUtf8().constData();
1813 options = currentNodeTable.append_child("Options");
1814 options.append_attribute("type").set_value(Util::qStrToCstr(getTextureRBCheckedTypeTexture()->text()));
1815 options.append_attribute("genMipMaps").set_value(Util::boolToCstr(ui->cbMipMapsTextures->isChecked()));
1816 options.append_attribute("noUwrap").set_value(Util::boolToCstr(ui->cbNoUwrap->isChecked()));
1817 options.append_attribute("noVwrap").set_value(Util::boolToCstr(ui->cbNoVwrap->isChecked()));
1818 options.append_attribute("large").set_value(Util::boolToCstr(ui->cbLarge->isChecked()));
1819 options.append_attribute("envMap").set_value(Util::boolToCstr(ui->cbEnvMap->isChecked()));
1820 options.append_attribute("envMapValue").set_value(Util::qStrToCstr(ui->leEnvMapTexture->text()));
1821 }
1822 else if(table==ui->twSourcesCharacters){
1823 from = ui->cbFromCharacters->currentText().toUtf8().constData();
1824 to = ui->cbToCharacters->currentText().toUtf8().constData();
1825 options = currentNodeTable.append_child("Options");
1826 options.append_attribute("cellShading").set_value(Util::boolToCstr(ui->cbCellShading->isChecked()));
1827 options.append_attribute("normals").set_value(Util::boolToCstr(ui->cbNormals->isChecked()));
1828 options.append_attribute("extractTRBSONCC").set_value(Util::boolToCstr(ui->cbWithTRBS_ONCC->isChecked()));
1829 options.append_attribute("extractTRBSONCCValue").set_value(Util::qStrToCstr(ui->leTRBS_ONCC->text()));
1830 }
1831 else if(table==ui->twSourcesObjects){
1832 from = ui->cbFromObjects->currentText().toUtf8().constData();
1833 to = ui->cbToObjects->currentText().toUtf8().constData();
1834 options = currentNodeTable.append_child("Options");
1835 options.append_attribute("texture").set_value(Util::boolToCstr(ui->cbTexture->isChecked()));
1836 options.append_attribute("textureValue").set_value(Util::qStrToCstr(ui->leTextureName->text()));
1837 options.append_attribute("withAnimation").set_value(Util::boolToCstr(ui->cbWithAnimation->isChecked()));
1838 options.append_attribute("withAnimationValue").set_value(Util::qStrToCstr(ui->leAnimationName->text()));
1839 }
1840 else if(table==ui->twSourcesLevels){
1841 from = ui->cbFromLevels->currentText().toUtf8().constData();
1842 to = ui->cbToLevels->currentText().toUtf8().constData();
1843 options = currentNodeTable.append_child("Options");
1844 options.append_attribute("extractWithFiles").set_value(Util::boolToCstr(ui->cbSpecificFilesLevels->isChecked()));
1845 options.append_attribute("extractWithFilesValue").set_value(Util::qStrToCstr(ui->leSpecificFilesLevels->text()));
1846 options.append_attribute("datFilename").set_value(Util::boolToCstr(ui->cbDatLevels->isChecked()));
1847 options.append_attribute("datFilenameValue").set_value(Util::qStrToCstr(ui->leTargetDatLevels->text()));
1848 options.append_attribute("bnvSource").set_value(Util::boolToCstr(ui->cbBnvLevels->isChecked()));
1849 options.append_attribute("bnvSourceValue").set_value(Util::qStrToCstr(ui->leBnvLevels->text()));
1850 options.append_attribute("generateGrids").set_value(Util::boolToCstr(ui->cbGridsLevels->isChecked()));
1851 options.append_attribute("additionalSources").set_value(Util::boolToCstr(ui->cbAdditionalSourcesLevels->isChecked()));
1852 options.append_attribute("additionalSourcesValue").set_value(Util::qStrToCstr(ui->leAdditSourcesLevels->text()));
1853 }
1854 else{
1855 from = ui->cbFromMisc->currentText().toUtf8().constData();
1856 to = ui->cbToMisc->currentText().toUtf8().constData();
1857 }
1858
1859 currentNodeTable.set_name(tabName.toUtf8().constData());
1860
1861 currentNodeTable.append_attribute("from").set_value(from.toUtf8().constData());
1862 currentNodeTable.append_attribute("to").set_value(to.toUtf8().constData());
1863
1864
1865 for(int i=0; i<table->rowCount(); i++){
1866
1867 QString currFileFolder = table->item(i,0)->text();
1868 QString currFromTo = table->item(i,1)->text();
1869 QString currCommand = table->item(i,2)->text();
1870
1871 pugi::xml_node currentRow = currentNodeTable.append_child("Row");
1872
1873
1874 currentRow.append_attribute("fileFolder").set_value(Util::qStrToCstr(currFileFolder));
1875 currentRow.append_attribute("fromTo").set_value(Util::qStrToCstr(currFromTo));
1876 currentRow.append_attribute("command").set_value(Util::qStrToCstr(currCommand));
1877
1878 if(table->item(i,2)->background()==table->disabledBackStyle){
1879 currentRow.append_attribute("disabled").set_value(true);
1880 }
1881
1882 }
1883 }
1884
1885 QRadioButton* MainWindow::getTextureRBCheckedTypeTexture()
1886 {
1887 if(ui->rbBGR32->isChecked()){
1888 return ui->rbBGR32;
1889 }
1890 else if(ui->rbBGRA32->isChecked()){
1891 return ui->rbBGRA32;
1892 }
1893 else if(ui->rbBGR555->isChecked()){
1894 return ui->rbBGR555;
1895 }
1896 else if(ui->rbBGRA5551->isChecked()){
1897 return ui->rbBGRA5551;
1898 }
1899 else if(ui->rbBGRA444->isChecked()){
1900 return ui->rbBGRA444;
1901 }
1902 else{ //dxt1 checked
1903 return ui->rbDxt1;
1904 }
1905 }
1906
1907 QRadioButton* MainWindow::getTextureRBTypeTextureByName(const QString &texType)
1908 {
1909 if(QString::compare(texType,ui->rbBGR32->text(),Qt::CaseSensitive)==0){
1910 return ui->rbBGR32;
1911 }
1912 else if(QString::compare(texType,ui->rbBGRA32->text(),Qt::CaseSensitive)==0){
1913 return ui->rbBGRA32;
1914 }
1915 else if(QString::compare(texType, ui->rbBGR555->text(),Qt::CaseSensitive)==0){
1916 return ui->rbBGR555;
1917 }
1918 else if(QString::compare(texType,ui->rbBGRA5551->text(),Qt::CaseSensitive)==0){
1919 return ui->rbBGRA5551;
1920 }
1921 else if(QString::compare(texType,ui->rbBGRA444->text(),Qt::CaseSensitive)==0){
1922 return ui->rbBGRA444;
1923 }
1924 else{ //dxt1
1925 return ui->rbDxt1;
1926 }
1927
1928 }
1929
1930 void MainWindow::setVagoWindowTitle(){
1931
1932 QString vagoTitle = "Vago v"+GlobalVars::AppVersion + " - ";
1933
1934 if(this->lastProjectFilePath.isEmpty()){
1935 vagoTitle += "Untitled";
1936 }
1937 else{
1938 vagoTitle += Util::cutNameWithoutBackSlash(this->lastProjectFilePath);
1939 }
1940
1941 if(this->unsavedChangesExist){
1942 vagoTitle += "*";
1943 }
1944
1945 setWindowTitle(vagoTitle);
1946 }
1947
1948 DropTableWidget* MainWindow::getCurrentTableWidget(){
1949
1950 return getTableWidgetByTabName(ui->tabWidget->tabText(ui->tabWidget->currentIndex()));
1951
1952 }
1953
1954 DropTableWidget* MainWindow::getTableWidgetByTabName(const QString &tabName){
1955
1956 if(tabName.compare("XML",Qt::CaseSensitive)==0){ //case sentive is faster
1957 return ui->twSourcesXML;
1958 }
1959 else if(tabName.compare("Textures",Qt::CaseSensitive)==0){
1960 return ui->twSourcesTextures;
1961 }
1962 else if(tabName.compare("Characters",Qt::CaseSensitive)==0){
1963 return ui->twSourcesCharacters;
1964 }
1965 else if(tabName.compare("Objects",Qt::CaseSensitive)==0){
1966 return ui->twSourcesObjects;
1967 }
1968 else if(tabName.compare("Levels",Qt::CaseSensitive)==0){
1969 return ui->twSourcesLevels;
1970 }
1971 else{
1972 return ui->twSourcesMisc;
1973 }
1974
1975 }
1976
1977 QString MainWindow::getCurrentTabName(){
1978 return ui->tabWidget->tabText(ui->tabWidget->currentIndex());
1979 }
1980
1981 QString MainWindow::getTabNameByTableWidget(DropTableWidget* table){
1982
1983 if(table == ui->twSourcesXML){
1984 return ui->tabWidget->tabText(XMLTabIndex);
1985 }
1986 else if(table == ui->twSourcesTextures){
1987 return ui->tabWidget->tabText(TexturesTabIndex);
1988 }
1989 else if(table == ui->twSourcesCharacters){
1990 return ui->tabWidget->tabText(CharactersTabIndex);
1991 }
1992 else if(table == ui->twSourcesObjects){
1993 return ui->tabWidget->tabText(ObjectsTabIndex);
1994 }
1995 else if(table == ui->twSourcesLevels){
1996 return ui->tabWidget->tabText(LevelsTabIndex);
1997 }
1998 else{
1999 return ui->tabWidget->tabText(MiscTabIndex);
2000 }
2001
2002 }
2003
2004 QList<DropTableWidget*> MainWindow::getAllTableWidgets()
2005 {
2006 QList<DropTableWidget*> tableWidgets;
2007
2008 tableWidgets << ui->twSourcesXML << ui->twSourcesTextures << ui->twSourcesCharacters
2009 << ui->twSourcesObjects << ui->twSourcesLevels << ui->twSourcesMisc;
2010
2011 return tableWidgets;
2012 }
2013
2014 void MainWindow::loadProjectState(const QString &filePath)
2015 {
2016
2017 this->projectIsLoading = true;
2018
2019 if(this->vagoSettings->value("AskSaveProject").toBool() && this->unsavedChangesExist){
2020 QMessageBox::StandardButton result = askToSaveCurrentProject();
2021 if(result == QMessageBox::StandardButton::Cancel){
2022 this->projectIsLoading = false;
2023 return;
2024 }
2025 }
2026
2027 QString statusError = "Couldn't load project.";
2028
2029 pugi::xml_document doc;
2030
2031 pugi::xml_parse_result result = doc.load_file(Util::qStrToCstr(filePath));
2032
2033 if(result.status!=pugi::status_ok){
2034 UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "An error ocurred while loading project file.\n" + QString(result.description()));
2035 showErrStatusMessage(statusError);
2036 this->projectIsLoading = false;
2037 return;
2038 }
2039
2040
2041 if(QString(doc.root().first_child().name()) != "VagoProject"){
2042 UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, QString(doc.root().name()) + "The file opened is not a valid VagoProject file. Load aborted.");
2043 showErrStatusMessage(statusError);
2044 this->projectIsLoading = false;
2045 return;
2046 }
2047
2048 QString projVagoVersion;
2049
2050 try{
2051 projVagoVersion = QString(doc.select_node("/VagoProject/@vagoVersion").attribute().value());
2052 }
2053 catch (const pugi::xpath_exception& e)
2054 {
2055 UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't find the vagoVersion of the current project. Load aborted.\n" + QString(e.what()));
2056 showErrStatusMessage(statusError);
2057 this->projectIsLoading = false;
2058 return;
2059 }
2060
2061 if(!projVagoVersion.startsWith(GlobalVars::LastCompatibleVersion)){
2062 UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "The project that you are trying to load seems it is not compatible with your Vago Version. Please update Vago and try again.");
2063 showErrStatusMessage(statusError);
2064 this->projectIsLoading = false;
2065 return;
2066 }
2067
2068 // After the initial validations begin loading the project data
2069
2070 QList<DropTableWidget*> tableWidgets = getAllTableWidgets();
2071
2072 try{
2073 foreach(DropTableWidget* const &myTable, tableWidgets){
2074 loadProjectWidget(doc, myTable);
2075 }
2076 }
2077 catch(const std::exception& e){
2078 UtilVago::showAndLogErrorPopUpLogButton(this->myLogger, "Couldn't load the vago project. Error: " + QString(e.what()));
2079 showErrStatusMessage(statusError);
2080 this->projectIsLoading = false;
2081 return;
2082 }
2083
2084 this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2085
2086 this->lastProjectFilePath = filePath;
2087 this->unsavedChangesExist = false;
2088
2089 addNewRecentProject(filePath);
2090
2091 setVagoWindowTitle();
2092
2093 this->projectIsLoading = false;
2094
2095 showSuccessStatusMessage("Project loaded sucessfully.");
2096 }
2097
2098
2099 void MainWindow::loadProjectWidget(pugi::xml_document &doc, DropTableWidget* table)
2100 {
2101 QString tabName = getTabNameByTableWidget(table);
2102 QString from (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@from")).attribute().value());
2103 QString to (doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/@to")).attribute().value());
2104
2105 if(table==ui->twSourcesXML){
2106 ui->cbFromXML->setCurrentText(from);
2107 on_cbFromXML_currentIndexChanged(from);
2108 ui->cbToXML->setCurrentText(to);
2109 }
2110 else if(table==ui->twSourcesTextures){
2111 //ui->cbFromTextures->setCurrentText(from);
2112 on_cbFromTextures_currentIndexChanged(from);
2113 ui->cbToTextures->setCurrentText(to);
2114
2115 getTextureRBTypeTextureByName((doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@type")).attribute().value()))->setChecked(true);
2116 ui->cbMipMapsTextures->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@genMipMaps")).attribute().as_bool());
2117 ui->cbNoUwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noUwrap")).attribute().as_bool());
2118 ui->cbNoVwrap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@noVwrap")).attribute().as_bool());
2119 ui->cbLarge->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@large")).attribute().as_bool());
2120 ui->cbEnvMap->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMap")).attribute().as_bool());
2121 ui->leEnvMapTexture->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@envMapValue")).attribute().value()));
2122 }
2123 else if(table==ui->twSourcesCharacters){
2124 ui->cbFromCharacters->setCurrentText(from);
2125 on_cbFromCharacters_currentIndexChanged(from);
2126 ui->cbToCharacters->setCurrentText(to);
2127
2128
2129 ui->cbCellShading->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@cellShading")).attribute().as_bool());
2130 ui->cbNormals->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@normals")).attribute().as_bool());
2131 ui->cbWithTRBS_ONCC->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCC")).attribute().as_bool());
2132 ui->leTRBS_ONCC->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractTRBSONCCValue")).attribute().value()));
2133 }
2134 else if(table==ui->twSourcesObjects){
2135 ui->cbFromObjects->setCurrentText(from);
2136 on_cbFromObjects_currentIndexChanged(from);
2137 ui->cbToObjects->setCurrentText(to);
2138
2139 ui->cbTexture->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@texture")).attribute().as_bool());
2140 ui->leTextureName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@textureValue")).attribute().value()));
2141 ui->cbWithAnimation->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimation")).attribute().as_bool());
2142 ui->leAnimationName->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@withAnimationValue")).attribute().value()));
2143 }
2144 else if(table==ui->twSourcesLevels){
2145 ui->cbFromLevels->setCurrentText(from);
2146 on_cbFromLevels_currentIndexChanged(from);
2147 ui->cbToLevels->setCurrentText(to);
2148
2149 ui->cbSpecificFilesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFiles")).attribute().as_bool());
2150 ui->leSpecificFilesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@extractWithFilesValue")).attribute().value()));
2151 ui->cbDatLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilename")).attribute().as_bool());
2152 ui->leTargetDatLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@datFilenameValue")).attribute().value()));
2153 ui->cbBnvLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSource")).attribute().as_bool());
2154 ui->leBnvLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@bnvSourceValue")).attribute().value()));
2155 ui->cbGridsLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@generateGrids")).attribute().as_bool());
2156 ui->cbAdditionalSourcesLevels->setChecked(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSources")).attribute().as_bool());
2157 ui->leAdditSourcesLevels->setText(QString(doc.select_node(Util::qStrToCstr("/VagoProject/"+tabName+"/Options/@additionalSourcesValue")).attribute().value()));
2158 }
2159 else{
2160 ui->cbFromMisc->setCurrentText(from);
2161 on_cbFromMisc_currentIndexChanged(from);
2162 ui->cbToMisc->setCurrentText(to);
2163 }
2164
2165 // Clean previous rows
2166 clearTableNoPrompt(table);
2167
2168 for(const pugi::xpath_node &xPathNode : doc.select_nodes(Util::qStrToCstr("/VagoProject/"+tabName+"/Row"))){
2169 pugi::xml_node currNode = xPathNode.node();
2170
2171 QString currFileFolder = currNode.attribute("fileFolder").value();
2172 QString currFromTo = currNode.attribute("fromTo").value();
2173 QString currCommand = currNode.attribute("command").value();
2174
2175 bool isToDisable = false;
2176 pugi::xml_attribute disabledAttr = currNode.attribute("disabled");
2177 isToDisable = disabledAttr.empty() ? false : disabledAttr.as_bool();
2178
2179 addRowTable(table,currFileFolder,currFromTo,currCommand, isToDisable);
2180 }
2181 }
2182
2183 void MainWindow::saveRecentProjects(){
2184 for(int i=0; i<this->recentProjectsList.size(); i++){
2185 this->vagoSettings->setValue("RecentProject" + QString::number(i+1), recentProjectsList[i]);
2186 }
2187 }
2188
2189 void MainWindow::loadRecentProjects(){
2190 for(int i=0; i<this->recentProjectsMaxSize; i++){
2191
2192 QString currProj = this->vagoSettings->value("RecentProject" + QString::number(i+1)).toString();
2193
2194 if(!currProj.isEmpty()){
2195 recentProjectsList.append(currProj);
2196 }
2197 else{
2198 break;
2199 }
2200 }
2201
2202 reloadRecentProjectsMenu();
2203
2204 }
2205
2206 void MainWindow::addNewRecentProject(const QString &filePath){
2207
2208 // If the new project is equal to the last one simply ignore
2209 if(filePath == this->vagoSettings->value("RecentProject1").toString()){
2210 return;
2211 }
2212
2213 // If the item already exists in our list remove it, so it can go to the top again
2214 for(auto it = this->recentProjectsList.begin(); it != this->recentProjectsList.end();){
2215 if(*it == filePath){
2216 it = this->recentProjectsList.erase(it);
2217 }
2218 else{
2219 it++;
2220 }
2221 }
2222
2223 // if we gonna overflow our list, remove the older item to reserve space to the new one
2224 if(this->recentProjectsList.size()==this->recentProjectsMaxSize){
2225 this->recentProjectsList.removeLast();
2226 }
2227
2228 this->vagoSettings->setValue("LastProjectPath",QFileInfo(filePath).absoluteDir().path());
2229
2230 // add new recent file
2231 this->recentProjectsList.prepend(filePath);
2232
2233 reloadRecentProjectsMenu();
2234
2235 saveRecentProjects();
2236 }
2237
2238 void MainWindow::reloadRecentProjectsMenu(){
2239
2240 ui->menuRecent_Projects->setEnabled(false);
2241 ui->actionProject1->setVisible(false);
2242 ui->actionProject2->setVisible(false);
2243 ui->actionProject3->setVisible(false);
2244 ui->actionProject4->setVisible(false);
2245 ui->actionProject5->setVisible(false);
2246
2247 {
2248 QList<QString>::const_iterator it;
2249 int i;
2250 for(it = recentProjectsList.cbegin(), i=0; it != recentProjectsList.cend(); it++, i++){
2251
2252 QAction* currAction = nullptr;
2253
2254 switch (i){
2255 case 0:
2256 currAction = ui->actionProject1;
2257 break;
2258 case 1:
2259 currAction = ui->actionProject2;
2260 break;
2261 case 2:
2262 currAction = ui->actionProject3;
2263 break;
2264 case 3:
2265 currAction = ui->actionProject4;
2266 break;
2267 case 4:
2268 currAction = ui->actionProject5;
2269 break;
2270 }
2271
2272 if(currAction){
2273 ui->menuRecent_Projects->setEnabled(true);
2274 currAction->setText(*it);
2275 currAction->setVisible(true);
2276 }
2277 }
2278 }
2279
2280 }