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