File indexing completed on 2024-04-28 04:48:05

0001 /****************************************************************************************
0002 * Copyright (c) 2009 Gary Steinert <gary.steinert@gmail.com>                           *
0003 *                                                                                      *
0004 * This program is free software; you can redistribute it and/or modify it under        *
0005 * the terms of the GNU General Public License as published by the Free Software        *
0006 * Foundation; either version 2 of the License, or (at your option) any later           *
0007 * version.                                                                             *
0008 *                                                                                      *
0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012 *                                                                                      *
0013 * You should have received a copy of the GNU General Public License along with         *
0014 * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015 ****************************************************************************************/
0016 
0017 #define INDENT "    "
0018 
0019 #include "log.h"
0020 
0021 #include <QDebug>
0022 #include <QFile>
0023 #include <QTextStream>
0024 #include <QDateTime>
0025 
0026 LogEntry::LogEntry( QString filename, QString message, LogEntry::Type type = LogEntry::information )
0027 {
0028   m_filename = filename;
0029   m_message = message;
0030   m_type = type;
0031 }
0032 
0033 LogEntry::~LogEntry()
0034 {
0035 }
0036 
0037 void Log::print(LogEntry::PrintStyle style, bool errors, bool warnings, bool information, bool success, QString outputFile)
0038 {
0039   //Get number of failed files, warnings and autofixes
0040   int failedCount = 0;
0041   int warningCount = 0;
0042   int autoFixCount = 0;
0043   
0044   foreach( LogEntry i, *this )
0045   {
0046     if( i.getType() == LogEntry::failure )
0047       failedCount++;
0048     if( i.getType() == LogEntry::warning )
0049       warningCount++;
0050     if( i.getType() == LogEntry::information && i.getMessage().endsWith( " - Fixed" ) )
0051       autoFixCount++;
0052   }
0053     
0054   
0055   
0056   QFile filePtr( outputFile );
0057   bool opened;
0058 
0059   if( outputFile.isEmpty() )
0060     opened = filePtr.open( stdout, QFile::WriteOnly );
0061   else
0062     opened = filePtr.open( QFile::WriteOnly | QFile::Truncate );
0063   
0064   if( !opened )
0065   {
0066     //Cant print an error message as its possible it was stdout that failed
0067     return;
0068   }
0069 
0070   QTextStream output( &filePtr );
0071   
0072   if( style == LogEntry::plainText )
0073   {
0074     //Print header
0075     output << "AMAROK LICENSE HEADER CHECKER REPORT\n";
0076     output << "Date: " << QDateTime::currentDateTime().toString() << "\n";
0077     output << "------------------------------------\n\n";
0078 
0079     //Print contents
0080     QString lastFile = "";
0081 
0082     foreach( LogEntry i, *this )
0083     {
0084       //Skip if not to be included
0085       if( ( i.getType() == LogEntry::error && !errors ) ||
0086       ( i.getType() == LogEntry::failure && !errors ) ||
0087       ( i.getType() == LogEntry::warning && !warnings ) ||
0088       ( i.getType() == LogEntry::success && !success ) ||
0089       ( i.getType() == LogEntry::information && !information ) )
0090       {
0091     continue;
0092       }
0093 
0094       //Print filename if first entry for file
0095       if( i.getFilename() != lastFile )
0096       {
0097     output << i.getFilename() << "\n";
0098       }
0099 
0100       //Print type & message
0101       QString typeSymbol;
0102 
0103       if( i.getType() == LogEntry::information )  typeSymbol = "[I]";
0104       else if( i.getType() == LogEntry::error )   typeSymbol = "[E]";
0105       else if( i.getType() == LogEntry::warning ) typeSymbol = "[W]";
0106       else if( i.getType() == LogEntry::success ) typeSymbol = "[S]";
0107       else if( i.getType() == LogEntry::failure ) typeSymbol = "[F]";
0108       else                                        typeSymbol = "[?]";
0109 
0110       output << INDENT << typeSymbol << i.getMessage() << "\n";
0111 
0112       lastFile = i.getFilename();
0113 
0114     }
0115 
0116     //Print footer
0117     output << "-----------------------------\n";
0118     output << "END OF REPORT\n";
0119   }
0120 
0121   if( style == LogEntry::HTML )
0122   {
0123     //Print header
0124     output << "<html>" << "\n";
0125     output << "<head>" << "\n";
0126     output << "<style>" << "\n";
0127     output << "table {" << "\n";
0128     output << "  color: #7F7F7F;" << "\n";
0129     output << "  font: 0.8em/1.6em \"Trebuchet MS\",Verdana,sans-serif;" << "\n";
0130     output << "  border-collapse: collapse" << "\n";
0131     output << "}" << "\n\n";
0132     
0133     output << "table,caption {" << "\n";
0134     output << "  margin: 0 auto;" << "\n";
0135     output << "border-right: 1px solid #CCC;" << "\n";
0136     output << "  border-left: 1px solid #CCC" << "\n";
0137     output << "}" << "\n\n";
0138     
0139     output << "caption,th,td {" << "\n";
0140     output << "  border-left: 0;" << "\n";
0141     output << "  padding: 10px" << "\n";
0142     output << "}" << "\n\n";
0143 
0144     output << "caption,thead th,tfoot th,tfoot td {" << "\n";
0145     output << "  background-color: #E63C1E;" << "\n";
0146     output << "  color: #FFF;" << "\n";
0147     output << "  font-weight: bold;" << "\n";
0148     output << "  text-transform: uppercase" << "\n";
0149     output << "}" << "\n\n";
0150 
0151     output << "thead th {" << "\n";
0152     output << "  background-color: #C30;" << "\n";
0153     output << "  color: #FFB3A6;" << "\n";
0154     output << "  text-align: center" << "\n";
0155     output << "}" << "\n\n";
0156 
0157     output << "tbody th {" << "\n";
0158     output << "  padding: 20px 10px" << "\n";
0159     output << "}" << "\n\n";
0160 
0161     output << "tbody tr.green {" << "\n";
0162     output << "  background-color: #D0FFD0;" << "\n";
0163     output << "  color: #666" << "\n";
0164     output << "}" << "\n\n";
0165 
0166     output << "tbody tr.yellow {" << "\n";
0167     output << "  background-color: #FFFFD0;" << "\n";
0168     output << "  color: #666" << "\n";
0169     output << "}" << "\n\n";
0170 
0171     output << "tbody tr.red {" << "\n";
0172     output << "  background-color: #FFD0D0;" << "\n";
0173     output << "  color: #666" << "\n";
0174     output << "}" << "\n\n";
0175 
0176     output << "tbody tr.blue {" << "\n";
0177     output << "  background-color: #D0D0FF;" << "\n";
0178     output << "  color: #666" << "\n";
0179     output << "}" << "\n\n";
0180 
0181     output << "tbody tr.header {" << "\n";
0182     output << "  background-color: #D0D0D0;" << "\n";
0183     output << "  color: #666" << "\n";
0184     output << "  font-weight: bold" << "\n";
0185     output << "}" << "\n\n";
0186 
0187     output << "tbody a {" << "\n";
0188     output << "  padding: 1px 2px;" << "\n";
0189     output << "  color: #333;" << "\n";
0190     output << "  text-decoration: none;" << "\n";
0191     output << "  border-bottom: 1px dotted #E63C1E" << "\n";
0192     output << "}" << "\n\n";
0193 
0194     output << "tbody a:active,tbody a:hover,tbody a:focus,tbody a:visited {" << "\n";
0195     output << "  color: #666" << "\n";
0196     output << "}" << "\n\n";
0197 
0198     output << "tbody tr:hover {" << "\n";
0199     output << "  background-color: #EEE;" << "\n";
0200     output << "  color: #333" << "\n";
0201     output << "}" << "\n\n";
0202 
0203     output << "tbody tr:hover a {" << "\n";
0204     output << "  background-color: #FFF" << "\n";
0205     output << "}" << "\n\n";
0206 
0207     output << "tbody td+td+td+td a {" << "\n";
0208     output << "  color: #C30;" << "\n";
0209     output << "  font-weight: bold;" << "\n";
0210     output << "  border-bottom: 0" << "\n";
0211     output << "}" << "\n\n";
0212 
0213     output << "tbody td+td+td+td a:active,tbody td+td+td+td a:hover,tbody td+td+td+td a:focus,tbody td+td+td+td a:visited {" << "\n";
0214     output << "  color: #E63C1E" << "\n";
0215     output << "}" << "\n";
0216 
0217     output << "</style>" << "\n";
0218     output << "<script type=\"text/javascript\">" << "\n";
0219     output << "function showFiles(id, count) {" << "\n";
0220     output << "  if(document.getElementById(id + \".0\").style.display == 'table-row')" << "\n";
0221     output << "    newDisplay = 'none';" << "\n";
0222     output << "  else" << "\n";
0223     output << "    newDisplay = 'table-row';" << "\n";
0224     output << "  for (i=0; i<count; i++) {" << "\n";
0225     output << "    document.getElementById(id + \".\" + i).style.display = newDisplay;" << "\n";
0226     output << "  }" << "\n";
0227     output << "}" << "\n";
0228     output << "</script>" << "\n";
0229     output << "<title>Amarok License Checker Report - " << QDateTime::currentDateTime().toString() << "</title>" << "\n";
0230     output << "</head>" << "\n";
0231     output << "<body>" << "\n";
0232     output << "<h1>Amarok License Checker Report</h1>" << "\n";
0233     output << "<h3>Report Date: " << QDateTime::currentDateTime().toString() << "</h3>" << "\n";
0234     output << "<table border=\"1\">" << "\n";
0235     output << "<tr class=\"header\"><td colspan=\"2\">General Information:</td></tr>" << "\n";
0236     output << "<tr><td>Number of failures:</td><td>" << failedCount << "</td></tr>" << "\n";
0237     output << "<tr><td>Number of warnings:</td><td>" << warningCount << "</td></tr>" << "\n";
0238     output << "<tr><td>Number of autofixes:</td><td>" << autoFixCount << "</td></tr>" << "\n";
0239     output << "</table>" << "\n";
0240     output << "<p></p>" << "\n";
0241     output << "<table border=\"1\">" << "\n";
0242     
0243     //Print contents
0244     QString lastFile = "";
0245 
0246     foreach( LogEntry i, *this )
0247     {
0248       //Skip if not to be included
0249       if( ( i.getType() == LogEntry::error && !errors ) ||
0250       ( i.getType() == LogEntry::failure && !errors ) ||
0251       ( i.getType() == LogEntry::warning && !warnings ) ||
0252       ( i.getType() == LogEntry::success && !success ) ||
0253       ( i.getType() == LogEntry::information && !information ) )
0254       {
0255     continue;
0256       }
0257 
0258       //Print filename if first entry for file
0259       if( i.getFilename() != lastFile )
0260       {
0261     output << "<tr>" << "\n";
0262     output << "<td colspan=\"2\">" << i.getFilename() << "</td>" << "\n";
0263     output << "</tr>" << "\n";
0264       }
0265 
0266       //Print type & message
0267       QString typeSymbol;
0268 
0269       if( i.getType() == LogEntry::information )  typeSymbol = "[I]";
0270       else if( i.getType() == LogEntry::error )   typeSymbol = "[E]";
0271       else if( i.getType() == LogEntry::warning ) typeSymbol = "[W]";
0272       else if( i.getType() == LogEntry::success ) typeSymbol = "[S]";
0273       else if( i.getType() == LogEntry::failure ) typeSymbol = "[F]";
0274       else                                        typeSymbol = "[?]";
0275 
0276       QString rowClass;
0277 
0278       if( i.getType() == LogEntry::error || i.getType() == LogEntry::failure )
0279     rowClass = "red";
0280       else if( i.getType() == LogEntry::warning )
0281     rowClass = "yellow";
0282       else if( i.getType() == LogEntry::success )
0283     rowClass = "green";
0284       else if( i.getType() == LogEntry::information )
0285     rowClass = "blue";
0286 
0287       output << "<tr class=\"" << rowClass << "\">" << "\n";
0288       output << "<td style=\"width:10px\">" << typeSymbol << "</td>" << "\n";
0289       output << "<td>" << i.getMessage() << "</td>" << "\n";
0290       output << "</tr>" << "\n";
0291 
0292       lastFile = i.getFilename();
0293 
0294     }
0295 
0296     //Print files table footer and copyHolders table header
0297     output << "</table>" << "\n";
0298     output << "<p></p>" << "\n";
0299     output << "<table border=\"1\">" << "\n";
0300     output << "<tr class=\"header\"><td colspan=\"2\" align=\"center\">Copyright Holders" << "\n";
0301     if( !information )
0302       output << "<br>(Duplicate names shown only)" << "\n";
0303     output << "<br>Click on row to view files</td></tr>" << "\n";
0304     output << "<tr class=\"header\"><td>Name</td><td>Email</td></tr>" << "\n";
0305     
0306     for( int i = 0; i < copyHolders.count(); i++ )
0307     {
0308       //Beginning and end require special cases
0309       //Disaply all if information==true
0310       if( information ||
0311       ( i == 0 && copyHolders[i + 1].name == copyHolders[i].name ) ||
0312       ( i == copyHolders.count() - 1 && copyHolders[i - 1].name == copyHolders[i].name ) ||
0313       ( ( i > 0 && i < copyHolders.count() - 1 ) && ( copyHolders[i + 1].name == copyHolders[i].name || copyHolders[i - 1].name == copyHolders[i].name ) ) )
0314       {
0315     output << "<tr onClick=\"showFiles('filesRow" << i << "'," << copyHolders[i].files.count() << ")\">" << "\n";
0316     output << "<td>" << copyHolders[i].name << "</td>" << "\n";
0317     output << "<td>" << copyHolders[i].email << "</td>" << "\n";
0318     output << "</tr>" << "\n";
0319     
0320     for( int j = 0; j < copyHolders[i].files.count(); j++ )
0321     {
0322       output << "<tr class=\"yellow\" id=\"filesRow" << i << "." << j << "\" style=\"display:none\">" << "\n";
0323       output << "<td colspan=2>" << copyHolders[i].files[j] << "</td>" << "\n";
0324       output << "</tr>" << "\n";
0325     }
0326       }
0327     
0328     }
0329 
0330     //Print footer
0331     output << "</table>" << "\n";
0332     output << "</body>" << "\n";
0333     output << "</html>" << "\n";
0334   }
0335 }
0336 
0337 void Log::addCopyHolder( QString a, QString b, QString filename )
0338 {
0339   //If empty list no search required
0340   if( copyHolders.isEmpty() )
0341   {
0342     copyHolders.append( CopyHolder( a , b ) );
0343     return;
0344   }
0345   
0346   //Search for same name
0347   //Using a binary search to check for existence then an incremental search
0348   //to find insertion point as I have had trouble implementing it off the
0349   //binary search results
0350   int start, end, mid;
0351   start = 0;
0352   end = copyHolders.count() - 1;
0353   mid = 0;
0354   int insert = -1;
0355   
0356   //This is a change to a normal binary search
0357   //Because i want to insert when things are NOT found, i need to run an
0358   //extra iteration. start<=end is kept in place for end < start eventualities
0359   //and as start==end situations either turn into start>end situations or result
0360   //in a found entry (and therefore either a return or break) no checks for start==end
0361   //are required
0362   while( start <= end )
0363   {
0364     mid = (int)( ( start + end ) / 2 );
0365     
0366     if( copyHolders[mid].name.toLower() == a.toLower() )
0367     {
0368       //Might not have found the first entry for the name, so cycle back
0369       while( mid >= 0 && copyHolders[mid].name.toLower() == a.toLower() )
0370     mid--;
0371       
0372       //Now mid++ to select the first entry for name
0373     mid++;
0374       
0375       while( mid < copyHolders.count() && copyHolders[mid].name.toLower() == a.toLower() && copyHolders[mid].email.toLower() != b.toLower() )
0376       {
0377     mid++;
0378       }
0379 
0380       //Checking name here because if email happens to be the same for the next entry
0381       //(different name) then entry will not be added
0382       if( mid < copyHolders.count() && copyHolders[mid].name.toLower() == a.toLower() )
0383       {
0384     //If found, no need to add so add file name and exit function
0385     copyHolders[mid].addFile( filename );
0386     return;
0387       }
0388       else
0389       {
0390     //Found the insertion point
0391     insert = mid;
0392     break;
0393       }
0394     }
0395     else
0396     {
0397       if( copyHolders[mid].name.toLower() < a.toLower() )
0398     start = mid + 1;
0399       else
0400     end = mid - 1;
0401     }
0402     
0403   }
0404   
0405   mid = (int)( ( start + end ) / 2 );
0406   
0407   if( insert > -1 )
0408   {
0409     copyHolders.insert( insert, CopyHolder( a, b ) );
0410     copyHolders[insert].addFile( filename );
0411   }
0412   else if( copyHolders[mid].name < a )
0413   {
0414     copyHolders.insert( mid + 1, CopyHolder( a, b ) );
0415     copyHolders[mid + 1].addFile( filename );
0416   }
0417   else
0418   {
0419     copyHolders.insert( mid, CopyHolder( a, b ) );
0420     copyHolders[mid].addFile( filename );
0421   }
0422 }
0423 
0424 void Log::writeShellScript( QString filename )
0425 {
0426   QFile filePtr( filename );
0427   
0428   if( !filePtr.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
0429   {
0430     return;
0431   }
0432   
0433   QTextStream output( &filePtr );
0434   
0435   output << "#!/bin/bash" << "\n";
0436   
0437   int count = 1; 
0438 
0439   foreach( const QString &i, problemFiles )
0440   {
0441     output << "echo \"Next file: " << i << "\"" << "\n";
0442     output << "echo \"Press enter to edit, type 'exit' to end script\"" << "\n";
0443     output << "read EXIT" << "\n";
0444     output << "if [ \"$EXIT\" = \"exit\" ]; then" << "\n";
0445     output << "  exit 0;" << "\n";
0446     output << "fi" << "\n";
0447     output << " echo \"Files processed so far: " << count << "\"" << "\n";
0448     count++;
0449     output << "vim " << i << "\n";
0450   }
0451 }
0452