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.
258 lines
8.3 KiB
258 lines
8.3 KiB
15 years ago
|
/***************************************************************************
|
||
|
* 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 <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"
|