KDevelop API Documentation

haskellproject_part.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           haskellproject_part.cpp  -  description
00003                              -------------------
00004     begin                : Mon Aug 11 2003
00005     copyright            : (C) 2003 Peter Robinson
00006     email                : listener@thaldyron.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
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 <qdom.h>
00019 #include <qfileinfo.h>
00020 #include <qdir.h>
00021 #include <qvaluestack.h>
00022 #include <qregexp.h>
00023 #include <qvbox.h>
00024 #include <qlabel.h>
00025 
00026 #include <kiconloader.h>
00027 #include <klocale.h>
00028 #include <kaction.h>
00029 #include <kgenericfactory.h>
00030 #include <kdebug.h>
00031 #include <kdialogbase.h>
00032 #include <kmessagebox.h>
00033 #include <klibloader.h>
00034 #include <kservice.h>
00035 #include <kconfig.h>
00036 #include <kdeversion.h>
00037 #include <kprocess.h>
00038 #include <ktrader.h>
00039 
00040 #include "domutil.h"
00041 #include "kdevcore.h"
00042 #include "kdevmainwindow.h"
00043 #include "kdevmakefrontend.h"
00044 #include "kdevappfrontend.h"
00045 #include "kdevpartcontroller.h"
00046 #include "kdevlanguagesupport.h"
00047 #include "kdevcompileroptions.h"
00048 #include "runoptionswidget.h"
00049 #include "haskellprojectoptionsdlg.h"
00050 #include "haskellproject_part.h"
00051 
00052 typedef KGenericFactory<HaskellProjectPart> HaskellProjectFactory;
00053 K_EXPORT_COMPONENT_FACTORY( libkdevhaskellproject, HaskellProjectFactory( "kdevhaskellproject" ) )
00054 
00055 
00056 HaskellProjectPart::HaskellProjectPart(QObject *parent, const char *name, const QStringList& )
00057   : KDevProject("KDevPart", "kdevpart", parent, name ? name : "HaskellProjectPart" )
00058 {
00059     setInstance(HaskellProjectFactory::instance());
00060     setXMLFile("kdevhaskellproject.rc");
00061 
00062  // _widget = new HaskellProjectWidget(this);
00063 
00064     _buildAction = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8,
00065                                   this, SLOT(slotBuild()),
00066                                   actionCollection(), "build_build" );
00067     _runAction = new KAction( i18n("Execute Program"), "exec", 0,
00068                               this, SLOT(slotExecute()),
00069                               actionCollection(), "build_execute" );
00070 
00071     connect( core(), SIGNAL( projectConfigWidget( KDialogBase* ) ),
00072              this, SLOT( projectConfigWidget( KDialogBase* ) ) );
00073 
00074     connect( core(), SIGNAL( configWidget( KDialogBase* ) ),
00075              this, SLOT( configWidget( KDialogBase* ) ) );                          
00076 }
00077 
00078 
00079 HaskellProjectPart::~HaskellProjectPart()
00080 {
00081   //delete _widget;
00082 }
00083 
00084 
00085 void HaskellProjectPart::openProject(const QString &dirName, const QString &projectName)
00086 {
00087     _buildDir = dirName;
00088     _projectDir = dirName;
00089     _projectName = projectName;
00090     loadProjectConfig();
00091     QDomDocument &dom = *projectDom();
00092     QString directoryRadioString = DomUtil::readEntry( dom,
00093                                     "/kdevhaskellproject/run/directoryradio" );
00094     QString mainProgram = DomUtil::readEntry( dom,
00095                                     "/kdevhaskellproject/run/mainprogram" );
00096     QString customDir = DomUtil::readEntry( dom,
00097                                     "/kdevhaskellproject/run/customdirectory" );
00098 }
00099 
00100 void HaskellProjectPart::closeProject()
00101 {
00102 }
00103 
00104 
00105 QString HaskellProjectPart::projectDirectory() const
00106 {
00107     return _projectDir;
00108 }
00109 
00110 QString HaskellProjectPart::projectName() const
00111 {
00112     return _projectName;
00113 }
00114 
00116 DomUtil::PairList HaskellProjectPart::runEnvironmentVars() const
00117 {
00118     return DomUtil::readPairListEntry(*projectDom(),
00119                                       "/kdevhaskellproject/run/envvars",
00120                                       "envvar", "name", "value");
00121 }
00122 
00132 QString HaskellProjectPart::mainProgram( bool relative ) const
00133 {
00134     QString progName;
00135     QDomDocument &dom = *projectDom();
00136     QString directoryRadioString = DomUtil::readEntry( dom,
00137                                         "/kdevhaskellproject/run/directoryradio" );
00138     QString mainProgram = DomUtil::readEntry( dom,
00139                                         "/kdevhaskellproject/run/mainprogram" );
00140 
00141     if( mainProgram.isEmpty() ) {
00142         QFileInfo fileInfo( mainSource() );
00143         progName = buildDirectory() + "/" + fileInfo.baseName();
00144         if( relative ) {
00145             return fileInfo.baseName();
00146         }
00147         else {
00148             return buildDirectory() + "/" + fileInfo.baseName();
00149         }
00150     }
00151     else {
00152         if( directoryRadioString == "custom" ) {
00153             if( relative ) {
00154                 return( mainProgram );
00155             }
00156             else {
00157                 QString customDir = DomUtil::readEntry( dom,
00158                                         "/kdevhaskellproject/run/customdirectory" );
00159                 return( customDir + '/' + mainProgram );
00160             }
00161         }
00162         else if( directoryRadioString == "build" ) {
00163             if( relative ) {
00164                 return( mainProgram );
00165             }
00166         }
00167     }
00168     return QString::null;      
00169 }
00170 
00171 QString HaskellProjectPart::runDirectory() const
00172 {
00173     QDomDocument &dom = *projectDom();
00174 
00175     QString directoryRadioString = DomUtil::readEntry(dom, "/kdevhaskellproject/run/directoryradio");
00176     QString DomMainProgram = DomUtil::readEntry(dom, "/kdevhaskellproject/run/mainprogram");
00177 
00178     if ( directoryRadioString == "build" )
00179         return buildDirectory();
00180 
00181     if ( directoryRadioString == "custom" )
00182         return DomUtil::readEntry(dom, "/kdevhaskellproject/run/customdirectory");
00183 
00184     int pos = DomMainProgram.findRev('/');
00185     if (pos != -1)
00186         return buildDirectory() + "/" + DomMainProgram.left(pos);
00187 
00188     return buildDirectory() + "/" + DomMainProgram;
00189 }
00190 
00192 QString HaskellProjectPart::runArguments() const
00193 {
00194     return DomUtil::readEntry(*projectDom(), "/kdevhaskellproject/run/programargs");
00195 }
00196 
00197 QString HaskellProjectPart::activeDirectory() const
00198 {
00199     QFileInfo fi(mainSource());
00200             // @todo shouldn't that be false = relative path?
00201     return fi.dirPath(true).replace(QRegExp(projectDirectory()),"");
00202 }
00203 
00204 QString HaskellProjectPart::buildDirectory() const
00205 {
00206     QFileInfo fi(mainSource());
00207     return fi.dirPath(true);
00208 }
00209 
00210 QStringList HaskellProjectPart::allFiles() const
00211 {
00212     return _sourceFiles;
00213 }
00214 
00215 void HaskellProjectPart::addFiles(const QStringList& /*fileList*/)
00216 {
00217 }
00218 
00219 
00220 void HaskellProjectPart::addFile(const QString& /*fileName*/)
00221 {
00222 }
00223 
00224 void HaskellProjectPart::removeFiles(const QStringList& /*fileList*/)
00225 {
00226 }
00227 
00228 void HaskellProjectPart::removeFile(const QString& /*fileName*/)
00229 {
00230 }
00231 
00232 
00233 /*QString HaskellProjectPart::mainProgram()
00234 {
00235     QDomDocument &dom = *projectDom();
00236     QString configMainProg = DomUtil::readEntry(dom, "/kdevhaskellproject/run/mainprogram", "");
00237     if (configMainProg.isEmpty())
00238     {
00239         QFileInfo fi(mainSource());
00240         return buildDirectory() + "/" + fi.baseName();
00241     }
00242     else
00243         return QDir::cleanDirPath(projectDirectory() + "/" + configMainProg);
00244 }*/
00245 
00246 QString HaskellProjectPart::mainSource() const
00247 {
00248     return projectDirectory() + "/" + _mainSource;
00249 }
00250 
00251 void HaskellProjectPart::setMainSource(QString fullPath)
00252 {
00253     _mainSource = fullPath.replace(QRegExp(QString(projectDirectory() + QString("/"))),"");
00254 }
00255 
00256 
00257 
00258 void HaskellProjectPart::listOfFiles(QStringList &result, QString path)
00259 {
00260     QDir d(path);
00261     if (!d.exists())
00262         return;
00263 
00264     QFileInfoList *entries = const_cast<QFileInfoList*>(d.entryInfoList(QDir::Dirs |
00265                                                             QDir::Files | QDir::Hidden));
00266     for (QFileInfo *it = entries->first(); it; it = entries->next()) {
00267         if ((it->isDir()) && (!(it->filePath() == path))) {
00268             listOfFiles(result, it->dirPath());
00269         }
00270         else
00271         {
00272             result << it->filePath();
00273         }
00274     }
00275 }
00276 
00277 QString HaskellProjectPart::createPackageString()
00278 {
00279     // @todo create "-package network -package concurrent" etc.
00280     return "";
00281 }
00282 
00283 QString HaskellProjectPart::createCmdLine( QString srcFile)
00284 {
00285     // @todo test which haskell comp/interpreter is used and build cmdLine accordingly
00286     // at the moment only ghc is supported
00287     QString cmdLine = _compilerExec + " " + createPackageString() + " " + srcFile + " "
00288                                     + _compilerOpts + " -o " + mainProgram();
00289     QString dirCmd = "cd ";
00290     dirCmd += KProcess::quote(buildDirectory());
00291     dirCmd += " && ";
00292     return dirCmd + cmdLine;
00293 }
00294 
00295 void HaskellProjectPart::slotBuild()
00296 {
00297     partController()->saveAllFiles();
00298 
00299     if (_compilerExec.isEmpty()) {
00300         KMessageBox::sorry(0, i18n("Could not find the Haskell Translator.\nCheck if your settings are correct."));
00301         return;
00302     }
00303 
00304     QString cmdline = createCmdLine( QFileInfo( mainSource() ).fileName() );
00305     makeFrontend()->queueCommand( buildDirectory(), cmdline );
00306 }
00307 
00308 void HaskellProjectPart::slotExecute()
00309 {
00310     partController()->saveAllFiles();
00311 
00312     QDomDocument &dom = *(projectDom());
00313     bool runInTerminal = DomUtil::readBoolEntry(dom, "/kdevhaskellproject/run/terminal", true);
00314 
00315     // Get the run environment variables pairs into the environstr string
00316     // in the form of: "ENV_VARIABLE=ENV_VALUE"
00317     // Note that we quote the variable value due to the possibility of
00318     // embedded spaces
00319     DomUtil::PairList envvars = DomUtil::readPairListEntry( *projectDom(),
00320                                     "/kdevhaskellproject/run/envvars",
00321                                     "envvar", "name", "value");
00322     QString environstr;
00323     DomUtil::PairList::ConstIterator it;
00324     for (it = envvars.begin(); it != envvars.end(); ++it) {
00325         environstr += (*it).first;
00326         environstr += "=";
00327 #if (KDE_VERSION > 305)
00328         environstr += KProcess::quote((*it).second);
00329 #else
00330         environstr += KShellProcess::quote((*it).second);
00331 #endif
00332         environstr += " ";
00333     }
00334 
00335     QString program = mainProgram();
00336     program.prepend( environstr );
00337     program += " " + DomUtil::readEntry(*projectDom(),
00338                                                                     "/kdevhaskellproject/run/programargs" );
00339 
00340     appFrontend()->startAppCommand(buildDirectory(), program, runInTerminal);
00341 }
00342 
00343 void HaskellProjectPart::changedFiles( const QStringList & fileList )
00344 {
00345     KDevProject::changedFiles( fileList );
00346 }
00347 
00348 void HaskellProjectPart::changedFile( const QString & fileName )
00349 {
00350     KDevProject::changedFile( fileName );
00351 }
00352 
00353 void HaskellProjectPart::projectConfigWidget( KDialogBase * dlg )
00354 {
00355     QVBox *vbox;
00356     vbox = dlg->addVBoxPage( i18n("Haskell Options") );
00357     HaskellProjectOptionsDlg *optionsDlg = new HaskellProjectOptionsDlg( this, vbox );
00358     
00359     connect( dlg, SIGNAL( okClicked() ),
00360                      optionsDlg, SLOT( accept() ) );
00361          
00362     connect( dlg, SIGNAL( okClicked() ),
00363                      this, SLOT( loadProjectConfig() ) );
00364 
00365     vbox = dlg->addVBoxPage( i18n( "Run Options" ) );
00366     RunOptionsWidget *w3 = new RunOptionsWidget( *projectDom(),
00367                                     "/kdevhaskellproject", buildDirectory(), vbox );
00368     w3->mainprogram_label->setText( i18n( "Main program (relative to project directory):" ) );
00369     connect( dlg, SIGNAL(okClicked()),
00370              w3, SLOT( accept() ) );
00371 }
00372 
00373 void HaskellProjectPart::loadProjectConfig()
00374 {
00375     QDomDocument &dom = *(projectDom());
00376 
00377     QString config = DomUtil::readEntry(dom,
00378                                 "/kdevhaskellproject/general/useconfiguration",
00379                                 "default");
00380     _mainSource = DomUtil::readEntry(dom,
00381                                 QString("/kdevhaskellproject/configurations/") +
00382                                 config + QString("/mainsource") );
00383     _compilerOpts = DomUtil::readEntry(dom,
00384                                 QString("/kdevhaskellproject/configurations/") +
00385                                 config + QString("/compileroptions"));
00386     _compilerExec = DomUtil::readEntry(dom,
00387                                 QString("/kdevhaskellproject/configurations/") +
00388                                 config + QString("/compilerexec"));
00389 
00390     if ( _compilerExec.isEmpty() ) {
00391         KTrader::OfferList offers = KTrader::self()->query("KDevelop/CompilerOptions", "[X-KDevelop-Language] == 'Haskell'");
00392         QValueList<KService::Ptr>::ConstIterator it;
00393         for (it = offers.begin(); it != offers.end(); ++it) {
00394             if ( (*it)->property( "X-KDevelop-Default" ).toBool() ) {
00395                 _compilerExec = (*it)->exec();
00396                 break;
00397             }
00398         }
00399     }
00400   // no entries found set standard to Glasgow Haskell Compiler
00401 //  if( _compilerExec.isEmpty() ) {
00402 //      _compilerExec = "ghc";
00403 //    _compilerOpts = "--make";
00404 //  }
00405 }
00406 
00407 void HaskellProjectPart::configWidget( KDialogBase * dlg )
00408 {
00409     // @todo create config page for KDevelop Settings
00410     /*QVBox *vbox;
00411     vbox = dlg->addVBoxPage( i18n( "Haskell Options" ) );
00412     HaskellGlobalOptionsDlg *w = new HaskellGlobalOptionsDlg( this, vbox );
00413     connect( dlg, SIGNAL( okClicked() ), w, SLOT( accept() ) );*/
00414 }
00415 
00416 KDevCompilerOptions *HaskellProjectPart::createCompilerOptions(const QString &name)
00417 {
00418     KService::Ptr service = KService::serviceByName( name );
00419     if ( !service ) {
00420         kdDebug() << "Can't find service " << name;
00421         return 0;
00422     }
00423 
00424     KLibFactory *factory = KLibLoader::self()->factory(QFile::encodeName(service->library()));
00425     if (!factory) {
00426         QString errorMessage = KLibLoader::self()->lastErrorMessage();
00427         KMessageBox::error(0, i18n("There was an error loading the module %1.\n"
00428                                    "The diagnostics is:\n%2").arg(service->name()).arg(errorMessage));
00429         exit(1);
00430     }
00431 
00432     QStringList args;
00433     QVariant prop = service->property("X-KDevelop-Args");
00434     if (prop.isValid())
00435         args = QStringList::split(" ", prop.toString());
00436 
00437     QObject *obj = factory->create(this, service->name().latin1(),
00438                                    "KDevCompilerOptions", args);
00439 
00440     if (!obj->inherits("KDevCompilerOptions")) {
00441         kdDebug() << "Component does not inherit KDevCompilerOptions" << endl;
00442         return 0;
00443     }
00444     KDevCompilerOptions *dlg = (KDevCompilerOptions*)obj;
00445 
00446     return dlg;
00447 }
00448 
00449 QString HaskellProjectPart::defaultOptions( const QString compiler )
00450 {
00451     KConfig *config = KGlobal::config();
00452     config->setGroup("Haskell Compiler");
00453 kdDebug(9000) << "*********** " << config->readPathEntry( compiler ) << "::" << endl;
00454     return config->readPathEntry(compiler);
00455 }
00456 
00457 QString HaskellProjectPart::mainProgram()
00458 {
00459     QDomDocument &dom = *projectDom();
00460     QString configMainProg = DomUtil::readEntry(dom, "/kdevhaskellproject/run/mainprogram", "");
00461     if (configMainProg.isEmpty())
00462     {
00463         QFileInfo fi(mainSource());
00464         return buildDirectory() + "/" + fi.baseName();
00465     }
00466     else
00467         return QDir::cleanDirPath(projectDirectory() + "/" + configMainProg);
00468 }
00469 
00470 
00474 QStringList HaskellProjectPart::distFiles() const
00475 {
00476     QStringList sourceList = allFiles();
00477     // Scan current source directory for any .pro files.
00478     QString projectDir = projectDirectory();
00479     QDir dir(projectDir);
00480     QStringList files = dir.entryList( "*README*");
00481     return sourceList + files;
00482 }
00483 
00484 #include "haskellproject_part.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:40 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003