File indexing completed on 2024-04-28 04:38:40

0001 /*
0002     SPDX-FileCopyrightText: 2009 Andreas Pakulat <apaku@gmx.de>
0003     SPDX-FileCopyrightText: 2009 Niko Sams <niko.sams@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "scriptappconfig.h"
0009 
0010 #include <KConfigGroup>
0011 #include <KLineEdit>
0012 #include <KLocalizedString>
0013 #include <KShell>
0014 
0015 #include <QIcon>
0016 #include <QMimeDatabase>
0017 
0018 #include <interfaces/icore.h>
0019 #include <interfaces/ilaunchconfiguration.h>
0020 
0021 #include <project/projectmodel.h>
0022 
0023 #include "scriptappjob.h"
0024 #include <interfaces/iproject.h>
0025 #include <interfaces/idocumentcontroller.h>
0026 
0027 #include "executescriptplugin.h"
0028 #include <util/kdevstringhandler.h>
0029 #include <util/path.h>
0030 #include <debug.h>
0031 
0032 using namespace KDevelop;
0033 
0034 static const QString interpreterForUrl(const QUrl& url) {
0035     auto mimetype = QMimeDatabase().mimeTypeForUrl(url);
0036     static QHash<QString, QString> knownMimetypes;
0037     if ( knownMimetypes.isEmpty() ) {
0038         knownMimetypes[QStringLiteral("text/x-python")] = QStringLiteral("python3");
0039         knownMimetypes[QStringLiteral("application/x-php")] = QStringLiteral("php");
0040         knownMimetypes[QStringLiteral("application/x-ruby")] = QStringLiteral("ruby");
0041         knownMimetypes[QStringLiteral("application/x-shellscript")] = QStringLiteral("bash");
0042         knownMimetypes[QStringLiteral("application/x-perl")] = QStringLiteral("perl -e");
0043     }
0044     const QString& interp = knownMimetypes.value(mimetype.name());
0045     return interp;
0046 }
0047 
0048 QIcon ScriptAppConfigPage::icon() const
0049 {
0050     return QIcon::fromTheme(QStringLiteral("system-run"));
0051 }
0052 
0053 void ScriptAppConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project )
0054 {
0055     QSignalBlocker blocker(this);
0056     if( project )
0057     {
0058         executablePath->setStartDir( project->path().toUrl() );
0059     }
0060 
0061     auto doc = KDevelop::ICore::self()->documentController()->activeDocument();
0062     interpreter->lineEdit()->setText( cfg.readEntry( ExecuteScriptPlugin::interpreterEntry,
0063                                                      doc ? interpreterForUrl(doc->url()) : QString() ) );
0064     executablePath->setUrl( QUrl::fromLocalFile(cfg.readEntry( ExecuteScriptPlugin::executableEntry, QString() )) );
0065     remoteHostCheckbox->setChecked( cfg.readEntry( ExecuteScriptPlugin::executeOnRemoteHostEntry, false ) );
0066     remoteHost->setText( cfg.readEntry( ExecuteScriptPlugin::remoteHostEntry, "" ) );
0067     bool runCurrent = cfg.readEntry( ExecuteScriptPlugin::runCurrentFileEntry, true );
0068     if ( runCurrent ) {
0069         runCurrentFile->setChecked( true );
0070     } else {
0071         runFixedFile->setChecked( true );
0072     }
0073     arguments->setText( cfg.readEntry( ExecuteScriptPlugin::argumentsEntry, "" ) );
0074     workingDirectory->setUrl( cfg.readEntry( ExecuteScriptPlugin::workingDirEntry, QUrl() ) );
0075     environment->setCurrentProfile(cfg.readEntry(ExecuteScriptPlugin::environmentProfileEntry, QString()));
0076     outputFilteringMode->setCurrentIndex( cfg.readEntry( ExecuteScriptPlugin::outputFilteringEntry, 2u ));
0077 }
0078 
0079 ScriptAppConfigPage::ScriptAppConfigPage( QWidget* parent )
0080     : LaunchConfigurationPage( parent )
0081 {
0082     setupUi(this);
0083     interpreter->lineEdit()->setPlaceholderText(i18nc("@info:placeholder", "Type or select an interpreter..."));
0084 
0085     //Set workingdirectory widget to ask for directories rather than files
0086     workingDirectory->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly);
0087 
0088     configureEnvironment->setSelectionWidget(environment);
0089 
0090     //connect signals to changed signal
0091     connect( interpreter->lineEdit(), &QLineEdit::textEdited, this, &ScriptAppConfigPage::changed );
0092     connect( executablePath->lineEdit(), &KLineEdit::textEdited, this, &ScriptAppConfigPage::changed );
0093     connect( executablePath, &KUrlRequester::urlSelected, this, &ScriptAppConfigPage::changed );
0094     connect( arguments, &QLineEdit::textEdited, this, &ScriptAppConfigPage::changed );
0095     connect( workingDirectory, &KUrlRequester::urlSelected, this, &ScriptAppConfigPage::changed );
0096     connect( workingDirectory->lineEdit(), &KLineEdit::textEdited, this, &ScriptAppConfigPage::changed );
0097     connect( environment, &EnvironmentSelectionWidget::currentProfileChanged, this, &ScriptAppConfigPage::changed );
0098 }
0099 
0100 void ScriptAppConfigPage::saveToConfiguration( KConfigGroup cfg, KDevelop::IProject* project ) const
0101 {
0102     Q_UNUSED( project );
0103     cfg.writeEntry( ExecuteScriptPlugin::interpreterEntry, interpreter->lineEdit()->text() );
0104     cfg.writeEntry( ExecuteScriptPlugin::executableEntry, executablePath->url() );
0105     cfg.writeEntry( ExecuteScriptPlugin::executeOnRemoteHostEntry, remoteHostCheckbox->isChecked() );
0106     cfg.writeEntry( ExecuteScriptPlugin::remoteHostEntry, remoteHost->text() );
0107     cfg.writeEntry( ExecuteScriptPlugin::runCurrentFileEntry, runCurrentFile->isChecked() );
0108     cfg.writeEntry( ExecuteScriptPlugin::argumentsEntry, arguments->text() );
0109     cfg.writeEntry( ExecuteScriptPlugin::workingDirEntry, workingDirectory->url() );
0110     cfg.writeEntry( ExecuteScriptPlugin::environmentProfileEntry, environment->currentProfile() );
0111     cfg.writeEntry( ExecuteScriptPlugin::outputFilteringEntry, outputFilteringMode->currentIndex() );
0112 }
0113 
0114 QString ScriptAppConfigPage::title() const
0115 {
0116     return i18nc("@title:tab", "Configure Script Application");
0117 }
0118 
0119 QList< KDevelop::LaunchConfigurationPageFactory* > ScriptAppLauncher::configPages() const
0120 {
0121     return QList<KDevelop::LaunchConfigurationPageFactory*>();
0122 }
0123 
0124 QString ScriptAppLauncher::description() const
0125 {
0126     return i18n("Executes Script Applications");
0127 }
0128 
0129 QString ScriptAppLauncher::id()
0130 {
0131     return QStringLiteral("scriptAppLauncher");
0132 }
0133 
0134 QString ScriptAppLauncher::name() const
0135 {
0136     return i18n("Script Application");
0137 }
0138 
0139 ScriptAppLauncher::ScriptAppLauncher(ExecuteScriptPlugin* plugin)
0140 : m_plugin( plugin )
0141 {
0142 }
0143 
0144 KJob* ScriptAppLauncher::start(const QString& launchMode, KDevelop::ILaunchConfiguration* cfg)
0145 {
0146     Q_ASSERT(cfg);
0147     if( !cfg )
0148     {
0149         return nullptr;
0150     }
0151     if( launchMode == QLatin1String("execute") )
0152     {
0153         return new ScriptAppJob( m_plugin, cfg);
0154     }
0155     qCWarning(PLUGIN_EXECUTESCRIPT) << "Unknown launch mode " << launchMode << "for config:" << cfg->name();
0156     return nullptr;
0157 }
0158 
0159 QStringList ScriptAppLauncher::supportedModes() const
0160 {
0161     return QStringList() << QStringLiteral("execute");
0162 }
0163 
0164 KDevelop::LaunchConfigurationPage* ScriptAppPageFactory::createWidget(QWidget* parent)
0165 {
0166     return new ScriptAppConfigPage( parent );
0167 }
0168 
0169 ScriptAppPageFactory::ScriptAppPageFactory()
0170 {
0171 }
0172 
0173 ScriptAppConfigType::ScriptAppConfigType()
0174 {
0175     factoryList.append( new ScriptAppPageFactory() );
0176 }
0177 
0178 ScriptAppConfigType::~ScriptAppConfigType()
0179 {
0180     qDeleteAll(factoryList);
0181     factoryList.clear();
0182 }
0183 
0184 QString ScriptAppConfigType::name() const
0185 {
0186     return i18n("Script Application");
0187 }
0188 
0189 
0190 QList<KDevelop::LaunchConfigurationPageFactory*> ScriptAppConfigType::configPages() const
0191 {
0192     return factoryList;
0193 }
0194 
0195 QString ScriptAppConfigType::sharedId()
0196 {
0197     return QStringLiteral("Script Application");
0198 }
0199 
0200 QString ScriptAppConfigType::id() const
0201 {
0202     return sharedId();
0203 }
0204 
0205 QIcon ScriptAppConfigType::icon() const
0206 {
0207     return QIcon::fromTheme(QStringLiteral("preferences-plugin-script"));
0208 }
0209 
0210 bool ScriptAppConfigType::canLaunch(const QUrl& file) const
0211 {
0212     return ! interpreterForUrl(file).isEmpty();
0213 }
0214 
0215 bool ScriptAppConfigType::canLaunch(KDevelop::ProjectBaseItem* item) const
0216 {
0217     return ! interpreterForUrl(item->path().toUrl()).isEmpty();
0218 }
0219 
0220 void ScriptAppConfigType::configureLaunchFromItem(KConfigGroup config, KDevelop::ProjectBaseItem* item) const
0221 {
0222     config.writeEntry(ExecuteScriptPlugin::executableEntry, item->path().toUrl());
0223     config.writeEntry(ExecuteScriptPlugin::interpreterEntry, interpreterForUrl(item->path().toUrl()));
0224     config.writeEntry(ExecuteScriptPlugin::outputFilteringEntry, 2u);
0225     config.writeEntry(ExecuteScriptPlugin::runCurrentFileEntry, false);
0226     config.sync();
0227 }
0228 
0229 void ScriptAppConfigType::configureLaunchFromCmdLineArguments(KConfigGroup cfg, const QStringList &args) const
0230 {
0231     QStringList a(args);
0232     cfg.writeEntry( ExecuteScriptPlugin::interpreterEntry, a.takeFirst() );
0233     cfg.writeEntry( ExecuteScriptPlugin::executableEntry, a.takeFirst() );
0234     cfg.writeEntry( ExecuteScriptPlugin::argumentsEntry, KShell::joinArgs(a) );
0235     cfg.writeEntry( ExecuteScriptPlugin::runCurrentFileEntry, false );
0236     cfg.sync();
0237 }
0238 
0239 #include "moc_scriptappconfig.cpp"