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