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 * Copyright 2009 Andreas Pakulat <apaku@gmx.de> 0005 * 0006 * This program is free software; you can redistribute it and/or modify 0007 * it under the terms of the GNU Library General Public License as 0008 * published by the Free Software Foundation; either version 2 of the 0009 * License, or (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public 0017 * License along with this program; if not, write to the 0018 * Free Software Foundation, Inc., 0019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "launcherjob.h" 0023 #include "executeplugin.h" 0024 #include "toolkit.h" 0025 0026 #include <QDebug> 0027 #include <QFileInfo> 0028 #include <QMessageBox> 0029 0030 #include <KLocalizedString> 0031 #include <KShell> 0032 #include <KSharedConfig> 0033 #include <KConfigGroup> 0034 0035 #include <interfaces/ilaunchconfiguration.h> 0036 #include <interfaces/iruncontroller.h> 0037 #include <outputview/outputmodel.h> 0038 #include <util/environmentprofilelist.h> 0039 0040 #include <interfaces/icore.h> 0041 #include <interfaces/isession.h> 0042 #include <interfaces/iplugincontroller.h> 0043 #include <project/projectmodel.h> 0044 0045 #include <execute/iexecuteplugin.h> 0046 0047 #include "debug.h" 0048 0049 using namespace KDevelop; 0050 0051 Q_LOGGING_CATEGORY(LaMsg, "Kdev.embedded.la.msg") 0052 0053 LauncherJob::LauncherJob(QObject* parent, KDevelop::ILaunchConfiguration* cfg) 0054 : KDevelop::OutputExecuteJob(parent) 0055 , m_cfgname(cfg->name()) 0056 { 0057 qCDebug(LaMsg) << "LauncherJob::LauncherJob"; 0058 qCDebug(LaMsg) << "name" << cfg->name(); 0059 qCDebug(LaMsg) << "entryMap" << cfg->config().entryMap(); 0060 qCDebug(LaMsg) << "groupList" << cfg->config().groupList(); 0061 qCDebug(LaMsg) << "keyList" << cfg->config().keyList(); 0062 0063 setCapabilities(Killable); 0064 0065 IExecutePlugin* iface = KDevelop::ICore::self()->pluginController()->pluginForExtension(QStringLiteral("org.kdevelop.IExecutePlugin"), QStringLiteral("kdevembedded-launcher"))->extension<IExecutePlugin>(); 0066 Q_ASSERT(iface); 0067 0068 KDevelop::EnvironmentProfileList l(KSharedConfig::openConfig()); 0069 QString envProfileName = iface->environmentProfileName(cfg); 0070 qCDebug(LaMsg) << "LauncherJob::LauncherJob envProfileName" << envProfileName; 0071 0072 QString err; 0073 QUrl executable = iface->executable(cfg, err); 0074 qCDebug(LaMsg) << "LauncherJob::LauncherJob executable" << executable; 0075 0076 if (!err.isEmpty()) 0077 { 0078 setError(-1); 0079 setErrorText(err); 0080 return; 0081 } 0082 0083 if (envProfileName.isEmpty()) 0084 { 0085 qWarning() << "Launch Configuration:" << cfg->name() << "no environment profile specified, looks like a broken " 0086 "configuration, please check run configuration" << cfg->name() 0087 << "Using default environment profile."; 0088 envProfileName = l.defaultProfileName(); 0089 } 0090 setEnvironmentProfile(envProfileName); 0091 0092 QStringList arguments = iface->arguments(cfg, err); 0093 qCDebug(LaMsg) << "LauncherJob::LauncherJob arguments" << arguments; 0094 if (!err.isEmpty()) 0095 { 0096 setError(-2); 0097 setErrorText(err); 0098 } 0099 0100 if (error() != 0) 0101 { 0102 qWarning() << "Launch Configuration:" << cfg->name() << "oops, problem" << errorText(); 0103 return; 0104 } 0105 0106 setStandardToolView(KDevelop::IOutputView::RunView); 0107 setBehaviours(KDevelop::IOutputView::AllowUserClose | KDevelop::IOutputView::AutoScroll); 0108 setFilteringStrategy(OutputModel::NativeAppErrorFilter); 0109 setProperties(DisplayStdout | DisplayStderr); 0110 0111 // Now setup the process parameters 0112 0113 QUrl wc = iface->workingDirectory(cfg); 0114 if (!wc.isValid() || wc.isEmpty()) 0115 { 0116 wc = QUrl::fromLocalFile(QFileInfo(executable.toLocalFile()).absolutePath()); 0117 } 0118 setWorkingDirectory(wc); 0119 0120 qCDebug(EpMsg) << "setting app:" << executable << arguments; 0121 0122 // Add terminal support in the future 0123 /* 0124 if (iface->useTerminal(cfg)) 0125 { 0126 QStringList args = KShell::splitArgs(iface->terminal(cfg)); 0127 for (QStringList::iterator it = args.begin(); it != args.end(); ++it) 0128 { 0129 if (*it == QLatin1String("%exe")) 0130 { 0131 *it = KShell::quoteArg(executable.toLocalFile()); 0132 } 0133 else if (*it == QLatin1String("%workdir")) 0134 { 0135 *it = KShell::quoteArg(wc.toLocalFile()); 0136 } 0137 } 0138 args.append(arguments); 0139 *this << args; 0140 } 0141 */ 0142 *this << executable.toLocalFile(); 0143 *this << arguments; 0144 0145 setJobName(cfg->name()); 0146 } 0147 0148 LauncherJob* findNativeJob(KJob* j) 0149 { 0150 LauncherJob* job = qobject_cast<LauncherJob*>(j); 0151 if (!job) 0152 { 0153 const QList<LauncherJob*> jobs = j->findChildren<LauncherJob*>(); 0154 if (!jobs.isEmpty()) 0155 job = jobs.first(); 0156 } 0157 return job; 0158 } 0159 0160 void LauncherJob::start() 0161 { 0162 // We kill any execution of the configuration 0163 foreach (KJob* j, ICore::self()->runController()->currentJobs()) 0164 { 0165 LauncherJob* job = findNativeJob(j); 0166 if (job && job != this && job->m_cfgname == m_cfgname) 0167 { 0168 QMessageBox::StandardButton button = QMessageBox::question(nullptr, i18n("Job already running"), i18n("'%1' is already being executed. Should we kill the previous instance?", m_cfgname)); 0169 if (button != QMessageBox::No) 0170 j->kill(); 0171 } 0172 } 0173 0174 OutputExecuteJob::start(); 0175 } 0176 0177 void LauncherJob::output(const QStringList& l) 0178 { 0179 if (KDevelop::OutputModel* m = model()) 0180 { 0181 m->appendLines(l); 0182 } 0183 } 0184 0185 KDevelop::OutputModel* LauncherJob::model() 0186 { 0187 return dynamic_cast<KDevelop::OutputModel*>(KDevelop::OutputJob::model()); 0188 }