File indexing completed on 2024-04-28 04:37:24
0001 /* 0002 SPDX-FileCopyrightText: 2017 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "runtimecontroller.h" 0008 #include <QProcess> 0009 #include <QComboBox> 0010 #include <KActionCollection> 0011 #include <KLocalizedString> 0012 #include <KProcess> 0013 #include <KShell> 0014 #include <util/path.h> 0015 #include "core.h" 0016 #include "uicontroller.h" 0017 #include "mainwindow.h" 0018 #include "debug.h" 0019 0020 using namespace KDevelop; 0021 0022 class IdentityRuntime : public IRuntime 0023 { 0024 Q_OBJECT 0025 public: 0026 QString name() const override { return i18n("Host System"); } 0027 0028 void startProcess(KProcess *process) const override { 0029 catchErrors(*process); 0030 process->start(); 0031 } 0032 void startProcess(QProcess *process) const override { 0033 catchErrors(*process); 0034 process->start(); 0035 } 0036 KDevelop::Path pathInHost(const KDevelop::Path & runtimePath) const override { return runtimePath; } 0037 KDevelop::Path pathInRuntime(const KDevelop::Path & localPath) const override { return localPath; } 0038 QString findExecutable(const QString& executableName) const override 0039 { 0040 return QStandardPaths::findExecutable(executableName); 0041 } 0042 void setEnabled(bool /*enabled*/) override {} 0043 QByteArray getenv(const QByteArray & varname) const override { return qgetenv(varname.constData()); } 0044 KDevelop::Path buildPath() const override { return {}; } 0045 0046 private: 0047 static void catchErrors(const QProcess& process) 0048 { 0049 connect(&process, &QProcess::errorOccurred, [&process](QProcess::ProcessError error) { 0050 qCWarning(SHELL).noquote().nospace() 0051 << "process finished with error: " << error << " \"" << process.errorString() 0052 << "\", the command line: \"" << KShell::quoteArg(process.program()) << ' ' 0053 << KShell::joinArgs(process.arguments()) << '"'; 0054 }); 0055 } 0056 }; 0057 0058 KDevelop::RuntimeController::RuntimeController(KDevelop::Core* core) 0059 : m_core(core) 0060 { 0061 const bool haveUI = (core->setupFlags() != Core::NoUi); 0062 if (haveUI) { 0063 m_runtimesMenu.reset(new QMenu()); 0064 } 0065 0066 addRuntimes(new IdentityRuntime); 0067 setCurrentRuntime(m_runtimes.first()); 0068 0069 if (haveUI) { 0070 setupActions(); 0071 } 0072 } 0073 0074 KDevelop::RuntimeController::~RuntimeController() 0075 { 0076 m_currentRuntime->setEnabled(false); 0077 m_currentRuntime = nullptr; 0078 } 0079 0080 void RuntimeController::setupActions() 0081 { 0082 // TODO not multi-window friendly, FIXME 0083 KActionCollection* ac = m_core->uiControllerInternal()->defaultMainWindow()->actionCollection(); 0084 0085 auto action = new QAction(this); 0086 action->setToolTip(i18n("Allows to select a runtime")); 0087 action->setMenu(m_runtimesMenu.data()); 0088 action->setIcon(QIcon::fromTheme(QStringLiteral("file-library-symbolic"))); 0089 auto updateActionText = [action](IRuntime* currentRuntime){ 0090 action->setText(i18n("Runtime: %1", currentRuntime->name())); 0091 }; 0092 connect(this, &RuntimeController::currentRuntimeChanged, action, updateActionText); 0093 updateActionText(m_currentRuntime); 0094 0095 ac->addAction(QStringLiteral("switch_runtimes"), action); 0096 } 0097 0098 void KDevelop::RuntimeController::initialize() 0099 { 0100 } 0101 0102 KDevelop::IRuntime * KDevelop::RuntimeController::currentRuntime() const 0103 { 0104 Q_ASSERT(m_currentRuntime); 0105 return m_currentRuntime; 0106 } 0107 0108 QVector<KDevelop::IRuntime *> KDevelop::RuntimeController::availableRuntimes() const 0109 { 0110 return m_runtimes; 0111 } 0112 0113 void KDevelop::RuntimeController::setCurrentRuntime(KDevelop::IRuntime* runtime) 0114 { 0115 if (m_currentRuntime == runtime) 0116 return; 0117 0118 Q_ASSERT(m_runtimes.contains(runtime)); 0119 0120 if (m_currentRuntime) { 0121 m_currentRuntime->setEnabled(false); 0122 } 0123 qCDebug(SHELL) << "setting runtime..." << runtime->name() << "was" << m_currentRuntime; 0124 m_currentRuntime = runtime; 0125 m_currentRuntime->setEnabled(true); 0126 Q_EMIT currentRuntimeChanged(runtime); 0127 } 0128 0129 void KDevelop::RuntimeController::addRuntimes(KDevelop::IRuntime * runtime) 0130 { 0131 if (!runtime->parent()) 0132 runtime->setParent(this); 0133 0134 if (m_core->setupFlags() != Core::NoUi) { 0135 auto* runtimeAction = new QAction(runtime->name(), m_runtimesMenu.data()); 0136 runtimeAction->setCheckable(true); 0137 connect(runtimeAction, &QAction::triggered, runtime, [this, runtime]() { 0138 setCurrentRuntime(runtime); 0139 }); 0140 connect(this, &RuntimeController::currentRuntimeChanged, runtimeAction, [runtimeAction, runtime](IRuntime* currentRuntime) { 0141 runtimeAction->setChecked(runtime == currentRuntime); 0142 }); 0143 0144 connect(runtime, &QObject::destroyed, this, [this, runtimeAction](QObject* obj) { 0145 Q_ASSERT(m_currentRuntime != obj); 0146 m_runtimes.removeAll(qobject_cast<KDevelop::IRuntime *>(obj)); 0147 delete runtimeAction; 0148 }); 0149 m_runtimesMenu->addAction(runtimeAction); 0150 } else { 0151 connect(runtime, &QObject::destroyed, this, [this](QObject* obj) { 0152 Q_ASSERT(m_currentRuntime != obj); 0153 m_runtimes.removeAll(qobject_cast<KDevelop::IRuntime *>(obj)); 0154 }); 0155 } 0156 0157 m_runtimes << runtime; 0158 } 0159 0160 #include "runtimecontroller.moc" 0161 #include "moc_runtimecontroller.cpp"