forked from qt-creator/qt-creator
Merge "Merge remote-tracking branch 'origin/4.3'"
This commit is contained in:
@@ -58,12 +58,28 @@ Controls.ComboBox {
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
onCurrentTextChanged: {
|
||||
onAccepted: {
|
||||
if (backendValue === undefined)
|
||||
return;
|
||||
|
||||
if (backendValue.value !== currentText)
|
||||
backendValue.value = currentText;
|
||||
if (editText === "")
|
||||
return
|
||||
|
||||
if (backendValue.value !== editText)
|
||||
backendValue.value = editText;
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
if (backendValue === undefined)
|
||||
return;
|
||||
|
||||
if (editText === "")
|
||||
return
|
||||
|
||||
var indexText = comboBox.textAt(index)
|
||||
|
||||
if (backendValue.value !== indexText)
|
||||
backendValue.value = indexText;
|
||||
}
|
||||
|
||||
ExtendedFunctionButton {
|
||||
@@ -73,6 +89,13 @@ Controls.ComboBox {
|
||||
visible: comboBox.enabled
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: modelNodeBackend
|
||||
onSelectionChanged: {
|
||||
comboBox.editText = backendValue.value
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
//Hack to style the text input
|
||||
for (var i = 0; i < comboBox.children.length; i++) {
|
||||
|
@@ -53,16 +53,22 @@ public:
|
||||
: m_accumulating(false), m_aborted(false), m_lockDepth(0)
|
||||
{}
|
||||
|
||||
bool resolveMacro(const QString &name, QString *ret)
|
||||
bool resolveMacro(const QString &name, QString *ret, QSet<AbstractMacroExpander *> &seen)
|
||||
{
|
||||
// Prevent loops:
|
||||
const int count = seen.count();
|
||||
seen.insert(this);
|
||||
if (seen.count() == count)
|
||||
return false;
|
||||
|
||||
bool found;
|
||||
*ret = value(name.toUtf8(), &found);
|
||||
if (found)
|
||||
return true;
|
||||
|
||||
found = Utils::anyOf(m_subProviders, [name, ret] (const MacroExpanderProvider &p) -> bool {
|
||||
found = Utils::anyOf(m_subProviders, [name, ret, &seen] (const MacroExpanderProvider &p) -> bool {
|
||||
MacroExpander *expander = p ? p() : 0;
|
||||
return expander && expander->resolveMacro(name, ret);
|
||||
return expander && expander->d->resolveMacro(name, ret, seen);
|
||||
});
|
||||
|
||||
if (found)
|
||||
@@ -75,7 +81,7 @@ public:
|
||||
if (found)
|
||||
return true;
|
||||
|
||||
return this == globalMacroExpander()->d ? false : globalMacroExpander()->d->resolveMacro(name, ret);
|
||||
return this == globalMacroExpander()->d ? false : globalMacroExpander()->d->resolveMacro(name, ret, seen);
|
||||
}
|
||||
|
||||
QString value(const QByteArray &variable, bool *found)
|
||||
@@ -243,7 +249,8 @@ MacroExpander::~MacroExpander()
|
||||
*/
|
||||
bool MacroExpander::resolveMacro(const QString &name, QString *ret) const
|
||||
{
|
||||
return d->resolveMacro(name, ret);
|
||||
QSet<AbstractMacroExpander*> seen;
|
||||
return d->resolveMacro(name, ret, seen);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@@ -68,8 +68,6 @@ QPlainTextEdit *OutputFormatter::plainTextEdit() const
|
||||
|
||||
void OutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText)
|
||||
{
|
||||
plainText->setReadOnly(true);
|
||||
plainText->setTextInteractionFlags(plainText->textInteractionFlags() | Qt::TextSelectableByKeyboard);
|
||||
d->plainTextEdit = plainText;
|
||||
d->cursor = plainText ? plainText->textCursor() : QTextCursor();
|
||||
initFormats();
|
||||
|
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <QDir>
|
||||
#include <QRegularExpression>
|
||||
#include <QSet>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
@@ -153,7 +154,8 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt
|
||||
*pos = i;
|
||||
return true;
|
||||
}
|
||||
if (resolveMacro(varName, ret)) {
|
||||
QSet<AbstractMacroExpander*> seen;
|
||||
if (resolveMacro(varName, ret, seen)) {
|
||||
*pos = i;
|
||||
if (!pattern.isEmpty() && currArg == &replace) {
|
||||
const QRegularExpression regexp(pattern);
|
||||
|
@@ -65,7 +65,7 @@ public:
|
||||
//! \param name The name of the expando
|
||||
//! \param ret Replacement string on output
|
||||
//! \return True if the expando was found
|
||||
virtual bool resolveMacro(const QString &name, QString *ret) = 0;
|
||||
virtual bool resolveMacro(const QString &name, QString *ret, QSet<AbstractMacroExpander *> &seen) = 0;
|
||||
private:
|
||||
bool expandNestedMacros(const QString &str, int *pos, QString *ret);
|
||||
};
|
||||
|
@@ -277,10 +277,6 @@ void BuildDirManager::generateProjectTree(CMakeProjectNode *root, const QList<co
|
||||
const Utils::FileName projectFile = m_buildConfiguration->target()->project()->projectFilePath();
|
||||
|
||||
m_reader->generateProjectTree(root, allFiles);
|
||||
|
||||
// Make sure the top level CMakeLists.txt is always visible:
|
||||
if (root->isEmpty())
|
||||
root->addNode(new FileNode(projectFile, FileType::Project, false));
|
||||
}
|
||||
|
||||
void BuildDirManager::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
@@ -336,7 +332,12 @@ QList<CMakeBuildTarget> BuildDirManager::buildTargets() const
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::installTarget(), this));
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::testTarget(), this));
|
||||
|
||||
m_buildTargets.append(m_reader->buildTargets());
|
||||
m_buildTargets.append(Utils::filtered(m_reader->buildTargets(), [](const CMakeBuildTarget &bt) {
|
||||
return bt.title != CMakeBuildStep::allTarget()
|
||||
&& bt.title != CMakeBuildStep::cleanTarget()
|
||||
&& bt.title != CMakeBuildStep::installTarget()
|
||||
&& bt.title != CMakeBuildStep::testTarget();
|
||||
}));
|
||||
}
|
||||
return m_buildTargets;
|
||||
}
|
||||
|
@@ -221,6 +221,10 @@ CMakeBuildConfiguration::generateProjectTree(const QList<const FileNode*> &allFi
|
||||
|
||||
auto root = new CMakeProjectNode(target()->project()->projectDirectory());
|
||||
m_buildDirManager->generateProjectTree(root, allFiles);
|
||||
if (root->isEmpty()) {
|
||||
delete root;
|
||||
return nullptr;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -280,7 +284,9 @@ QList<ConfigModel::DataItem> CMakeBuildConfiguration::completeCMakeConfiguration
|
||||
j.values = i.values;
|
||||
j.inCMakeCache = i.inCMakeCache;
|
||||
|
||||
j.isAdvanced = i.isAdvanced || i.type == CMakeConfigItem::INTERNAL;
|
||||
j.isAdvanced = i.isAdvanced;
|
||||
j.isHidden = i.type == CMakeConfigItem::INTERNAL || i.type == CMakeConfigItem::STATIC;
|
||||
|
||||
switch (i.type) {
|
||||
case CMakeConfigItem::FILEPATH:
|
||||
j.type = ConfigModel::DataItem::FILE;
|
||||
|
@@ -267,7 +267,7 @@ void CMakeBuildStep::run(QFutureInterface<bool> &fi)
|
||||
m_runTrigger = connect(bc, &CMakeBuildConfiguration::dataAvailable,
|
||||
this, [this, &fi]() { runImpl(fi); });
|
||||
m_errorTrigger = connect(bc, &CMakeBuildConfiguration::errorOccured,
|
||||
this, [this, &fi]() { reportRunResult(fi, false); });
|
||||
this, [this, &fi](const QString& em) { handleCMakeError(fi, em); });
|
||||
} else {
|
||||
runImpl(fi);
|
||||
}
|
||||
@@ -276,10 +276,21 @@ void CMakeBuildStep::run(QFutureInterface<bool> &fi)
|
||||
void CMakeBuildStep::runImpl(QFutureInterface<bool> &fi)
|
||||
{
|
||||
// Do the actual build:
|
||||
disconnectTriggers();
|
||||
AbstractProcessStep::run(fi);
|
||||
}
|
||||
|
||||
void CMakeBuildStep::handleCMakeError(QFutureInterface<bool> &fi, const QString& errorMessage)
|
||||
{
|
||||
disconnectTriggers();
|
||||
AbstractProcessStep::stdError(tr("Error parsing CMake: %1\n").arg(errorMessage));
|
||||
reportRunResult(fi, false);
|
||||
}
|
||||
|
||||
void CMakeBuildStep::disconnectTriggers()
|
||||
{
|
||||
disconnect(m_runTrigger);
|
||||
disconnect(m_errorTrigger);
|
||||
|
||||
AbstractProcessStep::run(fi);
|
||||
}
|
||||
|
||||
BuildStepConfigWidget *CMakeBuildStep::createConfigWidget()
|
||||
|
@@ -104,6 +104,8 @@ private:
|
||||
void ctor(ProjectExplorer::BuildStepList *bsl);
|
||||
|
||||
void runImpl(QFutureInterface<bool> &fi);
|
||||
void handleCMakeError(QFutureInterface<bool> &fi, const QString& errorMessage);
|
||||
void disconnectTriggers();
|
||||
|
||||
void handleBuildTargetChanges();
|
||||
CMakeRunConfiguration *targetsActiveRunConfiguration() const;
|
||||
|
@@ -170,15 +170,20 @@ std::function<bool (const CMakeConfigItem &a, const CMakeConfigItem &b)> CMakeCo
|
||||
|
||||
CMakeConfigItem CMakeConfigItem::fromString(const QString &s)
|
||||
{
|
||||
// Strip comments:
|
||||
// Strip comments (only at start of line!):
|
||||
int commentStart = s.count();
|
||||
int pos = s.indexOf(QLatin1Char('#'));
|
||||
if (pos >= 0)
|
||||
commentStart = pos;
|
||||
pos = s.indexOf(QLatin1String("//"));
|
||||
if (pos >= 0 && pos < commentStart)
|
||||
commentStart = pos;
|
||||
|
||||
for (int i = 0; i < s.count(); ++i) {
|
||||
const QChar c = s.at(i);
|
||||
if (c == ' ' || c == '\t')
|
||||
continue;
|
||||
else if ((c == '#')
|
||||
|| (c == '/' && i < s.count() - 1 && s.at(i + 1) == '/')) {
|
||||
commentStart = i;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const QString line = s.mid(0, commentStart);
|
||||
|
||||
// Split up line:
|
||||
|
@@ -32,7 +32,7 @@
|
||||
using namespace CMakeProjectManager;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
const char COMMON_ERROR_PATTERN[] = "^CMake Error at (.*):([0-9]*) \\((.*)\\):";
|
||||
const char COMMON_ERROR_PATTERN[] = "^CMake Error at (.*):([0-9]*)( \\((.*)\\))?:";
|
||||
const char NEXT_SUBERROR_PATTERN[] = "^CMake Error in (.*):";
|
||||
const char LOCATION_LINE_PATTERN[] = ":(\\d+):(?:(\\d+))?$";
|
||||
|
||||
@@ -250,6 +250,20 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
|
||||
Utils::FileName(), -1, categoryBuild))
|
||||
<< QString();
|
||||
|
||||
QTest::newRow("cmake error at")
|
||||
<< QString::fromLatin1("CMake Error at CMakeLists.txt:4:\n"
|
||||
" Parse error. Expected \"(\", got newline with text \"\n"
|
||||
"\n"
|
||||
" \".\n")
|
||||
<< OutputParserTester::STDERR
|
||||
<< QString() << QString()
|
||||
<< (QList<ProjectExplorer::Task>()
|
||||
<< Task(Task::Error,
|
||||
QLatin1String("Parse error. Expected \"(\", got newline with text \" \"."),
|
||||
Utils::FileName::fromUserInput(QLatin1String("CMakeLists.txt")), 4,
|
||||
categoryBuild))
|
||||
<< QString();
|
||||
|
||||
QTest::newRow("cmake warning")
|
||||
<< QString::fromLatin1("Syntax Warning in cmake code at\n"
|
||||
"/test/path/CMakeLists.txt:9:15\n"
|
||||
|
@@ -147,8 +147,8 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
|
||||
|
||||
auto newRoot = bc->generateProjectTree(m_allFiles);
|
||||
if (newRoot) {
|
||||
setRootProjectNode(newRoot);
|
||||
setDisplayName(newRoot->displayName());
|
||||
setRootProjectNode(newRoot);
|
||||
}
|
||||
|
||||
updateApplicationAndDeploymentTargets();
|
||||
@@ -495,8 +495,13 @@ void CMakeProject::updateApplicationAndDeploymentTargets()
|
||||
if (ct.targetType == UtilityType)
|
||||
continue;
|
||||
|
||||
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType)
|
||||
deploymentData.addFile(ct.executable.toString(), deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()), DeployableFile::TypeExecutable);
|
||||
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) {
|
||||
if (!ct.executable.isEmpty()) {
|
||||
deploymentData.addFile(ct.executable.toString(),
|
||||
deploymentPrefix + buildDir.relativeFilePath(ct.executable.toFileInfo().dir().path()),
|
||||
DeployableFile::TypeExecutable);
|
||||
}
|
||||
}
|
||||
if (ct.targetType == ExecutableType) {
|
||||
FileName srcWithTrailingSlash = FileName::fromString(ct.sourceDirectory.toString());
|
||||
srcWithTrailingSlash.appendString('/');
|
||||
|
@@ -257,7 +257,9 @@ void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
|
||||
|
||||
QList<InternalDataItem> result;
|
||||
while (newIt != newEndIt && oldIt != oldEndIt) {
|
||||
if (newIt->key < oldIt->key) {
|
||||
if (newIt->isHidden) {
|
||||
++newIt;
|
||||
} else if (newIt->key < oldIt->key) {
|
||||
// Add new entry:
|
||||
result << InternalDataItem(*newIt);
|
||||
++newIt;
|
||||
@@ -279,8 +281,11 @@ void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
|
||||
}
|
||||
|
||||
// Add remaining new entries:
|
||||
for (; newIt != newEndIt; ++newIt)
|
||||
for (; newIt != newEndIt; ++newIt) {
|
||||
if (newIt->isHidden)
|
||||
continue;
|
||||
result << InternalDataItem(*newIt);
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
m_configuration = result;
|
||||
|
@@ -45,6 +45,7 @@ public:
|
||||
|
||||
QString key;
|
||||
Type type = STRING;
|
||||
bool isHidden = false;
|
||||
bool isAdvanced = false;
|
||||
bool inCMakeCache = false;
|
||||
QString value;
|
||||
|
@@ -73,6 +73,17 @@ ServerModeReader::ServerModeReader()
|
||||
if (m_cmakeFiles.contains(document->filePath()))
|
||||
emit dirty();
|
||||
});
|
||||
|
||||
connect(&m_parser, &CMakeParser::addOutput,
|
||||
this, [](const QString &m) { Core::MessageManager::write(m); });
|
||||
connect(&m_parser, &CMakeParser::addTask, this, [this](const Task &t) {
|
||||
Task editable(t);
|
||||
if (!editable.file.isEmpty()) {
|
||||
QDir srcDir(m_parameters.sourceDirectory.toString());
|
||||
editable.file = FileName::fromString(srcDir.absoluteFilePath(editable.file.toString()));
|
||||
}
|
||||
TaskHub::addTask(editable);
|
||||
});
|
||||
}
|
||||
|
||||
ServerModeReader::~ServerModeReader()
|
||||
@@ -98,8 +109,13 @@ void ServerModeReader::setParameters(const BuildDirReader::Parameters &p)
|
||||
this, &ServerModeReader::handleProgress);
|
||||
connect(m_cmakeServer.get(), &ServerMode::cmakeSignal,
|
||||
this, &ServerModeReader::handleSignal);
|
||||
connect(m_cmakeServer.get(), &ServerMode::cmakeMessage,
|
||||
this, [this](const QString &m) { Core::MessageManager::write(m); });
|
||||
connect(m_cmakeServer.get(), &ServerMode::cmakeMessage, [this](const QString &m) {
|
||||
const QStringList lines = m.split('\n');
|
||||
for (const QString &l : lines) {
|
||||
m_parser.stdError(l);
|
||||
Core::MessageManager::write(l);
|
||||
}
|
||||
});
|
||||
connect(m_cmakeServer.get(), &ServerMode::message,
|
||||
this, [](const QString &m) { Core::MessageManager::write(m); });
|
||||
connect(m_cmakeServer.get(), &ServerMode::connected,
|
||||
@@ -170,6 +186,7 @@ void ServerModeReader::stop()
|
||||
m_future->reportFinished();
|
||||
m_future.reset();
|
||||
}
|
||||
m_parser.flush();
|
||||
}
|
||||
|
||||
bool ServerModeReader::isReady() const
|
||||
@@ -732,6 +749,9 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
|
||||
void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *> knownHeaders,
|
||||
const QList<const FileNode *> &allFiles)
|
||||
{
|
||||
if (root->isEmpty())
|
||||
return;
|
||||
|
||||
auto headerNode = new VirtualFolderNode(root->filePath(), Node::DefaultPriority - 5);
|
||||
headerNode->setDisplayName(tr("<Headers>"));
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "builddirreader.h"
|
||||
#include "servermode.h"
|
||||
#include "cmakeparser.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -148,6 +149,8 @@ private:
|
||||
QList<Project *> m_projects;
|
||||
mutable QList<Target *> m_targets;
|
||||
QList<FileGroup *> m_fileGroups;
|
||||
|
||||
CMakeParser m_parser;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -243,6 +243,10 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
|
||||
{
|
||||
FileName cacheFile = m_parameters.buildDirectory;
|
||||
cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
|
||||
|
||||
if (!cacheFile.exists())
|
||||
return { };
|
||||
|
||||
QString errorMessage;
|
||||
CMakeConfig result = BuildDirManager::parseConfiguration(cacheFile, &errorMessage);
|
||||
|
||||
@@ -266,6 +270,9 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
|
||||
|
||||
void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<const FileNode *> &allFiles)
|
||||
{
|
||||
if (m_files.isEmpty())
|
||||
return;
|
||||
|
||||
root->setDisplayName(m_projectName);
|
||||
|
||||
// Delete no longer necessary file watcher based on m_cmakeFiles:
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "treescanner.h"
|
||||
|
||||
#include <coreplugin/iversioncontrol.h>
|
||||
#include <coreplugin/vcsmanager.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <cpptools/cpptoolsconstants.h>
|
||||
@@ -67,7 +69,10 @@ bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory)
|
||||
m_scanFuture = fi->future();
|
||||
m_futureWatcher.setFuture(m_scanFuture);
|
||||
|
||||
Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); });
|
||||
if (m_versionControls.isEmpty())
|
||||
m_versionControls = Core::VcsManager::versionControls();
|
||||
|
||||
Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory, m_versionControls); });
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -144,12 +149,16 @@ FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Uti
|
||||
return Node::fileTypeForMimeType(mimeType);
|
||||
}
|
||||
|
||||
void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory, const FileFilter &filter, const FileTypeFactory &factory)
|
||||
void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory,
|
||||
const FileFilter &filter, const FileTypeFactory &factory,
|
||||
QList<Core::IVersionControl *> &versionControls)
|
||||
{
|
||||
std::unique_ptr<FutureInterface> fip(fi);
|
||||
fip->reportStarted();
|
||||
|
||||
Result nodes = FileNode::scanForFiles(directory,
|
||||
Result nodes
|
||||
= FileNode::scanForFilesWithVersionControls(
|
||||
directory,
|
||||
[&filter, &factory](const Utils::FileName &fn) -> FileNode * {
|
||||
const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString());
|
||||
|
||||
@@ -163,8 +172,7 @@ void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& direc
|
||||
type = factory(mimeType, fn);
|
||||
|
||||
return new FileNode(fn, type, false);
|
||||
},
|
||||
fip.get());
|
||||
}, versionControls, fip.get());
|
||||
|
||||
Utils::sort(nodes, ProjectExplorer::Node::sortByPath);
|
||||
|
||||
|
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Core { class IVersionControl; }
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
@@ -86,7 +88,8 @@ signals:
|
||||
|
||||
private:
|
||||
static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory,
|
||||
const FileFilter &filter, const FileTypeFactory &factory);
|
||||
const FileFilter &filter, const FileTypeFactory &factory,
|
||||
QList<Core::IVersionControl *> &versionControls);
|
||||
|
||||
private:
|
||||
FileFilter m_filter;
|
||||
@@ -94,6 +97,7 @@ private:
|
||||
|
||||
FutureWatcher m_futureWatcher;
|
||||
Future m_scanFuture;
|
||||
QList<Core::IVersionControl *> m_versionControls;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -100,6 +100,8 @@ public:
|
||||
*
|
||||
* It will return true only for exact matches of the name, not for e.g. files in a
|
||||
* directory owned by the version control system (e.g. .git/control).
|
||||
*
|
||||
* This method needs to be thread safe!
|
||||
*/
|
||||
virtual bool isVcsFileOrDirectory(const Utils::FileName &fileName) const = 0;
|
||||
|
||||
|
@@ -300,6 +300,7 @@ void CompilerOptionsBuilder::addDefineToAvoidIncludingGccOrMinGwIntrinsics()
|
||||
if (type == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID
|
||||
|| type == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID) {
|
||||
addDefine("#define _X86INTRIN_H_INCLUDED");
|
||||
addDefine("#define BOOST_UUID_NO_SIMD");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2303,26 +2303,32 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
|
||||
}
|
||||
|
||||
// Run to, jump to line below in stopped state.
|
||||
if (currentEngine()->state() == InferiorStopOk && args.isValid()) {
|
||||
DebuggerEngine *engine = currentEngine();
|
||||
QTC_ASSERT(engine, return);
|
||||
if (engine->state() == InferiorStopOk && args.isValid()) {
|
||||
menu->addSeparator();
|
||||
if (currentEngine()->hasCapability(RunToLineCapability)) {
|
||||
if (engine->hasCapability(RunToLineCapability)) {
|
||||
auto act = menu->addAction(args.address
|
||||
? DebuggerEngine::tr("Run to Address 0x%1").arg(args.address, 0, 16)
|
||||
: DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber));
|
||||
connect(act, &QAction::triggered, [this, args] {
|
||||
currentEngine()->executeRunToLine(args);
|
||||
DebuggerEngine *engine = currentEngine();
|
||||
QTC_ASSERT(engine, return);
|
||||
engine->executeRunToLine(args);
|
||||
});
|
||||
}
|
||||
if (currentEngine()->hasCapability(JumpToLineCapability)) {
|
||||
if (engine->hasCapability(JumpToLineCapability)) {
|
||||
auto act = menu->addAction(args.address
|
||||
? DebuggerEngine::tr("Jump to Address 0x%1").arg(args.address, 0, 16)
|
||||
: DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber));
|
||||
connect(act, &QAction::triggered, [this, args] {
|
||||
currentEngine()->executeJumpToLine(args);
|
||||
DebuggerEngine *engine = currentEngine();
|
||||
QTC_ASSERT(engine, return);
|
||||
engine->executeJumpToLine(args);
|
||||
});
|
||||
}
|
||||
// Disassemble current function in stopped state.
|
||||
if (currentEngine()->hasCapability(DisassemblerCapability)) {
|
||||
if (engine->hasCapability(DisassemblerCapability)) {
|
||||
StackFrame frame;
|
||||
frame.function = cppFunctionAt(args.fileName, lineNumber, 1);
|
||||
frame.line = 42; // trick gdb into mixed mode.
|
||||
@@ -2331,7 +2337,9 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
|
||||
.arg(frame.function);
|
||||
auto act = new QAction(text, menu);
|
||||
connect(act, &QAction::triggered, [this, frame] {
|
||||
currentEngine()->openDisassemblerView(Location(frame));
|
||||
DebuggerEngine *engine = currentEngine();
|
||||
QTC_ASSERT(engine, return);
|
||||
engine->openDisassemblerView(Location(frame));
|
||||
});
|
||||
menu->addAction(act);
|
||||
}
|
||||
|
@@ -31,6 +31,8 @@
|
||||
#include "../nimconstants.h"
|
||||
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
#include <coreplugin/iversioncontrol.h>
|
||||
#include <coreplugin/vcsmanager.h>
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/kit.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
@@ -113,8 +115,11 @@ void NimProject::collectProjectFiles()
|
||||
m_lastProjectScan.start();
|
||||
QTC_ASSERT(!m_futureWatcher.future().isRunning(), return);
|
||||
FileName prjDir = projectDirectory();
|
||||
QFuture<QList<ProjectExplorer::FileNode *>> future = Utils::runAsync([prjDir] {
|
||||
return FileNode::scanForFiles(prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); });
|
||||
const QList<Core::IVersionControl *> versionControls = Core::VcsManager::versionControls();
|
||||
QFuture<QList<ProjectExplorer::FileNode *>> future = Utils::runAsync([prjDir, versionControls] {
|
||||
return FileNode::scanForFilesWithVersionControls(
|
||||
prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); },
|
||||
versionControls);
|
||||
});
|
||||
m_futureWatcher.setFuture(future);
|
||||
Core::ProgressManager::addTask(future, tr("Scanning for Nim files"), "Nim.Project.Scan");
|
||||
|
@@ -149,7 +149,10 @@ void TabWidget::slotContextMenuRequested(const QPoint &pos)
|
||||
|
||||
AppOutputPane::RunControlTab::RunControlTab(RunControl *rc, Core::OutputWindow *w) :
|
||||
runControl(rc), window(w)
|
||||
{ }
|
||||
{
|
||||
if (rc && w)
|
||||
w->setFormatter(rc->outputFormatter());
|
||||
}
|
||||
|
||||
AppOutputPane::AppOutputPane() :
|
||||
m_mainWidget(new QWidget),
|
||||
@@ -262,7 +265,7 @@ AppOutputPane::~AppOutputPane()
|
||||
qDebug() << "OutputPane::~OutputPane: Entries left" << m_runControlTabs.size();
|
||||
|
||||
foreach (const RunControlTab &rt, m_runControlTabs) {
|
||||
rt.window->setFormatter(nullptr);
|
||||
delete rt.window;
|
||||
delete rt.runControl;
|
||||
}
|
||||
delete m_mainWidget;
|
||||
@@ -416,13 +419,14 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
|
||||
RunControlTab &tab = m_runControlTabs[tabIndex];
|
||||
// Reuse this tab
|
||||
delete tab.runControl;
|
||||
handleOldOutput(tab.window);
|
||||
tab.runControl = rc;
|
||||
tab.window->setFormatter(rc ? rc->outputFormatter() : nullptr);
|
||||
|
||||
handleOldOutput(tab.window);
|
||||
|
||||
// Update the title.
|
||||
m_tabWidget->setTabText(tabIndex, rc->displayName());
|
||||
|
||||
tab.window->setFormatter(nullptr);
|
||||
tab.window->scrollToBottom();
|
||||
if (debug)
|
||||
qDebug() << "OutputPane::createNewOutputWindow: Reusing tab" << tabIndex << " for " << rc;
|
||||
@@ -435,7 +439,6 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
|
||||
Core::OutputWindow *ow = new Core::OutputWindow(context, m_tabWidget);
|
||||
ow->setWindowTitle(tr("Application Output Window"));
|
||||
ow->setWindowIcon(Icons::WINDOW.icon());
|
||||
ow->setFormatter(nullptr);
|
||||
ow->setWordWrapEnabled(ProjectExplorerPlugin::projectExplorerSettings().wrapAppOutput);
|
||||
ow->setMaxLineCount(ProjectExplorerPlugin::projectExplorerSettings().maxAppOutputLines);
|
||||
ow->setWheelZoomEnabled(TextEditor::TextEditorSettings::behaviorSettings().m_scrollWheelZooming);
|
||||
@@ -590,9 +593,8 @@ bool AppOutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode)
|
||||
}
|
||||
|
||||
m_tabWidget->removeTab(tabIndex);
|
||||
m_runControlTabs[index].window->setFormatter(nullptr);
|
||||
delete m_runControlTabs[index].runControl;
|
||||
delete m_runControlTabs[index].window;
|
||||
delete m_runControlTabs[index].runControl;
|
||||
m_runControlTabs.removeAt(index);
|
||||
updateCloseActions();
|
||||
|
||||
@@ -706,10 +708,6 @@ void AppOutputPane::contextMenuRequested(const QPoint &pos, int index)
|
||||
void AppOutputPane::slotRunControlStarted()
|
||||
{
|
||||
RunControl *current = currentRunControl();
|
||||
const int rcIndex = indexOf(current);
|
||||
if (rcIndex >= 0 && m_runControlTabs.at(rcIndex).window)
|
||||
m_runControlTabs.at(rcIndex).window->setFormatter(current->outputFormatter());
|
||||
|
||||
if (current && current == sender())
|
||||
enableButtons(current, true); // RunControl::isRunning() cannot be trusted in signal handler.
|
||||
}
|
||||
@@ -740,8 +738,6 @@ void AppOutputPane::slotRunControlFinished2(RunControl *sender)
|
||||
if (current && current == sender)
|
||||
enableButtons(current, false); // RunControl::isRunning() cannot be trusted in signal handler.
|
||||
|
||||
m_runControlTabs.at(senderIndex).window->setFormatter(nullptr); // Reset formater for this RC
|
||||
|
||||
ProjectExplorerPlugin::instance()->updateRunActions();
|
||||
|
||||
if (!isRunning())
|
||||
|
@@ -339,7 +339,8 @@ FileType FileNode::fileType() const
|
||||
static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &directory,
|
||||
const std::function<FileNode *(const Utils::FileName &)> factory,
|
||||
QSet<QString> &visited, QFutureInterface<QList<FileNode*>> *future,
|
||||
double progressStart, double progressRange)
|
||||
double progressStart, double progressRange,
|
||||
const QList<Core::IVersionControl*> &versionControls)
|
||||
{
|
||||
QList<FileNode *> result;
|
||||
|
||||
@@ -351,8 +352,6 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
|
||||
if (visitedCount == visited.count())
|
||||
return result;
|
||||
|
||||
const Core::IVersionControl *vcsControl
|
||||
= Core::VcsManager::findVersionControlForDirectory(baseDir.absolutePath(), nullptr);
|
||||
const QList<QFileInfo> entries = baseDir.entryInfoList(QStringList(), QDir::AllEntries|QDir::NoDotAndDotDot);
|
||||
double progress = 0;
|
||||
const double progressIncrement = progressRange / static_cast<double>(entries.count());
|
||||
@@ -362,9 +361,11 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
|
||||
return result;
|
||||
|
||||
const Utils::FileName entryName = Utils::FileName::fromString(entry.absoluteFilePath());
|
||||
if (!vcsControl || !vcsControl->isVcsFileOrDirectory(entryName)) {
|
||||
if (!Utils::contains(versionControls, [&entryName](const Core::IVersionControl *vc) {
|
||||
return vc->isVcsFileOrDirectory(entryName);
|
||||
})) {
|
||||
if (entry.isDir())
|
||||
result.append(scanForFilesRecursively(entryName, factory, visited, future, progress, progressIncrement));
|
||||
result.append(scanForFilesRecursively(entryName, factory, visited, future, progress, progressIncrement, versionControls));
|
||||
else if (FileNode *node = factory(entryName))
|
||||
result.append(node);
|
||||
}
|
||||
@@ -382,14 +383,24 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
QList<FileNode *> FileNode::scanForFiles(const Utils::FileName &directory,
|
||||
const std::function<FileNode *(const Utils::FileName &)> factory,
|
||||
QFutureInterface<QList<FileNode *> > *future)
|
||||
{
|
||||
return FileNode::scanForFilesWithVersionControls(directory, factory, QList<Core::IVersionControl *>(), future);
|
||||
}
|
||||
|
||||
QList<FileNode *>
|
||||
FileNode::scanForFilesWithVersionControls(const Utils::FileName &directory,
|
||||
const std::function<FileNode *(const Utils::FileName &)> factory,
|
||||
const QList<Core::IVersionControl *> &versionControls,
|
||||
QFutureInterface<QList<FileNode *>> *future)
|
||||
{
|
||||
QSet<QString> visited;
|
||||
if (future)
|
||||
future->setProgressRange(0, 1000000);
|
||||
return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0);
|
||||
return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, versionControls);
|
||||
}
|
||||
|
||||
bool FileNode::supportsAction(ProjectAction action, Node *node) const
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <functional>
|
||||
|
||||
namespace Utils { class MimeType; }
|
||||
namespace Core { class IVersionControl; }
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
@@ -188,9 +189,16 @@ public:
|
||||
FileNode *asFileNode() final { return this; }
|
||||
const FileNode *asFileNode() const final { return this; }
|
||||
|
||||
// For ABI compatibility, remove in QtC 4.4:
|
||||
static QList<FileNode *> scanForFiles(const Utils::FileName &directory,
|
||||
const std::function<FileNode *(const Utils::FileName &fileName)> factory,
|
||||
QFutureInterface<QList<FileNode *>> *future = nullptr);
|
||||
|
||||
static QList<FileNode *>
|
||||
scanForFilesWithVersionControls(const Utils::FileName &directory,
|
||||
const std::function<FileNode *(const Utils::FileName &fileName)> factory,
|
||||
const QList<Core::IVersionControl *> &versionControls,
|
||||
QFutureInterface<QList<FileNode *>> *future = nullptr);
|
||||
bool supportsAction(ProjectAction action, Node *node) const override;
|
||||
|
||||
private:
|
||||
|
@@ -330,7 +330,7 @@ void QmakeProjectManagerPlugin::updateContextActions()
|
||||
Project *project = ProjectTree::currentProject();
|
||||
|
||||
ContainerNode *containerNode = node ? node->asContainerNode() : nullptr;
|
||||
ProjectNode *proFileNode = containerNode ? containerNode->rootProjectNode() : dynamic_cast<QmakeProFileNode *>(node);
|
||||
QmakeProFileNode *proFileNode = dynamic_cast<QmakeProFileNode *>(containerNode ? containerNode->rootProjectNode() : node);
|
||||
|
||||
m_addLibraryActionContextMenu->setEnabled(proFileNode);
|
||||
QmakeProject *qmakeProject = qobject_cast<QmakeProject *>(QmakeManager::contextProject());
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "gradientmodel.h"
|
||||
|
||||
#include "qmlanchorbindingproxy.h"
|
||||
#include "propertyeditorview.h"
|
||||
|
||||
#include <nodeproperty.h>
|
||||
#include <nodelistproperty.h>
|
||||
@@ -35,7 +36,7 @@
|
||||
#include <rewritertransaction.h>
|
||||
|
||||
GradientModel::GradientModel(QObject *parent) :
|
||||
QAbstractListModel(parent), m_lock(false)
|
||||
QAbstractListModel(parent), m_locked(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -93,7 +94,7 @@ QVariant GradientModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
int GradientModel::addStop(qreal position, const QColor &color)
|
||||
{
|
||||
if (m_lock)
|
||||
if (m_locked)
|
||||
return -1;
|
||||
|
||||
if (!m_itemNode.isValid() || gradientPropertyName().isEmpty())
|
||||
@@ -131,7 +132,7 @@ int GradientModel::addStop(qreal position, const QColor &color)
|
||||
|
||||
void GradientModel::addGradient()
|
||||
{
|
||||
if (m_lock)
|
||||
if (m_locked)
|
||||
return;
|
||||
|
||||
if (!m_itemNode.isValid() || gradientPropertyName().isEmpty())
|
||||
@@ -174,7 +175,7 @@ void GradientModel::addGradient()
|
||||
|
||||
void GradientModel::setColor(int index, const QColor &color)
|
||||
{
|
||||
if (m_lock)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (!m_itemNode.modelNode().isSelected())
|
||||
@@ -191,7 +192,7 @@ void GradientModel::setColor(int index, const QColor &color)
|
||||
|
||||
void GradientModel::setPosition(int index, qreal positition)
|
||||
{
|
||||
if (m_lock)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (index < rowCount()) {
|
||||
@@ -266,12 +267,12 @@ void GradientModel::deleteGradient()
|
||||
|
||||
void GradientModel::lock()
|
||||
{
|
||||
m_lock = true;
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
void GradientModel::unlock()
|
||||
{
|
||||
m_lock = false;
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
void GradientModel::registerDeclarativeType()
|
||||
@@ -281,11 +282,11 @@ void GradientModel::registerDeclarativeType()
|
||||
|
||||
void GradientModel::setupModel()
|
||||
{
|
||||
m_lock = true;
|
||||
m_locked = true;
|
||||
beginResetModel();
|
||||
|
||||
endResetModel();
|
||||
m_lock = false;
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
void GradientModel::setAnchorBackend(const QVariant &anchorBackend)
|
||||
@@ -300,12 +301,12 @@ void GradientModel::setAnchorBackend(const QVariant &anchorBackend)
|
||||
|
||||
setupModel();
|
||||
|
||||
m_lock = true;
|
||||
m_locked = true;
|
||||
|
||||
emit anchorBackendChanged();
|
||||
emit hasGradientChanged();
|
||||
|
||||
m_lock = false;
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
QString GradientModel::gradientPropertyName() const
|
||||
@@ -323,3 +324,16 @@ bool GradientModel::hasGradient() const
|
||||
return m_itemNode.isValid()
|
||||
&& m_itemNode.modelNode().hasProperty(gradientPropertyName().toUtf8());
|
||||
}
|
||||
|
||||
bool GradientModel::locked() const
|
||||
{
|
||||
if (m_locked)
|
||||
return true;
|
||||
|
||||
QmlDesigner::PropertyEditorView *view = qobject_cast<QmlDesigner::PropertyEditorView*>(m_itemNode.view());
|
||||
|
||||
if (view && view->locked())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -76,11 +76,12 @@ private:
|
||||
QString gradientPropertyName() const;
|
||||
void setGradientPropertyName(const QString &name);
|
||||
bool hasGradient() const;
|
||||
bool locked() const;
|
||||
|
||||
private:
|
||||
QmlDesigner::QmlItemNode m_itemNode;
|
||||
QString m_gradientPropertyName;
|
||||
bool m_lock;
|
||||
bool m_locked;
|
||||
|
||||
};
|
||||
|
||||
|
@@ -135,7 +135,7 @@ void PropertyEditorView::changeValue(const QString &name)
|
||||
if (propertyName.isNull())
|
||||
return;
|
||||
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (propertyName == "className")
|
||||
@@ -231,7 +231,7 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
|
||||
if (name.isNull())
|
||||
return;
|
||||
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (!m_selectedNode.isValid())
|
||||
@@ -306,7 +306,7 @@ void PropertyEditorView::exportPopertyAsAlias(const QString &name)
|
||||
if (name.isNull())
|
||||
return;
|
||||
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (!m_selectedNode.isValid())
|
||||
@@ -340,7 +340,7 @@ void PropertyEditorView::removeAliasExport(const QString &name)
|
||||
if (name.isNull())
|
||||
return;
|
||||
|
||||
if (m_locked)
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (!m_selectedNode.isValid())
|
||||
@@ -362,6 +362,11 @@ void PropertyEditorView::removeAliasExport(const QString &name)
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertyEditorView::locked() const
|
||||
{
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
void PropertyEditorView::updateSize()
|
||||
{
|
||||
if (!m_qmlBackEndForCurrentType)
|
||||
@@ -523,7 +528,6 @@ void PropertyEditorView::modelAttached(Model *model)
|
||||
|
||||
m_locked = true;
|
||||
|
||||
resetView();
|
||||
if (!m_setupCompleted) {
|
||||
m_singleShotTimer->setSingleShot(true);
|
||||
m_singleShotTimer->setInterval(100);
|
||||
@@ -532,6 +536,8 @@ void PropertyEditorView::modelAttached(Model *model)
|
||||
}
|
||||
|
||||
m_locked = false;
|
||||
|
||||
resetView();
|
||||
}
|
||||
|
||||
void PropertyEditorView::modelAboutToBeDetached(Model *model)
|
||||
|
@@ -92,6 +92,8 @@ public:
|
||||
void exportPopertyAsAlias(const QString &name);
|
||||
void removeAliasExport(const QString &name);
|
||||
|
||||
bool locked() const;
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
void setupPane(const TypeName &typeName);
|
||||
|
@@ -344,7 +344,7 @@ QString NodeInstanceServerProxy::qrcMappingString() const
|
||||
|
||||
foreach (const StringPair &pair, rewriterView->qrcMapping()) {
|
||||
if (!mappingString.isEmpty())
|
||||
mappingString.append(QLatin1String(","));
|
||||
mappingString.append(QLatin1String(";"));
|
||||
mappingString.append(pair.first);
|
||||
mappingString.append(QLatin1String("="));
|
||||
mappingString.append(pair.second);
|
||||
|
@@ -34,8 +34,14 @@ using namespace Utils;
|
||||
|
||||
class MacroMapExpander : public AbstractMacroExpander {
|
||||
public:
|
||||
virtual bool resolveMacro(const QString &name, QString *ret)
|
||||
virtual bool resolveMacro(const QString &name, QString *ret, QSet<AbstractMacroExpander*> &seen)
|
||||
{
|
||||
// loop prevention
|
||||
const int count = seen.count();
|
||||
seen.insert(this);
|
||||
if (seen.count() == count)
|
||||
return false;
|
||||
|
||||
QHash<QString, QString>::const_iterator it = m_map.constFind(name);
|
||||
if (it != m_map.constEnd()) {
|
||||
*ret = it.value();
|
||||
|
@@ -32,8 +32,14 @@
|
||||
class TestMacroExpander : public Utils::AbstractMacroExpander
|
||||
{
|
||||
public:
|
||||
virtual bool resolveMacro(const QString &name, QString *ret)
|
||||
virtual bool resolveMacro(const QString &name, QString *ret, QSet<AbstractMacroExpander*> &seen)
|
||||
{
|
||||
// loop prevention
|
||||
const int count = seen.count();
|
||||
seen.insert(this);
|
||||
if (seen.count() == count)
|
||||
return false;
|
||||
|
||||
if (name == QLatin1String("foo")) {
|
||||
*ret = QLatin1String("a");
|
||||
return true;
|
||||
|
Reference in New Issue
Block a user