/***************************************************************************
* Copyright ( C ) 2001 - 2002 by Bernd Gehrmann *
* bernd @ 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 "pythonsupportpart.h"
# include "pythonconfigwidget.h"
# include <kdevcore.h>
# include <kdevproject.h>
# include <kdevappfrontend.h>
# include <kdevpartcontroller.h>
# include <codemodel.h>
# include <domutil.h>
# include <tqfileinfo.h>
# include <tqpopupmenu.h>
# include <tqstringlist.h>
# include <tqtextstream.h>
# include <tqtimer.h>
# include <tqvbox.h>
# include <tdeaction.h>
# include <tdeapplication.h>
# include <kdebug.h>
# include <kdialogbase.h>
# include <kdevgenericfactory.h>
# include <kdevplugininfo.h>
# include <kinputdialog.h>
# include <tdelocale.h>
# include <tqregexp.h>
# include "qtdesignerpythonintegration.h"
# include "pythonimplementationwidget.h"
typedef KDevGenericFactory < PythonSupportPart > PythonSupportFactory ;
static const KDevPluginInfo data ( " kdevpythonsupport " ) ;
K_EXPORT_COMPONENT_FACTORY ( libkdevpythonsupport , PythonSupportFactory ( data ) )
PythonSupportPart : : PythonSupportPart ( TQObject * parent , const char * name , const TQStringList & )
: KDevLanguageSupport ( & data , parent , name ? name : " PythonSupportPart " )
{
setInstance ( PythonSupportFactory : : instance ( ) ) ;
setXMLFile ( " kdevpythonsupport.rc " ) ;
connect ( core ( ) , TQT_SIGNAL ( projectOpened ( ) ) , this , TQT_SLOT ( projectOpened ( ) ) ) ;
connect ( core ( ) , TQT_SIGNAL ( projectClosed ( ) ) , this , TQT_SLOT ( projectClosed ( ) ) ) ;
connect ( partController ( ) , TQT_SIGNAL ( savedFile ( const KURL & ) ) ,
this , TQT_SLOT ( savedFile ( const KURL & ) ) ) ;
connect ( core ( ) , TQT_SIGNAL ( projectConfigWidget ( KDialogBase * ) ) ,
this , TQT_SLOT ( projectConfigWidget ( KDialogBase * ) ) ) ;
connect ( core ( ) , TQT_SIGNAL ( contextMenu ( TQPopupMenu * , const Context * ) ) ,
this , TQT_SLOT ( contextMenu ( TQPopupMenu * , const Context * ) ) ) ;
TDEAction * action ;
action = new TDEAction ( i18n ( " Execute Program " ) , " application-x-executable " , 0 ,
this , TQT_SLOT ( slotExecute ( ) ) ,
actionCollection ( ) , " build_exec " ) ;
action - > setToolTip ( i18n ( " Execute program " ) ) ;
action - > setWhatsThis ( i18n ( " <b>Execute program</b><p>Runs the Python program. " ) ) ;
action = new TDEAction ( i18n ( " Execute String... " ) , " application-x-executable " , 0 ,
this , TQT_SLOT ( slotExecuteString ( ) ) ,
actionCollection ( ) , " build_execstring " ) ;
action - > setToolTip ( i18n ( " Execute string " ) ) ;
action - > setWhatsThis ( i18n ( " <b>Execute String</b><p>Executes a string as Python code. " ) ) ;
action = new TDEAction ( i18n ( " Start Python Interpreter " ) , " application-x-executable " , 0 ,
this , TQT_SLOT ( slotStartInterpreter ( ) ) ,
actionCollection ( ) , " build_runinterpreter " ) ;
action - > setToolTip ( i18n ( " Start Python interpreter " ) ) ;
action - > setWhatsThis ( i18n ( " <b>Start python interpreter</b><p>Starts the Python interpreter without a program " ) ) ;
action = new TDEAction ( i18n ( " Python Documentation... " ) , 0 ,
this , TQT_SLOT ( slotPydoc ( ) ) ,
actionCollection ( ) , " help_pydoc " ) ;
action - > setToolTip ( i18n ( " Python documentation " ) ) ;
action - > setWhatsThis ( i18n ( " <b>Python documentation</b><p>Shows a Python documentation page. " ) ) ;
}
PythonSupportPart : : ~ PythonSupportPart ( )
{ }
void PythonSupportPart : : contextMenu ( TQPopupMenu * popup , const Context * context )
{
if ( context - > hasType ( Context : : FileContext ) ) {
const FileContext * fc = static_cast < const FileContext * > ( context ) ;
//this is a .ui file and only selection contains only one such file
KURL url = fc - > urls ( ) . first ( ) ;
if ( url . fileName ( ) . endsWith ( " .ui " ) )
{
m_contextFileName = url . fileName ( ) ;
int id = popup - > insertItem ( i18n ( " Create or Select Implementation... " ) , this , TQT_SLOT ( slotCreateSubclass ( ) ) ) ;
popup - > setWhatsThis ( id , i18n ( " <b>Create or select implementation</b><p>Creates or selects a subclass of selected form for use with integrated KDevDesigner. " ) ) ;
}
}
}
void PythonSupportPart : : projectConfigWidget ( KDialogBase * dlg )
{
TQVBox * vbox = dlg - > addVBoxPage ( i18n ( " Python " ) ) ;
PythonConfigWidget * w = new PythonConfigWidget ( * projectDom ( ) , vbox , " python config widget " ) ;
connect ( dlg , TQT_SIGNAL ( okClicked ( ) ) , w , TQT_SLOT ( accept ( ) ) ) ;
}
void PythonSupportPart : : projectOpened ( )
{
kdDebug ( 9014 ) < < " projectOpened() " < < endl ;
connect ( project ( ) , TQT_SIGNAL ( addedFilesToProject ( const TQStringList & ) ) ,
this , TQT_SLOT ( addedFilesToProject ( const TQStringList & ) ) ) ;
connect ( project ( ) , TQT_SIGNAL ( removedFilesFromProject ( const TQStringList & ) ) ,
this , TQT_SLOT ( removedFilesFromProject ( const TQStringList & ) ) ) ;
// We want to parse only after all components have been
// properly initialized
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( initialParse ( ) ) ) ;
}
void PythonSupportPart : : projectClosed ( )
{
}
void PythonSupportPart : : maybeParse ( const TQString fileName )
{
TQFileInfo fi ( fileName ) ;
if ( fi . extension ( ) = = " py " ) {
if ( codeModel ( ) - > hasFile ( fileName ) ) {
emit aboutToRemoveSourceInfo ( fileName ) ;
codeModel ( ) - > removeFile ( codeModel ( ) - > fileByName ( fileName ) ) ;
}
parse ( fileName ) ;
}
}
void PythonSupportPart : : initialParse ( )
{
kdDebug ( 9014 ) < < " initialParse() " < < endl ;
if ( project ( ) ) {
kapp - > setOverrideCursor ( waitCursor ) ;
TQStringList files = project ( ) - > allFiles ( ) ;
for ( TQStringList : : Iterator it = files . begin ( ) ; it ! = files . end ( ) ; + + it ) {
kdDebug ( 9014 ) < < " maybe parse " < < project ( ) - > projectDirectory ( ) + " / " + ( * it ) < < endl ;
maybeParse ( project ( ) - > projectDirectory ( ) + " / " + * it ) ;
}
emit updatedSourceInfo ( ) ;
kapp - > restoreOverrideCursor ( ) ;
} else {
kdDebug ( 9014 ) < < " No project " < < endl ;
}
}
void PythonSupportPart : : addedFilesToProject ( const TQStringList & fileList )
{
kdDebug ( 9014 ) < < " addedFilesToProject() " < < endl ;
TQStringList : : ConstIterator it ;
for ( it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it )
{
TQString fileName = project ( ) - > projectDirectory ( ) + " / " + ( * it ) ;
maybeParse ( fileName ) ;
emit addedSourceInfo ( fileName ) ;
}
//emit updatedSourceInfo();
}
void PythonSupportPart : : removedFilesFromProject ( const TQStringList & fileList )
{
kdDebug ( 9014 ) < < " removedFilesFromProject() " < < endl ;
TQStringList : : ConstIterator it ;
for ( it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it )
{
TQString fileName = project ( ) - > projectDirectory ( ) + " / " + ( * it ) ;
if ( codeModel ( ) - > hasFile ( fileName ) ) {
emit aboutToRemoveSourceInfo ( fileName ) ;
codeModel ( ) - > removeFile ( codeModel ( ) - > fileByName ( fileName ) ) ;
}
}
//emit updatedSourceInfo();
}
void PythonSupportPart : : savedFile ( const KURL & fileName )
{
kdDebug ( 9014 ) < < " savedFile() " < < endl ;
if ( project ( ) - > allFiles ( ) . contains ( fileName . path ( ) . mid ( project ( ) - > projectDirectory ( ) . length ( ) + 1 ) ) ) {
maybeParse ( fileName . path ( ) ) ;
emit addedSourceInfo ( fileName . path ( ) ) ;
}
}
KDevLanguageSupport : : Features PythonSupportPart : : features ( )
{
return Features ( Classes | Functions ) ;
}
KMimeType : : List PythonSupportPart : : mimeTypes ( )
{
KMimeType : : List list ;
KMimeType : : Ptr mime = KMimeType : : mimeType ( " text/x-python " ) ;
if ( mime )
list < < mime ;
mime = KMimeType : : mimeType ( " application/x-python " ) ;
if ( mime )
list < < mime ;
return list ;
}
void PythonSupportPart : : parse ( const TQString & fileName )
{
TQFile f ( TQFile : : encodeName ( fileName ) ) ;
if ( ! f . open ( IO_ReadOnly ) )
return ;
TQTextStream stream ( & f ) ;
TQRegExp classre ( " ^[ \t ]*class[ \t ]+([A-Za-z0-9_]+) [ \ t ] * ( \ \ ( ( [ A - Za - z0 - 9 _ , \ t ] + ) \ \ ) ) ? . * $ " ) ;
TQRegExp methodre ( " ^[ \t ]*def[ \t ]+([A-Za-z0-9_]+) . * $ " ) ;
FileDom m_file = codeModel ( ) - > create < FileModel > ( ) ;
m_file - > setName ( fileName ) ;
ClassDom lastClass ;
TQString rawline ;
TQCString line ;
int lineNo = 0 ;
while ( ! stream . atEnd ( ) ) {
rawline = stream . readLine ( ) ;
line = rawline . stripWhiteSpace ( ) . local8Bit ( ) ;
if ( classre . search ( line ) ! = - 1 ) {
lastClass = codeModel ( ) - > create < ClassModel > ( ) ;
lastClass - > setName ( classre . cap ( 1 ) ) ;
lastClass - > setFileName ( fileName ) ;
lastClass - > setStartPosition ( lineNo , 0 ) ;
TQStringList parentList = TQStringList : : split ( " , " , classre . cap ( 3 ) ) ;
TQStringList : : ConstIterator it ;
for ( it = parentList . begin ( ) ; it ! = parentList . end ( ) ; + + it ) {
TQString baseName = ( * it ) . stripWhiteSpace ( ) ;
kdDebug ( 9014 ) < < " Add parent " < < baseName < < endl ;
lastClass - > addBaseClass ( baseName ) ;
}
if ( m_file - > hasClass ( lastClass - > name ( ) ) ) {
ClassDom old = m_file - > classByName ( lastClass - > name ( ) ) [ 0 ] ;
old - > setFileName ( lastClass - > fileName ( ) ) ;
int line , col ;
lastClass - > getStartPosition ( & line , & col ) ;
old - > setStartPosition ( line , col ) ;
lastClass = old ;
} else {
kdDebug ( 9014 ) < < " Add class " < < lastClass - > name ( ) < < endl ;
m_file - > addClass ( lastClass ) ;
}
} else if ( methodre . search ( line ) ! = - 1 ) {
FunctionDom method = codeModel ( ) - > create < FunctionModel > ( ) ;
method - > setName ( methodre . cap ( 1 ) ) ;
method - > setFileName ( fileName ) ;
method - > setStartPosition ( lineNo , 0 ) ;
if ( lastClass & & rawline . left ( 3 ) ! = " def " ) {
if ( ! lastClass - > hasFunction ( method - > name ( ) ) )
lastClass - > addFunction ( method ) ;
TQStringList scope ;
scope < < lastClass - > name ( ) ;
method - > setScope ( scope ) ;
} else if ( ! m_file - > hasFunction ( method - > name ( ) ) ) {
m_file - > addFunction ( method ) ;
lastClass = 0 ;
}
}
+ + lineNo ;
}
f . close ( ) ;
codeModel ( ) - > addFile ( m_file ) ;
}
TQString PythonSupportPart : : interpreter ( )
{
TQString prog = DomUtil : : readEntry ( * projectDom ( ) , " /kdevpythonsupport/run/interpreter " ) ;
if ( prog . isEmpty ( ) )
prog = " python " ;
return prog ;
}
void PythonSupportPart : : startApplication ( const TQString & program )
{
bool inTerminal = DomUtil : : readBoolEntry ( * projectDom ( ) , " /kdevpythonsupport/run/terminal " ) ;
if ( KDevAppFrontend * appFrontend = extension < KDevAppFrontend > ( " TDevelop/AppFrontend " ) )
appFrontend - > startAppCommand ( TQString ( ) , program , inTerminal ) ;
}
void PythonSupportPart : : slotExecute ( )
{
TQString program = project ( ) - > mainProgram ( ) ;
TQString cmd = interpreter ( ) + " " + program ;
startApplication ( cmd ) ;
}
void PythonSupportPart : : slotStartInterpreter ( )
{
startApplication ( interpreter ( ) ) ;
}
void PythonSupportPart : : slotExecuteString ( )
{
bool ok ;
TQString cmd = KInputDialog : : getText ( i18n ( " String to Execute " ) , i18n ( " String to execute: " ) , TQString ( ) , & ok , 0 ) ;
if ( ok ) {
cmd . prepend ( " ' " ) ;
cmd . append ( " ' " ) ;
startApplication ( cmd ) ;
}
}
void PythonSupportPart : : slotPydoc ( )
{
bool ok ;
TQString key = KInputDialog : : getText ( i18n ( " Show Python Documentation " ) , i18n ( " Show Python documentation on keyword: " ) , " " , & ok , 0 ) ;
if ( ok & & ! key . isEmpty ( ) ) {
TQString url = " pydoc: " ;
url + = key ;
partController ( ) - > showDocument ( KURL ( url ) ) ;
}
}
KDevDesignerIntegration * PythonSupportPart : : designer ( KInterfaceDesigner : : DesignerType type )
{
KDevDesignerIntegration * des = 0 ;
switch ( type )
{
case KInterfaceDesigner : : TQtDesigner :
des = m_designers [ type ] ;
if ( des = = 0 )
{
PythonImplementationWidget * impl = new PythonImplementationWidget ( this ) ;
des = new QtDesignerPythonIntegration ( this , impl ) ;
des - > loadSettings ( * project ( ) - > projectDom ( ) ,
" kdevpythonsupport/designerintegration " ) ;
m_designers [ type ] = des ;
}
break ;
case KInterfaceDesigner : : Glade :
break ;
}
return des ;
}
void PythonSupportPart : : slotCreateSubclass ( )
{
TQFileInfo fi ( m_contextFileName ) ;
kdDebug ( 9014 ) < < k_funcinfo < < " file: " < < m_contextFileName < < " ext: " < < fi . extension ( false ) < < endl ;
if ( fi . extension ( false ) ! = " ui " )
return ;
QtDesignerPythonIntegration * des = dynamic_cast < QtDesignerPythonIntegration * > ( designer ( KInterfaceDesigner : : TQtDesigner ) ) ;
if ( des )
{
kdDebug ( 9014 ) < < " ok: " < < des < < endl ;
kdDebug ( 9014 ) < < " have impl: " < < des - > selectImplementation ( m_contextFileName ) ;
}
kdDebug ( 9014 ) < < " end: " < < des < < endl ;
}
# include "pythonsupportpart.moc"