forked from qt-creator/qt-creator
debugger: let debugger attach to currently running process
Change-Id: I4aab1aa84a3dc9211d84d59be76005a8e841239e (cherry picked from commit 55e399b524721e3561b6c7faae8aef84bf064565) Reviewed-on: http://codereview.qt.nokia.com/251 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -520,6 +520,8 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
|
|||||||
|
|
||||||
d->m_inferiorPid = d->m_startParameters.attachPID > 0
|
d->m_inferiorPid = d->m_startParameters.attachPID > 0
|
||||||
? d->m_startParameters.attachPID : 0;
|
? d->m_startParameters.attachPID : 0;
|
||||||
|
if (d->m_inferiorPid)
|
||||||
|
d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
|
||||||
|
|
||||||
if (!d->m_startParameters.environment.size())
|
if (!d->m_startParameters.environment.size())
|
||||||
d->m_startParameters.environment = Utils::Environment();
|
d->m_startParameters.environment = Utils::Environment();
|
||||||
@@ -1174,6 +1176,7 @@ void DebuggerEngine::notifyInferiorPid(qint64 pid)
|
|||||||
return;
|
return;
|
||||||
d->m_inferiorPid = pid;
|
d->m_inferiorPid = pid;
|
||||||
if (pid) {
|
if (pid) {
|
||||||
|
d->m_runControl->setApplicationProcessHandle(ProcessHandle(pid));
|
||||||
showMessage(tr("Taking notice of pid %1").arg(pid));
|
showMessage(tr("Taking notice of pid %1").arg(pid));
|
||||||
if (d->m_startParameters.startMode == StartInternal
|
if (d->m_startParameters.startMode == StartInternal
|
||||||
|| d->m_startParameters.startMode == StartExternal
|
|| d->m_startParameters.startMode == StartExternal
|
||||||
|
@@ -688,9 +688,10 @@ public slots:
|
|||||||
void startRemoteApplication();
|
void startRemoteApplication();
|
||||||
void startRemoteEngine();
|
void startRemoteEngine();
|
||||||
void attachExternalApplication();
|
void attachExternalApplication();
|
||||||
|
Q_SLOT void attachExternalApplication(ProjectExplorer::RunControl *rc);
|
||||||
void attachExternalApplication(qint64 pid, const QString &binary,
|
void attachExternalApplication(qint64 pid, const QString &binary,
|
||||||
const ProjectExplorer::Abi &abi = ProjectExplorer::Abi(),
|
const ProjectExplorer::Abi &abi,
|
||||||
const QString &debuggerCommand = QString());
|
const QString &debuggerCommand);
|
||||||
void runScheduled();
|
void runScheduled();
|
||||||
void attachCore();
|
void attachCore();
|
||||||
void attachCore(const QString &core, const QString &exeFileName,
|
void attachCore(const QString &core, const QString &exeFileName,
|
||||||
@@ -1065,6 +1066,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
|
|||||||
m_dummyEngine(0),
|
m_dummyEngine(0),
|
||||||
m_globalDebuggerOptions(new GlobalDebuggerOptions)
|
m_globalDebuggerOptions(new GlobalDebuggerOptions)
|
||||||
{
|
{
|
||||||
|
setObjectName("DebuggerCore");
|
||||||
qRegisterMetaType<WatchData>("WatchData");
|
qRegisterMetaType<WatchData>("WatchData");
|
||||||
qRegisterMetaType<ContextData>("ContextData");
|
qRegisterMetaType<ContextData>("ContextData");
|
||||||
qRegisterMetaType<DebuggerStartParameters>("DebuggerStartParameters");
|
qRegisterMetaType<DebuggerStartParameters>("DebuggerStartParameters");
|
||||||
@@ -1434,6 +1436,18 @@ void DebuggerPluginPrivate::attachExternalApplication(qint64 pid, const QString
|
|||||||
startDebugger(rc);
|
startDebugger(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebuggerPluginPrivate::attachExternalApplication(ProjectExplorer::RunControl *rc)
|
||||||
|
{
|
||||||
|
DebuggerStartParameters sp;
|
||||||
|
sp.attachPID = rc->applicationProcessHandle().pid();
|
||||||
|
sp.displayName = tr("Debugger attached to %1").arg(rc->displayName());
|
||||||
|
sp.startMode = AttachExternal;
|
||||||
|
//sp.toolChainAbi = abiOfBinary(sp.executable);
|
||||||
|
sp.toolChainAbi = ProjectExplorer::Abi::hostAbi(); // FIXME: Extract from RunControl?
|
||||||
|
if (DebuggerRunControl *rc = createDebugger(sp))
|
||||||
|
startDebugger(rc);
|
||||||
|
}
|
||||||
|
|
||||||
void DebuggerPluginPrivate::attachCore()
|
void DebuggerPluginPrivate::attachCore()
|
||||||
{
|
{
|
||||||
AttachCoreDialog dlg(mainWindow());
|
AttachCoreDialog dlg(mainWindow());
|
||||||
@@ -2538,6 +2552,8 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
|||||||
Core::ActionManager *am = core->actionManager();
|
Core::ActionManager *am = core->actionManager();
|
||||||
QTC_ASSERT(am, return);
|
QTC_ASSERT(am, return);
|
||||||
|
|
||||||
|
m_plugin->addObject(this);
|
||||||
|
|
||||||
const Context globalcontext(CC::C_GLOBAL);
|
const Context globalcontext(CC::C_GLOBAL);
|
||||||
const Context cppDebuggercontext(C_CPPDEBUGGER);
|
const Context cppDebuggercontext(C_CPPDEBUGGER);
|
||||||
const Context qmlDebuggerContext(C_QMLDEBUGGER);
|
const Context qmlDebuggerContext(C_QMLDEBUGGER);
|
||||||
@@ -3128,6 +3144,7 @@ void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName,
|
|||||||
|
|
||||||
void DebuggerPluginPrivate::aboutToShutdown()
|
void DebuggerPluginPrivate::aboutToShutdown()
|
||||||
{
|
{
|
||||||
|
m_plugin->removeObject(this);
|
||||||
disconnect(sessionManager(),
|
disconnect(sessionManager(),
|
||||||
SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
|
SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
|
||||||
this, 0);
|
this, 0);
|
||||||
|
@@ -46,6 +46,8 @@
|
|||||||
#include <aggregation/aggregate.h>
|
#include <aggregation/aggregate.h>
|
||||||
#include <texteditor/fontsettings.h>
|
#include <texteditor/fontsettings.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
#include <extensionsystem/invoker.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/outputformatter.h>
|
#include <utils/outputformatter.h>
|
||||||
@@ -62,6 +64,11 @@ enum { debug = 0 };
|
|||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace ProjectExplorer::Internal;
|
using namespace ProjectExplorer::Internal;
|
||||||
|
|
||||||
|
static QObject *debuggerCore()
|
||||||
|
{
|
||||||
|
return ExtensionSystem::PluginManager::instance()->getObjectByName("DebuggerCore");
|
||||||
|
}
|
||||||
|
|
||||||
AppOutputPane::RunControlTab::RunControlTab(RunControl *rc, Core::OutputWindow *w) :
|
AppOutputPane::RunControlTab::RunControlTab(RunControl *rc, Core::OutputWindow *w) :
|
||||||
runControl(rc), window(w), asyncClosing(false)
|
runControl(rc), window(w), asyncClosing(false)
|
||||||
{
|
{
|
||||||
@@ -72,7 +79,8 @@ AppOutputPane::AppOutputPane() :
|
|||||||
m_tabWidget(new QTabWidget),
|
m_tabWidget(new QTabWidget),
|
||||||
m_stopAction(new QAction(QIcon(QLatin1String(Constants::ICON_STOP)), tr("Stop"), this)),
|
m_stopAction(new QAction(QIcon(QLatin1String(Constants::ICON_STOP)), tr("Stop"), this)),
|
||||||
m_reRunButton(new QToolButton),
|
m_reRunButton(new QToolButton),
|
||||||
m_stopButton(new QToolButton)
|
m_stopButton(new QToolButton),
|
||||||
|
m_attachButton(new QToolButton)
|
||||||
{
|
{
|
||||||
// Rerun
|
// Rerun
|
||||||
m_reRunButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL));
|
m_reRunButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL));
|
||||||
@@ -97,6 +105,15 @@ AppOutputPane::AppOutputPane() :
|
|||||||
connect(m_stopAction, SIGNAL(triggered()),
|
connect(m_stopAction, SIGNAL(triggered()),
|
||||||
this, SLOT(stopRunControl()));
|
this, SLOT(stopRunControl()));
|
||||||
|
|
||||||
|
// Attach
|
||||||
|
m_attachButton->setToolTip(tr("Attach debugger to this process"));
|
||||||
|
m_attachButton->setEnabled(false);
|
||||||
|
m_attachButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_DEBUG_SMALL));
|
||||||
|
m_attachButton->setAutoRaise(true);
|
||||||
|
|
||||||
|
connect(m_attachButton, SIGNAL(clicked()),
|
||||||
|
this, SLOT(attachToRunControl()));
|
||||||
|
|
||||||
// Spacer (?)
|
// Spacer (?)
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
@@ -185,7 +202,7 @@ QWidget *AppOutputPane::outputWidget(QWidget *)
|
|||||||
|
|
||||||
QList<QWidget*> AppOutputPane::toolBarWidgets() const
|
QList<QWidget*> AppOutputPane::toolBarWidgets() const
|
||||||
{
|
{
|
||||||
return QList<QWidget*>() << m_reRunButton << m_stopButton;
|
return QList<QWidget*>() << m_reRunButton << m_stopButton << m_attachButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AppOutputPane::displayName() const
|
QString AppOutputPane::displayName() const
|
||||||
@@ -313,6 +330,15 @@ void AppOutputPane::reRunRunControl()
|
|||||||
tab.runControl->start();
|
tab.runControl->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppOutputPane::attachToRunControl()
|
||||||
|
{
|
||||||
|
const int index = currentIndex();
|
||||||
|
QTC_ASSERT(index != -1, return);
|
||||||
|
ProjectExplorer::RunControl *rc = m_runControlTabs.at(index).runControl;
|
||||||
|
QTC_ASSERT(rc->isRunning(), return);
|
||||||
|
ExtensionSystem::Invoker<void>(debuggerCore(), "attachExternalApplication", rc);
|
||||||
|
}
|
||||||
|
|
||||||
void AppOutputPane::stopRunControl()
|
void AppOutputPane::stopRunControl()
|
||||||
{
|
{
|
||||||
const int index = currentIndex();
|
const int index = currentIndex();
|
||||||
@@ -399,6 +425,7 @@ void AppOutputPane::tabChanged(int i)
|
|||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
m_stopAction->setEnabled(false);
|
m_stopAction->setEnabled(false);
|
||||||
m_reRunButton->setEnabled(false);
|
m_reRunButton->setEnabled(false);
|
||||||
|
m_attachButton->setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
const int index = indexOf(m_tabWidget->widget(i));
|
const int index = indexOf(m_tabWidget->widget(i));
|
||||||
QTC_ASSERT(index != -1, return; )
|
QTC_ASSERT(index != -1, return; )
|
||||||
@@ -407,6 +434,7 @@ void AppOutputPane::tabChanged(int i)
|
|||||||
m_stopAction->setEnabled(rc->isRunning());
|
m_stopAction->setEnabled(rc->isRunning());
|
||||||
m_reRunButton->setEnabled(!rc->isRunning());
|
m_reRunButton->setEnabled(!rc->isRunning());
|
||||||
m_reRunButton->setIcon(rc->icon());
|
m_reRunButton->setIcon(rc->icon());
|
||||||
|
m_attachButton->setEnabled(debuggerCore());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,6 +444,7 @@ void AppOutputPane::runControlStarted()
|
|||||||
if (current && current == sender()) {
|
if (current && current == sender()) {
|
||||||
m_reRunButton->setEnabled(false);
|
m_reRunButton->setEnabled(false);
|
||||||
m_stopAction->setEnabled(true);
|
m_stopAction->setEnabled(true);
|
||||||
|
m_attachButton->setEnabled(debuggerCore());
|
||||||
m_reRunButton->setIcon(current->icon());
|
m_reRunButton->setIcon(current->icon());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,6 +466,7 @@ void AppOutputPane::runControlFinished()
|
|||||||
if (current && current == sender()) {
|
if (current && current == sender()) {
|
||||||
m_reRunButton->setEnabled(true);
|
m_reRunButton->setEnabled(true);
|
||||||
m_stopAction->setEnabled(false);
|
m_stopAction->setEnabled(false);
|
||||||
|
m_attachButton->setEnabled(false);
|
||||||
m_reRunButton->setIcon(current->icon());
|
m_reRunButton->setIcon(current->icon());
|
||||||
}
|
}
|
||||||
// Check for asynchronous close. Close the tab.
|
// Check for asynchronous close. Close the tab.
|
||||||
|
@@ -97,6 +97,7 @@ public slots:
|
|||||||
private slots:
|
private slots:
|
||||||
void reRunRunControl();
|
void reRunRunControl();
|
||||||
void stopRunControl();
|
void stopRunControl();
|
||||||
|
void attachToRunControl();
|
||||||
bool closeTab(int index);
|
bool closeTab(int index);
|
||||||
void tabChanged(int);
|
void tabChanged(int);
|
||||||
void runControlStarted();
|
void runControlStarted();
|
||||||
@@ -132,6 +133,7 @@ private:
|
|||||||
QAction *m_stopAction;
|
QAction *m_stopAction;
|
||||||
QToolButton *m_reRunButton;
|
QToolButton *m_reRunButton;
|
||||||
QToolButton *m_stopButton;
|
QToolButton *m_stopButton;
|
||||||
|
QToolButton *m_attachButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -109,6 +109,7 @@ void LocalApplicationRunControl::start()
|
|||||||
emit finished();
|
emit finished();
|
||||||
} else {
|
} else {
|
||||||
m_applicationLauncher.start(m_runMode, m_executable, m_commandLineArguments);
|
m_applicationLauncher.start(m_runMode, m_executable, m_commandLineArguments);
|
||||||
|
setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
|
||||||
QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));
|
QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));
|
||||||
appendMessage(msg, Utils::NormalMessageFormat);
|
appendMessage(msg, Utils::NormalMessageFormat);
|
||||||
}
|
}
|
||||||
|
@@ -71,6 +71,7 @@ private:
|
|||||||
QString m_executable;
|
QString m_executable;
|
||||||
QString m_commandLineArguments;
|
QString m_commandLineArguments;
|
||||||
ProjectExplorer::ApplicationLauncher::Mode m_runMode;
|
ProjectExplorer::ApplicationLauncher::Mode m_runMode;
|
||||||
|
ProcessHandle m_applicationProcessHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -150,6 +150,12 @@ IRunConfigurationFactory *findRunConfigurationFactory(RunConfigurationFactoryMat
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class ProjectExplorer::ProcessHandle
|
||||||
|
\brief Helper class to describe a process.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class ProjectExplorer::RunConfiguration
|
\class ProjectExplorer::RunConfiguration
|
||||||
\brief Base class for a run configuration. A run configuration specifies how a
|
\brief Base class for a run configuration. A run configuration specifies how a
|
||||||
@@ -351,6 +357,7 @@ Utils::OutputFormatter *RunConfiguration::createOutputFormatter() const
|
|||||||
return new Utils::OutputFormatter();
|
return new Utils::OutputFormatter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class ProjectExplorer::IRunConfigurationFactory
|
\class ProjectExplorer::IRunConfigurationFactory
|
||||||
|
|
||||||
@@ -492,6 +499,16 @@ QString RunControl::displayName() const
|
|||||||
return m_displayName;
|
return m_displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessHandle RunControl::applicationProcessHandle() const
|
||||||
|
{
|
||||||
|
return m_applicationProcessHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
|
||||||
|
{
|
||||||
|
m_applicationProcessHandle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
bool RunControl::promptToStop(bool *optionalPrompt) const
|
bool RunControl::promptToStop(bool *optionalPrompt) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(isRunning(), return true;)
|
QTC_ASSERT(isRunning(), return true;)
|
||||||
|
@@ -51,6 +51,20 @@ class IRunConfigurationAspect;
|
|||||||
class RunControl;
|
class RunControl;
|
||||||
class Target;
|
class Target;
|
||||||
|
|
||||||
|
// FIXME: This should also contain a handle to an remote device if used.
|
||||||
|
class PROJECTEXPLORER_EXPORT ProcessHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ProcessHandle(quint64 pid = 0) : m_pid(pid) {}
|
||||||
|
|
||||||
|
bool isValid() const { return m_pid != 0; }
|
||||||
|
void setPid(quint64 pid) { m_pid = pid; }
|
||||||
|
quint64 pid() const { return m_pid; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
quint64 m_pid;
|
||||||
|
};
|
||||||
|
|
||||||
// Documentation inside.
|
// Documentation inside.
|
||||||
class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
|
class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
|
||||||
{
|
{
|
||||||
@@ -210,6 +224,9 @@ public:
|
|||||||
virtual QString displayName() const;
|
virtual QString displayName() const;
|
||||||
virtual QIcon icon() const = 0;
|
virtual QIcon icon() const = 0;
|
||||||
|
|
||||||
|
ProcessHandle applicationProcessHandle() const;
|
||||||
|
void setApplicationProcessHandle(const ProcessHandle &handle);
|
||||||
|
|
||||||
bool sameRunConfiguration(const RunControl *other) const;
|
bool sameRunConfiguration(const RunControl *other) const;
|
||||||
|
|
||||||
Utils::OutputFormatter *outputFormatter();
|
Utils::OutputFormatter *outputFormatter();
|
||||||
@@ -240,6 +257,9 @@ private:
|
|||||||
const QWeakPointer<RunConfiguration> m_runConfiguration;
|
const QWeakPointer<RunConfiguration> m_runConfiguration;
|
||||||
Utils::OutputFormatter *m_outputFormatter;
|
Utils::OutputFormatter *m_outputFormatter;
|
||||||
|
|
||||||
|
// A handle to the actual application process.
|
||||||
|
ProcessHandle m_applicationProcessHandle;
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
//these two are used to bring apps in the foreground on Mac
|
//these two are used to bring apps in the foreground on Mac
|
||||||
qint64 m_internalPid;
|
qint64 m_internalPid;
|
||||||
@@ -251,5 +271,6 @@ private:
|
|||||||
|
|
||||||
// Allow a RunConfiguration to be stored in a QVariant
|
// Allow a RunConfiguration to be stored in a QVariant
|
||||||
Q_DECLARE_METATYPE(ProjectExplorer::RunConfiguration*)
|
Q_DECLARE_METATYPE(ProjectExplorer::RunConfiguration*)
|
||||||
|
Q_DECLARE_METATYPE(ProjectExplorer::RunControl*)
|
||||||
|
|
||||||
#endif // RUNCONFIGURATION_H
|
#endif // RUNCONFIGURATION_H
|
||||||
|
@@ -96,7 +96,7 @@ void QmlProjectRunControl::start()
|
|||||||
{
|
{
|
||||||
m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable,
|
m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable,
|
||||||
m_commandLineArguments);
|
m_commandLineArguments);
|
||||||
|
setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
|
||||||
emit started();
|
emit started();
|
||||||
QString msg = tr("Starting %1 %2\n")
|
QString msg = tr("Starting %1 %2\n")
|
||||||
.arg(QDir::toNativeSeparators(m_executable), m_commandLineArguments);
|
.arg(QDir::toNativeSeparators(m_executable), m_commandLineArguments);
|
||||||
|
@@ -348,13 +348,14 @@ S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runCon
|
|||||||
this, SLOT(slotAppendMessage(QString, Utils::OutputFormat)));
|
this, SLOT(slotAppendMessage(QString, Utils::OutputFormat)));
|
||||||
connect(&m_applicationLauncher, SIGNAL(processExited(int)),
|
connect(&m_applicationLauncher, SIGNAL(processExited(int)),
|
||||||
this, SLOT(processExited(int)));
|
this, SLOT(processExited(int)));
|
||||||
connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
|
connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(quint64)),
|
||||||
this, SLOT(bringApplicationToForeground(qint64)));
|
this, SLOT(bringApplicationToForeground(quint64)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void S60EmulatorRunControl::start()
|
void S60EmulatorRunControl::start()
|
||||||
{
|
{
|
||||||
m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QString());
|
m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QString());
|
||||||
|
setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
|
||||||
emit started();
|
emit started();
|
||||||
|
|
||||||
QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));
|
QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));
|
||||||
|
Reference in New Issue
Block a user