00001
00002
00003
00004
00005
00006
00007
00008
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
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 }
00091
00092 PascalProjectPart::~PascalProjectPart()
00093 {
00094
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
00121
if (DomUtil::readEntry(dom,
"/kdevpascalproject/run/directoryradio") ==
"" ) {
00122 DomUtil::writeEntry(dom,
"/kdevpascalproject/run/directoryradio",
"executable");
00123 }
00124
00125
loadProjectConfig();
00126
00127
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
00308
listOfFiles(result, it->dirPath());
00309 }
00310
else
00311 {
00312
00313 result << it->filePath();
00314 }
00315 }
00316 }
00317
00318 QStringList PascalProjectPart::allFiles()
const
00319
{
00320
00321
00322
00323
00324
00325
return m_sourceFiles;
00326 }
00327
00328 void PascalProjectPart::addFile(
const QString& )
00329 {
00330 }
00331
00332 void PascalProjectPart::addFiles(
const QStringList& )
00333 {
00334 }
00335
00336 void PascalProjectPart::removeFile(
const QString& )
00337 {
00338 }
00339
00340 void PascalProjectPart::removeFiles(
const QStringList& )
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 +=
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
00374
00375
00376
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
00387
00388
00389
00390
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"