diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 0543f9c54f7be241e5255986d18c98eeae55bebb..ba1feb77f96fb0be5e266e6496b5a167d4da246a 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -113,7 +113,9 @@ public: QString symbolFileName; QString serverStartScript; QString sysRoot; + QString debuggerCommand; int toolChainType; + QString remoteDumperLib; QString dumperLibrary; QStringList dumperLibraryLocations; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index f9ae5cd24c1386c4c7397b6accc608e9f268122c..9ce3c0ef81a646866b1158f4e5a886c9407d8801 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -451,6 +451,7 @@ void DebuggerPlugin::shutdown() delete m_locationMark; m_locationMark = 0; + removeObject(m_manager); delete m_manager; m_manager = 0; } @@ -545,6 +546,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess } m_manager = new DebuggerManager; + ExtensionSystem::PluginManager::instance()->addObject(m_manager); const QList<Core::IOptionsPage *> engineOptionPages = m_manager->initializeEngines(m_cmdLineEnabledEngines); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 874488e6e24593ef9372910d02d1173c9ec82c68..343066a71e772f962d9f58aa9f0bc400888d55cf 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3796,47 +3796,56 @@ void GdbEngine::tryLoadDebuggingHelpers() } m_debuggingHelperState = DebuggingHelperLoadTried; + const QString dlopenLib = + (startParameters().startMode == StartRemote) + ? startParameters().remoteDumperLib : lib; #if defined(Q_OS_WIN) if (m_dumperInjectionLoad) { /// Launch asynchronous remote thread to load. SharedLibraryInjector injector(inferiorPid()); QString errorMessage; - if (injector.remoteInject(lib, false, &errorMessage)) { - debugMessage(tr("Dumper injection loading triggered (%1)...").arg(lib)); + if (injector.remoteInject(dlopenLib, false, &errorMessage)) { + debugMessage(tr("Dumper injection loading triggered (%1)..."). + arg(dlopenLib)); } else { - debugMessage(tr("Dumper loading (%1) failed: %2").arg(lib, errorMessage)); + debugMessage(tr("Dumper loading (%1) failed: %2"). + arg(dlopenLib, errorMessage)); debugMessage(errorMessage); manager()->showQtDumperLibraryWarning(errorMessage); m_debuggingHelperState = DebuggingHelperUnavailable; return; } } else { - debugMessage(tr("Loading dumpers via debugger call (%1)...").arg(lib)); + debugMessage(tr("Loading dumpers via debugger call (%1)..."). + arg(dlopenLib)); postCommand(_("sharedlibrary .*")); // for LoadLibraryA //postCommand(_("handle SIGSEGV pass stop print")); //postCommand(_("set unwindonsignal off")); - postCommand(_("call LoadLibraryA(\"") + GdbMi::escapeCString(lib) + _("\")"), + postCommand(_("call LoadLibraryA(\"") + GdbMi::escapeCString(dlopenLib) + _("\")"), CB(handleDebuggingHelperSetup)); - postCommand(_("sharedlibrary ") + dotEscape(lib)); + postCommand(_("sharedlibrary ") + dotEscape(dlopenLib)); } #elif defined(Q_OS_MAC) //postCommand(_("sharedlibrary libc")); // for malloc //postCommand(_("sharedlibrary libdl")); // for dlopen - postCommand(_("call (void)dlopen(\"") + GdbMi::escapeCString(lib) + _("\", " STRINGIFY(RTLD_NOW) ")"), + postCommand(_("call (void)dlopen(\"") + GdbMi::escapeCString(dlopenLib) + + _("\", " STRINGIFY(RTLD_NOW) ")"), CB(handleDebuggingHelperSetup)); - //postCommand(_("sharedlibrary ") + dotEscape(lib)); + //postCommand(_("sharedlibrary ") + dotEscape(dlopenLib)); m_debuggingHelperState = DebuggingHelperLoadTried; #else //postCommand(_("p dlopen")); QString flag = QString::number(RTLD_NOW); postCommand(_("sharedlibrary libc")); // for malloc postCommand(_("sharedlibrary libdl")); // for dlopen - postCommand(_("call (void*)dlopen(\"") + GdbMi::escapeCString(lib) + _("\", " STRINGIFY(RTLD_NOW) ")"), + postCommand(_("call (void*)dlopen(\"") + GdbMi::escapeCString(dlopenLib) + + _("\", " STRINGIFY(RTLD_NOW) ")"), CB(handleDebuggingHelperSetup)); // some older systems like CentOS 4.6 prefer this: - postCommand(_("call (void*)__dlopen(\"") + GdbMi::escapeCString(lib) + _("\", " STRINGIFY(RTLD_NOW) ")"), + postCommand(_("call (void*)__dlopen(\"") + GdbMi::escapeCString(dlopenLib) + + _("\", " STRINGIFY(RTLD_NOW) ")"), CB(handleDebuggingHelperSetup)); - postCommand(_("sharedlibrary ") + dotEscape(lib)); + postCommand(_("sharedlibrary ") + dotEscape(dlopenLib)); #endif if (!m_dumperInjectionLoad) tryQueryDebuggingHelpers(); diff --git a/src/plugins/debugger/gdb/remotegdbadapter.cpp b/src/plugins/debugger/gdb/remotegdbadapter.cpp index 0a32bfc28b2cbb6c7aa4c2ff75cf8c4eb2c7db37..a8347ac33909da4f4d3d1fc2f35d7381c49e075c 100644 --- a/src/plugins/debugger/gdb/remotegdbadapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbadapter.cpp @@ -160,6 +160,8 @@ void RemoteGdbAdapter::startInferior() m_engine->postCommand(_("set architecture %1") .arg(startParameters().remoteArchitecture)); m_engine->postCommand(_("set sysroot %1").arg(startParameters().sysRoot)); + m_engine->postCommand(_("set solib-search-path %1"). + arg(QFileInfo(startParameters().dumperLibrary).path())); if (!startParameters().processArgs.isEmpty()) m_engine->postCommand(_("-exec-arguments ") diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index 7626445a8dedb678dc2f5f98fdfab13df7881b26..02608a6c2937c6ad9ce8606b38bc6a7933630e0e 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -127,6 +127,8 @@ QString ToolChain::toolChainName(ToolChainType tc) return QCoreApplication::translate("ToolChain", "RVCT (ARMV5)"); case RVCT_ARMV6: return QCoreApplication::translate("ToolChain", "RVCT (ARMV6)"); + case GCC_MAEMO: + return QCoreApplication::translate("ToolChain", "GCC for Maemo"); case OTHER: return QCoreApplication::translate("ToolChain", "Other"); case INVALID: diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index b3a11cb7be28305f4bd3e2519503d9e192ee77a8..26863c0245e6ecaccd14a9ca559b4172b8ae2246 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -83,7 +83,8 @@ public: GCCE = 6, RVCT_ARMV5 = 7, RVCT_ARMV6 = 8, - LAST_VALID = 9, + GCC_MAEMO = 9, + LAST_VALID = 10, OTHER = 200, UNKNOWN = 201, INVALID = 202 diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec index 0dc3a49bcb4069eaffc972c951df79465ad5ae5a..a39d5609fa6cc53b399d62069509a67f47043acf 100644 --- a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec +++ b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec @@ -25,5 +25,6 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license> <dependency name="CppEditor" version="1.3.80"/> <dependency name="Help" version="1.3.80"/> <dependency name="Designer" version="1.3.80"/> + <dependency name="Debugger" version="1.3.80"/> </dependencyList> </plugin> diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp index fc6296576ab00e3d25b14cdea7acfc8acbc3b174..84a1b5cf47327db0d61c597a85bb360919e3eb2d 100644 --- a/src/plugins/qt4projectmanager/qmakestep.cpp +++ b/src/plugins/qt4projectmanager/qmakestep.cpp @@ -68,6 +68,12 @@ QStringList QMakeStep::arguments(const QString &buildConfiguration) arguments << "-r"; +#ifdef Q_OS_WIN + ToolChain::ToolChainType type = m_pro->toolChainType(bc); + if (type == ToolChain::GCC_MAEMO) + arguments << QLatin1String("-unix"); +#endif + if (bc->value("buildConfiguration").isValid()) { QStringList configarguments; QtVersion::QmakeBuildConfig defaultBuildConfiguration = m_pro->qtVersion(bc)->defaultBuildConfig(); diff --git a/src/plugins/qt4projectmanager/qt-maemo/images/qemu-run.png b/src/plugins/qt4projectmanager/qt-maemo/images/qemu-run.png new file mode 100644 index 0000000000000000000000000000000000000000..dc4f5190a23303d00a8ef896c8db32038a70a722 Binary files /dev/null and b/src/plugins/qt4projectmanager/qt-maemo/images/qemu-run.png differ diff --git a/src/plugins/qt4projectmanager/qt-maemo/images/qemu-stop.png b/src/plugins/qt4projectmanager/qt-maemo/images/qemu-stop.png new file mode 100644 index 0000000000000000000000000000000000000000..53d0663d6ef4964b979faebd7614a71fc58b22f8 Binary files /dev/null and b/src/plugins/qt4projectmanager/qt-maemo/images/qemu-stop.png differ diff --git a/src/plugins/qt4projectmanager/qt-maemo/images/qemu.xcf b/src/plugins/qt4projectmanager/qt-maemo/images/qemu.xcf new file mode 100644 index 0000000000000000000000000000000000000000..226dd2b30a66259e6259de72f25bdab958da43da Binary files /dev/null and b/src/plugins/qt4projectmanager/qt-maemo/images/qemu.xcf differ diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d1049ee5da8314b303870a20f01fc3087e9272b --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp @@ -0,0 +1,158 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "maemomanager.h" + +#include "maemotoolchain.h" +#include "maemorunconfiguration.h" + +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/coreconstants.h> +#include <coreplugin/icore.h> +#include <coreplugin/modemanager.h> +#include <extensionsystem/pluginmanager.h> + +#include <QtCore/QList> +#include <QtCore/QMutexLocker> + +#include <QtGui/QAction> + +namespace Qt4ProjectManager { + namespace Internal { + + +QMutex MaemoManager::m_mutex; +MaemoManager *MaemoManager::m_instance = 0; + +const QSize iconSize = QSize(24, 20); + +MaemoManager::MaemoManager() + : QObject(0) + , m_runControlFactory(new MaemoRunControlFactory(this)) + , m_runConfigurationFactory(new MaemoRunConfigurationFactory(this)) + , m_qemuCommand(0) +{ + + icon.addFile(":/qt-maemo/images/qemu-run.png", iconSize); + icon.addFile(":/qt-maemo/images/qemu-stop.png", iconSize, QIcon::Normal, + QIcon::On); + + ExtensionSystem::PluginManager::instance()->addObject(m_runControlFactory); + ExtensionSystem::PluginManager::instance()->addObject(m_runConfigurationFactory); +} + +MaemoManager::~MaemoManager() +{ + ExtensionSystem::PluginManager::instance()->removeObject(m_runControlFactory); + ExtensionSystem::PluginManager::instance()->removeObject(m_runConfigurationFactory); +} + +MaemoManager *MaemoManager::instance() +{ + if (!m_instance) { + QMutexLocker _(&m_mutex); + if (!m_instance) + m_instance = new MaemoManager; + } + return m_instance; +} + +ProjectExplorer::ToolChain* +MaemoManager::maemoToolChain(const QtVersion *version) const +{ + return new MaemoToolChain(version); +} + +void +MaemoManager::addQemuSimulatorStarter(Project *project) +{ + projects.insert(project); + + if (m_qemuCommand) { + m_qemuCommand->action()->setVisible(true); + return; + } + + Core::ICore *core = Core::ICore::instance(); + Core::ModeManager *modeManager = core->modeManager(); + Core::ActionManager *actionManager = core->actionManager(); + + QAction *action = new QAction("Qemu", this); + action->setIcon(icon.pixmap(iconSize)); + action->setToolTip(tr("Start Qemu")); + m_qemuCommand = actionManager->registerAction(action, "qemu", + QList<int>() << Core::Constants::C_GLOBAL_ID); + modeManager->addAction(m_qemuCommand, 1); + m_qemuCommand->action()->setEnabled(true); + m_qemuCommand->setAttribute(Core::Command::CA_UpdateText); + m_qemuCommand->setAttribute(Core::Command::CA_UpdateIcon); + + connect(m_qemuCommand->action(), SIGNAL(triggered()), this, SLOT(triggered())); +} + +void +MaemoManager::removeQemuSimulatorStarter(Project *project) +{ + projects.remove(project); + if (projects.isEmpty() && m_qemuCommand) + m_qemuCommand->action()->setVisible(false); +} + +void +MaemoManager::setQemuSimulatorStarterEnabled(bool enable) +{ + if (m_qemuCommand) + m_qemuCommand->action()->setEnabled(enable); +} + +void +MaemoManager::triggered() +{ + emit startStopQemu(); +} + +void +MaemoManager::updateQemuSimulatorStarter(bool running) +{ + if (m_qemuCommand) { + QIcon::State state = QIcon::Off; + QString toolTip(tr("Start Qemu")); + if (running) { + state = QIcon::On; + toolTip = tr("Stop Qemu"); + } + + QAction *action = m_qemuCommand->action(); + action->setToolTip(toolTip); + action->setIcon(icon.pixmap(iconSize, QIcon::Normal, state)); + } +} + + } // namespace Internal +} // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h new file mode 100644 index 0000000000000000000000000000000000000000..f76c83346ab4e0238ec82931d8d4c33b8cc9df0a --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h @@ -0,0 +1,103 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef MAEMOMANAGER_H +#define MAEMOMANAGER_H + +#include "qtversionmanager.h" + +#include <coreplugin/actionmanager/command.h> + +#include <QtCore/QMutex> +#include <QtCore/QObject> +#include <QtCore/QSet> + +#include <QtGui/QIcon> + +QT_BEGIN_NAMESPACE +class QAction; +QT_END_NAMESPACE + +namespace ProjectExplorer { + class Project; + class ToolChain; +} +using ProjectExplorer::Project; +using ProjectExplorer::ToolChain; + +namespace Qt4ProjectManager { + class QtVersion; + namespace Internal { + +class MaemoRunControlFactory; +class MaemoRunConfigurationFactory; + +class MaemoManager : public QObject +{ + Q_OBJECT + +public: + static MaemoManager *instance(); + + void addVersion(const Qt4ProjectManager::QtVersion *version) { Q_UNUSED(version); } + ToolChain *maemoToolChain(const Qt4ProjectManager::QtVersion *version) const; + + void addQemuSimulatorStarter(Project *project); + void removeQemuSimulatorStarter(Project *project); + + void setQemuSimulatorStarterEnabled(bool state); + +public slots: + void triggered(); + void updateQemuSimulatorStarter(bool running); + +signals: + void startStopQemu(); + +private: + MaemoManager(); + ~MaemoManager(); + +private: + static QMutex m_mutex; + static MaemoManager *m_instance; + + MaemoRunControlFactory *m_runControlFactory; + MaemoRunConfigurationFactory *m_runConfigurationFactory; + + QIcon icon; + int m_runCount; + QSet<Project*> projects; + Core::Command *m_qemuCommand; +}; + + } // namespace Internal +} // namespace Qt4ProjectManager + +#endif // MAEMOMANAGER_H diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5a46a1d9414b5fc64ecaced3069bd5491a9920f --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp @@ -0,0 +1,1497 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "maemorunconfiguration.h" + +#include "maemomanager.h" +#include "maemotoolchain.h" +#include "profilereader.h" +#include "qt4project.h" + +#include <coreplugin/icore.h> +#include <coreplugin/messagemanager.h> +#include <debugger/debuggermanager.h> +#include <extensionsystem/pluginmanager.h> +#include <utils/pathchooser.h> +#include <utils/qtcassert.h> +#include <projectexplorer/persistentsettings.h> +#include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/session.h> + +#include <QtCore/QDebug> +#include <QtCore/QProcess> +#include <QtCore/QSharedPointer> + +#include <QtGui/QCheckBox> +#include <QtGui/QFormLayout> +#include <QtGui/QFrame> +#include <QtGui/QHBoxLayout> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> +#include <QtGui/QRadioButton> + +using namespace ProjectExplorer; + +namespace Qt4ProjectManager { +namespace Internal { + +class MaemoRunConfigurationWidget : public QWidget +{ + Q_OBJECT +public: + MaemoRunConfigurationWidget( + MaemoRunConfiguration *runConfiguration, QWidget *parent = 0); + +private slots: + void configNameEdited(const QString &text); + void argumentsEdited(const QString &args); + void hostNameEdited(const QString &name); + void userNameEdited(const QString &name); + void portEdited(const QString &port); + void hostTypeChanged(); + +#if USE_SSL_PASSWORD + void passwordUseChanged(); + void passwordEdited(const QString &password); +#endif + + void updateTargetInformation(); + void updateVisibleSimulatorParameter(); + +private: + QLineEdit *m_configNameLineEdit; + QLineEdit *m_argsLineEdit; + QLineEdit *m_hostNameLineEdit; + QLineEdit *m_userLineEdit; + QLineEdit *m_passwordLineEdit; + QLineEdit *m_portLineEdit; + QLabel *m_executableLabel; + QLabel *m_debuggerLabel; + QLabel *m_simParamsValueLabel; + QLabel *m_chooseSimPathLabel; + QLabel *m_simParamsNameLabel; + QCheckBox *m_passwordCheckBox; + QRadioButton *m_hwButton; + QRadioButton *m_simButton; + Utils::PathChooser *m_simPathChooser; + MaemoRunConfiguration *m_runConfiguration; +}; + +class AbstractMaemoRunControl : public ProjectExplorer::RunControl +{ + Q_OBJECT + +public: + AbstractMaemoRunControl(RunConfig runConfig); + virtual ~AbstractMaemoRunControl() {} + +protected: + void startDeployment(bool forDebugging); + void stopDeployment(); + bool isDeploying() const; + const QString executableOnHost() const; + const QString executableOnTarget() const; + const QString executableFileName() const; + const QString port() const; + const QString targetCmdLinePrefix() const; + virtual void deploymentFinished(bool success)=0; + virtual bool setProcessEnvironment(QProcess &process); + +private slots: + void readStandardError(); + void readStandardOutput(); + void deployProcessFinished(); + +protected: + ErrorDumper dumper; + const QSharedPointer<MaemoRunConfiguration> runConfig; + +private: + QProcess deployProcess; + bool deployingExecutable; + bool deployingDumperLib; +}; + +class MaemoRunControl : public AbstractMaemoRunControl +{ + Q_OBJECT +public: + MaemoRunControl(RunConfig runConfiguration); + ~MaemoRunControl(); + void start(); + void stop(); + bool isRunning() const; + +private slots: + void executionFinished(); + +private: + void deploymentFinished(bool success); + void startExecution(); + + QProcess sshProcess; + QProcess stopProcess; + bool stoppedByUser; +}; + +class MaemoDebugRunControl : public AbstractMaemoRunControl +{ + Q_OBJECT +public: + MaemoDebugRunControl(RunConfig runConfiguration); + ~MaemoDebugRunControl(); + void start(); + void stop(); + bool isRunning() const; + Q_SLOT void debuggingFinished(); + +signals: + void stopRequested(); + +private slots: + void gdbServerStarted(); + void debuggerOutput(const QString &output); + +private: + void deploymentFinished(bool success); + + void startGdbServer(); + void gdbServerStartFailed(const QString &reason); + void startDebugging(); + + QProcess gdbServer; + QProcess stopProcess; + const QString gdbServerPort; + Debugger::DebuggerManager *debuggerManager; + QSharedPointer<Debugger::DebuggerStartParameters> startParams; + int inferiorPid; +}; + +void ErrorDumper::printToStream(QProcess::ProcessError error) +{ + QString reason; + switch (error) { + case QProcess::FailedToStart: + reason = "The process failed to start. Either the invoked program is" + " missing, or you may have insufficient permissions to invoke " + "the program."; + break; + + case QProcess::Crashed: + reason = "The process crashed some time after starting successfully."; + break; + + case QProcess::Timedout: + reason = "The last waitFor...() function timed out. The state of " + "QProcess is unchanged, and you can try calling waitFor...() " + "again."; + break; + + case QProcess::WriteError: + reason = "An error occurred when attempting to write to the process." + " For example, the process may not be running, or it may have " + "closed its input channel."; + break; + + case QProcess::ReadError: + reason = "An error occurred when attempting to read from the process." + " For example, the process may not be running."; + break; + + default: + reason = "QProcess::UnknownError"; + break; + } + qWarning() << "Failed to run emulator. Reason:" << reason; +} + + +// #pragma mark -- MaemoRunConfiguration + + +const QString MaemoRunConfiguration::ArgumentsKey("Arguments"); +const QString MaemoRunConfiguration::RemoteHostIsSimulatorKey = + "RemoteHostIsSimulator"; +const QString MaemoRunConfiguration::RemoteHostNameKey = + "RemoteHostName"; +const QString MaemoRunConfiguration::RemoteUserNameKey = + "RemoteUserName"; +const QString MaemoRunConfiguration::RemotePortKey("RemotePort"); +const QString MaemoRunConfiguration::LastDeployedKey("LastDeployed"); +const QString MaemoRunConfiguration::DebuggingHelpersLastDeployedKey = + "DebuggingHelpersLastDeployed"; + +#if USE_SSL_PASSWORD +const QString MaemoRunConfiguration::RemoteUserPasswordKey = + "RemoteUserPassword"; +const QString MaemoRunConfiguration::RemoteHostRequiresPasswordKey = + "RemoteHostRequiresPassword"; +#endif + +MaemoRunConfiguration::MaemoRunConfiguration(Project *project, + const QString &proFilePath) + : RunConfiguration(project) + , m_proFilePath(proFilePath) + , m_cachedTargetInformationValid(false) + , m_cachedSimulatorInformationValid(false) + , qemu(0) +{ + if (!m_proFilePath.isEmpty()) { + setName(tr("%1 on Maemo device").arg(QFileInfo(m_proFilePath) + .completeBaseName())); + } else { + setName(tr("MaemoRunConfiguration")); + } + + connect(project, SIGNAL(targetInformationChanged()), this, + SLOT(invalidateCachedTargetInformation())); + connect(project, SIGNAL(activeBuildConfigurationChanged()), this, + SLOT(invalidateCachedTargetInformation())); + + connect(project, SIGNAL(targetInformationChanged()), this, + SLOT(invalidateCachedSimulatorInformation())); + connect(project, SIGNAL(activeBuildConfigurationChanged()), this, + SLOT(invalidateCachedSimulatorInformation())); + + qemu = new QProcess(this); + connect(qemu, SIGNAL(error(QProcess::ProcessError)), &dumper, + SLOT(printToStream(QProcess::ProcessError))); + connect(qemu, SIGNAL(finished(int, QProcess::ExitStatus)), this, + SLOT(qemuProcessFinished())); +} + +MaemoRunConfiguration::~MaemoRunConfiguration() +{ + if (qemu && qemu->state() != QProcess::NotRunning) { + qemu->terminate(); + qemu->kill(); + } + delete qemu; + qemu = NULL; +} + +QString MaemoRunConfiguration::type() const +{ + return QLatin1String("Qt4ProjectManager.MaemoRunConfiguration"); +} + +Qt4Project *MaemoRunConfiguration::project() const +{ + Qt4Project *pro = qobject_cast<Qt4Project *>(RunConfiguration::project()); + Q_ASSERT(pro != 0); + return pro; +} + +bool MaemoRunConfiguration::isEnabled() const +{ + Qt4Project *qt4Project = qobject_cast<Qt4Project*>(project()); + QTC_ASSERT(qt4Project, return false); + ToolChain::ToolChainType type = + qt4Project->toolChainType(qt4Project->activeBuildConfiguration()); + return type == ToolChain::GCC_MAEMO; +} + +QWidget *MaemoRunConfiguration::configurationWidget() +{ + return new MaemoRunConfigurationWidget(this); +} + +void MaemoRunConfiguration::save(PersistentSettingsWriter &writer) const +{ + writer.saveValue("Runtime", m_simulatorPath); + writer.saveValue(ArgumentsKey, m_arguments); + writer.saveValue(RemoteHostIsSimulatorKey, m_remoteHostIsSimulator); + writer.saveValue(RemoteHostNameKey, m_remoteHostName); + writer.saveValue(RemoteUserNameKey, m_remoteUserName); +#if USE_SSL_PASSWORD + writer.saveValue(RemoteUserPasswordKey, m_remoteUserPassword); + writer.saveValue(RemoteHostRequiresPasswordKey, m_remoteHostRequiresPassword); +#endif + writer.saveValue(RemotePortKey, m_remotePort); + writer.saveValue(LastDeployedKey, m_lastDeployed); + writer.saveValue(DebuggingHelpersLastDeployedKey, + m_debuggingHelpersLastDeployed); + + const QDir &dir = QFileInfo(project()->file()->fileName()).absoluteDir(); + writer.saveValue("ProFile", dir.relativeFilePath(m_proFilePath)); + + RunConfiguration::save(writer); +} + +void MaemoRunConfiguration::restore(const PersistentSettingsReader &reader) +{ + RunConfiguration::restore(reader); + + m_simulatorPath = reader.restoreValue("Runtime").toString(); + m_arguments = reader.restoreValue(ArgumentsKey).toStringList(); + m_remoteHostIsSimulator = + reader.restoreValue(RemoteHostIsSimulatorKey).toBool(); + m_remoteHostName = reader.restoreValue(RemoteHostNameKey).toString(); + m_remoteUserName = reader.restoreValue(RemoteUserNameKey).toString(); +#if USE_SSL_PASSWORD + m_remoteUserPassword = reader.restoreValue(RemoteUserPasswordKey).toString(); + m_remoteHostRequiresPassword = + reader.restoreValue(RemoteHostRequiresPasswordKey).toBool(); +#endif + m_remotePort = reader.restoreValue(RemotePortKey).toInt(); + m_lastDeployed = reader.restoreValue(LastDeployedKey).toDateTime(); + m_debuggingHelpersLastDeployed = + reader.restoreValue(DebuggingHelpersLastDeployedKey).toDateTime(); + + const QDir &dir = QFileInfo(project()->file()->fileName()).absoluteDir(); + m_proFilePath = dir.filePath(reader.restoreValue("ProFile").toString()); +} + +bool MaemoRunConfiguration::currentlyNeedsDeployment() const +{ + return fileNeedsDeployment(executable(), m_lastDeployed); +} + +void MaemoRunConfiguration::wasDeployed() +{ + m_lastDeployed = QDateTime::currentDateTime(); +} + +bool MaemoRunConfiguration::hasDebuggingHelpers() const +{ + return project()->qtVersion(project()->activeBuildConfiguration()) + ->hasDebuggingHelper(); +} + +bool MaemoRunConfiguration::debuggingHelpersNeedDeployment() const +{ + if (hasDebuggingHelpers()) + return fileNeedsDeployment(dumperLib(), m_debuggingHelpersLastDeployed); + return false; +} + +void MaemoRunConfiguration::debuggingHelpersDeployed() +{ + m_debuggingHelpersLastDeployed = QDateTime::currentDateTime(); +} + +bool MaemoRunConfiguration::fileNeedsDeployment(const QString &path, + const QDateTime &lastDeployed) const +{ + return !lastDeployed.isValid() + || QFileInfo(path).lastModified() > lastDeployed; +} + +const QString MaemoRunConfiguration::remoteDir() const +{ + return remoteUserName() == QString::fromLocal8Bit("root") + ? QString::fromLocal8Bit("/root") + : QString::fromLocal8Bit("/home/") + remoteUserName(); +} + +const QString MaemoRunConfiguration::sshCmd() const +{ + return cmd(QString::fromLocal8Bit("ssh")); +} + +const QString MaemoRunConfiguration::scpCmd() const +{ + return cmd(QString::fromLocal8Bit("scp")); +} + +const QString MaemoRunConfiguration::cmd(const QString &cmdName) const +{ + QString command(cmdName); +#ifdef Q_OS_WIN + command = maddeRoot() + QLatin1String("/bin/") + command + + QLatin1String(".exe"); +#endif + return command; +} + +const MaemoToolChain *MaemoRunConfiguration::toolchain() const +{ + Qt4Project *qt4Project = qobject_cast<Qt4Project *>(project()); + QTC_ASSERT(qt4Project != 0, return 0); + MaemoToolChain *tc = dynamic_cast<MaemoToolChain *>( + qt4Project->toolChain(qt4Project->activeBuildConfiguration()) ); + QTC_ASSERT(tc != 0, return 0); + return tc; +} + +const QString MaemoRunConfiguration::gdbCmd() const +{ + return toolchain() != 0 + ? toolchain()->targetRoot() + "/bin/gdb" + : QString(); +} + +QString MaemoRunConfiguration::maddeRoot() const +{ + return toolchain() != 0 ? toolchain()->maddeRoot() : QString(); +} + +const QString MaemoRunConfiguration::sysRoot() const +{ + return toolchain() != 0 ? toolchain()->sysrootRoot() : QString(); +} + +const QString MaemoRunConfiguration::dumperLib() const +{ + return project()->qtVersion(project()->activeBuildConfiguration())-> + debuggingHelperLibrary(); +} + +QString MaemoRunConfiguration::executable() const +{ + const_cast<MaemoRunConfiguration*> (this)->updateTarget(); + return m_executable; +} + +QString MaemoRunConfiguration::simulatorPath() const +{ + qDebug("MaemoRunConfiguration::simulatorPath() called, %s", + qPrintable(m_simulatorPath)); + + const_cast<MaemoRunConfiguration*> (this)->updateSimulatorInformation(); + return m_simulatorPath; +} + +QString MaemoRunConfiguration::visibleSimulatorParameter() const +{ + qDebug("MaemoRunConfiguration::visibleSimulatorParameter() called"); + + const_cast<MaemoRunConfiguration*> (this)->updateSimulatorInformation(); + return m_visibleSimulatorParameter; +} + +QString MaemoRunConfiguration::simulator() const +{ + const_cast<MaemoRunConfiguration*> (this)->updateSimulatorInformation(); + return m_simulator; +} + +QString MaemoRunConfiguration::simulatorArgs() const +{ + const_cast<MaemoRunConfiguration*> (this)->updateSimulatorInformation(); + return m_simulatorArgs; +} + +void MaemoRunConfiguration::setArguments(const QStringList &args) +{ + m_arguments = args; +} + +void MaemoRunConfiguration::setRemoteHostIsSimulator(bool isSimulator) +{ + m_remoteHostIsSimulator = isSimulator; +} + +void MaemoRunConfiguration::setRemoteHostName(const QString &hostName) +{ + m_lastDeployed = QDateTime(); + m_debuggingHelpersLastDeployed = QDateTime(); + m_remoteHostName = hostName; +} + +void MaemoRunConfiguration::setRemoteUserName(const QString &userName) +{ + m_lastDeployed = QDateTime(); + m_debuggingHelpersLastDeployed = QDateTime(); + m_remoteUserName = userName; +} + +void MaemoRunConfiguration::setRemotePort(int port) +{ + m_lastDeployed = QDateTime(); + m_debuggingHelpersLastDeployed = QDateTime(); + m_remotePort = port; +} + +#if USE_SSL_PASSWORD +void MaemoRunConfiguration::setRemotePassword(const QString &password) +{ + Q_ASSERT(remoteHostRequiresPassword()); + m_remoteUserPassword = password; +} + +void MaemoRunConfiguration::setRemoteHostRequiresPassword(bool requiresPassword) +{ + m_remoteHostRequiresPassword = requiresPassword; +} +#endif + +bool MaemoRunConfiguration::isQemuRunning() const +{ + return (qemu && qemu->state() != QProcess::NotRunning); +} + +void MaemoRunConfiguration::invalidateCachedTargetInformation() +{ + m_cachedTargetInformationValid = false; + emit targetInformationChanged(); +} + +void MaemoRunConfiguration::setSimulatorPath(const QString &path) +{ + qDebug("MaemoRunConfiguration::setSimulatorPath() called, " + "m_simulatorPath: %s, new path: %s", qPrintable(m_simulatorPath), + qPrintable(path)); + + if (m_simulatorPath != path) + m_cachedSimulatorInformationValid = false; + + m_simulatorPath = path; + emit cachedSimulatorInformationChanged(); +} + +void MaemoRunConfiguration::invalidateCachedSimulatorInformation() +{ + qDebug("MaemoRunConfiguration::invalidateCachedSimulatorInformation() " + "called"); + + m_cachedSimulatorInformationValid = false; + emit cachedSimulatorInformationChanged(); +} + +void MaemoRunConfiguration::updateTarget() +{ + if (m_cachedTargetInformationValid) + return; + + m_executable = QString::null; + m_cachedTargetInformationValid = true; + + if (Qt4Project *qt4Project = static_cast<Qt4Project *>(project())) { + Qt4PriFileNode * priFileNode = qt4Project->rootProjectNode() + ->findProFileFor(m_proFilePath); + if (!priFileNode) { + emit targetInformationChanged(); + return; + } + + QtVersion *qtVersion = + qt4Project->qtVersion(qt4Project->activeBuildConfiguration()); + ProFileReader *reader = priFileNode->createProFileReader(); + reader->setCumulative(false); + reader->setQtVersion(qtVersion); + + // Find out what flags we pass on to qmake, this code is duplicated in + // the qmake step + QtVersion::QmakeBuildConfig defaultBuildConfiguration = + qtVersion->defaultBuildConfig(); + QtVersion::QmakeBuildConfig projectBuildConfiguration = + QtVersion::QmakeBuildConfig(qt4Project->activeBuildConfiguration() + ->value("buildConfiguration").toInt()); + + QStringList addedUserConfigArguments; + QStringList removedUserConfigArguments; + if ((defaultBuildConfiguration & QtVersion::BuildAll) + && !(projectBuildConfiguration & QtVersion::BuildAll)) + removedUserConfigArguments << "debug_and_release"; + + if (!(defaultBuildConfiguration & QtVersion::BuildAll) + && (projectBuildConfiguration & QtVersion::BuildAll)) + addedUserConfigArguments << "debug_and_release"; + + if ((defaultBuildConfiguration & QtVersion::DebugBuild) + && !(projectBuildConfiguration & QtVersion::DebugBuild)) + addedUserConfigArguments << "release"; + + if (!(defaultBuildConfiguration & QtVersion::DebugBuild) + && (projectBuildConfiguration & QtVersion::DebugBuild)) + addedUserConfigArguments << "debug"; + + reader->setUserConfigCmdArgs(addedUserConfigArguments, + removedUserConfigArguments); + + if (!reader->readProFile(m_proFilePath)) { + delete reader; + Core::ICore::instance()->messageManager()->printToOutputPane(tr( + "Could not parse %1. The Maemo run configuration %2 " + "can not be started.").arg(m_proFilePath).arg(name())); + emit targetInformationChanged(); + return; + } + + // Extract data + QDir baseProjectDirectory = + QFileInfo(project()->file()->fileName()).absoluteDir(); + QString relSubDir = + baseProjectDirectory.relativeFilePath(QFileInfo(m_proFilePath).path()); + QDir baseBuildDirectory = + project()->buildDirectory(project()->activeBuildConfiguration()); + QString baseDir = baseBuildDirectory.absoluteFilePath(relSubDir); + + if (!reader->contains("DESTDIR")) { +#if 0 // TODO: fix this, seems to be wrong on windows + if (reader->values("CONFIG").contains("debug_and_release_target")) { + QString qmakeBuildConfig = "release"; + if (projectBuildConfiguration & QtVersion::DebugBuild) + qmakeBuildConfig = "debug"; + baseDir += QLatin1Char('/') + qmakeBuildConfig; + } +#endif + } else { + const QString &destDir = reader->value("DESTDIR"); + if (QDir::isRelativePath(destDir)) + baseDir += QLatin1Char('/') + destDir; + else + baseDir = destDir; + } + + QString target = reader->value("TARGET"); + if (target.isEmpty()) + target = QFileInfo(m_proFilePath).baseName(); + + m_executable = QDir::cleanPath(baseDir + QLatin1Char('/') + target); + delete reader; + } + + emit targetInformationChanged(); +} + +void MaemoRunConfiguration::updateSimulatorInformation() +{ + qDebug("MaemoRunConfiguration::updateSimulatorInformation() called"); + + if (m_cachedSimulatorInformationValid) + return; + + m_simulator = QString::null; + m_simulatorArgs == QString::null; + m_cachedSimulatorInformationValid = true; + m_visibleSimulatorParameter = tr("Please select a Maemo simulator."); + + if (!m_simulatorPath.isEmpty()) { + m_visibleSimulatorParameter = tr("'%1' is not a valid Maemo simulator.") + .arg(m_simulatorPath); + } + + const QStringList &files = QDir(m_simulatorPath).entryList(QDir::Files + | QDir::NoSymLinks | QDir::NoDotAndDotDot); + if (files.count() >= 2) { + const QLatin1String info("information"); + if (files.contains(info)) { + QFile file(m_simulatorPath + QLatin1Char('/') + info); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMap<QString, QString> map; + QTextStream stream(&file); + while (!stream.atEnd()) { + const QString &line = stream.readLine().trimmed(); + const int index = line.indexOf(QLatin1Char('=')); + map.insert(line.mid(0, index).remove(QLatin1Char('\'')), + line.mid(index + 1).remove(QLatin1Char('\''))); + } + + m_simulator = map.value(QLatin1String("runcommand")); + m_simulatorArgs = map.value(QLatin1String("runcommand_args")); + + m_visibleSimulatorParameter = m_simulator +#ifdef Q_OS_WIN + + QLatin1String(".exe") +#endif + + QLatin1Char(' ') + m_simulatorArgs; + } + } + } + + emit cachedSimulatorInformationChanged(); +} + +void MaemoRunConfiguration::startStopQemu() +{ + if (qemu->state() != QProcess::NotRunning) { + if (qemu->state() == QProcess::Running) { + qemu->terminate(); + qemu->kill(); + emit qemuProcessStatus(false); + } + return; + } + + QString root = maddeRoot(); + if (root.isEmpty() || simulator().isEmpty()) + return; + + const QLatin1Char colon(';'); + const QString path = QDir::toNativeSeparators(root + QLatin1Char('/')); + + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("PATH", env.value("Path") + colon + path + QLatin1String("bin")); + env.insert("PATH", env.value("Path") + colon + path + QLatin1String("madlib")); + + qemu->setProcessEnvironment(env); + qemu->setWorkingDirectory(simulatorPath()); + + QString app = root + QLatin1String("/madlib/") + simulator() +#ifdef Q_OS_WIN + + QLatin1String(".exe") +#endif + ; // keep + + qemu->start(app + QLatin1Char(' ') + simulatorArgs(), QIODevice::ReadWrite); + emit qemuProcessStatus(qemu->waitForStarted()); +} + +void MaemoRunConfiguration::qemuProcessFinished() +{ + emit qemuProcessStatus(false); +} + +void MaemoRunConfiguration::enabledStateChanged() +{ + MaemoManager::instance()->setQemuSimulatorStarterEnabled(isEnabled()); +} + + +// #pragma mark -- MaemoRunConfigurationWidget + + +MaemoRunConfigurationWidget::MaemoRunConfigurationWidget( + MaemoRunConfiguration *runConfiguration, QWidget *parent) + : QWidget(parent) + , m_runConfiguration(runConfiguration) +{ + QFormLayout *mainLayout = new QFormLayout; + setLayout(mainLayout); + mainLayout->setFormAlignment(Qt::AlignLeft | Qt::AlignVCenter); + m_configNameLineEdit = new QLineEdit(m_runConfiguration->name()); + mainLayout->addRow(tr("Run configuration name:"), m_configNameLineEdit); + m_executableLabel = new QLabel(m_runConfiguration->executable()); + mainLayout->addRow(tr("Executable:"), m_executableLabel); + m_argsLineEdit = new QLineEdit(m_runConfiguration->arguments().join(" ")); + mainLayout->addRow(tr("Arguments:"), m_argsLineEdit); + m_debuggerLabel = new QLabel(m_runConfiguration->gdbCmd()); + mainLayout->addRow(tr("Debugger:"), m_debuggerLabel); + + QWidget *hostTypeWidget = new QWidget; + QHBoxLayout *hostTypeLayout = new QHBoxLayout; + hostTypeLayout->setContentsMargins(0, 0, 0, 0); + hostTypeWidget->setLayout(hostTypeLayout); + m_hwButton = new QRadioButton(tr("Physical device")); + m_simButton = new QRadioButton(tr("Simulator")); + hostTypeLayout->addWidget(m_hwButton); + hostTypeLayout->addWidget(m_simButton); + hostTypeLayout->addStretch(1); + mainLayout->addRow(tr("Remote host type:"), hostTypeWidget); + m_chooseSimPathLabel = new QLabel(tr("Choose simulator:")); + m_simPathChooser = new Utils::PathChooser; + m_simPathChooser->setPath(m_runConfiguration->simulatorPath()); + mainLayout->addRow(m_chooseSimPathLabel, m_simPathChooser); + m_simParamsNameLabel = new QLabel(tr("Simulator command line:")); + m_simParamsValueLabel= new QLabel(m_runConfiguration->visibleSimulatorParameter()); + mainLayout->addRow(m_simParamsNameLabel, m_simParamsValueLabel); + + m_hostNameLineEdit = new QLineEdit(m_runConfiguration->remoteHostName()); + mainLayout->addRow(tr("Remote host name:"), m_hostNameLineEdit); + m_userLineEdit = new QLineEdit(m_runConfiguration->remoteUserName()); + mainLayout->addRow(tr("Remote user name:"), m_userLineEdit); + + // Unlikely to ever work: ssh uses /dev/tty directly instead of stdin/out +#if USE_SSL_PASSWORD + m_passwordCheckBox = new QCheckBox(tr("Remote password:")); + m_passwordCheckBox->setToolTip(tr("Uncheck for passwordless login")); + m_passwordCheckBox->setChecked(m_runConfiguration + ->remoteHostRequiresPassword()); + m_passwordLineEdit = new QLineEdit(m_runConfiguration->remoteUserPassword()); + m_passwordLineEdit->setEchoMode(QLineEdit::Password); + m_passwordLineEdit->setEnabled(m_passwordCheckBox->isChecked()); + mainLayout->addRow(m_passwordCheckBox, m_passwordLineEdit); +#endif + + m_portLineEdit = new QLineEdit(QString::number(m_runConfiguration->remotePort())); + mainLayout->addRow(tr("Remote SSH port:"), m_portLineEdit); + + connect(m_configNameLineEdit, SIGNAL(textEdited(QString)), this, + SLOT(configNameEdited(QString))); + connect(m_argsLineEdit, SIGNAL(textEdited(QString)), this, + SLOT(argumentsEdited(QString))); + connect(m_runConfiguration, SIGNAL(targetInformationChanged()), this, + SLOT(updateTargetInformation())); + connect(m_hwButton, SIGNAL(toggled(bool)), this, SLOT(hostTypeChanged())); + connect(m_simButton, SIGNAL(toggled(bool)), this, SLOT(hostTypeChanged())); + connect(m_hostNameLineEdit, SIGNAL(textEdited(QString)), this, + SLOT(hostNameEdited(QString))); + connect(m_userLineEdit, SIGNAL(textEdited(QString)), this, + SLOT(userNameEdited(QString))); +#if USE_SSL_PASSWORD + connect(m_passwordCheckBox, SIGNAL(stateChanged(int)), this, + SLOT(passwordUseChanged())); + connect(m_passwordLineEdit, SIGNAL(textEdited(QString)), this, + SLOT(passwordEdited(QString))); +#endif + connect(m_portLineEdit, SIGNAL(textEdited(QString)), this, + SLOT(portEdited(QString))); + connect(m_simPathChooser, SIGNAL(changed(QString)), m_runConfiguration, + SLOT(setSimulatorPath(QString))); + connect(m_runConfiguration, SIGNAL(cachedSimulatorInformationChanged()), + this, SLOT(updateVisibleSimulatorParameter())); + if (m_runConfiguration->remoteHostIsSimulator()) + m_simButton->setChecked(true); + else + m_hwButton->setChecked(true); +} + +void MaemoRunConfigurationWidget::configNameEdited(const QString &text) +{ + m_runConfiguration->setName(text); +} + +void MaemoRunConfigurationWidget::argumentsEdited(const QString &text) +{ + m_runConfiguration->setArguments(text.split(' ', QString::SkipEmptyParts)); +} + +void MaemoRunConfigurationWidget::updateTargetInformation() +{ + m_executableLabel->setText(m_runConfiguration->executable()); +} + +void MaemoRunConfigurationWidget::updateVisibleSimulatorParameter() +{ + m_simParamsValueLabel->setText(m_runConfiguration->visibleSimulatorParameter()); +} + +void MaemoRunConfigurationWidget::hostTypeChanged() +{ + Q_ASSERT(m_hwButton->isChecked() != m_simButton->isChecked()); + const bool isSimulator = m_simButton->isChecked(); + m_chooseSimPathLabel->setVisible(isSimulator); + m_simPathChooser->setVisible(isSimulator); + m_simParamsNameLabel->setVisible(isSimulator); + m_simParamsValueLabel->setVisible(isSimulator); + m_runConfiguration->setRemoteHostIsSimulator(isSimulator); +} + +void MaemoRunConfigurationWidget::hostNameEdited(const QString &hostName) +{ + m_runConfiguration->setRemoteHostName(hostName); +} + +void MaemoRunConfigurationWidget::userNameEdited(const QString &userName) +{ + m_runConfiguration->setRemoteUserName(userName); +} + +#if USE_SSL_PASSWORD +void MaemoRunConfigurationWidget::passwordUseChanged() +{ + const bool usePassword = m_passwordCheckBox->checkState() == Qt::Checked; + m_passwordLineEdit->setEnabled(usePassword); + m_runConfiguration->setRemoteHostRequiresPassword(usePassword); +} + +void MaemoRunConfigurationWidget::passwordEdited(const QString &password) +{ + m_runConfiguration->setRemotePassword(password); +} +#endif + +void MaemoRunConfigurationWidget::portEdited(const QString &portString) +{ + bool isValidString; + int port = portString.toInt(&isValidString); + if (isValidString) + m_runConfiguration->setRemotePort(port); + else + m_portLineEdit->setText(QString::number(m_runConfiguration->remotePort())); +} + + +// #pragma mark -- MaemoRunConfigurationFactory + + +MaemoRunConfigurationFactory::MaemoRunConfigurationFactory(QObject* parent) + : IRunConfigurationFactory(parent) +{ +} + +MaemoRunConfigurationFactory::~MaemoRunConfigurationFactory() +{ +} + +bool MaemoRunConfigurationFactory::canRestore(const QString &type) const +{ + return type == "Qt4ProjectManager.MaemoRunConfiguration"; +} + +QStringList MaemoRunConfigurationFactory::availableCreationTypes( + Project *pro) const +{ + Qt4Project *qt4project = qobject_cast<Qt4Project *>(pro); + if (qt4project) { + QStringList applicationProFiles; + QList<Qt4ProFileNode *> list = qt4project->applicationProFiles(); + foreach (Qt4ProFileNode * node, list) { + applicationProFiles.append("MaemoRunConfiguration." + node->path()); + } + return applicationProFiles; + } + return QStringList(); +} + +QString MaemoRunConfigurationFactory::displayNameForType( + const QString &type) const +{ + const int size = QString::fromLocal8Bit("MaemoRunConfiguration.").size(); + return tr("%1 on Maemo device").arg(QFileInfo(type.mid(size)) + .completeBaseName()); +} + +RunConfig MaemoRunConfigurationFactory::create(Project *project, + const QString &type) +{ + Qt4Project *qt4project = qobject_cast<Qt4Project *>(project); + Q_ASSERT(qt4project); + + connect(project, SIGNAL(addedRunConfiguration(ProjectExplorer::Project*, + QString)), this, SLOT(addedRunConfiguration(ProjectExplorer::Project*))); + connect(project, SIGNAL(removedRunConfiguration(ProjectExplorer::Project*, + QString)), this, SLOT(removedRunConfiguration(ProjectExplorer::Project*))); + + RunConfig rc; + const QLatin1String prefix("MaemoRunConfiguration."); + if (type.startsWith(prefix)) { + rc = RunConfig(new MaemoRunConfiguration(qt4project, + type.mid(QString(prefix).size()))); + } else { + Q_ASSERT(type == "Qt4ProjectManager.MaemoRunConfiguration"); + rc = RunConfig(new MaemoRunConfiguration(qt4project, + QString::null)); + } + + if (rc.data()) { + connect(project, SIGNAL(runConfigurationsEnabledStateChanged()), + rc.data(), SLOT(enabledStateChanged())); + connect(MaemoManager::instance(), SIGNAL(startStopQemu()), rc.data(), + SLOT(startStopQemu())); + connect(rc.data(), SIGNAL(qemuProcessStatus(bool)), + MaemoManager::instance(), SLOT(updateQemuSimulatorStarter(bool))); + } + + ProjectExplorerPlugin *explorer = ProjectExplorerPlugin::instance(); + connect(explorer->session(), SIGNAL(projectAdded(ProjectExplorer::Project*)), + this, SLOT(projectAdded(ProjectExplorer::Project*))); + connect(explorer->session(), SIGNAL(projectRemoved(ProjectExplorer::Project*)), + this, SLOT(projectRemoved(ProjectExplorer::Project*))); + connect(explorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), + this, SLOT(currentProjectChanged(ProjectExplorer::Project*))); + + return rc; +} + +bool hasMaemoRunConfig(ProjectExplorer::Project* project) +{ + if (Qt4Project *qt4Project = qobject_cast<Qt4Project *>(project)) { + QList<RunConfig> list = qt4Project->runConfigurations(); + foreach (const RunConfig &rc, list) { + if (!rc.dynamicCast<MaemoRunConfiguration>().isNull()) + return true; + } + } + return false; +} + +void MaemoRunConfigurationFactory::addedRunConfiguration( + ProjectExplorer::Project* project) +{ + if (hasMaemoRunConfig(project)) + MaemoManager::instance()->addQemuSimulatorStarter(project); +} + +void MaemoRunConfigurationFactory::removedRunConfiguration( + ProjectExplorer::Project* project) +{ + if (!hasMaemoRunConfig(project)) + MaemoManager::instance()->removeQemuSimulatorStarter(project); +} + +void MaemoRunConfigurationFactory::projectAdded( + ProjectExplorer::Project* project) +{ + if (hasMaemoRunConfig(project)) + MaemoManager::instance()->addQemuSimulatorStarter(project); +} + +void MaemoRunConfigurationFactory::projectRemoved( + ProjectExplorer::Project* project) +{ + if (hasMaemoRunConfig(project)) + MaemoManager::instance()->removeQemuSimulatorStarter(project); +} + +void MaemoRunConfigurationFactory::currentProjectChanged( + ProjectExplorer::Project* project) +{ + bool hasRunConfig = hasMaemoRunConfig(project); + MaemoManager::instance()->setQemuSimulatorStarterEnabled(hasRunConfig); + + bool isRunning = false; + if (Qt4Project *qt4Project = qobject_cast<Qt4Project *>(project)) { + const RunConfig &rc = qt4Project->activeRunConfiguration(); + if (!rc.dynamicCast<MaemoRunConfiguration>().isNull()) + isRunning = rc.dynamicCast<MaemoRunConfiguration>()->isQemuRunning(); + } + MaemoManager::instance()->updateQemuSimulatorStarter(isRunning); +} + + +// #pragma mark -- MaemoRunControlFactory + + +MaemoRunControlFactory::MaemoRunControlFactory(QObject *parent) + : IRunControlFactory(parent) +{ +} + +bool MaemoRunControlFactory::canRun(const RunConfig &runConfiguration, + const QString &mode) const +{ + return !runConfiguration.dynamicCast<MaemoRunConfiguration>().isNull() + && (mode == ProjectExplorer::Constants::RUNMODE + || mode == ProjectExplorer::Constants::DEBUGMODE); +} + +RunControl* MaemoRunControlFactory::create(const RunConfig &runConfig, + const QString &mode) +{ + QSharedPointer<MaemoRunConfiguration> rc = runConfig + .dynamicCast<MaemoRunConfiguration>(); + Q_ASSERT(!rc.isNull()); + Q_ASSERT(mode == ProjectExplorer::Constants::RUNMODE + || mode == ProjectExplorer::Constants::DEBUGMODE); + if (mode == ProjectExplorer::Constants::RUNMODE) + return new MaemoRunControl(rc); + return new MaemoDebugRunControl(rc); +} + +QString MaemoRunControlFactory::displayName() const +{ + return tr("Run on device"); +} + +QWidget* MaemoRunControlFactory::configurationWidget(const RunConfig &config) +{ + Q_UNUSED(config) + return 0; +} + + +// #pragma mark -- AbstractMaemoRunControl + + +AbstractMaemoRunControl::AbstractMaemoRunControl(RunConfig rc) + : RunControl(rc) + , runConfig(rc.objectCast<MaemoRunConfiguration>()) +{ + setProcessEnvironment(deployProcess); + + connect(&deployProcess, SIGNAL(readyReadStandardError()), this, + SLOT(readStandardError())); + connect(&deployProcess, SIGNAL(readyReadStandardOutput()), this, + SLOT(readStandardOutput())); + connect(&deployProcess, SIGNAL(error(QProcess::ProcessError)), &dumper, + SLOT(printToStream(QProcess::ProcessError))); + connect(&deployProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, + SLOT(deployProcessFinished())); +} + +void AbstractMaemoRunControl::startDeployment(bool forDebugging) +{ + QTC_ASSERT(!runConfig.isNull(), return); + QStringList deployables; + if (runConfig->currentlyNeedsDeployment()) { + deployingExecutable = true; + deployables << executableFileName(); + } else { + deployingExecutable = false; + } + if (forDebugging && runConfig->debuggingHelpersNeedDeployment()) { + deployables << runConfig->dumperLib(); + deployingDumperLib = true; + } else { + deployingDumperLib = false; + } + if (!deployables.isEmpty()) { + emit addToOutputWindow(this, tr("Files to deploy: %1.") + .arg(deployables.join(" "))); + QStringList cmdArgs; + cmdArgs << "-P" << port() << deployables << (runConfig->remoteUserName() + + "@" + runConfig->remoteHostName() + ":" + runConfig->remoteDir()); + deployProcess.setWorkingDirectory(QFileInfo(executableOnHost()).absolutePath()); + deployProcess.start(runConfig->scpCmd(), cmdArgs); + if (!deployProcess.waitForStarted()) { + emit error(this, tr("Could not start scp. Deployment failed.")); + deployProcess.kill(); + } else { + emit started(); + } + } else { + deploymentFinished(true); + } +} + +void AbstractMaemoRunControl::stopDeployment() +{ + deployProcess.kill(); +} + +bool AbstractMaemoRunControl::isDeploying() const +{ + return deployProcess.state() != QProcess::NotRunning; +} + +void AbstractMaemoRunControl::deployProcessFinished() +{ + bool success; + if (deployProcess.exitCode() == 0) { + emit addToOutputWindow(this, tr("Target deployed.")); + success = true; + if (deployingExecutable) + runConfig->wasDeployed(); + if (deployingDumperLib) + runConfig->debuggingHelpersDeployed(); + } else { + emit error(this, tr("Deployment failed.")); + success = false; + } + deploymentFinished(success); +} + +const QString AbstractMaemoRunControl::executableOnHost() const +{ + return runConfig->executable(); +} + +const QString AbstractMaemoRunControl::port() const +{ + return QString::number(runConfig->remotePort()); +} + +const QString AbstractMaemoRunControl::executableFileName() const +{ + return QFileInfo(executableOnHost()).fileName(); +} + +const QString AbstractMaemoRunControl::executableOnTarget() const +{ + return QString::fromLocal8Bit("%1/%2").arg(runConfig->remoteDir()). + arg(executableFileName()); +} + +const QString AbstractMaemoRunControl::targetCmdLinePrefix() const +{ + return QString::fromLocal8Bit("chmod u+x %1; source /etc/profile; "). + arg(executableOnTarget()); +} + +bool AbstractMaemoRunControl::setProcessEnvironment(QProcess &process) +{ + QTC_ASSERT(!runConfig.isNull(), return false); + Qt4Project *qt4Project = qobject_cast<Qt4Project *>(runConfig->project()); + QTC_ASSERT(runConfig, return false); + Environment env = Environment::systemEnvironment(); + qt4Project->toolChain(qt4Project->activeBuildConfiguration()) + ->addToEnvironment(env); + process.setEnvironment(env.toStringList()); + + return true; +} + +void AbstractMaemoRunControl::readStandardError() +{ + QProcess *process = static_cast<QProcess *>(sender()); + const QByteArray &data = process->readAllStandardError(); + emit addToOutputWindow(this, QString::fromLocal8Bit(data.constData(), + data.length())); +} + +void AbstractMaemoRunControl::readStandardOutput() +{ + QProcess *process = static_cast<QProcess *>(sender()); + const QByteArray &data = process->readAllStandardOutput(); + emit addToOutputWindow(this, QString::fromLocal8Bit(data.constData(), + data.length())); +} + + +// #pragma mark -- MaemoRunControl + + +MaemoRunControl::MaemoRunControl(RunConfig runConfiguration) + : AbstractMaemoRunControl(runConfiguration) +{ + setProcessEnvironment(sshProcess); + setProcessEnvironment(stopProcess); + + connect(&sshProcess, SIGNAL(readyReadStandardError()), this, + SLOT(readStandardError())); + connect(&sshProcess, SIGNAL(readyReadStandardOutput()), this, + SLOT(readStandardOutput())); + connect(&sshProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, + SLOT(executionFinished())); + connect(&sshProcess, SIGNAL(error(QProcess::ProcessError)), &dumper, + SLOT(printToStream(QProcess::ProcessError))); +} + +MaemoRunControl::~MaemoRunControl() +{ + stop(); + stopProcess.waitForFinished(5000); +} + +void MaemoRunControl::start() +{ + stoppedByUser = false; + startDeployment(false); +} + +void MaemoRunControl::deploymentFinished(bool success) +{ + if (success) + startExecution(); + else + emit finished(); +} + +void MaemoRunControl::startExecution() +{ + const QString remoteCall = QString::fromLocal8Bit("%1 %2 %3") + .arg(targetCmdLinePrefix()).arg(executableOnTarget()) + .arg(runConfig->arguments().join(" ")); + + QStringList cmdArgs; + cmdArgs << "-n" << "-p" << port() << "-l" << runConfig->remoteUserName() + << runConfig->remoteHostName() << remoteCall; + sshProcess.start(runConfig->sshCmd(), cmdArgs); + + sshProcess.start(runConfig->sshCmd(), cmdArgs); + emit addToOutputWindow(this, tr("Starting remote application.")); + if (sshProcess.waitForStarted()) { + emit started(); + } else { + emit error(this, tr("Could not start ssh!")); + sshProcess.kill(); + } +} + +void MaemoRunControl::executionFinished() +{ + if (stoppedByUser) + emit addToOutputWindow(this, tr("Remote process stopped by user.")); + else if (sshProcess.exitCode() != 0) + emit addToOutputWindow(this, tr("Remote process exited with error.")); + else + emit addToOutputWindow(this, tr("Remote process finished successfully.")); + emit finished(); +} + +void MaemoRunControl::stop() +{ + stoppedByUser = true; + if (isDeploying()) { + stopDeployment(); + } else { + stopProcess.kill(); + QStringList cmdArgs; + const QString remoteCall = QString::fromLocal8Bit("pkill -f %1; " + "sleep 1; pkill -9 -f %1").arg(executableFileName()); + cmdArgs << "-n" << "-p" << port() << "-l" << runConfig->remoteUserName() + << runConfig->remoteHostName() << remoteCall; + stopProcess.start(runConfig->sshCmd(), cmdArgs); + } +} + +bool MaemoRunControl::isRunning() const +{ + return isDeploying() || sshProcess.state() != QProcess::NotRunning; +} + + +// #pragma mark -- MaemoDebugRunControl + + +MaemoDebugRunControl::MaemoDebugRunControl(RunConfig runConfiguration) + : AbstractMaemoRunControl(runConfiguration) + , gdbServerPort("10000"), debuggerManager(0) + , startParams(new Debugger::DebuggerStartParameters) +{ + setProcessEnvironment(gdbServer); + setProcessEnvironment(stopProcess); + + qDebug("Maemo Debug run controls started"); + debuggerManager = ExtensionSystem::PluginManager::instance() + ->getObject<Debugger::DebuggerManager>(); + + QTC_ASSERT(debuggerManager != 0, return); + startParams->startMode = Debugger::StartRemote; + startParams->executable = executableOnHost(); + startParams->remoteChannel = runConfig->remoteHostName() + ":" + + gdbServerPort; + startParams->remoteArchitecture = "arm"; + startParams->sysRoot = runConfig->sysRoot(); + startParams->toolChainType = ToolChain::GCC_MAEMO; + startParams->debuggerCommand = runConfig->gdbCmd(); + startParams->dumperLibrary = runConfig->dumperLib(); + startParams->remoteDumperLib = QString::fromLocal8Bit("%1/%2") + .arg(runConfig->remoteDir()).arg(QFileInfo(runConfig->dumperLib()) + .fileName()); + + connect(this, SIGNAL(stopRequested()), debuggerManager, SLOT(exitDebugger())); + connect(debuggerManager, SIGNAL(debuggingFinished()), this, + SLOT(debuggingFinished()), Qt::QueuedConnection); + connect(debuggerManager, SIGNAL(applicationOutputAvailable(QString)), + this, SLOT(debuggerOutput(QString)), Qt::QueuedConnection); +} + +MaemoDebugRunControl::~MaemoDebugRunControl() +{ + disconnect(SIGNAL(addToOutputWindow(RunControl*,QString))); + disconnect(SIGNAL(addToOutputWindowInline(RunControl*,QString))); + stop(); + debuggingFinished(); +} + +void MaemoDebugRunControl::start() +{ + startDeployment(true); +} + +void MaemoDebugRunControl::deploymentFinished(bool success) +{ + if (success) { + startGdbServer(); + } else { + emit finished(); + } +} + +void MaemoDebugRunControl::startGdbServer() +{ + const QString remoteCall(QString::fromLocal8Bit("%1 gdbserver :%2 %3 %4"). + arg(targetCmdLinePrefix()).arg(gdbServerPort). arg(executableOnTarget()) + .arg(runConfig->arguments().join(" "))); + QStringList sshArgs; + sshArgs << "-t" << "-n" << "-l" << runConfig->remoteUserName() << "-p" + << port() << runConfig->remoteHostName() << remoteCall; + inferiorPid = -1; + disconnect(&gdbServer, SIGNAL(readyReadStandardError()), 0, 0); + connect(&gdbServer, SIGNAL(readyReadStandardError()), this, + SLOT(gdbServerStarted())); + gdbServer.start(runConfig->sshCmd(), sshArgs); + qDebug("Maemo: started gdb server, ssh arguments were %s", qPrintable(sshArgs.join(" "))); +} + +void MaemoDebugRunControl::gdbServerStartFailed(const QString &reason) +{ + emit addToOutputWindow(this, tr("Debugging failed: %1").arg(reason)); + emit stopRequested(); + emit finished(); +} + +void MaemoDebugRunControl::gdbServerStarted() +{ + const QByteArray output = gdbServer.readAllStandardError(); + qDebug("gdbserver's stderr output: %s", output.data()); + + const QByteArray searchString("pid = "); + const int searchStringLength = searchString.length(); + + int pidStartPos = output.indexOf(searchString); + const int pidEndPos = output.indexOf("\n", pidStartPos + searchStringLength); + if (pidStartPos == -1 || pidEndPos == -1) { + gdbServerStartFailed(output.data()); + return; + } + + pidStartPos += searchStringLength; + QByteArray pidString = output.mid(pidStartPos, pidEndPos - pidStartPos); + qDebug("pidString = %s", pidString.data()); + + bool ok; + const int pid = pidString.toInt(&ok); + if (!ok) { + gdbServerStartFailed(tr("Debugging failed, could not parse gdb " + "server pid!")); + return; + } + + inferiorPid = pid; + qDebug("inferiorPid = %d", inferiorPid); + + disconnect(&gdbServer, SIGNAL(readyReadStandardError()), 0, 0); + connect(&gdbServer, SIGNAL(readyReadStandardError()), this, + SLOT(readStandardError())); + startDebugging(); +} + +void MaemoDebugRunControl::startDebugging() +{ + debuggerManager->startNewDebugger(startParams); +} + +void MaemoDebugRunControl::stop() +{ + if (!isRunning()) + return; + emit addToOutputWindow(this, tr("Stopping debugging operation ...")); + if (isDeploying()) { + stopDeployment(); + } else { + emit stopRequested(); + } +} + +bool MaemoDebugRunControl::isRunning() const +{ + return isDeploying() || gdbServer.state() != QProcess::NotRunning + || debuggerManager->state() != Debugger::DebuggerNotReady; +} + +void MaemoDebugRunControl::debuggingFinished() +{ + if (gdbServer.state() != QProcess::NotRunning) { + stopProcess.kill(); + const QString remoteCall = QString::fromLocal8Bit("kill %1; sleep 1; " + "kill -9 %1; pkill -9 -f gdbserver").arg(inferiorPid); + QStringList sshArgs; + sshArgs << "-n" << "-l" << runConfig->remoteUserName() << "-p" << port() + << runConfig->remoteHostName() << remoteCall; + stopProcess.start(runConfig->sshCmd(), sshArgs); + } + qDebug("ssh return code is %d", gdbServer.exitCode()); + emit addToOutputWindow(this, tr("Debugging finished.")); + emit finished(); +} + +void MaemoDebugRunControl::debuggerOutput(const QString &output) +{ + emit addToOutputWindowInline(this, output); +} + +} // namespace Internal +} // namespace Qt4ProjectManager + +#include "maemorunconfiguration.moc" diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h new file mode 100644 index 0000000000000000000000000000000000000000..e03dc263caa100ffa1c178911bfba3dddc09ebd4 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h @@ -0,0 +1,228 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MAEMORUNCONFIGURATION_H +#define MAEMORUNCONFIGURATION_H + +#include <QtCore/QDateTime> +#include <QtGui/QWidget> + +#include <debugger/debuggermanager.h> +#include <projectexplorer/runconfiguration.h> +#include <projectexplorer/applicationlauncher.h> + +namespace Qt4ProjectManager { +class Qt4Project; + +namespace Internal { + +class MaemoManager; +class MaemoToolChain; +using namespace ProjectExplorer; +typedef QSharedPointer<RunConfiguration> RunConfig; + +#define USE_SSL_PASSWORD 0 + +class ErrorDumper : public QObject +{ + Q_OBJECT +public: + ErrorDumper(QObject *parent = 0) + : QObject(parent) {} + +public slots: + void printToStream(QProcess::ProcessError error); +}; + + +class MaemoRunConfiguration : public RunConfiguration +{ + Q_OBJECT +public: + MaemoRunConfiguration(Project *project, const QString &proFilePath); + ~MaemoRunConfiguration(); + + QString type() const; + bool isEnabled() const; + QWidget *configurationWidget(); + Qt4Project *project() const; + + void save(ProjectExplorer::PersistentSettingsWriter &writer) const; + void restore(const ProjectExplorer::PersistentSettingsReader &reader); + + bool currentlyNeedsDeployment() const; + void wasDeployed(); + + bool hasDebuggingHelpers() const; + bool debuggingHelpersNeedDeployment() const; + void debuggingHelpersDeployed(); + + QString maddeRoot() const; + QString executable() const; + const QString sysRoot() const; + const QStringList arguments() const { return m_arguments; } + void setArguments(const QStringList &args); + + QString simulator() const; + QString simulatorArgs() const; + QString simulatorPath() const; + QString visibleSimulatorParameter() const; + + bool remoteHostIsSimulator() const { return m_remoteHostIsSimulator; } + const QString remoteHostName() const { return m_remoteHostName; } + const QString remoteUserName() const { return m_remoteUserName; } + int remotePort() const { return m_remotePort > 0 ? m_remotePort : 22; } + + const QString remoteDir() const; + const QString sshCmd() const; + const QString scpCmd() const; + const QString gdbCmd() const; + const QString dumperLib() const; + + void setRemoteHostIsSimulator(bool isSimulator); + void setRemoteHostName(const QString &hostName); + void setRemoteUserName(const QString &userName); + void setRemotePort(int port); + + bool isQemuRunning() const; + +#if USE_SSL_PASSWORD + // Only valid if remoteHostRequiresPassword() == true. + void setRemotePassword(const QString &password); + const QString remoteUserPassword() const { return m_remoteUserPassword; } + + void setRemoteHostRequiresPassword(bool requiresPassword); + bool remoteHostRequiresPassword() const { return m_remoteHostRequiresPassword; } +#endif + +signals: + void targetInformationChanged(); + void cachedSimulatorInformationChanged(); + void qemuProcessStatus(bool running); + +private slots: + void invalidateCachedTargetInformation(); + + void setSimulatorPath(const QString &path); + void invalidateCachedSimulatorInformation(); + + void startStopQemu(); + void qemuProcessFinished(); + + void enabledStateChanged(); + +private: + void updateTarget(); + void updateSimulatorInformation(); + const QString cmd(const QString &cmdName) const; + const MaemoToolChain *toolchain() const; + bool fileNeedsDeployment(const QString &path, const QDateTime &lastDeployed) const; + +private: + // Keys for saving/loading attributes. + static const QString ArgumentsKey; + static const QString RemoteHostIsSimulatorKey; + static const QString RemoteHostRequiresPasswordKey; + static const QString RemoteHostNameKey; + static const QString RemoteUserNameKey; + static const QString RemoteUserPasswordKey; + static const QString RemotePortKey; + static const QString LastDeployedKey; + static const QString DebuggingHelpersLastDeployedKey; + + QString m_executable; + QString m_proFilePath; + bool m_cachedTargetInformationValid; + + QStringList m_arguments; + QString m_simulator; + QString m_simulatorArgs; + QString m_simulatorPath; + QString m_visibleSimulatorParameter; + bool m_cachedSimulatorInformationValid; + + QString m_gdbPath; + + // Information about the remote host. + bool m_remoteHostIsSimulator; + QString m_remoteHostName; + QString m_remoteUserName; + int m_remotePort; + + QDateTime m_lastDeployed; + QDateTime m_debuggingHelpersLastDeployed; + + QProcess *qemu; + ErrorDumper dumper; + +#if USE_SSL_PASSWORD + QString m_remoteUserPassword; + bool m_remoteHostRequiresPassword; +#endif +}; + + +class MaemoRunConfigurationFactory : public IRunConfigurationFactory +{ + Q_OBJECT +public: + MaemoRunConfigurationFactory(QObject *parent); + ~MaemoRunConfigurationFactory(); + + bool canRestore(const QString &type) const; + QStringList availableCreationTypes(Project *project) const; + QString displayNameForType(const QString &type) const; + RunConfig create(Project *project, const QString &type); + +private slots: + void addedRunConfiguration(ProjectExplorer::Project* project); + void removedRunConfiguration(ProjectExplorer::Project* project); + + void projectAdded(ProjectExplorer::Project* project); + void projectRemoved(ProjectExplorer::Project* project); + void currentProjectChanged(ProjectExplorer::Project* project); +}; + + +class MaemoRunControlFactory : public IRunControlFactory +{ + Q_OBJECT +public: + MaemoRunControlFactory(QObject *parent = 0); + bool canRun(const RunConfig &runConfiguration, const QString &mode) const; + RunControl* create(const RunConfig &runConfiguration, const QString &mode); + QString displayName() const; + QWidget *configurationWidget(const RunConfig &runConfiguration); +}; + +} // namespace Internal +} // namespace Qt4ProjectManager + + +#endif // MAEMORUNCONFIGURATION_H diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c029e5b0d33dc1750f2d0b607ee88d6e5d4c0ba --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp @@ -0,0 +1,220 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "maemotoolchain.h" +#include "qtversionmanager.h" + +#include <QtCore/QDir> +#include <QtCore/QtDebug> + +using namespace ProjectExplorer; +using namespace Qt4ProjectManager::Internal; + +#ifdef Q_OS_WIN32 +#define EXEC_SUFFIX ".exe" +#else +#define EXEC_SUFFIX "" +#endif + +namespace { + const char *GCC_MAEMO_COMMAND = "arm-none-linux-gnueabi-gcc" EXEC_SUFFIX; +} + +MaemoToolChain::MaemoToolChain(const Qt4ProjectManager::QtVersion *version) + : GccToolChain(QLatin1String(GCC_MAEMO_COMMAND)) + , m_maddeInitialized(false) + , m_sysrootInitialized(false) + , m_simulatorInitialized(false) + , m_targetInitialized(false) + , m_toolchainInitialized(false) + , m_version(version) +{ +} + +MaemoToolChain::~MaemoToolChain() +{ +} + +ToolChain::ToolChainType MaemoToolChain::type() const +{ + return ToolChain::GCC_MAEMO; +} + +QList<HeaderPath> MaemoToolChain::systemHeaderPaths() +{ + if (m_systemHeaderPaths.isEmpty()) { + GccToolChain::systemHeaderPaths(); + m_systemHeaderPaths + .append(HeaderPath(QString("%1/usr/include").arg(sysrootRoot()), + HeaderPath::GlobalHeaderPath)); + } + return m_systemHeaderPaths; +} + +void MaemoToolChain::addToEnvironment(ProjectExplorer::Environment &env) +{ + if (m_version) { + env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/bin") + .arg(maddeRoot()))); + env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/bin") + .arg(targetRoot()))); + env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/bin") + .arg(toolchainRoot()))); +#ifdef Q_OS_WIN + env.set("HOME", QDir::toNativeSeparators(maddeRoot() + + QLatin1String("/home/") + QDir::home().dirName())); +#endif + } +} + +QString MaemoToolChain::makeCommand() const +{ + return QLatin1String("make" EXEC_SUFFIX); +} + +bool MaemoToolChain::equals(ToolChain *other) const +{ + MaemoToolChain *toolChain = static_cast<MaemoToolChain*> (other); + return (other->type() == type() + && toolChain->sysrootRoot() == sysrootRoot() + && toolChain->simulatorRoot() == simulatorRoot() + && toolChain->targetRoot() == targetRoot() + && toolChain->toolchainRoot() == toolchainRoot()); +} + +QString MaemoToolChain::maddeRoot() const +{ + if (!m_maddeInitialized) + (const_cast<MaemoToolChain*> (this))->setMaddeRoot(); + return m_maddeRoot; +} + +QString MaemoToolChain::targetRoot() const +{ + if (!m_targetInitialized) + (const_cast<MaemoToolChain*> (this))->setTargetRoot(); + return m_targetRoot; +} + +QString MaemoToolChain::sysrootRoot() const +{ + if (!m_sysrootInitialized) + (const_cast<MaemoToolChain*> (this))->setSysrootAndToolchain(); + return m_sysrootRoot; +} + +QString MaemoToolChain::simulatorRoot() const +{ + if (!m_simulatorInitialized) + (const_cast<MaemoToolChain*> (this))->setSimulatorRoot(); + return m_simulatorRoot; +} + +QString MaemoToolChain::toolchainRoot() const +{ + if (!m_toolchainInitialized) + (const_cast<MaemoToolChain*> (this))->setSysrootAndToolchain(); + return m_toolchainRoot; +} + +void MaemoToolChain::setTargetRoot() +{ + m_targetInitialized = true; + QString qmake = QDir::cleanPath(m_version->qmakeCommand()); + m_targetRoot = qmake.remove(QLatin1String("/bin/qmake" EXEC_SUFFIX)); +} + +void MaemoToolChain::setMaddeRoot() +{ + QDir dir(targetRoot()); + dir.cdUp(); dir.cdUp(); + + m_maddeInitialized = true; + m_maddeRoot = dir.absolutePath(); +} + +void MaemoToolChain::setSimulatorRoot() +{ + QString target = QDir::cleanPath(targetRoot()); + target = target.mid(target.lastIndexOf(QLatin1Char('/')) + 1); + + QFile file(maddeRoot() + QLatin1String("/cache/madde.conf")); + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + QString line = stream.readLine().trimmed(); + if (!line.startsWith(QLatin1String("target"))) + continue; + + const QStringList &list = line.split(QLatin1Char(' ')); + if (list.count() <= 1 || list.at(1) != target) + continue; + + line = stream.readLine().trimmed(); + while (!stream.atEnd() && line != QLatin1String("end")) { + if (line.startsWith(QLatin1String("runtime"))) { + const QStringList &list = line.split(QLatin1Char(' ')); + if (list.count() > 1) { + m_simulatorRoot = maddeRoot() + + QLatin1String("/runtimes/") + list.at(1).trimmed(); + } + break; + } + line = stream.readLine().trimmed(); + } + } + } + + m_simulatorInitialized = true; +} + +void MaemoToolChain::setSysrootAndToolchain() +{ + QFile file(QDir::cleanPath(targetRoot()) + QLatin1String("/information")); + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + const QString &line = stream.readLine().trimmed(); + const QStringList &list = line.split(QLatin1Char(' ')); + if (list.count() <= 1) + continue; + if (list.at(0) == QLatin1String("sysroot")) { + m_sysrootRoot = maddeRoot() + QLatin1String("/sysroots/") + + list.at(1); + } + if (list.at(0) == QLatin1String("toolchain")) { + m_toolchainRoot = maddeRoot() + QLatin1String("/toolchains/") + + list.at(1); + } + } + } + + m_sysrootInitialized = true; + m_toolchainInitialized = true; +} diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h new file mode 100644 index 0000000000000000000000000000000000000000..1ed3d52af224dab3c08109638021a117ecd738c0 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h @@ -0,0 +1,87 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MAEMOTOOLCHAIN_H +#define MAEMOTOOLCHAIN_H + +#include <projectexplorer/toolchain.h> + +namespace Qt4ProjectManager { + class QtVersion; + namespace Internal { + +class MaemoToolChain : public ProjectExplorer::GccToolChain +{ +public: + MaemoToolChain(const Qt4ProjectManager::QtVersion *version); + virtual ~MaemoToolChain(); + + QList<ProjectExplorer::HeaderPath> systemHeaderPaths(); + void addToEnvironment(ProjectExplorer::Environment &env); + ProjectExplorer::ToolChain::ToolChainType type() const; + QString makeCommand() const; + + QString maddeRoot() const; + QString targetRoot() const; + QString sysrootRoot() const; + QString simulatorRoot() const; + QString toolchainRoot() const; + +protected: + bool equals(ToolChain *other) const; + +private: + void setMaddeRoot(); + void setTargetRoot(); + void setSimulatorRoot(); + void setSysrootAndToolchain(); + +private: + QString m_maddeRoot; + bool m_maddeInitialized; + + QString m_sysrootRoot; + bool m_sysrootInitialized; + + QString m_simulatorRoot; + bool m_simulatorInitialized; + + QString m_targetRoot; + bool m_targetInitialized; + + QString m_toolchainRoot; + bool m_toolchainInitialized; + + const Qt4ProjectManager::QtVersion *m_version; +}; + + } // namespace Internal +} // namespace Qt4ProjectManager + +#endif // MAEMOTOOLCHAIN_H diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri new file mode 100644 index 0000000000000000000000000000000000000000..31d800c74a4ff3311aa3232d305dad8e5082cc5c --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.pri @@ -0,0 +1,14 @@ +SUPPORT_QT_MAEMO = $$(QTCREATOR_WITH_MAEMO) +!isEmpty(SUPPORT_QT_MAEMO) { + message("Adding experimental support for Qt/Maemo applications.") + DEFINES += QTCREATOR_WITH_MAEMO + HEADERS += \ + $$PWD/maemorunconfiguration.h \ + $$PWD/maemomanager.h \ + $$PWD/maemotoolchain.h + SOURCES += \ + $$PWD/maemorunconfiguration.cpp \ + $$PWD/maemomanager.cpp \ + $$PWD/maemotoolchain.cpp + RESOURCES += $$PWD/qt-maemo.qrc +} diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.qrc b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.qrc new file mode 100644 index 0000000000000000000000000000000000000000..354fe64d1be9a16a17ec3a1d86223c8db39ffd9c --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-maemo/qt-maemo.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/qt-maemo"> + <file>images/qemu-run.png</file> + <file>images/qemu-stop.png</file> + </qresource> +</RCC> diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro index a85ffcef011e6fdc409e650dc4f098070f9b18e6..de942dadbee0e3bd0ec59e1cc8a1ab28f48a14e4 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.pro +++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro @@ -88,6 +88,7 @@ RESOURCES += qt4projectmanager.qrc \ wizards/wizards.qrc include(../../shared/proparser/proparser.pri) include(qt-s60/qt-s60.pri) +include(qt-maemo/qt-maemo.pri) include(customwidgetwizard/customwidgetwizard.pri) DEFINES += QT_NO_CAST_TO_ASCII OTHER_FILES += Qt4ProjectManager.pluginspec diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp index 468e9a260a2b7f035020d8d5b6b3a936e094f176..9471e3d1f30c8a8ce4dffd830d56b7fe2b4a8dd2 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp @@ -51,6 +51,10 @@ #include "qt-s60/s60manager.h" #endif +#ifdef QTCREATOR_WITH_MAEMO +#include "qt-maemo/maemomanager.h" +#endif + #include <coreplugin/icore.h> #include <extensionsystem/pluginmanager.h> #include <projectexplorer/buildmanager.h> @@ -160,6 +164,10 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString * addAutoReleasedObject(new S60Manager); #endif +#ifdef QTCREATOR_WITH_MAEMO + addAutoReleasedObject(MaemoManager::instance()); +#endif + // TODO reenable //m_embeddedPropertiesPage = new EmbeddedPropertiesPage; //addObject(m_embeddedPropertiesPage); diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp index ac35590a6b476afb0828d04ee67e1ee105ccc6eb..a17b7e7092e37ac0f62a82c1d9b9201ca5294e5e 100644 --- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp @@ -95,15 +95,21 @@ QString Qt4RunConfiguration::type() const bool Qt4RunConfiguration::isEnabled() const { -#ifdef QTCREATOR_WITH_S60 +#if defined(QTCREATOR_WITH_S60) || defined(QTCREATOR_WITH_MAEMO) Qt4Project *pro = qobject_cast<Qt4Project*>(project()); QTC_ASSERT(pro, return false); ProjectExplorer::ToolChain::ToolChainType type = pro->toolChainType(pro->activeBuildConfiguration()); +#ifdef QTCREATOR_WITH_S60 if (type == ProjectExplorer::ToolChain::WINSCW || type == ProjectExplorer::ToolChain::GCCE || type == ProjectExplorer::ToolChain::RVCT_ARMV5 || type == ProjectExplorer::ToolChain::RVCT_ARMV6) return false; +#endif +#ifdef QTCREATOR_WITH_MAEMO + if (type == ProjectExplorer::ToolChain::GCC_MAEMO) + return false; +#endif #endif return true; } diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index d7a1dc3843c59bbcb6c06478b9789404111c2fb0..3125fccddd2d6af4357078766dd48d86583bae51 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -35,6 +35,9 @@ #ifdef QTCREATOR_WITH_S60 #include "qt-s60/s60manager.h" #endif +#ifdef QTCREATOR_WITH_MAEMO +#include "qt-maemo/maemomanager.h" +#endif #include <projectexplorer/debugginghelper.h> #include <projectexplorer/projectexplorer.h> @@ -1055,6 +1058,10 @@ ProjectExplorer::ToolChain *QtVersion::createToolChain(ProjectExplorer::ToolChai } else if (type == ProjectExplorer::ToolChain::RVCT_ARMV5 || type == ProjectExplorer::ToolChain::RVCT_ARMV6) { tempToolchain = S60Manager::instance()->createRVCTToolChain(this, type); +#endif +#ifdef QTCREATOR_WITH_MAEMO + } else if (type == ProjectExplorer::ToolChain::GCC_MAEMO) { + tempToolchain = MaemoManager::instance()->maemoToolChain(this); #endif } else { qDebug()<<"Could not create ToolChain for"<<mkspec(); @@ -1150,6 +1157,25 @@ QList<ProjectExplorer::ToolChain::ToolChainType> QtVersion::possibleToolChainTyp << ProjectExplorer::ToolChain::RVCT_ARMV5 << ProjectExplorer::ToolChain::RVCT_ARMV6 << ProjectExplorer::ToolChain::WINSCW; +#endif +#ifdef QTCREATOR_WITH_MAEMO + } else if (spec.contains("linux-g++-opengl")) { + bool maemo = false; + const QString baseDir = m_versionInfo.contains("QT_INSTALL_DATA") ? + m_versionInfo.value("QT_INSTALL_DATA") : QLatin1String(""); + QFile qconfigpri(baseDir + QLatin1String("/mkspecs/qconfig.pri")); + if (qconfigpri.exists()) { + qconfigpri.open(QIODevice::ReadOnly | QIODevice::Text); + QTextStream stream(&qconfigpri); + while (!stream.atEnd()) { + QString line = stream.readLine().trimmed(); + if (line.startsWith(QLatin1String("QT_ARCH")) + && line.endsWith(QLatin1String("arm"))) + maemo = true; + } + } + toolChains << (maemo ? ProjectExplorer::ToolChain::GCC_MAEMO + : ProjectExplorer::ToolChain::GCC); #endif } else { toolChains << ProjectExplorer::ToolChain::GCC;