|
|
|
/* ****************************************************************************
|
|
|
|
This file is part of KBabel
|
|
|
|
|
|
|
|
Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
|
|
|
|
Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.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.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
In addition, as a special exception, the copyright holders give
|
|
|
|
permission to link the code of this program with any edition of
|
|
|
|
the TQt library by Trolltech AS, Norway (or with modified versions
|
|
|
|
of TQt that use the same license as TQt), and distribute linked
|
|
|
|
combinations including the two. You must obey the GNU General
|
|
|
|
Public License in all respects for all of the code used other than
|
|
|
|
TQt. If you modify this file, you may extend this exception to
|
|
|
|
your version of the file, but you are not obligated to do so. If
|
|
|
|
you do not wish to do so, delete this exception statement from
|
|
|
|
your version.
|
|
|
|
|
|
|
|
**************************************************************************** */
|
|
|
|
|
|
|
|
|
|
|
|
// TQt include files
|
|
|
|
#include <tqcheckbox.h>
|
|
|
|
#include <tqcombobox.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqframe.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqlistbox.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqtextedit.h>
|
|
|
|
#include <tqtextcodec.h>
|
|
|
|
// KDE include files
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <ktempfile.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kstringhandler.h>
|
|
|
|
#include <kcombobox.h>
|
|
|
|
#include <kcharsets.h>
|
|
|
|
// Project specific include files
|
|
|
|
#include "cvsdialog.h"
|
|
|
|
|
|
|
|
|
|
|
|
CVSDialog::CVSDialog( CVS::Command cmd, TQWidget * parent, KSharedConfig* config )
|
|
|
|
: KDialog( parent, "CVSDIALOG", true ), m_config( config )
|
|
|
|
{
|
|
|
|
_cmd = cmd;
|
|
|
|
p=0L;
|
|
|
|
setCaption( i18n( "CVS Dialog" ) );
|
|
|
|
|
|
|
|
TQString temp;
|
|
|
|
|
|
|
|
TQVBoxLayout * tqlayout = new TQVBoxLayout( this, 6, 6, "MAIN LAYOUT" );
|
|
|
|
|
|
|
|
// Set the label's text depending on the CVS command.
|
|
|
|
switch ( cmd ) {
|
|
|
|
case CVS::Update:
|
|
|
|
temp = i18n( "Update the following files:" );
|
|
|
|
break;
|
|
|
|
case CVS::Commit:
|
|
|
|
temp = i18n( "Commit the following files:" );
|
|
|
|
break;
|
|
|
|
case CVS::Status:
|
|
|
|
temp = i18n( "Get status for the following files:" );
|
|
|
|
break;
|
|
|
|
case CVS::Diff:
|
|
|
|
temp = i18n( "Get diff for the following files:" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tqlayout->addWidget( new TQLabel( temp, this ) );
|
|
|
|
|
|
|
|
// Widget for showing the list of files.
|
|
|
|
filebox = new TQListBox( this );
|
|
|
|
tqlayout->addWidget( filebox );
|
|
|
|
|
|
|
|
// Add special widgets for 'cvs commit'.
|
|
|
|
if ( cmd == CVS::Commit ) {
|
|
|
|
TQLabel * label;
|
|
|
|
|
|
|
|
// Combobox for displaying old log messages.
|
|
|
|
label = new TQLabel( i18n( "&Old messages:" ), this );
|
|
|
|
oldMessages = new TQComboBox( this );
|
|
|
|
oldMessages->setDuplicatesEnabled( false );
|
|
|
|
label->setBuddy( oldMessages );
|
|
|
|
tqlayout->addWidget( label );
|
|
|
|
tqlayout->addWidget( oldMessages );
|
|
|
|
|
|
|
|
// Textfield for entering a log message.
|
|
|
|
label = new TQLabel( i18n( "&Log message:" ), this );
|
|
|
|
logedit = new TQTextEdit( this );
|
|
|
|
label->setBuddy( logedit );
|
|
|
|
tqlayout->addWidget( label );
|
|
|
|
tqlayout->addWidget( logedit );
|
|
|
|
|
|
|
|
label = new TQLabel( i18n( "E&ncoding:" ), this );
|
|
|
|
m_encodingComboBox = new KComboBox( this );
|
|
|
|
label->setBuddy( m_encodingComboBox );
|
|
|
|
tqlayout->addWidget( label );
|
|
|
|
tqlayout->addWidget( m_encodingComboBox );
|
|
|
|
TQStringList encodingList;
|
|
|
|
// The last encoding will be added at the top of the list, when the seetings will be read.
|
|
|
|
encodingList << i18n( "Descriptive encoding name", "Recommended ( %1 )" ).arg( "UTF-8" );
|
|
|
|
encodingList << i18n( "Descriptive encoding name", "Locale ( %1 )" ).arg( TQTextCodec::codecForLocale()->mimeName() );
|
|
|
|
encodingList += KGlobal::charsets()->descriptiveEncodingNames();
|
|
|
|
m_encodingComboBox->insertStringList( encodingList );
|
|
|
|
|
|
|
|
connect( oldMessages, TQT_SIGNAL( activated( int ) ),
|
|
|
|
this, TQT_SLOT( slotComboActivated( int ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQHBoxLayout * buttons = new TQHBoxLayout( 0, 0, 6, "BUTTON LAYOUT" );
|
|
|
|
// Add special buttons for 'cvs commit'.
|
|
|
|
if ( cmd == CVS::Commit ) {
|
|
|
|
autoAddBox = new TQCheckBox( i18n( "Auto&matically add files if necessary" ), this );
|
|
|
|
buttons->addWidget( autoAddBox );
|
|
|
|
}
|
|
|
|
buttons->addItem( new TQSpacerItem( 1, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum ) );
|
|
|
|
|
|
|
|
// Set the main button's text depending on the CVS comand.
|
|
|
|
switch ( cmd ) {
|
|
|
|
case CVS::Update:
|
|
|
|
temp = i18n( "&Update" );
|
|
|
|
break;
|
|
|
|
case CVS::Commit:
|
|
|
|
temp = i18n( "&Commit" );
|
|
|
|
break;
|
|
|
|
case CVS::Status:
|
|
|
|
temp = i18n( "&Get Status" );
|
|
|
|
break;
|
|
|
|
case CVS::Diff:
|
|
|
|
temp = i18n( "&Get Diff" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mainBtn = new TQPushButton( temp, this );
|
|
|
|
mainBtn->setDefault( true );
|
|
|
|
buttons->addWidget( mainBtn );
|
|
|
|
|
|
|
|
cancelBtn = new TQPushButton( i18n( "C&ancel" ), this );
|
|
|
|
buttons->addWidget( cancelBtn );
|
|
|
|
tqlayout->addLayout( buttons );
|
|
|
|
|
|
|
|
TQFrame * line = new TQFrame( this );
|
|
|
|
line->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
|
|
|
|
tqlayout->addWidget( line );
|
|
|
|
|
|
|
|
tqlayout->addWidget( new TQLabel( i18n( "Command output:" ), this ) );
|
|
|
|
|
|
|
|
output = new TQTextEdit( this );
|
|
|
|
output->setReadOnly( true );
|
|
|
|
tqlayout->addWidget( output );
|
|
|
|
|
|
|
|
resize( TQSize( 600, 450 ).expandedTo( minimumSizeHint( ) ) );
|
|
|
|
|
|
|
|
if ( cmd == CVS::Commit )
|
|
|
|
logedit->setFocus( );
|
|
|
|
|
|
|
|
readSettings( );
|
|
|
|
|
|
|
|
connect( mainBtn, TQT_SIGNAL( clicked( ) ), this, TQT_SLOT( slotExecuteCommand( ) ) );
|
|
|
|
connect( cancelBtn, TQT_SIGNAL( clicked( ) ), this, TQT_SLOT( reject( ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::slotComboActivated( int index )
|
|
|
|
{
|
|
|
|
if ( index < 0 || index >= m_logMessages.count() )
|
|
|
|
return;
|
|
|
|
logedit->setText( m_logMessages[index] );
|
|
|
|
}
|
|
|
|
|
|
|
|
CVSDialog::~CVSDialog()
|
|
|
|
{
|
|
|
|
delete p;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::accept( )
|
|
|
|
{
|
|
|
|
saveSettings( );
|
|
|
|
KDialog::accept( );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::setFiles( const TQStringList& files )
|
|
|
|
{
|
|
|
|
filebox->insertStringList( files );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::setCommandLine( const TQString& command )
|
|
|
|
{
|
|
|
|
_commandLine = command;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::setAddCommand( const TQString& command )
|
|
|
|
{
|
|
|
|
_addCommand = command;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::slotExecuteCommand( )
|
|
|
|
{
|
|
|
|
// Nothing to do here.
|
|
|
|
if ( _commandLine.isEmpty( ) ) return;
|
|
|
|
|
|
|
|
kdDebug() << "Preparing KProcess" << endl;
|
|
|
|
|
|
|
|
// Create a new shell process
|
|
|
|
p = new KProcess;
|
|
|
|
p->setUseShell( true, "/bin/sh" );
|
|
|
|
|
|
|
|
if ( _cmd == CVS::Commit ) {
|
|
|
|
// Include command for 'cvs add'.
|
|
|
|
if ( autoAddBox->isChecked( ) && !_addCommand.isEmpty( ) )
|
|
|
|
_commandLine.prepend( _addCommand );
|
|
|
|
|
|
|
|
const TQString msg( logedit->text() );
|
|
|
|
|
|
|
|
if ( msg.isEmpty() )
|
|
|
|
{
|
|
|
|
// A good commit should never have an empty comment, so ask the user if he really wants it.
|
|
|
|
const int res = KMessageBox::warningContinueCancel( this,
|
|
|
|
i18n( "The commit log message is empty. Do you want to continue?" ) );
|
|
|
|
if ( res != KMessageBox::Continue )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_encoding = KGlobal::charsets()->encodingForName( m_encodingComboBox->currentText() );
|
|
|
|
TQTextCodec* codec = TQTextCodec::codecForName( m_encoding.utf8() );
|
|
|
|
|
|
|
|
if ( !codec )
|
|
|
|
{
|
|
|
|
KMessageBox::error( this, i18n( "Cannot find encoding: %1" ).arg( m_encoding ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if ( !codec->canEncode( msg ) )
|
|
|
|
{
|
|
|
|
const int res = KMessageBox::warningContinueCancel( this,
|
|
|
|
i18n( "The commit log message cannot be encoded in the selected encoding: %1.\n"
|
|
|
|
"Do you want to continue?" ).arg( m_encoding ) );
|
|
|
|
if ( res != KMessageBox::Continue )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the commit log message from the input field to a temporary file
|
|
|
|
m_tempFile = new KTempFile;
|
|
|
|
m_tempFile->setAutoDelete( true );
|
|
|
|
TQTextStream* stream = m_tempFile->textStream();
|
|
|
|
if ( !stream )
|
|
|
|
{
|
|
|
|
kdError() << "Could not create TQTextStream for file " << m_tempFile->name();
|
|
|
|
delete m_tempFile;
|
|
|
|
m_tempFile = 0;
|
|
|
|
KMessageBox::error( this, i18n( "Cannot open temporary file for writing. Aborting.") );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
stream->setCodec( codec );
|
|
|
|
*stream << msg;
|
|
|
|
m_tempFile->close();
|
|
|
|
|
|
|
|
if ( m_tempFile->status() )
|
|
|
|
{
|
|
|
|
kdError() << "Could not write to file " << m_tempFile->name();
|
|
|
|
delete m_tempFile;
|
|
|
|
m_tempFile = 0;
|
|
|
|
KMessageBox::error( this, i18n( "Cannot write to temporary file. Aborting.") );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change the command line to have the real name of the temporary file
|
|
|
|
_commandLine.replace( "@LOG@FILE@", KProcess::quote( m_tempFile->name() ) );
|
|
|
|
|
|
|
|
// Update the list of log messages
|
|
|
|
if ( !msg.isEmpty() ) {
|
|
|
|
const TQString shortLog = KStringHandler::csqueeze( msg, 80 );
|
|
|
|
|
|
|
|
|
|
|
|
// Remove the message from the list if it already exists
|
|
|
|
m_logMessages.remove( msg );
|
|
|
|
// Prepend the current message to the list
|
|
|
|
m_logMessages.prepend( msg );
|
|
|
|
|
|
|
|
// At this time of the process, we do not need the combobox anymore, so we do not squeeze the changed strings.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the KProcess' command line.
|
|
|
|
*p << _commandLine;
|
|
|
|
|
|
|
|
connect( p, TQT_SIGNAL( receivedStdout( KProcess*, char*, int ) ),
|
|
|
|
this, TQT_SLOT ( slotProcessStdout( KProcess*, char*, int ) ) );
|
|
|
|
connect( p, TQT_SIGNAL( receivedStderr( KProcess*, char*, int ) ),
|
|
|
|
this, TQT_SLOT ( slotProcessStderr( KProcess*, char*, int ) ) );
|
|
|
|
connect( p, TQT_SIGNAL( processExited( KProcess* ) ),
|
|
|
|
this, TQT_SLOT( slotProcessExited( KProcess* ) ) );
|
|
|
|
|
|
|
|
output->append( i18n( "[ Starting command ]" ) );
|
|
|
|
|
|
|
|
if ( p->start( KProcess::NotifyOnExit, KProcess::Communication( KProcess::AllOutput ) ) ) {
|
|
|
|
// Disable the main button (and the log edit if in commit mode) to
|
|
|
|
// indicate activity.
|
|
|
|
mainBtn->setEnabled( false );
|
|
|
|
if ( _cmd == CVS::Commit )
|
|
|
|
logedit->setEnabled( false );
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
kdError() << "Process could not be started." << endl;
|
|
|
|
KMessageBox::error( this, i18n( "The process could not be started." ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::slotProcessStdout( KProcess*, char * buffer, int len )
|
|
|
|
{
|
|
|
|
output->append( TQString::fromLocal8Bit( buffer, len ) );
|
|
|
|
// Set the cursor's position at the end of the output.
|
|
|
|
output->setCursorPosition( output->lines( ), 0 );
|
|
|
|
|
|
|
|
// If the command is 'cvs status' or 'cvs diff' collect the output of stdout.
|
|
|
|
if ( (_cmd == CVS::Status) || (_cmd == CVS::Diff) )
|
|
|
|
_statusOutput += TQString::fromLocal8Bit( buffer, len );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::slotProcessStderr( KProcess*, char * buffer, int len )
|
|
|
|
{
|
|
|
|
// If an error occurs while executing the command display stderr in
|
|
|
|
// another color.
|
|
|
|
TQColor oldColor( output->color( ) );
|
|
|
|
output->setColor( TQt::red );
|
|
|
|
output->append( TQString::fromLocal8Bit( buffer, len ) );
|
|
|
|
output->setColor( oldColor );
|
|
|
|
output->setCursorPosition( output->lines( ), 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::slotProcessExited( KProcess * p )
|
|
|
|
{
|
|
|
|
if ( p->exitStatus( ) )
|
|
|
|
output->append( i18n( "[ Exited with status %1 ]" ).arg( p->exitStatus( ) ) );
|
|
|
|
else
|
|
|
|
output->append( i18n( "[ Finished ]" ) );
|
|
|
|
|
|
|
|
// The command is finished. Now we can reconnect the main button.
|
|
|
|
disconnect( mainBtn, 0, 0, 0 );
|
|
|
|
if ( _cmd == CVS::Diff )
|
|
|
|
mainBtn->setText( i18n( "&Show Diff" ) );
|
|
|
|
else
|
|
|
|
mainBtn->setText( i18n( "&Close" ) );
|
|
|
|
connect( mainBtn, TQT_SIGNAL( clicked( ) ), this, TQT_SLOT( accept( ) ) );
|
|
|
|
|
|
|
|
// Reenable the button and the log edit now that the process is finished.
|
|
|
|
mainBtn->setEnabled( true );
|
|
|
|
if ( _cmd == CVS::Commit )
|
|
|
|
logedit->setEnabled( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString CVSDialog::statusOutput( )
|
|
|
|
{
|
|
|
|
return _statusOutput;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::readSettings( )
|
|
|
|
{
|
|
|
|
KSharedConfig * config = m_config;
|
|
|
|
config->setGroup( "CVSSupport" );
|
|
|
|
|
|
|
|
if ( _cmd == CVS::Commit ) {
|
|
|
|
autoAddBox->setChecked( config->readBoolEntry( "AutoAddFiles", true ) );
|
|
|
|
|
|
|
|
// Fill the combobox with old messages.
|
|
|
|
m_logMessages.clear();
|
|
|
|
m_squeezedLogMessages.clear();
|
|
|
|
for ( int cnt = 0; cnt < 10; cnt++ )
|
|
|
|
if ( config->hasKey( TQString( "CommitLogMessage%1" ).arg( cnt ) ) )
|
|
|
|
{
|
|
|
|
const TQString logMessage = config->readEntry( TQString( "CommitLogMessage%1" ).arg( cnt ) );
|
|
|
|
if ( !logMessage.isEmpty() )
|
|
|
|
{
|
|
|
|
// If the message is too long, cut it to 80 characters (or the combo box becomes too wide)
|
|
|
|
// ### FIXME: if the string matches the squeezed 80 chars, it might overwrite another entry
|
|
|
|
const TQString shortLog = KStringHandler::csqueeze( logMessage );
|
|
|
|
m_logMessages.append( logMessage );
|
|
|
|
m_squeezedLogMessages.append( shortLog );
|
|
|
|
oldMessages->insertItem( shortLog );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_encoding = config->readEntry( "CVSEncoding", "UTF-8" );
|
|
|
|
m_encodingComboBox->insertItem( i18n( "Descriptive encoding name", "Last choice ( %1 )" ).arg( m_encoding ), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSDialog::saveSettings( )
|
|
|
|
{
|
|
|
|
KSharedConfig * config = m_config;
|
|
|
|
config->setGroup( "CVSSupport" );
|
|
|
|
if ( _cmd == CVS::Commit ) {
|
|
|
|
config->writeEntry( "AutoAddFiles", autoAddBox->isChecked( ) );
|
|
|
|
|
|
|
|
// Write the log messages to the config file.
|
|
|
|
int cnt = 0;
|
|
|
|
TQStringList::const_iterator it;
|
|
|
|
for ( it = m_logMessages.constBegin( ); it != m_logMessages.constEnd( ) && cnt < 10 ; ++it, ++cnt )
|
|
|
|
config->writeEntry( TQString( "CommitLogMessage%1" ).arg( cnt ), *it );
|
|
|
|
|
|
|
|
config->writeEntry( "CVSEncoding", m_encoding );
|
|
|
|
}
|
|
|
|
m_config->sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "cvsdialog.moc"
|