You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/vcs/cvsservice/annotatepage.cpp

258 lines
8.4 KiB

/***************************************************************************
* Copyright (C) 2005 by Robert Gruber *
* rgruber@users.sourceforge.net *
* *
* 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 <tqlayout.h>
#include <tqregexp.h>
#include <tqstringlist.h>
#include <tqdatetime.h>
#include <tqlabel.h>
#include <tdemessagebox.h>
#include <kcursor.h>
#include <tdelocale.h>
#include <kdebug.h>
#include <krfcdate.h>
#include <klineedit.h>
#include <kpushbutton.h>
#include <kdialogbase.h>
#include <tdemessagebox.h>
#include <dcopref.h>
#include <cvsjob_stub.h>
#include <cvsservice_stub.h>
#include "annotatepage.h"
#include "annotateview.h"
AnnotatePage::AnnotatePage( CvsService_stub *cvsService, TQWidget *parent, const char *name, int )
: DCOPObject( "CvsAnnotatePageDCOPIface" ),
TQWidget( parent, name? name : "annotateformpage" ),
m_cvsService( cvsService ), m_cvsAnnotateJob( 0 )
{
kdDebug(9006) << "AnnotatePage::AnnotatePage()" << endl;
TQLayout *dialogLayout = new TQVBoxLayout( this );
//First create the top-line where user can choose a revision
TQWidget * LayoutWidget = new TQWidget( this );
TQHBoxLayout * AnnotateLayout = new TQHBoxLayout( LayoutWidget );
TQLabel * lblRevision = new TQLabel( 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( TQKeySequence( tr( "Alt+A" ) ) );
dialogLayout->add( LayoutWidget );
connect( m_btnAnnotate, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotNewAnnotate()) );
connect( m_leRevision, TQ_SIGNAL( returnPressed() ),
m_btnAnnotate, TQ_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 TQString pathName, const TQString 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(TQString)", "slotReceivedOutput(TQString)", true );
//clear both the outputbuffer and the AnnotateView
m_output = "";
((TDEListView*)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
TQStringList lines = TQStringList::split("\n", m_output);
parseAnnotateOutput(lines);
}
void AnnotatePage::slotReceivedOutput( TQString someOutput )
{
kdDebug(9006) << "AnnotatePage::slotReceivedOutput(TQString)" << endl;
m_output += someOutput;
}
void AnnotatePage::slotReceivedErrors( TQString )
{
kdDebug(9006) << "AnnotatePage::slotReceivedErrors(TQString)" << endl;
}
void AnnotatePage::cancel()
{
if (m_cvsAnnotateJob && m_cvsAnnotateJob->isRunning())
m_cvsAnnotateJob->cancel();
}
void AnnotatePage::parseAnnotateOutput(TQStringList& lines)
{
kdDebug(9006) << "AnnotatePage::parseAnnotateOutput(TQStringList)" << endl;
/**
* First we need to parse the output of "cvs log" which the dcop-interface delivers
* everytime annotate is requested.
* The TQMap m_comments stores the revisions together with the matching comments.
* The comments will be passed to the AnnotateView in order to display them as TQToolTip
*/
TQString line, comment, rev;
enum { Begin, Tags, Admin, Revision,
Author, Branches, Comment, Finished } state;
TQStringList::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 += TQString("\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."));
((TDEListView*)m_annotateView)->clear();
return;
}
++it;
TQString author, content;
TQString oldRevision = ""; //we always store the last revision to recognice...
bool changeColor = false; //...when the AnnotateView needs to change the coloring
TQDateTime logDate;
do
{
line = *it;
//the log date should be printed according to the user's global setting
//so we pass it as TQDateTime to the AnnotateView below
TQString dateString = line.mid(23, 9);
if( !dateString.isEmpty() )
logDate.setTime_t(KRFCDate::parseDate(dateString), TQt::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"