From 5bca241afb51e89688b88e0dfb6580a5cf23372e Mon Sep 17 00:00:00 2001
From: Christian Kandeler <christian.kandeler@digia.com>
Date: Thu, 27 Jun 2013 17:12:08 +0200
Subject: [PATCH] Device support: Make device testing a "well-known" concept.

This entails the following:
    - Rename AbstractLinuxDeviceTester to DeviceTester and
      move it up into ProjectExplorer. The class stays
      unchanged, as there was nothing Linux-specific about it.
      The same goes for the associated dialog.
    - Move the createDeviceTester() function from LinuxDevice
      to IDevice and introduce IDevice::hasDeviceTester() to
      enable generic code to make use of this feature.
    - Move device testing out of the list of opaque
      device-specific actions; instead, the device settings widget
      now uses the device tester directly, if applicable.
Rationale:
    - Device testing, just like remote process listing (if not more so),
      is a general concept that implementors of device classes will
      probably want to implement (and they should be encouraged to do so).
      Without the mechanism provided here, they would all need to put
      basically the same code into the actionIds(), displayNameForActionId()
      and executeAction() functions.

This patch is the natural extension of b90e3bbd8bea27ad915a4d9033e0d5bda26f5667.

Change-Id: I94f2badb4ceeda9f5cd3b066c13626bb4f65505d
Reviewed-by: hjk <hjk121@nokiamail.com>
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
---
 src/plugins/madde/maddedevice.cpp             |  3 +-
 src/plugins/madde/maddedevice.h               |  2 +-
 src/plugins/madde/maddedevicetester.cpp       |  6 +--
 src/plugins/madde/maddedevicetester.h         |  6 +--
 src/plugins/madde/maemodeviceconfigwizard.cpp | 10 ----
 .../devicesupport/devicesettingswidget.cpp    | 18 +++++++
 .../devicesupport/devicesettingswidget.h      |  1 +
 .../devicesupport/devicetestdialog.cpp}       | 47 +++++++++----------
 .../devicesupport/devicetestdialog.h}         | 29 +++++-------
 .../devicesupport/devicetestdialog.ui}        |  8 ++--
 .../projectexplorer/devicesupport/idevice.cpp |  7 +++
 .../projectexplorer/devicesupport/idevice.h   | 26 +++++++++-
 .../projectexplorer/projectexplorer.pro       |  3 ++
 .../projectexplorer/projectexplorer.qbs       |  3 ++
 src/plugins/qnx/qnxdeviceconfiguration.cpp    |  2 +-
 src/plugins/qnx/qnxdeviceconfiguration.h      |  2 +-
 .../qnx/qnxdeviceconfigurationwizard.cpp      |  4 --
 src/plugins/qnx/qnxdevicetester.cpp           |  8 ++--
 src/plugins/qnx/qnxdevicetester.h             |  6 +--
 .../genericlinuxdeviceconfigurationwizard.cpp |  6 ---
 src/plugins/remotelinux/linuxdevice.cpp       | 13 ++---
 src/plugins/remotelinux/linuxdevice.h         |  4 +-
 src/plugins/remotelinux/linuxdevicetester.cpp |  7 +--
 src/plugins/remotelinux/linuxdevicetester.h   | 24 +---------
 src/plugins/remotelinux/remotelinux.pro       |  3 --
 src/plugins/remotelinux/remotelinux.qbs       |  3 --
 .../remotelinux/remotelinux_constants.h       |  1 -
 27 files changed, 122 insertions(+), 130 deletions(-)
 rename src/plugins/{remotelinux/linuxdevicetestdialog.cpp => projectexplorer/devicesupport/devicetestdialog.cpp} (69%)
 rename src/plugins/{remotelinux/linuxdevicetestdialog.h => projectexplorer/devicesupport/devicetestdialog.h} (71%)
 rename src/plugins/{remotelinux/linuxdevicetestdialog.ui => projectexplorer/devicesupport/devicetestdialog.ui} (83%)

diff --git a/src/plugins/madde/maddedevice.cpp b/src/plugins/madde/maddedevice.cpp
index e8f3c5546f4..821fb059f6a 100644
--- a/src/plugins/madde/maddedevice.cpp
+++ b/src/plugins/madde/maddedevice.cpp
@@ -31,7 +31,6 @@
 #include "maddedevicetester.h"
 #include "maemoconstants.h"
 
-#include <remotelinux/linuxdevicetestdialog.h>
 #include <remotelinux/publickeydeploymentdialog.h>
 #include <remotelinux/remotelinux_constants.h>
 #include <utils/qtcassert.h>
@@ -111,7 +110,7 @@ QSize MaddeDevice::packageManagerIconSize(Core::Id type)
     return QSize();
 }
 
-AbstractLinuxDeviceTester *MaddeDevice::createDeviceTester() const
+DeviceTester *MaddeDevice::createDeviceTester() const
 {
     return new MaddeDeviceTester;
 }
diff --git a/src/plugins/madde/maddedevice.h b/src/plugins/madde/maddedevice.h
index 463c2252319..bd2ec00253b 100644
--- a/src/plugins/madde/maddedevice.h
+++ b/src/plugins/madde/maddedevice.h
@@ -58,7 +58,7 @@ public:
 
     static QSize packageManagerIconSize(Core::Id type);
 
-    RemoteLinux::AbstractLinuxDeviceTester *createDeviceTester() const;
+    ProjectExplorer::DeviceTester *createDeviceTester() const;
 
 private:
     MaddeDevice();
diff --git a/src/plugins/madde/maddedevicetester.cpp b/src/plugins/madde/maddedevicetester.cpp
index 8a68d985659..29b7d888f8e 100644
--- a/src/plugins/madde/maddedevicetester.cpp
+++ b/src/plugins/madde/maddedevicetester.cpp
@@ -47,7 +47,7 @@ const char QmlToolingDirectory[] = "/usr/lib/qt4/plugins/qmltooling";
 } // anonymous namespace
 
 MaddeDeviceTester::MaddeDeviceTester(QObject *parent)
-    : AbstractLinuxDeviceTester(parent),
+    : ProjectExplorer::DeviceTester(parent),
       m_genericTester(new GenericLinuxDeviceTester(this)),
       m_state(Inactive),
       m_processRunner(0)
@@ -68,8 +68,8 @@ void MaddeDeviceTester::testDevice(const ProjectExplorer::IDevice::ConstPtr &dev
     m_state = GenericTest;
     connect(m_genericTester, SIGNAL(progressMessage(QString)), SIGNAL(progressMessage(QString)));
     connect(m_genericTester, SIGNAL(errorMessage(QString)), SIGNAL(errorMessage(QString)));
-    connect(m_genericTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)),
-        SLOT(handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)));
+    connect(m_genericTester, SIGNAL(finished(ProjectExplorer::DeviceTester::TestResult)),
+        SLOT(handleGenericTestFinished(ProjectExplorer::DeviceTester::TestResult)));
     m_genericTester->testDevice(deviceConfiguration);
 }
 
diff --git a/src/plugins/madde/maddedevicetester.h b/src/plugins/madde/maddedevicetester.h
index cf63d413114..98461f0bebf 100644
--- a/src/plugins/madde/maddedevicetester.h
+++ b/src/plugins/madde/maddedevicetester.h
@@ -38,7 +38,7 @@ class SshRemoteProcessRunner;
 namespace Madde {
 namespace Internal {
 
-class MaddeDeviceTester : public RemoteLinux::AbstractLinuxDeviceTester
+class MaddeDeviceTester : public ProjectExplorer::DeviceTester
 {
     Q_OBJECT
 
@@ -50,7 +50,7 @@ public:
     void stopTest();
 
 private slots:
-    void handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result);
+    void handleGenericTestFinished(ProjectExplorer::DeviceTester::TestResult result);
     void handleConnectionError();
     void handleProcessFinished(int exitStatus);
 
@@ -66,7 +66,7 @@ private:
 
     RemoteLinux::GenericLinuxDeviceTester * const m_genericTester;
     State m_state;
-    TestResult m_result;
+    ProjectExplorer::DeviceTester::TestResult m_result;
     QSsh::SshRemoteProcessRunner *m_processRunner;
     ProjectExplorer::IDevice::ConstPtr m_deviceConfiguration;
 };
diff --git a/src/plugins/madde/maemodeviceconfigwizard.cpp b/src/plugins/madde/maemodeviceconfigwizard.cpp
index 0b352549e28..f3f8c311d9e 100644
--- a/src/plugins/madde/maemodeviceconfigwizard.cpp
+++ b/src/plugins/madde/maemodeviceconfigwizard.cpp
@@ -40,7 +40,6 @@
 #include "maemoglobal.h"
 
 #include <remotelinux/genericlinuxdeviceconfigurationwizardpages.h>
-#include <remotelinux/linuxdevicetestdialog.h>
 #include <remotelinux/sshkeydeployer.h>
 #include <utils/fileutils.h>
 #include <ssh/sshkeygenerator.h>
@@ -553,7 +552,6 @@ MaemoDeviceConfigWizard::~MaemoDeviceConfigWizard()
 
 IDevice::Ptr MaemoDeviceConfigWizard::device()
 {
-    bool doTest;
     QString freePortsSpec;
     QSsh::SshConnectionParameters sshParams;
     sshParams.userName = defaultUser();
@@ -564,24 +562,16 @@ IDevice::Ptr MaemoDeviceConfigWizard::device()
         sshParams.password.clear();
         sshParams.timeout = 30;
         freePortsSpec = QLatin1String("13219,14168");
-        doTest = false;
     } else {
         sshParams.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePublicKey;
         sshParams.privateKeyFile = d->wizardData.privateKeyFilePath;
         sshParams.timeout = 10;
         freePortsSpec = QLatin1String("10000-10100");
-        doTest = true;
     }
     const MaddeDevice::Ptr device = MaddeDevice::create(d->wizardData.configName,
         d->wizardData.deviceType, d->wizardData.machineType);
     device->setFreePorts(PortList::fromString(freePortsSpec));
     device->setSshParameters(sshParams);
-    if (doTest) {
-        // Might be called after accept.
-        QWidget *parent = isVisible() ? this : static_cast<QWidget *>(0);
-        LinuxDeviceTestDialog dlg(device, new MaddeDeviceTester(this), parent);
-        dlg.exec();
-    }
     return device;
 }
 
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
index fb3a428752a..2679225e397 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp
@@ -34,6 +34,7 @@
 #include "devicemanager.h"
 #include "devicemanagermodel.h"
 #include "deviceprocessesdialog.h"
+#include "devicetestdialog.h"
 #include "idevice.h"
 #include "idevicefactory.h"
 #include "idevicewidget.h"
@@ -167,6 +168,8 @@ void DeviceSettingsWidget::addDevice()
     m_deviceManager->addDevice(device);
     m_ui->removeConfigButton->setEnabled(true);
     m_ui->configurationComboBox->setCurrentIndex(m_deviceManagerModel->indexOf(device));
+    if (device->hasDeviceTester())
+        testDevice();
 }
 
 void DeviceSettingsWidget::removeDevice()
@@ -262,6 +265,14 @@ void DeviceSettingsWidget::setDefaultDevice()
     m_ui->defaultDeviceButton->setEnabled(false);
 }
 
+void DeviceSettingsWidget::testDevice()
+{
+    const IDevice::ConstPtr &device = currentDevice();
+    QTC_ASSERT(device && device->hasDeviceTester(), return);
+    DeviceTestDialog dlg(device, this);
+    dlg.exec();
+}
+
 void DeviceSettingsWidget::handleDeviceUpdated(Id id)
 {
     const int index = m_deviceManagerModel->indexForId(id);
@@ -286,6 +297,13 @@ void DeviceSettingsWidget::currentDeviceChanged(int index)
     setDeviceInfoWidgetsEnabled(true);
     m_ui->removeConfigButton->setEnabled(true);
 
+    if (device->hasDeviceTester()) {
+        QPushButton * const button = new QPushButton(tr("Test"));
+        m_additionalActionButtons << button;
+        connect(button, SIGNAL(clicked()), SLOT(testDevice()));
+        m_ui->buttonsLayout->insertWidget(m_ui->buttonsLayout->count() - 1, button);
+    }
+
     if (device->canCreateProcessModel()) {
         QPushButton * const button = new QPushButton(tr("Show Running Processes"));
         m_additionalActionButtons << button;
diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
index d589400a43f..f6974831659 100644
--- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
+++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h
@@ -68,6 +68,7 @@ private slots:
     void removeDevice();
     void deviceNameEditingFinished();
     void setDefaultDevice();
+    void testDevice();
     void handleAdditionalActionRequest(int actionId);
     void handleProcessListRequested();
 
diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.cpp b/src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp
similarity index 69%
rename from src/plugins/remotelinux/linuxdevicetestdialog.cpp
rename to src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp
index 63605db74de..ef09413a2ff 100644
--- a/src/plugins/remotelinux/linuxdevicetestdialog.cpp
+++ b/src/plugins/projectexplorer/devicesupport/devicetestdialog.cpp
@@ -26,8 +26,8 @@
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ****************************************************************************/
-#include "linuxdevicetestdialog.h"
-#include "ui_linuxdevicetestdialog.h"
+#include "devicetestdialog.h"
+#include "ui_devicetestdialog.h"
 
 #include <QBrush>
 #include <QColor>
@@ -35,72 +35,70 @@
 #include <QPushButton>
 #include <QTextCharFormat>
 
-namespace RemoteLinux {
+namespace ProjectExplorer {
 namespace Internal {
-class LinuxDeviceTestDialogPrivate {
+
+class DeviceTestDialog::DeviceTestDialogPrivate
+{
 public:
-    LinuxDeviceTestDialogPrivate(AbstractLinuxDeviceTester *tester)
+    DeviceTestDialogPrivate(DeviceTester *tester)
         : deviceTester(tester), finished(false)
     {
     }
 
-    Ui::LinuxDeviceTestDialog ui;
-    AbstractLinuxDeviceTester * const deviceTester;
+    Ui::DeviceTestDialog ui;
+    DeviceTester * const deviceTester;
     bool finished;
 };
 
-} // namespace Internal
-
-using namespace Internal;
-
-LinuxDeviceTestDialog::LinuxDeviceTestDialog(const ProjectExplorer::IDevice::ConstPtr &deviceConfiguration,
-        AbstractLinuxDeviceTester *deviceTester, QWidget *parent)
-    : QDialog(parent), d(new LinuxDeviceTestDialogPrivate(deviceTester))
+DeviceTestDialog::DeviceTestDialog(const ProjectExplorer::IDevice::ConstPtr &deviceConfiguration,
+                                   QWidget *parent)
+    : QDialog(parent), d(new DeviceTestDialogPrivate(deviceConfiguration->createDeviceTester()))
 {
     d->ui.setupUi(this);
 
     d->deviceTester->setParent(this);
     connect(d->deviceTester, SIGNAL(progressMessage(QString)), SLOT(handleProgressMessage(QString)));
     connect(d->deviceTester, SIGNAL(errorMessage(QString)), SLOT(handleErrorMessage(QString)));
-    connect(d->deviceTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)),
-        SLOT(handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)));
+    connect(d->deviceTester, SIGNAL(finished(ProjectExplorer::DeviceTester::TestResult)),
+        SLOT(handleTestFinished(ProjectExplorer::DeviceTester::TestResult)));
     d->deviceTester->testDevice(deviceConfiguration);
 }
 
-LinuxDeviceTestDialog::~LinuxDeviceTestDialog()
+DeviceTestDialog::~DeviceTestDialog()
 {
     delete d;
 }
 
-void LinuxDeviceTestDialog::reject()
+void DeviceTestDialog::reject()
 {
     if (!d->finished)
         d->deviceTester->stopTest();
     QDialog::reject();
 }
 
-void LinuxDeviceTestDialog::handleProgressMessage(const QString &message)
+void DeviceTestDialog::handleProgressMessage(const QString &message)
 {
     addText(message, QLatin1String("black"), false);
 }
 
-void LinuxDeviceTestDialog::handleErrorMessage(const QString &message)
+void DeviceTestDialog::handleErrorMessage(const QString &message)
 {
     addText(message, QLatin1String("red"), false);
 }
 
-void LinuxDeviceTestDialog::handleTestFinished(AbstractLinuxDeviceTester::TestResult result)
+void DeviceTestDialog::handleTestFinished(ProjectExplorer::DeviceTester::TestResult result)
 {
     d->finished = true;
     d->ui.buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close"));
 
-    if (result == AbstractLinuxDeviceTester::TestSuccess)
+    if (result == ProjectExplorer::DeviceTester::TestSuccess)
         addText(tr("Device test finished successfully."), QLatin1String("blue"), true);
     else
         addText(tr("Device test failed."), QLatin1String("red"), true);
 }
 
-void LinuxDeviceTestDialog::addText(const QString &text, const QString &color, bool bold)
+void DeviceTestDialog::addText(const QString &text, const QString &color, bool bold)
 {
     QTextCharFormat format = d->ui.textEdit->currentCharFormat();
     format.setForeground(QBrush(QColor(color)));
@@ -111,4 +109,5 @@ void LinuxDeviceTestDialog::addText(const QString &text, const QString &color, b
     d->ui.textEdit->appendPlainText(text);
 }
 
-} // namespace RemoteLinux
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.h b/src/plugins/projectexplorer/devicesupport/devicetestdialog.h
similarity index 71%
rename from src/plugins/remotelinux/linuxdevicetestdialog.h
rename to src/plugins/projectexplorer/devicesupport/devicetestdialog.h
index 1ac3535735e..e07493e3987 100644
--- a/src/plugins/remotelinux/linuxdevicetestdialog.h
+++ b/src/plugins/projectexplorer/devicesupport/devicetestdialog.h
@@ -26,42 +26,39 @@
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ****************************************************************************/
-#ifndef LINUXDEVICETESTDIALOG_H
-#define LINUXDEVICETESTDIALOG_H
+#ifndef DEVICETESTDIALOG_H
+#define DEVICETESTDIALOG_H
 
-#include "linuxdevicetester.h"
-#include "remotelinux_export.h"
+#include "idevice.h"
 
 #include <QDialog>
 
-namespace RemoteLinux {
+namespace ProjectExplorer {
 namespace Internal {
-class LinuxDeviceTestDialogPrivate;
-} // namespace Internal
 
-class REMOTELINUX_EXPORT LinuxDeviceTestDialog : public QDialog
+class DeviceTestDialog : public QDialog
 {
     Q_OBJECT
 
 public:
-    // Note: The dialog takes ownership of deviceTester
-    LinuxDeviceTestDialog(const ProjectExplorer::IDevice::ConstPtr &deviceConfiguration,
-        AbstractLinuxDeviceTester * deviceTester, QWidget *parent = 0);
-    ~LinuxDeviceTestDialog();
+    DeviceTestDialog(const IDevice::ConstPtr &deviceConfiguration, QWidget *parent = 0);
+    ~DeviceTestDialog();
 
     void reject();
 
 private slots:
     void handleProgressMessage(const QString &message);
     void handleErrorMessage(const QString &message);
-    void handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result);
+    void handleTestFinished(ProjectExplorer::DeviceTester::TestResult result);
 
 private:
     void addText(const QString &text, const QString &color, bool bold);
 
-    Internal::LinuxDeviceTestDialogPrivate * const d;
+    class DeviceTestDialogPrivate;
+    DeviceTestDialogPrivate * const d;
 };
 
-} // namespace RemoteLinux
+} // namespace Internal
+} // namespace ProjectExplorer
 
-#endif // LINUXDEVICETESTDIALOG_H
+#endif // Include guard.
diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.ui b/src/plugins/projectexplorer/devicesupport/devicetestdialog.ui
similarity index 83%
rename from src/plugins/remotelinux/linuxdevicetestdialog.ui
rename to src/plugins/projectexplorer/devicesupport/devicetestdialog.ui
index 4160d134529..b640f722d47 100644
--- a/src/plugins/remotelinux/linuxdevicetestdialog.ui
+++ b/src/plugins/projectexplorer/devicesupport/devicetestdialog.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
- <class>RemoteLinux::Internal::LinuxDeviceTestDialog</class>
- <widget class="QDialog" name="RemoteLinux::Internal::LinuxDeviceTestDialog">
+ <class>ProjectExplorer::Internal::DeviceTestDialog</class>
+ <widget class="QDialog" name="ProjectExplorer::Internal::DeviceTestDialog">
   <property name="geometry">
    <rect>
     <x>0</x>
@@ -38,7 +38,7 @@
   <connection>
    <sender>buttonBox</sender>
    <signal>accepted()</signal>
-   <receiver>RemoteLinux::Internal::LinuxDeviceTestDialog</receiver>
+   <receiver>ProjectExplorer::Internal::DeviceTestDialog</receiver>
    <slot>accept()</slot>
    <hints>
     <hint type="sourcelabel">
@@ -54,7 +54,7 @@
   <connection>
    <sender>buttonBox</sender>
    <signal>rejected()</signal>
-   <receiver>RemoteLinux::Internal::LinuxDeviceTestDialog</receiver>
+   <receiver>ProjectExplorer::Internal::DeviceTestDialog</receiver>
    <slot>reject()</slot>
    <hints>
     <hint type="sourcelabel">
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp
index 1afe29f6846..7f24712c73a 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.cpp
+++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp
@@ -194,6 +194,7 @@ public:
 
 PortsGatheringMethod::~PortsGatheringMethod() { }
 DeviceProcessSupport::~DeviceProcessSupport() { }
+DeviceTester::DeviceTester(QObject *parent) : QObject(parent) { }
 
 IDevice::IDevice() : d(new Internal::IDevicePrivate)
 { }
@@ -268,6 +269,12 @@ DeviceProcessList *IDevice::createProcessListModel(QObject *parent) const
     return 0;
 }
 
+DeviceTester *IDevice::createDeviceTester() const
+{
+    QTC_ASSERT(false, qDebug("This should not have been called..."));
+    return 0;
+}
+
 IDevice::DeviceState IDevice::deviceState() const
 {
     return d->deviceState;
diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h
index 3d54eb48ca4..b0666881327 100644
--- a/src/plugins/projectexplorer/devicesupport/idevice.h
+++ b/src/plugins/projectexplorer/devicesupport/idevice.h
@@ -35,11 +35,11 @@
 
 #include <QAbstractSocket>
 #include <QList>
+#include <QObject>
 #include <QSharedPointer>
 #include <QVariantMap>
 
 QT_BEGIN_NAMESPACE
-class QObject;
 class QWidget;
 QT_END_NAMESPACE
 
@@ -52,6 +52,7 @@ class DeviceProcessList;
 namespace Internal { class IDevicePrivate; }
 
 class IDeviceWidget;
+class DeviceTester;
 
 class PROJECTEXPLORER_EXPORT DeviceProcessSupport
 {
@@ -73,7 +74,6 @@ public:
     virtual QList<int> usedPorts(const QByteArray &commandOutput) const = 0;
 };
 
-
 // See cpp file for documentation.
 class PROJECTEXPLORER_EXPORT IDevice
 {
@@ -118,6 +118,8 @@ public:
     virtual PortsGatheringMethod::Ptr portsGatheringMethod() const;
     virtual bool canCreateProcessModel() const { return false; }
     virtual DeviceProcessList *createProcessListModel(QObject *parent = 0) const;
+    virtual bool hasDeviceTester() const { return false; }
+    virtual DeviceTester *createDeviceTester() const;
 
     enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown };
     DeviceState deviceState() const;
@@ -159,6 +161,26 @@ private:
     friend class DeviceManager;
 };
 
+
+class PROJECTEXPLORER_EXPORT DeviceTester : public QObject
+{
+    Q_OBJECT
+
+public:
+    enum TestResult { TestSuccess, TestFailure };
+
+    virtual void testDevice(const ProjectExplorer::IDevice::ConstPtr &deviceConfiguration) = 0;
+    virtual void stopTest() = 0;
+
+signals:
+    void progressMessage(const QString &message);
+    void errorMessage(const QString &message);
+    void finished(ProjectExplorer::DeviceTester::TestResult result);
+
+protected:
+    explicit DeviceTester(QObject *parent = 0);
+};
+
 } // namespace ProjectExplorer
 
 #endif // IDEVICE_H
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index fb713469583..f7788482404 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -121,6 +121,7 @@ HEADERS += projectexplorer.h \
     devicesupport/deviceprocessesdialog.h \
     devicesupport/devicesettingswidget.h \
     devicesupport/devicesettingspage.h \
+    devicesupport/devicetestdialog.h \
     devicesupport/deviceusedportsgatherer.h \
     devicesupport/deviceapplicationrunner.h \
     devicesupport/localprocesslist.h \
@@ -237,6 +238,7 @@ SOURCES += projectexplorer.cpp \
     devicesupport/deviceprocessesdialog.cpp \
     devicesupport/devicesettingswidget.cpp \
     devicesupport/devicesettingspage.cpp \
+    devicesupport/devicetestdialog.cpp \
     devicesupport/deviceusedportsgatherer.cpp \
     devicesupport/deviceapplicationrunner.cpp \
     devicesupport/localprocesslist.cpp \
@@ -257,6 +259,7 @@ FORMS += processstep.ui \
     codestylesettingspropertiespage.ui \
     devicesupport/devicefactoryselectiondialog.ui \
     devicesupport/devicesettingswidget.ui \
+    devicesupport/devicetestdialog.ui \
     devicesupport/desktopdeviceconfigurationwidget.ui
 
 WINSOURCES += \
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index 55dd5a3432c..e70197598a0 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -269,6 +269,9 @@ QtcPlugin {
         "devicesupport/devicesettingswidget.cpp",
         "devicesupport/devicesettingswidget.h",
         "devicesupport/devicesettingswidget.ui",
+        "devicesupport/devicetestdialog.cpp",
+        "devicesupport/devicetestdialog.h",
+        "devicesupport/devicetestdialog.ui",
         "devicesupport/deviceusedportsgatherer.cpp",
         "devicesupport/deviceusedportsgatherer.h",
         "devicesupport/idevice.cpp",
diff --git a/src/plugins/qnx/qnxdeviceconfiguration.cpp b/src/plugins/qnx/qnxdeviceconfiguration.cpp
index 7fb16988a66..13e1bd252fb 100644
--- a/src/plugins/qnx/qnxdeviceconfiguration.cpp
+++ b/src/plugins/qnx/qnxdeviceconfiguration.cpp
@@ -187,7 +187,7 @@ ProjectExplorer::DeviceProcessList *QnxDeviceConfiguration::createProcessListMod
     return new QnxDeviceProcessList(sharedFromThis(), parent);
 }
 
-RemoteLinux::AbstractLinuxDeviceTester *QnxDeviceConfiguration::createDeviceTester() const
+ProjectExplorer::DeviceTester *QnxDeviceConfiguration::createDeviceTester() const
 {
     return new QnxDeviceTester;
 }
diff --git a/src/plugins/qnx/qnxdeviceconfiguration.h b/src/plugins/qnx/qnxdeviceconfiguration.h
index 1e2a9d0aefe..5f0ccd9d958 100644
--- a/src/plugins/qnx/qnxdeviceconfiguration.h
+++ b/src/plugins/qnx/qnxdeviceconfiguration.h
@@ -54,7 +54,7 @@ public:
     ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const;
     ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const;
 
-    RemoteLinux::AbstractLinuxDeviceTester *createDeviceTester() const;
+    ProjectExplorer::DeviceTester *createDeviceTester() const;
 
     QString displayType() const;
 
diff --git a/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp b/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp
index d60ec64de17..01ef63389d0 100644
--- a/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp
+++ b/src/plugins/qnx/qnxdeviceconfigurationwizard.cpp
@@ -37,7 +37,6 @@
 
 #include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
 #include <remotelinux/genericlinuxdeviceconfigurationwizardpages.h>
-#include <remotelinux/linuxdevicetestdialog.h>
 #include <utils/portlist.h>
 
 using namespace ProjectExplorer;
@@ -76,8 +75,5 @@ IDevice::Ptr QnxDeviceConfigurationWizard::device()
     device->setSshParameters(sshParams);
     device->setFreePorts(Utils::PortList::fromString(QLatin1String("10000-10100")));
 
-    RemoteLinux::LinuxDeviceTestDialog dlg(device, device->createDeviceTester(), this);
-    dlg.exec();
-
     return device;
 }
diff --git a/src/plugins/qnx/qnxdevicetester.cpp b/src/plugins/qnx/qnxdevicetester.cpp
index c7ce3564833..72dd95c582f 100644
--- a/src/plugins/qnx/qnxdevicetester.cpp
+++ b/src/plugins/qnx/qnxdevicetester.cpp
@@ -38,7 +38,7 @@ using namespace Qnx;
 using namespace Qnx::Internal;
 
 QnxDeviceTester::QnxDeviceTester(QObject *parent)
-    : RemoteLinux::AbstractLinuxDeviceTester(parent)
+    : ProjectExplorer::DeviceTester(parent)
     , m_result(TestSuccess)
     , m_state(Inactive)
     , m_currentCommandIndex(-1)
@@ -70,8 +70,8 @@ void QnxDeviceTester::testDevice(const ProjectExplorer::IDevice::ConstPtr &devic
 
     connect(m_genericTester, SIGNAL(progressMessage(QString)), SIGNAL(progressMessage(QString)));
     connect(m_genericTester, SIGNAL(errorMessage(QString)), SIGNAL(errorMessage(QString)));
-    connect(m_genericTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)),
-        SLOT(handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)));
+    connect(m_genericTester, SIGNAL(finished(ProjectExplorer::DeviceTester::TestResult)),
+        SLOT(handleGenericTestFinished(ProjectExplorer::DeviceTester::TestResult)));
 
     m_state = GenericTest;
     m_genericTester->testDevice(deviceConfiguration);
@@ -96,7 +96,7 @@ void QnxDeviceTester::stopTest()
     setFinished();
 }
 
-void QnxDeviceTester::handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result)
+void QnxDeviceTester::handleGenericTestFinished(TestResult result)
 {
     QTC_ASSERT(m_state == GenericTest, return);
 
diff --git a/src/plugins/qnx/qnxdevicetester.h b/src/plugins/qnx/qnxdevicetester.h
index ccec636f08f..e3bff15a797 100644
--- a/src/plugins/qnx/qnxdevicetester.h
+++ b/src/plugins/qnx/qnxdevicetester.h
@@ -43,7 +43,7 @@ class SshRemoteProcessRunner;
 namespace Qnx {
 namespace Internal {
 
-class QnxDeviceTester : public RemoteLinux::AbstractLinuxDeviceTester
+class QnxDeviceTester : public ProjectExplorer::DeviceTester
 {
     Q_OBJECT
 public:
@@ -53,7 +53,7 @@ public:
     void stopTest();
 
 private slots:
-    void handleGenericTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result);
+    void handleGenericTestFinished(ProjectExplorer::DeviceTester::TestResult result);
 
     void handleProcessFinished(int exitStatus);
     void handleConnectionError();
@@ -70,7 +70,7 @@ private:
 
     RemoteLinux::GenericLinuxDeviceTester *m_genericTester;
     ProjectExplorer::IDevice::ConstPtr m_deviceConfiguration;
-    TestResult m_result;
+    ProjectExplorer::DeviceTester::TestResult m_result;
     State m_state;
 
     int m_currentCommandIndex;
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
index c33bef0c8e5..8ad502a052e 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp
@@ -31,8 +31,6 @@
 
 #include "genericlinuxdeviceconfigurationwizardpages.h"
 #include "linuxdevice.h"
-#include "linuxdevicetestdialog.h"
-#include "linuxdevicetester.h"
 #include "remotelinux_constants.h"
 
 #include <utils/portlist.h>
@@ -91,10 +89,6 @@ IDevice::Ptr GenericLinuxDeviceConfigurationWizard::device()
         Core::Id(Constants::GenericLinuxOsType), IDevice::Hardware);
     device->setFreePorts(Utils::PortList::fromString(QLatin1String("10000-10100")));
     device->setSshParameters(sshParams);
-    // Might be called after accept.
-    QWidget *parent = isVisible() ? this : static_cast<QWidget *>(0);
-    LinuxDeviceTestDialog dlg(device, new GenericLinuxDeviceTester(this), parent);
-    dlg.exec();
     return device;
 }
 
diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp
index 8c530ac3ac3..98625199a0e 100644
--- a/src/plugins/remotelinux/linuxdevice.cpp
+++ b/src/plugins/remotelinux/linuxdevice.cpp
@@ -30,7 +30,7 @@
 #include "linuxdevice.h"
 
 #include "genericlinuxdeviceconfigurationwidget.h"
-#include "linuxdevicetestdialog.h"
+#include "linuxdevicetester.h"
 #include "publickeydeploymentdialog.h"
 #include "remotelinux_constants.h"
 
@@ -192,16 +192,13 @@ ProjectExplorer::IDeviceWidget *LinuxDevice::createWidget()
 
 QList<Core::Id> LinuxDevice::actionIds() const
 {
-    return QList<Core::Id>() << Core::Id(Constants::GenericTestDeviceActionId)
-            << Core::Id(Constants::GenericDeployKeyToDeviceActionId);
+    return QList<Core::Id>() << Core::Id(Constants::GenericDeployKeyToDeviceActionId);
 }
 
 QString LinuxDevice::displayNameForActionId(Core::Id actionId) const
 {
     QTC_ASSERT(actionIds().contains(actionId), return QString());
 
-    if (actionId == Constants::GenericTestDeviceActionId)
-        return tr("Test");
     if (actionId == Constants::GenericDeployKeyToDeviceActionId)
         return tr("Deploy Public Key...");
     return QString(); // Can't happen.
@@ -213,9 +210,7 @@ void LinuxDevice::executeAction(Core::Id actionId, QWidget *parent) const
 
     QDialog *d = 0;
     const LinuxDevice::ConstPtr device = sharedFromThis().staticCast<const LinuxDevice>();
-    if (actionId == Constants::GenericTestDeviceActionId)
-        d = new LinuxDeviceTestDialog(device, createDeviceTester(), parent);
-    else if (actionId == Constants::GenericDeployKeyToDeviceActionId)
+    if (actionId == Constants::GenericDeployKeyToDeviceActionId)
         d = PublicKeyDeploymentDialog::createDialog(device, parent);
     if (d)
         d->exec();
@@ -264,7 +259,7 @@ DeviceProcessList *LinuxDevice::createProcessListModel(QObject *parent) const
     return new LinuxDeviceProcessList(sharedFromThis(), parent);
 }
 
-AbstractLinuxDeviceTester *LinuxDevice::createDeviceTester() const
+DeviceTester *LinuxDevice::createDeviceTester() const
 {
     return new GenericLinuxDeviceTester;
 }
diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h
index 0ec84cd44e0..7e8224a4754 100644
--- a/src/plugins/remotelinux/linuxdevice.h
+++ b/src/plugins/remotelinux/linuxdevice.h
@@ -41,7 +41,6 @@ namespace Utils { class PortList; }
 
 namespace RemoteLinux {
 namespace Internal { class LinuxDevicePrivate; }
-class AbstractLinuxDeviceTester;
 
 class REMOTELINUX_EXPORT LinuxDeviceProcessSupport : public ProjectExplorer::DeviceProcessSupport
 {
@@ -74,7 +73,8 @@ public:
     ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const;
     bool canCreateProcessModel() const { return true; }
     ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const;
-    virtual AbstractLinuxDeviceTester *createDeviceTester() const;
+    bool hasDeviceTester() const { return true; }
+    ProjectExplorer::DeviceTester *createDeviceTester() const;
 
 protected:
     LinuxDevice() {}
diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp
index 9f2fa97143e..7b30be03a97 100644
--- a/src/plugins/remotelinux/linuxdevicetester.cpp
+++ b/src/plugins/remotelinux/linuxdevicetester.cpp
@@ -61,13 +61,8 @@ public:
 
 using namespace Internal;
 
-AbstractLinuxDeviceTester::AbstractLinuxDeviceTester(QObject *parent) : QObject(parent)
-{
-}
-
-
 GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent)
-    : AbstractLinuxDeviceTester(parent), d(new GenericLinuxDeviceTesterPrivate)
+    : DeviceTester(parent), d(new GenericLinuxDeviceTesterPrivate)
 {
 }
 
diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h
index 4ecd8b9af1d..8c3070b0bf6 100644
--- a/src/plugins/remotelinux/linuxdevicetester.h
+++ b/src/plugins/remotelinux/linuxdevicetester.h
@@ -44,27 +44,7 @@ namespace Internal {
 class GenericLinuxDeviceTesterPrivate;
 }
 
-class REMOTELINUX_EXPORT AbstractLinuxDeviceTester : public QObject
-{
-    Q_OBJECT
-
-public:
-    enum TestResult { TestSuccess, TestFailure };
-
-    virtual void testDevice(const ProjectExplorer::IDevice::ConstPtr &deviceConfiguration) = 0;
-    virtual void stopTest() = 0;
-
-signals:
-    void progressMessage(const QString &message);
-    void errorMessage(const QString &message);
-    void finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result);
-
-protected:
-    explicit AbstractLinuxDeviceTester(QObject *parent = 0);
-};
-
-
-class REMOTELINUX_EXPORT GenericLinuxDeviceTester : public AbstractLinuxDeviceTester
+class REMOTELINUX_EXPORT GenericLinuxDeviceTester : public ProjectExplorer::DeviceTester
 {
     Q_OBJECT
 
@@ -85,7 +65,7 @@ private slots:
     void handlePortListReady();
 
 private:
-    void setFinished(TestResult result);
+    void setFinished(ProjectExplorer::DeviceTester::TestResult result);
 
     Internal::GenericLinuxDeviceTesterPrivate * const d;
 };
diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro
index 311cb6d1276..62b3061f409 100644
--- a/src/plugins/remotelinux/remotelinux.pro
+++ b/src/plugins/remotelinux/remotelinux.pro
@@ -35,7 +35,6 @@ HEADERS += \
     packageuploader.h \
     linuxdevicetester.h \
     remotelinux_constants.h \
-    linuxdevicetestdialog.h \
     remotelinuxenvironmentreader.h \
     sshkeydeployer.h \
     typespecificdeviceconfigurationlistmodel.h \
@@ -81,7 +80,6 @@ SOURCES += \
     remotelinuxpackageinstaller.cpp \
     packageuploader.cpp \
     linuxdevicetester.cpp \
-    linuxdevicetestdialog.cpp \
     remotelinuxenvironmentreader.cpp \
     sshkeydeployer.cpp \
     typespecificdeviceconfigurationlistmodel.cpp \
@@ -98,7 +96,6 @@ SOURCES += \
 
 FORMS += \
     genericlinuxdeviceconfigurationwizardsetuppage.ui \
-    linuxdevicetestdialog.ui \
     remotelinuxdeployconfigurationwidget.ui \
     genericlinuxdeviceconfigurationwidget.ui \
     remotelinuxcheckforfreediskspacestepwidget.ui
diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs
index 1458b756a31..7e6ad2b0d2e 100644
--- a/src/plugins/remotelinux/remotelinux.qbs
+++ b/src/plugins/remotelinux/remotelinux.qbs
@@ -46,9 +46,6 @@ QtcPlugin {
         "genericremotelinuxdeploystepfactory.h",
         "linuxdevice.cpp",
         "linuxdevice.h",
-        "linuxdevicetestdialog.cpp",
-        "linuxdevicetestdialog.h",
-        "linuxdevicetestdialog.ui",
         "linuxdevicetester.cpp",
         "linuxdevicetester.h",
         "packageuploader.cpp",
diff --git a/src/plugins/remotelinux/remotelinux_constants.h b/src/plugins/remotelinux/remotelinux_constants.h
index 0cfdfa5200b..42041f3ce58 100644
--- a/src/plugins/remotelinux/remotelinux_constants.h
+++ b/src/plugins/remotelinux/remotelinux_constants.h
@@ -34,7 +34,6 @@ namespace Constants {
 
 const char GenericLinuxOsType[] = "GenericLinuxOsType";
 
-const char GenericTestDeviceActionId[] = "RemoteLinux.GenericTestDeviceAction";
 const char GenericDeployKeyToDeviceActionId[] = "RemoteLinux.GenericDeployKeyToDeviceAction";
 
 const char EMBEDDED_LINUX_QT[] = "RemoteLinux.EmbeddedLinuxQt";
-- 
GitLab