00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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
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& )
00216 {
00217 }
00218
00219
00220 void HaskellProjectPart::addFile(const QString& )
00221 {
00222 }
00223
00224 void HaskellProjectPart::removeFiles(const QStringList& )
00225 {
00226 }
00227
00228 void HaskellProjectPart::removeFile(const QString& )
00229 {
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
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
00280 return "";
00281 }
00282
00283 QString HaskellProjectPart::createCmdLine( QString srcFile)
00284 {
00285
00286
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
00316
00317
00318
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
00401
00402
00403
00404
00405 }
00406
00407 void HaskellProjectPart::configWidget( KDialogBase * dlg )
00408 {
00409
00410
00411
00412
00413
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
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"