1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
4 ** Contact: KDAB (info@kdab.com)
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "qnxdevice.h"
27
28 #include "qnxconstants.h"
29 #include "qnxdevicetester.h"
30 #include "qnxdeviceprocesslist.h"
31 #include "qnxdeviceprocesssignaloperation.h"
32 #include "qnxdeployqtlibrariesdialog.h"
33 #include "qnxdeviceprocess.h"
34 #include "qnxdevicewizard.h"
35
36 #include <projectexplorer/devicesupport/sshdeviceprocess.h>
37 #include <projectexplorer/runcontrol.h>
38
39 #include <ssh/sshconnection.h>
40 #include <utils/port.h>
41 #include <utils/qtcassert.h>
42 #include <utils/stringutils.h>
43
44 #include <QApplication>
45 #include <QRegularExpression>
46 #include <QStringList>
47 #include <QThread>
48
49 using namespace ProjectExplorer;
50 using namespace Utils;
51
52 namespace Qnx {
53 namespace Internal {
54
55 const char QnxVersionKey[] = "QnxVersion";
56
57 class QnxPortsGatheringMethod : public PortsGatheringMethod
58 {
59 // TODO: The command is probably needlessly complicated because the parsing method
60 // used to be fixed. These two can now be matched to each other.
runnable(QAbstractSocket::NetworkLayerProtocol protocol) const61 Runnable runnable(QAbstractSocket::NetworkLayerProtocol protocol) const override
62 {
63 Q_UNUSED(protocol)
64 Runnable runnable;
65 runnable.executable = FilePath::fromString("netstat");
66 runnable.commandLineArguments = "-na";
67 return runnable;
68 }
69
usedPorts(const QByteArray & output) const70 QList<Port> usedPorts(const QByteArray &output) const override
71 {
72 QList<Utils::Port> ports;
73 const QList<QByteArray> lines = output.split('\n');
74 for (const QByteArray &line : lines) {
75 const Port port(Utils::parseUsedPortFromNetstatOutput(line));
76 if (port.isValid() && !ports.contains(port))
77 ports.append(port);
78 }
79 return ports;
80 }
81 };
82
QnxDevice()83 QnxDevice::QnxDevice()
84 {
85 setDisplayType(tr("QNX"));
86 setDefaultDisplayName(tr("QNX Device"));
87 setOsType(OsTypeOtherUnix);
88
89 addDeviceAction({tr("Deploy Qt libraries..."), [](const IDevice::Ptr &device, QWidget *parent) {
90 QnxDeployQtLibrariesDialog dialog(device, parent);
91 dialog.exec();
92 }});
93 }
94
qnxVersion() const95 int QnxDevice::qnxVersion() const
96 {
97 if (m_versionNumber == 0)
98 updateVersionNumber();
99
100 return m_versionNumber;
101 }
102
updateVersionNumber() const103 void QnxDevice::updateVersionNumber() const
104 {
105 QEventLoop eventLoop;
106 SshDeviceProcess versionNumberProcess(sharedFromThis());
107 QObject::connect(&versionNumberProcess, &SshDeviceProcess::finished, &eventLoop, &QEventLoop::quit);
108 QObject::connect(&versionNumberProcess, &DeviceProcess::error, &eventLoop, &QEventLoop::quit);
109
110 Runnable r;
111 r.executable = FilePath::fromString("uname");
112 r.commandLineArguments = QLatin1String("-r");
113 versionNumberProcess.start(r);
114
115 bool isGuiThread = QThread::currentThread() == QCoreApplication::instance()->thread();
116 if (isGuiThread)
117 QApplication::setOverrideCursor(Qt::WaitCursor);
118
119 eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
120
121 QByteArray output = versionNumberProcess.readAllStandardOutput();
122 QString versionMessage = QString::fromLatin1(output);
123 const QRegularExpression versionNumberRegExp("(\\d+)\\.(\\d+)\\.(\\d+)");
124 const QRegularExpressionMatch match = versionNumberRegExp.match(versionMessage);
125 if (match.hasMatch()) {
126 int major = match.captured(1).toInt();
127 int minor = match.captured(2).toInt();
128 int patch = match.captured(3).toInt();
129 m_versionNumber = (major << 16)|(minor<<8)|(patch);
130 }
131
132 if (isGuiThread)
133 QApplication::restoreOverrideCursor();
134 }
135
fromMap(const QVariantMap & map)136 void QnxDevice::fromMap(const QVariantMap &map)
137 {
138 m_versionNumber = map.value(QLatin1String(QnxVersionKey), 0).toInt();
139 RemoteLinux::LinuxDevice::fromMap(map);
140 }
141
toMap() const142 QVariantMap QnxDevice::toMap() const
143 {
144 QVariantMap map(RemoteLinux::LinuxDevice::toMap());
145 map.insert(QLatin1String(QnxVersionKey), m_versionNumber);
146 return map;
147 }
148
portsGatheringMethod() const149 PortsGatheringMethod::Ptr QnxDevice::portsGatheringMethod() const
150 {
151 return PortsGatheringMethod::Ptr(new QnxPortsGatheringMethod);
152 }
153
createProcessListModel(QObject * parent) const154 DeviceProcessList *QnxDevice::createProcessListModel(QObject *parent) const
155 {
156 return new QnxDeviceProcessList(sharedFromThis(), parent);
157 }
158
createDeviceTester() const159 DeviceTester *QnxDevice::createDeviceTester() const
160 {
161 return new QnxDeviceTester;
162 }
163
createProcess(QObject * parent) const164 DeviceProcess *QnxDevice::createProcess(QObject *parent) const
165 {
166 return new QnxDeviceProcess(sharedFromThis(), parent);
167 }
168
signalOperation() const169 DeviceProcessSignalOperation::Ptr QnxDevice::signalOperation() const
170 {
171 return DeviceProcessSignalOperation::Ptr(
172 new QnxDeviceProcessSignalOperation(sshParameters()));
173 }
174
175 // Factory
176
QnxDeviceFactory()177 QnxDeviceFactory::QnxDeviceFactory()
178 : ProjectExplorer::IDeviceFactory(Constants::QNX_QNX_OS_TYPE)
179 {
180 setDisplayName(QnxDevice::tr("QNX Device"));
181 setCombinedIcon(":/qnx/images/qnxdevicesmall.png",
182 ":/qnx/images/qnxdevice.png");
183 setCanCreate(true);
184 setConstructionFunction(&QnxDevice::create);
185 }
186
create() const187 ProjectExplorer::IDevice::Ptr QnxDeviceFactory::create() const
188 {
189 QnxDeviceWizard wizard;
190 if (wizard.exec() != QDialog::Accepted)
191 return ProjectExplorer::IDevice::Ptr();
192 return wizard.device();
193 }
194
195 } // namespace Internal
196 } // namespace Qnx
197