Warning, file /sdk/cervisia/annotatecontroller.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2002-2003 Christian Loose <christian.loose@hamburg.de> 0003 * 0004 * This program is free software; you can redistribute it and/or modify 0005 * it under the terms of the GNU General Public License as published by 0006 * the Free Software Foundation; either version 2 of the License, or 0007 * (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0017 */ 0018 0019 #include "annotatecontroller.h" 0020 0021 #include <qdatetime.h> 0022 #include <qmap.h> 0023 0024 #include <KLocalizedString> 0025 0026 #include "annotatedialog.h" 0027 #include "cvsjobinterface.h" 0028 #include "cvsserviceinterface.h" 0029 #include "loginfo.h" 0030 #include "progressdialog.h" 0031 0032 using namespace Cervisia; 0033 0034 struct AnnotateController::Private { 0035 using RevisionCommentMap = QMap<QString, QString>; 0036 RevisionCommentMap comments; // maps comment to a revision 0037 0038 OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService; 0039 AnnotateDialog *dialog; 0040 ProgressDialog *progress; 0041 0042 bool execute(const QString &fileName, const QString &revision); 0043 void parseCvsLogOutput(); 0044 void parseCvsAnnotateOutput(); 0045 }; 0046 0047 AnnotateController::AnnotateController(AnnotateDialog *dialog, OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService) 0048 : d(new Private) 0049 { 0050 // initialize private data 0051 d->cvsService = cvsService; 0052 d->dialog = dialog; 0053 d->progress = 0; 0054 } 0055 0056 AnnotateController::~AnnotateController() 0057 { 0058 delete d; 0059 } 0060 0061 void AnnotateController::showDialog(const QString &fileName, const QString &revision) 0062 { 0063 if (!d->execute(fileName, revision)) { 0064 delete d->dialog; 0065 return; 0066 } 0067 0068 d->parseCvsLogOutput(); 0069 d->parseCvsAnnotateOutput(); 0070 0071 // hide progress dialog 0072 delete d->progress; 0073 d->progress = 0; 0074 0075 d->dialog->setWindowTitle(i18n("CVS Annotate: %1", fileName)); 0076 d->dialog->show(); 0077 } 0078 0079 bool AnnotateController::Private::execute(const QString &fileName, const QString &revision) 0080 { 0081 QDBusReply<QDBusObjectPath> job = cvsService->annotate(fileName, revision); 0082 if (!job.isValid()) 0083 return false; 0084 0085 progress = new ProgressDialog(dialog, "Annotate", cvsService->service(), job, "annotate", i18n("CVS Annotate")); 0086 0087 return progress->execute(); 0088 } 0089 0090 void AnnotateController::Private::parseCvsLogOutput() 0091 { 0092 QString line, comment, rev; 0093 0094 enum { Begin, Tags, Admin, Revision, Author, Branches, Comment, Finished } state; 0095 0096 state = Begin; 0097 while (progress->getLine(line)) { 0098 switch (state) { 0099 case Begin: 0100 if (line == "symbolic names:") 0101 state = Tags; 0102 break; 0103 case Tags: 0104 if (line[0] != '\t') 0105 state = Admin; 0106 break; 0107 case Admin: 0108 if (line == "----------------------------") 0109 state = Revision; 0110 break; 0111 case Revision: 0112 rev = line.section(' ', 1, 1); 0113 state = Author; 0114 break; 0115 case Author: 0116 state = Branches; 0117 break; 0118 case Branches: 0119 if (!line.startsWith(QLatin1String("branches:"))) { 0120 state = Comment; 0121 comment = line; 0122 } 0123 break; 0124 case Comment: 0125 if (line == "----------------------------") 0126 state = Revision; 0127 else if (line == "=============================================================================") 0128 state = Finished; 0129 if (state == Comment) 0130 comment += QString("\n") + line; 0131 else 0132 comments[rev] = comment; 0133 break; 0134 case Finished:; 0135 } 0136 0137 if (state == Finished) 0138 break; 0139 } 0140 0141 // skip header part of cvs annotate output 0142 bool notEof = true; 0143 while (notEof && !line.startsWith(QLatin1String("*****"))) 0144 notEof = progress->getLine(line); 0145 } 0146 0147 void AnnotateController::Private::parseCvsAnnotateOutput() 0148 { 0149 LogInfo logInfo; 0150 QString rev, content, line; 0151 QString oldRevision; 0152 bool odd = false; 0153 0154 while (progress->getLine(line)) { 0155 int startIdxC2 = line.indexOf(QLatin1Char('(')); // column 2 "(author date):" 0156 0157 QString authorDate = line.mid(startIdxC2 + 1, line.indexOf(QLatin1Char(')'), startIdxC2 + 1) - startIdxC2 - 1); 0158 0159 QString dateString = authorDate.mid(authorDate.lastIndexOf(QLatin1Char(' '))).trimmed(); 0160 if (!dateString.isEmpty()) { 0161 QDate date(QLocale::c().toDate(dateString, QLatin1String("dd-MMM-yy"))); 0162 if (date.year() < 1970) 0163 date = date.addYears(100); 0164 logInfo.m_dateTime = QDateTime(date, QTime(), Qt::UTC); 0165 } 0166 0167 rev = line.left(startIdxC2).trimmed(); 0168 logInfo.m_author = authorDate.left(authorDate.indexOf(QLatin1Char(' '))).trimmed(); 0169 content = line.mid(line.indexOf(QLatin1String("): "), startIdxC2 + 1) + 3); 0170 0171 logInfo.m_comment = comments[rev]; 0172 0173 if (rev == oldRevision) { 0174 // don't remove revision/author info on following lines, since the user can not easily get 0175 // the revision nor show the check-in comment tooltip when the first line of a large 0176 // block with the same revision is already scrolled out of the viewport 0177 // logInfo.m_author.clear(); 0178 // rev.clear(); 0179 } else { 0180 oldRevision = rev; 0181 odd = !odd; 0182 } 0183 0184 logInfo.m_revision = rev; 0185 0186 dialog->addLine(logInfo, content, odd); 0187 } 0188 }