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

0001 /*
0002     SPDX-FileCopyrightText: 2007 Hamish Rodda <rodda@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "executeplugin.h"
0008 
0009 #include <KConfigGroup>
0010 #include <KJob>
0011 #include <KLocalizedString>
0012 #include <KParts/MainWindow>
0013 #include <KPluginFactory>
0014 #include <KShell>
0015 
0016 #include <interfaces/icore.h>
0017 #include <interfaces/iruncontroller.h>
0018 #include <interfaces/ilaunchconfiguration.h>
0019 #include <interfaces/iprojectcontroller.h>
0020 #include <interfaces/iuicontroller.h>
0021 #include <sublime/message.h>
0022 
0023 #include "nativeappconfig.h"
0024 #include "debug.h"
0025 #include <project/projectmodel.h>
0026 #include <project/builderjob.h>
0027 #include <util/kdevstringhandler.h>
0028 
0029 using namespace KDevelop;
0030 
0031 K_PLUGIN_FACTORY_WITH_JSON(KDevExecuteFactory, "kdevexecute.json", registerPlugin<ExecutePlugin>();)
0032 
0033 ExecutePlugin::ExecutePlugin(QObject *parent, const QVariantList&)
0034     : KDevelop::IPlugin(QStringLiteral("kdevexecute"), parent)
0035 {
0036     m_configType = new NativeAppConfigType();
0037     m_configType->addLauncher( new NativeAppLauncher() );
0038     qCDebug(PLUGIN_EXECUTE) << "adding native app launch config";
0039     core()->runController()->addConfigurationType( m_configType );
0040 }
0041 
0042 ExecutePlugin::~ExecutePlugin()
0043 {
0044 }
0045 
0046 void ExecutePlugin::unload()
0047 {
0048     core()->runController()->removeConfigurationType( m_configType );
0049     delete m_configType;
0050     m_configType = nullptr;
0051 }
0052 
0053 QStringList ExecutePlugin::arguments( KDevelop::ILaunchConfiguration* cfg, QString& err_ ) const
0054 {
0055 
0056     if( !cfg )
0057     {
0058         return QStringList();
0059     }
0060 
0061     KShell::Errors err;
0062     QStringList args = KShell::splitArgs( cfg->config().readEntry( ExecutePlugin::argumentsEntry, "" ), KShell::TildeExpand | KShell::AbortOnMeta, &err );
0063     if( err != KShell::NoError )
0064     {
0065 
0066         if( err == KShell::BadQuoting )
0067         {
0068             err_ = i18n("There is a quoting error in the arguments for "
0069             "the launch configuration '%1'. Aborting start.", cfg->name() );
0070         } else
0071         {
0072             err_ = i18n("A shell meta character was included in the "
0073             "arguments for the launch configuration '%1', "
0074             "this is not supported currently. Aborting start.", cfg->name() );
0075         }
0076         args = QStringList();
0077         qCWarning(PLUGIN_EXECUTE) << "Launch Configuration:" << cfg->name() << "arguments have meta characters";
0078     }
0079     return args;
0080 }
0081 
0082 
0083 KJob* ExecutePlugin::dependencyJob( KDevelop::ILaunchConfiguration* cfg ) const
0084 {
0085     const QVariantList deps = KDevelop::stringToQVariant( cfg->config().readEntry( dependencyEntry, QString() ) ).toList();
0086     QString depAction = cfg->config().readEntry( dependencyActionEntry, "Nothing" );
0087     if( depAction != QLatin1String("Nothing") && !deps.isEmpty() )
0088     {
0089         KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel();
0090         QList<KDevelop::ProjectBaseItem*> items;
0091         for (const QVariant& dep : deps) {
0092             KDevelop::ProjectBaseItem* item = model->itemFromIndex( model->pathToIndex( dep.toStringList() ) );
0093             if( item )
0094             {
0095                 items << item;
0096             }
0097             else
0098             {
0099                 const QString messageText = i18n("Couldn't resolve the dependency: %1", dep.toString());
0100                 auto* message = new Sublime::Message(messageText, Sublime::Message::Error);
0101                 ICore::self()->uiController()->postMessage(message);
0102             }
0103         }
0104         auto* job = new KDevelop::BuilderJob();
0105         if( depAction == QLatin1String("Build") )
0106         {
0107             job->addItems( KDevelop::BuilderJob::Build, items );
0108         } else if( depAction == QLatin1String("Install") )
0109         {
0110             job->addItems( KDevelop::BuilderJob::Install, items );
0111         }
0112         job->updateJobName();
0113         return job;
0114     }
0115     return nullptr;
0116 }
0117 
0118 
0119 QString ExecutePlugin::environmentProfileName(KDevelop::ILaunchConfiguration* cfg) const
0120 {
0121     if( !cfg )
0122     {
0123         return QString();
0124     }
0125 
0126     return cfg->config().readEntry(ExecutePlugin::environmentProfileEntry, QString());
0127 }
0128 
0129 
0130 QUrl ExecutePlugin::executable( KDevelop::ILaunchConfiguration* cfg, QString& err ) const
0131 {
0132     QUrl executable;
0133     if( !cfg )
0134     {
0135         return executable;
0136     }
0137     KConfigGroup grp = cfg->config();
0138     if( grp.readEntry(ExecutePlugin::isExecutableEntry, false ) )
0139     {
0140         executable = grp.readEntry( ExecutePlugin::executableEntry, QUrl() );
0141     } else
0142     {
0143         QStringList prjitem = grp.readEntry( ExecutePlugin::projectTargetEntry, QStringList() );
0144         KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel();
0145         KDevelop::ProjectBaseItem* item = model->itemFromIndex( model->pathToIndex(prjitem) );
0146         if( item && item->executable() )
0147         {
0148             // TODO: Need an option in the gui to choose between installed and builddir url here, currently cmake only supports builddir url
0149             executable = item->executable()->builtUrl();
0150         }
0151     }
0152     if( executable.isEmpty() )
0153     {
0154         err = i18n("No valid executable specified");
0155         qCWarning(PLUGIN_EXECUTE) << "Launch Configuration:" << cfg->name() << "no valid executable set";
0156     } else
0157     {
0158         KShell::Errors err_;
0159         if( KShell::splitArgs( executable.toLocalFile(), KShell::TildeExpand | KShell::AbortOnMeta, &err_ ).isEmpty() || err_ != KShell::NoError )
0160         {
0161             executable = QUrl();
0162             if( err_ == KShell::BadQuoting )
0163             {
0164                 err = i18n("There is a quoting error in the executable "
0165                 "for the launch configuration '%1'. "
0166                 "Aborting start.", cfg->name() );
0167             } else
0168             {
0169                 err = i18n("A shell meta character was included in the "
0170                 "executable for the launch configuration '%1', "
0171                 "this is not supported currently. Aborting start.", cfg->name() );
0172             }
0173             qCWarning(PLUGIN_EXECUTE) << "Launch Configuration:" << cfg->name() << "executable has meta characters";
0174         }
0175     }
0176     return executable;
0177 }
0178 
0179 
0180 bool ExecutePlugin::useTerminal( KDevelop::ILaunchConfiguration* cfg ) const
0181 {
0182     if( !cfg )
0183     {
0184         return false;
0185     }
0186 
0187     return cfg->config().readEntry( ExecutePlugin::useTerminalEntry, false );
0188 }
0189 
0190 
0191 QString ExecutePlugin::terminal( KDevelop::ILaunchConfiguration* cfg ) const
0192 {
0193     if( !cfg )
0194     {
0195         return QString();
0196     }
0197 
0198     return cfg->config().readEntry( ExecutePlugin::terminalEntry, QString() );
0199 }
0200 
0201 
0202 QUrl ExecutePlugin::workingDirectory( KDevelop::ILaunchConfiguration* cfg ) const
0203 {
0204     if( !cfg )
0205     {
0206         return QUrl();
0207     }
0208 
0209     return cfg->config().readEntry( ExecutePlugin::workingDirEntry, QUrl() );
0210 }
0211 
0212 
0213 QString ExecutePlugin::nativeAppConfigTypeId() const
0214 {
0215     return NativeAppConfigType::sharedId();
0216 }
0217 
0218 
0219 #include "executeplugin.moc"
0220 #include "moc_executeplugin.cpp"