diff options
Diffstat (limited to 'vcs/cvsservice/annotatepage.cpp')
-rw-r--r-- | vcs/cvsservice/annotatepage.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/vcs/cvsservice/annotatepage.cpp b/vcs/cvsservice/annotatepage.cpp new file mode 100644 index 00000000..fea16ece --- /dev/null +++ b/vcs/cvsservice/annotatepage.cpp @@ -0,0 +1,257 @@ +/*************************************************************************** + * Copyright (C) 2005 by Robert Gruber * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <qlayout.h> +#include <qregexp.h> +#include <qstringlist.h> +#include <qdatetime.h> +#include <qlabel.h> + +#include <kmessagebox.h> +#include <kcursor.h> +#include <klocale.h> +#include <kdebug.h> +#include <krfcdate.h> +#include <klineedit.h> +#include <kpushbutton.h> +#include <kdialogbase.h> +#include <kmessagebox.h> + +#include <dcopref.h> +#include <cvsjob_stub.h> +#include <cvsservice_stub.h> + +#include "annotatepage.h" +#include "annotateview.h" + +AnnotatePage::AnnotatePage( CvsService_stub *cvsService, QWidget *parent, const char *name, int ) + : DCOPObject( "CvsAnnotatePageDCOPIface" ), + QWidget( parent, name? name : "annotateformpage" ), + m_cvsService( cvsService ), m_cvsAnnotateJob( 0 ) +{ + kdDebug(9006) << "AnnotatePage::AnnotatePage()" << endl; + + QLayout *dialogLayout = new QVBoxLayout( this ); + + //First create the top-line where user can choose a revision + QWidget * LayoutWidget = new QWidget( this ); + QHBoxLayout * AnnotateLayout = new QHBoxLayout( LayoutWidget ); + + QLabel * lblRevision = new QLabel( LayoutWidget ); + AnnotateLayout->addWidget( lblRevision ); + lblRevision->setText( tr( "Revision:" ) ); + + m_leRevision = new KLineEdit( LayoutWidget ); + AnnotateLayout->addWidget( m_leRevision ); + + m_btnAnnotate = new KPushButton( LayoutWidget ); + AnnotateLayout->addWidget( m_btnAnnotate ); + m_btnAnnotate->setText( tr( "&Annotate" ) ); + m_btnAnnotate->setAccel( QKeySequence( tr( "Alt+A" ) ) ); + + dialogLayout->add( LayoutWidget ); + + connect( m_btnAnnotate, SIGNAL(clicked()), + this, SLOT(slotNewAnnotate()) ); + connect( m_leRevision, SIGNAL( returnPressed() ), + m_btnAnnotate, SLOT( setFocus() ) ); + + //Nest create the AnnotateView; it will do the actual displaying + m_annotateView = new AnnotateView(this, "annotateview"); + dialogLayout->add( m_annotateView ); +} + +AnnotatePage::~AnnotatePage() +{ + kdDebug(9006) << "AnnotatePage::~Annotate()" << endl; + cancel(); + delete m_cvsAnnotateJob; +} + +void AnnotatePage::startAnnotate( const QString pathName, const QString revision ) +{ + kdDebug(9006) << "AnnotatePage::startAnnotate() pathName = " << pathName << + "revision = " << revision << endl; + + m_leRevision->setText(revision); + + m_pathName = pathName; + + DCOPRef job = m_cvsService->annotate( pathName, revision ); + m_cvsAnnotateJob = new CvsJob_stub( job.app(), job.obj() ); + + // establish connections to the signals of the cvs m_job + connectDCOPSignal( job.app(), job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true ); + connectDCOPSignal( job.app(), job.obj(), "receivedStdout(QString)", "slotReceivedOutput(QString)", true ); + + //clear both the outputbuffer and the AnnotateView + m_output = ""; + ((KListView*)m_annotateView)->clear(); + + kdDebug(9006) << "Running: " << m_cvsAnnotateJob->cvsCommand() << endl; + m_cvsAnnotateJob->execute(); +} + +void AnnotatePage::slotJobExited( bool normalExit, int exitStatus ) +{ + kdDebug(9006) << "AnnotatePage::slotJobExited(bool, int)" << endl; + + if (!normalExit) + { + KMessageBox::sorry( this, i18n("Annotate failed with exitStatus == %1").arg( exitStatus), i18n("Annotate Failed") ); + return; + } + + //split the collected output and pass the lines to the parser function + QStringList lines = QStringList::split("\n", m_output); + parseAnnotateOutput(lines); +} + +void AnnotatePage::slotReceivedOutput( QString someOutput ) +{ + kdDebug(9006) << "AnnotatePage::slotReceivedOutput(QString)" << endl; + m_output += someOutput; +} + +void AnnotatePage::slotReceivedErrors( QString ) +{ + kdDebug(9006) << "AnnotatePage::slotReceivedErrors(QString)" << endl; +} + +void AnnotatePage::cancel() +{ + if (m_cvsAnnotateJob && m_cvsAnnotateJob->isRunning()) + m_cvsAnnotateJob->cancel(); +} + +void AnnotatePage::parseAnnotateOutput(QStringList& lines) +{ + kdDebug(9006) << "AnnotatePage::parseAnnotateOutput(QStringList)" << endl; + + /** + * First we need to parse the output of "cvs log" which the dcop-interface delivers + * everytime annotate is requested. + * The QMap m_comments stores the revisions together with the matching comments. + * The comments will be passed to the AnnotateView in order to display them as QToolTip + */ + QString line, comment, rev; + + enum { Begin, Tags, Admin, Revision, + Author, Branches, Comment, Finished } state; + + QStringList::Iterator it = lines.begin(); + state = Begin; + do + { + line = *it; + + switch( state ) + { + case Begin: + if( line == "symbolic names:" ) + state = Tags; + break; + case Tags: + if( line[0] != '\t' ) + state = Admin; + break; + case Admin: + if( line == "----------------------------" ) + state = Revision; + break; + case Revision: + rev = line.section(' ', 1, 1); + state = Author; + break; + case Author: + state = Branches; + break; + case Branches: + if( !line.startsWith("branches:") ) + { + state = Comment; + comment = line; + } + break; + case Comment: + if( line == "----------------------------" ) + state = Revision; + else if( line == "=============================================================================" ) + state = Finished; + if( state == Comment ) + comment += QString("\n") + line; + else + m_comments[rev] = comment; + break; + case Finished: + ; + } + + if (state == Finished) + break; + } while( ++it != lines.end()); + + // move forward until we get to the actual output of "cvs annotate" + bool notEof = true; + while( notEof && !(*it).startsWith("*****") ) { + notEof = (++it != lines.end()); + } + + //if the upper loop hit the ent of the list, this can only mean, that + //the selected revision is unknown to CVS + if (!notEof) { + KMessageBox::error(this, i18n("The selected revision does not exist.")); + ((KListView*)m_annotateView)->clear(); + return; + } + ++it; + + QString author, content; + QString oldRevision = ""; //we always store the last revision to recognice... + bool changeColor = false; //...when the AnnotateView needs to change the coloring + QDateTime logDate; + + do + { + line = *it; + + //the log date should be printed according to the user's global setting + //so we pass it as QDateTime to the AnnotateView below + QString dateString = line.mid(23, 9); + if( !dateString.isEmpty() ) + logDate.setTime_t(KRFCDate::parseDate(dateString), Qt::UTC); + + rev = line.left(13).stripWhiteSpace(); + author = line.mid(14, 8).stripWhiteSpace(); + content = line.mid(35, line.length()-35); + + comment = m_comments[rev]; + if( comment.isNull() ) + comment = ""; + + if( rev != oldRevision ) + { + oldRevision = rev; + changeColor = !changeColor; + } + + //finished parsing the annotate line + //We pass the needed data to the AnnotateView + m_annotateView->addLine(rev, author, logDate, content, m_comments[rev], changeColor); + } while (++it != lines.end()); +} + +void AnnotatePage::slotNewAnnotate() +{ + startAnnotate(m_pathName, m_leRevision->text()); +} + +#include "annotatepage.moc" |