/***************************************************************************
begin : mon 3 - 11 20 : 40 : 00 CEST 2003
copyright : ( C ) 2003 by Jeroen Wijnhout
email : Jeroen . Wijnhout @ kdemail . 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 "kiletool.h"
# include <tqdir.h>
# include <tqfileinfo.h>
# include <tqmetaobject.h>
# include <tqregexp.h>
# include <tqtimer.h>
# include <klocale.h>
# include <kconfig.h>
# include <kurl.h>
# include "kileconfig.h"
# include "kileuntitled.h"
# include "kiletool_enums.h"
# include "kilestdtools.h" //for the factory
# include "kiletoolmanager.h"
# include "kiledocmanager.h"
# include "kileinfo.h"
# include "kiledocumentinfo.h"
# include "kileproject.h"
namespace KileTool
{
Base : : Base ( const TQString & name , Manager * manager , bool prepare /* = true */ ) :
m_manager ( manager ) ,
m_name ( name ) ,
m_from ( TQString ( ) ) ,
m_to ( TQString ( ) ) ,
m_target ( TQString ( ) ) ,
m_basedir ( TQString ( ) ) ,
m_relativedir ( TQString ( ) ) ,
m_targetdir ( TQString ( ) ) ,
m_source ( TQString ( ) ) ,
m_S ( TQString ( ) ) ,
m_options ( TQString ( ) ) ,
m_resolution ( TQString ( ) ) ,
m_launcher ( 0L ) ,
m_quickie ( false ) ,
m_bPrepareToRun ( prepare )
{
m_manager - > initTool ( this ) ;
m_flags = NeedTargetDirExec | NeedTargetDirWrite | NeedActiveDoc | NeedMasterDoc | NoUntitledDoc | NeedSourceExists | NeedSourceRead ;
setMsg ( NeedTargetDirExec , i18n ( " Could not change to the folder %1. " ) ) ;
setMsg ( NeedTargetDirWrite , i18n ( " The folder %1 is not writable, therefore %2 will not be able to save its results. " ) ) ;
setMsg ( NeedTargetExists , i18n ( " The file %1/%2 does not exist. If you're surprised, check the file permissions. " ) ) ;
setMsg ( NeedTargetRead , i18n ( " The file %1/%2 is not readable. If you're surprised, check the file permissions. " ) ) ;
setMsg ( NeedActiveDoc , i18n ( " Could not determine on which file to run %1, because there is no active document. " ) ) ;
setMsg ( NeedMasterDoc , i18n ( " Could not determine the master file for this document. " ) ) ;
setMsg ( NoUntitledDoc , i18n ( " Please save the untitled document first. " ) ) ;
setMsg ( NeedSourceExists , i18n ( " Sorry, the file %1 does not exist. " ) ) ;
setMsg ( NeedSourceRead , i18n ( " Sorry, the file %1 is not readable. " ) ) ;
m_bPrepared = false ;
}
Base : : ~ Base ( )
{
KILE_DEBUG ( ) < < " DELETING TOOL: " < < name ( ) < < endl ;
delete m_launcher ;
}
const TQString Base : : source ( bool absolute /* = true */ ) const
{
if ( m_source . isNull ( ) )
return TQString ( ) ;
TQString src = m_source ;
if ( absolute )
src = m_basedir + ' / ' + src ;
return src ;
}
void Base : : setMsg ( long n , const TQString & msg )
{
m_messages [ n ] = msg ;
}
void Base : : translate ( TQString & str )
{
TQDictIterator < TQString > it ( * paramDict ( ) ) ;
for ( it . toFirst ( ) ; it . current ( ) ; + + it )
{
// KILE_DEBUG() << "translate " << str << " /// key=" << it.currentKey() << " value=" << *(it.current()) << endl;
str . tqreplace ( it . currentKey ( ) , * ( it . current ( ) ) ) ;
}
}
void Base : : prepareToRun ( const TQString & cfg )
{
KILE_DEBUG ( ) < < " ==Base::prepareToRun()======= " < < endl ;
m_bPrepared = true ;
m_nPreparationResult = Running ;
//configure me
if ( ! configure ( cfg ) )
{
m_nPreparationResult = ConfigureFailed ;
m_bPrepared = false ;
return ;
}
//install a launcher
if ( ! installLauncher ( ) )
{
m_nPreparationResult = NoLauncherInstalled ;
m_bPrepared = false ;
return ;
}
if ( ! determineSource ( ) )
{
m_nPreparationResult = NoValidSource ;
m_bPrepared = false ;
return ;
}
if ( ! determineTarget ( ) )
{
m_nPreparationResult = NoValidTarget ;
m_bPrepared = false ;
return ;
}
if ( m_launcher = = 0 )
{
m_nPreparationResult = NoLauncherInstalled ;
m_bPrepared = false ;
return ;
}
m_launcher - > setWorkingDirectory ( workingDir ( ) ) ;
//fill in the dictionary
addDict ( " %options " , m_options ) ;
m_resolution = KileConfig : : dvipngResolution ( ) ;
addDict ( " %res " , m_resolution ) ;
}
int Base : : run ( )
{
KILE_DEBUG ( ) < < " ==KileTool::Base::run()================= " < < endl ;
if ( m_nPreparationResult ! = 0 )
return m_nPreparationResult ;
if ( ! checkSource ( ) )
return NoValidSource ;
if ( ! checkTarget ( ) )
return TargetHasWrongPermissions ;
if ( ! checkPrereqs ( ) )
return NoValidPrereqs ;
//everything ok so far
emit ( requestSaveAll ( false , true ) ) ;
emit ( start ( this ) ) ;
if ( ! m_launcher - > launch ( ) )
{
KILE_DEBUG ( ) < < " \t launching failed " < < endl ;
if ( ! m_launcher - > selfCheck ( ) )
return SelfCheckFailed ;
else
return CouldNotLaunch ;
}
KILE_DEBUG ( ) < < " \t running... " < < endl ;
return Running ;
}
bool Base : : determineSource ( )
{
TQString src = source ( ) ;
//the basedir is determined from the current compile target
//determined by getCompileName()
if ( src . isNull ( ) ) src = m_ki - > getCompileName ( ) ;
setSource ( src ) ;
return true ;
}
bool Base : : checkSource ( )
{
//FIXME deal with tools that do not need a source or target (yes they exist)
//Is there an active document? Only check if the source file is not explicitly set.
if ( ( m_source . isNull ( ) ) & & ( m_manager - > info ( ) - > activeTextDocument ( ) = = 0L ) )
{
sendMessage ( Error , msg ( NeedActiveDoc ) . tqarg ( name ( ) ) ) ;
return false ;
}
if ( ( m_source . isNull ( ) ) & & ( m_manager - > info ( ) - > activeTextDocument ( ) ! = 0L ) )
{
//couldn't find a source file, huh?
//we know there is an active document, the only reason is could have failed is because
//we couldn't find a LaTeX root document
sendMessage ( Error , msg ( NeedMasterDoc ) ) ;
return false ;
}
if ( KileUntitled : : isUntitled ( m_source ) & & ( flags ( ) & NoUntitledDoc ) )
{
sendMessage ( Error , msg ( NoUntitledDoc ) ) ;
emit ( requestSaveAll ( ) ) ;
return false ;
}
TQFileInfo fi ( source ( ) ) ;
if ( ( flags ( ) & NeedSourceExists ) & & ! fi . exists ( ) )
{
sendMessage ( Error , msg ( NeedSourceExists ) . tqarg ( fi . absFilePath ( ) ) ) ;
return false ;
}
if ( ( flags ( ) & NeedSourceRead ) & & ! fi . isReadable ( ) )
{
sendMessage ( Error , msg ( NeedSourceRead ) . tqarg ( fi . absFilePath ( ) ) ) ;
return false ;
}
return true ;
}
void Base : : setSource ( const TQString & source )
{
m_from = readEntry ( " from " ) ;
TQFileInfo info ( source ) ;
if ( ! m_from . isNull ( ) )
{
TQString src = source ;
if ( ( m_from . length ( ) > 0 ) & & ( info . extension ( false ) . length ( ) > 0 ) )
src . tqreplace ( TQRegExp ( info . extension ( false ) + ' $ ' ) , m_from ) ;
info . setFile ( src ) ;
}
m_basedir = info . dirPath ( true ) ;
m_source = info . fileName ( ) ;
m_S = info . baseName ( true ) ;
addDict ( " %dir_base " , m_basedir ) ;
addDict ( " %source " , m_source ) ;
addDict ( " %S " , m_S ) ;
KILE_DEBUG ( ) < < " ===KileTool::Base::setSource()============== " < < endl ;
KILE_DEBUG ( ) < < " using " < < source < < endl ;
KILE_DEBUG ( ) < < " source= " < < m_source < < endl ;
KILE_DEBUG ( ) < < " S= " < < m_S < < endl ;
KILE_DEBUG ( ) < < " basedir= " < < m_basedir < < endl ;
}
bool Base : : determineTarget ( )
{
TQFileInfo info ( source ( ) ) ;
m_to = readEntry ( " to " ) ;
//if the target is not set previously, use the source filename
if ( m_target . isNull ( ) )
{
//test for explicit override
if ( ! readEntry ( " target " ) . isEmpty ( ) )
{
KILE_DEBUG ( ) < < " USING target SETTING " < < endl ;
m_target = readEntry ( " target " ) ;
}
else if ( to ( ) . length ( ) > 0 )
m_target = S ( ) + ' . ' + to ( ) ;
else
m_target = source ( false ) ;
}
if ( m_relativedir . isNull ( ) & & ( ! readEntry ( " relDir " ) . isEmpty ( ) ) )
{
m_relativedir = readEntry ( " relDir " ) ;
}
KURL url = KURL : : fromPathOrURL ( m_basedir ) ;
url . addPath ( m_relativedir ) ;
url . cleanPath ( ) ;
m_targetdir = url . path ( ) ;
setTarget ( m_target ) ;
setTargetDir ( m_targetdir ) ;
KILE_DEBUG ( ) < < " ==KileTool::Base::determineTarget()========= " < < endl ;
KILE_DEBUG ( ) < < " \t m_targetdir= " < < m_targetdir < < endl ;
KILE_DEBUG ( ) < < " \t m_target= " < < m_target < < endl ;
return true ;
}
bool Base : : checkTarget ( )
{
//check if the target directory is accessible
TQFileInfo info ( m_targetdir ) ;
if ( ( flags ( ) & NeedTargetDirExec ) & & ( ! info . isExecutable ( ) ) )
{
sendMessage ( Error , msg ( NeedTargetDirExec ) . tqarg ( m_targetdir ) ) ;
return false ;
}
if ( ( flags ( ) & NeedTargetDirWrite ) & & ( ! info . isWritable ( ) ) )
{
sendMessage ( Error , msg ( NeedTargetDirWrite ) . tqarg ( m_targetdir ) . tqarg ( m_name ) ) ;
return false ;
}
info . setFile ( m_targetdir + ' / ' + m_target ) ;
if ( ( flags ( ) & NeedTargetExists ) & & ( ! info . exists ( ) ) )
{
sendMessage ( Error , msg ( NeedTargetExists ) . tqarg ( m_targetdir ) . tqarg ( m_target ) ) ;
return false ;
}
if ( ( flags ( ) & NeedTargetRead ) & & ( ! info . isReadable ( ) ) )
{
sendMessage ( Error , msg ( NeedTargetRead ) . tqarg ( m_targetdir ) . tqarg ( m_target ) ) ;
return false ;
}
return true ;
}
void Base : : setTarget ( const TQString & target )
{
m_target = target ;
addDict ( " %target " , m_target ) ;
}
void Base : : setTargetDir ( const TQString & target )
{
m_targetdir = target ;
addDict ( " %dir_target " , m_targetdir ) ;
}
void Base : : setTargetPath ( const TQString & target )
{
TQFileInfo fi ( target ) ;
setTarget ( fi . fileName ( ) ) ;
setTargetDir ( fi . dirPath ( true ) ) ;
}
bool Base : : checkPrereqs ( )
{
return true ;
}
bool Base : : configure ( const TQString & cfg )
{
return m_manager - > configure ( this , cfg ) ;
}
void Base : : stop ( )
{
if ( m_launcher )
m_launcher - > kill ( ) ;
//emit(done(this, Aborted));
}
bool Base : : finish ( int result )
{
KILE_DEBUG ( ) < < " ==KileTool::Base::finish()============== " < < endl ;
if ( TQT_TQOBJECT ( const_cast < TQT_BASE_OBJECT_NAME * > ( sender ( ) ) ) )
{
KILE_DEBUG ( ) < < " \t called by " < < TQT_TQOBJECT ( const_cast < TQT_BASE_OBJECT_NAME * > ( sender ( ) ) ) - > name ( ) < < " " < < TQT_TQOBJECT ( const_cast < TQT_BASE_OBJECT_NAME * > ( sender ( ) ) ) - > className ( ) < < endl ;
}
if ( result = = Aborted )
sendMessage ( Error , " Aborted " ) ;
if ( result = = Success )
sendMessage ( Info , " Done! " ) ;
KILE_DEBUG ( ) < < " \t emitting done(Base*, int) " < < name ( ) < < endl ;
emit ( done ( this , result ) ) ;
//we will only get here if the done() signal is not connected to the manager (who will destroy this object)
if ( result = = Success )
return true ;
else
return false ;
}
void Base : : installLauncher ( Launcher * lr )
{
if ( m_launcher ! = lr )
delete m_launcher ;
m_launcher = lr ;
//lr->setParamDict(paramDict());
lr - > setTool ( this ) ;
connect ( lr , TQT_SIGNAL ( message ( int , const TQString & ) ) , this , TQT_SLOT ( sendMessage ( int , const TQString & ) ) ) ;
connect ( lr , TQT_SIGNAL ( output ( const TQString & ) ) , this , TQT_SLOT ( filterOutput ( const TQString & ) ) ) ;
connect ( lr , TQT_SIGNAL ( done ( int ) ) , this , TQT_SLOT ( finish ( int ) ) ) ;
}
bool Base : : installLauncher ( )
{
if ( m_launcher )
return true ;
TQString type = readEntry ( " type " ) ;
KILE_DEBUG ( ) < < " installing launcher of type " < < type < < endl ;
Launcher * lr = 0 ;
if ( type = = " Process " )
{
lr = new ProcessLauncher ( ) ;
}
else if ( type = = " Konsole " )
{
lr = new KonsoleLauncher ( ) ;
}
else if ( type = = " Part " )
{
lr = new PartLauncher ( ) ;
}
else if ( type = = " DocPart " )
{
lr = new DocPartLauncher ( ) ;
}
if ( lr )
{
installLauncher ( lr ) ;
return true ;
}
else
{
m_launcher = 0 ;
return false ;
}
}
void Base : : sendMessage ( int type , const TQString & msg )
{
emit ( message ( type , msg , name ( ) ) ) ;
}
void Base : : filterOutput ( const TQString & str )
{
//here you have the change to filter the output and do some error extraction for example
//this should be done by a OutputFilter class
//idea: store the buffer until a complete line (or more) has been received then parse these lines
//just send the buf immediately to the output widget, the results of the parsing are displayed in
//the log widget anyway.
emit ( output ( str ) ) ;
}
bool Base : : addDict ( const TQString & key , const TQString & value )
{
bool e = ( paramDict ( ) - > tqfind ( key ) = = 0 ) ;
paramDict ( ) - > tqreplace ( key , & value ) ;
return e ;
}
bool Base : : needsUpdate ( const TQString & target , const TQString & source )
{
KILE_DEBUG ( ) < < " ==Base::needsUpdate( " < < target < < " , " < < source < < endl ;
TQFileInfo targetinfo ( target ) ;
TQFileInfo sourceinfo ( source ) ;
TQDateTime currDateTime = TQDateTime : : tqcurrentDateTime ( ) ;
if ( ! ( sourceinfo . exists ( ) & & sourceinfo . isReadable ( ) ) )
{
KILE_DEBUG ( ) < < " \t returning false: source doesn't exist " < < endl ;
return false ;
}
if ( ! targetinfo . exists ( ) )
{
KILE_DEBUG ( ) < < " \t returning true: target doesn't exist " < < endl ;
return true ;
}
KILE_DEBUG ( ) < < " \t target: " < < targetinfo . lastModified ( ) . toString ( ) < < endl ;
KILE_DEBUG ( ) < < " \t source: " < < sourceinfo . lastModified ( ) . toString ( ) < < endl ;
if ( targetinfo . lastModified ( ) > currDateTime ) {
KILE_DEBUG ( ) < < " targetinfo.lastModifiedTime() is in the future " < < endl ;
return false ;
}
else if ( sourceinfo . lastModified ( ) > currDateTime ) {
KILE_DEBUG ( ) < < " sourceinfo.lastModifiedTime() is in the future " < < endl ;
return false ;
}
KILE_DEBUG ( ) < < " \t returning " < < ( targetinfo . lastModified ( ) < sourceinfo . lastModified ( ) ) < < endl ;
return targetinfo . lastModified ( ) < sourceinfo . lastModified ( ) ;
}
Compile : : Compile ( const TQString & name , Manager * manager , bool prepare /*= true*/ )
: Base ( name , manager , prepare )
{
setFlags ( flags ( ) | NeedTargetDirExec | NeedTargetDirWrite ) ;
}
Compile : : ~ Compile ( )
{ }
bool Compile : : checkSource ( )
{
if ( ! Base : : checkSource ( ) ) return false ;
bool isRoot = true ;
KileDocument : : TextInfo * docinfo = manager ( ) - > info ( ) - > docManager ( ) - > textInfoFor ( source ( ) ) ;
if ( docinfo ) isRoot = ( readEntry ( " checkForRoot " ) = = " yes " ) ? docinfo - > isLaTeXRoot ( ) : true ;
if ( ! isRoot )
{
return manager ( ) - > queryContinue ( i18n ( " The document %1 is not a LaTeX root document ; continue anyway ? " ).tqarg(source()), i18n( " Continue ? " ));
}
return true ;
}
View : : View ( const TQString & name , Manager * manager , bool prepare /*= true*/ )
: Base ( name , manager , prepare )
{
setFlags ( NeedTargetDirExec | NeedTargetExists | NeedTargetRead ) ;
KILE_DEBUG ( ) < < " View: flag " < < ( flags ( ) & NeedTargetExists ) < < endl ;
setMsg ( NeedTargetExists , i18n ( " The file %2/%3 does not exist; did you compile the source file? " ) ) ;
}
View : : ~ View ( )
{
}
Archive : : Archive ( const TQString & name , Manager * manager , bool prepare /* = true*/ )
: Base ( name , manager , prepare )
{
setFlags ( NeedTargetDirExec | NeedTargetDirWrite ) ;
}
Archive : : ~ Archive ( )
{ }
bool Archive : : checkPrereqs ( )
{
if ( m_project = = 0L )
{
sendMessage ( Error , i18n ( " The current document is not associated to a project. Please activate a document that is associated to the project you want to archive, then choose Archive again. " ) ) ;
return false ;
}
else if ( m_fileList . isEmpty ( ) )
{
sendMessage ( Error , i18n ( " No files have been chosen for archiving. " ) ) ;
return false ;
}
else
return true ;
}
void Archive : : setSource ( const TQString & source )
{
KURL url = KURL : : fromPathOrURL ( source ) ;
m_project = manager ( ) - > info ( ) - > docManager ( ) - > projectFor ( url ) ;
if ( ! m_project )
m_project = manager ( ) - > info ( ) - > docManager ( ) - > activeProject ( ) ;
if ( ! m_project )
m_project = manager ( ) - > info ( ) - > docManager ( ) - > selectProject ( i18n ( " Archive Project " ) ) ;
if ( ! m_project )
{
Base : : setSource ( source ) ;
return ;
}
manager ( ) - > info ( ) - > docManager ( ) - > projectSave ( m_project ) ;
Base : : setSource ( m_project - > url ( ) . path ( ) ) ;
m_fileList = m_project - > archiveFileList ( ) ;
addDict ( " %AFL " , m_fileList ) ;
KILE_DEBUG ( ) < < " ===KileTool::Archive::setSource( " < < source < < " )============== " < < endl ;
KILE_DEBUG ( ) < < " m_fileList= " < < m_fileList < < endl ;
}
Convert : : Convert ( const TQString & name , Manager * manager , bool prepare /*= true*/ )
: Base ( name , manager , prepare )
{
setFlags ( flags ( ) | NeedTargetDirExec | NeedTargetDirWrite ) ;
}
Convert : : ~ Convert ( )
{
}
bool Convert : : determineSource ( )
{
bool br = Base : : determineSource ( ) ;
setSource ( baseDir ( ) + ' / ' + S ( ) + ' . ' + from ( ) ) ;
return br ;
}
Sequence : : Sequence ( const TQString & name , Manager * manager , bool prepare /*= true*/ ) :
Base ( name , manager , prepare )
{
}
int Sequence : : run ( )
{
KILE_DEBUG ( ) < < " ==KileTool::Sequence::run()================== " < < endl ;
configure ( ) ;
determineSource ( ) ;
if ( ! checkSource ( ) ) return NoValidSource ;
TQStringList tools = TQStringList : : split ( ' , ' , readEntry ( " sequence " ) ) ;
TQString tl , cfg ;
Base * tool ;
for ( uint i = 0 ; i < tools . count ( ) ; + + i )
{
tools [ i ] = tools [ i ] . stripWhiteSpace ( ) ;
extract ( tools [ i ] , tl , cfg ) ;
tool = manager ( ) - > factory ( ) - > create ( tl , false ) ; //create tool with delayed preparation
if ( tool )
{
KILE_DEBUG ( ) < < " ===tool created with name " < < tool - > name ( ) < < endl ;
if ( ! ( manager ( ) - > info ( ) - > watchFile ( ) & & tool - > isViewer ( ) ) )
{
KILE_DEBUG ( ) < < " \t queueing " < < tl < < " ( " < < cfg < < " ) with " < < source ( ) < < endl ;
tool - > setSource ( source ( ) ) ;
manager ( ) - > run ( tool , cfg ) ;
}
}
else
{
sendMessage ( Error , i18n ( " Unknown tool %1. " ) . tqarg ( tools [ i ] ) ) ;
emit ( done ( this , Failed ) ) ;
return ConfigureFailed ;
}
}
emit ( done ( this , Silent ) ) ;
return Success ;
}
}
# include "kiletool.moc"