forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/master' into 4.5
Change-Id: Iaf279b5cf8f4cd417c87eb633f22efbe510ac31d
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
});
|
||||
QTC_ASSERT(index >= 0, return);
|
||||
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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -99,6 +99,7 @@ private:
|
||||
void rightButtonClicked();
|
||||
void upButtonClicked();
|
||||
void downButtonClicked();
|
||||
void filterToggled(bool);
|
||||
|
||||
protected: //functions
|
||||
QTreeView *treeWidget() const;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@ signals:
|
||||
void rightButtonClicked();
|
||||
void upButtonClicked();
|
||||
void downButtonClicked();
|
||||
void filterToggled(bool);
|
||||
|
||||
private: // functions
|
||||
NavigatorView *navigatorView() const;
|
||||
|
@@ -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();
|
||||
|
@@ -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 */
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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 {',
|
||||
|
@@ -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"
|
||||
|
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user