KDevelop API Documentation

pythonsupportpart.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2001-2002 by Bernd Gehrmann                             *
00003  *   bernd@kdevelop.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00012 #include "pythonsupportpart.h"
00013 #include "pythonconfigwidget.h"
00014 
00015 #include <kdevcore.h>
00016 #include <kdevproject.h>
00017 #include <kdevappfrontend.h>
00018 #include <kdevpartcontroller.h>
00019 #include <codemodel.h>
00020 #include <domutil.h>
00021 
00022 #include <qfileinfo.h>
00023 #include <qpopupmenu.h>
00024 #include <qstringlist.h>
00025 #include <qtextstream.h>
00026 #include <qtimer.h>
00027 #include <qvbox.h>
00028 #include <kaction.h>
00029 #include <kapplication.h>
00030 #include <kdebug.h>
00031 #include <kdialogbase.h>
00032 #include <kdevgenericfactory.h>
00033 #include <kinputdialog.h>
00034 #include <klocale.h>
00035 #include <qregexp.h>
00036 
00037 
00038 typedef KDevGenericFactory<PythonSupportPart> PythonSupportFactory;
00039 static const KAboutData data("kdevpythonsupport", I18N_NOOP("Language"), "1.0");
00040 K_EXPORT_COMPONENT_FACTORY( libkdevpythonsupport, PythonSupportFactory( &data ) )
00041 
00042 PythonSupportPart::PythonSupportPart(QObject *parent, const char *name, const QStringList &)
00043     : KDevLanguageSupport("PythonSupport", "python", parent, name ? name : "PythonSupportPart")
00044 {
00045     setInstance(PythonSupportFactory::instance());
00046 
00047     setXMLFile("kdevpythonsupport.rc");
00048 
00049     connect( core(), SIGNAL(projectOpened()), this, SLOT(projectOpened()) );
00050     connect( core(), SIGNAL(projectClosed()), this, SLOT(projectClosed()) );
00051     connect( partController(), SIGNAL(savedFile(const KURL&)),
00052              this, SLOT(savedFile(const KURL&)) );
00053     connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)),
00054              this, SLOT(projectConfigWidget(KDialogBase*)) );
00055 
00056     KAction *action;
00057 
00058     action = new KAction( i18n("Execute Program"), "exec", 0,
00059                           this, SLOT(slotExecute()),
00060                           actionCollection(), "build_exec" );
00061     action->setToolTip( i18n("Execute program") );
00062     action->setWhatsThis(i18n("<b>Execute program</b><p>Runs the Python program."));
00063 
00064     action = new KAction( i18n("Execute String..."), "exec", 0,
00065                           this, SLOT(slotExecuteString()),
00066                           actionCollection(), "build_execstring" );
00067     action->setToolTip( i18n("Execute string") );
00068     action->setWhatsThis(i18n("<b>Execute String</b><p>Executes a string as Python code."));
00069 
00070     action = new KAction( i18n("Start Python Interpreter"), "exec", 0,
00071                           this, SLOT(slotStartInterpreter()),
00072                           actionCollection(), "build_runinterpreter" );
00073     action->setToolTip( i18n("Start Python interpreter") );
00074     action->setWhatsThis(i18n("<b>Start python interpreter</b><p>Starts the Python interpreter without a program"));
00075 
00076     action = new KAction( i18n("Python Documentation..."), 0,
00077                           this, SLOT(slotPydoc()),
00078                           actionCollection(), "help_pydoc" );
00079     action->setToolTip( i18n("Python documentation") );
00080     action->setWhatsThis(i18n("<b>Python documentation</b><p>Shows a Python documentation page."));
00081 }
00082 
00083 
00084 PythonSupportPart::~PythonSupportPart()
00085 {}
00086 
00087 
00088 void PythonSupportPart::projectConfigWidget(KDialogBase *dlg)
00089 {
00090     QVBox *vbox = dlg->addVBoxPage(i18n("Python"));
00091     PythonConfigWidget *w = new PythonConfigWidget(*projectDom(), vbox, "python config widget");
00092     connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00093 }
00094 
00095 
00096 void PythonSupportPart::projectOpened()
00097 {
00098     kdDebug(9014) << "projectOpened()" << endl;
00099 
00100     connect( project(), SIGNAL(addedFilesToProject(const QStringList &)),
00101              this, SLOT(addedFilesToProject(const QStringList &)) );
00102     connect( project(), SIGNAL(removedFilesFromProject(const QStringList &)),
00103              this, SLOT(removedFilesFromProject(const QStringList &)) );
00104 
00105     // We want to parse only after all components have been
00106     // properly initialized
00107     QTimer::singleShot(0, this, SLOT(initialParse()));
00108 }
00109 
00110 
00111 void PythonSupportPart::projectClosed()
00112 {
00113 }
00114 
00115 
00116 void PythonSupportPart::maybeParse(const QString fileName)
00117 {
00118     QFileInfo fi(fileName);
00119     if (fi.extension() == "py") {
00120 
00121     if( codeModel()->hasFile(fileName) ){
00122         emit aboutToRemoveSourceInfo( fileName );
00123         codeModel()->removeFile( codeModel()->fileByName(fileName) );
00124     }
00125 
00126         parse( fileName );
00127     }
00128 }
00129 
00130 
00131 void PythonSupportPart::initialParse()
00132 {
00133     kdDebug(9014) << "initialParse()" << endl;
00134 
00135     if (project()) {
00136         kapp->setOverrideCursor(waitCursor);
00137         QStringList files = project()->allFiles();
00138         for (QStringList::Iterator it = files.begin(); it != files.end() ;++it) {
00139             kdDebug(9014) << "maybe parse " << project()->projectDirectory() + "/" + (*it) << endl;
00140             maybeParse(project()->projectDirectory() + "/" + *it);
00141         }
00142 
00143         emit updatedSourceInfo();
00144         kapp->restoreOverrideCursor();
00145     } else {
00146         kdDebug(9014) << "No project" << endl;
00147     }
00148 }
00149 
00150 
00151 void PythonSupportPart::addedFilesToProject(const QStringList &fileList)
00152 {
00153     kdDebug(9014) << "addedFilesToProject()" << endl;
00154 
00155     QStringList::ConstIterator it;
00156 
00157     for ( it = fileList.begin(); it != fileList.end(); ++it )
00158     {
00159         QString fileName = project()->projectDirectory() + "/" + ( *it );
00160         maybeParse( fileName );
00161         emit addedSourceInfo( fileName );
00162     }
00163 
00164     //emit updatedSourceInfo();
00165 }
00166 
00167 
00168 void PythonSupportPart::removedFilesFromProject(const QStringList &fileList)
00169 {
00170     kdDebug(9014) << "removedFilesFromProject()" << endl;
00171 
00172     QStringList::ConstIterator it;
00173 
00174     for ( it = fileList.begin(); it != fileList.end(); ++it )
00175     {
00176         QString fileName = project()->projectDirectory() + "/" + ( *it );
00177 
00178         if( codeModel()->hasFile(fileName) ){
00179             emit aboutToRemoveSourceInfo( fileName );
00180             codeModel()->removeFile( codeModel()->fileByName(fileName) );
00181         }
00182     }
00183 
00184     //emit updatedSourceInfo();
00185 }
00186 
00187 
00188 void PythonSupportPart::savedFile(const KURL &fileName)
00189 {
00190     kdDebug(9014) << "savedFile()" << endl;
00191 
00192     if (project()->allFiles().contains(fileName.path().mid ( project()->projectDirectory().length() + 1 ))) {
00193         maybeParse(fileName.path());
00194     emit addedSourceInfo( fileName.path() );
00195     }
00196 }
00197 
00198 
00199 KDevLanguageSupport::Features PythonSupportPart::features()
00200 {
00201     return Features(Classes | Functions);
00202 }
00203 
00204 
00205 KMimeType::List PythonSupportPart::mimeTypes( )
00206 {
00207     KMimeType::List list;
00208     KMimeType::Ptr mime = KMimeType::mimeType( "text/x-python" );
00209     if( mime )
00210     list << mime;
00211 
00212     mime = KMimeType::mimeType( "application/x-python" );
00213     if( mime )
00214         list << mime;
00215 
00216     return list;
00217 }
00218 
00219 void PythonSupportPart::parse(const QString &fileName)
00220 {
00221     QFile f(QFile::encodeName(fileName));
00222     if (!f.open(IO_ReadOnly))
00223         return;
00224     QTextStream stream(&f);
00225 
00226     QRegExp classre("^[ \t]*class[ \t]+([A-Za-z0-9_]+)[ \t]*(\\(([A-Za-z0-9_, \t]+)\\))?.*$");
00227     QRegExp methodre("^[ \t]*def[ \t]+([A-Za-z0-9_]+).*$");
00228 
00229     FileDom m_file = codeModel()->create<FileModel>();
00230     m_file->setName( fileName );
00231 
00232     ClassDom lastClass;
00233     QString rawline;
00234     QCString line;
00235     int lineNo = 0;
00236     while (!stream.atEnd()) {
00237         rawline = stream.readLine();
00238         line = rawline.stripWhiteSpace().local8Bit();
00239         if (classre.search(line) != -1) {
00240 
00241             lastClass = codeModel()->create<ClassModel>();
00242             lastClass->setName(classre.cap(1));
00243         lastClass->setFileName( fileName );
00244         lastClass->setStartPosition( lineNo, 0 );
00245 
00246             QStringList parentList = QStringList::split(",", classre.cap(3));
00247             QStringList::ConstIterator it;
00248             for (it = parentList.begin(); it != parentList.end(); ++it) {
00249                 QString baseName = (*it).stripWhiteSpace();
00250                 kdDebug(9014) << "Add parent" << baseName << endl;
00251                 lastClass->addBaseClass( baseName );
00252             }
00253 
00254            if (m_file->hasClass(lastClass->name())) {
00255                 ClassDom old = m_file->classByName( lastClass->name() )[ 0 ];
00256         old->setFileName( lastClass->fileName() );
00257 
00258         int line, col;
00259         lastClass->getStartPosition( &line, &col );
00260         old->setStartPosition( line, col );
00261 
00262                 lastClass = old;
00263             } else {
00264                 kdDebug(9014) << "Add class " << lastClass->name() << endl;
00265                 m_file->addClass( lastClass );
00266             }
00267 
00268         } else if (methodre.search(line) != -1 ) {
00269 
00270             FunctionDom method = codeModel()->create<FunctionModel>();
00271             method->setName(methodre.cap(1));
00272         method->setFileName( fileName );
00273             method->setStartPosition( lineNo, 0 );
00274 
00275             if (lastClass && rawline.left(3) != "def") {
00276             if( !lastClass->hasFunction(method->name()) )
00277                     lastClass->addFunction( method );
00278             } else if( !m_file->hasFunction(method->name()) ){
00279                 m_file->addFunction( method );
00280                 lastClass = 0;
00281             }
00282         }
00283         ++lineNo;
00284     }
00285 
00286     f.close();
00287 
00288     codeModel()->addFile( m_file );
00289 }
00290 
00291 
00292 QString PythonSupportPart::interpreter()
00293 {
00294     QString prog = DomUtil::readEntry(*projectDom(), "/kdevpythonsupport/run/interpreter");
00295     if (prog.isEmpty())
00296         prog = "python";
00297 
00298     return prog;
00299 }
00300 
00301 
00302 void PythonSupportPart::startApplication(const QString &program)
00303 {
00304     bool inTerminal = DomUtil::readBoolEntry(*projectDom(), "/kdevpythonsupport/run/terminal");
00305     appFrontend()->startAppCommand(QString::QString(), program, inTerminal);
00306 }
00307 
00308 
00309 void PythonSupportPart::slotExecute()
00310 {
00311     QString program = project()->mainProgram();
00312     QString cmd = interpreter() + " " + program;
00313     startApplication(cmd);
00314 }
00315 
00316 
00317 void PythonSupportPart::slotStartInterpreter()
00318 {
00319     startApplication(interpreter());
00320 }
00321 
00322 
00323 void PythonSupportPart::slotExecuteString()
00324 {
00325     bool ok;
00326     QString cmd = KInputDialog::getText(i18n("String to Execute"), i18n("String to execute:"), QString::null, &ok, 0);
00327     if (ok) {
00328         cmd.prepend("'");
00329         cmd.append("'");
00330         startApplication(cmd);
00331     }
00332 }
00333 
00334 
00335 void PythonSupportPart::slotPydoc()
00336 {
00337     bool ok;
00338     QString key = KInputDialog::getText(i18n("Show Python Documentation"), i18n("Show Python documentation on keyword:"), "", &ok, 0);
00339     if (ok && !key.isEmpty()) {
00340         QString url = "pydoc:";
00341         url += key;
00342         partController()->showDocument(KURL(url));
00343     }
00344 }
00345 
00346 #include "pythonsupportpart.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:33 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003