/*
   Copyright (C) 2005 by Nicolas Escuder <n.escuder@intra-links.com>
   Copyright (C) 2001 by smeier@kdevelop.org

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   version 2, License as published by the Free Software Foundation.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "phpsupportpart.h"

#include <iostream>

#include <tqdir.h>
#include <tqfileinfo.h>
#include <tqpopupmenu.h>
#include <tqprogressbar.h>
#include <tqstringlist.h>
#include <tqtextstream.h>
#include <tqtimer.h>
#include <tqvbox.h>
#include <tqwhatsthis.h>
#include <tqthread.h>

#include <tdeaction.h>
#include <tdeapplication.h>
#include <kdebug.h>
#include <tdehtmlview.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kprocess.h>
#include <kregexp.h>
#include <kstatusbar.h>
#include <tdeparts/browserextension.h>

#include <kdevcore.h>
#include <kdevproject.h>
#include <kdevmainwindow.h>
#include <kdevpartcontroller.h>
#include <codemodel.h>
#include <domutil.h>
#include <kdevplugininfo.h>
#include <kiconloader.h>

#include "phpconfigdata.h"
#include "phpconfigwidget.h"
#include "phpcodecompletion.h"
#include "phpparser.h"
#include "phpnewclassdlg.h"


#include "phphtmlview.h"
#include "phperrorview.h"

#include "phpsupport_event.h"

using namespace std;

static const KDevPluginInfo pluginData("kdevphpsupport");
K_EXPORT_COMPONENT_FACTORY( libkdevphpsupport, PHPSupportFactory( pluginData ) )

PHPSupportPart::PHPSupportPart(TQObject *parent, const char *name, const TQStringList &)
    : KDevLanguageSupport(&pluginData, parent, name ? name : "PHPSupportPart")
{
   m_htmlView = 0;
   m_parser = 0;
   phpExeProc = 0;
   setInstance(PHPSupportFactory::instance());

   setXMLFile("kdevphpsupport.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*)) );

   TDEAction *action;

   action = new TDEAction( i18n("&Run"), "application-x-executable",Key_F9,
   this, TQT_SLOT(slotRun()),
   actionCollection(), "build_execute" );
   action->setToolTip(i18n("Run"));
   action->setWhatsThis(i18n("<b>Run</b><p>Executes script on a terminal or a webserver."));

   action = new TDEAction( i18n("&New Class..."),0,
   this, TQT_SLOT(slotNewClass()),
   actionCollection(), "project_new_class" );
   action->setToolTip(i18n("New class"));
   action->setWhatsThis(i18n("<b>New class</b><p>Runs New Class wizard."));

   m_phpErrorView = new PHPErrorView(this, 0, "phpErrorWidget");
   m_phpErrorView->setIcon( SmallIcon("application-vnd.tde.info") );

   TQWhatsThis::add(m_phpErrorView, i18n("<b>PHP problems</b><p>This view shows PHP parser warnings, errors, and fatal errors."));
   mainWindow()->embedOutputView(m_phpErrorView, i18n("Problems"), i18n("Problems"));

   phpExeProc = new KShellProcess("/bin/sh");
   connect( phpExeProc, TQT_SIGNAL(receivedStdout (TDEProcess*, char*, int)),
            this, TQT_SLOT(slotReceivedPHPExeStdout (TDEProcess*, char*, int)));
   connect( phpExeProc, TQT_SIGNAL(receivedStderr (TDEProcess*, char*, int)),
            this, TQT_SLOT(slotReceivedPHPExeStderr (TDEProcess*, char*, int)));
   connect( phpExeProc, TQT_SIGNAL(processExited(TDEProcess*)),
            this, TQT_SLOT(slotPHPExeExited(TDEProcess*)));

   m_htmlView = new PHPHTMLView(this);
   mainWindow()->embedOutputView(m_htmlView->view(), i18n("PHP"), i18n("PHP"));
   connect( m_htmlView,  TQT_SIGNAL(started(TDEIO::Job*)),
            this, TQT_SLOT(slotWebJobStarted(TDEIO::Job*)));

   configData = new PHPConfigData(projectDom());
   connect( configData,  TQT_SIGNAL(configStored()),
            this, TQT_SLOT(slotConfigStored()));

   m_codeCompletion = new  PHPCodeCompletion(this, configData);

   new TDEAction(i18n("Complete Text"), CTRL+Key_Space, m_codeCompletion, TQT_SLOT(cursorPositionChanged()), actionCollection(), "edit_complete_text");

   connect( partController(), TQT_SIGNAL(activePartChanged(KParts::Part*)),
            this, TQT_SLOT(slotActivePartChanged(KParts::Part *)));
   connect( this, TQT_SIGNAL(fileParsed( PHPFile* )), this, TQT_SLOT(slotfileParsed( PHPFile* )));
}

PHPSupportPart::~PHPSupportPart()
{
   LastClass = NULL;
   LastMethod = NULL;
   LastVariable = NULL;

   if ( m_parser ) {
      m_parser->close() ;
      delete( m_parser );
      m_parser = NULL;
   }

   if ( m_phpErrorView ) {
      mainWindow()->removeView( m_phpErrorView );
      delete( m_phpErrorView );
      m_phpErrorView = NULL;
   }

   kdDebug(9018) << "remove codeCompletition" << endl;
   if ( m_codeCompletion )
      delete( m_codeCompletion );

   kdDebug(9018) << "remove configData" << endl;
   if ( configData )
      delete( configData );

   if ( m_htmlView ) {
      kdDebug(9018) << "remove htmlView" << endl;
      mainWindow()->removeView( m_htmlView->view() );
      delete( m_htmlView );
      m_htmlView = NULL;
   }

   kdDebug(9018) << "remove phpExec" << endl;
   if ( phpExeProc )
      delete( phpExeProc );

   kdDebug(9018) << "finish" << endl;
}

void PHPSupportPart::slotActivePartChanged(KParts::Part *part) {
   kdDebug(9018) << "enter slotActivePartChanged" << endl;
   if (!part || !part->widget())
      return;
   m_editInterface = dynamic_cast<KTextEditor::EditInterface*>(part);
   if (m_editInterface) { // connect to the editor
      disconnect(part, 0, this, 0 ); // to make sure that it is't connected twice
      if (configData->getRealtimeParsing()) {
         connect(part,TQT_SIGNAL(textChanged()),this,TQT_SLOT(slotTextChanged()));
      }
      m_codeCompletion->setActiveEditorPart(part);
   }
   kdDebug(9018) << "exit slotActivePartChanged" << endl;
}

void PHPSupportPart::slotTextChanged() {
   kdDebug(9018) << "enter text changed" << endl;

   KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(partController()->activePart());
   if (!ro_part)
      return;

   TQString fileName = ro_part->url().directory() + "/" + ro_part->url().fileName();

   if (m_parser) {
      if (m_parser->hasFile( fileName ))
         m_parser->reparseFile( fileName );
   }
}

void PHPSupportPart::slotConfigStored() {
   // fake a changing, this will read the configuration again and install the connects
   slotActivePartChanged(partController()->activePart());
}

void PHPSupportPart::projectConfigWidget(KDialogBase *dlg) {
   TQVBox *vbox = dlg->addVBoxPage(i18n( "PHP Specific" ), i18n("PHP Settings"), BarIcon( "text-x-src", TDEIcon::SizeMedium ));
   PHPConfigWidget* w = new PHPConfigWidget(configData,vbox, "php config widget");
   connect( dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept()) );
}

void PHPSupportPart::slotNewClass() {
   TQStringList classNames = sortedNameList( codeModel()->globalNamespace()->classList() );
   PHPNewClassDlg dlg(classNames,project()->projectDirectory());
   dlg.exec();
 }

void PHPSupportPart::slotRun() {
   configData = new PHPConfigData(projectDom());
   if (validateConfig()) {
      mainWindow()->raiseView(m_htmlView->view());
      PHPConfigData::InvocationMode mode = configData->getInvocationMode() ;
      if (mode == PHPConfigData::Web) {
         executeOnWebserver();
      }
      else if (mode == PHPConfigData::Shell) {
         executeInTerminal();
      }
   }
}

bool PHPSupportPart::validateConfig() {
   if (!configData->validateConfig()) {
      KMessageBox::information(0,i18n("There is no configuration for executing a PHP file.\nPlease set the correct values in the next dialog."));
      KDialogBase dlg(KDialogBase::TreeList, i18n("Customize PHP Mode"),
                     KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, 0,
                     "php config dialog");

      TQVBox *vbox = dlg.addVBoxPage(i18n("PHP Settings"));
      PHPConfigWidget* w = new PHPConfigWidget(configData,vbox, "php config widget");
      connect( &dlg, TQT_SIGNAL(okClicked()), w, TQT_SLOT(accept()) );
      dlg.exec();
   }
   if (configData->validateConfig()) {
      return true;
   }
   return false;
}

void PHPSupportPart::executeOnWebserver() {
   // Save all files once
   if (partController()->saveAllFiles()==false)
      return; //user cancelled

   // Figure out the name of the remote file
   TQString weburl = configData->getWebURL();
   TQString file = getExecuteFile();

   // Force TDEHTMLPart to reload the page
   KParts::BrowserExtension* be = m_htmlView->browserExtension();
   if (be) {
      KParts::URLArgs urlArgs( be->urlArgs() );
      urlArgs.reload = true;
      be->setURLArgs( urlArgs );
   }

   // Acutally do the request
   m_phpExeOutput="";
   m_htmlView->openURL(KURL(weburl + file));
   m_htmlView->show();
}

TQString PHPSupportPart::getExecuteFile() {
   TQString file;
   PHPConfigData::StartupFileMode mode = configData->getStartupFileMode();

   TQString weburl = configData->getWebURL();
   if (mode == PHPConfigData::Current) {
      KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(partController()->activePart());
      if (ro_part) {
         if ( configData->getInvocationMode() == PHPConfigData::Web )
            file = URLUtil::relativePath( project()->projectDirectory(), ro_part->url().path() );
         else
            file = ro_part->url().path();
      }
   }
   if (mode == PHPConfigData::Default) {
      file = configData->getStartupFile();
   }
   return file;
}

void PHPSupportPart::slotWebJobStarted(TDEIO::Job* job) {
   if (job && job->className() == TQString("TDEIO::TransferJob")) {
      kdDebug(9018) << endl << "job started" << job->progressId();
      TDEIO::TransferJob *tjob = static_cast<TDEIO::TransferJob*>(job);
      connect( tjob,  TQT_SIGNAL(data(TDEIO::Job*, const TQByteArray&)),
               this, TQT_SLOT(slotWebData(TDEIO::Job*, const TQByteArray&)));
      connect( tjob,  TQT_SIGNAL(result(TDEIO::Job*)),
               this, TQT_SLOT(slotWebResult(TDEIO::Job*)));
   }
}

void PHPSupportPart::slotWebData(TDEIO::Job* /*job*/,const TQByteArray& data) {
   kdDebug(9018) << "slotWebData()" << endl;
   TQString strData(data);
   m_phpExeOutput += strData;
}

void PHPSupportPart::slotWebResult(TDEIO::Job* /*job*/) {
   kdDebug(9018) << "slotWebResult()" << endl;
   TQString file = getExecuteFile();
   PHPFile *pfile = new PHPFile(this, file);
   pfile->ParseStdout(m_phpExeOutput);
   delete pfile;
}

void PHPSupportPart::executeInTerminal() {
   kdDebug(9018) << "slotExecuteInTerminal()" << endl;

   // Save all files once
   if (partController()->saveAllFiles()==false)
       return; //user cancelled

   TQString file = getExecuteFile();

   if (m_htmlView == 0) {
      m_htmlView = new PHPHTMLView(this);
      mainWindow()->embedOutputView(m_htmlView->view(), i18n("PHP"), i18n("PHP") );
   }

   m_htmlView->show();
   m_htmlView->begin();

   m_phpExeOutput = "";
   phpExeProc->clearArguments();
   *phpExeProc << configData->getPHPExecPath();
   *phpExeProc << "-f";

   *phpExeProc << KShellProcess::quote(file);
   kdDebug(9018) << "" << file.latin1() << endl;
   phpExeProc->start(TDEProcess::NotifyOnExit,TDEProcess::All);

   //    core()->gotoDocumentationFile(KURL("http://www.php.net"));
}

void PHPSupportPart::slotReceivedPHPExeStdout (TDEProcess* /*proc*/, char* buffer, int buflen) {
   kdDebug(9018) << "slotPHPExeStdout()" << endl;
   m_phpExeOutput += TQString::fromLocal8Bit(buffer,buflen+1);

   TQString buf = buffer;
   if (configData->getInvocationMode() == PHPConfigData::Shell)
     buf.replace("\n", "<br>");
    m_htmlView->write(buf);
}

void PHPSupportPart::slotReceivedPHPExeStderr (TDEProcess* /*proc*/, char* buffer, int buflen) {
   kdDebug(9018) << "slotPHPExeStderr()" << endl;
   m_phpExeOutput += TQString::fromLocal8Bit(buffer,buflen+1);

   TQString buf = buffer;
   if (configData->getInvocationMode() == PHPConfigData::Shell)
      buf.replace("\n", "<br>");
   m_htmlView->write(buf);
}

void PHPSupportPart::slotPHPExeExited (TDEProcess* /*proc*/) {
   kdDebug(9018) << "slotPHPExeExited()" << endl;
   m_htmlView->end();
   TQString file = getExecuteFile();
   PHPFile *pfile = new PHPFile(this, file);
   pfile->ParseStdout(m_phpExeOutput);
   delete pfile;
}

void PHPSupportPart::projectOpened()
{
    kdDebug(9018) << "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 &)) );

    if (!m_parser) {
       m_parser = new  PHPParser( this );
       m_parser->start();
    }

    // We want to parse only after all components have been
    // properly initialized
    TQTimer::singleShot(500, this, TQT_SLOT( initialParse() ) );
}

void PHPSupportPart::initialParse( )
{
        // For debugging
        if ( !project( ) )
        {
                // messagebox ?
                kdDebug( 9018 ) << "No project" << endl;
                return ;
        }

        parseProject( );
        return ;
}

void PHPSupportPart::projectClosed()
{
   kdDebug(9018) << "projectClosed()" << endl;

   if (m_parser) {
      m_parser->close() ;
      delete( m_parser );
      m_parser = 0;
   }
}

bool PHPSupportPart::parseProject()
{
   kdDebug(9018) << "parseProject()" << endl;
   mainWindow() ->statusBar() ->message( i18n( "Updating..." ) );

   kapp->setOverrideCursor( waitCursor );

   _jd = new JobData;

   _jd->files = project()->allFiles();

   TQProgressBar* bar = new TQProgressBar( _jd->files.count( ), mainWindow( ) ->statusBar( ) );
   bar->setMinimumWidth( 120 );
   bar->setCenterIndicator( true );
   mainWindow()->statusBar()->addWidget( bar );
   bar->show();

   _jd->progressBar = bar;
   _jd->it = _jd->files.begin();
   _jd->dir.setPath( project()->projectDirectory() );

   TQTimer::singleShot( 0, this, TQT_SLOT( slotParseFiles() ) );
   return TRUE;
}

void PHPSupportPart::slotParseFiles()
{
   kdDebug(9018) << "slotParseFiles()" << endl;

   kapp->lock();

   if ( _jd->it != _jd->files.end() )
   {
      _jd->progressBar->setProgress( _jd->progressBar->progress() + 1 );

      TQFileInfo fileInfo( _jd->dir, *( _jd->it ) );

      if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() )
      {
         TQString absFilePath = URLUtil::canonicalPath( fileInfo.absFilePath() );

//         if ( isValidSource( absFilePath ) )
         {
            if (m_parser)
               m_parser->addFile( absFilePath );
         }

         ++( _jd->it );
      }
      TQTimer::singleShot( 0, this, TQT_SLOT( slotParseFiles() ) );
   }
   else // finished or interrupted
   {
      kapp->restoreOverrideCursor();
      mainWindow()->statusBar()->removeWidget( _jd->progressBar );
      mainWindow()->statusBar()->message( i18n( "Done" ), 2000 );

      emit updatedSourceInfo();
      if (m_parser)
         m_parser->startParse();

      delete _jd;
      _jd = 0;
   }

   kapp->unlock();
}

void PHPSupportPart::addedFilesToProject(const TQStringList &fileList)
{
   kdDebug(9018) << "addedFilesToProject()" << endl;

   TQStringList::ConstIterator it;

   for ( it = fileList.begin(); it != fileList.end(); ++it )
   {
      TQFileInfo fileInfo( project()->projectDirectory(), *it );
      if (m_parser) {
         m_parser->addFile( fileInfo.absFilePath() );
         emit addedSourceInfo( fileInfo.absFilePath() );
      }
   }
}

void PHPSupportPart::removedFilesFromProject(const TQStringList &fileList)
{
   kdDebug(9018) << "removedFilesFromProject()" << endl;

   TQStringList::ConstIterator it;

   for ( it = fileList.begin(); it != fileList.end(); ++it )
   {
      TQFileInfo fileInfo( project()->projectDirectory(), *it );
      TQString path = fileInfo.absFilePath();
      if ( codeModel()->hasFile(path) ) {
         emit aboutToRemoveSourceInfo( path );
         codeModel()->removeFile( codeModel()->fileByName(path) );
      }
   }
}

void PHPSupportPart::savedFile(const KURL &fileName)
{
   kdDebug(9018) << "savedFile()" << fileName.fileName() << endl;
/// @fixme when activated could cause stop
/*
   if (m_parser) {
      if (m_parser->hasFile( fileName.path() )) {
         m_parser->reparseFile( fileName.path() );
      }
   }
*/
}

TQString PHPSupportPart::getIncludePath()
{
   return configData->getPHPIncludePath();
}

TQString PHPSupportPart::getExePath()
{
   return configData->getPHPExecPath();
}

KDevLanguageSupport::Features PHPSupportPart::features()
{
   return Features(Classes | Functions);
}

KMimeType::List PHPSupportPart::mimeTypes( )
{
   KMimeType::List list;
   KMimeType::Ptr mime = KMimeType::mimeType( "application/x-php" );
   if ( mime )
      list << mime;

   mime = KMimeType::mimeType( "text/plain" );
   if ( mime )
      list << mime;
   return list;
}

void PHPSupportPart::customEvent( TQCustomEvent* ev )
{
//   kdDebug(9018) << "phpSupportPart::customEvent(" << ev->type() << ") " << TQThread::currentThread() << endl;

   if ( ev->type() < Event_AddFile || ev->type() > Event_AddFixme )
      return;

   kapp->lock();

   FileParseEvent* event = (FileParseEvent*) ev;
   NamespaceDom ns = codeModel()->globalNamespace();
   FileDom m_file = codeModel()->fileByName( event->fileName() );

   if (!m_file) {
      m_file = codeModel()->create<FileModel>();
      m_file->setName( event->fileName() );
      codeModel()->addFile( m_file );
   }

   switch (int(ev->type())) {
      case Event_AddFile:
         m_parser->addFile( event->fileName() );
      break;

      case Event_StartParse:
//         kdDebug(9018) << "StartParse " << event->fileName() << endl;
         LastClass = NULL;
         LastMethod = NULL;
         LastVariable = NULL;
         if ( codeModel()->hasFile( event->fileName() ) ) {
            emit aboutToRemoveSourceInfo( event->fileName() );
            codeModel()->removeFile( codeModel()->fileByName( event->fileName() ) );
            emit removedSourceInfo( event->fileName() );
         }
         ErrorView()->removeAllProblems( event->fileName() );
      break;

      case Event_AddClass:
      {
//         kdDebug(9018) << "AddClass " << event->name() << endl;
         ClassDom nClass = codeModel()->create<ClassModel>();
         nClass->setFileName( event->fileName() );
         nClass->setName( event->name() );
         nClass->setStartPosition( event->posititon(), 0);

         m_file->addClass( nClass );
         if ( event->arguments().isEmpty() != TRUE )
            nClass->addBaseClass( event->arguments() );

         ns->addClass( nClass );
         LastClass = nClass;
      }
      break;

      case Event_CloseClass:
         if ( LastClass != NULL ) {
//            kdDebug(9018) << "CloseClass " << LastClass->name() << endl;
            LastClass->setEndPosition( event->posititon(), 0 );
            LastClass = NULL;
            LastMethod = NULL;
            LastVariable = NULL;
         }
      break;

      case Event_AddFunction:
      {
//         kdDebug(9018) << "AddFunction " << event->name() << endl;
         FunctionDom nMethod = codeModel()->create<FunctionModel>();
         nMethod->setFileName( event->fileName() );
         nMethod->setName( event->name() );
         nMethod->setStartPosition( event->posititon(), 0 );

         ArgumentDom nArgument;
         nArgument = codeModel()->create<ArgumentModel>();
         nArgument->setType(event->arguments().stripWhiteSpace().local8Bit());
         nMethod->addArgument( nArgument );

         if (LastClass != NULL) {
            LastClass->addFunction(nMethod);
         } else {
            ns->addFunction(nMethod);
         }
         LastMethod = nMethod;
      }
      break;

      case Event_SetFunction:
         if ( LastMethod != NULL ) {
//            kdDebug(9018) << "SetFunction " << LastMethod->name() << " " << event->name() << endl;
            if ( event->name() == "static" )
               LastMethod->setStatic(true);
            else if ( event->name() == "abstract" )
               LastMethod->setAbstract(true);
            else if ( event->name() == "private" )
               LastMethod->setAccess(FunctionModel::Private);
            else if ( event->name() == "public" )
               LastMethod->setAccess(FunctionModel::Public);
            else if ( event->name() == "protected" )
               LastMethod->setAccess(FunctionModel::Protected);
            else if ( event->name() == "result" ) {
               TQString ret = "";
               if (event->arguments().lower() == "$this" && LastClass ) {
                  ret = LastClass->name();
               }
               LastMethod->setResultType(ret);
            }
         }
      break;

      case Event_CloseFunction:
         if ( LastMethod != NULL ) {
//            kdDebug(9018) << "CloseFunction " << LastMethod->name() << endl;
            LastMethod->setEndPosition( event->posititon(), 0 );
            LastMethod = NULL;
            LastVariable = NULL;
         }
      break;

      case Event_AddVariable:
      {
         VariableDom nVariable = codeModel()->create<VariableModel>();

         nVariable->setFileName( event->fileName() );
         nVariable->setName( event->name() );
         nVariable->setStartPosition( event->posititon(), 0 );
         nVariable->setAccess(VariableModel::Public);

         if ( event->arguments().isEmpty() != TRUE )
            nVariable->setType( event->arguments() );

         if ( LastClass != NULL && ( LastMethod == NULL || event->global() == TRUE ) ) {
//               kdDebug(9018) << "AddVariable To Class " << LastClass->name() << " " << nVariable->name() << endl;
            LastClass->addVariable(nVariable);
         } else {
            if ( LastMethod != NULL ) {
               kdDebug(9018) << "AddVariable " << LastMethod->name() << " " << nVariable->name() << endl;
            } else {
               ns->addVariable(nVariable);
            }
         }
         LastVariable = nVariable;
      }
      break;

      case Event_SetVariable:
         if ( LastVariable != NULL ) {
//            kdDebug(9018) << "SetVariable " << LastVariable->name() << " " << event->arguments() << endl;
            if ( event->arguments() == "static" )
               LastVariable->setStatic(true);
            else if ( event->arguments() == "private" )
               LastVariable->setAccess(FunctionModel::Private);
            else if ( event->arguments() == "public" )
               LastVariable->setAccess(FunctionModel::Public);
            else if ( event->arguments() == "protected" )
               LastVariable->setAccess(FunctionModel::Protected);
         }
      break;

      case Event_AddTodo:
         ErrorView()->reportProblem(Todo, event->fileName(), event->posititon(), event->arguments());
      break;

      case Event_AddFixme:
         ErrorView()->reportProblem(Fixme, event->fileName(), event->posititon(), event->arguments());
      break;

      case Event_EndParse:
//         kdDebug(9018) << "EndParse " << event->fileName() << endl;
         emit addedSourceInfo( event->fileName() );
      break;

   }

   kapp->unlock();
   kapp->processEvents();
}

PHPErrorView *PHPSupportPart::ErrorView( ) {
   return m_phpErrorView;
}

PHPParser *PHPSupportPart::Parser( ) {
   return m_parser;
}

#include "phpsupportpart.moc"
