diff options
Diffstat (limited to 'buildtools/pascal/pascalproject_part.cpp')
-rw-r--r-- | buildtools/pascal/pascalproject_part.cpp | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/buildtools/pascal/pascalproject_part.cpp b/buildtools/pascal/pascalproject_part.cpp new file mode 100644 index 00000000..3fe09420 --- /dev/null +++ b/buildtools/pascal/pascalproject_part.cpp @@ -0,0 +1,493 @@ +/*************************************************************************** + * Copyright (C) 2003 Alexander Dymo * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include "pascalproject_part.h" + +#include <qdom.h> +#include <qfileinfo.h> +#include <qdir.h> +#include <qvaluestack.h> +#include <qregexp.h> +#include <qvbox.h> +#include <qlabel.h> + +#include <kiconloader.h> +#include <klocale.h> +#include <kaction.h> +#include <kdevgenericfactory.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <kmessagebox.h> +#include <klibloader.h> +#include <kservice.h> +#include <kconfig.h> +#include <kdeversion.h> +#include <kprocess.h> + +#include "domutil.h" +#include "kdevcore.h" +#include "kdevmainwindow.h" +#include "kdevmakefrontend.h" +#include "kdevappfrontend.h" +#include "kdevpartcontroller.h" +#include "kdevlanguagesupport.h" +#include "kdevcompileroptions.h" +#include "runoptionswidget.h" +#include "envvartools.h" + +#include "pascalproject_widget.h" +#include "pascalprojectoptionsdlg.h" +#include "pascalglobaloptionsdlg.h" + +#include <kdevplugininfo.h> + +typedef KDevGenericFactory<PascalProjectPart> PascalProjectFactory; +static const KDevPluginInfo data("kdevpascalproject"); +K_EXPORT_COMPONENT_FACTORY( libkdevpascalproject, PascalProjectFactory( data ) ) + +PascalProjectPart::PascalProjectPart(QObject *parent, const char *name, const QStringList& ) + :KDevBuildTool(&data, parent, name ? name : "PascalProjectPart" ) +{ + setInstance(PascalProjectFactory::instance()); + setXMLFile("kdevpascalproject.rc"); + + KAction *action; + action = new KAction( i18n("&Build Project"), "make_kdevelop", Key_F8, + this, SLOT(slotBuild()), + actionCollection(), "build_build" ); + action->setToolTip(i18n("Build project")); + action->setWhatsThis(i18n("<b>Build project</b><p>Runs the compiler on a main source file of the project. " + "The compiler and the main source file can be set in project settings, <b>Pascal Compiler</b> tab.")); + action = new KAction( i18n("Execute Program"), "exec", 0, + this, SLOT(slotExecute()), + actionCollection(), "build_execute" ); + action->setToolTip(i18n("Execute program")); + action->setWhatsThis(i18n("<b>Execute program</b><p>Executes the main program specified in project settings, <b>Run options</b> tab. " + "If nothing is set, the binary file with the same name as the main source file name is executed.")); + + connect( core(), SIGNAL(projectConfigWidget(KDialogBase*)), + this, SLOT(projectConfigWidget(KDialogBase*)) ); + + connect( core(), SIGNAL(configWidget(KDialogBase*)), + this, SLOT(configWidget(KDialogBase*)) ); + +// m_widget = new PascalProjectWidget(this); + +// QWhatsThis::add(m_widget, i18n("WHAT DOES THIS PART DO?")); + + // now you decide what should happen to the widget. Take a look at kdevcore.h + // or at other plugins how to embed it. + + // if you want to embed your widget as an outputview, simply uncomment + // the following line. + + // mainWindow()->embedOutputView( m_widget, "name that should appear", "enter a tooltip" ); + +} + +PascalProjectPart::~PascalProjectPart() +{ +// delete m_widget; +} + +/** + * @todo This should really be merged with FileTreeWidget::matchesHidePattern() + * and put in its own class. Currently this is repeated in scriptprojectpart.cpp, pascalproject_part.cpp, adaproject_part.cpp + */ +static bool matchesPattern(const QString &fileName, const QStringList &patternList) +{ + QStringList::ConstIterator it; + for (it = patternList.begin(); it != patternList.end(); ++it) { + QRegExp re(*it, true, true); + if (re.search(fileName) == 0 && re.matchedLength() == (int)fileName.length()) + return true; + } + + return false; +} + +void PascalProjectPart::openProject(const QString &dirName, const QString &projectName) +{ + m_buildDir = dirName; + m_projectDir = dirName; + m_projectName = projectName; + + QDomDocument &dom = *projectDom(); + // Set the default directory radio to "executable" + if (DomUtil::readEntry(dom, "/kdevpascalproject/run/directoryradio") == "" ) { + DomUtil::writeEntry(dom, "/kdevpascalproject/run/directoryradio", "executable"); + } + + loadProjectConfig(); + + // Put all files from all subdirectories into file list + QValueStack<QString> s; + int prefixlen = m_projectDir.length()+1; + s.push(m_projectDir); + + QStringList includepatternList; + if ( languageSupport() ) + { + KMimeType::List list = languageSupport()->mimeTypes(); + KMimeType::List::Iterator it = list.begin(); + while( it != list.end() ){ + includepatternList += (*it)->patterns(); + ++it; + } + } + QString excludepatterns = "*~"; + QStringList excludepatternList = QStringList::split(",", excludepatterns); + + QDir dir; + do { + dir.setPath(s.pop()); + kdDebug(9033) << "Examining: " << dir.path() << endl; + const QFileInfoList *dirEntries = dir.entryInfoList(); + QPtrListIterator<QFileInfo> it(*dirEntries); + for (; it.current(); ++it) { + QString fileName = it.current()->fileName(); + if (fileName == "." || fileName == "..") + continue; + QString path = it.current()->absFilePath(); + if (it.current()->isDir()) { + kdDebug(9033) << "Pushing: " << path << endl; + s.push(path); + } + else { + if (matchesPattern(path, includepatternList) + && !matchesPattern(path, excludepatternList)) { + kdDebug(9033) << "Adding: " << path << endl; + m_sourceFiles.append(path.mid(prefixlen)); + } else { + kdDebug(9033) << "Ignoring: " << path << endl; + } + } + } + } while (!s.isEmpty()); + + KDevProject::openProject( dirName, projectName ); +} + +void PascalProjectPart::closeProject() +{ +} + +/** Retuns a PairList with the run environment variables */ +DomUtil::PairList PascalProjectPart::runEnvironmentVars() const +{ + return DomUtil::readPairListEntry(*projectDom(), "/kdevpascalproject/run/envvars", "envvar", "name", "value"); +} + + +/** Retuns the currently selected run directory + * The returned string can be: + * if run/directoryradio == executable + * The directory where the executable is + * if run/directoryradio == build + * The directory where the executable is relative to build directory + * if run/directoryradio == custom + * The custom directory absolute path + */ +QString PascalProjectPart::runDirectory() const +{ + QString cwd = defaultRunDirectory("kdevpascalproject"); + if (cwd.isEmpty()) + cwd = buildDirectory(); + return cwd; +} + + +/** Retuns the currently selected main program + * The returned string can be: + * if run/directoryradio == executable + * The executable name + * if run/directoryradio == build + * The path to executable relative to build directory + * if run/directoryradio == custom or relative == false + * The absolute path to executable + */ +QString PascalProjectPart::mainProgram() const +{ + QDomDocument * dom = projectDom(); + + if ( !dom ) return QString(); + + QString DomMainProgram = DomUtil::readEntry( *dom, "/kdevpascalproject/run/mainprogram"); + + if ( DomMainProgram.isEmpty() ) return QString(); + + if ( DomMainProgram.startsWith("/") ) // assume absolute path + { + return DomMainProgram; + } + else // assume project relative path + { + return projectDirectory() + "/" + DomMainProgram; + } + + return QString(); +} + +/** Retuns a QString with the debug command line arguments */ +QString PascalProjectPart::debugArguments() const +{ + return DomUtil::readEntry(*projectDom(), "/kdevpascalproject/run/globaldebugarguments"); +} + + +/** Retuns a QString with the run command line arguments */ +QString PascalProjectPart::runArguments() const +{ + return DomUtil::readEntry(*projectDom(), "/kdevpascalproject/run/programargs"); +} + +QString PascalProjectPart::mainSource() const +{ + return projectDirectory() + "/" + m_mainSource; +} + +void PascalProjectPart::setMainSource(QString fullPath) +{ + QString olddir = activeDirectory(); + m_mainSource = fullPath.replace(QRegExp(QString(projectDirectory() + QString("/"))),""); + emit activeDirectoryChanged( olddir, activeDirectory() ); +} + +QString PascalProjectPart::projectDirectory() const +{ + return m_projectDir; +} + +QString PascalProjectPart::projectName() const +{ + return m_projectName; +} + +QString PascalProjectPart::activeDirectory() const +{ + QFileInfo fi(mainSource()); + return fi.dirPath(true).replace(QRegExp(projectDirectory()),""); +} + +QString PascalProjectPart::buildDirectory() const +{ + QFileInfo fi(mainSource()); + return fi.dirPath(true); +} + +void PascalProjectPart::listOfFiles(QStringList &result, QString path) const +{ + QDir d(path); + if (!d.exists()) + return; + QFileInfoList *entries = const_cast<QFileInfoList*>(d.entryInfoList(QDir::Dirs | QDir::Files | QDir::Hidden)); + for (QFileInfo *it = entries->first(); it; it = entries->next()) + { + if ((it->isDir()) && (it->filePath() != path)) + { +// qWarning("entering dir %s", it->dirPath().latin1()); + listOfFiles(result, it->dirPath()); + } + else + { +// qWarning("adding to result: %s", it->filePath().latin1()); + result << it->filePath(); + } + } +} + +QStringList PascalProjectPart::allFiles() const +{ +// QStringList files; + +// listOfFiles(files, projectDirectory()); + +// return files; + return m_sourceFiles; +} + +void PascalProjectPart::addFile(const QString& /*fileName*/) +{ +} + +void PascalProjectPart::addFiles(const QStringList& /*fileList*/) +{ +} + +void PascalProjectPart::removeFile(const QString& /*fileName*/) +{ +} + +void PascalProjectPart::removeFiles(const QStringList& /*fileList*/) +{ +} + +void PascalProjectPart::slotBuild() +{ + if (partController()->saveAllFiles()==false) + return; //user cancelled + + QString cmdline = m_compilerExec + " " + m_compilerOpts + " "; + + if (cmdline.isEmpty()) + { + KMessageBox::sorry(0, i18n("Could not find pascal compiler.\nCheck if your compiler settings are correct.")); + return; + } + + QFileInfo fi(mainSource()); + cmdline += fi.fileName(); + + QString dircmd = "cd "; + dircmd += KProcess::quote(buildDirectory()); + dircmd += " && "; + + makeFrontend()->queueCommand(buildDirectory(), dircmd + cmdline); +} + +void PascalProjectPart::slotExecute() +{ + partController()->saveAllFiles(); + + QDomDocument &dom = *(projectDom()); + bool runInTerminal = DomUtil::readBoolEntry(dom, "/kdevpascalproject/run/terminal", true); + + // Get the run environment variables pairs into the environstr string + // in the form of: "ENV_VARIABLE=ENV_VALUE" + // Note that we quote the variable value due to the possibility of + // embedded spaces + DomUtil::PairList envvars = + DomUtil::readPairListEntry(*projectDom(), "/kdevpascalproject/run/envvars", "envvar", "name", "value"); + + QString environstr; + DomUtil::PairList::ConstIterator it; + for (it = envvars.begin(); it != envvars.end(); ++it) { + environstr += (*it).first; + environstr += "="; + environstr += EnvVarTools::quote((*it).second); + environstr += " "; + } + + QString program = mainProgram(); + program.prepend(environstr); + program += " " + DomUtil::readEntry(*projectDom(), "/kdevpascalproject/run/programargs"); + + appFrontend()->startAppCommand(buildDirectory(), program, runInTerminal); +} + +void PascalProjectPart::changedFiles( const QStringList & fileList ) +{ + KDevProject::changedFiles(fileList); +} + +void PascalProjectPart::changedFile( const QString & fileName ) +{ + KDevProject::changedFile(fileName); +} + +void PascalProjectPart::projectConfigWidget( KDialogBase * dlg ) +{ + QVBox *vbox; + vbox = dlg->addVBoxPage(i18n("Pascal Compiler")); + PascalProjectOptionsDlg *w = new PascalProjectOptionsDlg(this, vbox); + connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) ); + connect( dlg, SIGNAL(okClicked()), this, SLOT(loadProjectConfig()) ); + + vbox = dlg->addVBoxPage(i18n("Run Options"), i18n("Run Options"), BarIcon( "make", KIcon::SizeMedium )); + RunOptionsWidget *w3 = new RunOptionsWidget(*projectDom(), "/kdevpascalproject", buildDirectory(), vbox); + connect( dlg, SIGNAL(okClicked()), w3, SLOT(accept()) ); + +} + +void PascalProjectPart::loadProjectConfig( ) +{ + QDomDocument &dom = *(projectDom()); + + QString config = DomUtil::readEntry(dom, "/kdevpascalproject/general/useconfiguration", "default"); + m_mainSource = DomUtil::readEntry(dom, QString("/kdevpascalproject/configurations/") + config + QString("/mainsource") ); + m_compilerOpts = DomUtil::readEntry(dom, QString("/kdevpascalproject/configurations/") + config + QString("/compileroptions")); + m_compilerExec = DomUtil::readEntry(dom, QString("/kdevpascalproject/configurations/") + config + QString("/compilerexec")); + + if (m_compilerExec.isEmpty()) + { + KTrader::OfferList offers = KTrader::self()->query("KDevelop/CompilerOptions", "[X-KDevelop-Language] == 'Pascal'"); + QValueList<KService::Ptr>::ConstIterator it; + for (it = offers.begin(); it != offers.end(); ++it) { + if ((*it)->property("X-KDevelop-Default").toBool()) { + m_compilerExec = (*it)->exec(); + break; + } + } + } +} + +void PascalProjectPart::configWidget( KDialogBase * dlg ) +{ + QVBox *vbox; + vbox = dlg->addVBoxPage(i18n("Pascal Compiler")); + PascalGlobalOptionsDlg *w = new PascalGlobalOptionsDlg(this, vbox); + connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) ); +} + +KDevCompilerOptions *PascalProjectPart::createCompilerOptions(const QString &name) +{ + KService::Ptr service = KService::serviceByDesktopName(name); + if (!service) { + kdDebug() << "Can't find service " << name; + return 0; + } + + KLibFactory *factory = KLibLoader::self()->factory(QFile::encodeName(service->library())); + if (!factory) { + QString errorMessage = KLibLoader::self()->lastErrorMessage(); + KMessageBox::error(0, i18n("There was an error loading the module %1.\n" + "The diagnostics is:\n%2").arg(service->name()).arg(errorMessage)); + exit(1); + } + + QStringList args; + QVariant prop = service->property("X-KDevelop-Args"); + if (prop.isValid()) + args = QStringList::split(" ", prop.toString()); + + QObject *obj = factory->create(this, service->name().latin1(), + "KDevCompilerOptions", args); + + if (!obj->inherits("KDevCompilerOptions")) { + kdDebug() << "Component does not inherit KDevCompilerOptions" << endl; + return 0; + } + KDevCompilerOptions *dlg = (KDevCompilerOptions*) obj; + + return dlg; +} + +QString PascalProjectPart::defaultOptions( const QString compiler ) const +{ + KConfig *config = KGlobal::config(); + config->setGroup("Pascal Compiler"); + return config->readPathEntry(compiler); +} + +#include "pascalproject_part.moc" + + +/*! + \fn PascalProjectPart::distFiles() const + */ +QStringList PascalProjectPart::distFiles() const +{ + QStringList sourceList = allFiles(); + // Scan current source directory for any .pro files. + QString projectDir = projectDirectory(); + QDir dir(projectDir); + QStringList files = dir.entryList( "Makefile"); + return sourceList + files; +} |