diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | bd9e6617827818fd043452c08c606f07b78014a0 (patch) | |
tree | 425bb4c3168f9c02f10150f235d2cb998dcc6108 /kbabel/catalogmanager/libcvs | |
download | tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.tar.gz tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdesdk@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kbabel/catalogmanager/libcvs')
-rw-r--r-- | kbabel/catalogmanager/libcvs/Makefile.am | 11 | ||||
-rw-r--r-- | kbabel/catalogmanager/libcvs/cvsdialog.cpp | 423 | ||||
-rw-r--r-- | kbabel/catalogmanager/libcvs/cvsdialog.h | 158 | ||||
-rw-r--r-- | kbabel/catalogmanager/libcvs/cvshandler.cpp | 398 | ||||
-rw-r--r-- | kbabel/catalogmanager/libcvs/cvshandler.h | 114 | ||||
-rw-r--r-- | kbabel/catalogmanager/libcvs/cvsresources.h | 41 |
6 files changed, 1145 insertions, 0 deletions
diff --git a/kbabel/catalogmanager/libcvs/Makefile.am b/kbabel/catalogmanager/libcvs/Makefile.am new file mode 100644 index 00000000..e3e4f9ac --- /dev/null +++ b/kbabel/catalogmanager/libcvs/Makefile.am @@ -0,0 +1,11 @@ +noinst_LTLIBRARIES = libcatalogmanagercvs.la + +# set the include path for X, qt and KDE +INCLUDES = -I.. -I../../common $(all_includes) + +libcatalogmanagercvs_la_SOURCES = cvshandler.cpp cvsdialog.cpp + +noinst_HEADERS = cvshandler.h cvsdialog.h cvsresources.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO diff --git a/kbabel/catalogmanager/libcvs/cvsdialog.cpp b/kbabel/catalogmanager/libcvs/cvsdialog.cpp new file mode 100644 index 00000000..af76d9d0 --- /dev/null +++ b/kbabel/catalogmanager/libcvs/cvsdialog.cpp @@ -0,0 +1,423 @@ +/* **************************************************************************** + 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 Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +// Qt include files +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qfileinfo.h> +#include <qframe.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlistbox.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qtextedit.h> +#include <qtextcodec.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, QWidget * parent, KSharedConfig* config ) + : KDialog( parent, "CVSDIALOG", true ), m_config( config ) +{ + _cmd = cmd; + p=0L; + setCaption( i18n( "CVS Dialog" ) ); + + QString temp; + + QVBoxLayout * layout = new QVBoxLayout( 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; + } + layout->addWidget( new QLabel( temp, this ) ); + + // Widget for showing the list of files. + filebox = new QListBox( this ); + layout->addWidget( filebox ); + + // Add special widgets for 'cvs commit'. + if ( cmd == CVS::Commit ) { + QLabel * label; + + // Combobox for displaying old log messages. + label = new QLabel( i18n( "&Old messages:" ), this ); + oldMessages = new QComboBox( this ); + oldMessages->setDuplicatesEnabled( false ); + label->setBuddy( oldMessages ); + layout->addWidget( label ); + layout->addWidget( oldMessages ); + + // Textfield for entering a log message. + label = new QLabel( i18n( "&Log message:" ), this ); + logedit = new QTextEdit( this ); + label->setBuddy( logedit ); + layout->addWidget( label ); + layout->addWidget( logedit ); + + label = new QLabel( i18n( "E&ncoding:" ), this ); + m_encodingComboBox = new KComboBox( this ); + label->setBuddy( m_encodingComboBox ); + layout->addWidget( label ); + layout->addWidget( m_encodingComboBox ); + QStringList 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( QTextCodec::codecForLocale()->mimeName() ); + encodingList += KGlobal::charsets()->descriptiveEncodingNames(); + m_encodingComboBox->insertStringList( encodingList ); + + connect( oldMessages, SIGNAL( activated( int ) ), + this, SLOT( slotComboActivated( int ) ) ); + } + + QHBoxLayout * buttons = new QHBoxLayout( 0, 0, 6, "BUTTON LAYOUT" ); + // Add special buttons for 'cvs commit'. + if ( cmd == CVS::Commit ) { + autoAddBox = new QCheckBox( i18n( "Auto&matically add files if necessary" ), this ); + buttons->addWidget( autoAddBox ); + } + buttons->addItem( new QSpacerItem( 1, 0, QSizePolicy::Expanding, QSizePolicy::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 QPushButton( temp, this ); + mainBtn->setDefault( true ); + buttons->addWidget( mainBtn ); + + cancelBtn = new QPushButton( i18n( "C&ancel" ), this ); + buttons->addWidget( cancelBtn ); + layout->addLayout( buttons ); + + QFrame * line = new QFrame( this ); + line->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + layout->addWidget( line ); + + layout->addWidget( new QLabel( i18n( "Command output:" ), this ) ); + + output = new QTextEdit( this ); + output->setReadOnly( true ); + layout->addWidget( output ); + + resize( QSize( 600, 450 ).expandedTo( minimumSizeHint( ) ) ); + + if ( cmd == CVS::Commit ) + logedit->setFocus( ); + + readSettings( ); + + connect( mainBtn, SIGNAL( clicked( ) ), this, SLOT( slotExecuteCommand( ) ) ); + connect( cancelBtn, SIGNAL( clicked( ) ), this, 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 QStringList& files ) +{ + filebox->insertStringList( files ); +} + +void CVSDialog::setCommandLine( const QString& command ) +{ + _commandLine = command; +} + +void CVSDialog::setAddCommand( const QString& 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 QString 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() ); + QTextCodec* codec = QTextCodec::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 ); + QTextStream* stream = m_tempFile->textStream(); + if ( !stream ) + { + kdError() << "Could not create QTextStream 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 QString 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, SIGNAL( receivedStdout( KProcess*, char*, int ) ), + this, SLOT ( slotProcessStdout( KProcess*, char*, int ) ) ); + connect( p, SIGNAL( receivedStderr( KProcess*, char*, int ) ), + this, SLOT ( slotProcessStderr( KProcess*, char*, int ) ) ); + connect( p, SIGNAL( processExited( KProcess* ) ), + this, 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( QString::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 += QString::fromLocal8Bit( buffer, len ); +} + +void CVSDialog::slotProcessStderr( KProcess*, char * buffer, int len ) +{ + // If an error occurs while executing the command display stderr in + // another color. + QColor oldColor( output->color( ) ); + output->setColor( Qt::red ); + output->append( QString::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, SIGNAL( clicked( ) ), this, 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 ); +} + +QString 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( QString( "CommitLogMessage%1" ).arg( cnt ) ) ) + { + const QString logMessage = config->readEntry( QString( "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 QString 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; + QStringList::const_iterator it; + for ( it = m_logMessages.constBegin( ); it != m_logMessages.constEnd( ) && cnt < 10 ; ++it, ++cnt ) + config->writeEntry( QString( "CommitLogMessage%1" ).arg( cnt ), *it ); + + config->writeEntry( "CVSEncoding", m_encoding ); + } + m_config->sync(); +} + +#include "cvsdialog.moc" diff --git a/kbabel/catalogmanager/libcvs/cvsdialog.h b/kbabel/catalogmanager/libcvs/cvsdialog.h new file mode 100644 index 00000000..658e9883 --- /dev/null +++ b/kbabel/catalogmanager/libcvs/cvsdialog.h @@ -0,0 +1,158 @@ +/* **************************************************************************** + 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 Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef CVSDIALOG_H +#define CVSDIALOG_H + +// KDE include files +#include <kdialog.h> +// Project specific include files +#include "cvsresources.h" +// Forwarding Qt classes +class QCheckBox; +class QComboBox; +class QListBox; +class QPushButton; +class QString; +class QStringList; +class QTextEdit; +// Forwarding KDE classes +class KProcess; +class KTempFile; +class KComboBox; + +/** + * This class represents the dialog which is used for executing CVS commands + * in KBabel's Catalog Manager. The dialog shows the list of files to be + * processed as well as the output from the command. + * + * In Commit mode there is also an option for automatically executing + * 'cvs add' if necessary. + * + * @short Dialog for CVS support in Catalog Manager + * @author Marco Wegner <mail@marcowegner.de> + */ +class CVSDialog : public KDialog +{ + Q_OBJECT + + public: + /** + * Constructor for creating the dialog. + * @param cmd The type of command to be executed. + */ + CVSDialog( CVS::Command cmd, QWidget * parent, KSharedConfig* config ); + ~CVSDialog(); + /** + * Set the list of files which will be used for the CVS command. + * @param files The list of files. + */ + void setFiles( const QStringList& files ); + /** + * Set the command line for the execution of the CVS command. + * @param command The command line. + */ + void setCommandLine( const QString& command ); + /** + * Set the command line for adding files to the CVS repository. + * This method is only used together with a 'cvs commit' for automatically + * adding files which are not yet in the repository. + * @param command The command line. + */ + void setAddCommand( const QString& command ); + /** + * Return the output of a 'cvs status' command. + * @returns The complete output. + */ + QString statusOutput( ); + + protected: + /** + * This method is overwritten so that the settings can be saved after + * pressing the 'Close' button. + */ + virtual void accept( ); + /** Read the dialog's settings. */ + void readSettings( ); + /** Save the dialog's settings. */ + void saveSettings( ); + + protected slots: + /** Slot for executing the CVS Command. */ + void slotExecuteCommand( ); + /** Slot for processing the stdout of the CVS Command. */ + void slotProcessStdout( KProcess*, char * buffer, int len ); + /** Slot for processing the stderr of the CVS Command. */ + void slotProcessStderr( KProcess*, char * buffer, int len ); + /** Slot for post-processing after the CVS command is fninished. */ + void slotProcessExited( KProcess * p ); + /// Slot for combox having been activated + void slotComboActivated( int ); + + private: + CVS::Command _cmd; + + QPushButton * mainBtn; + QPushButton * cancelBtn; + QListBox * filebox; + QComboBox * oldMessages; + QTextEdit * logedit; + QTextEdit * output; + QCheckBox * autoAddBox; + + KProcess * p; + + QString _commandLine; + QString _addCommand; + QString _statusOutput; + + /// Log messages (long version) + QStringList m_logMessages; + /// Log messages (short version) + QStringList m_squeezedLogMessages; + + /// Temporary file (for commits) + KTempFile* m_tempFile; + + /// Encoding for the commit log message + QString m_encoding; + + /// Combo box for the encoding + KComboBox* m_encodingComboBox; + + /// Configuration data (of the KBabel project) + KSharedConfig* m_config; +}; + +#endif // CVSDIALOG_H diff --git a/kbabel/catalogmanager/libcvs/cvshandler.cpp b/kbabel/catalogmanager/libcvs/cvshandler.cpp new file mode 100644 index 00000000..d3f2ae18 --- /dev/null +++ b/kbabel/catalogmanager/libcvs/cvshandler.cpp @@ -0,0 +1,398 @@ +/* **************************************************************************** + 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 Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +// System include files +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> +// Qt include files +#include <qdir.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qregexp.h> +#include <qstring.h> +#include <qstringlist.h> +// KDE include files +#include <kapplication.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ktempfile.h> +// project specific include files +#include "cvshandler.h" + + +CVSHandler::CVSHandler( const QString& poBaseDir, const QString& potBaseDir ) +{ + setPOBaseDir( poBaseDir ); + setPOTBaseDir( potBaseDir ); + _autoUpdateTemplates = false; +} + +void CVSHandler::setPOBaseDir( const QString& dir ) +{ + // check if 'CVS/Entries' exists in the PO base directory + if ( QFileInfo( dir + "/CVS/Entries" ).exists( ) ) { + _isPORepository = true; + _poBaseDir = dir; + } else + _isPORepository = false; + emit signalIsPORepository( _isPORepository ); +} + +void CVSHandler::setPOTBaseDir( const QString& dir ) +{ + // check if 'CVS/Entries' exists in the POT base directory + if ( QFileInfo( dir + "/CVS/Entries" ).exists( ) ) { + _isPOTRepository = true; + _potBaseDir = dir; + } else + _isPOTRepository = false; + emit signalIsPOTRepository( _isPOTRepository ); +} + +QString CVSHandler::fileStatus( const FileStatus status ) const +{ + switch ( status ) { + case NO_REPOSITORY: + return i18n( "No CVS repository" ); + break; + case NOT_IN_CVS: + return i18n( "Not in CVS" ); + break; + case LOCALLY_ADDED: + return i18n( "Locally added" ); + break; + case LOCALLY_REMOVED: + return i18n( "Locally removed" ); + break; + case LOCALLY_MODIFIED: + return i18n( "Locally modified" ); + break; + case UP_TO_DATE: + return i18n( "Up-to-date" ); + break; + case CONFLICT: + return i18n( "Conflict" ); + break; + default: + return i18n( "Unknown" ); + break; + } +} + +CVSHandler::FileStatus CVSHandler::fstatus( const QString& filename ) const +{ + // no valid repository + if ( !_isPORepository ) + return NO_REPOSITORY; + + QString fn( filename ); + fn = fn.remove( QRegExp( "/$" ) ); + + QFileInfo info( fn ); + + // check if 'CVS/Entries' exists and can be read + QFile entries( info.dir( true ).path( ) + "/CVS/Entries" ); + if ( !entries.open( IO_ReadOnly ) ) + return NOT_IN_CVS; // we already know that it's a repository + + // ### FIXME: it does not take care of CVS/Entries.Log + // a line in CVS/Entries has the following format: + // [D]/NAME/REVISION/[CONFLICT+]TIMESTAMP/OPTIONS/TAGDATE + QRegExp rx( QString( "^D?/%1/" ).arg( info.fileName( ) ) ); + + QString temp; + QTextStream stream( &entries ); + + bool isInRepository = false; + while ( !stream.atEnd() ) { + temp = stream.readLine( ); + if ( temp.find( rx ) == 0 ) { + isInRepository = true; + break; + } + } + entries.close( ); + + // no entry found + if ( !isInRepository ) + return NOT_IN_CVS; + + const QStringList fields = QStringList::split( '/', temp, true ); + // bool isDir = ( fields[0] == "D" ); + const QString cvsname( fields[1] ); + const QString revision( fields[2] ); + const QString timestamp( fields[3] ); + // ignore the other fields for now + + if ( revision == "0" && timestamp == "dummy timestamp" ) + return LOCALLY_ADDED; + if ( revision.startsWith( "-" ) && timestamp == "dummy timestamp" ) + return LOCALLY_REMOVED; + + // check for conflicts + if ( timestamp.find( '+' ) >= 0 ) + return CONFLICT; + + // calculate the UTC time from the file's last modified date + struct stat st; + lstat( QFile::encodeName(fn), &st ); + struct tm * tm_p = gmtime( &st.st_mtime ); + QString ftime = QString( asctime( tm_p ) ); + ftime.truncate( ftime.length( ) - 1 ); + if ( ftime != timestamp ) + return LOCALLY_MODIFIED; + + return UP_TO_DATE; +} + +QString CVSHandler::cvsStatus( const QString& filename ) const +{ + return map[filename]; +} + +void CVSHandler::execCVSCommand( QWidget* parent, CVS::Command cmd, const QString& filename, bool templates, KSharedConfig* config ) +{ + if ( !_isPORepository ) { + // This message box should never be visible but who knows... ;-) + KMessageBox::sorry( parent, i18n( "This is not a valid CVS repository. " + "The CVS commands cannot be executed." ) ); + return; + } + + QFileInfo info( filename ); + if ( !info.isDir( ) ) { + execCVSCommand( parent, cmd, QStringList( filename ), templates, config ); + return; + } + + // ### FIXME: instead of making a QString, use KProcess directly, so that it cares about quoting. + // ### FIXME: use KProcess::setWorkingDirectory instead of using "cd" (therefore allowing to use KProcess without a shell.) + // it's a dir + QString command( "cd " + filename + " && cvs " ); + switch ( cmd ) { + case CVS::Update: + command += "update -dP"; + break; + case CVS::Commit: + // The cvs client does not care about the encoding, so we cannot set anything here + command += "commit -F @LOG@FILE@"; + checkToAdd( QStringList( filename ) ); + break; + case CVS::Status: + command += "status"; + break; + case CVS::Diff: + command += "diff"; + break; + } + + showDialog( parent, cmd, QStringList( filename ), command, config ); +} + +void CVSHandler::execCVSCommand( QWidget* parent, CVS::Command cmd, const QStringList& files, bool templates, KSharedConfig* config ) +{ + if ( !_isPORepository ) { + // This message box should never be visible but who knows... ;-) + KMessageBox::sorry( parent, i18n( "This is not a valid CVS repository. " + "The CVS commands cannot be executed." ) ); + return; + } + + // ### FIXME: instead of making a QString, use KProcess directly, so that it cares about quoting. + // ### FIXME: use KProcess::setWorkingDirectory instead of using "cd" (therefore allowing to use KProcess without a shell.) + QString command("cd " + (templates ? _potBaseDir : _poBaseDir) + " && cvs "); + switch ( cmd ) { + case CVS::Update: + command += "update -dP"; + break; + case CVS::Commit: + command += "commit -F @LOG@FILE@"; + checkToAdd( files ); + break; + case CVS::Status: + command += "status"; + break; + case CVS::Diff: + command += "diff"; + break; + } + + QRegExp rx; + if (templates) + rx.setPattern(_potBaseDir + "/?"); + else + rx.setPattern(_poBaseDir + "/?"); + + QStringList::ConstIterator it; + for ( it = files.begin( ); it != files.end( ); ++it ) { + QString temp = *it; + temp.remove(rx); + command += " \'" + temp + "\'"; + } + + showDialog( parent, cmd, files, command, config ); +} + +void CVSHandler::setAutoUpdateTemplates( bool update ) +{ + _autoUpdateTemplates = update; +} + +void CVSHandler::showDialog( QWidget* parent, CVS::Command cmd, const QStringList& files, const QString& commandLine, KSharedConfig* config ) +{ + CVSDialog * dia = new CVSDialog( cmd, parent, config ); + dia->setFiles( files ); + dia->setCommandLine( commandLine ); + if ( cmd == CVS::Commit ) { + dia->setAddCommand( _addCommand ); + } + + if ( dia->exec( ) == KDialog::Accepted ) { + if ( cmd == CVS::Status ) + processStatusOutput( dia->statusOutput( ) ); + if ( cmd == CVS::Diff ) + processDiff( dia->statusOutput( ) ); + } + + delete dia; + + // file status display update necessary in Catalog Manager + if ( cmd == CVS::Commit ) + emit signalFilesCommitted( files ); +} + +void CVSHandler::checkToAdd( const QStringList& files ) +{ + if ( files.isEmpty( ) ) + return; + + QStringList toBeAdded; + + QStringList::ConstIterator it; + for ( it = files.begin( ); it != files.end( ); ++it ) { + // check for every entry if it needs to be added + if ( fstatus( *it ) == NOT_IN_CVS ) { + QFileInfo info( *it ); + QString temp; // will hold the dir path + if ( info.isDir( ) ) { + toBeAdded << *it; + temp = *it; + } else { + toBeAdded << *it; + temp = QFileInfo( *it ).dirPath( true ); + } + // check recursivlely if parent dirs have to be added as well + while ( fstatus( temp ) == NOT_IN_CVS && toBeAdded.findIndex( temp ) == -1 ) { + toBeAdded << temp; + temp = QFileInfo( temp ).dirPath( true ); + } + } + } + + // remove an old command + _addCommand.setLength( 0 ); + + // make sure the diectories are added before the files + toBeAdded.sort( ); + + // create a command line for adding the files and dirs + for ( it = toBeAdded.begin( ); it != toBeAdded.end( ); ++it ) { + QFileInfo info( *it ); + _addCommand += "cd " + info.dirPath( true ) + " && cvs add " + info.fileName( ) + "; "; + } +} + +void CVSHandler::processStatusOutput( const QString& status ) +{ + if ( !_isPORepository ) + return; + + // at first we need to extract the name of the base directory on the server + QFile f( _poBaseDir + "/CVS/Root" ); + if ( !f.open( IO_ReadOnly ) ) + return; + + QTextStream stream( &f ); + // extract the string after the last colon in the first line + QString basedir = stream.readLine( ).section( ':', -1 ); + + f.close( ); + + // divide the complete status output in little chunks for every file + QStringList entries = QStringList::split( QRegExp( "={67,67}" ), status ); + QStringList::Iterator it; + for ( it = entries.begin( ); it != entries.end( ); ++it ) { + QString entr = *it; + // translate the filename from repository to local + QRegExp rx( basedir + ".*,v" ); + int pos = entr.find( rx ); + QString file = _poBaseDir + entr.mid( pos + basedir.length( ), + rx.matchedLength( ) - basedir.length( ) - 2 ); + + entr = "<qt>" + entr + "</qt>"; + + // TODO: do some markup + + map.replace( file, entr ); + } +} + +void CVSHandler::processDiff( QString output ) +{ + output.remove( QRegExp( "\\[ .* \\]$" )); + output.remove( QRegExp( "^" + i18n("[ Starting command ]" ).replace("[","\\[").replace("]","\\]"))); + + KTempFile tmpFile; + *(tmpFile.textStream()) << output; + tmpFile.close(); + + QString error; + if ( KApplication::startServiceByName( "Kompare", tmpFile.name(), &error ) ) + KMessageBox::error( 0, error ); +} + +bool CVSHandler::isConsideredModified( const FileStatus status ) const +{ + /* + * A file is modified if it is either: + * - locally modified for CVS + * - directory under CVS control but not the file + */ + return status == LOCALLY_MODIFIED || status == NOT_IN_CVS; +} + + + +#include "cvshandler.moc" diff --git a/kbabel/catalogmanager/libcvs/cvshandler.h b/kbabel/catalogmanager/libcvs/cvshandler.h new file mode 100644 index 00000000..44777aa3 --- /dev/null +++ b/kbabel/catalogmanager/libcvs/cvshandler.h @@ -0,0 +1,114 @@ +/* **************************************************************************** + 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 Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef CVSHANDLER_H +#define CVSHANDLER_H + +// Qt include files +#include <qmap.h> +#include <qobject.h> +// Project specific include files +#include "cvsdialog.h" +#include "cvsresources.h" +// Forwarding Qt classes +class QString; +class QStringList; +class QWidget; + +class KSharedConfig; + +/** + * This class is the backend for CVS support in Catalog Manager. + * + * @short Backend for CVS support in Catalog Manager + * @author Marco Wegner <mail@marcowegner.de> + */ +class CVSHandler : public QObject +{ + Q_OBJECT + + public: + enum FileStatus { + NO_REPOSITORY, + NOT_IN_CVS, + LOCALLY_ADDED, + LOCALLY_REMOVED, + LOCALLY_MODIFIED, + CONFLICT, + UP_TO_DATE + }; + + CVSHandler( const QString& poBaseDir = QString::null, const QString& potBaseDir = QString::null ); + + void setPOBaseDir( const QString& dir ); + void setPOTBaseDir( const QString& dir ); + + FileStatus fstatus( const QString& filename ) const; + QString fileStatus( const FileStatus status ) const; + QString cvsStatus( const QString& filename ) const; + + void execCVSCommand( QWidget* parent, CVS::Command cmd, const QString& filename, bool templates, KSharedConfig* config ); + void execCVSCommand( QWidget* parent, CVS::Command cmd, const QStringList& files, bool templates, KSharedConfig* config ); + + void setAutoUpdateTemplates( bool update ); + + /** + * True if the file was modified or has another status considered as a modification + */ + bool isConsideredModified( const FileStatus status ) const; + + signals: + void signalIsPORepository( bool ); + void signalIsPOTRepository( bool ); + void signalFilesCommitted( const QStringList& ); + + private: + void showDialog( QWidget* parent, CVS::Command cmd, const QStringList& files, const QString& commandLine, KSharedConfig* config ); + void checkToAdd( const QStringList& files ); + void processStatusOutput( const QString& status ); + void processDiff( QString output ); + + private: + QString _poBaseDir; + QString _potBaseDir; + bool _isPORepository; + bool _isPOTRepository; + bool _autoUpdateTemplates; + QString _addCommand; + + /** Mapping the output of 'cvs status' against the filename. */ + QMap<QString,QString> map; +}; + +#endif // CVSHANDLER_H diff --git a/kbabel/catalogmanager/libcvs/cvsresources.h b/kbabel/catalogmanager/libcvs/cvsresources.h new file mode 100644 index 00000000..627802f7 --- /dev/null +++ b/kbabel/catalogmanager/libcvs/cvsresources.h @@ -0,0 +1,41 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de> + + 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 Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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. + +**************************************************************************** */ + + +#ifndef CVSRESOURCES_H +#define CVSRESOURCES_H + +namespace CVS { + enum Command { Update, Commit, Status, Diff }; +} + +#endif // CVSRESOURCES_H |