Project Documentation Manager BRIGADOON-0002
Project Documentation Manager
Loading...
Searching...
No Matches
worker.cpp
Go to the documentation of this file.
1#include "worker.h"
3#include "readprojectinfo.h"
4#include <QProcess>
5#include <QSqlQuery>
6
8
9Worker::Worker(QObject *parent)
10 : QObject{parent}
11{
12 // Define the List of Source Directories of Containing Possible Documentation or Source Files
13 // Documentation files are composed exclussively of .dox files along with .dia files and .uml
14 // files.
15
16 docs_filter << "*.dox" << "Doxyfile" << "footer.html" << "header.html" << "customdoxygen.css" << "*.dia" << "*.uml" << "*.txt" << "*.pdf" << "*.doc" << "*.docx" << "*.tcw" << "*.tct" << "*.dwg" ;
17
18 source_dirs << "autoinstall" << "autosrc";
19 source_filter << "*.c" << "*.cpp" << "*.h" << ".hpp" << "*.ui" << "*.pro" << "*.pro.user" << "*.qrc" << "*.php" << "*.php" << "*.php4" << "*.php5" << "*.py" << "*.f" << "*.for" << "*.js" << "*.sh" << "*.sql";
20
21 all_filter << "*";
22
23 leadin_string = "[#";
24 leadout_string = "#]";
25}
26
27void Worker::LogAdd(LOGGING_SEVERITY Severity, LOGGING_MODE Mode, const QString Message)
28{
29 REMOTE_LOG_ENTRY log_entry;
30 log_entry.Severity = Severity;
31 log_entry.Mode = Mode;
32 log_entry.Message = Message;
33 emit SendLogEntry(log_entry);
34}
35
36
38{
39 LogAdd( LOG_INFO, MODE_THREAD, QString("Project %1 documentation processing started in Thread.").arg(ProjectInfo->ProjectDesc.ProjectIdent) );
40 docs_dirs.clear(); docs_dirs << "defaults";
41 autodoc_dir = "/autodocs/";
42
43 switch (ProjectInfo->TargetFamilyInfo.TargetFamilyIndex)
44 {
46 autodoc_dir += "not_defined";
47 break;
48
50 autodoc_dir += "open_sim_project";
51 break;
52
54 autodoc_dir += "open_sim_script";
55 break;
56
57 case TARGET_SOFTWARE:
58 autodoc_dir += "software";
59 break;
60
61 case TARGET_HARDWARE:
62 autodoc_dir += "hardware";
63 break;
64
66 autodoc_dir += "development";
67 break;
68
70 autodoc_dir += "documentation";
71 break;
72 }
74
75 if (PreProcessProject(ProjectInfo))
76 {
77 DoDoxygen(ProjectInfo);
78 }
79
80 // Create the Source Archive
81 if (project_opts_manager->CheckCreateSourceArchive(ProjectInfo->ProjectDesc.ProjectOptions))
82 {
83 CreateSourceArchive(ProjectInfo);
84 }
85
86 // Create the Installation Script, if required
87 if (project_opts_manager->CheckAutomaticInstall(ProjectInfo->ProjectDesc.ProjectOptions))
88 {
89 CreateInstallScript(ProjectInfo);
90 }
91
92 // Finish Off
93 LogAdd( LOG_INFO, MODE_THREAD, QString("Project %1 documentation processing ended in Thread.").arg(ProjectInfo->ProjectDesc.ProjectIdent) );
94 emit WorkDone (ProjectInfo);
95}
96
98{
99 QString project_ident = ProjectInfo->ProjectDesc.ProjectIdent;
100 // Generate the Doxygen Documentation
101 QProcess doxygen;
102 doxygen.start("doxygen", QStringList() << ProjectInfo->ProjectDesc.ProjectDirectory + "/source/" + ProjectInfo->ProjectDesc.ExeName + QString( "/Doxyfile" ) );
103
104 if (!doxygen.waitForStarted())
105 {
106 LogAdd( LOG_ERROR, MODE_THREAD, QString("Doxygen did NOT Start for Project %1.").arg(project_ident) );
107 }
108 else
109 {
110 LogAdd( LOG_DEBUG, MODE_THREAD, QString("Started Doxygen Process for Project %1.").arg(project_ident) );
111 }
112
113 doxygen.closeWriteChannel();
114 if (!doxygen.waitForFinished( 480000 )) // Maximum of 8 minutes.
115 {
116 LogAdd( LOG_ERROR, MODE_THREAD, QString("Doxygen did NOT end for Project %1.").arg(project_ident) );
117 ProjectInfo->ExecutionStatus = EXECUTION_FAILURE;
118 }
119 else
120 {
121 // Copy the Doxygen Log File into the Web Directory for Later Use.
122 QString source_file = ProjectInfo->ProjectDesc.ProjectDirectory + "/scratch/" + DOXY_LOG_FILE;
123 QString dest_directory = ProjectInfo->ProgramInformation.PrimaryWebsiteDirectory + "/projects/" + ProjectInfo->ProjectDesc.ProjectIdent + "/html/";
124 QFile file(source_file);
125 if (file.copy(dest_directory + DOXY_LOG_FILE))
126 {
127 LogAdd( LOG_DEBUG, MODE_THREAD, QString("Project %1 doxygen log file copied to web directory").arg(ProjectInfo->ProjectDesc.ProjectIdent));
128 }
129 else
130 {
131 LogAdd( LOG_ERROR, MODE_THREAD, QString("Project %1 doxygen log file NOT copied to web directory").arg(ProjectInfo->ProjectDesc.ProjectIdent));
132 }
133
134 LogAdd( LOG_DEBUG, MODE_THREAD, QString("Doxygen finished for Project %1.").arg(project_ident) );
135
136 // Flag Success
137 ProjectInfo->ExecutionStatus = EXECUTION_SUCCESS;
138 }
139}
140
141
142QString Worker::UpdateLine( PROJECT_INFORMATION* Project, QString SourceLine )
143{
144 // Get the Map holding the Keys and Values
145 QMap<QString, QString> subs_map = Project->SubsMap;
146
147 // Scan the Line Looking for a valid key construction
148 while(SourceLine.contains(leadin_string) && SourceLine.contains(leadout_string))
149 {
150 int key_start = SourceLine.indexOf(leadin_string);
151 int key_end = SourceLine.indexOf(leadout_string) + 2;
152 QString found_key = SourceLine.sliced(key_start, (key_end - key_start));
153 QString found_value = subs_map.value(found_key);
154 SourceLine.replace(found_key, found_value);
155 }
156
157 // return the Updated Line
158 return(SourceLine);
159}
160
161bool Worker::UpdateFile( PROJECT_INFORMATION* Project, QString SourceFile, QString DestinationFile )
162{
163 bool result = true;
164
165 // Line Buffer
166 //QString line; QString output_line;
167
168 // If the Destination File Already Exists, Remove it.
169 QFile output_file( DestinationFile );
170
171 // Remove Existing File (If it exists)
172 if ( output_file.remove() )
173 {
174 LogAdd( LOG_DEBUG, MODE_FILE, QString( "File " + DestinationFile + QString( " was removed." ) ) );
175 }
176 else
177 {
178 if (output_file.exists())
179 {
180 LogAdd( LOG_ERROR, MODE_FILE, QString( "File " + DestinationFile + QString( " was NOT removed." ) ) );
181 result = false;
182 }
183 else
184 {
185 LogAdd( LOG_DEBUG, MODE_FILE, QString( "File " + DestinationFile + QString( " did not Exist." ) ) );
186 }
187 }
188
189 // Update the Template File and Put into the Destination Location (If Possible)
190 if (result)
191 {
192 if (output_file.open(QIODevice::ReadWrite))
193 {
194 QTextStream out( &output_file );
195
196 QFile input_file( SourceFile );
197 if (input_file.open(QIODevice::ReadOnly))
198 {
199 QTextStream in( &input_file );
200
201 while (!in.atEnd())
202 {
203 QString line = in.readLine();
204 QString output_line = UpdateLine(Project, line);
205 out << output_line << "\n";
206 }
207 input_file.close();
208 output_file.close();
209 LogAdd( LOG_DEBUG, MODE_FILE, QString( "Update of File " ) + SourceFile + " to " + DestinationFile + QString( " completed." ) );
210 result = true;
211 }
212 else
213 {
214 LogAdd( LOG_ERROR, MODE_FILE, "Unable to Open Input " + SourceFile );
215 result = false;
216 }
217 }
218 else
219 {
220 LogAdd( LOG_ERROR, MODE_FILE, "Unable to Open Output " + DestinationFile );
221 result = false;
222 }
223 }
224 return( result );
225}
226
227bool Worker::TranslateRecursively(PROJECT_INFORMATION* Store, const QString &srcFilePath, const QString &tgtFilePath)
228{
229 // Check if the Source is a File or a Directory
230 QFileInfo srcFileInfo(srcFilePath);
231 if (srcFileInfo.isDir())
232 {
233 // If the Target Directory Doesn't Exist, Create It
234 QDir targetDir(tgtFilePath);
235 if ( !targetDir.exists() )
236 {
237 // Go Up a Level and Create the Directory
238 targetDir.cdUp();
239 if (!targetDir.mkpath(QFileInfo(tgtFilePath).fileName()))
240 {
241 return false;
242 }
243 }
244
245 // Copy Each Entry in the Directory to the Target
246 QDir sourceDir(srcFilePath);
247 QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
248 foreach (const QString &fileName, fileNames) {
249 const QString newSrcFilePath
250 = srcFilePath + QLatin1Char('/') + fileName;
251 const QString newTgtFilePath
252 = tgtFilePath + QLatin1Char('/') + fileName;
253 if (!TranslateRecursively(Store, newSrcFilePath, newTgtFilePath))
254 {
255 return false;
256 }
257 }
258 }
259
260 // If it is a File Translate It
261 else
262 {
263 if (!UpdateFile(Store, srcFilePath, tgtFilePath ))
264 {
265 LogAdd( LOG_ERROR, MODE_FILE, QString( "Error in file translation from '" ) + srcFilePath + QString("' to '") + tgtFilePath + "." );
266 return false;
267 }
268 }
269 return true;
270}
271
273{
274 bool result = false;
275
276 // Get ProjectData
277 QString project_ident = ProjectInfo->ProjectDesc.ProjectIdent;
278 QString source_directory = ProjectInfo->ProjectDesc.ProjectDirectory;
279 QString destination_directory = ProjectInfo->ProgramInformation.PrimaryWebsiteDirectory + "/projects/" + project_ident;
280 QString code_directory = source_directory + "/source/" + ProjectInfo->ProjectDesc.ExeName;
281
282 // Don't touch it if the Project is Locked or Excluded by Option
283 if (ProjectInfo->ProjectLock && !(ProjectInfo->ProjectDesc.ProjectOptions & EXCLUDE_PROJECT_LIST))
284 {
285 // Time to Clean out the Destination Directory
286 CleanDirectory(destination_directory);
287
288 QDir dir;
289 if (!dir.mkpath(destination_directory + "/html"))
290 {
291 LogAdd( LOG_ERROR, MODE_FILE, QString("Default webpage directory for Project %1 was NOT created.").arg(project_ident));
292 }
293 else
294 {
295 // Check to See if Only the Default Page Should be Produced
297 {
298 if (UpdateFile (ProjectInfo, source_directory + "/defaults/index.html", destination_directory + "/html/index.html"))
299 {
300 LogAdd( LOG_DEBUG, MODE_FILE, QString("Default webpage for Project %1 updated.").arg(project_ident));
301 }
302 else
303 {
304 LogAdd( LOG_ERROR, MODE_FILE, QString("Default webpage for Project %1 was NOT updated.").arg(project_ident));
305 }
306 }
307
308 // Otherwise Process the Entire Project using Doxygen
309 else
310 {
311 // Trim the Code Directory
312 TrimDirectory(code_directory, docs_filter);
313
314 // Count the Number of Lines in the files in the Code Directory
315 QString cloc_output = CountLines(ProjectInfo, code_directory);
316 ProjectInfo->SubsMap.insert("[#CLOC_INFO#]", cloc_output);
317
318 // Try to Find the Libraries that may be used by the Release Version of the Program
319 QString ldd_output = FindLibraries(ProjectInfo);
320 ProjectInfo->SubsMap.insert("[#LIBRARY_LIST#]", ldd_output);
321
322 // Check the C++ Source Files
323 QString cpp_check;
324 if (ProjectInfo->LangFamilyInfo.LangFamilyIndex == 5) // Test if C++
325 {
326 cpp_check = CppCheck( ProjectInfo );
327 }
328 else
329 {
330 cpp_check = "Currently Only available for C/C++ language.";
331 }
332 ProjectInfo->SubsMap.insert("[#CPP_CHECK#]", cpp_check);
333
334 // Update the Auto Source Files in the Code Directory
335 TranslateRecursively(ProjectInfo, source_directory + "/autosrc", code_directory);
336
337 // Translate the Auto Documentation Files into the Code Directory
338 TranslateRecursively(ProjectInfo, source_directory + autodoc_dir, code_directory);
339
340 // Translate the Doxy Files into the Code Directory
341 TranslateRecursively(ProjectInfo, source_directory + "/doxy", code_directory);
342
343 // Translate the Installation File Template
344
345 //Transfer the Images into the Image Directory
346 QString source_image_directory = source_directory + "/images";
347 QString destination_image_directory = destination_directory + "/images";
348 //CleanDirectory(destination_image_directory);
349 if (RecursiveCopy(source_image_directory, destination_image_directory))
350 {
351 LogAdd( LOG_DEBUG, MODE_FILE, QString("Image Directiory for Project %1 was updated.").arg(project_ident));
352 }
353 else
354 {
355 LogAdd( LOG_ERROR, MODE_FILE, QString("Image Directiory for Project %1 was NOT updated.").arg(project_ident));
356 }
357
358 // Transfer the Documents into the Documentation Directory
359 QString source_docs_directory = source_directory + "/docs";
360 QString destination_docs_directory = destination_directory + "/docs";
361 //CleanDirectory(destination_docs_directory);
362
363 if (RecursiveCopy(source_docs_directory, destination_docs_directory))
364 {
365 LogAdd( LOG_DEBUG, MODE_FILE, QString("Docs Directiory for Project %1 was updated.").arg(project_ident));
366 }
367 else
368 {
369 LogAdd( LOG_ERROR, MODE_FILE, QString("Docs Directiory for Project %1 was NOT updated.").arg(project_ident));
370 }
371
372
373 // Send to the Worker
374 result = true;
375 }
376 }
377 }
378 return(result);
379}
380
381bool Worker::CleanDirectory( QString Directory)
382{
383 bool result = false;
384 // Check if the Directory Exists
385 QDir dir(Directory);
386
387 // Delete the Directory if it Exists
388 if (dir.exists())
389 {
390 dir.removeRecursively();
391 }
392
393 // Recreate the Main Directory
394 result = dir.mkpath(Directory);
395
396 return(result);
397}
398
399bool Worker::TrimDirectory(QString Directory, QStringList FileFilter)
400{
401 bool result = true;
402
403 // Check if the Directory Exists
404 QDir dir(Directory);
405
406 // Check the Directory Exists
407 if (dir.exists())
408 {
409 // Get the Files in the Code Directory to Delete and Delete Them
410 dir.setNameFilters(FileFilter);
411 QStringList file_list = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks, QDir::NoSort);
412 for (int index = 0; index < file_list.size(); ++index)
413 {
414 if (!dir.remove(file_list.at(index))) result = false;
415 }
416 }
417 return(result);
418}
419
420QString Worker::CountLines(PROJECT_INFORMATION* Store, QString Directory)
421{
422 QString html_result_table = "<TABLE BORDER=1><TR><TH>Language</TH><TH>Files</TH><TH>Blank</TH><TH>Comment</TH><TH>Code</TH></TR>";
423 QString html_result_rows = "";
424 QString html_result_totals = "";
425
426 QDir::setCurrent( Directory );
427 // Get the Lines Of Code Information
428 QProcess cloc;
429 QString scratchdir = Store->ProgramInformation.LocalDevelopmentDirectory + "/" + Store->ProjectDesc.ProjectIdent + "/scratch/";
430 QString output_file = scratchdir + "cloc_output.txt";
431
432 cloc.setStandardErrorFile( scratchdir + "cloc_error.txt", QIODevice::WriteOnly | QIODevice::Text );
433 cloc.setStandardOutputFile( scratchdir + "cloc_output.txt", QIODevice::WriteOnly | QIODevice::Text );
434 QStringList Arg;
435 Arg << Directory << "--no-recurse";
436 cloc.start( "cloc", QStringList() << Arg );
437 if (!cloc.waitForStarted())
438 {
439 LogAdd( LOG_ERROR, MODE_THREAD, "cloc Process did NOT Start." );
440 html_result_table += "<TR><TD COLSPAN=5>Unable to Count Lines of Code.</TD></TR>";
441 }
442 else
443 {
444 LogAdd( LOG_DEBUG, MODE_THREAD, QString( "Started cloc Process " ) );
445 }
446 if (!cloc.waitForFinished(100000))
447 {
448 LogAdd( LOG_ERROR, MODE_THREAD, "cloc Process did NOT End." );
449 html_result_table += "<TR><TD COLSPAN=5>Error occurred during Count Lines of Code.</TD></TR>";
450 }
451 else
452 {
453 LogAdd( LOG_DEBUG, MODE_THREAD, "cloc Process finished." );
454
455 // Read the Ouptut of the CLOC Program
456 QFile cloc_file(output_file);
457 if ( !cloc_file.open( QIODevice::ReadOnly | QIODevice::Text ) )
458 {
459 LogAdd( LOG_ERROR, MODE_FILE, "Unable to open cloc result file." );
460 html_result_table += "<TR><TD COLSPAN=5>Error occurred reading cloc results.</TD></TR>";
461 }
462 else
463 {
464 int comment_count = 0;
465 QString text_line;
466
467 while( !cloc_file.atEnd() )
468 {
469 text_line = cloc_file.readLine();
470 if ( text_line.contains( "----", Qt::CaseInsensitive ) )
471 {
472 comment_count++;
473 }
474 else
475 {
476 // Process Column Headers
477 if ( comment_count == 1 )
478 {
479 QStringList tokens= text_line.split(" ",Qt::SkipEmptyParts);
480
481 html_result_table += "<TR><TD>" + tokens[0] + "</TD><TD>" + tokens[1] + "</TD><TD>" + tokens[2] + "</TD><TD>" +
482 tokens[3] + "</TD><TD>" + tokens[4] + "</TD></TR>";
483 }
484
485 //Process Report Rows
486 else if ( comment_count == 2 )
487 {
488
489 QString language_name = text_line.first(25);
490 language_name = language_name.trimmed();
491 text_line = text_line.mid(25);
492 QStringList tokens= text_line.split(" ",Qt::SkipEmptyParts);
493
494 html_result_rows += "<TR><TD><B><span style=\"color:red\">" + language_name + "</span></B></TD><TD><B><span style=\"color:red\">" + tokens[0] +
495 "</span></B></TD><TD><B><span style=\"color:red\">" + tokens[1] + "</span></B></TD><TD><B><span style=\"color:red\">" +
496 tokens[2] + "</span></B></TD><TD><B><span style=\"color:red\">" + tokens[3] + "</span></B></TD></TR>";
497 }
498 else if (comment_count ==3)
499 {
500 QStringList tokens= text_line.split(" ",Qt::SkipEmptyParts);
501
502 html_result_totals = "<TR><TD><B>" + tokens[0] + "</B></TD><TD>" + tokens[1] + "</TD><TD>" + tokens[2] + "</TD><TD>" +
503 tokens[3] + "</TD><TD>" + tokens[4] + "</TD></TR>";
504 }
505 }
506 }
507 }
508 }
509
510 // Finish table and Return Result
511 html_result_table += html_result_rows + html_result_totals + "</TABLE>";
512
513 // Remove Scratch Files
514 QFile::remove(Store->ProgramInformation.LocalDevelopmentDirectory + "cloc_error.txt" );
515 QFile::remove( Store->ProgramInformation.LocalDevelopmentDirectory + "cloc_output.txt" );
516 return ( html_result_table );
517};
518
519
520QString Worker::ParserLddResults( QString ResultFilename )
521{
522 QString table_string;
523 // Read the Ouptut of the ldd Program
524 QFile ldd_file( ResultFilename );
525 if ( !ldd_file.open( QIODevice::ReadOnly | QIODevice::Text ) )
526 {
527 LogAdd( LOG_ERROR, MODE_FILE, "Unable to open ldd result file." );
528 table_string += "<tr><td>Error occurred reading ldd results.</td></tr>";
529 }
530 else
531 {
532 while( !ldd_file.atEnd() )
533 {
534 QString text_line = ldd_file.readLine();
535 table_string += QString( "<tr><td>" + text_line + QString( "</td></tr>" ) );
536 }
537 }
538
539 // Finish table and Return Result
540 table_string += QString( "</table>" );
541
542 return( table_string );
543}
544
546{
547 QString scratchdir = Store->ProgramInformation.LocalDevelopmentDirectory + "/" + Store->ProjectDesc.ProjectIdent + "/scratch/";
548 QString program_file = Store->ProjectDesc.ExeDirectory + "/" + Store->ProjectDesc.ExeName;
549
550 QString html_result_table = "<table><tr><th>Dynamic Libraries Linked to Program</th></tr>";
551 if ( QSysInfo::kernelType() == "linux" )
552 {
553 QFile exe_file(program_file);
554
555 // Check if the File Exists and is executable
556 if (exe_file.exists())
557 {
558 QFileDevice::Permissions permissions = exe_file.permissions();
559 if(permissions & QFileDevice::ExeOwner)
560 {
561 // Get the Lines Of Code Information
562 QProcess ldd;
563 ldd.setStandardErrorFile( scratchdir + "ldd_error.txt", QIODevice::WriteOnly | QIODevice::Text );
564 ldd.setStandardOutputFile( scratchdir + "ldd_output.txt", QIODevice::WriteOnly | QIODevice::Text );
565 QStringList Arg;
566 Arg << program_file;
567 ldd.start( "ldd", QStringList() << Arg );
568 if (!ldd.waitForStarted(10000))
569 {
570 LogAdd( LOG_ERROR, MODE_THREAD, " Process did NOT Start." );
571 html_result_table += "<tr><td>Error - Unable to find dynamically lined libraries.</td></tr>";
572 }
573 else
574 {
575 LogAdd( LOG_DEBUG, MODE_THREAD, QString( "Started Process " ) );
576 }
577 if ( !ldd.waitForFinished(100000))
578 {
579 LogAdd( LOG_ERROR, MODE_THREAD, " ldd Process did NOT Flag an End." );
580 html_result_table += "<tr><td>Error occurred while finding Dynamically Linked Libraries.</td></tr>";
581 }
582 else
583 {
584 LogAdd( LOG_DEBUG, MODE_THREAD, " ldd Process finished." );
585 html_result_table += ParserLddResults( scratchdir + "ldd_output.txt" );
586 }
587
588 // Remove Scratch Files
589 QFile::remove( scratchdir + "ldd_error.txt" );
590 QFile::remove( scratchdir + "ldd_output.txt" );
591 }
592 else
593 {
594 html_result_table += "<tr><td>File is not currently directly executable.</td></tr>";
595 }
596 }
597 else
598 {
599 html_result_table += "<tr><td>File does not currently exist.</td></tr>";
600 }
601 }
602 else
603 {
604 html_result_table += "Currently only Linux Files can be checked for library requirements.</td></tr>";
605 }
606 html_result_table += "</TABLE>";
607
608 return ( html_result_table );
609};
610
611QString ReadProjectInfo::FindQtBuildVersion(QString ProUserFile)
612{
613 QString search_string = "ProjectExplorer.ProjectConfiguration.DefaultDisplayName";
614 QString target_string;
615 QString version_string;
616
617 QTextStream in (&ProUserFile);
618 QString line;
619 do
620 {
621 line = in.readLine();
622 if (!line.contains(search_string, Qt::CaseSensitive))
623 {
624 target_string = line;
625 break;
626 }
627 }
628 while (!line.isNull());
629
630 // If possible, Extract the QT Build Version
631 if (!target_string.isNull())
632 {
633 int qt_index = line.indexOf("Qt");
634 if (qt_index != -1)
635 {
636 int version_start = qt_index + 3;
637 int space_index = line.indexOf(" ", version_start);
638 version_string = line.sliced(version_start, space_index - version_start);
639 }
640 }
641 return(version_string);
642}
643
645{
646 bool result = false;
647
648 // Check if this should be Invoked
650 {
651 return(false);
652 }
653 else
654 {
655 QString destination_path = ProjectInfo->ProgramInformation.PrimaryWebsiteDirectory + "/projects/" + ProjectInfo->ProjectDesc.ProjectIdent + "/archive";
656 QDir dir;
657 if (!dir.mkpath(destination_path))
658 {
659 LogAdd( LOG_ERROR, MODE_FILE, destination_path + QString( " archive directory NOT created" ) );
660 }
661 else
662 {
663 LogAdd( LOG_DEBUG, MODE_FILE, destination_path + QString( " archive directory created" ) );
664
665 // Generate the Archive
666 QString source_path = ProjectInfo->ProgramInformation.LocalDevelopmentDirectory + "/" + ProjectInfo->ProjectDesc.ProjectIdent + "/source/" + ProjectInfo->ProjectDesc.ExeName + "/";
667 dir.cd( source_path );
668 QString archive_file = destination_path + "/" + ProjectInfo->ProjectDesc.ExeName + ".tar.gz";
669
670 QProcess tar;
671 QStringList Arg;
672 Arg << "-czf" << archive_file << "--exclude=build" << source_path;
673 tar.start( "tar", QStringList() << Arg );
674 if (!tar.waitForStarted())
675 {
676 LogAdd( LOG_ERROR, MODE_THREAD, "tar did NOT Start." );
677 }
678 else
679 {
680 LogAdd( LOG_DEBUG, MODE_THREAD, QString( "Started tar Process with " ) + QChar('"' ) + Arg.join( " " )+ QChar('"' ) );
681 }
682 tar.closeWriteChannel();
683 if (!tar.waitForFinished())
684 {
685 LogAdd( LOG_ERROR, MODE_THREAD, "tar did NOT End." );
686 }
687 else
688 {
689 LogAdd( LOG_DEBUG, MODE_THREAD, "tar finished." );
690 result = true;
691 }
692 }
693 return(result);
694 }
695}
696
697bool Worker::CreateSourceListFile(const QString Directory, const QString ResultFileName, const QString DevLanguage)
698{
699 bool result;
700
701 QString dev_language = DevLanguage.toUpper();
702
703 // Define What Filename To Search For
704 QStringList file_filter;
705
706 // Set the Filter based on the Language
707 if ( dev_language == "ASM" )
708 {
709 file_filter << "*.asm" << "*.s";
710 }
711 else if ( dev_language == "BASH" )
712 {
713 file_filter << "*.sh";
714 }
715 else if ( dev_language == "BASIC" )
716 {
717 file_filter << "*.bas" << "*.vb";
718 }
719 else if ( dev_language == "C++" )
720 {
721 file_filter << "*.cpp" << "*.c" << "*.cxx" << "*.ino" << "*.h" << "*.hpp";
722 }
723 else if ( dev_language == "CAD" )
724 {
725 file_filter << "*.tcw" << "*.tct" << "*.dwg" << "*.stl" << "*.dxf";
726 }
727 else if ( dev_language == "FORTRAN" )
728 {
729 file_filter << "*.f" << "*.f90" << "*.f95" << "*.f03";
730 }
731 else if ( dev_language == "HTML" )
732 {
733 file_filter << "*.htm" << "*.html" << "*.css" << "*.js" << "*.php";
734 }
735 else if ( dev_language == "JAVA" )
736 {
737 file_filter << "*.java" << "*.jar" << "*.ins";
738 }
739 else if ( dev_language == "JAVASCRIPT" )
740 {
741 file_filter << "*.js";
742 }
743 else if ( dev_language == "OCTAVE" )
744 {
745 file_filter << "*.m";
746 }
747 else if ( dev_language == "PERL" )
748 {
749 file_filter << "*.pl" << "*.pm";
750 }
751 else if ( dev_language == "PHP" )
752 {
753 file_filter << "*.php" << "*.phtml" << "*.php3" << "*.php4" << "*.php5" << "*.php7" << "*.phps";
754 }
755 else if (dev_language == "LINDENSCRIPT")
756 {
757 file_filter << "*.lsl" << "*.osl";
758 }
759
760 // Set the Directory and What to Look For
761 QDir source_directory( Directory );
762 source_directory.setFilter( QDir::Files | QDir::NoDotAndDotDot | QDir::Readable );
763
764 // Get the List of the Files
765 QStringList file_list;
766 file_list = source_directory.entryList( file_filter );
767
768 // Put the Filename into the Result File
769 QFile result_file( ResultFileName );
770 if ( !result_file.open( QIODevice::WriteOnly | QIODevice::Text ) )
771 {
772 result = false;
773 LogAdd( LOG_ERROR, MODE_FILE, QString( "Unable to open File List File " ) + ResultFileName );
774 }
775 else
776 {
777 LogAdd( LOG_DEBUG, MODE_FILE, QString( "Opened File List File " ) + ResultFileName );
778
779 QTextStream out( &result_file );
780
781 // Add the Filenames to the File
782 for ( const auto& filename : file_list )
783 {
784 out << filename << "\n";
785 }
786 result_file.close();
787 result = true;
788 }
789 return( result );
790}
791
793{
794 QString result_table;
795 QString output_file = ProjectInfo->ProjectDesc.ProjectDirectory + "/scratch/cppcheck_output.txt";
796 QString error_file = ProjectInfo->ProjectDesc.ProjectDirectory + "/scratch/cppcheck_error.txt";
797 QString file_list = ProjectInfo->ProjectDesc.ProjectDirectory + "/scratch/file_list.txt";
798
799 // Remove any legacy file list so that any file that exists after this routine will be current
800 QFile file(file_list);
801 if (file.remove())
802 {
803 LogAdd( LOG_DEBUG, MODE_FILE, QString("Deleted File List: %1").arg(file_list));
804 }
805 else
806 {
807 LogAdd( LOG_ERROR, MODE_FILE, QString("Could not delete File List: %1").arg(file_list));
808 }
809
810 // Set the Directory
811 QString directory = ProjectInfo->ProjectDesc.ProjectDirectory + "/source/" + ProjectInfo->ProjectDesc.ExeName;
812 QDir::setCurrent(directory);
813
814 // Select the Files to Process
815 if ( CreateSourceListFile( directory, file_list, ProjectInfo->LangFamilyInfo.ShortName ) )
816 {
817 // Initialise the cppcheck command line
818 QProcess cppcheck;
819 cppcheck.setStandardErrorFile( error_file, QIODevice::WriteOnly | QIODevice::Text );
820 cppcheck.setStandardOutputFile( output_file, QIODevice::WriteOnly | QIODevice::Text );
821 QStringList arg;
822 arg << "--enable=all" << "-UDEBUG" << "--inconclusive" << QString( "--file-list=" ) + file_list;
823
824 cppcheck.start( "cppcheck", arg );
825 if (!cppcheck.waitForStarted(10000))
826 {
827 LogAdd( LOG_ERROR, MODE_THREAD, "cppcheck Process did NOT Start." );
828 result_table += "ERROR - Unable to scan .cpp code.<BR>";
829 }
830 else
831 {
832 LogAdd( LOG_DEBUG, MODE_THREAD, QString( "Started cppcheck Process " ) );
833 }
834 if (!cppcheck.waitForFinished(100000))
835 {
836 LogAdd( LOG_ERROR, MODE_THREAD, "ccpcheck Process did NOT End." );
837 result_table += "ERROR - cppcheck failed during execution.<BR>";
838 }
839 else
840 {
841 LogAdd( LOG_DEBUG, MODE_THREAD, "ccpcheck Process finished." );
842
843 // Read the Ouptut of the ccpcheck Program
844 QFile ccpcheck_file( error_file );
845 if ( !ccpcheck_file.open( QIODevice::ReadOnly | QIODevice::Text ) )
846 {
847 LogAdd( LOG_ERROR, MODE_FILE, "Unable to open ccpcheck result file." );
848 result_table += "ERROR - Unable to read ccpcheck results.<BR>";
849 }
850 else
851 {
852 while( !ccpcheck_file.atEnd() )
853 {
854 QString line = ccpcheck_file.readLine();
855 line.replace("/*!<", "[").replace("*/", "]");
856 result_table += line + "<BR>";
857 }
858
859 // Write to the Website Directory
860 QString check_filename = ProjectInfo->ProgramInformation.PrimaryWebsiteDirectory + "/projects/" + ProjectInfo->ProjectDesc.ProjectIdent + "/html/" + CPP_CHECK_FILE;
861 QFile cpp_file(check_filename);
862 if (cpp_file.open(QIODevice::ReadWrite))
863 {
864 QTextStream stream(&cpp_file);
865 stream << result_table << Qt::endl;
866
867 LogAdd( LOG_DEBUG, MODE_THREAD, check_filename + " CCP Check written to Web Directory" );
868 }
869 else
870 {
871 LogAdd( LOG_ERROR, MODE_THREAD, check_filename + " CCP Check NOT written to Web Directory" );
872 }
873 }
874 }
875 }
876 else
877 {
878 LogAdd( LOG_ERROR, MODE_FILE, "Unable to list Files for cppcheck." );
879 }
880 return(result_table);
881};
882
883
884bool Worker::RecursiveCopy(QString Source, QString Destination)
885{
886 // Check if the Source is a File or a Directory
887 QFileInfo srcFileInfo(Source);
888 if (srcFileInfo.isDir())
889 {
890 // If the Target Directory Doesn't Exist, Create It
891 QDir targetDir(Destination);
892 if ( !targetDir.exists() )
893 {
894 // Go Up a Level and Create the Directory
895 targetDir.cdUp();
896 if (!targetDir.mkpath(QFileInfo(Destination).fileName()))
897 {
898 return false;
899 }
900 }
901
902 // Copy Each Entry in the Directory to the Target
903 QDir sourceDir(Source);
904 QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
905 foreach (const QString &fileName, fileNames)
906 {
907 const QString newSrcFilePath = Source + QLatin1Char('/') + fileName;
908 const QString newTgtFilePath = Destination + QLatin1Char('/') + fileName;
909 if (!RecursiveCopy(newSrcFilePath, newTgtFilePath))
910 {
911 return false;
912 }
913 }
914 }
915
916 // If it is a File Copy It
917 else
918 {
919 if (!QFile(Source).copy(Destination)) return(false);
920 }
921 return true;
922}
923
925{
926 bool result;
927
928 // Find the Source Directory
929 QString source_directory = ProjectInfo->ProjectDesc.ProjectDirectory + "/autoinstall";
930
931 // Set the Destination Directory
932 QString destination_directory = ProjectInfo->ProjectDesc.ProjectDirectory + "/scripts";
933
934 // Translate the File Recuresively
935 result = TranslateRecursively(ProjectInfo, source_directory, destination_directory);
936
937 return(result);
938}
QString FindQtBuildVersion(QString ConfigFile)
Find the Qt Builder Version.
Definition worker.cpp:611
Worker(QObject *parent=nullptr)
Worker Class Constructor.
Definition worker.cpp:9
QStringList source_filter
Definition worker.h:174
void DoWork(PROJECT_INFORMATION *ProjectInfo)
Process the Generation of Documentation by Doxygen & other processes.
Definition worker.cpp:37
void DoDoxygen(PROJECT_INFORMATION *ProjectInfo)
Run Doxygen to Generate the Source Documentaiton.
Definition worker.cpp:97
QString leadin_string
Definition worker.h:178
bool CreateSourceListFile(const QString Directory, const QString ResultFileName, const QString DevLanguage)
Create a List of Project Software Source Files.
Definition worker.cpp:697
QString ParserLddResults(QString ResultFilename)
Converts the Library List into an HTML compatible format.
Definition worker.cpp:520
QStringList docs_dirs
Definition worker.h:175
QString autodoc_dir
Definition worker.h:35
QStringList all_filter
Definition worker.h:177
bool TrimDirectory(QString Directory, QStringList FileFilter)
Remove files defined by the FileFilter from the Directory.
Definition worker.cpp:399
bool CreateInstallScript(PROJECT_INFORMATION *ProjectInfo)
Definition worker.cpp:924
bool CleanDirectory(QString Directory)
Clean a Directory Tree by recursively removing all files and subdirectories.
Definition worker.cpp:381
QString CountLines(PROJECT_INFORMATION *Store, QString Directory)
Definition worker.cpp:420
bool TranslateRecursively(PROJECT_INFORMATION *Store, const QString &srcFilePath, const QString &tgtFilePath)
Recursively process text substituition for a Directory Tree.
Definition worker.cpp:227
void LogAdd(LOGGING_SEVERITY Severity, LOGGING_MODE Mode, const QString Message)
Send Message to the Log.
Definition worker.cpp:27
QString CppCheck(PROJECT_INFORMATION *ProjectInfo)
Conduct Static Analysis of C++ code.
Definition worker.cpp:792
void SendLogEntry(REMOTE_LOG_ENTRY LogEntry)
QString UpdateLine(PROJECT_INFORMATION *Project, QString SourceLine)
Process text substitutions for a single line.
Definition worker.cpp:142
QStringList source_dirs
Definition worker.h:173
bool UpdateFile(PROJECT_INFORMATION *Project, QString SourceFile, QString DestinationFile)
Process text substituitions for a complete text file.
Definition worker.cpp:161
bool CreateSourceArchive(PROJECT_INFORMATION *Store)
Create an Archive using git.
Definition worker.cpp:644
QString leadout_string
Definition worker.h:179
bool RecursiveCopy(QString Source, QString Destination)
Definition worker.cpp:884
void WorkDone(PROJECT_INFORMATION *ProjectInfo)
QString FindLibraries(PROJECT_INFORMATION *Store)
Find the shared libraries the program needs to run.
Definition worker.cpp:545
QStringList docs_filter
Definition worker.h:176
bool PreProcessProject(PROJECT_INFORMATION *ProjectInfo)
Preprocess the Project's Documentation.
Definition worker.cpp:272
#define DOXY_LOG_FILE
The name of the Doxygen Log File.
#define EXCLUDE_PROJECT_LIST
Exclude Project from Public List Mask.
#define CPP_CHECK_FILE
#define CONTROL_DOC_ACCESS
Control Document Access to Public Mask.
@ TARGET_OPEN_SIM_SCRIPT
@ TARGET_SOFTWARE
@ TARGET_NOT_DEFINED
@ TARGET_OPEN_SIM_PROJECT
@ TARGET_DEVELOPMENT
@ TARGET_DOCUMENTATION
@ TARGET_HARDWARE
#define ONLY_DEFAULT_PAGE
Only Display Default Page to Public Mask.
@ EXECUTION_SUCCESS
@ EXECUTION_FAILURE
#define CREATE_SOURCE_ARCHIVE
Create a SOurce Archive when Documentation Generated.
LOGGING_SEVERITY
Log Severity allow the selection of logging events based on Severity.
Definition logger.h:48
@ LOG_ERROR
Definition logger.h:52
@ LOG_INFO
Definition logger.h:55
@ LOG_DEBUG
Definition logger.h:56
LOGGING_MODE
Log Severity allow the selection of logging events based on the mode.
Definition logger.h:21
@ MODE_FILE
Definition logger.h:32
@ MODE_THREAD
Definition logger.h:25
ProjectOptionsManager * project_opts_manager
Class Controlling the Database Creation.
Class for Reading Projects.
Project Information Passed Between Functions.
PROGRAM_INFORMATION ProgramInformation
EXECUTION_STATUS ExecutionStatus
TARGET_FAMILY_INFO TargetFamilyInfo
PROJECT_DESCRIPTION ProjectDesc
LANG_FAMILY_INFO LangFamilyInfo
QMap< QString, QString > SubsMap
Definition logger.h:60
LOGGING_MODE Mode
Definition logger.h:61
QString Message
Definition logger.h:63
LOGGING_SEVERITY Severity
Definition logger.h:62