Skip to content

Commit 7155fc9

Browse files
committed
add gui to configure ssh
1 parent 2cee804 commit 7155fc9

File tree

13 files changed

+380
-79
lines changed

13 files changed

+380
-79
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ set(hotspot_SRCS
5050
perfoutputwidgettext.cpp
5151
perfoutputwidgetkonsole.cpp
5252
costcontextmenu.cpp
53+
ssh.cpp
5354

5455
# ui files:
5556
mainwindow.ui

src/mainwindow.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ MainWindow::MainWindow(QWidget* parent)
128128
settings->setObjdump(m_settingsDialog->objdump());
129129
});
130130

131+
connect(m_settingsDialog, &QDialog::accepted, m_recordPage, &RecordPage::onRemoteDevicesChanged);
132+
131133
connect(settings, &Settings::sysrootChanged, m_resultsPage, &ResultsPage::setSysroot);
132134
connect(settings, &Settings::appPathChanged, m_resultsPage, &ResultsPage::setAppPath);
133135
connect(settings, &Settings::objdumpChanged, m_resultsPage, &ResultsPage::setObjdump);

src/perfrecordssh.cpp

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,11 @@
1616
#include <csignal>
1717

1818
#include "hotspot-config.h"
19-
20-
QString sshOutput(const QString& hostname, const QStringList& command)
21-
{
22-
QProcess ssh;
23-
ssh.setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
24-
const auto arguments = QStringList({hostname}) + command;
25-
ssh.setArguments(arguments);
26-
ssh.start();
27-
ssh.waitForFinished();
28-
return QString::fromUtf8(ssh.readAll());
29-
}
30-
31-
int sshExitCode(const QString& hostname, const QStringList& command)
32-
{
33-
QProcess ssh;
34-
ssh.setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
35-
const auto arguments = QStringList({hostname}) + command;
36-
ssh.setArguments(arguments);
37-
ssh.start();
38-
ssh.waitForFinished();
39-
return ssh.exitCode();
40-
}
19+
#include "ssh.h"
4120

4221
PerfRecordSSH::PerfRecordSSH(QObject* parent)
4322
: PerfRecord(parent)
4423
{
45-
m_hostname = QStringLiteral("user@localhost");
4624
}
4725

4826
PerfRecordSSH::~PerfRecordSSH() = default;
@@ -102,7 +80,7 @@ QString PerfRecordSSH::currentUsername()
10280

10381
bool PerfRecordSSH::canTrace(const QString& path)
10482
{
105-
if (m_hostname.isEmpty())
83+
if (m_deviceName.isEmpty())
10684
return false;
10785

10886
// assume best case
@@ -111,7 +89,7 @@ bool PerfRecordSSH::canTrace(const QString& path)
11189

11290
bool PerfRecordSSH::canProfileOffCpu()
11391
{
114-
if (m_hostname.isEmpty())
92+
if (m_deviceName.isEmpty())
11593
return false;
11694
return canTrace(QStringLiteral("events/sched/sched_switch"));
11795
}
@@ -142,16 +120,16 @@ QString perfBuildOptions(const QString& hostname)
142120

143121
bool PerfRecordSSH::canSampleCpu()
144122
{
145-
if (m_hostname.isEmpty())
123+
if (m_deviceName.isEmpty())
146124
return false;
147-
return perfRecordHelp(m_hostname).contains(QLatin1String("--sample-cpu"));
125+
return perfRecordHelp(m_deviceName).contains(QLatin1String("--sample-cpu"));
148126
}
149127

150128
bool PerfRecordSSH::canSwitchEvents()
151129
{
152-
if (m_hostname.isEmpty())
130+
if (m_deviceName.isEmpty())
153131
return false;
154-
return perfRecordHelp(m_hostname).contains(QLatin1String("--switch-events"));
132+
return perfRecordHelp(m_deviceName).contains(QLatin1String("--switch-events"));
155133
}
156134

157135
bool PerfRecordSSH::canUseAio()
@@ -162,16 +140,16 @@ bool PerfRecordSSH::canUseAio()
162140

163141
bool PerfRecordSSH::canCompress()
164142
{
165-
if (m_hostname.isEmpty())
143+
if (m_deviceName.isEmpty())
166144
return false;
167-
return Zstd_FOUND && perfBuildOptions(m_hostname).contains(QLatin1String("zstd: [ on ]"));
145+
return Zstd_FOUND && perfBuildOptions(m_deviceName).contains(QLatin1String("zstd: [ on ]"));
168146
}
169147

170148
bool PerfRecordSSH::isPerfInstalled()
171149
{
172-
if (m_hostname.isEmpty())
150+
if (m_deviceName.isEmpty())
173151
return false;
174-
return sshExitCode(m_hostname, {QLatin1String("command"), QLatin1String("-v"), QLatin1String("perf")}) != 0;
152+
return sshExitCode(m_deviceName, {QLatin1String("command"), QLatin1String("-v"), QLatin1String("perf")}) != 0;
175153
}
176154

177155
void PerfRecordSSH::startRecording(const QStringList& perfOptions, const QString& outputPath,
@@ -197,29 +175,26 @@ void PerfRecordSSH::startRecording(const QStringList& perfOptions, const QString
197175
return;
198176
}
199177

178+
qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
179+
200180
QStringList perfCommand = {QStringLiteral("record"), QStringLiteral("-o"), QStringLiteral("-")};
201181
perfCommand += perfOptions;
202182
perfCommand += recordOptions;
203-
204183
m_outputFile = new QFile(outputPath);
205184
m_outputFile->open(QIODevice::WriteOnly);
206185

207-
m_recordProcess = new QProcess(this);
208-
m_recordProcess->setProgram(QStandardPaths::findExecutable(QLatin1String("ssh")));
209-
m_recordProcess->setArguments({m_hostname, QLatin1String("perf ") + perfCommand.join(QLatin1Char(' '))});
210-
m_recordProcess->start();
211-
m_recordProcess->waitForStarted();
186+
m_recordProcess = createSshProcess(m_deviceName, perfCommand);
212187

213188
emit recordingStarted(QLatin1String("perf"), perfCommand);
214189

215-
connect(m_recordProcess, &QProcess::readyReadStandardOutput, this,
190+
connect(m_recordProcess.get(), &QProcess::readyReadStandardOutput, this,
216191
[this] { m_outputFile->write(m_recordProcess->readAllStandardOutput()); });
217192

218-
connect(m_recordProcess, &QProcess::readyReadStandardError, this,
193+
connect(m_recordProcess.get(), &QProcess::readyReadStandardError, this,
219194
[this] { emit recordingOutput(QString::fromUtf8(m_recordProcess->readAllStandardError())); });
220195

221-
connect(m_recordProcess, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this,
222-
[this](int exitCode, QProcess::ExitStatus exitStatus) {
196+
connect(m_recordProcess.get(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
197+
this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
223198
Q_UNUSED(exitStatus)
224199

225200
m_outputFile->close();

src/perfrecordssh.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#pragma once
99

1010
#include "perfrecord.h"
11+
#include <QProcess>
1112

1213
class QFile;
1314

@@ -18,6 +19,11 @@ class PerfRecordSSH : public PerfRecord
1819
PerfRecordSSH(QObject* parent = nullptr);
1920
~PerfRecordSSH();
2021

22+
void setDeviceName(const QString& device)
23+
{
24+
m_deviceName = device;
25+
}
26+
2127
void record(const QStringList& perfOptions, const QString& outputPath, bool elevatePrivileges,
2228
const QString& exePath, const QStringList& exeOptions, const QString& workingDirectory) override;
2329
void record(const QStringList& perfOptions, const QString& outputPath, bool elevatePrivileges,
@@ -48,8 +54,8 @@ class PerfRecordSSH : public PerfRecord
4854
void startRecording(const QStringList& perfOptions, const QString& outputPath, const QStringList& recordOptions,
4955
const QString& workingDirectory);
5056

51-
QProcess* m_recordProcess = nullptr;
57+
std::unique_ptr<QProcess> m_recordProcess = nullptr;
5258
QFile* m_outputFile;
53-
QString m_hostname;
59+
QString m_deviceName;
5460
bool m_userTerminated = false;
5561
};

src/recordpage.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,10 @@ RecordPage::RecordPage(QWidget* parent)
428428

429429
perfRecordChanged();
430430

431-
ui->remoteTargetComboBox->addItem(QStringLiteral("localhost"));
432-
ui->remoteTargetComboBox->addItem(QStringLiteral("remote test 1"));
431+
const auto sshPath = QStandardPaths::findExecutable(QLatin1String("ssh"));
432+
ui->remoteTargetGroup->setVisible(!sshPath.isEmpty());
433+
434+
onRemoteDevicesChanged();
433435

434436
connect(ui->remoteTargetComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
435437
[this, perfRecordChanged](int index) {
@@ -857,3 +859,17 @@ void RecordPage::updateOffCpuCheckboxState()
857859
ui->offCpuCheckBox->setChecked(config().readEntry(QStringLiteral("offCpuProfiling"), false));
858860
}
859861
}
862+
863+
void RecordPage::onRemoteDevicesChanged()
864+
{
865+
ui->remoteTargetComboBox->clear();
866+
ui->remoteTargetComboBox->addItem(QStringLiteral("localhost"));
867+
868+
const auto deviceConfig = KSharedConfig::openConfig()->group("devices");
869+
auto t = deviceConfig.groupList();
870+
for (const auto& device : deviceConfig.groupList()) {
871+
if (deviceConfig.hasGroup(device)) {
872+
ui->remoteTargetComboBox->addItem(device);
873+
}
874+
}
875+
}

src/recordpage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class RecordPage : public QWidget
5454
void homeButtonClicked();
5555
void openFile(QString filePath);
5656

57+
public slots:
58+
void onRemoteDevicesChanged();
59+
5760
private slots:
5861
void onApplicationNameChanged(const QString& filePath);
5962
void onStartRecordingButtonClicked(bool checked);

src/settings.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,13 @@ void Settings::loadFromFile()
221221
connect(this, &Settings::lastUsedEnvironmentChanged, [sharedConfig, this](const QString& envName) {
222222
sharedConfig->group("PerfPaths").writeEntry("lastUsed", envName);
223223
});
224+
225+
const auto askpass = QStandardPaths::findExecutable(QLatin1String("ksshaskpass"));
226+
setSshaskPassPath(sharedConfig->group("SSH").readEntry("sshaskpass", askpass));
227+
}
228+
229+
void Settings::setSshaskPassPath(const QString& sshaskpath)
230+
{
231+
m_sshaskPassPath = sshaskpath;
232+
emit sshaskPassChanged(m_sshaskPassPath);
224233
}

src/settings.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ class Settings : public QObject
138138
return m_lastUsedEnvironment;
139139
}
140140

141+
QString sshaskPassPath() const
142+
{
143+
return m_sshaskPassPath;
144+
}
145+
141146
void loadFromFile();
142147

143148
signals:
@@ -157,6 +162,7 @@ class Settings : public QObject
157162
void objdumpChanged(const QString& objdump);
158163
void callgraphChanged();
159164
void lastUsedEnvironmentChanged(const QString& envName);
165+
void sshaskPassChanged(const QString& path);
160166

161167
public slots:
162168
void setPrettifySymbols(bool prettifySymbols);
@@ -177,6 +183,7 @@ public slots:
177183
void setCallgraphColors(const QColor& active, const QColor& inactive);
178184
void setCostAggregation(CostAggregation costAggregation);
179185
void setLastUsedEnvironment(const QString& envName);
186+
void setSshaskPassPath(const QString& sshaskpath);
180187

181188
private:
182189
Settings() = default;
@@ -198,6 +205,7 @@ public slots:
198205
QString m_appPath;
199206
QString m_arch;
200207
QString m_objdump;
208+
QString m_sshaskPassPath;
201209

202210
QString m_lastUsedEnvironment;
203211

0 commit comments

Comments
 (0)