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