KDevelop API Documentation

pascalproject_part.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2003 Alexander Dymo                                     *
00003  *   cloudtemple@mksat.net                                                 *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  ***************************************************************************/
00011 #include <qdom.h>
00012 #include <qfileinfo.h>
00013 #include <qdir.h>
00014 #include <qvaluestack.h>
00015 #include <qregexp.h>
00016 #include <qvbox.h>
00017 #include <qlabel.h>
00018 
00019 #include <kiconloader.h>
00020 #include <klocale.h>
00021 #include <kaction.h>
00022 #include <kdevgenericfactory.h>
00023 #include <kdebug.h>
00024 #include <kdialogbase.h>
00025 #include <kmessagebox.h>
00026 #include <klibloader.h>
00027 #include <kservice.h>
00028 #include <kconfig.h>
00029 #include <kdeversion.h>
00030 #include <kprocess.h>
00031 
00032 #include "domutil.h"
00033 #include "kdevcore.h"
00034 #include "kdevmainwindow.h"
00035 #include "kdevmakefrontend.h"
00036 #include "kdevappfrontend.h"
00037 #include "kdevpartcontroller.h"
00038 #include "kdevlanguagesupport.h"
00039 #include "kdevcompileroptions.h"
00040 #include "runoptionswidget.h"
00041 #include "envvartools.h"
00042 
00043 #include "pascalproject_widget.h"
00044 #include "pascalproject_part.h"
00045 #include "pascalprojectoptionsdlg.h"
00046 #include "pascalglobaloptionsdlg.h"
00047 
00048 typedef KDevGenericFactory<PascalProjectPart> PascalProjectFactory;
00049 static const KAboutData data("kdevpascalproject", I18N_NOOP("Build Tool"), "1.0");
00050 K_EXPORT_COMPONENT_FACTORY( libkdevpascalproject, PascalProjectFactory( &data ) )
00051 
00052 PascalProjectPart::PascalProjectPart(QObject *parent, const char *name, const QStringList& )
00053     :KDevProject("PascalProject", "pascalproject", parent, name ? name : "PascalProjectPart" )
00054 {
00055     setInstance(PascalProjectFactory::instance());
00056     setXMLFile("kdevpascalproject.rc");
00057 
00058     KAction *action;
00059     action = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8,
00060                           this, SLOT(slotBuild()),
00061                           actionCollection(), "build_build" );
00062     action->setToolTip(i18n("Build project"));
00063     action->setWhatsThis(i18n("<b>Build project</b><p>Runs the compiler on a main source file of the project. "
00064         "The compiler and the main source file can be set in project settings, <b>Pascal Compiler</b> tab."));
00065     action = new KAction( i18n("Execute Program"), "exec", 0,
00066                           this, SLOT(slotExecute()),
00067                           actionCollection(), "build_execute" );
00068     action->setToolTip(i18n("Execute program"));
00069     action->setWhatsThis(i18n("<b>Execute program</b><p>Executes the main program specified in project settings, <b>Run options</b> tab. "
00070         "If nothing is set, the binary file with the same name as the main source file name is executed."));
00071 
00072     connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)),
00073              this, SLOT(projectConfigWidget(KDialogBase*)) );
00074 
00075     connect( core(), SIGNAL(configWidget(KDialogBase*)),
00076              this, SLOT(configWidget(KDialogBase*)) );
00077 
00078 //  m_widget = new PascalProjectWidget(this);
00079 
00080 //  QWhatsThis::add(m_widget, i18n("WHAT DOES THIS PART DO?"));
00081 
00082   // now you decide what should happen to the widget. Take a look at kdevcore.h
00083   // or at other plugins how to embed it.
00084 
00085   // if you want to embed your widget as an outputview, simply uncomment
00086   // the following line.
00087 
00088   // mainWindow()->embedOutputView( m_widget, "name that should appear", "enter a tooltip" );
00089 
00090 }
00091 
00092 PascalProjectPart::~PascalProjectPart()
00093 {
00094 //  delete m_widget;
00095 }
00096 
00101 static bool matchesPattern(const QString &fileName, const QStringList &patternList)
00102 {
00103     QStringList::ConstIterator it;
00104     for (it = patternList.begin(); it != patternList.end(); ++it) {
00105         QRegExp re(*it, true, true);
00106         if (re.search(fileName) == 0 && re.matchedLength() == (int)fileName.length())
00107             return true;
00108     }
00109 
00110     return false;
00111 }
00112 
00113 void PascalProjectPart::openProject(const QString &dirName, const QString &projectName)
00114 {
00115     m_buildDir = dirName;
00116     m_projectDir = dirName;
00117     m_projectName = projectName;
00118 
00119     QDomDocument &dom = *projectDom();
00120     // Set the default directory radio to "executable"
00121     if (DomUtil::readEntry(dom, "/kdevpascalproject/run/directoryradio") == "" ) {
00122         DomUtil::writeEntry(dom, "/kdevpascalproject/run/directoryradio", "executable");
00123     }
00124 
00125     loadProjectConfig();
00126 
00127     // Put all files from all subdirectories into file list
00128     QValueStack<QString> s;
00129     int prefixlen = m_projectDir.length()+1;
00130     s.push(m_projectDir);
00131 
00132     QStringList includepatternList;
00133     if ( languageSupport() )
00134     {
00135     KMimeType::List list = languageSupport()->mimeTypes();
00136     KMimeType::List::Iterator it = list.begin();
00137     while( it != list.end() ){
00138         includepatternList += (*it)->patterns();
00139         ++it;
00140     }
00141     }
00142     QString excludepatterns = "*~";
00143     QStringList excludepatternList = QStringList::split(",", excludepatterns);
00144 
00145     QDir dir;
00146     do {
00147         dir.setPath(s.pop());
00148         kdDebug(9033) << "Examining: " << dir.path() << endl;
00149         const QFileInfoList *dirEntries = dir.entryInfoList();
00150         QPtrListIterator<QFileInfo> it(*dirEntries);
00151         for (; it.current(); ++it) {
00152             QString fileName = it.current()->fileName();
00153             if (fileName == "." || fileName == "..")
00154                 continue;
00155             QString path = it.current()->absFilePath();
00156             if (it.current()->isDir()) {
00157                 kdDebug(9033) << "Pushing: " << path << endl;
00158                 s.push(path);
00159             }
00160             else {
00161                 if (matchesPattern(path, includepatternList)
00162                     && !matchesPattern(path, excludepatternList)) {
00163                     kdDebug(9033) << "Adding: " << path << endl;
00164                     m_sourceFiles.append(path.mid(prefixlen));
00165                 } else {
00166                     kdDebug(9033) << "Ignoring: " << path << endl;
00167                 }
00168             }
00169         }
00170     } while (!s.isEmpty());
00171     
00172     KDevProject::openProject( dirName, projectName );
00173 }
00174 
00175 void PascalProjectPart::closeProject()
00176 {
00177 }
00178 
00180 DomUtil::PairList PascalProjectPart::runEnvironmentVars() const
00181 {
00182     return DomUtil::readPairListEntry(*projectDom(), "/kdevpascalproject/run/envvars", "envvar", "name", "value");
00183 }
00184 
00185 
00195 QString PascalProjectPart::runDirectory() const
00196 {
00197     QDomDocument &dom = *projectDom();
00198 
00199     QString directoryRadioString = DomUtil::readEntry(dom, "/kdevpascalproject/run/directoryradio");
00200     QString DomMainProgram = DomUtil::readEntry(dom, "/kdevpascalproject/run/mainprogram");
00201 
00202     if ( directoryRadioString == "build" )
00203         return buildDirectory();
00204 
00205     if ( directoryRadioString == "custom" )
00206         return DomUtil::readEntry(dom, "/kdevpascalproject/run/customdirectory");
00207 
00208     int pos = DomMainProgram.findRev('/');
00209     if (pos != -1)
00210         return buildDirectory() + "/" + DomMainProgram.left(pos);
00211 
00212     return buildDirectory() + "/" + DomMainProgram;
00213 
00214 }
00215 
00216 
00226 QString PascalProjectPart::mainProgram(bool relative) const
00227 {
00228     QDomDocument &dom = *projectDom();
00229     QString configMainProg = DomUtil::readEntry(dom, "/kdevpascalproject/run/mainprogram", "");
00230     if (configMainProg.isEmpty())
00231     {
00232         QFileInfo fi(mainSource());
00233         return buildDirectory() + "/" + fi.baseName();
00234     }
00235     else
00236         return QDir::cleanDirPath(projectDirectory() + "/" + configMainProg);
00237 
00239     QString directoryRadioString = DomUtil::readEntry(dom, "/kdevpascalproject/run/directoryradio");
00240     QString DomMainProgram = DomUtil::readEntry(dom, "/kdevpascalproject/run/mainprogram");
00241 
00242     if ( directoryRadioString == "custom" )
00243         return DomMainProgram;
00244 
00245     if ( relative == false )
00246         return buildDirectory() + "/" + DomMainProgram;
00247 
00248     if ( directoryRadioString == "executable" ) {
00249         int pos = DomMainProgram.findRev('/');
00250         if (pos != -1)
00251             return DomMainProgram.mid(pos+1);
00252         return DomMainProgram;
00253     }
00254     else
00255         return DomMainProgram;
00256 }
00257 
00258 
00260 QString PascalProjectPart::runArguments() const
00261 {
00262     return DomUtil::readEntry(*projectDom(), "/kdevpascalproject/run/programargs");
00263 }
00264 
00265 QString PascalProjectPart::mainSource() const
00266 {
00267     return projectDirectory() + "/" + m_mainSource;
00268 }
00269 
00270 void PascalProjectPart::setMainSource(QString fullPath)
00271 {
00272     m_mainSource = fullPath.replace(QRegExp(QString(projectDirectory() + QString("/"))),"");
00273 }
00274 
00275 QString PascalProjectPart::projectDirectory() const
00276 {
00277     return m_projectDir;
00278 }
00279 
00280 QString PascalProjectPart::projectName() const
00281 {
00282     return m_projectName;
00283 }
00284 
00285 QString PascalProjectPart::activeDirectory() const
00286 {
00287     QFileInfo fi(mainSource());
00288     return fi.dirPath(true).replace(QRegExp(projectDirectory()),"");
00289 }
00290 
00291 QString PascalProjectPart::buildDirectory() const
00292 {
00293     QFileInfo fi(mainSource());
00294     return fi.dirPath(true);
00295 }
00296 
00297 void PascalProjectPart::listOfFiles(QStringList &result, QString path) const
00298 {
00299     QDir d(path);
00300     if (!d.exists())
00301         return;
00302     QFileInfoList *entries = const_cast<QFileInfoList*>(d.entryInfoList(QDir::Dirs | QDir::Files | QDir::Hidden));
00303     for (QFileInfo *it = entries->first(); it; it = entries->next())
00304     {
00305         if ((it->isDir()) && (it->filePath() != path))
00306         {
00307 //            qWarning("entering dir %s", it->dirPath().latin1());
00308             listOfFiles(result, it->dirPath());
00309         }
00310         else
00311         {
00312 //            qWarning("adding to result: %s", it->filePath().latin1());
00313             result << it->filePath();
00314         }
00315     }
00316 }
00317 
00318 QStringList PascalProjectPart::allFiles() const
00319 {
00320 //    QStringList files;
00321 
00322 //    listOfFiles(files, projectDirectory());
00323 
00324 //    return files;
00325     return m_sourceFiles;
00326 }
00327 
00328 void PascalProjectPart::addFile(const QString& /*fileName*/)
00329 {
00330 }
00331 
00332 void PascalProjectPart::addFiles(const QStringList& /*fileList*/)
00333 {
00334 }
00335 
00336 void PascalProjectPart::removeFile(const QString& /*fileName*/)
00337 {
00338 }
00339 
00340 void PascalProjectPart::removeFiles(const QStringList& /*fileList*/)
00341 {
00342 }
00343 
00344 void PascalProjectPart::slotBuild()
00345 {
00346     partController()->saveAllFiles();
00347 
00348     QString cmdline = m_compilerExec + " " + m_compilerOpts + " ";
00349 
00350     if (cmdline.isEmpty())
00351     {
00352         KMessageBox::sorry(0, i18n("Could not find pascal compiler.\nCheck if your compiler settings are correct."));
00353         return;
00354     }
00355 
00356     QFileInfo fi(mainSource());
00357     cmdline += fi.fileName();
00358 
00359     QString dircmd = "cd ";
00360     dircmd += KProcess::quote(buildDirectory());
00361     dircmd += " && ";
00362 
00363     makeFrontend()->queueCommand(buildDirectory(), dircmd + cmdline);
00364 }
00365 
00366 void PascalProjectPart::slotExecute()
00367 {
00368     partController()->saveAllFiles();
00369 
00370     QDomDocument &dom = *(projectDom());
00371     bool runInTerminal = DomUtil::readBoolEntry(dom, "/kdevpascalproject/run/terminal", true);
00372 
00373     // Get the run environment variables pairs into the environstr string
00374     // in the form of: "ENV_VARIABLE=ENV_VALUE"
00375     // Note that we quote the variable value due to the possibility of
00376     // embedded spaces
00377     DomUtil::PairList envvars =
00378         DomUtil::readPairListEntry(*projectDom(), "/kdevpascalproject/run/envvars", "envvar", "name", "value");
00379 
00380     QString environstr;
00381     DomUtil::PairList::ConstIterator it;
00382     for (it = envvars.begin(); it != envvars.end(); ++it) {
00383         environstr += (*it).first;
00384         environstr += "=";
00385 /*
00386 #if (KDE_VERSION > 305)
00387         environstr += KProcess::quote((*it).second);
00388 #else
00389         environstr += KShellProcess::quote((*it).second);
00390 #endif
00391 */
00392         environstr += EnvVarTools::quote((*it).second);
00393         environstr += " ";
00394     }
00395 
00396     QString program = mainProgram();
00397     program.prepend(environstr);
00398     program += " " + DomUtil::readEntry(*projectDom(), "/kdevpascalproject/run/programargs");
00399 
00400     appFrontend()->startAppCommand(buildDirectory(), program, runInTerminal);
00401 }
00402 
00403 void PascalProjectPart::changedFiles( const QStringList & fileList )
00404 {
00405     KDevProject::changedFiles(fileList);
00406 }
00407 
00408 void PascalProjectPart::changedFile( const QString & fileName )
00409 {
00410     KDevProject::changedFile(fileName);
00411 }
00412 
00413 void PascalProjectPart::projectConfigWidget( KDialogBase * dlg )
00414 {
00415     QVBox *vbox;
00416     vbox = dlg->addVBoxPage(i18n("Pascal Compiler"));
00417     PascalProjectOptionsDlg *w = new PascalProjectOptionsDlg(this, vbox);
00418     connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00419     connect( dlg, SIGNAL(okClicked()), this, SLOT(loadProjectConfig()) );
00420 
00421     vbox = dlg->addVBoxPage(i18n("Run Options"));
00422     RunOptionsWidget *w3 = new RunOptionsWidget(*projectDom(), "/kdevpascalproject", buildDirectory(), vbox);
00423     w3->mainprogram_label->setText(i18n("Main program (relative to project directory):"));
00424     connect( dlg, SIGNAL(okClicked()), w3, SLOT(accept()) );
00425 
00426 }
00427 
00428 void PascalProjectPart::loadProjectConfig( )
00429 {
00430     QDomDocument &dom = *(projectDom());
00431 
00432     QString config = DomUtil::readEntry(dom, "/kdevpascalproject/general/useconfiguration", "default");
00433     m_mainSource = DomUtil::readEntry(dom, QString("/kdevpascalproject/configurations/") + config + QString("/mainsource") );
00434     m_compilerOpts = DomUtil::readEntry(dom, QString("/kdevpascalproject/configurations/") + config + QString("/compileroptions"));
00435     m_compilerExec = DomUtil::readEntry(dom, QString("/kdevpascalproject/configurations/") + config + QString("/compilerexec"));
00436 
00437     if (m_compilerExec.isEmpty())
00438     {
00439         KTrader::OfferList offers = KTrader::self()->query("KDevelop/CompilerOptions", "[X-KDevelop-Language] == 'Pascal'");
00440         QValueList<KService::Ptr>::ConstIterator it;
00441         for (it = offers.begin(); it != offers.end(); ++it) {
00442             if ((*it)->property("X-KDevelop-Default").toBool()) {
00443                 m_compilerExec = (*it)->exec();
00444                 break;
00445             }
00446         }
00447     }
00448 }
00449 
00450 void PascalProjectPart::configWidget( KDialogBase * dlg )
00451 {
00452     QVBox *vbox;
00453     vbox = dlg->addVBoxPage(i18n("Pascal Compiler"));
00454     PascalGlobalOptionsDlg *w = new PascalGlobalOptionsDlg(this, vbox);
00455     connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00456 }
00457 
00458 KDevCompilerOptions *PascalProjectPart::createCompilerOptions(const QString &name)
00459 {
00460     KService::Ptr service = KService::serviceByDesktopName(name);
00461     if (!service) {
00462         kdDebug() << "Can't find service " << name;
00463         return 0;
00464     }
00465 
00466     KLibFactory *factory = KLibLoader::self()->factory(QFile::encodeName(service->library()));
00467     if (!factory) {
00468         QString errorMessage = KLibLoader::self()->lastErrorMessage();
00469         KMessageBox::error(0, i18n("There was an error loading the module %1.\n"
00470                                    "The diagnostics is:\n%2").arg(service->name()).arg(errorMessage));
00471         exit(1);
00472     }
00473 
00474     QStringList args;
00475     QVariant prop = service->property("X-KDevelop-Args");
00476     if (prop.isValid())
00477         args = QStringList::split(" ", prop.toString());
00478 
00479     QObject *obj = factory->create(this, service->name().latin1(),
00480                                    "KDevCompilerOptions", args);
00481 
00482     if (!obj->inherits("KDevCompilerOptions")) {
00483         kdDebug() << "Component does not inherit KDevCompilerOptions" << endl;
00484         return 0;
00485     }
00486     KDevCompilerOptions *dlg = (KDevCompilerOptions*) obj;
00487 
00488     return dlg;
00489 }
00490 
00491 QString PascalProjectPart::defaultOptions( const QString compiler ) const
00492 {
00493     KConfig *config = KGlobal::config();
00494     config->setGroup("Pascal Compiler");
00495     return config->readPathEntry(compiler);
00496 }
00497 
00498 #include "pascalproject_part.moc"
00499 
00500 
00504 QStringList PascalProjectPart::distFiles() const
00505 {
00506     QStringList sourceList = allFiles();
00507     // Scan current source directory for any .pro files.
00508     QString projectDir = projectDirectory();
00509     QDir dir(projectDir);
00510     QStringList files = dir.entryList( "Makefile");
00511     return sourceList + files;
00512 }
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:22 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003