KDevelop API Documentation

trollprojectpart.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2003 by Thomas Hasart                                   *
00003  *   thasart@gmx.de                                                        *
00004  *   Copyright (C) 2001-2002 by Bernd Gehrmann                             *
00005  *   bernd@kdevelop.org                                                    *
00006  *   Copyright (C) 2002 by Jakob Simon-Gaarde                              *
00007  *   jakob@jsg.dk                                                          *
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 
00016 #include "trollprojectpart.h"
00017 
00018 #include <qdir.h>
00019 #include <qfileinfo.h>
00020 #include <qwhatsthis.h>
00021 #include <kdeversion.h>
00022 #include <kdebug.h>
00023 #include <kdialogbase.h>
00024 #include <kiconloader.h>
00025 #include <klocale.h>
00026 #include <kmessagebox.h>
00027 #include <qmessagebox.h>
00028 #include <kdevgenericfactory.h>
00029 #include <kaction.h>
00030 #include <kparts/part.h>
00031 #include <kprocess.h>
00032 #include <makeoptionswidget.h>
00033 
00034 
00035 #include "domutil.h"
00036 #include "kdevcore.h"
00037 #include "kdevmainwindow.h"
00038 #include "kdevmakefrontend.h"
00039 #include "kdevappfrontend.h"
00040 #include "kdevpartcontroller.h"
00041 #include "trollprojectwidget.h"
00042 #include "runoptionswidget.h"
00043 #include "config.h"
00044 #include "envvartools.h"
00045 
00046 
00047 typedef KDevGenericFactory<TrollProjectPart> TrollProjectFactory;
00048 static const KAboutData data("kdevtrollproject", I18N_NOOP("QMake Manager"), "1.0");
00049 K_EXPORT_COMPONENT_FACTORY( libkdevtrollproject, TrollProjectFactory( &data ) )
00050 
00051 TrollProjectPart::TrollProjectPart(QObject *parent, const char *name, const QStringList& args )
00052     : KDevProject("TrollProject", "trollproject", parent, name ? name : "TrollProjectPart")
00053 {
00054     setInstance(TrollProjectFactory::instance());
00055 
00056     if ( args.count() == 1 && args[0] == "TMake" )
00057         m_tmakeProject = true;
00058     else
00059         m_tmakeProject = false;
00060 
00061     setXMLFile("kdevtrollproject.rc");
00062 
00063     m_executeAfterBuild = false;
00064 
00065     m_widget = new TrollProjectWidget(this);
00066     m_widget->setIcon(SmallIcon("make"));
00067     m_widget->setCaption(i18n("QMake Manager"));
00068     QWhatsThis::add(m_widget, i18n("<b>QMake manager</b><p>"
00069                                    "The QMake manager project tree consists of two parts. The 'overview' "
00070                                    "in the upper half shows the subprojects, each one having a "
00071                                    ".pro file. The 'details' view in the lower half shows the "
00072                                    "list of files for the active subproject selected in the overview."));
00073 
00074     mainWindow()->embedSelectViewRight(m_widget, i18n("QMake Manager"), i18n("QMake manager"));
00075 
00076     KAction *action;
00077 
00078     const QIconSet icon(SmallIcon("compfile"));
00079     action = new KAction( i18n("Compile &File"), "compfile", 0,
00080                           m_widget, SLOT(slotBuildFile()),
00081                           actionCollection(),"build_compilefile"  );
00082     action->setToolTip(i18n("Compile file"));
00083     action->setWhatsThis(i18n("<b>Compile file</b><p>Runs <b>make filename.o</b> command from the directory where 'filename' is the name of currently opened file.<br>"
00084                               "Environment variables and make arguments can be specified "
00085                               "in the project settings dialog, <b>Make Options</b> tab."));
00086 
00087 
00088     action = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8,
00089                           m_widget, SLOT(slotBuildProject()),
00090                           actionCollection(), "build_build_project" );
00091     action->setToolTip(i18n("Build project"));
00092     action->setWhatsThis(i18n("<b>Build project</b><p>Runs <b>make</b> from the project directory.<br>"
00093                               "Environment variables and make arguments can be specified "
00094                               "in the project settings dialog, <b>Make Options</b> tab."));
00095 
00096     action = new KAction( i18n("&Rebuild Project"),"rebuild" , 0,
00097                           m_widget, SLOT(slotRebuildProject()),
00098                           actionCollection(),"build_rebuild_project"  );
00099     action->setToolTip(i18n("Rebuild project"));
00100     action->setWhatsThis(i18n("<b>Rebuild project</b><p>Runs <b>make clean</b> and then <b>make</b> from the project directory.<br>"
00101                               "Environment variables and make arguments can be specified "
00102                               "in the project settings dialog, <b>Make Options</b> tab."));
00103 
00104     action = new KAction( i18n("&Clean Project"), 0,
00105                           m_widget, SLOT(slotCleanProject()),
00106                           actionCollection(), "build_clean_project" );
00107     action->setToolTip(i18n("Clean project"));
00108     action->setWhatsThis(i18n("<b>Clean project</b><p>Runs <b>make clean</b> command from the project directory.<br>"
00109                               "Environment variables and make arguments can be specified "
00110                               "in the project settings dialog, <b>Make Options</b> tab."));
00111 
00112     action = new KAction( i18n("Execute Main Program"), "exec", SHIFT+Key_F9,
00113                           m_widget, SLOT(slotExecuteProject()),
00114                           actionCollection(), "build_execute_project" );
00115     action->setToolTip(i18n("Execute main program"));
00116     action->setWhatsThis(i18n("<b>Execute program</b><p>Executes the main program specified in project settings, <b>Run Options</b> tab."));
00117 
00118 
00119 
00120 
00121 
00122     action = new KAction( i18n("&Build Subproject"), "make_kdevelop", Key_F7,
00123                           m_widget, SLOT(slotBuildTarget()),
00124                           actionCollection(), "build_build_target" );
00125     action->setToolTip(i18n("Build subproject"));
00126     action->setWhatsThis(i18n("<b>Build subproject</b><p>Runs <b>make</b> from the current subproject directory. "
00127                               "Current subproject is a subproject selected in <b>QMake manager</b> 'overview' window.<br>"
00128                               "Environment variables and make arguments can be specified "
00129                               "in the project settings dialog, <b>Make Options</b> tab."));
00130 
00131     action = new KAction( i18n("&Rebuild Subproject"), "rebuild", 0,
00132                           m_widget, SLOT(slotRebuildTarget()),
00133                           actionCollection(),"build_rebuild_target"  );
00134     action->setToolTip(i18n("Rebuild subproject"));
00135     action->setWhatsThis(i18n("<b>Rebuild subproject</b><p>Runs <b>make clean</b> and then <b>make</b> from the current subproject directory. "
00136                               "Current subproject is a subproject selected in <b>QMake manager</b> 'overview' window.<br>"
00137                               "Environment variables and make arguments can be specified "
00138                               "in the project settings dialog, <b>Make Options</b> tab."));
00139 
00140     action = new KAction( i18n("&Clean Subproject"), 0,
00141                           m_widget, SLOT(slotCleanTarget()),
00142                           actionCollection(), "build_clean_target" );
00143     action->setToolTip(i18n("Clean subproject"));
00144     action->setWhatsThis(i18n("<b>Clean subproject</b><p>Runs <b>make clean</b> from the current subproject directory. "
00145                               "Current subproject is a subproject selected in <b>QMake manager</b> 'overview' window.<br>"
00146                               "Environment variables and make arguments can be specified "
00147                               "in the project settings dialog, <b>Make Options</b> tab."));
00148 
00149     action = new KAction( i18n("Execute Subproject"), "exec", 0,
00150                           m_widget, SLOT(slotExecuteTarget()),
00151                           actionCollection(), "build_execute_target" );
00152     action->setToolTip(i18n("Execute subproject"));
00153     action->setWhatsThis(i18n("<b>Execute subproject</b><p>Executes the target program for the currently selected subproject. "
00154         "This action is allowed only if a type of the subproject is 'application'. The type of the subproject can be "
00155         "defined in <b>Subproject Settings</b> dialog (open it from the subproject context menu)."));
00156 
00157     connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)),
00158              this, SLOT(projectConfigWidget(KDialogBase*)) );
00159 
00160     connect( makeFrontend(), SIGNAL(commandFinished(const QString&)),
00161              this, SLOT(slotCommandFinished(const QString&)) );
00162 
00163     m_qmakeHeader = i18n("# File generated by kdevelop's qmake manager. \n"
00164                          "# ------------------------------------------- \n"
00165                          "# Subdir relative project main directory: %s\n"
00166                          "# Target is %s %s\n");
00167 
00168     m_availableQtDirList = availableQtDirList();
00169     m_defaultQtDir = ::getenv( "QTDIR" );
00170     if( m_defaultQtDir.isEmpty() && !m_availableQtDirList.isEmpty() )
00171         m_defaultQtDir = m_availableQtDirList.front();
00172 }
00173 
00174 
00175 TrollProjectPart::~TrollProjectPart()
00176 {
00177     if (m_widget)
00178         mainWindow()->removeView(m_widget);
00179     delete m_widget;
00180 }
00181 
00182 QString TrollProjectPart::makeEnvironment()
00183 {
00184     // Get the make environment variables pairs into the environstr string
00185     // in the form of: "ENV_VARIABLE=ENV_VALUE"
00186     // Note that we quote the variable value due to the possibility of
00187     // embedded spaces
00188     DomUtil::PairList envvars =
00189         DomUtil::readPairListEntry(*projectDom(), "/kdevtrollproject/make/envvars", "envvar", "name", "value");
00190 
00191     QString environstr;
00192     DomUtil::PairList::ConstIterator it;
00193     bool hasQtDir = false;
00194     for (it = envvars.begin(); it != envvars.end(); ++it) {
00195         if( (*it).first == "QTDIR" )
00196         hasQtDir = true;
00197 
00198         environstr += (*it).first;
00199         environstr += "=";
00200 /*
00201 #if (KDE_VERSION > 305)
00202         environstr += KProcess::quote((*it).second);
00203 #else
00204         environstr += KShellProcess::quote((*it).second);
00205 #endif
00206 */
00207         environstr += EnvVarTools::quote((*it).second);
00208         environstr += " ";
00209     }
00210 
00211     if( !hasQtDir && !m_defaultQtDir.isEmpty() )
00212     {
00213          environstr += QString( "QTDIR=" ) + EnvVarTools::quote( m_defaultQtDir ) + QString( " " );
00214     }
00215 
00216     return environstr;
00217 }
00218 
00219 void TrollProjectPart::projectConfigWidget(KDialogBase *dlg)
00220 {
00221     QVBox *vbox;
00222     vbox = dlg->addVBoxPage(i18n("Run Options"));
00223     RunOptionsWidget *optdlg = new RunOptionsWidget(*projectDom(), "/kdevtrollproject", buildDirectory(), vbox);
00224 
00225     vbox = dlg->addVBoxPage(i18n("Make Options"));
00226     MakeOptionsWidget *w4 = new MakeOptionsWidget(*projectDom(), "/kdevtrollproject", vbox);
00227     connect( dlg, SIGNAL(okClicked()), w4, SLOT(accept()) );
00228 
00229     connect( dlg, SIGNAL(okClicked()), optdlg, SLOT(accept()) );
00230 }
00231 
00232 
00233 void TrollProjectPart::openProject(const QString &dirName, const QString &projectName)
00234 {
00235     m_widget->openProject(dirName);
00236     m_projectName = projectName;
00237 
00238     QDomDocument &dom = *projectDom();
00239     // Set the default directory radio to "executable"
00240     if (DomUtil::readEntry(dom, "/kdevtrollproject/run/directoryradio") == "" ) {
00241         DomUtil::writeEntry(dom, "/kdevtrollproject/run/directoryradio", "executable");
00242     }
00243 
00244     KDevProject::openProject( dirName, projectName );
00245 }
00246 
00247 
00248 void TrollProjectPart::closeProject()
00249 {
00250     m_widget->closeProject();
00251 }
00252 
00253 
00254 QString TrollProjectPart::projectDirectory() const
00255 {
00256   return m_widget->projectDirectory();
00257 }
00258 
00259 
00260 QString TrollProjectPart::buildDirectory() const
00261 {
00262   return m_widget->projectDirectory();
00263 }
00264 
00265 QString TrollProjectPart::projectName() const
00266 {
00267     return m_projectName;
00268 }
00269 
00270 
00272 DomUtil::PairList TrollProjectPart::runEnvironmentVars() const
00273 {
00274     return DomUtil::readPairListEntry(*projectDom(), "/kdevtrollproject/run/envvars", "envvar", "name", "value");
00275 }
00276 
00277 
00287 QString TrollProjectPart::runDirectory() const
00288 {
00289     QDomDocument &dom = *projectDom();
00290 
00291     QString directoryRadioString = DomUtil::readEntry(dom, "/kdevtrollproject/run/directoryradio");
00292     QString DomMainProgram = DomUtil::readEntry(dom, "/kdevtrollproject/run/mainprogram");
00293 
00294     if ( directoryRadioString == "build" )
00295         return buildDirectory();
00296 
00297     if ( directoryRadioString == "custom" )
00298         return DomUtil::readEntry(dom, "/kdevtrollproject/run/customdirectory");
00299 
00300     int pos = DomMainProgram.findRev('/');
00301     if (pos != -1)
00302         return buildDirectory() + "/" + DomMainProgram.left(pos);
00303 
00304     if ( DomMainProgram.isEmpty() )
00305     {
00306         return m_widget->subprojectDirectory();
00307     }
00308     return buildDirectory() + "/" + DomMainProgram;
00309 
00310 }
00311 
00312 
00322 QString TrollProjectPart::mainProgram(bool relative) const
00323 {
00324     QDomDocument &dom = *projectDom();
00325 
00326     QString directoryRadioString = DomUtil::readEntry(dom, "/kdevtrollproject/run/directoryradio");
00327     QString DomMainProgram = DomUtil::readEntry(dom, "/kdevtrollproject/run/mainprogram");
00328 
00329     if ( directoryRadioString == "custom" )
00330         return DomMainProgram;
00331 
00332     if ( relative == false && !DomMainProgram.isEmpty() )
00333         return buildDirectory() + "/" + DomMainProgram;
00334 
00335     if ( directoryRadioString == "executable" ) {
00336         int pos = DomMainProgram.findRev('/');
00337         if (pos != -1)
00338             return DomMainProgram.mid(pos+1);
00339 
00340         if ( DomMainProgram.isEmpty() )
00341         {
00342             return runDirectory() + "/" + m_widget->getCurrentOutputFilename();
00343         }
00344         return DomMainProgram;
00345     }
00346     else
00347         return DomMainProgram;
00348 }
00349 
00350 
00352 QString TrollProjectPart::runArguments() const
00353 {
00354     return DomUtil::readEntry(*projectDom(), "/kdevtrollproject/run/programargs");
00355 }
00356 
00357 
00358 QString TrollProjectPart::activeDirectory() const
00359 {
00360     QDomDocument &dom = *projectDom();
00361 
00362     return DomUtil::readEntry(dom, "/kdevtrollproject/general/activedir");
00363 }
00364 
00365 
00366 QStringList TrollProjectPart::allFiles() const
00367 {
00368     return m_widget->allFiles();
00369 }
00370 
00371 
00372 void TrollProjectPart::addFile(const QString &fileName)
00373 {
00374     QStringList fileList;
00375     fileList.append ( fileName );
00376 
00377     this->addFiles ( fileList );
00378 }
00379 
00380 void TrollProjectPart::addFiles ( const QStringList &fileList )
00381 {
00382     QStringList files = fileList;
00383     for (QStringList::iterator it = files.begin(); it != files.end(); ++it)
00384 //        if (!(*it).contains(projectDirectory()))
00385         if (!isProjectFile(projectDirectory() + "/" + (*it)))
00386             *it = projectDirectory() + "/" + (*it);
00387 
00388     m_widget->addFiles(files);
00389 
00390 //  emit addedFilesToProject ( files );
00391 }
00392 
00393 void TrollProjectPart::removeFile(const QString & /* fileName */)
00394 {
00396 /*  QStringList fileList;
00397     fileList.append ( fileName );
00398 
00399     this->removeFiles ( fileList );*/
00400 }
00401 
00402 void TrollProjectPart::removeFiles ( const QStringList& fileList )
00403 {
00405 //  QStringList::ConstIterator it;
00406 //
00407 //  it = fileList.begin();
00408 //
00409 //  for ( ; it != fileList.end(); ++it )
00410 //  {
00411 //      FIXME
00412 //  }
00413 
00414     emit removedFilesFromProject ( fileList );
00415 }
00416 /*
00417 void TrollProjectPart::startMakeCommand(const QString &dir, const QString &target)
00418 {
00419     partController()->saveAllFiles();
00420 
00421     QFileInfo fi(dir + "/Makefile");
00422     if (!fi.exists()) {
00423         int r = KMessageBox::questionYesNo(m_widget, i18n("There is no Makefile in this directory. Run qmake first?"));
00424         if (r == KMessageBox::No)
00425             return;
00426         startQMakeCommand(dir);
00427     }
00428     QDomDocument &dom = *projectDom();
00429 
00430     if (target=="clean")
00431     {
00432       QString cmdline = DomUtil::readEntry(dom, "/kdevtrollproject/make/makebin");
00433       if (cmdline.isEmpty())
00434           cmdline = MAKE_COMMAND;
00435       cmdline += " clean";
00436       QString dircmd = "cd ";
00437       dircmd += dir;
00438       dircmd += " && ";
00439       cmdline.prepend(makeEnvironment());
00440       makeFrontend()->queueCommand(dir, dircmd + cmdline);
00441     }
00442 
00443     QString cmdline = DomUtil::readEntry(dom, "/kdevtrollproject/make/makebin");
00444     if (cmdline.isEmpty())
00445         cmdline = MAKE_COMMAND;
00446     if (!DomUtil::readBoolEntry(dom, "/kdevtrollproject/make/abortonerror"))
00447         cmdline += " -k";
00448     int jobs = DomUtil::readIntEntry(dom, "/kdevtrollproject/make/numberofjobs");
00449     if (jobs != 0) {
00450         cmdline += " -j";
00451         cmdline += QString::number(jobs);
00452     }
00453     if (DomUtil::readBoolEntry(dom, "/kdevtrollproject/make/dontact"))
00454         cmdline += " -n";
00455 
00456     cmdline += " ";
00457     cmdline += target;
00458 
00459     QString dircmd = "cd ";
00460     dircmd += dir;
00461     dircmd += " && ";
00462 
00463     cmdline.prepend(makeEnvironment());
00464     makeFrontend()->queueCommand(dir, dircmd + cmdline);
00465 }
00466 */
00467 
00468 void TrollProjectPart::startQMakeCommand(const QString &dir)
00469 {
00470     QFileInfo fi(dir);
00471 
00472     QString cmdline = QString::fromLatin1( isTMakeProject() ? "tmake " : "qmake " );
00473 //    cmdline += fi.baseName() + ".pro";
00474     QDir d(dir);
00475     QStringList l = d.entryList("*.pro");
00476 
00477     cmdline += l.count()?l[0]:(fi.baseName() + ".pro");
00478 
00479 //    cmdline += QString::fromLatin1( " -o Makefile" );
00480 
00481     QString dircmd = "cd ";
00482     dircmd += KProcess::quote(dir);
00483     dircmd += " && ";
00484 
00485     cmdline.prepend(makeEnvironment());
00486     makeFrontend()->queueCommand(dir, dircmd + cmdline);
00487 }
00488 
00489 void TrollProjectPart::queueCmd(const QString &dir, const QString &cmd)
00490 {
00491     makeFrontend()->queueCommand(dir, cmd);
00492 }
00493 
00494 void TrollProjectPart::slotCommandFinished( const QString& command )
00495 {
00496     Q_UNUSED( command );
00497 
00498     if( m_buildCommand != command )
00499         return;
00500 
00501     m_buildCommand = QString::null;
00502 
00503     m_timestamp.clear();
00504     QStringList fileList = allFiles();
00505     QStringList::Iterator it = fileList.begin();
00506     while( it != fileList.end() ){
00507         QString fileName = *it;
00508         ++it;
00509 
00510         m_timestamp[ fileName ] = QFileInfo( projectDirectory(), fileName ).lastModified();
00511     }
00512 
00513     emit projectCompiled();
00514 
00515     if( m_executeAfterBuild ){
00516         m_widget->slotExecuteProject();
00517         m_executeAfterBuild = false;
00518     }
00519 }
00520 
00521 bool TrollProjectPart::isDirty()
00522 {
00523     QStringList fileList = allFiles();
00524     QStringList::Iterator it = fileList.begin();
00525     while( it != fileList.end() ){
00526         QString fileName = *it;
00527         ++it;
00528 
00529         QMap<QString, QDateTime>::Iterator it = m_timestamp.find( fileName );
00530         QDateTime t = QFileInfo( projectDirectory(), fileName ).lastModified();
00531         if( it == m_timestamp.end() || *it != t ){
00532             return true;
00533         }
00534     }
00535 
00536     return false;
00537 }
00538 
00539 KDevProject::Options TrollProjectPart::options( ) const
00540 {
00541     return UsesQMakeBuildSystem;
00542 }
00543 
00544 bool TrollProjectPart::isValidQtDir( const QString& path ) const
00545 {
00546     return QFile::exists( path + "/include/qt.h" );
00547 }
00548 
00549 QStringList TrollProjectPart::availableQtDirList() const
00550 {
00551     QStringList qtdirs, lst;
00552     qtdirs.push_back( ::getenv("QTDIR") );
00553     qtdirs.push_back( "/usr/lib/qt3" );
00554     qtdirs.push_back( "/usr/lib/qt" );
00555     qtdirs.push_back( "/usr/share/qt3" );
00556 
00557     for( QStringList::Iterator it=qtdirs.begin(); it!=qtdirs.end(); ++it )
00558     {
00559         QString qtdir = *it;
00560         if( !qtdir.isEmpty() && isValidQtDir(qtdir) )
00561         lst.push_back( qtdir );
00562     }
00563     return lst;
00564 }
00565 
00566 QStringList recursiveProFind( const QString &currDir, const QString &baseDir )
00567 {
00568     kdDebug() << "Dir " << currDir << endl;
00569     QStringList fileList;
00570 
00571     if( !currDir.contains( "/..") && !currDir.contains("/.") )
00572     {
00573         QDir dir(currDir);
00574         QStringList dirList = dir.entryList(QDir::Dirs );
00575         QStringList::Iterator idx = dirList.begin();
00576         for( ; idx != dirList.end(); ++idx )
00577         {
00578             fileList += recursiveProFind( currDir + "/" + (*idx),baseDir );
00579         }
00580         QStringList newFiles = dir.entryList("*.pro *.PRO");
00581         idx = newFiles.begin();
00582         for( ; idx != newFiles.end(); ++idx )
00583         {
00584             QString file = currDir + "/" + (*idx);
00585             fileList.append( file.remove( baseDir ) );
00586         }
00587     }
00588 
00589 
00590     return fileList;
00591 }
00592 
00596 QStringList TrollProjectPart::distFiles() const
00597 {
00598     QStringList sourceList = allFiles();
00599     // Scan current source directory for any .pro files.
00600     QString projectDir = projectDirectory();
00601     QStringList files = recursiveProFind( projectDir, projectDir + "/" );
00602     return sourceList + files;
00603 }
00604 
00605 #include "trollprojectpart.moc"
00606 
00607 
00608 
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:23 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003