File indexing completed on 2024-04-21 04:34:28
0001 /* 0002 * This file is part of KDevelop project 0003 * Copyright 2016 Patrick José Pereira <patrickelectric@gmail.com> 0004 * Based onde the work of: 0005 * Hamish Rodda <rodda@kde.org> 0006 * 0007 * This program is free software; you can redistribute it and/or modify 0008 * it under the terms of the GNU Library General Public License as 0009 * published by the Free Software Foundation; either version 2 of the 0010 * License, or (at your option) any later version. 0011 * 0012 * This program is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public 0018 * License along with this program; if not, write to the 0019 * Free Software Foundation, Inc., 0020 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include "executeplugin.h" 0024 0025 #include <QDebug> 0026 0027 #include <KConfigGroup> 0028 #include <KJob> 0029 #include <KLocalizedString> 0030 #include <KMessageBox> 0031 #include <KParts/MainWindow> 0032 #include <KPluginFactory> 0033 #include <KShell> 0034 0035 #include <interfaces/icore.h> 0036 #include <interfaces/isession.h> 0037 #include <interfaces/iruncontroller.h> 0038 #include <interfaces/ilaunchconfiguration.h> 0039 #include <interfaces/iprojectcontroller.h> 0040 #include <interfaces/iuicontroller.h> 0041 0042 #include "debug.h" 0043 #include "toolkit.h" 0044 #include "embeddedlauncher.h" 0045 #include <project/projectmodel.h> 0046 #include <project/builderjob.h> 0047 #include <util/kdevstringhandler.h> 0048 0049 QString ExecutePlugin::_nativeAppConfigTypeId = QStringLiteral("Embedded Application"); 0050 QString ExecutePlugin::workingDirEntry = QStringLiteral("Working Directory"); 0051 QString ExecutePlugin::executableEntry = QStringLiteral("Executable"); 0052 QString ExecutePlugin::argumentsEntry = QStringLiteral("Arguments"); 0053 QString ExecutePlugin::isExecutableEntry = QStringLiteral("isExecutable"); 0054 QString ExecutePlugin::environmentProfileEntry = QStringLiteral("EnvironmentGroup"); 0055 QString ExecutePlugin::useTerminalEntry = QStringLiteral("Use External Terminal"); 0056 QString ExecutePlugin::commandEntry = QStringLiteral("Command"); 0057 QString ExecutePlugin::boardEntry = QStringLiteral("Board Index"); 0058 QString ExecutePlugin::mcuEntry = QStringLiteral("mcu Index"); 0059 QString ExecutePlugin::userIdToRunEntry = QStringLiteral("User Id to Run"); 0060 QString ExecutePlugin::dependencyActionEntry = QStringLiteral("Dependency Action"); 0061 QString ExecutePlugin::projectTargetEntry = QStringLiteral("Project Target"); 0062 QString ExecutePlugin::arduinoEntry = QStringLiteral("Arduino Entry"); 0063 QString ExecutePlugin::launcherIndexEntry = QStringLiteral("Embedded Launcher Index"); 0064 QString ExecutePlugin::openocdArgEntry = QStringLiteral("Openocd Arg Entry"); 0065 QString ExecutePlugin::openocdWorkEntry = QStringLiteral("Openocd Work Entry"); 0066 QString ExecutePlugin::openocdCommEntry = QStringLiteral("Openocd Command Entry"); 0067 0068 using namespace KDevelop; 0069 0070 Q_LOGGING_CATEGORY(EpMsg, "Kdev.embedded.ep.msg") 0071 K_PLUGIN_FACTORY_WITH_JSON(KDevExecuteFactory, "kdevembedded-launcher.json", registerPlugin<ExecutePlugin>();) 0072 0073 ExecutePlugin::ExecutePlugin(QObject *parent, const QVariantList&) 0074 : KDevelop::IPlugin(QStringLiteral("kdevembedded-launcher"), parent) 0075 { 0076 m_configType = new NativeAppConfigType(); 0077 m_configType->addLauncher(new EmbeddedLauncher()); 0078 qCDebug(EpMsg) << "adding native app launch config"; 0079 core()->runController()->addConfigurationType(m_configType); 0080 } 0081 0082 ExecutePlugin::~ExecutePlugin() 0083 { 0084 delete m_configType; 0085 } 0086 0087 void ExecutePlugin::unload() 0088 { 0089 core()->runController()->removeConfigurationType(m_configType); 0090 delete m_configType; 0091 m_configType = nullptr; 0092 } 0093 0094 QStringList ExecutePlugin::arguments(KDevelop::ILaunchConfiguration* cfg, QString& err_) const 0095 { 0096 qCDebug(EpMsg) << "ExecutePlugin::arguments"; 0097 qCDebug(EpMsg) << "name" << cfg->name(); 0098 qCDebug(EpMsg) << "entryMap" << cfg->config().entryMap(); 0099 qCDebug(EpMsg) << "groupList" << cfg->config().groupList(); 0100 qCDebug(EpMsg) << "keyList" << cfg->config().keyList(); 0101 0102 if (!cfg) 0103 { 0104 qCDebug(EpMsg) << "ExecutePlugin::arguments" << "!cfg"; 0105 return QStringList(); 0106 } 0107 0108 KShell::Errors err; 0109 uint launcherIndex = cfg->config().readEntry(ExecutePlugin::launcherIndexEntry, 0); 0110 0111 QStringList args; 0112 switch (launcherIndex) 0113 { 0114 case index::arduino: 0115 args = KShell::splitArgs(cfg->config().readEntry(ExecutePlugin::argumentsEntry, ""), KShell::TildeExpand | KShell::AbortOnMeta, &err); 0116 break; 0117 0118 case index::openocd: 0119 args = KShell::splitArgs(cfg->config().readEntry(ExecutePlugin::openocdArgEntry, ""), KShell::TildeExpand | KShell::AbortOnMeta, &err); 0120 break; 0121 } 0122 0123 if (err != KShell::NoError) 0124 { 0125 0126 if (err == KShell::BadQuoting) 0127 { 0128 err_ = i18n("There is a quoting error in the arguments for " 0129 "the launch configuration '%1'. Aborting start.", cfg->name()); 0130 } 0131 else 0132 { 0133 err_ = i18n("A shell meta character was included in the " 0134 "arguments for the launch configuration '%1', " 0135 "this is not supported currently. Aborting start.", cfg->name()); 0136 } 0137 args = QStringList(); 0138 qWarning() << "Launch Configuration:" << cfg->name() << "arguments have meta characters"; 0139 } 0140 0141 switch (launcherIndex) 0142 { 0143 case index::arduino: 0144 { 0145 QStringList arduinoConfig = cfg->config().readEntry(ExecutePlugin::arduinoEntry, QStringList()); 0146 0147 for (QStringList::iterator it = args.begin(); it != args.end(); ++it) 0148 { 0149 qCDebug(EpMsg) << *it; 0150 if (!arduinoConfig.empty()) 0151 { 0152 it->replace(QLatin1String("%mcu"), KShell::quoteArg(arduinoConfig[1])); 0153 it->replace(QLatin1String("%baud"), KShell::quoteArg(arduinoConfig[2])); 0154 it->replace(QLatin1String("%interface"), KShell::quoteArg(arduinoConfig[3])); 0155 it->replace(QLatin1String("%hex"), KShell::quoteArg(arduinoConfig[4])); 0156 it->replace(QLatin1String("%avrdudeconf"), KShell::quoteArg(arduinoConfig[5])); 0157 } 0158 } 0159 } 0160 0161 case index::openocd: 0162 { 0163 QString binary = cfg->config().readEntry(ExecutePlugin::executableEntry, QString()); 0164 0165 for (QStringList::iterator it = args.begin(); it != args.end(); ++it) 0166 { 0167 qCDebug(EpMsg) << *it; 0168 if (!binary.isEmpty()) 0169 { 0170 it->replace(QLatin1String("%hex"), binary); 0171 } 0172 } 0173 } 0174 0175 } 0176 0177 qCDebug(EpMsg) << "ExecutePlugin::arguments" << args; 0178 return args; 0179 } 0180 0181 0182 KJob* ExecutePlugin::dependencyJob(KDevelop::ILaunchConfiguration* cfg) const 0183 { 0184 Q_UNUSED(cfg) 0185 return nullptr; 0186 } 0187 0188 0189 QString ExecutePlugin::environmentProfileName(KDevelop::ILaunchConfiguration* cfg) const 0190 { 0191 if (!cfg) 0192 { 0193 return QString(); 0194 } 0195 0196 return cfg->config().readEntry(ExecutePlugin::environmentProfileEntry, ""); 0197 } 0198 0199 0200 QUrl ExecutePlugin::executable(KDevelop::ILaunchConfiguration* cfg, QString& err) const 0201 { 0202 Q_UNUSED(err) 0203 if (!cfg) 0204 { 0205 qCDebug(EpMsg) << "ExecutePlugin::executable" << "!cfg"; 0206 return QUrl(); 0207 } 0208 0209 QString exe; 0210 uint launcherIndex = cfg->config().readEntry(ExecutePlugin::launcherIndexEntry, 0); 0211 qCDebug(EpMsg) << "ExecutePlugin::executable" << "launcherIndex" << launcherIndex; 0212 switch (launcherIndex) 0213 { 0214 case index::arduino: 0215 exe = cfg->config().readEntry(ExecutePlugin::commandEntry, QString()); 0216 break; 0217 case index::openocd: 0218 exe = cfg->config().readEntry(ExecutePlugin::openocdCommEntry, QString()); 0219 break; 0220 } 0221 qCDebug(EpMsg) << "ExecutePlugin::executable" << "exe" << exe; 0222 if (!exe.isEmpty()) 0223 { 0224 if (exe.contains(QLatin1String("%avrdude"))) 0225 { 0226 exe.replace(QLatin1String("%avrdude"), Toolkit::instance().getAvrdudeFile()); 0227 } 0228 0229 if (exe.contains(QLatin1String("%openocd"))) 0230 { 0231 exe.replace(QLatin1String("%openocd"), Toolkit::instance().getOpenocdFile()); 0232 } 0233 0234 } 0235 0236 return QUrl::fromLocalFile(exe); 0237 } 0238 0239 0240 bool ExecutePlugin::useTerminal(KDevelop::ILaunchConfiguration* cfg) const 0241 { 0242 if (!cfg) 0243 { 0244 return false; 0245 } 0246 0247 return cfg->config().readEntry(ExecutePlugin::useTerminalEntry, false); 0248 } 0249 0250 0251 QString ExecutePlugin::terminal(KDevelop::ILaunchConfiguration* cfg) const 0252 { 0253 if (!cfg) 0254 { 0255 return QString(); 0256 } 0257 0258 return cfg->config().readEntry(ExecutePlugin::commandEntry, QString()); 0259 } 0260 0261 0262 QUrl ExecutePlugin::workingDirectory(KDevelop::ILaunchConfiguration* cfg) const 0263 { 0264 if (!cfg) 0265 { 0266 return QUrl(); 0267 } 0268 0269 uint launcherIndex = cfg->config().readEntry(ExecutePlugin::launcherIndexEntry, 0); 0270 0271 switch (launcherIndex) 0272 { 0273 case index::arduino: 0274 return cfg->config().readEntry(ExecutePlugin::openocdWorkEntry, QUrl()); 0275 break; 0276 0277 case index::openocd: 0278 return cfg->config().readEntry(ExecutePlugin::workingDirEntry, QUrl()); 0279 break; 0280 } 0281 0282 return QUrl(); 0283 } 0284 0285 0286 QString ExecutePlugin::nativeAppConfigTypeId() const 0287 { 0288 return _nativeAppConfigTypeId; 0289 } 0290 0291 0292 #include "executeplugin.moc"