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 }