diff options
Diffstat (limited to 'src/plugins')
468 files changed, 10760 insertions, 5894 deletions
diff --git a/src/plugins/QtcPlugin.qbs b/src/plugins/QtcPlugin.qbs index da48870f3b..8d4ca84bb1 100644 --- a/src/plugins/QtcPlugin.qbs +++ b/src/plugins/QtcPlugin.qbs @@ -20,7 +20,7 @@ Product { Depends { name: "pluginspec" } Depends { name: 'cpp' } - cpp.defines: [ name.toUpperCase() + "_LIBRARY" ] + cpp.defines: [name.toUpperCase() + "_LIBRARY"] cpp.rpaths: ["$ORIGIN/../../.."] Group { diff --git a/src/plugins/analyzerbase/AnalyzerBase.pluginspec.in b/src/plugins/analyzerbase/AnalyzerBase.pluginspec.in index 3bcb94e25c..70beca98a1 100644 --- a/src/plugins/analyzerbase/AnalyzerBase.pluginspec.in +++ b/src/plugins/analyzerbase/AnalyzerBase.pluginspec.in @@ -17,5 +17,6 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"RemoteLinux\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/> </dependencyList> </plugin> diff --git a/src/plugins/analyzerbase/analyzerbase.qbs b/src/plugins/analyzerbase/analyzerbase.qbs index 9ca081487e..7b8f2ff30f 100644 --- a/src/plugins/analyzerbase/analyzerbase.qbs +++ b/src/plugins/analyzerbase/analyzerbase.qbs @@ -7,7 +7,7 @@ QtcPlugin { Depends { name: "qt"; submodules: ['gui'] } Depends { name: "Core" } - Depends { name: "CPlusPlus" } + Depends { name: "CppTools" } Depends { name: "RemoteLinux" } Depends { name: "ProjectExplorer" } Depends { name: "TextEditor" } diff --git a/src/plugins/analyzerbase/analyzerbase_dependencies.pri b/src/plugins/analyzerbase/analyzerbase_dependencies.pri index 65e1ef20fa..8ac7abd387 100644 --- a/src/plugins/analyzerbase/analyzerbase_dependencies.pri +++ b/src/plugins/analyzerbase/analyzerbase_dependencies.pri @@ -2,3 +2,4 @@ include(../../plugins/coreplugin/coreplugin.pri) include(../../libs/cplusplus/cplusplus.pri) include(../../plugins/projectexplorer/projectexplorer.pri) include(../../plugins/remotelinux/remotelinux.pri) +include(../../plugins/cpptools/cpptools.pri) diff --git a/src/plugins/analyzerbase/analyzerplugin.cpp b/src/plugins/analyzerbase/analyzerplugin.cpp index a8a3367c3e..fd7084de9c 100644 --- a/src/plugins/analyzerbase/analyzerplugin.cpp +++ b/src/plugins/analyzerbase/analyzerplugin.cpp @@ -43,7 +43,7 @@ #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> -#include <extensionsystem/pluginmanager.h> +#include <projectexplorer/projectexplorer.h> #include <projectexplorer/task.h> #include <projectexplorer/taskhub.h> @@ -83,10 +83,9 @@ bool AnalyzerPlugin::initialize(const QStringList &arguments, QString *errorStri addAutoReleasedObject(new AnalyzerRunControlFactory()); // Task integration. - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - ProjectExplorer::TaskHub *hub = pm->getObject<ProjectExplorer::TaskHub>(); //: Category under which Analyzer tasks are listed in Issues view - hub->addCategory(Core::Id(Constants::ANALYZERTASK_ID), tr("Analyzer")); + ProjectExplorer::ProjectExplorerPlugin::instance()->taskHub() + ->addCategory(Core::Id(Constants::ANALYZERTASK_ID), tr("Analyzer")); return true; } diff --git a/src/plugins/analyzerbase/analyzerplugin.h b/src/plugins/analyzerbase/analyzerplugin.h index 7db7c8c206..da5d80588c 100644 --- a/src/plugins/analyzerbase/analyzerplugin.h +++ b/src/plugins/analyzerbase/analyzerplugin.h @@ -43,6 +43,7 @@ namespace Internal { class AnalyzerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "AnalyzerBase.json") public: static AnalyzerPlugin *instance(); diff --git a/src/plugins/analyzerbase/analyzerruncontrol.cpp b/src/plugins/analyzerbase/analyzerruncontrol.cpp index bda27e8fbf..5cb91674a5 100644 --- a/src/plugins/analyzerbase/analyzerruncontrol.cpp +++ b/src/plugins/analyzerbase/analyzerruncontrol.cpp @@ -39,8 +39,8 @@ #include "analyzermanager.h" #include "analyzerstartparameters.h" -#include <extensionsystem/pluginmanager.h> #include <projectexplorer/applicationrunconfiguration.h> +#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/task.h> #include <projectexplorer/taskhub.h> @@ -115,10 +115,9 @@ void AnalyzerRunControl::start() AnalyzerManager::handleToolStarted(); - // clear about-to-be-outdated tasks - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - TaskHub *hub = pm->getObject<TaskHub>(); - hub->clearTasks(Core::Id(Constants::ANALYZERTASK_ID)); + // Clear about-to-be-outdated tasks. + ProjectExplorerPlugin::instance()->taskHub() + ->clearTasks(Core::Id(Constants::ANALYZERTASK_ID)); if (d->m_engine->start()) { d->m_isRunning = true; @@ -177,8 +176,7 @@ void AnalyzerRunControl::receiveOutput(const QString &text, Utils::OutputFormat void AnalyzerRunControl::addTask(Task::TaskType type, const QString &description, const QString &file, int line) { - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - TaskHub *hub = pm->getObject<TaskHub>(); + TaskHub *hub = ProjectExplorerPlugin::instance()->taskHub(); hub->addTask(Task(type, description, Utils::FileName::fromUserInput(file), line, Core::Id(Constants::ANALYZERTASK_ID))); hub->popup(false); diff --git a/src/plugins/analyzerbase/analyzerstartparameters.h b/src/plugins/analyzerbase/analyzerstartparameters.h index 651e05d7ce..d84bd95771 100644 --- a/src/plugins/analyzerbase/analyzerstartparameters.h +++ b/src/plugins/analyzerbase/analyzerstartparameters.h @@ -51,7 +51,6 @@ class ANALYZER_EXPORT AnalyzerStartParameters { public: AnalyzerStartParameters() - : connParams(Utils::SshConnectionParameters::NoProxy) {} StartMode startMode; diff --git a/src/plugins/analyzerbase/analyzerutils.cpp b/src/plugins/analyzerbase/analyzerutils.cpp index 902bac3404..870cb160df 100644 --- a/src/plugins/analyzerbase/analyzerutils.cpp +++ b/src/plugins/analyzerbase/analyzerutils.cpp @@ -41,7 +41,7 @@ #include <utils/qtcassert.h> #include <cplusplus/ExpressionUnderCursor.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/LookupItem.h> #include <cplusplus/TypeOfExpression.h> diff --git a/src/plugins/analyzerbase/startremotedialog.cpp b/src/plugins/analyzerbase/startremotedialog.cpp index 4e071aa47d..25b784f607 100644 --- a/src/plugins/analyzerbase/startremotedialog.cpp +++ b/src/plugins/analyzerbase/startremotedialog.cpp @@ -115,7 +115,7 @@ void StartRemoteDialog::validate() Utils::SshConnectionParameters StartRemoteDialog::sshParams() const { - Utils::SshConnectionParameters params(Utils::SshConnectionParameters::NoProxy); + Utils::SshConnectionParameters params; params.host = m_ui->host->text(); params.userName = m_ui->user->text(); if (m_ui->keyFile->isValid()) { diff --git a/src/plugins/autotoolsprojectmanager/autogenstep.cpp b/src/plugins/autotoolsprojectmanager/autogenstep.cpp index e6d1b93b57..4c3c4e6607 100644 --- a/src/plugins/autotoolsprojectmanager/autogenstep.cpp +++ b/src/plugins/autotoolsprojectmanager/autogenstep.cpp @@ -84,7 +84,7 @@ bool AutogenStepFactory::canCreate(BuildStepList *parent, const QString &id) con if (parent->target()->project()->id() != QLatin1String(Constants::AUTOTOOLS_PROJECT_ID)) return false; - if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD) + if (parent->id() != QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD)) return false; return QLatin1String(AUTOGEN_STEP_ID) == id; @@ -282,7 +282,7 @@ void AutogenStepConfigWidget::updateDetails() param.setMacroExpander(bc->macroExpander()); param.setEnvironment(bc->environment()); param.setWorkingDirectory(bc->buildDirectory()); - param.setCommand("autogen.sh"); + param.setCommand(QLatin1String("autogen.sh")); param.setArguments(m_autogenStep->additionalArguments()); m_summaryText = param.summary(displayName()); emit updateSummary(); diff --git a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp index 09d7d3cc2a..587bd68333 100644 --- a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp +++ b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp @@ -83,7 +83,7 @@ bool AutoreconfStepFactory::canCreate(BuildStepList *parent, const QString &id) if (parent->target()->project()->id() != QLatin1String(Constants::AUTOTOOLS_PROJECT_ID)) return false; - if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD) + if (parent->id() != QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD)) return false; return QLatin1String(AUTORECONF_STEP_ID) == id; @@ -166,7 +166,7 @@ bool AutoreconfStep::init() pp->setMacroExpander(bc->macroExpander()); pp->setEnvironment(bc->environment()); pp->setWorkingDirectory(bc->buildDirectory()); - pp->setCommand("autoreconf"); + pp->setCommand(QLatin1String("autoreconf")); pp->setArguments(additionalArguments()); return AbstractProcessStep::init(); @@ -276,7 +276,7 @@ void AutoreconfStepConfigWidget::updateDetails() param.setMacroExpander(bc->macroExpander()); param.setEnvironment(bc->environment()); param.setWorkingDirectory(bc->buildDirectory()); - param.setCommand("autoreconf"); + param.setCommand(QLatin1String("autoreconf")); param.setArguments(m_autoreconfStep->additionalArguments()); m_summaryText = param.summary(displayName()); emit updateSummary(); diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp index b0986cfc73..92eafe762b 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildconfiguration.cpp @@ -170,7 +170,7 @@ AutotoolsBuildConfiguration *AutotoolsBuildConfigurationFactory::create(Target * bc->setDisplayName(buildConfigurationName); t->addBuildConfiguration(bc); - t->addDeployConfiguration(t->createDeployConfiguration(DEFAULT_DEPLOYCONFIGURATION_ID)); + t->addDeployConfiguration(t->createDeployConfiguration(QLatin1String(DEFAULT_DEPLOYCONFIGURATION_ID))); // User needs to choose where the executable file is. // TODO: Parse the file in *Anjuta style* to be able to add custom RunConfigurations. t->addRunConfiguration(new CustomExecutableRunConfiguration(t)); @@ -181,7 +181,7 @@ AutotoolsBuildConfiguration *AutotoolsBuildConfigurationFactory::create(Target * AutotoolsBuildConfiguration *AutotoolsBuildConfigurationFactory::createDefaultConfiguration(AutotoolsTarget *target) const { AutotoolsBuildConfiguration *bc = new AutotoolsBuildConfiguration(target); - BuildStepList *buildSteps = bc->stepList(BUILDSTEPS_BUILD); + BuildStepList *buildSteps = bc->stepList(QLatin1String(BUILDSTEPS_BUILD)); // ### Build Steps Build ### // autogen.sh or autoreconf @@ -205,7 +205,7 @@ AutotoolsBuildConfiguration *AutotoolsBuildConfigurationFactory::createDefaultCo makeStep->setBuildTarget(QLatin1String("all"), /*on =*/ true); // ### Build Steps Clean ### - BuildStepList *cleanSteps = bc->stepList(BUILDSTEPS_CLEAN); + BuildStepList *cleanSteps = bc->stepList(QLatin1String(BUILDSTEPS_CLEAN)); MakeStep *cleanMakeStep = new MakeStep(cleanSteps); cleanMakeStep->setAdditionalArguments(QLatin1String("clean")); cleanMakeStep->setClean(true); diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp index 132f805937..92603861af 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp @@ -48,7 +48,7 @@ #include <projectexplorer/buildsteplist.h> #include <projectexplorer/projectexplorerconstants.h> #include <extensionsystem/pluginmanager.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <coreplugin/icore.h> #include <utils/qtcassert.h> @@ -148,11 +148,6 @@ AutotoolsTarget *AutotoolsProject::activeTarget() const return static_cast<AutotoolsTarget *>(Project::activeTarget()); } -QList<Project *> AutotoolsProject::dependsOn() -{ - return QList<Project *>(); -} - QString AutotoolsProject::defaultBuildDirectory() const { return projectDirectory(); @@ -317,7 +312,7 @@ void AutotoolsProject::makefileParsingFinished() // Add configure.ac file to project and watch for changes. const QLatin1String configureAc(QLatin1String("configure.ac")); - const QFile configureAcFile(fileInfo.absolutePath() + QChar('/') + configureAc); + const QFile configureAcFile(fileInfo.absolutePath() + QLatin1Char('/') + configureAc); if (configureAcFile.exists()) { files.append(configureAc); const QString configureAcFilePath = dir.absoluteFilePath(configureAc); @@ -368,13 +363,10 @@ void AutotoolsProject::buildFileNodeTree(const QDir &directory, if (file.contains(QLatin1String(".moc"))) continue; - QString subDir = baseDir + QChar('/') + file; - for (int i = subDir.length() - 1; i >= 0; --i) { - if (subDir.at(i) == QChar('/')) { - subDir = subDir.left(i); - break; - } - } + QString subDir = baseDir + QLatin1Char('/') + file; + const int lastSlashPos = subDir.lastIndexOf(QLatin1Char('/')); + if (lastSlashPos != -1) + subDir.truncate(lastSlashPos); // Add folder nodes, that are not already available oldParentFolder = parentFolder; diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.h b/src/plugins/autotoolsprojectmanager/autotoolsproject.h index 5524e012b7..b737e11ebb 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.h +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.h @@ -84,7 +84,6 @@ public: QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets(); ProjectExplorer::ProjectNode *rootProjectNode() const; QStringList files(FilesMode fileMode) const; - QList<ProjectExplorer::Project *> dependsOn(); QString defaultBuildDirectory() const; QStringList buildTargets() const; ProjectExplorer::ToolChain *toolChain() const; diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro index b642847aa7..b428d54a28 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro +++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectmanager.pro @@ -1,6 +1,7 @@ TEMPLATE = lib TARGET = AutotoolsProjectManager #PROVIDER = Openismus +DEFINES += QT_NO_CAST_FROM_ASCII include(../../qtcreatorplugin.pri) include(autotoolsprojectmanager_dependencies.pri) diff --git a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h index e7210d0ac3..2e46de1746 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h +++ b/src/plugins/autotoolsprojectmanager/autotoolsprojectplugin.h @@ -70,6 +70,9 @@ namespace Internal { class AutotoolsProjectPlugin : public ExtensionSystem::IPlugin { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "AutotoolsProjectManager.json") + public: AutotoolsProjectPlugin(); diff --git a/src/plugins/autotoolsprojectmanager/autotoolstarget.cpp b/src/plugins/autotoolsprojectmanager/autotoolstarget.cpp index 1ed7d5de70..431a9e6367 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolstarget.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolstarget.cpp @@ -146,10 +146,10 @@ AutotoolsTarget *AutotoolsTargetFactory::create(Project *parent, const QString & // Add default build configuration: AutotoolsBuildConfigurationFactory *bcf = t->buildConfigurationFactory(); AutotoolsBuildConfiguration *bc = bcf->createDefaultConfiguration(t); - bc->setDisplayName("Default Build"); + bc->setDisplayName(tr("Default Build")); t->addBuildConfiguration(bc); - t->addDeployConfiguration(t->createDeployConfiguration(ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID)); + t->addDeployConfiguration(t->createDeployConfiguration(QLatin1String(ProjectExplorer::Constants::DEFAULT_DEPLOYCONFIGURATION_ID))); // User needs to choose where the executable file is. // TODO: Parse the file in *Anjuta style* to be able to add custom RunConfigurations. t->addRunConfiguration(new CustomExecutableRunConfiguration(t)); diff --git a/src/plugins/autotoolsprojectmanager/configurestep.cpp b/src/plugins/autotoolsprojectmanager/configurestep.cpp index 1fce702ca8..095911a326 100644 --- a/src/plugins/autotoolsprojectmanager/configurestep.cpp +++ b/src/plugins/autotoolsprojectmanager/configurestep.cpp @@ -84,7 +84,7 @@ bool ConfigureStepFactory::canCreate(BuildStepList *parent, const QString &id) c if (parent->target()->project()->id() != QLatin1String(Constants::AUTOTOOLS_PROJECT_ID)) return false; - if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD) + if (parent->id() != QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD)) return false; return QLatin1String(CONFIGURE_STEP_ID) == id; @@ -167,7 +167,7 @@ bool ConfigureStep::init() pp->setMacroExpander(bc->macroExpander()); pp->setEnvironment(bc->environment()); pp->setWorkingDirectory(bc->buildDirectory()); - pp->setCommand("configure"); + pp->setCommand(QLatin1String("configure")); pp->setArguments(additionalArguments()); return AbstractProcessStep::init(); @@ -280,7 +280,7 @@ void ConfigureStepConfigWidget::updateDetails() param.setMacroExpander(bc->macroExpander()); param.setEnvironment(bc->environment()); param.setWorkingDirectory(bc->buildDirectory()); - param.setCommand("configure"); + param.setCommand(QLatin1String("configure")); param.setArguments(m_configureStep->additionalArguments()); m_summaryText = param.summary(displayName()); emit updateSummary(); diff --git a/src/plugins/autotoolsprojectmanager/makefileparser.cpp b/src/plugins/autotoolsprojectmanager/makefileparser.cpp index 0bee440343..c87ca62b46 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparser.cpp +++ b/src/plugins/autotoolsprojectmanager/makefileparser.cpp @@ -134,7 +134,7 @@ MakefileParser::TopTarget MakefileParser::topTarget() const TopTarget topTarget = Undefined; const QString line = m_line.simplified(); - if (!line.isEmpty() && !line.startsWith(QChar('#'))) { + if (!line.isEmpty() && !line.startsWith(QLatin1Char('#'))) { // TODO: Check how many fixed strings like AM_DEFAULT_SOURCE_EXT will // be needed vs. variable strings like _SOURCES. Dependent on this a // more clever way than this (expensive) if-cascading might be done. @@ -236,7 +236,7 @@ void MakefileParser::parseSubDirs() QStringList::iterator it = subDirs.begin(); while (it != subDirs.end()) { // Erase all entries that represent a '.' - if ((*it) == QChar('.')) { + if ((*it) == QLatin1String(".")) { hasDotSubDir = true; it = subDirs.erase(it); } else { @@ -256,7 +256,7 @@ void MakefileParser::parseSubDirs() // Delegate the parsing of all sub directories to a local // makefile parser and merge the results foreach (const QString& subDir, subDirs) { - const QChar slash('/'); + const QChar slash = QLatin1Char('/'); const QString subDirMakefile = path + slash + subDir + slash + makefileName; @@ -317,7 +317,7 @@ QStringList MakefileParser::directorySources(const QString &directory, extensions); const QString dirPath = info.fileName(); foreach (const QString& subDirSource, subDirSources) - list.append(dirPath + QChar('/') + subDirSource); + list.append(dirPath + QLatin1Char('/') + subDirSource); } else { // Check whether the file matches to an extension foreach (const QString& extension, extensions) { @@ -339,7 +339,7 @@ QStringList MakefileParser::targetValues(bool *hasVariables) if (hasVariables != 0) *hasVariables = false; - const int index = m_line.indexOf(QChar('=')); + const int index = m_line.indexOf(QLatin1Char('=')); if (index < 0) { m_success = false; return QStringList(); @@ -354,7 +354,7 @@ QStringList MakefileParser::targetValues(bool *hasVariables) // Get all values of a line separated by spaces. // Values representing a variable like $(value) get // removed currently. - QStringList lineValues = m_line.split(QChar(' ')); + QStringList lineValues = m_line.split(QLatin1Char(' ')); QStringList::iterator it = lineValues.begin(); while (it != lineValues.end()) { if ((*it).startsWith(QLatin1String("$("))) { @@ -368,7 +368,7 @@ QStringList MakefileParser::targetValues(bool *hasVariables) endReached = lineValues.isEmpty(); if (!endReached) { - const QChar backSlash('\\'); + const QChar backSlash = QLatin1Char('\\'); QString last = lineValues.last(); if (last.endsWith(backSlash)) { // The last value contains a backslash. Remove the diff --git a/src/plugins/autotoolsprojectmanager/makestep.cpp b/src/plugins/autotoolsprojectmanager/makestep.cpp index 57c3ef834a..e44eee9fe1 100644 --- a/src/plugins/autotoolsprojectmanager/makestep.cpp +++ b/src/plugins/autotoolsprojectmanager/makestep.cpp @@ -87,7 +87,7 @@ bool MakeStepFactory::canCreate(BuildStepList *parent, const QString &id) const if (parent->target()->project()->id() != QLatin1String(AUTOTOOLS_PROJECT_ID)) return false; - if (parent->id() != BUILDSTEPS_BUILD) + if (parent->id() != QLatin1String(BUILDSTEPS_BUILD)) return false; return QLatin1String(MAKE_STEP_ID) == id; diff --git a/src/plugins/bazaar/annotationhighlighter.cpp b/src/plugins/bazaar/annotationhighlighter.cpp index 6ea7fd7108..ed1d7b0980 100644 --- a/src/plugins/bazaar/annotationhighlighter.cpp +++ b/src/plugins/bazaar/annotationhighlighter.cpp @@ -40,7 +40,7 @@ BazaarAnnotationHighlighter::BazaarAnnotationHighlighter(const ChangeNumbers &ch const QColor &bg, QTextDocument *document) : VcsBase::BaseAnnotationHighlighter(changeNumbers, bg, document), - m_changeset(QLatin1String(Constants::CHANGESET_ID)) + m_changeset(QLatin1String(Constants::ANNOTATE_CHANGESET_ID)) { } diff --git a/src/plugins/bazaar/bazaarclient.cpp b/src/plugins/bazaar/bazaarclient.cpp index d148d07623..9257fa9fa9 100644 --- a/src/plugins/bazaar/bazaarclient.cpp +++ b/src/plugins/bazaar/bazaarclient.cpp @@ -140,6 +140,16 @@ QString BazaarClient::vcsEditorKind(VcsCommand cmd) const } } +QString BazaarClient::vcsCommandString(VcsCommand cmd) const +{ + switch (cmd) { + case CloneCommand: + return QLatin1String("branch"); + default: + return VcsBaseClient::vcsCommandString(cmd); + } +} + QStringList BazaarClient::revisionSpec(const QString &revision) const { QStringList args; diff --git a/src/plugins/bazaar/bazaarclient.h b/src/plugins/bazaar/bazaarclient.h index cdd4137871..2653a9dc36 100644 --- a/src/plugins/bazaar/bazaarclient.h +++ b/src/plugins/bazaar/bazaarclient.h @@ -64,6 +64,7 @@ public: protected: QString vcsEditorKind(VcsCommand cmd) const; + QString vcsCommandString(VcsCommand cmd) const; QStringList revisionSpec(const QString &revision) const; VcsBase::VcsBaseEditorParameterWidget *createDiffEditor(const QString &workingDir, const QStringList &files, diff --git a/src/plugins/bazaar/bazaareditor.cpp b/src/plugins/bazaar/bazaareditor.cpp index b122152244..2a52248c82 100644 --- a/src/plugins/bazaar/bazaareditor.cpp +++ b/src/plugins/bazaar/bazaareditor.cpp @@ -55,6 +55,7 @@ using namespace Bazaar; BazaarEditor::BazaarEditor(const VcsBase::VcsBaseEditorParameters *type, QWidget *parent) : VcsBase::VcsBaseEditorWidget(type, parent), + m_changesetId(QLatin1String(Constants::CHANGESET_ID)), m_exactChangesetId(QLatin1String(Constants::CHANGESET_ID_EXACT)), m_diffFileId(QLatin1String("^=== [a-z]+ [a-z]+ '(.*)'\\s*")) { @@ -86,12 +87,30 @@ QSet<QString> BazaarEditor::annotationChanges() const QString BazaarEditor::changeUnderCursor(const QTextCursor &cursorIn) const { + // The test is done in two steps: first we check if the line contains a + // changesetId. Then we check if the cursor is over the changesetId itself + // and not over "revno" or another part of the line. + // The two steps are necessary because matching only for the changesetId + // leads to many false-positives (a regex like "[0-9]+" matches a lot of text). + const int cursorCol = cursorIn.columnNumber(); QTextCursor cursor = cursorIn; - cursor.select(QTextCursor::WordUnderCursor); + cursor.select(QTextCursor::LineUnderCursor); if (cursor.hasSelection()) { - const QString change = cursor.selectedText(); - if (m_exactChangesetId.exactMatch(change)) - return change; + const QString line = cursor.selectedText(); + const int start = m_changesetId.indexIn(line); + if (start > -1) { + const QString match = m_changesetId.cap(0); + const int stop = start + match.length(); + if (start <= cursorCol && cursorCol <= stop) { + cursor = cursorIn; + cursor.select(QTextCursor::WordUnderCursor); + if (cursor.hasSelection()) { + const QString change = cursor.selectedText(); + if (m_exactChangesetId.exactMatch(change)) + return change; + } + } + } } return QString(); } diff --git a/src/plugins/bazaar/bazaareditor.h b/src/plugins/bazaar/bazaareditor.h index 0c9198509f..4538c70043 100644 --- a/src/plugins/bazaar/bazaareditor.h +++ b/src/plugins/bazaar/bazaareditor.h @@ -54,6 +54,7 @@ private: virtual VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const; virtual QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const; + const QRegExp m_changesetId; const QRegExp m_exactChangesetId; const QRegExp m_diffFileId; }; diff --git a/src/plugins/bazaar/bazaarplugin.h b/src/plugins/bazaar/bazaarplugin.h index dff7611977..f64372c814 100644 --- a/src/plugins/bazaar/bazaarplugin.h +++ b/src/plugins/bazaar/bazaarplugin.h @@ -81,6 +81,7 @@ class BazaarEditor; class BazaarPlugin : public VcsBase::VcsBasePlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Bazaar.json") public: BazaarPlugin(); diff --git a/src/plugins/bazaar/constants.h b/src/plugins/bazaar/constants.h index ccccc2e1fe..12560b1777 100644 --- a/src/plugins/bazaar/constants.h +++ b/src/plugins/bazaar/constants.h @@ -41,8 +41,13 @@ const char BAZAARREPO[] = ".bzr"; const char BAZAARDEFAULT[] = "bzr"; // Changeset identifiers -const char CHANGESET_ID[] = "([0-9]+)"; // match and capture -const char CHANGESET_ID_EXACT[] = "[0-9]+"; // match +const char CHANGESET_ID[] = "^(" + "revno: [.0-9]+" // detailed + "| +[.0-9]+" // short + "|[.0-9]+: " // line + ")"; +const char CHANGESET_ID_EXACT[] = "([.0-9]+)"; +const char ANNOTATE_CHANGESET_ID[] = "([.0-9]+)"; // Base editor parameters const char COMMANDLOG_ID[] = "Bazaar Command Log Editor"; diff --git a/src/plugins/bineditor/bineditorplugin.h b/src/plugins/bineditor/bineditorplugin.h index 2db7c38001..b4fd405089 100644 --- a/src/plugins/bineditor/bineditorplugin.h +++ b/src/plugins/bineditor/bineditorplugin.h @@ -60,6 +60,7 @@ class BinEditorFactory; class BinEditorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "BinEditor.json") public: BinEditorPlugin(); diff --git a/src/plugins/bookmarks/bookmarksplugin.h b/src/plugins/bookmarks/bookmarksplugin.h index 2607ebcb21..7f03ce93b8 100644 --- a/src/plugins/bookmarks/bookmarksplugin.h +++ b/src/plugins/bookmarks/bookmarksplugin.h @@ -59,6 +59,7 @@ class BookmarkManager; class BookmarksPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Bookmarks.json") public: BookmarksPlugin(); diff --git a/src/plugins/classview/classview_dependencies.pri b/src/plugins/classview/classview_dependencies.pri index 19ddab5e9a..b130241048 100644 --- a/src/plugins/classview/classview_dependencies.pri +++ b/src/plugins/classview/classview_dependencies.pri @@ -2,5 +2,4 @@ include(../../libs/utils/utils.pri) include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/cpptools/cpptools.pri) include(../../plugins/projectexplorer/projectexplorer.pri) -include(../../libs/cplusplus/cplusplus.pri) include(../../plugins/texteditor/texteditor.pri) diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp index e3e78ccbff..d2bedb4f42 100644 --- a/src/plugins/classview/classviewmanager.cpp +++ b/src/plugins/classview/classviewmanager.cpp @@ -40,7 +40,7 @@ #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> #include <texteditor/basetexteditor.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cpptools/cpptoolsconstants.h> #include <coreplugin/icore.h> #include <coreplugin/progressmanager/progressmanager.h> diff --git a/src/plugins/classview/classviewparser.cpp b/src/plugins/classview/classviewparser.cpp index 0056918976..2eff6ab8e3 100644 --- a/src/plugins/classview/classviewparser.cpp +++ b/src/plugins/classview/classviewparser.cpp @@ -41,7 +41,7 @@ #include <Name.h> // other -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/Overview.h> #include <cplusplus/Icons.h> #include <projectexplorer/projectexplorer.h> diff --git a/src/plugins/classview/classviewparser.h b/src/plugins/classview/classviewparser.h index 0706991860..a74d7e4360 100644 --- a/src/plugins/classview/classviewparser.h +++ b/src/plugins/classview/classviewparser.h @@ -38,7 +38,7 @@ #include "classviewparsertreeitem.h" #include <CPlusPlusForwardDeclarations.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/CppDocument.h> // might be changed to forward declaration - is not done to be less dependent diff --git a/src/plugins/classview/classviewplugin.h b/src/plugins/classview/classviewplugin.h index 912856b064..3a0f8d455a 100644 --- a/src/plugins/classview/classviewplugin.h +++ b/src/plugins/classview/classviewplugin.h @@ -46,6 +46,7 @@ namespace Internal { class Plugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClassView.json") public: //! Constructor diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index a0586f9168..0f970bfef6 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp @@ -37,7 +37,10 @@ #include "cmakeprojectconstants.h" #include "cmakeproject.h" +#include <coreplugin/icore.h> #include <coreplugin/infobar.h> +#include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/actionmanager/actionmanager.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> #include <texteditor/fontsettings.h> @@ -72,6 +75,11 @@ Core::IEditor *CMakeEditor::duplicate(QWidget *parent) return ret->editor(); } +Core::Context CMakeEditor::context() const +{ + return Core::Context(Constants::C_CMAKEEDITOR); +} + Core::Id CMakeEditor::id() const { return CMakeProjectManager::Constants::CMAKE_EDITOR_ID; @@ -116,9 +124,12 @@ CMakeEditorWidget::CMakeEditorWidget(QWidget *parent, CMakeEditorFactory *factor doc->setMimeType(QLatin1String(CMakeProjectManager::Constants::CMAKEMIMETYPE)); setBaseTextDocument(doc); - ah->setupActions(this); - baseTextDocument()->setSyntaxHighlighter(new CMakeHighlighter); + + m_commentDefinition.clearCommentStyles(); + m_commentDefinition.setSingleLine(QLatin1String("#")); + + ah->setupActions(this); } TextEditor::BaseTextEditor *CMakeEditorWidget::createEditor() @@ -126,6 +137,28 @@ TextEditor::BaseTextEditor *CMakeEditorWidget::createEditor() return new CMakeEditor(this); } +void CMakeEditorWidget::unCommentSelection() +{ + Utils::unCommentSelection(this, m_commentDefinition); +} + +void CMakeEditorWidget::contextMenuEvent(QContextMenuEvent *e) +{ + QMenu *menu = new QMenu(); + + Core::ActionManager *am = Core::ICore::instance()->actionManager(); + Core::ActionContainer *mcontext = am->actionContainer(Constants::M_CONTEXT); + QMenu *contextMenu = mcontext->menu(); + + foreach (QAction *action, contextMenu->actions()) + menu->addAction(action); + + appendStandardContextMenuActions(menu); + + menu->exec(e->globalPos()); + delete menu; +} + void CMakeEditorWidget::setFontSettings(const TextEditor::FontSettings &fs) { TextEditor::BaseTextEditorWidget::setFontSettings(fs); @@ -147,8 +180,85 @@ void CMakeEditorWidget::setFontSettings(const TextEditor::FontSettings &fs) highlighter->rehighlight(); } +static bool isValidFileNameChar(const QChar &c) +{ + if (c.isLetterOrNumber() + || c == QLatin1Char('.') + || c == QLatin1Char('_') + || c == QLatin1Char('-') + || c == QLatin1Char('/') + || c == QLatin1Char('\\')) + return true; + return false; +} + +CMakeEditorWidget::Link CMakeEditorWidget::findLinkAt(const QTextCursor &cursor, + bool/* resolveTarget*/) +{ + Link link; + + int lineNumber = 0, positionInBlock = 0; + convertPosition(cursor.position(), &lineNumber, &positionInBlock); + + const QString block = cursor.block().text(); + + // check if the current position is commented out + const int hashPos = block.indexOf(QLatin1Char('#')); + if (hashPos >= 0 && hashPos < positionInBlock) + return link; + + // find the beginning of a filename + QString buffer; + int beginPos = positionInBlock - 1; + while (beginPos >= 0) { + QChar c = block.at(beginPos); + if (isValidFileNameChar(c)) { + buffer.prepend(c); + beginPos--; + } else { + break; + } + } + + // find the end of a filename + int endPos = positionInBlock; + while (endPos < block.count()) { + QChar c = block.at(endPos); + if (isValidFileNameChar(c)) { + buffer.append(c); + endPos++; + } else { + break; + } + } + + if (buffer.isEmpty()) + return link; + + // TODO: Resolve variables + + QDir dir(QFileInfo(editorDocument()->fileName()).absolutePath()); + QString fileName = dir.filePath(buffer); + QFileInfo fi(fileName); + if (fi.exists()) { + if (fi.isDir()) { + QDir subDir(fi.absoluteFilePath()); + QString subProject = subDir.filePath("CMakeLists.txt"); + if (QFileInfo(subProject).exists()) + fileName = subProject; + else + return link; + } + link.fileName = fileName; + link.begin = cursor.position() - positionInBlock + beginPos + 1; + link.end = cursor.position() - positionInBlock + endPos; + } + return link; +} + + // -// ProFileDocument +// CMakeDocument // CMakeDocument::CMakeDocument() diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.h b/src/plugins/cmakeprojectmanager/cmakeeditor.h index 4a89cced20..97fe2529f9 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.h +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.h @@ -37,6 +37,7 @@ #include <texteditor/basetextdocument.h> #include <texteditor/basetexteditor.h> +#include <utils/uncommentselection.h> namespace TextEditor { @@ -59,6 +60,7 @@ public: bool duplicateSupported() const { return true; } Core::IEditor *duplicate(QWidget *parent); + Core::Context context() const; Core::Id id() const; bool isTemporary() const { return false; } @@ -81,15 +83,21 @@ public: CMakeEditorFactory *factory() { return m_factory; } TextEditor::TextEditorActionHandler *actionHandler() const { return m_ah; } + Link findLinkAt(const QTextCursor &cursor, + bool resolveTarget = true); + protected: TextEditor::BaseTextEditor *createEditor(); + void contextMenuEvent(QContextMenuEvent *e); public slots: - virtual void setFontSettings(const TextEditor::FontSettings &); + void unCommentSelection(); + void setFontSettings(const TextEditor::FontSettings &); private: CMakeEditorFactory *m_factory; TextEditor::TextEditorActionHandler *m_ah; + Utils::CommentDefinition m_commentDefinition; }; class CMakeDocument : public TextEditor::BaseTextDocument diff --git a/src/plugins/cmakeprojectmanager/cmakeeditorfactory.cpp b/src/plugins/cmakeprojectmanager/cmakeeditorfactory.cpp index c5b8ee9053..f054f6f066 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditorfactory.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditorfactory.cpp @@ -34,18 +34,45 @@ #include "cmakeprojectconstants.h" #include "cmakeeditor.h" +#include <coreplugin/icore.h> +#include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/editormanager/editormanager.h> +#include <texteditor/texteditoractionhandler.h> +#include <texteditor/texteditorconstants.h> #include <texteditor/texteditorsettings.h> using namespace CMakeProjectManager; using namespace CMakeProjectManager::Internal; -CMakeEditorFactory::CMakeEditorFactory(CMakeManager *manager, TextEditor::TextEditorActionHandler *handler) +CMakeEditorFactory::CMakeEditorFactory(CMakeManager *manager) : m_mimeTypes(QStringList() << QLatin1String(CMakeProjectManager::Constants::CMAKEMIMETYPE)), - m_manager(manager), - m_actionHandler(handler) + m_manager(manager) { + using namespace Core; + using namespace TextEditor; + m_actionHandler = + new TextEditorActionHandler(Constants::C_CMAKEEDITOR, + TextEditorActionHandler::UnCommentSelection + | TextEditorActionHandler::JumpToFileUnderCursor); + + ICore *core = ICore::instance(); + ActionManager *am = core->actionManager(); + ActionContainer *contextMenu = am->createMenu(Constants::M_CONTEXT); + Command *cmd; + Context cmakeEditorContext = Context(Constants::C_CMAKEEDITOR); + + cmd = am->command(TextEditor::Constants::JUMP_TO_FILE_UNDER_CURSOR); + contextMenu->addAction(cmd); + + QAction *separator = new QAction(this); + separator->setSeparator(true); + contextMenu->addAction(am->registerAction(separator, + Id(Constants::SEPARATOR), cmakeEditorContext)); + + cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION); + contextMenu->addAction(cmd); } Core::Id CMakeEditorFactory::id() const diff --git a/src/plugins/cmakeprojectmanager/cmakeeditorfactory.h b/src/plugins/cmakeprojectmanager/cmakeeditorfactory.h index e23a654808..a58a4115d1 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditorfactory.h +++ b/src/plugins/cmakeprojectmanager/cmakeeditorfactory.h @@ -51,7 +51,7 @@ class CMakeEditorFactory : public Core::IEditorFactory Q_OBJECT public: - CMakeEditorFactory(CMakeManager *parent, TextEditor::TextEditorActionHandler *handler); + CMakeEditorFactory(CMakeManager *parent); // IEditorFactory QStringList mimeTypes() const; diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index ba79dff82c..4c6ffd8d86 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -47,7 +47,7 @@ #include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildmanager.h> #include <projectexplorer/toolchain.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> #include <coreplugin/icore.h> @@ -62,6 +62,7 @@ #include <QFormLayout> #include <QMainWindow> #include <QInputDialog> +#include <QFileSystemWatcher> using namespace CMakeProjectManager; using namespace CMakeProjectManager::Internal; @@ -496,11 +497,6 @@ CMakeTarget *CMakeProject::activeTarget() const return static_cast<CMakeTarget *>(Project::activeTarget()); } -QList<ProjectExplorer::Project *> CMakeProject::dependsOn() -{ - return QList<Project *>(); -} - QList<ProjectExplorer::BuildConfigWidget*> CMakeProject::subConfigWidgets() { QList<ProjectExplorer::BuildConfigWidget*> list; diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index f5bb915b80..778bc7fc9e 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -48,10 +48,13 @@ #include <coreplugin/editormanager/ieditor.h> #include <QXmlStreamReader> -#include <QFileSystemWatcher> #include <QPushButton> #include <QLineEdit> +QT_BEGIN_NAMESPACE +class QFileSystemWatcher; +QT_END_NAMESPACE + namespace CMakeProjectManager { namespace Internal { @@ -86,8 +89,6 @@ public: CMakeTarget *activeTarget() const; - QList<ProjectExplorer::Project *> dependsOn(); //NBS TODO implement dependsOn - QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets(); ProjectExplorer::ProjectNode *rootProjectNode() const; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h index 4c16602e1c..1b92962767 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h @@ -47,6 +47,12 @@ const char RUNCMAKECONTEXTMENU[] = "CMakeProject.RunCMakeContextMenu"; // Project const char CMAKEPROJECT_ID[] = "CMakeProjectManager.CMakeProject"; +// Menu +const char M_CONTEXT[] = "CMakeEditor.ContextMenu"; + +// Actions +const char SEPARATOR[] = "CMakeEditor.Separator"; + } // namespace Constants } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp index 9f0749e90e..46b1db69d9 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp @@ -67,10 +67,8 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString * addAutoReleasedObject(manager); addAutoReleasedObject(new MakeStepFactory); addAutoReleasedObject(new CMakeRunConfigurationFactory); - TextEditor::TextEditorActionHandler *editorHandler - = new TextEditor::TextEditorActionHandler(CMakeProjectManager::Constants::C_CMAKEEDITOR); - addAutoReleasedObject(new CMakeEditorFactory(manager, editorHandler)); + addAutoReleasedObject(new CMakeEditorFactory(manager)); addAutoReleasedObject(new CMakeTargetFactory); addAutoReleasedObject(new CMakeLocatorFilter); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h index 913f1b2ced..f876807d59 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h @@ -44,6 +44,7 @@ class CMakeProjectPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "CMakeProjectManager.json") public: CMakeProjectPlugin(); diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index 1f7ead2a78..4e04743482 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -316,7 +316,7 @@ void CMakeRunConfiguration::setEnabled(bool b) if (m_enabled == b) return; m_enabled = b; - emit isEnabledChanged(isEnabled()); + emit enabledChanged(); setDefaultDisplayName(defaultDisplayName()); } diff --git a/src/plugins/cmakeprojectmanager/cmaketarget.cpp b/src/plugins/cmakeprojectmanager/cmaketarget.cpp index 31d47abbf2..4b92f2360f 100644 --- a/src/plugins/cmakeprojectmanager/cmaketarget.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketarget.cpp @@ -32,7 +32,6 @@ #include "cmaketarget.h" -#include "cmakeopenprojectwizard.h" #include "cmakeproject.h" #include "cmakerunconfiguration.h" #include "cmakebuildconfiguration.h" diff --git a/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp index fb1a727936..1a4e427cf9 100644 --- a/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.cpp @@ -35,7 +35,7 @@ #include "cmaketarget.h" #include "cmakebuildconfiguration.h" -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <QProcess> diff --git a/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h index 2fe7cc0ffc..b04b9a5f8b 100644 --- a/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h +++ b/src/plugins/cmakeprojectmanager/cmakeuicodemodelsupport.h @@ -33,7 +33,7 @@ #ifndef CMAKEUICODEMODELSUPPORT_H #define CMAKEUICODEMODELSUPPORT_H -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cpptools/uicodecompletionsupport.h> #include <QDateTime> diff --git a/src/plugins/coreplugin/basefilewizard.cpp b/src/plugins/coreplugin/basefilewizard.cpp index 2e19226150..7d7a156489 100644 --- a/src/plugins/coreplugin/basefilewizard.cpp +++ b/src/plugins/coreplugin/basefilewizard.cpp @@ -464,10 +464,17 @@ void BaseFileWizard::runWizard(const QString &path, QWidget *parent, const QStri // Create dialog and run it. Ensure that the dialog is deleted when // leaving the func, but not before the IFileWizardExtension::process // has been called + + WizardDialogParameters::DialogParameterFlags dialogParameterFlags; + + if (flags().testFlag(ForceCapitalLetterForFileName)) + dialogParameterFlags |= WizardDialogParameters::ForceCapitalLetterForFileName; + const QScopedPointer<QWizard> wizard(createWizardDialog(parent, WizardDialogParameters(path, allExtensionPages, platform, - requiredFeatures()))); + requiredFeatures(), + dialogParameterFlags))); QTC_ASSERT(!wizard.isNull(), return); GeneratedFiles files; @@ -811,6 +818,8 @@ QWizard *StandardFileWizard::createWizardDialog(QWidget *parent, const WizardDialogParameters &wizardDialogParameters) const { Utils::FileWizardDialog *standardWizardDialog = new Utils::FileWizardDialog(parent); + if (wizardDialogParameters.flags().testFlag(WizardDialogParameters::ForceCapitalLetterForFileName)) + standardWizardDialog->setForceFirstCapitalLetterForFileName(true); standardWizardDialog->setWindowTitle(tr("New %1").arg(displayName())); setupWizard(standardWizardDialog); standardWizardDialog->setPath(wizardDialogParameters.defaultPath()); diff --git a/src/plugins/coreplugin/basefilewizard.h b/src/plugins/coreplugin/basefilewizard.h index 6f4fc76baa..4f424058a6 100644 --- a/src/plugins/coreplugin/basefilewizard.h +++ b/src/plugins/coreplugin/basefilewizard.h @@ -113,12 +113,19 @@ class CORE_EXPORT WizardDialogParameters public: typedef QList<QWizardPage *> WizardPageList; + enum DialogParameterEnum { + ForceCapitalLetterForFileName = 0x01 + }; + Q_DECLARE_FLAGS(DialogParameterFlags, DialogParameterEnum) + explicit WizardDialogParameters(const QString &defaultPath, const WizardPageList &extensionPages, - const QString &platform, const Core::FeatureSet &requiredFeatures) + const QString &platform, const Core::FeatureSet &requiredFeatures, + DialogParameterFlags flags) : m_defaultPath(defaultPath), m_extensionPages(extensionPages), m_selectedPlatform(platform), - m_requiredFeatures(requiredFeatures) {} + m_requiredFeatures(requiredFeatures), + m_parameterFlags(flags) {} QString defaultPath() const { return m_defaultPath; } @@ -132,11 +139,15 @@ public: Core::FeatureSet requiredFeatures() const { return m_requiredFeatures; } + DialogParameterFlags flags() const + { return m_parameterFlags; } + private: QString m_defaultPath; WizardPageList m_extensionPages; QString m_selectedPlatform; Core::FeatureSet m_requiredFeatures; + DialogParameterFlags m_parameterFlags; }; class CORE_EXPORT BaseFileWizard : public IWizard @@ -221,5 +232,6 @@ QList<WizardClass*> createMultipleBaseFileWizardInstances(const QList<BaseFileWi } // namespace Core Q_DECLARE_OPERATORS_FOR_FLAGS(Core::GeneratedFile::Attributes) +Q_DECLARE_OPERATORS_FOR_FLAGS(Core::WizardDialogParameters::DialogParameterFlags) #endif // BASEFILEWIZARD_H diff --git a/src/plugins/coreplugin/coreplugin.h b/src/plugins/coreplugin/coreplugin.h index 947abf800f..e8a444b3e5 100644 --- a/src/plugins/coreplugin/coreplugin.h +++ b/src/plugins/coreplugin/coreplugin.h @@ -45,6 +45,7 @@ class MainWindow; class CorePlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Core.json") public: CorePlugin(); diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index d7eb7b20b0..c32ec82c72 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -75,7 +75,6 @@ SOURCES += mainwindow.cpp \ dialogs/ioptionspage.cpp \ dialogs/iwizard.cpp \ settingsdatabase.cpp \ - eventfilteringmainwindow.cpp \ imode.cpp \ editormanager/systemeditor.cpp \ designmode.cpp \ @@ -170,7 +169,6 @@ HEADERS += mainwindow.h \ fileiconprovider.h \ mimedatabase.h \ settingsdatabase.h \ - eventfilteringmainwindow.h \ editormanager/systemeditor.h \ designmode.h \ editortoolbar.h \ @@ -213,7 +211,10 @@ win32 { LIBS += -lole32 } else:macx { - OBJECTIVE_SOURCES += progressmanager/progressmanager_mac.mm + HEADERS += macfullscreen.h + OBJECTIVE_SOURCES += \ + progressmanager/progressmanager_mac.mm \ + macfullscreen.mm LIBS += -framework AppKit } else:unix { @@ -228,4 +229,3 @@ else:unix { } } OTHER_FILES += editormanager/BinFiles.mimetypes.xml - diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index 53dde48347..6fa9516b78 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -45,8 +45,6 @@ QtcPlugin { "editmode.h", "editortoolbar.cpp", "editortoolbar.h", - "eventfilteringmainwindow.cpp", - "eventfilteringmainwindow.h", "externaltool.cpp", "externaltool.h", "externaltoolmanager.h", diff --git a/src/plugins/coreplugin/dialogs/iwizard.h b/src/plugins/coreplugin/dialogs/iwizard.h index 8347cd0252..fe7b2ee0ca 100644 --- a/src/plugins/coreplugin/dialogs/iwizard.h +++ b/src/plugins/coreplugin/dialogs/iwizard.h @@ -57,7 +57,8 @@ public: }; Q_DECLARE_FLAGS(WizardKinds, WizardKind) enum WizardFlag { - PlatformIndependent = 0x01 + PlatformIndependent = 0x01, + ForceCapitalLetterForFileName = 0x02 }; Q_DECLARE_FLAGS(WizardFlags, WizardFlag) diff --git a/src/plugins/coreplugin/eventfilteringmainwindow.cpp b/src/plugins/coreplugin/eventfilteringmainwindow.cpp deleted file mode 100644 index b4a786b0ec..0000000000 --- a/src/plugins/coreplugin/eventfilteringmainwindow.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "eventfilteringmainwindow.h" - -#ifdef Q_OS_WIN -#include <windows.h> -#endif - -#include <QtDebug> -#include <QEvent> -#include <QCoreApplication> - -namespace Core { -namespace Internal { - -/* The notification signal is delayed by using a custom event - * as otherwise device removal is not detected properly - * (devices are still present in the registry. */ - -class DeviceNotifyEvent : public QEvent { -public: - explicit DeviceNotifyEvent(int id) : QEvent(static_cast<QEvent::Type>(id)) {} -}; - -EventFilteringMainWindow::EventFilteringMainWindow() : - m_deviceEventId(QEvent::registerEventType(QEvent::User + 2)) -{ -} - -#ifdef Q_OS_WIN -bool EventFilteringMainWindow::event(QEvent *event) -{ - if (event->type() == m_deviceEventId) { - event->accept(); - emit deviceChange(); - return true; - } - return QMainWindow::event(event); -} - -bool EventFilteringMainWindow::winEvent(MSG *msg, long *result) -{ - if (msg->message == WM_DEVICECHANGE) { - if (msg->wParam & 0x7 /* DBT_DEVNODES_CHANGED */) { - *result = TRUE; - QCoreApplication::postEvent(this, new DeviceNotifyEvent(m_deviceEventId)); - } - } - return false; -} -#endif - -} // namespace Internal -} // namespace Core - diff --git a/src/plugins/coreplugin/fileiconprovider.cpp b/src/plugins/coreplugin/fileiconprovider.cpp index 458d7cfcca..4cb33223ee 100644 --- a/src/plugins/coreplugin/fileiconprovider.cpp +++ b/src/plugins/coreplugin/fileiconprovider.cpp @@ -58,8 +58,8 @@ own overlay icon handling (Mac/Windows). The class is a singleton: It's instance can be accessed via the static instance() method. - Plugins can register custom icons via registerIconSuffix(), and retrieve icons via the icon() - method. + Plugins can register custom overlay icons via registerIconOverlayForSuffix(), and + retrieve icons via the icon() method. The instance is explicitly deleted by the core plugin for destruction order reasons. */ diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index 87d2db42cf..c75caa48e9 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -220,19 +220,19 @@ void GeneralSettings::resetInterfaceColor() m_page->colorButton->setColor(StyleHelper::DEFAULT_BASE_COLOR); } -#ifdef Q_OS_UNIX void GeneralSettings::resetTerminal() { +#if defined(Q_OS_UNIX) m_page->terminalEdit->setText(ConsoleProcess::defaultTerminalEmulator() + QLatin1String(" -e")); +#endif } -#ifndef Q_OS_MAC void GeneralSettings::resetFileBrowser() { +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) m_page->externalFileBrowserEdit->setText(UnixUtils::defaultFileBrowser()); -} -#endif #endif +} void GeneralSettings::variableHelpDialogCreator(const QString &helpText) @@ -257,12 +257,12 @@ void GeneralSettings::variableHelpDialogCreator(const QString &helpText) } -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) void GeneralSettings::showHelpForFileBrowser() { +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) variableHelpDialogCreator(UnixUtils::fileBrowserHelpText()); -} #endif +} void GeneralSettings::resetLanguage() { diff --git a/src/plugins/coreplugin/generalsettings.h b/src/plugins/coreplugin/generalsettings.h index 66ccbeb814..e5b5220d74 100644 --- a/src/plugins/coreplugin/generalsettings.h +++ b/src/plugins/coreplugin/generalsettings.h @@ -67,13 +67,9 @@ public: private slots: void resetInterfaceColor(); void resetLanguage(); -#ifdef Q_OS_UNIX -# ifndef Q_OS_MAC void showHelpForFileBrowser(); void resetFileBrowser(); -# endif void resetTerminal(); -#endif private: void variableHelpDialogCreator(const QString &helpText); diff --git a/src/plugins/coreplugin/eventfilteringmainwindow.h b/src/plugins/coreplugin/macfullscreen.h index ae534ecd90..3a8a99aeff 100644 --- a/src/plugins/coreplugin/eventfilteringmainwindow.h +++ b/src/plugins/coreplugin/macfullscreen.h @@ -30,43 +30,22 @@ ** **************************************************************************/ -#ifndef EVENTFILTERINGMAINWINDOW_H -#define EVENTFILTERINGMAINWINDOW_H +#ifndef MACFULLSCREEN_H +#define MACFULLSCREEN_H -#include <QMainWindow> - -QT_BEGIN_NAMESPACE - -QT_END_NAMESPACE +#include "mainwindow.h" namespace Core { namespace Internal { +namespace MacFullScreen { -/*! - * This class only exists because we can't include windows.h in mainwindow.cpp - * because windows defines an IContext... - */ - -class EventFilteringMainWindow : public QMainWindow -{ - Q_OBJECT -public: - EventFilteringMainWindow(); - -signals: - void deviceChange(); - -#ifdef Q_OS_WIN -protected: - virtual bool winEvent(MSG *message, long *result); - virtual bool event(QEvent *event); -#endif - -private: - const int m_deviceEventId; -}; +bool supportsFullScreen(); +// adds fullscreen button to window for lion +void addFullScreen(Core::Internal::MainWindow *window); +void toggleFullScreen(Core::Internal::MainWindow *window); +} // MacFullScreen } // Internal } // Core -#endif // EVENTFILTERINGMAINWINDOW_H +#endif // MACFULLSCREEN_H diff --git a/src/plugins/coreplugin/macfullscreen.mm b/src/plugins/coreplugin/macfullscreen.mm new file mode 100644 index 0000000000..3392328e87 --- /dev/null +++ b/src/plugins/coreplugin/macfullscreen.mm @@ -0,0 +1,123 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "macfullscreen.h" + +#include <AppKit/NSView.h> +#include <AppKit/NSWindow.h> +#include <Foundation/NSNotification.h> + +#include <QSysInfo> +#include <qglobal.h> + +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6 +enum { + NSWindowCollectionBehaviorFullScreenPrimary = (1 << 7) +}; + +static const NSString *NSWindowDidEnterFullScreenNotification = @"NSWindowDidEnterFullScreenNotification"; +static const NSString *NSWindowDidExitFullScreenNotification = @"NSWindowDidExitFullScreenNotification"; +#endif + +@interface WindowObserver : NSObject { + Core::Internal::MainWindow *window; +} + +- (id)initWithMainWindow:(Core::Internal::MainWindow *)w; + +- (void)notifyDidEnterFullScreen:(NSNotification *)notification; +- (void)notifyDidExitFullScreen:(NSNotification *)notification; + +@end + +@implementation WindowObserver + +- (id)initWithMainWindow:(Core::Internal::MainWindow *)w; +{ + if ((self = [self init])) { + window = w; + } + return self; +} + +- (void)notifyDidEnterFullScreen:(NSNotification *)notification +{ + Q_UNUSED(notification) + window->setIsFullScreen(true); +} + +- (void)notifyDidExitFullScreen:(NSNotification* )notification +{ + Q_UNUSED(notification) + window->setIsFullScreen(false); +} + +@end + +static WindowObserver *observer = nil; + +using namespace Core::Internal; + +bool MacFullScreen::supportsFullScreen() +{ +#if QT_VERSION >= 0x040800 + return QSysInfo::MacintoshVersion >= QSysInfo::MV_LION; +#else + return QSysInfo::MacintoshVersion >= 0x0009; /* MV_LION not defined */ +#endif +} + +void MacFullScreen::addFullScreen(MainWindow *window) +{ + if (supportsFullScreen()) { + NSView *nsview = (NSView *) window->winId(); + NSWindow *nswindow = [nsview window]; + [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; + + if (observer == nil) + observer = [[WindowObserver alloc] initWithMainWindow:window]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:observer selector:@selector(notifyDidEnterFullScreen:) + name:NSWindowDidEnterFullScreenNotification object:nswindow]; + [nc addObserver:observer selector:@selector(notifyDidExitFullScreen:) + name:NSWindowDidExitFullScreenNotification object:nswindow]; + } +} + +void MacFullScreen::toggleFullScreen(MainWindow *window) +{ + if (supportsFullScreen()) { + NSView *nsview = (NSView *) window->winId(); + NSWindow *nswindow = [nsview window]; + [nswindow performSelector:@selector(toggleFullScreen:) withObject: nil]; + } +} diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 4397688d7b..c4123834e7 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -58,7 +58,6 @@ #include "shortcutsettings.h" #include "vcsmanager.h" #include "variablechooser.h" - #include "scriptmanager_p.h" #include "settingsdialog.h" #include "variablemanager.h" @@ -75,6 +74,10 @@ #include "externaltoolmanager.h" #include "editormanager/systemeditor.h" +#if defined(Q_OS_MAC) +#include "macfullscreen.h" +#endif + #include <app/app_version.h> #include <coreplugin/findplaceholder.h> #include <coreplugin/icorelistener.h> @@ -126,7 +129,7 @@ using namespace Core::Internal; enum { debugMainWindow = 0 }; MainWindow::MainWindow() : - EventFilteringMainWindow(), + Utils::AppMainWindow(), m_coreImpl(new ICore(this)), m_additionalContexts(Constants::C_GLOBAL), m_settings(ExtensionSystem::PluginManager::instance()->settings()), @@ -227,6 +230,10 @@ MainWindow::MainWindow() : statusBar()->setProperty("p_styled", true); setAcceptDrops(true); + +#if defined(Q_OS_MAC) + MacFullScreen::addFullScreen(this); +#endif } void MainWindow::setSidebarVisible(bool visible) @@ -262,6 +269,16 @@ void MainWindow::setPresentationModeEnabled(bool enabled) m_actionManager->setPresentationModeEnabled(enabled); } +#ifdef Q_OS_MAC +void MainWindow::setIsFullScreen(bool fullScreen) +{ + if (fullScreen) + m_toggleFullScreenAction->setText(tr("Exit Full Screen")); + else + m_toggleFullScreenAction->setText(tr("Enter Full Screen")); +} +#endif + MainWindow::~MainWindow() { ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); @@ -772,14 +789,26 @@ void MainWindow::registerDefaultActions() mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS); m_toggleSideBarAction->setEnabled(false); -#ifndef Q_OS_MAC +#if defined(Q_OS_MAC) + bool fullScreenCheckable = false; + QKeySequence fullScreenKeySequence(tr("Ctrl+Meta+F")); + const QString fullScreenActionText(tr("Enter Full Screen")); + if (MacFullScreen::supportsFullScreen()) { +#else + bool fullScreenCheckable = true; + QKeySequence fullScreenKeySequence(tr("Ctrl+Shift+F11")); + const QString fullScreenActionText(tr("Full Screen")); +#endif // Full Screen Action - m_toggleFullScreenAction = new QAction(tr("Full Screen"), this); - m_toggleFullScreenAction->setCheckable(true); + m_toggleFullScreenAction = new QAction(fullScreenActionText, this); + m_toggleFullScreenAction->setCheckable(fullScreenCheckable); cmd = am->registerAction(m_toggleFullScreenAction, Constants::TOGGLE_FULLSCREEN, globalContext); - cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11"))); + cmd->setDefaultKeySequence(fullScreenKeySequence); + cmd->setAttribute(Command::CA_UpdateText); /* for Mac */ mwindow->addAction(cmd, Constants::G_WINDOW_SIZE); connect(m_toggleFullScreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool))); +#ifdef Q_OS_MAC + } #endif // Window->Views @@ -1352,6 +1381,10 @@ QPrinter *MainWindow::printer() const void MainWindow::setFullScreen(bool on) { +#if defined(Q_OS_MAC) + Q_UNUSED(on) + MacFullScreen::toggleFullScreen(this); +#else if (bool(windowState() & Qt::WindowFullScreen) == on) return; @@ -1364,6 +1397,7 @@ void MainWindow::setFullScreen(bool on) //menuBar()->show(); //statusBar()->show(); } +#endif } // Display a warning with an additional button to open diff --git a/src/plugins/coreplugin/mainwindow.h b/src/plugins/coreplugin/mainwindow.h index 86d77f7800..96a50729bf 100644 --- a/src/plugins/coreplugin/mainwindow.h +++ b/src/plugins/coreplugin/mainwindow.h @@ -33,10 +33,11 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include "eventfilteringmainwindow.h" #include "icontext.h" #include "icore.h" +#include <utils/appmainwindow.h> + #include <QMap> #include <QColor> @@ -80,7 +81,7 @@ class StatusBarManager; class VersionDialog; class SystemEditor; -class MainWindow : public EventFilteringMainWindow +class MainWindow : public Utils::AppMainWindow { Q_OBJECT @@ -126,6 +127,9 @@ public: bool isPresentationModeEnabled(); void setPresentationModeEnabled(bool); +#ifdef Q_OS_MAC + void setIsFullScreen(bool fullScreen); +#endif signals: void windowActivated(); diff --git a/src/plugins/coreplugin/textdocument.cpp b/src/plugins/coreplugin/textdocument.cpp index 78a3447d7d..377567180b 100644 --- a/src/plugins/coreplugin/textdocument.cpp +++ b/src/plugins/coreplugin/textdocument.cpp @@ -140,6 +140,13 @@ void TextDocument::setCodec(const QTextCodec *codec) d->m_format.codec = codec; } +void TextDocument::switchUtf8Bom() +{ + if (debug) + qDebug() << Q_FUNC_INFO << this << "UTF-8 BOM: " << !d->m_format.hasUtf8Bom; + d->m_format.hasUtf8Bom = !d->m_format.hasUtf8Bom; +} + /*! \brief Returns the format obtained from the last call to read(). */ diff --git a/src/plugins/coreplugin/textdocument.h b/src/plugins/coreplugin/textdocument.h index 9fc5a89056..6c59c69fcb 100644 --- a/src/plugins/coreplugin/textdocument.h +++ b/src/plugins/coreplugin/textdocument.h @@ -55,6 +55,7 @@ public: Utils::TextFileFormat format() const; const QTextCodec *codec() const; void setCodec(const QTextCodec *); + void switchUtf8Bom(); ReadResult read(const QString &fileName, QStringList *plainTextList, QString *errorString); ReadResult read(const QString &fileName, QString *plainText, QString *errorString); diff --git a/src/plugins/cpaster/cpasterplugin.h b/src/plugins/cpaster/cpasterplugin.h index 4b50faa91c..f7c93526b5 100644 --- a/src/plugins/cpaster/cpasterplugin.h +++ b/src/plugins/cpaster/cpasterplugin.h @@ -63,6 +63,7 @@ public slots: class CodepasterPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "CodePaster.json") public: CodepasterPlugin(); diff --git a/src/plugins/cppeditor/cppcompleteswitch.cpp b/src/plugins/cppeditor/cppcompleteswitch.cpp index c0deb7a5e2..d39831c404 100644 --- a/src/plugins/cppeditor/cppcompleteswitch.cpp +++ b/src/plugins/cppeditor/cppcompleteswitch.cpp @@ -103,7 +103,7 @@ public: class Operation: public CppQuickFixOperation { public: - Operation(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface, + Operation(const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface, int priority, CompoundStatementAST *compoundStatement, const QStringList &values) @@ -156,7 +156,7 @@ static Enum *findEnum(const QList<LookupItem> &results, return 0; } -static Enum *conditionEnum(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface, +static Enum *conditionEnum(const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface, SwitchStatementAST *statement) { Block *block = statement->symbol; @@ -173,7 +173,7 @@ static Enum *conditionEnum(const QSharedPointer<const Internal::CppQuickFixAssis } // end of anonymous namespace QList<CppQuickFixOperation::Ptr> CompleteSwitchCaseStatement::match( - const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface) + const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface) { const QList<AST *> &path = interface->path(); diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 1e7a3b891a..b18cc1dacb 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -49,7 +49,7 @@ #include <SymbolVisitor.h> #include <TranslationUnit.h> #include <cplusplus/ASTPath.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/TypeOfExpression.h> #include <cplusplus/Overview.h> @@ -1485,11 +1485,6 @@ CPPEditorWidget::Link CPPEditorWidget::findLinkAt(const QTextCursor &cursor, return Link(); } -void CPPEditorWidget::jumpToDefinition() -{ - openLink(findLinkAt(textCursor())); -} - Symbol *CPPEditorWidget::findDefinition(Symbol *symbol, const Snapshot &snapshot) const { if (symbol->isFunction()) diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 999e4dacc7..b9a75de2ce 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -36,7 +36,7 @@ #include "cppeditorenums.h" #include "cppfunctiondecldeflink.h" -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/CppDocument.h> #include <cplusplus/LookupContext.h> #include <texteditor/basetexteditor.h> @@ -208,7 +208,6 @@ public Q_SLOTS: virtual void setTabSettings(const TextEditor::TabSettings &); void setSortedOutline(bool sort); void switchDeclarationDefinition(); - void jumpToDefinition(); void renameSymbolUnderCursor(); void renameUsages(); void findUsages(); diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index 1178b5f70b..5fc351a3b6 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -2,8 +2,6 @@ TEMPLATE = lib TARGET = CppEditor DEFINES += CPPEDITOR_LIBRARY include(../../qtcreatorplugin.pri) -include($$IDE_SOURCE_TREE/src/libs/utils/utils.pri) -include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri) include(cppeditor_dependencies.pri) HEADERS += cppplugin.h \ cppeditor.h \ diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h index e2aeff9d68..6ad17f0fda 100644 --- a/src/plugins/cppeditor/cppeditorconstants.h +++ b/src/plugins/cppeditor/cppeditorconstants.h @@ -48,7 +48,6 @@ const char SEPARATOR[] = "CppEditor.Separator"; const char SEPARATOR2[] = "CppEditor.Separator2"; const char SEPARATOR3[] = "CppEditor.Separator3"; const char SEPARATOR4[] = "CppEditor.Separator4"; -const char JUMP_TO_DEFINITION[] = "CppEditor.JumpToDefinition"; const char UPDATE_CODEMODEL[] = "CppEditor.UpdateCodeModel"; const int TYPE_HIERARCHY_PRIORITY = 700; diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp index faa723a215..56d9660997 100644 --- a/src/plugins/cppeditor/cppelementevaluator.cpp +++ b/src/plugins/cppeditor/cppelementevaluator.cpp @@ -42,8 +42,8 @@ #include <Scope.h> #include <Symbol.h> #include <Symbols.h> -#include <TypeHierarchyBuilder.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/TypeHierarchyBuilder.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/Overview.h> #include <cplusplus/TypeOfExpression.h> diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp index 2534df0d97..7f3ec478d2 100644 --- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp +++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp @@ -993,7 +993,7 @@ class ApplyDeclDefLinkOperation : public CppQuickFixOperation { public: explicit ApplyDeclDefLinkOperation( - const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface, + const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface, const QSharedPointer<FunctionDeclDefLink> &link) : CppQuickFixOperation(interface, 10) , m_link(link) diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index 6e6d3e30ee..0c1ed57da9 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -37,7 +37,7 @@ #include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/helpmanager.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <extensionsystem/pluginmanager.h> #include <texteditor/itexteditor.h> #include <texteditor/basetexteditor.h> diff --git a/src/plugins/cppeditor/cppinsertdecldef.cpp b/src/plugins/cppeditor/cppinsertdecldef.cpp index 87cb345dba..ff15aba075 100644 --- a/src/plugins/cppeditor/cppinsertdecldef.cpp +++ b/src/plugins/cppeditor/cppinsertdecldef.cpp @@ -64,7 +64,7 @@ namespace { class InsertDeclOperation: public CppQuickFixOperation { public: - InsertDeclOperation(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface, + InsertDeclOperation(const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface, const QString &targetFileName, const Class *targetSymbol, InsertionPointLocator::AccessSpec xsSpec, const QString &decl) @@ -151,7 +151,7 @@ Class *isMemberFunction(const LookupContext &context, Function *function) } // anonymous namespace QList<CppQuickFixOperation::Ptr> DeclFromDef::match( - const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface) + const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface) { const QList<AST *> &path = interface->path(); CppRefactoringFilePtr file = interface->currentFile(); @@ -229,7 +229,7 @@ namespace { class InsertDefOperation: public CppQuickFixOperation { public: - InsertDefOperation(const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface, + InsertDefOperation(const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface, Declaration *decl, const InsertionLocation &loc) : CppQuickFixOperation(interface, 0) , m_decl(decl) @@ -297,7 +297,7 @@ private: } // anonymous namespace QList<CppQuickFixOperation::Ptr> DefFromDecl::match( - const QSharedPointer<const Internal::CppQuickFixAssistInterface> &interface) + const QSharedPointer<const CppEditor::Internal::CppQuickFixAssistInterface> &interface) { const QList<AST *> &path = interface->path(); diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp index ca3476bd40..bfc49aafdf 100644 --- a/src/plugins/cppeditor/cppplugin.cpp +++ b/src/plugins/cppeditor/cppplugin.cpp @@ -57,7 +57,7 @@ #include <texteditor/texteditorplugin.h> #include <texteditor/texteditorsettings.h> #include <texteditor/texteditorconstants.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolssettings.h> @@ -242,12 +242,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess cmd = am->command(Core::Id(CppTools::Constants::SWITCH_HEADER_SOURCE)); contextMenu->addAction(cmd); - QAction *jumpToDefinition = new QAction(tr("Follow Symbol Under Cursor"), this); - cmd = am->registerAction(jumpToDefinition, - Constants::JUMP_TO_DEFINITION, context, true); - cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); - connect(jumpToDefinition, SIGNAL(triggered()), - this, SLOT(jumpToDefinition())); + cmd = am->command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR); contextMenu->addAction(cmd); cppToolsMenu->addAction(cmd); @@ -304,7 +299,8 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess m_actionHandler = new TextEditor::TextEditorActionHandler(CppEditor::Constants::C_CPPEDITOR, TextEditor::TextEditorActionHandler::Format | TextEditor::TextEditorActionHandler::UnCommentSelection - | TextEditor::TextEditorActionHandler::UnCollapseAll); + | TextEditor::TextEditorActionHandler::UnCollapseAll + | TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor); m_actionHandler->initializeActions(); @@ -355,14 +351,6 @@ void CppPlugin::switchDeclarationDefinition() editor->switchDeclarationDefinition(); } -void CppPlugin::jumpToDefinition() -{ - Core::EditorManager *em = Core::EditorManager::instance(); - CPPEditorWidget *editor = qobject_cast<CPPEditorWidget*>(em->currentEditor()->widget()); - if (editor) - editor->jumpToDefinition(); -} - void CppPlugin::renameSymbolUnderCursor() { Core::EditorManager *em = Core::EditorManager::instance(); diff --git a/src/plugins/cppeditor/cppplugin.h b/src/plugins/cppeditor/cppplugin.h index acc251e5cb..652c942d76 100644 --- a/src/plugins/cppeditor/cppplugin.h +++ b/src/plugins/cppeditor/cppplugin.h @@ -55,6 +55,7 @@ class CppQuickFixAssistProvider; class CppPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "CppEditor.json") public: CppPlugin(); @@ -82,7 +83,6 @@ public slots: private slots: void switchDeclarationDefinition(); - void jumpToDefinition(); void renameSymbolUnderCursor(); void onTaskStarted(const QString &type); void onAllTasksFinished(const QString &type); diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 7833f99099..44292fe075 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -56,7 +56,7 @@ #include <cplusplus/DependencyTable.h> #include <cplusplus/Overview.h> #include <cplusplus/TypeOfExpression.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/CppRewriter.h> #include <cpptools/cpptoolsconstants.h> #include <cpptools/cpprefactoringchanges.h> diff --git a/src/plugins/cpptools/ModelManagerInterface.cpp b/src/plugins/cpptools/ModelManagerInterface.cpp new file mode 100644 index 0000000000..18443186df --- /dev/null +++ b/src/plugins/cpptools/ModelManagerInterface.cpp @@ -0,0 +1,99 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "ModelManagerInterface.h" + +#include <QtCore/QSet> + +using namespace CPlusPlus; + +static CppModelManagerInterface *g_instance = 0; + +CppModelManagerInterface::CppModelManagerInterface(QObject *parent) + : QObject(parent) +{ + Q_ASSERT(! g_instance); + g_instance = this; +} + +CppModelManagerInterface::~CppModelManagerInterface() +{ + Q_ASSERT(g_instance == this); + g_instance = 0; +} + +CppModelManagerInterface *CppModelManagerInterface::instance() +{ + return g_instance; +} + + +void CppModelManagerInterface::ProjectInfo::clearProjectParts() +{ + m_projectParts.clear(); + m_includePaths.clear(); + m_frameworkPaths.clear(); + m_sourceFiles.clear(); + m_defines.clear(); +} + +void CppModelManagerInterface::ProjectInfo::appendProjectPart( + const CppModelManagerInterface::ProjectPart::Ptr &part) +{ + if (!part) + return; + + m_projectParts.append(part); + + // update include paths + QSet<QString> incs = QSet<QString>::fromList(m_includePaths); + foreach (const QString &ins, part->includePaths) + incs.insert(ins); + m_includePaths = incs.toList(); + + // update framework paths + QSet<QString> frms = QSet<QString>::fromList(m_frameworkPaths); + foreach (const QString &frm, part->frameworkPaths) + frms.insert(frm); + m_frameworkPaths = frms.toList(); + + // update source files + QSet<QString> srcs = QSet<QString>::fromList(m_sourceFiles); + foreach (const QString &src, part->sourceFiles) + srcs.insert(src); + m_sourceFiles = srcs.toList(); + + // update defines + if (!m_defines.isEmpty()) + m_defines.append('\n'); + m_defines.append(part->defines); +} diff --git a/src/plugins/cpptools/ModelManagerInterface.h b/src/plugins/cpptools/ModelManagerInterface.h new file mode 100644 index 0000000000..b873e880fe --- /dev/null +++ b/src/plugins/cpptools/ModelManagerInterface.h @@ -0,0 +1,237 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef CPPMODELMANAGERINTERFACE_H +#define CPPMODELMANAGERINTERFACE_H + +#include <cplusplus/CppDocument.h> +#include <languageutils/fakemetaobject.h> +#include "cpptools_global.h" + +#include <QObject> +#include <QHash> +#include <QPointer> +#include <QStringList> +#include <QFuture> + +namespace Core { + class IEditor; +} + +namespace CPlusPlus { + class LookupContext; +} + +namespace ProjectExplorer { + class Project; +} + +namespace CppTools { + class AbstractEditorSupport; + class CppCompletionSupport; + class CppCompletionAssistProvider; + class CppHighlightingSupport; + class CppHighlightingSupportFactory; +} + +namespace CPlusPlus { + +class CPPTOOLS_EXPORT CppModelManagerInterface : public QObject +{ + Q_OBJECT + +public: + enum Language { CXX, OBJC }; + + class CPPTOOLS_EXPORT ProjectPart + { + public: + ProjectPart() + : language(CXX) + , cxx11Enabled(false) + , qtVersion(UnknownQt) + {} + + public: //attributes + QStringList sourceFiles; + QByteArray defines; + QStringList includePaths; + QStringList frameworkPaths; + QStringList precompiledHeaders; + Language language; + bool cxx11Enabled; + enum QtVersion { + UnknownQt = -1, + NoQt = 0, + Qt4 = 1, + Qt5 = 2 + }; + QtVersion qtVersion; + + bool objcEnabled() const + { return language == CppModelManagerInterface::OBJC; } + + typedef QSharedPointer<ProjectPart> Ptr; + }; + + class CPPTOOLS_EXPORT ProjectInfo + { + public: + ProjectInfo() + { } + + ProjectInfo(QWeakPointer<ProjectExplorer::Project> project) + : m_project(project) + { } + + operator bool() const + { return ! m_project.isNull(); } + + bool isValid() const + { return ! m_project.isNull(); } + + bool isNull() const + { return m_project.isNull(); } + + QWeakPointer<ProjectExplorer::Project> project() const + { return m_project; } + + const QList<ProjectPart::Ptr> projectParts() const + { return m_projectParts; } + + void clearProjectParts(); + void appendProjectPart(const ProjectPart::Ptr &part); + + const QStringList includePaths() const + { return m_includePaths; } + + const QStringList frameworkPaths() const + { return m_frameworkPaths; } + + const QStringList sourceFiles() const + { return m_sourceFiles; } + + const QByteArray defines() const + { return m_defines; } + + private: // attributes + QWeakPointer<ProjectExplorer::Project> m_project; + QList<ProjectPart::Ptr> m_projectParts; + // the attributes below are calculated from the project parts. + QStringList m_includePaths; + QStringList m_frameworkPaths; + QStringList m_sourceFiles; + QByteArray m_defines; + }; + + class CPPTOOLS_EXPORT WorkingCopy + { + public: + void insert(const QString &fileName, const QString &source, unsigned revision = 0) + { _elements.insert(fileName, qMakePair(source, revision)); } + + bool contains(const QString &fileName) const + { return _elements.contains(fileName); } + + QString source(const QString &fileName) const + { return _elements.value(fileName).first; } + + QPair<QString, unsigned> get(const QString &fileName) const + { return _elements.value(fileName); } + + QHashIterator<QString, QPair<QString, unsigned> > iterator() const + { return QHashIterator<QString, QPair<QString, unsigned> >(_elements); } + + private: + typedef QHash<QString, QPair<QString, unsigned> > Table; + Table _elements; + }; + + enum ExtraDiagnosticKind + { + AllExtraDiagnostics = -1, + ExportedQmlTypesDiagnostic + }; + +public: + CppModelManagerInterface(QObject *parent = 0); + virtual ~CppModelManagerInterface(); + + static CppModelManagerInterface *instance(); + + virtual bool isCppEditor(Core::IEditor *editor) const = 0; + + virtual WorkingCopy workingCopy() const = 0; + virtual CPlusPlus::Snapshot snapshot() const = 0; + + virtual QList<ProjectInfo> projectInfos() const = 0; + virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const = 0; + virtual void updateProjectInfo(const ProjectInfo &pinfo) = 0; + virtual QList<ProjectPart::Ptr> projectPart(const QString &fileName) const = 0; + + virtual void addEditorSupport(CppTools::AbstractEditorSupport *editorSupport) = 0; + virtual void removeEditorSupport(CppTools::AbstractEditorSupport *editorSupport) = 0; + + virtual QList<int> references(CPlusPlus::Symbol *symbol, + const CPlusPlus::LookupContext &context) = 0; + + virtual void renameUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context, + const QString &replacement = QString()) = 0; + virtual void findUsages(CPlusPlus::Symbol *symbol, const CPlusPlus::LookupContext &context) = 0; + + virtual void findMacroUsages(const CPlusPlus::Macro ¯o) = 0; + + virtual void setExtraDiagnostics(const QString &fileName, int key, + const QList<CPlusPlus::Document::DiagnosticMessage> &diagnostics) = 0; + virtual QList<CPlusPlus::Document::DiagnosticMessage> extraDiagnostics( + const QString &fileName, int key = AllExtraDiagnostics) const = 0; + + virtual CppTools::CppCompletionSupport *completionSupport(Core::IEditor *editor) const = 0; + virtual void setCppCompletionAssistProvider(CppTools::CppCompletionAssistProvider *completionAssistProvider) = 0; + + virtual CppTools::CppHighlightingSupport *highlightingSupport(Core::IEditor *editor) const = 0; + virtual void setHighlightingSupportFactory(CppTools::CppHighlightingSupportFactory *highlightingFactory) = 0; + +Q_SIGNALS: + void documentUpdated(CPlusPlus::Document::Ptr doc); + void sourceFilesRefreshed(const QStringList &files); + void extraDiagnosticsUpdated(QString fileName); + +public Q_SLOTS: + virtual void updateModifiedSourceFiles() = 0; + virtual QFuture<void> updateSourceFiles(const QStringList &sourceFiles) = 0; + virtual void GC() = 0; +}; + +} // namespace CPlusPlus + +#endif // CPPMODELMANAGERINTERFACE_H diff --git a/src/plugins/cpptools/TypeHierarchyBuilder.cpp b/src/plugins/cpptools/TypeHierarchyBuilder.cpp new file mode 100644 index 0000000000..73eba4dc85 --- /dev/null +++ b/src/plugins/cpptools/TypeHierarchyBuilder.cpp @@ -0,0 +1,204 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "TypeHierarchyBuilder.h" +#include "FindUsages.h" +#include "Symbols.h" +#include "SymbolVisitor.h" +#include "DependencyTable.h" +#include "CppDocument.h" +#include "Literals.h" +#include "TranslationUnit.h" +#include "CoreTypes.h" + +using namespace CPlusPlus; + +namespace { + +QString unqualifyName(const QString &qualifiedName) +{ + const int index = qualifiedName.lastIndexOf(QLatin1String("::")); + if (index == -1) + return qualifiedName; + return qualifiedName.right(qualifiedName.length() - index - 2); +} + +class DerivedHierarchyVisitor : public SymbolVisitor +{ +public: + DerivedHierarchyVisitor(const QString &qualifiedName) + : _qualifiedName(qualifiedName) + , _unqualifiedName(unqualifyName(qualifiedName)) + {} + + void execute(const Document::Ptr &doc, const Snapshot &snapshot); + + virtual bool visit(Class *); + + const QList<Symbol *> &derived() { return _derived; } + const QStringList otherBases() { return _otherBases; } + +private: + LookupContext _context; + QString _qualifiedName; + QString _unqualifiedName; + Overview _overview; + QHash<Symbol *, QString> _actualBases; + QStringList _otherBases; + QList<Symbol *> _derived; +}; + +void DerivedHierarchyVisitor::execute(const Document::Ptr &doc, const Snapshot &snapshot) +{ + _derived.clear(); + _otherBases.clear(); + _context = LookupContext(doc, snapshot); + + for (unsigned i = 0; i < doc->globalSymbolCount(); ++i) + accept(doc->globalSymbolAt(i)); +} + +bool DerivedHierarchyVisitor::visit(Class *symbol) +{ + for (unsigned i = 0; i < symbol->baseClassCount(); ++i) { + BaseClass *baseSymbol = symbol->baseClassAt(i); + + QString baseName = _actualBases.value(baseSymbol); + if (baseName.isEmpty()) { + QList<LookupItem> items = _context.lookup(baseSymbol->name(), symbol->enclosingScope()); + if (items.isEmpty() || !items.first().declaration()) + continue; + + Symbol *actualBaseSymbol = items.first().declaration(); + if (actualBaseSymbol->isTypedef()) { + NamedType *namedType = actualBaseSymbol->type()->asNamedType(); + if (!namedType) { + // Anonymous aggregate such as: typedef struct {} Empty; + continue; + } + const QString &typeName = _overview.prettyName(namedType->name()); + if (typeName == _unqualifiedName || typeName == _qualifiedName) { + items = _context.lookup(namedType->name(), actualBaseSymbol->enclosingScope()); + if (items.isEmpty() || !items.first().declaration()) + continue; + actualBaseSymbol = items.first().declaration(); + } + } + + const QList<const Name *> &full = LookupContext::fullyQualifiedName(actualBaseSymbol); + baseName = _overview.prettyName(full); + _actualBases.insert(baseSymbol, baseName); + } + + if (_qualifiedName == baseName) + _derived.append(symbol); + else + _otherBases.append(baseName); + } + + return true; +} + +} + +TypeHierarchy::TypeHierarchy() : _symbol(0) +{} + +TypeHierarchy::TypeHierarchy(Symbol *symbol) : _symbol(symbol) +{} + +Symbol *TypeHierarchy::symbol() const +{ + return _symbol; +} + +const QList<TypeHierarchy> &TypeHierarchy::hierarchy() const +{ + return _hierarchy; +} + +TypeHierarchyBuilder::TypeHierarchyBuilder(Symbol *symbol, const Snapshot &snapshot) + : _symbol(symbol) + , _snapshot(snapshot) + , _dependencies(QString::fromUtf8(symbol->fileName(), symbol->fileNameLength())) +{ + DependencyTable dependencyTable; + dependencyTable.build(_snapshot); + _dependencies.append(dependencyTable.filesDependingOn(_dependencies.first())); +} + +void TypeHierarchyBuilder::reset() +{ + _visited.clear(); + _candidates.clear(); +} + +TypeHierarchy TypeHierarchyBuilder::buildDerivedTypeHierarchy() +{ + reset(); + TypeHierarchy hierarchy(_symbol); + buildDerived(&hierarchy); + return hierarchy; +} + +void TypeHierarchyBuilder::buildDerived(TypeHierarchy *typeHierarchy) +{ + Symbol *symbol = typeHierarchy->_symbol; + if (_visited.contains(symbol)) + return; + + _visited.insert(symbol); + + const QString &symbolName = _overview.prettyName(LookupContext::fullyQualifiedName(symbol)); + DerivedHierarchyVisitor visitor(symbolName); + + foreach (const QString &fileName, _dependencies) { + Document::Ptr doc = _snapshot.document(fileName); + if ((_candidates.contains(fileName) && !_candidates.value(fileName).contains(symbolName)) + || !doc->control()->findIdentifier(symbol->identifier()->chars(), + symbol->identifier()->size())) { + continue; + } + + visitor.execute(doc, _snapshot); + _candidates.insert(fileName, QSet<QString>()); + + foreach (const QString &candidate, visitor.otherBases()) + _candidates[fileName].insert(candidate); + + foreach (Symbol *s, visitor.derived()) { + TypeHierarchy derivedHierarchy(s); + buildDerived(&derivedHierarchy); + typeHierarchy->_hierarchy.append(derivedHierarchy); + } + } +} diff --git a/src/plugins/cpptools/TypeHierarchyBuilder.h b/src/plugins/cpptools/TypeHierarchyBuilder.h new file mode 100644 index 0000000000..93727f548e --- /dev/null +++ b/src/plugins/cpptools/TypeHierarchyBuilder.h @@ -0,0 +1,84 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef FINDDERIVEDCLASSES_H +#define FINDDERIVEDCLASSES_H + +#include "CppDocument.h" +#include "ModelManagerInterface.h" +#include "Overview.h" +#include "cpptools_global.h" + +#include <QList> +#include <QStringList> +#include <QSet> + +namespace CPlusPlus { + +class CPPTOOLS_EXPORT TypeHierarchy +{ + friend class TypeHierarchyBuilder; + +public: + TypeHierarchy(); + TypeHierarchy(Symbol *symbol); + + Symbol *symbol() const; + const QList<TypeHierarchy> &hierarchy() const; + +private: + Symbol *_symbol; + QList<TypeHierarchy> _hierarchy; +}; + +class CPPTOOLS_EXPORT TypeHierarchyBuilder +{ +public: + TypeHierarchyBuilder(Symbol *symbol, const Snapshot &snapshot); + + TypeHierarchy buildDerivedTypeHierarchy(); + +private: + void reset(); + void buildDerived(TypeHierarchy *typeHierarchy); + + Symbol *_symbol; + Snapshot _snapshot; + QStringList _dependencies; + QSet<Symbol *> _visited; + QHash<QString, QSet<QString> > _candidates; + Overview _overview; +}; + +} // CPlusPlus + +#endif // FINDDERIVEDCLASSES_H diff --git a/src/plugins/cpptools/abstracteditorsupport.cpp b/src/plugins/cpptools/abstracteditorsupport.cpp index e6e3e20651..3fb2d76983 100644 --- a/src/plugins/cpptools/abstracteditorsupport.cpp +++ b/src/plugins/cpptools/abstracteditorsupport.cpp @@ -37,7 +37,7 @@ #include <cplusplus/Overview.h> #include <cplusplus/CppDocument.h> #include <cplusplus/ExpressionUnderCursor.h> -#include <cplusplus/ModelManagerInterface.h> +#include "ModelManagerInterface.h" #include <CoreTypes.h> #include <Names.h> #include <Symbols.h> diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp index 50f2165659..be10cab616 100644 --- a/src/plugins/cpptools/cppcodeformatter.cpp +++ b/src/plugins/cpptools/cppcodeformatter.cpp @@ -229,9 +229,74 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block) default: tryExpression(); break; } break; + case lambda_instroducer_or_subscribtion: + switch (kind) { + case T_RBRACKET: turnInto(lambda_declarator_expected); break; // we can't determine exact kind of expression. Try again + case T_COMMA: + case T_EQUAL: turnInto(lambda_instroducer); break; // ',' or '=' inside brackets can be only whithin lambda capture list + case T_IDENTIFIER: // '&', id, 'this' are allowed both in the capture list and subscribtion + case T_AMPER: + case T_THIS: break; + default: leave(); leave(); tryExpression(m_currentState.at(m_currentState.size() - 1).type == declaration_start); break; + // any other symbol allowed only in subscribtion operator + } break; + + case lambda_declarator_expected: + switch (kind) { + case T_LPAREN: turnInto(lambda_declarator_or_expression); break; // '(' just after ']'. We can't make decisioin here + case T_LBRACE: turnInto(substatement_open); break; // '{' just after ']' opens a lambda-compound statement + default: + if (m_currentState.size() >= 3 && m_currentState.at(m_currentState.size() - 3).type == declaration_start) + leave(); + + leave(); + continue; + } break; + + case lambda_instroducer: + switch (kind) { + case T_RBRACKET: turnInto(lambda_declarator); break; + } break; + + case lambda_declarator_or_expression: + switch (kind) { + case T_LBRACE: turnInto(substatement_open); /*tryStatement();*/ break; + case T_RPAREN: turnInto(lambda_statement_expected); break; + case T_IDENTIFIER: + case T_SEMICOLON: leave(); continue; + default: + if (tryDeclaration()) {// We found the declaration within '()' so it is lambda declarator + leave(); + turnInto(lambda_declarator); + break; + } else { + turnInto(expression); + enter(arglist_open); + continue; + } + } break; + + case lambda_statement_expected: + switch (kind) { + case T_LBRACE: turnInto(substatement_open); /*tryStatement()*/; break; + case T_NOEXCEPT: // 'noexcept', 'decltype' and 'mutable' are only part of lambda declarator + case T_DECLTYPE: + case T_MUTABLE: turnInto(lambda_declarator); break; + case T_RBRACKET: // '[', ']' and '->' can be part of lambda declarator + case T_LBRACKET: + case T_ARROW: break; + default: leave(); continue; + } break; + + case lambda_declarator: + switch (kind) { + case T_LBRACE: turnInto(substatement_open); /*tryStatement()*/; break; + } break; + case arglist_open: switch (kind) { case T_SEMICOLON: leave(true); break; + case T_LBRACE: enter(brace_list_open); break; case T_RBRACE: leave(true); continue; case T_RPAREN: leave(); break; default: tryExpression(); break; @@ -739,6 +804,9 @@ bool CodeFormatter::tryExpression(bool alsoExpression) } } break; + case T_LBRACKET: + newState = lambda_instroducer_or_subscribtion; + break; } if (newState != -1) { diff --git a/src/plugins/cpptools/cppcodeformatter.h b/src/plugins/cpptools/cppcodeformatter.h index 8dab0dbc81..a7da67f57c 100644 --- a/src/plugins/cpptools/cppcodeformatter.h +++ b/src/plugins/cpptools/cppcodeformatter.h @@ -177,7 +177,16 @@ public: // must be public to make Q_GADGET introspection work assign_open, // after an assignment token expression, // after a '=' in a declaration_start once we're sure it's not '= {' - assign_open_or_initializer // after a '=' in a declaration start + assign_open_or_initializer, // after a '=' in a declaration start + + lambda_instroducer_or_subscribtion, // just after '[' or in cases '[]' and '[id]' when we're not sure in the exact kind of expression + lambda_declarator_expected, // just after ']' in lambda_introducer_or_subscribtion + lambda_declarator_or_expression, // just after '](' when previous state is 'lambda_instroducer_or_subscribtion' + lambda_statement_expected, + lambda_instroducer, // when '=', '&' or ',' occurred within '[]' + lambda_declarator, // just after ']' when previous state is lambda_introducer + lambda_statement // just after '{' when previous state is lambda_declarator or lambda_declarator_or_expression + }; Q_ENUMS(StateType) diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index e7f41b2b73..c40b6306fc 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -79,7 +79,7 @@ using namespace CPlusPlus; using namespace CppEditor; using namespace CppTools; -using namespace Internal; +using namespace CppTools::Internal; using namespace TextEditor; namespace CppTools { diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 46f68f55a5..2c47a6b371 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -55,7 +55,7 @@ #include <Names.h> #include <Scope.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/CppDocument.h> #include <cplusplus/Overview.h> #include <cplusplus/FindUsages.h> @@ -562,7 +562,7 @@ public: unsigned lineStart; const QString &lineSource = matchingLine(use.begin(), source, &lineStart); usages.append(Usage(fileName, lineSource, use.beginLine(), - use.begin() - lineStart, use.length())); + use.begin() - lineStart, useMacro.name().length())); } } @@ -646,8 +646,13 @@ void CppFindReferences::findMacroUses(const Macro ¯o) { // ### FIXME: Encoding? const QByteArray &source = getSource(macro.fileName(), workingCopy).toLatin1(); - search->addResult(macro.fileName(), macro.line(), - source.mid(macro.offset(), macro.length()), 0, macro.length()); + int lineBegin = source.lastIndexOf('\n', macro.offset()) + 1; + int lineEnd = source.indexOf('\n', macro.offset()); + if (lineEnd == -1) + lineEnd = source.length(); + const QByteArray line = source.mid(lineBegin, lineEnd - lineBegin); + search->addResult(macro.fileName(), macro.line(), line, + line.indexOf(macro.name()), macro.name().length()); } QFuture<Usage> result; diff --git a/src/plugins/cpptools/cpphighlightingsupport.h b/src/plugins/cpptools/cpphighlightingsupport.h index 6b80542037..4319ff9c4e 100644 --- a/src/plugins/cpptools/cpphighlightingsupport.h +++ b/src/plugins/cpptools/cpphighlightingsupport.h @@ -72,6 +72,8 @@ public: virtual ~CppHighlightingSupportFactory() = 0; virtual CppHighlightingSupport *highlightingSupport(TextEditor::ITextEditor *editor) = 0; + + virtual bool hightlighterHandlesDiagnostics() const = 0; }; } // namespace CppTools diff --git a/src/plugins/cpptools/cpphighlightingsupportinternal.h b/src/plugins/cpptools/cpphighlightingsupportinternal.h index 52ab1f8118..16c81e983a 100644 --- a/src/plugins/cpptools/cpphighlightingsupportinternal.h +++ b/src/plugins/cpptools/cpphighlightingsupportinternal.h @@ -62,6 +62,9 @@ public: virtual ~CppHighlightingSupportInternalFactory(); virtual CppHighlightingSupport *highlightingSupport(TextEditor::ITextEditor *editor); + + virtual bool hightlighterHandlesDiagnostics() const + { return false; } }; } // namespace Internal diff --git a/src/plugins/cpptools/cpplocalsymbols.cpp b/src/plugins/cpptools/cpplocalsymbols.cpp index 0b62d58c25..7c84b5cac3 100644 --- a/src/plugins/cpptools/cpplocalsymbols.cpp +++ b/src/plugins/cpptools/cpplocalsymbols.cpp @@ -109,6 +109,8 @@ protected: bool checkLocalUse(NameAST *nameAst, unsigned firstToken) { if (SimpleNameAST *simpleName = nameAst->asSimpleName()) { + if (tokenAt(simpleName->identifier_token).generated()) + return false; const Identifier *id = identifier(simpleName->identifier_token); for (int i = _scopeStack.size() - 1; i != -1; --i) { if (Symbol *member = _scopeStack.at(i)->find(id)) { diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 4e3b4a8f07..ae79ec65a8 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -96,7 +96,7 @@ namespace CPlusPlus { uint qHash(const CppModelManagerInterface::ProjectPart &p) { - uint h = qHash(p.defines) ^ p.language ^ p.flags; + uint h = qHash(p.defines) ^ p.language ^ ((int) p.cxx11Enabled); foreach (const QString &i, p.includePaths) h ^= qHash(i); @@ -113,7 +113,7 @@ bool operator==(const CppModelManagerInterface::ProjectPart &p1, return false; if (p1.language != p2.language) return false; - if (p1.flags != p2.flags) + if (p1.cxx11Enabled != p2.cxx11Enabled) return false; if (p1.includePaths != p2.includePaths) return false; @@ -201,9 +201,10 @@ static const char pp_configuration[] = "#define __forceinline inline\n"; #ifndef ICHECK_BUILD -CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) +CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing) : snapshot(modelManager->snapshot()), m_modelManager(modelManager), + m_dumpFileNameWhileParsing(dumpFileNameWhileParsing), preprocess(this, &env), m_revision(0) { @@ -214,6 +215,7 @@ CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) CppPreprocessor::CppPreprocessor(QPointer<CPlusPlus::ParseManager> modelManager) : preprocess(this, &env), + m_dumpFileNameWhileParsing(false), m_revision(0) { } @@ -503,7 +505,7 @@ void CppPreprocessor::passedMacroDefinitionCheck(unsigned offset, const Macro &m return; m_currentDoc->addMacroUse(macro, offset, macro.name().length(), env.currentLine, - QVector<MacroArgumentReference>(), true); + QVector<MacroArgumentReference>()); } void CppPreprocessor::failedMacroDefinitionCheck(unsigned offset, const QByteArray &name) @@ -517,7 +519,6 @@ void CppPreprocessor::failedMacroDefinitionCheck(unsigned offset, const QByteArr void CppPreprocessor::startExpandingMacro(unsigned offset, const Macro ¯o, const QByteArray &originalText, - bool inCondition, const QVector<MacroArgumentReference> &actuals) { if (! m_currentDoc) @@ -525,7 +526,7 @@ void CppPreprocessor::startExpandingMacro(unsigned offset, //qDebug() << "start expanding:" << macro.name() << "text:" << originalText; m_currentDoc->addMacroUse(macro, offset, originalText.length(), env.currentLine, - actuals, inCondition); + actuals); } void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &) @@ -600,7 +601,11 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned } } - //qDebug() << "parse file:" << fileName << "contents:" << contents.size(); + if (m_dumpFileNameWhileParsing) { + qDebug() << "Parsing file:" << fileName +// << "contents:" << contents.size() + ; + } Document::Ptr doc = snapshot.document(fileName); if (doc) { @@ -620,6 +625,8 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned const QByteArray preprocessedCode = preprocess(fileName, contents); +// { QByteArray b(preprocessedCode); b.replace("\n", "<<<\n"); qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(), b.constData()); } + doc->setUtf8Source(preprocessedCode); doc->keepSourceAndAST(); doc->tokenize(); @@ -692,6 +699,7 @@ CppModelManager::CppModelManager(QObject *parent) { m_findReferences = new CppFindReferences(this); m_indexerEnabled = qgetenv("QTCREATOR_NO_CODE_INDEXER").isNull(); + m_dumpFileNameWhileParsing = !qgetenv("QTCREATOR_DUMP_FILENAME_WHILE_PARSING").isNull(); m_revision = 0; m_synchronizer.setCancelOnWait(true); @@ -917,11 +925,12 @@ void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo) #if 0 // Tons of debug output... qDebug()<<"========= CppModelManager::updateProjectInfo ======"; - qDebug()<<" for project:"<< pinfo.project.data()->file()->fileName(); - foreach (const ProjectPart::Ptr &part, pinfo.projectParts) { + qDebug()<<" for project:"<< pinfo.project().data()->document()->fileName(); + foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) { qDebug() << "=== part ==="; qDebug() << "language:" << (part->language == CXX ? "C++" : "ObjC++"); - qDebug() << "compilerflags:" << part->flags; + qDebug() << "C++11:" << part->cxx11Enabled; + qDebug() << "Qt version:" << part->qtVersion; qDebug() << "precompiled header:" << part->precompiledHeaders; qDebug() << "defines:" << part->defines; qDebug() << "includes:" << part->includePaths; @@ -980,7 +989,7 @@ QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles if (! sourceFiles.isEmpty() && m_indexerEnabled) { const WorkingCopy workingCopy = buildWorkingCopyList(); - CppPreprocessor *preproc = new CppPreprocessor(this); + CppPreprocessor *preproc = new CppPreprocessor(this, m_dumpFileNameWhileParsing); preproc->setRevision(++m_revision); preproc->setProjectFiles(projectFiles()); preproc->setIncludePaths(includePaths()); @@ -1108,8 +1117,6 @@ void CppModelManager::updateEditor(Document::Ptr doc) blockRanges.append(TextEditor::BaseTextEditorWidget::BlockRange(block.begin(), block.end())); } - QList<QTextEdit::ExtraSelection> selections; - // set up the format for the errors QTextCharFormat errorFormat; errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline); @@ -1120,47 +1127,51 @@ void CppModelManager::updateEditor(Document::Ptr doc) warningFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline); warningFormat.setUnderlineColor(Qt::darkYellow); - QSet<int> lines; - QList<Document::DiagnosticMessage> messages = doc->diagnosticMessages(); - messages += extraDiagnostics(doc->fileName()); - foreach (const Document::DiagnosticMessage &m, messages) { - if (m.fileName() != fileName) - continue; - else if (lines.contains(m.line())) - continue; - - lines.insert(m.line()); - - QTextEdit::ExtraSelection sel; - if (m.isWarning()) - sel.format = warningFormat; - else - sel.format = errorFormat; - - QTextCursor c(ed->document()->findBlockByNumber(m.line() - 1)); - const QString text = c.block().text(); - for (int i = 0; i < text.size(); ++i) { - if (! text.at(i).isSpace()) { - c.setPosition(c.position() + i); - break; - } - } - c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - sel.cursor = c; - sel.format.setToolTip(m.text()); - selections.append(sel); - } - QList<Editor> todo; - foreach (const Editor &e, todo) { + foreach (const Editor &e, m_todo) { if (e.textEditor != textEditor) todo.append(e); } - Editor e; + + if (m_highlightingFactory->hightlighterHandlesDiagnostics()) { + e.updateSelections = false; + } else { + QSet<int> lines; + QList<Document::DiagnosticMessage> messages = doc->diagnosticMessages(); + messages += extraDiagnostics(doc->fileName()); + foreach (const Document::DiagnosticMessage &m, messages) { + if (m.fileName() != fileName) + continue; + else if (lines.contains(m.line())) + continue; + + lines.insert(m.line()); + + QTextEdit::ExtraSelection sel; + if (m.isWarning()) + sel.format = warningFormat; + else + sel.format = errorFormat; + + QTextCursor c(ed->document()->findBlockByNumber(m.line() - 1)); + const QString text = c.block().text(); + for (int i = 0; i < text.size(); ++i) { + if (! text.at(i).isSpace()) { + c.setPosition(c.position() + i); + break; + } + } + c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + sel.cursor = c; + sel.format.setToolTip(m.text()); + e.selections.append(sel); + } + } + + e.revision = ed->document()->revision(); e.textEditor = textEditor; - e.selections = selections; e.ifdefedOutBlocks = blockRanges; todo.append(e); m_todo = todo; @@ -1189,8 +1200,9 @@ void CppModelManager::updateEditorSelections() else if (editor->document()->revision() != ed.revision) continue; // outdated - editor->setExtraSelections(TextEditor::BaseTextEditorWidget::CodeWarningsSelection, - ed.selections); + if (ed.updateSelections) + editor->setExtraSelections(TextEditor::BaseTextEditorWidget::CodeWarningsSelection, + ed.selections); editor->setIfdefedOutBlocks(ed.ifdefedOutBlocks); } diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 7cf4b85685..a661d1bf41 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -35,7 +35,7 @@ #include "cpptools_global.h" #include "cpptoolsconstants.h" -#include <cplusplus/ModelManagerInterface.h> +#include "ModelManagerInterface.h" #ifndef ICHECK_BUILD # include <projectexplorer/project.h> #endif @@ -225,8 +225,11 @@ private: struct Editor { Editor() - : revision(-1) {} + : revision(-1) + , updateSelections(true) + {} int revision; + bool updateSelections; QPointer<TextEditor::ITextEditor> textEditor; QList<QTextEdit::ExtraSelection> selections; QList<TextEditor::BaseTextEditorWidget::BlockRange> ifdefedOutBlocks; @@ -241,6 +244,7 @@ private: CppFindReferences *m_findReferences; bool m_indexerEnabled; + bool m_dumpFileNameWhileParsing; mutable QMutex protectExtraDiagnostics; QHash<QString, QHash<int, QList<CPlusPlus::Document::DiagnosticMessage> > > m_extraDiagnostics; @@ -258,7 +262,7 @@ class CPPTOOLS_EXPORT CppPreprocessor: public CPlusPlus::Client { public: #ifndef ICHECK_BUILD - CppPreprocessor(QPointer<CppModelManager> modelManager); + CppPreprocessor(QPointer<CppModelManager> modelManager, bool dumpFileNameWhileParsing = false); #else CppPreprocessor(QPointer<CPlusPlus::ParseManager> modelManager); #endif @@ -300,7 +304,6 @@ protected: virtual void startExpandingMacro(unsigned offset, const CPlusPlus::Macro ¯o, const QByteArray &originalText, - bool inCondition, const QVector<CPlusPlus::MacroArgumentReference> &actuals); virtual void stopExpandingMacro(unsigned offset, const CPlusPlus::Macro ¯o); virtual void startSkippingBlocks(unsigned offset); @@ -312,6 +315,7 @@ private: #ifndef ICHECK_BUILD QPointer<CppModelManager> m_modelManager; #endif + bool m_dumpFileNameWhileParsing; CPlusPlus::Environment env; CPlusPlus::Preprocessor preprocess; QStringList m_includePaths; diff --git a/src/plugins/cpptools/cpprefactoringchanges.h b/src/plugins/cpptools/cpprefactoringchanges.h index e5612a9a2c..b59a7d48ed 100644 --- a/src/plugins/cpptools/cpprefactoringchanges.h +++ b/src/plugins/cpptools/cpprefactoringchanges.h @@ -34,7 +34,7 @@ #define CPPREFACTORINGCHANGES_H #include <ASTfwd.h> -#include <cplusplus/ModelManagerInterface.h> +#include "ModelManagerInterface.h" #include <cplusplus/CppDocument.h> #include <cplusplus/LookupContext.h> diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index c53c6e8a71..d0a78e7676 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -45,7 +45,9 @@ HEADERS += completionsettingspage.h \ cppchecksymbols.h \ cpplocalsymbols.h \ cppsemanticinfo.h \ - cppcompletionassistprovider.h + cppcompletionassistprovider.h \ + ModelManagerInterface.h \ + TypeHierarchyBuilder.h SOURCES += completionsettingspage.cpp \ cppclassesfilter.cpp \ @@ -82,7 +84,9 @@ SOURCES += completionsettingspage.cpp \ cppchecksymbols.cpp \ cpplocalsymbols.cpp \ cppsemanticinfo.cpp \ - cppcompletionassistprovider.cpp + cppcompletionassistprovider.cpp \ + ModelManagerInterface.cpp \ + TypeHierarchyBuilder.cpp FORMS += completionsettingspage.ui \ cppfilesettingspage.ui \ diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs index 34bd225eae..ad132ef756 100644 --- a/src/plugins/cpptools/cpptools.qbs +++ b/src/plugins/cpptools/cpptools.qbs @@ -100,7 +100,15 @@ QtcPlugin { "uicodecompletionsupport.h", "cppcompletionassistprovider.cpp", "cppcompletionassistprovider.h", - "cppcodestylepreferencesfactory.h" + "cppcodestylepreferencesfactory.h", + "ModelManagerInterface.cpp", + "ModelManagerInterface.h", + "TypeHierarchyBuilder.cpp", + "TypeHierarchyBuilder.h" ] + + ProductModule { + Depends { name: "CPlusPlus" } + } } diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 51319ffc96..b4b167b9a1 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -63,6 +63,7 @@ struct CppFileSettings; class CppToolsPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "CppTools.json") public: CppToolsPlugin(); diff --git a/src/plugins/cpptools/uicodecompletionsupport.h b/src/plugins/cpptools/uicodecompletionsupport.h index ad0495942c..acd8f5f81e 100644 --- a/src/plugins/cpptools/uicodecompletionsupport.h +++ b/src/plugins/cpptools/uicodecompletionsupport.h @@ -37,7 +37,7 @@ #include "cpptools_global.h" #include "abstracteditorsupport.h" -#include <cplusplus/ModelManagerInterface.h> +#include "ModelManagerInterface.h" #include <QDateTime> diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h index f95caff99c..6f077e61a1 100644 --- a/src/plugins/cvs/cvsplugin.h +++ b/src/plugins/cvs/cvsplugin.h @@ -74,6 +74,7 @@ struct CvsResponse class CvsPlugin : public VcsBase::VcsBasePlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "CVS.json") public: CvsPlugin(); diff --git a/src/plugins/debugger/Debugger.pluginspec.in b/src/plugins/debugger/Debugger.pluginspec.in index 1b4327cc0a..77d13834f8 100644 --- a/src/plugins/debugger/Debugger.pluginspec.in +++ b/src/plugins/debugger/Debugger.pluginspec.in @@ -17,6 +17,7 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/> <!-- Debugger plugin adds items to the editor\'s context menu --> <dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\" type=\"optional\"/> </dependencyList> diff --git a/src/plugins/debugger/basewindow.cpp b/src/plugins/debugger/basewindow.cpp index 133dc86be0..92fdcd0d91 100644 --- a/src/plugins/debugger/basewindow.cpp +++ b/src/plugins/debugger/basewindow.cpp @@ -35,116 +35,44 @@ #include "debuggeractions.h" #include "debuggercore.h" +#include <aggregation/aggregate.h> +#include <coreplugin/findplaceholder.h> +#include <find/treeviewfind.h> #include <utils/savedaction.h> -#include <QDebug> -#include <QContextMenuEvent> -#include <QHeaderView> #include <QMenu> +#include <QVBoxLayout> namespace Debugger { namespace Internal { -BaseWindow::BaseWindow(QWidget *parent) - : QTreeView(parent) +BaseTreeView::BaseTreeView(QWidget *parent) + : Utils::BaseTreeView(parent) { QAction *act = debuggerCore()->action(UseAlternatingRowColors); - - setAttribute(Qt::WA_MacShowFocusRect, false); - setFrameStyle(QFrame::NoFrame); setAlternatingRowColors(act->isChecked()); - setRootIsDecorated(false); - setIconSize(QSize(10, 10)); - setSelectionMode(QAbstractItemView::ExtendedSelection); - setUniformRowHeights(true); - - header()->setDefaultAlignment(Qt::AlignLeft); - header()->setClickable(true); - connect(act, SIGNAL(toggled(bool)), - SLOT(setAlternatingRowColorsHelper(bool))); - connect(this, SIGNAL(activated(QModelIndex)), - SLOT(rowActivatedHelper(QModelIndex))); - connect(header(), SIGNAL(sectionClicked(int)), - SLOT(headerSectionClicked(int))); - - m_adjustColumnsAction = new QAction(tr("Adjust Column Widths to Contents"), 0); - m_alwaysAdjustColumnsAction = 0; -} - -void BaseWindow::setAlwaysAdjustColumnsAction(QAction *action) -{ - m_alwaysAdjustColumnsAction = action; - connect(action, SIGNAL(toggled(bool)), - SLOT(setAlwaysResizeColumnsToContents(bool))); + SLOT(setAlternatingRowColorsHelper(bool))); } -void BaseWindow::addBaseContextActions(QMenu *menu) +void BaseTreeView::addBaseContextActions(QMenu *menu) { - menu->addSeparator(); - if (m_alwaysAdjustColumnsAction) - menu->addAction(m_alwaysAdjustColumnsAction); - menu->addAction(m_adjustColumnsAction); - menu->addSeparator(); + Utils::BaseTreeView::addBaseContextActions(menu); menu->addAction(debuggerCore()->action(SettingsDialog)); } -bool BaseWindow::handleBaseContextAction(QAction *act) -{ - if (act == 0) - return true; - if (act == m_adjustColumnsAction) { - resizeColumnsToContents(); - return true; - } - if (act == m_alwaysAdjustColumnsAction) { - if (act->isChecked()) - resizeColumnsToContents(); - // Action triggered automatically. - return true; - } - return false; -} - -void BaseWindow::setModel(QAbstractItemModel *model) -{ - QTreeView::setModel(model); - if (header() && m_alwaysAdjustColumnsAction) - setAlwaysResizeColumnsToContents(m_alwaysAdjustColumnsAction->isChecked()); -} - -void BaseWindow::mousePressEvent(QMouseEvent *ev) -{ - QTreeView::mousePressEvent(ev); - if (!indexAt(ev->pos()).isValid()) - resizeColumnsToContents(); -} - -void BaseWindow::resizeColumnsToContents() -{ - const int columnCount = model()->columnCount(); - for (int c = 0 ; c != columnCount; ++c) - resizeColumnToContents(c); -} - -void BaseWindow::setAlwaysResizeColumnsToContents(bool on) -{ - QHeaderView::ResizeMode mode = on - ? QHeaderView::ResizeToContents : QHeaderView::Interactive; - header()->setResizeMode(0, mode); -} - -void BaseWindow::headerSectionClicked(int logicalIndex) -{ - resizeColumnToContents(logicalIndex); -} - -void BaseWindow::reset() +BaseWindow::BaseWindow(QTreeView *treeView, QWidget *parent) + : QWidget(parent), m_treeView(treeView) { - QTreeView::reset(); - if (header() && m_alwaysAdjustColumnsAction - && m_alwaysAdjustColumnsAction->isChecked()) - resizeColumnsToContents(); + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->setMargin(0); + vbox->setSpacing(0); + vbox->addWidget(m_treeView); + vbox->addWidget(new Core::FindToolBarPlaceHolder(this)); + + Aggregation::Aggregate *agg = new Aggregation::Aggregate; + agg->add(m_treeView); + agg->add(new Find::TreeViewFind(m_treeView)); } } // namespace Internal diff --git a/src/plugins/debugger/basewindow.h b/src/plugins/debugger/basewindow.h index 1592df4202..4a0b95d8b8 100644 --- a/src/plugins/debugger/basewindow.h +++ b/src/plugins/debugger/basewindow.h @@ -33,39 +33,30 @@ #ifndef DEBUGGER_BASEWINDOW_H #define DEBUGGER_BASEWINDOW_H -#include <QTreeView> +#include <utils/basetreeview.h> namespace Debugger { namespace Internal { -class BaseWindow : public QTreeView +class BaseTreeView : public Utils::BaseTreeView { Q_OBJECT public: - BaseWindow(QWidget *parent = 0); - - void setAlwaysAdjustColumnsAction(QAction *action); + explicit BaseTreeView(QWidget *parent = 0); void addBaseContextActions(QMenu *menu); - bool handleBaseContextAction(QAction *action); - - void setModel(QAbstractItemModel *model); - virtual void rowActivated(const QModelIndex &) {} - void mousePressEvent(QMouseEvent *ev); - -public slots: - void resizeColumnsToContents(); - void setAlwaysResizeColumnsToContents(bool on); +}; -private slots: - void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); } - void rowActivatedHelper(const QModelIndex &index) { rowActivated(index); } - void headerSectionClicked(int logicalIndex); - void reset(); +class BaseWindow : public QWidget +{ +public: + explicit BaseWindow(QTreeView *treeView, QWidget *parent = 0); + void setModel(QAbstractItemModel *model) { m_treeView->setModel(model); } + QHeaderView *header() const { return m_treeView->header(); } + QAbstractItemModel *model() const { return m_treeView->model(); } private: - QAction *m_alwaysAdjustColumnsAction; - QAction *m_adjustColumnsAction; + QTreeView *m_treeView; }; } // namespace Internal diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index 699025a18e..63856af81f 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -486,11 +486,9 @@ MultiBreakPointsDialog::MultiBreakPointsDialog(QWidget *parent) : // /////////////////////////////////////////////////////////////////////// -BreakWindow::BreakWindow(QWidget *parent) - : BaseWindow(parent) +BreakTreeView::BreakTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Breakpoints")); - setObjectName(QLatin1String("ThreadsWindow")); setWindowIcon(QIcon(QLatin1String(":/debugger/images/debugger_breakpoints.png"))); setSelectionMode(QAbstractItemView::ExtendedSelection); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustBreakpointsColumnWidths)); @@ -498,12 +496,12 @@ BreakWindow::BreakWindow(QWidget *parent) SIGNAL(toggled(bool)), SLOT(showAddressColumn(bool))); } -void BreakWindow::showAddressColumn(bool on) +void BreakTreeView::showAddressColumn(bool on) { setColumnHidden(7, !on); } -void BreakWindow::keyPressEvent(QKeyEvent *ev) +void BreakTreeView::keyPressEvent(QKeyEvent *ev) { if (ev->key() == Qt::Key_Delete) { QItemSelectionModel *sm = selectionModel(); @@ -519,7 +517,7 @@ void BreakWindow::keyPressEvent(QKeyEvent *ev) QTreeView::keyPressEvent(ev); } -void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev) +void BreakTreeView::mouseDoubleClickEvent(QMouseEvent *ev) { QModelIndex indexUnderMouse = indexAt(ev->pos()); if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4) { @@ -529,16 +527,16 @@ void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev) QTreeView::mouseDoubleClickEvent(ev); } -void BreakWindow::setModel(QAbstractItemModel *model) +void BreakTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); resizeColumnToContents(0); // Number resizeColumnToContents(3); // Line resizeColumnToContents(6); // Ignore count connect(model, SIGNAL(layoutChanged()), this, SLOT(expandAll())); } -void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) +void BreakTreeView::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; QItemSelectionModel *sm = selectionModel(); @@ -654,21 +652,21 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void BreakWindow::setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled) +void BreakTreeView::setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled) { BreakHandler *handler = breakHandler(); foreach (const BreakpointModelId id, ids) handler->setEnabled(id, enabled); } -void BreakWindow::deleteBreakpoints(const BreakpointModelIds &ids) +void BreakTreeView::deleteBreakpoints(const BreakpointModelIds &ids) { BreakHandler *handler = breakHandler(); foreach (const BreakpointModelId id, ids) handler->removeBreakpoint(id); } -void BreakWindow::editBreakpoint(BreakpointModelId id, QWidget *parent) +void BreakTreeView::editBreakpoint(BreakpointModelId id, QWidget *parent) { BreakpointParameters data = breakHandler()->breakpointData(id); BreakpointParts parts = NoParts; @@ -677,7 +675,7 @@ void BreakWindow::editBreakpoint(BreakpointModelId id, QWidget *parent) breakHandler()->changeBreakpointData(id, data, parts); } -void BreakWindow::addBreakpoint() +void BreakTreeView::addBreakpoint() { BreakpointParameters data(BreakpointByFileAndLine); BreakpointParts parts = NoParts; @@ -687,7 +685,7 @@ void BreakWindow::addBreakpoint() breakHandler()->appendBreakpoint(data); } -void BreakWindow::editBreakpoints(const BreakpointModelIds &ids) +void BreakTreeView::editBreakpoints(const BreakpointModelIds &ids) { QTC_ASSERT(!ids.isEmpty(), return); @@ -726,18 +724,24 @@ void BreakWindow::editBreakpoints(const BreakpointModelIds &ids) } } -void BreakWindow::associateBreakpoint(const BreakpointModelIds &ids, int threadId) +void BreakTreeView::associateBreakpoint(const BreakpointModelIds &ids, int threadId) { BreakHandler *handler = breakHandler(); foreach (const BreakpointModelId id, ids) handler->setThreadSpec(id, threadId); } -void BreakWindow::rowActivated(const QModelIndex &index) +void BreakTreeView::rowActivated(const QModelIndex &index) { breakHandler()->gotoLocation(breakHandler()->findBreakpointByIndex(index)); } +BreakWindow::BreakWindow() + : BaseWindow(new BreakTreeView) +{ + setWindowTitle(tr("Breakpoints")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h index 877f3dfcaa..b06055ad10 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -39,12 +39,12 @@ namespace Debugger { namespace Internal { -class BreakWindow : public BaseWindow +class BreakTreeView : public BaseTreeView { Q_OBJECT public: - explicit BreakWindow(QWidget *parent = 0); + explicit BreakTreeView(QWidget *parent = 0); static void editBreakpoint(BreakpointModelId id, QWidget *parent); void setModel(QAbstractItemModel *model); @@ -65,6 +65,12 @@ private: void setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled); }; +class BreakWindow : public BaseWindow +{ +public: + BreakWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index eac6068952..bce3ac1910 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -75,7 +75,7 @@ #include <cplusplus/findcdbbreakpoint.h> #include <cplusplus/CppDocument.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <QCoreApplication> #include <QFileInfo> diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp index 4718a1cc9f..98806c9784 100644 --- a/src/plugins/debugger/commonoptionspage.cpp +++ b/src/plugins/debugger/commonoptionspage.cpp @@ -72,6 +72,8 @@ CommonOptionsPageWidget::CommonOptionsPageWidget m_ui.checkBoxCloseBuffersOnExit); m_group->insert(dc->action(SwitchModeOnExit), m_ui.checkBoxSwitchModeOnExit); + m_group->insert(dc->action(RaiseOnInterrupt), + m_ui.checkBoxBringToForegroundOnInterrrupt); m_group->insert(dc->action(FontSizeFollowsEditor), m_ui.checkBoxFontSizeFollowsEditor); m_group->insert(dc->action(AutoDerefPointers), 0); @@ -120,6 +122,7 @@ QString CommonOptionsPageWidget::searchKeyWords() const << sep << m_ui.checkBoxCloseBuffersOnExit->text() << sep << m_ui.checkBoxSwitchModeOnExit->text() << sep << m_ui.labelMaximalStackDepth->text() + << sep << m_ui.checkBoxBringToForegroundOnInterrrupt->text() ; rc.remove(QLatin1Char('&')); return rc; diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui index 8cf9ae4f0e..b44f2f36cb 100644 --- a/src/plugins/debugger/commonoptionspage.ui +++ b/src/plugins/debugger/commonoptionspage.ui @@ -65,16 +65,6 @@ </property> </widget> </item> - <item row="3" column="0"> - <widget class="QCheckBox" name="checkBoxRegisterForPostMortem"> - <property name="toolTip"> - <string>Register Qt Creator for debugging crashed applications.</string> - </property> - <property name="text"> - <string>Use Qt Creator for post-mortem debugging</string> - </property> - </widget> - </item> <item row="4" column="0"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> @@ -130,6 +120,23 @@ </item> </layout> </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="checkBoxRegisterForPostMortem"> + <property name="toolTip"> + <string>Register Qt Creator for debugging crashed applications.</string> + </property> + <property name="text"> + <string>Use Qt Creator for post-mortem debugging</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBoxBringToForegroundOnInterrrupt"> + <property name="text"> + <string>Bring Qt Creator to foreground when application interrupts</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 0712a37124..ffb0d1842d 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -398,6 +398,12 @@ DebuggerSettings::DebuggerSettings(QSettings *settings) insertItem(SwitchModeOnExit, item); item = new SavedAction(this); + item->setSettingsKey(debugModeGroup, QLatin1String("RaiseOnInterrupt")); + item->setCheckable(true); + item->setDefaultValue(true); + insertItem(RaiseOnInterrupt, item); + + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("AutoQuit")); item->setText(tr("Automatically Quit Debugger")); item->setCheckable(true); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 1bdc34c496..9da4ab1b05 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -100,6 +100,7 @@ enum DebuggerActionCode OperateByInstruction, CloseBuffersOnExit, SwitchModeOnExit, + RaiseOnInterrupt, UseDebuggingHelpers, diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 1367cbeb5b..5925f2df17 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -134,6 +134,12 @@ enum DebuggerStartMode StartRemoteEngine // Start ipc guest engine on other machine }; +enum DebuggerCloseMode +{ + KillAtClose, + DetachAtClose +}; + enum DebuggerCapabilities { ReverseSteppingCapability = 0x1, diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index ab623dee5b..1a53d207c6 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -61,8 +61,8 @@ #include <texteditor/itexteditor.h> #include <texteditor/basetextmark.h> +#include <projectexplorer/projectexplorer.h> #include <projectexplorer/taskhub.h> -#include <extensionsystem/pluginmanager.h> #include <utils/savedaction.h> #include <utils/qtcassert.h> @@ -269,6 +269,8 @@ public slots: m_disassemblerAgent.resetLocation(); } + TaskHub *taskHub(); + public: DebuggerState state() const { return m_state; } RemoteSetupState remoteSetupState() const { return m_remoteSetupState; } @@ -1038,6 +1040,8 @@ void DebuggerEngine::notifyInferiorSpontaneousStop() QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state()); showStatusMessage(tr("Stopped.")); setState(InferiorStopOk); + if (debuggerCore()->boolSetting(RaiseOnInterrupt)) + emit raiseWindow(); } void DebuggerEngine::notifyInferiorStopFailed() @@ -1394,6 +1398,8 @@ void DebuggerEngine::quitDebugger() break; case EngineRunFailed: case DebuggerFinished: + case InferiorExitOk: + case InferiorShutdownOk: break; case InferiorSetupRequested: notifyInferiorSetupFailed(); @@ -1518,6 +1524,7 @@ void DebuggerEngine::updateAll() void DebuggerEngine::attemptBreakpointSynchronization() { + showMessage(_("ATTEMPT BREAKPOINT SYNCHRONIZATION")); if (!stateAcceptsBreakpointChanges()) { showMessage(_("BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE")); return; @@ -1527,8 +1534,14 @@ void DebuggerEngine::attemptBreakpointSynchronization() foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { // Take ownership of the breakpoint. Requests insertion. - if (acceptsBreakpoint(id)) + if (acceptsBreakpoint(id)) { + showMessage(_("TAKING OWNERSHIP OF BREAKPOINT %1 IN STATE %2") + .arg(id.toString()).arg(handler->state(id))); handler->setEngine(id, this); + } else { + showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE") + .arg(id.toString()).arg(handler->state(id))); + } } bool done = true; @@ -1568,8 +1581,12 @@ void DebuggerEngine::attemptBreakpointSynchronization() QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state()); } - if (done) + if (done) { + showMessage(_("BREAKPOINTS ARE SYNCHRONIZED")); d->m_disassemblerAgent.updateBreakpointMarkers(); + } else { + showMessage(_("BREAKPOINTS ARE NOT FULLY SYNCHRONIZED")); + } } void DebuggerEngine::insertBreakpoint(BreakpointModelId id) @@ -1951,15 +1968,23 @@ void DebuggerEnginePrivate::reportTestError(const QString &msg, int line) { m_engine->showMessage(_("### Line %1: %2").arg(line).arg(msg)); m_foundError = true; + Task task(Task::Error, msg, Utils::FileName::fromUserInput(m_testFileName), line + 1, Core::Id("DebuggerTest")); + taskHub()->addTask(task); +} +TaskHub *DebuggerEnginePrivate::taskHub() +{ if (!m_taskHub) { - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - m_taskHub = pm->getObject<TaskHub>(); + m_taskHub = ProjectExplorerPlugin::instance()->taskHub(); + m_taskHub->addCategory(Core::Id("Debuginfo"), tr("Debug Information")); m_taskHub->addCategory(Core::Id("DebuggerTest"), tr("Debugger Test")); } + return m_taskHub; +} - Task task(Task::Error, msg, Utils::FileName::fromUserInput(m_testFileName), line + 1, Core::Id("DebuggerTest")); - m_taskHub->addTask(task); +TaskHub *DebuggerEngine::taskHub() +{ + return d->taskHub(); } } // namespace Debugger diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index f2f133dff1..8665edd954 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -47,13 +47,9 @@ class QMessageBox; class QAbstractItemModel; QT_END_NAMESPACE -namespace TextEditor { -class ITextEditor; -} - -namespace Core { -class IOptionsPage; -} +namespace TextEditor { class ITextEditor; } +namespace Core { class IOptionsPage; } +namespace ProjectExplorer { class TaskHub; } namespace Debugger { @@ -201,6 +197,7 @@ public: virtual void createSnapshot(); virtual void updateAll(); + ProjectExplorer::TaskHub *taskHub(); typedef Internal::BreakpointModelId BreakpointModelId; virtual bool stateAcceptsBreakpointChanges() const { return true; } @@ -289,10 +286,9 @@ public: QString toFileInProject(const QUrl &fileUrl); signals: - void stateChanged(const Debugger::DebuggerState &state); + void stateChanged(Debugger::DebuggerState state); // A new stack frame is on display including locals. void stackFrameCompleted(); - void updateViewsRequested(); /* * For "external" clients of a debugger run control that needs to do * further setup before the debugger is started (e.g. Maemo). @@ -302,6 +298,7 @@ signals: * a server start script should be used, but none is given. */ void requestRemoteSetup(); + void raiseWindow(); protected: // The base notify*() function implementation should be sufficient diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index d5c1102b9e..bce0213b5f 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -32,7 +32,9 @@ #include "debuggermainwindow.h" #include "debuggercore.h" +#include "debuggerengine.h" +#include <utils/appmainwindow.h> #include <utils/styledbar.h> #include <utils/qtcassert.h> #include <utils/fancymainwindow.h> @@ -124,7 +126,8 @@ public: DebuggerLanguages m_supportedLanguages; - QStackedWidget *m_toolBarStack; + QWidget *m_debugToolBar; + QHBoxLayout *m_debugToolBarLayout; QHash<DebuggerLanguage, Context> m_contextsForLanguage; @@ -141,13 +144,16 @@ public: Project *m_previousProject; Target *m_previousTarget; RunConfiguration *m_previousRunConfiguration; + + DebuggerEngine *m_engine; }; DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *mw) : q(mw) , m_resizeEventFilter(this) , m_supportedLanguages(AnyLanguage) - , m_toolBarStack(new QStackedWidget) + , m_debugToolBar(new QWidget) + , m_debugToolBarLayout(new QHBoxLayout(m_debugToolBar)) , m_inDebugMode(false) , m_changingUI(false) , m_previousDebugLanguages(AnyLanguage) @@ -157,8 +163,12 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *mw) , m_previousProject(0) , m_previousTarget(0) , m_previousRunConfiguration(0) + , m_engine(0) { + m_debugToolBarLayout->setMargin(0); + m_debugToolBarLayout->setSpacing(0); createViewsMenuItems(); + addLanguage(AnyLanguage, Context()); addLanguage(CppLanguage, Context(C_CPPDEBUGGER)); addLanguage(QmlLanguage, Context(C_QMLDEBUGGER)); } @@ -271,6 +281,15 @@ DebuggerMainWindow::~DebuggerMainWindow() delete d; } +void DebuggerMainWindow::setCurrentEngine(DebuggerEngine *engine) +{ + if (d->m_engine) + disconnect(d->m_engine, SIGNAL(raiseWindow()), this, SLOT(raiseDebuggerWindow())); + d->m_engine = engine; + if (d->m_engine) + connect(d->m_engine, SIGNAL(raiseWindow()), this, SLOT(raiseDebuggerWindow())); +} + DebuggerLanguages DebuggerMainWindow::activeDebugLanguages() const { return d->m_activeDebugLanguages; @@ -353,8 +372,10 @@ void DebuggerMainWindowPrivate::activateQmlCppLayout() { Context qmlCppContext = m_contextsForLanguage.value(QmlLanguage); qmlCppContext.add(m_contextsForLanguage.value(CppLanguage)); - if (m_toolBars.value(QmlLanguage)) - m_toolBarStack->setCurrentWidget(m_toolBars.value(QmlLanguage)); + if (m_toolBars.value(QmlLanguage)) { + m_toolBars.value(QmlLanguage)->show(); + m_debugToolBarLayout->insertWidget(1, m_toolBars.value(QmlLanguage)); + } if (m_previousDebugLanguages & QmlLanguage) { m_dockWidgetActiveStateQmlCpp = q->saveSettings(); @@ -373,7 +394,10 @@ void DebuggerMainWindowPrivate::activateCppLayout() { Context qmlCppContext = m_contextsForLanguage.value(QmlLanguage); qmlCppContext.add(m_contextsForLanguage.value(CppLanguage)); - m_toolBarStack->setCurrentWidget(m_toolBars.value(CppLanguage)); + if (m_toolBars.value(QmlLanguage)) { + m_toolBars.value(QmlLanguage)->hide(); + m_debugToolBarLayout->removeWidget(m_toolBars.value(QmlLanguage)); + } if (m_previousDebugLanguages & QmlLanguage) { m_dockWidgetActiveStateQmlCpp = q->saveSettings(); @@ -394,7 +418,12 @@ void DebuggerMainWindow::setToolBar(DebuggerLanguage language, QWidget *widget) { Q_ASSERT(d->m_toolBars.contains(language)); d->m_toolBars[language] = widget; - d->m_toolBarStack->addWidget(widget); + if (language == CppLanguage) + d->m_debugToolBarLayout->addWidget(widget); + + //Add widget at the end + if (language == AnyLanguage) + d->m_debugToolBarLayout->insertWidget(-1, widget, 10); } QDockWidget *DebuggerMainWindow::dockWidget(const QString &objectName) const @@ -493,7 +522,7 @@ QWidget *DebuggerMainWindow::createContents(IMode *mode) QHBoxLayout *debugToolBarLayout = new QHBoxLayout(debugToolBar); debugToolBarLayout->setMargin(0); debugToolBarLayout->setSpacing(0); - debugToolBarLayout->addWidget(d->m_toolBarStack); + debugToolBarLayout->addWidget(d->m_debugToolBar); debugToolBarLayout->addWidget(new Utils::StyledSeparator); QDockWidget *dock = new QDockWidget(DebuggerMainWindowPrivate::tr("Debugger Toolbar")); @@ -559,6 +588,14 @@ void DebuggerMainWindow::writeSettings() const settings->endGroup(); } +void DebuggerMainWindow::raiseDebuggerWindow() +{ + Core::ICore *core = Core::ICore::instance(); + Utils::AppMainWindow *appMainWindow = qobject_cast<Utils::AppMainWindow*>(core->mainWindow()); + QTC_ASSERT(appMainWindow, return) + appMainWindow->raiseWindow(); +} + void DebuggerMainWindow::readSettings() { QSettings *settings = ICore::settings(); diff --git a/src/plugins/debugger/debuggermainwindow.h b/src/plugins/debugger/debuggermainwindow.h index a43ee833c5..ed82cbdd72 100644 --- a/src/plugins/debugger/debuggermainwindow.h +++ b/src/plugins/debugger/debuggermainwindow.h @@ -45,6 +45,8 @@ class IMode; namespace Debugger { +class DebuggerEngine; + namespace Internal { class DebuggerMainWindowPrivate; } @@ -57,6 +59,8 @@ public: DebuggerMainWindow(); ~DebuggerMainWindow(); + void setCurrentEngine(DebuggerEngine *engine); + // Debugger toolbars are registered with this function. void setToolBar(DebuggerLanguage language, QWidget *widget); @@ -81,6 +85,9 @@ public: void readSettings(); void writeSettings() const; +private slots: + void raiseDebuggerWindow(); + signals: void activeDebugLanguagesChanged(Debugger::DebuggerLanguages); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 844497c42e..f568d9346c 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -84,7 +84,7 @@ #include <coreplugin/modemanager.h> #include <cppeditor/cppeditorconstants.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <extensionsystem/pluginmanager.h> #include <extensionsystem/invoker.h> @@ -1001,7 +1001,7 @@ public slots: QTC_ASSERT(act, return); const BreakpointModelId id = act->data().value<BreakpointModelId>(); QTC_ASSERT(id > 0, return); - BreakWindow::editBreakpoint(id, mainWindow()); + BreakTreeView::editBreakpoint(id, mainWindow()); } void slotRunToLine() @@ -1169,18 +1169,18 @@ public: Utils::StatusLabel *m_statusLabel; QComboBox *m_threadBox; - BreakWindow *m_breakWindow; + BaseWindow *m_breakWindow; BreakHandler *m_breakHandler; QtMessageLogWindow *m_qtMessageLogWindow; - QTreeView *m_returnWindow; - QTreeView *m_localsWindow; - QTreeView *m_watchersWindow; - QAbstractItemView *m_registerWindow; - QAbstractItemView *m_modulesWindow; - QAbstractItemView *m_snapshotWindow; - SourceFilesWindow *m_sourceFilesWindow; - QAbstractItemView *m_stackWindow; - QAbstractItemView *m_threadsWindow; + WatchWindow *m_returnWindow; + WatchWindow *m_localsWindow; + WatchWindow *m_watchersWindow; + BaseWindow *m_registerWindow; + BaseWindow *m_modulesWindow; + BaseWindow *m_snapshotWindow; + BaseWindow *m_sourceFilesWindow; + BaseWindow *m_stackWindow; + BaseWindow *m_threadsWindow; LogWindow *m_logWindow; bool m_busy; @@ -1339,6 +1339,7 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it, qulonglong pid = it->toULongLong(); if (pid) { sp.startMode = AttachExternal; + sp.closeMode = DetachAtClose; sp.attachPID = pid; sp.displayName = tr("Process %1").arg(sp.attachPID); sp.startMessage = tr("Attaching to local process %1.").arg(sp.attachPID); @@ -1560,6 +1561,7 @@ void DebuggerPluginPrivate::attachExternalApplication() sp.displayName = tr("Process %1").arg(dlg.attachPID()); sp.executable = dlg.executable(); sp.startMode = AttachExternal; + sp.closeMode = DetachAtClose; sp.toolChainAbi = dlg.abi(); sp.debuggerCommand = dlg.debuggerCommand(); if (DebuggerRunControl *rc = createDebugger(sp)) @@ -1572,6 +1574,7 @@ void DebuggerPluginPrivate::attachExternalApplication(RunControl *rc) sp.attachPID = rc->applicationProcessHandle().pid(); sp.displayName = tr("Debugger attached to %1").arg(rc->displayName()); sp.startMode = AttachExternal; + sp.closeMode = DetachAtClose; sp.toolChainAbi = rc->abi(); if (DebuggerRunControl *rc = createDebugger(sp)) startDebugger(rc); @@ -1617,6 +1620,7 @@ void DebuggerPluginPrivate::attachToRemoteServer(const QString &spec) sp.remoteArchitecture = spec.section(QLatin1Char('@'), 2, 2); sp.displayName = tr("Remote: \"%1\"").arg(sp.remoteChannel); sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.toolChainAbi = anyAbiOfBinary(sp.executable); if (DebuggerRunControl *rc = createDebugger(sp)) startDebugger(rc); @@ -1630,6 +1634,7 @@ void DebuggerPluginPrivate::startRemoteCdbSession() sp.toolChainAbi = Abi(hostAbi.architecture(), Abi::WindowsOS, Abi::WindowsMsvc2010Flavor, Abi::PEFormat, hostAbi.wordWidth()); sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; StartRemoteCdbDialog dlg(mainWindow()); QString previousConnection = configValue(connectionKey).toString(); if (previousConnection.isEmpty()) @@ -1666,6 +1671,7 @@ void DebuggerPluginPrivate::attachToRemoteServer() DebuggerStartParameters sp; if (StartRemoteDialog::run(mainWindow(), m_coreSettings, false, &sp)) { sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.useServerStartScript = false; sp.serverStartScript.clear(); if (RunControl *rc = createDebugger(sp)) @@ -1742,6 +1748,7 @@ void DebuggerPluginPrivate::attachedToProcess(const QString &channel, sp.sysroot = sysroot; sp.executable = localExecutable; sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.overrideStartScript.clear(); sp.useServerStartScript = false; sp.serverStartScript.clear(); @@ -1785,6 +1792,7 @@ void DebuggerPluginPrivate::attachToQmlPort() sp.sysroot = dlg.sysroot(); sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.languages = QmlLanguage; // @@ -2114,6 +2122,7 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine) engine->watchHandler()->rebuildModel(); mainWindow()->setEngineDebugLanguages(engine->languages()); + mainWindow()->setCurrentEngine(engine); } static void changeFontSize(QWidget *widget, qreal size) @@ -2332,6 +2341,8 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) m_attachToRemoteServerAction->setEnabled(true); m_attachToRemoteProcessAction->setEnabled(true); + m_threadBox->setEnabled(state == InferiorStopOk); + const bool isCore = engine->startParameters().startMode == AttachCore; const bool stopped = state == InferiorStopOk; const bool detachable = stopped && !isCore; @@ -2897,11 +2908,11 @@ void DebuggerPluginPrivate::extensionsInitialized() m_sourceFilesWindow->setObjectName(QLatin1String(DOCKWIDGET_SOURCE_FILES)); m_threadsWindow = new ThreadsWindow; m_threadsWindow->setObjectName(QLatin1String(DOCKWIDGET_THREADS)); - m_returnWindow = new WatchWindow(WatchWindow::ReturnType); + m_returnWindow = new WatchWindow(WatchTreeView::ReturnType); m_returnWindow->setObjectName(QLatin1String("CppDebugReturn")); - m_localsWindow = new WatchWindow(WatchWindow::LocalsType); + m_localsWindow = new WatchWindow(WatchTreeView::LocalsType); m_localsWindow->setObjectName(QLatin1String("CppDebugLocals")); - m_watchersWindow = new WatchWindow(WatchWindow::WatchersType); + m_watchersWindow = new WatchWindow(WatchTreeView::WatchersType); m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers")); // Snapshot @@ -3446,9 +3457,9 @@ void DebuggerPluginPrivate::extensionsInitialized() hbox->addWidget(m_threadBox); hbox->addSpacerItem(new QSpacerItem(4, 0)); - hbox->addWidget(m_statusLabel, 10); m_mainWindow->setToolBar(CppLanguage, toolbarContainer); + m_mainWindow->setToolBar(AnyLanguage, m_statusLabel); connect(action(EnableReverseDebugging), SIGNAL(valueChanged(QVariant)), diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h index c18f93bbe9..4850459572 100644 --- a/src/plugins/debugger/debuggerplugin.h +++ b/src/plugins/debugger/debuggerplugin.h @@ -53,6 +53,7 @@ class DebuggerStartParameters; class DEBUGGER_EXPORT DebuggerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Debugger.json") public: DebuggerPlugin(); diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index fcb8fc788e..f4296747e4 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -167,9 +167,10 @@ public: QString displayName() const { return tr("Debugger Settings"); } private slots: - void useCppDebuggerToggled(bool toggled); - void useQmlDebuggerToggled(bool toggled); + void useCppDebuggerToggled(bool on); + void useQmlDebuggerToggled(bool on); void qmlDebugServerPortChanged(int port); + void useMultiProcessToggled(bool on); public: DebuggerRunConfigurationAspect *m_aspect; // not owned @@ -179,6 +180,7 @@ public: QSpinBox *m_debugServerPort; QLabel *m_debugServerPortLabel; QLabel *m_qmlDebuggerInfoLabel; + QCheckBox *m_useMultiProcess; }; DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfiguration) @@ -204,6 +206,12 @@ DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfigurat m_debugServerPort->setValue(m_aspect->qmlDebugServerPort()); + static const QByteArray env = qgetenv("QTC_DEBUGGER_MULTIPROCESS"); + m_useMultiProcess = + new QCheckBox(tr("Enable Debugging of Subprocesses"), this); + m_useMultiProcess->setChecked(m_aspect->useMultiProcess()); + m_useMultiProcess->setVisible(env.toInt()); + connect(m_qmlDebuggerInfoLabel, SIGNAL(linkActivated(QString)), Core::HelpManager::instance(), SLOT(handleHelpRequest(QString))); connect(m_useQmlDebugger, SIGNAL(toggled(bool)), @@ -212,6 +220,8 @@ DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfigurat SLOT(useCppDebuggerToggled(bool))); connect(m_debugServerPort, SIGNAL(valueChanged(int)), SLOT(qmlDebugServerPortChanged(int))); + connect(m_useMultiProcess, SIGNAL(toggled(bool)), + SLOT(useMultiProcessToggled(bool))); if (m_aspect->isDisplaySuppressed()) hide(); @@ -242,6 +252,7 @@ DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfigurat layout->setMargin(0); layout->addWidget(m_useCppDebugger); layout->addLayout(qmlLayout); + layout->addWidget(m_useMultiProcess); setLayout(layout); } @@ -250,25 +261,30 @@ void DebuggerRunConfigWidget::qmlDebugServerPortChanged(int port) m_aspect->m_qmlDebugServerPort = port; } -void DebuggerRunConfigWidget::useCppDebuggerToggled(bool toggled) +void DebuggerRunConfigWidget::useCppDebuggerToggled(bool on) { - m_aspect->m_useCppDebugger = toggled; - if (!toggled && !m_useQmlDebugger->isChecked()) + m_aspect->m_useCppDebugger = on; + if (!on && !m_useQmlDebugger->isChecked()) m_useQmlDebugger->setChecked(true); } -void DebuggerRunConfigWidget::useQmlDebuggerToggled(bool toggled) +void DebuggerRunConfigWidget::useQmlDebuggerToggled(bool on) { - m_debugServerPort->setEnabled(toggled); - m_debugServerPortLabel->setEnabled(toggled); + m_debugServerPort->setEnabled(on); + m_debugServerPortLabel->setEnabled(on); - m_aspect->m_useQmlDebugger = toggled + m_aspect->m_useQmlDebugger = on ? DebuggerRunConfigurationAspect::EnableQmlDebugger : DebuggerRunConfigurationAspect::DisableQmlDebugger; - if (!toggled && !m_useCppDebugger->isChecked()) + if (!on && !m_useCppDebugger->isChecked()) m_useCppDebugger->setChecked(true); } +void DebuggerRunConfigWidget::useMultiProcessToggled(bool on) +{ + m_aspect->m_useMultiProcess = on; +} + //////////////////////////////////////////////////////////////////////// // // DebuggerRunControlPrivate @@ -900,12 +916,15 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu } } - if (runConfiguration->debuggerAspect()->useCppDebugger()) + DebuggerRunConfigurationAspect *aspect = runConfiguration->debuggerAspect(); + sp.multiProcess = aspect->useMultiProcess(); + + if (aspect->useCppDebugger()) sp.languages |= CppLanguage; - if (runConfiguration->debuggerAspect()->useQmlDebugger()) { + if (aspect->useQmlDebugger()) { sp.qmlServerAddress = _("127.0.0.1"); - sp.qmlServerPort = runConfiguration->debuggerAspect()->qmlDebugServerPort(); + sp.qmlServerPort = aspect->qmlDebugServerPort(); sp.languages |= QmlLanguage; // Makes sure that all bindings go through the JavaScript engine, so that diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 6c556d222e..513bdea8e1 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -61,13 +61,14 @@ public: attachPID(-1), useTerminal(false), breakOnMain(false), + multiProcess(false), languages(AnyLanguage), qmlServerAddress(QLatin1String("127.0.0.1")), qmlServerPort(ProjectExplorer::Constants::QML_DEFAULT_DEBUG_SERVER_PORT), useServerStartScript(false), - connParams(Utils::SshConnectionParameters::NoProxy), requestRemoteSetup(false), startMode(NoStartMode), + closeMode(KillAtClose), executableUid(0), communicationChannel(CommunicationChannelTcpIp), serverPort(0), @@ -88,6 +89,7 @@ public: qint64 attachPID; bool useTerminal; bool breakOnMain; + bool multiProcess; DebuggerLanguages languages; // Used by AttachCrashedExternal. @@ -126,6 +128,7 @@ public: QString dumperLibrary; QStringList dumperLibraryLocations; DebuggerStartMode startMode; + DebuggerCloseMode closeMode; // For Symbian debugging. quint32 executableUid; diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h index 05410a9d61..51ed0bf5c5 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.h +++ b/src/plugins/debugger/gdb/abstractgdbadapter.h @@ -75,7 +75,6 @@ public: virtual void setupInferior() = 0; virtual void runEngine() = 0; virtual void interruptInferior() = 0; - virtual void shutdownInferior() = 0; virtual void shutdownAdapter() = 0; virtual AbstractGdbProcess *gdbProc() = 0; diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp index 6e1f91f175..28c722a4e0 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.cpp +++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp @@ -116,11 +116,6 @@ void AttachGdbAdapter::interruptInferior() interruptLocalInferior(startParameters().attachPID); } -void AttachGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("detach"); -} - void AttachGdbAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/debugger/gdb/attachgdbadapter.h index 01a6feb9fc..e9a41ac49d 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.h +++ b/src/plugins/debugger/gdb/attachgdbadapter.h @@ -59,7 +59,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); AbstractGdbProcess *gdbProc() { return &m_gdbProc; } diff --git a/src/plugins/debugger/gdb/codagdbadapter.cpp b/src/plugins/debugger/gdb/codagdbadapter.cpp index 1cc5135f5e..1049e4a2f5 100644 --- a/src/plugins/debugger/gdb/codagdbadapter.cpp +++ b/src/plugins/debugger/gdb/codagdbadapter.cpp @@ -1237,11 +1237,6 @@ void CodaGdbAdapter::cleanup() } } -void CodaGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void CodaGdbAdapter::shutdownAdapter() { if (m_gdbProc.state() == QProcess::Running) { diff --git a/src/plugins/debugger/gdb/codagdbadapter.h b/src/plugins/debugger/gdb/codagdbadapter.h index d517cdedaf..56efb451a8 100644 --- a/src/plugins/debugger/gdb/codagdbadapter.h +++ b/src/plugins/debugger/gdb/codagdbadapter.h @@ -114,7 +114,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); void sendRunControlTerminateCommand(); void handleRunControlTerminate(const Coda::CodaCommandResult &); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 6af9fe4049..0b31cef073 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -72,14 +72,18 @@ #include <coreplugin/icore.h> #include <coreplugin/idocument.h> +#include <extensionsystem/pluginmanager.h> #include <projectexplorer/abi.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/taskhub.h> +#include <projectexplorer/itaskhandler.h> #include <texteditor/itexteditor.h> #include <utils/qtcassert.h> #include <QCoreApplication> #include <QDebug> #include <QDir> +#include <QDirIterator> #include <QFileInfo> #include <QMetaObject> #include <QTime> @@ -180,6 +184,52 @@ static QByteArray parsePlainConsoleStream(const GdbResponse &response) /////////////////////////////////////////////////////////////////////// // +// Debuginfo Taskhandler +// +/////////////////////////////////////////////////////////////////////// + +class DebugInfoTask +{ +public: + QString command; +}; + +class DebugInfoTaskHandler : public ProjectExplorer::ITaskHandler +{ +public: + DebugInfoTaskHandler(GdbEngine *engine) + : ITaskHandler(_("Debuginfo")), m_engine(engine) + {} + + bool canHandle(const Task &task) + { + return m_debugInfoTasks.contains(task.taskId); + } + + void handle(const Task &task) + { + m_engine->requestDebugInformation(m_debugInfoTasks.value(task.taskId)); + } + + void addTask(unsigned id, const DebugInfoTask &task) + { + m_debugInfoTasks[id] = task; + } + + QAction *createAction(QObject *parent = 0) + { + QAction *action = new QAction(tr("Install &Debug Information"), parent); + action->setToolTip(tr("This tries to install missing debug information.")); + return action; + } + +private: + GdbEngine *m_engine; + QHash<unsigned, DebugInfoTask> m_debugInfoTasks; +}; + +/////////////////////////////////////////////////////////////////////// +// // GdbEngine // /////////////////////////////////////////////////////////////////////// @@ -217,6 +267,9 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters, m_gdbAdapter = createAdapter(); + m_debugInfoTaskHandler = new DebugInfoTaskHandler(this); + ExtensionSystem::PluginManager::instance()->addObject(m_debugInfoTaskHandler); + m_commandTimer.setSingleShot(true); connect(&m_commandTimer, SIGNAL(timeout()), SLOT(commandTimeout())); @@ -238,6 +291,10 @@ AbstractGdbProcess *GdbEngine::gdbProc() const GdbEngine::~GdbEngine() { + ExtensionSystem::PluginManager::instance()->removeObject(m_debugInfoTaskHandler); + delete m_debugInfoTaskHandler; + m_debugInfoTaskHandler = 0; + // Prevent sending error messages afterwards. if (m_gdbAdapter) disconnect(gdbProc(), 0, this, 0); @@ -422,6 +479,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) } if (pid) notifyInferiorPid(pid); + handleThreadGroupCreated(result); } else if (asyncClass == "thread-created") { //"{id="1",group-id="28902"}" QByteArray id = result.findChild("id").data(); @@ -430,6 +488,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) // Archer has "{id="28902"}" QByteArray id = result.findChild("id").data(); showStatusMessage(tr("Thread group %1 exited").arg(_(id)), 1000); + handleThreadGroupExited(result); } else if (asyncClass == "thread-exited") { //"{id="1",group-id="28902"}" QByteArray id = result.findChild("id").data(); @@ -607,6 +666,34 @@ void GdbEngine::handleResponse(const QByteArray &buff) // version and/or OS version used. if (data.startsWith("warning:")) showMessage(_(data.mid(9)), AppStuff); // Cut "warning: " + + // Messages when the target exits (gdbserver) + if (data.trimmed() == "Remote connection closed" + || data.trimmed() == "Remote communication error. " + "Target disconnected.: No error." + || data.trimmed() == "Quit") { + notifyInferiorExited(); + } + + // From SuSE's gdb: >&"Missing separate debuginfo for ...\n" + // ">&"Try: zypper install -C \"debuginfo(build-id)=c084ee5876ed1ac12730181c9f07c3e027d8e943\"\n" + if (data.startsWith("Missing separate debuginfo for ")) { + m_lastMissingDebugInfo = QString::fromLocal8Bit(data.mid(32)); + } else if (data.startsWith("Try: zypper")) { + QString cmd = QString::fromLocal8Bit(data.mid(4)); + + Task task(Task::Warning, + tr("Missing debug information for %1\nTry: %2") + .arg(m_lastMissingDebugInfo).arg(cmd), + Utils::FileName(), 0, Core::Id("Debuginfo")); + + taskHub()->addTask(task); + + DebugInfoTask dit; + dit.command = cmd; + m_debugInfoTaskHandler->addTask(task.taskId, dit); + } + break; } @@ -1025,10 +1112,6 @@ void GdbEngine::handleResultRecord(GdbResponse *response) QTC_CHECK(state() == InferiorRunOk); notifyInferiorSpontaneousStop(); notifyEngineIll(); - } else if (msg.startsWith("Remote connection closed") - || msg.startsWith("Quit")) { - // Can happen when the target exits (gdbserver) - notifyInferiorExited(); } else { // Windows: Some DLL or some function not found. Report // the exception now in a box. @@ -1171,7 +1254,6 @@ void GdbEngine::updateAll() void GdbEngine::handleQuerySources(const GdbResponse &response) { m_sourcesListUpdating = false; - m_sourcesListOutdated = false; if (response.resultClass == GdbResultDone) { QMap<QString, QString> oldShortToFull = m_shortToFullName; m_shortToFullName.clear(); @@ -1180,16 +1262,17 @@ void GdbEngine::handleQuerySources(const GdbResponse &response) // fullname="/data5/dev/ide/main/bin/dumper/dumper.cpp"}, GdbMi files = response.data.findChild("files"); foreach (const GdbMi &item, files.children()) { - GdbMi fullName = item.findChild("fullname"); GdbMi fileName = item.findChild("file"); + if (fileName.data().endsWith("<built-in>")) + continue; + GdbMi fullName = item.findChild("fullname"); QString file = QString::fromLocal8Bit(fileName.data()); + QString full; if (fullName.isValid()) { - QString full = cleanupFullName(QString::fromLocal8Bit(fullName.data())); - m_shortToFullName[file] = full; + full = cleanupFullName(QString::fromLocal8Bit(fullName.data())); m_fullToShortName[full] = file; - } else if (fileName.isValid()) { - m_shortToFullName[file] = tr("<unknown>"); } + m_shortToFullName[file] = full; } if (m_shortToFullName != oldShortToFull) sourceFilesHandler()->setSourceFiles(m_shortToFullName); @@ -1722,6 +1805,11 @@ void GdbEngine::handleShowVersion(const GdbResponse &response) postCommand("set target-async on", ConsoleCommand); else postCommand("set target-async off", ConsoleCommand); + + if (startParameters().multiProcess) + postCommand("set detach-on-fork off", ConsoleCommand); + + postCommand("set build-id-verbose 2", ConsoleCommand); } } @@ -1846,6 +1934,43 @@ QString GdbEngine::cleanupFullName(const QString &fileName) cleanFilePath.replace(0, startParameters().remoteMountPoint.length(), startParameters().localMountDir); } + + if (!debuggerCore()->boolSetting(AutoEnrichParameters)) + return cleanFilePath; + + const QString sysroot = startParameters().sysroot; + if (QFileInfo(cleanFilePath).isReadable()) + return cleanFilePath; + if (!sysroot.isEmpty() && fileName.startsWith(QLatin1Char('/'))) { + cleanFilePath = sysroot + fileName; + if (QFileInfo(cleanFilePath).isReadable()) + return cleanFilePath; + } + if (m_baseNameToFullName.isEmpty()) { + QString debugSource = sysroot + QLatin1String("/usr/src/debug"); + if (QFileInfo(debugSource).isDir()) { + QDirIterator it(debugSource, QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + QString name = it.fileName(); + if (!name.startsWith(QLatin1Char('.'))) { + QString path = it.filePath(); + m_baseNameToFullName.insert(name, path); + } + } + } + } + + cleanFilePath.clear(); + const QString base = QFileInfo(fileName).fileName(); + + QMap<QString, QString>::const_iterator jt = m_baseNameToFullName.find(base); + while (jt != m_baseNameToFullName.end() && jt.key() == base) { + // FIXME: Use some heuristics to find the "best" match. + return jt.value(); + //++jt; + } + return cleanFilePath; } @@ -1853,13 +1978,15 @@ void GdbEngine::shutdownInferior() { QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); m_commandsToRunOnTemporaryBreak.clear(); - m_gdbAdapter->shutdownInferior(); -} - -void GdbEngine::defaultInferiorShutdown(const char *cmd) -{ - QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); - postCommand(cmd, NeedsStop | LosesChild, CB(handleInferiorShutdown)); + switch (startParameters().closeMode) { + case KillAtClose: + postCommand("kill", NeedsStop | LosesChild, CB(handleInferiorShutdown)); + return; + case DetachAtClose: + postCommand("detach", NeedsStop | LosesChild, CB(handleInferiorShutdown)); + return; + } + QTC_ASSERT(false, notifyInferiorShutdownFailed()); } void GdbEngine::handleInferiorShutdown(const GdbResponse &response) @@ -1946,6 +2073,18 @@ void GdbEngine::handleDetach(const GdbResponse &response) notifyInferiorExited(); } +void GdbEngine::handleThreadGroupCreated(const GdbMi &result) +{ + QByteArray id = result.findChild("id").data(); + QByteArray pid = result.findChild("pid").data(); + Q_UNUSED(pid); +} + +void GdbEngine::handleThreadGroupExited(const GdbMi &result) +{ + QByteArray id = result.findChild("id").data(); +} + int GdbEngine::currentFrame() const { return stackHandler()->currentIndex(); @@ -3372,7 +3511,6 @@ void GdbEngine::examineModules() void GdbEngine::invalidateSourcesList() { m_modulesListOutdated = true; - m_sourcesListOutdated = true; m_breakListOutdated = true; } @@ -5173,6 +5311,11 @@ void GdbEngine::scheduleTestResponse(int testCase, const QByteArray &response) m_scheduledTestResponses[token] = response; } +void GdbEngine::requestDebugInformation(const DebugInfoTask &task) +{ + QProcess::startDetached(task.command); +} + // // Factory // diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 08d4e0b17a..48551cd682 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -57,6 +57,8 @@ namespace Internal { class AbstractGdbAdapter; class AbstractGdbProcess; +class DebugInfoTask; +class DebugInfoTaskHandler; class GdbResponse; class GdbMi; class GdbToolTipContext; @@ -264,7 +266,6 @@ private: ////////// Gdb Process Management ////////// void handleNamespaceExtraction(const GdbResponse &response); void handleAdapterStarted(); - void defaultInferiorShutdown(const char *cmd); void loadInitScript(); void loadPythonDumpers(); void pythonDumpersFailed(); @@ -584,9 +585,9 @@ private: ////////// View & Data Stuff ////////// // awful hack to keep track of used files QMap<QString, QString> m_shortToFullName; QMap<QString, QString> m_fullToShortName; + QMultiMap<QString, QString> m_baseNameToFullName; void invalidateSourcesList(); - bool m_sourcesListOutdated; bool m_sourcesListUpdating; bool m_breakListOutdated; @@ -656,6 +657,9 @@ private: ////////// View & Data Stuff ////////// void handleDebuggingHelperVersionCheckClassic(const GdbResponse &response); void handleDetach(const GdbResponse &response); + void handleThreadGroupCreated(const GdbMi &result); + void handleThreadGroupExited(const GdbMi &result); + Q_SLOT void createFullBacktrace(); void handleCreateFullBacktrace(const GdbResponse &response); @@ -729,6 +733,7 @@ private: ////////// View & Data Stuff ////////// // HACK: QByteArray m_currentThread; QString m_lastWinException; + QString m_lastMissingDebugInfo; BreakpointResponseId m_qFatalBreakpointResponseId; bool m_actingOnExpectedStop; @@ -736,6 +741,11 @@ private: ////////// View & Data Stuff ////////// QHash<int, QByteArray> m_scheduledTestResponses; QSet<int> m_testCases; + + // Debug information + friend class DebugInfoTaskHandler; + void requestDebugInformation(const DebugInfoTask &task); + DebugInfoTaskHandler *m_debugInfoTaskHandler; }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.cpp b/src/plugins/debugger/gdb/localplaingdbadapter.cpp index 0b0060ffa6..1e0ad9ff24 100644 --- a/src/plugins/debugger/gdb/localplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/localplaingdbadapter.cpp @@ -114,11 +114,6 @@ void LocalPlainGdbAdapter::runEngine() AbstractPlainGdbAdapter::runEngine(); } -void LocalPlainGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void LocalPlainGdbAdapter::shutdownAdapter() { showMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state())); diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.h b/src/plugins/debugger/gdb/localplaingdbadapter.h index ced097faac..39181bac7e 100644 --- a/src/plugins/debugger/gdb/localplaingdbadapter.h +++ b/src/plugins/debugger/gdb/localplaingdbadapter.h @@ -58,7 +58,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); DumperHandling dumperHandling() const; diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp index 9cd71bd3a9..174fbb9069 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -233,9 +233,16 @@ void RemoteGdbServerAdapter::handleFileExecAndSymbols(const GdbResponse &respons if (response.resultClass == GdbResultDone) { callTargetRemote(); } else { + QByteArray reason = response.data.findChild("msg").data(); QString msg = tr("Reading debug information failed:\n"); - msg += QString::fromLocal8Bit(response.data.findChild("msg").data()); - m_engine->notifyInferiorSetupFailed(msg); + msg += QString::fromLocal8Bit(reason); + if (reason.endsWith("No such file or directory.")) { + showMessage(_("INFERIOR STARTUP: BINARY NOT FOUND")); + showMessage(msg, StatusBar); + callTargetRemote(); // Proceed nevertheless. + } else { + m_engine->notifyInferiorSetupFailed(msg); + } } } @@ -247,14 +254,24 @@ void RemoteGdbServerAdapter::callTargetRemote() // (1) connects to the gdb server // (2) starts the remote application // (3) stops the remote application (early, e.g. in the dynamic linker) - QString channel = startParameters().remoteChannel; - if (m_engine->m_isQnxGdb) { - m_engine->postCommand("target qnx " + channel.toLatin1(), - CB(handleTargetQnx)); - } else { - m_engine->postCommand("target remote " + channel.toLatin1(), - CB(handleTargetRemote)); + QByteArray channel = startParameters().remoteChannel.toLatin1(); + + // Don't touch channels with explicitly set protocols. + if (!channel.startsWith("tcp:") && !channel.startsWith("udp:") + && !channel.startsWith("file:") && channel.contains(':')) + { + // "Fix" the IPv6 case with host names without '['...']' + if (!channel.startsWith('[') && channel.count(':') >= 2) { + channel.insert(0, '['); + channel.insert(channel.lastIndexOf(':'), ']'); + } + channel = "tcp:" + channel; } + + if (m_engine->m_isQnxGdb) + m_engine->postCommand("target qnx " + channel, CB(handleTargetQnx)); + else + m_engine->postCommand("target remote " + channel, CB(handleTargetRemote)); } void RemoteGdbServerAdapter::handleTargetRemote(const GdbResponse &record) @@ -355,14 +372,6 @@ void RemoteGdbServerAdapter::handleInterruptInferior(const GdbResponse &response } } -void RemoteGdbServerAdapter::shutdownInferior() -{ - if (m_engine->startParameters().startMode == AttachToRemoteServer) - m_engine->defaultInferiorShutdown("detach"); - else - m_engine->defaultInferiorShutdown("kill"); -} - void RemoteGdbServerAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.h b/src/plugins/debugger/gdb/remotegdbserveradapter.h index 9261797d6d..7a3f88d642 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.h +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.h @@ -59,7 +59,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); AbstractGdbProcess *gdbProc() { return &m_gdbProc; } diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp index 5913ade032..a3a7263b14 100644 --- a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp @@ -98,11 +98,6 @@ void RemotePlainGdbAdapter::handleApplicationOutput(const QByteArray &output) showMessage(QString::fromUtf8(output), AppOutput); } -void RemotePlainGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void RemotePlainGdbAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.h b/src/plugins/debugger/gdb/remoteplaingdbadapter.h index b1e7644574..7c19e10df8 100644 --- a/src/plugins/debugger/gdb/remoteplaingdbadapter.h +++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.h @@ -55,7 +55,6 @@ private: void startAdapter(); void setupInferior(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); void handleRemoteSetupDone(int gdbServerPort, int qmlPort); void handleRemoteSetupFailed(const QString &reason); diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp index 8acff6ede4..135630e875 100644 --- a/src/plugins/debugger/gdb/termgdbadapter.cpp +++ b/src/plugins/debugger/gdb/termgdbadapter.cpp @@ -210,11 +210,6 @@ void TermGdbAdapter::stubExited() m_engine->notifyEngineIll(); } -void TermGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void TermGdbAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/termgdbadapter.h b/src/plugins/debugger/gdb/termgdbadapter.h index d9ecee078d..b56d969cd2 100644 --- a/src/plugins/debugger/gdb/termgdbadapter.h +++ b/src/plugins/debugger/gdb/termgdbadapter.h @@ -62,7 +62,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); AbstractGdbProcess *gdbProc() { return &m_gdbProc; } diff --git a/src/plugins/debugger/lldb/ipcenginehost.cpp b/src/plugins/debugger/lldb/ipcenginehost.cpp index 1c6765f4fc..73a01839de 100644 --- a/src/plugins/debugger/lldb/ipcenginehost.cpp +++ b/src/plugins/debugger/lldb/ipcenginehost.cpp @@ -591,7 +591,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) } } -void IPCEngineHost::m_stateChanged(const Debugger::DebuggerState &state) +void IPCEngineHost::m_stateChanged(Debugger::DebuggerState state) { QByteArray p; { diff --git a/src/plugins/debugger/lldb/ipcenginehost.h b/src/plugins/debugger/lldb/ipcenginehost.h index b75e1ceeaa..71756c02f2 100644 --- a/src/plugins/debugger/lldb/ipcenginehost.h +++ b/src/plugins/debugger/lldb/ipcenginehost.h @@ -124,7 +124,7 @@ protected: public slots: void rpcCallback(quint64 f, QByteArray payload = QByteArray()); private slots: - void m_stateChanged(const Debugger::DebuggerState &state); + void m_stateChanged(Debugger::DebuggerState state); void readyRead(); private: IPCEngineGuest *m_localGuest; diff --git a/src/plugins/debugger/moduleswindow.cpp b/src/plugins/debugger/moduleswindow.cpp index 70948ed429..3c7daa1838 100644 --- a/src/plugins/debugger/moduleswindow.cpp +++ b/src/plugins/debugger/moduleswindow.cpp @@ -57,10 +57,9 @@ namespace Debugger { namespace Internal { -ModulesWindow::ModulesWindow(QWidget *parent) - : BaseWindow(parent) +ModulesTreeView::ModulesTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Modules")); setSortingEnabled(true); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustModulesColumnWidths)); @@ -68,7 +67,7 @@ ModulesWindow::ModulesWindow(QWidget *parent) SLOT(moduleActivated(QModelIndex))); } -void ModulesWindow::moduleActivated(const QModelIndex &index) +void ModulesTreeView::moduleActivated(const QModelIndex &index) { DebuggerEngine *engine = debuggerCore()->currentEngine(); QTC_ASSERT(engine, return); @@ -76,7 +75,7 @@ void ModulesWindow::moduleActivated(const QModelIndex &index) engine->gotoLocation(index.sibling(index.row(), 1).data().toString()); } -void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) +void ModulesTreeView::contextMenuEvent(QContextMenuEvent *ev) { QString name; QString fileName; @@ -174,5 +173,11 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } +ModulesWindow::ModulesWindow() + : BaseWindow(new ModulesTreeView) +{ + setWindowTitle(tr("Modules")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/moduleswindow.h b/src/plugins/debugger/moduleswindow.h index 41a8d11ef8..e80ec0823c 100644 --- a/src/plugins/debugger/moduleswindow.h +++ b/src/plugins/debugger/moduleswindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class ModulesWindow : public BaseWindow +class ModulesTreeView : public BaseTreeView { Q_OBJECT public: - explicit ModulesWindow(QWidget *parent = 0); + explicit ModulesTreeView(QWidget *parent = 0); private slots: void moduleActivated(const QModelIndex &index); @@ -52,6 +52,12 @@ private: void contextMenuEvent(QContextMenuEvent *ev); }; +class ModulesWindow : public BaseWindow +{ +public: + ModulesWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp index 7ab699eb19..46d9cdcb9d 100644 --- a/src/plugins/debugger/qml/qmladapter.cpp +++ b/src/plugins/debugger/qml/qmladapter.cpp @@ -67,7 +67,7 @@ public: QWeakPointer<DebuggerEngine> m_engine; QmlDebuggerClient *m_qmlClient; - QmlJsDebugClient::QDeclarativeEngineDebug *m_engineDebugClient; + QmlJsDebugClient::QmlEngineDebugClient *m_engineDebugClient; QTimer m_connectionTimer; QDeclarativeDebugConnection *m_conn; QHash<QString, QmlDebuggerClient*> debugClients; @@ -304,14 +304,24 @@ QHash<QString, Internal::QmlDebuggerClient*> QmlAdapter::debuggerClients() return d->debugClients; } -QmlJsDebugClient::QDeclarativeEngineDebug *QmlAdapter::engineDebugClient() const +QmlJsDebugClient::QmlEngineDebugClient *QmlAdapter::engineDebugClient() const { return d->m_engineDebugClient; } -void QmlAdapter::setEngineDebugClient(QmlJsDebugClient::QDeclarativeEngineDebug *client) +void QmlAdapter::setEngineDebugClient(QmlJsDebugClient::QmlEngineDebugClient *client) { + Internal::QmlEngine *engine = + qobject_cast<Internal::QmlEngine *>(d->m_engine.data()); + if (engine && d->m_engineDebugClient) + disconnect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)), + engine, + SLOT(expressionEvaluated(quint32,QVariant))); d->m_engineDebugClient = client; + if (engine && d->m_engineDebugClient) + connect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)), + engine, + SLOT(expressionEvaluated(quint32,QVariant))); } QmlJsDebugClient::QDebugMessageClient *QmlAdapter::messageClient() const diff --git a/src/plugins/debugger/qml/qmladapter.h b/src/plugins/debugger/qml/qmladapter.h index 9abaf2d5aa..8851518836 100644 --- a/src/plugins/debugger/qml/qmladapter.h +++ b/src/plugins/debugger/qml/qmladapter.h @@ -40,7 +40,7 @@ #include <QAbstractSocket> namespace QmlJsDebugClient { -class QDeclarativeEngineDebug; +class QmlEngineDebugClient; class QDeclarativeDebugConnection; class QDebugMessageClient; } @@ -76,8 +76,8 @@ public: Internal::QmlDebuggerClient *activeDebuggerClient(); QHash<QString, Internal::QmlDebuggerClient*> debuggerClients(); - QmlJsDebugClient::QDeclarativeEngineDebug *engineDebugClient() const; - void setEngineDebugClient(QmlJsDebugClient::QDeclarativeEngineDebug *client); + QmlJsDebugClient::QmlEngineDebugClient *engineDebugClient() const; + void setEngineDebugClient(QmlJsDebugClient::QmlEngineDebugClient *client); QDebugMessageClient *messageClient() const; diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 2ee94881b6..890789fe86 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -40,6 +40,9 @@ #include <coreplugin/icore.h> #include <utils/qtcassert.h> +#include <texteditor/itexteditor.h> +#include <qmljseditor/qmljseditorconstants.h> +#include <cppeditor/cppeditorconstants.h> #include <QTimer> #include <QMainWindow> @@ -127,10 +130,20 @@ QmlCppEngine::~QmlCppEngine() delete d; } +bool QmlCppEngine::canDisplayTooltip() const +{ + return d->m_cppEngine->canDisplayTooltip() || d->m_qmlEngine->canDisplayTooltip(); +} + bool QmlCppEngine::setToolTipExpression(const QPoint & mousePos, TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx) { - return d->m_activeEngine->setToolTipExpression(mousePos, editor, ctx); + bool success = false; + if (editor->id() == CppEditor::Constants::CPPEDITOR_ID) + success = d->m_cppEngine->setToolTipExpression(mousePos, editor, ctx); + else if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) + success = d->m_qmlEngine->setToolTipExpression(mousePos, editor, ctx); + return success; } void QmlCppEngine::updateWatchData(const WatchData &data, @@ -216,9 +229,14 @@ bool QmlCppEngine::hasCapability(unsigned cap) const // ### this could also be an OR of both engines' capabilities bool hasCap = d->m_cppEngine->hasCapability(cap); if (d->m_activeEngine != d->m_cppEngine) { + //Some capabilities cannot be handled by QML Engine + //Expand this list as and when required if (cap == AddWatcherWhileRunningCapability) hasCap = hasCap || d->m_qmlEngine->hasCapability(cap); - if (cap == WatchWidgetsCapability) + if (cap == WatchWidgetsCapability || + cap == DisassemblerCapability || + cap == OperateByInstructionCapability || + cap == ReverseSteppingCapability) hasCap = hasCap && d->m_qmlEngine->hasCapability(cap); } return hasCap; @@ -268,7 +286,7 @@ bool QmlCppEngine::acceptsBreakpoint(BreakpointModelId id) const void QmlCppEngine::selectThread(int index) { - d->m_cppEngine->selectThread(index); + d->m_activeEngine->selectThread(index); } void QmlCppEngine::assignValueInDebugger(const WatchData *data, diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index efddd12f85..7d3483ed0a 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -50,6 +50,7 @@ public: QString *errorMessage); ~QmlCppEngine(); + bool canDisplayTooltip() const; bool setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor * editor, const DebuggerToolTipContext &); void updateWatchData(const WatchData &data, diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index abc050cf4c..f0e6ebc572 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -57,6 +57,7 @@ #include <extensionsystem/pluginmanager.h> #include <projectexplorer/applicationlauncher.h> #include <qmljsdebugclient/qdeclarativeoutputparser.h> +#include <qmljsdebugclient/qmlenginedebugclient.h> #include <qmljseditor/qmljseditorconstants.h> #include <qmljs/parser/qmljsast_p.h> #include <qmljs/qmljsmodelmanagerinterface.h> @@ -119,13 +120,16 @@ private: InteractiveInterpreter m_interpreter; bool m_validContext; QHash<QString,BreakpointModelId> pendingBreakpoints; + QList<quint32> queryIds; bool m_retryOnConnectFail; + bool m_automaticConnect; }; QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) : m_adapter(q), m_validContext(false), - m_retryOnConnectFail(false) + m_retryOnConnectFail(false), + m_automaticConnect(false) {} class ASTWalker: public Visitor @@ -367,6 +371,7 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters, if (startParameters.useTerminal) { d->m_noDebugOutputTimer.setInterval(0); d->m_retryOnConnectFail = true; + d->m_automaticConnect = true; } } @@ -397,6 +402,9 @@ void QmlEngine::setupInferior() QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); notifyInferiorSetupOk(); + + if (d->m_automaticConnect) + beginConnection(); } void QmlEngine::appendMessage(const QString &msg, Utils::OutputFormat /* format */) @@ -421,12 +429,22 @@ void QmlEngine::tryToConnect(quint16 port) { showMessage(QLatin1String("QML Debugger: No application output received in time, trying to connect ..."), LogStatus); d->m_retryOnConnectFail = true; - beginConnection(port); + if (state() == EngineRunRequested + && !d->m_automaticConnect) + beginConnection(port); + else + d->m_automaticConnect = true; } void QmlEngine::beginConnection(quint16 port) { d->m_noDebugOutputTimer.stop(); + + if (state() != EngineRunRequested && d->m_retryOnConnectFail) + return; + + QTC_ASSERT(state() == EngineRunRequested, return) + if (port > 0) { QTC_CHECK(startParameters().communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp); @@ -1038,23 +1056,15 @@ void QmlEngine::synchronizeWatchers() } } -void QmlEngine::onDebugQueryStateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery::State state) +void QmlEngine::expressionEvaluated(quint32 queryId, const QVariant &result) { - QmlJsDebugClient::QDeclarativeDebugExpressionQuery *query = - qobject_cast<QmlJsDebugClient::QDeclarativeDebugExpressionQuery *>( - sender()); - if (query && state != QmlJsDebugClient::QDeclarativeDebugQuery::Error) { + if (d->queryIds.contains(queryId)) { + d->queryIds.removeOne(queryId); QtMessageLogItem *item = constructLogItemTree(qtMessageLogHandler()->root(), - query->result()); + result); if (item) qtMessageLogHandler()->appendItem(item); - } else - qtMessageLogHandler()-> - appendItem(new QtMessageLogItem(qtMessageLogHandler()->root(), - QtMessageLogHandler::ErrorType, - _("Error evaluating expression."))); - delete query; + } } bool QmlEngine::hasCapability(unsigned cap) const @@ -1152,21 +1162,25 @@ bool QmlEngine::evaluateScriptExpression(const QString& expression) //is sent to V8DebugService. In all other cases, the //expression is evaluated by QDeclarativeEngine. if (state() != InferiorStopOk) { - QDeclarativeEngineDebug *engineDebug = + QmlEngineDebugClient *engineDebug = d->m_adapter.engineDebugClient(); int id = d->m_adapter.currentSelectedDebugId(); if (engineDebug && id != -1) { - QDeclarativeDebugExpressionQuery *query = - engineDebug->queryExpressionResult(id, expression); - connect(query, - SIGNAL(stateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery - ::State)), - this, - SLOT(onDebugQueryStateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery - ::State))); + quint32 queryId = + engineDebug->queryExpressionResult( + id, expression); + if (queryId) { + d->queryIds << queryId; + } else { + didEvaluate = false; + qtMessageLogHandler()-> + appendItem( + new QtMessageLogItem( + qtMessageLogHandler()->root(), + QtMessageLogHandler::ErrorType, + _("Error evaluating expression."))); + } } } else { executeDebuggerCommand(expression); diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 3f285da4a3..5a4876b39c 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -34,7 +34,6 @@ #define DEBUGGER_QMLENGINE_H #include "debuggerengine.h" -#include <qmljsdebugclient/qdeclarativeenginedebug.h> #include <qmljsdebugclient/qdebugmessageclient.h> #include <utils/outputformat.h> #include <qmljs/qmljsdocument.h> @@ -58,7 +57,7 @@ namespace Internal { class QtMessageLogItem; class QmlEnginePrivate; -class QmlEngine : public DebuggerEngine +class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine { Q_OBJECT @@ -96,6 +95,7 @@ public: public slots: void disconnected(); void documentUpdated(QmlJS::Document::Ptr doc); + void expressionEvaluated(quint32 queryId, const QVariant &result); private slots: void errorMessageBoxFinished(int result); @@ -171,8 +171,6 @@ private slots: void appendMessage(const QString &msg, Utils::OutputFormat); void synchronizeWatchers(); - void onDebugQueryStateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery::State state); private: void closeConnection(); diff --git a/src/plugins/debugger/qml/qmljsprivateapi.h b/src/plugins/debugger/qml/qmljsprivateapi.h index a8654ba926..003938c548 100644 --- a/src/plugins/debugger/qml/qmljsprivateapi.h +++ b/src/plugins/debugger/qml/qmljsprivateapi.h @@ -32,8 +32,10 @@ #ifndef QMLJSPRIVATEAPI_H #define QMLJSPRIVATEAPI_H -#include <qmljsdebugclient/qdeclarativeenginedebug.h> +#include <qmljsdebugclient/qmlenginedebugclient.h> #include <qmljsdebugclient/qdeclarativedebugclient.h> +#include <qmljsdebugclient/qdeclarativeengineclient.h> +#include <qmljsdebugclient/qmldebuggerclient.h> using namespace QmlJsDebugClient; diff --git a/src/plugins/debugger/qtmessagelogeditor.cpp b/src/plugins/debugger/qtmessagelogeditor.cpp index 62e3fdf821..cb198077d0 100644 --- a/src/plugins/debugger/qtmessagelogeditor.cpp +++ b/src/plugins/debugger/qtmessagelogeditor.cpp @@ -67,6 +67,7 @@ QtMessageLogEditor::QtMessageLogEditor(const QModelIndex &index, format.setName(_("prompt")); format.setHeight(9); format.setWidth(9); + textCursor().insertText(_(" ")); textCursor().insertImage(format); textCursor().insertText(_(" ")); m_startOfEditableArea = textCursor().position(); diff --git a/src/plugins/debugger/qtmessagelogitemdelegate.h b/src/plugins/debugger/qtmessagelogitemdelegate.h index 7d35f50727..ffb76d85e2 100644 --- a/src/plugins/debugger/qtmessagelogitemdelegate.h +++ b/src/plugins/debugger/qtmessagelogitemdelegate.h @@ -180,7 +180,7 @@ private: public: static const int TASK_ICON_SIZE = 16; - static const int ITEM_PADDING = 7; + static const int ITEM_PADDING = 8; static const int ITEM_SPACING = 4; }; diff --git a/src/plugins/debugger/qtmessagelogwindow.cpp b/src/plugins/debugger/qtmessagelogwindow.cpp index 3be4b73af6..5a0a5d4e96 100644 --- a/src/plugins/debugger/qtmessagelogwindow.cpp +++ b/src/plugins/debugger/qtmessagelogwindow.cpp @@ -79,18 +79,17 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) vbox->setMargin(0); vbox->setSpacing(0); - QWidget *statusbarContainer = new QWidget(); + QWidget *statusbarContainer = new Utils::StyledBar(); statusbarContainer->setFixedHeight(statusBarHeight); QHBoxLayout *hbox = new QHBoxLayout(statusbarContainer); hbox->setMargin(0); + hbox->setSpacing(5); + hbox->addSpacing(5); - const int spacing = 7; //Status Label m_statusLabel = new Utils::StatusLabel; - hbox->addSpacing(spacing); hbox->addWidget(m_statusLabel); hbox->addWidget(new Utils::StyledSeparator); - hbox->addSpacing(spacing); const int buttonWidth = 25; //Filters @@ -105,7 +104,6 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_showLogAction->setIcon(QIcon(_(":/debugger/images/log.png"))); button->setDefaultAction(m_showLogAction); hbox->addWidget(button); - hbox->addSpacing(spacing); button = new QToolButton(this); button->setAutoRaise(true); @@ -118,7 +116,6 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_showWarningAction->setIcon(QIcon(_(":/debugger/images/warning.png"))); button->setDefaultAction(m_showWarningAction); hbox->addWidget(button); - hbox->addSpacing(spacing); button = new QToolButton(this); button->setAutoRaise(true); @@ -131,7 +128,7 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_showErrorAction->setIcon(QIcon(_(":/debugger/images/error.png"))); button->setDefaultAction(m_showErrorAction); hbox->addWidget(button); - hbox->addSpacing(spacing); + hbox->addWidget(new Utils::StyledSeparator); //Clear Button button = new QToolButton; @@ -141,7 +138,7 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_clearAction->setIcon(QIcon(_(Core::Constants::ICON_CLEAN_PANE))); button->setDefaultAction(m_clearAction); hbox->addWidget(button); - hbox->addSpacing(spacing); + hbox->addWidget(new Utils::StyledSeparator); m_treeView = new QtMessageLogView(this); m_treeView->setSizePolicy(QSizePolicy::MinimumExpanding, diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp index 37608353bd..bf796bb43d 100644 --- a/src/plugins/debugger/registerwindow.cpp +++ b/src/plugins/debugger/registerwindow.cpp @@ -163,16 +163,13 @@ public: // /////////////////////////////////////////////////////////////////////// -RegisterWindow::RegisterWindow(QWidget *parent) - : BaseWindow(parent) +RegisterTreeView::RegisterTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Registers")); - setAlwaysAdjustColumnsAction(debuggerCore()->action(UseAlternatingRowColors)); setItemDelegate(new RegisterDelegate(this)); - setObjectName(QLatin1String("RegisterWindow")); } -void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) +void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; @@ -271,11 +268,17 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void RegisterWindow::reloadRegisters() +void RegisterTreeView::reloadRegisters() { // FIXME: Only trigger when becoming visible? currentEngine()->reloadRegisters(); } +RegisterWindow::RegisterWindow() + : BaseWindow(new RegisterTreeView) +{ + setWindowTitle(tr("Registers")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h index 8a7253f62e..c6c9e587c4 100644 --- a/src/plugins/debugger/registerwindow.h +++ b/src/plugins/debugger/registerwindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class RegisterWindow : public BaseWindow +class RegisterTreeView : public BaseTreeView { Q_OBJECT public: - explicit RegisterWindow(QWidget *parent = 0); + explicit RegisterTreeView(QWidget *parent = 0); public slots: void reloadRegisters(); @@ -52,6 +52,12 @@ private: void contextMenuEvent(QContextMenuEvent *ev); }; +class RegisterWindow : public BaseWindow +{ +public: + RegisterWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/snapshotwindow.cpp b/src/plugins/debugger/snapshotwindow.cpp index e29b7c6b2e..ebdc9ca0da 100644 --- a/src/plugins/debugger/snapshotwindow.cpp +++ b/src/plugins/debugger/snapshotwindow.cpp @@ -56,19 +56,19 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -SnapshotWindow::SnapshotWindow(SnapshotHandler *handler) +SnapshotTreeView::SnapshotTreeView(SnapshotHandler *handler) { m_snapshotHandler = handler; setWindowTitle(tr("Snapshots")); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustSnapshotsColumnWidths)); } -void SnapshotWindow::rowActivated(const QModelIndex &index) +void SnapshotTreeView::rowActivated(const QModelIndex &index) { m_snapshotHandler->activateSnapshot(index.row()); } -void SnapshotWindow::keyPressEvent(QKeyEvent *ev) +void SnapshotTreeView::keyPressEvent(QKeyEvent *ev) { if (ev->key() == Qt::Key_Delete) { QItemSelectionModel *sm = selectionModel(); @@ -84,7 +84,7 @@ void SnapshotWindow::keyPressEvent(QKeyEvent *ev) QTreeView::keyPressEvent(ev); } -void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev) +void SnapshotTreeView::contextMenuEvent(QContextMenuEvent *ev) { QModelIndex idx = indexAt(ev->pos()); @@ -109,7 +109,7 @@ void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void SnapshotWindow::removeSnapshot(int i) +void SnapshotTreeView::removeSnapshot(int i) { m_snapshotHandler->at(i)->quitDebugger(); } diff --git a/src/plugins/debugger/snapshotwindow.h b/src/plugins/debugger/snapshotwindow.h index 69c1c5df2b..302f4fd830 100644 --- a/src/plugins/debugger/snapshotwindow.h +++ b/src/plugins/debugger/snapshotwindow.h @@ -40,12 +40,12 @@ namespace Internal { class SnapshotHandler; -class SnapshotWindow : public BaseWindow +class SnapshotTreeView : public BaseTreeView { Q_OBJECT public: - explicit SnapshotWindow(SnapshotHandler *handler); + explicit SnapshotTreeView(SnapshotHandler *handler); private: void rowActivated(const QModelIndex &index); @@ -56,6 +56,16 @@ private: SnapshotHandler *m_snapshotHandler; }; +class SnapshotWindow : public BaseWindow +{ +public: + explicit SnapshotWindow(SnapshotHandler *handler) + : BaseWindow(new SnapshotTreeView(handler)) + { + setWindowTitle(tr("Snapshots")); + } +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/sourcefileswindow.cpp b/src/plugins/debugger/sourcefileswindow.cpp index e950ef4665..78c623ee84 100644 --- a/src/plugins/debugger/sourcefileswindow.cpp +++ b/src/plugins/debugger/sourcefileswindow.cpp @@ -56,21 +56,20 @@ namespace Debugger { namespace Internal { -SourceFilesWindow::SourceFilesWindow(QWidget *parent) - : BaseWindow(parent) +SourceFilesTreeView::SourceFilesTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Source Files")); setSortingEnabled(true); } -void SourceFilesWindow::rowActivated(const QModelIndex &index) +void SourceFilesTreeView::rowActivated(const QModelIndex &index) { DebuggerEngine *engine = debuggerCore()->currentEngine(); QTC_ASSERT(engine, return); engine->gotoLocation(index.data().toString()); } -void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) +void SourceFilesTreeView::contextMenuEvent(QContextMenuEvent *ev) { DebuggerEngine *engine = debuggerCore()->currentEngine(); QTC_ASSERT(engine, return); @@ -107,6 +106,12 @@ void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } +SourceFilesWindow::SourceFilesWindow() + : BaseWindow(new SourceFilesTreeView) +{ + setWindowTitle(tr("Source Files")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/sourcefileswindow.h b/src/plugins/debugger/sourcefileswindow.h index 8f150febfe..23088ec6fc 100644 --- a/src/plugins/debugger/sourcefileswindow.h +++ b/src/plugins/debugger/sourcefileswindow.h @@ -38,18 +38,24 @@ namespace Debugger { namespace Internal { -class SourceFilesWindow : public BaseWindow +class SourceFilesTreeView : public BaseTreeView { Q_OBJECT public: - SourceFilesWindow(QWidget *parent = 0); + SourceFilesTreeView(QWidget *parent = 0); private: void rowActivated(const QModelIndex &index); void contextMenuEvent(QContextMenuEvent *ev); }; +class SourceFilesWindow : public BaseWindow +{ +public: + SourceFilesWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/stackframe.cpp b/src/plugins/debugger/stackframe.cpp index 6c4fdbb62a..09841a7769 100644 --- a/src/plugins/debugger/stackframe.cpp +++ b/src/plugins/debugger/stackframe.cpp @@ -106,7 +106,26 @@ QString StackFrame::toToolTip() const str << "<tr><td>" << tr("From:") << "</td><td>" << from << "</td></tr>"; if (!to.isEmpty()) str << "<tr><td>" << tr("To:") << "</td><td>" << to << "</td></tr>"; - str << "</table></body></html>"; + str << "</table>"; + + str <<"<br> <br><i>" << tr("Note:") << " </i> "; + if (isUsable()) { + str << tr("Sources for this frame are available.<br>Double-click on " + "the file name to open an editor."); + } else if (line <= 0) { + str << tr("Binary debug information is not accessible for this " + "frame. This either means the core was not compiled " + "with debug information, or the debug information is not " + "accessible. Note that most distributions ship debug information " + "in separate packages."); + } else { + str << tr("Binary debug information is accessible for this " + "frame. However, matching sources have not been found. " + "Note that some distributions ship debug sources in " + "in separate packages."); + } + + str << "</body></html>"; return res; } diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index 04efb34b3c..674aa8709c 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -109,7 +109,7 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const case 2: // File name return frame.file.isEmpty() ? frame.from : QFileInfo(frame.file).fileName(); case 3: // Line number - return frame.line >= 0 ? QVariant(frame.line) : QVariant(); + return frame.line > 0 ? QVariant(frame.line) : QVariant(); case 4: // Address if (frame.address) return QString::fromLatin1("0x%1").arg(frame.address, 0, 16); diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp index cd70765e58..cf8a59d6ca 100644 --- a/src/plugins/debugger/stackwindow.cpp +++ b/src/plugins/debugger/stackwindow.cpp @@ -59,8 +59,8 @@ static DebuggerEngine *currentEngine() return debuggerCore()->currentEngine(); } -StackWindow::StackWindow(QWidget *parent) - : BaseWindow(parent) +StackTreeView::StackTreeView(QWidget *parent) + : BaseTreeView(parent) { setWindowTitle(tr("Stack")); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustStackColumnWidths)); @@ -74,19 +74,19 @@ StackWindow::StackWindow(QWidget *parent) showAddressColumn(false); } -void StackWindow::showAddressColumn(bool on) +void StackTreeView::showAddressColumn(bool on) { setColumnHidden(4, !on); } -void StackWindow::rowActivated(const QModelIndex &index) +void StackTreeView::rowActivated(const QModelIndex &index) { currentEngine()->activateFrame(index.row()); } -void StackWindow::setModel(QAbstractItemModel *model) +void StackTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); resizeColumnToContents(0); resizeColumnToContents(3); showAddressColumn(debuggerCore()->action(UseAddressInStackView)->isChecked()); @@ -100,8 +100,8 @@ static inline StackFrame inputFunctionForDisassembly() StackFrame frame; QInputDialog dialog; dialog.setInputMode(QInputDialog::TextInput); - dialog.setLabelText(StackWindow::tr("Function:")); - dialog.setWindowTitle(StackWindow::tr("Disassemble Function")); + dialog.setLabelText(StackTreeView::tr("Function:")); + dialog.setWindowTitle(StackTreeView::tr("Disassemble Function")); dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); if (dialog.exec() != QDialog::Accepted) return frame; @@ -119,7 +119,7 @@ static inline StackFrame inputFunctionForDisassembly() return frame; } -void StackWindow::contextMenuEvent(QContextMenuEvent *ev) +void StackTreeView::contextMenuEvent(QContextMenuEvent *ev) { DebuggerEngine *engine = currentEngine(); StackHandler *handler = engine->stackHandler(); @@ -213,7 +213,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void StackWindow::copyContentsToClipboard() +void StackTreeView::copyContentsToClipboard() { QString str; int n = model()->rowCount(); @@ -233,7 +233,7 @@ void StackWindow::copyContentsToClipboard() clipboard->setText(str, QClipboard::Clipboard); } -void StackWindow::reloadFullStack() +void StackTreeView::reloadFullStack() { currentEngine()->reloadFullStack(); } diff --git a/src/plugins/debugger/stackwindow.h b/src/plugins/debugger/stackwindow.h index 1e7e73b942..239c043c0d 100644 --- a/src/plugins/debugger/stackwindow.h +++ b/src/plugins/debugger/stackwindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class StackWindow : public BaseWindow +class StackTreeView : public BaseTreeView { Q_OBJECT public: - explicit StackWindow(QWidget *parent = 0); + explicit StackTreeView(QWidget *parent = 0); private slots: void showAddressColumn(bool on); @@ -56,6 +56,15 @@ private: void copyContentsToClipboard(); }; +class StackWindow : public BaseWindow +{ +public: + StackWindow() : BaseWindow(new StackTreeView) + { + setWindowTitle(tr("Stack")); + } +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/threadswindow.cpp b/src/plugins/debugger/threadswindow.cpp index d3065fa0ab..fb24b612ef 100644 --- a/src/plugins/debugger/threadswindow.cpp +++ b/src/plugins/debugger/threadswindow.cpp @@ -48,23 +48,20 @@ namespace Debugger { namespace Internal { -ThreadsWindow::ThreadsWindow(QWidget *parent) - : BaseWindow(parent) +ThreadsTreeView::ThreadsTreeView() { - setWindowTitle(tr("Thread")); setSortingEnabled(true); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustThreadsColumnWidths)); - setObjectName(QLatin1String("ThreadsWindow")); } -void ThreadsWindow::rowActivated(const QModelIndex &index) +void ThreadsTreeView::rowActivated(const QModelIndex &index) { debuggerCore()->currentEngine()->selectThread(index.row()); } -void ThreadsWindow::setModel(QAbstractItemModel *model) +void ThreadsTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); resizeColumnToContents(ThreadData::IdColumn); resizeColumnToContents(ThreadData::LineColumn); resizeColumnToContents(ThreadData::NameColumn); @@ -72,7 +69,7 @@ void ThreadsWindow::setModel(QAbstractItemModel *model) resizeColumnToContents(ThreadData::TargetIdColumn); } -void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) +void ThreadsTreeView::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; addBaseContextActions(&menu); @@ -80,5 +77,12 @@ void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } +ThreadsWindow::ThreadsWindow() + : BaseWindow(new ThreadsTreeView) +{ + setWindowTitle(tr("Threads")); + setObjectName(QLatin1String("ThreadsWindow")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/threadswindow.h b/src/plugins/debugger/threadswindow.h index 9681c5ae04..15e1e152a6 100644 --- a/src/plugins/debugger/threadswindow.h +++ b/src/plugins/debugger/threadswindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class ThreadsWindow : public BaseWindow +class ThreadsTreeView : public BaseTreeView { Q_OBJECT public: - ThreadsWindow(QWidget *parent = 0); + ThreadsTreeView(); private: void rowActivated(const QModelIndex &index); @@ -51,6 +51,12 @@ private: void contextMenuEvent(QContextMenuEvent *ev); }; +class ThreadsWindow : public BaseWindow +{ +public: + ThreadsWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index d95834e481..317a4887bc 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -47,7 +47,7 @@ #include <cpptools/cpptoolsconstants.h> #include <cpptools/abstracteditorsupport.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/Overview.h> #include <Symbols.h> diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 0350bb03e4..7379c02915 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -83,7 +83,7 @@ static DebuggerEngine *currentEngine() class WatchDelegate : public QItemDelegate { public: - explicit WatchDelegate(WatchWindow *parent) + explicit WatchDelegate(WatchTreeView *parent) : QItemDelegate(parent), m_watchWindow(parent) {} @@ -142,7 +142,7 @@ public: } private: - WatchWindow *m_watchWindow; + WatchTreeView *m_watchWindow; }; // Watch model query helpers. @@ -199,10 +199,10 @@ static QString variableToolTip(const QString &name, const QString &type, { return offset ? //: HTML tooltip of a variable in the memory editor - WatchWindow::tr("<i>%1</i> %2 at #%3"). + WatchTreeView::tr("<i>%1</i> %2 at #%3"). arg(type, name).arg(offset) : //: HTML tooltip of a variable in the memory editor - WatchWindow::tr("<i>%1</i> %2").arg(type, name); + WatchTreeView::tr("<i>%1</i> %2").arg(type, name); } static int memberVariableRecursion(const QAbstractItemModel *model, @@ -318,7 +318,7 @@ static MemoryMarkupList const quint64 offset = it.key() - address; if (offset < size) { ranges[offset] = ColorNumberToolTip(registerColorNumber, - WatchWindow::tr("Register <i>%1</i>").arg(it.value())); + WatchTreeView::tr("Register <i>%1</i>").arg(it.value())); } else { break; // Sorted. } @@ -406,9 +406,9 @@ static void addVariableMemoryView(DebuggerEngine *engine, bool separateView, const unsigned flags = separateView ? DebuggerEngine::MemoryView|DebuggerEngine::MemoryReadOnly : 0; const QString title = deferencePointer - ? WatchWindow::tr("Memory Referenced by Pointer \"%1\" (0x%2)") + ? WatchTreeView::tr("Memory Referenced by Pointer \"%1\" (0x%2)") .arg(nameOf(m)).arg(address, 0, 16) - : WatchWindow::tr("Memory at Variable \"%1\" (0x%2)") + : WatchTreeView::tr("Memory at Variable \"%1\" (0x%2)") .arg(nameOf(m)).arg(address, 0, 16); engine->openMemoryView(address, flags, markup, p, title, parent); } @@ -443,8 +443,8 @@ static void addStackLayoutMemoryView(DebuggerEngine *engine, bool separateView, // Anything found and everything in a sensible range (static data in-between)? if (end <= start || end - start > 100 * 1024) { QMessageBox::information(parent, - WatchWindow::tr("Cannot Display Stack Layout"), - WatchWindow::tr("Could not determine a suitable address range.")); + WatchTreeView::tr("Cannot Display Stack Layout"), + WatchTreeView::tr("Could not determine a suitable address range.")); return; } // Take a look at the register values. Extend the range a bit if suitable @@ -468,7 +468,7 @@ static void addStackLayoutMemoryView(DebuggerEngine *engine, bool separateView, const unsigned flags = separateView ? (DebuggerEngine::MemoryView|DebuggerEngine::MemoryReadOnly) : 0; const QString title = - WatchWindow::tr("Memory Layout of Local Variables at 0x%1").arg(start, 0, 16); + WatchTreeView::tr("Memory Layout of Local Variables at 0x%1").arg(start, 0, 16); engine->openMemoryView(start, flags, markup, p, title, parent); } @@ -478,8 +478,8 @@ static void addStackLayoutMemoryView(DebuggerEngine *engine, bool separateView, // ///////////////////////////////////////////////////////////////////// -WatchWindow::WatchWindow(Type type, QWidget *parent) - : BaseWindow(parent), +WatchTreeView::WatchTreeView(Type type, QWidget *parent) + : BaseTreeView(parent), m_type(type) { setObjectName(QLatin1String("WatchWindow")); @@ -499,17 +499,17 @@ WatchWindow::WatchWindow(Type type, QWidget *parent) SLOT(collapseNode(QModelIndex))); } -void WatchWindow::expandNode(const QModelIndex &idx) +void WatchTreeView::expandNode(const QModelIndex &idx) { setModelData(LocalsExpandedRole, true, idx); } -void WatchWindow::collapseNode(const QModelIndex &idx) +void WatchTreeView::collapseNode(const QModelIndex &idx) { setModelData(LocalsExpandedRole, false, idx); } -void WatchWindow::keyPressEvent(QKeyEvent *ev) +void WatchTreeView::keyPressEvent(QKeyEvent *ev) { if (ev->key() == Qt::Key_Delete && m_type == WatchersType) { QModelIndexList indices = selectionModel()->selectedRows(); @@ -533,7 +533,7 @@ void WatchWindow::keyPressEvent(QKeyEvent *ev) QTreeView::keyPressEvent(ev); } -void WatchWindow::dragEnterEvent(QDragEnterEvent *ev) +void WatchTreeView::dragEnterEvent(QDragEnterEvent *ev) { //QTreeView::dragEnterEvent(ev); if (ev->mimeData()->hasText()) { @@ -542,7 +542,7 @@ void WatchWindow::dragEnterEvent(QDragEnterEvent *ev) } } -void WatchWindow::dragMoveEvent(QDragMoveEvent *ev) +void WatchTreeView::dragMoveEvent(QDragMoveEvent *ev) { //QTreeView::dragMoveEvent(ev); if (ev->mimeData()->hasText()) { @@ -551,7 +551,7 @@ void WatchWindow::dragMoveEvent(QDragMoveEvent *ev) } } -void WatchWindow::dropEvent(QDropEvent *ev) +void WatchTreeView::dropEvent(QDropEvent *ev) { if (ev->mimeData()->hasText()) { watchExpression(ev->mimeData()->text()); @@ -562,7 +562,7 @@ void WatchWindow::dropEvent(QDropEvent *ev) //QTreeView::dropEvent(ev); } -void WatchWindow::mouseDoubleClickEvent(QMouseEvent *ev) +void WatchTreeView::mouseDoubleClickEvent(QMouseEvent *ev) { const QModelIndex idx = indexAt(ev->pos()); if (!idx.isValid()) { @@ -577,24 +577,24 @@ void WatchWindow::mouseDoubleClickEvent(QMouseEvent *ev) static QString addWatchActionText(QString exp) { if (exp.isEmpty()) - return WatchWindow::tr("Evaluate Expression"); + return WatchTreeView::tr("Evaluate Expression"); if (exp.size() > 30) { exp.truncate(30); exp.append(QLatin1String("...")); } - return WatchWindow::tr("Evaluate Expression \"%1\"").arg(exp); + return WatchTreeView::tr("Evaluate Expression \"%1\"").arg(exp); } // Text for add watch action with truncated expression. static QString removeWatchActionText(QString exp) { if (exp.isEmpty()) - return WatchWindow::tr("Remove Evaluated Expression"); + return WatchTreeView::tr("Remove Evaluated Expression"); if (exp.size() > 30) { exp.truncate(30); exp.append(QLatin1String("...")); } - return WatchWindow::tr("Remove Evaluated Expression \"%1\"").arg(exp); + return WatchTreeView::tr("Remove Evaluated Expression \"%1\"").arg(exp); } static void copyToClipboard(const QString &clipboardText) @@ -606,7 +606,7 @@ static void copyToClipboard(const QString &clipboardText) clipboard->setText(clipboardText, QClipboard::Clipboard); } -void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) +void WatchTreeView::contextMenuEvent(QContextMenuEvent *ev) { DebuggerEngine *engine = currentEngine(); WatchHandler *handler = engine->watchHandler(); @@ -970,7 +970,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) } } -bool WatchWindow::event(QEvent *ev) +bool WatchTreeView::event(QEvent *ev) { if (m_grabbing && ev->type() == QEvent::MouseButtonPress) { QMouseEvent *mev = static_cast<QMouseEvent *>(ev); @@ -981,14 +981,14 @@ bool WatchWindow::event(QEvent *ev) return QTreeView::event(ev); } -void WatchWindow::editItem(const QModelIndex &idx) +void WatchTreeView::editItem(const QModelIndex &idx) { Q_UNUSED(idx) // FIXME } -void WatchWindow::setModel(QAbstractItemModel *model) +void WatchTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); setRootIsDecorated(true); if (header()) { header()->setDefaultAlignment(Qt::AlignLeft); @@ -999,12 +999,12 @@ void WatchWindow::setModel(QAbstractItemModel *model) connect(model, SIGNAL(layoutChanged()), SLOT(resetHelper())); } -void WatchWindow::resetHelper() +void WatchTreeView::resetHelper() { resetHelper(model()->index(0, 0)); } -void WatchWindow::resetHelper(const QModelIndex &idx) +void WatchTreeView::resetHelper(const QModelIndex &idx) { if (idx.data(LocalsExpandedRole).toBool()) { //qDebug() << "EXPANDING " << model()->data(idx, INameRole); @@ -1022,24 +1022,24 @@ void WatchWindow::resetHelper(const QModelIndex &idx) } } -void WatchWindow::watchExpression(const QString &exp) +void WatchTreeView::watchExpression(const QString &exp) { currentEngine()->watchHandler()->watchExpression(exp); } -void WatchWindow::removeWatchExpression(const QString &exp) +void WatchTreeView::removeWatchExpression(const QString &exp) { currentEngine()->watchHandler()->removeWatchExpression(exp); } -void WatchWindow::setModelData +void WatchTreeView::setModelData (int role, const QVariant &value, const QModelIndex &index) { QTC_ASSERT(model(), return); model()->setData(index, value, role); } -void WatchWindow::setWatchpointAtAddress(quint64 address, unsigned size) +void WatchTreeView::setWatchpointAtAddress(quint64 address, unsigned size) { BreakpointParameters data(WatchpointAtAddress); data.address = address; @@ -1053,7 +1053,7 @@ void WatchWindow::setWatchpointAtAddress(quint64 address, unsigned size) breakHandler()->appendBreakpoint(data); } -void WatchWindow::setWatchpointAtExpression(const QString &exp) +void WatchTreeView::setWatchpointAtExpression(const QString &exp) { BreakpointParameters data(WatchpointAtExpression); data.expression = exp; @@ -1066,6 +1066,7 @@ void WatchWindow::setWatchpointAtExpression(const QString &exp) breakHandler()->appendBreakpoint(data); } + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index bf6658f389..b04f85c3f5 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -44,15 +44,16 @@ namespace Internal { // ///////////////////////////////////////////////////////////////////// -class WatchWindow : public BaseWindow +class WatchTreeView : public BaseTreeView { Q_OBJECT public: enum Type { ReturnType, LocalsType, TooltipType, WatchersType }; - explicit WatchWindow(Type type, QWidget *parent = 0); + explicit WatchTreeView(Type type, QWidget *parent = 0); Type type() const { return m_type; } + void setModel(QAbstractItemModel *model); public slots: void watchExpression(const QString &exp); @@ -63,7 +64,6 @@ private: Q_SLOT void expandNode(const QModelIndex &idx); Q_SLOT void collapseNode(const QModelIndex &idx); - void setModel(QAbstractItemModel *model); void keyPressEvent(QKeyEvent *ev); void contextMenuEvent(QContextMenuEvent *ev); void dragEnterEvent(QDragEnterEvent *ev); @@ -84,6 +84,15 @@ private: bool m_grabbing; }; +class WatchWindow : public BaseWindow +{ +public: + explicit WatchWindow(WatchTreeView::Type type) + : BaseWindow(new WatchTreeView(type)) + { + setWindowTitle(tr("Locals and Expressions")); + } +}; } // namespace Internal } // namespace Debugger diff --git a/src/plugins/designer/codemodelhelpers.cpp b/src/plugins/designer/codemodelhelpers.cpp index 0cf6eb48df..d6f150d550 100644 --- a/src/plugins/designer/codemodelhelpers.cpp +++ b/src/plugins/designer/codemodelhelpers.cpp @@ -32,7 +32,7 @@ #include "codemodelhelpers.h" -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/Symbols.h> #include <cplusplus/CoreTypes.h> #include <cplusplus/Name.h> diff --git a/src/plugins/designer/formeditorplugin.h b/src/plugins/designer/formeditorplugin.h index a6a9bab959..6d11abeb03 100644 --- a/src/plugins/designer/formeditorplugin.h +++ b/src/plugins/designer/formeditorplugin.h @@ -41,6 +41,7 @@ namespace Internal { class FormEditorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Designer.json") public: FormEditorPlugin(); diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp index e1ebe0cabd..e0b5724823 100644 --- a/src/plugins/designer/qtcreatorintegration.cpp +++ b/src/plugins/designer/qtcreatorintegration.cpp @@ -43,7 +43,7 @@ #include <cpptools/cpptoolsconstants.h> #include <cpptools/insertionpointlocator.h> #include <cpptools/symbolfinder.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/Symbols.h> #include <cplusplus/Overview.h> #include <cplusplus/CoreTypes.h> diff --git a/src/plugins/designer/qtcreatorintegration.h b/src/plugins/designer/qtcreatorintegration.h index 87b52e5ca1..50e97bb5d9 100644 --- a/src/plugins/designer/qtcreatorintegration.h +++ b/src/plugins/designer/qtcreatorintegration.h @@ -33,7 +33,7 @@ #ifndef QTCREATORINTEGRATION_H #define QTCREATORINTEGRATION_H -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #if QT_VERSION >= 0x050000 # include <QDesignerIntegration> diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 350d9b58a5..3253d9685b 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -78,8 +78,6 @@ #include <utils/treewidgetcolumnstretcher.h> #include <utils/stylehelper.h> -#include <cppeditor/cppeditorconstants.h> - #include <cpptools/cpptoolsconstants.h> #include <QAbstractTableModel> @@ -895,7 +893,7 @@ FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin) QRegExp("^(cN(ext)?|cp(revious)?)!?( (.*))?$"); defaultExCommandMap()["Coreplugin.OutputPane.nextitem"] = QRegExp("^cn(ext)?!?( (.*))?$"); - defaultExCommandMap()[CppEditor::Constants::JUMP_TO_DEFINITION] = + defaultExCommandMap()[TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR] = QRegExp("^tag?$"); defaultExCommandMap()[Core::Constants::GO_BACK] = QRegExp("^pop?$"); diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h index 88f60f619c..c7dba08b42 100644 --- a/src/plugins/fakevim/fakevimplugin.h +++ b/src/plugins/fakevim/fakevimplugin.h @@ -44,6 +44,7 @@ class FakeVimPluginPrivate; class FakeVimPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "FakeVim.json") public: FakeVimPlugin(); diff --git a/src/plugins/find/findplugin.h b/src/plugins/find/findplugin.h index f5862087db..9a34b9a3c9 100644 --- a/src/plugins/find/findplugin.h +++ b/src/plugins/find/findplugin.h @@ -54,6 +54,7 @@ class CurrentDocumentFind; class FIND_EXPORT FindPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Find.json") public: FindPlugin(); diff --git a/src/plugins/find/treeviewfind.cpp b/src/plugins/find/treeviewfind.cpp index 134f0d6c3e..b74c97564a 100644 --- a/src/plugins/find/treeviewfind.cpp +++ b/src/plugins/find/treeviewfind.cpp @@ -39,11 +39,10 @@ namespace Find { struct ItemModelFindPrivate { - explicit ItemModelFindPrivate(QTreeView *view, int role, int column) + explicit ItemModelFindPrivate(QTreeView *view, int role) : m_view(view) , m_incrementalWrappedState(false), - m_role(role), - m_column(column) + m_role(role) { } @@ -51,11 +50,10 @@ struct ItemModelFindPrivate QModelIndex m_incrementalFindStart; bool m_incrementalWrappedState; int m_role; - int m_column; }; -TreeViewFind::TreeViewFind(QTreeView *view, int role, int column) - : d(new ItemModelFindPrivate(view, role, column)) +TreeViewFind::TreeViewFind(QTreeView *view, int role) + : d(new ItemModelFindPrivate(view, role)) { } @@ -166,14 +164,17 @@ IFindSupport::Result TreeViewFind::find(const QString &searchTxt, QModelIndex resultIndex; QModelIndex currentIndex = d->m_view->currentIndex(); QModelIndex index = currentIndex; + int currentRow = currentIndex.row(); + bool backward = (flags & QTextDocument::FindBackward); if (wrapped) *wrapped = false; bool anyWrapped = false; bool stepWrapped = false; - if (!startFromCurrentIndex) index = followingIndex(index, backward, &stepWrapped); + else + currentRow = -1; do { anyWrapped |= stepWrapped; // update wrapped state if we actually stepped to next/prev item if (index.isValid()) { @@ -184,11 +185,17 @@ IFindSupport::Result TreeViewFind::find(const QString &searchTxt, QRegExp searchExpr = QRegExp(searchTxt, (sensitive ? Qt::CaseSensitive : Qt::CaseInsensitive)); - if (searchExpr.indexIn(text) != -1) + if (searchExpr.indexIn(text) != -1 + && d->m_view->model()->flags(index) & Qt::ItemIsSelectable + && currentRow != index.row()) resultIndex = index; } else { QTextDocument doc(text); - if (!doc.find(searchTxt, 0, flags).isNull()) + if (!doc.find(searchTxt, 0, + flags & (Find::FindCaseSensitively | + Find::FindWholeWords)).isNull() + && d->m_view->model()->flags(index) & Qt::ItemIsSelectable + && currentRow != index.row()) resultIndex = index; } } @@ -226,17 +233,23 @@ QModelIndex TreeViewFind::nextIndex(const QModelIndex &idx, bool *wrapped) const QModelIndex current = idx; while (!nextIndex.isValid()) { int row = current.row(); + int column = current.column(); current = current.parent(); - if (row + 1 < model->rowCount(current)) { - // Same parent has another child - nextIndex = model->index(row + 1, 0, current); + + if (column + 1 < model->columnCount(current)) { + nextIndex = model->index(row, column + 1, current); } else { - // go up one parent - if (!current.isValid()) { - // we start from the beginning - if (wrapped) - *wrapped = true; - nextIndex = model->index(0, 0); + if (row + 1 < model->rowCount(current)) { + // Same parent has another child + nextIndex = model->index(row + 1, 0, current); + } else { + // go up one parent + if (!current.isValid()) { + // we start from the beginning + if (wrapped) + *wrapped = true; + nextIndex = model->index(0, 0); + } } } } @@ -252,21 +265,27 @@ QModelIndex TreeViewFind::prevIndex(const QModelIndex &idx, bool *wrapped) const QAbstractItemModel *model = d->m_view->model(); if (current.isValid()) { int row = current.row(); - if (row > 0) { - current = model->index(row - 1, 0, current.parent()); + int column = current.column(); + if (column > 0) { + current = model->index(row, column - 1, current.parent()); } else { - current = current.parent(); - checkForChildren = !current.isValid(); - if (checkForChildren && wrapped) { - // we start from the end - *wrapped = true; + if (row > 0) { + current = model->index(row - 1, model->columnCount(current.parent()) - 1, + current.parent()); + } else { + current = current.parent(); + checkForChildren = !current.isValid(); + if (checkForChildren && wrapped) { + // we start from the end + *wrapped = true; + } } } } if (checkForChildren) { // traverse down the hierarchy while (int rc = model->rowCount(current)) { - current = model->index(rc - 1, d->m_column, current); + current = model->index(rc - 1, model->columnCount(current) - 1, current); } } return current; diff --git a/src/plugins/find/treeviewfind.h b/src/plugins/find/treeviewfind.h index 15fbbb361d..5c218512ba 100644 --- a/src/plugins/find/treeviewfind.h +++ b/src/plugins/find/treeviewfind.h @@ -48,8 +48,7 @@ class FIND_EXPORT TreeViewFind : public Find::IFindSupport { Q_OBJECT public: - explicit TreeViewFind(QTreeView *view, int role = Qt::DisplayRole, - int column = 0); + explicit TreeViewFind(QTreeView *view, int role = Qt::DisplayRole); virtual ~TreeViewFind(); bool supportsReplace() const; diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index db917e4249..a7ea37a461 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -42,7 +42,7 @@ #include <projectexplorer/customexecutablerunconfiguration.h> #include <projectexplorer/toolchainmanager.h> #include <projectexplorer/projectexplorerconstants.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <extensionsystem/pluginmanager.h> #include <utils/pathchooser.h> #include <utils/qtcassert.h> @@ -430,11 +430,6 @@ IProjectManager *GenericProject::projectManager() const return m_manager; } -QList<Project *> GenericProject::dependsOn() -{ - return QList<Project *>(); -} - QList<BuildConfigWidget*> GenericProject::subConfigWidgets() { QList<BuildConfigWidget*> list; diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h index 80517fc151..f35d7eb611 100644 --- a/src/plugins/genericprojectmanager/genericproject.h +++ b/src/plugins/genericprojectmanager/genericproject.h @@ -86,8 +86,6 @@ public: ProjectExplorer::IProjectManager *projectManager() const; GenericTarget *activeTarget() const; - QList<ProjectExplorer::Project *> dependsOn(); - QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets(); GenericProjectNode *rootProjectNode() const; diff --git a/src/plugins/genericprojectmanager/genericprojectplugin.h b/src/plugins/genericprojectmanager/genericprojectplugin.h index 277d219d55..29b1477fa9 100644 --- a/src/plugins/genericprojectmanager/genericprojectplugin.h +++ b/src/plugins/genericprojectmanager/genericprojectplugin.h @@ -51,6 +51,7 @@ class ProjectFilesFactory; class GenericProjectPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "GenericProjectManager.json") public: GenericProjectPlugin(); diff --git a/src/plugins/git/commitdata.cpp b/src/plugins/git/commitdata.cpp index dc485e1410..b18e9c6e53 100644 --- a/src/plugins/git/commitdata.cpp +++ b/src/plugins/git/commitdata.cpp @@ -58,6 +58,7 @@ void GitSubmitEditorPanelData::clear() { author.clear(); email.clear(); + bypassHooks = false; } QString GitSubmitEditorPanelData::authorString() const @@ -76,7 +77,8 @@ QString GitSubmitEditorPanelData::authorString() const QDebug operator<<(QDebug d, const GitSubmitEditorPanelData &data) { - d.nospace() << " author:" << data.author << " email: " << data.email; + d.nospace() << " author:" << data.author << " email: " << data.email + << " bypass hooks: " << data.bypassHooks; return d; } diff --git a/src/plugins/git/commitdata.h b/src/plugins/git/commitdata.h index 1d469ff7cc..7795dd720f 100644 --- a/src/plugins/git/commitdata.h +++ b/src/plugins/git/commitdata.h @@ -62,6 +62,7 @@ struct GitSubmitEditorPanelData QString author; QString email; + bool bypassHooks; }; QDebug operator<<(QDebug d, const GitSubmitEditorPanelData &); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 696560a783..dab54a13e6 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1519,7 +1519,7 @@ static inline QString trimFileSpecification(QString fileSpec) } GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, bool untracked, - QString *output, QString *errorMessage, bool *onBranch) + QString *output, QString *errorMessage) { // Run 'status'. Note that git returns exitcode 1 if there are no added files. QByteArray outputText; @@ -1537,8 +1537,6 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, bo static const char * NO_BRANCH = "## HEAD (no branch)\n"; const bool branchKnown = !outputText.startsWith(NO_BRANCH); - if (onBranch) - *onBranch = branchKnown; // Is it something really fatal? if (!statusRc && !branchKnown) { if (errorMessage) { @@ -1605,6 +1603,13 @@ void GitClient::launchGitK(const QString &workingDirectory) tryLauchingGitK(env, workingDirectory, foundBinDir.path() + QLatin1String("/bin"), false); } +void GitClient::launchRepositoryBrowser(const QString &workingDirectory) +{ + const QString repBrowserBinary = settings()->stringValue(GitSettings::repositoryBrowserCmd); + if (!repBrowserBinary.isEmpty()) + QProcess::startDetached(repBrowserBinary, QStringList(workingDirectory), workingDirectory); +} + bool GitClient::tryLauchingGitK(const QProcessEnvironment &env, const QString &workingDirectory, const QString &gitBinDirectory, @@ -1688,15 +1693,10 @@ bool GitClient::getCommitData(const QString &workingDirectory, } // Run status. Note that it has exitcode 1 if there are no added files. - bool onBranch; QString output; - const StatusResult status = gitStatus(repoDirectory, true, &output, errorMessage, &onBranch); + const StatusResult status = gitStatus(repoDirectory, true, &output, errorMessage); switch (status) { case StatusChanged: - if (!onBranch) { - *errorMessage = tr("You did not checkout a branch."); - return false; - } break; case StatusUnchanged: if (amend) @@ -1867,6 +1867,8 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory, const QString &authorString = data.authorString(); if (!authorString.isEmpty()) args << QLatin1String("--author") << authorString; + if (data.bypassHooks) + args << QLatin1String("--no-verify"); QByteArray outputText; QByteArray errorText; diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 00bad95e53..0110852238 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -212,9 +212,11 @@ public: StatusResult gitStatus(const QString &workingDirectory, bool untracked = false, QString *output = 0, - QString *errorMessage = 0, bool *onBranch = 0); + QString *errorMessage = 0); void launchGitK(const QString &workingDirectory); + void launchRepositoryBrowser(const QString &workingDirectory); + QStringList synchronousRepositoryBranches(const QString &repositoryURL); GitSettings *settings() const; diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index b845f4db34..3eec1999d8 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -430,6 +430,11 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage) tr("Launch gitk"), Core::Id("Git.LaunchGitK"), globalcontext, true, &GitClient::launchGitK); + m_repositoryBrowserAction + = createRepositoryAction(actionManager, gitContainer, + tr("Launch repository browser"), Core::Id("Git.LaunchRepositoryBrowser"), + globalcontext, true, &GitClient::launchRepositoryBrowser).first; + createRepositoryAction(actionManager, gitContainer, tr("Branches..."), Core::Id("Git.BranchList"), globalcontext, true, SLOT(branchList())); @@ -1031,11 +1036,19 @@ void GitPlugin::updateActions(VcsBase::VcsBasePlugin::ActionState as) foreach (QAction *repositoryAction, m_repositoryActions) repositoryAction->setEnabled(repositoryEnabled); + updateRepositoryBrowserAction(); // Prompts for repo. m_showAction->setEnabled(true); } +void GitPlugin::updateRepositoryBrowserAction() +{ + const bool repositoryEnabled = currentState().hasTopLevel(); + const bool hasRepositoryBrowserCmd = !settings().stringValue(GitSettings::repositoryBrowserCmd).isEmpty(); + m_repositoryBrowserAction->setEnabled(repositoryEnabled && hasRepositoryBrowserCmd); +} + void GitPlugin::showCommit() { const VcsBase::VcsBasePluginState state = currentState(); @@ -1070,6 +1083,7 @@ void GitPlugin::setSettings(const GitSettings &s) m_settings = s; m_gitClient->saveSettings(); static_cast<GitVersionControl *>(versionControl())->emitConfigurationChanged(); + updateRepositoryBrowserAction(); } GitClient *GitPlugin::gitClient() const diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index e8c3d15f0c..9ad5f2c344 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -86,6 +86,7 @@ typedef QPair<Utils::ParameterAction *, Core::Command* > ParameterActionCommandP class GitPlugin : public VcsBase::VcsBasePlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Git.json") public: GitPlugin(); @@ -174,6 +175,7 @@ private: const Core::Context &context, bool addToLocator, GitClientMemberFunc); + void updateRepositoryBrowserAction(); bool isCommitEditorOpen() const; Core::IEditor *openSubmitEditor(const QString &fileName, const CommitData &cd, bool amend); void cleanCommitMessageFile(); @@ -192,6 +194,7 @@ private: QAction *m_undoAction; QAction *m_redoAction; QAction *m_menuAction; + QAction *m_repositoryBrowserAction; QVector<Utils::ParameterAction *> m_fileActions; QVector<Utils::ParameterAction *> m_projectActions; diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index 177d79a270..095922306c 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -49,6 +49,7 @@ const QLatin1String GitSettings::winSetHomeEnvironmentKey("WinSetHomeEnvironment const QLatin1String GitSettings::showPrettyFormatKey("DiffPrettyFormat"); const QLatin1String GitSettings::gitkOptionsKey("GitKOptions"); const QLatin1String GitSettings::logDiffKey("LogDiff"); +const QLatin1String GitSettings::repositoryBrowserCmd("RepositoryBrowserCmd"); GitSettings::GitSettings() { @@ -70,6 +71,7 @@ GitSettings::GitSettings() declareKey(gitkOptionsKey, QString()); declareKey(showPrettyFormatKey, 2); declareKey(logDiffKey, false); + declareKey(repositoryBrowserCmd, QString()); } QString GitSettings::gitBinaryPath(bool *ok, QString *errorMessage) const diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h index e381dd014a..a6929bd5fd 100644 --- a/src/plugins/git/gitsettings.h +++ b/src/plugins/git/gitsettings.h @@ -56,6 +56,7 @@ public: static const QLatin1String showPrettyFormatKey; static const QLatin1String gitkOptionsKey; static const QLatin1String logDiffKey; + static const QLatin1String repositoryBrowserCmd; QString gitBinaryPath(bool *ok = 0, QString *errorMessage = 0) const; diff --git a/src/plugins/git/gitsubmiteditorwidget.cpp b/src/plugins/git/gitsubmiteditorwidget.cpp index b3e782698e..36a1087fec 100644 --- a/src/plugins/git/gitsubmiteditorwidget.cpp +++ b/src/plugins/git/gitsubmiteditorwidget.cpp @@ -143,6 +143,7 @@ GitSubmitEditorPanelData GitSubmitEditorWidget::panelData() const GitSubmitEditorPanelData rc; rc.author = m_gitSubmitPanelUi.authorLineEdit->text(); rc.email = m_gitSubmitPanelUi.emailLineEdit->text(); + rc.bypassHooks = m_gitSubmitPanelUi.bypassHooksCheckBox->isChecked(); return rc; } @@ -150,6 +151,7 @@ void GitSubmitEditorWidget::setPanelData(const GitSubmitEditorPanelData &data) { m_gitSubmitPanelUi.authorLineEdit->setText(data.author); m_gitSubmitPanelUi.emailLineEdit->setText(data.email); + m_gitSubmitPanelUi.bypassHooksCheckBox->setChecked(data.bypassHooks); authorInformationChanged(); } diff --git a/src/plugins/git/gitsubmitpanel.ui b/src/plugins/git/gitsubmitpanel.ui index c790299aa1..7830c490d8 100644 --- a/src/plugins/git/gitsubmitpanel.ui +++ b/src/plugins/git/gitsubmitpanel.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>364</width> - <height>172</height> + <height>177</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout"> @@ -60,23 +60,6 @@ <string>Commit Information</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="authorLabel"> - <property name="text"> - <string>Author:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="authorLineEdit"> - <property name="minimumSize"> - <size> - <width>150</width> - <height>0</height> - </size> - </property> - </widget> - </item> <item row="0" column="2"> <widget class="QLabel" name="invalidAuthorLabel"> <property name="minimumSize"> @@ -93,22 +76,6 @@ </property> </widget> </item> - <item row="0" column="3"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::MinimumExpanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>5</width> - <height>20</height> - </size> - </property> - </spacer> - </item> <item row="1" column="0"> <widget class="QLabel" name="emailLabel"> <property name="text"> @@ -142,6 +109,46 @@ </property> </widget> </item> + <item row="0" column="0"> + <widget class="QLabel" name="authorLabel"> + <property name="text"> + <string>Author:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="authorLineEdit"> + <property name="minimumSize"> + <size> + <width>150</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>5</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="bypassHooksCheckBox"> + <property name="text"> + <string>By&pass hooks</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/plugins/git/settingspage.cpp b/src/plugins/git/settingspage.cpp index bcb3ecedd3..5c023a3358 100644 --- a/src/plugins/git/settingspage.cpp +++ b/src/plugins/git/settingspage.cpp @@ -36,6 +36,7 @@ #include "gitclient.h" #include <vcsbase/vcsbaseconstants.h> +#include <utils/pathchooser.h> #include <QCoreApplication> #include <QDir> @@ -65,6 +66,8 @@ SettingsPageWidget::SettingsPageWidget(QWidget *parent) : #else m_ui.winHomeCheckBox->setVisible(false); #endif + m_ui.repBrowserCommandPathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); + m_ui.repBrowserCommandPathChooser->setPromptDialogTitle(tr("Git Repository Browser Command")); } GitSettings SettingsPageWidget::settings() const @@ -77,6 +80,7 @@ GitSettings SettingsPageWidget::settings() const rc.setValue(GitSettings::promptOnSubmitKey, m_ui.promptToSubmitCheckBox->isChecked()); rc.setValue(GitSettings::winSetHomeEnvironmentKey, m_ui.winHomeCheckBox->isChecked()); rc.setValue(GitSettings::gitkOptionsKey, m_ui.gitkOptionsLineEdit->text().trimmed()); + rc.setValue(GitSettings::repositoryBrowserCmd, m_ui.repBrowserCommandPathChooser->path().trimmed()); return rc; } @@ -89,6 +93,7 @@ void SettingsPageWidget::setSettings(const GitSettings &s) m_ui.promptToSubmitCheckBox->setChecked(s.boolValue(GitSettings::promptOnSubmitKey)); m_ui.winHomeCheckBox->setChecked(s.boolValue(GitSettings::winSetHomeEnvironmentKey)); m_ui.gitkOptionsLineEdit->setText(s.stringValue(GitSettings::gitkOptionsKey)); + m_ui.repBrowserCommandPathChooser->setPath(s.stringValue(GitSettings::repositoryBrowserCmd)); } QString SettingsPageWidget::searchKeywords() const @@ -105,6 +110,8 @@ QString SettingsPageWidget::searchKeywords() const << sep << m_ui.promptToSubmitCheckBox->text() << sep << m_ui.gitkGroupBox->title() << sep << m_ui.gitkOptionsLabel->text() + << sep << m_ui.repBrowserGroupBox->title() + << sep << m_ui.repBrowserCommandLabel->text() ; rc.remove(QLatin1Char('&')); return rc; diff --git a/src/plugins/git/settingspage.ui b/src/plugins/git/settingspage.ui index 2453404c74..b12fbe028d 100644 --- a/src/plugins/git/settingspage.ui +++ b/src/plugins/git/settingspage.ui @@ -153,6 +153,32 @@ </widget> </item> <item> + <widget class="QGroupBox" name="repBrowserGroupBox"> + <property name="title"> + <string>Repository browser</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="repBrowserCommandLabel"> + <property name="text"> + <string>Command:</string> + </property> + </widget> + </item> + <item> + <widget class="Utils::PathChooser" name="repBrowserCommandPathChooser" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -167,6 +193,18 @@ </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>Utils::PathChooser</class> + <extends>QWidget</extends> + <header location="global">utils/pathchooser.h</header> + <container>1</container> + <slots> + <signal>editingFinished()</signal> + <signal>browsingFinished()</signal> + </slots> + </customwidget> + </customwidgets> <tabstops> <tabstop>pathLineEdit</tabstop> </tabstops> diff --git a/src/plugins/glsleditor/glsleditorplugin.h b/src/plugins/glsleditor/glsleditorplugin.h index 4951cdeb46..37e892b472 100644 --- a/src/plugins/glsleditor/glsleditorplugin.h +++ b/src/plugins/glsleditor/glsleditorplugin.h @@ -73,6 +73,7 @@ class GLSLQuickFixCollector; class GLSLEditorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "GLSLEditor.json") public: GLSLEditorPlugin(); diff --git a/src/plugins/helloworld/helloworldplugin.h b/src/plugins/helloworld/helloworldplugin.h index 3e0852ca65..0702513b25 100644 --- a/src/plugins/helloworld/helloworldplugin.h +++ b/src/plugins/helloworld/helloworldplugin.h @@ -42,6 +42,7 @@ class HelloWorldPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "HelloWorld.json") public: HelloWorldPlugin(); diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index df86dc24c8..0ef8f145d9 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -472,6 +472,8 @@ void HelpPlugin::setupUi() m_bookmarkItem = new Core::SideBarItem(bookmarkWidget, QLatin1String(SB_BOOKMARKS)); connect(bookmarkWidget, SIGNAL(linkActivated(QUrl)), m_centralWidget, SLOT(setSource(QUrl))); + connect(bookmarkWidget, SIGNAL(createPage(QUrl,bool)), &OpenPagesManager::instance(), + SLOT(createPage(QUrl,bool))); shortcut = new QShortcut(m_splitter); shortcut->setWhatsThis(tr("Activate Bookmarks in Help mode")); diff --git a/src/plugins/help/helpplugin.h b/src/plugins/help/helpplugin.h index 17c0138318..4a0b10df12 100644 --- a/src/plugins/help/helpplugin.h +++ b/src/plugins/help/helpplugin.h @@ -70,6 +70,7 @@ class SearchWidget; class HelpPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Help.json") public: HelpPlugin(); diff --git a/src/plugins/imageviewer/imageviewerplugin.h b/src/plugins/imageviewer/imageviewerplugin.h index 66aba08157..c077f7b767 100644 --- a/src/plugins/imageviewer/imageviewerplugin.h +++ b/src/plugins/imageviewer/imageviewerplugin.h @@ -46,6 +46,7 @@ class ImageViewerFactory; class ImageViewerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ImageViewer.json") public: ImageViewerPlugin(); diff --git a/src/plugins/locator/locatorplugin.h b/src/plugins/locator/locatorplugin.h index 8c5a56a9e7..99913c1bfa 100644 --- a/src/plugins/locator/locatorplugin.h +++ b/src/plugins/locator/locatorplugin.h @@ -44,6 +44,10 @@ #include <QTimer> #include <QFutureWatcher> +#if QT_VERSION >= 0x050000 +# include <QtPlugin> +#endif + namespace Locator { namespace Internal { @@ -56,6 +60,7 @@ class LocatorPlugin; class LocatorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Locator.json") public: LocatorPlugin(); diff --git a/src/plugins/macros/macrosplugin.h b/src/plugins/macros/macrosplugin.h index f434508480..39c8547686 100644 --- a/src/plugins/macros/macrosplugin.h +++ b/src/plugins/macros/macrosplugin.h @@ -44,6 +44,7 @@ namespace Internal { class MacrosPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Macros.json") public: MacrosPlugin(); diff --git a/src/plugins/madde/maddedeviceconfigurationfactory.cpp b/src/plugins/madde/maddedeviceconfigurationfactory.cpp index e7e3cdfafc..dbde15a5fb 100644 --- a/src/plugins/madde/maddedeviceconfigurationfactory.cpp +++ b/src/plugins/madde/maddedeviceconfigurationfactory.cpp @@ -43,6 +43,7 @@ #include <remotelinux/genericlinuxdeviceconfigurationwidget.h> #include <utils/qtcassert.h> +using namespace ProjectExplorer; using namespace RemoteLinux; namespace Madde { @@ -53,7 +54,7 @@ const char MaddeRemoteProcessesActionId[] = "Madde.RemoteProcessesAction"; } // anonymous namespace MaddeDeviceConfigurationFactory::MaddeDeviceConfigurationFactory(QObject *parent) - : ILinuxDeviceConfigurationFactory(parent) + : IDeviceFactory(parent) { } @@ -62,30 +63,39 @@ QString MaddeDeviceConfigurationFactory::displayName() const return tr("Device with MADDE support (Fremantle, Harmattan, MeeGo)"); } -ILinuxDeviceConfigurationWizard *MaddeDeviceConfigurationFactory::createWizard(QWidget *parent) const +IDeviceWizard *MaddeDeviceConfigurationFactory::createWizard(QWidget *parent) const { return new MaemoDeviceConfigWizard(parent); } -ILinuxDeviceConfigurationWidget *MaddeDeviceConfigurationFactory::createWidget( - const LinuxDeviceConfiguration::Ptr &deviceConfig, +IDeviceWidget *MaddeDeviceConfigurationFactory::createWidget(const IDevice::Ptr &device, QWidget *parent) const { - return new GenericLinuxDeviceConfigurationWidget(deviceConfig, parent); + return new GenericLinuxDeviceConfigurationWidget(device.staticCast<LinuxDeviceConfiguration>(), + parent); } -bool MaddeDeviceConfigurationFactory::supportsOsType(const QString &osType) const +IDevice::Ptr MaddeDeviceConfigurationFactory::loadDevice(const QVariantMap &map) const { - return osType == QLatin1String(Maemo5OsType) || osType == QLatin1String(HarmattanOsType) - || osType == QLatin1String(MeeGoOsType); + QTC_ASSERT(supportsDeviceType(IDevice::typeFromMap(map)), + return LinuxDeviceConfiguration::Ptr()); + LinuxDeviceConfiguration::Ptr device = LinuxDeviceConfiguration::create(); + device->fromMap(map); + return device; } -QString MaddeDeviceConfigurationFactory::displayNameForOsType(const QString &osType) const +bool MaddeDeviceConfigurationFactory::supportsDeviceType(const QString &type) const { - QTC_ASSERT(supportsOsType(osType), return QString()); - if (osType == QLatin1String(Maemo5OsType)) + return type == QLatin1String(Maemo5OsType) || type == QLatin1String(HarmattanOsType) + || type == QLatin1String(MeeGoOsType); +} + +QString MaddeDeviceConfigurationFactory::displayNameForDeviceType(const QString &deviceType) const +{ + QTC_ASSERT(supportsDeviceType(deviceType), return QString()); + if (deviceType == QLatin1String(Maemo5OsType)) return tr("Maemo5/Fremantle"); - if (osType == QLatin1String(HarmattanOsType)) + if (deviceType == QLatin1String(HarmattanOsType)) return tr("MeeGo 1.2 Harmattan"); return tr("Other MeeGo OS"); } @@ -111,16 +121,18 @@ QString MaddeDeviceConfigurationFactory::displayNameForActionId(const QString &a } QDialog *MaddeDeviceConfigurationFactory::createDeviceAction(const QString &actionId, - const LinuxDeviceConfiguration::ConstPtr &deviceConfig, QWidget *parent) const + const IDevice::ConstPtr &device, QWidget *parent) const { Q_ASSERT(supportedDeviceActionIds().contains(actionId)); + const LinuxDeviceConfiguration::ConstPtr lDevice + = device.staticCast<const LinuxDeviceConfiguration>(); if (actionId == QLatin1String(MaddeDeviceTestActionId)) - return new LinuxDeviceTestDialog(deviceConfig, new MaddeDeviceTester, parent); + return new LinuxDeviceTestDialog(lDevice, new MaddeDeviceTester, parent); if (actionId == QLatin1String(MaddeRemoteProcessesActionId)) - return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(deviceConfig), parent); + return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(lDevice), parent); if (actionId == QLatin1String(Constants::GenericDeployKeyToDeviceActionId)) - return PublicKeyDeploymentDialog::createDialog(deviceConfig, parent); + return PublicKeyDeploymentDialog::createDialog(lDevice, parent); return 0; // Can't happen. } diff --git a/src/plugins/madde/maddedeviceconfigurationfactory.h b/src/plugins/madde/maddedeviceconfigurationfactory.h index b07bbd74ea..cc1451bc34 100644 --- a/src/plugins/madde/maddedeviceconfigurationfactory.h +++ b/src/plugins/madde/maddedeviceconfigurationfactory.h @@ -32,28 +32,28 @@ #ifndef MADDEDEVICECONFIGURATIONFACTORY_H #define MADDEDEVICECONFIGURATIONFACTORY_H -#include <remotelinux/linuxdeviceconfiguration.h> +#include <projectexplorer/devicesupport/idevicefactory.h> namespace Madde { namespace Internal { -class MaddeDeviceConfigurationFactory : public RemoteLinux::ILinuxDeviceConfigurationFactory +class MaddeDeviceConfigurationFactory : public ProjectExplorer::IDeviceFactory { Q_OBJECT public: MaddeDeviceConfigurationFactory(QObject *parent = 0); QString displayName() const; - RemoteLinux::ILinuxDeviceConfigurationWizard *createWizard(QWidget *parent) const; - RemoteLinux::ILinuxDeviceConfigurationWidget *createWidget( - const RemoteLinux::LinuxDeviceConfiguration::Ptr &deviceConfig, - QWidget *parent = 0) const; - bool supportsOsType(const QString &osType) const; - QString displayNameForOsType(const QString &osType) const; + ProjectExplorer::IDeviceWizard *createWizard(QWidget *parent) const; + ProjectExplorer::IDeviceWidget *createWidget( + const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = 0) const; + ProjectExplorer::IDevice::Ptr loadDevice(const QVariantMap &map) const; + bool supportsDeviceType(const QString &type) const; + QString displayNameForDeviceType(const QString &deviceType) const; QStringList supportedDeviceActionIds() const; QString displayNameForActionId(const QString &actionId) const; QDialog *createDeviceAction(const QString &actionId, - const RemoteLinux::LinuxDeviceConfiguration::ConstPtr &deviceConfig, QWidget *parent) const; + const ProjectExplorer::IDevice::ConstPtr &device, QWidget *parent) const; }; } // namespace Internal diff --git a/src/plugins/madde/maddedevicetester.cpp b/src/plugins/madde/maddedevicetester.cpp index 77ce8a59fc..c3e6498b11 100644 --- a/src/plugins/madde/maddedevicetester.cpp +++ b/src/plugins/madde/maddedevicetester.cpp @@ -117,7 +117,7 @@ void MaddeDeviceTester::handleGenericTestFinished(TestResult result) connect(m_processRunner, SIGNAL(processClosed(int)), SLOT(handleProcessFinished(int))); QString qtInfoCmd; - if (m_deviceConfiguration->osType() == QLatin1String(MeeGoOsType)) { + if (m_deviceConfiguration->type() == QLatin1String(MeeGoOsType)) { qtInfoCmd = QLatin1String("rpm -qa 'libqt*' --queryformat '%{NAME} %{VERSION}\\n'"); } else { qtInfoCmd = QLatin1String("dpkg-query -W -f " @@ -212,7 +212,7 @@ void MaddeDeviceTester::handleMadDeveloperTestFinished(int exitStatus) } else if (m_processRunner->processExitCode() != 0) { QString message = tr("Connectivity tool not installed on device. " "Deployment currently not possible."); - if (m_deviceConfiguration->osType() == QLatin1String(HarmattanOsType)) { + if (m_deviceConfiguration->type() == QLatin1String(HarmattanOsType)) { message += tr("Please switch the device to developer mode " "via Settings -> Security."); } @@ -222,7 +222,7 @@ void MaddeDeviceTester::handleMadDeveloperTestFinished(int exitStatus) emit progressMessage(tr("Connectivity tool present.\n")); } - if (m_deviceConfiguration->osType() != QLatin1String(HarmattanOsType)) { + if (m_deviceConfiguration->type() != QLatin1String(HarmattanOsType)) { setFinished(); return; } @@ -263,7 +263,7 @@ QString MaddeDeviceTester::processedQtLibsList() QString unfilteredLibs = QString::fromUtf8(m_stdout); QString filteredLibs; QString patternString; - if (m_deviceConfiguration->osType() == QLatin1String(MeeGoOsType)) + if (m_deviceConfiguration->type() == QLatin1String(MeeGoOsType)) patternString = QLatin1String("(libqt\\S+) ((\\d+)\\.(\\d+)\\.(\\d+))"); else patternString = QLatin1String("(\\S+) (\\S*(\\d+)\\.(\\d+)\\.(\\d+)\\S*) \\S+ \\S+ \\S+"); diff --git a/src/plugins/madde/maddeplugin.h b/src/plugins/madde/maddeplugin.h index 1d68602342..60930b83c5 100644 --- a/src/plugins/madde/maddeplugin.h +++ b/src/plugins/madde/maddeplugin.h @@ -41,6 +41,8 @@ namespace Internal { class MaddePlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Madde.json") + public: MaddePlugin(); ~MaddePlugin(); diff --git a/src/plugins/madde/maddeuploadandinstallpackagesteps.cpp b/src/plugins/madde/maddeuploadandinstallpackagesteps.cpp index c689be8abd..2071dfb7af 100644 --- a/src/plugins/madde/maddeuploadandinstallpackagesteps.cpp +++ b/src/plugins/madde/maddeuploadandinstallpackagesteps.cpp @@ -61,7 +61,7 @@ protected: void doDeviceSetup() { - if (deviceConfiguration()->deviceType() == LinuxDeviceConfiguration::Hardware) { + if (deviceConfiguration()->machineType() == LinuxDeviceConfiguration::Hardware) { handleDeviceSetupDone(true); return; } diff --git a/src/plugins/madde/maemodeploybymountsteps.cpp b/src/plugins/madde/maemodeploybymountsteps.cpp index 03dde4061a..e30338e3b6 100644 --- a/src/plugins/madde/maemodeploybymountsteps.cpp +++ b/src/plugins/madde/maemodeploybymountsteps.cpp @@ -157,7 +157,7 @@ void AbstractMaemoDeployByMountService::doDeviceSetup() { QTC_ASSERT(m_state == Inactive, return); - if (deviceConfiguration()->deviceType() == LinuxDeviceConfiguration::Hardware) { + if (deviceConfiguration()->machineType() == LinuxDeviceConfiguration::Hardware) { handleDeviceSetupDone(true); return; } diff --git a/src/plugins/madde/maemodeployconfigurationwidget.cpp b/src/plugins/madde/maemodeployconfigurationwidget.cpp index 8aaa4c4aab..fc73329d1a 100644 --- a/src/plugins/madde/maemodeployconfigurationwidget.cpp +++ b/src/plugins/madde/maemodeployconfigurationwidget.cpp @@ -147,7 +147,7 @@ void MaemoDeployConfigurationWidget::addIcon() { DeployableFilesPerProFile * const proFileInfo = m_remoteLinuxWidget->currentModel(); const int iconDim - = MaemoGlobal::applicationIconSize(deployConfiguration()->target()->supportedOsType()); + = MaemoGlobal::applicationIconSize(deployConfiguration()->target()); const QString origFilePath = QFileDialog::getOpenFileName(this, tr("Choose Icon (will be scaled to %1x%1 pixels, if necessary)").arg(iconDim), proFileInfo->projectDir(), QLatin1String("(*.png)")); @@ -212,7 +212,7 @@ QString MaemoDeployConfigurationWidget::remoteIconFilePath(const DeployableFiles QString MaemoDeployConfigurationWidget::remoteIconDir() const { return QString::fromLatin1("/usr/share/icons/hicolor/%1x%1/apps") - .arg(MaemoGlobal::applicationIconSize(deployConfiguration()->target()->supportedOsType())); + .arg(MaemoGlobal::applicationIconSize(deployConfiguration()->target())); } } // namespace Internal diff --git a/src/plugins/madde/maemodeploymentmounter.cpp b/src/plugins/madde/maemodeploymentmounter.cpp index 505b849942..5a43ec4c8d 100644 --- a/src/plugins/madde/maemodeploymentmounter.cpp +++ b/src/plugins/madde/maemodeploymentmounter.cpp @@ -142,7 +142,7 @@ void MaemoDeploymentMounter::handleUnmounted() break; case UnmountingCurrentDirs: setState(GatheringPorts); - m_portsGatherer->start(m_connection, m_devConf); + m_portsGatherer->start(m_devConf); break; case UnmountingCurrentMounts: setState(Inactive); diff --git a/src/plugins/madde/maemodeploymentmounter.h b/src/plugins/madde/maemodeploymentmounter.h index a35e6d43f0..8e58628ffa 100644 --- a/src/plugins/madde/maemodeploymentmounter.h +++ b/src/plugins/madde/maemodeploymentmounter.h @@ -35,7 +35,7 @@ #include "maemomountspecification.h" -#include <remotelinux/portlist.h> +#include <utils/portlist.h> #include <QList> #include <QObject> @@ -97,7 +97,7 @@ private: QSharedPointer<const RemoteLinux::LinuxDeviceConfiguration> m_devConf; MaemoRemoteMounter * const m_mounter; RemoteLinux::RemoteLinuxUsedPortsGatherer * const m_portsGatherer; - RemoteLinux::PortList m_freePorts; + Utils::PortList m_freePorts; QList<MaemoMountSpecification> m_mountSpecs; const Qt4ProjectManager::Qt4BuildConfiguration *m_buildConfig; }; diff --git a/src/plugins/madde/maemodeviceconfigwizard.cpp b/src/plugins/madde/maemodeviceconfigwizard.cpp index 2bc5558227..c8619f7a07 100644 --- a/src/plugins/madde/maemodeviceconfigwizard.cpp +++ b/src/plugins/madde/maemodeviceconfigwizard.cpp @@ -40,9 +40,10 @@ #include "maemoconstants.h" #include "maemoglobal.h" +#include <projectexplorer/devicesupport/devicemanager.h> #include <remotelinux/genericlinuxdeviceconfigurationwizardpages.h> +#include <remotelinux/linuxdeviceconfiguration.h> #include <remotelinux/linuxdevicetestdialog.h> -#include <remotelinux/remotelinuxutils.h> #include <remotelinux/sshkeydeployer.h> #include <utils/fileutils.h> #include <utils/ssh/sshkeygenerator.h> @@ -54,6 +55,7 @@ #include <QMessageBox> #include <QWizardPage> +using namespace ProjectExplorer; using namespace RemoteLinux; using namespace Utils; @@ -61,14 +63,14 @@ namespace Madde { namespace Internal { namespace { -QString defaultUser(const QString &osType) +QString defaultUser(const QString &deviceType) { - if (osType == QLatin1String(MeeGoOsType)) + if (deviceType == QLatin1String(MeeGoOsType)) return QLatin1String("meego"); return QLatin1String("developer"); } -QString defaultHost(LinuxDeviceConfiguration::DeviceType type) +QString defaultHost(LinuxDeviceConfiguration::MachineType type) { return QLatin1String(type == LinuxDeviceConfiguration::Hardware ? "192.168.2.15" : "localhost"); } @@ -77,9 +79,9 @@ struct WizardData { QString configName; QString hostName; - QString osType; + QString deviceType; SshConnectionParameters::AuthenticationType authType; - LinuxDeviceConfiguration::DeviceType deviceType; + LinuxDeviceConfiguration::MachineType machineType; QString privateKeyFilePath; QString publicKeyFilePath; QString userName; @@ -104,25 +106,24 @@ public: setTitle(tr("General Information")); setSubTitle(QLatin1String(" ")); // For Qt bug (background color) - m_ui->osTypeComboBox->addItem(RemoteLinuxUtils::osTypeToString(QLatin1String(Maemo5OsType)), + m_ui->osTypeComboBox->addItem(DeviceManager::displayNameForDeviceType(QLatin1String(Maemo5OsType)), QLatin1String(Maemo5OsType)); - m_ui->osTypeComboBox->addItem(RemoteLinuxUtils::osTypeToString(QLatin1String(HarmattanOsType)), + m_ui->osTypeComboBox->addItem(DeviceManager::displayNameForDeviceType(QLatin1String(HarmattanOsType)), QLatin1String(HarmattanOsType)); - m_ui->osTypeComboBox->addItem(RemoteLinuxUtils::osTypeToString(QLatin1String(MeeGoOsType)), + m_ui->osTypeComboBox->addItem(DeviceManager::displayNameForDeviceType(QLatin1String(MeeGoOsType)), QLatin1String(MeeGoOsType)); QButtonGroup *buttonGroup = new QButtonGroup(this); buttonGroup->setExclusive(true); buttonGroup->addButton(m_ui->hwButton); buttonGroup->addButton(m_ui->emulatorButton); - connect(buttonGroup, SIGNAL(buttonClicked(int)), - SLOT(handleDeviceTypeChanged())); + connect(buttonGroup, SIGNAL(buttonClicked(int)), SLOT(handleMachineTypeChanged())); m_ui->nameLineEdit->setText(tr("MeeGo Device")); m_ui->osTypeComboBox->setCurrentIndex(m_ui->osTypeComboBox->findData(QLatin1String(HarmattanOsType))); m_ui->hwButton->setChecked(true); - handleDeviceTypeChanged(); - m_ui->hostNameLineEdit->setText(defaultHost(deviceType())); + handleMachineTypeChanged(); + m_ui->hostNameLineEdit->setText(defaultHost(machineType())); m_ui->sshPortSpinBox->setMinimum(1); m_ui->sshPortSpinBox->setMaximum(65535); m_ui->sshPortSpinBox->setValue(22); @@ -141,17 +142,17 @@ public: QString hostName() const { - return deviceType() == LinuxDeviceConfiguration::Emulator + return machineType() == LinuxDeviceConfiguration::Emulator ? defaultHost(LinuxDeviceConfiguration::Emulator) : m_ui->hostNameLineEdit->text().trimmed(); } - QString osType() const + QString deviceType() const { return m_ui->osTypeComboBox->itemData(m_ui->osTypeComboBox->currentIndex()).toString(); } - LinuxDeviceConfiguration::DeviceType deviceType() const + LinuxDeviceConfiguration::MachineType machineType() const { return m_ui->hwButton->isChecked() ? LinuxDeviceConfiguration::Hardware : LinuxDeviceConfiguration::Emulator; @@ -159,14 +160,14 @@ public: int sshPort() const { - return deviceType() == LinuxDeviceConfiguration::Emulator + return machineType() == LinuxDeviceConfiguration::Emulator ? 6666 : m_ui->sshPortSpinBox->value(); } private slots: - void handleDeviceTypeChanged() + void handleMachineTypeChanged() { - const bool enable = deviceType() == LinuxDeviceConfiguration::Hardware; + const bool enable = machineType() == LinuxDeviceConfiguration::Hardware; m_ui->hostNameLabel->setEnabled(enable); m_ui->hostNameLineEdit->setEnabled(enable); m_ui->sshPortLabel->setEnabled(enable); @@ -422,7 +423,7 @@ public: m_ui->deviceAddressLineEdit->setText(m_wizardData.hostName); m_ui->instructionLabel->setText(QString(m_instructionTextTemplate) .replace(QLatin1String("%%%maddev%%%"), - MaemoGlobal::madDeveloperUiName(m_wizardData.osType))); + MaemoGlobal::madDeveloperUiName(m_wizardData.deviceType))); m_ui->passwordLineEdit->clear(); enableInput(); } @@ -446,13 +447,13 @@ private: m_ui->deviceAddressLineEdit->setEnabled(false); m_ui->passwordLineEdit->setEnabled(false); m_ui->deployButton->setEnabled(false); - SshConnectionParameters sshParams(SshConnectionParameters::NoProxy); + SshConnectionParameters sshParams; sshParams.authenticationType = SshConnectionParameters::AuthenticationByPassword; sshParams.host = hostAddress(); sshParams.port = m_wizardData.sshPort; sshParams.password = password(); sshParams.timeout = 10; - sshParams.userName = defaultUser(m_wizardData.osType); + sshParams.userName = defaultUser(m_wizardData.deviceType); m_ui->statusLabel->setText(tr("Deploying... ")); m_keyDeployer->deployPublicKey(sshParams, m_wizardData.publicKeyFilePath); } @@ -468,7 +469,7 @@ private: QMessageBox::information(this, tr("Key Deployment Success"), tr("The key was successfully deployed. You may now close " "the \"%1\" application and continue.") - .arg(MaemoGlobal::madDeveloperUiName(m_wizardData.osType))); + .arg(MaemoGlobal::madDeveloperUiName(m_wizardData.deviceType))); m_ui->statusLabel->setText(m_ui->statusLabel->text() + tr("Done.")); m_isComplete = true; emit completeChanged(); @@ -506,7 +507,7 @@ public: private: QString infoText() const { - if (m_wizardData.deviceType == LinuxDeviceConfiguration::Emulator) + if (m_wizardData.machineType == LinuxDeviceConfiguration::Emulator) return tr("The new device configuration will now be created."); return GenericLinuxDeviceConfigurationWizardFinalPage::infoText(); } @@ -539,7 +540,7 @@ struct MaemoDeviceConfigWizardPrivate MaemoDeviceConfigWizard::MaemoDeviceConfigWizard(QWidget *parent) - : ILinuxDeviceConfigurationWizard(parent), d(new MaemoDeviceConfigWizardPrivate(this)) + : IDeviceWizard(parent), d(new MaemoDeviceConfigWizardPrivate(this)) { setWindowTitle(tr("New Device Configuration Setup")); setPage(StartPageId, &d->startPage); @@ -556,17 +557,17 @@ MaemoDeviceConfigWizard::~MaemoDeviceConfigWizard() delete d; } -LinuxDeviceConfiguration::Ptr MaemoDeviceConfigWizard::deviceConfiguration() +IDevice::Ptr MaemoDeviceConfigWizard::device() { bool doTest; QString freePortsSpec; - Utils::SshConnectionParameters sshParams(Utils::SshConnectionParameters::NoProxy); - sshParams.userName = defaultUser(d->wizardData.osType); + Utils::SshConnectionParameters sshParams; + sshParams.userName = defaultUser(d->wizardData.deviceType); sshParams.host = d->wizardData.hostName; sshParams.port = d->wizardData.sshPort; - if (d->wizardData.deviceType == LinuxDeviceConfiguration::Emulator) { + if (d->wizardData.machineType == LinuxDeviceConfiguration::Emulator) { sshParams.authenticationType = Utils::SshConnectionParameters::AuthenticationByPassword; - sshParams.password = d->wizardData.osType == QLatin1String(MeeGoOsType) + sshParams.password = d->wizardData.deviceType == QLatin1String(MeeGoOsType) ? QLatin1String("meego") : QString(); sshParams.timeout = 30; freePortsSpec = QLatin1String("13219,14168"); @@ -579,8 +580,9 @@ LinuxDeviceConfiguration::Ptr MaemoDeviceConfigWizard::deviceConfiguration() doTest = true; } const LinuxDeviceConfiguration::Ptr devConf = LinuxDeviceConfiguration::create(d->wizardData.configName, - d->wizardData.osType, d->wizardData.deviceType, PortList::fromString(freePortsSpec), - sshParams); + d->wizardData.deviceType, d->wizardData.machineType); + devConf->setFreePorts(PortList::fromString(freePortsSpec)); + devConf->setSshParameters(sshParams); if (doTest) { LinuxDeviceTestDialog dlg(devConf, new MaddeDeviceTester(this), this); dlg.exec(); @@ -593,11 +595,11 @@ int MaemoDeviceConfigWizard::nextId() const switch (currentId()) { case StartPageId: d->wizardData.configName = d->startPage.configName(); - d->wizardData.osType = d->startPage.osType(); d->wizardData.deviceType = d->startPage.deviceType(); + d->wizardData.machineType = d->startPage.machineType(); d->wizardData.hostName = d->startPage.hostName(); d->wizardData.sshPort = d->startPage.sshPort(); - if (d->wizardData.deviceType == LinuxDeviceConfiguration::Emulator) + if (d->wizardData.machineType == LinuxDeviceConfiguration::Emulator) return FinalPageId; return PreviousKeySetupCheckPageId; case PreviousKeySetupCheckPageId: diff --git a/src/plugins/madde/maemodeviceconfigwizard.h b/src/plugins/madde/maemodeviceconfigwizard.h index 99dfba76c5..9ea0f11eab 100644 --- a/src/plugins/madde/maemodeviceconfigwizard.h +++ b/src/plugins/madde/maemodeviceconfigwizard.h @@ -32,14 +32,15 @@ #ifndef MAEMODEVICECONFIGWIZARD_H #define MAEMODEVICECONFIGWIZARD_H -#include <remotelinux/linuxdeviceconfiguration.h> +#include <projectexplorer/devicesupport/idevice.h> +#include <projectexplorer/devicesupport/idevicewizard.h> namespace Madde { namespace Internal { struct MaemoDeviceConfigWizardPrivate; -class MaemoDeviceConfigWizard : public RemoteLinux::ILinuxDeviceConfigurationWizard +class MaemoDeviceConfigWizard : public ProjectExplorer::IDeviceWizard { Q_OBJECT @@ -47,7 +48,7 @@ public: explicit MaemoDeviceConfigWizard(QWidget *parent = 0); ~MaemoDeviceConfigWizard(); - RemoteLinux::LinuxDeviceConfiguration::Ptr deviceConfiguration(); + ProjectExplorer::IDevice::Ptr device(); virtual int nextId() const; diff --git a/src/plugins/madde/maemoglobal.cpp b/src/plugins/madde/maemoglobal.cpp index d59998d803..7ff3b4851f 100644 --- a/src/plugins/madde/maemoglobal.cpp +++ b/src/plugins/madde/maemoglobal.cpp @@ -33,6 +33,7 @@ #include "maemoconstants.h" #include "maemoqemumanager.h" +#include "qt4maemotarget.h" #include <qt4projectmanager/qt4projectmanagerconstants.h> #include <qtsupport/baseqtversion.h> @@ -92,9 +93,9 @@ bool MaemoGlobal::isValidMeegoQtVersion(const QString &qmakePath) return isValidMaemoQtVersion(qmakePath, QLatin1String(MeeGoOsType)); } -bool MaemoGlobal::isValidMaemoQtVersion(const QString &qmakePath, const QString &osType) +bool MaemoGlobal::isValidMaemoQtVersion(const QString &qmakePath, const QString &deviceType) { - if (MaemoGlobal::osType(qmakePath) != osType) + if (MaemoGlobal::deviceType(qmakePath) != deviceType) return false; QProcess madAdminProc; const QStringList arguments(QLatin1String("list")); @@ -127,17 +128,17 @@ QString MaemoGlobal::devrootshPath() return QLatin1String("/usr/lib/mad-developer/devrootsh"); } -int MaemoGlobal::applicationIconSize(const QString &osType) +int MaemoGlobal::applicationIconSize(const ProjectExplorer::Target *target) { - return osType == QLatin1String(HarmattanOsType) ? 80 : 64; + return qobject_cast<const Qt4HarmattanTarget *>(target) ? 80 : 64; } -QString MaemoGlobal::remoteSudo(const QString &osType, const QString &uname) +QString MaemoGlobal::remoteSudo(const QString &deviceType, const QString &uname) { if (uname == QLatin1String("root")) return QString(); - if (osType == QLatin1String(Maemo5OsType) || osType == QLatin1String(HarmattanOsType) - || osType == QLatin1String(MeeGoOsType)) { + if (deviceType == QLatin1String(Maemo5OsType) || deviceType == QLatin1String(HarmattanOsType) + || deviceType == QLatin1String(MeeGoOsType)) { return devrootshPath(); } return QString(); // Using sudo would open a can of worms. @@ -153,12 +154,12 @@ QString MaemoGlobal::remoteSourceProfilesCommand() return QString::fromAscii(remoteCall); } -PortList MaemoGlobal::freePorts(const LinuxDeviceConfiguration::ConstPtr &devConf, +Utils::PortList MaemoGlobal::freePorts(const LinuxDeviceConfiguration::ConstPtr &devConf, const QtSupport::BaseQtVersion *qtVersion) { if (!devConf || !qtVersion) - return PortList(); - if (devConf->deviceType() == LinuxDeviceConfiguration::Emulator) { + return Utils::PortList(); + if (devConf->machineType() == LinuxDeviceConfiguration::Emulator) { MaemoQemuRuntime rt; const int id = qtVersion->uniqueId(); if (MaemoQemuManager::instance().runtimeForQtVersion(id, &rt)) @@ -199,13 +200,13 @@ QString MaemoGlobal::madCommand(const QString &qmakePath) return maddeRoot(qmakePath) + QLatin1String("/bin/mad"); } -QString MaemoGlobal::madDeveloperUiName(const QString &osType) +QString MaemoGlobal::madDeveloperUiName(const QString &deviceType) { - return osType == QLatin1String(HarmattanOsType) + return deviceType == QLatin1String(HarmattanOsType) ? tr("SDK Connectivity") : tr("Mad Developer"); } -QString MaemoGlobal::osType(const QString &qmakePath) +QString MaemoGlobal::deviceType(const QString &qmakePath) { const QString &name = targetName(qmakePath); if (name.startsWith(QLatin1String("fremantle"))) diff --git a/src/plugins/madde/maemoglobal.h b/src/plugins/madde/maemoglobal.h index 3fb9b54aac..9dfc1b2742 100644 --- a/src/plugins/madde/maemoglobal.h +++ b/src/plugins/madde/maemoglobal.h @@ -34,7 +34,7 @@ #define MAEMOGLOBAL_H #include <coreplugin/idocument.h> -#include <remotelinux/portlist.h> +#include <utils/portlist.h> #include <utils/environment.h> #include <QCoreApplication> @@ -45,13 +45,9 @@ class QProcess; class QString; QT_END_NAMESPACE -namespace QtSupport { -class BaseQtVersion; -} - -namespace RemoteLinux { -class LinuxDeviceConfiguration; -} +namespace QtSupport { class BaseQtVersion; } +namespace RemoteLinux { class LinuxDeviceConfiguration; } +namespace ProjectExplorer { class Target; } namespace Madde { namespace Internal { @@ -97,10 +93,10 @@ public: static QString homeDirOnDevice(const QString &uname); static QString devrootshPath(); - static int applicationIconSize(const QString &osType); - static QString remoteSudo(const QString &osType, const QString &uname); + static int applicationIconSize(const ProjectExplorer::Target *target); + static QString remoteSudo(const QString &deviceType, const QString &uname); static QString remoteSourceProfilesCommand(); - static RemoteLinux::PortList freePorts(const QSharedPointer<const RemoteLinux::LinuxDeviceConfiguration> &devConf, + static Utils::PortList freePorts(const QSharedPointer<const RemoteLinux::LinuxDeviceConfiguration> &devConf, const QtSupport::BaseQtVersion *qtVersion); static void addMaddeEnvironment(Utils::Environment &env, const QString &qmakePath); @@ -109,8 +105,8 @@ public: static QString targetRoot(const QString &qmakePath); static QString targetName(const QString &qmakePath); static QString madCommand(const QString &qmakePath); - static QString madDeveloperUiName(const QString &osType); - static QString osType(const QString &qmakePath); + static QString madDeveloperUiName(const QString &deviceType); + static QString deviceType(const QString &qmakePath); // TODO: IS this still needed with Qt Version having an Abi? static QString architecture(const QString &qmakePath); @@ -120,7 +116,7 @@ public: static bool callMadAdmin(QProcess &proc, const QStringList &args, const QString &qmakePath, bool useTarget); - static bool isValidMaemoQtVersion(const QString &qmakePath, const QString &osType); + static bool isValidMaemoQtVersion(const QString &qmakePath, const QString &deviceType); private: static QString madAdminCommand(const QString &qmakePath); static bool callMaddeShellScript(QProcess &proc, const QString &qmakePath, diff --git a/src/plugins/madde/maemopublisherfremantlefree.cpp b/src/plugins/madde/maemopublisherfremantlefree.cpp index cf39195f66..896a138513 100644 --- a/src/plugins/madde/maemopublisherfremantlefree.cpp +++ b/src/plugins/madde/maemopublisherfremantlefree.cpp @@ -69,7 +69,6 @@ MaemoPublisherFremantleFree::MaemoPublisherFremantleFree(const ProjectExplorer:: QObject(parent), m_project(project), m_state(Inactive), - m_sshParams(SshConnectionParameters::DefaultProxy), m_uploader(0) { m_sshParams.authenticationType = SshConnectionParameters::AuthenticationByKey; diff --git a/src/plugins/madde/maemopublishingbuildsettingspagefremantlefree.cpp b/src/plugins/madde/maemopublishingbuildsettingspagefremantlefree.cpp index 53da32fe71..396d1246e3 100644 --- a/src/plugins/madde/maemopublishingbuildsettingspagefremantlefree.cpp +++ b/src/plugins/madde/maemopublishingbuildsettingspagefremantlefree.cpp @@ -86,7 +86,7 @@ void MaemoPublishingBuildSettingsPageFremantleFree::collectBuildConfigurations(c QtSupport::BaseQtVersion *lqt = qt4Bc->qtVersion(); if (!lqt) continue; - if (MaemoGlobal::osType(lqt->qmakeCommand().toString()) == QLatin1String(Maemo5OsType)) + if (MaemoGlobal::deviceType(lqt->qmakeCommand().toString()) == QLatin1String(Maemo5OsType)) m_buildConfigs << qt4Bc; } break; diff --git a/src/plugins/madde/maemopublishingwizardfactories.cpp b/src/plugins/madde/maemopublishingwizardfactories.cpp index eb90bde72b..6524527856 100644 --- a/src/plugins/madde/maemopublishingwizardfactories.cpp +++ b/src/plugins/madde/maemopublishingwizardfactories.cpp @@ -84,7 +84,7 @@ bool MaemoPublishingWizardFactoryFremantleFree::canCreateWizard(const Project *p QtSupport::BaseQtVersion *qt = qt4Bc->qtVersion(); if (!qt) continue; - if (MaemoGlobal::osType(qt->qmakeCommand().toString()) == QLatin1String(Maemo5OsType)) + if (MaemoGlobal::deviceType(qt->qmakeCommand().toString()) == QLatin1String(Maemo5OsType)) return true; } break; diff --git a/src/plugins/madde/maemoqemumanager.cpp b/src/plugins/madde/maemoqemumanager.cpp index 4f0a29e783..49d2ee10eb 100644 --- a/src/plugins/madde/maemoqemumanager.cpp +++ b/src/plugins/madde/maemoqemumanager.cpp @@ -593,7 +593,7 @@ bool MaemoQemuManager::targetUsesMatchingRuntimeConfig(Target *target, if (qtVersion) *qtVersion = version; const LinuxDeviceConfiguration::ConstPtr &config = mrc->deviceConfig(); - return config && config->deviceType() == LinuxDeviceConfiguration::Emulator; + return config && config->machineType() == LinuxDeviceConfiguration::Emulator; } void MaemoQemuManager::notify(const QList<int> uniqueIds) diff --git a/src/plugins/madde/maemoqemuruntime.h b/src/plugins/madde/maemoqemuruntime.h index 04adfd255a..6b06cb489c 100644 --- a/src/plugins/madde/maemoqemuruntime.h +++ b/src/plugins/madde/maemoqemuruntime.h @@ -34,7 +34,7 @@ #include "maemoqemusettings.h" -#include <remotelinux/portlist.h> +#include <utils/portlist.h> #include <QHash> #include <QList> @@ -79,7 +79,7 @@ struct MaemoQemuRuntime QString m_args; QString m_sshPort; QString m_watchPath; - RemoteLinux::PortList m_freePorts; + Utils::PortList m_freePorts; QList<Variable> m_normalVars; QString m_openGlBackendVarName; QHash<MaemoQemuSettings::OpenGlMode, QString> m_openGlBackendVarValues; diff --git a/src/plugins/madde/maemoqemuruntimeparser.cpp b/src/plugins/madde/maemoqemuruntimeparser.cpp index 0c6979ce73..e889dbe075 100644 --- a/src/plugins/madde/maemoqemuruntimeparser.cpp +++ b/src/plugins/madde/maemoqemuruntimeparser.cpp @@ -190,7 +190,7 @@ void MaemoQemuRuntimeParserV1::fillRuntimeInformation(MaemoQemuRuntime *runtime) runtime->m_args = map.value(QLatin1String("qemu_args")); setEnvironment(runtime, map.value(QLatin1String("libpath"))); runtime->m_sshPort = map.value(QLatin1String("sshport")); - runtime->m_freePorts = PortList(); + runtime->m_freePorts = Utils::PortList(); int i = 2; while (true) { const QString port = map.value(QLatin1String("redirport") diff --git a/src/plugins/madde/maemoqtversion.cpp b/src/plugins/madde/maemoqtversion.cpp index 6c5a692a81..1ca3e9f8bc 100644 --- a/src/plugins/madde/maemoqtversion.cpp +++ b/src/plugins/madde/maemoqtversion.cpp @@ -57,7 +57,7 @@ MaemoQtVersion::MaemoQtVersion() MaemoQtVersion::MaemoQtVersion(const Utils::FileName &path, bool isAutodetected, const QString &autodetectionSource) : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource), - m_osType(MaemoGlobal::osType(path.toString())), + m_deviceType(MaemoGlobal::deviceType(path.toString())), m_isvalidVersion(false), m_initialized(false) { @@ -73,7 +73,7 @@ void MaemoQtVersion::fromMap(const QVariantMap &map) { QtSupport::BaseQtVersion::fromMap(map); QString path = qmakeCommand().toString(); - m_osType = MaemoGlobal::osType(path); + m_deviceType = MaemoGlobal::deviceType(path); } QString MaemoQtVersion::type() const @@ -86,7 +86,7 @@ bool MaemoQtVersion::isValid() const if (!BaseQtVersion::isValid()) return false; if (!m_initialized) { - m_isvalidVersion = MaemoGlobal::isValidMaemoQtVersion(qmakeCommand().toString(), m_osType); + m_isvalidVersion = MaemoGlobal::isValidMaemoQtVersion(qmakeCommand().toString(), m_deviceType); m_initialized = true; } return m_isvalidVersion; @@ -124,16 +124,16 @@ QList<ProjectExplorer::Abi> MaemoQtVersion::detectQtAbis() const QList<ProjectExplorer::Abi> result; if (!isValid()) return result; - if (m_osType == QLatin1String(Maemo5OsType)) { + if (m_deviceType == QLatin1String(Maemo5OsType)) { result.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, ProjectExplorer::Abi::LinuxOS, ProjectExplorer::Abi::MaemoLinuxFlavor, ProjectExplorer::Abi::ElfFormat, 32)); - } else if (m_osType == QLatin1String(HarmattanOsType)) { + } else if (m_deviceType == QLatin1String(HarmattanOsType)) { result.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, ProjectExplorer::Abi::LinuxOS, ProjectExplorer::Abi::HarmattanLinuxFlavor, ProjectExplorer::Abi::ElfFormat, 32)); - } else if (m_osType == QLatin1String(MeeGoOsType)) { + } else if (m_deviceType == QLatin1String(MeeGoOsType)) { result.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, ProjectExplorer::Abi::LinuxOS, ProjectExplorer::Abi::MeegoLinuxFlavor, ProjectExplorer::Abi::ElfFormat, 32)); @@ -151,11 +151,11 @@ QSet<QString> MaemoQtVersion::supportedTargetIds() const QSet<QString> result; if (!isValid()) return result; - if (m_osType == QLatin1String(Maemo5OsType)) { + if (m_deviceType == QLatin1String(Maemo5OsType)) { result.insert(QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID)); - } else if (m_osType == QLatin1String(HarmattanOsType)) { + } else if (m_deviceType == QLatin1String(HarmattanOsType)) { result.insert(QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID)); - } else if (m_osType == QLatin1String(MeeGoOsType)) { + } else if (m_deviceType == QLatin1String(MeeGoOsType)) { result.insert(QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID)); } return result; @@ -163,11 +163,11 @@ QSet<QString> MaemoQtVersion::supportedTargetIds() const QString MaemoQtVersion::description() const { - if (m_osType == QLatin1String(Maemo5OsType)) + if (m_deviceType == QLatin1String(Maemo5OsType)) return QCoreApplication::translate("QtVersion", "Maemo", "Qt Version is meant for Maemo5"); - else if (m_osType == QLatin1String(HarmattanOsType)) + else if (m_deviceType == QLatin1String(HarmattanOsType)) return QCoreApplication::translate("QtVersion", "Harmattan ", "Qt Version is meant for Harmattan"); - else if (m_osType == QLatin1String(MeeGoOsType)) + else if (m_deviceType == QLatin1String(MeeGoOsType)) return QCoreApplication::translate("QtVersion", "MeeGo", "Qt Version is meant for MeeGo"); return QString(); } @@ -180,9 +180,9 @@ bool MaemoQtVersion::supportsShadowBuilds() const return true; } -QString MaemoQtVersion::osType() const +QString MaemoQtVersion::deviceType() const { - return m_osType; + return m_deviceType; } Core::FeatureSet MaemoQtVersion::availableFeatures() const @@ -192,7 +192,7 @@ Core::FeatureSet MaemoQtVersion::availableFeatures() const features |= Core::FeatureSet(QtSupport::Constants::FEATURE_QTQUICK_COMPONENTS_MEEGO); features |= Core::FeatureSet(QtSupport::Constants::FEATURE_MOBILE); - if (osType() != QLatin1String(Maemo5OsType)) //Only Maemo5 has proper support for Widgets + if (deviceType() != QLatin1String(Maemo5OsType)) //Only Maemo5 has proper support for Widgets features.remove(Core::Feature(QtSupport::Constants::FEATURE_QWIDGETS)); return features; diff --git a/src/plugins/madde/maemoqtversion.h b/src/plugins/madde/maemoqtversion.h index 2b55c2cee8..ec65f43fcc 100644 --- a/src/plugins/madde/maemoqtversion.h +++ b/src/plugins/madde/maemoqtversion.h @@ -59,14 +59,14 @@ public: QString description() const; bool supportsShadowBuilds() const; - QString osType() const; + QString deviceType() const; Core::FeatureSet availableFeatures() const; QString platformName() const; QString platformDisplayName() const; private: mutable QString m_systemRoot; - mutable QString m_osType; + mutable QString m_deviceType; mutable bool m_isvalidVersion; mutable bool m_initialized; }; diff --git a/src/plugins/madde/maemoremotecopyfacility.cpp b/src/plugins/madde/maemoremotecopyfacility.cpp index 849c497514..574a2efcba 100644 --- a/src/plugins/madde/maemoremotecopyfacility.cpp +++ b/src/plugins/madde/maemoremotecopyfacility.cpp @@ -138,7 +138,7 @@ void MaemoRemoteCopyFacility::copyNextFile() #endif QString command = QString::fromLatin1("%1 mkdir -p %3 && %1 cp -a %2 %3") - .arg(MaemoGlobal::remoteSudo(m_devConf->osType(), m_devConf->sshParameters().userName), + .arg(MaemoGlobal::remoteSudo(m_devConf->type(), m_devConf->sshParameters().userName), sourceFilePath, d.remoteDir); emit progress(tr("Copying file '%1' to directory '%2' on the device...") .arg(d.localFilePath, d.remoteDir)); diff --git a/src/plugins/madde/maemoremotemounter.cpp b/src/plugins/madde/maemoremotemounter.cpp index fd39e54855..c8de89c90a 100644 --- a/src/plugins/madde/maemoremotemounter.cpp +++ b/src/plugins/madde/maemoremotemounter.cpp @@ -129,7 +129,7 @@ void MaemoRemoteMounter::unmount() } QString remoteCall; - const QString remoteSudo = MaemoGlobal::remoteSudo(m_devConf->osType(), + const QString remoteSudo = MaemoGlobal::remoteSudo(m_devConf->type(), m_connection->connectionParameters().userName); for (int i = 0; i < m_mountSpecs.count(); ++i) { remoteCall += QString::fromLatin1("%1 umount %2 && %1 rmdir %2;") @@ -188,7 +188,7 @@ void MaemoRemoteMounter::stop() void MaemoRemoteMounter::startUtfsClients() { const QString userName = m_connection->connectionParameters().userName; - const QString chmodFuse = MaemoGlobal::remoteSudo(m_devConf->osType(), + const QString chmodFuse = MaemoGlobal::remoteSudo(m_devConf->type(), userName) + QLatin1String(" chmod a+r+w /dev/fuse"); const QString chmodUtfsClient = QLatin1String("chmod a+x ") + utfsClientOnDevice(); @@ -205,7 +205,7 @@ void MaemoRemoteMounter::startUtfsClients() } const QString remoteSudo - = MaemoGlobal::remoteSudo(m_devConf->osType(), userName); + = MaemoGlobal::remoteSudo(m_devConf->type(), userName); const MaemoMountSpecification &mountSpec = mountInfo.mountSpec; const QString mkdir = QString::fromLatin1("%1 mkdir -p %2") .arg(remoteSudo, mountSpec.remoteMountPoint); @@ -216,7 +216,7 @@ void MaemoRemoteMounter::startUtfsClients() .arg(utfsClientOnDevice()).arg(mountInfo.remotePort) .arg(mountSpec.remoteMountPoint); if (mountInfo.mountAsRoot) { - utfsClient.prepend(MaemoGlobal::remoteSudo(m_devConf->osType(), + utfsClient.prepend(MaemoGlobal::remoteSudo(m_devConf->type(), userName) + QLatin1Char(' ')); } QLatin1String seqOp("; "); diff --git a/src/plugins/madde/maemoremotemounter.h b/src/plugins/madde/maemoremotemounter.h index d01cdec728..8c4fa5c00d 100644 --- a/src/plugins/madde/maemoremotemounter.h +++ b/src/plugins/madde/maemoremotemounter.h @@ -44,6 +44,7 @@ QT_FORWARD_DECLARE_CLASS(QTimer) namespace Utils { +class PortList; class SftpChannel; class SshConnection; class SshRemoteProcess; @@ -53,7 +54,6 @@ namespace Qt4ProjectManager { class Qt4BuildConfiguration; } namespace RemoteLinux { class LinuxDeviceConfiguration; -class PortList; class RemoteLinuxUsedPortsGatherer; } @@ -76,7 +76,7 @@ public: bool mountAsRoot); bool hasValidMountSpecifications() const; void resetMountSpecifications() { m_mountSpecs.clear(); } - void mount(RemoteLinux::PortList *freePorts, + void mount(Utils::PortList *freePorts, const RemoteLinux::RemoteLinuxUsedPortsGatherer *portsGatherer); void unmount(); void stop(); @@ -132,7 +132,7 @@ private: typedef QSharedPointer<QProcess> ProcPtr; QList<ProcPtr> m_utfsServers; - RemoteLinux::PortList *m_freePorts; + Utils::PortList *m_freePorts; const RemoteLinux::RemoteLinuxUsedPortsGatherer *m_portsGatherer; bool m_remoteMountsAllowed; QString m_maddeRoot; diff --git a/src/plugins/madde/maemorunconfiguration.cpp b/src/plugins/madde/maemorunconfiguration.cpp index 845d1422fb..04d3e15853 100644 --- a/src/plugins/madde/maemorunconfiguration.cpp +++ b/src/plugins/madde/maemorunconfiguration.cpp @@ -41,7 +41,7 @@ #include <projectexplorer/project.h> #include <projectexplorer/projectexplorerconstants.h> #include <qt4projectmanager/qt4buildconfiguration.h> -#include <remotelinux/portlist.h> +#include <utils/portlist.h> #include <utils/ssh/sshconnection.h> #include <QDir> @@ -125,18 +125,18 @@ QString MaemoRunConfiguration::commandPrefix() const return QString(); QString prefix = environmentPreparationCommand() + QLatin1Char(';'); - if (deviceConfig()->osType() == QLatin1String(MeeGoOsType)) + if (deviceConfig()->type() == QLatin1String(MeeGoOsType)) prefix += QLatin1String("DISPLAY=:0.0 "); return QString::fromLatin1("%1 %2").arg(prefix, userEnvironmentChangesAsString()); } -PortList MaemoRunConfiguration::freePorts() const +Utils::PortList MaemoRunConfiguration::freePorts() const { const Qt4BuildConfiguration * const bc = activeQt4BuildConfiguration(); return bc && deployConfig() ? MaemoGlobal::freePorts(deployConfig()->deviceConfiguration(), bc->qtVersion()) - : PortList(); + : Utils::PortList(); } QString MaemoRunConfiguration::localDirToMountForRemoteGdb() const diff --git a/src/plugins/madde/maemorunconfiguration.h b/src/plugins/madde/maemorunconfiguration.h index 3499e30679..ecd93e9be6 100644 --- a/src/plugins/madde/maemorunconfiguration.h +++ b/src/plugins/madde/maemorunconfiguration.h @@ -52,7 +52,7 @@ public: QWidget *createConfigurationWidget(); QString environmentPreparationCommand() const; QString commandPrefix() const; - RemoteLinux::PortList freePorts() const; + Utils::PortList freePorts() const; Internal::MaemoRemoteMountsModel *remoteMounts() const { return m_remoteMounts; } bool hasEnoughFreePorts(ProjectExplorer::RunMode mode) const; diff --git a/src/plugins/madde/maemorunconfigurationwidget.cpp b/src/plugins/madde/maemorunconfigurationwidget.cpp index 95d238c8af..137f19d479 100644 --- a/src/plugins/madde/maemorunconfigurationwidget.cpp +++ b/src/plugins/madde/maemorunconfigurationwidget.cpp @@ -93,13 +93,14 @@ MaemoRunConfigurationWidget::MaemoRunConfigurationWidget( = qobject_cast<AbstractQt4MaemoTarget *>(runConfiguration->target()); m_mountDetailsContainer->setVisible(maemoTarget->allowsRemoteMounts()); - connect(m_runConfiguration, SIGNAL(isEnabledChanged(bool)), - this, SLOT(runConfigurationEnabledChange(bool))); - runConfigurationEnabledChange(m_runConfiguration->isEnabled()); + connect(m_runConfiguration, SIGNAL(enabledChanged()), + this, SLOT(runConfigurationEnabledChange())); + runConfigurationEnabledChange(); } -void MaemoRunConfigurationWidget::runConfigurationEnabledChange(bool enabled) +void MaemoRunConfigurationWidget::runConfigurationEnabledChange() { + bool enabled = m_runConfiguration->isEnabled(); m_subWidget->setEnabled(enabled); } @@ -214,7 +215,7 @@ void MaemoRunConfigurationWidget::handleRemoteMountsChanged() void MaemoRunConfigurationWidget::updateMountWarning() { QString mountWarning; - const PortList &portList = m_runConfiguration->freePorts(); + const Utils::PortList &portList = m_runConfiguration->freePorts(); const int availablePortCount = portList.count(); const int mountDirCount = m_runConfiguration->remoteMounts()->validMountSpecificationCount(); diff --git a/src/plugins/madde/maemorunconfigurationwidget.h b/src/plugins/madde/maemorunconfigurationwidget.h index d25e1b69db..cf738827f5 100644 --- a/src/plugins/madde/maemorunconfigurationwidget.h +++ b/src/plugins/madde/maemorunconfigurationwidget.h @@ -66,7 +66,7 @@ private slots: void enableOrDisableRemoveMountSpecButton(); void handleRemoteMountsChanged(); void updateMountWarning(); - void runConfigurationEnabledChange(bool enabled); + void runConfigurationEnabledChange(); private: void addMountWidgets(QVBoxLayout *mainLayout); diff --git a/src/plugins/madde/maemosettingspages.cpp b/src/plugins/madde/maemosettingspages.cpp index d93f8588f2..4f7a618f9f 100644 --- a/src/plugins/madde/maemosettingspages.cpp +++ b/src/plugins/madde/maemosettingspages.cpp @@ -34,7 +34,7 @@ #include "maemoqemusettingswidget.h" #include <coreplugin/icore.h> -#include <remotelinux/remotelinux_constants.h> +#include <projectexplorer/projectexplorerconstants.h> #include <QCoreApplication> #include <QDialog> @@ -169,7 +169,7 @@ QString MaemoQemuSettingsPage::pageId() QString MaemoQemuSettingsPage::pageCategory() { - return QLatin1String(RemoteLinux::Constants::RemoteLinuxSettingsCategory); + return QLatin1String(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY); } } // namespace Internal diff --git a/src/plugins/madde/maemosshrunner.cpp b/src/plugins/madde/maemosshrunner.cpp index 846ef068e8..219b93515a 100644 --- a/src/plugins/madde/maemosshrunner.cpp +++ b/src/plugins/madde/maemosshrunner.cpp @@ -73,7 +73,7 @@ bool MaemoSshRunner::canRun(QString &whyNot) const if (!AbstractRemoteLinuxApplicationRunner::canRun(whyNot)) return false; - if (devConfig()->deviceType() == LinuxDeviceConfiguration::Emulator + if (devConfig()->machineType() == LinuxDeviceConfiguration::Emulator && !MaemoQemuManager::instance().qemuIsRunning()) { MaemoQemuRuntime rt; if (MaemoQemuManager::instance().runtimeForQtVersion(m_qtId, &rt)) { diff --git a/src/plugins/madde/qt4maemotarget.cpp b/src/plugins/madde/qt4maemotarget.cpp index 377ea648dd..b64eb3bfd9 100644 --- a/src/plugins/madde/qt4maemotarget.cpp +++ b/src/plugins/madde/qt4maemotarget.cpp @@ -122,8 +122,8 @@ bool adaptTagValue(QByteArray &document, const QByteArray &fieldName, AbstractQt4MaemoTarget::AbstractQt4MaemoTarget(Qt4Project *parent, const QString &id, - const QString &supportedOsType, const QString &qmakeScope) : - AbstractEmbeddedLinuxTarget(parent, id, supportedOsType), + const QString &qmakeScope) : + AbstractEmbeddedLinuxTarget(parent, id), m_filesWatcher(new Utils::FileSystemWatcher(this)), m_deploymentSettingsAssistant(new DeploymentSettingsAssistant(qmakeScope, QLatin1String("/opt"), deploymentInfo())), @@ -375,8 +375,8 @@ void AbstractQt4MaemoTarget::raiseError(const QString &reason) } AbstractDebBasedQt4MaemoTarget::AbstractDebBasedQt4MaemoTarget(Qt4Project *parent, - const QString &id, const QString &supportedOsType, const QString &qmakeScope) - : AbstractQt4MaemoTarget(parent, id, supportedOsType, qmakeScope) + const QString &id, const QString &qmakeScope) + : AbstractQt4MaemoTarget(parent, id, qmakeScope) { } @@ -958,8 +958,8 @@ QString AbstractDebBasedQt4MaemoTarget::shortDayOfWeekName(const QDateTime &dt) AbstractRpmBasedQt4MaemoTarget::AbstractRpmBasedQt4MaemoTarget(Qt4Project *parent, - const QString &id, const QString &supportedOsType, const QString &qmakeScope) - : AbstractQt4MaemoTarget(parent, id, supportedOsType, qmakeScope) + const QString &id, const QString &qmakeScope) + : AbstractQt4MaemoTarget(parent, id, qmakeScope) { } @@ -1124,14 +1124,18 @@ bool AbstractRpmBasedQt4MaemoTarget::setValueForTag(const QByteArray &tag, } Qt4Maemo5Target::Qt4Maemo5Target(Qt4Project *parent, const QString &id) - : AbstractDebBasedQt4MaemoTarget(parent, id, QLatin1String(Maemo5OsType), - QLatin1String("maemo5")) + : AbstractDebBasedQt4MaemoTarget(parent, id, QLatin1String("maemo5")) { setDisplayName(defaultDisplayName()); } Qt4Maemo5Target::~Qt4Maemo5Target() {} +bool Qt4Maemo5Target::supportsDevice(const ProjectExplorer::IDevice::ConstPtr &device) const +{ + return device->type() == QLatin1String(Maemo5OsType); +} + QString Qt4Maemo5Target::defaultDisplayName() { return QApplication::translate("Qt4ProjectManager::Qt4Target", "Maemo5", @@ -1164,14 +1168,18 @@ QByteArray Qt4Maemo5Target::defaultSection() const } Qt4HarmattanTarget::Qt4HarmattanTarget(Qt4Project *parent, const QString &id) - : AbstractDebBasedQt4MaemoTarget(parent, id, QLatin1String(HarmattanOsType), - QLatin1String("contains(MEEGO_EDITION,harmattan)")) + : AbstractDebBasedQt4MaemoTarget(parent, id, QLatin1String("contains(MEEGO_EDITION,harmattan)")) { setDisplayName(defaultDisplayName()); } Qt4HarmattanTarget::~Qt4HarmattanTarget() {} +bool Qt4HarmattanTarget::supportsDevice(const ProjectExplorer::IDevice::ConstPtr &device) const +{ + return device->type() == QLatin1String(HarmattanOsType); +} + QString Qt4HarmattanTarget::defaultDisplayName() { return QApplication::translate("Qt4ProjectManager::Qt4Target", "Harmattan", @@ -1208,7 +1216,9 @@ void Qt4HarmattanTarget::handleTargetAddedSpecial() void Qt4HarmattanTarget::addAdditionalControlFileFields(QByteArray &controlContents) { - Q_UNUSED(controlContents); + adaptControlFileField(controlContents, "XB-Maemo-Flags", "visible"); + adaptControlFileField(controlContents, "XB-MeeGo-Desktop-Entry-Filename", QString::fromLatin1("%1_harmattan").arg(project()->displayName()).toUtf8()); + adaptControlFileField(controlContents, "XB-MeeGo-Desktop-Entry", QString::fromLatin1("\n [Desktop Entry]\n Type=Application\n Name=%1\n Icon=/usr/share/icons/hicolor/80x80/apps/%1%2.png").arg(project()->displayName()).arg(80).toUtf8()); } QString Qt4HarmattanTarget::debianDirName() const @@ -1233,7 +1243,7 @@ QByteArray Qt4HarmattanTarget::defaultSection() const Qt4MeegoTarget::Qt4MeegoTarget(Qt4Project *parent, const QString &id) - : AbstractRpmBasedQt4MaemoTarget(parent, id, QLatin1String(MeeGoOsType), + : AbstractRpmBasedQt4MaemoTarget(parent, id, QLatin1String("!isEmpty(MEEGO_VERSION_MAJOR):!contains(MEEGO_EDITION,harmattan)")) { setDisplayName(defaultDisplayName()); @@ -1241,6 +1251,11 @@ Qt4MeegoTarget::Qt4MeegoTarget(Qt4Project *parent, const QString &id) Qt4MeegoTarget::~Qt4MeegoTarget() {} +bool Qt4MeegoTarget::supportsDevice(const ProjectExplorer::IDevice::ConstPtr &device) const +{ + return device->type() == QLatin1String(MeeGoOsType); +} + QString Qt4MeegoTarget::defaultDisplayName() { return QApplication::translate("Qt4ProjectManager::Qt4Target", diff --git a/src/plugins/madde/qt4maemotarget.h b/src/plugins/madde/qt4maemotarget.h index 4489521981..3be2877d96 100644 --- a/src/plugins/madde/qt4maemotarget.h +++ b/src/plugins/madde/qt4maemotarget.h @@ -57,7 +57,7 @@ class AbstractQt4MaemoTarget : public RemoteLinux::AbstractEmbeddedLinuxTarget Q_OBJECT public: explicit AbstractQt4MaemoTarget(Qt4ProjectManager::Qt4Project *parent, const QString &id, - const QString &supportedOsType, const QString &qmakeScope); + const QString &qmakeScope); virtual ~AbstractQt4MaemoTarget(); void createApplicationProFiles(bool reparse); @@ -120,7 +120,7 @@ class AbstractDebBasedQt4MaemoTarget : public AbstractQt4MaemoTarget Q_OBJECT public: AbstractDebBasedQt4MaemoTarget(Qt4ProjectManager::Qt4Project *parent, const QString &id, - const QString &supportedOsType, const QString &qmakeScope); + const QString &qmakeScope); ~AbstractDebBasedQt4MaemoTarget(); QString debianDirPath() const; @@ -193,7 +193,7 @@ class AbstractRpmBasedQt4MaemoTarget : public AbstractQt4MaemoTarget Q_OBJECT public: AbstractRpmBasedQt4MaemoTarget(Qt4ProjectManager::Qt4Project *parent, const QString &id, - const QString &supportedOsType, const QString &qmakeScope); + const QString &qmakeScope); ~AbstractRpmBasedQt4MaemoTarget(); virtual bool allowsRemoteMounts() const { return false; } @@ -240,6 +240,8 @@ public: const QString &id); virtual ~Qt4Maemo5Target(); + virtual bool supportsDevice(const QSharedPointer<const ProjectExplorer::IDevice> &device) const; + virtual bool allowsRemoteMounts() const { return true; } virtual bool allowsPackagingDisabling() const { return true; } virtual bool allowsQmlDebugging() const { return false; } @@ -264,6 +266,8 @@ public: const QString &id); virtual ~Qt4HarmattanTarget(); + virtual bool supportsDevice(const QSharedPointer<const ProjectExplorer::IDevice> &device) const; + virtual bool allowsRemoteMounts() const { return false; } virtual bool allowsPackagingDisabling() const { return false; } virtual bool allowsQmlDebugging() const { return true; } @@ -289,6 +293,7 @@ public: explicit Qt4MeegoTarget(Qt4ProjectManager::Qt4Project *parent, const QString &id); virtual ~Qt4MeegoTarget(); + virtual bool supportsDevice(const QSharedPointer<const ProjectExplorer::IDevice> &device) const; static QString defaultDisplayName(); private: virtual QString specFileName() const; diff --git a/src/plugins/mercurial/mercurialplugin.h b/src/plugins/mercurial/mercurialplugin.h index f020d67244..17596be5f3 100644 --- a/src/plugins/mercurial/mercurialplugin.h +++ b/src/plugins/mercurial/mercurialplugin.h @@ -68,6 +68,7 @@ class MercurialSettings; class MercurialPlugin : public VcsBase::VcsBasePlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Mercurial.json") public: MercurialPlugin(); diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h index 1c2f7ed36c..51ae8cc2bd 100644 --- a/src/plugins/perforce/perforceplugin.h +++ b/src/plugins/perforce/perforceplugin.h @@ -80,6 +80,7 @@ struct PerforceResponse class PerforcePlugin : public VcsBase::VcsBasePlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Perforce.json") public: PerforcePlugin(); diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index e1058767cd..0bfef636e1 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -58,7 +58,7 @@ linux-* { include(../../qtcreator.pri) -contains(QT_CONFIG, declarative) { +contains(QT_CONFIG, declarative)|contains(QT_CONFIG, quick1) { SUBDIRS += \ plugin_qmlprojectmanager \ plugin_qmljsinspector @@ -120,6 +120,7 @@ plugin_vcsbase.depends = plugin_find plugin_vcsbase.depends += plugin_texteditor plugin_vcsbase.depends += plugin_coreplugin plugin_vcsbase.depends += plugin_projectexplorer +plugin_vcsbase.depends += plugin_cpptools plugin_perforce.subdir = perforce plugin_perforce.depends = plugin_vcsbase @@ -253,6 +254,7 @@ plugin_qmldesigner.depends += plugin_qmljseditor plugin_qmldesigner.depends += plugin_projectexplorer plugin_qmldesigner.depends += plugin_qt4projectmanager plugin_qmldesigner.depends += plugin_qmlprojectmanager +plugin_qmldesigner.depends += plugin_cpptools plugin_qmljsinspector.subdir = qmljsinspector plugin_qmljsinspector.depends += plugin_projectexplorer @@ -283,6 +285,7 @@ plugin_analyzerbase.subdir = analyzerbase plugin_analyzerbase.depends = plugin_coreplugin plugin_analyzerbase.depends += plugin_projectexplorer plugin_analyzerbase.depends += plugin_remotelinux +plugin_analyzerbase.depends += plugin_cpptools plugin_valgrind.subdir = valgrind plugin_valgrind.depends = plugin_coreplugin @@ -300,6 +303,7 @@ plugin_qmljstools.depends = plugin_projectexplorer plugin_qmljstools.depends += plugin_coreplugin plugin_qmljstools.depends += plugin_texteditor plugin_qmljstools.depends += plugin_qtsupport +plugin_qmljstools.depends += plugin_cpptools plugin_macros.subdir = macros plugin_macros.depends = plugin_texteditor @@ -311,4 +315,4 @@ plugin_todo.subdir = todo plugin_todo.depends = plugin_coreplugin plugin_todo.depends += plugin_projectexplorer plugin_todo.depends += plugin_texteditor -plugin_todo.depends += plugin_cpptools
\ No newline at end of file +plugin_todo.depends += plugin_cpptools diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index 983d50d0a6..361a146300 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -119,7 +119,7 @@ BuildManagerPrivate::BuildManagerPrivate() : { } -BuildManager::BuildManager(ProjectExplorerPlugin *parent) +BuildManager::BuildManager(ProjectExplorerPlugin *parent, QAction *cancelBuildAction) : QObject(parent), d(new BuildManagerPrivate) { ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); @@ -138,10 +138,10 @@ BuildManager::BuildManager(ProjectExplorerPlugin *parent) connect(parent->session(), SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)), this, SLOT(aboutToRemoveProject(ProjectExplorer::Project*))); - d->m_outputWindow = new Internal::CompileOutputWindow(this); + d->m_outputWindow = new Internal::CompileOutputWindow(this, cancelBuildAction); pm->addObject(d->m_outputWindow); - d->m_taskHub = pm->getObject<TaskHub>(); + d->m_taskHub = ProjectExplorerPlugin::instance()->taskHub(); d->m_taskWindow = new Internal::TaskWindow(d->m_taskHub); pm->addObject(d->m_taskWindow); diff --git a/src/plugins/projectexplorer/buildmanager.h b/src/plugins/projectexplorer/buildmanager.h index eff114e8b8..0ae6c6f84c 100644 --- a/src/plugins/projectexplorer/buildmanager.h +++ b/src/plugins/projectexplorer/buildmanager.h @@ -51,7 +51,7 @@ class PROJECTEXPLORER_EXPORT BuildManager : public QObject Q_OBJECT public: - explicit BuildManager(ProjectExplorerPlugin *parent); + explicit BuildManager(ProjectExplorerPlugin *parent, QAction *cancelBuildAction); virtual ~BuildManager(); void extensionsInitialized(); diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp index 2b941dc87c..28f8bf07da 100644 --- a/src/plugins/projectexplorer/compileoutputwindow.cpp +++ b/src/plugins/projectexplorer/compileoutputwindow.cpp @@ -37,6 +37,7 @@ #include "projectexplorerconstants.h" #include "projectexplorer.h" #include "projectexplorersettings.h" +#include "taskhub.h" #include <coreplugin/icontext.h> #include <find/basetextfind.h> @@ -51,6 +52,7 @@ #include <QTextEdit> #include <QScrollBar> #include <QPlainTextEdit> +#include <QToolButton> using namespace ProjectExplorer; using namespace ProjectExplorer::Internal; @@ -59,16 +61,59 @@ namespace { const int MAX_LINECOUNT = 50000; } -CompileOutputWindow::CompileOutputWindow(BuildManager * /*bm*/) +namespace ProjectExplorer { +namespace Internal { + +class CompileOutputTextEdit : public Core::OutputWindow +{ +public: + CompileOutputTextEdit(const Core::Context &context) : Core::OutputWindow(context) + { + } + + void addTask(const Task &task, int blocknumber) + { + m_taskids.insert(blocknumber, task.taskId); + } + + void clearTasks() + { + m_taskids.clear(); + } + +protected: + void mouseDoubleClickEvent(QMouseEvent *ev) + { + int line = cursorForPosition(ev->pos()).block().blockNumber(); + if (unsigned taskid = m_taskids.value(line, 0)) { + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + TaskHub *hub = pm->getObject<TaskHub>(); + hub->showTaskInEditor(taskid); + } else { + QPlainTextEdit::mouseDoubleClickEvent(ev); + } + } + +private: + QHash<int, unsigned int> m_taskids; //Map blocknumber to taskId +}; + +} // namespace Internal +} // namespace ProjectExplorer + +CompileOutputWindow::CompileOutputWindow(BuildManager * /*bm*/, QAction *cancelBuildAction) : + m_cancelBuildButton(new QToolButton) { Core::Context context(Constants::C_COMPILE_OUTPUT); - m_outputWindow = new Core::OutputWindow(context); + m_outputWindow = new CompileOutputTextEdit(context); m_outputWindow->setWindowTitle(tr("Compile Output")); m_outputWindow->setWindowIcon(QIcon(QLatin1String(Constants::ICON_WINDOW))); m_outputWindow->setReadOnly(true); m_outputWindow->setUndoRedoEnabled(false); m_outputWindow->setMaxLineCount(MAX_LINECOUNT); + m_cancelBuildButton->setDefaultAction(cancelBuildAction); + Aggregation::Aggregate *agg = new Aggregation::Aggregate; agg->add(m_outputWindow); agg->add(new Find::BaseTextFind(m_outputWindow)); @@ -86,6 +131,7 @@ CompileOutputWindow::~CompileOutputWindow() { ExtensionSystem::PluginManager::instance()->removeObject(m_handler); delete m_handler; + delete m_cancelBuildButton; } void CompileOutputWindow::updateWordWrapMode() @@ -113,6 +159,11 @@ QWidget *CompileOutputWindow::outputWidget(QWidget *) return m_outputWindow; } +QList<QWidget *> CompileOutputWindow::toolBarWidgets() const +{ + return QList<QWidget *>() << m_cancelBuildButton; +} + static QColor mix_colors(QColor a, QColor b) { return QColor((a.red() + 2 * b.red()) / 3, (a.green() + 2 * b.green()) / 3, @@ -148,6 +199,7 @@ void CompileOutputWindow::appendText(const QString &text, ProjectExplorer::Build void CompileOutputWindow::clearContents() { m_outputWindow->clear(); + m_outputWindow->clearTasks(); m_taskPositions.clear(); } @@ -191,7 +243,9 @@ void CompileOutputWindow::registerPositionOf(const Task &task) int blocknumber = m_outputWindow->blockCount(); if (blocknumber > MAX_LINECOUNT) return; + m_taskPositions.insert(task.taskId, blocknumber); + m_outputWindow->addTask(task, blocknumber); } bool CompileOutputWindow::knowsPositionOf(const Task &task) diff --git a/src/plugins/projectexplorer/compileoutputwindow.h b/src/plugins/projectexplorer/compileoutputwindow.h index 6a1844207d..676bbf007f 100644 --- a/src/plugins/projectexplorer/compileoutputwindow.h +++ b/src/plugins/projectexplorer/compileoutputwindow.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE class QPlainTextEdit; class QTextCharFormat; +class QToolButton; QT_END_NAMESPACE namespace ProjectExplorer { @@ -52,17 +53,18 @@ class Task; namespace Internal { class ShowOutputTaskHandler; +class CompileOutputTextEdit; class CompileOutputWindow : public Core::IOutputPane { Q_OBJECT public: - CompileOutputWindow(BuildManager *bm); + CompileOutputWindow(BuildManager *bm, QAction *cancelBuildAction); ~CompileOutputWindow(); QWidget *outputWidget(QWidget *); - QList<QWidget *> toolBarWidgets() const { return QList<QWidget *>(); } + QList<QWidget *> toolBarWidgets() const; QString displayName() const { return tr("Compile Output"); } int priorityInStatusBar() const; void clearContents(); @@ -86,9 +88,10 @@ private slots: void updateWordWrapMode(); private: - Core::OutputWindow *m_outputWindow; + CompileOutputTextEdit *m_outputWindow; QHash<unsigned int, int> m_taskPositions; ShowOutputTaskHandler * m_handler; + QToolButton *m_cancelBuildButton; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/deployconfiguration.cpp b/src/plugins/projectexplorer/deployconfiguration.cpp index e1d67a7a43..2499ad7f19 100644 --- a/src/plugins/projectexplorer/deployconfiguration.cpp +++ b/src/plugins/projectexplorer/deployconfiguration.cpp @@ -94,6 +94,16 @@ DeployConfigurationWidget *DeployConfiguration::configurationWidget() const return 0; } +bool DeployConfiguration::isEnabled() const +{ + return false; +} + +QString DeployConfiguration::disabledReason() const +{ + return QString(); +} + bool DeployConfiguration::fromMap(const QVariantMap &map) { if (!ProjectConfiguration::fromMap(map)) diff --git a/src/plugins/projectexplorer/deployconfiguration.h b/src/plugins/projectexplorer/deployconfiguration.h index cc2844a6e3..cc7bebf3d7 100644 --- a/src/plugins/projectexplorer/deployconfiguration.h +++ b/src/plugins/projectexplorer/deployconfiguration.h @@ -63,8 +63,14 @@ public: virtual DeployConfigurationWidget *configurationWidget() const; + virtual bool isEnabled() const; + virtual QString disabledReason() const; + Target *target() const; +signals: + void enabledChanged(); + protected: DeployConfiguration(Target *target, const QString &id); DeployConfiguration(Target *target, DeployConfiguration *source); diff --git a/src/plugins/remotelinux/linuxdevicefactoryselectiondialog.cpp b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.cpp index 5a3f495960..7ce9e57c7a 100644 --- a/src/plugins/remotelinux/linuxdevicefactoryselectiondialog.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.cpp @@ -29,28 +29,29 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ -#include "linuxdevicefactoryselectiondialog.h" -#include "ui_linuxdevicefactoryselectiondialog.h" +#include "devicefactoryselectiondialog.h" +#include "ui_devicefactoryselectiondialog.h" -#include "linuxdeviceconfiguration.h" +#include "idevice.h" +#include "idevicefactory.h" #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> #include <QPushButton> -namespace RemoteLinux { +namespace ProjectExplorer { namespace Internal { -LinuxDeviceFactorySelectionDialog::LinuxDeviceFactorySelectionDialog(QWidget *parent) : - QDialog(parent), ui(new Ui::LinuxDeviceFactorySelectionDialog) +DeviceFactorySelectionDialog::DeviceFactorySelectionDialog(QWidget *parent) : + QDialog(parent), ui(new Ui::DeviceFactorySelectionDialog) { ui->setupUi(this); ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Start Wizard")); - const QList<ILinuxDeviceConfigurationFactory *> &factories - = ExtensionSystem::PluginManager::instance()->getObjects<ILinuxDeviceConfigurationFactory>(); - foreach (const ILinuxDeviceConfigurationFactory * const factory, factories) { + const QList<IDeviceFactory *> &factories + = ExtensionSystem::PluginManager::instance()->getObjects<IDeviceFactory>(); + foreach (const IDeviceFactory * const factory, factories) { m_factories << factory; ui->listWidget->addItem(factory->displayName()); } @@ -59,21 +60,21 @@ LinuxDeviceFactorySelectionDialog::LinuxDeviceFactorySelectionDialog(QWidget *pa handleItemSelectionChanged(); } -LinuxDeviceFactorySelectionDialog::~LinuxDeviceFactorySelectionDialog() +DeviceFactorySelectionDialog::~DeviceFactorySelectionDialog() { delete ui; } -void LinuxDeviceFactorySelectionDialog::handleItemSelectionChanged() +void DeviceFactorySelectionDialog::handleItemSelectionChanged() { ui->buttonBox->button(QDialogButtonBox::Ok) ->setEnabled(!ui->listWidget->selectedItems().isEmpty()); } -const ILinuxDeviceConfigurationFactory *LinuxDeviceFactorySelectionDialog::selectedFactory() const +const IDeviceFactory *DeviceFactorySelectionDialog::selectedFactory() const { return m_factories.at(ui->listWidget->row(ui->listWidget->selectedItems().first())); } } // namespace Internal -} // namespace RemoteLinux +} // namespace ProjectExplorer diff --git a/src/plugins/remotelinux/linuxdevicefactoryselectiondialog.h b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.h index 3d6fd0ce72..f56ce34ba8 100644 --- a/src/plugins/remotelinux/linuxdevicefactoryselectiondialog.h +++ b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.h @@ -30,35 +30,35 @@ ** **************************************************************************/ -#ifndef LINUXDEVICEFACTORYSELECTIONDIALOG_H -#define LINUXDEVICEFACTORYSELECTIONDIALOG_H +#ifndef DEVICEFACTORYSELECTIONDIALOG_H +#define DEVICEFACTORYSELECTIONDIALOG_H #include <QList> #include <QDialog> -namespace RemoteLinux { -class ILinuxDeviceConfigurationFactory; +namespace ProjectExplorer { +class IDeviceFactory; namespace Internal { -namespace Ui { class LinuxDeviceFactorySelectionDialog; } +namespace Ui { class DeviceFactorySelectionDialog; } -class LinuxDeviceFactorySelectionDialog : public QDialog +class DeviceFactorySelectionDialog : public QDialog { Q_OBJECT public: - explicit LinuxDeviceFactorySelectionDialog(QWidget *parent = 0); - ~LinuxDeviceFactorySelectionDialog(); - const ILinuxDeviceConfigurationFactory *selectedFactory() const; + explicit DeviceFactorySelectionDialog(QWidget *parent = 0); + ~DeviceFactorySelectionDialog(); + const IDeviceFactory *selectedFactory() const; private: Q_SLOT void handleItemSelectionChanged(); - Ui::LinuxDeviceFactorySelectionDialog *ui; - QList<const ILinuxDeviceConfigurationFactory *> m_factories; + Ui::DeviceFactorySelectionDialog *ui; + QList<const IDeviceFactory *> m_factories; }; } // namespace Internal -} // namespace RemoteLinux +} // namespace ProjectExplorer -#endif // LINUXDEVICEFACTORYSELECTIONDIALOG_H +#endif // DEVICEFACTORYSELECTIONDIALOG_H diff --git a/src/plugins/remotelinux/linuxdevicefactoryselectiondialog.ui b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.ui index 9cbcddf434..48f26d3021 100644 --- a/src/plugins/remotelinux/linuxdevicefactoryselectiondialog.ui +++ b/src/plugins/projectexplorer/devicesupport/devicefactoryselectiondialog.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>RemoteLinux::Internal::LinuxDeviceFactorySelectionDialog</class> - <widget class="QDialog" name="RemoteLinux::Internal::LinuxDeviceFactorySelectionDialog"> + <class>ProjectExplorer::Internal::DeviceFactorySelectionDialog</class> + <widget class="QDialog" name="ProjectExplorer::Internal::DeviceFactorySelectionDialog"> <property name="geometry"> <rect> <x>0</x> @@ -54,7 +54,7 @@ <connection> <sender>buttonBox</sender> <signal>accepted()</signal> - <receiver>RemoteLinux::Internal::LinuxDeviceFactorySelectionDialog</receiver> + <receiver>ProjectExplorer::Internal::DeviceFactorySelectionDialog</receiver> <slot>accept()</slot> <hints> <hint type="sourcelabel"> @@ -70,7 +70,7 @@ <connection> <sender>buttonBox</sender> <signal>rejected()</signal> - <receiver>RemoteLinux::Internal::LinuxDeviceFactorySelectionDialog</receiver> + <receiver>ProjectExplorer::Internal::DeviceFactorySelectionDialog</receiver> <slot>reject()</slot> <hints> <hint type="sourcelabel"> diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp new file mode 100644 index 0000000000..4afb2132b0 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -0,0 +1,431 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#include "devicemanager.h" + +#include "idevicefactory.h" + +#include <coreplugin/icore.h> +#include <extensionsystem/pluginmanager.h> +#include <utils/persistentsettings.h> +#include <utils/qtcassert.h> + +#include <QFileInfo> +#include <QHash> +#include <QList> +#include <QMainWindow> +#include <QSettings> +#include <QString> +#include <QVariantHash> +#include <QVariantList> + +#include <limits> + +namespace ProjectExplorer { +namespace Internal { + +static IDevice::Ptr findAutoDetectedDevice(const QList<IDevice::Ptr> &deviceList, + const QString &type, const QString &fingerprint) +{ + foreach (const IDevice::Ptr &device, deviceList) { + if (device->isAutoDetected() && device->type() == type + && device->fingerprint() == fingerprint) { + return device; + } + } + return IDevice::Ptr(); +} + +const char DeviceManagerKey[] = "DeviceManager"; +const char DeviceListKey[] = "DeviceList"; +const char DefaultDevicesKey[] = "DefaultDevices"; + +class DeviceManagerPrivate +{ +public: + static DeviceManager *clonedInstance; + QList<IDevice::Ptr> devices; + QList<IDevice::Ptr> inactiveAutoDetectedDevices; + QHash<QString, IDevice::Id> defaultDevices; +}; +DeviceManager *DeviceManagerPrivate::clonedInstance = 0; + +} // namespace Internal + +using namespace Internal; + + +DeviceManager *DeviceManager::instance() +{ + static DeviceManager deviceManager(true); + return &deviceManager; +} + +int DeviceManager::deviceCount() const +{ + return d->devices.count(); +} + +void DeviceManager::replaceInstance() +{ + copy(DeviceManagerPrivate::clonedInstance, instance(), false); + instance()->save(); + emit instance()->deviceListChanged(); + emit instance()->updated(); +} + +void DeviceManager::removeClonedInstance() +{ + delete DeviceManagerPrivate::clonedInstance; + DeviceManagerPrivate::clonedInstance = 0; +} + +DeviceManager *DeviceManager::cloneInstance() +{ + QTC_ASSERT(!DeviceManagerPrivate::clonedInstance, return 0); + + DeviceManagerPrivate::clonedInstance = new DeviceManager; + copy(instance(), DeviceManagerPrivate::clonedInstance, true); + return DeviceManagerPrivate::clonedInstance; +} + +void DeviceManager::copy(const DeviceManager *source, DeviceManager *target, bool deep) +{ + if (deep) { + foreach (const IDevice::ConstPtr &device, source->d->devices) + target->d->devices << device->clone(); + } else { + target->d->devices = source->d->devices; + } + target->d->defaultDevices = source->d->defaultDevices; +} + +void DeviceManager::save() +{ + Utils::PersistentSettingsWriter writer; + writer.saveValue(QLatin1String(DeviceManagerKey), toMap()); + writer.save(settingsFilePath(), QLatin1String("QtCreatorDevices"), Core::ICore::mainWindow()); +} + +void DeviceManager::load() +{ + Utils::PersistentSettingsReader reader; + if (reader.load(settingsFilePath())) + fromMap(reader.restoreValues().value(QLatin1String(DeviceManagerKey)).toMap()); + else + loadPre2_6(); + ensureOneDefaultDevicePerType(); +} + +// TODO: Remove in 2.8 +void DeviceManager::loadPre2_6() +{ + QSettings *settings = Core::ICore::settings(); + settings->beginGroup(QLatin1String("MaemoDeviceConfigs")); + const QVariantHash defaultDevsHash = settings->value(QLatin1String("DefaultConfigs")).toHash(); + for (QVariantHash::ConstIterator it = defaultDevsHash.constBegin(); + it != defaultDevsHash.constEnd(); ++it) { + d->defaultDevices.insert(it.key(), it.value().toULongLong()); + } + int count = settings->beginReadArray(QLatin1String("ConfigList")); + for (int i = 0; i < count; ++i) { + settings->setArrayIndex(i); + QVariantMap map; + foreach (const QString &key, settings->childKeys()) + map.insert(key, settings->value(key)); + const IDeviceFactory *factory = factoryForDeviceType(IDevice::typeFromMap(map)); + if (!factory) + continue; + IDevice::Ptr device = factory->loadDevice(map); + QTC_ASSERT(device, continue); + if (device->internalId() == IDevice::invalidId()) + device->setInternalId(unusedId()); + d->devices << device; + } + settings->endArray(); + settings->endGroup(); +} + +void DeviceManager::fromMap(const QVariantMap &map) +{ + const QVariantMap defaultDevsMap = map.value(QLatin1String(DefaultDevicesKey)).toMap(); + for (QVariantMap::ConstIterator it = defaultDevsMap.constBegin(); + it != defaultDevsMap.constEnd(); ++it) { + d->defaultDevices.insert(it.key(), it.value().toULongLong()); + } + const QVariantList deviceList = map.value(QLatin1String(DeviceListKey)).toList(); + foreach (const QVariant &v, deviceList) { + const QVariantMap map = v.toMap(); + const IDeviceFactory * const factory = factoryForDeviceType(IDevice::typeFromMap(map)); + if (!factory) + continue; + IDevice::Ptr device = factory->loadDevice(map); + QTC_ASSERT(device, continue); + if (device->internalId() == IDevice::invalidId()) + device->setInternalId(unusedId()); + if (device->isAutoDetected()) + d->inactiveAutoDetectedDevices << device; + else + d->devices << device; + } +} + +QVariantMap DeviceManager::toMap() const +{ + QVariantMap map; + QVariantMap defaultDeviceMap; + typedef QHash<QString, IDevice::Id> TypeIdHash; + for (TypeIdHash::ConstIterator it = d->defaultDevices.constBegin(); + it != d->defaultDevices.constEnd(); ++it) { + defaultDeviceMap.insert(it.key(), it.value()); + } + map.insert(QLatin1String(DefaultDevicesKey), defaultDeviceMap); + QVariantList deviceList; + foreach (const IDevice::ConstPtr &device, d->devices) + deviceList << device->toMap(); + foreach (const IDevice::ConstPtr &device, d->inactiveAutoDetectedDevices) + deviceList << device->toMap(); + map.insert(QLatin1String(DeviceListKey), deviceList); + return map; +} + +QString DeviceManager::settingsFilePath() +{ + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + return QFileInfo(pm->settings()->fileName()).absolutePath() + QLatin1String("/devices.xml"); +} + +void DeviceManager::addDevice(const IDevice::Ptr &device) +{ + QTC_ASSERT(this != instance() || (device->isAutoDetected()), return); + QTC_ASSERT(!device->isAutoDetected() || !findAutoDetectedDevice(d->devices, device->type(), + device->fingerprint()), return); + + // Ensure uniqueness of name. + QString name = device->displayName(); + if (hasDevice(name)) { + const QString nameTemplate = name + QLatin1String(" (%1)"); + int suffix = 2; + do + name = nameTemplate.arg(QString::number(suffix++)); + while (hasDevice(name)); + } + device->setDisplayName(name); + device->setInternalId(unusedId()); + if (!defaultDevice(device->type())) + d->defaultDevices.insert(device->type(), device->internalId()); + d->devices << device; + if (this == instance() && d->clonedInstance) + d->clonedInstance->addDevice(device->clone()); + if (this == instance()) { + QList<IDevice::Ptr>::Iterator it = d->inactiveAutoDetectedDevices.begin(); + while (it != d->inactiveAutoDetectedDevices.end()) { + if (it->data()->type() == device->type() + && it->data()->fingerprint() == device->fingerprint()) { + d->inactiveAutoDetectedDevices.erase(it); + break; + } + ++it; + } + } + + emit deviceAdded(device); + emit updated(); +} + +void DeviceManager::removeDevice(int idx) +{ + const IDevice::Ptr device = mutableDeviceAt(idx); + QTC_ASSERT(device, return); + QTC_ASSERT(this != instance() || device->isAutoDetected(), return); + + const bool wasDefault = d->defaultDevices.value(device->type()) == device->internalId(); + const QString deviceType = device->type(); + d->devices.removeAt(idx); + emit deviceRemoved(idx); + + if (wasDefault) { + for (int i = 0; i < d->devices.count(); ++i) { + if (deviceAt(i)->type() == deviceType) { + d->defaultDevices.insert(deviceAt(i)->type(), deviceAt(i)->internalId()); + emit defaultStatusChanged(i); + break; + } + } + } + if (this == instance() && d->clonedInstance) { + d->clonedInstance->removeDevice(d->clonedInstance-> + indexForInternalId(device->internalId())); + } + if (this == instance() && device->isAutoDetected()) + d->inactiveAutoDetectedDevices << device; + + emit updated(); +} + +void DeviceManager::setDeviceDisplayName(int i, const QString &name) +{ + QTC_ASSERT(this != instance(), return); + QTC_ASSERT(i >= 0 && i < deviceCount(), return); + + d->devices.at(i)->setDisplayName(name); + emit displayNameChanged(i); +} + +void DeviceManager::setDefaultDevice(int idx) +{ + QTC_ASSERT(this != instance(), return); + QTC_ASSERT(idx >= 0 && idx < deviceCount(), return); + + const IDevice::ConstPtr &device = d->devices.at(idx); + const IDevice::ConstPtr &oldDefaultDevice = defaultDevice(device->type()); + if (device == oldDefaultDevice) + return; + d->defaultDevices.insert(device->type(), device->internalId()); + emit defaultStatusChanged(idx); + for (int i = 0; i < d->devices.count(); ++i) { + if (d->devices.at(i) == oldDefaultDevice) { + emit defaultStatusChanged(i); + break; + } + } + + emit updated(); +} + +const IDeviceFactory *DeviceManager::factoryForDeviceType(const QString &type) +{ + const QList<IDeviceFactory *> &factories + = ExtensionSystem::PluginManager::instance()->getObjects<IDeviceFactory>(); + foreach (const IDeviceFactory * const factory, factories) { + if (factory->supportsDeviceType(type)) + return factory; + } + return 0; +} + +QString DeviceManager::displayNameForDeviceType(const QString &type) +{ + if (const IDeviceFactory * const factory = factoryForDeviceType(type)) + return factory->displayNameForDeviceType(type); + return tr("Unknown OS"); +} + +DeviceManager::DeviceManager(bool doLoad) : d(new DeviceManagerPrivate) +{ + if (doLoad) + load(); +} + +DeviceManager::~DeviceManager() +{ + delete d; +} + +IDevice::ConstPtr DeviceManager::deviceAt(int idx) const +{ + QTC_ASSERT(idx >= 0 && idx < deviceCount(), return IDevice::ConstPtr()); + return d->devices.at(idx); +} + +IDevice::Ptr DeviceManager::mutableDeviceAt(int idx) const +{ + QTC_ASSERT(idx >= 0 && idx < deviceCount(), return IDevice::Ptr()); + return d->devices.at(idx); +} + +bool DeviceManager::hasDevice(const QString &name) const +{ + foreach (const IDevice::Ptr &device, d->devices) { + if (device->displayName() == name) + return true; + } + return false; +} + +IDevice::ConstPtr DeviceManager::find(IDevice::Id id) const +{ + const int index = indexForInternalId(id); + return index == -1 ? IDevice::ConstPtr() : deviceAt(index); +} + +IDevice::ConstPtr DeviceManager::findInactiveAutoDetectedDevice(const QString &type, + const QString &fingerprint) +{ + return findAutoDetectedDevice(d->inactiveAutoDetectedDevices, type, fingerprint); +} + +IDevice::ConstPtr DeviceManager::defaultDevice(const QString &deviceType) const +{ + const IDevice::Id id = d->defaultDevices.value(deviceType, IDevice::invalidId()); + if (id == IDevice::invalidId()) + return IDevice::ConstPtr(); + return find(id); +} + +int DeviceManager::indexForInternalId(IDevice::Id internalId) const +{ + for (int i = 0; i < d->devices.count(); ++i) { + if (deviceAt(i)->internalId() == internalId) + return i; + } + return -1; +} + +IDevice::Id DeviceManager::internalId(const IDevice::ConstPtr &device) const +{ + return device ? device->internalId() : IDevice::invalidId(); +} + +int DeviceManager::indexOf(const IDevice::ConstPtr &device) const +{ + return indexForInternalId(device->internalId()); +} + +void DeviceManager::ensureOneDefaultDevicePerType() +{ + foreach (const IDevice::Ptr &device, d->devices) { + if (!defaultDevice(device->type())) + d->defaultDevices.insert(device->type(), device->internalId()); + } +} + +IDevice::Id DeviceManager::unusedId() const +{ + for (IDevice::Id id = 0; id <= std::numeric_limits<IDevice::Id>::max(); ++id) { + if (id != IDevice::invalidId() && !find(id)) + return id; + } + QTC_CHECK(false); + return IDevice::invalidId(); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.h b/src/plugins/projectexplorer/devicesupport/devicemanager.h new file mode 100644 index 0000000000..fd94ae0af9 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.h @@ -0,0 +1,111 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#ifndef DEVICEMANAGER_H +#define DEVICEMANAGER_H + +#include "idevice.h" + +#include <projectexplorer/projectexplorer_export.h> + +#include <QObject> + +namespace ProjectExplorer { +class IDeviceFactory; + +namespace Internal { +class DeviceManagerPrivate; +class DeviceSettingsWidget; +} // namespace Internal + +class PROJECTEXPLORER_EXPORT DeviceManager : public QObject +{ + Q_OBJECT + friend class Internal::DeviceSettingsWidget; +public: + ~DeviceManager(); + + static DeviceManager *instance(); + + int deviceCount() const; + IDevice::ConstPtr deviceAt(int index) const; + IDevice::ConstPtr find(IDevice::Id id) const; + IDevice::ConstPtr findInactiveAutoDetectedDevice(const QString &type, + const QString &fingerprint); + IDevice::ConstPtr defaultDevice(const QString &deviceType) const; + bool hasDevice(const QString &name) const; + IDevice::Id internalId(const IDevice::ConstPtr &device) const; + + int indexOf(const IDevice::ConstPtr &device) const; + + void addDevice(const IDevice::Ptr &device); + void removeDevice(int index); + + static const IDeviceFactory *factoryForDeviceType(const QString &type); + static QString displayNameForDeviceType(const QString &type); + +signals: + void deviceAdded(const QSharedPointer<const IDevice> &device); + void deviceRemoved(int index); + void displayNameChanged(int index); + void defaultStatusChanged(int index); + void deviceListChanged(); + void updated(); // Emitted for all of the above. + +private: + DeviceManager(bool doLoad = false); + + void load(); + void save(); + void loadPre2_6(); + void fromMap(const QVariantMap &map); + QVariantMap toMap() const; + void ensureOneDefaultDevicePerType(); + IDevice::Id unusedId() const; + int indexForInternalId(IDevice::Id internalId) const; + + // For SettingsWidget. + IDevice::Ptr mutableDeviceAt(int index) const; + void setDeviceDisplayName(int i, const QString &name); + void setDefaultDevice(int index); + static DeviceManager *cloneInstance(); + static void replaceInstance(); + static void removeClonedInstance(); + + static QString settingsFilePath(); + static void copy(const DeviceManager *source, DeviceManager *target, bool deep); + + Internal::DeviceManagerPrivate * const d; +}; + +} // namespace ProjectExplorer + +#endif // DEVICEMANAGER_H diff --git a/src/plugins/projectexplorer/devicesupport/devicemanagermodel.cpp b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.cpp new file mode 100644 index 0000000000..1d87fddec1 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.cpp @@ -0,0 +1,114 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#include "devicemanagermodel.h" + +#include "devicemanager.h" + +#include <QString> + +namespace ProjectExplorer { +namespace Internal { +class DeviceManagerModelPrivate +{ +public: + const DeviceManager *deviceManager; + QList<IDevice::ConstPtr> devices; +}; +} // namespace Internal + +DeviceManagerModel::DeviceManagerModel(const DeviceManager *deviceManager, QObject *parent) : + QAbstractListModel(parent), d(new Internal::DeviceManagerModelPrivate) +{ + d->deviceManager = deviceManager; + handleDeviceListChanged(); + connect(deviceManager, SIGNAL(deviceAdded(QSharedPointer<const IDevice>)), + SLOT(handleDeviceAdded(QSharedPointer<const IDevice>))); + connect(deviceManager, SIGNAL(deviceRemoved(int)), SLOT(handleDeviceRemoved(int))); + connect(deviceManager, SIGNAL(displayNameChanged(int)), SLOT(handleDataChanged(int))); + connect(deviceManager, SIGNAL(defaultStatusChanged(int)), SLOT(handleDataChanged(int))); + connect(deviceManager, SIGNAL(deviceListChanged()), SLOT(handleDeviceListChanged())); +} + +DeviceManagerModel::~DeviceManagerModel() +{ + delete d; +} + +void DeviceManagerModel::handleDeviceAdded(const IDevice::ConstPtr &device) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + d->devices << device; + endInsertRows(); +} + +void DeviceManagerModel::handleDeviceRemoved(int idx) +{ + beginRemoveRows(QModelIndex(), idx, idx); + d->devices.removeAt(idx); + endRemoveRows(); +} + +void DeviceManagerModel::handleDataChanged(int idx) +{ + const QModelIndex changedIndex = index(idx, 0); + emit dataChanged(changedIndex, changedIndex); +} + +void DeviceManagerModel::handleDeviceListChanged() +{ + beginResetModel(); + d->devices.clear(); + for (int i = 0; i < d->deviceManager->deviceCount(); ++i) + d->devices << d->deviceManager->deviceAt(i); + endResetModel(); +} + +int DeviceManagerModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return d->devices.count(); +} + +QVariant DeviceManagerModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= rowCount() || role != Qt::DisplayRole) + return QVariant(); + const IDevice::ConstPtr device = d->devices.at(index.row()); + QString name = device->displayName(); + if (d->deviceManager->defaultDevice(device->type()) == device) { + name = tr("%1 (default for %2)").arg(name, + d->deviceManager->displayNameForDeviceType(device->type())); + } + return name; +} + +} // namespace ProjectExplorer diff --git a/src/plugins/qmljsinspector/qmljstoolbarcolorbox.h b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h index 449804d139..301e1138c2 100644 --- a/src/plugins/qmljsinspector/qmljstoolbarcolorbox.h +++ b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h @@ -29,47 +29,39 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ -#ifndef TOOLBARCOLORBOX_H -#define TOOLBARCOLORBOX_H +#ifndef DEVICEMANAGERMODEL_H +#define DEVICEMANAGERMODEL_H -#include <QLabel> -#include <QColor> -#include <QPoint> +#include <projectexplorer/projectexplorer_export.h> -QT_FORWARD_DECLARE_CLASS(QContextMenuEvent) -QT_FORWARD_DECLARE_CLASS(QAction) +#include <QAbstractListModel> +#include <QSharedPointer> -namespace QmlJSInspector { +namespace ProjectExplorer { +namespace Internal { class DeviceManagerModelPrivate; } +class IDevice; +class DeviceManager; -class ToolBarColorBox : public QLabel +class PROJECTEXPLORER_EXPORT DeviceManagerModel : public QAbstractListModel { Q_OBJECT public: - explicit ToolBarColorBox(QWidget *parent = 0); - void setColor(const QColor &color); - void setInnerBorderColor(const QColor &color); - void setOuterBorderColor(const QColor &color); + explicit DeviceManagerModel(const DeviceManager *deviceManager, QObject *parent = 0); + ~DeviceManagerModel(); -protected: - void contextMenuEvent(QContextMenuEvent *ev); - void mousePressEvent(QMouseEvent *ev); - void mouseMoveEvent(QMouseEvent *ev); private slots: - void copyColorToClipboard(); + void handleDeviceAdded(const QSharedPointer<const IDevice> &device); + void handleDeviceRemoved(int idx); + void handleDataChanged(int idx); + void handleDeviceListChanged(); private: - QPixmap createDragPixmap(int size = 24) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; -private: - bool m_dragStarted; - QPoint m_dragBeginPoint; - QAction *m_copyHexColorAction; - QColor m_color; - - QColor m_borderColorOuter; - QColor m_borderColorInner; + Internal::DeviceManagerModelPrivate * const d; }; -} // namespace QmlJSInspector +} // namespace ProjectExplorer -#endif // TOOLBARCOLORBOX_H +#endif // DEVICEMANAGERMODEL_H diff --git a/src/plugins/remotelinux/remotelinuxsettingspages.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp index 817edef0d9..9c1345e653 100644 --- a/src/plugins/remotelinux/remotelinuxsettingspages.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicesettingspage.cpp @@ -28,83 +28,84 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ -#include "remotelinuxsettingspages.h" +#include "devicesettingspage.h" -#include "linuxdeviceconfigurationssettingswidget.h" -#include "remotelinux_constants.h" +#include "devicesettingswidget.h" + +#include <projectexplorer/projectexplorerconstants.h> #include <QCoreApplication> #include <QString> #include <QIcon> -namespace RemoteLinux { +namespace ProjectExplorer { namespace Internal { -LinuxDeviceConfigurationsSettingsPage::LinuxDeviceConfigurationsSettingsPage(QObject *parent) +DeviceSettingsPage::DeviceSettingsPage(QObject *parent) : Core::IOptionsPage(parent) { } -LinuxDeviceConfigurationsSettingsPage::~LinuxDeviceConfigurationsSettingsPage() +DeviceSettingsPage::~DeviceSettingsPage() { } -QString LinuxDeviceConfigurationsSettingsPage::id() const +QString DeviceSettingsPage::id() const { return pageId(); } -QString LinuxDeviceConfigurationsSettingsPage::displayName() const +QString DeviceSettingsPage::displayName() const { - return tr("Device Configurations"); + return tr("Devices"); } -QString LinuxDeviceConfigurationsSettingsPage::category() const +QString DeviceSettingsPage::category() const { return pageCategory(); } -QString LinuxDeviceConfigurationsSettingsPage::displayCategory() const +QString DeviceSettingsPage::displayCategory() const { - return QCoreApplication::translate("RemoteLinux", "Linux Devices"); + return QCoreApplication::translate("ProjectExplorer", "Devices"); } -QIcon LinuxDeviceConfigurationsSettingsPage::categoryIcon() const +QIcon DeviceSettingsPage::categoryIcon() const { return QIcon(QLatin1String(":/projectexplorer/images/MaemoDevice.png")); } -bool LinuxDeviceConfigurationsSettingsPage::matches(const QString &searchKeyWord) const +bool DeviceSettingsPage::matches(const QString &searchKeyWord) const { return m_keywords.contains(searchKeyWord, Qt::CaseInsensitive); } -QWidget *LinuxDeviceConfigurationsSettingsPage::createPage(QWidget *parent) +QWidget *DeviceSettingsPage::createPage(QWidget *parent) { - m_widget = new LinuxDeviceConfigurationsSettingsWidget(parent); + m_widget = new DeviceSettingsWidget(parent); if (m_keywords.isEmpty()) m_keywords = m_widget->searchKeywords(); return m_widget; } -void LinuxDeviceConfigurationsSettingsPage::apply() +void DeviceSettingsPage::apply() { m_widget->saveSettings(); } -void LinuxDeviceConfigurationsSettingsPage::finish() +void DeviceSettingsPage::finish() { } -QString LinuxDeviceConfigurationsSettingsPage::pageId() +QString DeviceSettingsPage::pageId() { - return QLatin1String(Constants::RemoteLinuxSettingsPageId); + return QLatin1String(Constants::DEVICE_SETTINGS_PAGE_ID); } -QString LinuxDeviceConfigurationsSettingsPage::pageCategory() +QString DeviceSettingsPage::pageCategory() { - return QLatin1String(Constants::RemoteLinuxSettingsCategory); + return QLatin1String(Constants::DEVICE_SETTINGS_CATEGORY); } } // namespace Internal -} // namespace RemoteLinux +} // namespace ProjectExplorer diff --git a/src/plugins/remotelinux/remotelinuxsettingspages.h b/src/plugins/projectexplorer/devicesupport/devicesettingspage.h index f6e20b6eb6..15e690ebea 100644 --- a/src/plugins/remotelinux/remotelinuxsettingspages.h +++ b/src/plugins/projectexplorer/devicesupport/devicesettingspage.h @@ -28,21 +28,21 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ -#ifndef REMOTELINUXSETTINGSPAGES_H -#define REMOTELINUXSETTINGSPAGES_H +#ifndef DEVICESETTINGSPAGE_H +#define DEVICESETTINGSPAGE_H #include <coreplugin/dialogs/ioptionspage.h> -namespace RemoteLinux { +namespace ProjectExplorer { namespace Internal { -class LinuxDeviceConfigurationsSettingsWidget; +class DeviceSettingsWidget; -class LinuxDeviceConfigurationsSettingsPage : public Core::IOptionsPage +class DeviceSettingsPage : public Core::IOptionsPage { Q_OBJECT public: - LinuxDeviceConfigurationsSettingsPage(QObject *parent = 0); - ~LinuxDeviceConfigurationsSettingsPage(); + DeviceSettingsPage(QObject *parent = 0); + ~DeviceSettingsPage(); virtual QString id() const; virtual QString displayName() const; @@ -59,10 +59,10 @@ public: private: QString m_keywords; - LinuxDeviceConfigurationsSettingsWidget *m_widget; + DeviceSettingsWidget *m_widget; }; } // namespace Internal -} // namespace RemoteLinux +} // namespace ProjectExplorer -#endif // REMOTELINUXSETTINGSPAGES_H +#endif // DEVICESETTINGSPAGE_H diff --git a/src/plugins/remotelinux/linuxdeviceconfigurationssettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp index 4184dcb14a..e0a439300a 100644 --- a/src/plugins/remotelinux/linuxdeviceconfigurationssettingswidget.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp @@ -28,19 +28,20 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ -#include "linuxdeviceconfigurationssettingswidget.h" +#include "devicesettingswidget.h" +#include "ui_devicesettingswidget.h" -#include "ui_linuxdeviceconfigurationssettingswidget.h" - -#include "linuxdeviceconfigurations.h" -#include "linuxdevicefactoryselectiondialog.h" -#include "portlist.h" -#include "remotelinuxutils.h" -#include "sshkeycreationdialog.h" +#include "devicefactoryselectiondialog.h" +#include "devicemanager.h" +#include "devicemanagermodel.h" +#include "idevice.h" +#include "idevicefactory.h" +#include "idevicewidget.h" +#include "idevicewizard.h" #include <coreplugin/icore.h> #include <extensionsystem/pluginmanager.h> -#include <utils/ssh/sshremoteprocessrunner.h> +#include <utils/portlist.h> #include <QFileInfo> #include <QRegExp> @@ -57,19 +58,15 @@ using namespace Core; using namespace Utils; -namespace RemoteLinux { +namespace ProjectExplorer { namespace Internal { -namespace { -const QLatin1String LastDeviceConfigIndexKey("LastDisplayedMaemoDeviceConfig"); -} // anonymous namespace - +const char LastDeviceIndexKey[] = "LastDisplayedMaemoDeviceConfig"; class NameValidator : public QValidator { public: - NameValidator(const LinuxDeviceConfigurations *devConfigs, - QWidget *parent = 0) - : QValidator(parent), m_devConfigs(devConfigs) + NameValidator(const DeviceManager *deviceManager, QWidget *parent = 0) + : QValidator(parent), m_deviceManager(deviceManager) { } @@ -78,7 +75,7 @@ public: virtual State validate(QString &input, int & /* pos */) const { if (input.trimmed().isEmpty() - || (input != m_oldName && m_devConfigs->hasConfig(input))) + || (input != m_oldName && m_deviceManager->hasDevice(input))) return Intermediate; return Acceptable; } @@ -92,42 +89,39 @@ public: private: QString m_oldName; - const LinuxDeviceConfigurations * const m_devConfigs; + const DeviceManager * const m_deviceManager; }; -LinuxDeviceConfigurationsSettingsWidget::LinuxDeviceConfigurationsSettingsWidget(QWidget *parent) +DeviceSettingsWidget::DeviceSettingsWidget(QWidget *parent) : QWidget(parent), - m_ui(new Ui::LinuxDeviceConfigurationsSettingsWidget), - m_devConfigs(LinuxDeviceConfigurations::cloneInstance()), - m_nameValidator(new NameValidator(m_devConfigs.data(), this)), + m_ui(new Ui::DeviceSettingsWidget), + m_deviceManager(DeviceManager::cloneInstance()), + m_nameValidator(new NameValidator(m_deviceManager, this)), m_saveSettingsRequested(false), m_additionalActionsMapper(new QSignalMapper(this)), m_configWidget(0) { - LinuxDeviceConfigurations::blockCloning(); initGui(); connect(m_additionalActionsMapper, SIGNAL(mapped(QString)), SLOT(handleAdditionalActionRequest(QString))); } -LinuxDeviceConfigurationsSettingsWidget::~LinuxDeviceConfigurationsSettingsWidget() +DeviceSettingsWidget::~DeviceSettingsWidget() { if (m_saveSettingsRequested) { - Core::ICore::settings()->setValue(LastDeviceConfigIndexKey, + Core::ICore::settings()->setValue(QLatin1String(LastDeviceIndexKey), currentIndex()); - LinuxDeviceConfigurations::replaceInstance(m_devConfigs.data()); + DeviceManager::replaceInstance(); } - LinuxDeviceConfigurations::unblockCloning(); + DeviceManager::removeClonedInstance(); delete m_ui; } -QString LinuxDeviceConfigurationsSettingsWidget::searchKeywords() const +QString DeviceSettingsWidget::searchKeywords() const { QString rc; QTextStream(&rc) << m_ui->configurationLabel->text() - << ' ' << m_ui->deviceTypeLabel->text() - << ' ' << m_ui->deviceTypeValueLabel->text() << ' ' << m_ui->deviceNameLabel->text() << ' ' << m_ui->nameLineEdit->text(); if (m_configWidget) @@ -135,114 +129,107 @@ QString LinuxDeviceConfigurationsSettingsWidget::searchKeywords() const return rc; } -void LinuxDeviceConfigurationsSettingsWidget::initGui() +void DeviceSettingsWidget::initGui() { m_ui->setupUi(this); - m_ui->configurationComboBox->setModel(m_devConfigs.data()); + DeviceManagerModel * const model = new DeviceManagerModel(m_deviceManager, this); + m_ui->configurationComboBox->setModel(model); m_ui->nameLineEdit->setValidator(m_nameValidator); int lastIndex = Core::ICore::settings() - ->value(LastDeviceConfigIndexKey, 0).toInt(); + ->value(QLatin1String(LastDeviceIndexKey), 0).toInt(); if (lastIndex == -1) lastIndex = 0; if (lastIndex < m_ui->configurationComboBox->count()) m_ui->configurationComboBox->setCurrentIndex(lastIndex); connect(m_ui->configurationComboBox, SIGNAL(currentIndexChanged(int)), - SLOT(currentConfigChanged(int))); - currentConfigChanged(currentIndex()); + SLOT(currentDeviceChanged(int))); + currentDeviceChanged(currentIndex()); connect(m_ui->defaultDeviceButton, SIGNAL(clicked()), SLOT(setDefaultDevice())); } -void LinuxDeviceConfigurationsSettingsWidget::addConfig() +void DeviceSettingsWidget::addDevice() { - const QList<ILinuxDeviceConfigurationFactory *> &factories - = ExtensionSystem::PluginManager::instance()->getObjects<ILinuxDeviceConfigurationFactory>(); + const QList<IDeviceFactory *> &factories + = ExtensionSystem::PluginManager::instance()->getObjects<IDeviceFactory>(); if (factories.isEmpty()) // Can't happen, because this plugin provides the generic one. return; - LinuxDeviceFactorySelectionDialog d; + DeviceFactorySelectionDialog d; if (d.exec() != QDialog::Accepted) return; - const QScopedPointer<ILinuxDeviceConfigurationWizard> wizard(d.selectedFactory()->createWizard(this)); + const QScopedPointer<IDeviceWizard> wizard(d.selectedFactory()->createWizard(this)); if (wizard->exec() != QDialog::Accepted) return; - m_devConfigs->addConfiguration(wizard->deviceConfiguration()); + m_deviceManager->addDevice(wizard->device()); m_ui->removeConfigButton->setEnabled(true); m_ui->configurationComboBox->setCurrentIndex(m_ui->configurationComboBox->count()-1); } -void LinuxDeviceConfigurationsSettingsWidget::deleteConfig() +void DeviceSettingsWidget::removeDevice() { - m_devConfigs->removeConfiguration(currentIndex()); - if (m_devConfigs->rowCount() == 0) - currentConfigChanged(-1); + m_deviceManager->removeDevice(currentIndex()); + if (m_deviceManager->deviceCount() == 0) + currentDeviceChanged(-1); } -void LinuxDeviceConfigurationsSettingsWidget::displayCurrent() +void DeviceSettingsWidget::displayCurrent() { - const LinuxDeviceConfiguration::ConstPtr ¤t = currentConfig(); - m_ui->defaultDeviceButton->setEnabled(!current->isDefault()); - m_ui->osTypeValueLabel->setText(RemoteLinuxUtils::osTypeToString(current->osType())); - - if (current->deviceType() == LinuxDeviceConfiguration::Hardware) - m_ui->deviceTypeValueLabel->setText(tr("Physical Device")); - else - m_ui->deviceTypeValueLabel->setText(tr("Emulator")); + const IDevice::ConstPtr ¤t = currentDevice(); + m_ui->defaultDeviceButton->setEnabled( + m_deviceManager->defaultDevice(current->type()) != current); + m_ui->osTypeValueLabel->setText(DeviceManager::displayNameForDeviceType(current->type())); + m_ui->autoDetectionValueLabel->setText(current->isAutoDetected() + ? tr("Yes (fingerprint is '%1')").arg(current->fingerprint()) : tr("No")); m_nameValidator->setDisplayName(current->displayName()); m_ui->removeConfigButton->setEnabled(!current->isAutoDetected()); fillInValues(); } -void LinuxDeviceConfigurationsSettingsWidget::fillInValues() +void DeviceSettingsWidget::fillInValues() { - const LinuxDeviceConfiguration::ConstPtr ¤t = currentConfig(); + const IDevice::ConstPtr ¤t = currentDevice(); m_ui->nameLineEdit->setText(current->displayName()); } -void LinuxDeviceConfigurationsSettingsWidget::saveSettings() +void DeviceSettingsWidget::saveSettings() { // We must defer this step because of a stupid bug on MacOS. See QTCREATORBUG-1675. m_saveSettingsRequested = true; } -int LinuxDeviceConfigurationsSettingsWidget::currentIndex() const +int DeviceSettingsWidget::currentIndex() const { return m_ui->configurationComboBox->currentIndex(); } -LinuxDeviceConfiguration::ConstPtr LinuxDeviceConfigurationsSettingsWidget::currentConfig() const +QSharedPointer<const IDevice> DeviceSettingsWidget::currentDevice() const { Q_ASSERT(currentIndex() != -1); - return m_devConfigs->deviceAt(currentIndex()); + return m_deviceManager->deviceAt(currentIndex()); } -void LinuxDeviceConfigurationsSettingsWidget::configNameEditingFinished() +void DeviceSettingsWidget::deviceNameEditingFinished() { if (m_ui->configurationComboBox->count() == 0) return; const QString &newName = m_ui->nameLineEdit->text(); - m_devConfigs->setConfigurationName(currentIndex(), newName); + m_deviceManager->setDeviceDisplayName(currentIndex(), newName); m_nameValidator->setDisplayName(newName); } -void LinuxDeviceConfigurationsSettingsWidget::setDefaultDevice() +void DeviceSettingsWidget::setDefaultDevice() { - m_devConfigs->setDefaultDevice(currentIndex()); + m_deviceManager->setDefaultDevice(currentIndex()); m_ui->defaultDeviceButton->setEnabled(false); } -void LinuxDeviceConfigurationsSettingsWidget::showGenerateSshKeyDialog() -{ - SshKeyCreationDialog dialog(this); - dialog.exec(); -} - -void LinuxDeviceConfigurationsSettingsWidget::currentConfigChanged(int index) +void DeviceSettingsWidget::currentDeviceChanged(int index) { qDeleteAll(m_additionalActionButtons); delete m_configWidget; @@ -252,13 +239,11 @@ void LinuxDeviceConfigurationsSettingsWidget::currentConfigChanged(int index) m_ui->osSpecificGroupBox->setEnabled(false); if (index == -1) { m_ui->removeConfigButton->setEnabled(false); - m_ui->generateKeyButton->setEnabled(false); clearDetails(); m_ui->defaultDeviceButton->setEnabled(false); } else { m_ui->removeConfigButton->setEnabled(true); - m_ui->generateKeyButton->setEnabled(true); - const ILinuxDeviceConfigurationFactory * const factory = factoryForCurrentConfig(); + const IDeviceFactory * const factory = factoryForCurrentDevice(); if (factory) { const QStringList &actionIds = factory->supportedDeviceActionIds(); foreach (const QString &actionId, actionIds) { @@ -271,11 +256,9 @@ void LinuxDeviceConfigurationsSettingsWidget::currentConfigChanged(int index) } if (!m_ui->osSpecificGroupBox->layout()) new QVBoxLayout(m_ui->osSpecificGroupBox); - m_configWidget = factory->createWidget(m_devConfigs->mutableDeviceAt(currentIndex()), + m_configWidget = factory->createWidget(m_deviceManager->mutableDeviceAt(currentIndex()), m_ui->osSpecificGroupBox); if (m_configWidget) { - connect(m_configWidget, SIGNAL(defaultSshKeyFilePathChanged(QString)), - m_devConfigs.data(), SLOT(setDefaultSshKeyFilePath(QString))); m_ui->osSpecificGroupBox->layout()->addWidget(m_configWidget); m_ui->osSpecificGroupBox->setEnabled(factory->isUserEditable()); } @@ -286,34 +269,28 @@ void LinuxDeviceConfigurationsSettingsWidget::currentConfigChanged(int index) } } -void LinuxDeviceConfigurationsSettingsWidget::clearDetails() +void DeviceSettingsWidget::clearDetails() { m_ui->nameLineEdit->clear(); m_ui->osTypeValueLabel->clear(); - m_ui->deviceTypeValueLabel->clear(); + m_ui->autoDetectionValueLabel->clear(); } -const ILinuxDeviceConfigurationFactory *LinuxDeviceConfigurationsSettingsWidget::factoryForCurrentConfig() const +const IDeviceFactory *DeviceSettingsWidget::factoryForCurrentDevice() const { - Q_ASSERT(currentConfig()); - const QList<ILinuxDeviceConfigurationFactory *> &factories - = ExtensionSystem::PluginManager::instance()->getObjects<ILinuxDeviceConfigurationFactory>(); - foreach (const ILinuxDeviceConfigurationFactory * const factory, factories) { - if (factory->supportsOsType(currentConfig()->osType())) - return factory; - } - return 0; + Q_ASSERT(currentDevice()); + return DeviceManager::factoryForDeviceType(currentDevice()->type()); } -void LinuxDeviceConfigurationsSettingsWidget::handleAdditionalActionRequest(const QString &actionId) +void DeviceSettingsWidget::handleAdditionalActionRequest(const QString &actionId) { - const ILinuxDeviceConfigurationFactory * const factory = factoryForCurrentConfig(); + const IDeviceFactory * const factory = factoryForCurrentDevice(); Q_ASSERT(factory); - QDialog * const action = factory->createDeviceAction(actionId, currentConfig(), this); + QDialog * const action = factory->createDeviceAction(actionId, currentDevice(), this); if (action) action->exec(); delete action; } } // namespace Internal -} // namespace RemoteLinux +} // namespace ProjectExplorer diff --git a/src/plugins/remotelinux/linuxdeviceconfigurationssettingswidget.h b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h index 855bacef80..3194dc407f 100644 --- a/src/plugins/remotelinux/linuxdeviceconfigurationssettingswidget.h +++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.h @@ -29,71 +29,66 @@ ** **************************************************************************/ -#ifndef LINUXDEVICECONFIGURATIONSSETTINGSWIDGET_H -#define LINUXDEVICECONFIGURATIONSSETTINGSWIDGET_H +#ifndef DEVICESETTINGSWIDGET_H +#define DEVICESETTINGSWIDGET_H #include <QList> -#include <QScopedPointer> #include <QString> #include <QPushButton> #include <QWidget> QT_BEGIN_NAMESPACE -class QLineEdit; class QSignalMapper; QT_END_NAMESPACE -namespace RemoteLinux { -class ILinuxDeviceConfigurationFactory; -class LinuxDeviceConfiguration; -class LinuxDeviceConfigurations; -class ILinuxDeviceConfigurationWidget; +namespace ProjectExplorer { +class IDevice; +class DeviceManager; +class IDeviceFactory; +class IDeviceWidget; namespace Internal { -namespace Ui { class LinuxDeviceConfigurationsSettingsWidget; } +namespace Ui { class DeviceSettingsWidget; } class NameValidator; -class LinuxDeviceConfigurationsSettingsWidget : public QWidget +class DeviceSettingsWidget : public QWidget { Q_OBJECT public: - LinuxDeviceConfigurationsSettingsWidget(QWidget *parent); - ~LinuxDeviceConfigurationsSettingsWidget(); + DeviceSettingsWidget(QWidget *parent); + ~DeviceSettingsWidget(); void saveSettings(); QString searchKeywords() const; private slots: - void currentConfigChanged(int index); - void addConfig(); - void deleteConfig(); - void configNameEditingFinished(); + void currentDeviceChanged(int index); + void addDevice(); + void removeDevice(); + void deviceNameEditingFinished(); void setDefaultDevice(); - - void showGenerateSshKeyDialog(); - void handleAdditionalActionRequest(const QString &actionId); private: void initGui(); void displayCurrent(); - QSharedPointer<const LinuxDeviceConfiguration> currentConfig() const; + QSharedPointer<const IDevice> currentDevice() const; int currentIndex() const; void clearDetails(); QString parseTestOutput(); void fillInValues(); - const ILinuxDeviceConfigurationFactory *factoryForCurrentConfig() const; + const IDeviceFactory *factoryForCurrentDevice() const; - Ui::LinuxDeviceConfigurationsSettingsWidget *m_ui; - const QScopedPointer<LinuxDeviceConfigurations> m_devConfigs; + Ui::DeviceSettingsWidget *m_ui; + DeviceManager * const m_deviceManager; NameValidator * const m_nameValidator; bool m_saveSettingsRequested; QList<QPushButton *> m_additionalActionButtons; QSignalMapper * const m_additionalActionsMapper; - ILinuxDeviceConfigurationWidget *m_configWidget; + IDeviceWidget *m_configWidget; }; } // namespace Internal -} // namespace RemoteLinux +} // namespace ProjectExplorer -#endif // LINUXDEVICECONFIGURATIONSSETTINGSWIDGET_H +#endif // DEVICESETTINGSWIDGET_H diff --git a/src/plugins/remotelinux/linuxdeviceconfigurationssettingswidget.ui b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.ui index bdee36b870..66db396b26 100644 --- a/src/plugins/remotelinux/linuxdeviceconfigurationssettingswidget.ui +++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.ui @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>RemoteLinux::Internal::LinuxDeviceConfigurationsSettingsWidget</class> - <widget class="QWidget" name="RemoteLinux::Internal::LinuxDeviceConfigurationsSettingsWidget"> + <class>ProjectExplorer::Internal::DeviceSettingsWidget</class> + <widget class="QWidget" name="ProjectExplorer::Internal::DeviceSettingsWidget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>726</width> - <height>473</height> + <width>829</width> + <height>516</height> </rect> </property> <property name="windowTitle"> @@ -24,7 +24,7 @@ <item row="0" column="0"> <widget class="QLabel" name="configurationLabel"> <property name="text"> - <string>&Configuration:</string> + <string>&Device:</string> </property> <property name="buddy"> <cstring>configurationComboBox</cstring> @@ -51,27 +51,11 @@ <property name="title"> <string>General</string> </property> - <layout class="QFormLayout" name="formLayout_3"> - <property name="fieldGrowthPolicy"> - <enum>QFormLayout::FieldsStayAtSizeHint</enum> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="deviceNameLabel"> - <property name="text"> - <string>&Name:</string> - </property> - <property name="buddy"> - <cstring>nameLineEdit</cstring> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="nameLineEdit"/> - </item> + <layout class="QGridLayout" name="gridLayout"> <item row="1" column="0"> <widget class="QLabel" name="oSTypeLabel"> <property name="text"> - <string>OS type:</string> + <string>Type:</string> </property> </widget> </item> @@ -82,15 +66,41 @@ </property> </widget> </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="nameLineEdit"/> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="deviceNameLabel"> + <property name="text"> + <string>&Name:</string> + </property> + <property name="buddy"> + <cstring>nameLineEdit</cstring> + </property> + </widget> + </item> <item row="2" column="0"> - <widget class="QLabel" name="deviceTypeLabel"> + <widget class="QLabel" name="autoDetectionKeyLabel"> <property name="text"> - <string>Device type:</string> + <string>Auto-detected:</string> </property> </widget> </item> <item row="2" column="1"> - <widget class="QLabel" name="deviceTypeValueLabel"> + <widget class="QLabel" name="autoDetectionValueLabel"> <property name="text"> <string/> </property> @@ -102,7 +112,7 @@ <item> <widget class="QGroupBox" name="osSpecificGroupBox"> <property name="title"> - <string>OS Type Specific</string> + <string>Type Specific</string> </property> </widget> </item> @@ -160,22 +170,6 @@ </widget> </item> <item> - <widget class="QPushButton" name="generateKeyButton"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="toolTip"> - <string>Click here if you do not have an SSH key yet.</string> - </property> - <property name="text"> - <string>&Generate SSH Key...</string> - </property> - </widget> - </item> - <item> <widget class="Line" name="line"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -204,12 +198,12 @@ <connection> <sender>addConfigButton</sender> <signal>clicked()</signal> - <receiver>RemoteLinux::Internal::LinuxDeviceConfigurationsSettingsWidget</receiver> - <slot>addConfig()</slot> + <receiver>ProjectExplorer::Internal::DeviceSettingsWidget</receiver> + <slot>addDevice()</slot> <hints> <hint type="sourcelabel"> - <x>697</x> - <y>33</y> + <x>818</x> + <y>35</y> </hint> <hint type="destinationlabel"> <x>516</x> @@ -220,8 +214,8 @@ <connection> <sender>nameLineEdit</sender> <signal>editingFinished()</signal> - <receiver>RemoteLinux::Internal::LinuxDeviceConfigurationsSettingsWidget</receiver> - <slot>configNameEditingFinished()</slot> + <receiver>ProjectExplorer::Internal::DeviceSettingsWidget</receiver> + <slot>deviceNameEditingFinished()</slot> <hints> <hint type="sourcelabel"> <x>204</x> @@ -234,30 +228,14 @@ </hints> </connection> <connection> - <sender>generateKeyButton</sender> - <signal>clicked()</signal> - <receiver>RemoteLinux::Internal::LinuxDeviceConfigurationsSettingsWidget</receiver> - <slot>showGenerateSshKeyDialog()</slot> - <hints> - <hint type="sourcelabel"> - <x>697</x> - <y>131</y> - </hint> - <hint type="destinationlabel"> - <x>358</x> - <y>0</y> - </hint> - </hints> - </connection> - <connection> <sender>removeConfigButton</sender> <signal>clicked()</signal> - <receiver>RemoteLinux::Internal::LinuxDeviceConfigurationsSettingsWidget</receiver> - <slot>deleteConfig()</slot> + <receiver>ProjectExplorer::Internal::DeviceSettingsWidget</receiver> + <slot>removeDevice()</slot> <hints> <hint type="sourcelabel"> - <x>697</x> - <y>63</y> + <x>818</x> + <y>67</y> </hint> <hint type="destinationlabel"> <x>351</x> @@ -267,16 +245,16 @@ </connection> </connections> <slots> - <slot>configNameEditingFinished()</slot> + <slot>deviceNameEditingFinished()</slot> <slot>deviceTypeChanged()</slot> <slot>hostNameEditingFinished()</slot> <slot>sshPortEditingFinished()</slot> <slot>timeoutEditingFinished()</slot> <slot>userNameEditingFinished()</slot> <slot>passwordEditingFinished()</slot> - <slot>addConfig()</slot> + <slot>addDevice()</slot> <slot>selectionChanged()</slot> - <slot>deleteConfig()</slot> + <slot>removeDevice()</slot> <slot>authenticationTypeChanged()</slot> <slot>keyFileEditingFinished()</slot> <slot>testConfig()</slot> diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp new file mode 100644 index 0000000000..14c2c0e2e1 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -0,0 +1,221 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#include "idevice.h" + +#include <utils/qtcassert.h> + +#include <QString> + +/*! + * \class ProjectExplorer::IDevice + * \brief This is the base class for all devices. + * + * The term "device" refers + * here to some host to which e.g. files can be deployed or on which an application can run. + * In the typical case, this would be some sort of embedded computer connected in some way to + * the PC on which QtCreator runs. This class itself does not specify a connection protocol; that + * kind of detail is to be added by subclasses. + * Devices are managed by a \c DeviceManager. + * \sa ProjectExplorer::DeviceManager + */ + +/*! + * \fn QString ProjectExplorer::IDevice::type() const + * \brief Identifies the type of the device. + * Devices with the same type share certain abilities. + * This attribute is immutable. + * \sa ProjectExplorer::IDeviceFactory + */ + + +/*! + * \fn QString ProjectExplorer::IDevice::displayName() const + * \brief A free-text name for the device to be displayed in GUI elements. + */ + +/*! + * \fn bool ProjectExplorer::IDevice::isAutoDetected() const + * \brief True iff the device has been added via some sort of auto-detection mechanism. + * Devices that are not auto-detected can only ever be created interactively from the + * settings page. + * This attribute is immutable. + * \sa DeviceSettingsWidget + */ + +/*! + * \fn ProjectExplorer::IDevice::Id ProjectExplorer::IDevice::internalId() const + * \brief Identify the device internally. + */ + +/*! + * \fn QString ProjectExplorer::IDevice::fingerprint() const + * \brief Uniquely identifies an auto-detected device. + * The fingerprint can later be used to retrieve changes the user has done to the settings + * of an auto-detected device so they are not lost when the device goes away, e.g. because + * it has been disconnected. + * \sa ProjectExplorer::DeviceManager::findInactiveAutoDetectedDevice() + */ + +/*! + * \fn ProjectExplorer::IDevice::Id ProjectExplorer::IDevice::invalidId() + * \brief A value that no device can ever have as its internal id. + */ + +/*! + * \fn ProjectExplorer::IDevice::Ptr ProjectExploer::IDevice::clone() const + * \brief Creates an identical copy of a device object. + */ + +/*! + * \fn void fromMap(const QVariantMap &map) + * \brief Restores a device object from a serialized state as written by \c toMap(). + * If subclasses override this to restore additional state, they must call the base class + * implementation. + */ + +/*! + * \fn QVariantMap toMap() const + * \brief Serializes a device object, e.g. to save it to a file. + * If subclasses override this to save additional state, they must call the base class + * implementation. + */ + +namespace ProjectExplorer { + +const char DisplayNameKey[] = "Name"; +const char TypeKey[] = "OsType"; +const char InternalIdKey[] = "InternalId"; +const char OriginKey[] = "Origin"; +const char FingerprintKey[] = "FingerPrint"; + +namespace Internal { +class IDevicePrivate +{ +public: + QString displayName; + QString type; + IDevice::Origin origin; + IDevice::Id internalId; + QString fingerprint; +}; +} // namespace Internal + +IDevice::IDevice() : d(new Internal::IDevicePrivate) +{ +} + +IDevice::IDevice(const QString &type, Origin origin, const QString fingerprint) + : d(new Internal::IDevicePrivate) +{ + d->type = type; + d->origin = origin; + d->fingerprint = fingerprint; + QTC_CHECK(d->origin == ManuallyAdded || !d->fingerprint.isEmpty()); +} + +IDevice::IDevice(const IDevice &other) : d(new Internal::IDevicePrivate) +{ + *d = *other.d; +} + +IDevice::~IDevice() +{ + delete d; +} + +QString IDevice::displayName() const +{ + return d->displayName; +} + +void IDevice::setDisplayName(const QString &name) +{ + d->displayName = name; +} + +QString IDevice::type() const +{ + return d->type; +} + +bool IDevice::isAutoDetected() const +{ + return d->origin == AutoDetected; +} + +QString IDevice::fingerprint() const +{ + return d->fingerprint; +} + +IDevice::Id IDevice::internalId() const +{ + return d->internalId; +} + +void IDevice::setInternalId(IDevice::Id id) +{ + d->internalId = id; +} + +IDevice::Id IDevice::invalidId() +{ + return 0; +} + +QString IDevice::typeFromMap(const QVariantMap &map) +{ + return map.value(QLatin1String(TypeKey)).toString(); +} + +void IDevice::fromMap(const QVariantMap &map) +{ + d->type = typeFromMap(map); + d->displayName = map.value(QLatin1String(DisplayNameKey)).toString(); + d->internalId = map.value(QLatin1String(InternalIdKey), invalidId()).toULongLong(); + d->origin = static_cast<Origin>(map.value(QLatin1String(OriginKey), ManuallyAdded).toInt()); + d->fingerprint = map.value(QLatin1String(FingerprintKey)).toString(); + QTC_CHECK(d->origin == ManuallyAdded || !d->fingerprint.isEmpty()); +} + +QVariantMap IDevice::toMap() const +{ + QVariantMap map; + map.insert(QLatin1String(DisplayNameKey), d->displayName); + map.insert(QLatin1String(TypeKey), d->type); + map.insert(QLatin1String(InternalIdKey), d->internalId); + map.insert(QLatin1String(OriginKey), d->origin); + map.insert(QLatin1String(FingerprintKey), d->fingerprint); + return map; +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h new file mode 100644 index 0000000000..047d7698d6 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -0,0 +1,89 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#ifndef IDEVICE_H +#define IDEVICE_H + +#include <projectexplorer/projectexplorer_export.h> + +#include <QSharedPointer> +#include <QVariantMap> + +namespace ProjectExplorer { +namespace Internal { class IDevicePrivate; } + +// See cpp file for documentation. +class PROJECTEXPLORER_EXPORT IDevice +{ + friend class DeviceManager; +public: + typedef QSharedPointer<IDevice> Ptr; + typedef QSharedPointer<const IDevice> ConstPtr; + + typedef quint64 Id; + + enum Origin { ManuallyAdded, AutoDetected }; + + virtual ~IDevice(); + + QString displayName() const; + void setDisplayName(const QString &name); + + QString type() const; + bool isAutoDetected() const; + QString fingerprint() const; + Id internalId() const; + + virtual void fromMap(const QVariantMap &map); + virtual Ptr clone() const = 0; + + static Id invalidId(); + + static QString typeFromMap(const QVariantMap &map); + +protected: + IDevice(); + IDevice(const QString &type, Origin origin, const QString fingerprint = QString()); + IDevice(const IDevice &other); + + virtual QVariantMap toMap() const; + +private: + void setInternalId(Id id); + + IDevice &operator=(const IDevice &); + + Internal::IDevicePrivate *d; +}; + +} // namespace ProjectExplorer + +#endif // IDEVICE_H diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.h b/src/plugins/projectexplorer/devicesupport/idevicefactory.h new file mode 100644 index 0000000000..b55570c98a --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.h @@ -0,0 +1,129 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#ifndef IDEVICEFACTORY_H +#define IDEVICEFACTORY_H + +#include "idevice.h" +#include <projectexplorer/projectexplorer_export.h> + +#include <QObject> +#include <QStringList> +#include <QVariantMap> + +QT_BEGIN_NAMESPACE +class QDialog; +class QWidget; +QT_END_NAMESPACE + +namespace ProjectExplorer { +class IDeviceWidget; +class IDeviceWizard; + +/*! + \class ProjectExplorer::IDeviceFactory + + \brief Provides an interface for classes providing services related to certain type of device. + + The factory objects have to be added to the global object pool via + \c ExtensionSystem::PluginManager::addObject(). + \sa ExtensionSystem::PluginManager::addObject() +*/ +class PROJECTEXPLORER_EXPORT IDeviceFactory : public QObject +{ + Q_OBJECT + +public: + /*! + A short, one-line description of what kind of device this factory supports. + */ + virtual QString displayName() const = 0; + + /*! + A wizard that can create the types of device this factory supports. + */ + virtual IDeviceWizard *createWizard(QWidget *parent = 0) const = 0; + + /*! + Loads a device from a serialized state. The device must be of a matching type. + */ + virtual IDevice::Ptr loadDevice(const QVariantMap &map) const = 0; + + /*! + A widget that can configure the device this factory supports. + */ + virtual IDeviceWidget *createWidget(const IDevice::Ptr &device, QWidget *parent = 0) const = 0; + + /*! + Returns true iff this factory supports the given device type. + */ + virtual bool supportsDeviceType(const QString &type) const = 0; + + /*! + Returns a human-readable string for the given device type, if this factory supports that type. + */ + virtual QString displayNameForDeviceType(const QString &type) const = 0; + + /*! + Returns a list of ids representing actions that can be run on devices + that this factory supports. These actions will be available in the "Devices" + options page. + */ + virtual QStringList supportedDeviceActionIds() const = 0; + + /*! + A human-readable string for the given id. Will be displayed on a button which, when clicked, + starts the respective action. + */ + virtual QString displayNameForActionId(const QString &actionId) const = 0; + + /*! + True iff the user should be allowed to edit the devices created by this + factory. Returns true by default. Override if your factory creates fixed configurations + for which later editing makes no sense. + */ + virtual bool isUserEditable() const { return true; } + + /*! + Produces a dialog implementing the respective action. The dialog is supposed to be + modal, so implementers must make sure to make it interruptible as to not needlessly + block the UI. + */ + virtual QDialog *createDeviceAction(const QString &actionId, const IDevice::ConstPtr &device, + QWidget *parent = 0) const = 0; + +protected: + IDeviceFactory(QObject *parent) : QObject(parent) { } +}; + +} // namespace ProjectExplorer + +#endif // IDEVICEFACTORY_H diff --git a/src/plugins/remotelinux/portlist.h b/src/plugins/projectexplorer/devicesupport/idevicewidget.h index d9681ad80f..487592a638 100644 --- a/src/plugins/remotelinux/portlist.h +++ b/src/plugins/projectexplorer/devicesupport/idevicewidget.h @@ -29,41 +29,40 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ -#ifndef PORTLIST_H -#define PORTLIST_H +#ifndef IDEVICEWIDGET_H +#define IDEVICEWIDGET_H -#include "remotelinux_export.h" +#include "idevice.h" +#include <projectexplorer/projectexplorer_export.h> -QT_FORWARD_DECLARE_CLASS(QString) +#include <QWidget> -namespace RemoteLinux { -namespace Internal { -class PortListPrivate; -} // namespace Internal +namespace ProjectExplorer { -class REMOTELINUX_EXPORT PortList +/*! + \class ProjectExplorer::IDeviceWidget + + \brief Provides an interface for the widget configuring an IDevice. + + A class implementing this interface will display a widget in the configuration + options page "Devices". + It is used to let the user configure a particular device. +*/ + +class PROJECTEXPLORER_EXPORT IDeviceWidget : public QWidget { -public: - PortList(); - PortList(const PortList &other); - PortList &operator=(const PortList &other); - ~PortList(); + Q_OBJECT - void addPort(int port); - void addRange(int startPort, int endPort); - bool hasMore() const; - bool contains(int port) const; - int count() const; - int getNext(); - QString toString() const; +protected: + IDeviceWidget(const IDevice::Ptr &device, QWidget *parent = 0) + : QWidget(parent), m_device(device) {} - static PortList fromString(const QString &portsSpec); - static QString regularExpression(); + IDevice::Ptr device() const { return m_device; } private: - Internal::PortListPrivate * const d; + IDevice::Ptr m_device; }; -} // namespace RemoteLinux +} // namespace ProjectExplorer -#endif // PORTLIST_H +#endif // IDEVICEWIDGET_H diff --git a/src/plugins/remotelinux/sshkeycreationdialog.h b/src/plugins/projectexplorer/devicesupport/idevicewizard.h index 2acb22480e..5e109f0b47 100644 --- a/src/plugins/remotelinux/sshkeycreationdialog.h +++ b/src/plugins/projectexplorer/devicesupport/idevicewizard.h @@ -6,6 +6,7 @@ ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** +** ** GNU Lesser General Public License Usage ** ** This file may be used under the terms of the GNU Lesser General Public @@ -28,44 +29,36 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ +#ifndef IDEVICEWIZARD_H +#define IDEVICEWIZARD_H + +#include "idevice.h" +#include <projectexplorer/projectexplorer_export.h> -#ifndef SSHKEYCREATIONDIALOG_H -#define SSHKEYCREATIONDIALOG_H +#include <QWizard> -#include <QDialog> +namespace ProjectExplorer { -namespace Utils { -class SshKeyGenerator; -} +/*! + \class ProjectExplorer::IDeviceWizard -namespace RemoteLinux { -namespace Internal { -namespace Ui { -class SshKeyCreationDialog; -} + \brief Provides an interface for wizards creating an IDevice subclass. -class SshKeyCreationDialog : public QDialog + A class implementing this interface is a wizard whose final result is + an \c IDevice object. The wizard will be started when the user chooses the + "Add..." action from the "Devices" options page. +*/ +class PROJECTEXPLORER_EXPORT IDeviceWizard : public QWizard { Q_OBJECT -public: - SshKeyCreationDialog(QWidget *parent = 0); - ~SshKeyCreationDialog(); -private slots: - void keyTypeChanged(); - void generateKeys(); - void filePathChanged(); - -private: - void saveKeys(); - QString privateKeyFilePath() const; +public: + virtual IDevice::Ptr device() = 0; -private: - Utils::SshKeyGenerator *m_keyGenerator; - Ui::SshKeyCreationDialog *m_ui; +protected: + IDeviceWizard(QWidget *parent) : QWizard(parent) { } }; -} // namespace Internal -} // namespace RemoteLinux +} // namespace ProjectExplorer -#endif // SSHKEYCREATIONDIALOG_H +#endif // IDEVICEWIZARD_H diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index ec4c0c91a4..a6b1d6942e 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -146,10 +146,12 @@ static QByteArray gccPredefinedMacros(const Utils::FileName &gcc, const QStringL return predefinedMacros; } -static QList<HeaderPath> gccHeaderPathes(const Utils::FileName &gcc, const QStringList &env) +QList<HeaderPath> GccToolChain::gccHeaderPaths(const Utils::FileName &gcc, const QStringList &env, const QString &sysrootPath) { QList<HeaderPath> systemHeaderPaths; QStringList arguments; + if (!sysrootPath.isEmpty()) + arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysrootPath)); arguments << QLatin1String("-xc++") << QLatin1String("-E") << QLatin1String("-v") @@ -326,7 +328,7 @@ GccToolChain::GccToolChain(const GccToolChain &tc) : m_debuggerCommand(tc.debuggerCommand()), m_targetAbi(tc.m_targetAbi), m_supportedAbis(tc.m_supportedAbis), - m_headerPathes(tc.m_headerPathes), + m_headerPaths(tc.m_headerPaths), m_version(tc.m_version) { } @@ -409,13 +411,13 @@ ProjectExplorer::ToolChain::CompilerFlags GccToolChain::compilerFlags(const QStr QList<HeaderPath> GccToolChain::systemHeaderPaths() const { - if (m_headerPathes.isEmpty()) { + if (m_headerPaths.isEmpty()) { // Using a clean environment breaks ccache/distcc/etc. Utils::Environment env = Utils::Environment::systemEnvironment(); addToEnvironment(env); - m_headerPathes = gccHeaderPathes(m_compilerCommand, env.toStringList()); + m_headerPaths = gccHeaderPaths(m_compilerCommand, env.toStringList()); } - return m_headerPathes; + return m_headerPaths; } void GccToolChain::addToEnvironment(Utils::Environment &env) const diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index ca9a2c239f..4a77843c16 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -97,6 +97,8 @@ protected: virtual QList<Abi> detectSupportedAbis() const; virtual QString detectVersion() const; + static QList<HeaderPath> gccHeaderPaths(const Utils::FileName &gcc, const QStringList &env, const QString &sysrootPath = QString()); + mutable QByteArray m_predefinedMacros; private: @@ -109,7 +111,7 @@ private: Abi m_targetAbi; mutable QList<Abi> m_supportedAbis; - mutable QList<HeaderPath> m_headerPathes; + mutable QList<HeaderPath> m_headerPaths; mutable QString m_version; friend class Internal::GccToolChainFactory; diff --git a/src/plugins/projectexplorer/iprojectproperties.h b/src/plugins/projectexplorer/iprojectproperties.h index 110b4f9a53..b86d3351e9 100644 --- a/src/plugins/projectexplorer/iprojectproperties.h +++ b/src/plugins/projectexplorer/iprojectproperties.h @@ -87,8 +87,6 @@ class PROJECTEXPLORER_EXPORT IProjectPanelFactory : public IPanelFactory public: virtual bool supports(Project *project) = 0; virtual PropertiesPanel *createPanel(Project *project) = 0; -signals: - void projectUpdated(ProjectExplorer::Project *project); }; class PROJECTEXPLORER_EXPORT ITargetPanelFactory : public IPanelFactory diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index cb60322621..46166a08aa 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -388,4 +388,9 @@ bool Project::needsConfiguration() const return false; } +void Project::configureAsExampleProject(const QStringList &platforms) +{ + Q_UNUSED(platforms); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index b4f217c900..712de97233 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -74,8 +74,6 @@ public: virtual Core::IDocument *document() const = 0; virtual IProjectManager *projectManager() const = 0; - virtual QList<Project *> dependsOn() = 0; //NBS TODO implement dependsOn - bool hasActiveBuildSettings() const; // EditorConfiguration: @@ -118,6 +116,7 @@ public: void setNamedSettings(const QString &name, QVariant &value); virtual bool needsConfiguration() const; + virtual void configureAsExampleProject(const QStringList &platforms); signals: void fileListChanged(); diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 016644bdfd..1611a7356d 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -79,6 +79,7 @@ #include "buildconfiguration.h" #include "miniprojecttargetselector.h" #include "taskhub.h" +#include "devicesupport/devicesettingspage.h" #include "publishing/ipublishingwizardfactory.h" #include "publishing/publishingwizardselectiondialog.h" @@ -375,13 +376,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er addAutoReleasedObject(new CopyTaskHandler); addAutoReleasedObject(new ShowInEditorTaskHandler); addAutoReleasedObject(new VcsAnnotateTaskHandler); - - d->m_buildManager = new BuildManager(this); - connect(d->m_buildManager, SIGNAL(buildStateChanged(ProjectExplorer::Project*)), - this, SLOT(buildStateChanged(ProjectExplorer::Project*))); - connect(d->m_buildManager, SIGNAL(buildQueueFinished(bool)), - this, SLOT(buildQueueFinished(bool))); - addAutoReleasedObject(new CoreListener); d->m_outputPane = new AppOutputPane; @@ -420,8 +414,9 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er addAutoReleasedObject(new ProjectFileWizardExtension); - // Settings page + // Settings pages addAutoReleasedObject(new ProjectExplorerSettingsPage); + addAutoReleasedObject(new DeviceSettingsPage); // context menus Core::ActionContainer *msessionContextMenu = @@ -796,7 +791,9 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er mbuild->addAction(cmd, Constants::G_BUILD_RUN); // cancel build action - d->m_cancelBuildAction = new QAction(tr("Cancel Build"), this); + QIcon stopIcon = QIcon(QLatin1String(Constants::ICON_STOP)); + stopIcon.addFile(QLatin1String(Constants::ICON_STOP_SMALL)); + d->m_cancelBuildAction = new QAction(stopIcon, tr("Cancel Build"), this); cmd = am->registerAction(d->m_cancelBuildAction, Constants::CANCELBUILD, globalcontext); mbuild->addAction(cmd, Constants::G_BUILD_CANCEL); @@ -1001,6 +998,12 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er connect(this, SIGNAL(updateRunActions()), this, SLOT(slotUpdateRunActions())); connect(this, SIGNAL(settingsChanged()), this, SLOT(updateRunWithoutDeployMenu())); + d->m_buildManager = new BuildManager(this, d->m_cancelBuildAction); + connect(d->m_buildManager, SIGNAL(buildStateChanged(ProjectExplorer::Project*)), + this, SLOT(buildStateChanged(ProjectExplorer::Project*))); + connect(d->m_buildManager, SIGNAL(buildQueueFinished(bool)), + this, SLOT(buildQueueFinished(bool))); + updateActions(); connect(Core::ICore::instance(), SIGNAL(coreAboutToOpen()), @@ -1277,7 +1280,7 @@ void ProjectExplorerPlugin::openProjectWelcomePage(const QString &fileName) QMessageBox::critical(Core::ICore::mainWindow(), tr("Failed to open project"), errorMessage); } -bool ProjectExplorerPlugin::openProject(const QString &fileName, QString *errorString) +Project *ProjectExplorerPlugin::openProject(const QString &fileName, QString *errorString) { if (debug) qDebug() << "ProjectExplorerPlugin::openProject"; @@ -1286,9 +1289,9 @@ bool ProjectExplorerPlugin::openProject(const QString &fileName, QString *errorS if (!list.isEmpty()) { addToRecentProjects(fileName, list.first()->displayName()); d->m_session->setStartupProject(list.first()); - return true; + return list.first(); } - return false; + return 0; } static inline QList<IProjectManager*> allProjectManagers() @@ -1865,6 +1868,11 @@ void ProjectExplorerPlugin::buildProject(ProjectExplorer::Project *p) QStringList(QLatin1String(Constants::BUILDSTEPS_BUILD))); } +void ProjectExplorerPlugin::requestProjectModeUpdate(Project *p) +{ + d->m_proWindow->projectUpdated(p); +} + void ProjectExplorerPlugin::buildProject() { queue(d->m_session->projectOrder(session()->startupProject()), @@ -2200,14 +2208,14 @@ void ProjectExplorerPlugin::activeRunConfigurationChanged() if (rc == previousRunConfiguration) return; if (previousRunConfiguration) { - disconnect(previousRunConfiguration, SIGNAL(isEnabledChanged(bool)), + disconnect(previousRunConfiguration, SIGNAL(enabledChanged()), this, SIGNAL(updateRunActions())); disconnect(previousRunConfiguration->debuggerAspect(), SIGNAL(debuggersChanged()), this, SIGNAL(updateRunActions())); } previousRunConfiguration = rc; if (rc) { - connect(rc, SIGNAL(isEnabledChanged(bool)), + connect(rc, SIGNAL(enabledChanged()), this, SIGNAL(updateRunActions())); connect(rc->debuggerAspect(), SIGNAL(debuggersChanged()), this, SIGNAL(updateRunActions())); diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 49145de8f2..8e61dbc71f 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -72,6 +72,7 @@ class PROJECTEXPLORER_EXPORT ProjectExplorerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ProjectExplorer.json") public: ProjectExplorerPlugin(); @@ -79,7 +80,7 @@ public: static ProjectExplorerPlugin *instance(); - bool openProject(const QString &fileName, QString *error); + Project *openProject(const QString &fileName, QString *error); QList<Project *> openProjects(const QStringList &fileNames, QString *error); Q_SLOT void openProjectWelcomePage(const QString &fileName); @@ -126,6 +127,9 @@ public: void addExistingFiles(const QStringList &filePaths); void buildProject(ProjectExplorer::Project *p); + /// Normally there's no need to call this function. + /// This function needs to be called, only if the pages that support a project changed. + void requestProjectModeUpdate(ProjectExplorer::Project *p); QList<RunControl *> runControls() const; diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 5c7dfe9d19..1727a93388 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -1,8 +1,12 @@ TEMPLATE = lib TARGET = ProjectExplorer -QT += xml \ - script \ - declarative +QT += xml script +greaterThan(QT_MAJOR_VERSION, 4) { + QT += quick1 +} else { + QT += declarative +} + include(../../qtcreatorplugin.pri) include(projectexplorer_dependencies.pri) include(../../libs/utils/utils.pri) @@ -102,7 +106,16 @@ HEADERS += projectexplorer.h \ appoutputpane.h \ codestylesettingspropertiespage.h \ settingsaccessor.h \ - environmentitemswidget.h + environmentitemswidget.h \ + devicesupport/idevice.h \ + devicesupport/idevicewizard.h \ + devicesupport/idevicewidget.h \ + devicesupport/idevicefactory.h \ + devicesupport/devicemanager.h \ + devicesupport/devicemanagermodel.h \ + devicesupport/devicefactoryselectiondialog.h \ + devicesupport/devicesettingswidget.h \ + devicesupport/devicesettingspage.h SOURCES += projectexplorer.cpp \ abi.cpp \ @@ -188,7 +201,13 @@ SOURCES += projectexplorer.cpp \ appoutputpane.cpp \ codestylesettingspropertiespage.cpp \ settingsaccessor.cpp \ - environmentitemswidget.cpp + environmentitemswidget.cpp \ + devicesupport/idevice.cpp \ + devicesupport/devicemanager.cpp \ + devicesupport/devicemanagermodel.cpp \ + devicesupport/devicefactoryselectiondialog.cpp \ + devicesupport/devicesettingswidget.cpp \ + devicesupport/devicesettingspage.cpp FORMS += processstep.ui \ toolchainoptionspage.ui \ @@ -200,7 +219,9 @@ FORMS += processstep.ui \ targetsettingswidget.ui \ doubletabwidget.ui \ publishing/publishingwizardselectiondialog.ui \ - codestylesettingspropertiespage.ui + codestylesettingspropertiespage.ui \ + devicesupport/devicefactoryselectiondialog.ui \ + devicesupport/devicesettingswidget.ui WINSOURCES += \ windebuginterface.cpp \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 539ec48d03..f559c571aa 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -271,7 +271,24 @@ QtcPlugin { "publishing/publishingwizardselectiondialog.ui", "publishing/ipublishingwizardfactory.h", "publishing/publishingwizardselectiondialog.cpp", - "publishing/publishingwizardselectiondialog.h" + "publishing/publishingwizardselectiondialog.h", + "devicesupport/idevice.h", + "devicesupport/idevice.cpp", + "devicesupport/devicemanager.h", + "devicesupport/devicemanager.cpp", + "devicesupport/devicemanagermodel.h", + "devicesupport/devicemanagermodel.cpp", + "devicesupport/devicesettingspage.h", + "devicesupport/devicesettingspage.cpp", + "devicesupport/devicefactoryselectiondialog.cpp", + "devicesupport/devicefactoryselectiondialog.h", + "devicesupport/devicefactoryselectiondialog.ui", + "devicesupport/devicesettingswidget.cpp", + "devicesupport/devicesettingswidget.h", + "devicesupport/devicesettingswidget.ui", + "devicesupport/idevicewizard.h", + "devicesupport/idevicewidget.h", + "devicesupport/idevicefactory.h" ] Group { diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index 5c6c18cdf0..decd9d7350 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -185,6 +185,10 @@ const char PROJECTEXPLORER_SETTINGS_CATEGORY_ICON[] = ":/core/images/category_b const char PROJECTEXPLORER_SETTINGS_ID[] = "A.ProjectExplorer.ProjectExplorer"; const char TOOLCHAIN_SETTINGS_PAGE_ID[] = "M.ProjectExplorer.ToolChainOptions"; +// Device settings page +const char DEVICE_SETTINGS_CATEGORY[] = "X.Devices"; +const char DEVICE_SETTINGS_PAGE_ID[] = "AA.Device Settings"; + // Task categories const char TASK_CATEGORY_COMPILE[] = "Task.Category.Compile"; const char TASK_CATEGORY_BUILDSYSTEM[] = "Task.Category.Buildsystem"; diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index ee4c436d5a..f26e4d2e45 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -32,6 +32,8 @@ #include "projectwelcomepage.h" +#include "projectexplorerconstants.h" + #include <utils/stringutils.h> #include <QDeclarativeEngine> @@ -216,6 +218,11 @@ void ProjectWelcomePage::facilitateQml(QDeclarativeEngine *engine) ctx->setContextProperty(QLatin1String("projectWelcomePage"), this); } +ProjectWelcomePage::Id ProjectWelcomePage::id() const +{ + return Develop; +} + void ProjectWelcomePage::reloadWelcomeScreenData() { if (m_sessionModel) diff --git a/src/plugins/projectexplorer/projectwelcomepage.h b/src/plugins/projectexplorer/projectwelcomepage.h index 2e85551b2e..5c0d963a3b 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.h +++ b/src/plugins/projectexplorer/projectwelcomepage.h @@ -101,6 +101,7 @@ public: QWidget *page() { return 0; } QString title() const { return tr("Develop"); } int priority() const { return 20; } + Id id() const; void reloadWelcomeScreenData(); diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp index 5ea53f46c1..ceddef50bd 100644 --- a/src/plugins/projectexplorer/projectwindow.cpp +++ b/src/plugins/projectexplorer/projectwindow.cpp @@ -268,10 +268,6 @@ void ProjectWindow::extensionsInitialized() QList<IProjectPanelFactory *> list = ExtensionSystem::PluginManager::instance()->getObjects<IProjectPanelFactory>(); qSort(list.begin(), list.end(), &IPanelFactory::prioritySort); - foreach (IProjectPanelFactory *fac, list) - connect (fac, SIGNAL(projectUpdated(ProjectExplorer::Project*)), - this, SLOT(projectUpdated(ProjectExplorer::Project*))); - } void ProjectWindow::aboutToShutdown() diff --git a/src/plugins/projectexplorer/projectwindow.h b/src/plugins/projectexplorer/projectwindow.h index c4f372a09e..8a5be9f2f9 100644 --- a/src/plugins/projectexplorer/projectwindow.h +++ b/src/plugins/projectexplorer/projectwindow.h @@ -82,6 +82,7 @@ public: void aboutToShutdown(); void extensionsInitialized(); + void projectUpdated(ProjectExplorer::Project *p); private slots: void targetFactoriesChanged(); void showProperties(int index, int subIndex); @@ -90,7 +91,6 @@ private slots: void registerProject(ProjectExplorer::Project*); void deregisterProject(ProjectExplorer::Project*); void startupProjectChanged(ProjectExplorer::Project *); - void projectUpdated(ProjectExplorer::Project *p); private: bool useTargetPage(ProjectExplorer::Project *project); diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp index 846d732b81..925b141f94 100644 --- a/src/plugins/projectexplorer/projectwizardpage.cpp +++ b/src/plugins/projectexplorer/projectwizardpage.cpp @@ -34,6 +34,7 @@ #include "ui_projectwizardpage.h" #include <coreplugin/icore.h> +#include <utils/fileutils.h> #include <vcsbase/vcsbaseconstants.h> #include <QDir> @@ -135,6 +136,18 @@ void ProjectWizardPage::changeEvent(QEvent *e) } } +// Alphabetically, and files in sub-directories first +static bool generatedFilePathLessThan(const QString &filePath1, const QString &filePath2) +{ + const bool filePath1HasDir = filePath1.contains(QLatin1Char('/')); + const bool filePath2HasDir = filePath2.contains(QLatin1Char('/')); + + if (filePath1HasDir == filePath2HasDir) + return Utils::FileName::fromString(filePath1) < Utils::FileName::fromString(filePath2); + else + return filePath1HasDir; +} + void ProjectWizardPage::setFilesDisplay(const QString &commonPath, const QStringList &files) { QString fileMessage; @@ -143,15 +156,21 @@ void ProjectWizardPage::setFilesDisplay(const QString &commonPath, const QString str << "<qt>" << (commonPath.isEmpty() ? tr("Files to be added:") : tr("Files to be added in")) << "<pre>"; + + QStringList formattedFiles; if (commonPath.isEmpty()) { - foreach(const QString &f, files) - str << QDir::toNativeSeparators(f) << '\n'; + formattedFiles = files; } else { str << QDir::toNativeSeparators(commonPath) << ":\n\n"; const int prefixSize = commonPath.size() + 1; - foreach(const QString &f, files) - str << QDir::toNativeSeparators(f.right(f.size() - prefixSize)) << '\n'; + foreach (const QString &f, files) + formattedFiles.append(f.right(f.size() - prefixSize)); } + qSort(formattedFiles.begin(), formattedFiles.end(), generatedFilePathLessThan); + + foreach (const QString &f, formattedFiles) + str << QDir::toNativeSeparators(f) << '\n'; + str << "</pre>"; } m_ui->filesLabel->setText(fileMessage); diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 765b22b0e1..dad8503c5a 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -64,6 +64,7 @@ const char USE_CPP_DEBUGGER_KEY[] = "RunConfiguration.UseCppDebugger"; const char USE_QML_DEBUGGER_KEY[] = "RunConfiguration.UseQmlDebugger"; const char USE_QML_DEBUGGER_AUTO_KEY[] = "RunConfiguration.UseQmlDebuggerAuto"; const char QML_DEBUG_SERVER_PORT_KEY[] = "RunConfiguration.QmlDebugServerPort"; +const char USE_MULTIPROCESS_KEY[] = "RunConfiguration.UseMultiProcess"; // Function objects: @@ -203,6 +204,7 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(RunConfiguration m_useCppDebugger(true), m_useQmlDebugger(AutoEnableQmlDebugger), m_qmlDebugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT), + m_useMultiProcess(false), m_suppressDisplay(false), m_suppressQmlDebuggingOptions(false), m_suppressCppDebuggingOptions(false), @@ -214,6 +216,7 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(DebuggerRunConfig m_useCppDebugger(other->m_useCppDebugger), m_useQmlDebugger(other->m_useQmlDebugger), m_qmlDebugServerPort(other->m_qmlDebugServerPort), + m_useMultiProcess(other->m_useMultiProcess), m_suppressDisplay(other->m_suppressDisplay), m_suppressQmlDebuggingOptions(other->m_suppressQmlDebuggingOptions), m_suppressCppDebuggingOptions(other->m_suppressCppDebuggingOptions), @@ -266,6 +269,16 @@ void DebuggerRunConfigurationAspect::setQmllDebugServerPort(uint port) m_qmlDebugServerPort = port; } +bool DebuggerRunConfigurationAspect::useMultiProcess() const +{ + return m_useMultiProcess; +} + +void DebuggerRunConfigurationAspect::setUseMultiProcess(bool value) +{ + m_useMultiProcess = value; +} + void DebuggerRunConfigurationAspect::suppressDisplay() { m_suppressDisplay = true; @@ -318,6 +331,7 @@ QVariantMap DebuggerRunConfigurationAspect::toMap() const map.insert(QLatin1String(USE_QML_DEBUGGER_KEY), m_useQmlDebugger == EnableQmlDebugger); map.insert(QLatin1String(USE_QML_DEBUGGER_AUTO_KEY), m_useQmlDebugger == AutoEnableQmlDebugger); map.insert(QLatin1String(QML_DEBUG_SERVER_PORT_KEY), m_qmlDebugServerPort); + map.insert(QLatin1String(USE_MULTIPROCESS_KEY), m_useMultiProcess); return map; } @@ -330,6 +344,7 @@ void DebuggerRunConfigurationAspect::fromMap(const QVariantMap &map) bool useQml = map.value(QLatin1String(USE_QML_DEBUGGER_KEY), false).toBool(); m_useQmlDebugger = useQml ? EnableQmlDebugger : DisableQmlDebugger; } + m_useMultiProcess = map.value(QLatin1String(USE_MULTIPROCESS_KEY), false).toBool(); } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index aa6981f0d8..978f01b99a 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -106,12 +106,14 @@ public: QString displayName() const; - void setUseQmlDebugger(bool value); - void setUseCppDebugger(bool value); bool useCppDebugger() const; + void setUseCppDebugger(bool value); bool useQmlDebugger() const; + void setUseQmlDebugger(bool value); uint qmlDebugServerPort() const; void setQmllDebugServerPort(uint port); + bool useMultiProcess() const; + void setUseMultiProcess(bool on); void suppressDisplay(); void suppressQmlDebuggingOptions(); void suppressCppDebuggingOptions(); @@ -130,6 +132,8 @@ public: bool m_useCppDebugger; QmlDebuggerStatus m_useQmlDebugger; uint m_qmlDebugServerPort; + bool m_useMultiProcess; + bool m_suppressDisplay; bool m_suppressQmlDebuggingOptions; bool m_suppressCppDebuggingOptions; @@ -174,7 +178,7 @@ public: virtual ProjectExplorer::Abi abi() const; signals: - void isEnabledChanged(bool value); + void enabledChanged(); protected: RunConfiguration(Target *parent, const QString &id); diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index 5cc125d8ee..4ee674d3ef 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -129,6 +129,20 @@ void Target::changeBuildConfigurationEnabled() emit buildConfigurationEnabledChanged(); } +void Target::changeDeployConfigurationEnabled() +{ + DeployConfiguration *dc = qobject_cast<DeployConfiguration *>(sender()); + if (dc == activeDeployConfiguration()) + emit deployConfigurationEnabledChanged(); +} + +void Target::changeRunConfigurationEnabled() +{ + RunConfiguration *rc = qobject_cast<RunConfiguration *>(sender()); + if (rc == activeRunConfiguration()) + emit runConfigurationEnabledChanged(); +} + Project *Target::project() const { return static_cast<Project *>(parent()); @@ -243,6 +257,8 @@ void Target::addDeployConfiguration(DeployConfiguration *dc) // add it d->m_deployConfigurations.push_back(dc); + connect(dc, SIGNAL(enabledChanged()), this, SLOT(changeDeployConfigurationEnabled())); + emit addedDeployConfiguration(dc); if (!d->m_activeDeployConfiguration) @@ -293,6 +309,7 @@ void Target::setActiveDeployConfiguration(DeployConfiguration *dc) dc != d->m_activeDeployConfiguration)) { d->m_activeDeployConfiguration = dc; emit activeDeployConfigurationChanged(d->m_activeDeployConfiguration); + emit deployConfigurationEnabledChanged(); } } @@ -341,6 +358,9 @@ void Target::addRunConfiguration(RunConfiguration* runConfiguration) runConfiguration->setDisplayName(configurationDisplayName); d->m_runConfigurations.push_back(runConfiguration); + + connect(runConfiguration, SIGNAL(enabledChanged()), this, SLOT(changeRunConfigurationEnabled())); + emit addedRunConfiguration(runConfiguration); if (!activeRunConfiguration()) @@ -376,6 +396,7 @@ void Target::setActiveRunConfiguration(RunConfiguration* configuration) configuration != d->m_activeRunConfiguration)) { d->m_activeRunConfiguration = configuration; emit activeRunConfigurationChanged(d->m_activeRunConfiguration); + emit runConfigurationEnabledChanged(); } } diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h index 2bfb2bf584..d15c1b0420 100644 --- a/src/plugins/projectexplorer/target.h +++ b/src/plugins/projectexplorer/target.h @@ -112,7 +112,6 @@ public: virtual QList<ToolChain *> possibleToolChains(BuildConfiguration *) const; virtual ToolChain *preferredToolChain(BuildConfiguration *) const; - virtual QVariantMap toMap() const; signals: @@ -123,8 +122,6 @@ signals: // TODO clean up signal names // might be better to also have aboutToRemove signals - void runConfigurationsEnabledStateChanged(); - void removedRunConfiguration(ProjectExplorer::RunConfiguration *); void addedRunConfiguration(ProjectExplorer::RunConfiguration *); void activeRunConfigurationChanged(ProjectExplorer::RunConfiguration *); @@ -141,9 +138,11 @@ signals: /// environmentChanged() or if the active build configuration changes void environmentChanged(); - /// convenience signal, emitted if either the active buildconfiguration emits + /// convenience signal, emitted if either the active configuration emits /// enabledChanged() or if the active build configuration changes void buildConfigurationEnabledChanged(); + void deployConfigurationEnabledChanged(); + void runConfigurationEnabledChanged(); protected: Target(Project *parent, const QString &id); @@ -155,6 +154,8 @@ protected: private slots: void changeEnvironment(); void changeBuildConfigurationEnabled(); + void changeDeployConfigurationEnabled(); + void changeRunConfigurationEnabled(); private: TargetPrivate *d; diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp index 1223b46b20..39ce6a4bd1 100644 --- a/src/plugins/projectexplorer/taskhub.cpp +++ b/src/plugins/projectexplorer/taskhub.cpp @@ -144,6 +144,11 @@ void TaskHub::taskMarkClicked(unsigned int id) emit showTask(id); } +void TaskHub::showTaskInEditor(unsigned int id) +{ + emit openTask(id); +} + void TaskHub::setCategoryVisibility(const Core::Id &categoryId, bool visible) { emit categoryVisibilityChanged(categoryId, visible); diff --git a/src/plugins/projectexplorer/taskhub.h b/src/plugins/projectexplorer/taskhub.h index e48d3f507c..66370c30ff 100644 --- a/src/plugins/projectexplorer/taskhub.h +++ b/src/plugins/projectexplorer/taskhub.h @@ -55,6 +55,7 @@ public: void updateTaskFileName(unsigned int id, const QString &fileName); void updateTaskLineNumber(unsigned int id, int line); void taskMarkClicked(unsigned int id); + void showTaskInEditor(unsigned int id); void setCategoryVisibility(const Core::Id &categoryId, bool visible); void popup(bool withFocus); @@ -71,6 +72,7 @@ signals: void categoryVisibilityChanged(const Core::Id &categoryId, bool visible); void popupRequested(bool withFocus); void showTask(unsigned int id); + void openTask(unsigned int id); private: const QIcon m_errorIcon; const QIcon m_warningIcon; diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index 3858c2661e..41dea75060 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -309,6 +309,8 @@ TaskWindow::TaskWindow(TaskHub *taskhub) : d(new TaskWindowPrivate) this, SLOT(popup(bool))); connect(d->m_taskHub, SIGNAL(showTask(uint)), this, SLOT(showTask(uint))); + connect(d->m_taskHub, SIGNAL(openTask(uint)), + this, SLOT(openTask(uint))); } TaskWindow::~TaskWindow() @@ -408,6 +410,14 @@ void TaskWindow::showTask(unsigned int id) popup(false); } +void TaskWindow::openTask(unsigned int id) +{ + int sourceRow = d->m_model->rowForId(id); + QModelIndex sourceIdx = d->m_model->index(sourceRow, 0); + QModelIndex filterIdx = d->m_filter->mapFromSource(sourceIdx); + triggerDefaultHandler(filterIdx); +} + void TaskWindow::triggerDefaultHandler(const QModelIndex &index) { if (!index.isValid()) diff --git a/src/plugins/projectexplorer/taskwindow.h b/src/plugins/projectexplorer/taskwindow.h index a83789b5db..1866d9c05a 100644 --- a/src/plugins/projectexplorer/taskwindow.h +++ b/src/plugins/projectexplorer/taskwindow.h @@ -92,6 +92,7 @@ private slots: void updatedTaskFileName(unsigned int id, const QString &fileName); void updatedTaskLineNumber(unsigned int id, int line); void showTask(unsigned int id); + void openTask(unsigned int id); void clearTasks(const Core::Id &categoryId); void setCategoryVisibility(const Core::Id &categoryId, bool visible); diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h index ec5cbb9af3..87d192e24a 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.h +++ b/src/plugins/qmldesigner/qmldesignerplugin.h @@ -65,6 +65,7 @@ class DesignModeContext; class BauhausPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlDesigner.json") public: BauhausPlugin(); diff --git a/src/plugins/qmljseditor/qmlfilewizard.cpp b/src/plugins/qmljseditor/qmlfilewizard.cpp index 5456908c8e..36911ddca6 100644 --- a/src/plugins/qmljseditor/qmlfilewizard.cpp +++ b/src/plugins/qmljseditor/qmlfilewizard.cpp @@ -59,12 +59,10 @@ Core::GeneratedFiles QmlFileWizard::generateFilesFromPath(const QString &path, return Core::GeneratedFiles() << file; } -QString QmlFileWizard::fileContents(const QString &fileName) const +QString QmlFileWizard::fileContents(const QString &) const { - const QString baseName = QFileInfo(fileName).completeBaseName(); QString contents; QTextStream str(&contents); -// str << CppTools::AbstractEditorSupport::licenseTemplate(); // 100:62 is the 'golden ratio' str << QLatin1String("// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5\n") diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 78ea9cff7b..b2f303a0e4 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -1387,11 +1387,6 @@ TextEditor::BaseTextEditorWidget::Link QmlJSTextEditorWidget::findLinkAt(const Q return Link(); } -void QmlJSTextEditorWidget::followSymbolUnderCursor() -{ - openLink(findLinkAt(textCursor())); -} - void QmlJSTextEditorWidget::findUsages() { m_findReferences->findUsages(editorDocument()->fileName(), textCursor().position()); diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index b97f327083..566dc0aa60 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -176,7 +176,6 @@ public slots: void reparseDocumentNow(); void updateSemanticInfo(); void updateSemanticInfoNow(); - void followSymbolUnderCursor(); void findUsages(); void renameUsages(); void showContextPane(); diff --git a/src/plugins/qmljseditor/qmljseditorconstants.h b/src/plugins/qmljseditor/qmljseditorconstants.h index dda05bb967..34dccae4f4 100644 --- a/src/plugins/qmljseditor/qmljseditorconstants.h +++ b/src/plugins/qmljseditor/qmljseditorconstants.h @@ -51,7 +51,6 @@ const char TASK_SEARCH[] = "QmlJSEditor.TaskSearch"; const char SETTINGS_CATEGORY_QML[] = "J.QtQuick"; const char SETTINGS_TR_CATEGORY_QML[] = QT_TRANSLATE_NOOP("QmlJSEditor", "Qt Quick"); -const char FOLLOW_SYMBOL_UNDER_CURSOR[] = "QmlJSEditor.FollowSymbolUnderCursor"; const char FIND_USAGES[] = "QmlJSEditor.FindUsages"; const char RENAME_USAGES[] = "QmlJSEditor.RenameUsages"; const char RUN_SEMANTIC_SCAN[] = "QmlJSEditor.RunSemanticScan"; diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp index 6795134d62..5faae4381f 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.cpp +++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp @@ -64,7 +64,7 @@ #include <coreplugin/actionmanager/command.h> #include <coreplugin/editormanager/editormanager.h> #include <projectexplorer/taskhub.h> -#include <extensionsystem/pluginmanager.h> +#include <projectexplorer/projectexplorer.h> #include <texteditor/texteditorconstants.h> #include <texteditor/texteditorsettings.h> #include <texteditor/textfilewizard.h> @@ -84,6 +84,7 @@ using namespace QmlJSEditor; using namespace QmlJSEditor::Internal; using namespace QmlJSEditor::Constants; +using namespace ProjectExplorer; enum { QUICKFIX_INTERVAL = 20 @@ -173,7 +174,8 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e m_actionHandler = new TextEditor::TextEditorActionHandler(QmlJSEditor::Constants::C_QMLJSEDITOR_ID, TextEditor::TextEditorActionHandler::Format | TextEditor::TextEditorActionHandler::UnCommentSelection - | TextEditor::TextEditorActionHandler::UnCollapseAll); + | TextEditor::TextEditorActionHandler::UnCollapseAll + | TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor); m_actionHandler->initializeActions(); Core::ActionManager *am = Core::ICore::actionManager(); @@ -184,10 +186,7 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e qmlToolsMenu->addAction(createSeparator(am, this, globalContext, QmlJSEditor::Constants::SEPARATOR3)); Core::Command *cmd; - QAction *followSymbolUnderCursorAction = new QAction(tr("Follow Symbol Under Cursor"), this); - cmd = am->registerAction(followSymbolUnderCursorAction, Constants::FOLLOW_SYMBOL_UNDER_CURSOR, context); - cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); - connect(followSymbolUnderCursorAction, SIGNAL(triggered()), this, SLOT(followSymbolUnderCursor())); + cmd = am->command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR); contextMenu->addAction(cmd); qmlToolsMenu->addAction(cmd); @@ -266,8 +265,7 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e void QmlJSEditorPlugin::extensionsInitialized() { - ProjectExplorer::TaskHub *taskHub = - ExtensionSystem::PluginManager::instance()->getObject<ProjectExplorer::TaskHub>(); + TaskHub *taskHub = ProjectExplorerPlugin::instance()->taskHub(); taskHub->addCategory(Constants::TASK_CATEGORY_QML, tr("QML")); taskHub->addCategory(Constants::TASK_CATEGORY_QML_ANALYSIS, tr("QML Analysis"), false); } @@ -294,14 +292,6 @@ Utils::JsonSchemaManager *QmlJSEditorPlugin::jsonManager() const return m_jsonManager.data(); } -void QmlJSEditorPlugin::followSymbolUnderCursor() -{ - Core::EditorManager *em = Core::EditorManager::instance(); - - if (QmlJSTextEditorWidget *editor = qobject_cast<QmlJSTextEditorWidget*>(em->currentEditor()->widget())) - editor->followSymbolUnderCursor(); -} - void QmlJSEditorPlugin::findUsages() { Core::EditorManager *em = Core::EditorManager::instance(); @@ -380,7 +370,7 @@ void QmlJSEditorPlugin::currentEditorChanged(Core::IEditor *editor) void QmlJSEditorPlugin::runSemanticScan() { m_qmlTaskManager->updateSemanticMessagesNow(); - ProjectExplorer::TaskHub *hub = ExtensionSystem::PluginManager::instance()->getObject<ProjectExplorer::TaskHub>(); + TaskHub *hub = ProjectExplorerPlugin::instance()->taskHub(); hub->setCategoryVisibility(Constants::TASK_CATEGORY_QML_ANALYSIS, true); hub->popup(false); } diff --git a/src/plugins/qmljseditor/qmljseditorplugin.h b/src/plugins/qmljseditor/qmljseditorplugin.h index 1633f0fd84..29e22f6b32 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.h +++ b/src/plugins/qmljseditor/qmljseditorplugin.h @@ -79,6 +79,7 @@ class QmlTaskManager; class QmlJSEditorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlJSEditor.json") public: QmlJSEditorPlugin(); @@ -99,7 +100,6 @@ public: Utils::JsonSchemaManager *jsonManager() const; public Q_SLOTS: - void followSymbolUnderCursor(); void findUsages(); void renameUsages(); void reformatFile(); diff --git a/src/plugins/qmljseditor/qmltaskmanager.cpp b/src/plugins/qmljseditor/qmltaskmanager.cpp index 4a238d5b8d..ed4e636af1 100644 --- a/src/plugins/qmljseditor/qmltaskmanager.cpp +++ b/src/plugins/qmljseditor/qmltaskmanager.cpp @@ -34,7 +34,7 @@ #include "qmljseditorconstants.h" #include <coreplugin/idocument.h> -#include <extensionsystem/pluginmanager.h> +#include <projectexplorer/projectexplorer.h> #include <projectexplorer/taskhub.h> #include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljscontext.h> @@ -57,7 +57,7 @@ QmlTaskManager::QmlTaskManager(QObject *parent) : m_taskHub(0), m_updatingSemantic(false) { - m_taskHub = ExtensionSystem::PluginManager::instance()->getObject<ProjectExplorer::TaskHub>(); + m_taskHub = ProjectExplorer::ProjectExplorerPlugin::instance()->taskHub(); // displaying results incrementally leads to flickering // connect(&m_messageCollector, SIGNAL(resultsReadyAt(int,int)), diff --git a/src/plugins/qmljsinspector/images/color-picker-small-hicontrast.png b/src/plugins/qmljsinspector/images/color-picker-small-hicontrast.png Binary files differdeleted file mode 100644 index 95b88ac8f0..0000000000 --- a/src/plugins/qmljsinspector/images/color-picker-small-hicontrast.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/color-picker-small.png b/src/plugins/qmljsinspector/images/color-picker-small.png Binary files differdeleted file mode 100644 index 026c31b3e1..0000000000 --- a/src/plugins/qmljsinspector/images/color-picker-small.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/color-picker.png b/src/plugins/qmljsinspector/images/color-picker.png Binary files differdeleted file mode 100644 index 73d9ae3dfc..0000000000 --- a/src/plugins/qmljsinspector/images/color-picker.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp index 418de0119f..5c8b3104a4 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp +++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp @@ -53,13 +53,10 @@ ClientProxy::ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent) , m_adapter(adapter) , m_engineClient(0) , m_inspectorClient(0) - , m_engineQuery(0) - , m_contextQuery(0) + , m_engineQueryId(0) + , m_contextQueryId(0) , m_isConnected(false) { - m_requestObjectsTimer.setSingleShot(true); - m_requestObjectsTimer.setInterval(3000); - connect(&m_requestObjectsTimer, SIGNAL(timeout()), this, SLOT(refreshObjectTree())); connectToServer(); } @@ -71,22 +68,29 @@ ClientProxy::~ClientProxy() void ClientProxy::connectToServer() { - m_engineClient = new QDeclarativeEngineDebug(m_adapter.data()->connection(), this); + QmlEngineDebugClient *client1 = new QDeclarativeEngineClient( + m_adapter.data()->connection()); + QmlEngineDebugClient *client2 = new QmlDebuggerClient( + m_adapter.data()->connection()); - connect(m_engineClient, SIGNAL(newObjects()), this, SLOT(newObjects())); - connect(m_engineClient, SIGNAL(statusChanged(QDeclarativeDebugClient::Status)), - this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status))); - connect(m_engineClient, SIGNAL(statusChanged(QDeclarativeDebugClient::Status)), - this, SLOT(engineClientStatusChanged(QDeclarativeDebugClient::Status))); + connect(client1, SIGNAL(newStatus(QDeclarativeDebugClient::Status)), + SLOT(clientStatusChanged(QDeclarativeDebugClient::Status))); + connect(client1, SIGNAL(newStatus(QDeclarativeDebugClient::Status)), + SLOT(engineClientStatusChanged(QDeclarativeDebugClient::Status))); + + connect(client2, SIGNAL(newStatus(QDeclarativeDebugClient::Status)), + SLOT(clientStatusChanged(QDeclarativeDebugClient::Status))); + connect(client2, SIGNAL(newStatus(QDeclarativeDebugClient::Status)), + SLOT(engineClientStatusChanged(QDeclarativeDebugClient::Status))); - m_inspectorClient = new QmlJSInspectorClient(m_adapter.data()->connection(), this); + m_inspectorClient = + new QmlJSInspectorClient(m_adapter.data()->connection(), this); - connect(m_inspectorClient, SIGNAL(connectedStatusChanged(QDeclarativeDebugClient::Status)), - this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status))); + connect(m_inspectorClient, + SIGNAL(connectedStatusChanged(QDeclarativeDebugClient::Status)), + this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status))); connect(m_inspectorClient, SIGNAL(currentObjectsChanged(QList<int>)), SLOT(onCurrentObjectsChanged(QList<int>))); - connect(m_inspectorClient, SIGNAL(colorPickerActivated()), - SIGNAL(colorPickerActivated())); connect(m_inspectorClient, SIGNAL(zoomToolActivated()), SIGNAL(zoomToolActivated())); connect(m_inspectorClient, SIGNAL(selectToolActivated()), @@ -103,8 +107,6 @@ void ClientProxy::connectToServer() SIGNAL(showAppOnTopChanged(bool))); connect(m_inspectorClient, SIGNAL(reloaded()), this, SIGNAL(serverReloaded())); - connect(m_inspectorClient, SIGNAL(selectedColorChanged(QColor)), - SIGNAL(selectedColorChanged(QColor))); connect(m_inspectorClient, SIGNAL(logActivity(QString,QString)), m_adapter.data(), SLOT(logServiceActivity(QString,QString))); @@ -127,42 +129,65 @@ void ClientProxy::clientStatusChanged(QDeclarativeDebugClient::Status status) void ClientProxy::engineClientStatusChanged(QDeclarativeDebugClient::Status status) { if (status == QDeclarativeDebugClient::Enabled) { - m_adapter.data()->setEngineDebugClient(qobject_cast<QDeclarativeEngineDebug *>(sender())); + m_engineClient = qobject_cast<QmlEngineDebugClient *>(sender()); + connect(m_engineClient, SIGNAL(newObjects()), this, SLOT(newObjects())); + connect(m_engineClient, SIGNAL(result(quint32,QVariant,QByteArray)), + SLOT(onResult(quint32,QVariant,QByteArray))); + connect(m_engineClient, SIGNAL(valueChanged(int,QByteArray,QVariant)), + SLOT(objectWatchTriggered(int,QByteArray,QVariant))); + m_adapter.data()->setEngineDebugClient(m_engineClient); + updateConnected(); } } void ClientProxy::refreshObjectTree() { - if (!m_contextQuery) { - m_requestObjectsTimer.stop(); - qDeleteAll(m_objectTreeQuery); - m_objectTreeQuery.clear(); + if (!m_contextQueryId) { + m_objectTreeQueryIds.clear(); queryEngineContext(m_engines.value(0).debugId()); } } -void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds, bool requestIfNeeded) +void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds, + bool requestIfNeeded) { - QList<QDeclarativeDebugObjectReference> selectedItems; - + QList<QmlDebugObjectReference> selectedItems; + m_fetchCurrentObjects.clear(); + m_fetchCurrentObjectsQueryIds.clear(); foreach (int debugId, debugIds) { - QDeclarativeDebugObjectReference ref = objectReferenceForId(debugId); - if (ref.debugId() != -1) { + QmlDebugObjectReference ref = objectReferenceForId(debugId); + if (ref.debugId() != -1 && !ref.needsMoreData()) { selectedItems << ref; } else if (requestIfNeeded) { - // ### FIXME right now, there's no way in the protocol to - // a) get some item and know its parent (although that's possible - // by adding it to a separate plugin) - // b) add children to part of an existing tree. - // So the only choice that remains is to update the complete - // tree when we have an unknown debug id. - // break; + m_fetchCurrentObjectsQueryIds << fetchContextObject( + QmlDebugObjectReference(debugId)); + } } emit selectedItemsChanged(selectedItems); } +void ClientProxy::onCurrentObjectsFetched(quint32 queryId, const QVariant &result) +{ + m_fetchCurrentObjectsQueryIds.removeOne(queryId); + QmlDebugObjectReference obj = qvariant_cast<QmlDebugObjectReference>(result); + m_fetchCurrentObjects.push_front(obj); + + //If this is not a root object, check if we have the parent + QmlDebugObjectReference parent = objectReferenceForId(obj.parentId()); + if (obj.parentId() != -1 && (parent.debugId() == -1 || parent.needsMoreData())) { + m_fetchCurrentObjectsQueryIds << fetchContextObject( + QmlDebugObjectReference(obj.parentId())); + return; + } + + foreach (const QmlDebugObjectReference &o, m_fetchCurrentObjects) + addObjectToTree(o); + emit selectedItemsChanged(QList<QmlDebugObjectReference>() << + m_fetchCurrentObjects.last()); +} + void ClientProxy::setSelectedItemsByDebugId(const QList<int> &debugIds) { if (!isConnected()) @@ -171,12 +196,13 @@ void ClientProxy::setSelectedItemsByDebugId(const QList<int> &debugIds) m_inspectorClient->setCurrentObjects(debugIds); } -void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs) +void ClientProxy::setSelectedItemsByObjectId( + const QList<QmlDebugObjectReference> &objectRefs) { if (isConnected()) { QList<int> debugIds; - foreach (const QDeclarativeDebugObjectReference &ref, objectRefs) { + foreach (const QmlDebugObjectReference &ref, objectRefs) { debugIds << ref.debugId(); } @@ -184,14 +210,26 @@ void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObject } } -QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const +void ClientProxy::addObjectToTree(const QmlDebugObjectReference &obj) +{ + int count = m_rootObjects.count(); + for (int i = 0; i < count; i++) { + if (m_rootObjects[i].insertObjectInTree(obj)) { + buildDebugIdHashRecursive(obj); + emit objectTreeUpdated(); + break; + } + } +} + +QmlDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const { - foreach (const QDeclarativeDebugObjectReference& it, m_rootObjects) { - QDeclarativeDebugObjectReference result = objectReferenceForId(debugId, it); + foreach (const QmlDebugObjectReference& it, m_rootObjects) { + QmlDebugObjectReference result = objectReferenceForId(debugId, it); if (result.debugId() == debugId) return result; } - return QDeclarativeDebugObjectReference(); + return QmlDebugObjectReference(); } void ClientProxy::log(LogDirection direction, const QString &message) @@ -208,71 +246,76 @@ void ClientProxy::log(LogDirection direction, const QString &message) m_adapter.data()->logServiceActivity("QDeclarativeDebug", msg); } -QList<QDeclarativeDebugObjectReference> QmlJSInspector::Internal::ClientProxy::rootObjectReference() const +QList<QmlDebugObjectReference> +QmlJSInspector::Internal::ClientProxy::rootObjectReference() const { return m_rootObjects; } -QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId, - const QDeclarativeDebugObjectReference &objectRef) const +QmlDebugObjectReference +ClientProxy::objectReferenceForId(int debugId, + const QmlDebugObjectReference &objectRef) const { if (objectRef.debugId() == debugId) return objectRef; - foreach (const QDeclarativeDebugObjectReference &child, objectRef.children()) { - QDeclarativeDebugObjectReference result = objectReferenceForId(debugId, child); + foreach (const QmlDebugObjectReference &child, objectRef.children()) { + QmlDebugObjectReference result = objectReferenceForId(debugId, child); if (result.debugId() == debugId) return result; } - return QDeclarativeDebugObjectReference(); + return QmlDebugObjectReference(); } -QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(const QString &objectId) const +QmlDebugObjectReference ClientProxy::objectReferenceForId( + const QString &objectId) const { if (!objectId.isEmpty() && objectId[0].isLower()) { - const QList<QDeclarativeDebugObjectReference> refs = objectReferences(); - foreach (const QDeclarativeDebugObjectReference &ref, refs) { + const QList<QmlDebugObjectReference> refs = objectReferences(); + foreach (const QmlDebugObjectReference &ref, refs) { if (ref.idString() == objectId) return ref; } } - return QDeclarativeDebugObjectReference(); + return QmlDebugObjectReference(); } -QDeclarativeDebugObjectReference ClientProxy::objectReferenceForLocation(const int line, const int column) const +QmlDebugObjectReference ClientProxy::objectReferenceForLocation( + const int line, const int column) const { - const QList<QDeclarativeDebugObjectReference> refs = objectReferences(); - foreach (const QDeclarativeDebugObjectReference &ref, refs) { + const QList<QmlDebugObjectReference> refs = objectReferences(); + foreach (const QmlDebugObjectReference &ref, refs) { if (ref.source().lineNumber() == line && ref.source().columnNumber() == column) return ref; } - return QDeclarativeDebugObjectReference(); + return QmlDebugObjectReference(); } -QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences() const +QList<QmlDebugObjectReference> ClientProxy::objectReferences() const { - QList<QDeclarativeDebugObjectReference> result; - foreach (const QDeclarativeDebugObjectReference &it, m_rootObjects) { + QList<QmlDebugObjectReference> result; + foreach (const QmlDebugObjectReference &it, m_rootObjects) { result.append(objectReferences(it)); } return result; } -QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QDeclarativeDebugObjectReference &objectRef) const +QList<QmlDebugObjectReference> +ClientProxy::objectReferences(const QmlDebugObjectReference &objectRef) const { - QList<QDeclarativeDebugObjectReference> result; + QList<QmlDebugObjectReference> result; result.append(objectRef); - foreach (const QDeclarativeDebugObjectReference &child, objectRef.children()) { + foreach (const QmlDebugObjectReference &child, objectRef.children()) { result.append(objectReferences(child)); } return result; } -bool ClientProxy::setBindingForObject(int objectDebugId, +quint32 ClientProxy::setBindingForObject(int objectDebugId, const QString &propertyName, const QVariant &value, bool isLiteralValue, @@ -288,17 +331,23 @@ bool ClientProxy::setBindingForObject(int objectDebugId, if (!isConnected()) return false; - log(LogSend, QString("SET_BINDING %1 %2 %3 %4").arg(QString::number(objectDebugId), propertyName, value.toString(), QString(isLiteralValue ? "true" : "false"))); + log(LogSend, QString("SET_BINDING %1 %2 %3 %4").arg( + QString::number(objectDebugId), propertyName, value.toString(), + QString(isLiteralValue ? "true" : "false"))); - bool result = m_engineClient->setBindingForObject(objectDebugId, propertyName, value.toString(), isLiteralValue, source, line); + quint32 queryId = m_engineClient->setBindingForObject( + objectDebugId, propertyName, value.toString(), isLiteralValue, + source, line); - if (!result) + if (!queryId) log(LogSend, QString("failed!")); - return result; + return queryId; } -bool ClientProxy::setMethodBodyForObject(int objectDebugId, const QString &methodName, const QString &methodBody) +quint32 ClientProxy::setMethodBodyForObject(int objectDebugId, + const QString &methodName, + const QString &methodBody) { if (objectDebugId == -1) return false; @@ -306,17 +355,20 @@ bool ClientProxy::setMethodBodyForObject(int objectDebugId, const QString &metho if (!isConnected()) return false; - log(LogSend, QString("SET_METHOD_BODY %1 %2 %3").arg(QString::number(objectDebugId), methodName, methodBody)); + log(LogSend, QString("SET_METHOD_BODY %1 %2 %3").arg( + QString::number(objectDebugId), methodName, methodBody)); - bool result = m_engineClient->setMethodBody(objectDebugId, methodName, methodBody); + quint32 queryId = m_engineClient->setMethodBody( + objectDebugId, methodName, methodBody); - if (!result) + if (!queryId) log(LogSend, QString("failed!")); - return result; + return queryId; } -bool ClientProxy::resetBindingForObject(int objectDebugId, const QString& propertyName) +quint32 ClientProxy::resetBindingForObject(int objectDebugId, + const QString& propertyName) { if (objectDebugId == -1) return false; @@ -324,17 +376,20 @@ bool ClientProxy::resetBindingForObject(int objectDebugId, const QString& proper if (!isConnected()) return false; - log(LogSend, QString("RESET_BINDING %1 %2").arg(QString::number(objectDebugId), propertyName)); + log(LogSend, QString("RESET_BINDING %1 %2").arg( + QString::number(objectDebugId), propertyName)); - bool result = m_engineClient->resetBindingForObject(objectDebugId, propertyName); + quint32 queryId = m_engineClient->resetBindingForObject( + objectDebugId, propertyName); - if (!result) + if (!queryId) log(LogSend, QString("failed!")); - return result; + return queryId; } -QDeclarativeDebugExpressionQuery *ClientProxy::queryExpressionResult(int objectDebugId, const QString &expr) +quint32 ClientProxy::queryExpressionResult(int objectDebugId, + const QString &expr) { if (objectDebugId == -1) return 0; @@ -346,13 +401,13 @@ QDeclarativeDebugExpressionQuery *ClientProxy::queryExpressionResult(int objectD if (m_adapter) block = m_adapter.data()->disableJsDebugging(true); - log(LogSend, QString("EVAL_EXPRESSION %1 %2").arg(QString::number(objectDebugId), expr)); - QDeclarativeDebugExpressionQuery *query - = m_engineClient->queryExpressionResult(objectDebugId, expr, m_engineClient); + log(LogSend, QString("EVAL_EXPRESSION %1 %2").arg( + QString::number(objectDebugId), expr)); + quint32 queryId = m_engineClient->queryExpressionResult(objectDebugId, expr); if (m_adapter) m_adapter.data()->disableJsDebugging(block); - return query; + return queryId; } void ClientProxy::clearComponentCache() @@ -370,32 +425,34 @@ bool ClientProxy::addObjectWatch(int objectDebugId) return false; // already set - if (m_objectWatches.keys().contains(objectDebugId)) + if (m_objectWatches.contains(objectDebugId)) return true; - QDeclarativeDebugObjectReference ref = objectReferenceForId(objectDebugId); + QmlDebugObjectReference ref = objectReferenceForId(objectDebugId); if (ref.debugId() != objectDebugId) return false; // is flooding the debugging output log! // log(LogSend, QString("WATCH_PROPERTY %1").arg(objectDebugId)); - QDeclarativeDebugWatch *watch = m_engineClient->addWatch(ref, m_engineClient); - m_objectWatches.insert(objectDebugId, watch); - - connect(watch,SIGNAL(valueChanged(QByteArray,QVariant)),this,SLOT(objectWatchTriggered(QByteArray,QVariant))); + if (m_engineClient->addWatch(ref)) + m_objectWatches.append(objectDebugId); return false; } -void ClientProxy::objectWatchTriggered(const QByteArray &propertyName, const QVariant &propertyValue) +bool ClientProxy::isObjectBeingWatched(int objectDebugId) { - // is flooding the debugging output log! - // log(LogReceive, QString("UPDATE_WATCH %1 %2").arg(QString::fromAscii(propertyName), propertyValue.toString())); + return m_objectWatches.contains(objectDebugId); +} - QDeclarativeDebugWatch *watch = dynamic_cast<QDeclarativeDebugWatch *>(QObject::sender()); - if (watch) - emit propertyChanged(watch->objectDebugId(),propertyName, propertyValue); + +void ClientProxy::objectWatchTriggered(int objectDebugId, + const QByteArray &propertyName, + const QVariant &propertyValue) +{ + if (m_objectWatches.contains(objectDebugId)) + emit propertyChanged(objectDebugId, propertyName, propertyValue); } bool ClientProxy::removeObjectWatch(int objectDebugId) @@ -403,29 +460,19 @@ bool ClientProxy::removeObjectWatch(int objectDebugId) if (objectDebugId == -1) return false; - if (!m_objectWatches.keys().contains(objectDebugId)) + if (!m_objectWatches.contains(objectDebugId)) return false; if (!isConnected()) return false; - QDeclarativeDebugWatch *watch = m_objectWatches.value(objectDebugId); - disconnect(watch,SIGNAL(valueChanged(QByteArray,QVariant)), this, SLOT(objectWatchTriggered(QByteArray,QVariant))); - - // is flooding the debugging output log! - // log(LogSend, QString("NO_WATCH %1").arg(QString::number(objectDebugId))); - - m_engineClient->removeWatch(watch); - delete watch; - m_objectWatches.remove(objectDebugId); - - + m_objectWatches.removeOne(objectDebugId); return true; } void ClientProxy::removeAllObjectWatches() { - foreach (int watchedObject, m_objectWatches.keys()) + foreach (int watchedObject, m_objectWatches) removeObjectWatch(watchedObject); } @@ -437,87 +484,94 @@ void ClientProxy::queryEngineContext(int id) if (!isConnected()) return; - if (m_contextQuery) { - delete m_contextQuery; - m_contextQuery = 0; - } + if (m_contextQueryId) + m_contextQueryId = 0; log(LogSend, QString("LIST_OBJECTS %1").arg(QString::number(id))); - m_contextQuery = m_engineClient->queryRootContexts(QDeclarativeDebugEngineReference(id), - m_engineClient); - if (!m_contextQuery->isWaiting()) - contextChanged(); - else - connect(m_contextQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)), - this, SLOT(contextChanged())); + m_contextQueryId = m_engineClient->queryRootContexts(QmlDebugEngineReference(id)); } -void ClientProxy::contextChanged() +void ClientProxy::contextChanged(const QVariant &value) { - log(LogReceive, QString("LIST_OBJECTS_R")); - if (m_contextQuery) { - m_rootObjects.clear(); - QDeclarativeDebugContextReference rootContext = m_contextQuery->rootContext(); - delete m_contextQuery; - m_contextQuery = 0; - qDeleteAll(m_objectTreeQuery); - m_objectTreeQuery.clear(); - m_requestObjectsTimer.stop(); - - fetchContextObjectRecursive(rootContext); + if (m_contextQueryId) { + m_contextQueryId = 0; + emit rootContext(value); } } -void ClientProxy::fetchContextObjectRecursive(const QDeclarativeDebugContextReference& context) +quint32 ClientProxy::fetchContextObject(const QmlDebugObjectReference& obj) { - if (!isConnected()) - return; - - foreach (const QDeclarativeDebugObjectReference & obj, context.objects()) { + log(LogSend, QString("FETCH_OBJECT %1").arg(obj.idString())); - log(LogSend, QString("FETCH_OBJECT %1").arg(obj.idString())); + return m_engineClient->queryObject(obj); +} - QDeclarativeDebugObjectQuery* query - = m_engineClient->queryObjectRecursive(obj, m_engineClient); - if (!query->isWaiting()) { - query->deleteLater(); //ignore errors; - } else { - m_objectTreeQuery << query; - connect(query, - SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)), - SLOT(objectTreeFetched(QmlJsDebugClient::QDeclarativeDebugQuery::State))); - } +void ClientProxy::fetchContextObjectRecursive( + const QmlDebugContextReference& context, bool clear) +{ + if (!isConnected()) + return; + if (clear) { + m_rootObjects.clear(); + m_objectTreeQueryIds.clear(); + } + foreach (const QmlDebugObjectReference & obj, context.objects()) { + quint32 queryId = fetchContextObject(obj); + if (queryId) + m_objectTreeQueryIds << queryId; } - foreach (const QDeclarativeDebugContextReference& child, context.contexts()) { - fetchContextObjectRecursive(child); + foreach (const QmlDebugContextReference& child, context.contexts()) { + fetchContextObjectRecursive(child, false); } } - -void ClientProxy::objectTreeFetched(QmlJsDebugClient::QDeclarativeDebugQuery::State state) +void ClientProxy::insertObjectInTreeIfNeeded(const QmlDebugObjectReference &object) { - QDeclarativeDebugObjectQuery *query = qobject_cast<QDeclarativeDebugObjectQuery *>(sender()); - if (!query || state == QDeclarativeDebugQuery::Error) { - delete query; + if (!m_rootObjects.contains(object)) return; + int count = m_rootObjects.count(); + for (int i = 0; i < count; i++) { + if (m_rootObjects[i].parentId() < 0 && m_rootObjects[i].insertObjectInTree(object)) { + m_rootObjects.removeOne(object); + break; + } } +} - log(LogReceive, QString("FETCH_OBJECT_R %1").arg(query->object().idString())); +void ClientProxy::onResult(quint32 queryId, const QVariant &value, const QByteArray &type) +{ + if (type == "FETCH_OBJECT_R") { + log(LogReceive, QString("FETCH_OBJECT_R %1").arg( + qvariant_cast<QmlDebugObjectReference>(value).idString())); + } else { + log(LogReceive, QLatin1String(type)); + } - m_rootObjects.append(query->object()); + if (m_objectTreeQueryIds.contains(queryId)) + objectTreeFetched(queryId, value); + else if (queryId == m_engineQueryId) + updateEngineList(value); + else if (queryId == m_contextQueryId) + contextChanged(value); + else if (m_fetchCurrentObjectsQueryIds.contains(queryId)) + onCurrentObjectsFetched(queryId, value); + else + emit result(queryId, value); +} - int removed = m_objectTreeQuery.removeAll(query); - Q_ASSERT(removed == 1); - Q_UNUSED(removed); - delete query; +void ClientProxy::objectTreeFetched(quint32 queryId, const QVariant &result) +{ + QmlDebugObjectReference obj = qvariant_cast<QmlDebugObjectReference>(result); + m_rootObjects.append(obj); - if (m_objectTreeQuery.isEmpty()) { + m_objectTreeQueryIds.removeOne(queryId); + if (m_objectTreeQueryIds.isEmpty()) { int old_count = m_debugIdHash.count(); m_debugIdHash.clear(); m_debugIdHash.reserve(old_count + 1); - foreach (const QDeclarativeDebugObjectReference &it, m_rootObjects) + foreach (const QmlDebugObjectReference &it, m_rootObjects) buildDebugIdHashRecursive(it); emit objectTreeUpdated(); @@ -530,14 +584,15 @@ void ClientProxy::objectTreeFetched(QmlJsDebugClient::QDeclarativeDebugQuery::St } } -void ClientProxy::buildDebugIdHashRecursive(const QDeclarativeDebugObjectReference& ref) +void ClientProxy::buildDebugIdHashRecursive(const QmlDebugObjectReference& ref) { QUrl fileUrl = ref.source().url(); int lineNum = ref.source().lineNumber(); int colNum = ref.source().columnNumber(); int rev = 0; - // handle the case where the url contains the revision number encoded. (for object created by the debugger) + // handle the case where the url contains the revision number encoded. + //(for object created by the debugger) static QRegExp rx("(.*)_(\\d+):(\\d+)$"); if (rx.exactMatch(fileUrl.path())) { fileUrl.setPath(rx.cap(1)); @@ -548,9 +603,10 @@ void ClientProxy::buildDebugIdHashRecursive(const QDeclarativeDebugObjectReferen const QString filePath = InspectorUi::instance()->findFileInProject(fileUrl); // append the debug ids in the hash - m_debugIdHash[qMakePair<QString, int>(filePath, rev)][qMakePair<int, int>(lineNum, colNum)].append(ref.debugId()); + m_debugIdHash[qMakePair<QString, int>(filePath, rev)][qMakePair<int, int>( + lineNum, colNum)].append(ref.debugId()); - foreach (const QDeclarativeDebugObjectReference &it, ref.children()) + foreach (const QmlDebugObjectReference &it, ref.children()) buildDebugIdHashRecursive(it); } @@ -579,12 +635,6 @@ void ClientProxy::setAnimationPaused(bool paused) m_inspectorClient->setAnimationPaused(paused); } -void ClientProxy::changeToColorPickerTool() -{ - if (isConnected()) - m_inspectorClient->changeToColorPickerTool(); -} - void ClientProxy::changeToZoomTool() { if (isConnected()) @@ -609,10 +659,12 @@ void ClientProxy::showAppOnTop(bool showOnTop) } void ClientProxy::createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, const QString &filename, int order) + const QStringList &imports, + const QString &filename, int order) { if (isConnected()) - m_inspectorClient->createQmlObject(qmlText, parentDebugId, imports, filename, order); + m_inspectorClient->createQmlObject(qmlText, parentDebugId, imports, + filename, order); } void ClientProxy::destroyQmlObject(int debugId) @@ -629,8 +681,10 @@ void ClientProxy::reparentQmlObject(int debugId, int newParent) void ClientProxy::updateConnected() { - bool isConnected = m_inspectorClient && m_inspectorClient->status() == QDeclarativeDebugClient::Enabled - && m_engineClient && m_engineClient->status() == QDeclarativeDebugClient::Enabled; + bool isConnected = m_inspectorClient && + m_inspectorClient->status() == QDeclarativeDebugClient::Enabled && + m_engineClient && + m_engineClient->status() == QDeclarativeDebugClient::Enabled; if (isConnected != m_isConnected) { m_isConnected = isConnected; @@ -645,11 +699,6 @@ void ClientProxy::updateConnected() void ClientProxy::reloadEngines() { - if (m_engineQuery) { - emit connectionStatusMessage("[Inspector] Waiting for response to previous engine query"); - return; - } - if (!isConnected()) return; @@ -657,28 +706,18 @@ void ClientProxy::reloadEngines() log(LogSend, QString("LIST_ENGINES")); - m_engineQuery = m_engineClient->queryAvailableEngines(m_engineClient); - if (!m_engineQuery->isWaiting()) { - updateEngineList(); - } else { - connect(m_engineQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)), - this, SLOT(updateEngineList())); - } + m_engineQueryId = m_engineClient->queryAvailableEngines(); } -QList<QDeclarativeDebugEngineReference> ClientProxy::engines() const +QList<QmlDebugEngineReference> ClientProxy::engines() const { return m_engines; } -void ClientProxy::updateEngineList() +void ClientProxy::updateEngineList(const QVariant &value) { - log(LogReceive, QString("LIST_ENGINES_R")); - - m_engines = m_engineQuery->engines(); - delete m_engineQuery; - m_engineQuery = 0; - + m_engines = qvariant_cast<QmlDebugEngineReferenceList>(value); + m_engineQueryId = 0; emit enginesChanged(); } @@ -695,6 +734,5 @@ bool ClientProxy::isConnected() const void ClientProxy::newObjects() { log(LogReceive, QString("OBJECT_CREATED")); - if (!m_requestObjectsTimer.isActive()) - m_requestObjectsTimer.start(); + refreshObjectTree(); } diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h index 2824e3cc2d..bcdef3537b 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.h +++ b/src/plugins/qmljsinspector/qmljsclientproxy.h @@ -60,39 +60,45 @@ public: explicit ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent = 0); ~ClientProxy(); - bool setBindingForObject(int objectDebugId, + quint32 setBindingForObject(int objectDebugId, const QString &propertyName, const QVariant &value, bool isLiteralValue, QString source, int line); - bool setMethodBodyForObject(int objectDebugId, const QString &methodName, const QString &methodBody); - bool resetBindingForObject(int objectDebugId, const QString &propertyName); - QDeclarativeDebugExpressionQuery *queryExpressionResult(int objectDebugId, const QString &expr); + quint32 setMethodBodyForObject(int objectDebugId, const QString &methodName, const QString &methodBody); + quint32 resetBindingForObject(int objectDebugId, const QString &propertyName); + quint32 queryExpressionResult(int objectDebugId, const QString &expr); void clearComponentCache(); bool addObjectWatch(int objectDebugId); + bool isObjectBeingWatched(int objectDebugId); bool removeObjectWatch(int objectDebugId); void removeAllObjectWatches(); // returns the object references - QList<QDeclarativeDebugObjectReference> objectReferences() const; - QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const; - QDeclarativeDebugObjectReference objectReferenceForId(const QString &objectId) const; - QDeclarativeDebugObjectReference objectReferenceForLocation(const int line, const int column) const; - QList<QDeclarativeDebugObjectReference> rootObjectReference() const; + QList<QmlDebugObjectReference> objectReferences() const; + QmlDebugObjectReference objectReferenceForId(int debugId) const; + QmlDebugObjectReference objectReferenceForId(const QString &objectId) const; + QmlDebugObjectReference objectReferenceForLocation(const int line, const int column) const; + QList<QmlDebugObjectReference> rootObjectReference() const; DebugIdHash debugIdHash() const { return m_debugIdHash; } bool isConnected() const; void setSelectedItemsByDebugId(const QList<int> &debugIds); - void setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs); + void setSelectedItemsByObjectId(const QList<QmlDebugObjectReference> &objectRefs); - QList<QDeclarativeDebugEngineReference> engines() const; + QList<QmlDebugEngineReference> engines() const; Debugger::QmlAdapter *qmlAdapter() const; + quint32 fetchContextObject(const QmlDebugObjectReference& obj); + void addObjectToTree(const QmlDebugObjectReference &obj); + void fetchContextObjectRecursive(const QmlDebugContextReference &context, bool clear); + void insertObjectInTreeIfNeeded(const QmlDebugObjectReference &object); + signals: void objectTreeUpdated(); void connectionStatusMessage(const QString &text); @@ -100,12 +106,11 @@ signals: void aboutToReloadEngines(); void enginesChanged(); - void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &selectedItems); + void selectedItemsChanged(const QList<QmlDebugObjectReference> &selectedItems); void connected(); void disconnected(); - void colorPickerActivated(); void selectToolActivated(); void selectMarqueeToolActivated(); void zoomToolActivated(); @@ -114,9 +119,11 @@ signals: void designModeBehaviorChanged(bool inDesignMode); void showAppOnTopChanged(bool showAppOnTop); void serverReloaded(); - void selectedColorChanged(const QColor &color); void propertyChanged(int debugId, const QByteArray &propertyName, const QVariant &propertyValue); + void result(quint32 queryId, const QVariant &result); + void rootContext(const QVariant &context); + public slots: void refreshObjectTree(); void queryEngineContext(int id); @@ -125,7 +132,6 @@ public slots: void setDesignModeBehavior(bool inDesignMode); void setAnimationSpeed(qreal slowDownFactor); void setAnimationPaused(bool paused); - void changeToColorPickerTool(); void changeToZoomTool(); void changeToSelectTool(); void changeToSelectMarqueeTool(); @@ -140,21 +146,21 @@ private slots: void clientStatusChanged(QDeclarativeDebugClient::Status status); void engineClientStatusChanged(QDeclarativeDebugClient::Status status); - void contextChanged(); - void onCurrentObjectsChanged(const QList<int> &debugIds, bool requestIfNeeded = true); - void updateEngineList(); - void objectTreeFetched(QmlJsDebugClient::QDeclarativeDebugQuery::State state = QmlJsDebugClient::QDeclarativeDebugQuery::Completed); - void fetchContextObjectRecursive(const QmlJsDebugClient::QDeclarativeDebugContextReference& context); void newObjects(); - void objectWatchTriggered(const QByteArray &propertyName, const QVariant &propertyValue); + void objectWatchTriggered(int debugId, const QByteArray &propertyName, const QVariant &propertyValue); + void onResult(quint32 queryId, const QVariant &value, const QByteArray &type); + void onCurrentObjectsFetched(quint32 queryId, const QVariant &result); private: + void contextChanged(const QVariant &value); + void updateEngineList(const QVariant &value); + void objectTreeFetched(quint32 queryId, const QVariant &result); void updateConnected(); void reloadEngines(); - QList<QDeclarativeDebugObjectReference> objectReferences(const QDeclarativeDebugObjectReference &objectRef) const; - QDeclarativeDebugObjectReference objectReferenceForId(int debugId, const QDeclarativeDebugObjectReference &ref) const; + QList<QmlDebugObjectReference> objectReferences(const QmlDebugObjectReference &objectRef) const; + QmlDebugObjectReference objectReferenceForId(int debugId, const QmlDebugObjectReference &ref) const; enum LogDirection { LogSend, @@ -164,22 +170,23 @@ private: private: - void buildDebugIdHashRecursive(const QDeclarativeDebugObjectReference &ref); + void buildDebugIdHashRecursive(const QmlDebugObjectReference &ref); QWeakPointer<Debugger::QmlAdapter> m_adapter; - QDeclarativeEngineDebug *m_engineClient; + QmlEngineDebugClient *m_engineClient; QmlJSInspectorClient *m_inspectorClient; - QDeclarativeDebugEnginesQuery *m_engineQuery; - QDeclarativeDebugRootContextQuery *m_contextQuery; - QList<QDeclarativeDebugObjectQuery *> m_objectTreeQuery; + quint32 m_engineQueryId; + quint32 m_contextQueryId; + QList<quint32> m_objectTreeQueryIds; + QList<quint32> m_fetchCurrentObjectsQueryIds; - QList<QDeclarativeDebugObjectReference> m_rootObjects; - QList<QDeclarativeDebugEngineReference> m_engines; - QTimer m_requestObjectsTimer; + QList<QmlDebugObjectReference> m_rootObjects; + QList<QmlDebugObjectReference> m_fetchCurrentObjects; + QmlDebugEngineReferenceList m_engines; DebugIdHash m_debugIdHash; - QHash<int, QDeclarativeDebugWatch *> m_objectWatches; + QList<int> m_objectWatches; bool m_isConnected; }; diff --git a/src/plugins/qmljsinspector/qmljscontextcrumblepath.cpp b/src/plugins/qmljsinspector/qmljscontextcrumblepath.cpp index d12e1682e2..25f055a161 100644 --- a/src/plugins/qmljsinspector/qmljscontextcrumblepath.cpp +++ b/src/plugins/qmljsinspector/qmljscontextcrumblepath.cpp @@ -52,7 +52,7 @@ void ContextCrumblePath::updateContextPath(const QStringList &path, const QList< m_isEmpty = path.isEmpty(); if (m_isEmpty) { - pushElement(tr("[no context]"), -1); + pushElement(tr("[no context]"), -2); } else { for (int i = 0; i < path.count(); i++) pushElement(path[i], debugIds[i]); diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp index f499111533..9e18a43919 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.cpp +++ b/src/plugins/qmljsinspector/qmljsinspector.cpp @@ -45,10 +45,9 @@ #include <qmljs/parser/qmljsast_p.h> #include <qmljseditor/qmljseditorconstants.h> #include <qmljseditor/qmljseditor.h> -#include <debugger/debuggerconstants.h> #include <debugger/debuggermainwindow.h> #include <debugger/debuggerplugin.h> -#include <debugger/debuggerengine.h> +#include <debugger/qml/qmlengine.h> #include <debugger/debuggerstartparameters.h> #include <debugger/qml/qmladapter.h> @@ -86,6 +85,9 @@ #include <extensionsystem/pluginmanager.h> +#include <aggregation/aggregate.h> +#include <find/treeviewfind.h> + #include <QDebug> #include <QStringList> #include <QTimer> @@ -119,24 +121,6 @@ enum { ConnectionAttemptSimultaneousInterval = 500 }; -/** - * A widget that has the base color. - */ -class StyledBackground : public QWidget -{ -public: - explicit StyledBackground(QWidget *parent = 0) - : QWidget(parent) - {} - -protected: - void paintEvent(QPaintEvent *e) - { - QPainter p(this); - p.fillRect(e->rect(), Utils::StyleHelper::baseColor()); - } -}; - InspectorUi *InspectorUi::m_instance = 0; QmlJS::ModelManagerInterface *modelManager() @@ -149,14 +133,13 @@ InspectorUi::InspectorUi(QObject *parent) , m_listeningToEditorManager(false) , m_toolBar(0) , m_crumblePath(0) - , m_filterExp(0) , m_propertyInspector(0) , m_settings(new InspectorSettings(this)) , m_clientProxy(0) - , m_qmlEngine(0) , m_debugQuery(0) , m_selectionCallbackExpected(false) , m_cursorPositionChangedExternally(false) + , m_onCrumblePathClicked(false) { m_instance = this; m_toolBar = new QmlJsInspectorToolBar(this); @@ -184,23 +167,31 @@ void InspectorUi::restoreSettings() m_settings->restoreSettings(Core::ICore::settings()); } -void InspectorUi::setDebuggerEngine(QObject *qmlEngine) +void InspectorUi::setDebuggerEngine(QObject *engine) { - if (m_qmlEngine && !qmlEngine) { - disconnect(m_qmlEngine, SIGNAL(tooltipRequested(QPoint,TextEditor::ITextEditor*,int)), - this, SLOT(showDebuggerTooltip(QPoint,TextEditor::ITextEditor*,int))); - } + Debugger::Internal::QmlEngine *qmlEngine = + qobject_cast<Debugger::Internal::QmlEngine *>(engine); + QTC_ASSERT(qmlEngine, return); + Debugger::DebuggerEngine *masterEngine = qmlEngine; + if (qmlEngine->isSlaveEngine()) + masterEngine = qmlEngine->masterEngine(); - m_qmlEngine = qmlEngine; - if (m_qmlEngine) { - connect(m_qmlEngine, SIGNAL(tooltipRequested(QPoint,TextEditor::ITextEditor*,int)), - this, SLOT(showDebuggerTooltip(QPoint,TextEditor::ITextEditor*,int))); - } + connect(qmlEngine, SIGNAL(tooltipRequested(QPoint,TextEditor::ITextEditor*,int)), + this, SLOT(showDebuggerTooltip(QPoint,TextEditor::ITextEditor*,int))); + connect(masterEngine, SIGNAL(stateChanged(Debugger::DebuggerState)), + this, SLOT(onEngineStateChanged(Debugger::DebuggerState))); } -QObject *InspectorUi::debuggerEngine() const +void InspectorUi::onEngineStateChanged(Debugger::DebuggerState state) { - return m_qmlEngine; + bool enable = state == Debugger::InferiorRunOk; + if (enable) + m_toolBar->enable(); + else + m_toolBar->disable(); + m_crumblePath->setEnabled(enable); + m_propertyInspector->setContentsValid(enable); + m_propertyInspector->reset(); } void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextEditor *editor, @@ -224,7 +215,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE if (!qmlNode) return; - QDeclarativeDebugObjectReference ref; + QmlDebugObjectReference ref; if (QmlJS::AST::Node *node = qmlEditor->semanticInfo().declaringMemberNoProperties(cursorPos)) { if (QmlJS::AST::UiObjectMember *objMember = node->uiObjectMemberCast()) { @@ -249,7 +240,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE if ((qmlNode->kind == QmlJS::AST::Node::Kind_IdentifierExpression) && (m_clientProxy->objectReferenceForId(refToLook).debugId() == -1)) { query = doubleQuote + QString("local: ") + refToLook + doubleQuote; - foreach (const QDeclarativeDebugPropertyReference &property, ref.properties()) { + foreach (const QmlDebugPropertyReference &property, ref.properties()) { if (property.name() == wordAtCursor && !property.valueTypeName().isEmpty()) { query = doubleQuote + property.name() + QLatin1Char(':') @@ -263,7 +254,7 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE + QLatin1Char('+') + refToLook; } else { // show properties - foreach (const QDeclarativeDebugPropertyReference &property, ref.properties()) { + foreach (const QmlDebugPropertyReference &property, ref.properties()) { if (property.name() == wordAtCursor && !property.valueTypeName().isEmpty()) { query = doubleQuote + property.name() + QLatin1Char(':') + doubleQuote + QLatin1Char('+') + property.name(); @@ -275,25 +266,39 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE if (!query.isEmpty()) { m_debugQuery = m_clientProxy->queryExpressionResult(ref.debugId(), query); - connect(m_debugQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)), - this, SLOT(debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State))); } } } -void InspectorUi::debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State newState) +void InspectorUi::onResult(quint32 queryId, const QVariant &result) { - if (newState != QDeclarativeDebugExpressionQuery::Completed) + if (m_showObjectQueryId == queryId) { + m_showObjectQueryId = 0; + QmlDebugObjectReference obj = qvariant_cast<QmlDebugObjectReference>(result); + m_clientProxy->addObjectToTree(obj); + if (m_onCrumblePathClicked) { + m_onCrumblePathClicked = false; + showObject(obj); + } + return; + } + + if (m_updateObjectQueryIds.contains(queryId)) { + m_updateObjectQueryIds.removeOne(queryId); + QmlDebugObjectReference obj = qvariant_cast<QmlDebugObjectReference>(result); + m_clientProxy->addObjectToTree(obj); + if (m_updateObjectQueryIds.empty()) + showObject(obj); return; - if (!m_debugQuery) + } + + if (m_debugQuery != queryId) return; - QString text = m_debugQuery->result().toString(); + m_debugQuery = 0; + QString text = result.toString(); if (!text.isEmpty()) QToolTip::showText(QCursor::pos(), text); - - disconnect(m_debugQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)), - this, SLOT(debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State))); } bool InspectorUi::isConnected() const @@ -303,7 +308,13 @@ bool InspectorUi::isConnected() const void InspectorUi::connected(ClientProxy *clientProxy) { + if (m_clientProxy) + disconnect(m_clientProxy, SIGNAL(result(quint32,QVariant)), + this, SLOT(onResult(quint32,QVariant))); m_clientProxy = clientProxy; + if (m_clientProxy) + connect(m_clientProxy, SIGNAL(result(quint32,QVariant)), + SLOT(onResult(quint32,QVariant))); QmlJS::Snapshot snapshot = modelManager()->snapshot(); for (QHash<QString, QmlJSLiveTextPreview *>::const_iterator it = m_textPreviews.constBegin(); @@ -337,7 +348,6 @@ void InspectorUi::disconnected() disconnectSignals(); disable(); - m_qmlEngine = 0; resetViews(); applyChangesToQmlInspectorHelper(false); @@ -350,35 +360,51 @@ void InspectorUi::disconnected() m_clientProxy = 0; m_propertyInspector->clear(); m_pendingPreviewDocumentNames.clear(); - setDebuggerEngine(0); +} + +void InspectorUi::onRootContext(const QVariant &value) +{ + if (m_crumblePath->dataForLastIndex().toInt() < 0) { + m_clientProxy->fetchContextObjectRecursive( + qvariant_cast<QmlDebugContextReference>( + value), true); + } else { + for (int i = 1; i < m_crumblePath->length(); i++) { + m_updateObjectQueryIds << m_clientProxy->fetchContextObject( + m_crumblePath->dataForIndex(i).toInt()); + } + } } void InspectorUi::objectTreeReady() { - // Should only run once, after debugger startup - if (!m_clientProxy->rootObjectReference().isEmpty()) { - selectItems(m_clientProxy->rootObjectReference()); - disconnect(m_clientProxy, SIGNAL(objectTreeUpdated()), - this, SLOT(objectTreeReady())); + if (m_crumblePath->dataForLastIndex().toInt() >= 0) { + selectItems(QList<QmlDebugObjectReference>() << + m_clientProxy->objectReferenceForId( + m_crumblePath->dataForLastIndex().toInt())); + } else { + showRoot(); } } void InspectorUi::updateEngineList() { - QList<QDeclarativeDebugEngineReference> engines = m_clientProxy->engines(); + QList<QmlDebugEngineReference> engines = m_clientProxy->engines(); //#warning update the QML engines combo if (engines.isEmpty()) qWarning("qmldebugger: no engines found!"); else { - const QDeclarativeDebugEngineReference engine = engines.first(); + const QmlDebugEngineReference engine = engines.first(); m_clientProxy->queryEngineContext(engine.debugId()); } } -void InspectorUi::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects) +void InspectorUi::changeSelectedItems(const QList<QmlDebugObjectReference> &objects) { + if (!m_propertyInspector->contentsValid()) + return; if (m_selectionCallbackExpected) { m_selectionCallbackExpected = false; return; @@ -386,9 +412,9 @@ void InspectorUi::changeSelectedItems(const QList<QDeclarativeDebugObjectReferen m_cursorPositionChangedExternally = true; // QmlJSLiveTextPreview doesn't provide valid references, only correct debugIds. We need to remap them - QList <QDeclarativeDebugObjectReference> realList; - foreach (const QDeclarativeDebugObjectReference &obj, objects) { - QDeclarativeDebugObjectReference clientRef = m_clientProxy->objectReferenceForId(obj.debugId()); + QList <QmlDebugObjectReference> realList; + foreach (const QmlDebugObjectReference &obj, objects) { + QmlDebugObjectReference clientRef = m_clientProxy->objectReferenceForId(obj.debugId()); realList << clientRef; } @@ -476,8 +502,8 @@ QmlJSLiveTextPreview *InspectorUi::createPreviewForEditor(Core::IEditor *newEdit } else { preview = new QmlJSLiveTextPreview(doc, initdoc, m_clientProxy, this); connect(preview, - SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), - SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>))); + SIGNAL(selectedItemsChanged(QList<QmlDebugObjectReference>)), + SLOT(changeSelectedItems(QList<QmlDebugObjectReference>))); connect(preview, SIGNAL(reloadQmlViewerRequested()), m_clientProxy, SLOT(reloadQmlViewer())); connect(preview, SIGNAL(disableLivePreviewRequested()), SLOT(disableLivePreview())); @@ -503,36 +529,39 @@ void InspectorUi::reloadQmlViewer() m_clientProxy->reloadQmlViewer(); } -inline QDeclarativeDebugObjectReference findParentRecursive( int goalDebugId, - const QList< QDeclarativeDebugObjectReference > &objectsToSearch) +QmlDebugObjectReference InspectorUi::findParentRecursive( + int goalDebugId, const QList<QmlDebugObjectReference > &objectsToSearch) { if (goalDebugId == -1) - return QDeclarativeDebugObjectReference(); + return QmlDebugObjectReference(); - foreach (const QDeclarativeDebugObjectReference &possibleParent, objectsToSearch) { + foreach (const QmlDebugObjectReference &possibleParent, objectsToSearch) { // Am I a root object? No parent - if ( possibleParent.debugId() == goalDebugId ) - return QDeclarativeDebugObjectReference(); + if ( possibleParent.debugId() == goalDebugId && possibleParent.parentId() < 0) + return QmlDebugObjectReference(); // Is the goal one of my children? - foreach (const QDeclarativeDebugObjectReference &child, possibleParent.children()) - if ( child.debugId() == goalDebugId ) + foreach (const QmlDebugObjectReference &child, possibleParent.children()) + if ( child.debugId() == goalDebugId ) { + m_clientProxy->insertObjectInTreeIfNeeded(child); return possibleParent; + } // no luck? pass this on - QDeclarativeDebugObjectReference candidate = findParentRecursive(goalDebugId, possibleParent.children()); + QmlDebugObjectReference candidate = findParentRecursive( + goalDebugId, possibleParent.children()); if (candidate.debugId() != -1) return candidate; } - return QDeclarativeDebugObjectReference(); + return QmlDebugObjectReference(); } -inline QString displayName(const QDeclarativeDebugObjectReference &obj) +inline QString displayName(const QmlDebugObjectReference &obj) { // special! state names if (obj.className() == "State") { - foreach (const QDeclarativeDebugPropertyReference &prop, obj.properties()) { + foreach (const QmlDebugPropertyReference &prop, obj.properties()) { if (prop.name() == "name") return prop.value().toString(); } @@ -551,44 +580,52 @@ inline QString displayName(const QDeclarativeDebugObjectReference &obj) return QString("<%1>").arg(objTypeName); } -void InspectorUi::selectItems(const QList<QDeclarativeDebugObjectReference> &objectReferences) +void InspectorUi::selectItems(const QList<QmlDebugObjectReference> &objectReferences) { - foreach (const QDeclarativeDebugObjectReference &objref, objectReferences) { + foreach (const QmlDebugObjectReference &objref, objectReferences) { int debugId = objref.debugId(); if (debugId != -1) { // select only the first valid element of the list - - m_clientProxy->removeAllObjectWatches(); - m_clientProxy->addObjectWatch(debugId); - QList <QDeclarativeDebugObjectReference> selectionList; - selectionList << objref; - m_propertyInspector->setCurrentObjects(selectionList); - populateCrumblePath(objref); - gotoObjectReferenceDefinition(objref); - Debugger::QmlAdapter *qmlAdapter = m_clientProxy->qmlAdapter(); - if (qmlAdapter) { - qmlAdapter->setCurrentSelectedDebugInfo(debugId, displayName(objref)); - } + if (!m_clientProxy->isObjectBeingWatched(debugId)) + m_clientProxy->removeAllObjectWatches(); + //Check if the object is complete + if (objref.needsMoreData()) + m_showObjectQueryId = m_clientProxy->fetchContextObject(objref); + else + showObject(objref); break; } } } -bool InspectorUi::isRoot(const QDeclarativeDebugObjectReference &obj) const +void InspectorUi::showObject(const QmlDebugObjectReference &obj) +{ + m_clientProxy->addObjectWatch(obj.debugId()); + QList <QmlDebugObjectReference> selectionList; + selectionList << obj; + m_propertyInspector->setCurrentObjects(selectionList); + populateCrumblePath(obj); + gotoObjectReferenceDefinition(obj); + Debugger::QmlAdapter *qmlAdapter = m_clientProxy->qmlAdapter(); + if (qmlAdapter) + qmlAdapter->setCurrentSelectedDebugInfo(obj.debugId(), displayName(obj)); +} + +bool InspectorUi::isRoot(const QmlDebugObjectReference &obj) const { - foreach (const QDeclarativeDebugObjectReference &rootObj, m_clientProxy->rootObjectReference()) - if (obj.debugId() == rootObj.debugId()) + foreach (const QmlDebugObjectReference &rootObj, m_clientProxy->rootObjectReference()) + if (obj.debugId() == rootObj.debugId() && obj.parentId() < 0) return true; return false; } -void InspectorUi::populateCrumblePath(const QDeclarativeDebugObjectReference &objRef) +void InspectorUi::populateCrumblePath(const QmlDebugObjectReference &objRef) { QStringList crumbleStrings; QList <int> crumbleData; // first find path by climbing the hierarchy - QDeclarativeDebugObjectReference ref = objRef; + QmlDebugObjectReference ref = objRef; crumbleData << objRef.debugId(); crumbleStrings << displayName(objRef); @@ -597,13 +634,16 @@ void InspectorUi::populateCrumblePath(const QDeclarativeDebugObjectReference &ob crumbleData.push_front( ref.debugId() ); crumbleStrings.push_front( displayName(ref) ); } + //Prepend Root + crumbleData.push_front(-1); + crumbleStrings.push_front(QLatin1String("/")); m_crumblePath->updateContextPath(crumbleStrings, crumbleData); crumbleStrings.clear(); crumbleData.clear(); // now append the children - foreach (const QDeclarativeDebugObjectReference &child, objRef.children()) { + foreach (const QmlDebugObjectReference &child, objRef.children()) { crumbleData.push_back(child.debugId()); crumbleStrings.push_back( displayName(child) ); } @@ -611,12 +651,39 @@ void InspectorUi::populateCrumblePath(const QDeclarativeDebugObjectReference &ob m_crumblePath->addChildren(crumbleStrings, crumbleData); } +void InspectorUi::showRoot() +{ + QStringList crumbleStrings; + QList <int> crumbleData; + + crumbleData << -1; + crumbleStrings << QLatin1String("/"); + + m_crumblePath->updateContextPath(crumbleStrings, crumbleData); + crumbleStrings.clear(); + crumbleData.clear(); + + // now append the children + foreach (const QmlDebugObjectReference &child, m_clientProxy->rootObjectReference()) { + if (child.parentId() != -1) + continue; + crumbleData.push_back(child.debugId()); + crumbleStrings.push_back( displayName(child) ); + } + + m_crumblePath->addChildren(crumbleStrings, crumbleData); + m_propertyInspector->clear(); + Debugger::QmlAdapter *qmlAdapter = m_clientProxy->qmlAdapter(); + if (qmlAdapter) + qmlAdapter->setCurrentSelectedDebugInfo(-1, QLatin1String("/")); +} + void InspectorUi::selectItems(const QList<int> &objectIds) { - QList<QDeclarativeDebugObjectReference> objectReferences; + QList<QmlDebugObjectReference> objectReferences; foreach (int objectId, objectIds) { - QDeclarativeDebugObjectReference ref = m_clientProxy->objectReferenceForId(objectId); + QmlDebugObjectReference ref = m_clientProxy->objectReferenceForId(objectId); if (ref.debugId() == objectId) objectReferences.append(ref); } @@ -633,20 +700,18 @@ void InspectorUi::changePropertyValue(int debugId,const QString &propertyName, c void InspectorUi::enable() { m_toolBar->enable(); - m_crumblePath->setEnabled(true); - m_propertyInspector->setEnabled(true); - m_filterExp->setEnabled(true); + m_crumblePath->clear(); + m_propertyInspector->clear(); } void InspectorUi::disable() { m_toolBar->disable(); - m_crumblePath->setEnabled(false); - m_propertyInspector->setEnabled(false); - m_filterExp->setEnabled(false); + m_crumblePath->clear(); + m_propertyInspector->clear(); } -QDeclarativeDebugObjectReference InspectorUi::objectReferenceForLocation(const QString &fileName, int cursorPosition) const +QmlDebugObjectReference InspectorUi::objectReferenceForLocation(const QString &fileName, int cursorPosition) const { Core::EditorManager *editorManager = Core::EditorManager::instance(); Core::IEditor *editor = editorManager->openEditor(fileName); @@ -667,17 +732,17 @@ QDeclarativeDebugObjectReference InspectorUi::objectReferenceForLocation(const Q } } } - return QDeclarativeDebugObjectReference(); + return QmlDebugObjectReference(); } -void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj) +void InspectorUi::gotoObjectReferenceDefinition(const QmlDebugObjectReference &obj) { if (m_cursorPositionChangedExternally) { m_cursorPositionChangedExternally = false; return; } - QDeclarativeDebugFileReference source = obj.source(); + QmlDebugFileReference source = obj.source(); const QString fileName = m_projectFinder.findFile(source.url()); @@ -690,7 +755,7 @@ void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectRef m_selectionCallbackExpected = true; if (textEditor) { - QDeclarativeDebugObjectReference ref = objectReferenceForLocation(fileName); + QmlDebugObjectReference ref = objectReferenceForLocation(fileName); if (ref.debugId() != obj.debugId()) { m_selectionCallbackExpected = true; editorManager->addCurrentPositionToNavigationHistory(); @@ -700,20 +765,6 @@ void InspectorUi::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectRef } } -bool InspectorUi::addQuotesForData(const QVariant &value) const -{ - switch (value.type()) { - case QVariant::String: - case QVariant::Color: - case QVariant::Date: - return true; - default: - break; - } - - return false; -} - void InspectorUi::setupDockWidgets() { Debugger::DebuggerMainWindow *mw = Debugger::DebuggerPlugin::mainWindow(); @@ -733,18 +784,13 @@ void InspectorUi::setupDockWidgets() inspectorWidget->setWindowTitle(tr("QML Inspector")); inspectorWidget->setObjectName(Debugger::Constants::DOCKWIDGET_QML_INSPECTOR); - QWidget *pathAndFilterWidget = new StyledBackground; + QWidget *pathAndFilterWidget = new Utils::StyledBar(); pathAndFilterWidget->setMaximumHeight(m_crumblePath->height()); - m_filterExp = new Utils::FilterLineEdit; - m_filterExp->setPlaceholderText(tr("Filter properties")); - m_filterExp->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); - QHBoxLayout *pathAndFilterLayout = new QHBoxLayout(pathAndFilterWidget); pathAndFilterLayout->setMargin(0); pathAndFilterLayout->setSpacing(0); pathAndFilterLayout->addWidget(m_crumblePath); - pathAndFilterLayout->addWidget(m_filterExp); QVBoxLayout *wlay = new QVBoxLayout(inspectorWidget); wlay->setMargin(0); @@ -752,22 +798,33 @@ void InspectorUi::setupDockWidgets() inspectorWidget->setLayout(wlay); wlay->addWidget(pathAndFilterWidget); wlay->addWidget(m_propertyInspector); + wlay->addWidget(new Core::FindToolBarPlaceHolder(inspectorWidget)); QDockWidget *dock = mw->createDockWidget(Debugger::QmlLanguage, inspectorWidget); dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); dock->setTitleBarWidget(new QWidget(dock)); + + mw->addStagedMenuEntries(); + + Aggregation::Aggregate *aggregate = new Aggregation::Aggregate(); + aggregate->add(m_propertyInspector); + aggregate->add(new Find::TreeViewFind(m_propertyInspector)); } void InspectorUi::crumblePathElementClicked(const QVariant &data) { bool ok; const int debugId = data.toInt(&ok); - if (!ok || debugId == -1) + if (!ok || debugId == -2) return; + if (debugId == -1) + return showRoot(); + QList<int> debugIds; debugIds << debugId; + m_onCrumblePathClicked = true; selectItems(debugIds); m_clientProxy->setSelectedItemsByDebugId(debugIds); } @@ -843,21 +900,21 @@ void InspectorUi::connectSignals() connect(m_clientProxy, SIGNAL(propertyChanged(int,QByteArray,QVariant)), m_propertyInspector, SLOT(propertyValueChanged(int,QByteArray,QVariant))); - connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), - this, SLOT(selectItems(QList<QDeclarativeDebugObjectReference>))); + connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QmlDebugObjectReference>)), + this, SLOT(selectItems(QList<QmlDebugObjectReference>))); connect(m_clientProxy, SIGNAL(enginesChanged()), this, SLOT(updateEngineList())); connect(m_clientProxy, SIGNAL(serverReloaded()), this, SLOT(serverReloaded())); connect(m_clientProxy, SIGNAL(objectTreeUpdated()), this, SLOT(objectTreeReady())); + connect(m_clientProxy, SIGNAL(rootContext(QVariant)), + this, SLOT(onRootContext(QVariant))); connect(m_clientProxy, SIGNAL(connected()), this, SLOT(enable())); connect(m_clientProxy, SIGNAL(disconnected()), this, SLOT(disable())); - connect(m_clientProxy, SIGNAL(colorPickerActivated()), - m_toolBar, SLOT(activateColorPicker())); connect(m_clientProxy, SIGNAL(selectToolActivated()), m_toolBar, SLOT(activateSelectTool())); connect(m_clientProxy, SIGNAL(zoomToolActivated()), @@ -866,8 +923,6 @@ void InspectorUi::connectSignals() m_toolBar, SLOT(setDesignModeBehavior(bool))); connect(m_clientProxy, SIGNAL(showAppOnTopChanged(bool)), m_toolBar, SLOT(setShowAppOnTop(bool))); - connect(m_clientProxy, SIGNAL(selectedColorChanged(QColor)), - m_toolBar, SLOT(setSelectedColor(QColor))); connect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)), m_toolBar, SLOT(setAnimationSpeed(qreal))); connect(m_clientProxy, SIGNAL(animationPausedChanged(bool)), @@ -884,17 +939,12 @@ void InspectorUi::connectSignals() m_clientProxy, SLOT(setAnimationSpeed(qreal))); connect(m_toolBar, SIGNAL(animationPausedChanged(bool)), m_clientProxy, SLOT(setAnimationPaused(bool))); - connect(m_toolBar, SIGNAL(colorPickerSelected()), - m_clientProxy, SLOT(changeToColorPickerTool())); connect(m_toolBar, SIGNAL(zoomToolSelected()), m_clientProxy, SLOT(changeToZoomTool())); connect(m_toolBar, SIGNAL(selectToolSelected()), m_clientProxy, SLOT(changeToSelectTool())); connect(m_toolBar, SIGNAL(showAppOnTopSelected(bool)), m_clientProxy, SLOT(showAppOnTop(bool))); - - connect(m_filterExp, SIGNAL(textChanged(QString)), - m_propertyInspector, SLOT(filterBy(QString))); } void InspectorUi::disconnectSignals() diff --git a/src/plugins/qmljsinspector/qmljsinspector.h b/src/plugins/qmljsinspector/qmljsinspector.h index 6a9544f55a..37796b7522 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.h +++ b/src/plugins/qmljsinspector/qmljsinspector.h @@ -41,11 +41,11 @@ #include <qmljs/qmljsdocument.h> #include <qmljs/parser/qmljsastfwd_p.h> +#include <debugger/debuggerconstants.h> + #include <QAction> #include <QObject> -QT_FORWARD_DECLARE_CLASS(QLineEdit) - namespace ProjectExplorer { class Project; class Environment; @@ -102,7 +102,6 @@ public: void connected(ClientProxy *clientProxy); void disconnected(); void setDebuggerEngine(QObject *qmlEngine); - QObject *debuggerEngine() const; signals: void statusMessage(const QString &text); @@ -112,16 +111,18 @@ public slots: void reloadQmlViewer(); void serverReloaded(); void setApplyChangesToQmlInspector(bool applyChanges); + void onResult(quint32 queryId, const QVariant &result); private slots: void enable(); void disable(); - void gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj); - void selectItems(const QList<QDeclarativeDebugObjectReference> &objectReferences); + void gotoObjectReferenceDefinition(const QmlDebugObjectReference &obj); + void selectItems(const QList<QmlDebugObjectReference> &objectReferences); void selectItems(const QList<int> &objectIds); - void changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects); + void changeSelectedItems(const QList<QmlDebugObjectReference> &objects); void changePropertyValue(int debugId,const QString &propertyName, const QString &valueExpression); void objectTreeReady(); + void onRootContext(const QVariant &value); void updateEngineList(); @@ -133,34 +134,38 @@ private slots: void updatePendingPreviewDocuments(QmlJS::Document::Ptr doc); void showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos); - void debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State); + void onEngineStateChanged(Debugger::DebuggerState state); private: - bool addQuotesForData(const QVariant &value) const; + void showRoot(); void resetViews(); void initializeDocuments(); void applyChangesToQmlInspectorHelper(bool applyChanges); void setupDockWidgets(); QString filenameForShadowBuildFile(const QString &filename) const; - void populateCrumblePath(const QDeclarativeDebugObjectReference &objRef); - bool isRoot(const QDeclarativeDebugObjectReference &obj) const; - QDeclarativeDebugObjectReference objectReferenceForLocation(const QString &fileName, int cursorPosition=-1) const; + void populateCrumblePath(const QmlDebugObjectReference &objRef); + bool isRoot(const QmlDebugObjectReference &obj) const; + QmlDebugObjectReference objectReferenceForLocation(const QString &fileName, int cursorPosition=-1) const; void connectSignals(); void disconnectSignals(); + void showObject(const QmlDebugObjectReference &obj); + + QmlDebugObjectReference findParentRecursive( + int goalDebugId, const QList<QmlDebugObjectReference > &objectsToSearch); private: bool m_listeningToEditorManager; QmlJsInspectorToolBar *m_toolBar; ContextCrumblePath *m_crumblePath; - QLineEdit *m_filterExp; QmlJSPropertyInspector *m_propertyInspector; InspectorSettings *m_settings; ClientProxy *m_clientProxy; - QObject *m_qmlEngine; - QDeclarativeDebugExpressionQuery *m_debugQuery; + quint32 m_debugQuery; + quint32 m_showObjectQueryId; + QList<quint32> m_updateObjectQueryIds; // Qml/JS integration QHash<QString, QmlJSLiveTextPreview *> m_textPreviews; @@ -172,6 +177,7 @@ private: static InspectorUi *m_instance; bool m_selectionCallbackExpected; bool m_cursorPositionChangedExternally; + bool m_onCrumblePathClicked; }; } // Internal diff --git a/src/plugins/qmljsinspector/qmljsinspector.pro b/src/plugins/qmljsinspector/qmljsinspector.pro index 5d39cfa5e0..72d6395bff 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.pro +++ b/src/plugins/qmljsinspector/qmljsinspector.pro @@ -2,7 +2,12 @@ TEMPLATE = lib TARGET = QmlJSInspector INCLUDEPATH += . DEPENDPATH += . -QT += declarative network +QT += network +greaterThan(QT_MAJOR_VERSION, 4) { + QT += quick1 +} else { + QT += declarative +} DEFINES += QMLJSINSPECTOR_LIBRARY @@ -15,7 +20,6 @@ qmljsclientproxy.h \ qmljsinspector.h \ qmljsinspectortoolbar.h \ qmljslivetextpreview.h \ -qmljstoolbarcolorbox.h \ qmljsinspectorclient.h \ qmljscontextcrumblepath.h \ qmljsinspectorsettings.h \ @@ -27,7 +31,6 @@ qmljsclientproxy.cpp \ qmljsinspector.cpp \ qmljsinspectortoolbar.cpp \ qmljslivetextpreview.cpp \ -qmljstoolbarcolorbox.cpp \ qmljsinspectorclient.cpp \ qmljscontextcrumblepath.cpp \ qmljsinspectorsettings.cpp \ diff --git a/src/plugins/qmljsinspector/qmljsinspector.qbs b/src/plugins/qmljsinspector/qmljsinspector.qbs index f76b02cc95..c2eb41dee2 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.qbs +++ b/src/plugins/qmljsinspector/qmljsinspector.qbs @@ -39,7 +39,6 @@ QtcPlugin { "qmljsinspector.h", "qmljsinspectortoolbar.h", "qmljslivetextpreview.h", - "qmljstoolbarcolorbox.h", "qmljsinspectorclient.h", "qmljscontextcrumblepath.h", "qmljsinspectorsettings.h", @@ -50,7 +49,6 @@ QtcPlugin { "qmljsinspector.cpp", "qmljsinspectortoolbar.cpp", "qmljslivetextpreview.cpp", - "qmljstoolbarcolorbox.cpp", "qmljsinspectorclient.cpp", "qmljscontextcrumblepath.cpp", "qmljsinspectorsettings.cpp", diff --git a/src/plugins/qmljsinspector/qmljsinspector.qrc b/src/plugins/qmljsinspector/qmljsinspector.qrc index 9c1a710a6e..51f4e888ab 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.qrc +++ b/src/plugins/qmljsinspector/qmljsinspector.qrc @@ -1,6 +1,5 @@ <RCC> <qresource prefix="/qml"> - <file>images/color-picker.png</file> <file>images/from-qml.png</file> <file>images/pause.png</file> <file>images/reload.png</file> @@ -9,7 +8,6 @@ <file>images/to-qml.png</file> <file>images/select-marquee.png</file> <file>images/zoom.png</file> - <file>images/color-picker-small.png</file> <file>images/select-small.png</file> <file>images/play-small.png</file> <file>images/to-qml-small.png</file> @@ -17,7 +15,6 @@ <file>images/from-qml-small.png</file> <file>images/zoom-small.png</file> <file>images/select-marquee-small.png</file> - <file>images/color-picker-small-hicontrast.png</file> <file>images/app-on-top.png</file> </qresource> </RCC> diff --git a/src/plugins/qmljsinspector/qmljsinspectorclient.cpp b/src/plugins/qmljsinspector/qmljsinspectorclient.cpp index d4bf615c8c..0b4bc2aaab 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorclient.cpp +++ b/src/plugins/qmljsinspector/qmljsinspectorclient.cpp @@ -33,8 +33,6 @@ #include "qmljsclientproxy.h" #include "qmljsinspectorconstants.h" -#include <QColor> - using namespace QmlJSDebugger; namespace QmlJSInspector { @@ -85,9 +83,7 @@ void QmlJSInspectorClient::messageReceived(const QByteArray &message) log(LogReceive, type, QString::number(toolId)); - if (toolId == Constants::ColorPickerMode) { - emit colorPickerActivated(); - } else if (toolId == Constants::ZoomMode) { + if (toolId == Constants::ZoomMode) { emit zoomToolActivated(); } else if (toolId == Constants::SelectionToolMode) { emit selectToolActivated(); @@ -137,17 +133,8 @@ void QmlJSInspectorClient::messageReceived(const QByteArray &message) emit reloaded(); break; } - case InspectorProtocol::ColorChanged: { - QColor col; - ds >> col; - - log(LogReceive, type, col.name()); - - emit selectedColorChanged(col); - break; - } default: - qWarning() << "Warning: Not handling message:" << type; + log(LogReceive, type, QLatin1String("Warning: Not handling message")); } } @@ -182,15 +169,15 @@ void QmlJSInspectorClient::setCurrentObjects(const QList<int> &debugIds) sendMessage(message); } -void recurseObjectIdList(const QDeclarativeDebugObjectReference &ref, QList<int> &debugIds, QList<QString> &objectIds) +void recurseObjectIdList(const QmlDebugObjectReference &ref, QList<int> &debugIds, QList<QString> &objectIds) { debugIds << ref.debugId(); objectIds << ref.idString(); - foreach (const QDeclarativeDebugObjectReference &child, ref.children()) + foreach (const QmlDebugObjectReference &child, ref.children()) recurseObjectIdList(child, debugIds, objectIds); } -void QmlJSInspectorClient::setObjectIdList(const QList<QDeclarativeDebugObjectReference> &objectRoots) +void QmlJSInspectorClient::setObjectIdList(const QList<QmlDebugObjectReference> &objectRoots) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); @@ -198,7 +185,7 @@ void QmlJSInspectorClient::setObjectIdList(const QList<QDeclarativeDebugObjectRe QList<int> debugIds; QList<QString> objectIds; - foreach (const QDeclarativeDebugObjectReference &ref, objectRoots) + foreach (const QmlDebugObjectReference &ref, objectRoots) recurseObjectIdList(ref, debugIds, objectIds); InspectorProtocol::Message cmd = InspectorProtocol::ObjectIdList; @@ -300,24 +287,6 @@ void QmlJSInspectorClient::setAnimationPaused(bool paused) sendMessage(message); } -void QmlJSInspectorClient::changeToColorPickerTool() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; - InspectorProtocol::Tool tool = InspectorProtocol::ColorPickerTool; - ds << cmd - << tool; - - log(LogSend, cmd, InspectorProtocol::toString(tool)); - - sendMessage(message); -} - void QmlJSInspectorClient::changeToSelectTool() { if (!m_connection || !m_connection->isConnected()) diff --git a/src/plugins/qmljsinspector/qmljsinspectorclient.h b/src/plugins/qmljsinspector/qmljsinspectorclient.h index f090841fbd..37420d192c 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorclient.h +++ b/src/plugins/qmljsinspector/qmljsinspectorclient.h @@ -51,7 +51,6 @@ public: void setDesignModeBehavior(bool inDesignMode); void setAnimationSpeed(qreal slowDownFactor); void setAnimationPaused(bool paused); - void changeToColorPickerTool(); void changeToSelectTool(); void changeToSelectMarqueeTool(); void changeToZoomTool(); @@ -68,7 +67,7 @@ public: QList<int> currentObjects() const; // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's - void setObjectIdList(const QList<QDeclarativeDebugObjectReference> &objectRoots); + void setObjectIdList(const QList<QmlDebugObjectReference> &objectRoots); void clearComponentCache(); @@ -76,8 +75,6 @@ signals: void connectedStatusChanged(QDeclarativeDebugClient::Status status); void currentObjectsChanged(const QList<int> &debugIds); - void selectedColorChanged(const QColor &color); - void colorPickerActivated(); void selectToolActivated(); void selectMarqueeToolActivated(); void zoomToolActivated(); diff --git a/src/plugins/qmljsinspector/qmljsinspectorconstants.h b/src/plugins/qmljsinspector/qmljsinspectorconstants.h index d338a9eea5..41b985f6a6 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorconstants.h +++ b/src/plugins/qmljsinspector/qmljsinspectorconstants.h @@ -42,7 +42,6 @@ const char INFO_OUT_OF_SYNC[] = "QmlInspector.OutOfSyncWarning"; const char PLAY_ACTION[] = "QmlInspector.Play"; const char SELECT_ACTION[] = "QmlInspector.Select"; const char ZOOM_ACTION[] = "QmlInspector.Zoom"; -const char COLOR_PICKER_ACTION[] = "QmlInspector.ColorPicker"; const char FROM_QML_ACTION[] = "QmlInspector.FromQml"; const char SHOW_APP_ON_TOP_ACTION[] = "QmlInspector.ShowAppOnTop"; @@ -56,7 +55,6 @@ enum DesignTool { MarqueeSelectionToolMode = 2, MoveToolMode = 3, ResizeToolMode = 4, - ColorPickerMode = 5, ZoomMode = 6 }; diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.h b/src/plugins/qmljsinspector/qmljsinspectorplugin.h index 34bedf6d65..d3322121fd 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.h +++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.h @@ -52,6 +52,7 @@ class InspectorUi; class InspectorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlJSInspector.json") public: InspectorPlugin(); diff --git a/src/plugins/qmljsinspector/qmljsinspectortoolbar.cpp b/src/plugins/qmljsinspector/qmljsinspectortoolbar.cpp index 88a015adf2..0c055ba7d3 100644 --- a/src/plugins/qmljsinspector/qmljsinspectortoolbar.cpp +++ b/src/plugins/qmljsinspector/qmljsinspectortoolbar.cpp @@ -33,7 +33,6 @@ #include "qmljsinspectortoolbar.h" #include "qmljsinspectorconstants.h" -#include "qmljstoolbarcolorbox.h" #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/command.h> @@ -46,6 +45,7 @@ #include <projectexplorer/projectexplorerconstants.h> #include <utils/styledbar.h> +#include <utils/savedaction.h> #include <QAction> #include <QActionGroup> @@ -70,12 +70,10 @@ QmlJsInspectorToolBar::QmlJsInspectorToolBar(QObject *parent) : m_playAction(0), m_selectAction(0), m_zoomAction(0), - m_colorPickerAction(0), m_showAppOnTopAction(0), m_playSpeedMenuActions(0), m_playIcon(QIcon(QLatin1String(":/qml/images/play-small.png"))), m_pauseIcon(QIcon(QLatin1String(":/qml/images/pause-small.png"))), - m_colorBox(0), m_emitSignals(true), m_paused(false), m_animationSpeed(1.0f), @@ -92,15 +90,12 @@ void QmlJsInspectorToolBar::setEnabled(bool value) m_playAction->setEnabled(value); m_selectAction->setEnabled(value); m_zoomAction->setEnabled(value); - m_colorPickerAction->setEnabled(value); - m_colorBox->setEnabled(value); } void QmlJsInspectorToolBar::enable() { setEnabled(true); m_emitSignals = false; - m_showAppOnTopAction->setChecked(false); setAnimationSpeed(1.0f); m_designModeActive = false; updateDesignModeActions(NoTool); @@ -115,11 +110,6 @@ void QmlJsInspectorToolBar::disable() setEnabled(false); } -void QmlJsInspectorToolBar::activateColorPicker() -{ - updateDesignModeActions(ColorPickerMode); -} - void QmlJsInspectorToolBar::activateSelectTool() { updateDesignModeActions(SelectionToolMode); @@ -177,12 +167,22 @@ void QmlJsInspectorToolBar::createActions() Core::Context context(Debugger::Constants::C_QMLDEBUGGER); Core::ActionManager *am = Core::ICore::actionManager(); - m_fromQmlAction = - new QAction(QIcon(QLatin1String(":/qml/images/from-qml-small.png")), - tr("Apply Changes on Save"), this); - m_showAppOnTopAction = - new QAction(QIcon(QLatin1String(":/qml/images/app-on-top.png")), - tr("Show application on top"), this); + m_fromQmlAction = new Utils::SavedAction(this); + m_fromQmlAction->setDefaultValue(false); + m_fromQmlAction->setSettingsKey(QLatin1String(Constants::S_QML_INSPECTOR), + QLatin1String(Constants::FROM_QML_ACTION)); + m_fromQmlAction->setText(tr("Apply Changes on Save")); + m_fromQmlAction->setCheckable(true); + m_fromQmlAction->setIcon(QIcon(QLatin1String(":/qml/images/from-qml-small.png"))); + + m_showAppOnTopAction = new Utils::SavedAction(this); + m_showAppOnTopAction->setDefaultValue(false); + m_showAppOnTopAction->setSettingsKey(QLatin1String(Constants::S_QML_INSPECTOR), + QLatin1String(Constants::SHOW_APP_ON_TOP_ACTION)); + m_showAppOnTopAction->setText(tr("Show application on top")); + m_showAppOnTopAction->setCheckable(true); + m_showAppOnTopAction->setIcon(QIcon(QLatin1String(":/qml/images/app-on-top.png"))); + m_playAction = new QAction(m_pauseIcon, tr("Play/Pause Animations"), this); m_selectAction = @@ -191,29 +191,18 @@ void QmlJsInspectorToolBar::createActions() m_zoomAction = new QAction(QIcon(QLatin1String(":/qml/images/zoom-small.png")), tr("Zoom"), this); - m_colorPickerAction = - new QAction(QIcon(QLatin1String(":/qml/images/color-picker-small.png")), - tr("Color Picker"), this); - m_fromQmlAction->setCheckable(true); - m_fromQmlAction->setChecked(true); - m_showAppOnTopAction->setCheckable(true); - m_showAppOnTopAction->setChecked(false); m_selectAction->setCheckable(true); m_zoomAction->setCheckable(true); - m_colorPickerAction->setCheckable(true); Core::Command *command = am->registerAction(m_playAction, Constants::PLAY_ACTION, context); command->setAttribute(Core::Command::CA_UpdateIcon); am->registerAction(m_selectAction, Constants::SELECT_ACTION, context); am->registerAction(m_zoomAction, Constants::ZOOM_ACTION, context); - am->registerAction(m_colorPickerAction, Constants::COLOR_PICKER_ACTION, context); am->registerAction(m_fromQmlAction, Constants::FROM_QML_ACTION, context); am->registerAction(m_showAppOnTopAction, Constants::SHOW_APP_ON_TOP_ACTION, context); - m_barWidget = new Utils::StyledBar; - m_barWidget->setSingleRow(true); - m_barWidget->setProperty("topBorder", true); + m_barWidget = new QWidget; QMenu *playSpeedMenu = new QMenu(m_barWidget); m_playSpeedMenuActions = new QActionGroup(this); @@ -248,19 +237,7 @@ void QmlJsInspectorToolBar::createActions() toolBarLayout->setMargin(0); toolBarLayout->setSpacing(5); - m_operateByInstructionButton = toolButton(am->command(Debugger::Constants::OPERATE_BY_INSTRUCTION)->action()); - - // Add generic debugging controls - toolBarLayout->addWidget(toolButton(Debugger::DebuggerPlugin::visibleDebugAction())); - toolBarLayout->addWidget(toolButton(am->command(Debugger::Constants::STOP)->action())); - toolBarLayout->addWidget(toolButton(am->command(Debugger::Constants::NEXT)->action())); - toolBarLayout->addWidget(toolButton(am->command(Debugger::Constants::STEP)->action())); - toolBarLayout->addWidget(toolButton(am->command(Debugger::Constants::STEPOUT)->action())); - toolBarLayout->addWidget(m_operateByInstructionButton); - toolBarLayout->addStretch(1); - // QML Helpers - toolBarLayout->addWidget(new Utils::StyledSeparator); toolBarLayout->addWidget(toolButton(am->command(Constants::FROM_QML_ACTION)->action())); toolBarLayout->addWidget(toolButton(am->command(Constants::SHOW_APP_ON_TOP_ACTION)->action())); m_playButton = toolButton(am->command(Constants::PLAY_ACTION)->action()); @@ -271,26 +248,31 @@ void QmlJsInspectorToolBar::createActions() toolBarLayout->addWidget(new Utils::StyledSeparator); toolBarLayout->addWidget(toolButton(am->command(Constants::SELECT_ACTION)->action())); toolBarLayout->addWidget(toolButton(am->command(Constants::ZOOM_ACTION)->action())); - toolBarLayout->addWidget(toolButton(am->command(Constants::COLOR_PICKER_ACTION)->action())); - - m_colorBox = new ToolBarColorBox(m_barWidget); - m_colorBox->setMinimumSize(20, 20); - m_colorBox->setMaximumSize(20, 20); - m_colorBox->setInnerBorderColor(QColor(192, 192, 192)); - m_colorBox->setOuterBorderColor(QColor(58, 58, 58)); - toolBarLayout->addWidget(m_colorBox); + toolBarLayout->addWidget(new Utils::StyledSeparator); connect(m_fromQmlAction, SIGNAL(triggered()), SLOT(activateFromQml())); connect(m_showAppOnTopAction, SIGNAL(triggered()), SLOT(showAppOnTopClick())); connect(m_playAction, SIGNAL(triggered()), SLOT(activatePlayOnClick())); - connect(m_colorPickerAction, SIGNAL(triggered(bool)), SLOT(colorPickerTriggered(bool))); connect(m_selectAction, SIGNAL(triggered(bool)), SLOT(selectToolTriggered(bool))); connect(m_zoomAction, SIGNAL(triggered(bool)), SLOT(zoomToolTriggered(bool))); - Debugger::DebuggerMainWindow *mw = Debugger::DebuggerPlugin::mainWindow(); - activeDebugLanguagesChanged(mw->activeDebugLanguages()); - connect(mw, SIGNAL(activeDebugLanguagesChanged(Debugger::DebuggerLanguages)), - this, SLOT(activeDebugLanguagesChanged(Debugger::DebuggerLanguages))); + readSettings(); + connect(Core::ICore::instance(), + SIGNAL(saveSettingsRequested()), SLOT(writeSettings())); +} + +void QmlJsInspectorToolBar::readSettings() +{ + QSettings *settings = Core::ICore::settings(); + m_fromQmlAction->readSettings(settings); + m_showAppOnTopAction->readSettings(settings); +} + +void QmlJsInspectorToolBar::writeSettings() const +{ + QSettings *settings = Core::ICore::settings(); + m_fromQmlAction->writeSettings(settings); + m_showAppOnTopAction->writeSettings(settings); } QWidget *QmlJsInspectorToolBar::widget() const @@ -320,19 +302,6 @@ void QmlJsInspectorToolBar::updatePlayAction() m_playAction->setIcon(m_paused ? m_playIcon : m_pauseIcon); } -void QmlJsInspectorToolBar::colorPickerTriggered(bool checked) -{ - updateDesignModeActions(ColorPickerMode); - - if (m_designModeActive != checked) { - m_designModeActive = checked; - emit designModeSelected(checked); - } - - if (checked) - emit colorPickerSelected(); -} - void QmlJsInspectorToolBar::selectToolTriggered(bool checked) { updateDesignModeActions(SelectionToolMode); @@ -365,28 +334,17 @@ void QmlJsInspectorToolBar::showAppOnTopClick() emit showAppOnTopSelected(m_showAppOnTopAction->isChecked()); } -void QmlJsInspectorToolBar::setSelectedColor(const QColor &color) -{ - m_colorBox->setColor(color); -} - void QmlJsInspectorToolBar::activateFromQml() { if (m_emitSignals) emit applyChangesFromQmlFileTriggered(m_fromQmlAction->isChecked()); } -void QmlJsInspectorToolBar::activeDebugLanguagesChanged(Debugger::DebuggerLanguages languages) -{ - m_operateByInstructionButton->setVisible(languages & Debugger::CppLanguage); -} - void QmlJsInspectorToolBar::updateDesignModeActions(DesignTool activeTool) { m_activeTool = activeTool; m_selectAction->setChecked(m_designModeActive && (m_activeTool == SelectionToolMode)); m_zoomAction->setChecked(m_designModeActive && (m_activeTool == ZoomMode)); - m_colorPickerAction->setChecked(m_designModeActive && (m_activeTool == ColorPickerMode)); } } // namespace Internal diff --git a/src/plugins/qmljsinspector/qmljsinspectortoolbar.h b/src/plugins/qmljsinspector/qmljsinspectortoolbar.h index b533c38de6..99c4fd9a39 100644 --- a/src/plugins/qmljsinspector/qmljsinspectortoolbar.h +++ b/src/plugins/qmljsinspector/qmljsinspectortoolbar.h @@ -41,18 +41,16 @@ QT_BEGIN_NAMESPACE class QAction; class QActionGroup; -class QColor; class QToolButton; QT_END_NAMESPACE namespace Utils { class StyledBar; +class SavedAction; } namespace QmlJSInspector { -class ToolBarColorBox; - namespace Internal { class QmlJsInspectorToolBar : public QObject @@ -66,20 +64,20 @@ public: MarqueeSelectionToolMode = 2, MoveToolMode = 3, ResizeToolMode = 4, - ColorPickerMode = 5, ZoomMode = 6 }; explicit QmlJsInspectorToolBar(QObject *parent = 0); void createActions(); QWidget *widget() const; + void readSettings(); public slots: + void writeSettings() const; void setEnabled(bool value); void enable(); void disable(); - void activateColorPicker(); void activateSelectTool(); void activateZoomTool(); @@ -88,14 +86,12 @@ public slots: void setDesignModeBehavior(bool inDesignMode); void setShowAppOnTop(bool showAppOnTop); - void setSelectedColor(const QColor &color); signals: void applyChangesFromQmlFileTriggered(bool isChecked); void designModeSelected(bool); void reloadSelected(); - void colorPickerSelected(); void selectToolSelected(); void zoomToolSelected(); @@ -106,7 +102,6 @@ signals: private slots: void activatePlayOnClick(); - void colorPickerTriggered(bool checked); void selectToolTriggered(bool checked); void zoomToolTriggered(bool checked); @@ -118,20 +113,15 @@ private slots: void updatePlayAction(); - void activeDebugLanguagesChanged(Debugger::DebuggerLanguages languages); - private: void updateDesignModeActions(DesignTool activeTool); - QToolButton *m_operateByInstructionButton; - - QAction *m_fromQmlAction; + Utils::SavedAction *m_fromQmlAction; QAction *m_playAction; QAction *m_selectAction; QAction *m_zoomAction; - QAction *m_colorPickerAction; - QAction *m_showAppOnTopAction; + Utils::SavedAction *m_showAppOnTopAction; QActionGroup *m_playSpeedMenuActions; @@ -139,8 +129,6 @@ private: QIcon m_playIcon; QIcon m_pauseIcon; - ToolBarColorBox *m_colorBox; - bool m_emitSignals; bool m_paused; qreal m_animationSpeed; @@ -148,7 +136,7 @@ private: bool m_designModeActive; DesignTool m_activeTool; - Utils::StyledBar *m_barWidget; + QWidget *m_barWidget; }; } // namespace Internal diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp index 17eed26cde..0496e30b48 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -178,6 +178,8 @@ QmlJSLiveTextPreview::QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc, , m_initialDoc(initDoc) , m_applyChangesToQmlInspector(true) , m_clientProxy(clientProxy) + , m_nodeForOffset(0) + , m_updateNodeForOffset(false) { Q_ASSERT(doc->fileName() == initDoc->fileName()); m_filename = doc->fileName(); @@ -200,17 +202,32 @@ void QmlJSLiveTextPreview::resetInitialDoc(const QmlJS::Document::Ptr &doc) } -QList<int> QmlJSLiveTextPreview::objectReferencesForOffset(quint32 offset) const +QList<int> QmlJSLiveTextPreview::objectReferencesForOffset(quint32 offset) { QList<int> result; QHashIterator<QmlJS::AST::UiObjectMember*, QList<int> > iter(m_debugIds); + QmlJS::AST::UiObjectMember *possibleNode = 0; while(iter.hasNext()) { iter.next(); QmlJS::AST::UiObjectMember *member = iter.key(); - if (member->firstSourceLocation().offset == offset) { - result = iter.value(); - break; + quint32 startOffset = member->firstSourceLocation().offset; + quint32 endOffset = member->lastSourceLocation().offset; + if (startOffset <= offset && offset <= endOffset) { + if (!possibleNode) + possibleNode = member; + if (possibleNode->firstSourceLocation().offset <= startOffset && + endOffset <= possibleNode->lastSourceLocation().offset) + possibleNode = member; + } + } + if (possibleNode) { + if (possibleNode != m_nodeForOffset) { + //We have found a better match, set flag so that we can + //query again to check if this is the best match for the offset + m_updateNodeForOffset = true; + m_nodeForOffset = possibleNode; } + result = m_debugIds.value(possibleNode); } return result; } @@ -220,7 +237,9 @@ void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QStr if (m_editors.isEmpty() || !m_previousDoc || !m_clientProxy) return; - QDeclarativeDebugObjectReference objectRefUnderCursor; + m_updateNodeForOffset = false; + m_lastOffsets = offsets; + QmlDebugObjectReference objectRefUnderCursor; objectRefUnderCursor = m_clientProxy.data()->objectReferenceForId(wordAtCursor); QList<int> selectedReferences; @@ -252,20 +271,20 @@ void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QStr } if (!selectedReferences.isEmpty()) { - QList<QDeclarativeDebugObjectReference> refs; + QList<QmlDebugObjectReference> refs; foreach(int i, selectedReferences) - refs << QDeclarativeDebugObjectReference(i); + refs << QmlDebugObjectReference(i); emit selectedItemsChanged(refs); } } -static QList<int> findRootObjectRecursive(const QDeclarativeDebugObjectReference &object, const Document::Ptr &doc) +static QList<int> findRootObjectRecursive(const QmlDebugObjectReference &object, const Document::Ptr &doc) { QList<int> result; if (object.className() == doc->componentName()) result += object.debugId(); - foreach (const QDeclarativeDebugObjectReference &it, object.children()) { + foreach (const QmlDebugObjectReference &it, object.children()) { result += findRootObjectRecursive(it, doc); } return result; @@ -305,7 +324,7 @@ void QmlJSLiveTextPreview::updateDebugIds() if(doc->qmlProgram()->members && doc->qmlProgram()->members->member) { UiObjectMember* root = doc->qmlProgram()->members->member; QList<int> r; - foreach(const QDeclarativeDebugObjectReference& it, clientProxy->rootObjectReference()) + foreach (const QmlDebugObjectReference& it, clientProxy->rootObjectReference()) r += findRootObjectRecursive(it, doc); if (!r.isEmpty()) m_debugIds[root] += r; @@ -338,6 +357,8 @@ void QmlJSLiveTextPreview::updateDebugIds() m_debugIds[it2.key()] += it2.value(); } } + if (m_updateNodeForOffset) + changeSelectedElements(m_lastOffsets, QString()); } @@ -464,7 +485,10 @@ protected: if (isLiteral) expr = castToLiteral(scriptCode, scriptBinding); appliedChangesToViewer = true; - m_clientProxy->setBindingForObject(debugId, propertyName, expr, isLiteral, document()->fileName(), scriptBinding->firstSourceLocation().startLine); + m_clientProxy->setBindingForObject( + debugId, propertyName, expr, + isLiteral, document()->fileName(), + scriptBinding->firstSourceLocation().startLine); } virtual void resetBindingForObject(int debugId, const QString &propertyName) diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h index 661b2d0e77..6ada1e56ad 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.h +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h @@ -72,8 +72,8 @@ public: void associateEditor(Core::IEditor *editor); void unassociateEditor(Core::IEditor *editor); - void setActiveObject(const QDeclarativeDebugObjectReference &object); - void mapObjectToQml(const QDeclarativeDebugObjectReference &object); + void setActiveObject(const QmlDebugObjectReference &object); + void mapObjectToQml(const QmlDebugObjectReference &object); void resetInitialDoc(const QmlJS::Document::Ptr &doc); void setClientProxy(ClientProxy *clientProxy); @@ -85,7 +85,7 @@ public: }; signals: - void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &objects); + void selectedItemsChanged(const QList<QmlDebugObjectReference> &objects); void reloadQmlViewerRequested(); void disableLivePreviewRequested(); @@ -101,7 +101,7 @@ private slots: private: static QmlJS::ModelManagerInterface *modelManager(); - QList<int> objectReferencesForOffset(quint32 offset) const; + QList<int> objectReferencesForOffset(quint32 offset); QVariant castToLiteral(const QString &expression, QmlJS::AST::UiScriptBinding *scriptBinding); void showSyncWarning(UnsyncronizableChangeType unsyncronizableChangeType, const QString &elementName, unsigned line, unsigned column); @@ -120,6 +120,9 @@ private: bool m_applyChangesToQmlInspector; QmlJS::Document::Ptr m_docWithUnappliedChanges; QWeakPointer<ClientProxy> m_clientProxy; + QList<int> m_lastOffsets; + QmlJS::AST::UiObjectMember *m_nodeForOffset; + bool m_updateNodeForOffset; }; diff --git a/src/plugins/qmljsinspector/qmljsprivateapi.h b/src/plugins/qmljsinspector/qmljsprivateapi.h index a8654ba926..003938c548 100644 --- a/src/plugins/qmljsinspector/qmljsprivateapi.h +++ b/src/plugins/qmljsinspector/qmljsprivateapi.h @@ -32,8 +32,10 @@ #ifndef QMLJSPRIVATEAPI_H #define QMLJSPRIVATEAPI_H -#include <qmljsdebugclient/qdeclarativeenginedebug.h> +#include <qmljsdebugclient/qmlenginedebugclient.h> #include <qmljsdebugclient/qdeclarativedebugclient.h> +#include <qmljsdebugclient/qdeclarativeengineclient.h> +#include <qmljsdebugclient/qmldebuggerclient.h> using namespace QmlJsDebugClient; diff --git a/src/plugins/qmljsinspector/qmljspropertyinspector.cpp b/src/plugins/qmljsinspector/qmljspropertyinspector.cpp index 4ee78abf2a..9f4c325c48 100644 --- a/src/plugins/qmljsinspector/qmljspropertyinspector.cpp +++ b/src/plugins/qmljsinspector/qmljspropertyinspector.cpp @@ -47,6 +47,10 @@ #include <utils/qtcassert.h> +const int PROPERTY_NAME_COLUMN = 0; +const int PROPERTY_TYPE_COLUMN = 1; +const int PROPERTY_VALUE_COLUMN = 2; + namespace QmlJSInspector { namespace Internal { @@ -65,16 +69,16 @@ class PropertyEditDelegate : public QItemDelegate const QModelIndex &index) const { Q_UNUSED(option); - if (index.column() != 1) + if (index.column() != PROPERTY_VALUE_COLUMN) return 0; switch (m_treeWidget->getTypeFor(index.row())) { case QmlJSPropertyInspector::BooleanType: { // invert the bool, skip editor - int objectId = m_treeWidget->getData(index.row(), 0, Qt::UserRole).toInt(); - QString propertyName = m_treeWidget->getData(index.row(), 0, Qt::DisplayRole).toString(); - bool propertyValue = m_treeWidget->getData(index.row(), 1, Qt::DisplayRole).toBool(); + int objectId = m_treeWidget->getData(index.row(), PROPERTY_NAME_COLUMN, Qt::UserRole).toInt(); + QString propertyName = m_treeWidget->getData(index.row(), PROPERTY_NAME_COLUMN, Qt::DisplayRole).toString(); + bool propertyValue = m_treeWidget->getData(index.row(), PROPERTY_VALUE_COLUMN, Qt::DisplayRole).toBool(); m_treeWidget->propertyValueEdited(objectId, propertyName, !propertyValue?"true":"false"); return 0; } @@ -95,7 +99,7 @@ class PropertyEditDelegate : public QItemDelegate void setEditorData(QWidget *editor, const QModelIndex &index) const { - QVariant data = m_treeWidget->getData(index.row(), 1, Qt::DisplayRole); + QVariant data = m_treeWidget->getData(index.row(), PROPERTY_VALUE_COLUMN, Qt::DisplayRole); QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); lineEdit->setText(data.toString()); } @@ -104,11 +108,11 @@ class PropertyEditDelegate : public QItemDelegate { Q_UNUSED(model); - int objectId = m_treeWidget->getData(index.row(), 0, Qt::UserRole).toInt(); + int objectId = m_treeWidget->getData(index.row(), PROPERTY_NAME_COLUMN, Qt::UserRole).toInt(); if (objectId == -1) return; - QString propertyName = m_treeWidget->getData(index.row(), 0, Qt::DisplayRole).toString(); + QString propertyName = m_treeWidget->getData(index.row(), PROPERTY_NAME_COLUMN, Qt::DisplayRole).toString(); QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); QString propertyValue = lineEdit->text(); @@ -240,20 +244,6 @@ void ColorChooserDialog::acceptColor(const QColor &color) } // ************************************************************************* -// FILTER -// ************************************************************************* -bool PropertiesFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const -{ - QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent); - QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent); - QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent); - - return (sourceModel()->data(index0).toString().contains(filterRegExp()) - || sourceModel()->data(index1).toString().contains(filterRegExp()) - || sourceModel()->data(index2).toString().contains(filterRegExp())); -} - -// ************************************************************************* // QmlJSObjectTree // ************************************************************************* inline QString cleanPropertyValue(QString propertyValue) @@ -265,44 +255,76 @@ inline QString cleanPropertyValue(QString propertyValue) return propertyValue; } -QmlJSPropertyInspector::QmlJSPropertyInspector(QWidget *parent) - : QTreeView(parent) +// ************************************************************************* +// QmlJSPropertyInspectorModel +// ************************************************************************* +QmlJSPropertyInspectorModel::QmlJSPropertyInspectorModel() + : QStandardItemModel() + , m_contentsValid(false) { - setAttribute(Qt::WA_MacShowFocusRect, false); - setFrameStyle(QFrame::NoFrame); - setExpandsOnDoubleClick(true); +} + +Qt::ItemFlags QmlJSPropertyInspectorModel::flags(const QModelIndex &index) const +{ + return m_contentsValid ? QStandardItemModel::flags(index) : Qt::ItemFlags(); +} - header()->setResizeMode(QHeaderView::ResizeToContents); - header()->setMinimumSectionSize(150); - setRootIsDecorated(false); +QVariant QmlJSPropertyInspectorModel::headerData(int section, Qt::Orientation orient, int role) const +{ + if (orient == Qt::Horizontal && role == Qt::DisplayRole) { + switch (section) { + case PROPERTY_NAME_COLUMN: return tr("Name"); + case PROPERTY_VALUE_COLUMN: return tr("Value"); + case PROPERTY_TYPE_COLUMN: return tr("Type"); + }; + } + return QStandardItemModel::headerData(section, orient, role); +} - setItemDelegateForColumn(1, new PropertyEditDelegate(this)); +void QmlJSPropertyInspectorModel::setContentsValid(bool contentsValid) +{ + m_contentsValid = contentsValid; +} - m_filter = new PropertiesFilter(this); - m_filter->setSourceModel(&m_model); - setModel(m_filter); +bool QmlJSPropertyInspectorModel::contentsValid() const +{ + return m_contentsValid; } -void QmlJSPropertyInspector::filterBy(const QString &expression) +QmlJSPropertyInspector::QmlJSPropertyInspector(QWidget *parent) + : Utils::BaseTreeView(parent) { - m_filter->setFilterWildcard(expression); - m_filter->setFilterCaseSensitivity(Qt::CaseInsensitive); + setItemDelegateForColumn(PROPERTY_VALUE_COLUMN, new PropertyEditDelegate(this)); + + setModel(&m_model); + //Add an empty Row to make the headers visible! + addRow(QString(), QString(), QString(), -1, false); } void QmlJSPropertyInspector::clear() { - m_model.clear(); + m_model.removeRows(0, m_model.rowCount()); m_currentObjects.clear(); } -void QmlJSPropertyInspector::setCurrentObjects(const QList<QDeclarativeDebugObjectReference> &objectList) +void QmlJSPropertyInspector::setContentsValid(bool contentsValid) +{ + m_model.setContentsValid(contentsValid); +} + +bool QmlJSPropertyInspector::contentsValid() const +{ + return m_model.contentsValid(); +} + +void QmlJSPropertyInspector::setCurrentObjects(const QList<QmlDebugObjectReference> &objectList) { if (objectList.isEmpty()) return; clear(); - foreach (const QDeclarativeDebugObjectReference &obj, objectList) { + foreach (const QmlDebugObjectReference &obj, objectList) { m_currentObjects << obj.debugId(); buildPropertyTree(obj); } @@ -310,12 +332,12 @@ void QmlJSPropertyInspector::setCurrentObjects(const QList<QDeclarativeDebugObje QVariant QmlJSPropertyInspector::getData(int row, int column, int role) const { - return m_filter->data(m_filter->index(row, column), role); + return m_model.data(m_model.index(row, column), role); } QmlJSPropertyInspector::PropertyType QmlJSPropertyInspector::getTypeFor(int row) const { - return static_cast<QmlJSPropertyInspector::PropertyType>(m_filter->data(m_filter->index(row,2),Qt::UserRole).toInt()); + return static_cast<QmlJSPropertyInspector::PropertyType>(m_model.data(m_model.index(row, PROPERTY_TYPE_COLUMN), Qt::UserRole).toInt()); } void QmlJSPropertyInspector::propertyValueChanged(int debugId, const QByteArray &propertyName, const QVariant &propertyValue) @@ -325,18 +347,18 @@ void QmlJSPropertyInspector::propertyValueChanged(int debugId, const QByteArray QString propertyNameS = QString(propertyName); for (int i = 0; i < m_model.rowCount(); i++) { - if (m_model.data(m_model.index(i, 0), Qt::DisplayRole).toString() == propertyNameS && - m_model.data(m_model.index(i, 0), Qt::UserRole).toInt() == debugId) { - QString oldData = m_model.data(m_model.index(i, 1), Qt::DisplayRole).toString(); + if (m_model.data(m_model.index(i, PROPERTY_NAME_COLUMN), Qt::DisplayRole).toString() == propertyNameS && + m_model.data(m_model.index(i, PROPERTY_NAME_COLUMN), Qt::UserRole).toInt() == debugId) { + QString oldData = m_model.data(m_model.index(i, PROPERTY_VALUE_COLUMN), Qt::DisplayRole).toString(); QString newData = propertyValue.toString(); if (QString(propertyValue.typeName()) == "QColor") newData = extendedNameFromColor(propertyValue); if (oldData != newData) { - m_model.setData(m_model.index(i, 1), newData, Qt::DisplayRole); - m_model.item(i, 1)->setToolTip(newData); - m_model.item(i, 0)->setForeground(QBrush(Qt::red)); - m_model.item(i, 1)->setForeground(QBrush(Qt::red)); - m_model.item(i, 2)->setForeground(QBrush(Qt::red)); + m_model.setData(m_model.index(i, PROPERTY_VALUE_COLUMN), newData, Qt::DisplayRole); + m_model.item(i, PROPERTY_VALUE_COLUMN)->setToolTip(newData); + m_model.item(i, PROPERTY_NAME_COLUMN)->setForeground(QBrush(Qt::red)); + m_model.item(i, PROPERTY_VALUE_COLUMN)->setForeground(QBrush(Qt::red)); + m_model.item(i, PROPERTY_TYPE_COLUMN)->setForeground(QBrush(Qt::red)); if (getTypeFor(i) == QmlJSPropertyInspector::ColorType) setColorIcon(i); } @@ -350,7 +372,7 @@ void QmlJSPropertyInspector::propertyValueEdited(const int objectId,const QStrin emit changePropertyValue(objectId, propertyName, propertyValue); } -void QmlJSPropertyInspector::buildPropertyTree(const QDeclarativeDebugObjectReference &obj) +void QmlJSPropertyInspector::buildPropertyTree(const QmlDebugObjectReference &obj) { // Strip off the misleading metadata QString objTypeName = obj.className(); @@ -375,7 +397,7 @@ void QmlJSPropertyInspector::buildPropertyTree(const QDeclarativeDebugObjectRefe false); } - foreach (const QDeclarativeDebugPropertyReference &prop, obj.properties()) { + foreach (const QmlDebugPropertyReference &prop, obj.properties()) { QString propertyName = prop.name(); QString propertyValue = prop.value().toString(); @@ -389,9 +411,9 @@ void QmlJSPropertyInspector::buildPropertyTree(const QDeclarativeDebugObjectRefe addRow(propertyName, propertyValue, prop.valueTypeName(), obj.debugId(), prop.hasNotifySignal()); } - m_model.setHeaderData(0,Qt::Horizontal,QVariant("name")); - m_model.setHeaderData(1,Qt::Horizontal,QVariant("value")); - m_model.setHeaderData(2,Qt::Horizontal,QVariant("type")); + m_model.setHeaderData(PROPERTY_NAME_COLUMN, Qt::Horizontal,QVariant("name")); + m_model.setHeaderData(PROPERTY_VALUE_COLUMN, Qt::Horizontal,QVariant("value")); + m_model.setHeaderData(PROPERTY_TYPE_COLUMN, Qt::Horizontal,QVariant("type")); } @@ -426,7 +448,7 @@ void QmlJSPropertyInspector::addRow(const QString &name,const QString &value, co typeColumn->setData(typeCode, Qt::UserRole); QList<QStandardItem *> newRow; - newRow << nameColumn << valueColumn << typeColumn; + newRow << nameColumn << typeColumn << valueColumn; m_model.appendRow(newRow); if (typeCode == QmlJSPropertyInspector::ColorType) @@ -435,7 +457,7 @@ void QmlJSPropertyInspector::addRow(const QString &name,const QString &value, co void QmlJSPropertyInspector::setColorIcon(int row) { - QStandardItem *item = m_model.itemFromIndex(m_model.index(row, 1)); + QStandardItem *item = m_model.item(row, PROPERTY_VALUE_COLUMN); QColor color = colorFromExtendedName(item->data(Qt::DisplayRole).toString()); int recomendedLength = viewOptions().decorationSize.height() - 2; @@ -457,7 +479,7 @@ void QmlJSPropertyInspector::contextMenuEvent(QContextMenuEvent *ev) bool isEditable = false; bool isColor = false; if (itemIndex.isValid()) { - isEditable = m_model.itemFromIndex(m_filter->mapToSource(m_filter->index(itemIndex.row(), 1)))->isEditable(); + isEditable = m_model.item(itemIndex.row(), PROPERTY_VALUE_COLUMN)->isEditable(); isColor = (getTypeFor(itemIndex.row()) == QmlJSPropertyInspector::ColorType); } @@ -468,6 +490,7 @@ void QmlJSPropertyInspector::contextMenuEvent(QContextMenuEvent *ev) QAction colorAction(tr("Choose color"), this); if (isColor) menu.addAction(&colorAction); + addBaseContextActions(&menu); QAction *action = menu.exec(ev->globalPos()); if (action == 0) @@ -477,13 +500,14 @@ void QmlJSPropertyInspector::contextMenuEvent(QContextMenuEvent *ev) openExpressionEditor(itemIndex); if (action == &colorAction) openColorSelector(itemIndex); + handleBaseContextAction(action); } void QmlJSPropertyInspector::openExpressionEditor(const QModelIndex &itemIndex) { - const QString propertyName = getData(itemIndex.row(), 0, Qt::DisplayRole).toString(); + const QString propertyName = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, Qt::DisplayRole).toString(); const QString dialogText = tr("JavaScript expression for %1").arg(propertyName); - const int objectId = getData(itemIndex.row(), 0, Qt::UserRole).toInt(); + const int objectId = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, Qt::UserRole).toInt(); ExpressionEdit *expressionDialog = new ExpressionEdit(dialogText); expressionDialog->setItemData(objectId, propertyName); @@ -496,10 +520,10 @@ void QmlJSPropertyInspector::openExpressionEditor(const QModelIndex &itemIndex) void QmlJSPropertyInspector::openColorSelector(const QModelIndex &itemIndex) { - const QString propertyName = getData(itemIndex.row(), 0, Qt::DisplayRole).toString(); + const QString propertyName = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, Qt::DisplayRole).toString(); const QString dialogText = tr("Color selection for %1").arg(propertyName); - const int objectId = getData(itemIndex.row(), 0, Qt::UserRole).toInt(); - const QString propertyValue = getData(itemIndex.row(), 1, Qt::DisplayRole).toString(); + const int objectId = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, Qt::UserRole).toInt(); + const QString propertyValue = getData(itemIndex.row(), PROPERTY_VALUE_COLUMN, Qt::DisplayRole).toString(); ColorChooserDialog *colorDialog = new ColorChooserDialog(dialogText); colorDialog->setItemData(objectId, propertyName, propertyValue); diff --git a/src/plugins/qmljsinspector/qmljspropertyinspector.h b/src/plugins/qmljsinspector/qmljspropertyinspector.h index 31fe1d61b6..3080c64652 100644 --- a/src/plugins/qmljsinspector/qmljspropertyinspector.h +++ b/src/plugins/qmljsinspector/qmljspropertyinspector.h @@ -33,9 +33,8 @@ #define PROPERTYINSPECTOR_H #include <qmljsprivateapi.h> -#include <QTreeView> +#include <utils/basetreeview.h> #include <QStandardItemModel> -#include <QSortFilterProxyModel> #include <QDialog> #include <QDialogButtonBox> @@ -51,21 +50,6 @@ namespace Internal { class PropertyEditDelegate; -class PropertiesFilter : public QSortFilterProxyModel -{ - Q_OBJECT -public: - explicit PropertiesFilter(QObject *parent = 0) - : QSortFilterProxyModel(parent) - { - setDynamicSortFilter(true); - } - - ~PropertiesFilter() { } - - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; -}; - class ExpressionEdit : public QDialog { Q_OBJECT @@ -108,7 +92,23 @@ private: QmlEditorWidgets::CustomColorDialog *m_mainFrame; }; -class QmlJSPropertyInspector : public QTreeView +class QmlJSPropertyInspectorModel : public QStandardItemModel +{ + Q_OBJECT +public: + QmlJSPropertyInspectorModel(); + void setContentsValid(bool contentsValid); + bool contentsValid() const; + +protected: + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + +private: + bool m_contentsValid; +}; + +class QmlJSPropertyInspector : public Utils::BaseTreeView { Q_OBJECT public: @@ -123,23 +123,24 @@ public: explicit QmlJSPropertyInspector(QWidget *parent = 0); void clear(); + void setContentsValid(bool contentsValid); + bool contentsValid() const; signals: void changePropertyValue(int debugId, QString propertyName, QString valueExpression); void customContextMenuRequested(const QPoint &pos); public slots: - void setCurrentObjects(const QList<QDeclarativeDebugObjectReference> &); + void setCurrentObjects(const QList<QmlDebugObjectReference> &); void propertyValueEdited(const int objectId,const QString &propertyName, const QString &propertyValue); void propertyValueChanged(int debugId, const QByteArray &propertyName, const QVariant &propertyValue); - void filterBy(const QString &expression); void openExpressionEditor(const QModelIndex &itemIndex); void openColorSelector(const QModelIndex &itemIndex); private: friend class PropertyEditDelegate; - void buildPropertyTree(const QDeclarativeDebugObjectReference &); + void buildPropertyTree(const QmlDebugObjectReference &); void addRow(const QString &name, const QString &value, const QString &type, const int debugId = -1, bool editable = true); void setColorIcon(int row); @@ -149,8 +150,7 @@ private: void contextMenuEvent(QContextMenuEvent *ev); - QStandardItemModel m_model; - PropertiesFilter *m_filter; + QmlJSPropertyInspectorModel m_model; QList<int> m_currentObjects; }; diff --git a/src/plugins/qmljsinspector/qmljstoolbarcolorbox.cpp b/src/plugins/qmljsinspector/qmljstoolbarcolorbox.cpp deleted file mode 100644 index b16fa40771..0000000000 --- a/src/plugins/qmljsinspector/qmljstoolbarcolorbox.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#include "qmljstoolbarcolorbox.h" - -#include <QPixmap> -#include <QPainter> -#include <QMenu> -#include <QAction> -#include <QContextMenuEvent> -#include <QClipboard> -#include <QApplication> -#include <QColorDialog> -#include <QDrag> - -#include <QMimeData> -#include <QDebug> - -namespace QmlJSInspector { - -ToolBarColorBox::ToolBarColorBox(QWidget *parent) : - QLabel(parent) -{ - m_color = Qt::white; - m_borderColorOuter = Qt::white; - m_borderColorInner = QColor(143, 143 ,143); - - m_copyHexColorAction = new QAction(QIcon(QLatin1String(":/qml/images/color-picker-small-hicontrast.png")), tr("Copy Color"), this); - connect(m_copyHexColorAction, SIGNAL(triggered()), SLOT(copyColorToClipboard())); - setScaledContents(false); -} - -void ToolBarColorBox::setColor(const QColor &color) -{ - m_color = color; - - QPixmap pix = createDragPixmap(width()); - setPixmap(pix); - update(); -} - -void ToolBarColorBox::setInnerBorderColor(const QColor &color) -{ - m_borderColorInner = color; - setColor(m_color); -} - -void ToolBarColorBox::setOuterBorderColor(const QColor &color) - { - m_borderColorOuter = color; - setColor(m_color); - } - -void ToolBarColorBox::mousePressEvent(QMouseEvent *event) -{ - m_dragBeginPoint = event->pos(); - m_dragStarted = false; -} - -void ToolBarColorBox::mouseMoveEvent(QMouseEvent *event) -{ - if (event->buttons() & Qt::LeftButton - && QPoint(event->pos() - m_dragBeginPoint).manhattanLength() > QApplication::startDragDistance() - && !m_dragStarted) - { - m_dragStarted = true; - QDrag *drag = new QDrag(this); - QMimeData *mimeData = new QMimeData; - - mimeData->setText(m_color.name()); - drag->setMimeData(mimeData); - drag->setPixmap(createDragPixmap()); - - drag->exec(); - } -} - -QPixmap ToolBarColorBox::createDragPixmap(int size) const -{ - QPixmap pix(size, size); - QPainter p(&pix); - - p.setBrush(QBrush(m_color)); - p.setPen(QPen(QBrush(m_borderColorInner),1)); - - p.fillRect(0, 0, size, size, m_borderColorOuter); - p.drawRect(1,1, size - 3, size - 3); - return pix; -} - -void ToolBarColorBox::contextMenuEvent(QContextMenuEvent *ev) -{ - QMenu contextMenu; - contextMenu.addAction(m_copyHexColorAction); - contextMenu.exec(ev->globalPos()); -} - -void ToolBarColorBox::copyColorToClipboard() -{ - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(m_color.name()); -} - -} // namespace QmlJSInspector diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp index e10c15e4e8..9f9f66f373 100644 --- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp +++ b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp @@ -45,7 +45,7 @@ #include <cplusplus/CoreTypes.h> #include <cplusplus/Symbols.h> #include <cplusplus/SimpleLexer.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <utils/qtcassert.h> #include <QDebug> @@ -143,7 +143,12 @@ protected: if (!templateIdentifier) return false; const QString callName = QString::fromUtf8(templateIdentifier->chars()); - if (callName != QLatin1String("qmlRegisterType")) + int argCount = 0; + if (callName == QLatin1String("qmlRegisterType")) + argCount = 4; + else if (callName == QLatin1String("qmlRegisterUncreatableType")) + argCount = 5; + else return false; // must have a single typeid template argument @@ -154,16 +159,21 @@ protected: if (!typeId) return false; - // must have four arguments + // must have four arguments for qmlRegisterType and five for qmlRegisterUncreatableType if (!ast->expression_list || !ast->expression_list->value || !ast->expression_list->next || !ast->expression_list->next->value || !ast->expression_list->next->next || !ast->expression_list->next->next->value || !ast->expression_list->next->next->next - || !ast->expression_list->next->next->next->value - || ast->expression_list->next->next->next->next) + || !ast->expression_list->next->next->next->value) + return false; + if (argCount == 4 && ast->expression_list->next->next->next->next) + return false; + if (argCount == 5 && (!ast->expression_list->next->next->next->next + || !ast->expression_list->next->next->next->next->value + || ast->expression_list->next->next->next->next->next)) return false; - // last argument must be a string literal + // 4th argument must be a string literal const StringLiteral *nameLit = 0; if (StringLiteralAST *nameAst = skipStringCall(ast->expression_list->next->next->next->value)->asStringLiteral()) nameLit = translationUnit()->stringLiteral(nameAst->literal_token); @@ -748,12 +758,17 @@ bool FindExportedCppTypes::maybeExportsTypes(const Document::Ptr &document) if (!document->control()) return false; const QByteArray qmlRegisterTypeToken("qmlRegisterType"); + const QByteArray qmlRegisterUncreatableTypeToken("qmlRegisterUncreatableType"); const QByteArray setContextPropertyToken("setContextProperty"); if (document->control()->findIdentifier( qmlRegisterTypeToken.constData(), qmlRegisterTypeToken.size())) { return true; } if (document->control()->findIdentifier( + qmlRegisterUncreatableTypeToken.constData(), qmlRegisterUncreatableTypeToken.size())) { + return true; + } + if (document->control()->findIdentifier( setContextPropertyToken.constData(), setContextPropertyToken.size())) { return true; } diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index 35f141539a..ea67158e79 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -40,7 +40,7 @@ #include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/mimedatabase.h> #include <coreplugin/messagemanager.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/CppDocument.h> #include <qmljs/qmljscontext.h> #include <qmljs/qmljsbind.h> diff --git a/src/plugins/qmljstools/qmljstools.qbs b/src/plugins/qmljstools/qmljstools.qbs index 4636611129..a62978f0e4 100644 --- a/src/plugins/qmljstools/qmljstools.qbs +++ b/src/plugins/qmljstools/qmljstools.qbs @@ -8,7 +8,7 @@ QtcPlugin { Depends { name: "qt"; submodules: ['gui'] } Depends { name: "Core" } Depends { name: "LanguageUtils" } - Depends { name: "CPlusPlus" } + Depends { name: "CppTools" } Depends { name: "QmlJS" } Depends { name: "ProjectExplorer" } Depends { name: "TextEditor" } @@ -58,7 +58,7 @@ QtcPlugin { ] ProductModule { - Depends { name: "CPlusPlus" } + Depends { name: "CppTools" } Depends { name: "QmlJSDebugClient" } } } diff --git a/src/plugins/qmljstools/qmljstools_dependencies.pri b/src/plugins/qmljstools/qmljstools_dependencies.pri index b9b7d70c88..fe173668db 100644 --- a/src/plugins/qmljstools/qmljstools_dependencies.pri +++ b/src/plugins/qmljstools/qmljstools_dependencies.pri @@ -4,3 +4,4 @@ include($$IDE_SOURCE_TREE/src/libs/qmljs/qmljs.pri) include($$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.pri) include($$IDE_SOURCE_TREE/src/plugins/qtsupport/qtsupport.pri) include($$IDE_SOURCE_TREE/src/plugins/texteditor/texteditor.pri) +include($$IDE_SOURCE_TREE/src/plugins/cpptools/cpptools.pri) diff --git a/src/plugins/qmljstools/qmljstoolsplugin.h b/src/plugins/qmljstools/qmljstoolsplugin.h index f35917fd4d..54b8837a37 100644 --- a/src/plugins/qmljstools/qmljstoolsplugin.h +++ b/src/plugins/qmljstools/qmljstoolsplugin.h @@ -56,6 +56,7 @@ class ModelManager; class QmlJSToolsPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlJSTools.json") public: static QmlJSToolsPlugin *instance() { return m_instance; } diff --git a/src/plugins/qmlprofiler/abstractqmlprofilerrunner.h b/src/plugins/qmlprofiler/abstractqmlprofilerrunner.h index ace4c28a51..78fc5cd9df 100644 --- a/src/plugins/qmlprofiler/abstractqmlprofilerrunner.h +++ b/src/plugins/qmlprofiler/abstractqmlprofilerrunner.h @@ -49,7 +49,7 @@ public: virtual void start() = 0; virtual void stop() = 0; - virtual int debugPort() const = 0; + virtual quint16 debugPort() const = 0; signals: void started(); diff --git a/src/plugins/qmlprofiler/codaqmlprofilerrunner.cpp b/src/plugins/qmlprofiler/codaqmlprofilerrunner.cpp index 3a1ddd1f66..d78c889a1c 100644 --- a/src/plugins/qmlprofiler/codaqmlprofilerrunner.cpp +++ b/src/plugins/qmlprofiler/codaqmlprofilerrunner.cpp @@ -80,7 +80,7 @@ void CodaQmlProfilerRunner::appendMessage(ProjectExplorer::RunControl *, const Q emit appendMessage(message, format); } -int QmlProfiler::Internal::CodaQmlProfilerRunner::debugPort() const +quint16 QmlProfiler::Internal::CodaQmlProfilerRunner::debugPort() const { return m_configuration->debuggerAspect()->qmlDebugServerPort(); } diff --git a/src/plugins/qmlprofiler/codaqmlprofilerrunner.h b/src/plugins/qmlprofiler/codaqmlprofilerrunner.h index 3bc86fb634..aca03e9174 100644 --- a/src/plugins/qmlprofiler/codaqmlprofilerrunner.h +++ b/src/plugins/qmlprofiler/codaqmlprofilerrunner.h @@ -55,7 +55,7 @@ public: // AbstractQmlProfilerRunner virtual void start(); virtual void stop(); - virtual int debugPort() const; + virtual quint16 debugPort() const; private slots: void appendMessage(ProjectExplorer::RunControl *, const QString &message, diff --git a/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp index 1d708dda59..e7b11f5cf9 100644 --- a/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp +++ b/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp @@ -85,7 +85,7 @@ void LocalQmlProfilerRunner::stop() } } -int LocalQmlProfilerRunner::debugPort() const +quint16 LocalQmlProfilerRunner::debugPort() const { return m_configuration.port; } diff --git a/src/plugins/qmlprofiler/localqmlprofilerrunner.h b/src/plugins/qmlprofiler/localqmlprofilerrunner.h index c71b234f7c..c49c38c283 100644 --- a/src/plugins/qmlprofiler/localqmlprofilerrunner.h +++ b/src/plugins/qmlprofiler/localqmlprofilerrunner.h @@ -59,7 +59,7 @@ public: // AbstractQmlProfilerRunner virtual void start(); virtual void stop(); - virtual int debugPort() const; + virtual quint16 debugPort() const; bool hasExecutable() const { return !m_configuration.executable.isEmpty(); } diff --git a/src/plugins/qmlprofiler/qml/Label.qml b/src/plugins/qmlprofiler/qml/Label.qml index 0d89c057ab..21e322d5be 100644 --- a/src/plugins/qmlprofiler/qml/Label.qml +++ b/src/plugins/qmlprofiler/qml/Label.qml @@ -60,17 +60,19 @@ Item { function updateHeight() { height = root.singleRowHeight * (1 + - (expanded ? qmlEventList.uniqueEventsOfType(typeIndex) : qmlEventList.maxNestingForType(typeIndex))); + (expanded ? qmlProfilerDataModel.uniqueEventsOfType(typeIndex) : + qmlProfilerDataModel.maxNestingForType(typeIndex))); } function getDescriptions() { var desc=[]; var ids=[]; var extdesc=[]; - for (var i=0; i<qmlEventList.uniqueEventsOfType(typeIndex); i++) { - desc[i] = qmlEventList.eventTextForType(typeIndex, i); - ids[i] = qmlEventList.eventIdForType(typeIndex, i); - extdesc[i] = qmlEventList.eventDisplayNameForType(typeIndex, i) + " : " + desc[i]; + for (var i=0; i<qmlProfilerDataModel.uniqueEventsOfType(typeIndex); i++) { + desc[i] = qmlProfilerDataModel.eventTextForType(typeIndex, i); + ids[i] = qmlProfilerDataModel.eventIdForType(typeIndex, i); + extdesc[i] = qmlProfilerDataModel.eventDisplayNameForType(typeIndex, i) + + " : " + desc[i]; } descriptions = desc; eventIds = ids; @@ -79,18 +81,18 @@ Item { } Connections { - target: qmlEventList + target: qmlProfilerDataModel onReloadDetailLabels: getDescriptions(); onStateChanged: { // Empty - if (qmlEventList.getCurrentStateFromQml() == 0) { + if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) { descriptions = []; eventIds = []; extdescriptions = []; updateHeight(); } else // Done - if (qmlEventList.getCurrentStateFromQml() == 3) { + if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) { getDescriptions(); } } diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index ae2b9a8122..b810a78530 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -51,11 +51,16 @@ Rectangle { property alias selectionLocked : view.selectionLocked signal updateLockButton property alias selectedItem: view.selectedItem - signal selectedEventIdChanged(int eventId) + signal selectedEventChanged(int eventId) property bool lockItemSelection : false - property variant names: [ qsTr("Painting"), qsTr("Compiling"), qsTr("Creating"), qsTr("Binding"), qsTr("Handling Signal")] - property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ] + property variant names: [ qsTr("Painting"), + qsTr("Compiling"), + qsTr("Creating"), + qsTr("Binding"), + qsTr("Handling Signal")] + property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC", + "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ] property variant mainviewTimePerPixel : 0 @@ -64,9 +69,6 @@ Rectangle { property int lineNumber: -1 property int columnNumber: 0 - property real elapsedTime - signal updateTimer - signal updateRangeButton property bool selectionRangeMode: false @@ -77,7 +79,11 @@ Rectangle { signal changeToolTip(string text) signal updateVerticalScroll(int newPosition) - property bool applicationDied : false + property bool recordingEnabled: false + property bool appKilled : false + + property date recordingStartDate + property real elapsedTime // ***** connections with external objects Connections { @@ -92,7 +98,8 @@ Rectangle { backgroundMarks.updateMarks(startTime, endTime); view.updateFlickRange(startTime, endTime); if (duration > 0) { - var candidateWidth = qmlEventList.traceDuration() * flick.width / duration; + var candidateWidth = qmlProfilerDataModel.traceDuration() * + flick.width / duration; if (flick.contentWidth !== candidateWidth) flick.contentWidth = candidateWidth; } @@ -101,20 +108,21 @@ Rectangle { } Connections { - target: qmlEventList + target: qmlProfilerDataModel onCountChanged: { - eventCount = qmlEventList.count(); + eventCount = qmlProfilerDataModel.count(); if (eventCount === 0) root.clearAll(); if (eventCount > 1) { root.progress = Math.min(1.0, - (qmlEventList.lastTimeMark() - qmlEventList.traceStartTime()) / root.elapsedTime * 1e-9 ); + (qmlProfilerDataModel.lastTimeMark() - + qmlProfilerDataModel.traceStartTime()) / root.elapsedTime * 1e-9 ); } else { root.progress = 0; } } onStateChanged: { - switch (qmlEventList.getCurrentStateFromQml()) { + switch (qmlProfilerDataModel.getCurrentStateFromQml()) { case 0: { root.clearAll(); break; @@ -133,7 +141,9 @@ Rectangle { dataAvailable = true; view.visible = true; view.requestPaint(); - zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceStartTime() + qmlEventList.traceDuration()/10); + zoomControl.setRange(qmlProfilerDataModel.traceStartTime(), + qmlProfilerDataModel.traceStartTime() + + qmlProfilerDataModel.traceDuration()/10); break; } } @@ -151,7 +161,7 @@ Rectangle { function clearData() { view.clearData(); dataAvailable = false; - applicationDied = false; + appKilled = false; eventCount = 0; hideRangeDetails(); selectionRangeMode = false; @@ -166,8 +176,6 @@ Rectangle { function clearAll() { clearDisplay(); - root.elapsedTime = 0; - root.updateTimer(); } function nextEvent() { @@ -180,9 +188,10 @@ Rectangle { function updateWindowLength(absoluteFactor) { var windowLength = view.endTime - view.startTime; - if (qmlEventList.traceEndTime() <= qmlEventList.traceStartTime() || windowLength <= 0) + if (qmlProfilerDataModel.traceEndTime() <= qmlProfilerDataModel.traceStartTime() || + windowLength <= 0) return; - var currentFactor = windowLength / qmlEventList.traceDuration(); + var currentFactor = windowLength / qmlProfilerDataModel.traceDuration(); updateZoom(absoluteFactor / currentFactor); } @@ -193,8 +202,8 @@ Rectangle { windowLength = min_length; var newWindowLength = windowLength * relativeFactor; - if (newWindowLength > qmlEventList.traceDuration()) { - newWindowLength = qmlEventList.traceDuration(); + if (newWindowLength > qmlProfilerDataModel.traceDuration()) { + newWindowLength = qmlProfilerDataModel.traceDuration(); relativeFactor = newWindowLength / windowLength; } if (newWindowLength < min_length) { @@ -205,7 +214,7 @@ Rectangle { var fixedPoint = (view.startTime + view.endTime) / 2; if (view.selectedItem !== -1) { // center on selected item if it's inside the current screen - var newFixedPoint = qmlEventList.getStartTime(view.selectedItem); + var newFixedPoint = qmlProfilerDataModel.getStartTime(view.selectedItem); if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime) fixedPoint = newFixedPoint; } @@ -222,8 +231,8 @@ Rectangle { windowLength = min_length; var newWindowLength = windowLength * relativeFactor; - if (newWindowLength > qmlEventList.traceDuration()) { - newWindowLength = qmlEventList.traceDuration(); + if (newWindowLength > qmlProfilerDataModel.traceDuration()) { + newWindowLength = qmlProfilerDataModel.traceDuration(); relativeFactor = newWindowLength / windowLength; } if (newWindowLength < min_length) { @@ -241,8 +250,8 @@ Rectangle { var newStart = Math.floor(centerPoint - windowLength/2); if (newStart < 0) newStart = 0; - if (newStart + windowLength > qmlEventList.traceEndTime()) - newStart = qmlEventList.traceEndTime() - windowLength; + if (newStart + windowLength > qmlProfilerDataModel.traceEndTime()) + newStart = qmlProfilerDataModel.traceEndTime() - windowLength; zoomControl.setRange(newStart, newStart + windowLength); } @@ -252,17 +261,16 @@ Rectangle { return; // if item is outside of the view, jump back to its position - if (qmlEventList.getEndTime(itemIndex) < view.startTime || qmlEventList.getStartTime(itemIndex) > view.endTime) { - recenter((qmlEventList.getStartTime(itemIndex) + qmlEventList.getEndTime(itemIndex)) / 2); + if (qmlProfilerDataModel.getEndTime(itemIndex) < view.startTime || + qmlProfilerDataModel.getStartTime(itemIndex) > view.endTime) { + recenter((qmlProfilerDataModel.getStartTime(itemIndex) + + qmlProfilerDataModel.getEndTime(itemIndex)) / 2); } } - function globalZoom() { - zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceEndTime()); - } - function wheelZoom(wheelCenter, wheelDelta) { - if (qmlEventList.traceEndTime() > qmlEventList.traceStartTime() && wheelDelta !== 0) { + if (qmlProfilerDataModel.traceEndTime() > qmlProfilerDataModel.traceStartTime() && + wheelDelta !== 0) { if (wheelDelta>0) updateZoomCentered(wheelCenter, 1/1.2); else @@ -311,34 +319,22 @@ Rectangle { onSelectedItemChanged: { if (selectedItem != -1 && !lockItemSelection) { lockItemSelection = true; - selectedEventIdChanged( qmlEventList.getEventId(selectedItem) ); + selectedEventChanged( qmlProfilerDataModel.getEventId(selectedItem) ); lockItemSelection = false; } } - // ***** child items - Timer { - id: elapsedTimer - property date startDate - property bool reset: true - running: connection ? (connection.recording && connection.enabled) : false - repeat: true - onRunningChanged: { - if (running) reset = true; - } - interval: 100 - triggeredOnStart: true - onTriggered: { - if (reset) { - startDate = new Date(); - reset = false; - } - var time = (new Date() - startDate)/1000; - root.elapsedTime = time.toFixed(1); - root.updateTimer(); + onRecordingEnabledChanged: { + if (recordingEnabled) { + recordingStartDate = new Date(); + elapsedTime = 0; + } else { + elapsedTime = (new Date() - recordingStartDate)/1000.0; } } + + // ***** child items TimeMarks { id: backgroundMarks y: labels.y @@ -380,7 +376,8 @@ Rectangle { selectionRange.isDragging = false; } onDoubleClicked: { - zoomControl.setRange(selectionRange.startTime, selectionRange.startTime + selectionRange.duration); + zoomControl.setRange(selectionRange.startTime, + selectionRange.startTime + selectionRange.duration); root.selectionRangeMode = false; root.updateRangeButton(); } @@ -394,10 +391,10 @@ Rectangle { z: 2 } - TimelineView { + TimelineRenderer { id: view - eventList: qmlEventList + profilerDataModel: qmlProfilerDataModel x: flick.contentX width: flick.width @@ -405,9 +402,13 @@ Rectangle { property variant startX: 0 onStartXChanged: { - var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) + qmlEventList.traceStartTime(); + var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) + + qmlProfilerDataModel.traceStartTime(); if (Math.abs(newStartTime - startTime) > 1) { - var newEndTime = Math.round((startX+flick.width)* (endTime - startTime) / flick.width) + qmlEventList.traceStartTime(); + var newEndTime = Math.round((startX+flick.width) * + (endTime - startTime) / + flick.width) + + qmlProfilerDataModel.traceStartTime(); zoomControl.setRange(newStartTime, newEndTime); } @@ -419,7 +420,8 @@ Rectangle { if (start !== startTime || end !== endTime) { startTime = start; endTime = end; - var newStartX = (startTime - qmlEventList.traceStartTime()) * flick.width / (endTime-startTime); + var newStartX = (startTime - qmlProfilerDataModel.traceStartTime()) * + flick.width / (endTime-startTime); if (Math.abs(newStartX - startX) >= 1) startX = newStartX; } @@ -428,24 +430,25 @@ Rectangle { onSelectedItemChanged: { if (selectedItem !== -1) { // display details - rangeDetails.duration = qmlEventList.getDuration(selectedItem)/1000.0; - rangeDetails.label = qmlEventList.getDetails(selectedItem); - rangeDetails.file = qmlEventList.getFilename(selectedItem); - rangeDetails.line = qmlEventList.getLine(selectedItem); - rangeDetails.column = qmlEventList.getColumn(selectedItem); - rangeDetails.type = root.names[qmlEventList.getType(selectedItem)]; - rangeDetails.isBindingLoop = qmlEventList.getBindingLoopDest(selectedItem)!==-1; + rangeDetails.duration = qmlProfilerDataModel.getDuration(selectedItem)/1000.0; + rangeDetails.label = qmlProfilerDataModel.getDetails(selectedItem); + rangeDetails.file = qmlProfilerDataModel.getFilename(selectedItem); + rangeDetails.line = qmlProfilerDataModel.getLine(selectedItem); + rangeDetails.column = qmlProfilerDataModel.getColumn(selectedItem); + rangeDetails.type = root.names[qmlProfilerDataModel.getType(selectedItem)]; + rangeDetails.isBindingLoop = qmlProfilerDataModel.getBindingLoopDest(selectedItem)!==-1; rangeDetails.visible = true; // center view (horizontally) var windowLength = view.endTime - view.startTime; - var eventStartTime = qmlEventList.getStartTime(selectedItem); - var eventEndTime = eventStartTime + qmlEventList.getDuration(selectedItem); + var eventStartTime = qmlProfilerDataModel.getStartTime(selectedItem); + var eventEndTime = eventStartTime + + qmlProfilerDataModel.getDuration(selectedItem); if (eventEndTime < view.startTime || eventStartTime > view.endTime) { var center = (eventStartTime + eventEndTime)/2; - var from = Math.min(qmlEventList.traceEndTime()-windowLength, + var from = Math.min(qmlProfilerDataModel.traceEndTime()-windowLength, Math.max(0, Math.floor(center - windowLength/2))); zoomControl.setRange(from, from + windowLength); @@ -456,8 +459,10 @@ Rectangle { if (itemY < root.scrollY) { root.updateVerticalScroll(itemY); } else - if (itemY + root.singleRowHeight > root.scrollY + root.candidateHeight) { - root.updateVerticalScroll(itemY + root.singleRowHeight - root.candidateHeight); + if (itemY + root.singleRowHeight > + root.scrollY + root.candidateHeight) { + root.updateVerticalScroll(itemY + root.singleRowHeight - + root.candidateHeight); } } else { root.hideRangeDetails(); @@ -466,14 +471,18 @@ Rectangle { onItemPressed: { if (pressedItem !== -1) { - root.gotoSourceLocation(qmlEventList.getFilename(pressedItem), qmlEventList.getLine(pressedItem), qmlEventList.getColumn(pressedItem)); + root.gotoSourceLocation(qmlProfilerDataModel.getFilename(pressedItem), + qmlProfilerDataModel.getLine(pressedItem), + qmlProfilerDataModel.getColumn(pressedItem)); } } // hack to pass mouse events to the other mousearea if enabled - startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x : -flick.contentX + startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x : + -flick.contentX endDragArea: selectionRangeDrag.enabled ? - selectionRangeDrag.x + selectionRangeDrag.width : -flick.contentX-1 + selectionRangeDrag.x + selectionRangeDrag.width : + -flick.contentX-1 } MouseArea { id: selectionRangeControl diff --git a/src/plugins/qmlprofiler/qml/Overview.js b/src/plugins/qmlprofiler/qml/Overview.js index 4fe625a7fd..821f344653 100644 --- a/src/plugins/qmlprofiler/qml/Overview.js +++ b/src/plugins/qmlprofiler/qml/Overview.js @@ -32,7 +32,7 @@ .pragma library -var qmlEventList = 0; +var qmlProfilerDataModel = 0; //draw background of the graph function drawGraph(canvas, ctxt, region) @@ -44,7 +44,7 @@ function drawGraph(canvas, ctxt, region) //draw the actual data to be graphed function drawData(canvas, ctxt, region) { - if ((!qmlEventList) || qmlEventList.count() == 0) + if ((!qmlProfilerDataModel) || qmlProfilerDataModel.count() == 0) return; var typeCount = 5; @@ -53,17 +53,18 @@ function drawData(canvas, ctxt, region) var height = canvas.height - bump; var blockHeight = height / typeCount; - var spacing = width / qmlEventList.traceDuration(); + var spacing = width / qmlProfilerDataModel.traceDuration(); var highest = [0,0,0,0,0]; // note: change if typeCount changes - for (var ii = 0; ii < qmlEventList.count(); ++ii) { + for (var ii = 0; ii < qmlProfilerDataModel.count(); ++ii) { - var xx = (qmlEventList.getStartTime(ii) - qmlEventList.traceStartTime()) * spacing; + var xx = (qmlProfilerDataModel.getStartTime(ii) - + qmlProfilerDataModel.traceStartTime()) * spacing; if (xx > region.x + region.width) continue; - var eventWidth = qmlEventList.getDuration(ii) * spacing; + var eventWidth = qmlProfilerDataModel.getDuration(ii) * spacing; if (xx + eventWidth < region.x) continue; @@ -71,24 +72,26 @@ function drawData(canvas, ctxt, region) eventWidth = 1; xx = Math.round(xx); - var ty = qmlEventList.getType(ii); + var ty = qmlProfilerDataModel.getType(ii); if (xx + eventWidth > highest[ty]) { // special: animations - if (ty === 0 && qmlEventList.getAnimationCount(ii) >= 0) { - var vertScale = qmlEventList.getMaximumAnimationCount() - qmlEventList.getMinimumAnimationCount(); + if (ty === 0 && qmlProfilerDataModel.getAnimationCount(ii) >= 0) { + var vertScale = qmlProfilerDataModel.getMaximumAnimationCount() - + qmlProfilerDataModel.getMinimumAnimationCount(); if (vertScale < 1) vertScale = 1; - var fraction = (qmlEventList.getAnimationCount(ii) - qmlEventList.getMinimumAnimationCount()) / vertScale; + var fraction = (qmlProfilerDataModel.getAnimationCount(ii) - + qmlProfilerDataModel.getMinimumAnimationCount()) / vertScale; var eventHeight = blockHeight * (fraction * 0.85 + 0.15); var yy = bump + ty*blockHeight + blockHeight - eventHeight; - var fpsFraction = qmlEventList.getFramerate(ii) / 60.0; + var fpsFraction = qmlProfilerDataModel.getFramerate(ii) / 60.0; if (fpsFraction > 1.0) fpsFraction = 1.0; ctxt.fillStyle = "hsl("+(fpsFraction*0.27+0.028)+",0.3,0.65)"; ctxt.fillRect(xx, yy, eventWidth, eventHeight); } else { - var hue = ( qmlEventList.getEventId(ii) * 25 ) % 360; + var hue = ( qmlProfilerDataModel.getEventId(ii) * 25 ) % 360; ctxt.fillStyle = "hsl("+(hue/360.0+0.001)+",0.3,0.65)"; ctxt.fillRect(xx, bump + ty*blockHeight, eventWidth, blockHeight); } @@ -100,12 +103,13 @@ function drawData(canvas, ctxt, region) ctxt.strokeStyle = "orange"; ctxt.lineWidth = 2; var radius = 1; - for (var ii = 0; ii < qmlEventList.count(); ++ii) { - if (qmlEventList.getBindingLoopDest(ii) >= 0) { - var xcenter = Math.round(qmlEventList.getStartTime(ii) + - qmlEventList.getDuration(ii) - - qmlEventList.traceStartTime()) * spacing; - var ycenter = Math.round(bump + qmlEventList.getType(ii) * blockHeight + blockHeight/2); + for (var ii = 0; ii < qmlProfilerDataModel.count(); ++ii) { + if (qmlProfilerDataModel.getBindingLoopDest(ii) >= 0) { + var xcenter = Math.round(qmlProfilerDataModel.getStartTime(ii) + + qmlProfilerDataModel.getDuration(ii) - + qmlProfilerDataModel.traceStartTime()) * spacing; + var ycenter = Math.round(bump + qmlProfilerDataModel.getType(ii) * + blockHeight + blockHeight/2); ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true); ctxt.stroke(); } @@ -114,19 +118,20 @@ function drawData(canvas, ctxt, region) function drawTimeBar(canvas, ctxt, region) { - if (!qmlEventList) + if (!qmlProfilerDataModel) return; var width = canvas.width; var height = 10; - var startTime = qmlEventList.traceStartTime(); - var endTime = qmlEventList.traceEndTime(); + var startTime = qmlProfilerDataModel.traceStartTime(); + var endTime = qmlProfilerDataModel.traceEndTime(); - var totalTime = qmlEventList.traceDuration(); + var totalTime = qmlProfilerDataModel.traceDuration(); var spacing = width / totalTime; var initialBlockLength = 120; - var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) ); + var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * + initialBlockLength ) / Math.LN2 ) ); var pixelsPerBlock = timePerBlock * spacing; var pixelsPerSection = pixelsPerBlock / 5; var blockCount = width / pixelsPerBlock; diff --git a/src/plugins/qmlprofiler/qml/Overview.qml b/src/plugins/qmlprofiler/qml/Overview.qml index 5526502169..c82277bc26 100644 --- a/src/plugins/qmlprofiler/qml/Overview.qml +++ b/src/plugins/qmlprofiler/qml/Overview.qml @@ -51,8 +51,8 @@ Canvas2D { } function updateRange() { - var newStartTime = Math.round(rangeMover.x * qmlEventList.traceDuration() / width) + qmlEventList.traceStartTime(); - var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlEventList.traceDuration() / width) + qmlEventList.traceStartTime(); + var newStartTime = Math.round(rangeMover.x * qmlProfilerDataModel.traceDuration() / width) + qmlProfilerDataModel.traceStartTime(); + var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlProfilerDataModel.traceDuration() / width) + qmlProfilerDataModel.traceStartTime(); if (startTime !== newStartTime || endTime !== newEndTime) { zoomControl.setRange(newStartTime, newEndTime); } @@ -62,13 +62,13 @@ Canvas2D { Connections { target: zoomControl onRangeChanged: { - if (qmlEventList) { + if (qmlProfilerDataModel) { startTime = zoomControl.startTime(); endTime = zoomControl.endTime(); - var newRangeX = (startTime - qmlEventList.traceStartTime()) * width / qmlEventList.traceDuration(); + var newRangeX = (startTime - qmlProfilerDataModel.traceStartTime()) * width / qmlProfilerDataModel.traceDuration(); if (rangeMover.x !== newRangeX) rangeMover.x = newRangeX; - var newWidth = (endTime-startTime) * width / qmlEventList.traceDuration(); + var newWidth = (endTime-startTime) * width / qmlProfilerDataModel.traceDuration(); if (rangeMover.width !== newWidth) rangeMover.width = newWidth; } @@ -76,10 +76,10 @@ Canvas2D { } Connections { - target: qmlEventList + target: qmlProfilerDataModel onStateChanged: { // State is "done" - if (qmlEventList.getCurrentStateFromQml() == 3) { + if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) { dataAvailable = true; requestRedraw(); } @@ -88,7 +88,7 @@ Canvas2D { // ***** slots onDrawRegion: { - Plotter.qmlEventList = qmlEventList; + Plotter.qmlProfilerDataModel = qmlProfilerDataModel; if (dataAvailable) { Plotter.plot(canvas, ctxt, region); } else { diff --git a/src/plugins/qmlprofiler/qml/SelectionRange.qml b/src/plugins/qmlprofiler/qml/SelectionRange.qml index 616fd89598..b8b6507258 100644 --- a/src/plugins/qmlprofiler/qml/SelectionRange.qml +++ b/src/plugins/qmlprofiler/qml/SelectionRange.qml @@ -50,7 +50,7 @@ Rectangle { property string endTimeString: detailedPrintTime(startTime+duration) property string durationString: detailedPrintTime(duration) - property variant startTime: x * selectionRange.viewTimePerPixel + qmlEventList.traceStartTime() + property variant startTime: x * selectionRange.viewTimePerPixel + qmlProfilerDataModel.traceStartTime() property variant duration: width * selectionRange.viewTimePerPixel property variant viewTimePerPixel: 1 property variant creationState : 0 diff --git a/src/plugins/qmlprofiler/qml/StatusDisplay.qml b/src/plugins/qmlprofiler/qml/StatusDisplay.qml index d4507a37d6..8919d07b13 100644 --- a/src/plugins/qmlprofiler/qml/StatusDisplay.qml +++ b/src/plugins/qmlprofiler/qml/StatusDisplay.qml @@ -69,7 +69,7 @@ Item { states: [ // no data available State { - when: (root.eventCount == 0) && !elapsedTimer.running + when: (root.eventCount == 0) && !root.recordingEnabled PropertyChanges { target: statusDisplay visible: true @@ -85,7 +85,7 @@ Item { }, // running app State { - when: elapsedTimer.running + when: root.recordingEnabled PropertyChanges { target: statusDisplay visible: true @@ -99,7 +99,7 @@ Item { // loading data State { name: "loading" - when: (!root.dataAvailable) && (root.eventCount > 0) && !root.applicationDied + when: !root.dataAvailable && (root.eventCount > 0) && !root.appKilled PropertyChanges { target: statusDisplay visible: true @@ -118,7 +118,7 @@ Item { // application died State { name: "deadApp" - when: (!root.dataAvailable) && (root.eventCount > 0) && root.applicationDied + when: !root.dataAvailable && (root.eventCount > 0) && root.appKilled PropertyChanges { target: statusDisplay visible: true diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml index 2cb176c0a1..d38e4de741 100644 --- a/src/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml @@ -91,15 +91,15 @@ Canvas2D { // gray off out-of-bounds areas var rectWidth; - if (startTime < qmlEventList.traceStartTime()) { + if (startTime < qmlProfilerDataModel.traceStartTime()) { ctxt.fillStyle = "rgba(127,127,127,0.2)"; - rectWidth = (qmlEventList.traceStartTime() - startTime) * spacing; + rectWidth = (qmlProfilerDataModel.traceStartTime() - startTime) * spacing; ctxt.fillRect(0, 0, rectWidth, height); } - if (endTime > qmlEventList.traceEndTime()) { + if (endTime > qmlProfilerDataModel.traceEndTime()) { ctxt.fillStyle = "rgba(127,127,127,0.2)"; - var rectX = (qmlEventList.traceEndTime() - startTime) * spacing; - rectWidth = (endTime - qmlEventList.traceEndTime()) * spacing; + var rectX = (qmlProfilerDataModel.traceEndTime() - startTime) * spacing; + rectWidth = (endTime - qmlProfilerDataModel.traceEndTime()) * spacing; ctxt.fillRect(rectX, 0, rectWidth, height); } } @@ -126,8 +126,8 @@ Canvas2D { var cumulatedHeight = 0; for (var i=0; i<labels.rowCount; i++) { cumulatedHeight += root.singleRowHeight + (labels.rowExpanded[i] ? - qmlEventList.uniqueEventsOfType(i) * root.singleRowHeight : - qmlEventList.maxNestingForType(i) * root.singleRowHeight); + qmlProfilerDataModel.uniqueEventsOfType(i) * root.singleRowHeight : + qmlProfilerDataModel.maxNestingForType(i) * root.singleRowHeight); ctxt.strokeStyle = "#B0B0B0"; ctxt.beginPath(); diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro index 2f41d50db1..4dc919bef2 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.pro +++ b/src/plugins/qmlprofiler/qmlprofiler.pro @@ -3,7 +3,12 @@ TARGET = QmlProfiler DEFINES += PROFILER_LIBRARY -QT += network script declarative +QT += network script +greaterThan(QT_MAJOR_VERSION, 4) { + QT += quick1 +} else { + QT += declarative +} include(../../qtcreatorplugin.pri) include(../../plugins/coreplugin/coreplugin.pri) @@ -19,14 +24,19 @@ SOURCES += \ qmlprofilerplugin.cpp \ qmlprofilertool.cpp \ qmlprofilerengine.cpp \ - tracewindow.cpp \ - timelineview.cpp \ qmlprofilerattachdialog.cpp \ localqmlprofilerrunner.cpp \ codaqmlprofilerrunner.cpp \ remotelinuxqmlprofilerrunner.cpp \ qmlprofilereventview.cpp \ - qmlprofilerdetailsrewriter.cpp + qmlprofilerdetailsrewriter.cpp \ + qmlprofilertraceview.cpp \ + timelinerenderer.cpp \ + qmlprofilerstatemanager.cpp \ + qv8profilerdatamodel.cpp \ + qmlprofilerdatamodel.cpp \ + qmlprofilerclientmanager.cpp \ + qmlprofilerviewmanager.cpp HEADERS += \ qmlprofilerconstants.h \ @@ -34,22 +44,26 @@ HEADERS += \ qmlprofilerplugin.h \ qmlprofilertool.h \ qmlprofilerengine.h \ - tracewindow.h \ - timelineview.h \ qmlprofilerattachdialog.h \ abstractqmlprofilerrunner.h \ localqmlprofilerrunner.h \ codaqmlprofilerrunner.h \ remotelinuxqmlprofilerrunner.h \ qmlprofilereventview.h \ - qmlprofilerdetailsrewriter.h + qmlprofilerdetailsrewriter.h \ + qmlprofilertraceview.h \ + timelinerenderer.h \ + qmlprofilerstatemanager.h \ + qv8profilerdatamodel.h \ + qmlprofilerdatamodel.h \ + qmlprofilerclientmanager.h \ + qmlprofilerviewmanager.h RESOURCES += \ qml/qmlprofiler.qrc OTHER_FILES += \ qml/Detail.qml \ - qml/Elapsed.qml \ qml/Label.qml \ qml/MainView.qml \ qml/RangeDetails.qml \ @@ -59,8 +73,7 @@ OTHER_FILES += \ qml/StatusDisplay.qml \ qml/SelectionRange.qml \ qml/SelectionRangeDetails.qml \ - qml/Overview.qml \ - qml/Overview.js + qml/Overview.qml FORMS += \ qmlprofilerattachdialog.ui diff --git a/src/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofiler/qmlprofiler.qbs index 13cbca838c..f4af4e4366 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.qbs +++ b/src/plugins/qmlprofiler/qmlprofiler.qbs @@ -35,27 +35,37 @@ QtcPlugin { "codaqmlprofilerrunner.h", "localqmlprofilerrunner.cpp", "localqmlprofilerrunner.h", - "qmlprofiler_global.h", "qmlprofilerattachdialog.cpp", "qmlprofilerattachdialog.h", "qmlprofilerattachdialog.ui", + "qmlprofilerclientmanager.cpp", + "qmlprofilerclientmanager.h", "qmlprofilerconstants.h", + "qmlprofilerdatamodel.cpp", + "qmlprofilerdatamodel.h", "qmlprofilerdetailsrewriter.cpp", "qmlprofilerdetailsrewriter.h", "qmlprofilerengine.cpp", "qmlprofilerengine.h", "qmlprofilereventview.cpp", "qmlprofilereventview.h", + "qmlprofiler_global.h", "qmlprofilerplugin.cpp", "qmlprofilerplugin.h", + "qmlprofilerstatemanager.cpp", + "qmlprofilerstatemanager.h", "qmlprofilertool.cpp", "qmlprofilertool.h", + "qmlprofilertraceview.cpp", + "qmlprofilertraceview.h", + "qmlprofilerviewmanager.cpp", + "qmlprofilerviewmanager.h", + "qv8profilerdatamodel.cpp", + "qv8profilerdatamodel.h", "remotelinuxqmlprofilerrunner.cpp", "remotelinuxqmlprofilerrunner.h", - "timelineview.cpp", - "timelineview.h", - "tracewindow.cpp", - "tracewindow.h", + "timelinerenderer.cpp", + "timelinerenderer.h", "canvas/qdeclarativecanvas.cpp", "canvas/qdeclarativecanvas_p.h", "canvas/qdeclarativecanvastimer.cpp", @@ -75,7 +85,8 @@ QtcPlugin { "qml/StatusDisplay.qml", "qml/TimeDisplay.qml", "qml/TimeMarks.qml", - "qml/qmlprofiler.qrc" + "qml/qmlprofiler.qrc", + "qml/Overview.js" ] } diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp new file mode 100644 index 0000000000..a9002aa85b --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -0,0 +1,433 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "qmlprofilerclientmanager.h" +#include "qmlprofilertool.h" +#include "qmlprofilerplugin.h" + +#include <qmljsdebugclient/qdeclarativedebugclient.h> +#include <qmljsdebugclient/qmlprofilertraceclient.h> +#include <qmljsdebugclient/qv8profilerclient.h> + +#include <utils/qtcassert.h> +#include <QWeakPointer> +#include <QTimer> +#include <QMessageBox> + +using namespace QmlJsDebugClient; +using namespace Core; + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerClientManager::QmlProfilerClientManagerPrivate { +public: + QmlProfilerClientManagerPrivate(QmlProfilerClientManager *qq) { Q_UNUSED(qq); } + + QmlProfilerStateManager* profilerState; + + QDeclarativeDebugConnection *connection; + QWeakPointer<QmlProfilerTraceClient> qmlclientplugin; + QWeakPointer<QV8ProfilerClient> v8clientplugin; + + QTimer connectionTimer; + int connectionAttempts; + + enum ConnectMode { + TcpConnection, OstConnection + }; + ConnectMode connectMode; + QString tcpHost; + quint64 tcpPort; + QString ostDevice; + QString sysroot; + + bool v8DataReady; + bool qmlDataReady; +}; + +QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) : + QObject(parent), d(new QmlProfilerClientManagerPrivate(this)) +{ + setObjectName("QML Profiler Connections"); + + d->profilerState = 0; + + d->connection = 0; + d->connectionAttempts = 0; + d->v8DataReady = false; + d->qmlDataReady = false; + + d->connectionTimer.setInterval(200); + connect(&d->connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect())); +} + +QmlProfilerClientManager::~QmlProfilerClientManager() +{ + disconnectClientSignals(); + delete d->connection; + delete d->qmlclientplugin.data(); + delete d->v8clientplugin.data(); + + delete d; +} +//////////////////////////////////////////////////////////////// +// Interface +void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port) +{ + d->connectMode = QmlProfilerClientManagerPrivate::TcpConnection; + d->tcpHost = host; + d->tcpPort = port; +} + +void QmlProfilerClientManager::setOstConnection(QString ostDevice) +{ + d->connectMode = QmlProfilerClientManagerPrivate::OstConnection; + d->ostDevice = ostDevice; +} + +void QmlProfilerClientManager::clearBufferedData() +{ + if (d->qmlclientplugin) + d->qmlclientplugin.data()->clearData(); + if (d->v8clientplugin) + d->v8clientplugin.data()->clearData(); +} + +void QmlProfilerClientManager::discardPendingData() +{ + if (d->connection) + d->connection->flush(); + clearBufferedData(); +} + +//////////////////////////////////////////////////////////////// +// Internal +void QmlProfilerClientManager::connectClient(quint16 port) +{ + if (d->connection) + delete d->connection; + d->connection = new QDeclarativeDebugConnection; + enableServices(); + connect(d->connection, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + this, SLOT(connectionStateChanged())); + d->connectionTimer.start(); + d->tcpPort = port; +} + +void QmlProfilerClientManager::enableServices() +{ + QTC_ASSERT(d->profilerState, return); + + disconnectClientSignals(); + d->profilerState->setServerRecording(false); // false by default (will be set to true when connected) + delete d->qmlclientplugin.data(); + d->qmlclientplugin = new QmlProfilerTraceClient(d->connection); + delete d->v8clientplugin.data(); + d->v8clientplugin = new QV8ProfilerClient(d->connection); + connectClientSignals(); +} + +void QmlProfilerClientManager::connectClientSignals() +{ + QTC_ASSERT(d->profilerState, return); + if (d->qmlclientplugin) { + connect(d->qmlclientplugin.data(), SIGNAL(complete()), + this, SLOT(qmlComplete())); + connect(d->qmlclientplugin.data(), + SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), + this, + SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation))); + connect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), + this, SIGNAL(traceFinished(qint64))); + connect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), + this, SIGNAL(traceStarted(qint64))); + connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), + this, SIGNAL(addFrameEvent(qint64,int,int))); + connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), + d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); + // fixme: this should be unified for both clients + connect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), + d->profilerState, SLOT(setServerRecording(bool))); + } + if (d->v8clientplugin) { + connect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); + connect(d->v8clientplugin.data(), + SIGNAL(v8range(int,QString,QString,int,double,double)), + this, + SIGNAL(addV8Event(int,QString,QString,int,double,double))); + connect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), + d->v8clientplugin.data(), SLOT(sendRecordingStatus())); + } +} + +void QmlProfilerClientManager::disconnectClientSignals() +{ + if (d->qmlclientplugin) { + disconnect(d->qmlclientplugin.data(), SIGNAL(complete()), + this, SLOT(qmlComplete())); + disconnect(d->qmlclientplugin.data(), + SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), + this, + SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation))); + disconnect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), + this, SIGNAL(traceFinished(qint64))); + disconnect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), + this, SIGNAL(traceStarted(qint64))); + disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), + this, SIGNAL(addFrameEvent(qint64,int,int))); + disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), + d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); + // fixme: this should be unified for both clients + disconnect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), + d->profilerState, SLOT(setServerRecording(bool))); + } + if (d->v8clientplugin) { + disconnect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); + disconnect(d->v8clientplugin.data(), + SIGNAL(v8range(int,QString,QString,int,double,double)), + this, + SIGNAL(addV8Event(int,QString,QString,int,double,double))); + disconnect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), + d->v8clientplugin.data(), SLOT(sendRecordingStatus())); + } +} + +void QmlProfilerClientManager::connectToClient() +{ + if (!d->connection || d->connection->state() != QAbstractSocket::UnconnectedState) + return; + + if (d->connectMode == QmlProfilerClientManagerPrivate::TcpConnection) { + QmlProfilerTool::logStatus(QString("QML Profiler: Connecting to %1:%2 ...").arg(d->tcpHost, QString::number(d->tcpPort))); + d->connection->connectToHost(d->tcpHost, d->tcpPort); + } else { + QmlProfilerTool::logStatus(QString("QML Profiler: Connecting to %1 ...").arg(d->tcpHost)); + d->connection->connectToOst(d->ostDevice); + } +} + +void QmlProfilerClientManager::disconnectClient() +{ + // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow + // method to complete before deleting object + if (d->connection) { + d->connection->deleteLater(); + d->connection = 0; + } +} + +void QmlProfilerClientManager::tryToConnect() +{ + ++d->connectionAttempts; + + if (d->connection && d->connection->isConnected()) { + d->connectionTimer.stop(); + d->connectionAttempts = 0; + } else if (d->connectionAttempts == 50) { + d->connectionTimer.stop(); + d->connectionAttempts = 0; + + QMessageBox *infoBox = QmlProfilerTool::requestMessageBox(); + infoBox->setIcon(QMessageBox::Critical); + infoBox->setWindowTitle(tr("Qt Creator")); + infoBox->setText(tr("Could not connect to the in-process QML profiler.\n" + "Do you want to retry?")); + infoBox->setStandardButtons(QMessageBox::Retry | + QMessageBox::Cancel | + QMessageBox::Help); + infoBox->setDefaultButton(QMessageBox::Retry); + infoBox->setModal(true); + + connect(infoBox, SIGNAL(finished(int)), + this, SLOT(retryMessageBoxFinished(int))); + + infoBox->show(); + } else { + connectToClient(); + } +} + +void QmlProfilerClientManager::connectionStateChanged() +{ + if (!d->connection) + return; + switch (d->connection->state()) { + case QAbstractSocket::UnconnectedState: + { + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: disconnected"); + break; + } + case QAbstractSocket::HostLookupState: + break; + case QAbstractSocket::ConnectingState: { + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: Connecting to debug server ..."); + break; + } + case QAbstractSocket::ConnectedState: + { + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: connected and running"); + // notify the client recording status + clientRecordingChanged(); + break; + } + case QAbstractSocket::ClosingState: + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: closing ..."); + break; + case QAbstractSocket::BoundState: + case QAbstractSocket::ListeningState: + break; + } +} + +void QmlProfilerClientManager::retryMessageBoxFinished(int result) +{ + switch (result) { + case QMessageBox::Retry: { + d->connectionAttempts = 0; + d->connectionTimer.start(); + break; + } + case QMessageBox::Help: { + QmlProfilerTool::handleHelpRequest(QString("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html")); + // fall through + } + default: { + if (d->connection) { + QmlProfilerTool::logStatus("QML Profiler: Failed to connect! " + d->connection->errorString()); + } else { + QmlProfilerTool::logStatus("QML Profiler: Failed to connect!"); + } + + emit connectionFailed(); + break; + } + } +} + +void QmlProfilerClientManager::qmlComplete() +{ + d->qmlDataReady = true; + if (!d->v8clientplugin || d->v8clientplugin.data()->status() != QDeclarativeDebugClient::Enabled || d->v8DataReady) { + emit dataReadyForProcessing(); + // once complete is sent, reset the flags + d->qmlDataReady = false; + d->v8DataReady = false; + } +} + +void QmlProfilerClientManager::v8Complete() +{ + d->v8DataReady = true; + if (!d->qmlclientplugin || d->qmlclientplugin.data()->status() != QDeclarativeDebugClient::Enabled || d->qmlDataReady) { + emit dataReadyForProcessing(); + // once complete is sent, reset the flags + d->v8DataReady = false; + d->qmlDataReady = false; + } +} + +void QmlProfilerClientManager::stopClientsRecording() +{ + if (d->qmlclientplugin) + d->qmlclientplugin.data()->setRecording(false); + if (d->v8clientplugin) + d->v8clientplugin.data()->setRecording(false); +} + +//////////////////////////////////////////////////////////////// +// Profiler State +void QmlProfilerClientManager::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) +{ + if (d->profilerState) { + disconnect(d->profilerState, SIGNAL(stateChanged()), + this, SLOT(profilerStateChanged())); + disconnect(d->profilerState, SIGNAL(clientRecordingChanged()), + this, SLOT(clientRecordingChanged())); + disconnect(d->profilerState, SIGNAL(serverRecordingChanged()), + this, SLOT(serverRecordingChanged())); + } + + d->profilerState = profilerState; + + // connect + if (d->profilerState) { + connect(d->profilerState, SIGNAL(stateChanged()), + this, SLOT(profilerStateChanged())); + connect(d->profilerState, SIGNAL(clientRecordingChanged()), + this, SLOT(clientRecordingChanged())); + connect(d->profilerState, SIGNAL(serverRecordingChanged()), + this, SLOT(serverRecordingChanged())); + } +} + +void QmlProfilerClientManager::profilerStateChanged() +{ + QTC_ASSERT(d->profilerState, return); + switch (d->profilerState->currentState()) { + case QmlProfilerStateManager::AppStopRequested : + if (d->profilerState->serverRecording()) { + stopClientsRecording(); + } + else + d->profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop); + break; + default: + break; + } +} + +void QmlProfilerClientManager::clientRecordingChanged() +{ + QTC_ASSERT(d->profilerState, return); + if (d->profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + if (d->qmlclientplugin) + d->qmlclientplugin.data()->setRecording(d->profilerState->clientRecording()); + if (d->v8clientplugin) + d->v8clientplugin.data()->setRecording(d->profilerState->clientRecording()); + } +} + +void QmlProfilerClientManager::serverRecordingChanged() +{ + if (d->profilerState->serverRecording()) { + d->v8DataReady = false; + d->qmlDataReady = false; + } +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h new file mode 100644 index 0000000000..0ee061993a --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -0,0 +1,103 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef QMLPROFILERCLIENTMANAGER_H +#define QMLPROFILERCLIENTMANAGER_H + +#include <QObject> +#include <QStringList> + +#include "qmlprofilerstatemanager.h" +#include <qmljsdebugclient/qmlprofilereventlocation.h> + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerClientManager : public QObject +{ + Q_OBJECT +public: + explicit QmlProfilerClientManager(QObject *parent = 0); + ~QmlProfilerClientManager(); + + void registerProfilerStateManager(QmlProfilerStateManager *profilerState); + + void setTcpConnection(QString host, quint64 port); + void setOstConnection(QString ostDevice); + + void clearBufferedData(); + void discardPendingData(); + +signals: + void connectionFailed(); + + // data + void addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation); + void addV8Event(int,QString,QString,int,double,double); + void addFrameEvent(qint64,int,int); + void traceStarted(qint64); + void traceFinished(qint64); + void dataReadyForProcessing(); + +public slots: + void connectClient(quint16 port); + void disconnectClient(); + +private slots: + void tryToConnect(); + void connectionStateChanged(); + void retryMessageBoxFinished(int result); + + void qmlComplete(); + void v8Complete(); + + void profilerStateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); + +private: + class QmlProfilerClientManagerPrivate; + QmlProfilerClientManagerPrivate *d; + + void connectToClient(); + + void enableServices(); + void connectClientSignals(); + void disconnectClientSignals(); + + void stopClientsRecording(); +}; + +} +} + +#endif // QMLPROFILERCLIENTMANAGER_H diff --git a/src/plugins/qmlprofiler/qmlprofilerconstants.h b/src/plugins/qmlprofiler/qmlprofilerconstants.h index 38a47c11f1..fec1b6b539 100644 --- a/src/plugins/qmlprofiler/qmlprofilerconstants.h +++ b/src/plugins/qmlprofiler/qmlprofilerconstants.h @@ -37,6 +37,7 @@ namespace QmlProfiler { namespace Constants { const char ATTACH[] = "Menu.Analyzer.Attach"; +const char TraceFileExtension[] = ".qtd"; } // namespace Constants } // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp new file mode 100644 index 0000000000..95d44dca63 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp @@ -0,0 +1,1667 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "qmlprofilerdatamodel.h" + +#include <QUrl> +#include <QHash> +#include <QtAlgorithms> +#include <QString> +#include <QStringList> + +#include <QFile> +#include <QXmlStreamReader> +#include <QXmlStreamWriter> + +#include <QTimer> +#include <utils/qtcassert.h> + +using namespace QmlJsDebugClient; + +namespace QmlProfiler { +namespace Internal { + +/////////////////////////////////////////////////////////// +QmlRangeEventData::QmlRangeEventData() +{ + eventType = MaximumQmlEventType; + eventId = -1; + duration = 0; + calls = 0; + minTime = 0; + maxTime = 0; + timePerCall = 0; + percentOfTime = 0; + medianTime = 0; + isBindingLoop = false; +} + +QmlRangeEventData::~QmlRangeEventData() +{ + qDeleteAll(parentHash.values()); + parentHash.clear(); + qDeleteAll(childrenHash.values()); + childrenHash.clear(); +} + +QmlRangeEventData &QmlRangeEventData::operator=(const QmlRangeEventData &ref) +{ + if (this == &ref) + return *this; + + displayName = ref.displayName; + location = ref.location; + eventHashStr = ref.eventHashStr; + details = ref.details; + eventType = ref.eventType; + duration = ref.duration; + calls = ref.calls; + minTime = ref.minTime; + maxTime = ref.maxTime; + timePerCall = ref.timePerCall; + percentOfTime = ref.percentOfTime; + medianTime = ref.medianTime; + eventId = ref.eventId; + isBindingLoop = ref.isBindingLoop; + + qDeleteAll(parentHash.values()); + parentHash.clear(); + foreach (const QString &key, ref.parentHash.keys()) { + parentHash.insert(key, new QmlRangeEventRelative(ref.parentHash.value(key))); + } + + qDeleteAll(childrenHash.values()); + childrenHash.clear(); + foreach (const QString &key, ref.childrenHash.keys()) { + childrenHash.insert(key, new QmlRangeEventRelative(ref.childrenHash.value(key))); + } + + return *this; +} + +/////////////////////////////////////////////////////////// + +// endtimedata +struct QmlRangeEventEndInstance { + qint64 endTime; + int startTimeIndex; + QmlRangeEventData *description; +}; + +// starttimedata +struct QmlRangeEventStartInstance { + qint64 startTime; + qint64 duration; + qint64 level; + int endTimeIndex; + qint64 nestingLevel; + qint64 nestingDepth; + QmlRangeEventData *statsInfo; + + int baseEventIndex; + + // animation-related data + int frameRate; + int animationCount; + + int bindingLoopHead; +}; + +struct QmlRangeEventTypeCount { + QVector<int> eventIds; + int nestingCount; +}; + +// used by quicksort +bool compareEndTimes(const QmlRangeEventEndInstance &t1, const QmlRangeEventEndInstance &t2) +{ + return t1.endTime < t2.endTime; +} + +bool compareStartTimes(const QmlRangeEventStartInstance &t1, const QmlRangeEventStartInstance &t2) +{ + return t1.startTime < t2.startTime; +} + +bool compareStartIndexes(const QmlRangeEventEndInstance &t1, const QmlRangeEventEndInstance &t2) +{ + return t1.startTimeIndex < t2.startTimeIndex; +} + +////////////////////////////////////////////////////////////// +class QmlProfilerDataModel::QmlProfilerDataModelPrivate +{ +public: + QmlProfilerDataModelPrivate(QmlProfilerDataModel *qq) : q(qq) {} + + QmlProfilerDataModel *q; + + // convenience functions + void clearQmlRootEvent(); + void insertQmlRootEvent(); + void postProcess(); + void sortEndTimes(); + void findAnimationLimits(); + void sortStartTimes(); + void computeNestingLevels(); + void computeNestingDepth(); + void prepareForDisplay(); + void linkStartsToEnds(); + void linkEndsToStarts(); + bool checkBindingLoop(QmlRangeEventData *from, QmlRangeEventData *current, QList<QmlRangeEventData *>visited); + + + // stats + void clearStatistics(); + void redoTree(qint64 fromTime, qint64 toTime); + void computeMedianTime(qint64 fromTime, qint64 toTime); + void findBindingLoops(qint64 fromTime, qint64 toTime); + + QmlProfilerDataModel::State listState; + + // Stored data + QHash<QString, QmlRangeEventData *> rangeEventDictionary; + QVector<QmlRangeEventEndInstance> endInstanceList; + QVector<QmlRangeEventStartInstance> startInstanceList; + + QmlRangeEventData qmlRootEvent; + + QV8ProfilerDataModel *v8DataModel; + + QHash<int, QmlRangeEventTypeCount *> typeCounts; + + qint64 traceEndTime; + qint64 traceStartTime; + qint64 qmlMeasuredTime; + + QmlRangeEventStartInstance *lastFrameEvent; + qint64 maxAnimationCount; + qint64 minAnimationCount; + + // file to load + QString fileName; +}; + + +//////////////////////////////////////////////////////////////////////////////////// + + +QmlProfilerDataModel::QmlProfilerDataModel(QObject *parent) : + QObject(parent), d(new QmlProfilerDataModelPrivate(this)) +{ + setObjectName("QmlProfilerDataModel"); + + d->listState = Empty; + + d->traceEndTime = 0; + d->traceStartTime = -1; + d->qmlMeasuredTime = 0; + d->clearQmlRootEvent(); + d->lastFrameEvent = 0; + d->maxAnimationCount = 0; + d->minAnimationCount = 0; + d->v8DataModel = new QV8ProfilerDataModel(this, this); +} + +QmlProfilerDataModel::~QmlProfilerDataModel() +{ + clear(); + delete d; +} + +//////////////////////////////////////////////////////////////////////////////////// +QList<QmlRangeEventData *> QmlProfilerDataModel::getEventDescriptions() const +{ + return d->rangeEventDictionary.values(); +} + +QmlRangeEventData *QmlProfilerDataModel::eventDescription(int eventId) const +{ + foreach (QmlRangeEventData *event, d->rangeEventDictionary.values()) { + if (event->eventId == eventId) + return event; + } + return 0; +} + +QList<QV8EventData *> QmlProfilerDataModel::getV8Events() const +{ + return d->v8DataModel->getV8Events(); +} + +QV8EventData *QmlProfilerDataModel::v8EventDescription(int eventId) const +{ + return d->v8DataModel->v8EventDescription(eventId); +} + +//////////////////////////////////////////////////////////////////////////////////// + +void QmlProfilerDataModel::clear() +{ + qDeleteAll(d->rangeEventDictionary.values()); + d->rangeEventDictionary.clear(); + + d->endInstanceList.clear(); + d->startInstanceList.clear(); + + d->clearQmlRootEvent(); + + foreach (QmlRangeEventTypeCount *typeCount, d->typeCounts.values()) + delete typeCount; + d->typeCounts.clear(); + + d->traceEndTime = 0; + d->traceStartTime = -1; + d->qmlMeasuredTime = 0; + + d->lastFrameEvent = 0; + d->maxAnimationCount = 0; + d->minAnimationCount = 0; + + d->v8DataModel->clear(); + + emit countChanged(); + setState(Empty); +} + +void QmlProfilerDataModel::addRangedEvent(int type, qint64 startTime, qint64 length, + const QStringList &data, + const QmlJsDebugClient::QmlEventLocation &location) +{ + const QChar colon = QLatin1Char(':'); + QString displayName, eventHashStr, details; + QmlJsDebugClient::QmlEventLocation eventLocation = location; + + setState(AcquiringData); + + // generate details string + if (data.isEmpty()) + details = tr("Source code not available"); + else { + details = data.join(" ").replace('\n'," ").simplified(); + QRegExp rewrite("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)"); + bool match = rewrite.exactMatch(details); + if (match) { + details = rewrite.cap(1) + ": " + rewrite.cap(3); + } + if (details.startsWith(QString("file://"))) + details = details.mid(details.lastIndexOf(QChar('/')) + 1); + } + + // backwards compatibility: "compiling" events don't have a proper location in older + // version of the protocol, but the filename is passed in the details string + if (type == QmlJsDebugClient::Compiling && eventLocation.filename.isEmpty()) { + eventLocation.filename = details; + eventLocation.line = 1; + eventLocation.column = 1; + } + + // generate hash + if (eventLocation.filename.isEmpty()) { + displayName = tr("<bytecode>"); + eventHashStr = getHashStringForQmlEvent(eventLocation, type); + } else { + const QString filePath = QUrl(eventLocation.filename).path(); + displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon + + QString::number(eventLocation.line); + eventHashStr = getHashStringForQmlEvent(eventLocation, type); + } + + QmlRangeEventData *newEvent; + if (d->rangeEventDictionary.contains(eventHashStr)) { + newEvent = d->rangeEventDictionary[eventHashStr]; + } else { + newEvent = new QmlRangeEventData; + newEvent->displayName = displayName; + newEvent->location = eventLocation; + newEvent->eventHashStr = eventHashStr; + newEvent->eventType = (QmlJsDebugClient::QmlEventType)type; + newEvent->details = details; + d->rangeEventDictionary.insert(eventHashStr, newEvent); + } + + QmlRangeEventEndInstance endTimeData; + endTimeData.endTime = startTime + length; + endTimeData.description = newEvent; + endTimeData.startTimeIndex = d->startInstanceList.count(); + + QmlRangeEventStartInstance startTimeData; + startTimeData.startTime = startTime; + startTimeData.duration = length; + startTimeData.statsInfo = newEvent; + startTimeData.endTimeIndex = d->endInstanceList.count(); + startTimeData.animationCount = -1; + startTimeData.frameRate = 1e9/length; + startTimeData.baseEventIndex = d->startInstanceList.count(); // point to itself by default + + d->endInstanceList << endTimeData; + d->startInstanceList << startTimeData; + + emit countChanged(); +} + +void QmlProfilerDataModel::addV8Event(int depth, const QString &function, + const QString &filename, int lineNumber, + double totalTime, double selfTime) +{ + d->v8DataModel->addV8Event(depth, function, filename, lineNumber, totalTime, selfTime); +} + +void QmlProfilerDataModel::addFrameEvent(qint64 time, int framerate, int animationcount) +{ + QString displayName, eventHashStr, details; + + setState(AcquiringData); + + details = tr("Animation Timer Update"); + displayName = tr("<Animation Update>"); + eventHashStr = displayName; + + QmlRangeEventData *newEvent; + if (d->rangeEventDictionary.contains(eventHashStr)) { + newEvent = d->rangeEventDictionary[eventHashStr]; + } else { + newEvent = new QmlRangeEventData; + newEvent->displayName = displayName; + newEvent->eventHashStr = eventHashStr; + newEvent->eventType = QmlJsDebugClient::Painting; + newEvent->details = details; + d->rangeEventDictionary.insert(eventHashStr, newEvent); + } + + qint64 length = 1e9/framerate; + // avoid overlap + if (d->lastFrameEvent && + d->lastFrameEvent->startTime + d->lastFrameEvent->duration >= time) { + d->lastFrameEvent->duration = time - 1 - d->lastFrameEvent->startTime; + d->endInstanceList[d->lastFrameEvent->endTimeIndex].endTime = + d->lastFrameEvent->startTime + d->lastFrameEvent->duration; + } + + QmlRangeEventEndInstance endTimeData; + endTimeData.endTime = time + length; + endTimeData.description = newEvent; + endTimeData.startTimeIndex = d->startInstanceList.count(); + + QmlRangeEventStartInstance startTimeData; + startTimeData.startTime = time; + startTimeData.duration = length; + startTimeData.statsInfo = newEvent; + startTimeData.endTimeIndex = d->endInstanceList.count(); + startTimeData.animationCount = animationcount; + startTimeData.frameRate = framerate; + startTimeData.baseEventIndex = d->startInstanceList.count(); // point to itself by default + + d->endInstanceList << endTimeData; + d->startInstanceList << startTimeData; + + d->lastFrameEvent = &d->startInstanceList.last(); + + emit countChanged(); +} + +void QmlProfilerDataModel::setTraceEndTime(qint64 time) +{ + d->traceEndTime = time; +} + +void QmlProfilerDataModel::setTraceStartTime(qint64 time) +{ + d->traceStartTime = time; +} + +//////////////////////////////////////////////////////////////////////////////////// + +QString QmlProfilerDataModel::getHashStringForQmlEvent( + const QmlJsDebugClient::QmlEventLocation &location, int eventType) +{ + return QString("%1:%2:%3:%4").arg(location.filename, + QString::number(location.line), + QString::number(location.column), + QString::number(eventType)); +} + +QString QmlProfilerDataModel::getHashStringForV8Event(const QString &displayName, + const QString &function) +{ + return QString("%1:%2").arg(displayName, function); +} + +QString QmlProfilerDataModel::rootEventName() +{ + return tr("<program>"); +} + +QString QmlProfilerDataModel::rootEventDescription() +{ + return tr("Main Program"); +} + +QString QmlProfilerDataModel::qmlEventTypeAsString(QmlEventType typeEnum) +{ + switch (typeEnum) { + case Painting: + return QLatin1String(Constants::TYPE_PAINTING_STR); + break; + case Compiling: + return QLatin1String(Constants::TYPE_COMPILING_STR); + break; + case Creating: + return QLatin1String(Constants::TYPE_CREATING_STR); + break; + case Binding: + return QLatin1String(Constants::TYPE_BINDING_STR); + break; + case HandlingSignal: + return QLatin1String(Constants::TYPE_HANDLINGSIGNAL_STR); + break; + default: + return QString::number((int)typeEnum); + } +} + +QmlEventType QmlProfilerDataModel::qmlEventTypeAsEnum(const QString &typeString) +{ + if (typeString == QLatin1String(Constants::TYPE_PAINTING_STR)) { + return Painting; + } else if (typeString == QLatin1String(Constants::TYPE_COMPILING_STR)) { + return Compiling; + } else if (typeString == QLatin1String(Constants::TYPE_CREATING_STR)) { + return Creating; + } else if (typeString == QLatin1String(Constants::TYPE_BINDING_STR)) { + return Binding; + } else if (typeString == QLatin1String(Constants::TYPE_HANDLINGSIGNAL_STR)) { + return HandlingSignal; + } else { + bool isNumber = false; + int type = typeString.toUInt(&isNumber); + if (isNumber) { + return (QmlEventType)type; + } else { + return MaximumQmlEventType; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////// + +int QmlProfilerDataModel::findFirstIndex(qint64 startTime) const +{ + int candidate = -1; + // in the "endtime" list, find the first event that ends after startTime + if (d->endInstanceList.isEmpty()) + return 0; // -1 + if (d->endInstanceList.count() == 1 || d->endInstanceList.first().endTime >= startTime) + candidate = 0; + else + if (d->endInstanceList.last().endTime <= startTime) + return 0; // -1 + + if (candidate == -1) + { + int fromIndex = 0; + int toIndex = d->endInstanceList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->endInstanceList[midIndex].endTime < startTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + candidate = toIndex; + } + + int eventIndex = d->endInstanceList[candidate].startTimeIndex; + return d->startInstanceList[eventIndex].baseEventIndex; +} + +int QmlProfilerDataModel::findFirstIndexNoParents(qint64 startTime) const +{ + int candidate = -1; + // in the "endtime" list, find the first event that ends after startTime + if (d->endInstanceList.isEmpty()) + return 0; // -1 + if (d->endInstanceList.count() == 1 || d->endInstanceList.first().endTime >= startTime) + candidate = 0; + else + if (d->endInstanceList.last().endTime <= startTime) + return 0; // -1 + + if (candidate == -1) { + int fromIndex = 0; + int toIndex = d->endInstanceList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->endInstanceList[midIndex].endTime < startTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + candidate = toIndex; + } + + int ndx = d->endInstanceList[candidate].startTimeIndex; + + return ndx; +} + +int QmlProfilerDataModel::findLastIndex(qint64 endTime) const +{ + // in the "starttime" list, find the last event that starts before endtime + if (d->startInstanceList.isEmpty()) + return 0; // -1 + if (d->startInstanceList.first().startTime >= endTime) + return 0; // -1 + if (d->startInstanceList.count() == 1) + return 0; + if (d->startInstanceList.last().startTime <= endTime) + return d->startInstanceList.count()-1; + + int fromIndex = 0; + int toIndex = d->startInstanceList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->startInstanceList[midIndex].startTime < endTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + return fromIndex; +} + +qint64 QmlProfilerDataModel::firstTimeMark() const +{ + if (d->startInstanceList.isEmpty()) + return 0; + else { + return d->startInstanceList[0].startTime; + } +} + +qint64 QmlProfilerDataModel::lastTimeMark() const +{ + if (d->endInstanceList.isEmpty()) + return 0; + else { + return d->endInstanceList.last().endTime; + } +} + +//////////////////////////////////////////////////////////////////////////////////// + +int QmlProfilerDataModel::count() const +{ + return d->startInstanceList.count(); +} + +bool QmlProfilerDataModel::isEmpty() const +{ + return d->startInstanceList.isEmpty() && d->v8DataModel->isEmpty(); +} + +qint64 QmlProfilerDataModel::getStartTime(int index) const +{ + return d->startInstanceList[index].startTime; +} + +qint64 QmlProfilerDataModel::getEndTime(int index) const +{ + return d->startInstanceList[index].startTime + d->startInstanceList[index].duration; +} + +qint64 QmlProfilerDataModel::getDuration(int index) const +{ + return d->startInstanceList[index].duration; +} + +int QmlProfilerDataModel::getType(int index) const +{ + return d->startInstanceList[index].statsInfo->eventType; +} + +int QmlProfilerDataModel::getNestingLevel(int index) const +{ + return d->startInstanceList[index].nestingLevel; +} + +int QmlProfilerDataModel::getNestingDepth(int index) const +{ + return d->startInstanceList[index].nestingDepth; +} + +QString QmlProfilerDataModel::getFilename(int index) const +{ + return d->startInstanceList[index].statsInfo->location.filename; +} + +int QmlProfilerDataModel::getLine(int index) const +{ + return d->startInstanceList[index].statsInfo->location.line; +} + +int QmlProfilerDataModel::getColumn(int index) const +{ + return d->startInstanceList[index].statsInfo->location.column; +} + +QString QmlProfilerDataModel::getDetails(int index) const +{ + // special: animations + if (d->startInstanceList[index].statsInfo->eventType == QmlJsDebugClient::Painting && + d->startInstanceList[index].animationCount >= 0) + return tr("%1 animations at %2 FPS").arg( + QString::number(d->startInstanceList[index].animationCount), + QString::number(d->startInstanceList[index].frameRate)); + return d->startInstanceList[index].statsInfo->details; +} + +int QmlProfilerDataModel::getEventId(int index) const +{ + return d->startInstanceList[index].statsInfo->eventId; +} + +int QmlProfilerDataModel::getBindingLoopDest(int index) const +{ + return d->startInstanceList[index].bindingLoopHead; +} + +int QmlProfilerDataModel::getFramerate(int index) const +{ + return d->startInstanceList[index].frameRate; +} + +int QmlProfilerDataModel::getAnimationCount(int index) const +{ + return d->startInstanceList[index].animationCount; +} + +int QmlProfilerDataModel::getMaximumAnimationCount() const +{ + return d->maxAnimationCount; +} + +int QmlProfilerDataModel::getMinimumAnimationCount() const +{ + return d->minAnimationCount; +} + +///////////////////////////////////////// + +int QmlProfilerDataModel::uniqueEventsOfType(int type) const +{ + if (!d->typeCounts.contains(type)) + return 0; + return d->typeCounts[type]->eventIds.count(); +} + +int QmlProfilerDataModel::maxNestingForType(int type) const +{ + if (!d->typeCounts.contains(type)) + return 0; + return d->typeCounts[type]->nestingCount; +} + +QString QmlProfilerDataModel::eventTextForType(int type, int index) const +{ + if (!d->typeCounts.contains(type)) + return QString(); + return d->rangeEventDictionary.values().at(d->typeCounts[type]->eventIds[index])->details; +} + +QString QmlProfilerDataModel::eventDisplayNameForType(int type, int index) const +{ + if (!d->typeCounts.contains(type)) + return QString(); + return d->rangeEventDictionary.values().at(d->typeCounts[type]->eventIds[index])->displayName; +} + +int QmlProfilerDataModel::eventIdForType(int type, int index) const +{ + if (!d->typeCounts.contains(type)) + return -1; + return d->typeCounts[type]->eventIds[index]; +} + +int QmlProfilerDataModel::eventPosInType(int index) const +{ + int eventType = d->startInstanceList[index].statsInfo->eventType; + return d->typeCounts[eventType]->eventIds.indexOf(d->startInstanceList[index].statsInfo->eventId); +} + +///////////////////////////////////////// + +qint64 QmlProfilerDataModel::traceStartTime() const +{ + return d->traceStartTime != -1? d->traceStartTime : firstTimeMark(); +} + +qint64 QmlProfilerDataModel::traceEndTime() const +{ + return d->traceEndTime ? d->traceEndTime : lastTimeMark(); +} + +qint64 QmlProfilerDataModel::traceDuration() const +{ + return traceEndTime() - traceStartTime(); +} + +qint64 QmlProfilerDataModel::qmlMeasuredTime() const +{ + return d->qmlMeasuredTime; +} +qint64 QmlProfilerDataModel::v8MeasuredTime() const +{ + return d->v8DataModel->v8MeasuredTime(); +} + +//////////////////////////////////////////////////////////////////////////////////// + +void QmlProfilerDataModel::complete() +{ + if (currentState() == AcquiringData) { + setState(ProcessingData); + d->v8DataModel->collectV8Statistics(); + d->postProcess(); + } else + if (currentState() == Empty) { + setState(Done); + } else { + emit error("Unexpected complete signal in data model"); + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::postProcess() +{ + if (q->count() != 0) { + sortStartTimes(); + sortEndTimes(); + findAnimationLimits(); + computeNestingLevels(); + computeNestingDepth(); + linkEndsToStarts(); + insertQmlRootEvent(); + q->reloadDetails(); + prepareForDisplay(); + q->compileStatistics(q->traceStartTime(), q->traceEndTime()); + + } + q->setState(Done); +} + + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::prepareForDisplay() +{ + // generate numeric ids + int ndx = 0; + foreach (QmlRangeEventData *binding, rangeEventDictionary.values()) { + binding->eventId = ndx++; + } + + // collect type counts + foreach (const QmlRangeEventStartInstance &eventStartData, startInstanceList) { + int typeNumber = eventStartData.statsInfo->eventType; + if (!typeCounts.contains(typeNumber)) { + typeCounts[typeNumber] = new QmlRangeEventTypeCount; + typeCounts[typeNumber]->nestingCount = 0; + } + if (eventStartData.nestingLevel > typeCounts[typeNumber]->nestingCount) { + typeCounts[typeNumber]->nestingCount = eventStartData.nestingLevel; + } + if (!typeCounts[typeNumber]->eventIds.contains(eventStartData.statsInfo->eventId)) + typeCounts[typeNumber]->eventIds << eventStartData.statsInfo->eventId; + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::sortStartTimes() +{ + if (startInstanceList.count() < 2) + return; + + // assuming startTimes is partially sorted + // identify blocks of events and sort them with quicksort + QVector<QmlRangeEventStartInstance>::iterator itFrom = startInstanceList.end() - 2; + QVector<QmlRangeEventStartInstance>::iterator itTo = startInstanceList.end() - 1; + + while (itFrom != startInstanceList.begin() && itTo != startInstanceList.begin()) { + // find block to sort + while (itFrom != startInstanceList.begin() + && itTo->startTime > itFrom->startTime) { + itTo--; + itFrom = itTo - 1; + } + + // if we're at the end of the list + if (itFrom == startInstanceList.begin()) + break; + + // find block length + while (itFrom != startInstanceList.begin() + && itTo->startTime <= itFrom->startTime) + itFrom--; + + if (itTo->startTime <= itFrom->startTime) + qSort(itFrom, itTo + 1, compareStartTimes); + else + qSort(itFrom + 1, itTo + 1, compareStartTimes); + + // move to next block + itTo = itFrom; + itFrom = itTo - 1; + } + + // link back the endTimes + linkEndsToStarts(); +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::sortEndTimes() +{ + // assuming endTimes is partially sorted + // identify blocks of events and sort them with quicksort + + if (endInstanceList.count() < 2) + return; + + QVector<QmlRangeEventEndInstance>::iterator itFrom = endInstanceList.begin(); + QVector<QmlRangeEventEndInstance>::iterator itTo = endInstanceList.begin() + 1; + + while (itTo != endInstanceList.end() && itFrom != endInstanceList.end()) { + // find block to sort + while (itTo != endInstanceList.end() + && startInstanceList[itTo->startTimeIndex].startTime > + startInstanceList[itFrom->startTimeIndex].startTime + + startInstanceList[itFrom->startTimeIndex].duration) { + itFrom++; + itTo = itFrom+1; + } + + // if we're at the end of the list + if (itTo == endInstanceList.end()) + break; + + // find block length + while (itTo != endInstanceList.end() + && startInstanceList[itTo->startTimeIndex].startTime <= + startInstanceList[itFrom->startTimeIndex].startTime + + startInstanceList[itFrom->startTimeIndex].duration) + itTo++; + + // sort block + qSort(itFrom, itTo, compareEndTimes); + + // move to next block + itFrom = itTo; + itTo = itFrom+1; + + } + + // link back the startTimes + linkStartsToEnds(); +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::linkStartsToEnds() +{ + for (int i = 0; i < endInstanceList.count(); i++) + startInstanceList[endInstanceList[i].startTimeIndex].endTimeIndex = i; +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::findAnimationLimits() +{ + maxAnimationCount = 0; + minAnimationCount = 0; + lastFrameEvent = 0; + + for (int i = 0; i < startInstanceList.count(); i++) { + if (startInstanceList[i].statsInfo->eventType == QmlJsDebugClient::Painting && + startInstanceList[i].animationCount >= 0) { + int animationcount = startInstanceList[i].animationCount; + if (lastFrameEvent) { + if (animationcount > maxAnimationCount) + maxAnimationCount = animationcount; + if (animationcount < minAnimationCount) + minAnimationCount = animationcount; + } else { + maxAnimationCount = animationcount; + minAnimationCount = animationcount; + } + lastFrameEvent = &startInstanceList[i]; + } + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::computeNestingLevels() +{ + // compute levels + QHash<int, qint64> endtimesPerLevel; + QList<int> nestingLevels; + QList< QHash<int, qint64> > endtimesPerNestingLevel; + int level = Constants::QML_MIN_LEVEL; + endtimesPerLevel[Constants::QML_MIN_LEVEL] = 0; + int lastBaseEventIndex = 0; + qint64 lastBaseEventEndTime = traceStartTime; + + for (int i = 0; i < QmlJsDebugClient::MaximumQmlEventType; i++) { + nestingLevels << Constants::QML_MIN_LEVEL; + QHash<int, qint64> dummyHash; + dummyHash[Constants::QML_MIN_LEVEL] = 0; + endtimesPerNestingLevel << dummyHash; + } + + for (int i=0; i<startInstanceList.count(); i++) { + qint64 st = startInstanceList[i].startTime; + int type = startInstanceList[i].statsInfo->eventType; + + if (type == QmlJsDebugClient::Painting) { + // animation/paint events have level 0 by definition (same as "mainprogram"), + // but are not considered parents of other events for statistical purposes + startInstanceList[i].level = Constants::QML_MIN_LEVEL - 1; + startInstanceList[i].nestingLevel = Constants::QML_MIN_LEVEL; + if (lastBaseEventEndTime < startInstanceList[i].startTime) { + lastBaseEventIndex = i; + lastBaseEventEndTime = startInstanceList[i].startTime + startInstanceList[i].duration; + } + startInstanceList[i].baseEventIndex = lastBaseEventIndex; + continue; + } + + // general level + if (endtimesPerLevel[level] > st) { + level++; + } else { + while (level > Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= st) + level--; + } + endtimesPerLevel[level] = st + startInstanceList[i].duration; + + // per type + if (endtimesPerNestingLevel[type][nestingLevels[type]] > st) { + nestingLevels[type]++; + } else { + while (nestingLevels[type] > Constants::QML_MIN_LEVEL && + endtimesPerNestingLevel[type][nestingLevels[type]-1] <= st) + nestingLevels[type]--; + } + endtimesPerNestingLevel[type][nestingLevels[type]] = + st + startInstanceList[i].duration; + + startInstanceList[i].level = level; + startInstanceList[i].nestingLevel = nestingLevels[type]; + + if (level == Constants::QML_MIN_LEVEL) { + qmlMeasuredTime += startInstanceList[i].duration; + if (lastBaseEventEndTime < startInstanceList[i].startTime) { + lastBaseEventIndex = i; + lastBaseEventEndTime = startInstanceList[i].startTime + startInstanceList[i].duration; + } + } + startInstanceList[i].baseEventIndex = lastBaseEventIndex; + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::computeNestingDepth() +{ + QHash<int, int> nestingDepth; + for (int i = 0; i < endInstanceList.count(); i++) { + int type = endInstanceList[i].description->eventType; + int nestingInType = startInstanceList[endInstanceList[i].startTimeIndex].nestingLevel; + if (!nestingDepth.contains(type)) + nestingDepth[type] = nestingInType; + else { + int nd = nestingDepth[type]; + nestingDepth[type] = nd > nestingInType ? nd : nestingInType; + } + + startInstanceList[endInstanceList[i].startTimeIndex].nestingDepth = nestingDepth[type]; + if (nestingInType == Constants::QML_MIN_LEVEL) + nestingDepth[type] = Constants::QML_MIN_LEVEL; + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::linkEndsToStarts() +{ + for (int i = 0; i < startInstanceList.count(); i++) + endInstanceList[startInstanceList[i].endTimeIndex].startTimeIndex = i; +} + +//////////////////////////////////////////////////////////////////////////////////// + +void QmlProfilerDataModel::compileStatistics(qint64 startTime, qint64 endTime) +{ + d->clearStatistics(); + d->redoTree(startTime, endTime); + d->computeMedianTime(startTime, endTime); + d->findBindingLoops(startTime, endTime); +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::clearStatistics() +{ + // clear existing statistics + foreach (QmlRangeEventData *eventDescription, rangeEventDictionary.values()) { + eventDescription->calls = 0; + // maximum possible value + eventDescription->minTime = endInstanceList.last().endTime; + eventDescription->maxTime = 0; + eventDescription->medianTime = 0; + eventDescription->duration = 0; + qDeleteAll(eventDescription->parentHash); + qDeleteAll(eventDescription->childrenHash); + eventDescription->parentHash.clear(); + eventDescription->childrenHash.clear(); + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::redoTree(qint64 fromTime, + qint64 toTime) +{ + double totalTime = 0; + int fromIndex = q->findFirstIndex(fromTime); + int toIndex = q->findLastIndex(toTime); + + QmlRangeEventData *listedRootEvent = rangeEventDictionary.value(rootEventName()); + QTC_ASSERT(listedRootEvent, /**/); + + // compute parent-child relationship and call count + QHash<int, QmlRangeEventData*> lastParent; + for (int index = fromIndex; index <= toIndex; index++) { + QmlRangeEventData *eventDescription = startInstanceList[index].statsInfo; + + if (startInstanceList[index].startTime > toTime || + startInstanceList[index].startTime+startInstanceList[index].duration < fromTime) { + continue; + } + + if (eventDescription->eventType == QmlJsDebugClient::Painting) { + // skip animation/paint events + continue; + } + + eventDescription->calls++; + qint64 duration = startInstanceList[index].duration; + eventDescription->duration += duration; + if (eventDescription->maxTime < duration) + eventDescription->maxTime = duration; + if (eventDescription->minTime > duration) + eventDescription->minTime = duration; + + int level = startInstanceList[index].level; + + QmlRangeEventData *parentEvent = listedRootEvent; + if (level > Constants::QML_MIN_LEVEL && lastParent.contains(level-1)) { + parentEvent = lastParent[level-1]; + } + + if (!eventDescription->parentHash.contains(parentEvent->eventHashStr)) { + QmlRangeEventRelative *newParentEvent = new QmlRangeEventRelative(parentEvent); + newParentEvent->calls = 1; + newParentEvent->duration = duration; + + eventDescription->parentHash.insert(parentEvent->eventHashStr, newParentEvent); + } else { + QmlRangeEventRelative *newParentEvent = + eventDescription->parentHash.value(parentEvent->eventHashStr); + newParentEvent->duration += duration; + newParentEvent->calls++; + } + + if (!parentEvent->childrenHash.contains(eventDescription->eventHashStr)) { + QmlRangeEventRelative *newChildEvent = new QmlRangeEventRelative(eventDescription); + newChildEvent->calls = 1; + newChildEvent->duration = duration; + + parentEvent->childrenHash.insert(eventDescription->eventHashStr, newChildEvent); + } else { + QmlRangeEventRelative *newChildEvent = + parentEvent->childrenHash.value(eventDescription->eventHashStr); + newChildEvent->duration += duration; + newChildEvent->calls++; + } + + lastParent[level] = eventDescription; + + if (level == Constants::QML_MIN_LEVEL) { + totalTime += duration; + } + } + + // fake rootEvent statistics + // the +1 nanosecond is to force it to be on top of the sorted list + listedRootEvent->duration = totalTime+1; + listedRootEvent->minTime = totalTime+1; + listedRootEvent->maxTime = totalTime+1; + listedRootEvent->medianTime = totalTime+1; + if (totalTime > 0) + listedRootEvent->calls = 1; + + // copy to the global root reference + qmlRootEvent = *listedRootEvent; + + // compute percentages + foreach (QmlRangeEventData *binding, rangeEventDictionary.values()) { + binding->percentOfTime = binding->duration * 100.0 / totalTime; + binding->timePerCall = binding->calls > 0 ? double(binding->duration) / binding->calls : 0; + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::computeMedianTime(qint64 fromTime, + qint64 toTime) +{ + int fromIndex = q->findFirstIndex(fromTime); + int toIndex = q->findLastIndex(toTime); + + // compute median time + QHash< QmlRangeEventData* , QList<qint64> > durationLists; + for (int index = fromIndex; index <= toIndex; index++) { + QmlRangeEventData *desc = startInstanceList[index].statsInfo; + qint64 len = startInstanceList[index].duration; + durationLists[desc].append(len); + } + QMutableHashIterator < QmlRangeEventData* , QList<qint64> > iter(durationLists); + while (iter.hasNext()) { + iter.next(); + if (!iter.value().isEmpty()) { + qSort(iter.value()); + iter.key()->medianTime = iter.value().at(iter.value().count()/2); + } + } +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::findBindingLoops(qint64 fromTime, + qint64 toTime) +{ + int fromIndex = q->findFirstIndex(fromTime); + int toIndex = q->findLastIndex(toTime); + + // first clear existing data + foreach (QmlRangeEventData *event, rangeEventDictionary.values()) { + event->isBindingLoop = false; + foreach (QmlRangeEventRelative *parentEvent, event->parentHash.values()) + parentEvent->inLoopPath = false; + foreach (QmlRangeEventRelative *childEvent, event->childrenHash.values()) + childEvent->inLoopPath = false; + } + + QList<QmlRangeEventData *> stackRefs; + QList<QmlRangeEventStartInstance *> stack; + + for (int i = 0; i < startInstanceList.count(); i++) { + QmlRangeEventData *currentEvent = startInstanceList[i].statsInfo; + QmlRangeEventStartInstance *inTimeEvent = &startInstanceList[i]; + inTimeEvent->bindingLoopHead = -1; + + // special: skip animation events (but not old paint events) + if (inTimeEvent->statsInfo->eventType == Painting && inTimeEvent->animationCount >= 0) + continue; + + // managing call stack + for (int j = stack.count() - 1; j >= 0; j--) { + if (stack[j]->startTime + stack[j]->duration <= inTimeEvent->startTime) { + stack.removeAt(j); + stackRefs.removeAt(j); + } + } + + bool loopDetected = stackRefs.contains(currentEvent); + stack << inTimeEvent; + stackRefs << currentEvent; + + if (loopDetected) { + if (i >= fromIndex && i <= toIndex) { + // for the statistics + currentEvent->isBindingLoop = true; + for (int j = stackRefs.indexOf(currentEvent); j < stackRefs.count()-1; j++) { + QmlRangeEventRelative *nextEventSub = + stackRefs[j]->childrenHash.value(stackRefs[j+1]->eventHashStr); + nextEventSub->inLoopPath = true; + QmlRangeEventRelative *prevEventSub = + stackRefs[j+1]->parentHash.value(stackRefs[j]->eventHashStr); + prevEventSub->inLoopPath = true; + } + } + + // use crossed references to find index in starttimesortedlist + QmlRangeEventStartInstance *head = stack[stackRefs.indexOf(currentEvent)]; + inTimeEvent->bindingLoopHead = endInstanceList[head->endTimeIndex].startTimeIndex; + startInstanceList[inTimeEvent->bindingLoopHead].bindingLoopHead = i; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////// + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::clearQmlRootEvent() +{ + qmlRootEvent.displayName = rootEventName(); + qmlRootEvent.location = QmlEventLocation(); + qmlRootEvent.eventHashStr = rootEventName(); + qmlRootEvent.details = rootEventDescription(); + qmlRootEvent.eventType = QmlJsDebugClient::Binding; + qmlRootEvent.duration = 0; + qmlRootEvent.calls = 0; + qmlRootEvent.minTime = 0; + qmlRootEvent.maxTime = 0; + qmlRootEvent.timePerCall = 0; + qmlRootEvent.percentOfTime = 0; + qmlRootEvent.medianTime = 0; + qmlRootEvent.eventId = -1; + + qDeleteAll(qmlRootEvent.parentHash.values()); + qDeleteAll(qmlRootEvent.childrenHash.values()); + qmlRootEvent.parentHash.clear(); + qmlRootEvent.childrenHash.clear(); +} + +void QmlProfilerDataModel::QmlProfilerDataModelPrivate::insertQmlRootEvent() +{ + // create root event for statistics & insert into list + clearQmlRootEvent(); + QmlRangeEventData *listedRootEvent = rangeEventDictionary.value(rootEventName()); + if (!listedRootEvent) { + listedRootEvent = new QmlRangeEventData; + rangeEventDictionary.insert(rootEventName(), listedRootEvent); + } + *listedRootEvent = qmlRootEvent; +} + +void QmlProfilerDataModel::reloadDetails() +{ + // request binding/signal details from the AST + foreach (QmlRangeEventData *event, d->rangeEventDictionary.values()) { + if (event->eventType != Binding && event->eventType != HandlingSignal) + continue; + + // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them) + if (event->location.filename.isEmpty()) + continue; + + // Skip non-anonymous bindings from Qt4.8 (we already have correct details for them) + if (event->location.column == -1) + continue; + + emit requestDetailsForLocation(event->eventType, event->location); + } + emit reloadDocumentsForDetails(); +} + +void QmlProfilerDataModel::rewriteDetailsString(int eventType, + const QmlJsDebugClient::QmlEventLocation &location, + const QString &newString) +{ + QString eventHashStr = getHashStringForQmlEvent(location, eventType); + QTC_ASSERT(d->rangeEventDictionary.contains(eventHashStr), return); + d->rangeEventDictionary.value(eventHashStr)->details = newString; + emit detailsChanged(d->rangeEventDictionary.value(eventHashStr)->eventId, newString); +} + +void QmlProfilerDataModel::finishedRewritingDetails() +{ + emit reloadDetailLabels(); +} + +//////////////////////////////////////////////////////////////////////////////////// + +bool QmlProfilerDataModel::save(const QString &filename) +{ + if (isEmpty()) { + emit error(tr("No data to save")); + return false; + } + + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + emit error(tr("Could not open %1 for writing").arg(filename)); + return false; + } + + QXmlStreamWriter stream(&file); + stream.setAutoFormatting(true); + stream.writeStartDocument(); + + stream.writeStartElement("trace"); + stream.writeAttribute("version", Constants::PROFILER_FILE_VERSION); + + stream.writeAttribute("traceStart", QString::number(traceStartTime())); + stream.writeAttribute("traceEnd", QString::number(traceEndTime())); + + stream.writeStartElement("eventData"); + stream.writeAttribute("totalTime", QString::number(d->qmlMeasuredTime)); + + foreach (const QmlRangeEventData *eventData, d->rangeEventDictionary.values()) { + stream.writeStartElement("event"); + stream.writeAttribute("index", QString::number(d->rangeEventDictionary.keys().indexOf(eventData->eventHashStr))); + stream.writeTextElement("displayname", eventData->displayName); + stream.writeTextElement("type", qmlEventTypeAsString(eventData->eventType)); + if (!eventData->location.filename.isEmpty()) { + stream.writeTextElement("filename", eventData->location.filename); + stream.writeTextElement("line", QString::number(eventData->location.line)); + stream.writeTextElement("column", QString::number(eventData->location.column)); + } + stream.writeTextElement("details", eventData->details); + stream.writeEndElement(); + } + stream.writeEndElement(); // eventData + + stream.writeStartElement("profilerDataModel"); + foreach (const QmlRangeEventStartInstance &rangedEvent, d->startInstanceList) { + stream.writeStartElement("range"); + stream.writeAttribute("startTime", QString::number(rangedEvent.startTime)); + stream.writeAttribute("duration", QString::number(rangedEvent.duration)); + stream.writeAttribute("eventIndex", QString::number(d->rangeEventDictionary.keys().indexOf(rangedEvent.statsInfo->eventHashStr))); + if (rangedEvent.statsInfo->eventType == QmlJsDebugClient::Painting && rangedEvent.animationCount >= 0) { + // animation frame + stream.writeAttribute("framerate", QString::number(rangedEvent.frameRate)); + stream.writeAttribute("animationcount", QString::number(rangedEvent.animationCount)); + } + stream.writeEndElement(); + } + stream.writeEndElement(); // profilerDataModel + + d->v8DataModel->save(stream); + + stream.writeEndElement(); // trace + stream.writeEndDocument(); + + file.close(); + return true; +} + +void QmlProfilerDataModel::setFilename(const QString &filename) +{ + d->fileName = filename; +} + +void QmlProfilerDataModel::load(const QString &filename) +{ + setFilename(filename); + load(); +} + +// "be strict in your output but tolerant in your inputs" +void QmlProfilerDataModel::load() +{ + QString filename = d->fileName; + + QFile file(filename); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + emit error(tr("Could not open %1 for reading").arg(filename)); + return; + } + + // erase current + clear(); + + setState(AcquiringData); + + bool readingQmlEvents = false; + QHash<int, QmlRangeEventData *> descriptionBuffer; + QmlRangeEventData *currentEvent = 0; + bool startTimesAreSorted = true; + bool validVersion = true; + + // time computation + d->qmlMeasuredTime = 0; + + QXmlStreamReader stream(&file); + + while (validVersion && !stream.atEnd() && !stream.hasError()) { + QXmlStreamReader::TokenType token = stream.readNext(); + QString elementName = stream.name().toString(); + switch (token) { + case QXmlStreamReader::StartDocument : continue; + case QXmlStreamReader::StartElement : { + if (elementName == "trace") { + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute("version")) + validVersion = attributes.value("version").toString() == Constants::PROFILER_FILE_VERSION; + else + validVersion = false; + if (attributes.hasAttribute("traceStart")) + setTraceStartTime(attributes.value("traceStart").toString().toLongLong()); + if (attributes.hasAttribute("traceEnd")) + setTraceEndTime(attributes.value("traceEnd").toString().toLongLong()); + } + if (elementName == "eventData") { + readingQmlEvents = true; + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute("totalTime")) + d->qmlMeasuredTime = attributes.value("totalTime").toString().toDouble(); + break; + } + if (elementName == "v8profile" && !readingQmlEvents) { + d->v8DataModel->load(stream); + break; + } + + if (elementName == "trace") { + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute("traceStart")) + setTraceStartTime(attributes.value("traceStart").toString().toLongLong()); + if (attributes.hasAttribute("traceEnd")) + setTraceEndTime(attributes.value("traceEnd").toString().toLongLong()); + } + + if (elementName == "range") { + QmlRangeEventStartInstance rangedEvent; + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute("startTime")) + rangedEvent.startTime = attributes.value("startTime").toString().toLongLong(); + if (attributes.hasAttribute("duration")) + rangedEvent.duration = attributes.value("duration").toString().toLongLong(); + if (attributes.hasAttribute("framerate")) + rangedEvent.frameRate = attributes.value("framerate").toString().toInt(); + if (attributes.hasAttribute("animationcount")) + rangedEvent.animationCount = attributes.value("animationcount").toString().toInt(); + else + rangedEvent.animationCount = -1; + if (attributes.hasAttribute("eventIndex")) { + int ndx = attributes.value("eventIndex").toString().toInt(); + if (!descriptionBuffer.value(ndx)) + descriptionBuffer[ndx] = new QmlRangeEventData; + rangedEvent.statsInfo = descriptionBuffer.value(ndx); + } + rangedEvent.endTimeIndex = d->endInstanceList.count(); + + if (!d->startInstanceList.isEmpty() + && rangedEvent.startTime < d->startInstanceList.last().startTime) + startTimesAreSorted = false; + d->startInstanceList << rangedEvent; + + QmlRangeEventEndInstance endTimeEvent; + endTimeEvent.endTime = rangedEvent.startTime + rangedEvent.duration; + endTimeEvent.startTimeIndex = d->startInstanceList.count()-1; + endTimeEvent.description = rangedEvent.statsInfo; + d->endInstanceList << endTimeEvent; + break; + } + + if (readingQmlEvents) { + if (elementName == "event") { + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute("index")) { + int ndx = attributes.value("index").toString().toInt(); + if (!descriptionBuffer.value(ndx)) + descriptionBuffer[ndx] = new QmlRangeEventData; + currentEvent = descriptionBuffer[ndx]; + } else { + currentEvent = 0; + } + break; + } + + // the remaining are eventdata or v8eventdata elements + if (!currentEvent) + break; + + stream.readNext(); + if (stream.tokenType() != QXmlStreamReader::Characters) + break; + QString readData = stream.text().toString(); + + if (elementName == "displayname") { + currentEvent->displayName = readData; + break; + } + if (elementName == "type") { + currentEvent->eventType = qmlEventTypeAsEnum(readData); + break; + } + if (elementName == "filename") { + currentEvent->location.filename = readData; + break; + } + if (elementName == "line") { + currentEvent->location.line = readData.toInt(); + break; + } + if (elementName == "column") { + currentEvent->location.column = readData.toInt(); + } + if (elementName == "details") { + currentEvent->details = readData; + break; + } + } + break; + } + case QXmlStreamReader::EndElement : { + if (elementName == "event") { + currentEvent = 0; + break; + } + if (elementName == "eventData") { + readingQmlEvents = false; + break; + } + } + default: break; + } + } + + file.close(); + + if (stream.hasError()) { + emit error(tr("Error while parsing %1").arg(filename)); + clear(); + return; + } + + stream.clear(); + + if (!validVersion) { + clear(); + emit error(tr("Invalid version of QML Trace file.")); + return; + } + + // move the buffered data to the details cache + foreach (QmlRangeEventData *desc, descriptionBuffer.values()) { + desc->eventHashStr = getHashStringForQmlEvent(desc->location, desc->eventType);; + d->rangeEventDictionary[desc->eventHashStr] = desc; + } + + // sort startTimeSortedList + if (!startTimesAreSorted) { + qSort(d->startInstanceList.begin(), d->startInstanceList.end(), compareStartTimes); + for (int i = 0; i< d->startInstanceList.count(); i++) { + QmlRangeEventStartInstance startTimeData = d->startInstanceList[i]; + d->endInstanceList[startTimeData.endTimeIndex].startTimeIndex = i; + } + qSort(d->endInstanceList.begin(), d->endInstanceList.end(), compareStartIndexes); + } + + emit countChanged(); + + descriptionBuffer.clear(); + + setState(ProcessingData); + d->postProcess(); +} + +//////////////////////////////////////////////////////////////////////////////////// + +QmlProfilerDataModel::State QmlProfilerDataModel::currentState() const +{ + return d->listState; +} + +int QmlProfilerDataModel::getCurrentStateFromQml() const +{ + return (int)d->listState; +} + +void QmlProfilerDataModel::setState(QmlProfilerDataModel::State state) +{ + // It's not an error, we are continuously calling "AcquiringData" for example + if (d->listState == state) + return; + + switch (state) { + case Empty: + // if it's not empty, complain but go on + QTC_ASSERT(isEmpty(), /**/); + break; + case AcquiringData: + // we're not supposed to receive new data while processing older data + QTC_ASSERT(d->listState != ProcessingData, return); + break; + case ProcessingData: + QTC_ASSERT(d->listState == AcquiringData, return); + break; + case Done: + QTC_ASSERT(d->listState == ProcessingData || d->listState == Empty, return); + break; + default: + emit error("Trying to set unknown state in events list"); + break; + } + + d->listState = state; + emit stateChanged(); + + // special: if we were done with an empty list, clean internal data and go back to empty + if (d->listState == Done && isEmpty()) { + clear(); + } + return; +} + +} // namespace Internal +} // namespace QmlProfiler + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventData, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventStartInstance, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventEndInstance, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QmlRangeEventRelative, Q_MOVABLE_TYPE); +QT_END_NAMESPACE diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.h b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h new file mode 100644 index 0000000000..7e2ab03470 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h @@ -0,0 +1,202 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef QMLPROFILERDATAMODEL_H +#define QMLPROFILERDATAMODEL_H + +#include <qmljsdebugclient/qmlprofilereventtypes.h> +#include <qmljsdebugclient/qmlprofilereventlocation.h> +#include "qv8profilerdatamodel.h" + +#include <QHash> +#include <QObject> + +namespace QmlProfiler { +namespace Internal { + +// used for parents and children +struct QmlRangeEventRelative; + +struct QmlRangeEventData +{ + QmlRangeEventData(); + ~QmlRangeEventData(); + + int eventId; + QString displayName; + QString eventHashStr; + QString details; + QmlJsDebugClient::QmlEventLocation location; + QmlJsDebugClient::QmlEventType eventType; + + QHash <QString, QmlRangeEventRelative *> parentHash; + QHash <QString, QmlRangeEventRelative *> childrenHash; + + qint64 duration; + qint64 calls; + qint64 minTime; + qint64 maxTime; + double timePerCall; + double percentOfTime; + qint64 medianTime; + + bool isBindingLoop; + + QmlRangeEventData &operator=(const QmlRangeEventData &ref); +}; + +struct QmlRangeEventRelative { + QmlRangeEventRelative(QmlRangeEventData *from) : reference(from), duration(0), calls(0), inLoopPath(false) {} + QmlRangeEventRelative(QmlRangeEventRelative *from) : reference(from->reference), duration(from->duration), calls(from->calls), inLoopPath(from->inLoopPath) {} + QmlRangeEventData *reference; + qint64 duration; + qint64 calls; + bool inLoopPath; +}; + +class QmlProfilerDataModel : public QObject +{ + Q_OBJECT +public: + enum State { + Empty, + AcquiringData, + ProcessingData, + Done + }; + + explicit QmlProfilerDataModel(QObject *parent = 0); + ~QmlProfilerDataModel(); + + QList<QmlRangeEventData *> getEventDescriptions() const; + QmlRangeEventData *eventDescription(int eventId) const; + QList<QV8EventData *> getV8Events() const; + QV8EventData *v8EventDescription(int eventId) const; + + static QString getHashStringForQmlEvent(const QmlJsDebugClient::QmlEventLocation &location, int eventType); + static QString getHashStringForV8Event(const QString &displayName, const QString &function); + static QString rootEventName(); + static QString rootEventDescription(); + static QString qmlEventTypeAsString(QmlJsDebugClient::QmlEventType typeEnum); + static QmlJsDebugClient::QmlEventType qmlEventTypeAsEnum(const QString &typeString); + + int findFirstIndex(qint64 startTime) const; + int findFirstIndexNoParents(qint64 startTime) const; + int findLastIndex(qint64 endTime) const; + Q_INVOKABLE qint64 firstTimeMark() const; + Q_INVOKABLE qint64 lastTimeMark() const; + + // data access + Q_INVOKABLE int count() const; + Q_INVOKABLE bool isEmpty() const; + Q_INVOKABLE qint64 getStartTime(int index) const; + Q_INVOKABLE qint64 getEndTime(int index) const; + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE int getType(int index) const; + Q_INVOKABLE int getNestingLevel(int index) const; + Q_INVOKABLE int getNestingDepth(int index) const; + Q_INVOKABLE QString getFilename(int index) const; + Q_INVOKABLE int getLine(int index) const; + Q_INVOKABLE int getColumn(int index) const; + Q_INVOKABLE QString getDetails(int index) const; + Q_INVOKABLE int getEventId(int index) const; + Q_INVOKABLE int getBindingLoopDest(int index) const; + Q_INVOKABLE int getFramerate(int index) const; + Q_INVOKABLE int getAnimationCount(int index) const; + Q_INVOKABLE int getMaximumAnimationCount() const; + Q_INVOKABLE int getMinimumAnimationCount() const; + + + // per-type data + Q_INVOKABLE int uniqueEventsOfType(int type) const; + Q_INVOKABLE int maxNestingForType(int type) const; + Q_INVOKABLE QString eventTextForType(int type, int index) const; + Q_INVOKABLE QString eventDisplayNameForType(int type, int index) const; + Q_INVOKABLE int eventIdForType(int type, int index) const; + Q_INVOKABLE int eventPosInType(int index) const; + + Q_INVOKABLE qint64 traceStartTime() const; + Q_INVOKABLE qint64 traceEndTime() const; + Q_INVOKABLE qint64 traceDuration() const; + Q_INVOKABLE qint64 qmlMeasuredTime() const; + Q_INVOKABLE qint64 v8MeasuredTime() const; + + void compileStatistics(qint64 startTime, qint64 endTime); + State currentState() const; + Q_INVOKABLE int getCurrentStateFromQml() const; + +signals: + void stateChanged(); + void countChanged(); + void error(const QString &error); + + void requestDetailsForLocation(int eventType, const QmlJsDebugClient::QmlEventLocation &location); + void detailsChanged(int eventId, const QString &newString); + void reloadDetailLabels(); + void reloadDocumentsForDetails(); + +public slots: + void clear(); + + void addRangedEvent(int type, qint64 startTime, qint64 length, + const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location); + void addV8Event(int depth,const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime); + void addFrameEvent(qint64 time, int framerate, int animationcount); + void setTraceStartTime(qint64 time); + void setTraceEndTime(qint64 time); + + void complete(); + + bool save(const QString &filename); + void load(const QString &filename); + void setFilename(const QString &filename); + void load(); + + void rewriteDetailsString(int eventType, const QmlJsDebugClient::QmlEventLocation &location, const QString &newString); + void finishedRewritingDetails(); + +private: + void setState(State state); + void reloadDetails(); + +private: + class QmlProfilerDataModelPrivate; + QmlProfilerDataModelPrivate *d; + + friend class QV8ProfilerDataModel; +}; + + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERDATAMODEL_H diff --git a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h index 561717c890..4f61f8a640 100644 --- a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h +++ b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h @@ -35,7 +35,7 @@ #include <QObject> -#include "qmljsdebugclient/qmlprofilereventlocation.h" +#include <qmljsdebugclient/qmlprofilereventlocation.h> #include <qmljs/qmljsdocument.h> namespace QmlProfiler { diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.cpp b/src/plugins/qmlprofiler/qmlprofilerengine.cpp index d16ec2b840..5990df7c4c 100644 --- a/src/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -35,8 +35,6 @@ #include "codaqmlprofilerrunner.h" #include "localqmlprofilerrunner.h" #include "remotelinuxqmlprofilerrunner.h" -#include "qmlprofilerplugin.h" -#include "qmlprofilertool.h" #include <analyzerbase/analyzermanager.h> #include <coreplugin/icore.h> @@ -76,16 +74,11 @@ public: QmlProfilerEngine *q; - //AnalyzerStartParameters m_params; + QmlProfilerStateManager *m_profilerState; + AbstractQmlProfilerRunner *m_runner; - bool m_running; - bool m_fetchingData; - bool m_hasData; - bool m_fetchDataFromStart; - bool m_delayedDelete; QTimer m_noDebugOutputTimer; QmlJsDebugClient::QDeclarativeOutputParser m_outputParser; - QTimer m_runningTimer; }; AbstractQmlProfilerRunner * @@ -137,10 +130,7 @@ QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool, : IAnalyzerEngine(tool, sp, runConfiguration) , d(new QmlProfilerEnginePrivate(this)) { - d->m_running = false; - d->m_fetchingData = false; - d->m_fetchDataFromStart = false; - d->m_delayedDelete = false; + d->m_profilerState = 0; // Only wait 4 seconds for the 'Waiting for connection' on application ouput, then just try to connect // (application output might be redirected / blocked) @@ -157,29 +147,31 @@ QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool, this, SLOT(processIsRunning())); connect(&d->m_outputParser, SIGNAL(errorMessage(QString)), this, SLOT(wrongSetupMessageBox(QString))); - - d->m_runningTimer.setInterval(100); // ten times per second - connect(&d->m_runningTimer, SIGNAL(timeout()), this, SIGNAL(timeUpdate())); } QmlProfilerEngine::~QmlProfilerEngine() { - if (d->m_running) + if (d->m_profilerState && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) stop(); delete d; } bool QmlProfilerEngine::start() { + QTC_ASSERT(d->m_profilerState, return false); + if (d->m_runner) { delete d->m_runner; d->m_runner = 0; } + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStarting); + if (QmlProjectManager::QmlProjectRunConfiguration *rc = qobject_cast<QmlProjectManager::QmlProjectRunConfiguration *>(runConfiguration())) { if (rc->observerPath().isEmpty()) { QmlProjectManager::QmlProjectPlugin::showQmlObserverToolWarning(); + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); AnalyzerManager::stopTool(); return false; } @@ -190,13 +182,14 @@ bool QmlProfilerEngine::start() if (LocalQmlProfilerRunner *qmlRunner = qobject_cast<LocalQmlProfilerRunner *>(d->m_runner)) { if (!qmlRunner->hasExecutable()) { showNonmodalWarning(tr("No executable file to launch.")); + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); AnalyzerManager::stopTool(); return false; } } if (d->m_runner) { - connect(d->m_runner, SIGNAL(stopped()), this, SLOT(stopped())); + connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded())); connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), this, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); d->m_runner->start(); @@ -205,82 +198,80 @@ bool QmlProfilerEngine::start() emit processRunning(startParameters().connParams.port); } - - d->m_running = true; - d->m_delayedDelete = false; - d->m_runningTimer.start(); - - if (d->m_fetchDataFromStart) { - d->m_fetchingData = true; - d->m_hasData = false; - } - + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning); emit starting(this); return true; } void QmlProfilerEngine::stop() { - if (d->m_fetchingData) { - if (d->m_running) - d->m_delayedDelete = true; - // will result in dataReceived() call - emit stopRecording(); - d->m_fetchDataFromStart = true; - } else { - finishProcess(); - d->m_fetchDataFromStart = false; + QTC_ASSERT(d->m_profilerState, return); + + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppRunning : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopRequested); + break; + } + case QmlProfilerStateManager::AppReadyToStop : { + cancelProcess(); + break; + } + case QmlProfilerStateManager::AppKilled : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); + break; + } + default: + qDebug() << tr("Unexpected engine stop from state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__)); + break; } } -void QmlProfilerEngine::stopped() +void QmlProfilerEngine::processEnded() { - // if it was killed, preserve recording flag - if (d->m_running) - d->m_fetchDataFromStart = d->m_fetchingData; - - // user feedback - if (d->m_running && d->m_fetchingData && !d->m_hasData) { - showNonmodalWarning(tr("Application finished before loading profiled data.\n Please use the stop button instead.")); - emit applicationDied(); - } + QTC_ASSERT(d->m_profilerState, return); - d->m_running = false; - d->m_runningTimer.stop(); - AnalyzerManager::stopTool(); - emit finished(); - emit recordingChanged(d->m_fetchDataFromStart); -} + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppRunning : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); + AnalyzerManager::stopTool(); -void QmlProfilerEngine::setFetchingData(bool b) -{ - d->m_fetchingData = b; - if (d->m_running && b) - d->m_hasData = false; - if (!d->m_running) - d->m_fetchDataFromStart = b; + emit finished(); + break; + } + case QmlProfilerStateManager::AppStopped : + // fallthrough + case QmlProfilerStateManager::AppKilled : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); + break; + } + default: + qDebug() << tr("Process died unexpectedly from state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__)); + break; + } } -void QmlProfilerEngine::dataReceived() +void QmlProfilerEngine::cancelProcess() { - if (d->m_delayedDelete) - finishProcess(); - d->m_delayedDelete = false; - d->m_hasData = true; -} + QTC_ASSERT(d->m_profilerState, return); -void QmlProfilerEngine::finishProcess() -{ - // user stop? - if (d->m_running) { - d->m_running = false; - d->m_runningTimer.stop(); - d->m_noDebugOutputTimer.stop(); - if (d->m_runner) - d->m_runner->stop(); - emit finished(); - emit recordingChanged(d->m_fetchDataFromStart); + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppReadyToStop : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); + break; + } + case QmlProfilerStateManager::AppRunning : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); + break; } + default: { + qDebug() << tr("Unexpected process termination requested with state %1 in %2:%3").arg(d->m_profilerState->currentStateAsString(), QString(__FILE__), QString::number(__LINE__)); + return; + } + } + + if (d->m_runner) + d->m_runner->stop(); + emit finished(); } void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format) @@ -306,7 +297,10 @@ void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage) infoBox->show(); - finishProcess(); + // KILL + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); + AnalyzerManager::stopTool(); + emit finished(); } void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button) @@ -345,5 +339,44 @@ void QmlProfilerEngine::processIsRunning(quint16 port) emit processRunning(d->m_runner->debugPort()); } +//////////////////////////////////////////////////////////////// +// Profiler State +void QmlProfilerEngine::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) +{ + // disconnect old + if (d->m_profilerState) { + disconnect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); + } + + d->m_profilerState = profilerState; + + // connect + if (d->m_profilerState) { + connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); + } +} + +void QmlProfilerEngine::profilerStateChanged() +{ + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppReadyToStop : { + cancelProcess(); + break; + } + case QmlProfilerStateManager::Idle : { + // for some reason the engine is not deleted when it goes to idle + // a new one will be created on the next run, and this one will + // be only deleted if the new one is running the same app + + // we need to explictly disconnect it here without expecting a deletion + // as it will not be run any more, otherwise we will get funny side effects + registerProfilerStateManager(0); + break; + } + default: + break; + } +} + } // namespace Internal } // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.h b/src/plugins/qmlprofiler/qmlprofilerengine.h index b0199c3131..c438e69329 100644 --- a/src/plugins/qmlprofiler/qmlprofilerengine.h +++ b/src/plugins/qmlprofiler/qmlprofilerengine.h @@ -34,6 +34,7 @@ #define QMLPROFILERENGINE_H #include <analyzerbase/ianalyzerengine.h> +#include "qmlprofilerstatemanager.h" #include <utils/outputformat.h> namespace QmlProfiler { @@ -49,29 +50,29 @@ public: ProjectExplorer::RunConfiguration *runConfiguration); ~QmlProfilerEngine(); + void registerProfilerStateManager( QmlProfilerStateManager *profilerState ); + static void showNonmodalWarning(const QString &warningMsg); signals: - void processRunning(int port); - void stopRecording(); + void processRunning(quint16 port); void timeUpdate(); - void recordingChanged(bool recording); - void applicationDied(); public slots: bool start(); void stop(); private slots: - void stopped(); + void processEnded(); - void setFetchingData(bool); - void dataReceived(); - void finishProcess(); + void cancelProcess(); void logApplicationMessage(const QString &msg, Utils::OutputFormat format); void wrongSetupMessageBox(const QString &errorMessage); void wrongSetupMessageBoxFinished(int); void processIsRunning(quint16 port = 0); +private slots: + void profilerStateChanged(); + private: class QmlProfilerEnginePrivate; QmlProfilerEnginePrivate *d; diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.cpp b/src/plugins/qmlprofiler/qmlprofilereventview.cpp index 294c4ed555..169635fec9 100644 --- a/src/plugins/qmlprofiler/qmlprofilereventview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilereventview.cpp @@ -48,6 +48,11 @@ #include <QVBoxLayout> #include <QHBoxLayout> +#include "qmlprofilerviewmanager.h" +#include "qmlprofilertool.h" +#include <QMenu> + +#include <utils/qtcassert.h> using namespace QmlJsDebugClient; @@ -90,31 +95,63 @@ public: //////////////////////////////////////////////////////////////////////////////////// -QmlProfilerEventsWidget::QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent) : QWidget(parent) +class QmlProfilerEventsWidget::QmlProfilerEventsWidgetPrivate { - setObjectName("QmlProfilerEventsView"); +public: + QmlProfilerEventsWidgetPrivate(QmlProfilerEventsWidget *qq):q(qq) {} + ~QmlProfilerEventsWidgetPrivate() {} + + QmlProfilerEventsWidget *q; + + Analyzer::IAnalyzerTool *m_profilerTool; + QmlProfilerViewManager *m_viewContainer; + + QmlProfilerEventsMainView *m_eventTree; + QmlProfilerEventsParentsAndChildrenView *m_eventChildren; + QmlProfilerEventsParentsAndChildrenView *m_eventParents; + QmlProfilerDataModel *m_profilerDataModel; - m_eventTree = new QmlProfilerEventsMainView(model, this); - m_eventTree->setViewType(QmlProfilerEventsMainView::EventsView); - connect(m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); - connect(m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int))); + bool m_globalStatsEnabled; +}; + +QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerDataModel *profilerDataModel ) + : QWidget(parent), d(new QmlProfilerEventsWidgetPrivate(this)) +{ + setObjectName("QmlProfilerEventsView"); - m_eventChildren = new QmlProfilerEventsParentsAndChildrenView(model, QmlProfilerEventsParentsAndChildrenView::ChildrenView, this); - m_eventParents = new QmlProfilerEventsParentsAndChildrenView(model, QmlProfilerEventsParentsAndChildrenView::ParentsView, this); - connect(m_eventTree, SIGNAL(eventSelected(int)), m_eventChildren, SLOT(displayEvent(int))); - connect(m_eventTree, SIGNAL(eventSelected(int)), m_eventParents, SLOT(displayEvent(int))); - connect(m_eventChildren, SIGNAL(eventClicked(int)), m_eventTree, SLOT(selectEvent(int))); - connect(m_eventParents, SIGNAL(eventClicked(int)), m_eventTree, SLOT(selectEvent(int))); + d->m_profilerDataModel = profilerDataModel; + connect(d->m_profilerDataModel, SIGNAL(stateChanged()), + this, SLOT(profilerDataModelStateChanged())); + + d->m_eventTree = new QmlProfilerEventsMainView(QmlProfilerEventsMainView::EventsView, this, d->m_profilerDataModel); + connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); + connect(d->m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int))); + + d->m_eventChildren = new QmlProfilerEventsParentsAndChildrenView( + QmlProfilerEventsParentsAndChildrenView::ChildrenView, + this, + d->m_profilerDataModel); + d->m_eventParents = new QmlProfilerEventsParentsAndChildrenView( + QmlProfilerEventsParentsAndChildrenView::ParentsView, + this, + d->m_profilerDataModel); + connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventChildren, SLOT(displayEvent(int))); + connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventParents, SLOT(displayEvent(int))); + connect(d->m_eventChildren, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int))); + connect(d->m_eventParents, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int))); // widget arrangement QVBoxLayout *groupLayout = new QVBoxLayout; groupLayout->setContentsMargins(0,0,0,0); groupLayout->setSpacing(0); Core::MiniSplitter *splitterVertical = new Core::MiniSplitter; - splitterVertical->addWidget(m_eventTree); + splitterVertical->addWidget(d->m_eventTree); Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter; - splitterHorizontal->addWidget(m_eventParents); - splitterHorizontal->addWidget(m_eventChildren); + splitterHorizontal->addWidget(d->m_eventParents); + splitterHorizontal->addWidget(d->m_eventChildren); splitterHorizontal->setOrientation(Qt::Horizontal); splitterVertical->addWidget(splitterHorizontal); splitterVertical->setOrientation(Qt::Vertical); @@ -123,23 +160,21 @@ QmlProfilerEventsWidget::QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEv groupLayout->addWidget(splitterVertical); setLayout(groupLayout); - m_eventStatistics = model; - if (model) { - connect(model, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged())); - } - - m_globalStatsEnabled = true; + d->m_profilerTool = profilerTool; + d->m_viewContainer = container; + d->m_globalStatsEnabled = true; } QmlProfilerEventsWidget::~QmlProfilerEventsWidget() { + delete d; } -void QmlProfilerEventsWidget::eventListStateChanged() +void QmlProfilerEventsWidget::profilerDataModelStateChanged() { - if (m_eventStatistics) { - QmlProfilerEventList::State newState = m_eventStatistics->currentState(); - if (newState == QmlProfilerEventList::Empty) { + if (d->m_profilerDataModel) { + QmlProfilerDataModel::State newState = d->m_profilerDataModel->currentState(); + if (newState == QmlProfilerDataModel::Empty) { clear(); } } @@ -148,57 +183,119 @@ void QmlProfilerEventsWidget::eventListStateChanged() void QmlProfilerEventsWidget::switchToV8View() { setObjectName("QmlProfilerV8ProfileView"); - m_eventTree->setViewType(QmlProfilerEventsMainView::V8ProfileView); - m_eventParents->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ParentsView); - m_eventChildren->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ChildrenView); + d->m_eventTree->setViewType(QmlProfilerEventsMainView::V8ProfileView); + d->m_eventParents->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ParentsView); + d->m_eventChildren->setViewType(QmlProfilerEventsParentsAndChildrenView::V8ChildrenView); setToolTip(tr("Trace information from the v8 JavaScript engine. Available only in Qt5 based applications")); } void QmlProfilerEventsWidget::clear() { - m_eventTree->clear(); - m_eventChildren->clear(); - m_eventParents->clear(); + d->m_eventTree->clear(); + d->m_eventChildren->clear(); + d->m_eventParents->clear(); } void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) { clear(); - m_eventTree->getStatisticsInRange(rangeStart, rangeEnd); - m_globalStatsEnabled = m_eventTree->isRangeGlobal(rangeStart, rangeEnd); + d->m_eventTree->getStatisticsInRange(rangeStart, rangeEnd); + d->m_globalStatsEnabled = d->m_eventTree->isRangeGlobal(rangeStart, rangeEnd); } QModelIndex QmlProfilerEventsWidget::selectedItem() const { - return m_eventTree->selectedItem(); + return d->m_eventTree->selectedItem(); } void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) { - emit contextMenuRequested(ev->globalPos()); + QTC_ASSERT(d->m_viewContainer, return;); + + QMenu menu; + QAction *copyRowAction = 0; + QAction *copyTableAction = 0; + QAction *showExtendedStatsAction = 0; + QAction *getLocalStatsAction = 0; + QAction *getGlobalStatsAction = 0; + + QmlProfilerTool *profilerTool = qobject_cast<QmlProfilerTool *>(d->m_profilerTool); + QPoint position = ev->globalPos(); + + if (profilerTool) { + QList <QAction *> commonActions = profilerTool->profilerContextMenuActions(); + foreach (QAction *act, commonActions) { + menu.addAction(act); + } + } + + if (mouseOnTable(position)) { + menu.addSeparator(); + if (selectedItem().isValid()) + copyRowAction = menu.addAction(tr("Copy Row")); + copyTableAction = menu.addAction(tr("Copy Table")); + + if (isQml()) { + // only for qml events view, not for v8 + showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics")); + showExtendedStatsAction->setCheckable(true); + showExtendedStatsAction->setChecked(showExtendedStatistics()); + } + } + + if (isQml()) { + menu.addSeparator(); + getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); + if (!d->m_viewContainer->hasValidSelection()) + getLocalStatsAction->setEnabled(false); + getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); + if (hasGlobalStats()) + getGlobalStatsAction->setEnabled(false); + } + + QAction *selectedAction = menu.exec(position); + + if (selectedAction) { + if (selectedAction == copyRowAction) + copyRowToClipboard(); + if (selectedAction == copyTableAction) + copyTableToClipboard(); + if (selectedAction == getLocalStatsAction) { + getStatisticsInRange(d->m_viewContainer->selectionStart(), + d->m_viewContainer->selectionEnd()); + } + if (selectedAction == getGlobalStatsAction) { + if (d->m_profilerDataModel) { + getStatisticsInRange(d->m_profilerDataModel->traceStartTime(), + d->m_profilerDataModel->traceEndTime()); + } + } + if (selectedAction == showExtendedStatsAction) + setShowExtendedStatistics(!showExtendedStatistics()); + } } bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const { - QPoint tableTopLeft = m_eventTree->mapToGlobal(QPoint(0,0)); - QPoint tableBottomRight = m_eventTree->mapToGlobal(QPoint(m_eventTree->width(), m_eventTree->height())); + QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0)); + QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height())); return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y()); } void QmlProfilerEventsWidget::copyTableToClipboard() const { - m_eventTree->copyTableToClipboard(); + d->m_eventTree->copyTableToClipboard(); } void QmlProfilerEventsWidget::copyRowToClipboard() const { - m_eventTree->copyRowToClipboard(); + d->m_eventTree->copyRowToClipboard(); } void QmlProfilerEventsWidget::updateSelectedEvent(int eventId) const { - if (m_eventTree->selectedEventId() != eventId) - m_eventTree->selectEvent(eventId); + if (d->m_eventTree->selectedEventId() != eventId) + d->m_eventTree->selectEvent(eventId); } void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) @@ -207,22 +304,31 @@ void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, in // Our javascript trace data does not store column information // thus we ignore it here Q_UNUSED(column); - m_eventTree->selectEventByLocation(filename, line); + d->m_eventTree->selectEventByLocation(filename, line); } bool QmlProfilerEventsWidget::hasGlobalStats() const { - return m_globalStatsEnabled; + return d->m_globalStatsEnabled; } void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show) { - m_eventTree->setShowExtendedStatistics(show); + d->m_eventTree->setShowExtendedStatistics(show); } bool QmlProfilerEventsWidget::showExtendedStatistics() const { - return m_eventTree->showExtendedStatistics(); + return d->m_eventTree->showExtendedStatistics(); +} + +bool QmlProfilerEventsWidget::isQml() const +{ + return d->m_eventTree->viewType() == QmlProfilerEventsMainView::EventsView; +} +bool QmlProfilerEventsWidget::isV8() const +{ + return d->m_eventTree->viewType() == QmlProfilerEventsMainView::V8ProfileView; } //////////////////////////////////////////////////////////////////////////////////// @@ -232,8 +338,8 @@ class QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate public: QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {} - void buildModelFromList(const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList = QmlEventDescriptions() ); - void buildV8ModelFromList( const QV8EventDescriptions &list ); + void buildModelFromList(const QList<QmlRangeEventData *> &list, QStandardItem *parentItem ); + void buildV8ModelFromList( const QList<QV8EventData *> &list ); int getFieldCount(); QString textForItem(QStandardItem *item, bool recursive) const; @@ -242,7 +348,7 @@ public: QmlProfilerEventsMainView *q; QmlProfilerEventsMainView::ViewTypes m_viewType; - QmlProfilerEventList *m_eventStatistics; + QmlProfilerDataModel *m_profilerDataModel; QStandardItemModel *m_model; QList<bool> m_fieldShown; QHash<int, int> m_columnIndex; // maps field enum to column index @@ -254,8 +360,10 @@ public: //////////////////////////////////////////////////////////////////////////////////// -QmlProfilerEventsMainView::QmlProfilerEventsMainView(QmlProfilerEventList *model, QWidget *parent) : - QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this)) +QmlProfilerEventsMainView::QmlProfilerEventsMainView(ViewTypes viewType, + QWidget *parent, + QmlProfilerDataModel *dataModel) + : QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this)) { setObjectName("QmlProfilerEventsTable"); header()->setResizeMode(QHeaderView::Interactive); @@ -268,15 +376,17 @@ QmlProfilerEventsMainView::QmlProfilerEventsMainView(QmlProfilerEventList *model setModel(d->m_model); connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); - d->m_eventStatistics = 0; - setEventStatisticsModel(model); + d->m_profilerDataModel = dataModel; + connect(d->m_profilerDataModel,SIGNAL(stateChanged()), + this,SLOT(profilerDataModelStateChanged())); + connect(d->m_profilerDataModel,SIGNAL(detailsChanged(int,QString)), + this,SLOT(changeDetailsForEvent(int,QString))); d->m_firstNumericColumn = 0; d->m_preventSelectBounce = false; d->m_showExtendedStatistics = false; - // default view - setViewType(EventsView); + setViewType(viewType); } QmlProfilerEventsMainView::~QmlProfilerEventsMainView() @@ -286,24 +396,11 @@ QmlProfilerEventsMainView::~QmlProfilerEventsMainView() delete d; } -void QmlProfilerEventsMainView::setEventStatisticsModel( QmlProfilerEventList *model ) -{ - if (d->m_eventStatistics) { - disconnect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged())); - disconnect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString))); - } - d->m_eventStatistics = model; - if (model) { - connect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged())); - connect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString))); - } -} - -void QmlProfilerEventsMainView::eventListStateChanged() +void QmlProfilerEventsMainView::profilerDataModelStateChanged() { - if (d->m_eventStatistics) { - QmlProfilerEventList::State newState = d->m_eventStatistics->currentState(); - if (newState == QmlProfilerEventList::Done) + if (d->m_profilerDataModel) { + QmlProfilerDataModel::State newState = d->m_profilerDataModel->currentState(); + if (newState == QmlProfilerDataModel::Done) buildModel(); } } @@ -320,6 +417,11 @@ void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show) } } +QmlProfilerEventsMainView::ViewTypes QmlProfilerEventsMainView::viewType() const +{ + return d->m_viewType; +} + void QmlProfilerEventsMainView::setViewType(ViewTypes type) { d->m_viewType = type; @@ -466,12 +568,12 @@ int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount() void QmlProfilerEventsMainView::buildModel() { - if (d->m_eventStatistics) { + if (d->m_profilerDataModel) { clear(); if (d->m_viewType == V8ProfileView) - d->buildV8ModelFromList( d->m_eventStatistics->getV8Events() ); + d->buildV8ModelFromList( d->m_profilerDataModel->getV8Events() ); else - d->buildModelFromList( d->m_eventStatistics->getEventDescriptions(), d->m_model->invisibleRootItem() ); + d->buildModelFromList( d->m_profilerDataModel->getEventDescriptions(), d->m_model->invisibleRootItem() ); setShowExtendedStatistics(d->m_showExtendedStatistics); @@ -489,18 +591,15 @@ void QmlProfilerEventsMainView::buildModel() } } -void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFromList( const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList ) +void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFromList( const QList<QmlRangeEventData *> &list, QStandardItem *parentItem) { - foreach (QmlEventData *binding, list) { - if (visitedFunctionsList.contains(binding)) - continue; - + foreach (QmlRangeEventData *binding, list) { if (binding->calls == 0) continue; QList<QStandardItem *> newRow; if (m_fieldShown[Name]) { - newRow << new EventsViewItem(binding->displayname); + newRow << new EventsViewItem(binding->displayName); } if (m_fieldShown[Type]) { @@ -573,7 +672,7 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom } } -void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFromList(const QV8EventDescriptions &list) +void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFromList(const QList<QV8EventData *> &list) { for (int index = 0; index < list.count(); index++) { QV8EventData *v8event = list.at(index); @@ -650,13 +749,17 @@ QString QmlProfilerEventsMainView::nameForType(int typeNumber) void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) { - d->m_eventStatistics->compileStatistics(rangeStart, rangeEnd); + if (d->m_profilerDataModel) + d->m_profilerDataModel->compileStatistics(rangeStart, rangeEnd); buildModel(); } bool QmlProfilerEventsMainView::isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const { - return d->m_eventStatistics->traceStartTime() == rangeStart && d->m_eventStatistics->traceEndTime() == rangeEnd; + if (d->m_profilerDataModel) + return d->m_profilerDataModel->traceStartTime() == rangeStart && d->m_profilerDataModel->traceEndTime() == rangeEnd; + else + return true; } int QmlProfilerEventsMainView::selectedEventId() const @@ -692,7 +795,7 @@ void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index) // show in callers/callees subwindow emit eventSelected(infoItem->data(EventIdRole).toInt()); - // show in timelineview + // show in timelinerenderer if (d->m_viewType == EventsView) { emit showEventInTimeline(infoItem->data(EventIdRole).toInt()); } @@ -820,9 +923,11 @@ void QmlProfilerEventsMainView::copyRowToClipboard() const //////////////////////////////////////////////////////////////////////////////////// -QmlProfilerEventsParentsAndChildrenView::QmlProfilerEventsParentsAndChildrenView(QmlJsDebugClient::QmlProfilerEventList *model, SubViewType subtableType, QWidget *parent):QTreeView(parent) +QmlProfilerEventsParentsAndChildrenView::QmlProfilerEventsParentsAndChildrenView( + SubViewType subtableType, QWidget *parent, QmlProfilerDataModel *model) + : QTreeView(parent) { - m_eventList = model; + m_profilerDataModel = model; setModel(new QStandardItemModel(this)); setRootIsDecorated(false); setFrameStyle(QFrame::NoFrame); @@ -844,30 +949,33 @@ void QmlProfilerEventsParentsAndChildrenView::setViewType(SubViewType type) void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId) { + if (!m_profilerDataModel) + return; + bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView; bool isChildren = m_subtableType == ChildrenView || m_subtableType == V8ChildrenView; if (isV8) { - QmlJsDebugClient::QV8EventData *v8event = m_eventList->v8EventDescription(eventId); + QV8EventData *v8event = m_profilerDataModel->v8EventDescription(eventId); if (v8event) { if (isChildren) { - QList <QmlJsDebugClient::QV8EventSub *> childrenList = v8event->childrenHash.values(); + QList <QV8EventSub *> childrenList = v8event->childrenHash.values(); rebuildTree((QObject *)&childrenList); } else { - QList <QmlJsDebugClient::QV8EventSub *> parentList = v8event->parentHash.values(); + QList <QV8EventSub *> parentList = v8event->parentHash.values(); rebuildTree((QObject *)&parentList); } } } else { - QmlJsDebugClient::QmlEventData *qmlEvent = m_eventList->eventDescription(eventId); + QmlRangeEventData *qmlEvent = m_profilerDataModel->eventDescription(eventId); if (qmlEvent) { if (isChildren) { - QList <QmlJsDebugClient::QmlEventSub *> childrenList = qmlEvent->childrenHash.values(); + QList <QmlRangeEventRelative *> childrenList = qmlEvent->childrenHash.values(); rebuildTree((QObject *)&childrenList); } else { - QList <QmlJsDebugClient::QmlEventSub *> parentList = qmlEvent->parentHash.values(); + QList <QmlRangeEventRelative *> parentList = qmlEvent->parentHash.values(); rebuildTree((QObject *)&parentList); } } @@ -882,7 +990,7 @@ void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId) sortByColumn(2); } -void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList) +void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *profilerDataModel) { Q_ASSERT(treeModel()); treeModel()->clear(); @@ -890,8 +998,8 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList) QStandardItem *topLevelItem = treeModel()->invisibleRootItem(); bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView; - QList <QmlEventSub *> *qmlList = static_cast< QList <QmlEventSub *> *>(eventList); - QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(eventList); + QList <QmlRangeEventRelative *> *qmlList = static_cast< QList <QmlRangeEventRelative *> *>(profilerDataModel); + QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(profilerDataModel); int listLength; if (!isV8) @@ -902,9 +1010,9 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList) for (int index=0; index < listLength; index++) { QList<QStandardItem *> newRow; if (!isV8) { - QmlEventSub *event = qmlList->at(index); + QmlRangeEventRelative *event = qmlList->at(index); - newRow << new EventsViewItem(event->reference->displayname); + newRow << new EventsViewItem(event->reference->displayName); newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType)); newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration)); newRow << new EventsViewItem(QString::number(event->calls)); diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.h b/src/plugins/qmlprofiler/qmlprofilereventview.h index 1c7c87d7f2..409ea4dca0 100644 --- a/src/plugins/qmlprofiler/qmlprofilereventview.h +++ b/src/plugins/qmlprofiler/qmlprofilereventview.h @@ -34,9 +34,13 @@ #define QMLPROFILEREVENTVIEW_H #include <QTreeView> -#include <qmljsdebugclient/qmlprofilereventtypes.h> -#include <qmljsdebugclient/qmlprofilereventlist.h> #include <QStandardItemModel> +#include <qmljsdebugclient/qmlprofilereventtypes.h> +#include "qmlprofilerdatamodel.h" + +#include <analyzerbase/ianalyzertool.h> + +#include "qmlprofilerviewmanager.h" namespace QmlProfiler { namespace Internal { @@ -44,9 +48,6 @@ namespace Internal { class QmlProfilerEventsMainView; class QmlProfilerEventsParentsAndChildrenView; -typedef QHash<QString, QmlJsDebugClient::QmlEventData *> QmlEventHash; -typedef QList<QmlJsDebugClient::QmlEventData *> QmlEventList; - enum ItemRole { EventHashStrRole = Qt::UserRole+1, FilenameRole = Qt::UserRole+2, @@ -59,7 +60,10 @@ class QmlProfilerEventsWidget : public QWidget { Q_OBJECT public: - explicit QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent); + explicit QmlProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerDataModel *profilerDataModel ); ~QmlProfilerEventsWidget(); void switchToV8View(); @@ -75,9 +79,11 @@ public: void setShowExtendedStatistics(bool show); bool showExtendedStatistics() const; + bool isQml() const; + bool isV8() const; + signals: void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void contextMenuRequested(const QPoint &position); void showEventInTimeline(int eventId); public slots: @@ -85,18 +91,14 @@ public slots: void selectBySourceLocation(const QString &filename, int line, int column); private slots: - void eventListStateChanged(); + void profilerDataModelStateChanged(); protected: void contextMenuEvent(QContextMenuEvent *ev); private: - QmlProfilerEventsMainView *m_eventTree; - QmlProfilerEventsParentsAndChildrenView *m_eventChildren; - QmlProfilerEventsParentsAndChildrenView *m_eventParents; - QmlJsDebugClient::QmlProfilerEventList *m_eventStatistics; - - bool m_globalStatsEnabled; + class QmlProfilerEventsWidgetPrivate; + QmlProfilerEventsWidgetPrivate *d; }; class QmlProfilerEventsMainView : public QTreeView @@ -129,12 +131,14 @@ public: MaxViewTypes }; - explicit QmlProfilerEventsMainView(QmlJsDebugClient::QmlProfilerEventList *model, QWidget *parent); + explicit QmlProfilerEventsMainView(ViewTypes viewType, + QWidget *parent, + QmlProfilerDataModel *dataModel); ~QmlProfilerEventsMainView(); - void setEventStatisticsModel(QmlJsDebugClient::QmlProfilerEventList *model); void setFieldViewable(Fields field, bool show); void setViewType(ViewTypes type); + ViewTypes viewType() const; void setShowAnonymousEvents( bool showThem ); QModelIndex selectedItem() const; @@ -157,7 +161,6 @@ signals: void showEventInTimeline(int eventId); public slots: - void eventListStateChanged(); void clear(); void jumpToItem(const QModelIndex &index); void selectEvent(int eventId); @@ -165,6 +168,9 @@ public slots: void buildModel(); void changeDetailsForEvent(int eventId, const QString &newString); +private slots: + void profilerDataModelStateChanged(); + private: void setHeaderLabels(); @@ -186,7 +192,9 @@ public: MaxSubtableTypes }; - explicit QmlProfilerEventsParentsAndChildrenView(QmlJsDebugClient::QmlProfilerEventList *model, SubViewType subtableType, QWidget *parent); + explicit QmlProfilerEventsParentsAndChildrenView(SubViewType subtableType, + QWidget *parent, + QmlProfilerDataModel *model); ~QmlProfilerEventsParentsAndChildrenView(); void setViewType(SubViewType type); @@ -200,10 +208,10 @@ public slots: void clear(); private: - void rebuildTree(void *eventList); + void rebuildTree(void *profilerDataModel); void updateHeader(); QStandardItemModel *treeModel(); - QmlJsDebugClient::QmlProfilerEventList *m_eventList; + QmlProfilerDataModel *m_profilerDataModel; SubViewType m_subtableType; }; diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.h b/src/plugins/qmlprofiler/qmlprofilerplugin.h index 624d2a6988..6e0512e2e0 100644 --- a/src/plugins/qmlprofiler/qmlprofilerplugin.h +++ b/src/plugins/qmlprofiler/qmlprofilerplugin.h @@ -43,6 +43,7 @@ namespace Internal { class QmlProfilerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfiler.json") public: QmlProfilerPlugin() {} diff --git a/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp b/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp new file mode 100644 index 0000000000..194e2cdf1c --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp @@ -0,0 +1,163 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "qmlprofilerstatemanager.h" + +#include <QDebug> +#include <utils/qtcassert.h> + +// uncomment for printing the state changes to debug output +//#define _DEBUG_PROFILERSTATE_ + +namespace QmlProfiler { +namespace Internal { + +inline QString stringForState(int state) { + switch (state) { + case QmlProfilerStateManager::Idle: return QString("Idle"); + case QmlProfilerStateManager::AppStarting: return QString("AppStarting"); + case QmlProfilerStateManager::AppRunning: return QString("AppRunning"); + case QmlProfilerStateManager::AppStopRequested: return QString("AppStopRequested"); + case QmlProfilerStateManager::AppReadyToStop: return QString("AppReadyToStop"); + case QmlProfilerStateManager::AppStopped: return QString("AppStopped"); + case QmlProfilerStateManager::AppKilled: return QString("AppKilled"); + default: break; + } + return QString(); +} + +class QmlProfilerStateManager::QmlProfilerStateManagerPrivate +{ +public: + QmlProfilerStateManagerPrivate(QmlProfilerStateManager *qq) : q(qq) {} + ~QmlProfilerStateManagerPrivate() {} + + QmlProfilerStateManager *q; + + QmlProfilerStateManager::QmlProfilerState m_currentState; + bool m_clientRecording; + bool m_serverRecording; +}; +QmlProfilerStateManager::QmlProfilerStateManager(QObject *parent) : + QObject(parent),d(new QmlProfilerStateManagerPrivate(this)) +{ + d->m_currentState = Idle; + d->m_clientRecording = true; + d->m_serverRecording = false; +} + +QmlProfilerStateManager::~QmlProfilerStateManager() +{ + delete d; +} + +QmlProfilerStateManager::QmlProfilerState QmlProfilerStateManager::currentState() +{ + return d->m_currentState; +} + +bool QmlProfilerStateManager::clientRecording() +{ + return d->m_clientRecording; +} + +bool QmlProfilerStateManager::serverRecording() +{ + return d->m_serverRecording; +} + +QString QmlProfilerStateManager::currentStateAsString() +{ + return stringForState(d->m_currentState); +} + +void QmlProfilerStateManager::setCurrentState(QmlProfilerState newState) +{ +#ifdef _DEBUG_PROFILERSTATE_ + qDebug() << "Profiler state change request from" << stringForState(d->m_currentState) << "to" << stringForState(newState); +#endif + QTC_ASSERT(d->m_currentState != newState, /**/); + switch (newState) { + case Idle: + QTC_ASSERT(d->m_currentState == AppStarting || d->m_currentState == AppStopped || d->m_currentState == AppKilled, /**/); + break; + case AppStarting: + QTC_ASSERT(d->m_currentState == Idle, /**/); + break; + case AppRunning: + QTC_ASSERT(d->m_currentState == AppStarting, /**/); + break; + case AppStopRequested: + QTC_ASSERT(d->m_currentState == AppRunning, /**/); + break; + case AppReadyToStop: + QTC_ASSERT(d->m_currentState == AppStopRequested, /**/); + break; + case AppStopped: + QTC_ASSERT(d->m_currentState == AppReadyToStop, /**/); + break; + case AppKilled: + QTC_ASSERT(d->m_currentState == AppRunning, /**/); + break; + default: + qDebug() << tr("Switching to unknown state in %1:%2").arg(QString(__FILE__), QString::number(__LINE__)); + break; + } + + d->m_currentState = newState; + emit stateChanged(); +} + +void QmlProfilerStateManager::setClientRecording(bool recording) +{ +#ifdef _DEBUG_PROFILERSTATE_ + qDebug() << "Setting client recording flag from" << d->m_serverRecording << "to" << recording; +#endif + if (d->m_clientRecording != recording) { + d->m_clientRecording = recording; + emit clientRecordingChanged(); + } +} + +void QmlProfilerStateManager::setServerRecording(bool recording) +{ +#ifdef _DEBUG_PROFILERSTATE_ + qDebug() << "Setting server recording flag from" << d->m_serverRecording << "to" << recording; +#endif + if (d->m_serverRecording != recording) { + d->m_serverRecording = recording; + emit serverRecordingChanged(); + } +} + +} +} diff --git a/src/plugins/qmlprofiler/qmlprofilerstatemanager.h b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h new file mode 100644 index 0000000000..188b0b5be3 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef QMLPROFILERSTATEMANAGER_H +#define QMLPROFILERSTATEMANAGER_H + +#include <QObject> + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerStateManager : public QObject +{ + Q_OBJECT +public: + enum QmlProfilerState { + Idle, + AppStarting, + AppRunning, + AppStopRequested, + AppReadyToStop, + AppStopped, + AppKilled + }; + + explicit QmlProfilerStateManager(QObject *parent = 0); + ~QmlProfilerStateManager(); + + QmlProfilerState currentState(); + bool clientRecording(); + bool serverRecording(); + + QString currentStateAsString(); + +signals: + void stateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); + +public slots: + void setCurrentState(QmlProfilerState newState); + void setClientRecording(bool recording); + void setServerRecording(bool recording); + +private: + class QmlProfilerStateManagerPrivate; + QmlProfilerStateManagerPrivate *d; +}; + +} +} + +#endif // QMLPROFILERSTATEMANAGER_H diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index fa01ea592d..6a16546e1a 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -31,24 +31,20 @@ **************************************************************************/ #include "qmlprofilertool.h" +#include "qmlprofilerstatemanager.h" #include "qmlprofilerengine.h" -#include "qmlprofilerplugin.h" #include "qmlprofilerconstants.h" #include "qmlprofilerattachdialog.h" -#include "qmlprofilereventview.h" - -#include "tracewindow.h" -#include "timelineview.h" - -#include <qmljsdebugclient/qmlprofilereventlist.h> -#include <qmljsdebugclient/qdeclarativedebugclient.h> +#include "qmlprofilerviewmanager.h" +#include "qmlprofilerclientmanager.h" +#include "qmlprofilerdatamodel.h" +#include "qmlprofilerdetailsrewriter.h" +#include "timelinerenderer.h" #include <analyzerbase/analyzermanager.h> -#include <analyzerbase/analyzerconstants.h> #include <analyzerbase/analyzerruncontrol.h> -#include "canvas/qdeclarativecanvas_p.h" -#include "canvas/qdeclarativecanvastimer_p.h" +#include "canvas/qdeclarativecontext2d_p.h" #include "canvas/qmlprofilercanvas.h" #include <qmlprojectmanager/qmlprojectrunconfiguration.h> @@ -56,7 +52,6 @@ #include <utils/fileinprojectfinder.h> #include <utils/qtcassert.h> #include <projectexplorer/projectexplorer.h> -#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/project.h> #include <projectexplorer/target.h> #include <projectexplorer/session.h> @@ -65,7 +60,6 @@ #include <remotelinux/remotelinuxrunconfiguration.h> #include <remotelinux/linuxdeviceconfiguration.h> -#include <texteditor/itexteditor.h> #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/icore.h> @@ -82,23 +76,22 @@ #include <qt4projectmanager/qt-s60/s60devicerunconfiguration.h> #include <qt4projectmanager/qt-s60/s60deployconfiguration.h> -#include <QFile> - #include <QApplication> #include <QHBoxLayout> #include <QLabel> -#include <QTabWidget> #include <QToolButton> #include <QMessageBox> -#include <QDockWidget> #include <QFileDialog> #include <QMenu> +#include <QTimer> +#include <QTime> using namespace Core; using namespace Core::Constants; using namespace Analyzer; using namespace Analyzer::Constants; using namespace QmlProfiler::Internal; +using namespace QmlProfiler::Constants; using namespace QmlJsDebugClient; using namespace ProjectExplorer; using namespace QmlProjectManager; @@ -112,59 +105,67 @@ public: QmlProfilerTool *q; - QDeclarativeDebugConnection *m_client; - QTimer m_connectionTimer; - int m_connectionAttempts; - TraceWindow *m_traceWindow; - QmlProfilerEventsWidget *m_eventsView; - QmlProfilerEventsWidget *m_v8profilerView; + QmlProfilerStateManager *m_profilerState; + QmlProfilerClientManager *m_profilerConnections; + QmlProfilerDataModel *m_profilerDataModel; + QmlProfilerDetailsRewriter *m_detailsRewriter; + + QmlProfilerViewManager *m_viewContainer; Utils::FileInProjectFinder m_projectFinder; RunConfiguration *m_runConfiguration; - bool m_isAttached; QToolButton *m_recordButton; QToolButton *m_clearButton; - bool m_recordingEnabled; - bool m_appIsRunning; - bool m_qmlActive; - bool m_v8Active; - QTime m_appTimer; - qint64 m_appRunningTime; - - enum ConnectMode { - TcpConnection, OstConnection - }; - - ConnectMode m_connectMode; - QString m_tcpHost; - quint64 m_tcpPort; - QString m_ostDevice; - QString m_sysroot; + + // elapsed time display + QTimer m_recordingTimer; + QTime m_recordingElapsedTime; + QLabel *m_timeLabel; + + // save and load actions QAction *m_saveQmlTrace; + QAction *m_loadQmlTrace; }; QmlProfilerTool::QmlProfilerTool(QObject *parent) : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this)) { setObjectName("QmlProfilerTool"); - d->m_client = 0; - d->m_connectionAttempts = 0; - d->m_traceWindow = 0; - d->m_runConfiguration = 0; - d->m_isAttached = false; - d->m_recordingEnabled = true; - d->m_appIsRunning = false; - d->m_appTimer.start(); - d->m_appRunningTime = 0; - d->m_connectionTimer.setInterval(200); - connect(&d->m_connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect())); + d->m_profilerState = 0; + d->m_viewContainer = 0; + d->m_runConfiguration = 0; - qmlRegisterType<Canvas>("Monitor", 1, 0, "Canvas"); qmlRegisterType<QmlProfilerCanvas>("Monitor", 1, 0, "Canvas2D"); qmlRegisterType<Context2D>(); - qmlRegisterType<CanvasImage>(); qmlRegisterType<CanvasGradient>(); - qmlRegisterType<TimelineView>("Monitor", 1, 0,"TimelineView"); + qmlRegisterType<TimelineRenderer>("Monitor", 1, 0,"TimelineRenderer"); + + d->m_profilerState = new QmlProfilerStateManager(this); + connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); + connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), this, SLOT(clientRecordingChanged())); + connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), this, SLOT(serverRecordingChanged())); + + d->m_profilerConnections = new QmlProfilerClientManager(this); + d->m_profilerConnections->registerProfilerStateManager(d->m_profilerState); + + d->m_profilerDataModel = new QmlProfilerDataModel(this); + connect(d->m_profilerDataModel, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged())); + connect(d->m_profilerDataModel, SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString))); + connect(d->m_profilerConnections, SIGNAL(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), d->m_profilerDataModel, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation))); + connect(d->m_profilerConnections, SIGNAL(addV8Event(int,QString,QString,int,double,double)), d->m_profilerDataModel, SLOT(addV8Event(int,QString,QString,int,double,double))); + connect(d->m_profilerConnections, SIGNAL(addFrameEvent(qint64,int,int)), d->m_profilerDataModel, SLOT(addFrameEvent(qint64,int,int))); + connect(d->m_profilerConnections, SIGNAL(traceStarted(qint64)), d->m_profilerDataModel, SLOT(setTraceStartTime(qint64))); + connect(d->m_profilerConnections, SIGNAL(traceFinished(qint64)), d->m_profilerDataModel, SLOT(setTraceEndTime(qint64))); + connect(d->m_profilerConnections, SIGNAL(dataReadyForProcessing()), d->m_profilerDataModel, SLOT(complete())); + + + d->m_detailsRewriter = new QmlProfilerDetailsRewriter(this); + connect(d->m_profilerDataModel, SIGNAL(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)), + d->m_detailsRewriter, SLOT(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation))); + connect(d->m_detailsRewriter, SIGNAL(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)), + d->m_profilerDataModel, SLOT(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString))); + connect(d->m_detailsRewriter, SIGNAL(eventDetailsChanged()), d->m_profilerDataModel, SLOT(finishedRewritingDetails())); + connect(d->m_profilerDataModel, SIGNAL(reloadDocumentsForDetails()), d->m_detailsRewriter, SLOT(reloadDocuments())); Command *command = 0; const Context globalContext(C_GLOBAL); @@ -176,7 +177,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) menu->addMenu(options, G_ANALYZER_OPTIONS); options->menu()->setEnabled(true); - QAction *act = new QAction(tr("Load QML Trace"), options); + QAction *act = d->m_loadQmlTrace = new QAction(tr("Load QML Trace"), options); command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.LoadQMLTrace", globalContext); connect(act, SIGNAL(triggered()), this, SLOT(showLoadDialog())); options->addAction(command); @@ -186,11 +187,13 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) command = am->registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.SaveQMLTrace", globalContext); connect(act, SIGNAL(triggered()), this, SLOT(showSaveDialog())); options->addAction(command); + + d->m_recordingTimer.setInterval(100); + connect(&d->m_recordingTimer, SIGNAL(timeout()), this, SLOT(updateTimeDisplay())); } QmlProfilerTool::~QmlProfilerTool() { - delete d->m_client; delete d; } @@ -220,86 +223,14 @@ IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const return AnyMode; } -void QmlProfilerTool::showContextMenu(const QPoint &position) -{ - QmlProfilerEventsWidget *eventView = qobject_cast<QmlProfilerEventsWidget *>(sender()); - TraceWindow *traceView = qobject_cast<TraceWindow *>(sender()); - - QMenu menu; - QAction *loadAction = menu.addAction(tr("Load QML Trace")); - QAction *saveAction = menu.addAction(tr("Save QML Trace")); - QAction *copyRowAction = 0; - QAction *copyTableAction = 0; - QAction *showExtendedStatsAction = 0; - QAction *viewAllAction = 0; - QAction *getLocalStatsAction = 0; - QAction *getGlobalStatsAction = 0; - - if (eventView && eventView->mouseOnTable(position)) { - menu.addSeparator(); - if (eventView->selectedItem().isValid()) - copyRowAction = menu.addAction(tr("Copy Row")); - copyTableAction = menu.addAction(tr("Copy Table")); - - if (eventView == d->m_eventsView) { - // only for qml events view, not for v8 - showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics")); - showExtendedStatsAction->setCheckable(true); - showExtendedStatsAction->setChecked(eventView->showExtendedStatistics()); - } - } - - if (sender() == d->m_traceWindow || sender() == d->m_eventsView) { - menu.addSeparator(); - getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); - if (!d->m_traceWindow->hasValidSelection()) - getLocalStatsAction->setEnabled(false); - getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); - if (d->m_eventsView->hasGlobalStats()) - getGlobalStatsAction->setEnabled(false); - } - - if (traceView) { - if (traceView->getEventList()->count() > 0) { - menu.addSeparator(); - viewAllAction = menu.addAction(tr("Reset Zoom")); - } - } - - QAction *selectedAction = menu.exec(position); - - if (selectedAction) { - if (selectedAction == loadAction) - showLoadDialog(); - if (selectedAction == saveAction) - showSaveDialog(); - if (selectedAction == copyRowAction) - eventView->copyRowToClipboard(); - if (selectedAction == copyTableAction) - eventView->copyTableToClipboard(); - if (selectedAction == viewAllAction) - traceView->viewAll(); - if (selectedAction == getLocalStatsAction) { - d->m_eventsView->getStatisticsInRange( - d->m_traceWindow->selectionStart(), - d->m_traceWindow->selectionEnd()); - } - if (selectedAction == getGlobalStatsAction) { - d->m_eventsView->getStatisticsInRange( - d->m_traceWindow->getEventList()->traceStartTime(), - d->m_traceWindow->getEventList()->traceEndTime()); - } - if (selectedAction == showExtendedStatsAction) - eventView->setShowExtendedStatistics(!eventView->showExtendedStatistics()); - } -} - IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp, RunConfiguration *runConfiguration) { QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration); - d->m_connectMode = QmlProfilerToolPrivate::TcpConnection; + engine->registerProfilerStateManager(d->m_profilerState); + + bool isTcpConnection = true; if (runConfiguration) { // Check minimum Qt Version. We cannot really be sure what the Qt version @@ -324,16 +255,15 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp runConfiguration->target()->activeDeployConfiguration())) { if (deployConfig->communicationChannel() == Qt4ProjectManager::S60DeployConfiguration::CommunicationCodaSerialConnection) { - d->m_connectMode = QmlProfilerToolPrivate::OstConnection; - d->m_ostDevice = deployConfig->serialPortName(); + d->m_profilerConnections->setOstConnection(deployConfig->serialPortName()); + isTcpConnection = false; } } } // FIXME: Check that there's something sensible in sp.connParams - if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) { - d->m_tcpHost = sp.connParams.host; - d->m_tcpPort = sp.connParams.port; + if (isTcpConnection) { + d->m_profilerConnections->setTcpConnection(sp.connParams.host, sp.connParams.port); } d->m_runConfiguration = runConfiguration; @@ -364,20 +294,9 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp d->m_projectFinder.setProjectFiles(sourceFiles); d->m_projectFinder.setSysroot(sp.sysroot); - connect(engine, SIGNAL(processRunning(int)), this, SLOT(connectClient(int))); - connect(engine, SIGNAL(finished()), this, SLOT(disconnectClient())); - connect(engine, SIGNAL(finished()), this, SLOT(updateTimers())); - connect(engine, SIGNAL(stopRecording()), this, SLOT(stopRecording())); - connect(engine, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool))); - connect(engine, SIGNAL(timeUpdate()), this, SLOT(updateTimers())); - connect(d->m_traceWindow, SIGNAL(viewUpdated()), engine, SLOT(dataReceived())); - connect(this, SIGNAL(connectionFailed()), engine, SLOT(finishProcess())); - connect(this, SIGNAL(fetchingData(bool)), engine, SLOT(setFetchingData(bool))); - connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), this, SLOT(setAppIsRunning())); - connect(engine, SIGNAL(finished()), this, SLOT(setAppIsStopped())); - connect(this, SIGNAL(cancelRun()), engine, SLOT(finishProcess())); - connect(engine, SIGNAL(applicationDied()), d->m_traceWindow, SLOT(applicationDied())); - emit fetchingData(d->m_recordButton->isChecked()); + connect(engine, SIGNAL(processRunning(quint16)), d->m_profilerConnections, SLOT(connectClient(quint16))); + connect(engine, SIGNAL(finished()), d->m_profilerConnections, SLOT(disconnectClient())); + connect(d->m_profilerConnections, SIGNAL(connectionFailed()), engine, SLOT(cancelProcess())); return engine; } @@ -392,19 +311,6 @@ bool QmlProfilerTool::canRun(RunConfiguration *runConfiguration, RunMode mode) c return false; } -static QString sysroot(RunConfiguration *runConfig) -{ - QTC_ASSERT(runConfig, return QString()) - if (Qt4ProjectManager::Qt4BuildConfiguration *buildConfig = - qobject_cast<Qt4ProjectManager::Qt4BuildConfiguration*>( - runConfig->target()->activeBuildConfiguration())) { - if (QtSupport::BaseQtVersion *qtVersion = buildConfig->qtVersion()) - return qtVersion->systemRoot(); - } - - return QString(); -} - AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration *runConfiguration, RunMode mode) const { Q_UNUSED(mode); @@ -439,7 +345,6 @@ AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration sp.connParams = rc3->deviceConfig()->sshParameters(); sp.analyzerCmdPrefix = rc3->commandPrefix(); sp.displayName = rc3->displayName(); - sp.sysroot = sysroot(rc3); } else if (Qt4ProjectManager::S60DeviceRunConfiguration *rc4 = qobject_cast<Qt4ProjectManager::S60DeviceRunConfiguration *>(runConfiguration)) { Qt4ProjectManager::S60DeployConfiguration *deployConf = @@ -449,7 +354,6 @@ AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration sp.displayName = rc4->displayName(); sp.connParams.host = deployConf->deviceAddress(); sp.connParams.port = rc4->debuggerAspect()->qmlDebugServerPort(); - sp.sysroot = sysroot(rc4); } else { // What could that be? QTC_ASSERT(false, return sp); @@ -459,53 +363,15 @@ AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration QWidget *QmlProfilerTool::createWidgets() { - QTC_ASSERT(!d->m_traceWindow, return 0); - - // - // DockWidgets - // - - Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow(); - - d->m_traceWindow = new TraceWindow(mw); - d->m_traceWindow->reset(d->m_client); - - connect(d->m_traceWindow, SIGNAL(clearViewsFromTool()), this, SLOT(clearDisplay())); - connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int,int)),this, SLOT(gotoSourceLocation(QString,int,int))); - connect(d->m_traceWindow, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); - connect(d->m_traceWindow->getEventList(), SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString))); - connect(d->m_traceWindow->getEventList(), SIGNAL(stateChanged()), this, SLOT(eventListStateChanged())); - connect(d->m_traceWindow, SIGNAL(profilerStateChanged(bool,bool)), this, SLOT(profilerStateChanged(bool,bool))); - connect(d->m_traceWindow, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool))); - - d->m_eventsView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw); - connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int))); - connect(d->m_eventsView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); - connect(d->m_eventsView, SIGNAL(showEventInTimeline(int)), d->m_traceWindow, SLOT(selectNextEvent(int))); - connect(d->m_traceWindow, SIGNAL(selectedEventIdChanged(int)), d->m_eventsView, SLOT(updateSelectedEvent(int))); + QTC_ASSERT(!d->m_viewContainer, return 0); - d->m_v8profilerView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw); - d->m_v8profilerView->switchToV8View(); - connect(d->m_v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int))); - connect(d->m_v8profilerView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); - connect(d->m_v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), d->m_eventsView, SLOT(selectBySourceLocation(QString,int,int))); - connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), d->m_v8profilerView, SLOT(selectBySourceLocation(QString,int,int))); - - QDockWidget *eventsDock = AnalyzerManager::createDockWidget - (this, tr("Events"), d->m_eventsView, Qt::BottomDockWidgetArea); - QDockWidget *timelineDock = AnalyzerManager::createDockWidget - (this, tr("Timeline"), d->m_traceWindow, Qt::BottomDockWidgetArea); - QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget - (this, tr("JavaScript"), d->m_v8profilerView, Qt::BottomDockWidgetArea); - - eventsDock->show(); - timelineDock->show(); - v8profilerDock->show(); - - mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical); - mw->tabifyDockWidget(eventsDock, timelineDock); - mw->tabifyDockWidget(timelineDock, v8profilerDock); + d->m_viewContainer = new QmlProfilerViewManager(this, + this, + d->m_profilerDataModel, + d->m_profilerState); + connect(d->m_viewContainer, SIGNAL(gotoSourceLocation(QString,int,int)), + this, SLOT(gotoSourceLocation(QString,int,int))); // // Toolbar @@ -522,118 +388,53 @@ QWidget *QmlProfilerTool::createWidgets() connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool))); d->m_recordButton->setChecked(true); - setRecording(d->m_recordingEnabled); + setRecording(d->m_profilerState->clientRecording()); layout->addWidget(d->m_recordButton); d->m_clearButton = new QToolButton(toolbarWidget); d->m_clearButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/clean_pane_small.png"))); d->m_clearButton->setToolTip(tr("Discard data")); - connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearDisplay())); + + connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearData())); + layout->addWidget(d->m_clearButton); - QLabel *timeLabel = new QLabel(); - QPalette palette = timeLabel->palette(); + d->m_timeLabel = new QLabel(); + QPalette palette = d->m_timeLabel->palette(); palette.setColor(QPalette::WindowText, Qt::white); - timeLabel->setPalette(palette); - timeLabel->setIndent(10); - connect(d->m_traceWindow, SIGNAL(viewUpdated()), this, SLOT(updateTimers())); - connect(this, SIGNAL(setTimeLabel(QString)), timeLabel, SLOT(setText(QString))); - updateTimers(); - layout->addWidget(timeLabel); + d->m_timeLabel->setPalette(palette); + d->m_timeLabel->setIndent(10); + updateTimeDisplay(); + layout->addWidget(d->m_timeLabel); toolbarWidget->setLayout(layout); return toolbarWidget; } -void QmlProfilerTool::connectClient(int port) -{ - if (d->m_client) - delete d->m_client; - d->m_client = new QDeclarativeDebugConnection; - d->m_traceWindow->reset(d->m_client); - connect(d->m_client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), - this, SLOT(connectionStateChanged())); - d->m_connectionTimer.start(); - d->m_appTimer.start(); - d->m_tcpPort = port; -} - -void QmlProfilerTool::connectToClient() -{ - if (!d->m_client || d->m_client->state() != QAbstractSocket::UnconnectedState) - return; - - if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) { - logStatus(QString("QML Profiler: Connecting to %1:%2...").arg(d->m_tcpHost, QString::number(d->m_tcpPort))); - d->m_client->connectToHost(d->m_tcpHost, d->m_tcpPort); - } else { - logStatus(QString("QML Profiler: Connecting to %1...").arg(d->m_tcpHost)); - d->m_client->connectToOst(d->m_ostDevice); - } -} - -void QmlProfilerTool::disconnectClient() -{ - // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow - // method to complete before deleting object - if (d->m_client) { - d->m_client->deleteLater(); - d->m_client = 0; - } -} - -void QmlProfilerTool::startRecording() -{ - if (d->m_client && d->m_client->isConnected()) { - clearDisplay(); - d->m_traceWindow->setRecording(true); - } - emit fetchingData(true); -} - -void QmlProfilerTool::stopRecording() -{ - d->m_traceWindow->setRecording(false); - emit fetchingData(false); - - // manage early stop - if (d->m_client && !d->m_client->isConnected() && d->m_appIsRunning) - emit cancelRun(); -} - void QmlProfilerTool::recordingButtonChanged(bool recording) { - if (recording) - startRecording(); - else - stopRecording(); - - setRecording(recording); + d->m_profilerState->setClientRecording(recording); } void QmlProfilerTool::setRecording(bool recording) { - // update record button - d->m_recordingEnabled = recording; + // update display d->m_recordButton->setToolTip( recording ? tr("Disable profiling") : tr("Enable profiling")); d->m_recordButton->setIcon(QIcon(recording ? QLatin1String(":/qmlprofiler/recordOn.png") : QLatin1String(":/qmlprofiler/recordOff.png"))); d->m_recordButton->setChecked(recording); - updateTimers(); -} -void QmlProfilerTool::setAppIsRunning() -{ - d->m_appIsRunning = true; - updateTimers(); -} - -void QmlProfilerTool::setAppIsStopped() -{ - d->m_appIsRunning = false; - updateTimers(); + // manage timer + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + if (recording) { + d->m_recordingTimer.start(); + d->m_recordingElapsedTime.start(); + } else { + d->m_recordingTimer.stop(); + } + } } void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber) @@ -658,33 +459,31 @@ void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber, } } -inline QString stringifyTime(double seconds) +void QmlProfilerTool::updateTimeDisplay() { + double seconds = 0; + if (d->m_profilerState->serverRecording() && + d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + seconds = d->m_recordingElapsedTime.elapsed() / 1000.0; + } else if (d->m_profilerDataModel->currentState() != QmlProfilerDataModel::Empty ) { + seconds = (d->m_profilerDataModel->traceEndTime() - d->m_profilerDataModel->traceStartTime()) / 1.0e9; + } QString timeString = QString::number(seconds,'f',1); - return QmlProfilerTool::tr("%1 s").arg(timeString, 6); -} - -void QmlProfilerTool::updateTimers() -{ - // prof time - QString profilerTimeStr = stringifyTime(d->m_traceWindow->profiledTime()); - emit setTimeLabel(tr("Elapsed: %1").arg(profilerTimeStr)); + QString profilerTimeStr = QmlProfilerTool::tr("%1 s").arg(timeString, 6); + d->m_timeLabel->setText(tr("Elapsed: %1").arg(profilerTimeStr)); } -void QmlProfilerTool::profilerStateChanged(bool qmlActive, bool v8active) +void QmlProfilerTool::clearData() { - d->m_v8Active = v8active; - d->m_qmlActive = qmlActive; - updateTimers(); + d->m_profilerDataModel->clear(); + d->m_profilerConnections->discardPendingData(); } void QmlProfilerTool::clearDisplay() { - d->m_appRunningTime = 0; - d->m_traceWindow->clearDisplay(); - d->m_eventsView->clear(); - d->m_v8profilerView->clear(); - updateTimers(); + d->m_profilerConnections->clearBufferedData(); + d->m_viewContainer->clear(); + updateTimeDisplay(); } static void startRemoteTool(IAnalyzerTool *tool, StartMode mode) @@ -733,84 +532,6 @@ static void startRemoteTool(IAnalyzerTool *tool, StartMode mode) ProjectExplorerPlugin::instance()->startRunControl(rc, tool->runMode()); } -void QmlProfilerTool::tryToConnect() -{ - ++d->m_connectionAttempts; - - if (d->m_client && d->m_client->isConnected()) { - d->m_connectionTimer.stop(); - d->m_connectionAttempts = 0; - } else if (d->m_connectionAttempts == 50) { - d->m_connectionTimer.stop(); - d->m_connectionAttempts = 0; - - QMessageBox *infoBox = new QMessageBox(Core::ICore::mainWindow()); - infoBox->setIcon(QMessageBox::Critical); - infoBox->setWindowTitle(tr("Qt Creator")); - infoBox->setText(tr("Could not connect to the in-process QML profiler.\n" - "Do you want to retry?")); - infoBox->setStandardButtons(QMessageBox::Retry | QMessageBox::Cancel | QMessageBox::Help); - infoBox->setDefaultButton(QMessageBox::Retry); - infoBox->setModal(true); - - connect(infoBox, SIGNAL(finished(int)), - this, SLOT(retryMessageBoxFinished(int))); - - infoBox->show(); - } else { - connectToClient(); - } -} - -void QmlProfilerTool::connectionStateChanged() -{ - if (!d->m_client) - return; - switch (d->m_client->state()) { - case QAbstractSocket::UnconnectedState: - { - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: disconnected"); - break; - } - case QAbstractSocket::HostLookupState: - break; - case QAbstractSocket::ConnectingState: { - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: Connecting to debug server ..."); - break; - } - case QAbstractSocket::ConnectedState: - { - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: connected and running"); - updateRecordingState(); - break; - } - case QAbstractSocket::ClosingState: - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: closing ..."); - break; - case QAbstractSocket::BoundState: - case QAbstractSocket::ListeningState: - break; - } -} - -void QmlProfilerTool::updateRecordingState() -{ - if (d->m_client->isConnected()) { - d->m_traceWindow->setRecording(d->m_recordingEnabled); - } else { - d->m_traceWindow->setRecording(false); - } - - if (d->m_traceWindow->isRecording()) - clearDisplay(); - - updateTimers(); -} - void QmlProfilerTool::startTool(StartMode mode) { using namespace ProjectExplorer; @@ -836,14 +557,25 @@ void QmlProfilerTool::logStatus(const QString &msg) void QmlProfilerTool::logError(const QString &msg) { - // TODO: Rather show errors in the application ouput MessageManager *messageManager = MessageManager::instance(); messageManager->printToOutputPane(msg, true); } +void QmlProfilerTool::showErrorDialog(const QString &error) +{ + QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow()); + errorDialog->setIcon(QMessageBox::Warning); + errorDialog->setWindowTitle(tr("QML Profiler")); + errorDialog->setText(error); + errorDialog->setStandardButtons(QMessageBox::Ok); + errorDialog->setDefaultButton(QMessageBox::Ok); + errorDialog->setModal(false); + errorDialog->show(); +} + void QmlProfilerTool::showSaveOption() { - d->m_saveQmlTrace->setEnabled(d->m_traceWindow->getEventList()->count()); + d->m_saveQmlTrace->setEnabled(!d->m_profilerDataModel->isEmpty()); } void QmlProfilerTool::showSaveDialog() @@ -852,7 +584,7 @@ void QmlProfilerTool::showSaveDialog() if (!filename.isEmpty()) { if (!filename.endsWith(QLatin1String(TraceFileExtension))) filename += QLatin1String(TraceFileExtension); - d->m_traceWindow->getEventList()->save(filename); + d->m_profilerDataModel->save(filename); } } @@ -868,53 +600,98 @@ void QmlProfilerTool::showLoadDialog() if (!filename.isEmpty()) { // delayed load (prevent graphical artifacts due to long load time) - d->m_traceWindow->getEventList()->setFilename(filename); - QTimer::singleShot(100, d->m_traceWindow->getEventList(), SLOT(load())); + d->m_profilerDataModel->setFilename(filename); + QTimer::singleShot(100, d->m_profilerDataModel, SLOT(load())); } } -void QmlProfilerTool::showErrorDialog(const QString &error) +void QmlProfilerTool::profilerDataModelStateChanged() { - QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow()); - errorDialog->setIcon(QMessageBox::Warning); - errorDialog->setWindowTitle(tr("QML Profiler")); - errorDialog->setText(error); - errorDialog->setStandardButtons(QMessageBox::Ok); - errorDialog->setDefaultButton(QMessageBox::Ok); - errorDialog->setModal(false); - errorDialog->show(); + switch (d->m_profilerDataModel->currentState()) { + case QmlProfilerDataModel::Empty : + clearDisplay(); + break; + case QmlProfilerDataModel::AcquiringData : + case QmlProfilerDataModel::ProcessingData : + // nothing to be done for these two + break; + case QmlProfilerDataModel::Done : + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested) + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop); + showSaveOption(); + updateTimeDisplay(); + break; + default: + break; + } +} + +QList <QAction *> QmlProfilerTool::profilerContextMenuActions() const +{ + QList <QAction *> commonActions; + commonActions << d->m_loadQmlTrace << d->m_saveQmlTrace; + return commonActions; +} + +void QmlProfilerTool::showNonmodalWarning(const QString &warningMsg) +{ + QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow()); + noExecWarning->setIcon(QMessageBox::Warning); + noExecWarning->setWindowTitle(tr("QML Profiler")); + noExecWarning->setText(warningMsg); + noExecWarning->setStandardButtons(QMessageBox::Ok); + noExecWarning->setDefaultButton(QMessageBox::Ok); + noExecWarning->setModal(false); + noExecWarning->show(); +} + +QMessageBox *QmlProfilerTool::requestMessageBox() +{ + return new QMessageBox(Core::ICore::mainWindow()); } -void QmlProfilerTool::retryMessageBoxFinished(int result) +void QmlProfilerTool::handleHelpRequest(const QString &link) { - switch (result) { - case QMessageBox::Retry: { - d->m_connectionAttempts = 0; - d->m_connectionTimer.start(); + HelpManager *helpManager = HelpManager::instance(); + helpManager->handleHelpRequest(link); +} + +void QmlProfilerTool::profilerStateChanged() +{ + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppKilled : { + if (d->m_profilerDataModel->currentState() == QmlProfilerDataModel::AcquiringData) { + showNonmodalWarning(tr("Application finished before loading profiled data.\n Please use the stop button instead.")); + } break; } - case QMessageBox::Help: { - HelpManager *helpManager = HelpManager::instance(); - helpManager->handleHelpRequest("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html"); - // fall through - } - default: { - if (d->m_client) { - logStatus("QML Profiler: Failed to connect! " + d->m_client->errorString()); - } else { - logStatus("QML Profiler: Failed to connect!"); - } - - emit connectionFailed(); + case QmlProfilerStateManager::Idle : + // when the app finishes, set recording display to client status + setRecording(d->m_profilerState->clientRecording()); + break; + default: + // no special action needed for other states break; } +} + +void QmlProfilerTool::clientRecordingChanged() +{ + // if application is running, display server record changes + // if application is stopped, display client record changes + if (d->m_profilerState->currentState() != QmlProfilerStateManager::AppRunning) { + setRecording(d->m_profilerState->clientRecording()); } } -void QmlProfilerTool::eventListStateChanged() +void QmlProfilerTool::serverRecordingChanged() { - if (d->m_traceWindow->getEventList()->currentState() == QmlProfilerEventList::Done) { - showSaveOption(); - updateTimers(); + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + setRecording(d->m_profilerState->serverRecording()); + // clear the old data each time we start a new profiling session + if (d->m_profilerState->serverRecording()) { + clearData(); + } } } + diff --git a/src/plugins/qmlprofiler/qmlprofilertool.h b/src/plugins/qmlprofiler/qmlprofilertool.h index 3b53e5d727..fa9ba2e968 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.h +++ b/src/plugins/qmlprofiler/qmlprofilertool.h @@ -36,13 +36,13 @@ #include <analyzerbase/ianalyzertool.h> #include <analyzerbase/ianalyzerengine.h> -#include <QPoint> +QT_BEGIN_NAMESPACE +class QMessageBox; +QT_END_NAMESPACE namespace QmlProfiler { namespace Internal { -#define TraceFileExtension ".qtd" - class QmlProfilerTool : public Analyzer::IAnalyzerTool { Q_OBJECT @@ -72,49 +72,37 @@ public: QWidget *createWidgets(); void startTool(Analyzer::StartMode mode); + QList <QAction *> profilerContextMenuActions() const; + + // display dialogs / log output + static QMessageBox *requestMessageBox(); + static void handleHelpRequest(const QString &link); + static void logStatus(const QString &msg); + static void logError(const QString &msg); + static void showNonmodalWarning(const QString &warningMsg); + public slots: - void connectClient(int port); - void disconnectClient(); + void profilerStateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); - void startRecording(); - void stopRecording(); void recordingButtonChanged(bool recording); void setRecording(bool recording); - void setAppIsRunning(); - void setAppIsStopped(); - void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber); - void updateTimers(); - void profilerStateChanged(bool qmlActive, bool v8active); - - void clearDisplay(); - - void showContextMenu(const QPoint &position); - -signals: - void setTimeLabel(const QString &); - void setStatusLabel(const QString &); - void fetchingData(bool); - void connectionFailed(); - void cancelRun(); private slots: - void tryToConnect(); - void connectionStateChanged(); + void clearData(); + void showErrorDialog(const QString &error); + void profilerDataModelStateChanged(); + void updateTimeDisplay(); + void showSaveOption(); void showSaveDialog(); void showLoadDialog(); - void showErrorDialog(const QString &error); - void retryMessageBoxFinished(int result); - void eventListStateChanged(); private: - void connectToClient(); - void updateRecordingState(); - void ensureWidgets(); - void logStatus(const QString &msg); - void logError(const QString &msg); + void clearDisplay(); class QmlProfilerToolPrivate; QmlProfilerToolPrivate *d; diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp new file mode 100644 index 0000000000..ab02f45b08 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -0,0 +1,601 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "qmlprofilertraceview.h" +#include "qmlprofilertool.h" +#include "qmlprofilerstatemanager.h" +#include "qmlprofilerdatamodel.h" + +// Needed for the load&save actions in the context menu +#include <analyzerbase/ianalyzertool.h> + +// Comunication with the other views (limit events to range) +#include "qmlprofilerviewmanager.h" + +#include <utils/styledbar.h> + +#include <QDeclarativeContext> +#include <QToolButton> +#include <QEvent> +#include <QVBoxLayout> +#include <QGraphicsObject> +#include <QScrollBar> +#include <QSlider> +#include <QMenu> + +#include <math.h> + +using namespace QmlJsDebugClient; + +namespace QmlProfiler { +namespace Internal { + +const int sliderTicks = 10000; +const qreal sliderExp = 3; + + +///////////////////////////////////////////////////////// +bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::Wheel) { + QWheelEvent *ev = static_cast<QWheelEvent *>(event); + if (ev->modifiers() & Qt::ControlModifier) { + emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta()); + return true; + } + } + return QObject::eventFilter(obj, event); +} + +///////////////////////////////////////////////////////// +void ZoomControl::setRange(qint64 startTime, qint64 endTime) +{ + if (m_startTime != startTime || m_endTime != endTime) { + m_startTime = startTime; + m_endTime = endTime; + emit rangeChanged(); + } +} + +///////////////////////////////////////////////////////// +ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent) + : QDeclarativeView(parent) +{ +} + +ScrollableDeclarativeView::~ScrollableDeclarativeView() +{ +} + +void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy) +{ + // special workaround to track the scrollbar + if (rootObject()) { + int scrollY = rootObject()->property("scrollY").toInt(); + rootObject()->setProperty("scrollY", QVariant(scrollY - dy)); + } + QDeclarativeView::scrollContentsBy(dx,dy); +} + +///////////////////////////////////////////////////////// +class QmlProfilerTraceView::QmlProfilerTraceViewPrivate +{ +public: + QmlProfilerTraceViewPrivate(QmlProfilerTraceView *qq) : q(qq) {} + QmlProfilerTraceView *q; + + QmlProfilerStateManager *m_profilerState; + Analyzer::IAnalyzerTool *m_profilerTool; + QmlProfilerViewManager *m_viewContainer; + + QSize m_sizeHint; + + ScrollableDeclarativeView *m_mainView; + QDeclarativeView *m_timebar; + QDeclarativeView *m_overview; + QmlProfilerDataModel *m_profilerDataModel; + + ZoomControl *m_zoomControl; + + QToolButton *m_buttonRange; + QToolButton *m_buttonLock; + QWidget *m_zoomToolbar; + int m_currentZoomLevel; +}; + +QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerDataModel *model, QmlProfilerStateManager *profilerState) + : QWidget(parent), d(new QmlProfilerTraceViewPrivate(this)) +{ + setObjectName("QML Profiler"); + + d->m_zoomControl = new ZoomControl(this); + connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange())); + + QVBoxLayout *groupLayout = new QVBoxLayout; + groupLayout->setContentsMargins(0, 0, 0, 0); + groupLayout->setSpacing(0); + + d->m_mainView = new ScrollableDeclarativeView(this); + d->m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject); + d->m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + d->m_mainView->setBackgroundBrush(QBrush(Qt::white)); + d->m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop); + d->m_mainView->setFocus(); + + MouseWheelResizer *resizer = new MouseWheelResizer(this); + connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int))); + d->m_mainView->viewport()->installEventFilter(resizer); + + QHBoxLayout *toolsLayout = new QHBoxLayout; + + d->m_timebar = new QDeclarativeView(this); + d->m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView); + d->m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + d->m_timebar->setFixedHeight(24); + + d->m_overview = new QDeclarativeView(this); + d->m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView); + d->m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + d->m_overview->setMaximumHeight(50); + + d->m_zoomToolbar = createZoomToolbar(); + d->m_zoomToolbar->move(0, d->m_timebar->height()); + d->m_zoomToolbar->setVisible(false); + + toolsLayout->addWidget(createToolbar()); + toolsLayout->addWidget(d->m_timebar); + emit enableToolbar(false); + + groupLayout->addLayout(toolsLayout); + groupLayout->addWidget(d->m_mainView); + groupLayout->addWidget(d->m_overview); + + setLayout(groupLayout); + + d->m_profilerTool = profilerTool; + d->m_viewContainer = container; + d->m_profilerDataModel = model; + connect(d->m_profilerDataModel, SIGNAL(stateChanged()), + this, SLOT(profilerDataModelStateChanged())); + d->m_mainView->rootContext()->setContextProperty("qmlProfilerDataModel", + d->m_profilerDataModel); + d->m_overview->rootContext()->setContextProperty("qmlProfilerDataModel", + d->m_profilerDataModel); + + d->m_profilerState = profilerState; + connect(d->m_profilerState, SIGNAL(stateChanged()), + this, SLOT(profilerStateChanged())); + connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), + this, SLOT(clientRecordingChanged())); + connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), + this, SLOT(serverRecordingChanged())); + + // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin + setMinimumHeight(170); + d->m_currentZoomLevel = 0; +} + +QmlProfilerTraceView::~QmlProfilerTraceView() +{ + delete d; +} + +///////////////////////////////////////////////////////// +// Initialize widgets +void QmlProfilerTraceView::reset() +{ + d->m_mainView->rootContext()->setContextProperty("zoomControl", d->m_zoomControl); + d->m_timebar->rootContext()->setContextProperty("zoomControl", d->m_zoomControl); + d->m_overview->rootContext()->setContextProperty("zoomControl", d->m_zoomControl); + + d->m_timebar->setSource(QUrl("qrc:/qmlprofiler/TimeDisplay.qml")); + d->m_overview->setSource(QUrl("qrc:/qmlprofiler/Overview.qml")); + + d->m_mainView->setSource(QUrl("qrc:/qmlprofiler/MainView.qml")); + d->m_mainView->rootObject()->setProperty("width", QVariant(width())); + d->m_mainView->rootObject()->setProperty("candidateHeight", QVariant(height() - d->m_timebar->height() - d->m_overview->height())); + + connect(d->m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition())); + connect(d->m_mainView->rootObject(), SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton())); + connect(d->m_mainView->rootObject(), SIGNAL(updateLockButton()), this, SLOT(updateLockButton())); + connect(this, SIGNAL(jumpToPrev()), d->m_mainView->rootObject(), SLOT(prevEvent())); + connect(this, SIGNAL(jumpToNext()), d->m_mainView->rootObject(), SLOT(nextEvent())); + connect(d->m_mainView->rootObject(), SIGNAL(selectedEventChanged(int)), this, SIGNAL(selectedEventChanged(int))); + connect(d->m_mainView->rootObject(), SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString))); + connect(d->m_mainView->rootObject(), SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int))); +} + +QWidget *QmlProfilerTraceView::createToolbar() +{ + Utils::StyledBar *bar = new Utils::StyledBar(this); + bar->setSingleRow(true); + bar->setFixedWidth(150); + bar->setFixedHeight(24); + + QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); + toolBarLayout->setMargin(0); + toolBarLayout->setSpacing(0); + + QToolButton *buttonPrev= new QToolButton; + buttonPrev->setIcon(QIcon(":/qmlprofiler/ico_prev.png")); + buttonPrev->setToolTip(tr("Jump to previous event")); + connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev())); + connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool))); + + QToolButton *buttonNext= new QToolButton; + buttonNext->setIcon(QIcon(":/qmlprofiler/ico_next.png")); + buttonNext->setToolTip(tr("Jump to next event")); + connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext())); + connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool))); + + QToolButton *buttonZoomControls = new QToolButton; + buttonZoomControls->setIcon(QIcon(":/qmlprofiler/ico_zoom.png")); + buttonZoomControls->setToolTip(tr("Show zoom slider")); + buttonZoomControls->setCheckable(true); + buttonZoomControls->setChecked(false); + connect(buttonZoomControls, SIGNAL(toggled(bool)), d->m_zoomToolbar, SLOT(setVisible(bool))); + connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool))); + + d->m_buttonRange = new QToolButton; + d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); + d->m_buttonRange->setToolTip(tr("Select range")); + d->m_buttonRange->setCheckable(true); + d->m_buttonRange->setChecked(false); + connect(d->m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool))); + connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonRange, SLOT(setEnabled(bool))); + connect(this, SIGNAL(rangeModeChanged(bool)), d->m_buttonRange, SLOT(setChecked(bool))); + + d->m_buttonLock = new QToolButton; + d->m_buttonLock->setIcon(QIcon(":/qmlprofiler/ico_selectionmode.png")); + d->m_buttonLock->setToolTip(tr("View event information on mouseover")); + d->m_buttonLock->setCheckable(true); + d->m_buttonLock->setChecked(false); + connect(d->m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool))); + connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonLock, SLOT(setEnabled(bool))); + connect(this, SIGNAL(lockModeChanged(bool)), d->m_buttonLock, SLOT(setChecked(bool))); + + toolBarLayout->addWidget(buttonPrev); + toolBarLayout->addWidget(buttonNext); + toolBarLayout->addWidget(new Utils::StyledSeparator()); + toolBarLayout->addWidget(buttonZoomControls); + toolBarLayout->addWidget(new Utils::StyledSeparator()); + toolBarLayout->addWidget(d->m_buttonRange); + toolBarLayout->addWidget(d->m_buttonLock); + + return bar; +} + + +QWidget *QmlProfilerTraceView::createZoomToolbar() +{ + Utils::StyledBar *bar = new Utils::StyledBar(this); + bar->setSingleRow(true); + bar->setFixedWidth(150); + bar->setFixedHeight(24); + + QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); + toolBarLayout->setMargin(0); + toolBarLayout->setSpacing(0); + + QSlider *zoomSlider = new QSlider(Qt::Horizontal); + zoomSlider->setFocusPolicy(Qt::NoFocus); + zoomSlider->setRange(1, sliderTicks); + zoomSlider->setInvertedAppearance(true); + zoomSlider->setPageStep(sliderTicks/100); + connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool))); + connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int))); + connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int))); + zoomSlider->setStyleSheet("\ + QSlider:horizontal {\ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\ + border: 1px #313131;\ + height: 20px;\ + margin: 0px 0px 0px 0px;\ + }\ + QSlider::add-page:horizontal {\ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ + border: 1px #313131;\ + }\ + QSlider::sub-page:horizontal {\ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ + border: 1px #313131;\ + }\ + "); + + toolBarLayout->addWidget(zoomSlider); + + return bar; +} + +///////////////////////////////////////////////////////// +bool QmlProfilerTraceView::hasValidSelection() const +{ + if (d->m_mainView->rootObject()) { + return d->m_mainView->rootObject()->property("selectionRangeReady").toBool(); + } + return false; +} + +qint64 QmlProfilerTraceView::selectionStart() const +{ + if (d->m_mainView->rootObject()) { + return d->m_mainView->rootObject()->property("selectionRangeStart").toLongLong(); + } + return 0; +} + +qint64 QmlProfilerTraceView::selectionEnd() const +{ + if (d->m_mainView->rootObject()) { + return d->m_mainView->rootObject()->property("selectionRangeEnd").toLongLong(); + } + return 0; +} + +void QmlProfilerTraceView::clearDisplay() +{ + d->m_zoomControl->setRange(0,0); + + updateVerticalScroll(0); + d->m_mainView->rootObject()->setProperty("scrollY", QVariant(0)); + + QMetaObject::invokeMethod(d->m_mainView->rootObject(), "clearAll"); + QMetaObject::invokeMethod(d->m_overview->rootObject(), "clearDisplay"); +} + +void QmlProfilerTraceView::selectNextEventWithId(int eventId) +{ + if (d->m_mainView->rootObject()) + QMetaObject::invokeMethod(d->m_mainView->rootObject(), "selectNextWithId", + Q_ARG(QVariant,QVariant(eventId))); +} + +///////////////////////////////////////////////////////// +// Goto source location +void QmlProfilerTraceView::updateCursorPosition() +{ + emit gotoSourceLocation(d->m_mainView->rootObject()->property("fileName").toString(), + d->m_mainView->rootObject()->property("lineNumber").toInt(), + d->m_mainView->rootObject()->property("columnNumber").toInt()); +} + +///////////////////////////////////////////////////////// +// Toolbar buttons +void QmlProfilerTraceView::toggleRangeMode(bool active) +{ + bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool(); + if (active != rangeMode) { + if (active) + d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png")); + else + d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); + d->m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active)); + } +} + +void QmlProfilerTraceView::updateRangeButton() +{ + bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool(); + if (rangeMode) + d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png")); + else + d->m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); + emit rangeModeChanged(rangeMode); +} + +void QmlProfilerTraceView::toggleLockMode(bool active) +{ + bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool(); + if (active != lockMode) { + d->m_mainView->rootObject()->setProperty("selectionLocked", QVariant(!active)); + d->m_mainView->rootObject()->setProperty("selectedItem", QVariant(-1)); + } +} + +void QmlProfilerTraceView::updateLockButton() +{ + bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool(); + emit lockModeChanged(lockMode); +} + +//////////////////////////////////////////////////////// +// Zoom control +void QmlProfilerTraceView::setZoomLevel(int zoomLevel) +{ + if (d->m_currentZoomLevel != zoomLevel && d->m_mainView->rootObject()) { + QVariant newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp); + d->m_currentZoomLevel = zoomLevel; + QMetaObject::invokeMethod(d->m_mainView->rootObject(), "updateWindowLength", Q_ARG(QVariant, newFactor)); + } +} + +void QmlProfilerTraceView::updateRange() +{ + if (!d->m_profilerDataModel) + return; + qreal duration = d->m_zoomControl->endTime() - d->m_zoomControl->startTime(); + if (duration <= 0) + return; + if (d->m_profilerDataModel->traceDuration() <= 0) + return; + int newLevel = pow(duration / d->m_profilerDataModel->traceDuration(), 1/sliderExp) * sliderTicks; + if (d->m_currentZoomLevel != newLevel) { + d->m_currentZoomLevel = newLevel; + emit zoomLevelChanged(newLevel); + } +} + +void QmlProfilerTraceView::mouseWheelMoved(int mouseX, int mouseY, int wheelDelta) +{ + Q_UNUSED(mouseY); + if (d->m_mainView->rootObject()) { + QMetaObject::invokeMethod(d->m_mainView->rootObject(), "wheelZoom", + Q_ARG(QVariant, QVariant(mouseX)), + Q_ARG(QVariant, QVariant(wheelDelta))); + } +} +//////////////////////////////////////////////////////// +void QmlProfilerTraceView::updateToolTip(const QString &text) +{ + setToolTip(text); +} + +void QmlProfilerTraceView::updateVerticalScroll(int newPosition) +{ + d->m_mainView->verticalScrollBar()->setValue(newPosition); +} + +void QmlProfilerTraceView::resizeEvent(QResizeEvent *event) +{ + if (d->m_mainView->rootObject()) { + d->m_mainView->rootObject()->setProperty("width", QVariant(event->size().width())); + int newHeight = event->size().height() - d->m_timebar->height() - d->m_overview->height(); + d->m_mainView->rootObject()->setProperty("candidateHeight", QVariant(newHeight)); + } +} + +//////////////////////////////////////////////////////////////// +// Context menu +void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev) +{ + QMenu menu; + QAction *viewAllAction = 0; + QAction *getLocalStatsAction = 0; + QAction *getGlobalStatsAction = 0; + + QmlProfilerTool *profilerTool = qobject_cast<QmlProfilerTool *>(d->m_profilerTool); + QPoint position = ev->globalPos(); + + if (profilerTool) { + QList <QAction *> commonActions = profilerTool->profilerContextMenuActions(); + foreach (QAction *act, commonActions) { + menu.addAction(act); + } + } + + menu.addSeparator(); + getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); + if (!d->m_viewContainer->hasValidSelection()) + getLocalStatsAction->setEnabled(false); + getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); + if (d->m_viewContainer->hasGlobalStats()) + getGlobalStatsAction->setEnabled(false); + + + if (d->m_profilerDataModel->count() > 0) { + menu.addSeparator(); + viewAllAction = menu.addAction(tr("Reset Zoom")); + } + + + QAction *selectedAction = menu.exec(position); + + if (selectedAction) { + if (selectedAction == viewAllAction) { + d->m_zoomControl->setRange( + d->m_profilerDataModel->traceStartTime(), + d->m_profilerDataModel->traceEndTime()); + } + if (selectedAction == getLocalStatsAction) { + d->m_viewContainer->getStatisticsInRange( + d->m_viewContainer->selectionStart(), + d->m_viewContainer->selectionEnd()); + } + if (selectedAction == getGlobalStatsAction) { + d->m_viewContainer->getStatisticsInRange( + d->m_profilerDataModel->traceStartTime(), + d->m_profilerDataModel->traceEndTime()); + } + } +} + +///////////////////////////////////////////////// +// Tell QML the state of the profiler +void QmlProfilerTraceView::setRecording(bool recording) +{ + if (d->m_mainView->rootObject()) + d->m_mainView->rootObject()->setProperty("recordingEnabled", QVariant(recording)); +} + +void QmlProfilerTraceView::setAppKilled() +{ + if (d->m_mainView->rootObject()) + d->m_mainView->rootObject()->setProperty("appKilled",QVariant(true)); +} +//////////////////////////////////////////////////////////////// +// Profiler State +void QmlProfilerTraceView::profilerDataModelStateChanged() +{ + switch (d->m_profilerDataModel->currentState()) { + case QmlProfilerDataModel::Empty : + emit enableToolbar(false); + break; + case QmlProfilerDataModel::AcquiringData : + // nothing to be done + break; + case QmlProfilerDataModel::ProcessingData : + // nothing to be done + break; + case QmlProfilerDataModel::Done : + emit enableToolbar(true); + break; + default: + break; + } +} + +void QmlProfilerTraceView::profilerStateChanged() +{ + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppKilled : { + if (d->m_profilerDataModel->currentState() == QmlProfilerDataModel::AcquiringData) + setAppKilled(); + break; + } + default: + // no special action needed for other states + break; + } +} + +void QmlProfilerTraceView::clientRecordingChanged() +{ + // nothing yet +} + +void QmlProfilerTraceView::serverRecordingChanged() +{ + setRecording(d->m_profilerState->serverRecording()); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/qmlprofilertraceview.h index 2c653e5c0a..6b61380882 100644 --- a/src/plugins/qmlprofiler/tracewindow.h +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.h @@ -30,24 +30,23 @@ ** **************************************************************************/ -#ifndef TRACEWINDOW_H -#define TRACEWINDOW_H +#ifndef QMLPROFILERTRACEVIEW_H +#define QMLPROFILERTRACEVIEW_H -#include <qmljsdebugclient/qmlprofilertraceclient.h> -#include <qmljsdebugclient/qmlprofilereventlist.h> -#include "qmlprofilerdetailsrewriter.h" -#include <qmljsdebugclient/qv8profilerclient.h> - -#include <QPointer> -#include <QWidget> -#include <QToolButton> - -#include <QEvent> #include <QDeclarativeView> +namespace Analyzer { +class IAnalyzerTool; +} + namespace QmlProfiler { namespace Internal { +class QmlProfilerStateManager; +class QmlProfilerViewManager; +class QmlProfilerDataModel; + +// capture mouse wheel events class MouseWheelResizer : public QObject { Q_OBJECT public: @@ -87,118 +86,73 @@ protected: void scrollContentsBy(int dx, int dy); }; -class TraceWindow : public QWidget +class QmlProfilerTraceView : public QWidget { Q_OBJECT public: - TraceWindow(QWidget *parent = 0); - ~TraceWindow(); - - void reset(QmlJsDebugClient::QDeclarativeDebugConnection *conn); + explicit QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerDataModel *model, QmlProfilerStateManager *profilerState); + ~QmlProfilerTraceView(); - QmlJsDebugClient::QmlProfilerEventList *getEventList() const; - ZoomControl *rangeTimes() const; - - void setRecording(bool recording); - bool isRecording() const; - void viewAll(); + void reset(); bool hasValidSelection() const; qint64 selectionStart() const; qint64 selectionEnd() const; - double profiledTime() const; public slots: void clearDisplay(); - void selectNextEvent(int eventId); - void applicationDied(); + void selectNextEventWithId(int eventId); private slots: void updateCursorPosition(); - void updateTimer(); - void updateToolbar(); void toggleRangeMode(bool); - void toggleLockMode(bool); void updateRangeButton(); + void toggleLockMode(bool); void updateLockButton(); + void setZoomLevel(int zoomLevel); void updateRange(); - void mouseWheelMoved(int x, int y, int delta); + void mouseWheelMoved(int mouseX, int mouseY, int wheelDelta); - void qmlComplete(); - void v8Complete(); - void updateProfilerState(); void updateToolTip(const QString &text); void updateVerticalScroll(int newPosition); - void eventListStateChanged(); - void manageTraceStart(qint64 traceStart); - void firstDataReceived(); - void correctTimer(); + void profilerDataModelStateChanged(); + +protected: + virtual void resizeEvent(QResizeEvent *event); + +private slots: + void profilerStateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); signals: - void viewUpdated(); - void profilerStateChanged(bool qmlActive, bool v8active); void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columNumber); - void range(int type, qint64 startTime, qint64 length, const QStringList &data, const QmlJsDebugClient::QmlEventLocation &location); - void v8range(int depth,const QString &function,const QString &filename, - int lineNumber, double totalTime, double selfTime); - void traceFinished(qint64); - void traceStarted(qint64); - void frameEvent(qint64, int, int); - void recordingChanged(bool); - - void internalClearDisplay(); - void clearViewsFromTool(); + void selectedEventChanged(int eventId); + void jumpToPrev(); void jumpToNext(); void rangeModeChanged(bool); void lockModeChanged(bool); void enableToolbar(bool); void zoomLevelChanged(int); - void updateViewZoom(QVariant zoomLevel); - void wheelZoom(QVariant wheelCenter, QVariant wheelDelta); - void globalZoom(); - - void contextMenuRequested(const QPoint& position); - void selectNextEventInDisplay(QVariant eventId); - void selectedEventIdChanged(int eventId); private: void contextMenuEvent(QContextMenuEvent *); QWidget *createToolbar(); QWidget *createZoomToolbar(); - void connectClientSignals(); - void disconnectClientSignals(); - void initializeQmlViews(); -protected: - virtual void resizeEvent(QResizeEvent *event); + void setRecording(bool recording); + void setAppKilled(); private: - QWeakPointer<QmlJsDebugClient::QmlProfilerTraceClient> m_plugin; - QWeakPointer<QmlJsDebugClient::QV8ProfilerClient> m_v8plugin; - QSize m_sizeHint; - - ScrollableDeclarativeView *m_mainView; - QDeclarativeView *m_timebar; - QDeclarativeView *m_overview; - QmlJsDebugClient::QmlProfilerEventList *m_eventList; - QmlProfilerDetailsRewriter *m_rewriter; - bool m_qmlDataReady; - bool m_v8DataReady; - double m_profiledTime; - - QWeakPointer<ZoomControl> m_zoomControl; - - QToolButton *m_buttonRange; - QToolButton *m_buttonLock; - QWidget *m_zoomToolbar; - int m_currentZoomLevel; + class QmlProfilerTraceViewPrivate; + QmlProfilerTraceViewPrivate *d; }; } // namespace Internal } // namespace QmlProfiler -#endif // TRACEWINDOW_H +#endif // QMLPROFILERTRACEVIEW_H diff --git a/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp new file mode 100644 index 0000000000..a12a6ccda5 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp @@ -0,0 +1,172 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "qmlprofilerviewmanager.h" + +#include "qmlprofilertraceview.h" +#include "qmlprofilereventview.h" +#include "qmlprofilertool.h" +#include "qmlprofilerstatemanager.h" +#include "qmlprofilerdatamodel.h" + +#include <utils/qtcassert.h> +#include <utils/fancymainwindow.h> +#include <analyzerbase/analyzermanager.h> + + +#include <QDockWidget> + +using namespace Analyzer; + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerViewManager::QmlProfilerViewManagerPrivate { +public: + QmlProfilerViewManagerPrivate(QmlProfilerViewManager *qq) { Q_UNUSED(qq); } + + QmlProfilerTraceView *traceView; + QmlProfilerEventsWidget *eventsView; + QmlProfilerEventsWidget *v8profilerView; + QmlProfilerStateManager *profilerState; + QmlProfilerDataModel *profilerDataModel; + QmlProfilerTool *profilerTool; +}; + +QmlProfilerViewManager::QmlProfilerViewManager(QObject *parent, + QmlProfilerTool *profilerTool, + QmlProfilerDataModel *model, + QmlProfilerStateManager *profilerState) + : QObject(parent), d(new QmlProfilerViewManagerPrivate(this)) +{ + setObjectName("QML Profiler View Manager"); + d->traceView = 0; + d->eventsView = 0; + d->v8profilerView = 0; + d->profilerState = profilerState; + d->profilerDataModel = model; + d->profilerTool = profilerTool; + createViews(); +} + +QmlProfilerViewManager::~QmlProfilerViewManager() +{ + delete d; +} + +//////////////////////////////////////////////////////////// +// Views +void QmlProfilerViewManager::createViews() +{ + QTC_ASSERT(d->profilerDataModel, return); + QTC_ASSERT(d->profilerState, return); + + Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow(); + + d->traceView = new QmlProfilerTraceView(mw, + d->profilerTool, + this, + d->profilerDataModel, + d->profilerState); + connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)), + this, SIGNAL(gotoSourceLocation(QString,int,int))); + + d->traceView->reset(); + + d->eventsView = new QmlProfilerEventsWidget(mw, d->profilerTool, this, d->profilerDataModel); + connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, + SIGNAL(gotoSourceLocation(QString,int,int))); + connect(d->eventsView, SIGNAL(showEventInTimeline(int)), d->traceView, + SLOT(selectNextEventWithId(int))); + connect(d->traceView, SIGNAL(selectedEventChanged(int)), d->eventsView, + SLOT(updateSelectedEvent(int))); + + d->v8profilerView = new QmlProfilerEventsWidget(mw, d->profilerTool, + this, d->profilerDataModel); + d->v8profilerView->switchToV8View(); + connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), + this, SIGNAL(gotoSourceLocation(QString,int,int))); + connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), + d->eventsView, SLOT(selectBySourceLocation(QString,int,int))); + connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), + d->v8profilerView, SLOT(selectBySourceLocation(QString,int,int))); + + QDockWidget *eventsDock = AnalyzerManager::createDockWidget + (d->profilerTool, tr("Events"), d->eventsView, Qt::BottomDockWidgetArea); + QDockWidget *timelineDock = AnalyzerManager::createDockWidget + (d->profilerTool, tr("Timeline"), d->traceView, Qt::BottomDockWidgetArea); + QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget + (d->profilerTool, tr("JavaScript"), d->v8profilerView, Qt::BottomDockWidgetArea); + + eventsDock->show(); + timelineDock->show(); + v8profilerDock->show(); + + mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical); + mw->tabifyDockWidget(eventsDock, timelineDock); + mw->tabifyDockWidget(timelineDock, v8profilerDock); +} + +bool QmlProfilerViewManager::hasValidSelection() const +{ + return d->traceView->hasValidSelection(); +} + +qint64 QmlProfilerViewManager::selectionStart() const +{ + return d->traceView->selectionStart(); +} + +qint64 QmlProfilerViewManager::selectionEnd() const +{ + return d->traceView->selectionEnd(); +} + +bool QmlProfilerViewManager::hasGlobalStats() const +{ + return d->eventsView->hasGlobalStats(); +} + +void QmlProfilerViewManager::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ + d->eventsView->getStatisticsInRange(rangeStart, rangeEnd); +} + +void QmlProfilerViewManager::clear() +{ + d->traceView->clearDisplay(); + d->eventsView->clear(); + d->v8profilerView->clear(); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/qmlprofilerviewmanager.h b/src/plugins/qmlprofiler/qmlprofilerviewmanager.h new file mode 100644 index 0000000000..4e492918ee --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilerviewmanager.h @@ -0,0 +1,79 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef QMLPROFILERVIEWMANAGER_H +#define QMLPROFILERVIEWMANAGER_H + +#include <QObject> + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerTool; +class QmlProfilerDataModel; +class QmlProfilerStateManager; + +class QmlProfilerViewManager : public QObject +{ + Q_OBJECT +public: + explicit QmlProfilerViewManager(QObject *parent, + QmlProfilerTool *profilerTool, + QmlProfilerDataModel *model, + QmlProfilerStateManager *profilerState); + ~QmlProfilerViewManager(); + + void createViews(); + + // used by the options "limit events to range" + bool hasValidSelection() const; + qint64 selectionStart() const; + qint64 selectionEnd() const; + bool hasGlobalStats() const; + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); + +public slots: + void clear(); + +signals: + void gotoSourceLocation(QString,int,int); + +private: + class QmlProfilerViewManagerPrivate; + QmlProfilerViewManagerPrivate *d; +}; + + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERVIEWMANAGER_H diff --git a/src/plugins/qmlprofiler/qv8profilerdatamodel.cpp b/src/plugins/qmlprofiler/qv8profilerdatamodel.cpp new file mode 100644 index 0000000000..d58f198be6 --- /dev/null +++ b/src/plugins/qmlprofiler/qv8profilerdatamodel.cpp @@ -0,0 +1,445 @@ +#include "qv8profilerdatamodel.h" +#include "qmlprofilerdatamodel.h" + +#include <QStringList> + +using namespace QmlJsDebugClient; + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventData, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventSub, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + +namespace QmlProfiler { +namespace Internal { + +QV8EventData &QV8EventData::operator=(const QV8EventData &ref) +{ + if (this == &ref) + return *this; + + displayName = ref.displayName; + eventHashStr = ref.eventHashStr; + filename = ref.filename; + functionName = ref.functionName; + line = ref.line; + totalTime = ref.totalTime; + totalPercent = ref.totalPercent; + selfTime = ref.selfTime; + selfPercent = ref.selfPercent; + eventId = ref.eventId; + + qDeleteAll(parentHash.values()); + parentHash.clear(); + foreach (const QString &key, ref.parentHash.keys()) { + parentHash.insert(key, new QV8EventSub(ref.parentHash.value(key))); + } + + qDeleteAll(childrenHash.values()); + childrenHash.clear(); + foreach (const QString &key, ref.childrenHash.keys()) { + childrenHash.insert(key, new QV8EventSub(ref.childrenHash.value(key))); + } + return *this; +} + +QV8EventData::QV8EventData() +{ + line = -1; + eventId = -1; + totalTime = 0; + selfTime = 0; + totalPercent = 0; + selfPercent = 0; +} + +QV8EventData::~QV8EventData() +{ + qDeleteAll(parentHash.values()); + parentHash.clear(); + qDeleteAll(childrenHash.values()); + childrenHash.clear(); +} + +class QV8ProfilerDataModel::QV8ProfilerDataModelPrivate +{ +public: + QV8ProfilerDataModelPrivate(QV8ProfilerDataModel *qq) {Q_UNUSED(qq);} + + QmlProfilerDataModel *qmlProfilerDataModel; + + void clearV8RootEvent(); + void collectV8Statistics(); + + QHash<QString, QV8EventData *> v8EventHash; + QHash<int, QV8EventData *> v8parents; + QV8EventData v8RootEvent; + qint64 v8MeasuredTime; +}; + +QV8ProfilerDataModel::QV8ProfilerDataModel(QObject *parent, + QmlProfilerDataModel *profilerDataModel) + : QObject(parent), d(new QV8ProfilerDataModelPrivate(this)) +{ + d->v8MeasuredTime = 0; + d->clearV8RootEvent(); + d->qmlProfilerDataModel = profilerDataModel; +} + +QV8ProfilerDataModel::~QV8ProfilerDataModel() +{ + delete d; +} + +void QV8ProfilerDataModel::clear() +{ + qDeleteAll(d->v8EventHash.values()); + d->v8EventHash.clear(); + d->v8parents.clear(); + d->clearV8RootEvent(); + d->v8MeasuredTime = 0; +} + +bool QV8ProfilerDataModel::isEmpty() const +{ + return d->v8EventHash.isEmpty(); +} + +QV8EventData *QV8ProfilerDataModel::v8EventDescription(int eventId) const +{ + foreach (QV8EventData *event, d->v8EventHash.values()) { + if (event->eventId == eventId) + return event; + } + return 0; +} + +qint64 QV8ProfilerDataModel::v8MeasuredTime() const +{ + return d->v8MeasuredTime; +} + +QList<QV8EventData *> QV8ProfilerDataModel::getV8Events() const +{ + return d->v8EventHash.values(); +} + +void QV8ProfilerDataModel::addV8Event(int depth, + const QString &function, + const QString &filename, + int lineNumber, + double totalTime, + double selfTime) +{ + QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + + QLatin1Char(':') + QString::number(lineNumber); + QString hashStr = QmlProfilerDataModel::getHashStringForV8Event(displayName, function); + + d->qmlProfilerDataModel->setState(QmlProfilerDataModel::AcquiringData); + + // time is given in milliseconds, but internally we store it in microseconds + totalTime *= 1e6; + selfTime *= 1e6; + + // accumulate information + QV8EventData *eventData = d->v8EventHash[hashStr]; + if (!eventData) { + eventData = new QV8EventData; + eventData->displayName = displayName; + eventData->eventHashStr = hashStr; + eventData->filename = filename; + eventData->functionName = function; + eventData->line = lineNumber; + eventData->totalTime = totalTime; + eventData->selfTime = selfTime; + d->v8EventHash[hashStr] = eventData; + } else { + eventData->totalTime += totalTime; + eventData->selfTime += selfTime; + } + d->v8parents[depth] = eventData; + + QV8EventData *parentEvent = 0; + if (depth == 0) { + parentEvent = &d->v8RootEvent; + d->v8MeasuredTime += totalTime; + } + if (depth > 0 && d->v8parents.contains(depth-1)) { + parentEvent = d->v8parents.value(depth-1); + } + + if (parentEvent != 0) { + if (!eventData->parentHash.contains(parentEvent->eventHashStr)) { + QV8EventSub *newParentSub = new QV8EventSub(parentEvent); + newParentSub->totalTime = totalTime; + + eventData->parentHash.insert(parentEvent->eventHashStr, newParentSub); + } else { + QV8EventSub *newParentSub = eventData->parentHash.value(parentEvent->eventHashStr); + newParentSub->totalTime += totalTime; + } + + if (!parentEvent->childrenHash.contains(eventData->eventHashStr)) { + QV8EventSub *newChildSub = new QV8EventSub(eventData); + newChildSub->totalTime = totalTime; + + parentEvent->childrenHash.insert(eventData->eventHashStr, newChildSub); + } else { + QV8EventSub *newChildSub = parentEvent->childrenHash.value(eventData->eventHashStr); + newChildSub->totalTime += totalTime; + } + } +} + +void QV8ProfilerDataModel::collectV8Statistics() +{ + d->collectV8Statistics(); +} + +void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::collectV8Statistics() +{ + if (!v8EventHash.isEmpty()) { + double totalTimes = v8MeasuredTime; + double selfTimes = 0; + foreach (QV8EventData *v8event, v8EventHash.values()) { + selfTimes += v8event->selfTime; + } + + // prevent divisions by 0 + if (totalTimes == 0) + totalTimes = 1; + if (selfTimes == 0) + selfTimes = 1; + + // insert root event in eventlist + // the +1 ns is to get it on top of the sorted list + v8RootEvent.totalTime = v8MeasuredTime + 1; + v8RootEvent.selfTime = 0; + + QString rootEventHash = QmlProfilerDataModel::getHashStringForV8Event( + QmlProfilerDataModel::rootEventName(), + QmlProfilerDataModel::rootEventDescription()); + QV8EventData *v8RootEventPointer = v8EventHash[rootEventHash]; + if (v8RootEventPointer) { + v8RootEvent = *v8RootEventPointer; + } else { + v8EventHash[rootEventHash] = new QV8EventData; + *v8EventHash[rootEventHash] = v8RootEvent; + } + + foreach (QV8EventData *v8event, v8EventHash.values()) { + v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes; + v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes; + } + + int index = 0; + foreach (QV8EventData *v8event, v8EventHash.values()) { + v8event->eventId = index++; + } + v8RootEvent.eventId = v8EventHash[rootEventHash]->eventId; + } +} + +void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::clearV8RootEvent() +{ + v8RootEvent.displayName = QmlProfilerDataModel::rootEventName(); + v8RootEvent.eventHashStr = QmlProfilerDataModel::rootEventName(); + v8RootEvent.functionName = QmlProfilerDataModel::rootEventDescription(); + v8RootEvent.line = -1; + v8RootEvent.totalTime = 0; + v8RootEvent.totalPercent = 0; + v8RootEvent.selfTime = 0; + v8RootEvent.selfPercent = 0; + v8RootEvent.eventId = -1; + + qDeleteAll(v8RootEvent.parentHash.values()); + qDeleteAll(v8RootEvent.childrenHash.values()); + v8RootEvent.parentHash.clear(); + v8RootEvent.childrenHash.clear(); +} + +void QV8ProfilerDataModel::save(QXmlStreamWriter &stream) +{ + stream.writeStartElement("v8profile"); // v8 profiler output + stream.writeAttribute("totalTime", QString::number(d->v8MeasuredTime)); + foreach (QV8EventData *v8event, d->v8EventHash.values()) { + stream.writeStartElement("event"); + stream.writeAttribute("index", + QString::number( + d->v8EventHash.keys().indexOf( + v8event->eventHashStr))); + stream.writeTextElement("displayname", v8event->displayName); + stream.writeTextElement("functionname", v8event->functionName); + if (!v8event->filename.isEmpty()) { + stream.writeTextElement("filename", v8event->filename); + stream.writeTextElement("line", QString::number(v8event->line)); + } + stream.writeTextElement("totalTime", QString::number(v8event->totalTime)); + stream.writeTextElement("selfTime", QString::number(v8event->selfTime)); + if (!v8event->childrenHash.isEmpty()) { + stream.writeStartElement("childrenEvents"); + QStringList childrenIndexes; + QStringList childrenTimes; + QStringList parentTimes; + foreach (QV8EventSub *v8child, v8event->childrenHash.values()) { + childrenIndexes << QString::number(v8child->reference->eventId); + childrenTimes << QString::number(v8child->totalTime); + parentTimes << QString::number(v8child->totalTime); + } + + stream.writeAttribute("list", childrenIndexes.join(QString(", "))); + stream.writeAttribute("childrenTimes", childrenTimes.join(QString(", "))); + stream.writeAttribute("parentTimes", parentTimes.join(QString(", "))); + stream.writeEndElement(); + } + stream.writeEndElement(); + } + stream.writeEndElement(); // v8 profiler output +} + +void QV8ProfilerDataModel::load(QXmlStreamReader &stream) +{ + QHash <int, QV8EventData *> v8eventBuffer; + QHash <int, QString> childrenIndexes; + QHash <int, QString> childrenTimes; + QHash <int, QString> parentTimes; + QV8EventData *v8event = 0; + + // time computation + d->v8MeasuredTime = 0; + double cumulatedV8Time = 0; + + // get the v8 time + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute("totalTime")) + d->v8MeasuredTime = attributes.value("totalTime").toString().toDouble(); + + while (!stream.atEnd() && !stream.hasError()) { + QXmlStreamReader::TokenType token = stream.readNext(); + QString elementName = stream.name().toString(); + switch (token) { + case QXmlStreamReader::StartDocument : continue; + case QXmlStreamReader::StartElement : { + if (elementName == "event") { + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute("index")) { + int ndx = attributes.value("index").toString().toInt(); + if (!v8eventBuffer.value(ndx)) + v8eventBuffer[ndx] = new QV8EventData; + v8event = v8eventBuffer[ndx]; + } else { + v8event = 0; + } + break; + } + + if (!v8event) + break; + + if (elementName == "childrenEvents") { + QXmlStreamAttributes attributes = stream.attributes(); + int eventIndex = v8eventBuffer.key(v8event); + if (attributes.hasAttribute("list")) { + // store for later parsing (we haven't read all the events yet) + childrenIndexes[eventIndex] = attributes.value("list").toString(); + } + if (attributes.hasAttribute("childrenTimes")) { + childrenTimes[eventIndex] = + attributes.value("childrenTimes").toString(); + } + if (attributes.hasAttribute("parentTimes")) { + parentTimes[eventIndex] = attributes.value("parentTimes").toString(); + } + } + + stream.readNext(); + if (stream.tokenType() != QXmlStreamReader::Characters) + break; + QString readData = stream.text().toString(); + + if (elementName == "displayname") { + v8event->displayName = readData; + break; + } + + if (elementName == "functionname") { + v8event->functionName = readData; + break; + } + + if (elementName == "filename") { + v8event->filename = readData; + break; + } + + if (elementName == "line") { + v8event->line = readData.toInt(); + break; + } + + if (elementName == "totalTime") { + v8event->totalTime = readData.toDouble(); + cumulatedV8Time += v8event->totalTime; + break; + } + + if (elementName == "selfTime") { + v8event->selfTime = readData.toDouble(); + break; + } + break; + } + case QXmlStreamReader::EndElement : { + if (elementName == "v8profile") { + // done reading the v8 profile data + break; + } + } + default: break; + } +} + + // backwards compatibility + if (d->v8MeasuredTime == 0) + d->v8MeasuredTime = cumulatedV8Time; + + // find v8events' children and parents + foreach (int parentIndex, childrenIndexes.keys()) { + QStringList childrenStrings = childrenIndexes.value(parentIndex).split(","); + QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(", "); + QStringList parentTimesStrings = parentTimes.value(parentIndex).split(", "); + for (int ndx = 0; ndx < childrenStrings.count(); ndx++) { + int childIndex = childrenStrings[ndx].toInt(); + if (v8eventBuffer.value(childIndex)) { + QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]); + QV8EventSub *newParent = new QV8EventSub(v8eventBuffer[parentIndex]); + if (childrenTimesStrings.count() > ndx) { + newChild->totalTime = childrenTimesStrings[ndx].toDouble(); + } + if (parentTimesStrings.count() > ndx) { + newParent->totalTime = parentTimesStrings[ndx].toDouble(); + } + v8eventBuffer[parentIndex]->childrenHash.insert( + newChild->reference->displayName, + newChild); + v8eventBuffer[childIndex]->parentHash.insert( + newParent->reference->displayName, + newParent); + } + } + } + + // store v8 events + foreach (QV8EventData *storedV8Event, v8eventBuffer.values()) { + storedV8Event->eventHashStr = + QmlProfilerDataModel::getHashStringForV8Event( + storedV8Event->displayName, storedV8Event->functionName); + d->v8EventHash[storedV8Event->eventHashStr] = storedV8Event; + } + + d->collectV8Statistics(); + +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/qv8profilerdatamodel.h b/src/plugins/qmlprofiler/qv8profilerdatamodel.h new file mode 100644 index 0000000000..6441a24702 --- /dev/null +++ b/src/plugins/qmlprofiler/qv8profilerdatamodel.h @@ -0,0 +1,79 @@ +#ifndef QV8PROFILERDATAMODEL_H +#define QV8PROFILERDATAMODEL_H + +#include <QObject> +#include <QHash> + +#include <QXmlStreamReader> +#include <QXmlStreamWriter> + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerDataModel; +struct QV8EventSub; + +struct QV8EventData +{ + QV8EventData(); + ~QV8EventData(); + + QString displayName; + QString eventHashStr; + QString filename; + QString functionName; + int line; + double totalTime; // given in milliseconds + double totalPercent; + double selfTime; + double selfPercent; + QHash <QString, QV8EventSub *> parentHash; + QHash <QString, QV8EventSub *> childrenHash; + int eventId; + + QV8EventData &operator=(const QV8EventData &ref); +}; + +struct QV8EventSub { + QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {} + QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {} + + QV8EventData *reference; + qint64 totalTime; +}; + +class QV8ProfilerDataModel : public QObject +{ + Q_OBJECT +public: + explicit QV8ProfilerDataModel(QObject *parent, QmlProfilerDataModel *profilerDataModel); + ~QV8ProfilerDataModel(); + + void clear(); + bool isEmpty() const; + QList<QV8EventData *> getV8Events() const; + QV8EventData *v8EventDescription(int eventId) const; + + qint64 v8MeasuredTime() const; + void collectV8Statistics(); + + void save(QXmlStreamWriter &stream); + void load(QXmlStreamReader &stream); + +public slots: + void addV8Event(int depth, + const QString &function, + const QString &filename, + int lineNumber, + double totalTime, + double selfTime); + +private: + class QV8ProfilerDataModelPrivate; + QV8ProfilerDataModelPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QV8PROFILERDATAMODEL_H diff --git a/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp b/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp index 7ca1b59b6c..7930cf3333 100644 --- a/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp +++ b/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.cpp @@ -33,8 +33,8 @@ #include "remotelinuxqmlprofilerrunner.h" #include <extensionsystem/pluginmanager.h> #include <projectexplorer/projectexplorerconstants.h> -#include <remotelinux/portlist.h> #include <remotelinux/remotelinuxapplicationrunner.h> +#include <utils/portlist.h> #include <utils/qtcassert.h> using namespace ExtensionSystem; @@ -45,7 +45,7 @@ using namespace RemoteLinux; RemoteLinuxQmlProfilerRunner::RemoteLinuxQmlProfilerRunner( RemoteLinuxRunConfiguration *runConfiguration, QObject *parent) : AbstractQmlProfilerRunner(parent) - , m_port(-1) + , m_port(0) , m_runControl(0) { // find run control factory @@ -96,7 +96,7 @@ void RemoteLinuxQmlProfilerRunner::stop() runner()->stop(); } -int RemoteLinuxQmlProfilerRunner::debugPort() const +quint16 RemoteLinuxQmlProfilerRunner::debugPort() const { return m_port; } @@ -105,7 +105,7 @@ void RemoteLinuxQmlProfilerRunner::getPorts() { QTC_ASSERT(runner(), return); m_port = runner()->freePorts()->getNext(); - if (m_port == -1) { + if (m_port == 0) { emit appendMessage(tr("Not enough free ports on device for analyzing.\n"), Utils::ErrorMessageFormat); runner()->stop(); diff --git a/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.h b/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.h index 7841a6ae7c..086e1aa33e 100644 --- a/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.h +++ b/src/plugins/qmlprofiler/remotelinuxqmlprofilerrunner.h @@ -53,7 +53,7 @@ public: // AbstractQmlProfilerRunner virtual void start(); virtual void stop(); - virtual int debugPort() const; + virtual quint16 debugPort() const; private slots: void getPorts(); @@ -67,7 +67,7 @@ private slots: private: RemoteLinux::AbstractRemoteLinuxApplicationRunner *runner() const; - int m_port; + quint16 m_port; RemoteLinux::AbstractRemoteLinuxRunControl *m_runControl; }; diff --git a/src/plugins/qmlprofiler/timelineview.cpp b/src/plugins/qmlprofiler/timelinerenderer.cpp index 1e10eb0075..a078d31f84 100644 --- a/src/plugins/qmlprofiler/timelineview.cpp +++ b/src/plugins/qmlprofiler/timelinerenderer.cpp @@ -30,7 +30,7 @@ ** **************************************************************************/ -#include "timelineview.h" +#include "timelinerenderer.h" #include <qdeclarativecontext.h> #include <qdeclarativeproperty.h> @@ -45,9 +45,9 @@ using namespace QmlProfiler::Internal; const int DefaultRowHeight = 30; -TimelineView::TimelineView(QDeclarativeItem *parent) : +TimelineRenderer::TimelineRenderer(QDeclarativeItem *parent) : QDeclarativeItem(parent), m_startTime(0), m_endTime(0), m_spacing(0), - m_lastStartTime(0), m_lastEndTime(0), m_eventList(0) + m_lastStartTime(0), m_lastEndTime(0), m_profilerDataModel(0) { clearData(); setFlag(QGraphicsItem::ItemHasNoContents, false); @@ -57,12 +57,12 @@ TimelineView::TimelineView(QDeclarativeItem *parent) : m_rowsExpanded << false; } -void TimelineView::componentComplete() +void TimelineRenderer::componentComplete() { const QMetaObject *metaObject = this->metaObject(); int propertyCount = metaObject->propertyCount(); int requestPaintMethod = metaObject->indexOfMethod("requestPaint()"); - for (int ii = TimelineView::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) { + for (int ii = TimelineRenderer::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) { QMetaProperty p = metaObject->property(ii); if (p.hasNotifySignal()) QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0); @@ -70,12 +70,12 @@ void TimelineView::componentComplete() QDeclarativeItem::componentComplete(); } -void TimelineView::requestPaint() +void TimelineRenderer::requestPaint() { update(); } -void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) +void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { qint64 windowDuration = m_endTime - m_startTime; if (windowDuration <= 0) @@ -86,7 +86,8 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget m_rowWidths.clear(); // The "1+" is because the reference screenshot features an empty row per type, in order to leave space for the title for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++) { - m_rowWidths << 1 + (m_rowsExpanded[i] ? m_eventList->uniqueEventsOfType(i) : m_eventList->maxNestingForType(i)); + m_rowWidths << 1 + (m_rowsExpanded[i] ? m_profilerDataModel->uniqueEventsOfType(i) : + m_profilerDataModel->maxNestingForType(i)); } // event rows @@ -105,8 +106,8 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget for (int j=0; j<m_rowWidths[i]; j++) m_rowLastX << -m_startTime * m_spacing; - int firstIndex = m_eventList->findFirstIndex(m_startTime); - int lastIndex = m_eventList->findLastIndex(m_endTime); + int firstIndex = m_profilerDataModel->findFirstIndex(m_startTime); + int lastIndex = m_profilerDataModel->findLastIndex(m_endTime); drawItemsToPainter(p, firstIndex, lastIndex); drawSelectionBoxes(p, firstIndex, lastIndex); @@ -116,25 +117,27 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget m_lastEndTime = m_endTime; } -QColor TimelineView::colorForItem(int itemIndex) +QColor TimelineRenderer::colorForItem(int itemIndex) { - int ndx = m_eventList->getEventId(itemIndex); + int ndx = m_profilerDataModel->getEventId(itemIndex); return QColor::fromHsl((ndx*25)%360, 76, 166); } -void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) +void TimelineRenderer::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) { int x, y, width, height, rowNumber, eventType; for (int i = fromIndex; i <= toIndex; i++) { - x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing; + x = (m_profilerDataModel->getStartTime(i) - m_startTime) * m_spacing; - eventType = m_eventList->getType(i); + eventType = m_profilerDataModel->getType(i); if (m_rowsExpanded[eventType]) - y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1); + y = m_rowStarts[eventType] + DefaultRowHeight * + (m_profilerDataModel->eventPosInType(i) + 1); else - y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i); + y = m_rowStarts[eventType] + DefaultRowHeight * + m_profilerDataModel->getNestingLevel(i); - width = m_eventList->getDuration(i)*m_spacing; + width = m_profilerDataModel->getDuration(i)*m_spacing; if (width<1) width = 1; @@ -144,17 +147,19 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) m_rowLastX[rowNumber] = x+width; // special: animations - if (eventType == 0 && m_eventList->getAnimationCount(i) >= 0) { - double scale = m_eventList->getMaximumAnimationCount() - m_eventList->getMinimumAnimationCount(); + if (eventType == 0 && m_profilerDataModel->getAnimationCount(i) >= 0) { + double scale = m_profilerDataModel->getMaximumAnimationCount() - + m_profilerDataModel->getMinimumAnimationCount(); double fraction; if (scale > 1) - fraction = (double)(m_eventList->getAnimationCount(i) - m_eventList->getMinimumAnimationCount()) / scale; + fraction = (double)(m_profilerDataModel->getAnimationCount(i) - + m_profilerDataModel->getMinimumAnimationCount()) / scale; else fraction = 1.0; height = DefaultRowHeight * (fraction * 0.85 + 0.15); y += DefaultRowHeight - height; - double fpsFraction = m_eventList->getFramerate(i) / 60.0; + double fpsFraction = m_profilerDataModel->getFramerate(i) / 60.0; if (fpsFraction > 1.0) fpsFraction = 1.0; p->setBrush(QColor::fromHsl((fpsFraction*96)+10, 76, 166)); @@ -167,12 +172,12 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) } } -void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex) +void TimelineRenderer::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex) { if (m_selectedItem == -1) return; - int id = m_eventList->getEventId(m_selectedItem); + int id = m_profilerDataModel->getEventId(m_selectedItem); p->setBrush(Qt::transparent); QColor selectionColor = Qt::blue; @@ -188,17 +193,19 @@ void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex) QRect selectedItemRect(0,0,0,0); for (int i = fromIndex; i <= toIndex; i++) { - if (m_eventList->getEventId(i) != id) + if (m_profilerDataModel->getEventId(i) != id) continue; - x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing; - eventType = m_eventList->getType(i); + x = (m_profilerDataModel->getStartTime(i) - m_startTime) * m_spacing; + eventType = m_profilerDataModel->getType(i); if (m_rowsExpanded[eventType]) - y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1); + y = m_rowStarts[eventType] + DefaultRowHeight * + (m_profilerDataModel->eventPosInType(i) + 1); else - y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i); + y = m_rowStarts[eventType] + DefaultRowHeight * + m_profilerDataModel->getNestingLevel(i); - width = m_eventList->getDuration(i)*m_spacing; + width = m_profilerDataModel->getDuration(i)*m_spacing; if (width<1) width = 1; @@ -215,7 +222,7 @@ void TimelineView::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex) } } -void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex) +void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex) { int destindex; int xfrom, xto, eventType; @@ -228,35 +235,38 @@ void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toInde p->save(); for (int i = fromIndex; i <= toIndex; i++) { - destindex = m_eventList->getBindingLoopDest(i); + destindex = m_profilerDataModel->getBindingLoopDest(i); if (destindex >= 0) { // from - xfrom = (m_eventList->getStartTime(i) + m_eventList->getDuration(i)/2 - + xfrom = (m_profilerDataModel->getStartTime(i) + + m_profilerDataModel->getDuration(i)/2 - m_startTime) * m_spacing; - eventType = m_eventList->getType(i); + eventType = m_profilerDataModel->getType(i); if (m_rowsExpanded[eventType]) yfrom = m_rowStarts[eventType] + DefaultRowHeight* - (m_eventList->eventPosInType(i) + 1); + (m_profilerDataModel->eventPosInType(i) + 1); else - yfrom = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i); + yfrom = m_rowStarts[eventType] + DefaultRowHeight * + m_profilerDataModel->getNestingLevel(i); yfrom += DefaultRowHeight / 2; // to - xto = (m_eventList->getStartTime(destindex) + m_eventList->getDuration(destindex)/2 - + xto = (m_profilerDataModel->getStartTime(destindex) + + m_profilerDataModel->getDuration(destindex)/2 - m_startTime) * m_spacing; - eventType = m_eventList->getType(destindex); + eventType = m_profilerDataModel->getType(destindex); if (m_rowsExpanded[eventType]) - yto = m_rowStarts[eventType] + DefaultRowHeight* - (m_eventList->eventPosInType(destindex) + 1); + yto = m_rowStarts[eventType] + DefaultRowHeight * + (m_profilerDataModel->eventPosInType(destindex) + 1); else yto = m_rowStarts[eventType] + DefaultRowHeight * - m_eventList->getNestingLevel(destindex); + m_profilerDataModel->getNestingLevel(destindex); yto += DefaultRowHeight / 2; // radius - int eventWidth = m_eventList->getDuration(i) * m_spacing; + int eventWidth = m_profilerDataModel->getDuration(i) * m_spacing; radius = 5; if (radius * 2 > eventWidth) radius = eventWidth / 2; @@ -283,7 +293,7 @@ void TimelineView::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toInde p->restore(); } -void TimelineView::mousePressEvent(QGraphicsSceneMouseEvent *event) +void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event) { // special case: if there is a drag area below me, don't accept the // events unless I'm actually clicking inside an item @@ -294,19 +304,19 @@ void TimelineView::mousePressEvent(QGraphicsSceneMouseEvent *event) } -void TimelineView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +void TimelineRenderer::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event); manageClicked(); } -void TimelineView::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +void TimelineRenderer::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { event->setAccepted(false); } -void TimelineView::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +void TimelineRenderer::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event); manageHovered(event->pos().x(), event->pos().y()); @@ -314,7 +324,7 @@ void TimelineView::hoverMoveEvent(QGraphicsSceneHoverEvent *event) event->setAccepted(false); } -void TimelineView::manageClicked() +void TimelineRenderer::manageClicked() { if (m_currentSelection.eventIndex != -1) { if (m_currentSelection.eventIndex == m_selectedItem) @@ -328,7 +338,7 @@ void TimelineView::manageClicked() setSelectedItem(m_currentSelection.eventIndex); } -void TimelineView::manageHovered(int x, int y) +void TimelineRenderer::manageHovered(int x, int y) { if (m_endTime - m_startTime <=0 || m_lastEndTime - m_lastStartTime <= 0) return; @@ -337,13 +347,16 @@ void TimelineView::manageHovered(int x, int y) int row = y / DefaultRowHeight; // already covered? nothing to do - if (m_currentSelection.eventIndex != -1 && time >= m_currentSelection.startTime && time <= m_currentSelection.endTime && row == m_currentSelection.row) { + if (m_currentSelection.eventIndex != -1 && + time >= m_currentSelection.startTime && + time <= m_currentSelection.endTime && + row == m_currentSelection.row) { return; } // find if there's items in the time range - int eventFrom = m_eventList->findFirstIndex(time); - int eventTo = m_eventList->findLastIndex(time); + int eventFrom = m_profilerDataModel->findFirstIndex(time); + int eventTo = m_profilerDataModel->findLastIndex(time); if (eventTo < eventFrom) { m_currentSelection.eventIndex = -1; return; @@ -352,19 +365,21 @@ void TimelineView::manageHovered(int x, int y) // find if we are in the right column int itemRow, eventType; for (int i=eventTo; i>=eventFrom; --i) { - if (ceil(m_eventList->getEndTime(i)*m_spacing) < floor(time*m_spacing)) + if (ceil(m_profilerDataModel->getEndTime(i)*m_spacing) < floor(time*m_spacing)) continue; - eventType = m_eventList->getType(i); + eventType = m_profilerDataModel->getType(i); if (m_rowsExpanded[eventType]) - itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->eventPosInType(i) + 1; + itemRow = m_rowStarts[eventType]/DefaultRowHeight + + m_profilerDataModel->eventPosInType(i) + 1; else - itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->getNestingLevel(i); + itemRow = m_rowStarts[eventType]/DefaultRowHeight + + m_profilerDataModel->getNestingLevel(i); if (itemRow == row) { // match m_currentSelection.eventIndex = i; - m_currentSelection.startTime = m_eventList->getStartTime(i); - m_currentSelection.endTime = m_eventList->getEndTime(i); + m_currentSelection.startTime = m_profilerDataModel->getStartTime(i); + m_currentSelection.endTime = m_profilerDataModel->getEndTime(i); m_currentSelection.row = row; if (!m_selectionLocked) setSelectedItem(i); @@ -376,7 +391,7 @@ void TimelineView::manageHovered(int x, int y) return; } -void TimelineView::clearData() +void TimelineRenderer::clearData() { m_startTime = 0; m_endTime = 0; @@ -390,122 +405,125 @@ void TimelineView::clearData() m_selectionLocked = true; } -qint64 TimelineView::getDuration(int index) const +qint64 TimelineRenderer::getDuration(int index) const { - Q_ASSERT(m_eventList); - return m_eventList->getEndTime(index) - m_eventList->getStartTime(index); + Q_ASSERT(m_profilerDataModel); + return m_profilerDataModel->getEndTime(index) - + m_profilerDataModel->getStartTime(index); } -QString TimelineView::getFilename(int index) const +QString TimelineRenderer::getFilename(int index) const { - Q_ASSERT(m_eventList); - return m_eventList->getFilename(index); + Q_ASSERT(m_profilerDataModel); + return m_profilerDataModel->getFilename(index); } -int TimelineView::getLine(int index) const +int TimelineRenderer::getLine(int index) const { - Q_ASSERT(m_eventList); - return m_eventList->getLine(index); + Q_ASSERT(m_profilerDataModel); + return m_profilerDataModel->getLine(index); } -QString TimelineView::getDetails(int index) const +QString TimelineRenderer::getDetails(int index) const { - Q_ASSERT(m_eventList); - return m_eventList->getDetails(index); + Q_ASSERT(m_profilerDataModel); + return m_profilerDataModel->getDetails(index); } -int TimelineView::getYPosition(int index) const +int TimelineRenderer::getYPosition(int index) const { - Q_ASSERT(m_eventList); - if (index >= m_eventList->count() || m_rowStarts.isEmpty()) + Q_ASSERT(m_profilerDataModel); + if (index >= m_profilerDataModel->count() || m_rowStarts.isEmpty()) return 0; - int y, eventType = m_eventList->getType(index); + int y, eventType = m_profilerDataModel->getType(index); if (m_rowsExpanded[eventType]) - y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(index) + 1); + y = m_rowStarts[eventType] + DefaultRowHeight * + (m_profilerDataModel->eventPosInType(index) + 1); else - y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(index); + y = m_rowStarts[eventType] + DefaultRowHeight * + m_profilerDataModel->getNestingLevel(index); return y; } -void TimelineView::setRowExpanded(int rowIndex, bool expanded) +void TimelineRenderer::setRowExpanded(int rowIndex, bool expanded) { m_rowsExpanded[rowIndex] = expanded; update(); } -void TimelineView::selectNext() +void TimelineRenderer::selectNext() { - if (m_eventList->count() == 0) + if (m_profilerDataModel->count() == 0) return; // select next in view or after int newIndex = m_selectedItem+1; - if (newIndex >= m_eventList->count()) + if (newIndex >= m_profilerDataModel->count()) newIndex = 0; - if (m_eventList->getEndTime(newIndex) < m_startTime) - newIndex = m_eventList->findFirstIndexNoParents(m_startTime); + if (m_profilerDataModel->getEndTime(newIndex) < m_startTime) + newIndex = m_profilerDataModel->findFirstIndexNoParents(m_startTime); setSelectedItem(newIndex); } -void TimelineView::selectPrev() +void TimelineRenderer::selectPrev() { - if (m_eventList->count() == 0) + if (m_profilerDataModel->count() == 0) return; // select last in view or before int newIndex = m_selectedItem-1; if (newIndex < 0) - newIndex = m_eventList->count()-1; - if (m_eventList->getStartTime(newIndex) > m_endTime) - newIndex = m_eventList->findLastIndex(m_endTime); + newIndex = m_profilerDataModel->count()-1; + if (m_profilerDataModel->getStartTime(newIndex) > m_endTime) + newIndex = m_profilerDataModel->findLastIndex(m_endTime); setSelectedItem(newIndex); } -int TimelineView::nextItemFromId(int eventId) const +int TimelineRenderer::nextItemFromId(int eventId) const { int ndx = -1; if (m_selectedItem == -1) - ndx = m_eventList->findFirstIndexNoParents(m_startTime); + ndx = m_profilerDataModel->findFirstIndexNoParents(m_startTime); else ndx = m_selectedItem + 1; - if (ndx >= m_eventList->count()) + if (ndx >= m_profilerDataModel->count()) ndx = 0; int startIndex = ndx; do { - if (m_eventList->getEventId(ndx) == eventId) + if (m_profilerDataModel->getEventId(ndx) == eventId) return ndx; - ndx = (ndx + 1) % m_eventList->count(); + ndx = (ndx + 1) % m_profilerDataModel->count(); } while (ndx != startIndex); return -1; } -int TimelineView::prevItemFromId(int eventId) const +int TimelineRenderer::prevItemFromId(int eventId) const { int ndx = -1; if (m_selectedItem == -1) - ndx = m_eventList->findFirstIndexNoParents(m_startTime); + ndx = m_profilerDataModel->findFirstIndexNoParents(m_startTime); else ndx = m_selectedItem - 1; if (ndx < 0) - ndx = m_eventList->count() - 1; + ndx = m_profilerDataModel->count() - 1; int startIndex = ndx; do { - if (m_eventList->getEventId(ndx) == eventId) + if (m_profilerDataModel->getEventId(ndx) == eventId) return ndx; if (--ndx < 0) - ndx = m_eventList->count()-1; + ndx = m_profilerDataModel->count()-1; } while (ndx != startIndex); return -1; } -void TimelineView::selectNextFromId(int eventId) +void TimelineRenderer::selectNextFromId(int eventId) { int eventIndex = nextItemFromId(eventId); if (eventIndex != -1) setSelectedItem(eventIndex); } -void TimelineView::selectPrevFromId(int eventId) +void TimelineRenderer::selectPrevFromId(int eventId) { int eventIndex = prevItemFromId(eventId); if (eventIndex != -1) diff --git a/src/plugins/qmlprofiler/timelineview.h b/src/plugins/qmlprofiler/timelinerenderer.h index 357662ea3e..6b776b4c04 100644 --- a/src/plugins/qmlprofiler/timelineview.h +++ b/src/plugins/qmlprofiler/timelinerenderer.h @@ -30,29 +30,29 @@ ** **************************************************************************/ -#ifndef TIMELINEVIEW_H -#define TIMELINEVIEW_H +#ifndef TIMELINERENDERER_H +#define TIMELINERENDERER_H #include <QDeclarativeItem> #include <QScriptValue> -#include <qmljsdebugclient/qmlprofilereventlist.h> +#include "qmlprofilerdatamodel.h" namespace QmlProfiler { namespace Internal { -class TimelineView : public QDeclarativeItem +class TimelineRenderer : public QDeclarativeItem { Q_OBJECT Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged) Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged) - Q_PROPERTY(QObject* eventList READ eventList WRITE setEventList NOTIFY eventListChanged) + Q_PROPERTY(QObject* profilerDataModel READ profilerDataModel WRITE setProfilerDataModel NOTIFY profilerDataModelChanged) Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged) Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged) Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged) Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged) public: - explicit TimelineView(QDeclarativeItem *parent = 0); + explicit TimelineRenderer(QDeclarativeItem *parent = 0); qint64 startTime() const { @@ -84,11 +84,11 @@ public: return m_endDragArea; } - QmlJsDebugClient::QmlProfilerEventList *eventList() const { return m_eventList; } - void setEventList(QObject *eventList) + QmlProfilerDataModel *profilerDataModel() const { return m_profilerDataModel; } + void setProfilerDataModel(QObject *profilerDataModel) { - m_eventList = qobject_cast<QmlJsDebugClient::QmlProfilerEventList *>(eventList); - emit eventListChanged(m_eventList); + m_profilerDataModel = qobject_cast<QmlProfilerDataModel *>(profilerDataModel); + emit profilerDataModelChanged(m_profilerDataModel); } Q_INVOKABLE qint64 getDuration(int index) const; @@ -109,7 +109,7 @@ public: signals: void startTimeChanged(qint64 arg); void endTimeChanged(qint64 arg); - void eventListChanged(QmlJsDebugClient::QmlProfilerEventList *list); + void profilerDataModelChanged(QmlProfilerDataModel *list); void selectionLockedChanged(bool locked); void selectedItemChanged(int itemIndex); void startDragAreaChanged(int startDragArea); @@ -195,7 +195,7 @@ private: qint64 m_lastStartTime; qint64 m_lastEndTime; - QmlJsDebugClient::QmlProfilerEventList *m_eventList; + QmlProfilerDataModel *m_profilerDataModel; QList<int> m_rowLastX; QList<int> m_rowStarts; @@ -218,6 +218,6 @@ private: } // namespace Internal } // namespace QmlProfiler -QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineView) +QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineRenderer) -#endif // TIMELINEVIEW_H +#endif // TIMELINERENDERER_H diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp deleted file mode 100644 index f075c49ac6..0000000000 --- a/src/plugins/qmlprofiler/tracewindow.cpp +++ /dev/null @@ -1,666 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "tracewindow.h" - -#include "qmlprofilerplugin.h" - -#include <qmljsdebugclient/qmlprofilereventlist.h> -#include <qmljsdebugclient/qmlprofilertraceclient.h> -#include <utils/styledbar.h> - -#include <QDeclarativeView> -#include <QDeclarativeContext> -#include <QVBoxLayout> -#include <QGraphicsObject> -#include <QContextMenuEvent> -#include <QScrollBar> -#include <QSlider> -#include <QWidget> - -#include <math.h> - -using namespace QmlJsDebugClient; - -namespace QmlProfiler { -namespace Internal { - -const int sliderTicks = 10000; -const qreal sliderExp = 3; - -void ZoomControl::setRange(qint64 startTime, qint64 endTime) -{ - if (m_startTime != startTime || m_endTime != endTime) { - m_startTime = startTime; - m_endTime = endTime; - emit rangeChanged(); - } -} - -ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent) - : QDeclarativeView(parent) -{ -} - -ScrollableDeclarativeView::~ScrollableDeclarativeView() -{ -} - -void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy) -{ - // special workaround to track the scrollbar - if (rootObject()) { - int scrollY = rootObject()->property("scrollY").toInt(); - rootObject()->setProperty("scrollY", QVariant(scrollY - dy)); - } - QDeclarativeView::scrollContentsBy(dx,dy); -} - -TraceWindow::TraceWindow(QWidget *parent) - : QWidget(parent) -{ - setObjectName("QML Profiler"); - - m_zoomControl = new ZoomControl(this); - connect(m_zoomControl.data(), SIGNAL(rangeChanged()), this, SLOT(updateRange())); - - QVBoxLayout *groupLayout = new QVBoxLayout; - groupLayout->setContentsMargins(0, 0, 0, 0); - groupLayout->setSpacing(0); - - m_mainView = new ScrollableDeclarativeView(this); - m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject); - m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - m_mainView->setBackgroundBrush(QBrush(Qt::white)); - m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop); - m_mainView->setFocus(); - - MouseWheelResizer *resizer = new MouseWheelResizer(this); - connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int))); - m_mainView->viewport()->installEventFilter(resizer); - - QHBoxLayout *toolsLayout = new QHBoxLayout; - - m_timebar = new QDeclarativeView(this); - m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView); - m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_timebar->setFixedHeight(24); - - m_overview = new QDeclarativeView(this); - m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView); - m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_overview->setMaximumHeight(50); - - m_zoomToolbar = createZoomToolbar(); - m_zoomToolbar->move(0, m_timebar->height()); - m_zoomToolbar->setVisible(false); - - toolsLayout->addWidget(createToolbar()); - toolsLayout->addWidget(m_timebar); - - groupLayout->addLayout(toolsLayout); - groupLayout->addWidget(m_mainView); - groupLayout->addWidget(m_overview); - - setLayout(groupLayout); - - m_eventList = new QmlProfilerEventList(this); - connect(this,SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), m_eventList, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation))); - connect(this, SIGNAL(traceFinished(qint64)), m_eventList, SLOT(setTraceEndTime(qint64))); - connect(this, SIGNAL(traceStarted(qint64)), m_eventList, SLOT(setTraceStartTime(qint64))); - connect(this, SIGNAL(frameEvent(qint64,int,int)), m_eventList, SLOT(addFrameEvent(qint64,int,int))); - connect(m_eventList, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged())); - m_mainView->rootContext()->setContextProperty("qmlEventList", m_eventList); - m_overview->rootContext()->setContextProperty("qmlEventList", m_eventList); - - m_rewriter = new QmlProfilerDetailsRewriter(this); - connect(m_eventList, SIGNAL(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation)), m_rewriter, SLOT(requestDetailsForLocation(int,QmlJsDebugClient::QmlEventLocation))); - connect(m_rewriter, SIGNAL(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString)), m_eventList, SLOT(rewriteDetailsString(int,QmlJsDebugClient::QmlEventLocation,QString))); - connect(m_rewriter, SIGNAL(eventDetailsChanged()), m_eventList, SLOT(finishedRewritingDetails())); - connect(m_eventList, SIGNAL(reloadDocumentsForDetails()), m_rewriter, SLOT(reloadDocuments())); - - connect(this, SIGNAL(v8range(int,QString,QString,int,double,double)), m_eventList, SLOT(addV8Event(int,QString,QString,int,double,double))); - - // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin - setMinimumHeight(170); - m_currentZoomLevel = 0; - m_profiledTime = 0; - - initializeQmlViews(); -} - -TraceWindow::~TraceWindow() -{ - disconnectClientSignals(); - delete m_plugin.data(); - delete m_v8plugin.data(); -} - -QWidget *TraceWindow::createToolbar() -{ - Utils::StyledBar *bar = new Utils::StyledBar(this); - bar->setSingleRow(true); - bar->setFixedWidth(150); - bar->setFixedHeight(24); - - QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); - toolBarLayout->setMargin(0); - toolBarLayout->setSpacing(0); - - QToolButton *buttonPrev= new QToolButton; - buttonPrev->setIcon(QIcon(":/qmlprofiler/ico_prev.png")); - buttonPrev->setToolTip(tr("Jump to previous event")); - connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev())); - connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool))); - - QToolButton *buttonNext= new QToolButton; - buttonNext->setIcon(QIcon(":/qmlprofiler/ico_next.png")); - buttonNext->setToolTip(tr("Jump to next event")); - connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext())); - connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool))); - - QToolButton *buttonZoomControls = new QToolButton; - buttonZoomControls->setIcon(QIcon(":/qmlprofiler/ico_zoom.png")); - buttonZoomControls->setToolTip(tr("Show zoom slider")); - buttonZoomControls->setCheckable(true); - buttonZoomControls->setChecked(false); - connect(buttonZoomControls, SIGNAL(toggled(bool)), m_zoomToolbar, SLOT(setVisible(bool))); - connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool))); - - m_buttonRange = new QToolButton; - m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); - m_buttonRange->setToolTip(tr("Select range")); - m_buttonRange->setCheckable(true); - m_buttonRange->setChecked(false); - connect(m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool))); - connect(this, SIGNAL(enableToolbar(bool)), m_buttonRange, SLOT(setEnabled(bool))); - connect(this, SIGNAL(rangeModeChanged(bool)), m_buttonRange, SLOT(setChecked(bool))); - - m_buttonLock = new QToolButton; - m_buttonLock->setIcon(QIcon(":/qmlprofiler/ico_selectionmode.png")); - m_buttonLock->setToolTip(tr("View event information on mouseover")); - m_buttonLock->setCheckable(true); - m_buttonLock->setChecked(false); - connect(m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool))); - connect(this, SIGNAL(enableToolbar(bool)), m_buttonLock, SLOT(setEnabled(bool))); - connect(this, SIGNAL(lockModeChanged(bool)), m_buttonLock, SLOT(setChecked(bool))); - - toolBarLayout->addWidget(buttonPrev); - toolBarLayout->addWidget(buttonNext); - toolBarLayout->addWidget(new Utils::StyledSeparator()); - toolBarLayout->addWidget(buttonZoomControls); - toolBarLayout->addWidget(new Utils::StyledSeparator()); - toolBarLayout->addWidget(m_buttonRange); - toolBarLayout->addWidget(m_buttonLock); - - return bar; -} - - -QWidget *TraceWindow::createZoomToolbar() -{ - Utils::StyledBar *bar = new Utils::StyledBar(this); - bar->setSingleRow(true); - bar->setFixedWidth(150); - bar->setFixedHeight(24); - - QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); - toolBarLayout->setMargin(0); - toolBarLayout->setSpacing(0); - - QSlider *zoomSlider = new QSlider(Qt::Horizontal); - zoomSlider->setFocusPolicy(Qt::NoFocus); - zoomSlider->setRange(1, sliderTicks); - zoomSlider->setInvertedAppearance(true); - zoomSlider->setPageStep(sliderTicks/100); - connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool))); - connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int))); - connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int))); - zoomSlider->setStyleSheet("\ - QSlider:horizontal {\ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\ - border: 1px #313131;\ - height: 20px;\ - margin: 0px 0px 0px 0px;\ - }\ - QSlider::add-page:horizontal {\ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ - border: 1px #313131;\ - }\ - QSlider::sub-page:horizontal {\ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ - border: 1px #313131;\ - }\ - "); - - toolBarLayout->addWidget(zoomSlider); - - return bar; -} - -void TraceWindow::reset(QDeclarativeDebugConnection *conn) -{ - disconnectClientSignals(); - - delete m_plugin.data(); - m_plugin = new QmlProfilerTraceClient(conn); - delete m_v8plugin.data(); - m_v8plugin = new QV8ProfilerClient(conn); - - connectClientSignals(); - - m_v8DataReady = false; - m_qmlDataReady = false; - - m_mainView->rootContext()->setContextProperty("connection", m_plugin.data()); -} - -void TraceWindow::initializeQmlViews() -{ - m_mainView->rootContext()->setContextProperty("connection", m_plugin.data()); - m_mainView->rootContext()->setContextProperty("zoomControl", m_zoomControl.data()); - m_timebar->rootContext()->setContextProperty("zoomControl", m_zoomControl.data()); - m_overview->rootContext()->setContextProperty("zoomControl", m_zoomControl.data()); - - m_timebar->setSource(QUrl("qrc:/qmlprofiler/TimeDisplay.qml")); - m_overview->setSource(QUrl("qrc:/qmlprofiler/Overview.qml")); - - m_mainView->setSource(QUrl("qrc:/qmlprofiler/MainView.qml")); - m_mainView->rootObject()->setProperty("width", QVariant(width())); - m_mainView->rootObject()->setProperty("candidateHeight", QVariant(height() - m_timebar->height() - m_overview->height())); - - updateToolbar(); - - connect(m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition())); - connect(m_mainView->rootObject(), SIGNAL(updateTimer()), this, SLOT(updateTimer())); - connect(m_mainView->rootObject(), SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton())); - connect(m_mainView->rootObject(), SIGNAL(updateLockButton()), this, SLOT(updateLockButton())); - connect(m_eventList, SIGNAL(countChanged()), this, SLOT(updateToolbar())); - connect(this, SIGNAL(jumpToPrev()), m_mainView->rootObject(), SLOT(prevEvent())); - connect(this, SIGNAL(jumpToNext()), m_mainView->rootObject(), SLOT(nextEvent())); - connect(this, SIGNAL(updateViewZoom(QVariant)), m_mainView->rootObject(), SLOT(updateWindowLength(QVariant))); - connect(this, SIGNAL(wheelZoom(QVariant,QVariant)), m_mainView->rootObject(), SLOT(wheelZoom(QVariant,QVariant))); - connect(this, SIGNAL(globalZoom()), m_mainView->rootObject(), SLOT(globalZoom())); - connect(this, SIGNAL(selectNextEventInDisplay(QVariant)), m_mainView->rootObject(), SLOT(selectNextWithId(QVariant))); - connect(m_mainView->rootObject(), SIGNAL(selectedEventIdChanged(int)), this, SIGNAL(selectedEventIdChanged(int))); - connect(m_mainView->rootObject(), SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString))); - connect(m_mainView->rootObject(), SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int))); - - connect(this, SIGNAL(internalClearDisplay()), m_mainView->rootObject(), SLOT(clearAll())); - connect(this,SIGNAL(internalClearDisplay()), m_overview->rootObject(), SLOT(clearDisplay())); -} - -void TraceWindow::connectClientSignals() -{ - if (m_plugin) { - connect(m_plugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete())); - connect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), - this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation))); - connect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64))); - connect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64))); - connect(m_plugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(frameEvent(qint64,int,int))); - connect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState())); - connect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus())); - connect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool))); - } - if (m_v8plugin) { - connect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); - connect(m_v8plugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), this, SIGNAL(v8range(int,QString,QString,int,double,double))); - connect(m_v8plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState())); - connect(m_v8plugin.data(), SIGNAL(enabledChanged()), m_v8plugin.data(), SLOT(sendRecordingStatus())); - } -} - -void TraceWindow::disconnectClientSignals() -{ - if (m_plugin) { - disconnect(m_plugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete())); - disconnect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)), - this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation))); - disconnect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64))); - disconnect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64))); - disconnect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState())); - disconnect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus())); - disconnect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool))); - } - if (m_v8plugin) { - disconnect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); - disconnect(m_v8plugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), this, SIGNAL(v8range(int,QString,QString,int,double,double))); - disconnect(m_v8plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState())); - disconnect(m_v8plugin.data(), SIGNAL(enabledChanged()), m_v8plugin.data(), SLOT(sendRecordingStatus())); - } -} - -QmlProfilerEventList *TraceWindow::getEventList() const -{ - return m_eventList; -} - -ZoomControl *TraceWindow::rangeTimes() const -{ - return m_zoomControl.data(); -} - -void TraceWindow::contextMenuEvent(QContextMenuEvent *ev) -{ - emit contextMenuRequested(ev->globalPos()); -} - -void TraceWindow::updateCursorPosition() -{ - emit gotoSourceLocation(m_mainView->rootObject()->property("fileName").toString(), - m_mainView->rootObject()->property("lineNumber").toInt(), - m_mainView->rootObject()->property("columnNumber").toInt()); -} - -void TraceWindow::updateTimer() -{ - m_profiledTime = m_mainView->rootObject()->property("elapsedTime").toDouble(); -} - -void TraceWindow::correctTimer() -{ - // once the data is post-processed, use the eventlist time instead of the qml timer - m_profiledTime = (m_eventList->traceEndTime() - m_eventList->traceStartTime()) / 1.0e9; - if (m_profiledTime < 0) - m_profiledTime = 0; - emit viewUpdated(); -} - -double TraceWindow::profiledTime() const -{ - return m_profiledTime; -} - -void TraceWindow::clearDisplay() -{ - m_eventList->clear(); - - if (m_plugin) - m_plugin.data()->clearData(); - if (m_v8plugin) - m_v8plugin.data()->clearData(); - - m_zoomControl.data()->setRange(0,0); - m_profiledTime = 0; - - updateVerticalScroll(0); - m_mainView->rootObject()->setProperty("scrollY", QVariant(0)); - - emit internalClearDisplay(); -} - -void TraceWindow::updateToolbar() -{ - emit enableToolbar(m_eventList && m_eventList->count()>0); -} - -void TraceWindow::toggleRangeMode(bool active) -{ - bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool(); - if (active != rangeMode) { - if (active) - m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png")); - else - m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); - m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active)); - } -} - -void TraceWindow::updateRangeButton() -{ - bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool(); - if (rangeMode) - m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png")); - else - m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); - emit rangeModeChanged(rangeMode); -} - -void TraceWindow::toggleLockMode(bool active) -{ - bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool(); - if (active != lockMode) { - m_mainView->rootObject()->setProperty("selectionLocked", QVariant(!active)); - m_mainView->rootObject()->setProperty("selectedItem", QVariant(-1)); - } -} - -void TraceWindow::updateLockButton() -{ - bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool(); - emit lockModeChanged(lockMode); -} - -void TraceWindow::setRecording(bool recording) -{ - if (recording) { - m_v8DataReady = false; - m_qmlDataReady = false; - } - if (m_plugin) - m_plugin.data()->setRecording(recording); - if (m_v8plugin) - m_v8plugin.data()->setRecording(recording); -} - -bool TraceWindow::isRecording() const -{ - return m_plugin.data()->isRecording(); -} - -void TraceWindow::qmlComplete() -{ - m_qmlDataReady = true; - if (!m_v8plugin || m_v8plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_v8DataReady) { - m_eventList->complete(); - - // if no data was received, still notify completion - if (m_eventList->currentState() == QmlProfilerEventList::Empty) - emit viewUpdated(); - - // once complete is sent, reset the flags - m_qmlDataReady = false; - m_v8DataReady = false; - } -} - -void TraceWindow::v8Complete() -{ - m_v8DataReady = true; - if (!m_plugin || m_plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_qmlDataReady) { - m_eventList->complete(); - - // if no data was received, still notify completion - if (m_eventList->currentState() == QmlProfilerEventList::Empty) - emit viewUpdated(); - - // once complete is sent, reset the flags - m_v8DataReady = false; - m_qmlDataReady = false; - } -} - -void TraceWindow::resizeEvent(QResizeEvent *event) -{ - if (m_mainView->rootObject()) { - m_mainView->rootObject()->setProperty("width", QVariant(event->size().width())); - int newHeight = event->size().height() - m_timebar->height() - m_overview->height(); - m_mainView->rootObject()->setProperty("candidateHeight", QVariant(newHeight)); - } -} - -bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::Wheel) { - QWheelEvent *ev = static_cast<QWheelEvent *>(event); - if (ev->modifiers() & Qt::ControlModifier) { - emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta()); - return true; - } - } - return QObject::eventFilter(obj, event); -} - -void TraceWindow::mouseWheelMoved(int x, int y, int delta) -{ - Q_UNUSED(y); - if (m_mainView->rootObject()) { - emit wheelZoom(QVariant(x), QVariant(delta)); - } -} - -void TraceWindow::viewAll() -{ - emit globalZoom(); -} - -bool TraceWindow::hasValidSelection() const -{ - if (m_mainView->rootObject()) { - return m_mainView->rootObject()->property("selectionRangeReady").toBool(); - } - return false; -} - -qint64 TraceWindow::selectionStart() const -{ - if (m_mainView->rootObject()) { - return m_mainView->rootObject()->property("selectionRangeStart").toLongLong(); - } - return 0; -} - -qint64 TraceWindow::selectionEnd() const -{ - if (m_mainView->rootObject()) { - return m_mainView->rootObject()->property("selectionRangeEnd").toLongLong(); - } - return 0; -} - -void TraceWindow::setZoomLevel(int zoomLevel) -{ - if (m_currentZoomLevel != zoomLevel && m_mainView->rootObject()) { - qreal newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp); - m_currentZoomLevel = zoomLevel; - emit updateViewZoom(QVariant(newFactor)); - } -} - -void TraceWindow::updateRange() -{ - if (!m_eventList) - return; - qreal duration = m_zoomControl.data()->endTime() - m_zoomControl.data()->startTime(); - if (duration <= 0) - return; - if (m_eventList->traceDuration() <= 0) - return; - int newLevel = pow(duration / m_eventList->traceDuration(), 1/sliderExp) * sliderTicks; - if (m_currentZoomLevel != newLevel) { - m_currentZoomLevel = newLevel; - emit zoomLevelChanged(newLevel); - } -} - -void TraceWindow::selectNextEvent(int eventId) -{ - emit selectNextEventInDisplay(QVariant(eventId)); -} - -void TraceWindow::updateProfilerState() -{ - bool qmlActive = false; - bool v8Active = false; - if (m_plugin) - qmlActive = m_plugin.data()->isEnabled(); - if (m_v8plugin) - v8Active = m_v8plugin.data()->isEnabled(); - - emit profilerStateChanged(qmlActive, v8Active); -} - -void TraceWindow::updateToolTip(const QString &text) -{ - setToolTip(text); -} - -void TraceWindow::updateVerticalScroll(int newPosition) -{ - m_mainView->verticalScrollBar()->setValue(newPosition); -} - -void TraceWindow::eventListStateChanged() -{ - switch (m_eventList->currentState()) { - case QmlProfilerEventList::Empty : - clearDisplay(); - break; - case QmlProfilerEventList::AcquiringData : - firstDataReceived(); - break; - case QmlProfilerEventList::ProcessingData : - // nothing to be done - break; - case QmlProfilerEventList::Done : - correctTimer(); - break; - default: - break; - } -} - -void TraceWindow::manageTraceStart(qint64 traceStart) -{ - // new trace started - emit clearViewsFromTool(); - - emit traceStarted(traceStart); -} - -void TraceWindow::firstDataReceived() -{ - if (m_plugin && m_plugin.data()->isRecording()) { - // serverside recording disabled - m_plugin.data()->setRecordingFromServer(false); - } -} - -void TraceWindow::applicationDied() -{ - if (m_mainView->rootObject()) - m_mainView->rootObject()->setProperty("applicationDied",QVariant(true)); -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index e3f454df8a..c05d6b78b8 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -272,11 +272,6 @@ ProjectExplorer::IProjectManager *QmlProject::projectManager() const return m_manager; } -QList<ProjectExplorer::Project *> QmlProject::dependsOn() -{ - return QList<Project *>(); -} - QList<ProjectExplorer::BuildConfigWidget*> QmlProject::subConfigWidgets() { return QList<ProjectExplorer::BuildConfigWidget*>(); diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index 1d70f3025f..2c35a7b835 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -74,8 +74,6 @@ public: ProjectExplorer::IProjectManager *projectManager() const; Internal::QmlProjectTarget *activeTarget() const; - QList<ProjectExplorer::Project *> dependsOn(); - QList<ProjectExplorer::BuildConfigWidget*> subConfigWidgets(); ProjectExplorer::ProjectNode *rootProjectNode() const; diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro index 4885be0441..cd40ae3e2f 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectmanager.pro +++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.pro @@ -1,7 +1,12 @@ TEMPLATE = lib TARGET = QmlProjectManager -QT += declarative network +QT += network +greaterThan(QT_MAJOR_VERSION, 4) { + QT += quick1 +} else { + QT += declarative +} include(../../qtcreatorplugin.pri) include(qmlprojectmanager_dependencies.pri) diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.h b/src/plugins/qmlprojectmanager/qmlprojectplugin.h index 224c572aac..c9b10b7fe7 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectplugin.h +++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.h @@ -42,6 +42,7 @@ namespace QmlProjectManager { class QMLPROJECTMANAGER_EXPORT QmlProjectPlugin: public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProjectManager.json") public: QmlProjectPlugin(); diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 3899c87435..8f18d89e9c 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -364,7 +364,7 @@ void QmlProjectRunConfiguration::updateEnabled() // Always emit change signal to force reevaluation of run/debug buttons m_isEnabled = newValue; - emit isEnabledChanged(m_isEnabled); + emit enabledChanged(); } void QmlProjectRunConfiguration::updateQtVersions() diff --git a/src/plugins/qt4projectmanager/profileeditor.cpp b/src/plugins/qt4projectmanager/profileeditor.cpp index 25dfee554b..0041fb9ebc 100644 --- a/src/plugins/qt4projectmanager/profileeditor.cpp +++ b/src/plugins/qt4projectmanager/profileeditor.cpp @@ -233,11 +233,6 @@ void ProFileEditorWidget::setFontSettings(const TextEditor::FontSettings &fs) highlighter->rehighlight(); } -void ProFileEditorWidget::jumpToFile() -{ - openLink(findLinkAt(textCursor())); -} - // // ProFileDocument // diff --git a/src/plugins/qt4projectmanager/profileeditor.h b/src/plugins/qt4projectmanager/profileeditor.h index e2d153041d..1d143eb7d2 100644 --- a/src/plugins/qt4projectmanager/profileeditor.h +++ b/src/plugins/qt4projectmanager/profileeditor.h @@ -88,7 +88,6 @@ protected: public slots: virtual void setFontSettings(const TextEditor::FontSettings &); - void jumpToFile(); private: ProFileEditorFactory *m_factory; diff --git a/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp b/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp index 0fc6e30a5b..c0146d2896 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp +++ b/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp @@ -81,7 +81,6 @@ QString DesktopQtVersion::warningReason() const QList<ProjectExplorer::Abi> DesktopQtVersion::detectQtAbis() const { - ensureMkSpecParsed(); return qtAbisFromLibrary(qtCorePath(versionInfo(), qtVersionString())); } diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp index 185fd3d462..cc61c89869 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp @@ -165,7 +165,7 @@ void Qt4RunConfiguration::proFileUpdated(Qt4ProjectManager::Qt4ProFileNode *pro, m_parseSuccess = success; m_parseInProgress = parseInProgress; if (enabled != isEnabled()) - emit isEnabledChanged(!enabled); + emit enabledChanged(); if (!parseInProgress) { emit effectiveTargetInformationChanged(); @@ -287,7 +287,7 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run m_environmentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); vboxTopLayout->addWidget(m_environmentWidget); - runConfigurationEnabledChange(m_qt4RunConfiguration->isEnabled()); + runConfigurationEnabledChange(); connect(m_workingDirectoryEdit, SIGNAL(changed(QString)), this, SLOT(workDirectoryEdited())); @@ -321,8 +321,8 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run connect(qt4RunConfiguration, SIGNAL(baseEnvironmentChanged()), this, SLOT(baseEnvironmentChanged())); - connect(qt4RunConfiguration, SIGNAL(isEnabledChanged(bool)), - this, SLOT(runConfigurationEnabledChange(bool))); + connect(qt4RunConfiguration, SIGNAL(enabledChanged()), + this, SLOT(runConfigurationEnabledChange())); } Qt4RunConfigurationWidget::~Qt4RunConfigurationWidget() @@ -363,8 +363,9 @@ void Qt4RunConfigurationWidget::userChangesEdited() m_ignoreChange = false; } -void Qt4RunConfigurationWidget::runConfigurationEnabledChange(bool enabled) +void Qt4RunConfigurationWidget::runConfigurationEnabledChange() { + bool enabled = m_qt4RunConfiguration->isEnabled(); m_detailsContainer->setEnabled(enabled); m_environmentWidget->setEnabled(enabled); m_disabledIcon->setVisible(!enabled); diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h index 4762b8edec..062b013d4f 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h @@ -169,7 +169,7 @@ protected: void hideEvent(QHideEvent *event); private slots: - void runConfigurationEnabledChange(bool); + void runConfigurationEnabledChange(); void workDirectoryEdited(); void workingDirectoryReseted(); void argumentsEdited(const QString &arguments); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.cpp index f7d5d95bb6..fd892ef067 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.cpp @@ -193,7 +193,7 @@ void S60DeviceDebugRunControl::codaConnected() engine()->handleRemoteSetupDone(-1, -1); // calls notifyInferiorSetupOk() } -void S60DeviceDebugRunControl::qmlEngineStateChanged(const Debugger::DebuggerState &state) +void S60DeviceDebugRunControl::qmlEngineStateChanged(Debugger::DebuggerState state) { if (state == Debugger::EngineRunRequested) m_codaRunControl->run(); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.h b/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.h index 4ad373391a..c86ac0823c 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicedebugruncontrol.h @@ -56,7 +56,7 @@ public: private slots: void remoteSetupRequested(); void codaConnected(); - void qmlEngineStateChanged(const Debugger::DebuggerState &state); + void qmlEngineStateChanged(Debugger::DebuggerState state); void codaFinished(); void handleDebuggingFinished(); void handleMessageFromCoda(ProjectExplorer::RunControl *aCodaRunControl, const QString &msg, Utils::OutputFormat format); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 54bf0c2164..ce74f2e8fa 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -113,7 +113,7 @@ void S60DeviceRunConfiguration::proFileUpdate(Qt4ProjectManager::Qt4ProFileNode m_validParse = success; m_parseInProgress = parseInProgress; if (enabled != isEnabled()) - emit isEnabledChanged(!enabled); + emit enabledChanged(); if (!parseInProgress) emit targetInformationChanged(); } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp index f4034b906c..bba25dbf56 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp @@ -86,10 +86,10 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( connect(m_argumentsLineEdit, SIGNAL(textEdited(QString)), this, SLOT(argumentsEdited(QString))); - connect(m_runConfiguration, SIGNAL(isEnabledChanged(bool)), - this, SLOT(runConfigurationEnabledChange(bool))); + connect(m_runConfiguration, SIGNAL(enabledChanged()), + this, SLOT(runConfigurationEnabledChange())); - runConfigurationEnabledChange(m_runConfiguration->isEnabled()); + runConfigurationEnabledChange(); } void S60DeviceRunConfigurationWidget::argumentsEdited(const QString &text) @@ -97,8 +97,9 @@ void S60DeviceRunConfigurationWidget::argumentsEdited(const QString &text) m_runConfiguration->setCommandLineArguments(text.trimmed()); } -void S60DeviceRunConfigurationWidget::runConfigurationEnabledChange(bool enabled) +void S60DeviceRunConfigurationWidget::runConfigurationEnabledChange() { + bool enabled = m_runConfiguration->isEnabled(); m_detailsWidget->setEnabled(enabled); m_disabledIcon->setVisible(!enabled); m_disabledReason->setVisible(!enabled); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h index f5f69048a4..7a1ab41879 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h @@ -56,7 +56,7 @@ public: QWidget *parent = 0); private slots: void argumentsEdited(const QString &text); - void runConfigurationEnabledChange(bool enabled); + void runConfigurationEnabledChange(); private: S60DeviceRunConfiguration *m_runConfiguration; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp index 1a186a0d07..1a1a2146a7 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp @@ -116,7 +116,7 @@ void S60EmulatorRunConfiguration::proFileUpdate(Qt4ProjectManager::Qt4ProFileNod m_validParse = success; m_parseInProgress = parseInProgress; if (enabled != isEnabled()) { - emit isEnabledChanged(!enabled); + emit enabledChanged(); } if (parseInProgress) emit targetInformationChanged(); @@ -244,10 +244,10 @@ S60EmulatorRunConfigurationWidget::S60EmulatorRunConfigurationWidget(S60Emulator connect(m_runConfiguration, SIGNAL(targetInformationChanged()), this, SLOT(updateTargetInformation())); - connect(m_runConfiguration, SIGNAL(isEnabledChanged(bool)), - this, SLOT(runConfigurationEnabledChange(bool))); + connect(m_runConfiguration, SIGNAL(enabledChanged()), + this, SLOT(runConfigurationEnabledChange())); - runConfigurationEnabledChange(m_runConfiguration->isEnabled()); + runConfigurationEnabledChange(); } void S60EmulatorRunConfigurationWidget::updateTargetInformation() @@ -255,8 +255,9 @@ void S60EmulatorRunConfigurationWidget::updateTargetInformation() m_executableLabel->setText(m_runConfiguration->executable()); } -void S60EmulatorRunConfigurationWidget::runConfigurationEnabledChange(bool enabled) +void S60EmulatorRunConfigurationWidget::runConfigurationEnabledChange() { + bool enabled = m_runConfiguration->isEnabled(); m_detailsWidget->setEnabled(enabled); m_disabledIcon->setVisible(!enabled); m_disabledReason->setVisible(!enabled); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h index 1ce10f83fd..be38f4c238 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h @@ -108,7 +108,7 @@ public: private slots: void updateTargetInformation(); - void runConfigurationEnabledChange(bool enabled); + void runConfigurationEnabledChange(); private: S60EmulatorRunConfiguration *m_runConfiguration; diff --git a/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp b/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp index 97754fe163..1f5f980135 100644 --- a/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/sbsv2parser.cpp @@ -32,7 +32,7 @@ #include "sbsv2parser.h" -#include <extensionsystem/pluginmanager.h> +#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/taskhub.h> @@ -55,8 +55,7 @@ SbsV2Parser::SbsV2Parser() : m_hub(0) { setObjectName(QLatin1String("SbsV2Parser")); - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - m_hub = pm->getObject<TaskHub>(); + m_hub = ProjectExplorerPlugin::instance()->taskHub(); } void SbsV2Parser::stdOutput(const QString &line) diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp index 7e73d48501..35cecaee6a 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp @@ -673,14 +673,6 @@ Qt4BuildConfigurationFactory::~Qt4BuildConfigurationFactory() void Qt4BuildConfigurationFactory::update() { - m_versions.clear(); - QtSupport::QtVersionManager *vm = QtSupport::QtVersionManager::instance(); - foreach (QtSupport::BaseQtVersion *version, vm->validVersions()) { - QString key = QString::fromLatin1(QT4_BC_ID_PREFIX) - + QString::fromLatin1("Qt%1").arg(version->uniqueId()); - VersionInfo info(tr("Using Qt Version \"%1\"").arg(version->displayName()), version->uniqueId()); - m_versions.insert(key, info); - } emit availableCreationIdsChanged(); } @@ -691,30 +683,46 @@ QStringList Qt4BuildConfigurationFactory::availableCreationIds(ProjectExplorer:: QStringList results; QtSupport::QtVersionManager *vm = QtSupport::QtVersionManager::instance(); - for (QMap<QString, VersionInfo>::const_iterator i = m_versions.constBegin(); - i != m_versions.constEnd(); ++i) { - if (vm->version(i.value().versionId)->supportsTargetId(parent->id()) - && vm->version(i.value().versionId)->toolChainAvailable(parent->id())) - results.append(i.key()); + QList<QtSupport::BaseQtVersion *> versions = vm->versionsForTargetId(parent->id()); + foreach (QtSupport::BaseQtVersion *v, versions) { + if (v->toolChainAvailable(parent->id())) + results << QLatin1String(QT4_BC_ID_PREFIX) + QString::number(v->uniqueId()); } + + return results; } +int idToUniqueId(const QString &id) +{ + QString rest = id.mid(QString(QT4_BC_ID_PREFIX).length()); + bool ok; + int unqieuid = rest.toInt(&ok); + if (!ok) + return -1; + return unqieuid; +} + QString Qt4BuildConfigurationFactory::displayNameForId(const QString &id) const { - if (!m_versions.contains(id)) + if (!id.startsWith(QT4_BC_ID_PREFIX)) + return QString(); + + QtSupport::QtVersionManager *vm = QtSupport::QtVersionManager::instance(); + QtSupport::BaseQtVersion *v = vm->version(idToUniqueId(id)); + if (!v) return QString(); - return m_versions.value(id).displayName; + return tr("Using Qt Version \"%1\"").arg(v->displayName()); } bool Qt4BuildConfigurationFactory::canCreate(ProjectExplorer::Target *parent, const QString &id) const { if (!qobject_cast<Qt4BaseTarget *>(parent)) return false; - if (!m_versions.contains(id)) + if (!id.startsWith(QT4_BC_ID_PREFIX)) return false; - const VersionInfo &info = m_versions.value(id); - QtSupport::BaseQtVersion *version = QtSupport::QtVersionManager::instance()->version(info.versionId); + + QtSupport::BaseQtVersion *version = QtSupport::QtVersionManager::instance()->version(idToUniqueId(id)); if (!version || !version->supportsTargetId(parent->id())) return false; @@ -726,8 +734,7 @@ BuildConfiguration *Qt4BuildConfigurationFactory::create(ProjectExplorer::Target if (!canCreate(parent, id)) return 0; - const VersionInfo &info = m_versions.value(id); - QtSupport::BaseQtVersion *version = QtSupport::QtVersionManager::instance()->version(info.versionId); + QtSupport::BaseQtVersion *version = QtSupport::QtVersionManager::instance()->version(idToUniqueId(id)); Q_ASSERT(version); Qt4BaseTarget *qt4Target = static_cast<Qt4BaseTarget *>(parent); diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.h b/src/plugins/qt4projectmanager/qt4buildconfiguration.h index 17b98abd0e..8fb8a9deb7 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfiguration.h +++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.h @@ -188,20 +188,6 @@ public: private slots: void update(); - -private: - struct VersionInfo { - VersionInfo() - : versionId(-1) - {} - VersionInfo(const QString &d, int v) - : displayName(d), versionId(v) - {} - QString displayName; - int versionId; - }; - - QMap<QString, VersionInfo> m_versions; }; } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index 002eb5fd1a..54c4a91e7a 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -50,7 +50,7 @@ #include <coreplugin/iversioncontrol.h> #include <coreplugin/vcsmanager.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/CppDocument.h> #include <extensionsystem/pluginmanager.h> #include <projectexplorer/projectexplorer.h> @@ -107,8 +107,10 @@ static const FileTypeDataStorage fileTypeDataStorage[] = { ":/qt4projectmanager/images/unknown.png" } }; -struct Qt4NodeStaticData { - struct FileTypeData { +class Qt4NodeStaticData { +public: + class FileTypeData { + public: FileTypeData(ProjectExplorer::FileType t = ProjectExplorer::UnknownFileType, const QString &tN = QString(), const QIcon &i = QIcon()) : @@ -119,16 +121,19 @@ struct Qt4NodeStaticData { QIcon icon; }; + Qt4NodeStaticData(); + QVector<FileTypeData> fileTypeData; QIcon projectIcon; }; static void clearQt4NodeStaticData(); -Q_GLOBAL_STATIC_WITH_INITIALIZER(Qt4NodeStaticData, qt4NodeStaticData, { +Qt4NodeStaticData::Qt4NodeStaticData() +{ // File type data const unsigned count = sizeof(fileTypeDataStorage)/sizeof(FileTypeDataStorage); - x->fileTypeData.reserve(count); + fileTypeData.reserve(count); // Overlay the SP_DirIcon with the custom icons const QSize desiredSize = QSize(16, 16); @@ -141,18 +146,20 @@ Q_GLOBAL_STATIC_WITH_INITIALIZER(Qt4NodeStaticData, qt4NodeStaticData, { QIcon folderIcon; folderIcon.addPixmap(folderPixmap); const QString desc = Qt4ProjectManager::Qt4PriFileNode::tr(fileTypeDataStorage[i].typeName); - x->fileTypeData.push_back(Qt4NodeStaticData::FileTypeData(fileTypeDataStorage[i].type, - desc, folderIcon)); + fileTypeData.push_back(Qt4NodeStaticData::FileTypeData(fileTypeDataStorage[i].type, + desc, folderIcon)); } // Project icon const QIcon projectBaseIcon(QLatin1String(":/qt4projectmanager/images/qt_project.png")); const QPixmap projectPixmap = Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon, projectBaseIcon, desiredSize); - x->projectIcon.addPixmap(projectPixmap); + projectIcon.addPixmap(projectPixmap); qAddPostRoutine(clearQt4NodeStaticData); -}) +} + +Q_GLOBAL_STATIC(Qt4NodeStaticData, qt4NodeStaticData) static void clearQt4NodeStaticData() { diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index e935e5cea3..59f45cda4e 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -41,6 +41,8 @@ #include "qt4projectmanagerconstants.h" #include "qt4buildconfiguration.h" #include "findqt4profiles.h" +#include "qt4basetargetfactory.h" +#include "buildconfigurationinfo.h" #include <coreplugin/icore.h> #include <coreplugin/idocument.h> @@ -49,7 +51,7 @@ #include <coreplugin/coreconstants.h> #include <coreplugin/progressmanager/progressmanager.h> #include <extensionsystem/pluginmanager.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <qmljs/qmljsmodelmanagerinterface.h> #include <projectexplorer/toolchain.h> #include <projectexplorer/headerpath.h> @@ -540,7 +542,7 @@ void Qt4Project::updateCppCodeModel() part->language = CPlusPlus::CppModelManagerInterface::CXX; // part->flags if (tc) - part->flags = tc->compilerFlags(pro->variableValue(CppFlagsVar)); + part->cxx11Enabled = tc->compilerFlags(pro->variableValue(CppFlagsVar)) == ToolChain::STD_CXX11; part->sourceFiles = pro->variableValue(CppSourceVar); pinfo.appendProjectPart(part); @@ -909,12 +911,6 @@ QString Qt4Project::generatedUiHeader(const QString &formFile) const return QString(); } -QList<ProjectExplorer::Project*> Qt4Project::dependsOn() -{ - // NBS implement dependsOn - return QList<Project *>(); -} - void Qt4Project::proFileParseError(const QString &errorMessage) { Core::ICore::messageManager()->printToOutputPanePopup(errorMessage); @@ -1334,6 +1330,36 @@ bool Qt4Project::needsConfiguration() const return targets().isEmpty(); } +void Qt4Project::configureAsExampleProject(const QStringList &platforms) +{ + QList<Qt4BaseTargetFactory *> factories = ExtensionSystem::PluginManager::instance()->getObjects<Qt4BaseTargetFactory>(); + foreach (Qt4BaseTargetFactory *factory, factories) { + foreach (const QString &id, factory->supportedTargetIds()) { + QList<BuildConfigurationInfo> infos + = factory->availableBuildConfigurations(id, rootProjectNode()->path(), + QtSupport::QtVersionNumber(), + QtSupport::QtVersionNumber(INT_MAX, INT_MAX, INT_MAX), + Core::FeatureSet()); + if (!platforms.isEmpty()) { + QList<BuildConfigurationInfo> filtered; + foreach (const BuildConfigurationInfo &info, infos) { + foreach (const QString &platform, platforms) { + if (info.version()->supportsPlatform(platform)) { + filtered << info; + break; + } + } + } + infos = filtered; + } + + if (!infos.isEmpty()) + addTarget(factory->create(this, id, infos)); + } + } + ProjectExplorer::ProjectExplorerPlugin::instance()->requestProjectModeUpdate(this); +} + /*! Handle special case were a subproject of the qt directory is opened, and qt was configured to be built as a shadow build -> also build in the sub- diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h index 4b57c4f1e5..a22ab931a2 100644 --- a/src/plugins/qt4projectmanager/qt4project.h +++ b/src/plugins/qt4projectmanager/qt4project.h @@ -95,9 +95,6 @@ public: Qt4BaseTarget *activeTarget() const; - QList<Core::IDocument *> dependencies(); //NBS remove - QList<ProjectExplorer::Project *>dependsOn(); - ProjectExplorer::ProjectNode *rootProjectNode() const; Qt4ProFileNode *rootQt4ProjectNode() const; bool validParse(const QString &proFilePath) const; @@ -140,6 +137,8 @@ public: bool needsConfiguration() const; + void configureAsExampleProject(const QStringList &platforms); + signals: void proParsingDone(); void proFileUpdated(Qt4ProjectManager::Qt4ProFileNode *node, bool, bool); diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h index 3568058a69..410e0b48ee 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h +++ b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h @@ -63,7 +63,6 @@ const char BUILDSUBDIR[] = "Qt4Builder.BuildSubDir"; const char REBUILDSUBDIR[] = "Qt4Builder.RebuildSubDir"; const char CLEANSUBDIR[] = "Qt4Builder.CleanSubDir"; const char ADDLIBRARY[] = "Qt4.AddLibrary"; -const char JUMP_TO_FILE[] = "Qt4.JumpToFile"; const char SEPARATOR[] = "Qt4.Separator"; // Tasks diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp index 789c069921..5386769104 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp @@ -129,7 +129,8 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString * TextEditor::TextEditorActionHandler *editorHandler = new TextEditor::TextEditorActionHandler(Constants::C_PROFILEEDITOR, - TextEditor::TextEditorActionHandler::UnCommentSelection); + TextEditor::TextEditorActionHandler::UnCommentSelection + | TextEditor::TextEditorActionHandler::JumpToFileUnderCursor); m_proFileEditorFactory = new ProFileEditorFactory(m_qt4ProjectManager, editorHandler); addObject(m_proFileEditorFactory); @@ -238,12 +239,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString * Core::Context proFileEditorContext = Core::Context(Qt4ProjectManager::Constants::C_PROFILEEDITOR); - QAction *jumpToFile = new QAction(tr("Jump to File Under Cursor"), this); - command = am->registerAction(jumpToFile, - Constants::JUMP_TO_FILE, proFileEditorContext); - command->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); - connect(jumpToFile, SIGNAL(triggered()), - this, SLOT(jumpToFile())); + command = am->command(TextEditor::Constants::JUMP_TO_FILE_UNDER_CURSOR); contextMenu->addAction(command); m_addLibraryAction = new QAction(tr("Add Library..."), this); @@ -369,12 +365,4 @@ void Qt4ProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *pro) updateRunQMakeAction(); } -void Qt4ProjectManagerPlugin::jumpToFile() -{ - Core::EditorManager *em = Core::EditorManager::instance(); - ProFileEditorWidget *editor = qobject_cast<ProFileEditorWidget*>(em->currentEditor()->widget()); - if (editor) - editor->jumpToFile(); -} - Q_EXPORT_PLUGIN(Qt4ProjectManagerPlugin) diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h index c0bbe0ce3a..f7c2d5995d 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h +++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.h @@ -59,6 +59,7 @@ class ProFileEditorFactory; class Qt4ProjectManagerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Qt4ProjectManager.json") public: Qt4ProjectManagerPlugin(); @@ -74,7 +75,6 @@ private slots: void updateRunQMakeAction(); void currentNodeChanged(ProjectExplorer::Node *node); void buildStateChanged(ProjectExplorer::Project *pro); - void jumpToFile(); #ifdef WITH_TESTS void testAbldOutputParsers_data(); diff --git a/src/plugins/qt4projectmanager/qtmodulesinfo.cpp b/src/plugins/qt4projectmanager/qtmodulesinfo.cpp index a7e6bf3d2d..520afe0f8e 100644 --- a/src/plugins/qt4projectmanager/qtmodulesinfo.cpp +++ b/src/plugins/qt4projectmanager/qtmodulesinfo.cpp @@ -47,10 +47,7 @@ struct item bool isDefault; }; -typedef QVector<const item*> itemVectorType; -typedef QHash<QString, const item*> itemHashType; - -const itemVectorType itemVector() +static inline QVector<const item*> itemVector() { static const struct item items[] = { {"core", @@ -119,37 +116,37 @@ const itemVectorType itemVector() false} }; const int itemsCount = sizeof items / sizeof items[0]; - itemVectorType result; + QVector<const item*> result; result.reserve(itemsCount); for (int i = 0; i < itemsCount; i++) result.append(items + i); return result; } -Q_GLOBAL_STATIC_WITH_INITIALIZER(itemVectorType, staticItemVector, { - *x = itemVector(); -}) +class StaticQtModuleInfo +{ +public: + StaticQtModuleInfo() : items(itemVector()) {} -Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, staticModulesList, { - const itemVectorType * const itemVector = staticItemVector(); - for (int i = 0; i < itemVector->count(); i++) - x->append(QString::fromLatin1(itemVector->at(i)->config)); -}) + const QVector<const item*> items; +}; -Q_GLOBAL_STATIC_WITH_INITIALIZER(itemHashType, staticItemHash, { - const itemVectorType * const itemVector = staticItemVector(); - for (int i = 0; i < itemVector->count(); i++) - x->insert(QString::fromLatin1(itemVector->at(i)->config), itemVector->at(i)); -}) +Q_GLOBAL_STATIC(StaticQtModuleInfo, staticQtModuleInfo) QStringList QtModulesInfo::modules() { - return *staticModulesList(); + QStringList result; + foreach (const item *i, staticQtModuleInfo()->items) + result.push_back(i->config); + return result; } static inline const item *itemForModule(const QString &module) { - return staticItemHash()->value(module); + foreach (const item *i, staticQtModuleInfo()->items) + if (i->config == module) + return i; + return 0; } QString QtModulesInfo::moduleName(const QString &module) diff --git a/src/plugins/qt4projectmanager/unconfiguredprojectpanel.cpp b/src/plugins/qt4projectmanager/unconfiguredprojectpanel.cpp index 0481e059ff..ad08817780 100644 --- a/src/plugins/qt4projectmanager/unconfiguredprojectpanel.cpp +++ b/src/plugins/qt4projectmanager/unconfiguredprojectpanel.cpp @@ -43,6 +43,7 @@ #include <coreplugin/coreconstants.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/projectexplorer.h> #include <projectexplorer/toolchain.h> #include <QLabel> @@ -87,8 +88,6 @@ ProjectExplorer::PropertiesPanel *Qt4ProjectManager::Internal::UnconfiguredProje panel->setIcon(QIcon(":/projectexplorer/images/unconfigured.png")); TargetSetupPageWrapper *w = new TargetSetupPageWrapper(project); - connect (w, SIGNAL(projectUpdated(ProjectExplorer::Project*)), - this, SIGNAL(projectUpdated(ProjectExplorer::Project*))); panel->setWidget(w); return panel; } @@ -188,7 +187,7 @@ void TargetSetupPageWrapper::keyReleaseEvent(QKeyEvent *event) void TargetSetupPageWrapper::done() { m_targetSetupPage->setupProject(m_project); - emit projectUpdated(m_project); + ProjectExplorer::ProjectExplorerPlugin::instance()->requestProjectModeUpdate(m_project); Core::ICore::instance()->modeManager()->activateMode(QLatin1String(Core::Constants::MODE_EDIT)); } diff --git a/src/plugins/qt4projectmanager/unconfiguredprojectpanel.h b/src/plugins/qt4projectmanager/unconfiguredprojectpanel.h index c8a00cf3cd..6466108f3e 100644 --- a/src/plugins/qt4projectmanager/unconfiguredprojectpanel.h +++ b/src/plugins/qt4projectmanager/unconfiguredprojectpanel.h @@ -65,8 +65,6 @@ public: protected: void keyReleaseEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event); -signals: - void projectUpdated(ProjectExplorer::Project *project); private slots: void done(); void noteTextLinkActivated(); diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 3769089ff8..f4c6854eda 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -755,16 +755,7 @@ BaseQtVersion::QmakeBuildConfigs BaseQtVersion::defaultBuildConfig() const QString BaseQtVersion::qtVersionString() const { - if (!m_qtVersionString.isNull()) - return m_qtVersionString; - m_qtVersionString.clear(); - if (m_qmakeIsExecutable) { - const QString qmake = qmakeCommand().toString(); - m_qtVersionString = - ProjectExplorer::DebuggingHelperLibrary::qtVersionForQMake(qmake, &m_qmakeIsExecutable); - } else { - qWarning("Cannot determine the Qt version: %s cannot be run.", qPrintable(qmakeCommand().toString())); - } + updateVersionInfo(); return m_qtVersionString; } @@ -803,9 +794,6 @@ void BaseQtVersion::updateVersionInfo() const const QString qtInstallData = m_versionInfo.value(installDataKey); const QString qtInstallBins = m_versionInfo.value(installBinsKey); const QString qtHeaderData = m_versionInfo.value(installHeadersKey); - m_versionInfo.insert(QLatin1String("QMAKE_MKSPECS"), - QDir::cleanPath(qtInstallData + QLatin1String("/mkspecs"))); - if (!qtInstallData.isEmpty()) { m_hasDebuggingHelper = !ProjectExplorer::DebuggingHelperLibrary::debuggingHelperLibraryByInstallData(qtInstallData).isEmpty(); m_hasQmlDump @@ -847,6 +835,7 @@ void BaseQtVersion::updateVersionInfo() const if (fi.exists()) m_hasDemos = true; } + m_qtVersionString = m_versionInfo.value(QLatin1String("QT_VERSION"), QString()); m_versionInfoUpToDate = true; } diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp index c3ea5d3e7d..47fb57bca8 100644 --- a/src/plugins/qtsupport/exampleslistmodel.cpp +++ b/src/plugins/qtsupport/exampleslistmodel.cpp @@ -73,6 +73,7 @@ ExamplesListModel::ExamplesListModel(QObject *parent) : roleNames[IsVideo] = "isVideo"; roleNames[VideoUrl] = "videoUrl"; roleNames[VideoLength] = "videoLength"; + roleNames[Platforms] = "platforms"; setRoleNames(roleNames); connect(Core::HelpManager::instance(), SIGNAL(setupFinished()), @@ -91,6 +92,15 @@ static inline QString fixStringForTags(const QString &string) return returnString; } +static inline QStringList trimStringList(const QStringList &stringlist) +{ + QStringList returnList; + foreach (const QString &string, stringlist) + returnList << string.trimmed(); + + return returnList; +} + QList<ExampleItem> ExamplesListModel::parseExamples(QXmlStreamReader* reader, const QString& projectsOffset) { QList<ExampleItem> examples; @@ -117,15 +127,20 @@ QList<ExampleItem> ExamplesListModel::parseExamples(QXmlStreamReader* reader, co } else if (reader->name() == QLatin1String("dependency")) { item.dependencies.append(projectsOffset + slash + reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement)); } else if (reader->name() == QLatin1String("tags")) { - item.tags = reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).split(QLatin1Char(',')); + item.tags = trimStringList(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).split(QLatin1Char(','), QString::SkipEmptyParts)); m_tags.append(item.tags); - } + } else if (reader->name() == QLatin1String("platforms")) { + item.platforms = trimStringList(reader->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).split(QLatin1Char(','), QString::SkipEmptyParts)); + } break; case QXmlStreamReader::EndElement: - if (reader->name() == QLatin1String("example")) + if (reader->name() == QLatin1String("example")) { + if (item.projectPath.isEmpty() || !QFileInfo(item.projectPath).exists()) + item.tags.append("broken"); examples.append(item); - else if (reader->name() == QLatin1String("examples")) + } else if (reader->name() == QLatin1String("examples")) { return examples; + } break; default: // nothing break; @@ -429,6 +444,8 @@ QVariant ExamplesListModel::data(const QModelIndex &index, int role) const return item.videoUrl; case VideoLength: return item.videoLength; + case Platforms: + return item.platforms; default: qDebug() << Q_FUNC_INFO << "role type not supported"; return QVariant(); diff --git a/src/plugins/qtsupport/exampleslistmodel.h b/src/plugins/qtsupport/exampleslistmodel.h index 75f98e1c1e..c56f4b6ed7 100644 --- a/src/plugins/qtsupport/exampleslistmodel.h +++ b/src/plugins/qtsupport/exampleslistmodel.h @@ -43,7 +43,7 @@ namespace Internal { enum ExampleRoles { Name=Qt::UserRole, ProjectPath, Description, ImageUrl, DocUrl, FilesToOpen, Tags, Difficulty, HasSourceCode, - Type, Dependencies, IsVideo, VideoUrl, VideoLength }; + Type, Dependencies, IsVideo, VideoUrl, VideoLength, Platforms }; enum InstructionalType { Example=0, Demo, Tutorial }; @@ -63,6 +63,7 @@ struct ExampleItem { bool isVideo; QString videoUrl; QString videoLength; + QStringList platforms; }; class ExamplesListModel : public QAbstractListModel { diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index 86d18d5a8b..af8ef3bd27 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -35,15 +35,21 @@ #include "exampleslistmodel.h" #include "screenshotcropper.h" +#include "qtsupportconstants.h" + #include <utils/pathchooser.h> #include <utils/fileutils.h> #include <coreplugin/coreconstants.h> #include <coreplugin/coreplugin.h> +#include <coreplugin/documentmanager.h> #include <coreplugin/icore.h> #include <coreplugin/helpmanager.h> #include <coreplugin/modemanager.h> #include <projectexplorer/projectexplorer.h> +#include <projectexplorer/session.h> +#include <projectexplorer/project.h> +#include <projectexplorer/projectnodes.h> #include <QMutex> #include <QThread> @@ -67,7 +73,6 @@ #include <QDeclarativeImageProvider> #include <QDeclarativeEngine> #include <QDeclarativeContext> -#include <QtDeclarative> #include <QDesktopServices> namespace QtSupport { @@ -212,7 +217,7 @@ QString GettingStartedWelcomePage::title() const int GettingStartedWelcomePage::priority() const { - return 0; + return 4; } void GettingStartedWelcomePage::facilitateQml(QDeclarativeEngine *engine) @@ -220,6 +225,11 @@ void GettingStartedWelcomePage::facilitateQml(QDeclarativeEngine *engine) m_engine = engine; } +GettingStartedWelcomePage::Id GettingStartedWelcomePage::id() const +{ + return GettingStarted; +} + ExamplesWelcomePage::ExamplesWelcomePage() : m_engine(0), m_showExamples(false) { @@ -283,6 +293,11 @@ void ExamplesWelcomePage::facilitateQml(QDeclarativeEngine *engine) rootContenxt->setContextProperty(QLatin1String("gettingStarted"), this); } +ExamplesWelcomePage::Id ExamplesWelcomePage::id() const +{ + return m_showExamples ? Examples : Tutorials; +} + void ExamplesWelcomePage::openSplitHelp(const QUrl &help) { Core::ICore::helpManager()->handleHelpRequest(help.toString()+QLatin1String("?view=split")); @@ -325,8 +340,8 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI txt->setBuddy(chooser); chooser->setExpectedKind(Utils::PathChooser::ExistingDirectory); QSettings *settings = Core::ICore::settings(); - chooser->setPath(settings->value( - QString::fromLatin1(C_FALLBACK_ROOT), QDir::homePath()).toString()); + chooser->setPath(settings->value(QString::fromLatin1(C_FALLBACK_ROOT), + Core::DocumentManager::projectsDirectory()).toString()); lay->addWidget(txt, 1, 0); lay->addWidget(chooser, 1, 1); QDialogButtonBox *bb = new QDialogButtonBox; @@ -379,7 +394,7 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI } void ExamplesWelcomePage::openProject(const QString &projectFile, const QStringList &additionalFilesToOpen, - const QUrl &help, const QStringList &dependencies) + const QUrl &help, const QStringList &dependencies, const QStringList &platforms) { QString proFile = projectFile; if (proFile.isEmpty()) @@ -387,14 +402,22 @@ void ExamplesWelcomePage::openProject(const QString &projectFile, const QStringL QStringList filesToOpen = additionalFilesToOpen; QFileInfo proFileInfo(proFile); + if (!proFileInfo.exists()) + return; + // If the Qt is a distro Qt on Linux, it will not be writable, hence compilation will fail if (!proFileInfo.isWritable()) proFile = copyToAlternativeLocation(proFileInfo, filesToOpen, dependencies); // don't try to load help and files if loading the help request is being cancelled QString errorMessage; - if (!proFile.isEmpty() && ProjectExplorer::ProjectExplorerPlugin::instance()->openProject(proFile, &errorMessage)) { + ProjectExplorer::ProjectExplorerPlugin *peplugin = ProjectExplorer::ProjectExplorerPlugin::instance(); + if (proFile.isEmpty()) + return; + if (ProjectExplorer::Project *project = peplugin->openProject(proFile, &errorMessage)) { Core::ICore::openFiles(filesToOpen); + if (project->needsConfiguration()) + project->configureAsExampleProject(platforms); Core::ModeManager::activateModeType(QLatin1String(Core::Constants::MODE_EDIT_TYPE)); Core::ICore::helpManager()->handleHelpRequest(help.toString()+QLatin1String("?view=split")); } diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.h b/src/plugins/qtsupport/gettingstartedwelcomepage.h index aefa4fdeee..1b7855572e 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.h +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.h @@ -58,6 +58,7 @@ public: QString title() const; int priority() const; void facilitateQml(QDeclarativeEngine *); + Id id() const; private: QDeclarativeEngine *m_engine; @@ -76,6 +77,7 @@ public: int priority() const; bool hasSearchBar() const; void facilitateQml(QDeclarativeEngine *); + Id id() const; Q_INVOKABLE QStringList tagList() const; Q_INVOKABLE void openUrl(const QUrl &url); @@ -86,7 +88,7 @@ public slots: void openSplitHelp(const QUrl &help); void openHelp(const QUrl &help); void openProject(const QString& projectFile, const QStringList& additionalFilesToOpen, - const QUrl& help, const QStringList &dependencies); + const QUrl& help, const QStringList &dependencies, const QStringList &platforms); void updateTagsModel(); private: diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index 1964711318..d113448ce3 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -101,8 +101,7 @@ QIcon QtOptionsPage::categoryIcon() const QWidget *QtOptionsPage::createPage(QWidget *parent) { - QtVersionManager *vm = QtVersionManager::instance(); - m_widget = new QtOptionsPageWidget(parent, vm->versions()); + m_widget = new QtOptionsPageWidget(parent); if (m_searchKeywords.isEmpty()) m_searchKeywords = m_widget->searchKeywords(); return m_widget; @@ -126,7 +125,7 @@ bool QtOptionsPage::matches(const QString &s) const //----------------------------------------------------- -QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<BaseQtVersion *> versions) +QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent) : QWidget(parent) , m_specifyNameString(tr("<specify a name>")) , m_ui(new Internal::Ui::QtVersionManager()) @@ -135,11 +134,9 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<BaseQtVersion *> , m_invalidVersionIcon(QLatin1String(":/projectexplorer/images/compile_error.png")) , m_warningVersionIcon(QLatin1String(":/projectexplorer/images/compile_warning.png")) , m_configurationWidget(0) + , m_autoItem(0) + , m_manualItem(0) { - // Initialize m_versions - foreach (BaseQtVersion *version, versions) - m_versions.push_back(version->clone()); - QWidget *versionInfoWidget = new QWidget(); m_versionUi->setupUi(versionInfoWidget); m_versionUi->editPathPushButton->setText(tr(Utils::PathChooser::browseButtonLabel)); @@ -160,26 +157,23 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<BaseQtVersion *> m_ui->qtdirList->header()->setResizeMode(QHeaderView::ResizeToContents); m_ui->qtdirList->header()->setStretchLastSection(false); m_ui->qtdirList->setTextElideMode(Qt::ElideNone); - QTreeWidgetItem *autoItem = new QTreeWidgetItem(m_ui->qtdirList); + m_autoItem = new QTreeWidgetItem(m_ui->qtdirList); m_ui->qtdirList->installEventFilter(this); - autoItem->setText(0, tr("Auto-detected")); - autoItem->setFirstColumnSpanned(true); - autoItem->setFlags(Qt::ItemIsEnabled); - QTreeWidgetItem *manualItem = new QTreeWidgetItem(m_ui->qtdirList); - manualItem->setText(0, tr("Manual")); - manualItem->setFirstColumnSpanned(true); - manualItem->setFlags(Qt::ItemIsEnabled); + m_autoItem->setText(0, tr("Auto-detected")); + m_autoItem->setFirstColumnSpanned(true); + m_autoItem->setFlags(Qt::ItemIsEnabled); + m_manualItem = new QTreeWidgetItem(m_ui->qtdirList); + m_manualItem->setText(0, tr("Manual")); + m_manualItem->setFirstColumnSpanned(true); + m_manualItem->setFlags(Qt::ItemIsEnabled); + + QList<int> additions; + QList<BaseQtVersion *> versions = QtVersionManager::instance()->versions(); + foreach (BaseQtVersion *v, versions) + additions.append(v->uniqueId()); + + updateQtVersions(additions, QList<int>(), QList<int>()); - for (int i = 0; i < m_versions.count(); ++i) { - BaseQtVersion *version = m_versions.at(i); - QTreeWidgetItem *item = new QTreeWidgetItem(version->isAutodetected()? autoItem : manualItem); - item->setText(0, version->displayName()); - item->setText(1, version->qmakeCommand().toUserOutput()); - item->setData(0, VersionIdRole, version->uniqueId()); - item->setData(0, ToolChainIdRole, defaultToolChainId(version)); - const ValidityInfo info = validInformation(version); - item->setIcon(0, info.icon); - } m_ui->qtdirList->expandAll(); connect(m_versionUi->nameEdit, SIGNAL(textEdited(QString)), @@ -219,6 +213,9 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<BaseQtVersion *> connect(QtVersionManager::instance(), SIGNAL(dumpUpdatedFor(Utils::FileName)), this, SLOT(qtVersionsDumpUpdated(Utils::FileName))); + connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>,QList<int>,QList<int>)), + this, SLOT(updateQtVersions(QList<int>,QList<int>,QList<int>))); + connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainsChanged()), this, SLOT(toolChainsUpdated())); } @@ -567,6 +564,73 @@ void QtOptionsPageWidget::showDebuggingBuildLog(const QTreeWidgetItem *currentIt dialog->show(); } +void QtOptionsPageWidget::updateQtVersions(const QList<int> &additions, const QList<int> &removals, + const QList<int> &changes) +{ + QtVersionManager *vm = QtVersionManager::instance(); + + QList<QTreeWidgetItem *> toRemove; + QList<int> toAdd = additions; + + // Generate list of all existing items: + QList<QTreeWidgetItem *> itemList; + for (int i = 0; i < m_autoItem->childCount(); ++i) + itemList.append(m_autoItem->child(i)); + for (int i = 0; i < m_manualItem->childCount(); ++i) + itemList.append(m_manualItem->child(i)); + + // Find existing items to remove/change: + foreach (QTreeWidgetItem *item, itemList) { + int id = item->data(0, VersionIdRole).toInt(); + if (removals.contains(id)) { + toRemove.append(item); + continue; + } + + if (changes.contains(id)) { + toAdd.append(id); + toRemove.append(item); + continue; + } + } + + // Remove changed/removed items: + foreach (QTreeWidgetItem *item, toRemove) { + int index = indexForTreeItem(item); + delete m_versions.at(index); + m_versions.removeAt(index); + delete item; + } + + // Add changed/added items: + foreach (int a, toAdd) { + BaseQtVersion *version = vm->version(a)->clone(); + m_versions.append(version); + QTreeWidgetItem *item = new QTreeWidgetItem; + + item->setText(0, version->displayName()); + item->setText(1, version->qmakeCommand().toUserOutput()); + item->setData(0, VersionIdRole, version->uniqueId()); + item->setData(0, ToolChainIdRole, defaultToolChainId(version)); + const ValidityInfo info = validInformation(version); + item->setIcon(0, info.icon); + + // Insert in the right place: + QTreeWidgetItem *parent = version->isAutodetected()? m_autoItem : m_manualItem; + for (int i = 0; i < parent->childCount(); ++i) { + BaseQtVersion *currentVersion = m_versions.at(indexForTreeItem(parent->child(i))); + if (currentVersion->qtVersion() > version->qtVersion()) + continue; + parent->insertChild(i, item); + parent = 0; + break; + } + + if (parent) + parent->addChild(item); + } +} + QtOptionsPageWidget::~QtOptionsPageWidget() { delete m_ui; diff --git a/src/plugins/qtsupport/qtoptionspage.h b/src/plugins/qtsupport/qtoptionspage.h index f09ca28c39..ef854bc57e 100644 --- a/src/plugins/qtsupport/qtoptionspage.h +++ b/src/plugins/qtsupport/qtoptionspage.h @@ -64,7 +64,7 @@ class QtOptionsPageWidget : public QWidget Q_OBJECT public: - QtOptionsPageWidget(QWidget *parent, QList<BaseQtVersion *> versions); + QtOptionsPageWidget(QWidget *parent); ~QtOptionsPageWidget(); QList<BaseQtVersion *> versions() const; void finish(); @@ -97,6 +97,7 @@ private: QtConfigWidget *m_configurationWidget; private slots: + void updateQtVersions(const QList<int> &, const QList<int> &, const QList<int> &); void qtVersionChanged(); void versionChanged(QTreeWidgetItem *item, QTreeWidgetItem *old); void addQtDir(); @@ -129,6 +130,9 @@ private: ValidityInfo validInformation(const BaseQtVersion *version); QList<ProjectExplorer::ToolChain*> toolChains(const BaseQtVersion *version); QString defaultToolChainId(const BaseQtVersion *verison); + + QTreeWidgetItem *m_autoItem; + QTreeWidgetItem *m_manualItem; }; class QtOptionsPage : public Core::IOptionsPage diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp index a34316ca3c..2fb33a43c6 100644 --- a/src/plugins/qtsupport/qtoutputformatter.cpp +++ b/src/plugins/qtsupport/qtoutputformatter.cpp @@ -53,6 +53,7 @@ QtOutputFormatter::QtOutputFormatter(ProjectExplorer::Project *project) ":")) // colon , m_qtError(QLatin1String("Object::.*in (.*:\\d+)")) , m_qtAssert(QLatin1String("ASSERT: .* in file (.+, line \\d+)")) + , m_qtAssertX(QLatin1String("ASSERT failure in .*: \".*\", file (.+, line \\d+)")) , m_qtTestFail(QLatin1String("^ Loc: \\[(.*)\\]")) , m_project(project) { @@ -83,6 +84,10 @@ LinkResult QtOutputFormatter::matchLine(const QString &line) const lr.href = m_qtAssert.cap(1); lr.start = m_qtAssert.pos(1); lr.end = lr.start + lr.href.length(); + } else if (m_qtAssertX.indexIn(line) != -1) { + lr.href = m_qtAssertX.cap(1); + lr.start = m_qtAssertX.pos(1); + lr.end = lr.start + lr.href.length(); } else if (m_qtTestFail.indexIn(line) != -1) { lr.href = m_qtTestFail.cap(1); lr.start = m_qtTestFail.pos(1); @@ -97,9 +102,6 @@ void QtOutputFormatter::appendMessage(const QString &txt, Utils::OutputFormat fo cursor.movePosition(QTextCursor::End); cursor.beginEditBlock(); - QString text = txt; - text.remove(QLatin1Char('\r')); - QString deferedText; int start = 0; diff --git a/src/plugins/qtsupport/qtoutputformatter.h b/src/plugins/qtsupport/qtoutputformatter.h index 762f099bf6..b9c7ccf8bf 100644 --- a/src/plugins/qtsupport/qtoutputformatter.h +++ b/src/plugins/qtsupport/qtoutputformatter.h @@ -78,10 +78,10 @@ private: QRegExp m_qmlError; QRegExp m_qtError; QRegExp m_qtAssert; + QRegExp m_qtAssertX; QRegExp m_qtTestFail; QWeakPointer<ProjectExplorer::Project> m_project; QString m_lastLine; - QString m_deferedText; Utils::FileInProjectFinder m_projectFinder; }; diff --git a/src/plugins/qtsupport/qtsupport.pro b/src/plugins/qtsupport/qtsupport.pro index 088a61e7d0..383c154a42 100644 --- a/src/plugins/qtsupport/qtsupport.pro +++ b/src/plugins/qtsupport/qtsupport.pro @@ -1,7 +1,13 @@ TEMPLATE = lib TARGET = QtSupport DEFINES += QT_CREATOR QTSUPPORT_LIBRARY -QT += network declarative +QT += network +greaterThan(QT_MAJOR_VERSION, 4) { + QT += quick1 +} else { + QT += declarative +} + include(../../qtcreatorplugin.pri) include(qtsupport_dependencies.pri) DEFINES += \ diff --git a/src/plugins/qtsupport/qtsupportplugin.h b/src/plugins/qtsupport/qtsupportplugin.h index 8ea327febd..0400e313e9 100644 --- a/src/plugins/qtsupport/qtsupportplugin.h +++ b/src/plugins/qtsupport/qtsupportplugin.h @@ -45,6 +45,7 @@ class ExamplesWelcomePage; class QtSupportPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QtSupport.json") public: bool initialize(const QStringList &arguments, QString *errorMessage); diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp index 185023e851..b1472aad82 100644 --- a/src/plugins/qtsupport/qtversionmanager.cpp +++ b/src/plugins/qtsupport/qtversionmanager.cpp @@ -48,6 +48,7 @@ #include <extensionsystem/pluginmanager.h> +#include <utils/filesystemwatcher.h> #include <utils/persistentsettings.h> #include <utils/qtcprocess.h> #include <utils/qtcassert.h> @@ -98,6 +99,13 @@ static T *createToolChain(const QString &id) return 0; } +static QString globalSettingsFileName() +{ + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + return QFileInfo(pm->globalSettings()->fileName()).absolutePath() + + QLatin1String(QTVERSION_FILENAME); +} + static QString settingsFileName() { ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); @@ -117,7 +125,8 @@ bool qtVersionNumberCompare(BaseQtVersion *a, BaseQtVersion *b) // -------------------------------------------------------------------------- QtVersionManager *QtVersionManager::m_self = 0; -QtVersionManager::QtVersionManager() +QtVersionManager::QtVersionManager() : + m_configFileWatcher(0) { m_self = this; m_idcount = 1; @@ -139,6 +148,15 @@ void QtVersionManager::extensionsInitialized() } saveQtVersions(); + + const QString configFileName = globalSettingsFileName(); + if (QFileInfo(configFileName).exists()) { + m_configFileWatcher = new Utils::FileSystemWatcher(this); + connect(m_configFileWatcher, SIGNAL(fileChanged(QString)), + this, SLOT(updateFromInstaller())); + m_configFileWatcher->addFile(configFileName, + Utils::FileSystemWatcher::WatchModifiedDate); + } // exists } bool QtVersionManager::delayedInitialize() @@ -211,11 +229,17 @@ bool QtVersionManager::restoreQtVersions() void QtVersionManager::updateFromInstaller() { + // Handle overwritting of data: + if (m_configFileWatcher) { + const QString path = globalSettingsFileName(); + m_configFileWatcher->removeFile(path); + m_configFileWatcher->addFile(path, Utils::FileSystemWatcher::WatchModifiedDate); + } + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); QList<QtVersionFactory *> factories = pm->getObjects<QtVersionFactory>(); Utils::PersistentSettingsReader reader; - if (!reader.load(QFileInfo(pm->globalSettings()->fileName()).absolutePath() - + QLatin1String(QTVERSION_FILENAME))) + if (!reader.load(globalSettingsFileName())) return; QVariantMap data = reader.restoreValues(); diff --git a/src/plugins/qtsupport/qtversionmanager.h b/src/plugins/qtsupport/qtversionmanager.h index d192212256..7a95a5fe51 100644 --- a/src/plugins/qtsupport/qtversionmanager.h +++ b/src/plugins/qtsupport/qtversionmanager.h @@ -39,6 +39,8 @@ #include <QSet> #include <QStringList> +namespace Utils { class FileSystemWatcher; } + namespace QtSupport { namespace Internal { class QtOptionsPage; @@ -113,6 +115,9 @@ signals: public slots: void updateDumpFor(const Utils::FileName &qmakeCommand); +private slots: + void updateFromInstaller(); + private: // This function is really simplistic... static bool equals(BaseQtVersion *a, BaseQtVersion *b); @@ -127,7 +132,6 @@ private: bool restoreQtVersions(); bool legacyRestore(); void findSystemQt(); - void updateFromInstaller(); void saveQtVersions(); void updateDocumentation(); // Used by QtOptionsPage @@ -147,6 +151,8 @@ private: // Compatibility with pre-2.2: QStringList m_pendingMwcUpdates; QStringList m_pendingGcceUpdates; + + Utils::FileSystemWatcher *m_configFileWatcher; }; namespace Internal { diff --git a/src/plugins/qtsupport/screenshotcropper.cpp b/src/plugins/qtsupport/screenshotcropper.cpp index 0209cbc370..59d1585e9b 100644 --- a/src/plugins/qtsupport/screenshotcropper.cpp +++ b/src/plugins/qtsupport/screenshotcropper.cpp @@ -43,13 +43,20 @@ namespace QtSupport { namespace Internal { +class AreasOfInterest { +public: + AreasOfInterest(); + QMap<QString, QRect> areas; +}; + +AreasOfInterest::AreasOfInterest() +{ #ifdef QT_CREATOR -Q_GLOBAL_STATIC_WITH_INITIALIZER(AreasOfInterest, areasOfInterest, { - *x = ScreenshotCropper::loadAreasOfInterest(Core::ICore::resourcePath() + QLatin1String("/welcomescreen/images_areaofinterest.xml")); -}) -#else -Q_GLOBAL_STATIC(AreasOfInterest, areasOfInterest) + areas = ScreenshotCropper::loadAreasOfInterest(Core::ICore::resourcePath() + QLatin1String("/welcomescreen/images_areaofinterest.xml")); #endif // QT_CREATOR +} + +Q_GLOBAL_STATIC(AreasOfInterest, welcomeScreenAreas) static inline QString fileNameForPath(const QString &path) { @@ -81,7 +88,7 @@ static QRect cropRectForAreaOfInterest(const QSize &imageSize, const QSize &crop QImage ScreenshotCropper::croppedImage(const QImage &sourceImage, const QString &filePath, const QSize &cropSize) { - const QRect areaOfInterest = areasOfInterest()->value(fileNameForPath(filePath)); + const QRect areaOfInterest = welcomeScreenAreas()->areas.value(fileNameForPath(filePath)); if (areaOfInterest.isValid()) { const QRect cropRect = cropRectForAreaOfInterest(sourceImage.size(), cropSize, areaOfInterest); @@ -113,9 +120,9 @@ static const QString xmlAttributeY = QLatin1String("y"); static const QString xmlAttributeWidth = QLatin1String("width"); static const QString xmlAttributeHeight = QLatin1String("height"); -AreasOfInterest ScreenshotCropper::loadAreasOfInterest(const QString &areasXmlFile) +QMap<QString, QRect> ScreenshotCropper::loadAreasOfInterest(const QString &areasXmlFile) { - AreasOfInterest areasOfInterest; + QMap<QString, QRect> areasOfInterest; QFile xmlFile(areasXmlFile); if (!xmlFile.open(QIODevice::ReadOnly)) { qWarning() << Q_FUNC_INFO << "Could not open file" << areasXmlFile; @@ -144,7 +151,7 @@ AreasOfInterest ScreenshotCropper::loadAreasOfInterest(const QString &areasXmlFi return areasOfInterest; } -bool ScreenshotCropper::saveAreasOfInterest(const QString &areasXmlFile, AreasOfInterest &areas) +bool ScreenshotCropper::saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas) { QFile file(areasXmlFile); if (!file.open(QIODevice::WriteOnly)) diff --git a/src/plugins/qtsupport/screenshotcropper.h b/src/plugins/qtsupport/screenshotcropper.h index a3e52c9594..5ee91b42eb 100644 --- a/src/plugins/qtsupport/screenshotcropper.h +++ b/src/plugins/qtsupport/screenshotcropper.h @@ -40,14 +40,12 @@ namespace QtSupport { namespace Internal { -typedef QMap<QString, QRect> AreasOfInterest; - class ScreenshotCropper { public: static QImage croppedImage(const QImage &sourceImage, const QString &filePath, const QSize &cropSize); - static AreasOfInterest loadAreasOfInterest(const QString &areasXmlFile); - static bool saveAreasOfInterest(const QString &areasXmlFile, AreasOfInterest &areas); + static QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile); + static bool saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas); }; } // namespace Internal diff --git a/src/plugins/remotelinux/abstractembeddedlinuxtarget.cpp b/src/plugins/remotelinux/abstractembeddedlinuxtarget.cpp index 16985e39a7..78f7eb775b 100644 --- a/src/plugins/remotelinux/abstractembeddedlinuxtarget.cpp +++ b/src/plugins/remotelinux/abstractembeddedlinuxtarget.cpp @@ -41,13 +41,11 @@ using namespace Qt4ProjectManager; namespace RemoteLinux { -AbstractEmbeddedLinuxTarget::AbstractEmbeddedLinuxTarget(Qt4Project *parent, const QString &id, - const QString &supportedOsType) : +AbstractEmbeddedLinuxTarget::AbstractEmbeddedLinuxTarget(Qt4Project *parent, const QString &id) : Qt4BaseTarget(parent, id), m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this)), - m_supportedOsType(supportedOsType), m_deploymentInfo(new DeploymentInfo(this)), - m_deviceConfigModel(new Internal::TypeSpecificDeviceConfigurationListModel(supportedOsType, this)) + m_deviceConfigModel(new Internal::TypeSpecificDeviceConfigurationListModel(this)) { } diff --git a/src/plugins/remotelinux/abstractembeddedlinuxtarget.h b/src/plugins/remotelinux/abstractembeddedlinuxtarget.h index da0e26efea..f6ff1fe8d7 100644 --- a/src/plugins/remotelinux/abstractembeddedlinuxtarget.h +++ b/src/plugins/remotelinux/abstractembeddedlinuxtarget.h @@ -36,9 +36,13 @@ #include <qt4projectmanager/qt4target.h> +#include <QSharedPointer> #include <QString> -namespace ProjectExplorer { class IBuildConfigurationFactory; } +namespace ProjectExplorer { +class IBuildConfigurationFactory; +class IDevice; +} namespace Qt4ProjectManager { class Qt4BuildConfigurationFactory; } namespace RemoteLinux { @@ -49,20 +53,21 @@ class REMOTELINUX_EXPORT AbstractEmbeddedLinuxTarget : public Qt4ProjectManager: { Q_OBJECT public: - AbstractEmbeddedLinuxTarget(Qt4ProjectManager::Qt4Project *parent, const QString &id, - const QString &supportedOsType); + AbstractEmbeddedLinuxTarget(Qt4ProjectManager::Qt4Project *parent, const QString &id); ProjectExplorer::IBuildConfigurationFactory *buildConfigurationFactory() const; - QString supportedOsType() const { return m_supportedOsType; } DeploymentInfo *deploymentInfo() const { return m_deploymentInfo; } Internal::TypeSpecificDeviceConfigurationListModel *deviceConfigModel() const { return m_deviceConfigModel; } + virtual bool supportsDevice(const QSharedPointer<const ProjectExplorer::IDevice> &device) const = 0; + +signals: + void supportedDevicesChanged(); private: Qt4ProjectManager::Qt4BuildConfigurationFactory * const m_buildConfigurationFactory; - const QString m_supportedOsType; DeploymentInfo * const m_deploymentInfo; Internal::TypeSpecificDeviceConfigurationListModel * const m_deviceConfigModel; }; diff --git a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp index 80be33ea36..33433d61f8 100644 --- a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp +++ b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp @@ -304,7 +304,7 @@ void AbstractRemoteLinuxDeployService::handleConnectionFailure() break; case Connecting: { QString errorMsg = tr("Could not connect to host: %1").arg(d->connection->errorString()); - if (deviceConfiguration()->deviceType() == LinuxDeviceConfiguration::Emulator) + if (deviceConfiguration()->machineType() == LinuxDeviceConfiguration::Emulator) errorMsg += tr("\nDid the emulator fail to start?"); else errorMsg += tr("\nIs the device connected and set up for network access?"); diff --git a/src/plugins/remotelinux/deployablefilesperprofile.cpp b/src/plugins/remotelinux/deployablefilesperprofile.cpp index 8cfb982aa5..328cf5d51e 100644 --- a/src/plugins/remotelinux/deployablefilesperprofile.cpp +++ b/src/plugins/remotelinux/deployablefilesperprofile.cpp @@ -74,7 +74,7 @@ public: using namespace Internal; DeployableFilesPerProFile::DeployableFilesPerProFile(const Qt4ProFileNode *proFileNode, - QObject *parent) + const QString &installPrefix, QObject *parent) : QAbstractTableModel(parent), d(new DeployableFilesPerProFilePrivate(proFileNode)) { if (d->projectType == ApplicationTemplate) { @@ -90,6 +90,11 @@ DeployableFilesPerProFile::DeployableFilesPerProFile(const Qt4ProFileNode *proFi foreach (const QString &file, elem.files) d->deployables << DeployableFile(file, elem.path); } + + if (!installPrefix.isEmpty()) { + for (int i = 0; i < d->deployables.count(); ++i) + d->deployables[i].remoteDir.prepend(installPrefix + QLatin1Char('/')); + } } DeployableFilesPerProFile::~DeployableFilesPerProFile() @@ -133,7 +138,7 @@ QVariant DeployableFilesPerProFile::data(const QModelIndex &index, int role) con if (index.column() == 0 && role == Qt::DisplayRole) return QDir::toNativeSeparators(d.localFilePath); if (role == Qt::DisplayRole || role == Qt::EditRole) - return d.remoteDir; + return QDir::cleanPath(d.remoteDir); return QVariant(); } diff --git a/src/plugins/remotelinux/deployablefilesperprofile.h b/src/plugins/remotelinux/deployablefilesperprofile.h index 5fd9695995..c219f0743c 100644 --- a/src/plugins/remotelinux/deployablefilesperprofile.h +++ b/src/plugins/remotelinux/deployablefilesperprofile.h @@ -53,7 +53,7 @@ class REMOTELINUX_EXPORT DeployableFilesPerProFile : public QAbstractTableModel Q_OBJECT public: DeployableFilesPerProFile(const Qt4ProjectManager::Qt4ProFileNode *proFileNode, - QObject *parent); + const QString &installPrefix, QObject *parent); ~DeployableFilesPerProFile(); virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; diff --git a/src/plugins/remotelinux/deploymentinfo.cpp b/src/plugins/remotelinux/deploymentinfo.cpp index 42c31dff6d..9ab125493f 100644 --- a/src/plugins/remotelinux/deploymentinfo.cpp +++ b/src/plugins/remotelinux/deploymentinfo.cpp @@ -53,17 +53,17 @@ public: QList<DeployableFilesPerProFile *> listModels; const AbstractEmbeddedLinuxTarget * const target; + QString installPrefix; }; } // namespace Internal using namespace Internal; -DeploymentInfo::DeploymentInfo(AbstractEmbeddedLinuxTarget *target) : - QAbstractListModel(target), - d(new DeploymentInfoPrivate(target)) +DeploymentInfo::DeploymentInfo(AbstractEmbeddedLinuxTarget *target, const QString &installPrefix) + : QAbstractListModel(target), d(new DeploymentInfoPrivate(target)) { connect (d->target->qt4Project(), SIGNAL(proParsingDone()), SLOT(createModels())); - createModels(); + setInstallPrefix(installPrefix); } DeploymentInfo::~DeploymentInfo() @@ -102,7 +102,7 @@ void DeploymentInfo::createModels(const Qt4ProFileNode *proFileNode) case ApplicationTemplate: case LibraryTemplate: case AuxTemplate: - d->listModels << new DeployableFilesPerProFile(proFileNode, this); + d->listModels << new DeployableFilesPerProFile(proFileNode, d->installPrefix, this); break; case SubDirsTemplate: { const QList<Qt4PriFileNode *> &subProjects = proFileNode->subProjectNodesExact(); @@ -133,6 +133,12 @@ bool DeploymentInfo::isModified() const return false; } +void DeploymentInfo::setInstallPrefix(const QString &installPrefix) +{ + d->installPrefix = installPrefix; + createModels(); +} + int DeploymentInfo::deployableCount() const { int count = 0; diff --git a/src/plugins/remotelinux/deploymentinfo.h b/src/plugins/remotelinux/deploymentinfo.h index 5690b3f7c2..fffa093ac0 100644 --- a/src/plugins/remotelinux/deploymentinfo.h +++ b/src/plugins/remotelinux/deploymentinfo.h @@ -51,11 +51,12 @@ class REMOTELINUX_EXPORT DeploymentInfo : public QAbstractListModel { Q_OBJECT public: - DeploymentInfo(AbstractEmbeddedLinuxTarget *target); + DeploymentInfo(AbstractEmbeddedLinuxTarget *target, const QString &installPrefix = QString()); ~DeploymentInfo(); void setUnmodified(); bool isModified() const; + void setInstallPrefix(const QString &installPrefix); int deployableCount() const; DeployableFile deployableAt(int i) const; QString remoteExecutableFilePath(const QString &localExecutableFilePath) const; diff --git a/src/plugins/remotelinux/genericembeddedlinuxtarget.cpp b/src/plugins/remotelinux/genericembeddedlinuxtarget.cpp index a20ed770fc..db0371b7a2 100644 --- a/src/plugins/remotelinux/genericembeddedlinuxtarget.cpp +++ b/src/plugins/remotelinux/genericembeddedlinuxtarget.cpp @@ -36,6 +36,7 @@ #include "remotelinuxrunconfiguration.h" #include <projectexplorer/customexecutablerunconfiguration.h> +#include <projectexplorer/devicesupport/idevice.h> #include <qt4projectmanager/qt4buildconfiguration.h> #include <qt4projectmanager/qt4nodes.h> #include <qt4projectmanager/qt4project.h> @@ -47,8 +48,7 @@ namespace RemoteLinux { namespace Internal { GenericEmbeddedLinuxTarget::GenericEmbeddedLinuxTarget(Qt4ProjectManager::Qt4Project *parent, - const QString &id) : - AbstractEmbeddedLinuxTarget(parent, id, QLatin1String(Constants::GenericLinuxOsType)) + const QString &id) : AbstractEmbeddedLinuxTarget(parent, id) { setDisplayName(tr("Embedded Linux")); } @@ -71,6 +71,11 @@ Utils::FileName GenericEmbeddedLinuxTarget::mkspec(const Qt4ProjectManager::Qt4B return version->mkspec(); } +bool GenericEmbeddedLinuxTarget::supportsDevice(const ProjectExplorer::IDevice::ConstPtr &device) const +{ + return device->type() == QLatin1String(Constants::GenericLinuxOsType); +} + void GenericEmbeddedLinuxTarget::createApplicationProFiles(bool reparse) { if (!reparse) diff --git a/src/plugins/remotelinux/genericembeddedlinuxtarget.h b/src/plugins/remotelinux/genericembeddedlinuxtarget.h index 5850f4d142..cdb52f2034 100644 --- a/src/plugins/remotelinux/genericembeddedlinuxtarget.h +++ b/src/plugins/remotelinux/genericembeddedlinuxtarget.h @@ -50,6 +50,7 @@ public: void createApplicationProFiles(bool reparse); QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Node *n); Utils::FileName mkspec(const Qt4ProjectManager::Qt4BuildConfiguration *bc) const; + bool supportsDevice(const QSharedPointer<const ProjectExplorer::IDevice> &device) const; private: friend class EmbeddedLinuxTargetFactory; diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp index 0c7865199c..625b6bad70 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp @@ -33,6 +33,7 @@ #include "genericlinuxdeviceconfigurationwizard.h" #include "genericlinuxdeviceconfigurationwidget.h" +#include "linuxdeviceconfiguration.h" #include "linuxdevicetestdialog.h" #include "publickeydeploymentdialog.h" #include "remotelinuxprocessesdialog.h" @@ -41,10 +42,12 @@ #include <utils/qtcassert.h> +using namespace ProjectExplorer; + namespace RemoteLinux { GenericLinuxDeviceConfigurationFactory::GenericLinuxDeviceConfigurationFactory(QObject *parent) - : ILinuxDeviceConfigurationFactory(parent) + : IDeviceFactory(parent) { } @@ -53,26 +56,35 @@ QString GenericLinuxDeviceConfigurationFactory::displayName() const return tr("Generic Linux Device"); } -ILinuxDeviceConfigurationWizard *GenericLinuxDeviceConfigurationFactory::createWizard(QWidget *parent) const +IDeviceWizard *GenericLinuxDeviceConfigurationFactory::createWizard(QWidget *parent) const { return new GenericLinuxDeviceConfigurationWizard(parent); } -ILinuxDeviceConfigurationWidget *GenericLinuxDeviceConfigurationFactory::createWidget( - const LinuxDeviceConfiguration::Ptr &deviceConfig, - QWidget *parent) const +IDeviceWidget *GenericLinuxDeviceConfigurationFactory::createWidget(const IDevice::Ptr &device, + QWidget *parent) const { - return new GenericLinuxDeviceConfigurationWidget(deviceConfig, parent); + return new GenericLinuxDeviceConfigurationWidget(device.staticCast<LinuxDeviceConfiguration>(), + parent); } -bool GenericLinuxDeviceConfigurationFactory::supportsOsType(const QString &osType) const +IDevice::Ptr GenericLinuxDeviceConfigurationFactory::loadDevice(const QVariantMap &map) const { - return osType == QLatin1String(Constants::GenericLinuxOsType); + QTC_ASSERT(supportsDeviceType(IDevice::typeFromMap(map)), + return LinuxDeviceConfiguration::Ptr()); + LinuxDeviceConfiguration::Ptr device = LinuxDeviceConfiguration::create(); + device->fromMap(map); + return device; } -QString GenericLinuxDeviceConfigurationFactory::displayNameForOsType(const QString &osType) const +bool GenericLinuxDeviceConfigurationFactory::supportsDeviceType(const QString &deviceType) const { - QTC_ASSERT(supportsOsType(osType), return QString()); + return deviceType == QLatin1String(Constants::GenericLinuxOsType); +} + +QString GenericLinuxDeviceConfigurationFactory::displayNameForDeviceType(const QString &deviceType) const +{ + QTC_ASSERT(supportsDeviceType(deviceType), return QString()); return tr("Generic Linux"); } @@ -85,7 +97,7 @@ QStringList GenericLinuxDeviceConfigurationFactory::supportedDeviceActionIds() c QString GenericLinuxDeviceConfigurationFactory::displayNameForActionId(const QString &actionId) const { - Q_ASSERT(supportedDeviceActionIds().contains(actionId)); + QTC_ASSERT(supportedDeviceActionIds().contains(actionId), return QString()); if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) return tr("Test"); @@ -97,18 +109,18 @@ QString GenericLinuxDeviceConfigurationFactory::displayNameForActionId(const QSt } QDialog *GenericLinuxDeviceConfigurationFactory::createDeviceAction(const QString &actionId, - const LinuxDeviceConfiguration::ConstPtr &deviceConfig, QWidget *parent) const + const IDevice::ConstPtr &device, QWidget *parent) const { - Q_ASSERT(supportedDeviceActionIds().contains(actionId)); + QTC_ASSERT(supportedDeviceActionIds().contains(actionId), return 0); + const LinuxDeviceConfiguration::ConstPtr lDevice + = device.staticCast<const LinuxDeviceConfiguration>(); if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) - return new LinuxDeviceTestDialog(deviceConfig, new GenericLinuxDeviceTester, parent); - if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) { - return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(deviceConfig), - parent); - } + return new LinuxDeviceTestDialog(lDevice, new GenericLinuxDeviceTester, parent); + if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) + return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(lDevice, parent)); if (actionId == QLatin1String(Constants::GenericDeployKeyToDeviceActionId)) - return PublicKeyDeploymentDialog::createDialog(deviceConfig, parent); + return PublicKeyDeploymentDialog::createDialog(lDevice, parent); return 0; // Can't happen. } diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h index 24b4400b2f..193821763e 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.h @@ -32,13 +32,14 @@ #ifndef GENERICLINUXDEVICECONFIGURATIONFACTORY_H #define GENERICLINUXDEVICECONFIGURATIONFACTORY_H -#include "linuxdeviceconfiguration.h" #include "remotelinux_export.h" +#include <projectexplorer/devicesupport/idevicefactory.h> + namespace RemoteLinux { class REMOTELINUX_EXPORT GenericLinuxDeviceConfigurationFactory - : public ILinuxDeviceConfigurationFactory + : public ProjectExplorer::IDeviceFactory { Q_OBJECT @@ -46,16 +47,16 @@ public: GenericLinuxDeviceConfigurationFactory(QObject *parent = 0); QString displayName() const; - ILinuxDeviceConfigurationWizard *createWizard(QWidget *parent) const; - ILinuxDeviceConfigurationWidget *createWidget( - const LinuxDeviceConfiguration::Ptr &deviceConfig, - QWidget *parent = 0) const; - bool supportsOsType(const QString &osType) const; - QString displayNameForOsType(const QString &osType) const; + ProjectExplorer::IDeviceWizard *createWizard(QWidget *parent) const; + ProjectExplorer::IDeviceWidget *createWidget(const ProjectExplorer::IDevice::Ptr &device, + QWidget *parent = 0) const; + ProjectExplorer::IDevice::Ptr loadDevice(const QVariantMap &map) const; + bool supportsDeviceType(const QString &deviceType) const; + QString displayNameForDeviceType(const QString &deviceType) const; QStringList supportedDeviceActionIds() const; QString displayNameForActionId(const QString &actionId) const; QDialog *createDeviceAction(const QString &actionId, - const LinuxDeviceConfiguration::ConstPtr &deviceConfig, QWidget *parent) const; + const ProjectExplorer::IDevice::ConstPtr &device, QWidget *parent) const; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp index bbb32d03ea..e07ac7c535 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp @@ -32,19 +32,19 @@ #include "genericlinuxdeviceconfigurationwidget.h" #include "ui_genericlinuxdeviceconfigurationwidget.h" -#include <remotelinux/portlist.h> -#include <remotelinux/linuxdeviceconfigurations.h> - +#include <utils/portlist.h> #include <utils/ssh/sshconnection.h> +#include <utils/ssh/sshkeycreationdialog.h> #include <QTextStream> using namespace RemoteLinux; +using namespace Utils; GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget( const LinuxDeviceConfiguration::Ptr &deviceConfig, QWidget *parent) : - ILinuxDeviceConfigurationWidget(deviceConfig, parent), + ProjectExplorer::IDeviceWidget(deviceConfig, parent), m_ui(new Ui::GenericLinuxDeviceConfigurationWidget) { m_ui->setupUi(this); @@ -61,7 +61,7 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget( connect(m_ui->sshPortSpinBox, SIGNAL(valueChanged(int)), this, SLOT(sshPortEditingFinished())); connect(m_ui->showPasswordCheckBox, SIGNAL(toggled(bool)), this, SLOT(showPassword(bool))); connect(m_ui->portsLineEdit, SIGNAL(editingFinished()), this, SLOT(handleFreePortsChanged())); - connect(m_ui->makeKeyFileDefaultButton, SIGNAL(clicked()), SLOT(setDefaultKeyFilePath())); + connect(m_ui->createKeyButton, SIGNAL(clicked()), SLOT(createNewKey())); initGui(); } @@ -73,57 +73,56 @@ GenericLinuxDeviceConfigurationWidget::~GenericLinuxDeviceConfigurationWidget() void GenericLinuxDeviceConfigurationWidget::authenticationTypeChanged() { - Utils::SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); + SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); const bool usePassword = m_ui->passwordButton->isChecked(); sshParams.authenticationType = usePassword - ? Utils::SshConnectionParameters::AuthenticationByPassword - : Utils::SshConnectionParameters::AuthenticationByKey; + ? SshConnectionParameters::AuthenticationByPassword + : SshConnectionParameters::AuthenticationByKey; deviceConfiguration()->setSshParameters(sshParams); m_ui->pwdLineEdit->setEnabled(usePassword); m_ui->passwordLabel->setEnabled(usePassword); m_ui->keyFileLineEdit->setEnabled(!usePassword); m_ui->keyLabel->setEnabled(!usePassword); - m_ui->makeKeyFileDefaultButton->setEnabled(!usePassword); } void GenericLinuxDeviceConfigurationWidget::hostNameEditingFinished() { - Utils::SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); + SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); sshParams.host = m_ui->hostLineEdit->text(); deviceConfiguration()->setSshParameters(sshParams); } void GenericLinuxDeviceConfigurationWidget::sshPortEditingFinished() { - Utils::SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); + SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); sshParams.port = m_ui->sshPortSpinBox->value(); deviceConfiguration()->setSshParameters(sshParams); } void GenericLinuxDeviceConfigurationWidget::timeoutEditingFinished() { - Utils::SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); + SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); sshParams.timeout = m_ui->timeoutSpinBox->value(); deviceConfiguration()->setSshParameters(sshParams); } void GenericLinuxDeviceConfigurationWidget::userNameEditingFinished() { - Utils::SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); + SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); sshParams.userName = m_ui->userLineEdit->text(); deviceConfiguration()->setSshParameters(sshParams); } void GenericLinuxDeviceConfigurationWidget::passwordEditingFinished() { - Utils::SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); + SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); sshParams.password = m_ui->pwdLineEdit->text(); deviceConfiguration()->setSshParameters(sshParams); } void GenericLinuxDeviceConfigurationWidget::keyFileEditingFinished() { - Utils::SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); + SshConnectionParameters sshParams = deviceConfiguration()->sshParameters(); sshParams.privateKeyFile = m_ui->keyFileLineEdit->path(); deviceConfiguration()->setSshParameters(sshParams); } @@ -140,17 +139,19 @@ void GenericLinuxDeviceConfigurationWidget::showPassword(bool showClearText) ? QLineEdit::Normal : QLineEdit::Password); } -void GenericLinuxDeviceConfigurationWidget::setDefaultKeyFilePath() -{ - emit defaultSshKeyFilePathChanged(m_ui->keyFileLineEdit->path()); -} - void GenericLinuxDeviceConfigurationWidget::setPrivateKey(const QString &path) { m_ui->keyFileLineEdit->setPath(path); keyFileEditingFinished(); } +void GenericLinuxDeviceConfigurationWidget::createNewKey() +{ + SshKeyCreationDialog dialog(this); + if (dialog.exec() == QDialog::Accepted) + setPrivateKey(dialog.privateKeyFilePath()); +} + void GenericLinuxDeviceConfigurationWidget::updatePortsWarningLabel() { m_ui->portsWarningLabel->setVisible(!deviceConfiguration()->freePorts().hasMore()); @@ -158,18 +159,22 @@ void GenericLinuxDeviceConfigurationWidget::updatePortsWarningLabel() void GenericLinuxDeviceConfigurationWidget::initGui() { + if (deviceConfiguration()->machineType() == LinuxDeviceConfiguration::Hardware) + m_ui->machineTypeValueLabel->setText(tr("Physical Device")); + else + m_ui->machineTypeValueLabel->setText(tr("Emulator")); m_ui->portsWarningLabel->setPixmap(QPixmap(":/projectexplorer/images/compile_error.png")); m_ui->portsWarningLabel->setToolTip(QLatin1String("<font color=\"red\">") + tr("You will need at least one port.") + QLatin1String("</font>")); - m_ui->keyFileLineEdit->setExpectedKind(Utils::PathChooser::File); + m_ui->keyFileLineEdit->setExpectedKind(PathChooser::File); m_ui->keyFileLineEdit->lineEdit()->setMinimumWidth(0); QRegExpValidator * const portsValidator = new QRegExpValidator(QRegExp(PortList::regularExpression()), this); m_ui->portsLineEdit->setValidator(portsValidator); - const Utils::SshConnectionParameters &sshParams = deviceConfiguration()->sshParameters(); + const SshConnectionParameters &sshParams = deviceConfiguration()->sshParameters(); - if (sshParams.authenticationType == Utils::SshConnectionParameters::AuthenticationByPassword) + if (sshParams.authenticationType == SshConnectionParameters::AuthenticationByPassword) m_ui->passwordButton->setChecked(true); else m_ui->keyButton->setChecked(true); @@ -187,3 +192,8 @@ void GenericLinuxDeviceConfigurationWidget::initGui() m_ui->showPasswordCheckBox->setChecked(false); updatePortsWarningLabel(); } + +LinuxDeviceConfiguration::Ptr GenericLinuxDeviceConfigurationWidget::deviceConfiguration() const +{ + return device().staticCast<LinuxDeviceConfiguration>(); +} diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h index 7e5a3ef30d..14e53d5ff0 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h @@ -32,9 +32,10 @@ #ifndef REMOTELINUX_GENERICLINUXDEVICECONFIGURATIONWIDGET_H #define REMOTELINUX_GENERICLINUXDEVICECONFIGURATIONWIDGET_H -#include "remotelinux_export.h" +#include <projectexplorer/devicesupport/idevicewidget.h> #include "linuxdeviceconfiguration.h" +#include "remotelinux_export.h" namespace RemoteLinux { @@ -42,14 +43,14 @@ namespace Ui { class GenericLinuxDeviceConfigurationWidget; } -class REMOTELINUX_EXPORT GenericLinuxDeviceConfigurationWidget : public ILinuxDeviceConfigurationWidget +class REMOTELINUX_EXPORT GenericLinuxDeviceConfigurationWidget + : public ProjectExplorer::IDeviceWidget { Q_OBJECT public: explicit GenericLinuxDeviceConfigurationWidget( - const LinuxDeviceConfiguration::Ptr &deviceConfig, - QWidget *parent = 0); + const LinuxDeviceConfiguration::Ptr &deviceConfig, QWidget *parent = 0); ~GenericLinuxDeviceConfigurationWidget(); private slots: @@ -62,12 +63,13 @@ private slots: void keyFileEditingFinished(); void showPassword(bool showClearText); void handleFreePortsChanged(); - void setDefaultKeyFilePath(); void setPrivateKey(const QString &path); + void createNewKey(); private: void updatePortsWarningLabel(); void initGui(); + LinuxDeviceConfiguration::Ptr deviceConfiguration() const; Ui::GenericLinuxDeviceConfigurationWidget *m_ui; }; diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui index 6a72bec054..a1b2dbea5c 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>393</width> - <height>170</height> + <height>206</height> </rect> </property> <property name="windowTitle"> @@ -20,14 +20,14 @@ <property name="margin"> <number>0</number> </property> - <item row="0" column="0"> + <item row="1" column="0"> <widget class="QLabel" name="authTypeLabel"> <property name="text"> <string>Authentication type:</string> </property> </widget> </item> - <item row="0" column="1"> + <item row="1" column="1"> <widget class="QWidget" name="authTypeButtonsWidget" native="true"> <layout class="QHBoxLayout" name="horizontalLayout_3"> <property name="margin"> @@ -63,7 +63,7 @@ </layout> </widget> </item> - <item row="1" column="0"> + <item row="2" column="0"> <widget class="QLabel" name="hostNameLabel"> <property name="text"> <string>&Host name:</string> @@ -73,7 +73,7 @@ </property> </widget> </item> - <item row="1" column="1"> + <item row="2" column="1"> <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> <widget class="QLineEdit" name="hostLineEdit"> @@ -107,7 +107,7 @@ </item> </layout> </item> - <item row="2" column="0"> + <item row="3" column="0"> <widget class="QLabel" name="freePortsLabel"> <property name="text"> <string>Free ports:</string> @@ -117,7 +117,7 @@ </property> </widget> </item> - <item row="2" column="1"> + <item row="3" column="1"> <layout class="QHBoxLayout" name="horizontalLayout_7"> <item> <widget class="QLineEdit" name="portsLineEdit"> @@ -161,7 +161,7 @@ </item> </layout> </item> - <item row="3" column="0"> + <item row="4" column="0"> <widget class="QLabel" name="userNameLabel"> <property name="text"> <string>&Username:</string> @@ -171,10 +171,10 @@ </property> </widget> </item> - <item row="3" column="1"> + <item row="4" column="1"> <widget class="QLineEdit" name="userLineEdit"/> </item> - <item row="4" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="passwordLabel"> <property name="text"> <string>&Password:</string> @@ -184,7 +184,7 @@ </property> </widget> </item> - <item row="4" column="1"> + <item row="5" column="1"> <layout class="QHBoxLayout" name="horizontalLayout_6"> <item> <widget class="QLineEdit" name="pwdLineEdit"> @@ -202,27 +202,37 @@ </item> </layout> </item> - <item row="5" column="0"> + <item row="6" column="0"> <widget class="QLabel" name="keyLabel"> <property name="text"> <string>Private key file:</string> </property> </widget> </item> - <item row="5" column="1"> + <item row="6" column="1"> <layout class="QHBoxLayout" name="horizontalLayout_8"> <item> <widget class="Utils::PathChooser" name="keyFileLineEdit" native="true"/> </item> <item> - <widget class="QPushButton" name="makeKeyFileDefaultButton"> + <widget class="QPushButton" name="createKeyButton"> <property name="text"> - <string>Set as Default</string> + <string>Create New...</string> </property> </widget> </item> </layout> </item> + <item row="0" column="0"> + <widget class="QLabel" name="machineTypeLabel"> + <property name="text"> + <string>Machine type:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="machineTypeValueLabel"/> + </item> </layout> <zorder>passwordLabel</zorder> <zorder>authTypeButtonsWidget</zorder> @@ -232,6 +242,8 @@ <zorder>userLineEdit</zorder> <zorder>authTypeLabel</zorder> <zorder>keyLabel</zorder> + <zorder>machineTypeLabel</zorder> + <zorder>machineTypeValueLabel</zorder> </widget> <customwidgets> <customwidget> diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp index 30d5a302e4..0a5e290bc0 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.cpp @@ -31,11 +31,13 @@ #include "genericlinuxdeviceconfigurationwizard.h" #include "genericlinuxdeviceconfigurationwizardpages.h" +#include "linuxdeviceconfiguration.h" #include "linuxdevicetestdialog.h" #include "linuxdevicetester.h" -#include "portlist.h" #include "remotelinux_constants.h" +#include <utils/portlist.h> +using namespace ProjectExplorer; using namespace Utils; namespace RemoteLinux { @@ -58,7 +60,7 @@ public: } // namespace Internal GenericLinuxDeviceConfigurationWizard::GenericLinuxDeviceConfigurationWizard(QWidget *parent) - : ILinuxDeviceConfigurationWizard(parent), + : IDeviceWizard(parent), d(new Internal::GenericLinuxDeviceConfigurationWizardPrivate(this)) { setWindowTitle(tr("New Generic Linux Device Configuration Setup")); @@ -72,9 +74,9 @@ GenericLinuxDeviceConfigurationWizard::~GenericLinuxDeviceConfigurationWizard() delete d; } -LinuxDeviceConfiguration::Ptr GenericLinuxDeviceConfigurationWizard::deviceConfiguration() +IDevice::Ptr GenericLinuxDeviceConfigurationWizard::device() { - Utils::SshConnectionParameters sshParams(SshConnectionParameters::NoProxy); + Utils::SshConnectionParameters sshParams; sshParams.host = d->setupPage.hostName(); sshParams.userName = d->setupPage.userName(); sshParams.port = 22; @@ -85,8 +87,9 @@ LinuxDeviceConfiguration::Ptr GenericLinuxDeviceConfigurationWizard::deviceConfi else sshParams.privateKeyFile = d->setupPage.privateKeyFilePath(); LinuxDeviceConfiguration::Ptr devConf = LinuxDeviceConfiguration::create(d->setupPage.configurationName(), - QLatin1String(Constants::GenericLinuxOsType), LinuxDeviceConfiguration::Hardware, - PortList::fromString(QLatin1String("10000-10100")), sshParams); + QLatin1String(Constants::GenericLinuxOsType), LinuxDeviceConfiguration::Hardware); + devConf->setFreePorts(Utils::PortList::fromString(QLatin1String("10000-10100"))); + devConf->setSshParameters(sshParams); LinuxDeviceTestDialog dlg(devConf, new GenericLinuxDeviceTester(this), this); dlg.exec(); return devConf; diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h index 9d57cb8fa6..a599f5edb2 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwizard.h @@ -31,7 +31,9 @@ #ifndef GENERICLINUXDEVICECONFIGURATIONWIZARD_H #define GENERICLINUXDEVICECONFIGURATIONWIZARD_H -#include "linuxdeviceconfiguration.h" +#include "remotelinux_export.h" + +#include <projectexplorer/devicesupport/idevicewizard.h> namespace RemoteLinux { namespace Internal { @@ -39,7 +41,7 @@ class GenericLinuxDeviceConfigurationWizardPrivate; } // namespace Internal class REMOTELINUX_EXPORT GenericLinuxDeviceConfigurationWizard - : public ILinuxDeviceConfigurationWizard + : public ProjectExplorer::IDeviceWizard { Q_OBJECT @@ -47,7 +49,7 @@ public: GenericLinuxDeviceConfigurationWizard(QWidget *parent = 0); ~GenericLinuxDeviceConfigurationWizard(); - LinuxDeviceConfiguration::Ptr deviceConfiguration(); + ProjectExplorer::IDevice::Ptr device(); private: Internal::GenericLinuxDeviceConfigurationWizardPrivate * const d; diff --git a/src/plugins/remotelinux/linuxdeviceconfiguration.cpp b/src/plugins/remotelinux/linuxdeviceconfiguration.cpp index c35ca9b219..7ffc5e492f 100644 --- a/src/plugins/remotelinux/linuxdeviceconfiguration.cpp +++ b/src/plugins/remotelinux/linuxdeviceconfiguration.cpp @@ -31,15 +31,14 @@ **************************************************************************/ #include "linuxdeviceconfiguration.h" -#include "linuxdeviceconfigurations.h" -#include "portlist.h" #include "remotelinux_constants.h" +#include <utils/portlist.h> #include <utils/ssh/sshconnection.h> #include <utils/qtcassert.h> -#include <QSettings> #include <QDesktopServices> +#include <QStringList> using namespace Utils; typedef SshConnectionParameters::AuthenticationType AuthType; @@ -47,10 +46,7 @@ typedef SshConnectionParameters::AuthenticationType AuthType; namespace RemoteLinux { namespace Internal { namespace { -const QLatin1String NameKey("Name"); -const QLatin1String OldOsVersionKey("OsVersion"); // Outdated, only use for upgrading. -const QLatin1String OsTypeKey("OsType"); -const QLatin1String TypeKey("Type"); +const QLatin1String MachineTypeKey("Type"); const QLatin1String HostKey("Host"); const QLatin1String SshPortKey("SshPort"); const QLatin1String PortsSpecKey("FreePortsSpec"); @@ -59,32 +55,18 @@ const QLatin1String AuthKey("Authentication"); const QLatin1String KeyFileKey("KeyFile"); const QLatin1String PasswordKey("Password"); const QLatin1String TimeoutKey("Timeout"); -const QLatin1String IsDefaultKey("IsDefault"); -const QLatin1String InternalIdKey("InternalId"); -const QLatin1String AttributesKey("Attributes"); const AuthType DefaultAuthType(SshConnectionParameters::AuthenticationByKey); const int DefaultTimeout(10); -const LinuxDeviceConfiguration::DeviceType DefaultDeviceType(LinuxDeviceConfiguration::Hardware); +const LinuxDeviceConfiguration::MachineType DefaultMachineType(LinuxDeviceConfiguration::Hardware); } // anonymous namespace class LinuxDeviceConfigurationPrivate { public: - LinuxDeviceConfigurationPrivate(const SshConnectionParameters &sshParameters) - : sshParameters(sshParameters) - { - } - SshConnectionParameters sshParameters; - QString displayName; - QString osType; - LinuxDeviceConfiguration::DeviceType deviceType; + LinuxDeviceConfiguration::MachineType machineType; PortList freePorts; - bool isDefault; - LinuxDeviceConfiguration::Origin origin; - LinuxDeviceConfiguration::Id internalId; - QVariantHash attributes; }; } // namespace Internal @@ -96,88 +78,30 @@ LinuxDeviceConfiguration::~LinuxDeviceConfiguration() delete d; } -LinuxDeviceConfiguration::Ptr LinuxDeviceConfiguration::create(const QSettings &settings, - Id &nextId) -{ - return Ptr(new LinuxDeviceConfiguration(settings, nextId)); -} - -LinuxDeviceConfiguration::Ptr LinuxDeviceConfiguration::create(const ConstPtr &other) -{ - return Ptr(new LinuxDeviceConfiguration(other)); -} - LinuxDeviceConfiguration::Ptr LinuxDeviceConfiguration::create(const QString &name, - const QString &osType, DeviceType deviceType, const PortList &freePorts, - const SshConnectionParameters &sshParams, const QVariantHash &attributes, Origin origin) + const QString &type, MachineType machineType, Origin origin, const QString &fingerprint) { - return Ptr(new LinuxDeviceConfiguration(name, osType, deviceType, freePorts, sshParams, - attributes, origin)); + return Ptr(new LinuxDeviceConfiguration(name, type, machineType, origin, fingerprint)); } -LinuxDeviceConfiguration::LinuxDeviceConfiguration(const QString &name, const QString &osType, - DeviceType deviceType, const PortList &freePorts, const SshConnectionParameters &sshParams, - const QVariantHash &attributes, Origin origin) - : d(new LinuxDeviceConfigurationPrivate(sshParams)) +LinuxDeviceConfiguration::LinuxDeviceConfiguration() : d(new LinuxDeviceConfigurationPrivate) { - d->displayName = name; - d->osType = osType; - d->deviceType = deviceType; - d->freePorts = freePorts; - d->isDefault = false; - d->origin = origin; - d->attributes = attributes; } -LinuxDeviceConfiguration::LinuxDeviceConfiguration(const QSettings &settings, Id &nextId) - : d(new LinuxDeviceConfigurationPrivate(SshConnectionParameters::NoProxy)) +LinuxDeviceConfiguration::LinuxDeviceConfiguration(const QString &name, const QString &type, + MachineType machineType, Origin origin, const QString &fingerprint) + : IDevice(type, origin, fingerprint), d(new LinuxDeviceConfigurationPrivate) { - d->origin = ManuallyAdded; - d->displayName = settings.value(NameKey).toString(); - d->osType = settings.value(OsTypeKey).toString(); - d->deviceType = static_cast<DeviceType>(settings.value(TypeKey, DefaultDeviceType).toInt()); - d->isDefault = settings.value(IsDefaultKey, false).toBool(); - d->internalId = settings.value(InternalIdKey, nextId).toULongLong(); - - if (d->internalId == nextId) - ++nextId; - - d->attributes = settings.value(AttributesKey).toHash(); - - // Convert from version < 2.3. - if (d->osType.isEmpty()) { - const int oldOsType = settings.value(OldOsVersionKey, -1).toInt(); - switch (oldOsType) { - case 0: d->osType = QLatin1String("Maemo5OsType"); break; - case 1: d->osType = QLatin1String("HarmattanOsType"); break; - case 2: d->osType = QLatin1String("MeeGoOsType"); break; - default: d->osType = QLatin1String(Constants::GenericLinuxOsType); - } - } - - d->freePorts = PortList::fromString(settings.value(PortsSpecKey, QLatin1String("10000-10100")).toString()); - d->sshParameters.host = settings.value(HostKey).toString(); - d->sshParameters.port = settings.value(SshPortKey, 22).toInt(); - d->sshParameters.userName = settings.value(UserNameKey).toString(); - d->sshParameters.authenticationType - = static_cast<AuthType>(settings.value(AuthKey, DefaultAuthType).toInt()); - d->sshParameters.password = settings.value(PasswordKey).toString(); - d->sshParameters.privateKeyFile - = settings.value(KeyFileKey, defaultPrivateKeyFilePath()).toString(); - d->sshParameters.timeout = settings.value(TimeoutKey, DefaultTimeout).toInt(); + setDisplayName(name); + d->machineType = machineType; } -LinuxDeviceConfiguration::LinuxDeviceConfiguration(const LinuxDeviceConfiguration::ConstPtr &other) - : d(new LinuxDeviceConfigurationPrivate(other->d->sshParameters)) +LinuxDeviceConfiguration::LinuxDeviceConfiguration(const LinuxDeviceConfiguration &other) + : IDevice(other), d(new LinuxDeviceConfigurationPrivate) { - d->displayName = other->d->displayName; - d->osType = other->d->osType; - d->deviceType = other->deviceType(); - d->freePorts = other->freePorts(); - d->isDefault = other->d->isDefault; - d->origin = other->d->origin; - d->internalId = other->d->internalId; - d->attributes = other->d->attributes; + d->machineType = other.machineType(); + d->freePorts = other.freePorts(); + d->sshParameters = other.d->sshParameters; } QString LinuxDeviceConfiguration::defaultPrivateKeyFilePath() @@ -191,94 +115,68 @@ QString LinuxDeviceConfiguration::defaultPublicKeyFilePath() return defaultPrivateKeyFilePath() + QLatin1String(".pub"); } -void LinuxDeviceConfiguration::save(QSettings &settings) const +LinuxDeviceConfiguration::Ptr LinuxDeviceConfiguration::create() { - settings.setValue(NameKey, d->displayName); - settings.setValue(OsTypeKey, d->osType); - settings.setValue(TypeKey, d->deviceType); - settings.setValue(HostKey, d->sshParameters.host); - settings.setValue(SshPortKey, d->sshParameters.port); - settings.setValue(PortsSpecKey, d->freePorts.toString()); - settings.setValue(UserNameKey, d->sshParameters.userName); - settings.setValue(AuthKey, d->sshParameters.authenticationType); - settings.setValue(PasswordKey, d->sshParameters.password); - settings.setValue(KeyFileKey, d->sshParameters.privateKeyFile); - settings.setValue(TimeoutKey, d->sshParameters.timeout); - settings.setValue(IsDefaultKey, d->isDefault); - settings.setValue(InternalIdKey, d->internalId); - settings.setValue(AttributesKey, d->attributes); + return Ptr(new LinuxDeviceConfiguration); } -SshConnectionParameters LinuxDeviceConfiguration::sshParameters() const +void LinuxDeviceConfiguration::fromMap(const QVariantMap &map) { - return d->sshParameters; + IDevice::fromMap(map); + d->machineType = static_cast<MachineType>(map.value(MachineTypeKey, DefaultMachineType).toInt()); + d->freePorts = PortList::fromString(map.value(PortsSpecKey, + QLatin1String("10000-10100")).toString()); + d->sshParameters.host = map.value(HostKey).toString(); + d->sshParameters.port = map.value(SshPortKey, 22).toInt(); + d->sshParameters.userName = map.value(UserNameKey).toString(); + d->sshParameters.authenticationType + = static_cast<AuthType>(map.value(AuthKey, DefaultAuthType).toInt()); + d->sshParameters.password = map.value(PasswordKey).toString(); + d->sshParameters.privateKeyFile = map.value(KeyFileKey, defaultPrivateKeyFilePath()).toString(); + d->sshParameters.timeout = map.value(TimeoutKey, DefaultTimeout).toInt(); } -LinuxDeviceConfiguration::DeviceType LinuxDeviceConfiguration::deviceType() const - +QVariantMap LinuxDeviceConfiguration::toMap() const { - return d->deviceType; + QVariantMap map = IDevice::toMap(); + map.insert(MachineTypeKey, d->machineType); + map.insert(HostKey, d->sshParameters.host); + map.insert(SshPortKey, d->sshParameters.port); + map.insert(PortsSpecKey, d->freePorts.toString()); + map.insert(UserNameKey, d->sshParameters.userName); + map.insert(AuthKey, d->sshParameters.authenticationType); + map.insert(PasswordKey, d->sshParameters.password); + map.insert(KeyFileKey, d->sshParameters.privateKeyFile); + map.insert(TimeoutKey, d->sshParameters.timeout); + return map; } -LinuxDeviceConfiguration::Id LinuxDeviceConfiguration::internalId() const +ProjectExplorer::IDevice::Ptr LinuxDeviceConfiguration::clone() const { - return d->internalId; + return Ptr(new LinuxDeviceConfiguration(*this)); } -void LinuxDeviceConfiguration::setSshParameters(const SshConnectionParameters &sshParameters) -{ - d->sshParameters = sshParameters; -} - -void LinuxDeviceConfiguration::setFreePorts(const PortList &freePorts) +SshConnectionParameters LinuxDeviceConfiguration::sshParameters() const { - d->freePorts = freePorts; + return d->sshParameters; } -void LinuxDeviceConfiguration::setAttribute(const QString &name, const QVariant &value) -{ - d->attributes[name] = value; -} +LinuxDeviceConfiguration::MachineType LinuxDeviceConfiguration::machineType() const -bool LinuxDeviceConfiguration::isAutoDetected() const { - return d->origin == AutoDetected; + return d->machineType; } -QVariantHash LinuxDeviceConfiguration::attributes() const +void LinuxDeviceConfiguration::setSshParameters(const SshConnectionParameters &sshParameters) { - return d->attributes; + d->sshParameters = sshParameters; } -QVariant LinuxDeviceConfiguration::attribute(const QString &name) const +void LinuxDeviceConfiguration::setFreePorts(const PortList &freePorts) { - return d->attributes.value(name); + d->freePorts = freePorts; } PortList LinuxDeviceConfiguration::freePorts() const { return d->freePorts; } -QString LinuxDeviceConfiguration::displayName() const { return d->displayName; } -QString LinuxDeviceConfiguration::osType() const { return d->osType; } -bool LinuxDeviceConfiguration::isDefault() const { return d->isDefault; } - -void LinuxDeviceConfiguration::setDisplayName(const QString &name) { d->displayName = name; } -void LinuxDeviceConfiguration::setInternalId(Id id) { d->internalId = id; } -void LinuxDeviceConfiguration::setDefault(bool isDefault) { d->isDefault = isDefault; } - -const LinuxDeviceConfiguration::Id LinuxDeviceConfiguration::InvalidId = 0; - - -ILinuxDeviceConfigurationWidget::ILinuxDeviceConfigurationWidget( - const LinuxDeviceConfiguration::Ptr &deviceConfig, - QWidget *parent) - : QWidget(parent), - m_deviceConfiguration(deviceConfig) -{ - QTC_CHECK(m_deviceConfiguration); -} - -LinuxDeviceConfiguration::Ptr ILinuxDeviceConfigurationWidget::deviceConfiguration() const -{ - return m_deviceConfiguration; -} } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdeviceconfiguration.h b/src/plugins/remotelinux/linuxdeviceconfiguration.h index d3504c4782..c03b29bef1 100644 --- a/src/plugins/remotelinux/linuxdeviceconfiguration.h +++ b/src/plugins/remotelinux/linuxdeviceconfiguration.h @@ -34,210 +34,57 @@ #include "remotelinux_export.h" -#include <QSharedPointer> -#include <QString> -#include <QStringList> -#include <QVariantHash> -#include <QWizard> - -QT_BEGIN_NAMESPACE -class QDialog; -class QSettings; -QT_END_NAMESPACE +#include <projectexplorer/devicesupport/idevice.h> namespace Utils { class SshConnectionParameters; +class PortList; } namespace RemoteLinux { -class LinuxDeviceConfigurations; -class PortList; - namespace Internal { class LinuxDeviceConfigurationPrivate; } // namespace Internal -class REMOTELINUX_EXPORT LinuxDeviceConfiguration +class REMOTELINUX_EXPORT LinuxDeviceConfiguration : public ProjectExplorer::IDevice { - friend class LinuxDeviceConfigurations; public: typedef QSharedPointer<LinuxDeviceConfiguration> Ptr; typedef QSharedPointer<const LinuxDeviceConfiguration> ConstPtr; - typedef quint64 Id; - - enum DeviceType { Hardware, Emulator }; - enum Origin { ManuallyAdded, AutoDetected }; + enum MachineType { Hardware, Emulator }; ~LinuxDeviceConfiguration(); - PortList freePorts() const; + Utils::PortList freePorts() const; Utils::SshConnectionParameters sshParameters() const; - QString displayName() const; - QString osType() const; - DeviceType deviceType() const; - Id internalId() const; - bool isDefault() const; - bool isAutoDetected() const; - QVariantHash attributes() const; - QVariant attribute(const QString &name) const; + MachineType machineType() const; void setSshParameters(const Utils::SshConnectionParameters &sshParameters); - void setFreePorts(const PortList &freePorts); - void setAttribute(const QString &name, const QVariant &value); + void setFreePorts(const Utils::PortList &freePorts); static QString defaultPrivateKeyFilePath(); static QString defaultPublicKeyFilePath(); - static const Id InvalidId; + static Ptr create(); + static Ptr create(const QString &name, const QString &type, MachineType machineType, + Origin origin = ManuallyAdded, const QString &fingerprint = QString()); - static Ptr create(const QString &name, const QString &osType, DeviceType deviceType, - const PortList &freePorts, const Utils::SshConnectionParameters &sshParams, - const QVariantHash &attributes = QVariantHash(), Origin origin = ManuallyAdded); -private: - LinuxDeviceConfiguration(const QString &name, const QString &osType, DeviceType deviceType, - const PortList &freePorts, const Utils::SshConnectionParameters &sshParams, - const QVariantHash &attributes, Origin origin); - LinuxDeviceConfiguration(const QSettings &settings, Id &nextId); - LinuxDeviceConfiguration(const ConstPtr &other); - - LinuxDeviceConfiguration(const LinuxDeviceConfiguration &); - LinuxDeviceConfiguration &operator=(const LinuxDeviceConfiguration &); - - static Ptr create(const QSettings &settings, Id &nextId); - static Ptr create(const ConstPtr &other); - - void setDisplayName(const QString &name); - void setInternalId(Id id); - void setDefault(bool isDefault); - void save(QSettings &settings) const; - - Internal::LinuxDeviceConfigurationPrivate *d; -}; - - -/*! - \class RemoteLinux::ILinuxDeviceConfigurationWizard - - \brief Provides an interface for wizards creating a LinuxDeviceConfiguration - - A class implementing this interface is a wizard whose final result is - a LinuxDeviceConfiguration object. The wizard will be started when the user chooses the - "Add..." action from the "Linux devices" options page. -*/ -class REMOTELINUX_EXPORT ILinuxDeviceConfigurationWizard : public QWizard -{ - Q_OBJECT - -public: - virtual LinuxDeviceConfiguration::Ptr deviceConfiguration() = 0; + void fromMap(const QVariantMap &map); + ProjectExplorer::IDevice::Ptr clone() const; protected: - ILinuxDeviceConfigurationWizard(QWidget *parent) : QWizard(parent) {} -}; + LinuxDeviceConfiguration(); + LinuxDeviceConfiguration(const QString &name, const QString &type, MachineType machineType, + Origin origin, const QString &fingerprint); + LinuxDeviceConfiguration(const LinuxDeviceConfiguration &other); - -/*! - \class RemoteLinux::LinuxDeviceConfigurationWidget : public QWidget - - \brief Provides an interface for the widget configuring a LinuxDeviceConfiguration - - A class implementing this interface will display a widget in the configuration - options page "Linux Device", in the "Device configuration" tab. - It's used to configure a particular device, the default widget is empty. -*/ -class REMOTELINUX_EXPORT ILinuxDeviceConfigurationWidget : public QWidget -{ - Q_OBJECT - -public: - ILinuxDeviceConfigurationWidget(const LinuxDeviceConfiguration::Ptr &deviceConfig, - QWidget *parent = 0); - -signals: - void defaultSshKeyFilePathChanged(const QString &path); - -protected: - LinuxDeviceConfiguration::Ptr deviceConfiguration() const; + QVariantMap toMap() const; private: - LinuxDeviceConfiguration::Ptr m_deviceConfiguration; -}; - - -/*! - \class RemoteLinux::ILinuxDeviceConfiguration factory. - - \brief Provides an interface for classes providing services related to certain type of Linux devices. - - The main service is a wizard providing the device configuration itself. - - The factory objects have to be added to the global object pool via - \c ExtensionSystem::PluginManager::addObject(). - \sa ExtensionSystem::PluginManager::addObject() -*/ -class REMOTELINUX_EXPORT ILinuxDeviceConfigurationFactory : public QObject -{ - Q_OBJECT - -public: - /*! - A short, one-line description of what kind of device this factory supports. - */ - virtual QString displayName() const = 0; - - /*! - A wizard that can create the types of device configuration this factory supports. - */ - virtual ILinuxDeviceConfigurationWizard *createWizard(QWidget *parent = 0) const = 0; - - /*! - A widget that can configure the device this factory supports. - */ - virtual ILinuxDeviceConfigurationWidget *createWidget( - const LinuxDeviceConfiguration::Ptr &deviceConfig, - QWidget *parent = 0) const = 0; - - /*! - Returns true iff this factory supports the given device type. - */ - virtual bool supportsOsType(const QString &osType) const = 0; - - /*! - Returns a human-readable string for the given OS type, if this factory supports that type. - */ - virtual QString displayNameForOsType(const QString &osType) const = 0; - - /*! - Returns a list of ids representing actions that can be run on device configurations - that this factory supports. These actions will be available in the "Linux Devices" - options page. - */ - virtual QStringList supportedDeviceActionIds() const = 0; - - /*! - A human-readable string for the given id. Will be displayed on a button which, when clicked, - will start the respective action. - */ - virtual QString displayNameForActionId(const QString &actionId) const = 0; - - /*! - True iff the user should be allowed to edit the device configurations created by this - factory. Returns true by default. Override if your factory creates fixed configurations - for which later editing makes no sense. - */ - bool isUserEditable() const { return true; } - - /*! - Produces a dialog implementing the respective action. The dialog is supposed to be - modal, so implementers must make sure to make it interruptible as to not needlessly - block the UI. - */ - virtual QDialog *createDeviceAction(const QString &actionId, - const LinuxDeviceConfiguration::ConstPtr &deviceConfig, QWidget *parent = 0) const = 0; + LinuxDeviceConfiguration &operator=(const LinuxDeviceConfiguration &); -protected: - ILinuxDeviceConfigurationFactory(QObject *parent) : QObject(parent) {} + Internal::LinuxDeviceConfigurationPrivate *d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdeviceconfigurations.cpp b/src/plugins/remotelinux/linuxdeviceconfigurations.cpp deleted file mode 100644 index d1387ee6cf..0000000000 --- a/src/plugins/remotelinux/linuxdeviceconfigurations.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#include "linuxdeviceconfigurations.h" - -#include "remotelinuxutils.h" - -#include <coreplugin/icore.h> -#include <utils/qtcassert.h> - -#include <QHash> -#include <QList> -#include <QSettings> -#include <QString> - -#include <algorithm> - -namespace RemoteLinux { -namespace Internal { - -namespace { -const QLatin1String SettingsGroup("MaemoDeviceConfigs"); -const QLatin1String IdCounterKey("IdCounter"); -const QLatin1String ConfigListKey("ConfigList"); -const QLatin1String DefaultKeyFilePathKey("DefaultKeyFile"); - -bool cloningBlocked = false; - -class DevConfNameMatcher -{ -public: - DevConfNameMatcher(const QString &name) : m_name(name) {} - bool operator()(const LinuxDeviceConfiguration::ConstPtr &devConfig) - { - return devConfig->displayName() == m_name; - } -private: - const QString m_name; -}; - -} // anonymous namespace - -class LinuxDeviceConfigurationsPrivate -{ -public: - static LinuxDeviceConfigurations *instance; - LinuxDeviceConfiguration::Id nextId; - QList<LinuxDeviceConfiguration::Ptr> devConfigs; - QString defaultSshKeyFilePath; -}; -LinuxDeviceConfigurations *LinuxDeviceConfigurationsPrivate::instance = 0; - -} // namespace Internal - -using namespace Internal; - - -LinuxDeviceConfigurations *LinuxDeviceConfigurations::instance(QObject *parent) -{ - if (LinuxDeviceConfigurationsPrivate::instance == 0) { - LinuxDeviceConfigurationsPrivate::instance = new LinuxDeviceConfigurations(parent); - LinuxDeviceConfigurationsPrivate::instance->load(); - } - return LinuxDeviceConfigurationsPrivate::instance; -} - -void LinuxDeviceConfigurations::replaceInstance(const LinuxDeviceConfigurations *other) -{ - Q_ASSERT(LinuxDeviceConfigurationsPrivate::instance); - - LinuxDeviceConfigurationsPrivate::instance->beginResetModel(); - copy(other, LinuxDeviceConfigurationsPrivate::instance, false); - LinuxDeviceConfigurationsPrivate::instance->save(); - LinuxDeviceConfigurationsPrivate::instance->endResetModel(); - emit LinuxDeviceConfigurationsPrivate::instance->updated(); -} - -LinuxDeviceConfigurations *LinuxDeviceConfigurations::cloneInstance() -{ - if (cloningBlocked) - return 0; - LinuxDeviceConfigurations * const other = new LinuxDeviceConfigurations(0); - copy(LinuxDeviceConfigurationsPrivate::instance, other, true); - return other; -} - -void LinuxDeviceConfigurations::copy(const LinuxDeviceConfigurations *source, - LinuxDeviceConfigurations *target, bool deep) -{ - if (deep) { - foreach (const LinuxDeviceConfiguration::ConstPtr &devConf, source->d->devConfigs) - target->d->devConfigs << LinuxDeviceConfiguration::create(devConf); - } else { - target->d->devConfigs = source->d->devConfigs; - } - target->d->defaultSshKeyFilePath = source->d->defaultSshKeyFilePath; - target->d->nextId = source->d->nextId; -} - -void LinuxDeviceConfigurations::save() -{ - QSettings *settings = Core::ICore::settings(); - settings->beginGroup(SettingsGroup); - settings->setValue(IdCounterKey, d->nextId); - settings->setValue(DefaultKeyFilePathKey, d->defaultSshKeyFilePath); - settings->beginWriteArray(ConfigListKey); - int skippedCount = 0; - for (int i = 0; i < d->devConfigs.count(); ++i) { - const LinuxDeviceConfiguration::ConstPtr &devConf = d->devConfigs.at(i); - if (devConf->isAutoDetected()) { - ++skippedCount; - } else { - settings->setArrayIndex(i-skippedCount); - devConf->save(*settings); - } - } - settings->endArray(); - settings->endGroup(); -} - -void LinuxDeviceConfigurations::addConfiguration(const LinuxDeviceConfiguration::Ptr &devConfig) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - - // Ensure uniqueness of name. - QString name = devConfig->displayName(); - if (hasConfig(name)) { - const QString nameTemplate = name + QLatin1String(" (%1)"); - int suffix = 2; - do - name = nameTemplate.arg(QString::number(suffix++)); - while (hasConfig(name)); - } - devConfig->setDisplayName(name); - - devConfig->setInternalId(d->nextId++); - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - if (!defaultDeviceConfig(devConfig->osType())) - devConfig->setDefault(true); - d->devConfigs << devConfig; - endInsertRows(); -} - -void LinuxDeviceConfigurations::removeConfiguration(int idx) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - Q_ASSERT(idx >= 0 && idx < rowCount()); - - beginRemoveRows(QModelIndex(), idx, idx); - const bool wasDefault = deviceAt(idx)->isDefault(); - const QString osType = deviceAt(idx)->osType(); - d->devConfigs.removeAt(idx); - endRemoveRows(); - if (wasDefault) { - for (int i = 0; i < d->devConfigs.count(); ++i) { - if (deviceAt(i)->osType() == osType) { - d->devConfigs.at(i)->setDefault(true); - const QModelIndex changedIndex = index(i, 0); - emit dataChanged(changedIndex, changedIndex); - break; - } - } - } -} - -void LinuxDeviceConfigurations::setDefaultSshKeyFilePath(const QString &path) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - - d->defaultSshKeyFilePath = path; -} - -QString LinuxDeviceConfigurations::defaultSshKeyFilePath() const -{ - return d->defaultSshKeyFilePath; -} - -void LinuxDeviceConfigurations::setConfigurationName(int i, const QString &name) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - Q_ASSERT(i >= 0 && i < rowCount()); - - d->devConfigs.at(i)->setDisplayName(name); - const QModelIndex changedIndex = index(i, 0); - emit dataChanged(changedIndex, changedIndex); -} - -void LinuxDeviceConfigurations::setSshParameters(int i, - const Utils::SshConnectionParameters ¶ms) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - Q_ASSERT(i >= 0 && i < rowCount()); - - d->devConfigs.at(i)->setSshParameters(params); -} - -void LinuxDeviceConfigurations::setFreePorts(int i, const PortList &freePorts) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - Q_ASSERT(i >= 0 && i < rowCount()); - - d->devConfigs.at(i)->setFreePorts(freePorts); -} - -void LinuxDeviceConfigurations::setDefaultDevice(int idx) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - Q_ASSERT(idx >= 0 && idx < rowCount()); - - const LinuxDeviceConfiguration::Ptr &devConf = d->devConfigs.at(idx); - if (devConf->isDefault()) - return; - QModelIndex oldDefaultIndex; - for (int i = 0; i < d->devConfigs.count(); ++i) { - const LinuxDeviceConfiguration::Ptr &oldDefaultDev = d->devConfigs.at(i); - if (oldDefaultDev->isDefault() && oldDefaultDev->osType() == devConf->osType()) { - oldDefaultDev->setDefault(false); - oldDefaultIndex = index(i, 0); - break; - } - } - - QTC_CHECK(oldDefaultIndex.isValid()); - emit dataChanged(oldDefaultIndex, oldDefaultIndex); - devConf->setDefault(true); - const QModelIndex newDefaultIndex = index(idx, 0); - emit dataChanged(newDefaultIndex, newDefaultIndex); -} - -void LinuxDeviceConfigurations::setAttribute(int index, const QString &name, const QVariant &value) -{ - QTC_ASSERT(this != LinuxDeviceConfigurationsPrivate::instance, return); - Q_ASSERT(index >= 0 && index < rowCount()); - - d->devConfigs.at(index)->setAttribute(name, value); -} - -LinuxDeviceConfigurations::LinuxDeviceConfigurations(QObject *parent) - : QAbstractListModel(parent), d(new LinuxDeviceConfigurationsPrivate) -{ -} - -LinuxDeviceConfiguration::Ptr LinuxDeviceConfigurations::mutableDeviceAt(int idx) const -{ - Q_ASSERT(idx >= 0 && idx < rowCount()); - return d->devConfigs.at(idx); -} - -void LinuxDeviceConfigurations::blockCloning() -{ - QTC_ASSERT(!cloningBlocked, return); - cloningBlocked = true; -} - -void LinuxDeviceConfigurations::unblockCloning() -{ - QTC_ASSERT(cloningBlocked, return); - cloningBlocked = false; - emit instance()->cloningPossible(); -} - -LinuxDeviceConfigurations::~LinuxDeviceConfigurations() -{ - delete d; -} - -void LinuxDeviceConfigurations::load() -{ - QSettings *settings = Core::ICore::settings(); - settings->beginGroup(SettingsGroup); - d->nextId = settings->value(IdCounterKey, 1).toULongLong(); - d->defaultSshKeyFilePath = settings->value(DefaultKeyFilePathKey, - LinuxDeviceConfiguration::defaultPrivateKeyFilePath()).toString(); - int count = settings->beginReadArray(ConfigListKey); - for (int i = 0; i < count; ++i) { - settings->setArrayIndex(i); - LinuxDeviceConfiguration::Ptr devConf - = LinuxDeviceConfiguration::create(*settings, d->nextId); - d->devConfigs << devConf; - } - settings->endArray(); - settings->endGroup(); - ensureOneDefaultConfigurationPerOsType(); -} - -LinuxDeviceConfiguration::ConstPtr LinuxDeviceConfigurations::deviceAt(int idx) const -{ - Q_ASSERT(idx >= 0 && idx < rowCount()); - return d->devConfigs.at(idx); -} - -bool LinuxDeviceConfigurations::hasConfig(const QString &name) const -{ - QList<LinuxDeviceConfiguration::Ptr>::ConstIterator resultIt = - std::find_if(d->devConfigs.constBegin(), d->devConfigs.constEnd(), - DevConfNameMatcher(name)); - return resultIt != d->devConfigs.constEnd(); -} - -LinuxDeviceConfiguration::ConstPtr LinuxDeviceConfigurations::find(LinuxDeviceConfiguration::Id id) const -{ - const int index = indexForInternalId(id); - return index == -1 ? LinuxDeviceConfiguration::ConstPtr() : deviceAt(index); -} - -LinuxDeviceConfiguration::ConstPtr LinuxDeviceConfigurations::defaultDeviceConfig(const QString &osType) const -{ - foreach (const LinuxDeviceConfiguration::ConstPtr &devConf, d->devConfigs) { - if (devConf->isDefault() && devConf->osType() == osType) - return devConf; - } - return LinuxDeviceConfiguration::ConstPtr(); -} - -int LinuxDeviceConfigurations::indexForInternalId(LinuxDeviceConfiguration::Id internalId) const -{ - for (int i = 0; i < d->devConfigs.count(); ++i) { - if (deviceAt(i)->internalId() == internalId) - return i; - } - return -1; -} - -LinuxDeviceConfiguration::Id LinuxDeviceConfigurations::internalId(LinuxDeviceConfiguration::ConstPtr devConf) const -{ - return devConf ? devConf->internalId() : LinuxDeviceConfiguration::InvalidId; -} - -void LinuxDeviceConfigurations::ensureOneDefaultConfigurationPerOsType() -{ - QHash<QString, bool> osTypeHasDefault; - - // Step 1: Ensure there's at most one default configuration per device type. - foreach (const LinuxDeviceConfiguration::Ptr &devConf, d->devConfigs) { - if (devConf->isDefault()) { - if (osTypeHasDefault.value(devConf->osType())) - devConf->setDefault(false); - else - osTypeHasDefault.insert(devConf->osType(), true); - } - } - - // Step 2: Ensure there's at least one default configuration per device type. - foreach (const LinuxDeviceConfiguration::Ptr &devConf, d->devConfigs) { - if (!osTypeHasDefault.value(devConf->osType())) { - devConf->setDefault(true); - osTypeHasDefault.insert(devConf->osType(), true); - } - } -} - -int LinuxDeviceConfigurations::rowCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent); - return d->devConfigs.count(); -} - -QVariant LinuxDeviceConfigurations::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() >= rowCount() || role != Qt::DisplayRole) - return QVariant(); - const LinuxDeviceConfiguration::ConstPtr devConf = deviceAt(index.row()); - QString name = devConf->displayName(); - if (devConf->isDefault()) { - name += QLatin1Char(' ') + tr("(default for %1)") - .arg(RemoteLinuxUtils::osTypeToString(devConf->osType())); - } - return name; -} - -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdeviceconfigurations.h b/src/plugins/remotelinux/linuxdeviceconfigurations.h deleted file mode 100644 index b79be8a165..0000000000 --- a/src/plugins/remotelinux/linuxdeviceconfigurations.h +++ /dev/null @@ -1,113 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#ifndef LINUXDEVICECONFIGURATIONS_H -#define LINUXDEVICECONFIGURATIONS_H - -#include "linuxdeviceconfiguration.h" -#include "remotelinux_export.h" - -#include <QAbstractListModel> - -QT_FORWARD_DECLARE_CLASS(QString) - -namespace RemoteLinux { -namespace Internal { -class LinuxDeviceConfigurationsPrivate; -class LinuxDeviceConfigurationsSettingsWidget; -} // namespace Internal - -class REMOTELINUX_EXPORT LinuxDeviceConfigurations : public QAbstractListModel -{ - Q_OBJECT - friend class Internal::LinuxDeviceConfigurationsSettingsWidget; -public: - ~LinuxDeviceConfigurations(); - - static LinuxDeviceConfigurations *instance(QObject *parent = 0); - - // If you want to edit the list of device configurations programatically - // (e.g. when doing device auto-detection), call cloneInstance() to get a copy, - // do the changes there and then call replaceInstance() to write them back. - // Callers must be prepared to deal with cloneInstance() temporarily returning null, - // which happens if the settings dialog is currently open. - // All other callers are required to do the clone/replace operation synchronously! - static void replaceInstance(const LinuxDeviceConfigurations *other); - static LinuxDeviceConfigurations *cloneInstance(); - - LinuxDeviceConfiguration::ConstPtr deviceAt(int index) const; - LinuxDeviceConfiguration::ConstPtr find(LinuxDeviceConfiguration::Id id) const; - LinuxDeviceConfiguration::ConstPtr defaultDeviceConfig(const QString &osType) const; - bool hasConfig(const QString &name) const; - int indexForInternalId(LinuxDeviceConfiguration::Id internalId) const; - LinuxDeviceConfiguration::Id internalId(LinuxDeviceConfiguration::ConstPtr devConf) const; - - QString defaultSshKeyFilePath() const; - - void addConfiguration(const LinuxDeviceConfiguration::Ptr &devConfig); - void removeConfiguration(int index); - void setConfigurationName(int i, const QString &name); - void setSshParameters(int i, const Utils::SshConnectionParameters ¶ms); - void setFreePorts(int i, const PortList &freePorts); - void setDefaultDevice(int index); - void setAttribute(int index, const QString &name, const QVariant &value); - - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex &index, - int role = Qt::DisplayRole) const; - -public slots: - void setDefaultSshKeyFilePath(const QString &path); - -signals: - void updated(); - void cloningPossible(); - -private: - LinuxDeviceConfigurations(QObject *parent); - - LinuxDeviceConfiguration::Ptr mutableDeviceAt(int index) const; - - static void blockCloning(); - static void unblockCloning(); - - void load(); - void save(); - static void copy(const LinuxDeviceConfigurations *source, - LinuxDeviceConfigurations *target, bool deep); - void ensureOneDefaultConfigurationPerOsType(); - - Internal::LinuxDeviceConfigurationsPrivate * const d; -}; - -} // namespace RemoteLinux - -#endif // LINUXDEVICECONFIGURATIONS_H diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index c1b915a58e..e7b32afa51 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -159,7 +159,7 @@ void GenericLinuxDeviceTester::handleProcessFinished(int exitStatus) emit progressMessage(tr("Checking if specified ports are available...")); d->state = TestingPorts; - d->portsGatherer.start(d->connection, d->deviceConfiguration); + d->portsGatherer.start(d->deviceConfiguration); } void GenericLinuxDeviceTester::handlePortsGatheringError(const QString &message) diff --git a/src/plugins/remotelinux/portlist.cpp b/src/plugins/remotelinux/portlist.cpp deleted file mode 100644 index 679f139220..0000000000 --- a/src/plugins/remotelinux/portlist.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#include "portlist.h" - -#include <QList> -#include <QPair> -#include <QString> - -#include <cctype> - -namespace RemoteLinux { -namespace Internal { -namespace { - -typedef QPair<int, int> Range; - -class PortsSpecParser -{ - struct ParseException { - ParseException(const char *error) : error(error) {} - const char * const error; - }; - -public: - PortsSpecParser(const QString &portsSpec) - : m_pos(0), m_portsSpec(portsSpec) { } - - /* - * Grammar: Spec -> [ ElemList ] - * ElemList -> Elem [ ',' ElemList ] - * Elem -> Port [ '-' Port ] - */ - PortList parse() - { - try { - if (!atEnd()) - parseElemList(); - } catch (ParseException &e) { - qWarning("Malformed ports specification: %s", e.error); - } - return m_portList; - } - -private: - void parseElemList() - { - if (atEnd()) - throw ParseException("Element list empty."); - parseElem(); - if (atEnd()) - return; - if (nextChar() != ',') { - throw ParseException("Element followed by something else " - "than a comma."); - } - ++m_pos; - parseElemList(); - } - - void parseElem() - { - const int startPort = parsePort(); - if (atEnd() || nextChar() != '-') { - m_portList.addPort(startPort); - return; - } - ++m_pos; - const int endPort = parsePort(); - if (endPort < startPort) - throw ParseException("Invalid range (end < start)."); - m_portList.addRange(startPort, endPort); - } - - int parsePort() - { - if (atEnd()) - throw ParseException("Empty port string."); - int port = 0; - do { - const char next = nextChar(); - if (!std::isdigit(next)) - break; - port = 10*port + next - '0'; - ++m_pos; - } while (!atEnd()); - if (port == 0 || port >= 2 << 16) - throw ParseException("Invalid port value."); - return port; - } - - bool atEnd() const { return m_pos == m_portsSpec.length(); } - char nextChar() const { return m_portsSpec.at(m_pos).toAscii(); } - - PortList m_portList; - int m_pos; - const QString &m_portsSpec; -}; - -} // anonymous namespace - -class PortListPrivate -{ -public: - QList<Range> ranges; -}; - -} // namespace Internal - -PortList::PortList() : d(new Internal::PortListPrivate) -{ -} - -PortList::PortList(const PortList &other) : d(new Internal::PortListPrivate(*other.d)) -{ -} - -PortList::~PortList() -{ - delete d; -} - -PortList &PortList::operator=(const PortList &other) -{ - *d = *other.d; - return *this; -} - -PortList PortList::fromString(const QString &portsSpec) -{ - return Internal::PortsSpecParser(portsSpec).parse(); -} - -void PortList::addPort(int port) { addRange(port, port); } - -void PortList::addRange(int startPort, int endPort) -{ - d->ranges << Internal::Range(startPort, endPort); -} - -bool PortList::hasMore() const { return !d->ranges.isEmpty(); } - -bool PortList::contains(int port) const -{ - foreach (const Internal::Range &r, d->ranges) { - if (port >= r.first && port <= r.second) - return true; - } - return false; -} - -int PortList::count() const -{ - int n = 0; - foreach (const Internal::Range &r, d->ranges) - n += r.second - r.first + 1; - return n; -} - -int PortList::getNext() -{ - Q_ASSERT(!d->ranges.isEmpty()); - - Internal::Range &firstRange = d->ranges.first(); - const int next = firstRange.first++; - if (firstRange.first > firstRange.second) - d->ranges.removeFirst(); - return next; -} - -QString PortList::toString() const -{ - QString stringRep; - foreach (const Internal::Range &range, d->ranges) { - stringRep += QString::number(range.first); - if (range.second != range.first) - stringRep += QLatin1Char('-') + QString::number(range.second); - stringRep += QLatin1Char(','); - } - if (!stringRep.isEmpty()) - stringRep.remove(stringRep.length() - 1, 1); // Trailing comma. - return stringRep; -} - -QString PortList::regularExpression() -{ - const QLatin1String portExpr("(\\d)+"); - const QString listElemExpr = QString::fromLatin1("%1(-%1)?").arg(portExpr); - return QString::fromLatin1("((%1)(,%1)*)?").arg(listElemExpr); -} - -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro index 186f71f1f8..25ccbf6dd8 100644 --- a/src/plugins/remotelinux/remotelinux.pro +++ b/src/plugins/remotelinux/remotelinux.pro @@ -13,9 +13,7 @@ HEADERS += \ remotelinuxplugin.h \ remotelinux_export.h \ linuxdeviceconfiguration.h \ - linuxdeviceconfigurations.h \ remotelinuxrunconfiguration.h \ - linuxdevicefactoryselectiondialog.h \ publickeydeploymentdialog.h \ genericlinuxdeviceconfigurationwizard.h \ genericlinuxdeviceconfigurationfactory.h \ @@ -26,7 +24,6 @@ HEADERS += \ remotelinuxruncontrolfactory.h \ remotelinuxdebugsupport.h \ genericlinuxdeviceconfigurationwizardpages.h \ - portlist.h \ deployablefile.h \ deployablefilesperprofile.h \ deploymentinfo.h \ @@ -48,13 +45,10 @@ HEADERS += \ linuxdevicetestdialog.h \ remotelinuxprocesslist.h \ remotelinuxprocessesdialog.h \ - linuxdeviceconfigurationssettingswidget.h \ remotelinuxenvironmentreader.h \ sshkeydeployer.h \ typespecificdeviceconfigurationlistmodel.h \ - sshkeycreationdialog.h \ remotelinuxusedportsgatherer.h \ - remotelinuxsettingspages.h \ remotelinuxutils.h \ deploymentsettingsassistant.h \ remotelinuxdeployconfigurationwidget.h \ @@ -72,9 +66,7 @@ SOURCES += \ embeddedlinuxqtversionfactory.cpp \ remotelinuxplugin.cpp \ linuxdeviceconfiguration.cpp \ - linuxdeviceconfigurations.cpp \ remotelinuxrunconfiguration.cpp \ - linuxdevicefactoryselectiondialog.cpp \ publickeydeploymentdialog.cpp \ genericlinuxdeviceconfigurationwizard.cpp \ genericlinuxdeviceconfigurationfactory.cpp \ @@ -85,7 +77,6 @@ SOURCES += \ remotelinuxruncontrolfactory.cpp \ remotelinuxdebugsupport.cpp \ genericlinuxdeviceconfigurationwizardpages.cpp \ - portlist.cpp \ deployablefilesperprofile.cpp \ deploymentinfo.cpp \ abstractremotelinuxdeploystep.cpp \ @@ -105,13 +96,10 @@ SOURCES += \ linuxdevicetestdialog.cpp \ remotelinuxprocesslist.cpp \ remotelinuxprocessesdialog.cpp \ - linuxdeviceconfigurationssettingswidget.cpp \ remotelinuxenvironmentreader.cpp \ sshkeydeployer.cpp \ typespecificdeviceconfigurationlistmodel.cpp \ - sshkeycreationdialog.cpp \ remotelinuxusedportsgatherer.cpp \ - remotelinuxsettingspages.cpp \ remotelinuxutils.cpp \ deploymentsettingsassistant.cpp \ remotelinuxdeployconfigurationwidget.cpp \ @@ -123,12 +111,9 @@ SOURCES += \ genericlinuxdeviceconfigurationwidget.cpp FORMS += \ - linuxdevicefactoryselectiondialog.ui \ genericlinuxdeviceconfigurationwizardsetuppage.ui \ linuxdevicetestdialog.ui \ remotelinuxprocessesdialog.ui \ - linuxdeviceconfigurationssettingswidget.ui \ - sshkeycreationdialog.ui \ remotelinuxdeployconfigurationwidget.ui \ profilesupdatedialog.ui \ genericlinuxdeviceconfigurationwidget.ui diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs index 4ebd6d01cf..fe4d63af7c 100644 --- a/src/plugins/remotelinux/remotelinux.qbs +++ b/src/plugins/remotelinux/remotelinux.qbs @@ -60,17 +60,10 @@ QtcPlugin { "genericremotelinuxdeploystepfactory.h", "linuxdeviceconfiguration.cpp", "linuxdeviceconfiguration.h", - "linuxdeviceconfigurations.cpp", - "linuxdeviceconfigurations.h", - "linuxdevicefactoryselectiondialog.cpp", - "linuxdevicefactoryselectiondialog.h", - "linuxdevicefactoryselectiondialog.ui", "linuxdevicetestdialog.cpp", "linuxdevicetestdialog.h", "linuxdevicetester.cpp", "linuxdevicetester.h", - "portlist.cpp", - "portlist.h", "publickeydeploymentdialog.cpp", "publickeydeploymentdialog.h", "remotelinux.qrc", @@ -102,21 +95,14 @@ QtcPlugin { "remotelinuxrunconfigurationwidget.cpp", "remotelinuxrunconfigurationwidget.h", "remotelinuxruncontrol.h", - "remotelinuxsettingspages.cpp", - "remotelinuxsettingspages.h", "remotelinuxusedportsgatherer.cpp", "remotelinuxutils.cpp", "remotelinuxutils.h", - "sshkeycreationdialog.cpp", - "sshkeycreationdialog.h", "startgdbserverdialog.cpp", "startgdbserverdialog.h", "tarpackagecreationstep.h", "uploadandinstalltarpackagestep.h", "genericdirectuploadservice.h", - "linuxdeviceconfigurationssettingswidget.cpp", - "linuxdeviceconfigurationssettingswidget.h", - "linuxdeviceconfigurationssettingswidget.ui", "linuxdevicetestdialog.ui", "packageuploader.cpp", "packageuploader.h", @@ -130,7 +116,6 @@ QtcPlugin { "remotelinuxprocessesdialog.h", "remotelinuxprocessesdialog.ui", "remotelinuxusedportsgatherer.h", - "sshkeycreationdialog.ui", "sshkeydeployer.cpp", "sshkeydeployer.h", "typespecificdeviceconfigurationlistmodel.cpp", diff --git a/src/plugins/remotelinux/remotelinux_constants.h b/src/plugins/remotelinux/remotelinux_constants.h index fba006162f..dc7c90df81 100644 --- a/src/plugins/remotelinux/remotelinux_constants.h +++ b/src/plugins/remotelinux/remotelinux_constants.h @@ -37,9 +37,6 @@ namespace Constants { const char GenericLinuxOsType[] = "GenericLinuxOsType"; -const char RemoteLinuxSettingsCategory[] = "X.RemoteLinux"; -const char RemoteLinuxSettingsPageId[] = "AA.Remote Linux Device Configurations"; - const char GenericTestDeviceActionId[] = "RemoteLinux.GenericTestDeviceAction"; const char GenericDeployKeyToDeviceActionId[] = "RemoteLinux.GenericDeployKeyToDeviceAction"; const char GenericRemoteProcessesActionId[] = "RemoteLinux.GenericRemoteProcessesAction"; diff --git a/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp b/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp index 6c00de18ee..1485db51c5 100644 --- a/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp +++ b/src/plugins/remotelinux/remotelinuxapplicationrunner.cpp @@ -32,10 +32,10 @@ #include "remotelinuxapplicationrunner.h" #include "linuxdeviceconfiguration.h" -#include "portlist.h" #include "remotelinuxrunconfiguration.h" #include "remotelinuxusedportsgatherer.h" +#include <utils/portlist.h> #include <utils/qtcassert.h> #include <utils/ssh/sshconnection.h> #include <utils/ssh/sshconnectionmanager.h> @@ -422,7 +422,7 @@ void AbstractRemoteLinuxApplicationRunner::handleInitialCleanupDone(bool success } d->state = GatheringPorts; - d->portsGatherer.start(d->connection, d->devConfig); + d->portsGatherer.start(d->devConfig); } void AbstractRemoteLinuxApplicationRunner::handleInitializationsDone(bool success) diff --git a/src/plugins/remotelinux/remotelinuxapplicationrunner.h b/src/plugins/remotelinux/remotelinuxapplicationrunner.h index 86cd9cb66a..92f2b053c0 100644 --- a/src/plugins/remotelinux/remotelinuxapplicationrunner.h +++ b/src/plugins/remotelinux/remotelinuxapplicationrunner.h @@ -37,12 +37,12 @@ #include <QSharedPointer> namespace Utils { +class PortList; class SshConnection; } namespace RemoteLinux { class LinuxDeviceConfiguration; -class PortList; class RemoteLinuxRunConfiguration; class RemoteLinuxUsedPortsGatherer; @@ -67,7 +67,7 @@ public: QSharedPointer<Utils::SshConnection> connection() const; QSharedPointer<const LinuxDeviceConfiguration> devConfig() const; const RemoteLinuxUsedPortsGatherer *usedPortsGatherer() const; - PortList *freePorts(); + Utils::PortList *freePorts(); QString remoteExecutable() const; QString arguments() const; QString commandPrefix() const; diff --git a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp index 20c12f91af..73344d11bc 100644 --- a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp +++ b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp @@ -110,10 +110,7 @@ DebuggerStartParameters AbstractRemoteLinuxDebugSupport::startParameters(const R params.startMode = AttachToRemoteServer; params.executable = runConfig->localExecutableFilePath(); params.debuggerCommand = runConfig->gdbCmd(); - QString host = devConf->sshParameters().host; - params.remoteChannel = host.contains(QLatin1Char(':')) - ? QString::fromLatin1("[%1]:-1").arg(host) - : host + QLatin1String(":-1"); + params.remoteChannel = devConf->sshParameters().host + QLatin1String(":-1"); // TODO: This functionality should be inside the debugger. const ProjectExplorer::Abi &abi = runConfig->target() @@ -210,11 +207,14 @@ void AbstractRemoteLinuxDebugSupport::startExecution() .arg(d->qmlPort); } + const QHostAddress peerAddress = runner()->connection()->connectionInfo().peerAddress; + QString peerAddressString = peerAddress.toString(); + if (peerAddress.protocol() == QAbstractSocket::IPv6Protocol) + peerAddressString.prepend(QLatin1Char('[')).append(QLatin1Char(']')); const QString remoteCommandLine = (d->qmlDebugging && !d->cppDebugging) ? QString::fromLatin1("%1 %2 %3").arg(runner()->commandPrefix()).arg(remoteExe).arg(args) : QString::fromLatin1("%1 gdbserver %5:%2 %3 %4").arg(runner()->commandPrefix()) - .arg(d->gdbServerPort).arg(remoteExe).arg(args) - .arg(runner()->connection()->connectionInfo().peerAddress.toString()); + .arg(d->gdbServerPort).arg(remoteExe).arg(args).arg(peerAddressString); connect(runner(), SIGNAL(remoteProcessFinished(qint64)), SLOT(handleRemoteProcessFinished(qint64))); runner()->startExecution(remoteCommandLine.toUtf8()); diff --git a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp index 0b1a0333bb..7c77a918f6 100644 --- a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp @@ -33,10 +33,10 @@ #include "abstractembeddedlinuxtarget.h" #include "deploymentinfo.h" -#include "linuxdeviceconfigurations.h" #include "remotelinuxdeployconfigurationwidget.h" #include "typespecificdeviceconfigurationlistmodel.h" +#include <projectexplorer/devicesupport/devicemanager.h> #include <qt4projectmanager/qt4target.h> using namespace ProjectExplorer; @@ -82,13 +82,13 @@ RemoteLinuxDeployConfiguration::~RemoteLinuxDeployConfiguration() void RemoteLinuxDeployConfiguration::initialize() { d->deviceConfiguration = target()->deviceConfigModel()->defaultDeviceConfig(); - connect(target()->deviceConfigModel(), SIGNAL(updated()), + connect(target()->deviceConfigModel(), SIGNAL(modelReset()), SLOT(handleDeviceConfigurationListUpdated())); } void RemoteLinuxDeployConfiguration::handleDeviceConfigurationListUpdated() { - setDeviceConfig(LinuxDeviceConfigurations::instance()->internalId(d->deviceConfiguration)); + setDeviceConfig(DeviceManager::instance()->internalId(d->deviceConfiguration)); } void RemoteLinuxDeployConfiguration::setDeviceConfig(LinuxDeviceConfiguration::Id internalId) @@ -102,8 +102,7 @@ bool RemoteLinuxDeployConfiguration::fromMap(const QVariantMap &map) { if (!DeployConfiguration::fromMap(map)) return false; - setDeviceConfig(map.value(QLatin1String(DeviceIdKey), - LinuxDeviceConfiguration::InvalidId).toULongLong()); + setDeviceConfig(map.value(QLatin1String(DeviceIdKey), IDevice::invalidId()).toULongLong()); return true; } @@ -111,7 +110,7 @@ QVariantMap RemoteLinuxDeployConfiguration::toMap() const { QVariantMap map = DeployConfiguration::toMap(); map.insert(QLatin1String(DeviceIdKey), - LinuxDeviceConfigurations::instance()->internalId(d->deviceConfiguration)); + DeviceManager::instance()->internalId(d->deviceConfiguration)); return map; } diff --git a/src/plugins/remotelinux/remotelinuxdeployconfigurationwidget.cpp b/src/plugins/remotelinux/remotelinuxdeployconfigurationwidget.cpp index 30f71dfc52..950f7a68f2 100644 --- a/src/plugins/remotelinux/remotelinuxdeployconfigurationwidget.cpp +++ b/src/plugins/remotelinux/remotelinuxdeployconfigurationwidget.cpp @@ -34,13 +34,13 @@ #include "abstractembeddedlinuxtarget.h" #include "deployablefilesperprofile.h" #include "deploymentinfo.h" -#include "linuxdeviceconfigurations.h" #include "remotelinuxdeployconfiguration.h" -#include "remotelinuxsettingspages.h" #include "typespecificdeviceconfigurationlistmodel.h" #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/icore.h> +#include <projectexplorer/devicesupport/devicemanager.h> +#include <projectexplorer/projectexplorerconstants.h> #include <utils/qtcassert.h> #include <QTreeView> @@ -182,8 +182,7 @@ void RemoteLinuxDeployConfigurationWidget::handleDeviceConfigurationListChanged( { const LinuxDeviceConfiguration::ConstPtr &devConf = d->deployConfiguration->deviceConfiguration(); - const LinuxDeviceConfiguration::Id internalId - = LinuxDeviceConfigurations::instance()->internalId(devConf); + const IDevice::Id internalId = DeviceManager::instance()->internalId(devConf); const int newIndex = d->deployConfiguration->target()->deviceConfigModel()->indexForInternalId(internalId); d->ui.deviceConfigsComboBox->setCurrentIndex(newIndex); @@ -191,8 +190,9 @@ void RemoteLinuxDeployConfigurationWidget::handleDeviceConfigurationListChanged( void RemoteLinuxDeployConfigurationWidget::showDeviceConfigurations() { - Core::ICore::showOptionsDialog(LinuxDeviceConfigurationsSettingsPage::pageCategory(), - LinuxDeviceConfigurationsSettingsPage::pageId()); + Core::ICore::showOptionsDialog( + QLatin1String(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY), + QLatin1String(ProjectExplorer::Constants::DEVICE_SETTINGS_PAGE_ID)); } void RemoteLinuxDeployConfigurationWidget::openProjectFile() diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp index 0703560562..0cf91f4fdf 100644 --- a/src/plugins/remotelinux/remotelinuxplugin.cpp +++ b/src/plugins/remotelinux/remotelinuxplugin.cpp @@ -37,12 +37,10 @@ #include "deployablefile.h" #include "genericlinuxdeviceconfigurationfactory.h" #include "genericremotelinuxdeploystepfactory.h" -#include "linuxdeviceconfigurations.h" #include "qt4projectmanager/qt4projectmanagerconstants.h" #include "remotelinuxdeployconfigurationfactory.h" #include "remotelinuxrunconfigurationfactory.h" #include "remotelinuxruncontrolfactory.h" -#include "remotelinuxsettingspages.h" #include "startgdbserverdialog.h" #include <coreplugin/icore.h> @@ -71,10 +69,7 @@ bool RemoteLinuxPlugin::initialize(const QStringList &arguments, Q_UNUSED(arguments) Q_UNUSED(errorMessage) - LinuxDeviceConfigurations::instance(this); - addObject(this); - addAutoReleasedObject(new LinuxDeviceConfigurationsSettingsPage); addAutoReleasedObject(new GenericLinuxDeviceConfigurationFactory); addAutoReleasedObject(new RemoteLinuxRunConfigurationFactory); addAutoReleasedObject(new RemoteLinuxRunControlFactory); diff --git a/src/plugins/remotelinux/remotelinuxplugin.h b/src/plugins/remotelinux/remotelinuxplugin.h index b65e6da10d..7307bc8ea4 100644 --- a/src/plugins/remotelinux/remotelinuxplugin.h +++ b/src/plugins/remotelinux/remotelinuxplugin.h @@ -41,6 +41,7 @@ namespace Internal { class RemoteLinuxPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "RemoteLinux.json") public: RemoteLinuxPlugin(); diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp index 6b20963ba5..67392b4cd6 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp @@ -34,7 +34,6 @@ #include "deploymentinfo.h" #include "linuxdeviceconfiguration.h" -#include "portlist.h" #include "remotelinuxdeployconfiguration.h" #include "remotelinuxrunconfigurationwidget.h" @@ -47,10 +46,12 @@ #include <qt4projectmanager/qt4project.h> #include <qt4projectmanager/qt4target.h> +#include <utils/portlist.h> #include <utils/qtcassert.h> using namespace ProjectExplorer; using namespace Qt4ProjectManager; +using namespace Utils; namespace RemoteLinux { namespace Internal { @@ -94,8 +95,8 @@ public: QString gdbPath; QString arguments; RemoteLinuxRunConfiguration::BaseEnvironmentType baseEnvironmentType; - Utils::Environment remoteEnvironment; - QList<Utils::EnvironmentItem> userEnvironmentChanges; + Environment remoteEnvironment; + QList<EnvironmentItem> userEnvironmentChanges; bool validParse; bool parseInProgress; QString disabledReason; @@ -185,7 +186,7 @@ QWidget *RemoteLinuxRunConfiguration::createConfigurationWidget() return new RemoteLinuxRunConfigurationWidget(this); } -Utils::OutputFormatter *RemoteLinuxRunConfiguration::createOutputFormatter() const +OutputFormatter *RemoteLinuxRunConfiguration::createOutputFormatter() const { return new QtSupport::QtOutputFormatter(qt4Target()->qt4Project()); } @@ -211,7 +212,7 @@ QVariantMap RemoteLinuxRunConfiguration::toMap() const map.insert(QLatin1String(ProFileKey), dir.relativeFilePath(d->proFilePath)); map.insert(QLatin1String(BaseEnvironmentBaseKey), d->baseEnvironmentType); map.insert(QLatin1String(UserEnvironmentChangesKey), - Utils::EnvironmentItem::toStringList(d->userEnvironmentChanges)); + EnvironmentItem::toStringList(d->userEnvironmentChanges)); map.insert(QLatin1String(UseAlternateExeKey), d->useAlternateRemoteExecutable); map.insert(QLatin1String(AlternateExeKey), d->alternateRemoteExecutable); map.insert(QLatin1String(WorkingDirectoryKey), d->workingDirectory); @@ -227,7 +228,7 @@ bool RemoteLinuxRunConfiguration::fromMap(const QVariantMap &map) const QDir dir = QDir(target()->project()->projectDirectory()); d->proFilePath = QDir::cleanPath(dir.filePath(map.value(QLatin1String(ProFileKey)).toString())); d->userEnvironmentChanges = - Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(UserEnvironmentChangesKey)) + EnvironmentItem::fromStringList(map.value(QLatin1String(UserEnvironmentChangesKey)) .toStringList()); d->baseEnvironmentType = static_cast<BaseEnvironmentType>(map.value(QLatin1String(BaseEnvironmentBaseKey), RemoteBaseEnvironment).toInt()); @@ -417,20 +418,20 @@ void RemoteLinuxRunConfiguration::setBaseEnvironmentType(BaseEnvironmentType env } } -Utils::Environment RemoteLinuxRunConfiguration::environment() const +Environment RemoteLinuxRunConfiguration::environment() const { - Utils::Environment env = baseEnvironment(); + Environment env = baseEnvironment(); env.modify(userEnvironmentChanges()); return env; } -Utils::Environment RemoteLinuxRunConfiguration::baseEnvironment() const +Environment RemoteLinuxRunConfiguration::baseEnvironment() const { return (d->baseEnvironmentType == RemoteBaseEnvironment ? remoteEnvironment() - : Utils::Environment()); + : Environment()); } -QList<Utils::EnvironmentItem> RemoteLinuxRunConfiguration::userEnvironmentChanges() const +QList<EnvironmentItem> RemoteLinuxRunConfiguration::userEnvironmentChanges() const { return d->userEnvironmentChanges; } @@ -439,13 +440,13 @@ QString RemoteLinuxRunConfiguration::userEnvironmentChangesAsString() const { QString env; QString placeHolder = QLatin1String("%1=%2 "); - foreach (const Utils::EnvironmentItem &item, userEnvironmentChanges()) + foreach (const EnvironmentItem &item, userEnvironmentChanges()) env.append(placeHolder.arg(item.name, item.value)); return env.mid(0, env.size() - 1); } void RemoteLinuxRunConfiguration::setUserEnvironmentChanges( - const QList<Utils::EnvironmentItem> &diff) + const QList<EnvironmentItem> &diff) { if (d->userEnvironmentChanges != diff) { d->userEnvironmentChanges = diff; @@ -453,12 +454,12 @@ void RemoteLinuxRunConfiguration::setUserEnvironmentChanges( } } -Utils::Environment RemoteLinuxRunConfiguration::remoteEnvironment() const +Environment RemoteLinuxRunConfiguration::remoteEnvironment() const { return d->remoteEnvironment; } -void RemoteLinuxRunConfiguration::setRemoteEnvironment(const Utils::Environment &environment) +void RemoteLinuxRunConfiguration::setRemoteEnvironment(const Environment &environment) { if (d->remoteEnvironment.size() == 0 || d->remoteEnvironment != environment) { d->remoteEnvironment = environment; diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.h b/src/plugins/remotelinux/remotelinuxrunconfiguration.h index cd702ebe17..29b4656877 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfiguration.h +++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.h @@ -44,9 +44,12 @@ class Qt4BaseTarget; class Qt4ProFileNode; } // namespace Qt4ProjectManager +namespace Utils { +class PortList; +} + namespace RemoteLinux { class LinuxDeviceConfiguration; -class PortList; class RemoteLinuxRunConfigurationWidget; class RemoteLinuxDeployConfiguration; @@ -85,7 +88,7 @@ public: virtual QString environmentPreparationCommand() const; virtual QString commandPrefix() const; - virtual PortList freePorts() const; + virtual Utils::PortList freePorts() const; QString localExecutableFilePath() const; QString defaultRemoteExecutableFilePath() const; @@ -131,7 +134,9 @@ protected: QString defaultDisplayName(); void setDisabledReason(const QString &reason) const; QString userEnvironmentChangesAsString() const; - Q_SLOT void updateEnabledState() { emit isEnabledChanged(isEnabled()); } + +protected slots: + void updateEnabledState() { emit enabledChanged(); } private slots: void proFileUpdate(Qt4ProjectManager::Qt4ProFileNode *pro, bool success, bool parseInProgress); diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp index 10bc98e890..bf30a70ff5 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp @@ -34,12 +34,12 @@ #include "linuxdeviceconfiguration.h" #include "remotelinuxrunconfiguration.h" #include "remotelinuxenvironmentreader.h" -#include "remotelinuxsettingspages.h" #include "remotelinuxutils.h" #include <coreplugin/coreconstants.h> #include <coreplugin/icore.h> #include <projectexplorer/environmentwidget.h> +#include <projectexplorer/projectexplorerconstants.h> #include <qt4projectmanager/qt4buildconfiguration.h> #include <qt4projectmanager/qt4target.h> #include <utils/detailswidget.h> @@ -114,9 +114,9 @@ RemoteLinuxRunConfigurationWidget::RemoteLinuxRunConfigurationWidget(RemoteLinux connect(d->runConfiguration, SIGNAL(deviceConfigurationChanged(ProjectExplorer::Target*)), SLOT(handleCurrentDeviceConfigChanged())); handleCurrentDeviceConfigChanged(); - connect(d->runConfiguration, SIGNAL(isEnabledChanged(bool)), - SLOT(runConfigurationEnabledChange(bool))); - runConfigurationEnabledChange(d->runConfiguration->isEnabled()); + connect(d->runConfiguration, SIGNAL(enabledChanged()), + SLOT(runConfigurationEnabledChange())); + runConfigurationEnabledChange(); } RemoteLinuxRunConfigurationWidget::~RemoteLinuxRunConfigurationWidget() @@ -141,8 +141,9 @@ void RemoteLinuxRunConfigurationWidget::addDisabledLabel(QVBoxLayout *topLayout) topLayout->addLayout(hl); } -void RemoteLinuxRunConfigurationWidget::runConfigurationEnabledChange(bool enabled) +void RemoteLinuxRunConfigurationWidget::runConfigurationEnabledChange() { + bool enabled = d->runConfiguration->isEnabled(); d->topWidget.setEnabled(enabled); d->disabledIcon.setVisible(!enabled); d->disabledReason.setVisible(!enabled); @@ -289,8 +290,9 @@ void RemoteLinuxRunConfigurationWidget::handleWorkingDirectoryChanged() void RemoteLinuxRunConfigurationWidget::showDeviceConfigurationsDialog(const QString &link) { if (link == QLatin1String("deviceconfig")) { - Core::ICore::showOptionsDialog(LinuxDeviceConfigurationsSettingsPage::pageCategory(), - LinuxDeviceConfigurationsSettingsPage::pageId()); + Core::ICore::showOptionsDialog( + QLatin1String(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY), + QLatin1String(ProjectExplorer::Constants::DEVICE_SETTINGS_PAGE_ID)); } else if (link == QLatin1String("debugger")) { Core::ICore::showOptionsDialog(QLatin1String("O.Debugger"), QLatin1String("M.Gdb")); diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h index 74c5a90420..840c3b54f1 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h +++ b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h @@ -60,7 +60,7 @@ public: void addFormLayoutRow(QWidget *label, QWidget *field); void addDisabledLabel(QVBoxLayout *topLayout); - Q_SLOT void runConfigurationEnabledChange(bool enabled); + Q_SLOT void runConfigurationEnabledChange(); private slots: void argumentsEdited(const QString &args); diff --git a/src/plugins/remotelinux/remotelinuxruncontrolfactory.cpp b/src/plugins/remotelinux/remotelinuxruncontrolfactory.cpp index d283e10d1b..1e9ee52ae4 100644 --- a/src/plugins/remotelinux/remotelinuxruncontrolfactory.cpp +++ b/src/plugins/remotelinux/remotelinuxruncontrolfactory.cpp @@ -31,7 +31,6 @@ #include "remotelinuxruncontrolfactory.h" -#include "portlist.h" #include "remotelinuxdebugsupport.h" #include "remotelinuxrunconfiguration.h" #include "remotelinuxruncontrol.h" @@ -41,6 +40,7 @@ #include <debugger/debuggerrunner.h> #include <debugger/debuggerstartparameters.h> #include <projectexplorer/projectexplorerconstants.h> +#include <utils/portlist.h> using namespace Debugger; using namespace ProjectExplorer; diff --git a/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp b/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp index ade18dfcbb..23c442b52d 100644 --- a/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp +++ b/src/plugins/remotelinux/remotelinuxusedportsgatherer.cpp @@ -31,9 +31,12 @@ #include "remotelinuxusedportsgatherer.h" #include "linuxdeviceconfiguration.h" -#include "portlist.h" -#include <utils/ssh/sshremoteprocessrunner.h> +#include <utils/portlist.h> +#include <utils/qtcassert.h> +#include <utils/ssh/sshconnection.h> +#include <utils/ssh/sshconnectionmanager.h> +#include <utils/ssh/sshremoteprocess.h> #include <QString> @@ -45,14 +48,12 @@ namespace Internal { class RemoteLinuxUsedPortsGathererPrivate { public: - RemoteLinuxUsedPortsGathererPrivate() : running(false) {} - - SshRemoteProcessRunner procRunner; + SshConnection::Ptr connection; + SshRemoteProcess::Ptr process; PortList portsToCheck; QList<int> usedPorts; QByteArray remoteStdout; QByteArray remoteStderr; - bool running; // TODO: Redundant due to being in sync with procRunner? }; } // namespace Internal @@ -69,24 +70,26 @@ RemoteLinuxUsedPortsGatherer::~RemoteLinuxUsedPortsGatherer() delete d; } -void RemoteLinuxUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connection, - const LinuxDeviceConfiguration::ConstPtr &devConf) +void RemoteLinuxUsedPortsGatherer::start(const LinuxDeviceConfiguration::ConstPtr &devConf) { - if (d->running) - qWarning("Unexpected call of %s in running state", Q_FUNC_INFO); + QTC_ASSERT(!d->connection, return); d->portsToCheck = devConf->freePorts(); - d->usedPorts.clear(); - d->remoteStdout.clear(); - d->remoteStderr.clear(); - connect(&d->procRunner, SIGNAL(connectionError()), SLOT(handleConnectionError())); - connect(&d->procRunner, SIGNAL(processClosed(int)), SLOT(handleProcessClosed(int))); - connect(&d->procRunner, SIGNAL(processOutputAvailable(QByteArray)), - SLOT(handleRemoteStdOut(QByteArray))); - connect(&d->procRunner, SIGNAL(processErrorOutputAvailable(QByteArray)), - SLOT(handleRemoteStdErr(QByteArray))); + d->connection = SshConnectionManager::instance().acquireConnection(devConf->sshParameters()); + connect(d->connection.data(), SIGNAL(error(Utils::SshError)), SLOT(handleConnectionError())); + if (d->connection->state() == SshConnection::Connected) { + handleConnectionEstablished(); + return; + } + connect(d->connection.data(), SIGNAL(connected()), SLOT(handleConnectionEstablished())); + if (d->connection->state() == SshConnection::Unconnected) + d->connection->connectToHost(); +} + +void RemoteLinuxUsedPortsGatherer::handleConnectionEstablished() +{ QString procFilePath; int addressLength; - if (connection->connectionInfo().localAddress.protocol() == QAbstractSocket::IPv4Protocol) { + if (d->connection->connectionInfo().localAddress.protocol() == QAbstractSocket::IPv4Protocol) { procFilePath = QLatin1String("/proc/net/tcp"); addressLength = 8; } else { @@ -96,19 +99,28 @@ void RemoteLinuxUsedPortsGatherer::start(const Utils::SshConnection::Ptr &connec const QString command = QString::fromLatin1("sed " "'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2") .arg(addressLength).arg(procFilePath); + d->process = d->connection->createRemoteProcess(command.toUtf8()); + + connect(d->process.data(), SIGNAL(closed(int)), SLOT(handleProcessClosed(int))); + connect(d->process.data(), SIGNAL(readyReadStandardOutput()), SLOT(handleRemoteStdOut())); + connect(d->process.data(), SIGNAL(readyReadStandardError()), SLOT(handleRemoteStdErr())); - // TODO: We should not use an SshRemoteProcessRunner here, because we have to check - // for the type of the connection before we can say what the exact command line is. - d->procRunner.run(command.toUtf8(), connection->connectionParameters()); - d->running = true; + d->process->start(); } void RemoteLinuxUsedPortsGatherer::stop() { - if (!d->running) + if (!d->connection) return; - d->running = false; - disconnect(&d->procRunner, 0, this, 0); + d->usedPorts.clear(); + d->remoteStdout.clear(); + d->remoteStderr.clear(); + if (d->process) + disconnect(d->process.data(), 0, this, 0); + d->process.clear(); + disconnect(d->connection.data(), 0, this, 0); + SshConnectionManager::instance().releaseConnection(d->connection); + d->connection.clear(); } int RemoteLinuxUsedPortsGatherer::getNextFreePort(PortList *freePorts) const @@ -148,33 +160,29 @@ void RemoteLinuxUsedPortsGatherer::setupUsedPorts() void RemoteLinuxUsedPortsGatherer::handleConnectionError() { - if (!d->running) + if (!d->connection) return; - emit error(tr("Connection error: %1").arg(d->procRunner.lastConnectionErrorString())); + emit error(tr("Connection error: %1").arg(d->connection->errorString())); stop(); } void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus) { - if (!d->running) + if (!d->connection) return; QString errMsg; switch (exitStatus) { case SshRemoteProcess::FailedToStart: - errMsg = tr("Could not start remote process: %1") - .arg(d->procRunner.processErrorString()); + errMsg = tr("Could not start remote process: %1").arg(d->process->errorString()); break; case SshRemoteProcess::KilledBySignal: - errMsg = tr("Remote process crashed: %1") - .arg(d->procRunner.processErrorString()); + errMsg = tr("Remote process crashed: %1").arg(d->process->errorString()); break; case SshRemoteProcess::ExitedNormally: - if (d->procRunner.processExitCode() == 0) { + if (d->process->exitCode() == 0) setupUsedPorts(); - } else { - errMsg = tr("Remote process failed; exit code was %1.") - .arg(d->procRunner.processExitCode()); - } + else + errMsg = tr("Remote process failed; exit code was %1.").arg(d->process->exitCode()); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); @@ -190,14 +198,16 @@ void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus) stop(); } -void RemoteLinuxUsedPortsGatherer::handleRemoteStdOut(const QByteArray &output) +void RemoteLinuxUsedPortsGatherer::handleRemoteStdOut() { - d->remoteStdout += output; + if (d->process) + d->remoteStdout += d->process->readAllStandardOutput(); } -void RemoteLinuxUsedPortsGatherer::handleRemoteStdErr(const QByteArray &output) +void RemoteLinuxUsedPortsGatherer::handleRemoteStdErr() { - d->remoteStderr += output; + if (d->process) + d->remoteStderr += d->process->readAllStandardError(); } } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinuxusedportsgatherer.h b/src/plugins/remotelinux/remotelinuxusedportsgatherer.h index 16e40f9965..f3efb31ee1 100644 --- a/src/plugins/remotelinux/remotelinuxusedportsgatherer.h +++ b/src/plugins/remotelinux/remotelinuxusedportsgatherer.h @@ -39,13 +39,10 @@ QT_FORWARD_DECLARE_CLASS(QString) -namespace Utils { -class SshConnection; -} // namespace Utils +namespace Utils { class PortList; } namespace RemoteLinux { class LinuxDeviceConfiguration; -class PortList; namespace Internal { class RemoteLinuxUsedPortsGathererPrivate; @@ -58,10 +55,9 @@ class REMOTELINUX_EXPORT RemoteLinuxUsedPortsGatherer : public QObject public: explicit RemoteLinuxUsedPortsGatherer(QObject *parent = 0); ~RemoteLinuxUsedPortsGatherer(); - void start(const QSharedPointer<Utils::SshConnection> &connection, - const QSharedPointer<const LinuxDeviceConfiguration> &devConf); + void start(const QSharedPointer<const LinuxDeviceConfiguration> &devConf); void stop(); - int getNextFreePort(PortList *freePorts) const; // returns -1 if no more are left + int getNextFreePort(Utils::PortList *freePorts) const; // returns -1 if no more are left QList<int> usedPorts() const; signals: @@ -69,10 +65,11 @@ signals: void portListReady(); private slots: + void handleConnectionEstablished(); void handleConnectionError(); void handleProcessClosed(int exitStatus); - void handleRemoteStdOut(const QByteArray &output); - void handleRemoteStdErr(const QByteArray &output); + void handleRemoteStdOut(); + void handleRemoteStdErr(); private: void setupUsedPorts(); diff --git a/src/plugins/remotelinux/remotelinuxutils.cpp b/src/plugins/remotelinux/remotelinuxutils.cpp index 327af7a2e4..c8aa2d6c25 100644 --- a/src/plugins/remotelinux/remotelinuxutils.cpp +++ b/src/plugins/remotelinux/remotelinuxutils.cpp @@ -34,60 +34,14 @@ #include "linuxdeviceconfiguration.h" #include <extensionsystem/pluginmanager.h> -#include <projectexplorer/abi.h> -#include <qt4projectmanager/qt4buildconfiguration.h> -#include <qt4projectmanager/qt4target.h> -#include <qtsupport/baseqtversion.h> #include <QCoreApplication> #include <QList> #include <QString> using namespace ExtensionSystem; -using namespace ProjectExplorer; -using namespace Qt4ProjectManager; -using namespace QtSupport; namespace RemoteLinux { -namespace Internal { -namespace { - -bool isUnixQt(const BaseQtVersion *qtVersion) -{ - if (!qtVersion) - return false; - const QList<Abi> &abis = qtVersion->qtAbis(); - foreach (const Abi &abi, abis) { - switch (abi.os()) { - case Abi::UnixOS: case Abi::BsdOS: case Abi::LinuxOS: case Abi::MacOS: return true; - default: continue; - } - } - return false; -} - -} // anonymous namespace -} // namespace Internal - -bool RemoteLinuxUtils::hasUnixQt(const Target *target) -{ - const Qt4BaseTarget * const qtTarget = qobject_cast<const Qt4BaseTarget *>(target); - if (!qtTarget) - return false; - const Qt4BuildConfiguration * const bc = qtTarget->activeQt4BuildConfiguration(); - return bc && Internal::isUnixQt(bc->qtVersion()); -} - -QString RemoteLinuxUtils::osTypeToString(const QString &osType) -{ - const QList<ILinuxDeviceConfigurationFactory *> &factories - = PluginManager::instance()->getObjects<ILinuxDeviceConfigurationFactory>(); - foreach (const ILinuxDeviceConfigurationFactory * const factory, factories) { - if (factory->supportsOsType(osType)) - return factory->displayNameForOsType(osType); - } - return QCoreApplication::translate("RemoteLinux", "Unknown OS"); -} QString RemoteLinuxUtils::deviceConfigurationName(const LinuxDeviceConfiguration::ConstPtr &devConf) { diff --git a/src/plugins/remotelinux/remotelinuxutils.h b/src/plugins/remotelinux/remotelinuxutils.h index cec48c67c6..a365fbd616 100644 --- a/src/plugins/remotelinux/remotelinuxutils.h +++ b/src/plugins/remotelinux/remotelinuxutils.h @@ -36,18 +36,12 @@ #include <QSharedPointer> -namespace ProjectExplorer { -class Target; -} - namespace RemoteLinux { class LinuxDeviceConfiguration; class REMOTELINUX_EXPORT RemoteLinuxUtils { public: - static bool hasUnixQt(const ProjectExplorer::Target *target); - static QString osTypeToString(const QString &osType); static QString deviceConfigurationName(const QSharedPointer<const LinuxDeviceConfiguration> &devConf); }; diff --git a/src/plugins/remotelinux/sshkeycreationdialog.cpp b/src/plugins/remotelinux/sshkeycreationdialog.cpp deleted file mode 100644 index f0f3f4bb5a..0000000000 --- a/src/plugins/remotelinux/sshkeycreationdialog.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** GNU Lesser General Public License Usage -** -** 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. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#include "sshkeycreationdialog.h" -#include "ui_sshkeycreationdialog.h" - -#include "linuxdeviceconfiguration.h" - -#include <utils/ssh/sshkeygenerator.h> -#include <utils/fileutils.h> - -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <QApplication> -#include <QDesktopServices> -#include <QMessageBox> - -using namespace Utils; -using namespace RemoteLinux::Internal; - -SshKeyCreationDialog::SshKeyCreationDialog(QWidget *parent) - : QDialog(parent), m_keyGenerator(0), m_ui(new Ui::SshKeyCreationDialog) -{ - m_ui->setupUi(this); - m_ui->privateKeyFilePathChooser->setExpectedKind(PathChooser::File); - const QString defaultPath = QDesktopServices::storageLocation(QDesktopServices::HomeLocation) - + QLatin1String("/.ssh/qtc_id"); - m_ui->privateKeyFilePathChooser->setPath(defaultPath); - filePathChanged(); - - connect(m_ui->rsa, SIGNAL(toggled(bool)), this, SLOT(keyTypeChanged())); - connect(m_ui->dsa, SIGNAL(toggled(bool)), this, SLOT(keyTypeChanged())); - connect(m_ui->privateKeyFilePathChooser, SIGNAL(changed(QString)), SLOT(filePathChanged())); - connect(m_ui->generateButton, SIGNAL(clicked()), this, SLOT(generateKeys())); -} - -SshKeyCreationDialog::~SshKeyCreationDialog() -{ - delete m_keyGenerator; -} - -void SshKeyCreationDialog::keyTypeChanged() -{ - m_ui->comboBox->setCurrentIndex(0); - m_ui->comboBox->setEnabled(m_ui->rsa->isChecked()); -} - -void SshKeyCreationDialog::generateKeys() -{ - const SshKeyGenerator::KeyType keyType = m_ui->rsa->isChecked() - ? SshKeyGenerator::Rsa - : SshKeyGenerator::Dsa; - - if (!m_keyGenerator) - m_keyGenerator = new SshKeyGenerator; - - QApplication::setOverrideCursor(Qt::BusyCursor); - const bool success = m_keyGenerator->generateKeys(keyType, SshKeyGenerator::Mixed, - m_ui->comboBox->currentText().toUShort()); - QApplication::restoreOverrideCursor(); - - if (success) { - saveKeys(); - } else { - QMessageBox::critical(this, tr("Key Generation Failed"), m_keyGenerator->error()); - } -} - -void SshKeyCreationDialog::filePathChanged() -{ - m_ui->generateButton->setEnabled(!privateKeyFilePath().isEmpty()); - m_ui->publicKeyFileLabel->setText(privateKeyFilePath() + QLatin1String(".pub")); -} - -void SshKeyCreationDialog::saveKeys() -{ - const QString parentDir = QFileInfo(privateKeyFilePath()).dir().path(); - if (!QDir::root().mkpath(parentDir)) { - QMessageBox::critical(this, tr("Failure To Save Key File"), - tr("Failed to create directory: '%1'.").arg(parentDir)); - return; - } - - FileSaver privSaver(privateKeyFilePath()); - privSaver.write(m_keyGenerator->privateKey()); - if (!privSaver.finalize(this)) - return; - QFile::setPermissions(privateKeyFilePath(), QFile::ReadOwner | QFile::WriteOwner); - - FileSaver pubSaver(m_ui->publicKeyFileLabel->text()); - pubSaver.write(m_keyGenerator->publicKey()); - if (pubSaver.finalize(this)) - accept(); -} - -QString SshKeyCreationDialog::privateKeyFilePath() const -{ - return m_ui->privateKeyFilePathChooser->path(); -} diff --git a/src/plugins/remotelinux/sshkeycreationdialog.ui b/src/plugins/remotelinux/sshkeycreationdialog.ui deleted file mode 100644 index 48befd8d2d..0000000000 --- a/src/plugins/remotelinux/sshkeycreationdialog.ui +++ /dev/null @@ -1,251 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>RemoteLinux::Internal::SshKeyCreationDialog</class> - <widget class="QDialog" name="RemoteLinux::Internal::SshKeyCreationDialog"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>295</width> - <height>223</height> - </rect> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="windowTitle"> - <string>SSH Key Configuration</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Options</string> - </property> - <layout class="QFormLayout" name="formLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="keyAlgo"> - <property name="text"> - <string>Key algorithm:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QRadioButton" name="rsa"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>&RSA</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QRadioButton" name="dsa"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>&DSA</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="keySize"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Key &size:</string> - </property> - <property name="buddy"> - <cstring>comboBox</cstring> - </property> - </widget> - </item> - <item row="2" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QComboBox" name="comboBox"> - <item> - <property name="text"> - <string notr="true">1024</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">2048</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">4096</string> - </property> - </item> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="privateKeyFileLabel"> - <property name="text"> - <string>Private key file:</string> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Public key file:</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="Utils::PathChooser" name="privateKeyFilePathChooser" native="true"/> - </item> - <item row="8" column="1"> - <widget class="QLabel" name="publicKeyFileLabel"> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="spacing"> - <number>6</number> - </property> - <item> - <widget class="QPushButton" name="generateButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>&Generate And Save Key Pair</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="closeButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>&Cancel</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>Utils::PathChooser</class> - <extends>QWidget</extends> - <header location="global">utils/pathchooser.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>closeButton</sender> - <signal>clicked()</signal> - <receiver>RemoteLinux::Internal::SshKeyCreationDialog</receiver> - <slot>close()</slot> - <hints> - <hint type="sourcelabel"> - <x>195</x> - <y>184</y> - </hint> - <hint type="destinationlabel"> - <x>381</x> - <y>107</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/src/plugins/remotelinux/startgdbserverdialog.cpp b/src/plugins/remotelinux/startgdbserverdialog.cpp index ca7526c0fb..f2475b4b5e 100644 --- a/src/plugins/remotelinux/startgdbserverdialog.cpp +++ b/src/plugins/remotelinux/startgdbserverdialog.cpp @@ -34,15 +34,14 @@ #include "remotelinuxprocesslist.h" #include "linuxdeviceconfiguration.h" -#include "linuxdeviceconfigurations.h" #include "remotelinuxusedportsgatherer.h" -#include "portlist.h" #include <coreplugin/icore.h> - #include <extensionsystem/pluginmanager.h> - +#include <projectexplorer/devicesupport/devicemanager.h> +#include <projectexplorer/devicesupport/devicemanagermodel.h> #include <utils/pathchooser.h> +#include <utils/portlist.h> #include <utils/qtcassert.h> #include <utils/ssh/sshconnection.h> #include <utils/ssh/sshremoteprocessrunner.h> @@ -70,6 +69,7 @@ #include <QVBoxLayout> using namespace Core; +using namespace ProjectExplorer; using namespace Utils; const char LastSysroot[] = "RemoteLinux/LastSysroot"; @@ -87,8 +87,9 @@ public: LinuxDeviceConfiguration::ConstPtr currentDevice() const { - LinuxDeviceConfigurations *devices = LinuxDeviceConfigurations::instance(); - return devices->deviceAt(deviceComboBox->currentIndex()); + DeviceManager *devices = DeviceManager::instance(); + return devices->deviceAt(deviceComboBox->currentIndex()) + .dynamicCast<const LinuxDeviceConfiguration>(); } StartGdbServerDialog *q; @@ -174,15 +175,16 @@ StartGdbServerDialog::StartGdbServerDialog(QWidget *parent) : { setWindowTitle(tr("List of Remote Processes")); - LinuxDeviceConfigurations *devices = LinuxDeviceConfigurations::instance(); + DeviceManager *devices = DeviceManager::instance(); + DeviceManagerModel * const model = new DeviceManagerModel(devices, this); QObject::connect(d->closeButton, SIGNAL(clicked()), this, SLOT(reject())); - d->deviceComboBox->setModel(devices); + d->deviceComboBox->setModel(model); d->deviceComboBox->setCurrentIndex(d->settings->value(LastDevice).toInt()); connect(&d->gatherer, SIGNAL(error(QString)), SLOT(portGathererError(QString))); connect(&d->gatherer, SIGNAL(portListReady()), SLOT(portListReady())); - if (devices->rowCount() == 0) { + if (devices->deviceCount() == 0) { d->tableView->setEnabled(false); } else { d->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -217,9 +219,13 @@ StartGdbServerDialog::~StartGdbServerDialog() void StartGdbServerDialog::attachToDevice(int index) { - LinuxDeviceConfigurations *devices = LinuxDeviceConfigurations::instance(); + DeviceManager *devices = DeviceManager::instance(); + LinuxDeviceConfiguration::ConstPtr device + = devices->deviceAt(index).dynamicCast<const LinuxDeviceConfiguration>(); + if (!device) + return; delete d->processList; - d->processList = new GenericRemoteLinuxProcessList(devices->deviceAt(index)); + d->processList = new GenericRemoteLinuxProcessList(device); d->proxyModel.setSourceModel(d->processList); connect(d->processList, SIGNAL(error(QString)), SLOT(handleRemoteError(QString))); @@ -260,6 +266,8 @@ void StartGdbServerDialog::attachToProcess() d->attachProcessButton->setEnabled(false); LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); + if (!device) + return; PortList ports = device->freePorts(); const int port = d->gatherer.getNextFreePort(&ports); const int row = d->proxyModel.mapToSource(indexes.first()).row(); @@ -317,8 +325,7 @@ void StartGdbServerDialog::startGdbServer() d->startServerOnly = true; if (exec() == QDialog::Rejected) return; - LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); - d->gatherer.start(SshConnection::create(device->sshParameters()), device); + d->gatherer.start(d->currentDevice()); } void StartGdbServerDialog::attachToRemoteProcess() @@ -326,8 +333,7 @@ void StartGdbServerDialog::attachToRemoteProcess() d->startServerOnly = false; if (exec() == QDialog::Rejected) return; - LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); - d->gatherer.start(SshConnection::create(device->sshParameters()), device); + d->gatherer.start(d->currentDevice()); } void StartGdbServerDialog::handleConnectionError() @@ -363,12 +369,7 @@ void StartGdbServerDialog::reportOpenPort(int port) { logMessage(tr("Port %1 is now accessible.").arg(port)); LinuxDeviceConfiguration::ConstPtr device = d->currentDevice(); - QString host = device->sshParameters().host; - QString channel; - if (host.contains(QLatin1Char(':'))) - channel = QString::fromLatin1("[%1]:%2").arg(host).arg(port); - else - channel = QString::fromLatin1("%1:%2").arg(host).arg(port); + QString channel = QString("%1:%2").arg(device->sshParameters().host).arg(port); logMessage(tr("Server started on %1").arg(channel)); const char *member = d->startServerOnly ? "gdbServerStarted" : "attachedToProcess"; @@ -399,8 +400,8 @@ void StartGdbServerDialog::startGdbServerOnPort(int port, int pid) SLOT(handleProcessErrorOutput(QByteArray))); connect(&d->runner, SIGNAL(processClosed(int)), SLOT(handleProcessClosed(int))); - QByteArray cmd = "/usr/bin/gdbserver --attach localhost:" - + QByteArray::number(port) + ' ' + QByteArray::number(pid); + QByteArray cmd = "/usr/bin/gdbserver --attach :" + + QByteArray::number(port) + " " + QByteArray::number(pid); logMessage(tr("Running command: %1").arg(QString::fromLatin1(cmd))); d->runner.run(cmd, device->sshParameters()); } diff --git a/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp b/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp index 215e42b338..3b177f5b4f 100644 --- a/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp +++ b/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.cpp @@ -31,19 +31,22 @@ **************************************************************************/ #include "typespecificdeviceconfigurationlistmodel.h" -#include "linuxdeviceconfigurations.h" -#include "remotelinux_constants.h" +#include "abstractembeddedlinuxtarget.h" + +#include <projectexplorer/devicesupport/devicemanager.h> +#include <utils/qtcassert.h> + +using namespace ProjectExplorer; namespace RemoteLinux { namespace Internal { -TypeSpecificDeviceConfigurationListModel::TypeSpecificDeviceConfigurationListModel(const QString &osType, - QObject *parent) : QAbstractListModel(parent), m_targetOsType(osType) +TypeSpecificDeviceConfigurationListModel::TypeSpecificDeviceConfigurationListModel(AbstractEmbeddedLinuxTarget *target) + : QAbstractListModel(target) { - const LinuxDeviceConfigurations * const devConfs - = LinuxDeviceConfigurations::instance(); - connect(devConfs, SIGNAL(modelReset()), this, SIGNAL(modelReset())); - connect(devConfs, SIGNAL(updated()), this, SIGNAL(updated())); + const DeviceManager * const devConfs = DeviceManager::instance(); + connect(devConfs, SIGNAL(updated()), this, SIGNAL(modelReset())); + connect(target, SIGNAL(supportedDevicesChanged()), this, SIGNAL(modelReset())); } TypeSpecificDeviceConfigurationListModel::~TypeSpecificDeviceConfigurationListModel() @@ -55,13 +58,10 @@ int TypeSpecificDeviceConfigurationListModel::rowCount(const QModelIndex &parent if (parent.isValid()) return 0; int count = 0; - const LinuxDeviceConfigurations * const devConfs - = LinuxDeviceConfigurations::instance(); - const int devConfsCount = devConfs->rowCount(); - if (m_targetOsType == QLatin1String(Constants::GenericLinuxOsType)) - return devConfsCount; + const DeviceManager * const devConfs = DeviceManager::instance(); + const int devConfsCount = devConfs->deviceCount(); for (int i = 0; i < devConfsCount; ++i) { - if (devConfs->deviceAt(i)->osType() == m_targetOsType) + if (target()->supportsDevice(devConfs->deviceAt(i))) ++count; } return count; @@ -75,41 +75,46 @@ QVariant TypeSpecificDeviceConfigurationListModel::data(const QModelIndex &index const LinuxDeviceConfiguration::ConstPtr &devConf = deviceAt(index.row()); Q_ASSERT(devConf); QString displayedName = devConf->displayName(); - if (devConf->isDefault() && devConf->osType() == m_targetOsType) - displayedName += QLatin1Char(' ') + tr("(default)"); + if (target()->supportsDevice(devConf) && DeviceManager::instance() + ->defaultDevice(devConf->type()) == devConf) { + displayedName = tr("%1 (default)").arg(displayedName); + } return displayedName; } LinuxDeviceConfiguration::ConstPtr TypeSpecificDeviceConfigurationListModel::deviceAt(int idx) const { int currentRow = -1; - const LinuxDeviceConfigurations * const devConfs - = LinuxDeviceConfigurations::instance(); - if (m_targetOsType == QLatin1String(Constants::GenericLinuxOsType)) - return devConfs->deviceAt(idx); - const int devConfsCount = devConfs->rowCount(); + const DeviceManager * const devConfs = DeviceManager::instance(); + const int devConfsCount = devConfs->deviceCount(); for (int i = 0; i < devConfsCount; ++i) { - if (devConfs->deviceAt(i)->osType() == m_targetOsType) { - if (++currentRow == idx) - return devConfs->deviceAt(i); - } + const IDevice::ConstPtr device = devConfs->deviceAt(i); + if (target()->supportsDevice(device) && ++currentRow == idx) + return device.staticCast<const LinuxDeviceConfiguration>(); } - Q_ASSERT(false); - return LinuxDeviceConfiguration::ConstPtr(); + QTC_ASSERT(false, return LinuxDeviceConfiguration::ConstPtr()); } LinuxDeviceConfiguration::ConstPtr TypeSpecificDeviceConfigurationListModel::defaultDeviceConfig() const { - return LinuxDeviceConfigurations::instance()->defaultDeviceConfig(m_targetOsType); + const DeviceManager * const deviceManager = DeviceManager::instance(); + const int deviceCount = deviceManager->deviceCount(); + for (int i = 0; i < deviceCount; ++i) { + const IDevice::ConstPtr device = deviceManager->deviceAt(i); + if (target()->supportsDevice(device) + && deviceManager->defaultDevice(device->type()) == device) { + return device.staticCast<const LinuxDeviceConfiguration>(); + } + } + return LinuxDeviceConfiguration::ConstPtr(); } LinuxDeviceConfiguration::ConstPtr TypeSpecificDeviceConfigurationListModel::find(LinuxDeviceConfiguration::Id id) const { - const LinuxDeviceConfiguration::ConstPtr &devConf - = LinuxDeviceConfigurations::instance()->find(id); - return devConf && (devConf->osType() == m_targetOsType - || m_targetOsType == QLatin1String(Constants::GenericLinuxOsType)) - ? devConf : defaultDeviceConfig(); + const IDevice::ConstPtr &devConf = DeviceManager::instance()->find(id); + if (devConf && target()->supportsDevice(devConf)) + return devConf.staticCast<const LinuxDeviceConfiguration>(); + return defaultDeviceConfig(); } int TypeSpecificDeviceConfigurationListModel::indexForInternalId(LinuxDeviceConfiguration::Id id) const @@ -122,5 +127,10 @@ int TypeSpecificDeviceConfigurationListModel::indexForInternalId(LinuxDeviceConf return -1; } +AbstractEmbeddedLinuxTarget *TypeSpecificDeviceConfigurationListModel::target() const +{ + return qobject_cast<AbstractEmbeddedLinuxTarget *>(QObject::parent()); +} + } // namespace Internal } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.h b/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.h index 6de2cc6611..9fac87a802 100644 --- a/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.h +++ b/src/plugins/remotelinux/typespecificdeviceconfigurationlistmodel.h @@ -38,13 +38,14 @@ #include <QSharedPointer> namespace RemoteLinux { +class AbstractEmbeddedLinuxTarget; namespace Internal { class TypeSpecificDeviceConfigurationListModel : public QAbstractListModel { Q_OBJECT public: - explicit TypeSpecificDeviceConfigurationListModel(const QString &osType, QObject *parent = 0); + explicit TypeSpecificDeviceConfigurationListModel(AbstractEmbeddedLinuxTarget *target); ~TypeSpecificDeviceConfigurationListModel(); virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; @@ -56,11 +57,8 @@ public: QSharedPointer<const LinuxDeviceConfiguration> find(LinuxDeviceConfiguration::Id id) const; int indexForInternalId(LinuxDeviceConfiguration::Id id) const; -signals: - void updated(); - private: - const QString m_targetOsType; + AbstractEmbeddedLinuxTarget * target() const; }; } // namespace Internal diff --git a/src/plugins/resourceeditor/resourceeditorplugin.h b/src/plugins/resourceeditor/resourceeditorplugin.h index 60a5ee63af..8415d623aa 100644 --- a/src/plugins/resourceeditor/resourceeditorplugin.h +++ b/src/plugins/resourceeditor/resourceeditorplugin.h @@ -49,6 +49,7 @@ class ResourceEditorFactory; class ResourceEditorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ResourceEditor.json") public: ResourceEditorPlugin(); diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h index e348752101..aaf504a142 100644 --- a/src/plugins/subversion/subversionplugin.h +++ b/src/plugins/subversion/subversionplugin.h @@ -79,6 +79,7 @@ struct SubversionResponse class SubversionPlugin : public VcsBase::VcsBasePlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Subversion.json") public: SubversionPlugin(); diff --git a/src/plugins/tasklist/tasklistplugin.h b/src/plugins/tasklist/tasklistplugin.h index c264773986..57873d370d 100644 --- a/src/plugins/tasklist/tasklistplugin.h +++ b/src/plugins/tasklist/tasklistplugin.h @@ -47,6 +47,7 @@ class TaskListPluginPrivate; class TaskListPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "TaskList.json") public: TaskListPlugin(); diff --git a/src/plugins/texteditor/autocompleter.cpp b/src/plugins/texteditor/autocompleter.cpp index 221531a9b9..166ee33ea6 100644 --- a/src/plugins/texteditor/autocompleter.cpp +++ b/src/plugins/texteditor/autocompleter.cpp @@ -276,10 +276,12 @@ int AutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor, return 0; // verify that we indeed do have an extra opening brace in the document + QTextBlock block = cursor.block(); + const QString textFromCusror = block.text().mid(cursor.positionInBlock()).trimmed(); int braceDepth = BaseTextDocumentLayout::braceDepth(doc->lastBlock()); - if (braceDepth <= 0) - return 0; // braces are all balanced or worse, no need to do anything + if (braceDepth <= 0 && (textFromCusror.isEmpty() || textFromCusror.at(0) != QLatin1Char('}'))) + return 0; // braces are all balanced or worse, no need to do anything and separator inserted not between '{' and '}' // we have an extra brace , let's see if we should close it @@ -289,7 +291,6 @@ int AutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor, if (condition) {| statement; */ - QTextBlock block = cursor.block(); int indentation = tabSettings.indentationColumn(block.text()); if (block.next().isValid()) { // not the last block diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index a59e2ff895..1e8632df04 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1074,6 +1074,11 @@ void BaseTextEditorWidget::unindent() indentOrUnindent(false); } +void BaseTextEditorWidget::openLinkUnderCursor() +{ + openLink(findLinkAt(textCursor())); +} + void BaseTextEditorWidget::moveLineUpDown(bool up) { QTextCursor cursor = textCursor(); @@ -5838,6 +5843,11 @@ void BaseTextEditorWidget::circularPaste() QPlainTextEdit::copy(); } +void BaseTextEditorWidget::switchUtf8bom() +{ + baseTextDocument()->switchUtf8Bom(); +} + QMimeData *BaseTextEditorWidget::createMimeDataFromSelection() const { if (d->m_inBlockSelectionMode) { @@ -6087,6 +6097,17 @@ void BaseTextEditorWidget::appendStandardContextMenuActions(QMenu *menu) a = am->command(Constants::CIRCULAR_PASTE)->action(); if (a && a->isEnabled()) menu->addAction(a); + + BaseTextDocument *doc = baseTextDocument(); + if (doc->codec()->name() == QString(QLatin1String("UTF-8"))) { + a = am->command(Constants::SWITCH_UTF8BOM)->action(); + if (a && a->isEnabled()) { + a->setText(doc->format().hasUtf8Bom ? tr("Delete UTF-8 BOM on Save") + : tr("Add UTF-8 BOM on Save")); + menu->addSeparator(); + menu->addAction(a); + } + } } diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index dddb6bf008..45f2565f2c 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -260,6 +260,7 @@ public slots: virtual void selectAll(); void circularPaste(); + void switchUtf8bom(); void zoomIn(int range = 1); void zoomOut(int range = 1); @@ -325,6 +326,8 @@ public slots: void indent(); void unindent(); + void openLinkUnderCursor(); + signals: void changed(); diff --git a/src/plugins/texteditor/circularclipboard.cpp b/src/plugins/texteditor/circularclipboard.cpp index 32c20ab539..bba248a84a 100644 --- a/src/plugins/texteditor/circularclipboard.cpp +++ b/src/plugins/texteditor/circularclipboard.cpp @@ -53,6 +53,16 @@ CircularClipboard *CircularClipboard::instance() void CircularClipboard::collect(const QMimeData *mimeData) { + //Avoid duplicates + const QString text = mimeData->text(); + for (QList<const QMimeData *>::iterator i = m_items.begin(); i != m_items.end(); ++i) { + if (mimeData == *i || text == (*i)->text()) { + if (mimeData != *i) + delete *i; + m_items.erase(i); + break; + } + } if (m_items.size() > kMaxSize) { delete m_items.last(); m_items.removeLast(); diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp index 7e53d2dda9..f59ae41d85 100644 --- a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp @@ -512,7 +512,7 @@ bool GenericProposalWidget::eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::FocusOut) { abort(); -#if defined(Q_OS_DARWIN) && ! defined(QT_MAC_USE_COCOA) +#if (QT_VERSION < 0x050000) && defined(Q_OS_DARWIN) && ! defined(QT_MAC_USE_COCOA) QFocusEvent *fe = static_cast<QFocusEvent *>(e); if (fe->reason() == Qt::OtherFocusReason) { // Qt/carbon workaround @@ -559,7 +559,7 @@ bool GenericProposalWidget::eventFilter(QObject *o, QEvent *e) case Qt::Key_Tab: case Qt::Key_Return: -#if defined(QT_MAC_USE_COCOA) || !defined(Q_OS_DARWIN) +#if (QT_VERSION >= 0x050000) || (defined(QT_MAC_USE_COCOA) || !defined(Q_OS_DARWIN)) abort(); if (d->m_completionListView->currentIndex().isValid()) emit proposalItemActivated(d->m_model->proposalItem( diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index c12adef8c5..752535cfbf 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -257,5 +257,9 @@ QtcPlugin { "tooltip/tooltip.cpp", "tooltip/tooltip.h" ] + ProductModule { + Depends { name: "Find" } + Depends { name: "Locator" } + } } diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp index 0e20f1901f..84747b7675 100644 --- a/src/plugins/texteditor/texteditoractionhandler.cpp +++ b/src/plugins/texteditor/texteditoractionhandler.cpp @@ -65,6 +65,7 @@ TextEditorActionHandler::TextEditorActionHandler(const char *context, m_cutAction(0), m_pasteAction(0), m_circularPasteAction(0), + m_switchUtf8bomAction(0), m_selectAllAction(0), m_gotoAction(0), m_printAction(0), @@ -104,6 +105,8 @@ TextEditorActionHandler::TextEditorActionHandler(const char *context, m_lowerCaseSelectionAction(0), m_indentAction(0), m_unindentAction(0), + m_followSymbolAction(0), + m_jumpToFileAction(0), m_optionalActions(optionalActions), m_currentEditor(0), m_contextId(context), @@ -379,6 +382,11 @@ void TextEditorActionHandler::createActions() connect(m_circularPasteAction, SIGNAL(triggered()), this, SLOT(circularPasteAction())); medit->addAction(command, Core::Constants::G_EDIT_COPYPASTE); + m_switchUtf8bomAction = new QAction(this); + m_modifyingActions << m_switchUtf8bomAction; + command = am->registerAction(m_switchUtf8bomAction, Constants::SWITCH_UTF8BOM, m_contextId, true); + connect(m_switchUtf8bomAction, SIGNAL(triggered()), this, SLOT(switchUtf8bomAction())); + m_indentAction = new QAction(tr("Indent"), this); m_modifyingActions << m_indentAction; command = am->registerAction(m_indentAction, Constants::INDENT, m_contextId, true); @@ -389,6 +397,16 @@ void TextEditorActionHandler::createActions() command = am->registerAction(m_unindentAction, Constants::UNINDENT, m_contextId, true); connect(m_unindentAction, SIGNAL(triggered()), this, SLOT(unindent())); + m_followSymbolAction = new QAction(tr("Follow Symbol Under Cursor"), this); + command = am->registerAction(m_followSymbolAction, Constants::FOLLOW_SYMBOL_UNDER_CURSOR, m_contextId, true); + command->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); + connect(m_followSymbolAction, SIGNAL(triggered()), this, SLOT(openLinkUnderCursor())); + + m_jumpToFileAction = new QAction(tr("Jump To File Under Cursor"), this); + command = am->registerAction(m_jumpToFileAction, Constants::JUMP_TO_FILE_UNDER_CURSOR, m_contextId, true); + command->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); + connect(m_jumpToFileAction, SIGNAL(triggered()), this, SLOT(openLinkUnderCursor())); + QAction *a = 0; a = new QAction(tr("Go to Line Start"), this); command = am->registerAction(a, Constants::GOTO_LINE_START, m_contextId, true); @@ -502,6 +520,8 @@ void TextEditorActionHandler::updateActions(UpdateMode um) a->setEnabled(um != ReadOnlyMode); m_formatAction->setEnabled((m_optionalActions & Format) && um != ReadOnlyMode); m_unCommentSelectionAction->setEnabled((m_optionalActions & UnCommentSelection) && um != ReadOnlyMode); + m_followSymbolAction->setEnabled(m_optionalActions & FollowSymbolUnderCursor); + m_jumpToFileAction->setEnabled(m_optionalActions & JumpToFileUnderCursor); m_unfoldAllAction->setEnabled((m_optionalActions & UnCollapseAll)); m_visualizeWhitespaceAction->setChecked(m_currentEditor->displaySettings().m_visualizeWhitespace); @@ -589,6 +609,7 @@ FUNCTION2(copyAction, copy) FUNCTION2(cutAction, cut) FUNCTION2(pasteAction, paste) FUNCTION2(circularPasteAction, circularPaste) +FUNCTION2(switchUtf8bomAction, switchUtf8bom) FUNCTION2(formatAction, format) FUNCTION2(rewrapParagraphAction, rewrapParagraph) FUNCTION2(selectAllAction, selectAll) @@ -625,6 +646,7 @@ FUNCTION(insertLineAbove) FUNCTION(insertLineBelow) FUNCTION(indent) FUNCTION(unindent) +FUNCTION(openLinkUnderCursor) FUNCTION(gotoLineStart) FUNCTION(gotoLineStartWithSelection) diff --git a/src/plugins/texteditor/texteditoractionhandler.h b/src/plugins/texteditor/texteditoractionhandler.h index f94b384267..27f0d485ca 100644 --- a/src/plugins/texteditor/texteditoractionhandler.h +++ b/src/plugins/texteditor/texteditoractionhandler.h @@ -63,7 +63,9 @@ public: None = 0, Format = 1, UnCommentSelection = 2, - UnCollapseAll = 4 + UnCollapseAll = 4, + FollowSymbolUnderCursor = 8, + JumpToFileUnderCursor = 16 }; explicit TextEditorActionHandler(const char *context, uint optionalActions = None); @@ -99,6 +101,7 @@ private slots: void cutAction(); void pasteAction(); void circularPasteAction(); + void switchUtf8bomAction(); void selectAllAction(); void gotoAction(); void printAction(); @@ -140,6 +143,7 @@ private slots: void updateCurrentEditor(Core::IEditor *editor); void indent(); void unindent(); + void openLinkUnderCursor(); void gotoLineStart(); void gotoLineStartWithSelection(); @@ -170,6 +174,7 @@ private: QAction *m_cutAction; QAction *m_pasteAction; QAction *m_circularPasteAction; + QAction *m_switchUtf8bomAction; QAction *m_selectAllAction; QAction *m_gotoAction; QAction *m_printAction; @@ -210,6 +215,8 @@ private: QAction *m_lowerCaseSelectionAction; QAction *m_indentAction; QAction *m_unindentAction; + QAction *m_followSymbolAction; + QAction *m_jumpToFileAction; QList<QAction *> m_modifyingActions; uint m_optionalActions; diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index 86108f84a5..0fc099368b 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -102,8 +102,11 @@ const char TASK_DOWNLOAD_DEFINITIONS[] = "TextEditor.Task.Download"; const char TASK_REGISTER_DEFINITIONS[] = "TextEditor.Task.Register"; const char TASK_OPEN_FILE[] = "TextEditor.Task.OpenFile"; const char CIRCULAR_PASTE[] = "TextEditor.CircularPaste"; +const char SWITCH_UTF8BOM[] = "TextEditor.SwitchUtf8bom"; const char INDENT[] = "TextEditor.Indent"; const char UNINDENT[] = "TextEditor.Unindent"; +const char FOLLOW_SYMBOL_UNDER_CURSOR[] = "TextEditor.FollowSymbolUnderCursor"; +const char JUMP_TO_FILE_UNDER_CURSOR[] = "TextEditor.JumpToFileUnderCursor"; // Text color and style categories const char C_TEXT[] = "Text"; diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index d10a75d65f..001b48948a 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -65,6 +65,8 @@ #include <QtPlugin> #include <QMainWindow> #include <QShortcut> +#include <QDir> +#include <QTemporaryFile> using namespace TextEditor; using namespace TextEditor::Internal; @@ -98,6 +100,55 @@ TextEditorPlugin *TextEditorPlugin::instance() return m_instance; } +static const char wizardCategoryC[] = "U.General"; + +static inline QString wizardDisplayCategory() +{ + return TextEditorPlugin::tr("General"); +} + +// A wizard that quickly creates a scratch buffer +// based on a temporary file without prompting for a path. +class ScratchFileWizard : public Core::IWizard +{ +public: + virtual WizardKind kind() const { return FileWizard; } + virtual QIcon icon() const { return QIcon(); } + virtual QString description() const + { return TextEditorPlugin::tr("Creates a scratch buffer using a temporary file."); } + virtual QString displayName() const + { return TextEditorPlugin::tr("Scratch Buffer"); } + virtual QString id() const + { return QLatin1String("Z.ScratchFile"); } + virtual QString category() const + { return QLatin1String(wizardCategoryC); } + virtual QString displayCategory() const + { return wizardDisplayCategory(); } + virtual QString descriptionImage() const + { return QString(); } + virtual Core::FeatureSet requiredFeatures() const + { return Core::FeatureSet(); } + virtual WizardFlags flags() const + { return Core::IWizard::PlatformIndependent; } + + virtual void runWizard(const QString &path, QWidget *parent, const QString &platform, const QVariantMap &extraValues); +}; + +void ScratchFileWizard::runWizard(const QString &, QWidget *, const QString &, const QVariantMap &extraValues) +{ + Q_UNUSED(extraValues) + QString tempPattern = QDir::tempPath(); + if (!tempPattern.endsWith(QLatin1Char('/'))) + tempPattern += QLatin1Char('/'); + tempPattern += QLatin1String("scratchXXXXXX.txt"); + QTemporaryFile file(tempPattern); + file.setAutoRemove(false); + QTC_ASSERT(file.open(), return; ); + file.close(); + Core::EditorManager *em = Core::EditorManager::instance(); + em->openEditor(file.fileName(), Core::Id(), Core::EditorManager::ModeSwitch); +} + // ExtensionSystem::PluginInterface bool TextEditorPlugin::initialize(const QStringList &arguments, QString *errorMessage) { @@ -110,14 +161,15 @@ bool TextEditorPlugin::initialize(const QStringList &arguments, QString *errorMe wizardParameters.setDescription(tr("Creates a text file. The default file extension is <tt>.txt</tt>. " "You can specify a different extension as part of the filename.")); wizardParameters.setDisplayName(tr("Text File")); - wizardParameters.setCategory(QLatin1String("U.General")); - wizardParameters.setDisplayCategory(tr("General")); + wizardParameters.setCategory(QLatin1String(wizardCategoryC)); + wizardParameters.setDisplayCategory(wizardDisplayCategory()); wizardParameters.setFlags(Core::IWizard::PlatformIndependent); TextFileWizard *wizard = new TextFileWizard(QLatin1String(Constants::C_TEXTEDITOR_MIMETYPE_TEXT), QLatin1String("text$"), wizardParameters); // Add text file wizard addAutoReleasedObject(wizard); + addAutoReleasedObject(new ScratchFileWizard); m_settings = new TextEditorSettings(this); diff --git a/src/plugins/texteditor/texteditorplugin.h b/src/plugins/texteditor/texteditorplugin.h index 1927cf8bb0..d518a67897 100644 --- a/src/plugins/texteditor/texteditorplugin.h +++ b/src/plugins/texteditor/texteditorplugin.h @@ -55,6 +55,7 @@ class BaseTextMarkRegistry; class TextEditorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "TextEditor.json") public: TextEditorPlugin(); diff --git a/src/plugins/todo/Todo.pluginspec.in b/src/plugins/todo/Todo.pluginspec.in index edbb711cd6..ac2f43aba1 100644 --- a/src/plugins/todo/Todo.pluginspec.in +++ b/src/plugins/todo/Todo.pluginspec.in @@ -16,5 +16,6 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/> </dependencyList> </plugin> diff --git a/src/plugins/todo/cpptodoitemsscanner.h b/src/plugins/todo/cpptodoitemsscanner.h index dc5ff1d8da..8ce7fb208a 100644 --- a/src/plugins/todo/cpptodoitemsscanner.h +++ b/src/plugins/todo/cpptodoitemsscanner.h @@ -36,7 +36,7 @@ #include "todoitemsscanner.h" -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> namespace Todo { namespace Internal { diff --git a/src/plugins/todo/todoplugin.h b/src/plugins/todo/todoplugin.h index efac7a2323..537d89d735 100755 --- a/src/plugins/todo/todoplugin.h +++ b/src/plugins/todo/todoplugin.h @@ -49,6 +49,8 @@ class TodoItem; class TodoPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Todo.json") + public: TodoPlugin(); ~TodoPlugin(); diff --git a/src/plugins/updateinfo/updateinfoplugin.h b/src/plugins/updateinfo/updateinfoplugin.h index fdc4c4c0e5..0c8511e6c6 100644 --- a/src/plugins/updateinfo/updateinfoplugin.h +++ b/src/plugins/updateinfo/updateinfoplugin.h @@ -45,6 +45,8 @@ class UpdateInfoPluginPrivate; class UpdateInfoPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "UpdateInfo.json") + public: UpdateInfoPlugin(); virtual ~UpdateInfoPlugin(); diff --git a/src/plugins/valgrind/callgrindtextmark.cpp b/src/plugins/valgrind/callgrindtextmark.cpp index aa524442d9..b6b3d6fd67 100644 --- a/src/plugins/valgrind/callgrindtextmark.cpp +++ b/src/plugins/valgrind/callgrindtextmark.cpp @@ -80,10 +80,10 @@ void CallgrindTextMark::paint(QPainter *painter, const QRect &paintRect) const // decrease font size if paint rect is too small (very unlikely, but may happen) QFont font = painter->font(); - QFontMetrics fm = font; + QFontMetrics fm = QFontMetrics(font); while (fm.boundingRect(text).width() > paintRect.width()) { font.setPointSize(font.pointSize() - 1); - fm = font; + fm = QFontMetrics(font); } painter->setFont(font); diff --git a/src/plugins/valgrind/valgrindplugin.h b/src/plugins/valgrind/valgrindplugin.h index 937ce38d96..9aa9e9c946 100644 --- a/src/plugins/valgrind/valgrindplugin.h +++ b/src/plugins/valgrind/valgrindplugin.h @@ -44,6 +44,7 @@ namespace Internal { class ValgrindPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Valgrind.json") public: ValgrindPlugin() {} diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index cdc84cfd3f..25a0c8aad0 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -53,8 +53,7 @@ public: process(0), channelMode(QProcess::SeparateChannels), finished(false), - startMode(Analyzer::StartLocal), - connParams(Utils::SshConnectionParameters::DefaultProxy) + startMode(Analyzer::StartLocal) { } diff --git a/src/plugins/vcsbase/VcsBase.pluginspec.in b/src/plugins/vcsbase/VcsBase.pluginspec.in index 276ae7e0dd..9d0844c05b 100644 --- a/src/plugins/vcsbase/VcsBase.pluginspec.in +++ b/src/plugins/vcsbase/VcsBase.pluginspec.in @@ -17,5 +17,6 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/> </dependencyList> </plugin> diff --git a/src/plugins/vcsbase/vcsbase.qbs b/src/plugins/vcsbase/vcsbase.qbs index 3db7e2c69b..f7e239c4ff 100644 --- a/src/plugins/vcsbase/vcsbase.qbs +++ b/src/plugins/vcsbase/vcsbase.qbs @@ -11,6 +11,7 @@ QtcPlugin { Depends { name: "Find" } Depends { name: "cpp" } Depends { name: "qt"; submodules: ['gui'] } + Depends { name: "CppTools" } Depends { name: "CPlusPlus" } cpp.includePaths: [ diff --git a/src/plugins/vcsbase/vcsbase_dependencies.pri b/src/plugins/vcsbase/vcsbase_dependencies.pri index 672a4f65cf..3f3f1c378f 100644 --- a/src/plugins/vcsbase/vcsbase_dependencies.pri +++ b/src/plugins/vcsbase/vcsbase_dependencies.pri @@ -2,4 +2,4 @@ include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/texteditor/texteditor.pri) include(../../plugins/projectexplorer/projectexplorer.pri) include(../../plugins/find/find.pri) -include(../../libs/cplusplus/cplusplus.pri) +include(../../plugins/cpptools/cpptools.pri) diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index 07d9df8a9e..d9244961f9 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -952,11 +952,11 @@ void VcsBaseEditorWidget::mouseMoveEvent(QMouseEvent *e) handler->highlightCurrentContents(); overrideCursor = true; cursorShape = Qt::PointingHandCursor; + } else { + setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>()); + overrideCursor = true; + cursorShape = Qt::IBeamCursor; } - } else { - setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>()); - overrideCursor = true; - cursorShape = Qt::IBeamCursor; } TextEditor::BaseTextEditorWidget::mouseMoveEvent(e); diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 38edfae954..41360a5458 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -43,7 +43,7 @@ #include <cplusplus/CoreTypes.h> #include <cplusplus/FullySpecifiedType.h> #include <cplusplus/Literals.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/Symbol.h> #include <cplusplus/Symbols.h> #include <cplusplus/TranslationUnit.h> diff --git a/src/plugins/vcsbase/vcsplugin.h b/src/plugins/vcsbase/vcsplugin.h index 0147ece563..d60f13c2c1 100644 --- a/src/plugins/vcsbase/vcsplugin.h +++ b/src/plugins/vcsbase/vcsplugin.h @@ -51,6 +51,7 @@ class CoreListener; class VcsPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "VcsBase.json") public: VcsPlugin(); diff --git a/src/plugins/welcome/welcome.pro b/src/plugins/welcome/welcome.pro index 482506916b..57296515bf 100644 --- a/src/plugins/welcome/welcome.pro +++ b/src/plugins/welcome/welcome.pro @@ -1,6 +1,11 @@ TEMPLATE = lib TARGET = Welcome -QT += network declarative +QT += network +greaterThan(QT_MAJOR_VERSION, 4) { + QT += quick1 +} else { + QT += declarative +} include(../../qtcreatorplugin.pri) include(welcome_dependencies.pri) diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp index 6fa140612f..50c1739064 100644 --- a/src/plugins/welcome/welcomeplugin.cpp +++ b/src/plugins/welcome/welcomeplugin.cpp @@ -209,10 +209,35 @@ void WelcomeMode::initPlugins() QDeclarativeContext *ctx = m_welcomePage->rootContext(); ctx->setContextProperty(QLatin1String("welcomeMode"), this); - QList<Utils::IWelcomePage*> plugins = PluginManager::instance()->getObjects<Utils::IWelcomePage>(); - qSort(plugins.begin(), plugins.end(), &sortFunction); + QList<Utils::IWelcomePage*> duplicatePlugins = PluginManager::instance()->getObjects<Utils::IWelcomePage>(); + qSort(duplicatePlugins.begin(), duplicatePlugins.end(), &sortFunction); + + QList<Utils::IWelcomePage*> plugins; + QHash<Utils::IWelcomePage::Id, Utils::IWelcomePage*> pluginHash; + + //avoid duplicate ids - choose by priority + foreach (Utils::IWelcomePage* plugin, duplicatePlugins) { + if (pluginHash.contains(plugin->id())) { + Utils::IWelcomePage* pluginOther = pluginHash.value(plugin->id()); + + if (pluginOther->priority() > plugin->priority()) { + plugins.removeAll(pluginOther); + pluginHash.remove(pluginOther->id()); + plugins << plugin; + pluginHash.insert(plugin->id(), plugin); + } + + } else { + plugins << plugin; + pluginHash.insert(plugin->id(), plugin); + } + } + QDeclarativeEngine *engine = m_welcomePage->engine(); + QStringList importPathList = engine->importPathList(); + importPathList << Core::ICore::resourcePath() + QLatin1String("/welcomescreen"); + engine->setImportPathList(importPathList); if (!debug) engine->setOutputWarningsToStandardError(false); engine->setNetworkAccessManagerFactory(new NetworkAccessManagerFactory); @@ -253,7 +278,24 @@ QString WelcomeMode::platform() const void WelcomeMode::welcomePluginAdded(QObject *obj) { + QHash<Utils::IWelcomePage::Id, Utils::IWelcomePage*> pluginHash; + + foreach (QObject *obj, m_pluginList) { + Utils::IWelcomePage *plugin = qobject_cast<Utils::IWelcomePage*>(obj); + pluginHash.insert(plugin->id(), plugin); + } if (Utils::IWelcomePage *plugin = qobject_cast<Utils::IWelcomePage*>(obj)) { + //check for duplicated id + if (pluginHash.contains(plugin->id())) { + Utils::IWelcomePage* pluginOther = pluginHash.value(plugin->id()); + + if (pluginOther->priority() > plugin->priority()) { + m_pluginList.removeAll(pluginOther); + } else { + return; + } + } + int insertPos = 0; foreach (Utils::IWelcomePage* p, PluginManager::instance()->getObjects<Utils::IWelcomePage>()) { if (plugin->priority() < p->priority()) diff --git a/src/plugins/welcome/welcomeplugin.h b/src/plugins/welcome/welcomeplugin.h index 68664e3103..32cfb79e9f 100644 --- a/src/plugins/welcome/welcomeplugin.h +++ b/src/plugins/welcome/welcomeplugin.h @@ -47,6 +47,8 @@ class WelcomeMode; class WelcomePlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Welcome.json") + public: WelcomePlugin(); |