KDevelop API Documentation

cppsupportpart.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 1999 by Jonas Nordin                                    *
00003  *   jonas.nordin@syncom.se                                                *
00004  *   Copyright (C) 2000-2001 by Bernd Gehrmann                             *
00005  *   bernd@kdevelop.org                                                    *
00006  *   Copyright (C) 2002-2003 by Roberto Raggi                              *
00007  *   roberto@kdevelop.org                                                  *
00008  *   Copyright (C) 2003-2004 by Alexander Dymo                             *
00009  *   adymo@mksat.net                                                       *
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "cppsupportpart.h"
00019 #include "cppsupport_events.h"
00020 #include "problemreporter.h"
00021 #include "backgroundparser.h"
00022 #include "store_walker.h"
00023 #include "ast.h"
00024 #include "ast_utils.h"
00025 #include "cppcodecompletion.h"
00026 #include "ccconfigwidget.h"
00027 #include "KDevCppSupportIface.h"
00028 #include "cppsupportfactory.h"
00029 #include "catalog.h"
00030 #include "cpp_tags.h"
00031 #include "kdevdriver.h"
00032 #include "cppcodecompletionconfig.h"
00033 #include "tag_creator.h"
00034 #include "cppsupport_utils.h"
00035 #include "classgeneratorconfig.h"
00036 #include "urlutil.h"
00037 
00038 // wizards
00039 #include "cppnewclassdlg.h"
00040 #include "subclassingdlg.h"
00041 #include "addmethoddialog.h"
00042 #include "addattributedialog.h"
00043 
00044 // designer integration
00045 #include "qtdesignerintegration.h"
00046 
00047 #include <qheader.h>
00048 #include <qdir.h>
00049 #include <qdom.h>
00050 #include <qfileinfo.h>
00051 #include <qguardedptr.h>
00052 #include <qpopupmenu.h>
00053 #include <qprogressdialog.h>
00054 #include <qstringlist.h>
00055 #include <qtimer.h>
00056 #include <qstatusbar.h>
00057 #include <qprogressbar.h>
00058 #include <qregexp.h>
00059 #include <qlabel.h>
00060 #include <qvbox.h>
00061 #include <kmessagebox.h>
00062 #include <kaction.h>
00063 #include <kapplication.h>
00064 #include <kdebug.h>
00065 #include <kdialogbase.h>
00066 #include <kgenericfactory.h>
00067 #include <klocale.h>
00068 #include <kmessagebox.h>
00069 #include <kmainwindow.h>
00070 #include <kstatusbar.h>
00071 #include <kconfig.h>
00072 #include <kdeversion.h>
00073 #include <kstandarddirs.h>
00074 #include <kiconloader.h>
00075 
00076 #include <ktexteditor/document.h>
00077 #include <ktexteditor/editinterface.h>
00078 #include <ktexteditor/view.h>
00079 #include <ktexteditor/selectioninterface.h>
00080 #include <ktexteditor/viewcursorinterface.h>
00081 #include <ktexteditor/clipboardinterface.h>
00082 
00083 #if defined(KDE_MAKE_VERSION)
00084 # if KDE_VERSION >= KDE_MAKE_VERSION(3,1,90)
00085 #  include <ktexteditor/texthintinterface.h>
00086 # else
00087 #  include <kde30x_texthintinterface.h>
00088 # endif
00089 #else
00090 #  include <kde30x_texthintinterface.h>
00091 #endif
00092 
00093 #include <kdevcore.h>
00094 #include <kdevproject.h>
00095 #include <kdevmainwindow.h>
00096 #include <kdevpartcontroller.h>
00097 #include <kdevmakefrontend.h>
00098 #include <kdevcoderepository.h>
00099 #include <codemodel_utils.h>
00100 
00101 #include <domutil.h>
00102 #include <config.h>
00103 
00104 enum { KDEV_DB_VERSION = 6 };
00105 enum { KDEV_PCS_VERSION = 5 };
00106 
00107 QStringList CppSupportPart::m_sourceMimeTypes = QStringList() << "text/x-csrc" << "text/x-c++src";
00108 QStringList CppSupportPart::m_headerMimeTypes = QStringList() << "text/x-chdr" << "text/x-c++hdr";
00109 
00110 QStringList CppSupportPart::m_sourceExtensions = QStringList::split( ",", "c,C,cc,cpp,c++,cxx,m,mm,M" );
00111 QStringList CppSupportPart::m_headerExtensions = QStringList::split( ",", "h,H,hh,hxx,hpp,inl,tlh,diff,ui.h" );
00112 
00113 class CppDriver: public KDevDriver
00114 {
00115 public:
00116     CppDriver( CppSupportPart* cppSupport )
00117     : KDevDriver( cppSupport )
00118     {
00119     }
00120 
00121     void fileParsed( const QString& fileName )
00122     {
00123     //kdDebug(9007) << "-----> file " << fileName << " parsed!" << endl;
00124     TranslationUnitAST::Node ast = takeTranslationUnit( fileName );
00125 
00126         if( cppSupport()->problemReporter() ){
00127         cppSupport()->problemReporter()->removeAllProblems( fileName );
00128 
00129         QValueList<Problem> pl = problems( fileName );
00130         QValueList<Problem>::ConstIterator it = pl.begin();
00131         while( it != pl.end() ){
00132             const Problem& p = *it++;
00133             cppSupport()->problemReporter()->reportProblem( fileName, p );
00134         }
00135     }
00136 
00137     StoreWalker walker( fileName, cppSupport()->codeModel() );
00138 
00139     if( cppSupport()->codeModel()->hasFile(fileName) ){
00140         FileDom file = cppSupport()->codeModel()->fileByName( fileName );
00141         cppSupport()->removeWithReferences( fileName );
00142     }
00143 
00144     walker.parseTranslationUnit( ast.get() );
00145     cppSupport()->codeModel()->addFile( walker.file() );
00146     remove( fileName );
00147     }
00148 };
00149 
00150 CppSupportPart::CppSupportPart(QObject *parent, const char *name, const QStringList &args)
00151     : KDevLanguageSupport("CppSupport", "source_cpp", parent, name ? name : "KDevCppSupport"),
00152       m_activeDocument( 0 ), m_activeView( 0 ), m_activeSelection( 0 ), m_activeEditor( 0 ),
00153       m_activeViewCursor( 0 ), m_projectClosed( true ), m_valid( false )
00154 {
00155     setInstance(CppSupportFactory::instance());
00156 
00157     m_pCompletionConfig = new CppCodeCompletionConfig( this, projectDom() );
00158     connect( m_pCompletionConfig, SIGNAL(stored()), this, SLOT(codeCompletionConfigStored()) );
00159 
00160     m_driver = new CppDriver( this );
00161     m_problemReporter = 0;
00162 
00163     m_functionHintTimer = new QTimer( this );
00164 //    connect( m_functionHintTimer, SIGNAL(timeout()), this, SLOT(slotFunctionHint()) );
00165 
00166     setXMLFile( "kdevcppsupport.rc" );
00167 
00168     m_catalogList.setAutoDelete( true );
00169 
00170     connect( core(), SIGNAL(projectOpened()), this, SLOT(projectOpened()) );
00171     connect( core(), SIGNAL(projectClosed()), this, SLOT(projectClosed()) );
00172     connect( core(), SIGNAL(languageChanged()), this, SLOT(projectOpened()) );
00173     connect( partController(), SIGNAL(savedFile(const KURL&)),
00174              this, SLOT(savedFile(const KURL&)) );
00175     connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)),
00176              this, SLOT(contextMenu(QPopupMenu *, const Context *)) );
00177     connect( partController(), SIGNAL(activePartChanged(KParts::Part*)),
00178              this, SLOT(activePartChanged(KParts::Part*)));
00179     connect( partController(), SIGNAL(partRemoved(KParts::Part*)),
00180              this, SLOT(partRemoved(KParts::Part*)));
00181 
00182     connect( core(), SIGNAL(configWidget(KDialogBase*)),
00183              this, SLOT(configWidget(KDialogBase*)) );
00184 
00185     KAction *action;
00186 
00187     action = new KAction(i18n("Switch Header/Implementation"), SHIFT+Key_F12,
00188                          this, SLOT(slotSwitchHeader()),
00189                          actionCollection(), "edit_switchheader");
00190     action->setToolTip( i18n("Switch between header and implementation files") );
00191     action->setWhatsThis( i18n("<b>Switch Header/Implementation</b><p>"
00192                                "If you are currently looking at a header file, this "
00193                                "brings you to the corresponding implementation file. "
00194                                "If you are looking at an implementation file (.cpp etc.), "
00195                                "this brings you to the corresponding header file.") );
00196     action->setEnabled(false);
00197 
00198     action = new KAction(i18n("Complete Text"), CTRL+Key_Space,
00199                          this, SLOT(slotCompleteText()),
00200                          actionCollection(), "edit_complete_text");
00201     action->setToolTip( i18n("Complete current expression") );
00202     action->setWhatsThis( i18n("<b>Complete Text</p><p>Completes current expression using "
00203                                "memory class store for the current project and persistant class stores "
00204                                "for external libraries.") );
00205     action->setEnabled(false);
00206 
00207     action = new KAction(i18n("Make Member"), "makermember", Key_F2,
00208                          this, SLOT(slotMakeMember()),
00209                          actionCollection(), "edit_make_member");
00210     action->setToolTip(i18n("Make member"));
00211     action->setWhatsThis(i18n("<b>Make member</b><p>Creates a class member function in implementation file "
00212                               "based on the member declaration at the current line."));
00213     action->plug(new QWidget());
00214 
00215     action = new KAction(i18n("New Class..."), "classnew", 0,
00216                          this, SLOT(slotNewClass()),
00217                          actionCollection(), "project_newclass");
00218     action->setToolTip( i18n("Generate a new class") );
00219     action->setWhatsThis( i18n("<b>New Class</b><p>Calls the <b>New Class</b> wizard.") );
00220 
00221     m_pCompletion  = 0;
00222 
00223     withcpp = false;
00224     if ( args.count() == 1 && args[ 0 ] == "Cpp" )
00225         withcpp = true;
00226 
00227     // daniel
00228     connect( core( ), SIGNAL( projectConfigWidget( KDialogBase* ) ), this,
00229              SLOT( projectConfigWidget( KDialogBase* ) ) );
00230 
00231     new KDevCppSupportIface( this );
00232     //(void) dcopClient();
00233 }
00234 
00235 
00236 CppSupportPart::~CppSupportPart()
00237 {
00238     if ( !m_projectClosed )
00239       projectClosed();
00240 
00241     delete( m_driver );
00242     m_driver = 0;
00243 
00244     if( m_backgroundParser ){
00245     m_backgroundParser->close();
00246 //  m_backgroundParser->wait();
00247     delete m_backgroundParser;
00248     m_backgroundParser = 0;
00249     }
00250 
00251     codeRepository()->setMainCatalog( 0 );
00252 
00253     QPtrListIterator<Catalog> it( m_catalogList );
00254     while( Catalog* catalog = it.current() ){
00255         ++it;
00256         codeRepository()->unregisterCatalog( catalog );
00257     }
00258 
00259     mainWindow( )->removeView( m_problemReporter );
00260 
00261     delete m_pCompletion;
00262     delete m_problemReporter;
00263 
00264     m_pCompletion = 0;
00265     m_problemReporter = 0;
00266 
00267     delete _jd;
00268     _jd = 0;
00269 
00270     kdDebug(9007) << k_funcinfo << endl;
00271 }
00272 
00273 void CppSupportPart::customEvent( QCustomEvent* ev )
00274 {
00275     kdDebug(9007) << "CppSupportPart::customEvent(" << ev->type() << ")" << endl;
00276 
00277     QTime t;
00278     t.start();
00279 
00280     if( ev->type() == int(Event_FileParsed) ){
00281     FileParsedEvent* event = (FileParsedEvent*) ev;
00282     QString fileName = event->fileName();
00283         if( m_problemReporter ){
00284         m_problemReporter->removeAllProblems( fileName );
00285 
00286         bool hasErrors = false;
00287         QValueList<Problem> problems = event->problems();
00288         QValueList<Problem>::ConstIterator it = problems.begin();
00289         while( it != problems.end() ){
00290             const Problem& p = *it++;
00291         if( p.level() == Problem::Level_Error )
00292             hasErrors = true;
00293 
00294             m_problemReporter->reportProblem( fileName, p );
00295         }
00296             recomputeCodeModel( fileName );
00297         //QTimer::singleShot( 0, this, SLOT(recomputeCodeModel()) );
00298     }
00299 
00300     emit fileParsed( fileName );
00301     }
00302 }
00303 
00304 void CppSupportPart::projectConfigWidget( KDialogBase* dlg )
00305 {
00306     QVBox* vbox = 0;
00307 
00308     vbox = dlg->addVBoxPage( i18n( "C++ Specific" ), i18n( "C++ Specific" ), BarIcon( icon(), KIcon::SizeMedium) );
00309     CCConfigWidget* w = new CCConfigWidget( this, vbox );
00310     connect( dlg, SIGNAL( okClicked( ) ), w, SLOT( accept( ) ) );
00311 }
00312 
00313 void CppSupportPart::configWidget(KDialogBase *dlg)
00314 {
00315     QVBox *vbox = dlg->addVBoxPage(i18n("C++ Class Generator"), i18n( "C++ Class Generator" ), BarIcon( icon(), KIcon::SizeMedium) );
00316   ClassGeneratorConfig *w = new ClassGeneratorConfig(vbox, "classgenerator config widget");
00317   connect(dlg, SIGNAL(okClicked()), w, SLOT(storeConfig()));
00318 }
00319 
00320 void CppSupportPart::activePartChanged(KParts::Part *part)
00321 {
00322     kdDebug(9032) << "CppSupportPart::activePartChanged()" << endl;
00323 
00324     bool enabled = false;
00325 
00326     m_functionHintTimer->stop();
00327 
00328     if( m_activeView )
00329     {
00330     disconnect( m_activeView, SIGNAL(cursorPositionChanged()), this, SLOT(slotCursorPositionChanged()) );
00331     }
00332 
00333     m_activeDocument = dynamic_cast<KTextEditor::Document*>( part );
00334     m_activeView = part ? dynamic_cast<KTextEditor::View*>( part->widget() ) : 0;
00335     m_activeEditor = dynamic_cast<KTextEditor::EditInterface*>( part );
00336     m_activeSelection = dynamic_cast<KTextEditor::SelectionInterface*>( part );
00337     m_activeViewCursor = part ? dynamic_cast<KTextEditor::ViewCursorInterface*>( m_activeView ) : 0;
00338 
00339     m_activeFileName = QString::null;
00340 
00341     if (m_activeDocument) {
00342     m_activeFileName = URLUtil::canonicalPath( m_activeDocument->url().path() );
00343         QFileInfo fi( m_activeFileName );
00344         QString ext = fi.extension();
00345         if( isSource(m_activeFileName) || isHeader(m_activeFileName) )
00346         enabled = true;
00347     }
00348 
00349     actionCollection()->action( "edit_switchheader" )->setEnabled( enabled );
00350     actionCollection()->action( "edit_complete_text" )->setEnabled( enabled );
00351     actionCollection()->action( "edit_make_member" )->setEnabled( enabled );
00352 
00353     if( !part )
00354     return;
00355 
00356     if( !m_activeView )
00357     return;
00358 
00359     if( m_activeViewCursor )
00360     {
00361     connect( m_activeView, SIGNAL(cursorPositionChanged()),
00362          this, SLOT(slotCursorPositionChanged()) );
00363     }
00364 
00365 #if 0
00366     KTextEditor::TextHintInterface* textHintIface = dynamic_cast<KTextEditor::TextHintInterface*>( m_activeView );
00367     if( !textHintIface )
00368     return;
00369 
00370     connect( view, SIGNAL(needTextHint(int,int,QString&)),
00371          this, SLOT(slotNeedTextHint(int,int,QString&)) );
00372 
00373     textHintIface->enableTextHints( 1000 );
00374 #endif
00375 }
00376 
00377 
00378 void CppSupportPart::projectOpened( )
00379 {
00380     kdDebug( 9007 ) << "projectOpened( )" << endl;
00381 
00382     m_backgroundParser = new BackgroundParser( this, &m_eventConsumed );
00383     m_backgroundParser->start();
00384 
00385     // setup the driver
00386     QString conf_file_name = specialHeaderName();
00387     if( QFile::exists(conf_file_name) )
00388         m_driver->parseFile( conf_file_name, true );
00389 
00390     m_projectDirectory = URLUtil::canonicalPath( project()->projectDirectory() );
00391     m_projectFileList = project()->allFiles();
00392 
00393     setupCatalog();
00394 
00395     m_problemReporter = new ProblemReporter( this );
00396     m_problemReporter->setIcon( SmallIcon("info") );
00397     m_problemReporter->setCaption( i18n("Problem Reporter") );
00398     mainWindow( )->embedOutputView( m_problemReporter, i18n("Problems"), i18n("Problem reporter"));
00399 
00400     connect( core(), SIGNAL(configWidget(KDialogBase*)),
00401              m_problemReporter, SLOT(configWidget(KDialogBase*)) );
00402 
00403     connect( project( ), SIGNAL( addedFilesToProject( const QStringList & ) ),
00404              this, SLOT( addedFilesToProject( const QStringList & ) ) );
00405     connect( project( ), SIGNAL( removedFilesFromProject( const QStringList &) ),
00406              this, SLOT( removedFilesFromProject( const QStringList & ) ) );
00407     connect( project( ), SIGNAL( changedFilesInProject( const QStringList & ) ),
00408              this, SLOT( changedFilesInProject( const QStringList & ) ) );
00409     connect( project(), SIGNAL(projectCompiled()),
00410          this, SLOT(slotProjectCompiled()) );
00411 
00412     QDir::setCurrent( m_projectDirectory );
00413 
00414     m_timestamp.clear();
00415 
00416     m_pCompletion = new CppCodeCompletion( this );
00417     m_projectClosed = false;
00418 
00419     QTimer::singleShot( 500, this, SLOT( initialParse( ) ) );
00420 }
00421 
00422 
00423 void CppSupportPart::projectClosed( )
00424 {
00425     kdDebug( 9007 ) << "projectClosed( )" << endl;
00426 
00427     QStringList enabledPCSs;
00428     QValueList<Catalog*> catalogs = codeRepository()->registeredCatalogs();
00429     for( QValueList<Catalog*>::Iterator it=catalogs.begin(); it!=catalogs.end(); ++it )
00430     {
00431     Catalog* c = *it;
00432     if( c->enabled() )
00433         enabledPCSs.push_back( QFileInfo(c->dbName()).baseName() );
00434     }
00435     DomUtil::writeListEntry( *project()->projectDom(), "kdevcppsupport/references", "pcs", enabledPCSs );
00436 
00437     for (QMap<KInterfaceDesigner::DesignerType, KDevDesignerIntegration*>::const_iterator it =  m_designers.begin();
00438         it != m_designers.end(); ++it)
00439     {
00440         kdDebug() << "calling save settings fro designer integration" << endl;
00441         it.data()->saveSettings(*project()->projectDom(), "kdevcppsupport/designerintegration");
00442     }
00443     
00444     saveProjectSourceInfo();
00445 
00446     m_pCompletionConfig->store();
00447 
00448     delete _jd;
00449     _jd = 0;
00450 
00451     delete m_pCompletion;
00452     m_pCompletion = 0;
00453     m_projectClosed = true;
00454 }
00455 
00456 
00457 QString CppSupportPart::findHeader(const QStringList &list, const QString &header)
00458 {
00459     QStringList::ConstIterator it;
00460     for (it = list.begin(); it != list.end(); ++it) {
00461         QString s = *it;
00462         int pos = s.findRev('.');
00463         if (pos != -1)
00464             s = s.left(pos) + ".h";
00465         if (s.right(header.length()) == header)
00466             return s;
00467     }
00468 
00469     return QString::null;
00470 }
00471 
00472 
00473 void CppSupportPart::contextMenu(QPopupMenu *popup, const Context *context)
00474 {
00475     m_activeClass = 0;
00476     m_activeFunction = 0;
00477     m_activeVariable = 0;
00478 
00479     if( context->hasType(Context::EditorContext) ){
00480         int id;
00481     
00482     //Cache some values that are constant in this function
00483     bool is_header, is_source;
00484     QString source_header_candidate;
00485         
00486     is_header = isHeader(m_activeFileName);
00487     is_source = isSource(m_activeFileName); 
00488     
00489         QString text;
00490         int atline, atcol;
00491         MakeMemberHelper(text,atline,atcol);
00492         if(!text.isEmpty())
00493         {
00494          id = popup->insertItem( i18n( "Make Member"),
00495                 this, SLOT( slotMakeMember() ) );
00496          popup->setWhatsThis( id, i18n("<b>Make member</b><p>Creates a class member function in implementation file "
00497                               "based on the member declaration at the current line."));
00498         }
00499         
00500     if((source_header_candidate = sourceOrHeaderCandidate()) != QString::null)
00501     {
00502     
00503      
00504     }
00505 
00506        kdDebug(9007) << "======> code model has the file: " << m_activeFileName << " = " << codeModel()->hasFile( m_activeFileName ) << endl;
00507        if( codeModel()->hasFile(m_activeFileName) ){
00508            kdDebug() << "CppSupportPart::contextMenu 1" << endl;
00509            QString candidate;
00510            if (is_source)
00511                candidate = source_header_candidate;
00512            else
00513                candidate = m_activeFileName;
00514            
00515         unsigned int curLine = 0, curCol = 0;
00516         if (m_activeViewCursor != 0)
00517             m_activeViewCursor->cursorPosition(&curLine, &curCol);
00518         
00519         FunctionDom currentFunction = 0;
00520         bool hasDeclAndDef = false;//indicate wether a matfching declaration/definition has been found
00521         bool fileExists = !candidate.isEmpty() && codeModel()->hasFile(candidate);
00522 //           kdDebug() << "CppSupportPart::contextMenu 2: candidate: " << candidate << endl;
00523            if (fileExists )
00524            {
00525                 QPopupMenu* m2 = new QPopupMenu( popup );
00526                 id = popup->insertItem( i18n("Go to Declaration"), m2 );
00527                 popup->setWhatsThis(id, i18n("<b>Go to declaration</b><p>Provides a menu to select available function declarations "
00528                     "in the current file and in the corresponding header (if the current file is an implementation) or source (if the current file is a header) file."));
00529 
00530                 FileDom file2 = codeModel()->fileByName( candidate );
00531 //                kdDebug() << "CppSupportPart::contextMenu 3: " << file2->name() << endl;
00532 
00533                 FunctionList functionList2 = CodeModelUtils::allFunctions(file2);
00534                 for( FunctionList::ConstIterator it=functionList2.begin(); it!=functionList2.end(); ++it ){
00535                     QString text = (*it)->scope().join( "::");
00536 //                    kdDebug() << "CppSupportPart::contextMenu 3 text: " << text << endl;
00537             if( !text.isEmpty() )
00538             text += "::";
00539             text += formatModelItem( *it, true );
00540             text = text.replace( QString::fromLatin1("&"), QString::fromLatin1("&&") );
00541             int id = m2->insertItem( text, this, SLOT(gotoDeclarationLine(int)) );
00542             int line, column, endLine, endColumn;
00543             (*it)->getStartPosition( &line, &column );
00544             (*it)->getStartPosition( &line, &column );
00545             (*it)->getEndPosition(&endLine, &endColumn);
00546             m2->setItemParameter( id, line );
00547             if (m_activeViewCursor)
00548             if (curLine >= line && curLine <= endLine)//@todo currently column isn't checked, should be sufficient this way
00549                 currentFunction = *it;
00550                 }
00551             if(m2->count() == 0)
00552                 popup->removeItem(id);
00553 //                kdDebug() << "CppSupportPart::contextMenu 4" << endl;
00554            }
00555 
00556            QString candidate1;
00557            if (is_header)
00558                candidate1 = source_header_candidate;
00559            else
00560                candidate1 = m_activeFileName;
00561 //           kdDebug() << "CppSupportPart::go to definition in " << candidate1 << endl;
00562 
00563         FunctionDefinitionDom currentFunctionDefintion = 0;
00564         QString curFuncDefText;
00565         CodeModelUtils::PredDefinitionMatchesDeclaration comparator(currentFunction);
00566         
00567            if( codeModel()->hasFile(candidate1) ){
00568                QPopupMenu* m = new QPopupMenu( popup );
00569                id = popup->insertItem( i18n("Go to Definition"), m );
00570                popup->setWhatsThis(id, i18n("<b>Go to definition</b><p>Provides a menu to select available function definitions "
00571                     "in the current file and in the corresponding header (if the current file is an implementation) or source (if the current file is a header) file."));
00572 
00573                const FileDom file = codeModel()->fileByName( candidate1 );
00574 //               const FunctionDefinitionList functionDefinitionList = file->functionDefinitionList();
00575                const FunctionDefinitionList functionDefinitionList = CodeModelUtils::allFunctionDefinitionsDetailed(file).functionList;
00576                for( FunctionDefinitionList::ConstIterator it=functionDefinitionList.begin(); it!=functionDefinitionList.end(); ++it ){
00577                QString text = (*it)->scope().join( "::");
00578                if( !text.isEmpty() )
00579                text += "::";
00580                text += formatModelItem( *it, true );
00581                text = text.replace( QString::fromLatin1("&"), QString::fromLatin1("&&") );
00582                    int id = m->insertItem( text, this, SLOT(gotoLine(int)) );
00583                int line, column, endLine, endColumn;
00584                (*it)->getStartPosition( &line, &column );
00585            (*it)->getEndPosition(&endLine, &endColumn);
00586                m->setItemParameter( id, line );
00587             if (currentFunction == 0)
00588             {
00589                 if (curLine >= line && curLine <=endLine)//cursor is currently above function defintion, find matching declaration later
00590                 {//@todo currently column isn't checked, should be sufficient this way
00591                     currentFunctionDefintion = *it;
00592                     curFuncDefText= text;
00593                 }
00594             } else
00595             {
00596                 if ( comparator(*it) ) //functiondefintion found for declaration the cursor is currently above
00597                 {
00598                     int tmpId = popup->insertItem(i18n("Go to Definition of This Function")/* + text*/, this, SLOT(gotoLine(int))); 
00599                     int linel, coll;
00600                     (*it)->getStartPosition(&linel, &coll);
00601                     popup->setItemParameter(tmpId, linel);
00602                     hasDeclAndDef = true;
00603                 }
00604             }
00605            
00606                 }
00607                 if(m->count() == 0)
00608                     popup->removeItem(id);
00609                
00610            }
00611         if (fileExists && currentFunction == 0 && currentFunctionDefintion != 0)//cursor is above a functiondefintion, find matching  declaration
00612         {
00613             FileDom file2 = codeModel()->fileByName( candidate );
00614             FunctionList functionList2 = CodeModelUtils::allFunctions(file2);
00615             for( FunctionList::ConstIterator it=functionList2.begin(); it!=functionList2.end(); ++it )
00616                 if (CodeModelUtils::compareDeclarationToDefinition(*it, currentFunctionDefintion))
00617                 {
00618                     int tmpId = popup->insertItem(i18n("Go to Declaration of This Function")/* + curFuncDefText*/, this, SLOT(gotoDeclarationLine(int))); 
00619                     int linel, coll;
00620                     (*it)->getStartPosition(&linel, &coll);
00621                     popup->setItemParameter(tmpId, linel);
00622                     hasDeclAndDef = true;
00623                 }
00624         }
00625         if (!hasDeclAndDef)
00626         {
00627             QString tmp;
00628             if(is_source)
00629                 tmp = i18n("Switch To Header");
00630             else if(is_header)
00631                 tmp = i18n("Switch To Implementation");
00632       
00633             if(!tmp.isEmpty())
00634             {
00635                     id = popup->insertItem( tmp,
00636                         this, SLOT( slotSwitchHeader() ) );
00637                     popup->setWhatsThis( id, i18n("<b>Switch Header/Implementation</b><p>"
00638                                       "If you are currently looking at a header file, this "
00639                                       "brings you to the corresponding implementation file. "
00640                                       "If you are looking at an implementation file (.cpp etc.), "
00641                                       "this brings you to the corresponding header file.") );
00642             }
00643         }
00644        }
00645 
00646     const EditorContext *econtext = static_cast<const EditorContext*>(context);
00647     QString str = econtext->currentLine();
00648     if (str.isEmpty())
00649         return;
00650 
00651     QRegExp re("[ \t]*#include[ \t]*[<\"](.*)[>\"][ \t]*");
00652     if (!re.exactMatch(str))
00653         return;
00654 
00655     QString popupstr = re.cap(1);
00656     m_contextFileName = findHeader(m_projectFileList, popupstr);
00657     if (m_contextFileName.isEmpty())
00658         return;
00659 
00660     id = popup->insertItem( i18n("Goto Include File: %1").arg(popupstr),
00661                this, SLOT(slotGotoIncludeFile()) );
00662     popup->setWhatsThis(id, i18n("<b>Goto include file</b><p>Opens an include file under the cursor position."));
00663 
00664     } else if( context->hasType(Context::CodeModelItemContext) ){
00665     const CodeModelItemContext* mcontext = static_cast<const CodeModelItemContext*>( context );
00666 
00667     if( mcontext->item()->isClass() ){
00668         m_activeClass = (ClassModel*) mcontext->item();
00669         int id = popup->insertItem( i18n("Extract Interface..."), this, SLOT(slotExtractInterface()) );
00670         popup->setWhatsThis(id, i18n("<b>Extract interface</b><p>Extracts interface from the selected class and creates a new class with this interface. "
00671             "No implementation code is extracted and no implementation code is created."));
00672     } else if( mcontext->item()->isFunction() ){
00673         m_activeFunction = (FunctionModel*) mcontext->item();
00674     }
00675     }
00676     else if (context->hasType(Context::FileContext)){
00677         const FileContext *fc = static_cast<const FileContext*>(context);
00678         //this is a .ui file and only selection contains only one such file
00679         kdDebug() << "file context with " << fc->fileName() << endl;
00680         if (fc->fileName().endsWith(".ui"))
00681         {
00682             m_contextFileName = fc->fileName();
00683             int id = popup->insertItem(i18n("Create or Select Implementation..."), this, SLOT(slotCreateSubclass()));
00684             popup->setWhatsThis(id, i18n("<b>Create or select implementation</b><p>Creates or selects a subclass of selected form for use with integrated KDevDesigner."));
00685         }
00686     }
00687 }
00688 
00689 
00690 // Makes sure that header files come first
00691 QStringList CppSupportPart::reorder(const QStringList &list)
00692 {
00693     QStringList headers, others;
00694 
00695     QStringList headerExtensions = QStringList::split(",", "h,H,hh,hxx,hpp,tlh");
00696 
00697     QStringList::ConstIterator it;
00698     for (it = list.begin(); it != list.end(); ++it){
00699     QString fileName = *it;
00700         if (headerExtensions.contains(QFileInfo(*it).extension()))
00701             headers << (*it);
00702         else
00703             others << (*it);
00704     }
00705 
00706     return headers + others;
00707 }
00708 
00709 void CppSupportPart::addedFilesToProject(const QStringList &fileList)
00710 {
00711     m_projectFileList = project()->allFiles();
00712     QStringList files = reorder( fileList );
00713 
00714     for ( QStringList::ConstIterator it = files.begin(); it != files.end(); ++it )
00715     {
00716     QString path = URLUtil::canonicalPath( m_projectDirectory + "/" + (*it) );
00717 
00718     maybeParse( path );
00719     emit addedSourceInfo( path );
00720     }
00721 }
00722 
00723 void CppSupportPart::removedFilesFromProject(const QStringList &fileList)
00724 {
00725     m_projectFileList = project()->allFiles();
00726     for ( QStringList::ConstIterator it = fileList.begin(); it != fileList.end(); ++it )
00727     {
00728     QString path = URLUtil::canonicalPath( m_projectDirectory + "/" + *it );
00729         kdDebug(9007) << "=====================> remove file: " << path << endl;
00730 
00731     removeWithReferences( path );
00732     m_backgroundParser->removeFile( path );
00733     }
00734 }
00735 
00736 void CppSupportPart::changedFilesInProject( const QStringList & fileList )
00737 {
00738     QStringList files = reorder( fileList );
00739 
00740     for ( QStringList::ConstIterator it = files.begin(); it != files.end(); ++it )
00741     {
00742     QString path = URLUtil::canonicalPath( m_projectDirectory + "/" + *it );
00743 
00744     maybeParse( path );
00745     emit addedSourceInfo( path );
00746     }
00747 }
00748 
00749 void CppSupportPart::savedFile(const KURL &fileName)
00750 {
00751     Q_UNUSED( fileName.path() );
00752 
00753 #if 0  // not needed anymore
00754     kdDebug(9007) << "savedFile(): " << fileName.mid ( m_projectDirectory.length() + 1 ) << endl;
00755 
00756     if (m_projectFileList.contains(fileName.mid ( m_projectDirectory.length() + 1 ))) {
00757     maybeParse( fileName );
00758     emit addedSourceInfo( fileName );
00759     }
00760 #endif
00761 }
00762 
00763 QString CppSupportPart::findSourceFile()
00764 {
00765     QFileInfo fi( m_activeFileName );
00766     QString path = fi.filePath();
00767     QString ext = fi.extension();
00768     QString base = path.left( path.length() - ext.length() );
00769     QStringList candidates;
00770 
00771     if (ext == "h" || ext == "H" || ext == "hh" || ext == "hxx" || ext == "hpp" || ext == "tlh") {
00772         candidates << (base + "c");
00773         candidates << (base + "cc");
00774         candidates << (base + "cpp");
00775         candidates << (base + "c++");
00776         candidates << (base + "cxx");
00777         candidates << (base + "C");
00778         candidates << (base + "m");
00779         candidates << (base + "mm");
00780         candidates << (base + "M");
00781     candidates << (base + "inl");
00782     }
00783 
00784     QStringList::ConstIterator it;
00785     for (it = candidates.begin(); it != candidates.end(); ++it) {
00786         kdDebug(9007) << "Trying " << (*it) << endl;
00787         if (QFileInfo(*it).exists()) {
00788             return *it;
00789         }
00790     }
00791 
00792     return m_activeFileName;
00793 }
00794 
00795 QString CppSupportPart::sourceOrHeaderCandidate()
00796 {
00797     KTextEditor::Document *doc = dynamic_cast<KTextEditor::Document*>(partController()->activePart());
00798     if (!doc)
00799       return "";
00800 
00801     QFileInfo fi(doc->url().path());
00802     QString path = fi.filePath();
00803     QString ext = fi.extension();
00804     QString base = path.left(path.length()-ext.length());
00805     kdDebug(9007) << "base: " << base << ", ext: " << ext << endl;
00806     QStringList candidates;
00807     if (ext == "h" || ext == "H" || ext == "hh" || ext == "hxx" || ext == "hpp" || ext == "tlh") {
00808         candidates << (base + "c");
00809         candidates << (base + "cc");
00810         candidates << (base + "cpp");
00811         candidates << (base + "c++");
00812         candidates << (base + "cxx");
00813         candidates << (base + "C");
00814         candidates << (base + "m");
00815         candidates << (base + "mm");
00816         candidates << (base + "M");
00817     candidates << (base + "inl");
00818     } else if (QStringList::split(',', "c,cc,cpp,c++,cxx,C,m,mm,M,inl").contains(ext)) {
00819         candidates << (base + "h");
00820         candidates << (base + "H");
00821         candidates << (base + "hh");
00822         candidates << (base + "hxx");
00823         candidates << (base + "hpp");
00824         candidates << (base + "tlh");
00825     }
00826 
00827     QStringList::ConstIterator it;
00828     for (it = candidates.begin(); it != candidates.end(); ++it) {
00829         kdDebug(9007) << "Trying " << (*it) << endl;
00830         if (QFileInfo(*it).exists()) {
00831             return *it;
00832         }
00833     }
00834     return QString::null;
00835 }
00836 
00837 void CppSupportPart::slotSwitchHeader()
00838 {
00839     partController()->editDocument(KURL( sourceOrHeaderCandidate() ));
00840 }
00841 
00842 void CppSupportPart::slotGotoIncludeFile()
00843 {
00844     if (!m_contextFileName.isEmpty())
00845         partController()->editDocument(KURL( m_contextFileName ), 0);
00846 
00847 }
00848 
00849 KDevLanguageSupport::Features CppSupportPart::features()
00850 {
00851     if (withcpp)
00852         return Features(Classes | Structs | Functions | Variables | Namespaces | Declarations
00853                         | Signals | Slots | AddMethod | AddAttribute | NewClass);
00854     else
00855         return Features (Structs | Functions | Variables | Declarations);
00856 }
00857 
00858 QString CppSupportPart::formatClassName(const QString &name)
00859 {
00860     QString n = name;
00861     return n.replace(".", "::");
00862 }
00863 
00864 QString CppSupportPart::unformatClassName(const QString &name)
00865 {
00866     QString n = name;
00867     return n.replace("::", ".");
00868 }
00869 
00870 void CppSupportPart::slotNewClass()
00871 {
00872     CppNewClassDialog dlg(this);
00873     dlg.exec();
00874 }
00875 
00876 void CppSupportPart::addMethod( ClassDom klass )
00877 {
00878     if( !klass ){
00879     KMessageBox::error(0,i18n("Please select a class."),i18n("Error"));
00880     return;
00881     }
00882 
00883     AddMethodDialog dlg( this, klass, mainWindow()->main() );
00884     dlg.exec();
00885 }
00886 
00887 void CppSupportPart::addAttribute( ClassDom klass )
00888 {
00889     if( !klass ){
00890     KMessageBox::error(0,i18n("Please select a class."),i18n("Error"));
00891     return;
00892     }
00893 
00894     AddAttributeDialog dlg( this, klass, mainWindow()->main() );
00895     dlg.exec();
00896 }
00897 
00898 void CppSupportPart::slotCompleteText()
00899 {
00900     if (!m_pCompletion)
00901         return;
00902     m_pCompletion->completeText();
00903 }
00904 
00908 void CppSupportPart::initialParse( )
00909 {
00910     // For debugging
00911     if( !project( ) ){
00912         // messagebox ?
00913         kdDebug( 9007 ) << "No project" << endl;
00914         return;
00915     }
00916 
00917     parseProject( );
00918     m_valid = true;
00919     return;
00920 }
00921 
00922 #if QT_VERSION < 0x030100
00923 // Taken from qt-3.2/tools/qdatetime.cpp/QDateTime::toTime_t() and modified for normal function
00924 uint toTime_t(QDateTime t)
00925 {
00926     tm brokenDown;
00927     brokenDown.tm_sec = t.time().second();
00928     brokenDown.tm_min = t.time().minute();
00929     brokenDown.tm_hour = t.time().hour();
00930     brokenDown.tm_mday = t.date().day();
00931     brokenDown.tm_mon = t.date().month() - 1;
00932     brokenDown.tm_year = t.date().year() - 1900;
00933     brokenDown.tm_isdst = -1;
00934     int secsSince1Jan1970UTC = (int) mktime( &brokenDown );
00935     if ( secsSince1Jan1970UTC < -1 )
00936     secsSince1Jan1970UTC = -1;
00937     return (uint) secsSince1Jan1970UTC;
00938 }
00939 #endif
00940 
00941 bool
00942 CppSupportPart::parseProject( bool force )
00943 {
00944         kdDebug( 9007 ) << "CppSupportPart::parseProject 1" << endl;
00945     mainWindow()->statusBar()->message( i18n("Updating...") );
00946 
00947     kapp->setOverrideCursor( waitCursor );
00948 
00949     _jd = new JobData;
00950     _jd->file.setName( project()->projectDirectory() + "/" + project()->projectName() + ".pcs" );
00951 
00952     QString skip_file_name = project()->projectDirectory() + "/" + project()->projectName() + ".ignore_pcs";
00953 
00954     if( !force && !QFile::exists( skip_file_name ) && _jd->file.open(IO_ReadOnly) )
00955     {
00956         _jd->stream.setDevice( &(_jd->file) );
00957     
00958         createIgnorePCSFile();
00959     
00960         QString sig;
00961         int pcs_version = 0;
00962         _jd->stream >> sig >> pcs_version;
00963         if( sig == "PCS" && pcs_version == KDEV_PCS_VERSION ){
00964     
00965             int numFiles = 0;
00966             _jd->stream >> numFiles;
00967     
00968             for( int i=0; i<numFiles; ++i ){
00969             QString fn;
00970             uint ts;
00971             /*Q_LONG*/ uint offset;
00972     
00973             _jd->stream >> fn >> ts >> offset;
00974             _jd->pcs[ fn ] = qMakePair( ts, offset );
00975             }
00976         }
00977     }
00978         kdDebug( 9007 ) << "CppSupportPart::parseProject 2" << endl;
00979 
00980     _jd->files = reorder( modifiedFileList() );
00981         kdDebug( 9007 ) << "CppSupportPart::parseProject 3" << endl;
00982 
00983     QProgressBar* bar = new QProgressBar( _jd->files.count( ), mainWindow( )->statusBar( ) );
00984     bar->setMinimumWidth( 120 );
00985     bar->setCenterIndicator( true );
00986     mainWindow( )->statusBar( )->addWidget( bar );
00987     bar->show( );
00988         kdDebug( 9007 ) << "CppSupportPart::parseProject 4" << endl;
00989     
00990     _jd->progressBar = bar;
00991     _jd->dir.setPath( m_projectDirectory );
00992     _jd->it = _jd->files.begin();
00993 
00994         kdDebug( 9007 ) << "CppSupportPart::parseProject 5" << endl;
00995     QTimer::singleShot( 0, this, SLOT(slotParseFiles()) );
00996     
00997     return true;
00998 }
00999 
01000 void CppSupportPart::slotParseFiles()
01001 {
01002     // NOTE: The checking for m_projectClosed is actually (currently) not needed.
01003     // When the project is closed, the language support plugin is destroyed
01004     // and as a consequence, the timer job signal never arrives at this method
01005     
01006     if ( !m_projectClosed && _jd->it != _jd->files.end() )
01007     {
01008         _jd->progressBar->setProgress( _jd->progressBar->progress() +1 );
01009         
01010         QFileInfo fileInfo( _jd->dir, *(_jd->it) );
01011         
01012         if( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() )
01013         {
01014             QString absFilePath = URLUtil::canonicalPath(fileInfo.absFilePath() );
01015         
01016             if( isValidSource(absFilePath) )
01017             {
01018                 QDateTime t = fileInfo.lastModified();
01019                 if( ! (m_timestamp.contains(absFilePath) && m_timestamp[absFilePath] == t ) )
01020                 {   
01021                     if( _jd->pcs.contains(absFilePath) && t.toTime_t() == _jd->pcs[absFilePath].first )
01022                     {
01023                         _jd->stream.device()->at( _jd->pcs[absFilePath].second );
01024                         FileDom file = codeModel()->create<FileModel>();
01025                         file->read( _jd->stream );
01026                         codeModel()->addFile( file );
01027                     } 
01028                     else 
01029                     {
01030                         kdDebug(9007) << "newly parsing: " << absFilePath << endl;
01031                         m_driver->parseFile( absFilePath );
01032                     }
01033             
01034                     m_timestamp[ absFilePath ] = t;
01035                 }
01036             }
01037         }
01038         
01039         ++(_jd->it);
01040         QTimer::singleShot( 0, this, SLOT(slotParseFiles()) );
01041     }
01042     else // finished or interrupted
01043     {
01044         kapp->restoreOverrideCursor( );
01045         mainWindow( )->statusBar( )->removeWidget( _jd->progressBar );
01046             
01047         if ( !m_projectClosed )
01048         {
01049             kdDebug( 9007 ) << "updating sourceinfo" << endl;
01050             emit updatedSourceInfo();
01051             mainWindow( )->statusBar( )->message( i18n( "Done" ), 2000 );
01052             QFile::remove( project()->projectDirectory() + "/" + project()->projectName() + ".ignore_pcs" );
01053         }
01054         else
01055         {
01056             kdDebug(9007) << "ABORT" << endl;
01057         }
01058         
01059         delete _jd;
01060         _jd = 0;
01061     }
01062 }
01063 
01064 void CppSupportPart::maybeParse( const QString& fileName )
01065 {
01066     if( !isValidSource(fileName) )
01067         return;
01068 
01069     QFileInfo fileInfo( fileName );
01070     QString path = URLUtil::canonicalPath(fileName);
01071     QDateTime t = fileInfo.lastModified();
01072 
01073     if( !fileInfo.exists() ){
01074     removeWithReferences( path );
01075     return;
01076     }
01077 
01078     QMap<QString, QDateTime>::Iterator it = m_timestamp.find( path );
01079     if( it != m_timestamp.end() && *it == t ){
01080     return;
01081     }
01082 
01083     m_timestamp[ path ] = t;
01084     m_driver->parseFile( path );
01085 }
01086 
01087 void CppSupportPart::slotNeedTextHint( int line, int column, QString& textHint )
01088 {
01089     if( 1 || !m_activeEditor )
01090     return;
01091 
01092     m_backgroundParser->lock();
01093     TranslationUnitAST* ast = m_backgroundParser->translationUnit( m_activeFileName );
01094     AST* node = 0;
01095     if( ast && (node = findNodeAt(ast, line, column)) ){
01096 
01097     while( node && node->nodeType() != NodeType_FunctionDefinition )
01098         node = node->parent();
01099 
01100     if( node ){
01101         int startLine, startColumn;
01102         int endLine, endColumn;
01103         node->getStartPosition( &startLine, &startColumn );
01104         node->getEndPosition( &endLine, &endColumn );
01105 
01106         if( !node->text().isNull() )
01107             textHint = node->text();
01108         else
01109             textHint = m_activeEditor->textLine( startLine ).simplifyWhiteSpace();
01110     }
01111     }
01112     m_backgroundParser->unlock();
01113 }
01114 
01115 void CppSupportPart::MakeMemberHelper(QString& text, int& atLine, int& atColumn)
01116 {
01117     if( !m_activeViewCursor || !m_valid )
01118         return;
01119 
01120     m_backgroundParser->lock();
01121     TranslationUnitAST* translationUnit = m_backgroundParser->translationUnit( m_activeFileName );
01122     if( translationUnit ){
01123         unsigned int line, column;
01124     m_activeViewCursor->cursorPositionReal( &line, &column );
01125 
01126         AST* currentNode = findNodeAt( translationUnit, line, column );
01127     DeclaratorAST* declarator = 0;
01128     while( currentNode && currentNode->nodeType() != NodeType_SimpleDeclaration ){
01129         if( currentNode->nodeType() == NodeType_Declarator )
01130             declarator = (DeclaratorAST*) currentNode;
01131         currentNode = currentNode->parent();
01132     }
01133     SimpleDeclarationAST* decl = currentNode ? (SimpleDeclarationAST*) currentNode : 0;
01134     if( decl && decl->initDeclaratorList() && !declarator ){
01135         InitDeclaratorAST* i = decl->initDeclaratorList()->initDeclaratorList().at( 0 );
01136         if( i )
01137            declarator = i->declarator();
01138     }
01139 
01140     if( decl && declarator && declarator->parameterDeclarationClause() ){
01141 
01142         QStringList scope;
01143         scopeOfNode( decl, scope );
01144 
01145         QString scopeStr = scope.join( "::" );
01146         if( !scopeStr.isEmpty() )
01147             scopeStr += "::";
01148 
01149         QString declStr = declaratorToString( declarator, scopeStr ).simplifyWhiteSpace();
01150         if( declarator->exceptionSpecification() ){
01151         declStr += QString::fromLatin1( " throw( ");
01152         QPtrList<AST> l = declarator->exceptionSpecification()->nodeList();
01153         QPtrListIterator<AST> type_it( l );
01154         while( type_it.current() ){
01155             declStr += type_it.current()->text();
01156             ++type_it;
01157 
01158             if( type_it.current() )
01159             declStr += QString::fromLatin1( ", " );
01160         }
01161 
01162         declStr += QString::fromLatin1(" )");
01163         }
01164 
01165         text += "\n\n";
01166         QString type = typeSpecToString( decl->typeSpec() );
01167         text += type;
01168         if( !type.isNull() )
01169         text +=  + " ";
01170 
01171         text += declStr + "\n{\n}";
01172     }
01173  
01174         m_backgroundParser->unlock();
01175         
01176         QString implFile = findSourceFile();
01177         
01178         m_backgroundParser->lock();
01179     translationUnit = m_backgroundParser->translationUnit( implFile );
01180     if( translationUnit ){
01181         translationUnit->getEndPosition( &atLine, &atColumn );
01182     } else {
01183         atLine = -2;
01184         atColumn = 0;
01185     }
01186          kdDebug() << "at line in mm: " << atLine << endl;
01187     }
01188     m_backgroundParser->unlock();
01189 }
01190 
01191 void CppSupportPart::slotMakeMember()
01192 {
01193 QString text;
01194 int atColumn, atLine;
01195 MakeMemberHelper(text,atLine,atColumn);
01196 
01197 if(!text.isEmpty())
01198 { 
01199  QString implFile = findSourceFile();
01200 
01201  if(!implFile.isEmpty() ){
01202     partController()->editDocument( KURL( implFile ) );
01203     kapp->processEvents( 500 );
01204  }
01205  if (atLine == -2)
01206     atLine = m_activeEditor->numLines() - 1;
01207 
01208  m_backgroundParser->lock();
01209 
01210          kdDebug() << "at line in mm: " << atLine  << " atCol: " << atColumn << endl;
01211          kdDebug() << "text: " << text << endl;
01212  if( m_activeEditor )
01213   m_activeEditor->insertText( atLine, atColumn, text );
01214  if( m_activeViewCursor )
01215   m_activeViewCursor->setCursorPositionReal( atLine+3, 1 );
01216 
01217  m_backgroundParser->unlock();
01218  }
01219 }
01220 
01221 QStringList CppSupportPart::subclassWidget(const QString& formName)
01222 {
01223     QStringList newFileNames;
01224     SubclassingDlg *dlg = new SubclassingDlg(this, formName, newFileNames);
01225     dlg->exec();
01226     return newFileNames;
01227 }
01228 
01229 QStringList CppSupportPart::updateWidget(const QString& formName, const QString& fileName)
01230 {
01231     QStringList dummy;
01232     SubclassingDlg *dlg = new SubclassingDlg(this, formName, fileName, dummy);
01233     dlg->exec();
01234     return dummy;
01235 }
01236 
01237 void CppSupportPart::partRemoved( KParts::Part* part )
01238 {
01239     kdDebug(9032) << "CppSupportPart::partRemoved()" << endl;
01240 
01241     if( KTextEditor::Document* doc = dynamic_cast<KTextEditor::Document*>( part ) ){
01242 
01243     QString fileName = doc->url().path();
01244     if( !isValidSource(fileName) )
01245         return;
01246 
01247     QString canonicalFileName = URLUtil::canonicalPath( fileName );
01248     m_backgroundParser->removeFile( canonicalFileName );
01249     m_backgroundParser->addFile( canonicalFileName, true );
01250     }
01251 }
01252 
01253 void CppSupportPart::slotProjectCompiled()
01254 {
01255     kdDebug(9007) << "CppSupportPart::slotProjectCompiled()" << endl;
01256     parseProject();
01257 }
01258 
01259 QStringList CppSupportPart::modifiedFileList()
01260 {
01261     QStringList lst;
01262 
01263     QStringList fileList = m_projectFileList;
01264     QStringList::Iterator it = fileList.begin();
01265     while( it != fileList.end() ){
01266     QString fileName = *it;
01267     ++it;
01268 
01269     QFileInfo fileInfo( m_projectDirectory, fileName );
01270     QString path = URLUtil::canonicalPath(fileInfo.absFilePath());
01271 
01272     if( !(isSource(path) || isHeader(path)) )
01273         continue;
01274 
01275     QDateTime t = fileInfo.lastModified();
01276 
01277     QMap<QString, QDateTime>::Iterator dictIt = m_timestamp.find( path );
01278     if( fileInfo.exists() && dictIt != m_timestamp.end() && *dictIt == t )
01279         continue;
01280 
01281     lst << fileName;
01282     }
01283 
01284     return lst;
01285 }
01286 
01287 KTextEditor::Document * CppSupportPart::findDocument( const KURL & url )
01288 {
01289     if( !partController()->parts() )
01290         return 0;
01291 
01292     QPtrList<KParts::Part> parts( *partController()->parts() );
01293     QPtrListIterator<KParts::Part> it( parts );
01294     while( KParts::Part* part = it.current() ){
01295         KTextEditor::Document* doc = dynamic_cast<KTextEditor::Document*>( part );
01296     if( doc && doc->url() == url )
01297         return doc;
01298         ++it;
01299     }
01300 
01301     return 0;
01302 }
01303 
01304 void CppSupportPart::setupCatalog( )
01305 {
01306     kdDebug(9007) << "CppSupportPart::setupCatalog()" << endl;
01307 
01308     KStandardDirs *dirs = CppSupportFactory::instance()->dirs();
01309     QStringList pcsList = dirs->findAllResources( "pcs", "*.db", false, true );
01310     QStringList pcsIdxList = dirs->findAllResources( "pcs", "*.idx", false, true );
01311 
01312     QStringList enabledPCSs;
01313     if( DomUtil::elementByPath( *project()->projectDom(), "kdevcppsupport/references" ).isNull() ){
01314         for( QStringList::Iterator it=pcsList.begin(); it!=pcsList.end(); ++it ){
01315             enabledPCSs.push_back( QFileInfo(*it).baseName() );
01316         }
01317     } else {
01318         enabledPCSs = DomUtil::readListEntry( *project()->projectDom(), "kdevcppsupport/references", "pcs" );
01319     }
01320 
01321     QStringList indexList = QStringList() << "kind" << "name" << "scope" << "fileName" << "prefix";
01322 
01323     if( pcsList.size() && pcsVersion() < KDEV_DB_VERSION ){
01324         QStringList l = pcsList + pcsIdxList;
01325         int rtn = KMessageBox::questionYesNoList( 0, i18n("Persistant class store will be disabled!! You have a wrong version of pcs installed.\nRemove old pcs files?"), l, i18n("C++ Support") );
01326         if( rtn == KMessageBox::Yes ){
01327             QStringList::Iterator it = l.begin();
01328             while( it != l.end() ){
01329                 QFile::remove( *it );
01330                 ++it;
01331             }
01332             // @todo regenerate the pcs list
01333             pcsList.clear();
01334         } else {
01335             return;
01336         }
01337     }
01338 
01339     QStringList::Iterator it = pcsList.begin();
01340     while( it != pcsList.end() ){
01341         Catalog* catalog = new Catalog();
01342         catalog->open( *it );
01343     catalog->setEnabled( enabledPCSs.contains(QFileInfo(*it).baseName()) );
01344         ++it;
01345 
01346         for( QStringList::Iterator idxIt=indexList.begin(); idxIt!=indexList.end(); ++idxIt )
01347             catalog->addIndex( (*idxIt).utf8() );
01348 
01349         m_catalogList.append( catalog );
01350         codeRepository()->registerCatalog( catalog );
01351     }
01352 
01353     setPcsVersion( KDEV_DB_VERSION );
01354 }
01355 
01356 KMimeType::List CppSupportPart::mimeTypes( )
01357 {
01358     QStringList mimeList;
01359     mimeList += m_headerMimeTypes;
01360     mimeList += m_sourceMimeTypes;
01361 
01362     KMimeType::List list;
01363     for( QStringList::Iterator it=mimeList.begin(); it!=mimeList.end(); ++it )
01364     {
01365     if( KMimeType::Ptr mime = KMimeType::mimeType(*it) )
01366         list << mime;
01367     }
01368 
01369     return list;
01370 }
01371 
01372 int CppSupportPart::pcsVersion()
01373 {
01374     KConfig* config = CppSupportFactory::instance()->config();
01375     KConfigGroupSaver cgs( config, "PCS" );
01376     return config->readNumEntry( "Version", 0 );
01377 }
01378 
01379 void CppSupportPart::setPcsVersion( int version )
01380 {
01381     KConfig* config = CppSupportFactory::instance()->config();
01382     KConfigGroupSaver cgs( config, "PCS" );
01383     config->writeEntry( "Version", version );
01384     config->sync();
01385 }
01386 
01387 QString CppSupportPart::formatTag( const Tag & inputTag )
01388 {
01389     Tag tag = inputTag;
01390 
01391     switch( tag.kind() )
01392     {
01393         case Tag::Kind_Namespace:
01394             return QString::fromLatin1("namespace ") + tag.name();
01395 
01396         case Tag::Kind_Class:
01397             return QString::fromLatin1("class ") + tag.name();
01398 
01399         case Tag::Kind_Function:
01400         case Tag::Kind_FunctionDeclaration:
01401         {
01402             CppFunction<Tag> tagInfo( tag );
01403             return tagInfo.name() + "( " + tagInfo.arguments().join(", ") + " ) : " + tagInfo.type();
01404         }
01405         break;
01406 
01407         case Tag::Kind_Variable:
01408         case Tag::Kind_VariableDeclaration:
01409         {
01410             CppVariable<Tag> tagInfo( tag );
01411             return tagInfo.name() + " : " + tagInfo.type();
01412         }
01413         break;
01414     }
01415     return tag.name();
01416 }
01417 
01418 void CppSupportPart::codeCompletionConfigStored( )
01419 {
01420     partController()->setActivePart( partController()->activePart() );
01421 }
01422 
01423 void CppSupportPart::removeWithReferences( const QString & fileName )
01424 {
01425     kdDebug(9007) << "remove with references: " << fileName << endl;
01426     m_timestamp.remove( fileName );
01427     if( !codeModel()->hasFile(fileName) )
01428         return;
01429 
01430     emit aboutToRemoveSourceInfo( fileName );
01431 
01432     codeModel()->removeFile( codeModel()->fileByName(fileName) );
01433 }
01434 
01435 bool CppSupportPart::isValidSource( const QString& fileName ) const
01436 {
01437     QFileInfo fileInfo( fileName );
01438     QString path = URLUtil::canonicalPath( fileInfo.absFilePath() );
01439 
01440     return project() && project()->isProjectFile( path )
01441     && (isSource( path ) || isHeader( path ))
01442     && !QFile::exists(fileInfo.dirPath(true) + "/.kdev_ignore");
01443 }
01444 
01445 QString CppSupportPart::formatModelItem( const CodeModelItem *item, bool shortDescription )
01446 {
01447     if (item->isFunction() || item->isFunctionDefinition() )
01448     {
01449         const FunctionModel *model = static_cast<const FunctionModel*>(item);
01450         QString function;
01451         QString args;
01452         ArgumentList argumentList = model->argumentList();
01453         for (ArgumentList::const_iterator it = argumentList.begin(); it != argumentList.end(); ++it)
01454         {
01455             args.isEmpty() ? args += "" : args += ", " ;
01456             args += formatModelItem((*it).data());
01457         }
01458     if( !shortDescription )
01459             function += (model->isVirtual() ? QString("virtual ") : QString("") ) + model->resultType() + " ";
01460 
01461     function += model->name() + "(" + args + ")" + (model->isConstant() ? QString(" const") : QString("") ) +
01462             (model->isAbstract() ? QString(" = 0") : QString("") );
01463 
01464         return function;
01465     }
01466     else if (item->isVariable())
01467     {
01468         const VariableModel *model = static_cast<const VariableModel*>(item);
01469     if( shortDescription )
01470         return model->name();
01471         return model->type() + " " + model->name();
01472     }
01473     else if (item->isArgument())
01474     {
01475         const ArgumentModel *model = static_cast<const ArgumentModel*>(item);
01476     QString arg;
01477     if( !shortDescription )
01478         arg += model->type() + " ";
01479     arg += model->name();
01480     if( !shortDescription )
01481         arg += model->defaultValue().isEmpty() ? QString("") : QString(" = ") + model->defaultValue();
01482     return arg.stripWhiteSpace();
01483     }
01484     else
01485         return KDevLanguageSupport::formatModelItem( item, shortDescription );
01486 }
01487 
01488 void CppSupportPart::addClass( )
01489 {
01490     slotNewClass();
01491 }
01492 
01493 void CppSupportPart::saveProjectSourceInfo( )
01494 {
01495     const FileList fileList = codeModel()->fileList();
01496 
01497     if( !project() || fileList.isEmpty() )
01498     return;
01499 
01500     QFile f( project()->projectDirectory() + "/" + project()->projectName() + ".pcs" );
01501     if( !f.open( IO_WriteOnly ) )
01502     return;
01503 
01504     createIgnorePCSFile();
01505 
01506     QDataStream stream( &f );
01507     QMap<QString, uint> offsets;
01508 
01509     QString pcs( "PCS" );
01510     stream << pcs << KDEV_PCS_VERSION;
01511 
01512     stream << int( fileList.size() );
01513     for( FileList::ConstIterator it=fileList.begin(); it!=fileList.end(); ++it ){
01514     const FileDom dom = (*it);
01515 #if QT_VERSION >= 0x030100
01516   stream << dom->name() << m_timestamp[ dom->name() ].toTime_t();
01517 #else
01518   stream << dom->name() << toTime_t(m_timestamp[ dom->name() ]);
01519 #endif
01520     offsets.insert( dom->name(), stream.device()->at() );
01521     stream << (uint)0; // dummy offset
01522     }
01523 
01524     for( FileList::ConstIterator it=fileList.begin(); it!=fileList.end(); ++it ){
01525     const FileDom dom = (*it);
01526     int offset = stream.device()->at();
01527 
01528     dom->write( stream );
01529 
01530     int end = stream.device()->at();
01531 
01532     stream.device()->at( offsets[dom->name()] );
01533     stream << offset;
01534     stream.device()->at( end );
01535     }
01536 
01537     QString skip_file_name = project()->projectDirectory() + "/" + project()->projectName() + ".ignore_pcs";
01538     QFile::remove( skip_file_name );
01539 }
01540 
01541 QString CppSupportPart::extractInterface( const ClassDom& klass )
01542 {
01543     QString txt;
01544     QTextStream stream( &txt, IO_WriteOnly );
01545 
01546     QString name = klass->name() + "Interface";
01547     QString ind;
01548     ind.fill( QChar(' '), 4 );
01549 
01550     stream
01551     << "class " << name << "\n"
01552     << "{" << "\n"
01553     << "public:" << "\n"
01554     << ind << name << "() {}" << "\n"
01555     << ind << "virtual ~" << name << "() {}" << "\n"
01556     << "\n";
01557 
01558     const FunctionList functionList = klass->functionList();
01559     for( FunctionList::ConstIterator it=functionList.begin(); it!=functionList.end(); ++it ){
01560     const FunctionDom& fun = *it;
01561 
01562     if( !fun->isVirtual() || fun->name().startsWith("~") )
01563         continue;
01564 
01565     stream << ind << formatModelItem( fun );
01566     if( !fun->isAbstract() )
01567         stream << " = 0";
01568 
01569     stream << ";\n";
01570     }
01571 
01572     stream
01573     << "\n"
01574     << "private:" << "\n"
01575     << ind << name << "( const " << name << "& source );" << "\n"
01576     << ind << "void operator = ( const " << name << "& source );" << "\n"
01577     << "};" << "\n\n";
01578 
01579     return txt;
01580 }
01581 
01582 void CppSupportPart::slotExtractInterface( )
01583 {
01584     if( !m_activeClass )
01585     return;
01586 
01587     QFileInfo fileInfo( m_activeClass->fileName() );
01588     QString ifaceFileName = fileInfo.dirPath( true ) + "/" + m_activeClass->name().lower() + "_interface.h";
01589     if( QFile::exists(ifaceFileName) ){
01590     KMessageBox::error( mainWindow()->main(), i18n("File %1 already exists").arg(ifaceFileName),
01591                 i18n("C++ Support") );
01592     } else {
01593     QString text = extractInterface( m_activeClass );
01594 
01595     QFile f( ifaceFileName );
01596     if( f.open(IO_WriteOnly) ){
01597         QTextStream stream( &f );
01598         stream
01599         << "#ifndef __" << m_activeClass->name().upper() << "_INTERFACE_H" << "\n"
01600         << "#define __" << m_activeClass->name().upper() << "_INTERFACE_H" << "\n"
01601         << "\n"
01602         << extractInterface( m_activeClass )
01603         << "\n"
01604         << "#endif // __" << m_activeClass->name().upper() << "_INTERFACE_H" << "\n";
01605         f.close();
01606 
01607         project()->addFile( ifaceFileName );
01608     }
01609     }
01610 
01611     m_activeClass = 0;
01612 }
01613 
01614 void CppSupportPart::gotoLine( int line )
01615 {
01616     if (isHeader(m_activeFileName))
01617     {
01618         KURL url;
01619         url.setPath(sourceOrHeaderCandidate());
01620         partController()->editDocument(url, line);
01621     }
01622     else
01623         m_activeViewCursor->setCursorPositionReal( line, 0 );
01624 }
01625 
01626 void CppSupportPart::recomputeCodeModel( const QString& fileName )
01627 {
01628     if( codeModel()->hasFile(fileName) ){
01629     FileDom file = codeModel()->fileByName( fileName );
01630     removeWithReferences( fileName );
01631     }
01632 
01633     m_backgroundParser->lock();
01634     if( TranslationUnitAST* ast = m_backgroundParser->translationUnit(fileName) ){
01635 
01636     if( true  ){
01637         StoreWalker walker( fileName, codeModel() );
01638         walker.parseTranslationUnit( ast );
01639         codeModel()->addFile( walker.file() );
01640         emit addedSourceInfo( fileName );
01641     }
01642     }
01643     m_backgroundParser->unlock();
01644 }
01645 
01646 void CppSupportPart::emitFileParsed( )
01647 {
01648     emit fileParsed( m_activeFileName );
01649 }
01650 
01651 bool CppSupportPart::isHeader( const QString& fileName ) const
01652 {
01653     KMimeType::Ptr ptr = KMimeType::findByPath( fileName );
01654     if( ptr && m_headerMimeTypes.contains( ptr->name() ) )
01655     return true;
01656 
01657     return m_headerExtensions.contains( QFileInfo(fileName).extension() );
01658 }
01659 
01660 bool CppSupportPart::isSource( const QString& fileName ) const
01661 {
01662     KMimeType::Ptr ptr = KMimeType::findByPath( fileName );
01663     if( ptr && m_sourceMimeTypes.contains( ptr->name() ) )
01664     return true;
01665 
01666     return m_sourceExtensions.contains( QFileInfo(fileName).extension() );
01667 }
01668 
01669 void CppSupportPart::gotoDeclarationLine( int line )
01670 {
01671     if (isHeader(m_activeFileName))
01672         m_activeViewCursor->setCursorPositionReal( line, 0 );
01673     else
01674     {
01675         KURL url;
01676         url.setPath(sourceOrHeaderCandidate());
01677         partController()->editDocument(url, line);
01678     }
01679 }
01680 
01681 void CppSupportPart::removeCatalog( const QString & dbName )
01682 {
01683     if( !QFile::exists(dbName) )
01684     return;
01685 
01686     QValueList<Catalog*> catalogs = codeRepository()->registeredCatalogs();
01687     Catalog* c = 0;
01688     for( QValueList<Catalog*>::Iterator it=catalogs.begin(); it!=catalogs.end(); ++it )
01689     {
01690     if( (*it)->dbName() == dbName ){
01691         c = *it;
01692         break;
01693     }
01694     }
01695 
01696     if( c ){
01697     codeRepository()->unregisterCatalog( c );
01698     m_catalogList.remove( c );
01699     }
01700 
01701     QFileInfo fileInfo( dbName );
01702     QDir dir( fileInfo.dir(true) );
01703     QStringList fileList = dir.entryList( fileInfo.baseName() + "*.idx" );
01704     for( QStringList::Iterator it=fileList.begin(); it!=fileList.end(); ++it )
01705     {
01706     QString idxName = fileInfo.dirPath( true ) + "/" + *it;
01707     kdDebug(9007) << "=========> remove db index: " << idxName << endl;
01708     dir.remove( *it );
01709     }
01710 
01711     dir.remove( fileInfo.fileName() );
01712 }
01713 
01714 void CppSupportPart::addCatalog( Catalog * catalog )
01715 {
01716     m_catalogList.append( catalog );
01717     codeRepository()->registerCatalog( catalog );
01718 }
01719 
01720 FunctionDefinitionDom CppSupportPart::functionDefinitionAt( int line, int column )
01721 {
01722     if( !codeModel()->hasFile(m_activeFileName) )
01723     return FunctionDefinitionDom();
01724 
01725     FileDom file = codeModel()->fileByName( m_activeFileName );
01726     return functionDefinitionAt( model_cast<NamespaceDom>(file), line, column );
01727 }
01728 
01729 FunctionDefinitionDom CppSupportPart::currentFunctionDefinition( )
01730 {
01731     if( !this->m_activeViewCursor )
01732     return FunctionDefinitionDom();
01733 
01734     unsigned int line, column;
01735     this->m_activeViewCursor->cursorPositionReal( &line, &column );
01736     return functionDefinitionAt( line, column );
01737 }
01738 
01739 FunctionDefinitionDom CppSupportPart::functionDefinitionAt( NamespaceDom ns, int line, int column )
01740 {
01741     NamespaceList namespaceList = ns->namespaceList();
01742     for( NamespaceList::Iterator it=namespaceList.begin(); it!=namespaceList.end(); ++it )
01743     {
01744     if( FunctionDefinitionDom def = functionDefinitionAt(*it, line, column) )
01745         return def;
01746     }
01747 
01748     ClassList classList = ns->classList();
01749     for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
01750     {
01751     if( FunctionDefinitionDom def = functionDefinitionAt(*it, line, column) )
01752         return def;
01753     }
01754 
01755     FunctionDefinitionList functionDefinitionList = ns->functionDefinitionList();
01756     for( FunctionDefinitionList::Iterator it=functionDefinitionList.begin(); it!=functionDefinitionList.end(); ++it )
01757     {
01758     if( FunctionDefinitionDom def = functionDefinitionAt(*it, line, column) )
01759         return def;
01760     }
01761 
01762     return FunctionDefinitionDom();
01763 }
01764 
01765 FunctionDefinitionDom CppSupportPart::functionDefinitionAt( ClassDom klass, int line, int column )
01766 {
01767     ClassList classList = klass->classList();
01768     for( ClassList::Iterator it=classList.begin(); it!=classList.end(); ++it )
01769     {
01770     if( FunctionDefinitionDom def = functionDefinitionAt(*it, line, column) )
01771         return def;
01772     }
01773 
01774     FunctionDefinitionList functionDefinitionList = klass->functionDefinitionList();
01775     for( FunctionDefinitionList::Iterator it=functionDefinitionList.begin(); it!=functionDefinitionList.end(); ++it )
01776     {
01777     if( FunctionDefinitionDom def = functionDefinitionAt(*it, line, column) )
01778         return def;
01779     }
01780 
01781     return FunctionDefinitionDom();
01782 }
01783 
01784 FunctionDefinitionDom CppSupportPart::functionDefinitionAt( FunctionDefinitionDom fun, int line, int column )
01785 {
01786     int startLine, startColumn;
01787     int endLine, endColumn;
01788 
01789     fun->getStartPosition( &startLine, &startColumn );
01790     fun->getEndPosition( &endLine, &endColumn );
01791 
01792     if( ! (line >= startLine && line <= endLine) )
01793     return FunctionDefinitionDom();
01794 
01795     if( line == startLine && column < startColumn )
01796     return FunctionDefinitionDom();
01797 
01798     if( line == endLine && column > endColumn )
01799     return FunctionDefinitionDom();
01800 
01801     return fun;
01802 }
01803 
01804 void CppSupportPart::slotCursorPositionChanged()
01805 {
01806 //    m_functionHintTimer->changeInterval( 1000 );
01807 }
01808 
01809 void CppSupportPart::slotFunctionHint( )
01810 {
01811     kdDebug(9007) << "=======> compute current function definition" << endl;
01812     m_functionHintTimer->stop();
01813     if( FunctionDefinitionDom fun = currentFunctionDefinition() )
01814     {
01815     QStringList scope = fun->scope();
01816     QString funName = scope.join( "::" );
01817     if( !funName.isEmpty() )
01818         funName += "::";
01819 
01820     funName += formatModelItem( fun, true );
01821 
01822     mainWindow()->statusBar()->message( funName, 2000 );
01823     }
01824 }
01825 
01826 void CppSupportPart::createIgnorePCSFile( )
01827 {
01828     static QCString skip_me( "ignore me\n" );
01829 
01830     QString skip_file_name = project()->projectDirectory() + "/" + project()->projectName() + ".ignore_pcs";
01831     QFile skip_pcs_file( skip_file_name );
01832     if( skip_pcs_file.open(IO_WriteOnly) )
01833     {
01834         skip_pcs_file.writeBlock( skip_me );
01835         skip_pcs_file.close();
01836     }
01837 }
01838 
01839 QString CppSupportPart::specialHeaderName( bool local ) const
01840 {
01841     if( local )
01842         return ::locateLocal( "data", "kdevcppsupport/configuration", CppSupportFactory::instance() );
01843 
01844     return ::locate( "data", "kdevcppsupport/configuration", CppSupportFactory::instance() );
01845 }
01846 
01847 void CppSupportPart::updateParserConfiguration()
01848 {
01849     m_backgroundParser->updateParserConfiguration();
01850 
01851     QString conf_file_name = specialHeaderName();
01852     m_driver->removeAllMacrosInFile( conf_file_name );
01853 
01854     m_driver->parseFile( conf_file_name, true );
01855 
01856     parseProject( true );
01857 }
01858 
01859 KDevDesignerIntegration * CppSupportPart::designer( KInterfaceDesigner::DesignerType type )
01860 {
01861     KDevDesignerIntegration *des = 0;
01862     switch (type)
01863     {
01864         case KInterfaceDesigner::QtDesigner:
01865             des = m_designers[type];
01866             if (des == 0)
01867             {
01868                 des = new QtDesignerIntegration(this);
01869                 kdDebug() << "1" << endl;
01870                 des->loadSettings(*project()->projectDom(), "kdevcppsupport/designerintegration");
01871                 kdDebug() << "2" << endl;
01872                 m_designers[type] = des;
01873             }
01874             break;
01875     }
01876     kdDebug() << "3" << endl;
01877     return des;
01878 }
01879 
01880 void CppSupportPart::slotCreateSubclass()
01881 {
01882     QFileInfo fi(m_contextFileName);
01883     if (fi.extension(false) != "ui")
01884         return;
01885     QtDesignerIntegration *des = dynamic_cast<QtDesignerIntegration*>(designer(KInterfaceDesigner::QtDesigner));
01886     if (des)
01887         des->selectImplementation(m_contextFileName);
01888 }
01889 
01890 #include "cppsupportpart.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 Wed Mar 23 00:03:46 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003