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.
213 lines
7.4 KiB
213 lines
7.4 KiB
/***************************************************************************
|
|
* Copyright (C) 200?-2003 by KDevelop Authors *
|
|
* www.kdevelop.org *
|
|
* *
|
|
* 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 <qtextbrowser.h>
|
|
#include <qlayout.h>
|
|
#include <qregexp.h>
|
|
#include <qdir.h>
|
|
#include <qstringlist.h>
|
|
|
|
#include <kmessagebox.h>
|
|
#include <kcursor.h>
|
|
#include <klocale.h>
|
|
#include <kdebug.h>
|
|
#include <dcopref.h>
|
|
|
|
#include <cvsjob_stub.h>
|
|
#include <cvsservice_stub.h>
|
|
|
|
#include "cvsoptions.h"
|
|
#include "cvslogpage.h"
|
|
#include "cvsdiffpage.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// class CVSLogPage
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
CVSLogPage::CVSLogPage( CvsService_stub *cvsService, QWidget *parent, const char *name, int )
|
|
: DCOPObject( "CvsLogPageDCOPIface" ),
|
|
QWidget( parent, name? name : "logformpage" ),
|
|
m_cvsService( cvsService ), m_cvsLogJob( 0 )
|
|
{
|
|
QLayout *thisLayout = new QVBoxLayout( this );
|
|
|
|
m_textBrowser = new QTextBrowser( this, "logbrowser" );
|
|
thisLayout->add( m_textBrowser );
|
|
|
|
/// \FIXME a better way?
|
|
m_textBrowser->setMinimumWidth(fontMetrics().width('X')*50);
|
|
m_textBrowser->setMinimumHeight(fontMetrics().width('X')*43);
|
|
|
|
connect( m_textBrowser, SIGNAL(linkClicked( const QString& )), this, SLOT(slotLinkClicked( const QString& )) );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
CVSLogPage::~CVSLogPage()
|
|
{
|
|
kdDebug(9006) << "CVSLogPage::~CVSLogPage()" << endl;
|
|
cancel();
|
|
delete m_cvsLogJob;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CVSLogPage::startLog( const QString &workDir, const QString &pathName )
|
|
{
|
|
kdDebug(9006) << "CVSLogPage::start() here! workDir = " << workDir <<
|
|
", pathName = " << pathName << endl;
|
|
|
|
// CvsOptions *options = CvsOptions::instance();
|
|
// "cvs log" needs to be done on relative-path basis
|
|
m_pathName = pathName;
|
|
m_diffStrings.clear();
|
|
|
|
DCOPRef job = m_cvsService->log( pathName );
|
|
m_cvsLogJob = 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 );
|
|
// We'll read the ouput directly from the job ...
|
|
connectDCOPSignal( job.app(), job.obj(), "receivedStdout(QString)", "slotReceivedOutput(QString)", true );
|
|
// connectDCOPSignal( job.app(), job.obj(), "receivedStderr(QString)", "slotReceivedErrors(QString)", true );
|
|
|
|
kdDebug(9006) << "Running: " << m_cvsLogJob->cvsCommand() << endl;
|
|
m_cvsLogJob->execute();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
void CVSLogPage::parseLogContent( const QString& text )
|
|
{
|
|
kdDebug(9006) << "CVSLogPage::parseLogContent()" << endl;
|
|
|
|
m_base->contents->clear();
|
|
|
|
QStringList l = QStringList::split( "----------------------------", text );
|
|
QString header = l.front();
|
|
l.pop_front();
|
|
|
|
for( QStringList::Iterator it=l.begin(); it!=l.end(); ++it )
|
|
{
|
|
const QString &s = *it;
|
|
if (s)
|
|
{
|
|
m_base->contents->append( s );
|
|
m_base->contents->append( "<hr>" );
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CVSLogPage::slotJobExited( bool normalExit, int exitStatus )
|
|
{
|
|
// m_part->core()->running( m_part, false );
|
|
if (!normalExit)
|
|
{
|
|
KMessageBox::sorry( this, i18n("Log failed with exitStatus == %1").arg( exitStatus), i18n("Log Failed") );
|
|
return;
|
|
}
|
|
|
|
static QRegExp rx_sep( "\\-+" );
|
|
static QRegExp rx_sep2( "=+" );
|
|
static QRegExp rx_date( "date: .* author: .* state: .* lines: .*" );
|
|
// "revision" followed by one or more decimals followed by a optional dot
|
|
static QRegExp rx_rev( "revision ((\\d+\\.?)+)" );
|
|
m_textBrowser->setTextFormat( QTextBrowser::PlainText );
|
|
|
|
for (size_t i=0; i<m_diffStrings.count(); ++i) {
|
|
QString s = m_diffStrings[i];
|
|
kdDebug(9006) << "Examining line: " << s << endl;
|
|
if ( rx_rev.exactMatch(s) )
|
|
{
|
|
QString ver = rx_rev.cap( 1 );
|
|
QString dstr = "<b>" + s + "</b> ";
|
|
int lastVer = ver.section( '.', -1 ).toInt() - 1;
|
|
if ( lastVer > 0 ) {
|
|
QString lv = ver.left( ver.findRev( "." ) + 1 ) + QString::number( lastVer );
|
|
dstr += " [<a href=\"diff:/" + m_pathName + "/" + lv + "_" + ver + "\">diff to " + lv + "</a>]";
|
|
}
|
|
m_textBrowser->setTextFormat( QTextBrowser::RichText );
|
|
m_textBrowser->append( dstr );
|
|
m_textBrowser->setTextFormat( QTextBrowser::PlainText );
|
|
}
|
|
else if ( rx_date.exactMatch(s) )
|
|
{
|
|
m_textBrowser->setTextFormat( QTextBrowser::RichText );
|
|
m_textBrowser->append( "<i>" + s + "</i>" );
|
|
m_textBrowser->setTextFormat( QTextBrowser::PlainText );
|
|
}
|
|
else if ( rx_sep.exactMatch(s) || rx_sep2.exactMatch(s) )
|
|
{
|
|
m_textBrowser->append( "\n" );
|
|
m_textBrowser->setTextFormat( QTextBrowser::RichText );
|
|
m_textBrowser->append( "<hr>" );
|
|
m_textBrowser->setTextFormat( QTextBrowser::PlainText );
|
|
} else
|
|
{
|
|
m_textBrowser->append( s );
|
|
}
|
|
}
|
|
m_logTextBackup = m_textBrowser->source();
|
|
|
|
// emit jobFinished( normalExit, exitStatus );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CVSLogPage::slotLinkClicked( const QString &link )
|
|
{
|
|
kdDebug(9006) << "CVSLogPage::slotLinkClicked()" << endl;
|
|
|
|
// The text browser clears the page so we go back to our old one
|
|
/// \FIXME in this way I lose the source
|
|
m_textBrowser->setSource( m_logTextBackup );
|
|
|
|
QString ver = link.mid( link.findRev( "/" ) + 1 );
|
|
QString v1 = ver.section( '_', 0, 0 );
|
|
QString v2 = ver.section( '_', 1, 1 );
|
|
if ( v1.isEmpty() || v2.isEmpty() )
|
|
{
|
|
m_textBrowser->append( i18n( "invalid link clicked" ) );
|
|
return;
|
|
}
|
|
|
|
emit diffRequested( m_pathName, v1, v2 );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CVSLogPage::slotReceivedOutput( QString someOutput )
|
|
{
|
|
kdDebug(9006) << "CVSLogPage::slotReceivedOutput(QString)" << endl;
|
|
|
|
kdDebug(9006) << "OUTPUT: " << someOutput << endl;
|
|
m_diffStrings += m_outputBuffer.process(someOutput);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CVSLogPage::slotReceivedErrors( QString someErrors )
|
|
{
|
|
kdDebug(9006) << "ERRORS: " << someErrors << endl;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CVSLogPage::cancel()
|
|
{
|
|
if (m_cvsLogJob && m_cvsLogJob->isRunning())
|
|
m_cvsLogJob->cancel();
|
|
}
|
|
|
|
#include "cvslogpage.moc"
|