Merge remote-tracking branch 'origin/master' into 4.5

Change-Id: Iaf279b5cf8f4cd417c87eb633f22efbe510ac31d
This commit is contained in:
Eike Ziller
2017-09-26 14:45:12 +02:00
27 changed files with 536 additions and 120 deletions

View File

@@ -29,6 +29,7 @@
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/session.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
namespace Autotest {
@@ -293,11 +294,16 @@ QSet<QString> GTestTreeItem::internalTargets() const
QSet<QString> result;
const auto cppMM = CppTools::CppModelManager::instance();
const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject());
const QString file = filePath();
for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
if (projectPart->buildTargetType != CppTools::ProjectPart::Executable)
continue;
if (projectPart->projectFile == proFile())
if (projectPart->projectFile == proFile()
&& Utils::anyOf(projectPart->files, [&file] (const CppTools::ProjectFile &pf) {
return pf.path == file;
})) {
result.insert(projectPart->buildSystemTarget + '|' + projectPart->projectFile);
if (projectPart->buildTargetType != CppTools::ProjectPart::Executable)
result.unite(TestTreeItem::dependingInternalTargets(cppMM, file));
}
}
return result;
}

View File

@@ -72,11 +72,66 @@ static QString ensureExeEnding(const QString& file)
return Utils::HostOsInfo::withExecutableSuffix(file);
}
void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguration *rc,
TestRunMode runMode)
{
QTC_ASSERT(rc, return);
Project *project = SessionManager::startupProject();
if (!project)
return;
Target *target = project->activeTarget();
if (!target)
return;
if (!Utils::findOr(target->runConfigurations(), nullptr,
[&rc] (RunConfiguration *config) { return rc == config; })) {
return;
}
Runnable runnable = rc->runnable();
if (!runnable.is<StandardRunnable>())
return;
m_runnable = runnable.as<StandardRunnable>();
m_displayName = rc->displayName();
m_project = rc->project();
const QString buildSystemTarget = rc->buildSystemTarget();
BuildTargetInfo targetInfo
= Utils::findOrDefault(target->applicationTargets().list,
[&buildSystemTarget] (const BuildTargetInfo &bti) {
return bti.targetName == buildSystemTarget;
});
if (!targetInfo.targetFilePath.isEmpty())
m_runnable.executable = ensureExeEnding(targetInfo.targetFilePath.toString());
QString buildBase;
if (auto buildConfig = target->activeBuildConfiguration()) {
buildBase = buildConfig->buildDirectory().toString();
const QString projBase = m_project->projectDirectory().toString();
if (m_projectFile.startsWith(projBase))
m_buildDir = QFileInfo(buildBase + m_projectFile.mid(projBase.length())).absolutePath();
}
if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
m_runConfig = new TestRunConfiguration(rc->target(), this);
}
void TestConfiguration::completeTestInformation(TestRunMode runMode)
{
QTC_ASSERT(!m_projectFile.isEmpty(), return);
QTC_ASSERT(!m_buildTargets.isEmpty(), return);
if (m_origRunConfig) {
qCDebug(LOG) << "Using run configuration specified by user or found by first call";
completeTestInformation(m_origRunConfig, runMode);
if (hasExecutable()) {
qCDebug(LOG) << "Completed.\nRunnable:" << m_runnable.executable
<< "\nArgs:" << m_runnable.commandLineArguments
<< "\nWorking directory:" << m_runnable.workingDirectory;
return;
}
qCDebug(LOG) << "Failed to complete - using 'normal' way.";
}
Project *project = SessionManager::startupProject();
if (!project)
return;
@@ -90,7 +145,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
const QSet<QString> buildSystemTargets = m_buildTargets;
qCDebug(LOG) << "BuildSystemTargets\n " << buildSystemTargets;
const BuildTargetInfo targetInfo
BuildTargetInfo targetInfo
= Utils::findOrDefault(target->applicationTargets().list,
[&buildSystemTargets] (const BuildTargetInfo &bti) {
return Utils::anyOf(buildSystemTargets, [&bti](const QString &b) {
@@ -101,12 +156,22 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
&& targWithProjectFile.at(1).startsWith(bti.projectFilePath.toString());
});
});
if (!QTC_GUARD(!targetInfo.targetFilePath.isEmpty())) { // empty if BTI default created
// we might end up with an empty targetFilePath - e.g. when having a library we just link to
// there would be no BuildTargetInfo that could match
if (targetInfo.targetFilePath.isEmpty()) {
qCDebug(LOG) << "BuildTargetInfos";
for (const BuildTargetInfo &bti : target->applicationTargets().list)
qCDebug(LOG) << " " << bti.targetName << bti.projectFilePath << bti.targetFilePath;
const QList<BuildTargetInfo> buildTargets = target->applicationTargets().list;
// if there is only one build target just use it (but be honest that we're guessing)
if (buildTargets.size() == 1) {
targetInfo = buildTargets.first();
m_guessedConfiguration = true;
m_guessedFrom = targetInfo.targetName;
}
}
const QString localExecutable = ensureExeEnding(targetInfo.targetFilePath.toString());
if (localExecutable.isEmpty())
return;
QString buildBase;
if (auto buildConfig = target->activeBuildConfiguration()) {
@@ -153,6 +218,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
return b.startsWith(currentBST);
}))) {
qCDebug(LOG) << " Using this RunConfig.";
m_origRunConfig = runConfig;
m_runnable = stdRunnable;
m_runnable.executable = currentExecutable;
m_displayName = runConfig->displayName();
@@ -167,9 +233,9 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
// or we might have end up using the (wrong) path of a locally installed executable
// for this case try the original executable path of the BuildTargetInfo (the executable
// before installation) to have at least something to execute
if (m_runnable.executable.isEmpty() && !localExecutable.isEmpty())
if (!hasExecutable() && !localExecutable.isEmpty())
m_runnable.executable = localExecutable;
if (m_displayName.isEmpty() && !m_runnable.executable.isEmpty()) {
if (m_displayName.isEmpty() && hasExecutable()) {
qCDebug(LOG) << " Fallback";
// we failed to find a valid runconfiguration - but we've got the executable already
if (auto rc = target->activeRunConfiguration()) {
@@ -255,9 +321,14 @@ void TestConfiguration::setInternalTargets(const QSet<QString> &targets)
m_buildTargets = targets;
}
void TestConfiguration::setOriginalRunConfiguration(RunConfiguration *runConfig)
{
m_origRunConfig = runConfig;
}
QString TestConfiguration::executableFilePath() const
{
if (m_runnable.executable.isEmpty())
if (!hasExecutable())
return QString();
QFileInfo commandFileInfo(m_runnable.executable);
@@ -295,5 +366,10 @@ bool DebuggableTestConfiguration::isDebugRunMode() const
return m_runMode == TestRunMode::Debug || m_runMode == TestRunMode::DebugWithoutDeploy;
}
bool TestConfiguration::hasExecutable() const
{
return !m_runnable.executable.isEmpty();
}
} // namespace Internal
} // namespace Autotest

View File

@@ -56,6 +56,7 @@ public:
virtual ~TestConfiguration();
void completeTestInformation(TestRunMode runMode);
void completeTestInformation(ProjectExplorer::RunConfiguration *rc, TestRunMode runMode);
void setTestCases(const QStringList &testCases);
void setTestCaseCount(int count);
@@ -67,6 +68,7 @@ public:
void setEnvironment(const Utils::Environment &env);
void setProject(ProjectExplorer::Project *project);
void setInternalTargets(const QSet<QString> &targets);
void setOriginalRunConfiguration(ProjectExplorer::RunConfiguration *runConfig);
QStringList testCases() const { return m_testCases; }
int testCaseCount() const { return m_testCaseCount; }
@@ -77,7 +79,10 @@ public:
QString displayName() const { return m_displayName; }
Utils::Environment environment() const { return m_runnable.environment; }
ProjectExplorer::Project *project() const { return m_project.data(); }
QSet<QString> internalTargets() const { return m_buildTargets; }
ProjectExplorer::RunConfiguration *originalRunConfiguration() const { return m_origRunConfig; }
TestRunConfiguration *runConfiguration() const { return m_runConfig; }
bool hasExecutable() const;
bool isGuessed() const { return m_guessedConfiguration; }
QString runConfigDisplayName() const { return m_guessedConfiguration ? m_guessedFrom
: m_displayName; }
@@ -96,8 +101,9 @@ private:
QString m_guessedFrom;
QPointer<ProjectExplorer::Project> m_project;
bool m_guessedConfiguration = false;
TestRunConfiguration *m_runConfig = 0;
TestRunConfiguration *m_runConfig = nullptr;
QSet<QString> m_buildTargets;
ProjectExplorer::RunConfiguration *m_origRunConfig = nullptr;
ProjectExplorer::StandardRunnable m_runnable;
};

View File

@@ -32,6 +32,7 @@
#include "testsettings.h"
#include "testoutputreader.h"
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
@@ -39,19 +40,28 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorersettings.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <utils/outputformat.h>
#include <utils/runextensions.h>
#include <utils/hostosinfo.h>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QFuture>
#include <QFutureInterface>
#include <QLabel>
#include <QPushButton>
#include <QTime>
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
#include <utils/algorithm.h>
namespace Autotest {
namespace Internal {
@@ -284,8 +294,57 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
}
}
static QString firstTestCaseTarget(const TestConfiguration *config)
{
const QSet<QString> &internalTargets = config->internalTargets();
int size = internalTargets.size();
if (size)
return (*internalTargets.begin()).split('|').first();
return TestRunner::tr("<unknown>");
}
static bool askUserForRunConfiguration(TestConfiguration *config)
{
using namespace ProjectExplorer;
RunConfigurationSelectionDialog dialog(firstTestCaseTarget(config),
Core::ICore::dialogParent());
if (dialog.exec() == QDialog::Accepted) {
const QString dName = dialog.displayName();
if (dName.isEmpty())
return false;
// run configuration has been selected - fill config based on this one..
const QString exe = dialog.executable();
// paranoia... can the current startup project have changed meanwhile?
if (auto project = SessionManager::startupProject()) {
if (auto target = project->activeTarget()) {
RunConfiguration *runConfig
= Utils::findOr(target->runConfigurations(), nullptr,
[&dName, &exe] (const RunConfiguration *rc) {
if (rc->displayName() != dName)
return false;
if (!rc->runnable().is<StandardRunnable>())
return false;
StandardRunnable runnable = rc->runnable().as<StandardRunnable>();
return runnable.executable == exe;
});
if (runConfig) {
config->setOriginalRunConfiguration(runConfig);
return true;
}
}
}
}
return false;
}
void TestRunner::runTests()
{
for (TestConfiguration *config : m_selectedTests) {
config->completeTestInformation(TestRunMode::Run);
if (!config->hasExecutable())
if (askUserForRunConfiguration(config))
config->completeTestInformation(config->originalRunConfiguration(), TestRunMode::Run);
}
QFuture<TestResultPtr> future = Utils::runAsync(&performTestRun, m_selectedTests,
*AutotestPlugin::instance()->settings());
m_futureWatcher.setFuture(future);
@@ -327,6 +386,11 @@ void TestRunner::debugTests()
TestConfiguration *config = m_selectedTests.first();
config->completeTestInformation(TestRunMode::Debug);
if (!config->hasExecutable()) {
if (askUserForRunConfiguration(config))
config->completeTestInformation(config->originalRunConfiguration(), TestRunMode::Debug);
}
if (!config->runConfiguration()) {
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
TestRunner::tr("Failed to get run configuration."))));
@@ -453,5 +517,90 @@ void TestRunner::onFinished()
emit testRunFinished();
}
/*************************************************************************************************/
RunConfigurationSelectionDialog::RunConfigurationSelectionDialog(const QString &testsInfo,
QWidget *parent)
: QDialog(parent)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setWindowTitle(tr("Select Run Configuration"));
m_details = new QLabel(tr("Could not determine which run configuration to choose for running"
" tests (%1)").arg(testsInfo), this);
m_rcCombo = new QComboBox(this);
m_executable = new QLabel(this);
m_arguments = new QLabel(this);
m_workingDir = new QLabel(this);
m_buttonBox = new QDialogButtonBox(this);
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
auto line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
auto formLayout = new QFormLayout;
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
formLayout->addRow(m_details);
formLayout->addRow(tr("Run Configuration:"), m_rcCombo);
formLayout->addRow(line);
formLayout->addRow(tr("Executable:"), m_executable);
formLayout->addRow(tr("Arguments:"), m_arguments);
formLayout->addRow(tr("Working Directory:"), m_workingDir);
// TODO Device support
auto vboxLayout = new QVBoxLayout(this);
vboxLayout->addLayout(formLayout);
vboxLayout->addStretch();
vboxLayout->addWidget(line);
vboxLayout->addWidget(m_buttonBox);
connect(m_rcCombo, &QComboBox::currentTextChanged,
this, &RunConfigurationSelectionDialog::updateLabels);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
populate();
}
QString RunConfigurationSelectionDialog::displayName() const
{
return m_rcCombo ? m_rcCombo->currentText() : QString();
}
QString RunConfigurationSelectionDialog::executable() const
{
return m_executable ? m_executable->text() : QString();
}
void RunConfigurationSelectionDialog::populate()
{
m_rcCombo->addItem(QString(), QStringList({QString(), QString(), QString()})); // empty default
if (auto project = ProjectExplorer::SessionManager::startupProject()) {
if (auto target = project->activeTarget()) {
for (ProjectExplorer::RunConfiguration *rc : target->runConfigurations()) {
if (rc->runnable().is<ProjectExplorer::StandardRunnable>()) {
auto runnable = rc->runnable().as<ProjectExplorer::StandardRunnable>();
const QStringList rcDetails = { runnable.executable,
runnable.commandLineArguments,
runnable.workingDirectory };
m_rcCombo->addItem(rc->displayName(), rcDetails);
}
}
}
}
}
void RunConfigurationSelectionDialog::updateLabels()
{
int i = m_rcCombo->currentIndex();
const QStringList values = m_rcCombo->itemData(i).toStringList();
QTC_ASSERT(values.size() == 3, return);
m_executable->setText(values.at(0));
m_arguments->setText(values.at(1));
m_workingDir->setText(values.at(2));
}
} // namespace Internal
} // namespace Autotest

View File

@@ -28,10 +28,17 @@
#include "testconfiguration.h"
#include "testresult.h"
#include <QDialog>
#include <QFutureWatcher>
#include <QObject>
#include <QProcess>
QT_BEGIN_NAMESPACE
class QComboBox;
class QDialogButtonBox;
class QLabel;
QT_END_NAMESPACE
namespace ProjectExplorer {
class Project;
}
@@ -77,5 +84,23 @@ private:
QMetaObject::Connection m_buildConnect;
};
class RunConfigurationSelectionDialog : public QDialog
{
Q_OBJECT
public:
explicit RunConfigurationSelectionDialog(const QString &testsInfo, QWidget *parent = nullptr);
QString displayName() const;
QString executable() const;
private:
void populate();
void updateLabels();
QLabel *m_details;
QLabel *m_executable;
QLabel *m_arguments;
QLabel *m_workingDir;
QComboBox *m_rcCombo;
QDialogButtonBox *m_buttonBox;
};
} // namespace Internal
} // namespace Autotest

View File

@@ -30,6 +30,7 @@
#include <cplusplus/Icons.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsreuse.h>
#include <texteditor/texteditor.h>
#include <QIcon>
@@ -286,12 +287,12 @@ bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const
QSet<QString> TestTreeItem::internalTargets() const
{
auto cppMM = CppTools::CppModelManager::instance();
const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(filePath());
const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(m_filePath);
QSet<QString> targets;
for (const CppTools::ProjectPart::Ptr part : projectParts) {
if (part->buildTargetType != CppTools::ProjectPart::Executable)
continue;
targets.insert(part->buildSystemTarget + '|' + part->projectFile);
if (part->buildTargetType != CppTools::ProjectPart::Executable)
targets.unite(TestTreeItem::dependingInternalTargets(cppMM, m_filePath));
}
return targets;
}
@@ -359,5 +360,28 @@ TestTreeItem *TestTreeItem::findChildBy(CompareFunction compare) const
return nullptr;
}
/*
* try to find build system target that depends on the given file - if the file is no header
* try to find the corresponding header and use this instead to find the respective target
*/
QSet<QString> TestTreeItem::dependingInternalTargets(CppTools::CppModelManager *cppMM,
const QString &file)
{
QSet<QString> result;
QTC_ASSERT(cppMM, return result);
const CPlusPlus::Snapshot snapshot = cppMM->snapshot();
QTC_ASSERT(snapshot.contains(file), return result);
bool wasHeader;
const QString correspondingFile
= CppTools::correspondingHeaderOrSource(file, &wasHeader, CppTools::CacheUsage::ReadOnly);
const Utils::FileNameList dependingFiles = snapshot.filesDependingOn(
wasHeader ? file : correspondingFile);
for (const Utils::FileName &fn : dependingFiles) {
for (const CppTools::ProjectPart::Ptr part : cppMM->projectPart(fn))
result.insert(part->buildSystemTarget + '|' + part->projectFile);
}
return result;
}
} // namespace Internal
} // namespace Autotest

View File

@@ -28,6 +28,7 @@
#include <utils/treemodel.h>
#include <QList>
#include <QSet>
#include <QString>
#include <QMetaType>
@@ -40,6 +41,8 @@ namespace {
};
}
namespace CppTools { class CppModelManager; }
namespace Autotest {
namespace Internal {
@@ -114,6 +117,8 @@ public:
protected:
typedef std::function<bool(const TestTreeItem *)> CompareFunction;
TestTreeItem *findChildBy(CompareFunction compare) const;
static QSet<QString> dependingInternalTargets(CppTools::CppModelManager *cppMM,
const QString &file);
private:
void revalidateCheckState();

View File

@@ -1365,7 +1365,10 @@ FileName DocumentManager::projectsDirectory()
void DocumentManager::setProjectsDirectory(const FileName &directory)
{
if (d->m_projectsDirectory != directory) {
d->m_projectsDirectory = directory;
emit m_instance->projectsDirectoryChanged(d->m_projectsDirectory);
}
}
/*!

View File

@@ -146,6 +146,7 @@ signals:
void allDocumentsRenamed(const QString &from, const QString &to);
/// emitted if one document changed its name e.g. due to save as
void documentRenamed(Core::IDocument *document, const QString &from, const QString &to);
void projectsDirectoryChanged(const Utils::FileName &directory);
protected:
bool eventFilter(QObject *obj, QEvent *e);

View File

@@ -357,7 +357,8 @@ static int commonFilePathLength(const QString &s1, const QString &s2)
static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
const QStringList &candidateFileNames,
const ProjectExplorer::Project *project)
const ProjectExplorer::Project *project,
CacheUsage cacheUsage)
{
QString bestFileName;
int compareValue = 0;
@@ -376,8 +377,10 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
if (!bestFileName.isEmpty()) {
const QFileInfo candidateFi(bestFileName);
QTC_ASSERT(candidateFi.isFile(), return QString());
if (cacheUsage == CacheUsage::ReadWrite) {
m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath();
m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath();
}
return candidateFi.absoluteFilePath();
}
@@ -386,7 +389,7 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
} // namespace Internal
QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, CacheUsage cacheUsage)
{
using namespace Internal;
@@ -437,9 +440,11 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath);
const QFileInfo candidateFi(normalized);
if (candidateFi.isFile()) {
if (cacheUsage == CacheUsage::ReadWrite) {
m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
if (!isHeader || !baseName.endsWith(privateHeaderSuffix))
m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
}
return candidateFi.absoluteFilePath();
}
}
@@ -449,7 +454,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject();
if (currentProject) {
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
currentProject);
currentProject, cacheUsage);
if (!path.isEmpty())
return path;
@@ -462,7 +467,8 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
if (project == currentProject)
continue; // We have already checked the current project.
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames, project);
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
project, cacheUsage);
if (!path.isEmpty())
return path;
}

View File

@@ -68,7 +68,10 @@ bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,
const CPlusPlus::Macro CPPTOOLS_EXPORT *findCanonicalMacro(const QTextCursor &cursor,
CPlusPlus::Document::Ptr document);
QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0);
enum class CacheUsage { ReadWrite, ReadOnly };
QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0,
CacheUsage cacheUsage = CacheUsage::ReadWrite);
void CPPTOOLS_EXPORT switchHeaderSource();
class CppCodeModelSettings;

View File

@@ -27,6 +27,7 @@
#include "projectexplorer.h"
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/fileiconprovider.h>
@@ -53,12 +54,17 @@
#include <QDir>
#include <QFileInfo>
const int PATH_ROLE = Qt::UserRole;
const int ID_ROLE = Qt::UserRole + 1;
const char PROJECTSDIRECTORYROOT_ID[] = "A.Projects";
namespace ProjectExplorer {
namespace Internal {
static FolderNavigationWidgetFactory *m_instance = nullptr;
QVector<FolderNavigationWidgetFactory::DirectoryEntry>
QVector<FolderNavigationWidgetFactory::RootDirectory>
FolderNavigationWidgetFactory::m_rootDirectories;
// FolderNavigationModel: Shows path as tooltip.
@@ -164,21 +170,29 @@ void FolderNavigationWidget::toggleAutoSynchronization()
setAutoSynchronization(!m_autoSync);
}
void FolderNavigationWidget::addRootDirectory(const QString &displayName,
const Utils::FileName &directory)
void FolderNavigationWidget::insertRootDirectory(
const FolderNavigationWidgetFactory::RootDirectory &directory)
{
m_rootSelector->addItem(displayName, qVariantFromValue(directory));
m_rootSelector->setItemData(m_rootSelector->count() - 1,
directory.toUserOutput(),
Qt::ToolTipRole);
// insert sorted
int index = 0;
while (index < m_rootSelector->count()
&& m_rootSelector->itemData(index, ID_ROLE).toString() < directory.id)
++index;
if (m_rootSelector->itemData(index, ID_ROLE).toString() != directory.id)
m_rootSelector->insertItem(index, directory.displayName);
m_rootSelector->setItemData(index, qVariantFromValue(directory.path), PATH_ROLE);
m_rootSelector->setItemData(index, directory.id, ID_ROLE);
m_rootSelector->setItemData(index, directory.path.toUserOutput(), Qt::ToolTipRole);
if (m_rootSelector->currentIndex() == index)
setRootDirectory(directory.path);
if (m_autoSync) // we might find a better root for current selection now
setCurrentEditor(Core::EditorManager::currentEditor());
}
void FolderNavigationWidget::removeRootDirectory(const Utils::FileName &directory)
void FolderNavigationWidget::removeRootDirectory(const QString &id)
{
for (int i = 0; i < m_rootSelector->count(); ++i) {
if (m_rootSelector->itemData(i).value<Utils::FileName>() == directory) {
if (m_rootSelector->itemData(i, ID_ROLE).toString() == id) {
m_rootSelector->removeItem(i);
break;
}
@@ -343,18 +357,27 @@ FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
setPriority(400);
setId("File System");
setActivationSequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Y") : tr("Alt+Y")));
addRootDirectory(FolderNavigationWidget::tr("Computer"), Utils::FileName());
insertRootDirectory(
{QLatin1String("A.Computer"), FolderNavigationWidget::tr("Computer"), Utils::FileName()});
insertRootDirectory({QLatin1String("A.Home"),
FolderNavigationWidget::tr("Home"),
Utils::FileName::fromString(QDir::homePath())});
updateProjectsDirectoryRoot();
connect(Core::DocumentManager::instance(),
&Core::DocumentManager::projectsDirectoryChanged,
this,
&FolderNavigationWidgetFactory::updateProjectsDirectoryRoot);
}
Core::NavigationView FolderNavigationWidgetFactory::createWidget()
{
auto fnw = new FolderNavigationWidget;
for (const DirectoryEntry &root : m_rootDirectories)
fnw->addRootDirectory(root.first, root.second);
for (const RootDirectory &root : m_rootDirectories)
fnw->insertRootDirectory(root);
connect(this,
&FolderNavigationWidgetFactory::rootDirectoryAdded,
fnw,
&FolderNavigationWidget::addRootDirectory);
&FolderNavigationWidget::insertRootDirectory);
connect(this,
&FolderNavigationWidgetFactory::rootDirectoryRemoved,
fnw,
@@ -392,21 +415,33 @@ void FolderNavigationWidgetFactory::restoreSettings(QSettings *settings, int pos
fnw->setAutoSynchronization(settings->value(baseKey + QLatin1String(".SyncWithEditor"), true).toBool());
}
void FolderNavigationWidgetFactory::addRootDirectory(const QString &displayName,
const Utils::FileName &directory)
void FolderNavigationWidgetFactory::insertRootDirectory(const RootDirectory &directory)
{
m_rootDirectories.append(DirectoryEntry(displayName, directory));
emit m_instance->rootDirectoryAdded(displayName, directory);
const int index = rootIndex(directory.id);
if (index < 0)
m_rootDirectories.append(directory);
emit m_instance->rootDirectoryAdded(directory);
}
void FolderNavigationWidgetFactory::removeRootDirectory(const Utils::FileName &directory)
void FolderNavigationWidgetFactory::removeRootDirectory(const QString &id)
{
const int index = Utils::indexOf(m_rootDirectories, [directory](const DirectoryEntry &entry) {
return entry.second == directory;
});
const int index = rootIndex(id);
QTC_ASSERT(index >= 0, return );
m_rootDirectories.removeAt(index);
emit m_instance->rootDirectoryRemoved(directory);
emit m_instance->rootDirectoryRemoved(id);
}
int FolderNavigationWidgetFactory::rootIndex(const QString &id)
{
return Utils::indexOf(m_rootDirectories,
[id](const RootDirectory &entry) { return entry.id == id; });
}
void FolderNavigationWidgetFactory::updateProjectsDirectoryRoot()
{
insertRootDirectory({QLatin1String(PROJECTSDIRECTORYROOT_ID),
FolderNavigationWidget::tr("Projects"),
Core::DocumentManager::projectsDirectory()});
}
} // namespace Internal

View File

@@ -26,13 +26,13 @@
#pragma once
#include <coreplugin/inavigationwidgetfactory.h>
#include <utils/fileutils.h>
#include <QWidget>
namespace Core { class IEditor; }
namespace Utils {
class FileName;
class NavigationTreeView;
}
@@ -46,6 +46,36 @@ QT_END_NAMESPACE
namespace ProjectExplorer {
namespace Internal {
class FolderNavigationWidgetFactory : public Core::INavigationWidgetFactory
{
Q_OBJECT
public:
struct RootDirectory {
QString id;
QString displayName;
Utils::FileName path;
};
FolderNavigationWidgetFactory();
Core::NavigationView createWidget() override;
void saveSettings(QSettings *settings, int position, QWidget *widget) override;
void restoreSettings(QSettings *settings, int position, QWidget *widget) override;
static void insertRootDirectory(const RootDirectory &directory);
static void removeRootDirectory(const QString &id);
signals:
void rootDirectoryAdded(const RootDirectory &directory);
void rootDirectoryRemoved(const QString &id);
private:
static int rootIndex(const QString &id);
void updateProjectsDirectoryRoot();
static QVector<RootDirectory> m_rootDirectories;
};
class FolderNavigationWidget : public QWidget
{
Q_OBJECT
@@ -61,8 +91,8 @@ public:
void setAutoSynchronization(bool sync);
void toggleAutoSynchronization();
void addRootDirectory(const QString &displayName, const Utils::FileName &directory);
void removeRootDirectory(const Utils::FileName &directory);
void insertRootDirectory(const FolderNavigationWidgetFactory::RootDirectory &directory);
void removeRootDirectory(const QString &id);
protected:
void contextMenuEvent(QContextMenuEvent *ev) override;
@@ -86,28 +116,5 @@ private:
friend class FolderNavigationWidgetFactory;
};
class FolderNavigationWidgetFactory : public Core::INavigationWidgetFactory
{
Q_OBJECT
public:
FolderNavigationWidgetFactory();
Core::NavigationView createWidget() override;
void saveSettings(QSettings *settings, int position, QWidget *widget) override;
void restoreSettings(QSettings *settings, int position, QWidget *widget) override;
static void addRootDirectory(const QString &displayName, const Utils::FileName &directory);
static void removeRootDirectory(const Utils::FileName &directory);
signals:
void rootDirectoryAdded(const QString &displayName, const Utils::FileName &directory);
void rootDirectoryRemoved(const Utils::FileName &directory);
private:
using DirectoryEntry = std::pair<QString, Utils::FileName>;
static QVector<DirectoryEntry> m_rootDirectories;
};
} // namespace Internal
} // namespace ProjectExplorer

View File

@@ -118,6 +118,11 @@ private:
static SessionManager *m_instance = nullptr;
static SessionManagerPrivate *d = nullptr;
static QString projectFolderId(Project *pro)
{
return "P." + pro->displayName() + "." + pro->projectFilePath().toString();
}
SessionManager::SessionManager(QObject *parent) : QObject(parent)
{
m_instance = this;
@@ -386,10 +391,14 @@ void SessionManager::addProject(Project *pro)
m_instance, [pro]() { m_instance->projectDisplayNameChanged(pro); });
emit m_instance->projectAdded(pro);
FolderNavigationWidgetFactory::addRootDirectory(pro->displayName(),
pro->projectFilePath().parentDir());
const auto updateFolderNavigation = [pro] {
FolderNavigationWidgetFactory::insertRootDirectory(
{projectFolderId(pro), pro->displayName(), pro->projectFilePath().parentDir()});
};
updateFolderNavigation();
configureEditors(pro);
connect(pro, &Project::fileListChanged, [pro](){ configureEditors(pro); });
connect(pro, &Project::displayNameChanged, pro, updateFolderNavigation);
}
void SessionManager::removeProject(Project *project)
@@ -742,7 +751,7 @@ void SessionManager::removeProjects(QList<Project *> remove)
m_instance, &SessionManager::clearProjectFileCache);
d->m_projectFileCache.remove(pro);
emit m_instance->projectRemoved(pro);
FolderNavigationWidgetFactory::removeRootDirectory(pro->projectFilePath().parentDir());
FolderNavigationWidgetFactory::removeRootDirectory(projectFolderId(pro));
delete pro;
}

View File

@@ -43,6 +43,8 @@ public:
virtual void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
virtual void setFilter(bool showObjects) = 0;
virtual void resetModel() = 0;
};
} //QmlDesigner

View File

@@ -246,6 +246,16 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const
| Qt::ItemNeverHasChildren;
}
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter)
{
if (!filter)
return property.toModelNodeList();
return Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
return QmlItemNode::isValidQmlItemNode(arg);
});
}
QModelIndex NavigatorTreeModel::index(int row, int column,
const QModelIndex &parent) const
{
@@ -262,7 +272,7 @@ QModelIndex NavigatorTreeModel::index(int row, int column,
ModelNode modelNode;
if (parentModelNode.defaultNodeListProperty().isValid())
modelNode = parentModelNode.defaultNodeListProperty().at(row);
modelNode = filteredList(parentModelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).at(row);
if (!modelNode.isValid())
return QModelIndex();
@@ -293,7 +303,7 @@ QModelIndex NavigatorTreeModel::parent(const QModelIndex &index) const
int row = 0;
if (!parentModelNode.isRootNode() && parentModelNode.parentProperty().isNodeListProperty())
row = parentModelNode.parentProperty().toNodeListProperty().indexOf(parentModelNode);
row = filteredList(parentModelNode.parentProperty().toNodeListProperty(), m_showOnlyVisibleItems).indexOf(parentModelNode);
return createIndexFromModelNode(row, 0, parentModelNode);
}
@@ -313,7 +323,7 @@ int NavigatorTreeModel::rowCount(const QModelIndex &parent) const
int rows = 0;
if (modelNode.defaultNodeListProperty().isValid())
rows = modelNode.defaultNodeListProperty().count();
rows = filteredList(modelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).count();
return rows;
}
@@ -628,4 +638,17 @@ void NavigatorTreeModel::notifyModelNodesMoved(const QList<ModelNode> &modelNode
layoutChanged(indexes);
}
void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems)
{
m_showOnlyVisibleItems = showOnlyVisibleItems;
resetModel();
}
void NavigatorTreeModel::resetModel()
{
beginResetModel();
m_nodeIndexHash.clear();
endResetModel();
}
} // QmlDesigner

View File

@@ -87,6 +87,8 @@ public:
void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
void setFilter(bool showOnlyVisibleItems) override;
void resetModel() override;
private:
void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes, int targetIndex);
@@ -97,6 +99,7 @@ private:
QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;
bool m_showOnlyVisibleItems = true;
};
} // namespace QmlDesigner

View File

@@ -34,6 +34,7 @@
#include <bindingproperty.h>
#include <designmodecontext.h>
#include <designersettings.h>
#include <nodeproperty.h>
#include <nodelistproperty.h>
#include <variantproperty.h>
@@ -88,6 +89,7 @@ NavigatorView::NavigatorView(QObject* parent) :
connect(m_widget.data(), &NavigatorWidget::rightButtonClicked, this, &NavigatorView::rightButtonClicked);
connect(m_widget.data(), &NavigatorWidget::downButtonClicked, this, &NavigatorView::downButtonClicked);
connect(m_widget.data(), &NavigatorWidget::upButtonClicked, this, &NavigatorView::upButtonClicked);
connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled);
#ifndef QMLDESIGNER_TEST
NameItemDelegate *idDelegate = new NameItemDelegate(this);
@@ -145,6 +147,9 @@ void NavigatorView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
m_currentModelInterface->setFilter(
DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool());
QTreeView *treeView = treeWidget();
treeView->expandAll();
@@ -400,6 +405,13 @@ void NavigatorView::downButtonClicked()
blockSelectionChangedSignal(blocked);
}
void NavigatorView::filterToggled(bool flag)
{
m_currentModelInterface->setFilter(flag);
treeWidget()->expandAll();
DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, flag);
}
void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
{
if (m_blockSelectionChangedSignal)

View File

@@ -99,6 +99,7 @@ private:
void rightButtonClicked();
void upButtonClicked();
void downButtonClicked();
void filterToggled(bool);
protected: //functions
QTreeView *treeWidget() const;

View File

@@ -27,14 +27,17 @@
#include "navigatorview.h"
#include "qmldesignerconstants.h"
#include "qmldesignericons.h"
#include <designersettings.h>
#include <theme.h>
#include <QBoxLayout>
#include <QToolButton>
#include <QAbstractItemModel>
#include <QMenu>
#include <QHeaderView>
#include <QtDebug>
#include <utils/fileutils.h>
#include <utils/utilsicons.h>
namespace QmlDesigner {
@@ -80,29 +83,49 @@ QList<QToolButton *> NavigatorWidget::createToolBarWidgets()
{
QList<QToolButton *> buttons;
buttons.append(new QToolButton());
buttons.last()->setIcon(Icons::ARROW_LEFT.icon());
buttons.last()->setToolTip(tr("Become last sibling of parent (CTRL + Left)."));
buttons.last()->setShortcut(QKeySequence(Qt::Key_Left | Qt::CTRL));
connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::leftButtonClicked);
buttons.append(new QToolButton());
buttons.last()->setIcon(Icons::ARROW_RIGHT.icon());
buttons.last()->setToolTip(tr("Become child of last sibling (CTRL + Right)."));
buttons.last()->setShortcut(QKeySequence(Qt::Key_Right | Qt::CTRL));
connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::rightButtonClicked);
auto button = new QToolButton();
button->setIcon(Icons::ARROW_LEFT.icon());
button->setToolTip(tr("Become last sibling of parent (CTRL + Left)."));
button->setShortcut(QKeySequence(Qt::Key_Left | Qt::CTRL));
connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::leftButtonClicked);
buttons.append(button);
buttons.append(new QToolButton());
buttons.last()->setIcon(Icons::ARROW_DOWN.icon());
buttons.last()->setToolTip(tr("Move down (CTRL + Down)."));
buttons.last()->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL));
connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::downButtonClicked);
button = new QToolButton();
button->setIcon(Icons::ARROW_RIGHT.icon());
button->setToolTip(tr("Become child of last sibling (CTRL + Right)."));
button->setShortcut(QKeySequence(Qt::Key_Right | Qt::CTRL));
connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::rightButtonClicked);
buttons.append(button);
buttons.append(new QToolButton());
buttons.last()->setIcon(Icons::ARROW_UP.icon());
buttons.last()->setToolTip(tr("Move up (CTRL + Up)."));
buttons.last()->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL));
connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::upButtonClicked);
button = new QToolButton();
button->setIcon(Icons::ARROW_DOWN.icon());
button->setToolTip(tr("Move down (CTRL + Down)."));
button->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL));
connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::downButtonClicked);
buttons.append(button);
button = new QToolButton();
button->setIcon(Icons::ARROW_UP.icon());
button->setToolTip(tr("Move up (CTRL + Up)."));
button->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL));
connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::upButtonClicked);
buttons.append(button);
auto filter = new QToolButton;
filter->setIcon(Utils::Icons::FILTER.icon());
filter->setToolTip(tr("Filter Tree"));
filter->setPopupMode(QToolButton::InstantPopup);
filter->setProperty("noArrow", true);
auto filterMenu = new QMenu(filter);
auto objectAction = new QAction(tr("Show only visible itmes."));
objectAction->setCheckable(true);
objectAction->setChecked(
DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool());
connect(objectAction, &QAction::toggled, this, &NavigatorWidget::filterToggled);
filterMenu->addAction(objectAction);
filter->setMenu(filterMenu);
buttons.append(filter);
return buttons;
}

View File

@@ -53,6 +53,7 @@ signals:
void rightButtonClicked();
void upButtonClicked();
void downButtonClicked();
void filterToggled(bool);
private: // functions
NavigatorView *navigatorView() const;

View File

@@ -74,6 +74,8 @@ void DesignerSettings::fromSettings(QSettings *settings)
restoreValue(settings, DesignerSettingsKey::FORWARD_PUPPET_OUTPUT, QString());
restoreValue(settings, DesignerSettingsKey::REFORMAT_UI_QML_FILES, true);
restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false);
restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, false);
restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true);
settings->endGroup();
settings->endGroup();

View File

@@ -60,6 +60,7 @@ const char PUPPET_KILL_TIMEOUT[] = "PuppetKillTimeout";
const char DEBUG_PUPPET[] = "DebugPuppet";
const char FORWARD_PUPPET_OUTPUT[] = "ForwardPuppetOutput";
const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded";
const char NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS[] = "NavigatorShowOnlyVisibleItems";
const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */
const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */
}

View File

@@ -93,8 +93,8 @@ void LocalQmlProfilerRunnerTest::testRunner()
runControl->initiateStart();
QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 20000);
QTRY_VERIFY_WITH_TIMEOUT(!started, 20000);
QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 30000);
QTRY_VERIFY_WITH_TIMEOUT(!started, 30000);
QCOMPARE(stopCount, 1);
QCOMPARE(runCount, 0);
@@ -114,8 +114,8 @@ void LocalQmlProfilerRunnerTest::testRunner()
connectRunner();
runControl->initiateStart();
QTRY_VERIFY_WITH_TIMEOUT(running, 20000);
QTRY_VERIFY_WITH_TIMEOUT(!running, 20000);
QTRY_VERIFY_WITH_TIMEOUT(running, 30000);
QTRY_VERIFY_WITH_TIMEOUT(!running, 30000);
QCOMPARE(startCount, 2);
QCOMPARE(stopCount, 2);
QCOMPARE(runCount, 1);
@@ -134,9 +134,9 @@ void LocalQmlProfilerRunnerTest::testRunner()
connectRunner();
runControl->initiateStart();
QTRY_VERIFY_WITH_TIMEOUT(running, 20000);
QTRY_VERIFY_WITH_TIMEOUT(running, 30000);
runControl->initiateStop();
QTRY_VERIFY_WITH_TIMEOUT(!running, 20000);
QTRY_VERIFY_WITH_TIMEOUT(!running, 30000);
QCOMPARE(startCount, 3);
QCOMPARE(stopCount, 3);
QCOMPARE(runCount, 2);

View File

@@ -35,7 +35,9 @@ def main():
analyzerTargets = Targets.desktopTargetClasses()
checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=analyzerTargets)
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
if placeCursorToLine(editor, "MouseArea.*", True):
if placeCursorToLine(editor, "}"):
type(editor, '<Left>')
type(editor, '<Return>')
type(editor, '<Up>')
type(editor, '<Return>')
typeLines(editor, ['Timer {',

View File

@@ -3,18 +3,7 @@
"main.qml:15" "Handling Signal" "2" "onTriggered: { runCount += 1; var i; for (i = 1; i < 2500; ++i) { var j = i * i; console.log(j); } }"
"main.qml:15" "JavaScript" "2" "onTriggered"
"main.qml:4" "Creating" "2" "QtQuick.Window/Window"
"main.qml:33" "Creating" "2" "QtQuick/TextEdit"
"main.qml:1" "Compiling" "1" "main.qml"
"main.qml:10" "Creating" "2" "QtQuick/Timer"
"main.qml:37" "Binding" "1" "anchors.top: parent.top"
"main.qml:40" "Creating" "2" "QtQuick/Rectangle"
"main.qml:37" "JavaScript" "1" "expression for top"
"main.qml:14" "Binding" "3" "running: runCount < 2"
"main.qml:26" "Creating" "2" "QtQuick/MouseArea"
"main.qml:38" "Binding" "1" "anchors.horizontalCenter: parent.horizontalCenter"
"main.qml:38" "JavaScript" "1" "expression for horizontalCenter"
"main.qml:41" "Binding" "1" "anchors.fill: parent"
"main.qml:27" "Binding" "1" "anchors.fill: parent"
"main.qml:14" "JavaScript" "3" "expression for running"
"main.qml:41" "JavaScript" "1" "expression for fill"
"main.qml:27" "JavaScript" "1" "expression for fill"
1 0 1 6 11
3 main.qml:15 Handling Signal 2 onTriggered: { runCount += 1; var i; for (i = 1; i < 2500; ++i) { var j = i * i; console.log(j); } }
4 main.qml:15 JavaScript 2 onTriggered
5 main.qml:4 Creating 2 QtQuick.Window/Window
main.qml:33 Creating 2 QtQuick/TextEdit
6 main.qml:1 Compiling 1 main.qml
7 main.qml:10 Creating 2 QtQuick/Timer
main.qml:37 Binding 1 anchors.top: parent.top
main.qml:40 Creating 2 QtQuick/Rectangle
main.qml:37 JavaScript 1 expression for top
8 main.qml:14 Binding 3 running: runCount < 2
main.qml:26 Creating 2 QtQuick/MouseArea
main.qml:38 Binding 1 anchors.horizontalCenter: parent.horizontalCenter
main.qml:38 JavaScript 1 expression for horizontalCenter
main.qml:41 Binding 1 anchors.fill: parent
main.qml:27 Binding 1 anchors.fill: parent
9 main.qml:14 JavaScript 3 expression for running
main.qml:41 JavaScript 1 expression for fill
main.qml:27 JavaScript 1 expression for fill

View File

@@ -35,7 +35,9 @@ def main():
workingDir = tempDir()
checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=targets)
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
if placeCursorToLine(editor, "MouseArea.*", True):
if placeCursorToLine(editor, "}"):
type(editor, '<Left>')
type(editor, '<Return>')
type(editor, '<Up>')
type(editor, '<Return>')
typeLines(editor, ['Timer {',
@@ -50,7 +52,7 @@ def main():
test.log("Setting breakpoints")
result = setBreakpointsForCurrentProject(filesAndLines)
if result:
expectedBreakpointsOrder = [{os.path.join(workingDir, projectName, "main.cpp"):8},
expectedBreakpointsOrder = [{os.path.join(workingDir, projectName, "main.cpp"):10},
{os.path.join(workingDir, projectName, "main.qml"):13}]
availableConfigs = iterateBuildConfigs(len(checkedTargets), "Debug")
progressBarWait()