summaryrefslogtreecommitdiffstats
path: root/vcs/cvsservice/annotatepage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vcs/cvsservice/annotatepage.cpp')
-rw-r--r--vcs/cvsservice/annotatepage.cpp257
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 *
+ * *
+ * 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"