From 93c0ba247d5a2574416231a91bc59473ed3a11ec Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 18 Oct 2016 08:16:58 +0200 Subject: [PATCH 01/53] Revert "iOS: Replaced deprecated signal QProcess::error. Fixes compilation issues with GCC" This reverts commit a9f00a2da3d71fd365e93141527cfb755b8de75b as this commit uses functions that are available from Qt5.6 onwards but we still have Qt5.5 as minimum requirement. Change-Id: Ice16d4faeb3417dc80431299b308b37ab2b56c1f Reviewed-by: Eike Ziller --- src/plugins/ios/iostoolhandler.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index 8615713357d..c5da66c3598 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -589,7 +589,8 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de QObject::connect(process, static_cast(&QProcess::finished), std::bind(&IosDeviceToolHandlerPrivate::subprocessFinished,this, _1,_2)); - QObject::connect(process, &QProcess::errorOccurred, std::bind(&IosDeviceToolHandlerPrivate::subprocessError, this, _1)); + QObject::connect(process, static_cast(&QProcess::error), + std::bind(&IosDeviceToolHandlerPrivate::subprocessError, this, _1)); QObject::connect(&killTimer, &QTimer::timeout, std::bind(&IosDeviceToolHandlerPrivate::killProcess, this)); } @@ -749,7 +750,8 @@ void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &bundlePath, std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasErrorOutput,this)); QObject::connect(process, static_cast(&QProcess::finished), std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessFinished,this, _1,_2)); - QObject::connect(process, &QProcess::errorOccurred, std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessError, this, _1)); + QObject::connect(process, static_cast(&QProcess::error), + std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessError, this, _1)); appPId = pId; gotInferiorPid(bundlePath,deviceId,pId); From d29781fcd81decfb62aed0de5e2947f9f6f47dca Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 14 Oct 2016 12:38:37 +0200 Subject: [PATCH 02/53] Clang: Remove left-over functions ...that helped modifying the delayed parse timeout. Those are pointless now (at least in the backend) because we have a non-blocking translation unit (except for the first edit) around. The only client using the timer value is currently ClangCodeModelServer::registerUnsavedFilesForEditor - a case for which no configuration should be needed. Change-Id: I0f4171d6ee98bcac229aa5a207b6aa17b336a29a Reviewed-by: David Schulz --- .../ipcsource/clangcodemodelserver.cpp | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp index bea5eacea49..8a921320ad3 100644 --- a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp @@ -55,34 +55,9 @@ namespace ClangBackEnd { -namespace { - -int getIntervalFromEnviromentVariable() -{ - bool isConversionOk = false; - const int intervalAsInt = qEnvironmentVariableIntValue("QTC_CLANG_DELAYED_REPARSE_TIMEOUT", - &isConversionOk); - - if (isConversionOk) - return intervalAsInt; - else - return -1; -} - -int delayedDocumentAnnotationsTimerInterval() -{ - static const int defaultInterval = 1500; - static const int userDefinedInterval = getIntervalFromEnviromentVariable(); - static const int interval = userDefinedInterval >= 0 ? userDefinedInterval : defaultInterval; - - return interval; -} - -} // anonymous - ClangCodeModelServer::ClangCodeModelServer() : documents(projects, unsavedFiles) - , updateDocumentAnnotationsTimeOutInMs(delayedDocumentAnnotationsTimerInterval()) + , updateDocumentAnnotationsTimeOutInMs(1500) { updateDocumentAnnotationsTimer.setSingleShot(true); From 4fbdbdb1ee382a582035a4e9256ca2b7d4f3b943 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 14 Oct 2016 13:05:44 +0200 Subject: [PATCH 03/53] Clang: Fix delayed reparse of dirty and visible but not current documents 1. Open document foo.h 2. Create a split and open foo.cpp (#including "foo.h") 3. Edit foo.h (e.g. by introducing a syntax error, so that foo.cpp will indicate header errors in the toolbar or as info bar) => Actual: foo.cpp will be reparsed immediately. Expected: foo.cpp should be reparsed after a delay. This saves resources (cpu time) and minimizes poping up of the header info bar while editing header files in splits. Regression introduced by commit 380d756a03346e5bbb83101f49ed6f6696c42c6a Clang: Hook up supportive translation unit on first edit Change-Id: Ib5fd90e49415dfc3aefacab7cd627b0e1937f5fc Reviewed-by: David Schulz --- .../ipcsource/clangcodemodelserver.cpp | 62 +++++++++++++++---- .../ipcsource/clangcodemodelserver.h | 17 +++-- .../clangbackend/ipcsource/clangdocuments.cpp | 16 +++++ .../clangbackend/ipcsource/clangdocuments.h | 4 ++ tests/unit/unittest/clangdocuments-test.cpp | 36 +++++++++++ tests/unit/unittest/clangipcserver-test.cpp | 1 + 6 files changed, 121 insertions(+), 15 deletions(-) diff --git a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp index 8a921320ad3..62070b37b0b 100644 --- a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp @@ -50,6 +50,8 @@ #include #include +#include + #include #include @@ -57,16 +59,21 @@ namespace ClangBackEnd { ClangCodeModelServer::ClangCodeModelServer() : documents(projects, unsavedFiles) - , updateDocumentAnnotationsTimeOutInMs(1500) { updateDocumentAnnotationsTimer.setSingleShot(true); - QObject::connect(&updateDocumentAnnotationsTimer, &QTimer::timeout, [this]() { processJobsForDirtyAndVisibleDocuments(); }); + updateVisibleButNotCurrentDocumentsTimer.setSingleShot(true); + QObject::connect(&updateVisibleButNotCurrentDocumentsTimer, + &QTimer::timeout, + [this]() { + processJobsForDirtyAndVisibleButNotCurrentDocuments(); + }); + QObject::connect(documents.clangFileSystemWatcher(), &ClangFileSystemWatcher::fileChanged, [this](const Utf8String &filePath) { @@ -265,16 +272,44 @@ bool ClangCodeModelServer::isTimerRunningForTestOnly() const void ClangCodeModelServer::processJobsForDirtyAndVisibleDocuments() { - for (const auto &document : documents.documents()) { - if (document.isNeedingReparse() && document.isVisibleInEditor()) { - DocumentProcessor processor = documentProcessors().processor(document); - processor.addJob(createJobRequest(document, - JobRequest::Type::UpdateDocumentAnnotations, - PreferredTranslationUnit::PreviouslyParsed)); - } - } + processJobsForDirtyCurrentDocument(); + processTimerForVisibleButNotCurrentDocuments(); +} - documentProcessors().process(); +void ClangCodeModelServer::processJobsForDirtyCurrentDocument() +{ + const auto currentDirtyDocuments = documents.filtered([](const Document &document) { + return document.isNeedingReparse() && document.isUsedByCurrentEditor(); + }); + QTC_CHECK(currentDirtyDocuments.size() <= 1); + + addAndRunUpdateJobs(currentDirtyDocuments); +} + +void ClangCodeModelServer::addAndRunUpdateJobs(const std::vector &documents) +{ + for (const auto &document : documents) { + DocumentProcessor processor = documentProcessors().processor(document); + processor.addJob(createJobRequest(document, + JobRequest::Type::UpdateDocumentAnnotations, + PreferredTranslationUnit::PreviouslyParsed)); + processor.process(); + } +} + +void ClangCodeModelServer::processTimerForVisibleButNotCurrentDocuments() +{ + if (documents.dirtyAndVisibleButNotCurrentDocuments().empty()) { + updateVisibleButNotCurrentDocumentsTimer.stop(); + } else { + updateVisibleButNotCurrentDocumentsTimer.start( + updateVisibleButNotCurrentDocumentsTimeOutInMs); + } +} + +void ClangCodeModelServer::processJobsForDirtyAndVisibleButNotCurrentDocuments() +{ + addAndRunUpdateJobs(documents.dirtyAndVisibleButNotCurrentDocuments()); } void ClangCodeModelServer::processInitialJobsForDocuments(const std::vector &documents) @@ -332,6 +367,11 @@ void ClangCodeModelServer::setUpdateDocumentAnnotationsTimeOutInMsForTestsOnly(i updateDocumentAnnotationsTimeOutInMs = value; } +void ClangCodeModelServer::setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(int value) +{ + updateVisibleButNotCurrentDocumentsTimeOutInMs = value; +} + DocumentProcessors &ClangCodeModelServer::documentProcessors() { if (!documentProcessors_) { diff --git a/src/tools/clangbackend/ipcsource/clangcodemodelserver.h b/src/tools/clangbackend/ipcsource/clangcodemodelserver.h index ab4efdb7e29..b03b4327faf 100644 --- a/src/tools/clangbackend/ipcsource/clangcodemodelserver.h +++ b/src/tools/clangbackend/ipcsource/clangcodemodelserver.h @@ -65,16 +65,22 @@ public: // for tests int queueSizeForTestsOnly(); bool isTimerRunningForTestOnly() const; void setUpdateDocumentAnnotationsTimeOutInMsForTestsOnly(int value); + void setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(int value); DocumentProcessors &documentProcessors(); private: - void startDocumentAnnotationsTimerIfFileIsNotOpenAsDocument(const Utf8String &filePath); - void addJobRequestsForDirtyAndVisibleDocuments(); - void processJobsForDirtyAndVisibleDocuments(); + void processInitialJobsForDocuments(const std::vector &documents); void startInitializingSupportiveTranslationUnits(const std::vector &documents); + void processJobsForDirtyAndVisibleDocuments(); + void processJobsForDirtyCurrentDocument(); + void processTimerForVisibleButNotCurrentDocuments(); + void processJobsForDirtyAndVisibleButNotCurrentDocuments(); + + void addAndRunUpdateJobs(const std::vector &documents); + JobRequest createJobRequest(const Document &document, JobRequest::Type type, PreferredTranslationUnit preferredTranslationUnit @@ -88,7 +94,10 @@ private: QScopedPointer documentProcessors_; // Delayed initialization QTimer updateDocumentAnnotationsTimer; - int updateDocumentAnnotationsTimeOutInMs; + int updateDocumentAnnotationsTimeOutInMs = 1500; + + QTimer updateVisibleButNotCurrentDocumentsTimer; + int updateVisibleButNotCurrentDocumentsTimeOutInMs = 2000; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangdocuments.cpp b/src/tools/clangbackend/ipcsource/clangdocuments.cpp index 6077505b573..3c77089447a 100644 --- a/src/tools/clangbackend/ipcsource/clangdocuments.cpp +++ b/src/tools/clangbackend/ipcsource/clangdocuments.cpp @@ -33,6 +33,8 @@ #include #include +#include + #include #include @@ -143,6 +145,20 @@ const std::vector &Documents::documents() const return documents_; } +const std::vector Documents::filtered(const IsMatchingDocument &isMatchingDocument) const +{ + return Utils::filtered(documents_, isMatchingDocument); +} + +std::vector Documents::dirtyAndVisibleButNotCurrentDocuments() const +{ + return filtered([](const Document &document) { + return document.isNeedingReparse() + && document.isVisibleInEditor() + && !document.isUsedByCurrentEditor(); + }); +} + UnsavedFiles Documents::unsavedFiles() const { return unsavedFiles_; diff --git a/src/tools/clangbackend/ipcsource/clangdocuments.h b/src/tools/clangbackend/ipcsource/clangdocuments.h index 90c905f16c4..dc1699178aa 100644 --- a/src/tools/clangbackend/ipcsource/clangdocuments.h +++ b/src/tools/clangbackend/ipcsource/clangdocuments.h @@ -32,6 +32,7 @@ #include +#include #include namespace ClangBackEnd { @@ -57,6 +58,9 @@ public: bool hasDocumentWithFilePath(const Utf8String &filePath) const; const std::vector &documents() const; + using IsMatchingDocument = std::function; + const std::vector filtered(const IsMatchingDocument &isMatchingDocument) const; + std::vector dirtyAndVisibleButNotCurrentDocuments() const; UnsavedFiles unsavedFiles() const; diff --git a/tests/unit/unittest/clangdocuments-test.cpp b/tests/unit/unittest/clangdocuments-test.cpp index 58159924413..d4a6a0b1e55 100644 --- a/tests/unit/unittest/clangdocuments-test.cpp +++ b/tests/unit/unittest/clangdocuments-test.cpp @@ -289,6 +289,42 @@ TEST_F(Documents, HasNotDocument) ASSERT_FALSE(documents.hasDocument(filePath, projectPartId)); } +TEST_F(Documents, FilteredPositive) +{ + documents.create({{filePath, projectPartId}}); + const auto isMatchingFilePath = [this](const Document &document) { + return document.filePath() == filePath; + }; + + const bool hasMatches = !documents.filtered(isMatchingFilePath).empty(); + + ASSERT_TRUE(hasMatches); +} + +TEST_F(Documents, FilteredNegative) +{ + documents.create({{filePath, projectPartId}}); + const auto isMatchingNothing = [](const Document &) { + return false; + }; + + const bool hasMatches = !documents.filtered(isMatchingNothing).empty(); + + ASSERT_FALSE(hasMatches); +} + +TEST_F(Documents, DirtyAndVisibleButNotCurrentDocuments) +{ + documents.create({{filePath, projectPartId}}); + documents.updateDocumentsWithChangedDependency(filePath); + documents.setVisibleInEditors({filePath}); + documents.setUsedByCurrentEditor(Utf8String()); + + const bool hasMatches = !documents.dirtyAndVisibleButNotCurrentDocuments().empty(); + + ASSERT_TRUE(hasMatches); +} + TEST_F(Documents, isUsedByCurrentEditor) { documents.create({fileContainer}); diff --git a/tests/unit/unittest/clangipcserver-test.cpp b/tests/unit/unittest/clangipcserver-test.cpp index bcff6e95327..2a3c75dc2ac 100644 --- a/tests/unit/unittest/clangipcserver-test.cpp +++ b/tests/unit/unittest/clangipcserver-test.cpp @@ -375,6 +375,7 @@ void ClangClangCodeModelServer::SetUp() { clangServer.setClient(&mockClangCodeModelClient); clangServer.setUpdateDocumentAnnotationsTimeOutInMsForTestsOnly(0); + clangServer.setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(0); } void ClangClangCodeModelServer::TearDown() From 1fd5cd4dbcc892c68fa8e3f415293a500d291f93 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 17 Oct 2016 15:12:05 +0200 Subject: [PATCH 04/53] Clang: Use compiler specific undefine option libclang generated: warning: /U__cpp_aggregate_nsdmi: 'linker' input unused [-Wunused-command-line-argument] warning: /U__cpp_alias_templates: 'linker' input unused [-Wunused-command-line-argument] ... It needs -U. Change-Id: Ibbd2f97e6f806215e3008803f57608b9b6b4c641 Reviewed-by: Christian Kandeler --- .../clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp | 7 +++++++ src/plugins/cpptools/compileroptionsbuilder.cpp | 7 ++++++- src/plugins/cpptools/compileroptionsbuilder.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 75f4f025736..1ead54a811a 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -263,6 +263,13 @@ private: return CompilerOptionsBuilder::defineOption(); } + QString undefineOption() const override + { + if (m_isMsvcToolchain) + return QLatin1String("/U"); + return CompilerOptionsBuilder::undefineOption(); + } + void enableExceptions() override { if (m_isMsvcToolchain) diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 6f2991fea06..f3b89c27f6b 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -342,7 +342,7 @@ void CompilerOptionsBuilder::undefineCppLanguageFeatureMacrosForMsvc2015() // Undefine the language feature macros that are pre-defined in clang-cl 3.8.0, // but not in MSVC2015's cl.exe. foreach (const QString ¯oName, languageFeatureMacros()) - m_options.append(QLatin1String("/U") + macroName); + m_options.append(undefineOption() + macroName); } } @@ -364,6 +364,11 @@ QString CompilerOptionsBuilder::defineOption() const return QLatin1String("-D"); } +QString CompilerOptionsBuilder::undefineOption() const +{ + return QLatin1String("-U"); +} + static bool isGccOrMinGwToolchain(const Core::Id &toolchainType) { return toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index 34c7103f1b5..a4aec5afdd9 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -60,6 +60,7 @@ protected: virtual bool excludeHeaderPath(const QString &headerPath) const; virtual QString defineOption() const; + virtual QString undefineOption() const; virtual QString includeOption() const; const ProjectPart m_projectPart; From ddf1072d53dce57eca9219f8cdd55c22b8d9d142 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 18 Oct 2016 13:40:44 +0200 Subject: [PATCH 05/53] TextEditor: Tweak the refactoroverlay painting for HighDPI The lightbulb was slightly scaled up on HighDPI. Change-Id: Iea00532ebbf93ce185651ec01364efdbd924a067 Reviewed-by: David Schulz --- src/plugins/texteditor/refactoroverlay.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/texteditor/refactoroverlay.cpp b/src/plugins/texteditor/refactoroverlay.cpp index cc7fd3cebf9..dbce3755981 100644 --- a/src/plugins/texteditor/refactoroverlay.cpp +++ b/src/plugins/texteditor/refactoroverlay.cpp @@ -81,9 +81,10 @@ void RefactorOverlay::paintMarker(const RefactorMarker& marker, QPainter *painte if (icon.isNull()) icon = m_icon; + const qreal devicePixelRatio = painter->device()->devicePixelRatio(); const QSize proposedIconSize = QSize(m_editor->fontMetrics().width(QLatin1Char(' ')) + 3, - cursorRect.height()); - const QSize actualIconSize = icon.actualSize(proposedIconSize); + cursorRect.height()) * devicePixelRatio; + const QSize actualIconSize = icon.actualSize(proposedIconSize) / devicePixelRatio; const int y = cursorRect.top() + ((cursorRect.height() - actualIconSize.height()) / 2); const int x = cursorRect.right(); From b0a49ca1c1ad6a37bb0f6b4500d6a0625238abb6 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 17 Oct 2016 17:15:15 +0200 Subject: [PATCH 06/53] Clang: Fix parsing MSVC's crtdefs.h for 64 Bit ...by specifying the word width, as for the Clang Static Analyzer. This has gone unnoticed so far because it looks like that the error diagnostic from the bug report can be extracted with libclang (as shown in the info bar), but is not printed from libclang or clang.exe itself. Task-number: QTCREATORBUG-17130 Change-Id: Ia7a5ee3825c7211cdf80c2166a9eb454ce48cac1 Reviewed-by: David Schulz Reviewed-by: Christian Kandeler --- src/plugins/clangcodemodel/clangutils.cpp | 1 + .../refactoringcompileroptionsbuilder.cpp | 1 + .../clangstaticanalyzerruncontrol.cpp | 38 ++++++++----------- .../clangstaticanalyzerruncontrol.h | 7 +--- .../cpptools/compileroptionsbuilder.cpp | 8 ++++ src/plugins/cpptools/compileroptionsbuilder.h | 1 + src/plugins/cpptools/projectpart.cpp | 1 + src/plugins/cpptools/projectpart.h | 6 +++ src/plugins/cpptools/projectpartbuilder.cpp | 3 ++ 9 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index ae1e74020e6..943b731d907 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -89,6 +89,7 @@ public: LibClangOptionsBuilder optionsBuilder(*projectPart.data()); + optionsBuilder.addWordWidth(); optionsBuilder.addTargetTriple(); optionsBuilder.addLanguageOption(fileKind); optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); diff --git a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp index 372cf1af150..64feefa576f 100644 --- a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp +++ b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp @@ -124,6 +124,7 @@ Utils::SmallStringVector RefactoringCompilerOptionsBuilder::build(CppTools::Proj RefactoringCompilerOptionsBuilder optionsBuilder(projectPart); + optionsBuilder.addWordWidth(); optionsBuilder.addTargetTriple(); optionsBuilder.addLanguageOption(fileKind); optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 1ead54a811a..1577db6bec0 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -86,18 +86,18 @@ ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl( ToolChain *toolChain = ToolChainKitInformation::toolChain(target->kit(), ToolChain::Language::Cxx); QTC_ASSERT(toolChain, return); - m_extraToolChainInfo.wordWidth = toolChain->targetAbi().wordWidth(); - m_extraToolChainInfo.targetTriple = toolChain->originalTargetTriple(); + m_targetTriple = toolChain->originalTargetTriple(); } -static void prependWordWidthArgumentIfNotIncluded(QStringList *arguments, unsigned char wordWidth) +static void prependWordWidthArgumentIfNotIncluded(QStringList *arguments, + ProjectPart::ToolChainWordWidth wordWidth) { QTC_ASSERT(arguments, return); const QString m64Argument = QLatin1String("-m64"); const QString m32Argument = QLatin1String("-m32"); - const QString argument = wordWidth == 64 ? m64Argument : m32Argument; + const QString argument = wordWidth == ProjectPart::WordWidth64Bit ? m64Argument : m32Argument; if (!arguments->contains(argument)) arguments->prepend(argument); @@ -165,11 +165,11 @@ class ClangStaticAnalyzerOptionsBuilder : public CompilerOptionsBuilder { public: static QStringList build(const CppTools::ProjectPart &projectPart, - CppTools::ProjectFile::Kind fileKind, - const ExtraToolChainInfo &extraParams) + CppTools::ProjectFile::Kind fileKind) { ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart); + optionsBuilder.addWordWidth(); optionsBuilder.addTargetTriple(); optionsBuilder.addLanguageOption(fileKind); optionsBuilder.addOptionsForLanguage(false); @@ -195,10 +195,7 @@ public: if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) optionsBuilder.add(QLatin1String("-fPIC")); // TODO: Remove? - QStringList options = optionsBuilder.options(); - prependWordWidthArgumentIfNotIncluded(&options, extraParams.wordWidth); - - return options; + return optionsBuilder.options(); } ClangStaticAnalyzerOptionsBuilder(const CppTools::ProjectPart &projectPart) @@ -325,11 +322,11 @@ static QStringList createHeaderPathsOptionsForClangOnMac(const ProjectPart &proj static QStringList tweakedArguments(const ProjectPart &projectPart, const QString &filePath, const QStringList &arguments, - const ExtraToolChainInfo &extraParams) + const QString &targetTriple) { QStringList newArguments = inputAndOutputArgumentsRemoved(filePath, arguments); - prependWordWidthArgumentIfNotIncluded(&newArguments, extraParams.wordWidth); - prependTargetTripleIfNotIncludedAndNotEmpty(&newArguments, extraParams.targetTriple); + prependWordWidthArgumentIfNotIncluded(&newArguments, projectPart.toolChainWordWidth); + prependTargetTripleIfNotIncludedAndNotEmpty(&newArguments, targetTriple); newArguments.append(createHeaderPathsOptionsForClangOnMac(projectPart)); newArguments.append(createMsCompatibilityVersionOption(projectPart)); newArguments.append(createOptionsToUndefineClangVersionMacrosForMsvc(projectPart)); @@ -341,7 +338,7 @@ static QStringList tweakedArguments(const ProjectPart &projectPart, static AnalyzeUnits unitsToAnalyzeFromCompilerCallData( const QHash &projectFileToProjectPart, const ProjectInfo::CompilerCallData &compilerCallData, - const ExtraToolChainInfo &extraParams) + const QString &targetTriple) { qCDebug(LOG) << "Taking arguments for analyzing from CompilerCallData."; @@ -361,7 +358,7 @@ static AnalyzeUnits unitsToAnalyzeFromCompilerCallData( const QStringList arguments = tweakedArguments(*projectPart, file, options, - extraParams); + targetTriple); unitsToAnalyze << AnalyzeUnit(file, arguments); } } @@ -370,8 +367,7 @@ static AnalyzeUnits unitsToAnalyzeFromCompilerCallData( return unitsToAnalyze; } -static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QList projectParts, - const ExtraToolChainInfo &extraParams) +static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QList projectParts) { qCDebug(LOG) << "Taking arguments for analyzing from ProjectParts."; @@ -387,9 +383,7 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QList QTC_CHECK(file.kind != ProjectFile::Unclassified); if (ProjectFile::isSource(file.kind)) { const QStringList arguments - = ClangStaticAnalyzerOptionsBuilder::build(*projectPart.data(), - file.kind, - extraParams); + = ClangStaticAnalyzerOptionsBuilder::build(*projectPart.data(), file.kind); unitsToAnalyze << AnalyzeUnit(file.path, arguments); } } @@ -418,13 +412,13 @@ AnalyzeUnits ClangStaticAnalyzerRunControl::sortedUnitsToAnalyze() AnalyzeUnits units; const ProjectInfo::CompilerCallData compilerCallData = m_projectInfo.compilerCallData(); if (compilerCallData.isEmpty()) { - units = unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts(), m_extraToolChainInfo); + units = unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts()); } else { const QHash projectFileToProjectPart = generateProjectFileToProjectPartMapping(m_projectInfo.projectParts()); units = unitsToAnalyzeFromCompilerCallData(projectFileToProjectPart, compilerCallData, - m_extraToolChainInfo); + m_targetTriple); } Utils::sort(units, &AnalyzeUnit::file); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h index 18deebfcbd3..ce974bac37f 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h @@ -47,11 +47,6 @@ struct AnalyzeUnit { }; typedef QList AnalyzeUnits; -struct ExtraToolChainInfo { - unsigned char wordWidth = 0; - QString targetTriple; -}; - class ClangStaticAnalyzerRunControl : public ProjectExplorer::RunControl { Q_OBJECT @@ -88,7 +83,7 @@ private: private: const CppTools::ProjectInfo m_projectInfo; - ExtraToolChainInfo m_extraToolChainInfo; + QString m_targetTriple; Utils::Environment m_environment; QString m_clangExecutable; diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index f3b89c27f6b..68a2586c0d4 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -87,6 +87,14 @@ void CompilerOptionsBuilder::addDefine(const QByteArray &defineDirective) m_options.append(defineDirectiveToDefineOption(defineDirective)); } +void CompilerOptionsBuilder::addWordWidth() +{ + const QString argument = m_projectPart.toolChainWordWidth == ProjectPart::WordWidth64Bit + ? QLatin1String("-m64") + : QLatin1String("-m32"); + add(argument); +} + void CompilerOptionsBuilder::addTargetTriple() { if (!m_projectPart.targetTriple.isEmpty()) { diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index a4aec5afdd9..e1ec557d835 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -44,6 +44,7 @@ public: void addDefine(const QByteArray &defineDirective); // Add options based on project part + void addWordWidth(); virtual void addTargetTriple(); virtual void enableExceptions(); void addHeaderPathOptions(); diff --git a/src/plugins/cpptools/projectpart.cpp b/src/plugins/cpptools/projectpart.cpp index 85ea324c9f8..921d981a611 100644 --- a/src/plugins/cpptools/projectpart.cpp +++ b/src/plugins/cpptools/projectpart.cpp @@ -32,6 +32,7 @@ namespace CppTools { ProjectPart::ProjectPart() : project(0) + , toolChainWordWidth(WordWidth32Bit) , isMsvc2015Toolchain(false) , languageVersion(CXX14) , languageExtensions(NoExtensions) diff --git a/src/plugins/cpptools/projectpart.h b/src/plugins/cpptools/projectpart.h index b18a57e1497..ea45720589c 100644 --- a/src/plugins/cpptools/projectpart.h +++ b/src/plugins/cpptools/projectpart.h @@ -81,6 +81,11 @@ public: // Types Qt5 = 2 }; + enum ToolChainWordWidth { + WordWidth32Bit, + WordWidth64Bit, + }; + using Ptr = QSharedPointer; @@ -103,6 +108,7 @@ public: // fields QByteArray projectDefines; QByteArray toolchainDefines; Core::Id toolchainType; + ToolChainWordWidth toolChainWordWidth; bool isMsvc2015Toolchain; QString targetTriple; ProjectPartHeaderPaths headerPaths; diff --git a/src/plugins/cpptools/projectpartbuilder.cpp b/src/plugins/cpptools/projectpartbuilder.cpp index b01795f9cf2..98169f7d230 100644 --- a/src/plugins/cpptools/projectpartbuilder.cpp +++ b/src/plugins/cpptools/projectpartbuilder.cpp @@ -343,6 +343,9 @@ void ProjectPartBuilder::evaluateProjectPartToolchain( projectPart->toolchainType = toolChain->typeId(); projectPart->isMsvc2015Toolchain = toolChain->targetAbi().osFlavor() == ProjectExplorer::Abi::WindowsMsvc2015Flavor; + projectPart->toolChainWordWidth = toolChain->targetAbi().wordWidth() == 64 + ? ProjectPart::WordWidth64Bit + : ProjectPart::WordWidth32Bit; projectPart->targetTriple = targetTriple(projectPart->project, toolChain->typeId()); projectPart->updateLanguageFeatures(); } From 57ac8d96c76b322c1b28c0cd4ed1d13e7b6056d2 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 17 Oct 2016 12:06:35 +0200 Subject: [PATCH 07/53] Clang: Avoid running into gcc/mingw intrinsics Same as for the Clang Static Analyzer, so move the implementation into the base class and use it. This has gone unnoticed so far because it looks like that the error diagnostic from the bug report can be extracted with libclang (as shown in the info bar), but is not printed from libclang or clang.exe itself. Change-Id: I5b714ba374c5fdefe234faf012a3515e96c9a08c Reviewed-by: Christian Kandeler --- src/plugins/clangcodemodel/clangutils.cpp | 1 + .../refactoringcompileroptionsbuilder.cpp | 1 + .../clangstaticanalyzerruncontrol.cpp | 9 +-------- src/plugins/cpptools/compileroptionsbuilder.cpp | 14 ++++++++++++++ src/plugins/cpptools/compileroptionsbuilder.h | 2 ++ 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 943b731d907..573d1be1fd1 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -95,6 +95,7 @@ public: optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); optionsBuilder.enableExceptions(); + optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); optionsBuilder.addToolchainAndProjectDefines(); optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); diff --git a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp index 64feefa576f..ca79ca5e4ab 100644 --- a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp +++ b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp @@ -130,6 +130,7 @@ Utils::SmallStringVector RefactoringCompilerOptionsBuilder::build(CppTools::Proj optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); optionsBuilder.enableExceptions(); + optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); optionsBuilder.addToolchainAndProjectDefines(); optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 1577db6bec0..4185b6bfaa0 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -175,15 +175,8 @@ public: optionsBuilder.addOptionsForLanguage(false); optionsBuilder.enableExceptions(); - // In gcc headers, lots of built-ins are referenced that clang does not understand. - // Therefore, prevent the inclusion of the header that references them. Of course, this - // will break if code actually requires stuff from there, but that should be the less common - // case. + optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); const Core::Id type = projectPart.toolchainType; - if (type == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID - || type == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID) - optionsBuilder.addDefine("#define _X86INTRIN_H_INCLUDED"); - if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) optionsBuilder.addDefines(projectPart.toolchainDefines); optionsBuilder.addDefines(projectPart.projectDefines); diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 68a2586c0d4..c62feb94cd2 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -270,6 +270,20 @@ void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtension m_options.append(opts); } +void CompilerOptionsBuilder::addDefineToAvoidIncludingGccOrMinGwIntrinsics() +{ + // In gcc headers, lots of built-ins are referenced that clang does not understand. + // Therefore, prevent the inclusion of the header that references them. Of course, this + // will break if code actually requires stuff from there, but that should be the less common + // case. + + const Core::Id type = m_projectPart.toolchainType; + if (type == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID + || type == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID) { + addDefine("#define _X86INTRIN_H_INCLUDED"); + } +} + static QByteArray toMsCompatibilityVersionFormat(const QByteArray &mscFullVer) { return mscFullVer.left(2) diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index e1ec557d835..4cae4bb353d 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -53,6 +53,8 @@ public: virtual void addLanguageOption(ProjectFile::Kind fileKind); virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true); + void addDefineToAvoidIncludingGccOrMinGwIntrinsics(); + void addMsvcCompatibilityVersion(); void undefineCppLanguageFeatureMacrosForMsvc2015(); From df581265c3ff379389fa2000c11c1d9a39f680fa Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 17 Oct 2016 11:51:13 +0200 Subject: [PATCH 08/53] Clang*: Workaround parsing mingw's with clang 3.9 ...for -std=gnu++0x. Define the unknown identifier/type "__float128" so at least the headers can be parsed successfully. Of course this does not help for parsing client code referencing that identifier, but this should be the less common case. Task-number: QTCREATORBUG-17126 Change-Id: Id321311713029d8aa77e068b02361d86debfada6 Reviewed-by: Christian Kandeler --- src/plugins/clangcodemodel/clangutils.cpp | 1 + .../refactoringcompileroptionsbuilder.cpp | 1 + .../clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp | 1 + src/plugins/cpptools/compileroptionsbuilder.cpp | 8 ++++++++ src/plugins/cpptools/compileroptionsbuilder.h | 2 ++ 5 files changed, 13 insertions(+) diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 573d1be1fd1..1d704c8a88b 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -96,6 +96,7 @@ public: optionsBuilder.enableExceptions(); optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); + optionsBuilder.addDefineFloat128ForMingw(); optionsBuilder.addToolchainAndProjectDefines(); optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); diff --git a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp index ca79ca5e4ab..5fa28940f5a 100644 --- a/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp +++ b/src/plugins/clangrefactoring/refactoringcompileroptionsbuilder.cpp @@ -130,6 +130,7 @@ Utils::SmallStringVector RefactoringCompilerOptionsBuilder::build(CppTools::Proj optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true); optionsBuilder.enableExceptions(); + optionsBuilder.addDefineFloat128ForMingw(); optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); optionsBuilder.addToolchainAndProjectDefines(); optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 4185b6bfaa0..10cb6115ba5 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -175,6 +175,7 @@ public: optionsBuilder.addOptionsForLanguage(false); optionsBuilder.enableExceptions(); + optionsBuilder.addDefineFloat128ForMingw(); optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics(); const Core::Id type = projectPart.toolchainType; if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index c62feb94cd2..a2b2ed3ba68 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -368,6 +368,14 @@ void CompilerOptionsBuilder::undefineCppLanguageFeatureMacrosForMsvc2015() } } +void CompilerOptionsBuilder::addDefineFloat128ForMingw() +{ + // TODO: Remove once this is fixed in clang >= 3.9. + // https://llvm.org/bugs/show_bug.cgi?id=30685 + if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) + addDefine("#define __float128 void"); +} + QString CompilerOptionsBuilder::includeOption() const { return QLatin1String("-I"); diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index 4cae4bb353d..ced3c0af1ba 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -58,6 +58,8 @@ public: void addMsvcCompatibilityVersion(); void undefineCppLanguageFeatureMacrosForMsvc2015(); + void addDefineFloat128ForMingw(); + protected: virtual bool excludeDefineDirective(const QByteArray &defineDirective) const; virtual bool excludeHeaderPath(const QString &headerPath) const; From 69486b5a5dae388e4905450fb87a22193e7a20bc Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 18 Oct 2016 17:33:06 +0200 Subject: [PATCH 09/53] Utils: Add a "snapshot" icon Change-Id: Ife531bb493aa22db660e73d9e5b89bc882fac610 Reviewed-by: Alessandro Portale --- src/libs/utils/images/snapshot.png | Bin 0 -> 148 bytes src/libs/utils/images/snapshot@2x.png | Bin 0 -> 250 bytes src/libs/utils/utils.qrc | 2 ++ src/libs/utils/utilsicons.cpp | 2 ++ src/libs/utils/utilsicons.h | 1 + src/tools/icons/qtcreatoricons.svg | 41 ++++++++++++++++++++++++++ 6 files changed, 46 insertions(+) create mode 100644 src/libs/utils/images/snapshot.png create mode 100644 src/libs/utils/images/snapshot@2x.png diff --git a/src/libs/utils/images/snapshot.png b/src/libs/utils/images/snapshot.png new file mode 100644 index 0000000000000000000000000000000000000000..c8a731d41e10d6e23d69b2682962900884e7f247 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqM0>h8hDc0J{?X4SQNXEU zV4!k<<<;xg|Mf5b`{i5D=+eN*+Q1Uv+raf#W9k&0-<>J}uf9Inm~J_#;mPFx|K&Xu zxozBpH9psTIkA}O<^?0om0UX(zPPr?x@ST@Bm2Bo(-;!A zM+q=82)sPNwwbwdPV#TgCpUh(>=HlVkj!ZMmwDcbZsx-gs&o0~*zAl7$+}QkaC)1r zOh+7N(hl)SYjT%(2`rd$y12zF;n7EL-ZhB@R~r~wS**`?vH1B;`pPs@sD!EPp2=_4 zny;pjoIeBp&CEJr$LpIt_v;_FSI3xZA0H?XZm?c@>*j9b<4XDimages/iconoverlay_warning_background@2x.png images/bookmark.png images/bookmark@2x.png + images/snapshot.png + images/snapshot@2x.png diff --git a/src/libs/utils/utilsicons.cpp b/src/libs/utils/utilsicons.cpp index 2117acb09cb..e81aa34af7f 100644 --- a/src/libs/utils/utilsicons.cpp +++ b/src/libs/utils/utilsicons.cpp @@ -63,6 +63,8 @@ const Icon BOOKMARK_TOOLBAR({ {QLatin1String(":/utils/images/bookmark.png"), Theme::IconsBaseColor}}); const Icon BOOKMARK_TEXTEDITOR({ {QLatin1String(":/utils/images/bookmark.png"), Theme::Bookmarks_TextMarkColor}}, Icon::Tint); +const Icon SNAPSHOT_TOOLBAR({ + {QLatin1String(":/utils/images/snapshot.png"), Theme::IconsBaseColor}}); const Icon NEWFILE({ {QLatin1String(":/utils/images/filenew.png"), Theme::PanelTextColorMid}}, Icon::Tint); diff --git a/src/libs/utils/utilsicons.h b/src/libs/utils/utilsicons.h index 24c99bfb2bd..8a1dc4ed04c 100644 --- a/src/libs/utils/utilsicons.h +++ b/src/libs/utils/utilsicons.h @@ -48,6 +48,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon ERROR; QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK; QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TEXTEDITOR; +QTCREATOR_UTILS_EXPORT extern const Icon SNAPSHOT_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon NEWFILE; QTCREATOR_UTILS_EXPORT extern const Icon OPENFILE; diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index 4b03178b5ef..a16c374fb5d 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -3633,6 +3633,47 @@ inkscape:connector-curvature="0" sodipodi:nodetypes="ccc" /> + + + + + + + + Date: Tue, 18 Oct 2016 13:47:22 +0200 Subject: [PATCH 10/53] TextEditor: Improved lightbulb icon Hopefully now looks more like a light bulb than like an ice cream. Change-Id: Icc27fe786ea0cc1ca8c504ea6e766cb7d54e5050 Reviewed-by: Alessandro Portale --- src/plugins/texteditor/images/lightbulb.png | Bin 167 -> 124 bytes src/plugins/texteditor/images/lightbulb@2x.png | Bin 175 -> 175 bytes src/plugins/texteditor/images/lightbulbcap.png | Bin 115 -> 119 bytes .../texteditor/images/lightbulbcap@2x.png | Bin 126 -> 138 bytes src/tools/icons/qtcreatoricons.svg | 16 +++++++++++----- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/plugins/texteditor/images/lightbulb.png b/src/plugins/texteditor/images/lightbulb.png index 3f2e904000d85fe12bf661010dc0db243a2d1cb2..153d95a9368f655842893fa2a9fbbcc2f79da9ef 100644 GIT binary patch delta 106 zcmZ3^STjK)g@b{CfgzdI`3M68gR`fLV+cod@{j-Z-LmG}?@s&wU-IAi{dm4ShQ!PC{xWt~$( F69B7^GT{IK diff --git a/src/plugins/texteditor/images/lightbulb@2x.png b/src/plugins/texteditor/images/lightbulb@2x.png index ec43d8f1c1f338a7bac4e2db2146620fbed69e8c..24256e2dc9ce92abdab31c3c72a876b810c60021 100644 GIT binary patch delta 136 zcmZ3_xSnx>e!cy)_Ep8jtK0SdGd?qF=$Na;6R=>Du-cA}nT&i9V$LkMx-~1XsrZe(3u>4=Wuxn-G*&Jul9A@si$&O-^e=!w4mq|IeGvN4t sQLX`SKWqurLgTe~DS@#G0Je*ODpzcmVrwSW56vp+Lx=+JcH2~aQ*Rf{;&z~ZIQv|A$JfZ2ux%BvO# zM@$e8ogl8G(V?ZmBDTdzbPF5zId{<*2C+X2J9L))V19H?_C(X{L_03`4%Y*Ff6BaL s*tfjk;Q!*preZ3JjssSr%Q3VAo|}U|{fc^>bP0l)%^o068EtWB>pF diff --git a/src/plugins/texteditor/images/lightbulbcap.png b/src/plugins/texteditor/images/lightbulbcap.png index f860c9c408022c6b4a9ccd72db4ea723275305ed..e35b1a9bda037f5b106953dd4554f701fabf3ed0 100644 GIT binary patch delta 88 zcmXRepP&*f6yOu$%D})NA|jHOmR4V1|KrDx|NsB996S}tz`&s3>Eal|A)Cy>%E-3p t1Or>xf>R2rp$d{G6u4BJdt#j#9Ull}l%Mao$-uzC;OXk;vd$@?2>?Gt9f|+| delta 84 zcmXRfo}l8-AK(+>%D}+j;NTD%8d_gp|NsC0i>dnA3=9nNo-U3d9MQ=IjEroHJk(W1 o6<(f6U{aBlh;Vq+q^HMl=^3x*9&YxV3=9kmp00i_>zopr0C#&DlmGw# diff --git a/src/plugins/texteditor/images/lightbulbcap@2x.png b/src/plugins/texteditor/images/lightbulbcap@2x.png index 83cce03eed5d79c36e6f9f1947ee3567bf17b225..433822e1324ef7125da0f839b0247381414d2708 100644 GIT binary patch delta 108 zcmb>HVw|9oCK2Eh;>y6lAR;0X8ylOJmX@2Fd-Ukhr%#{$|No!=%}Fx`1_oVE7sn8e z=wyv{=C*^!Qy7?hmKh2p7_mx7NG$YWWn)v**nH-uitH&JelymI4DOxLzrM+J8Zt02 OFnGH9xvX delta 96 zcmeBTtec<`#UJ1k;>y6l;Nak}YSpU!`}hC<|9{c*^7#x53|gKpjv*Y;$pwwfZ3mBs zFfnONX5?7l!_LMg=A$-=No83#gYumi<}?9LhGun>P;TXPMg|5322WQ%mvv4FO#ocp B9xDI< diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index a16c374fb5d..2dfab39db74 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -3383,11 +3383,17 @@ height="11" id="rect6782-96-0-0-7-8-1-0-4-4" /> + sodipodi:nodetypes="ccccccc" /> + From 18f666aea588a5dcfb986eae7ed3949dd1015577 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 18 Oct 2016 17:49:43 +0200 Subject: [PATCH 11/53] ScxmlEditor: Use Utils::Icons::SNAPSHOT_TOOLBAR Change-Id: Ic7b873aac60bf07780a11dbcfae10dac6a81035b Reviewed-by: Alessandro Portale --- src/plugins/scxmleditor/common/common.qrc | 1 - .../scxmleditor/common/images/screenshot.png | Bin 1321 -> 0 bytes .../plugin_interface/actionhandler.cpp | 2 +- 3 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 src/plugins/scxmleditor/common/images/screenshot.png diff --git a/src/plugins/scxmleditor/common/common.qrc b/src/plugins/scxmleditor/common/common.qrc index 3106d4ae190..d0fdb605dd1 100644 --- a/src/plugins/scxmleditor/common/common.qrc +++ b/src/plugins/scxmleditor/common/common.qrc @@ -24,7 +24,6 @@ images/navigator.png images/parallel.png images/parallel_icon.png - images/screenshot.png images/state.png images/state_color.png images/statistics.png diff --git a/src/plugins/scxmleditor/common/images/screenshot.png b/src/plugins/scxmleditor/common/images/screenshot.png deleted file mode 100644 index 1f2378ab38dfd46b389f2c6bbd6e74a63fe7164e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1321 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZaGz#zuab;j&FdhY@guvwB zOI-{M45=kSe!&b3j7-cdtZbZIy!;}f;u2Ewib^UP+6IQkrgo0bu5O-Q-u?lBLE({6 z35m(6=@~hNB~`Wc4UNt1y%Q%-ojzmX%2lh^t>1R=(BUITkDs`3{m$Kc_a8of{^Ir9 zk6*ri`~LIS?>~S4**YDTVqjo)^mK6yskrraR(AO%1Br(FKBokBb{=rq(=grl_<=(K zZG7y-23JC7C^54|2mbp1ze)btP0wBTq$kPx&+ETC`-`IIWb=~@EKH3K3IZG~d=5U{ zl3^mZD*l}k)i-w%;Z4~5*SYv)X7%Ja<~Q@QN(& z3pW0Lbn$Yz{Z7sr&$VkAcM046$c;R{AoOH<(!&Cs$?LbUiLmaATl<*f!Dac$kGeD0 zi>P|Ld+&YO)OFzL-+FI}rrpciTGRhloysWkzWUpki%EXn^Z=Ip-cwpdM+~kzG6+U~ z)c+t+J!MB^QIPM9Wlz>W4); zV_wxch8InKtUO^?$@IsblWG{5IF4;DN?($>xNlA``}%o_D(WGut0t}MWZo%dcIEii z7>DbwK~tACOuA6&uxsTc!7SsouUlH2{1en(Yw7dkv+;6Uc~-jlE|5R?+AScgchMCi zNzs>=g(9wOoF(XRQ)dH@OG2%qXTmI{WATor+#%dYJbZjLIlpw=pDH(N`x^t_mTwxI zQ$B2PxcusK7Tbp#LaK~P|Ie%pW6J6~5%Q9Q=fjGGvsIJUvwnQRDB36{C%QfI)$u}` zU9PSRn%q<02KDO5#V%BupuWu9nlb6pnP9;a4+3Sa8~NnsE>sdYyx6UbN!iBA%~c_1 zW3T~3Ki_|OraQYEek(lrCs{PVV~79IJL1akP8J@cOBL~9+qw2?TwP_Z=d}?X)VjK^}-ym f1kc3%k7?<50k7FB%oQ0J7#KWV{an^LB{Ts5FZ=~y diff --git a/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp b/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp index d2cfe7f5ff6..9024bc1f340 100644 --- a/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp +++ b/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp @@ -55,7 +55,7 @@ ActionHandler::ActionHandler(QObject *parent) { Utils::Icon({{":/utils/images/editcopy.png", Utils::Theme::IconsBaseColor}}), AH::tr("Copy"), AH::tr("Copy (Ctrl + C)"), "Ctrl+C", false }, { Utils::Icon({{":/utils/images/editcut.png", Utils::Theme::IconsBaseColor}}), AH::tr("Cut"), AH::tr("Cut (Ctrl + X)"), "Ctrl+X", false }, { Utils::Icon({{":/utils/images/editpaste.png", Utils::Theme::IconsBaseColor}}), AH::tr("Paste"), AH::tr("Paste (Ctrl + V)"), "Ctrl+V", false }, - { Utils::Icon(":/scxmleditor/images/screenshot.png"), AH::tr("Screenshot"), AH::tr("Screenshot (Ctrl + Shift + C)"), "Ctrl+Shift+C", false }, + { Utils::Icons::SNAPSHOT_TOOLBAR, AH::tr("Screenshot"), AH::tr("Screenshot (Ctrl + Shift + C)"), "Ctrl+Shift+C", false }, { Utils::Icon(":/scxmleditor/images/icon-export-canvas.png"), AH::tr("Export to Image"), AH::tr("Export to Image"), "Ctrl+Shift+E", false }, { Utils::Icon(":/scxmleditor/images/fullnamespace.png"), AH::tr("Toggle Full Namespace"), AH::tr("Toggle Full Namespace"), "Ctrl+Shift+N", true }, From c465a25edc0c9e5b76e1757491023cdbb02ef0de Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 18 Oct 2016 19:21:04 +0200 Subject: [PATCH 12/53] ScxmlEditor: Themable, HighDPI-able export-canvas icon Change-Id: I966dee7c22903921d814141bc749b39dec7cf8d7 Reviewed-by: Alessandro Portale --- src/plugins/scxmleditor/common/common.qrc | 1 + .../common/images/icon-export-canvas.png | Bin 856 -> 164 bytes .../common/images/icon-export-canvas@2x.png | Bin 0 -> 256 bytes .../plugin_interface/actionhandler.cpp | 2 +- src/tools/icons/qtcreatoricons.svg | 54 ++++++++++++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/plugins/scxmleditor/common/images/icon-export-canvas@2x.png diff --git a/src/plugins/scxmleditor/common/common.qrc b/src/plugins/scxmleditor/common/common.qrc index d0fdb605dd1..49ee31ce666 100644 --- a/src/plugins/scxmleditor/common/common.qrc +++ b/src/plugins/scxmleditor/common/common.qrc @@ -15,6 +15,7 @@ images/fullnamespace.png images/history.png images/icon-export-canvas.png + images/icon-export-canvas@2x.png images/icon-fit-screen.png images/icon-pan.png images/icon-zoom-in.png diff --git a/src/plugins/scxmleditor/common/images/icon-export-canvas.png b/src/plugins/scxmleditor/common/images/icon-export-canvas.png index 4c0eca55602892540165377a6a6f92f5c23e1182..d2d47205a8f2df6cb40ad5e12472455d0fe12d17 100644 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqWP7?ehDc0J{?X4SVZc(C z5hA+Lkb&`a-HI;lm20ja)Y-V#Kv&Rc{p-dxhZ6)RG&t^5o51w4i7Voofx&@XhQ#Ux zPwIbHRqt?M_t+-KAvqyr;fjV8_y5a#GOVck|L1>(*1!Mmrp&Gkd>ej>G5j&y`|PP^ Q;XRP`p00i_>zopr0LSh;yZ`_I literal 856 zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4rT@hhHLjSRxvOz&JOSiab;j&U}k2Pl9Dnu zHkLvKT3T8V0X;oEGzIGF>QYits;a7(y42Oxjg5_EWo4zLq#(+qq@?8K<&BMvO-)VB z&CM+>Ev>AqY;0_7oLp^fZSCyr9GqPo9UUDbQ=P*T-2%hi-Q7JsJw3x>eFB2~60`l| z)BP*^f|IjDqT)i+^26ej!^6YFdzME=Mn;#lM7Pb2NzaWbtcjhpF0OHM%FL~)4SlII zx2CsE%b2u0Gcz-D&bF+o#_a6uoT;mF7VasmZ7G_xxVW~tWaW{vC40)}tgoE1uxkFM z>gwv6jc00WYisAOYiMX_oW8Je&7r2Irsf@2S~nbRo4u@U$EEh2S339J=-zOo`@o&v z-rl~wSNi8H?w_}O!r{AeXx4uHAI`@s=%H zwr<_J_0*M}J9qBhz5B?KBNs1TynOlcjT<-a-@pIh!GkAHo;-W@?A5DRZ{NQC`0?ZC z&!4}1`C{t2gr9+dL9ryrFBlX_Y@GaZD%$o=zJ7ionKM_cUbAt_;bSLn-+uDy?YEyB zX64UiU|{t2ba4!^=uJ*oV3%;^5LbX`=GCjojBYDdZMkKguz>U2s}%=Up4cvVZq1>k zD{gJvwV3&hLWt{`nnka)+{yx<>dMOInniweaFtEy2{@vrlq@)J#{8KQ8B4`32fPW% zY+2didP~PdoU7KBk z6jX0>C-FH=Y*@5tk%)D3SaQqCcoi0r66^!a}AzW?*+*xysu>Vo7A!;+ZNd zSDfJHT`t9&UoXJH+2J0nvQC4I`;3`1d$>S>zmZe0%8C=b!6A#@^Dtht`nsa)hiJsY zt|*?fxrzra@8Sp*oXn#0&gjdbq=g5Li-!s_i-!d6U1h|yVr$kzU)BJJV%Mk(5v& diff --git a/src/plugins/scxmleditor/common/images/icon-export-canvas@2x.png b/src/plugins/scxmleditor/common/images/icon-export-canvas@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bdc82b7ade6b4af26d989f7af0c0a84b07751c5c GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=#Ar_~TfA}*PTySkn zJ@)Q@p$`wof{#3|2bC90D16VUsUm8nALwIoonwm0zg7V!L*_Sa@^g83>g)x$N+yOl z$nKocsVL`h)mdbZQxIcl!0xWuiSPbbv2`^4_t09vC6T6+_&`6UL91bhNGRj&{|pl} zCNZ&vur~eY7HkUWo*-Hvzb^g2>V*CBXChd77b!60=`)9j_%cSlNz`(<;m68)L$>qH zzyG`udph6Ld5M}ZFe(cFdmPjtByF+Rb03qB!z?DQPihP`Z+`?TD3*DFyyofZ=d#Wz Gp$Py*S6EO0 literal 0 HcmV?d00001 diff --git a/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp b/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp index 9024bc1f340..076be01876b 100644 --- a/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp +++ b/src/plugins/scxmleditor/plugin_interface/actionhandler.cpp @@ -56,7 +56,7 @@ ActionHandler::ActionHandler(QObject *parent) { Utils::Icon({{":/utils/images/editcut.png", Utils::Theme::IconsBaseColor}}), AH::tr("Cut"), AH::tr("Cut (Ctrl + X)"), "Ctrl+X", false }, { Utils::Icon({{":/utils/images/editpaste.png", Utils::Theme::IconsBaseColor}}), AH::tr("Paste"), AH::tr("Paste (Ctrl + V)"), "Ctrl+V", false }, { Utils::Icons::SNAPSHOT_TOOLBAR, AH::tr("Screenshot"), AH::tr("Screenshot (Ctrl + Shift + C)"), "Ctrl+Shift+C", false }, - { Utils::Icon(":/scxmleditor/images/icon-export-canvas.png"), AH::tr("Export to Image"), AH::tr("Export to Image"), "Ctrl+Shift+E", false }, + { Utils::Icon({{":/scxmleditor/images/icon-export-canvas.png", Utils::Theme::IconsBaseColor}}), AH::tr("Export to Image"), AH::tr("Export to Image"), "Ctrl+Shift+E", false }, { Utils::Icon(":/scxmleditor/images/fullnamespace.png"), AH::tr("Toggle Full Namespace"), AH::tr("Toggle Full Namespace"), "Ctrl+Shift+N", true }, { Utils::Icon(":/scxmleditor/images/align_left.png"), AH::tr("Align Left"), AH::tr("Align Left (Ctrl+L,1)"), "Ctrl+L,1", false }, diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index 2dfab39db74..7002b7fd402 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -3680,6 +3680,60 @@ inkscape:connector-curvature="0" sodipodi:nodetypes="cc" /> + + + + + + + + + + Date: Tue, 18 Oct 2016 17:08:46 +0200 Subject: [PATCH 13/53] Doc: Use automatic linking to directly link to the type docs ...in Using QML Modules with Plugins. Change-Id: Icce8e1e2b902e593972bd9f14d118f6a5005ecb8 Reviewed-by: Thomas Hartmann --- doc/src/qtquick/qtquick-modules-with-plugins.qdoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/src/qtquick/qtquick-modules-with-plugins.qdoc b/doc/src/qtquick/qtquick-modules-with-plugins.qdoc index eab5678d641..de636b66367 100644 --- a/doc/src/qtquick/qtquick-modules-with-plugins.qdoc +++ b/doc/src/qtquick/qtquick-modules-with-plugins.qdoc @@ -43,8 +43,7 @@ information for code completion and the semantic checks to work correctly. When you write a QML module or use QML from a C++ application you typically - register new types with the \l{QQmlEngine} class \c qmlRegisterType() - function or expose some + register new types with the qmlRegisterType() function or expose some class instances with \l{QQmlContext::setContextProperty()}. The \QC C++ code model now scans for these calls and tells the QML code model about them. This means that properties are From 62ef0a1e74fc1e04fb260cfdc62f6df338689f25 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 18 Oct 2016 17:01:51 +0200 Subject: [PATCH 14/53] Doc: Add a step to add connections and bindings in Connections tab ...in Qt Quick Designer. Change-Id: Ifedb43e73eb868292d31941f432731c27320ca5e Reviewed-by: Thomas Hartmann --- doc/src/qtquick/qtquick-connection-editor.qdoc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/src/qtquick/qtquick-connection-editor.qdoc b/doc/src/qtquick/qtquick-connection-editor.qdoc index a9ff30855b1..886359d03bf 100644 --- a/doc/src/qtquick/qtquick-connection-editor.qdoc +++ b/doc/src/qtquick/qtquick-connection-editor.qdoc @@ -58,6 +58,9 @@ \li Select the \uicontrol {Connections} tab. + \li Select the \inlineimage plus.png + (\uicontrol Add) button to add a connection. + \li Select \uicontrol Target to add the object to connect to a signal. \li Select \uicontrol {Signal Handler} to select the signal that the connection @@ -105,6 +108,9 @@ \li Select the \uicontrol {Bindings} tab. + \li Select the \inlineimage plus.png + (\uicontrol Add) button to add a binding. + \li Select \uicontrol Item to select the target object whose property you want to change dynamically. From 4470c1a5a416bc3ddc2878a6c0243e3c397b9a5a Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 18 Oct 2016 15:59:00 +0200 Subject: [PATCH 15/53] Update qbs submodule To HEAD of master branch. Change-Id: I5b15266209328623f8df86102481ee9e06ab8fdc Reviewed-by: Jake Petroules --- src/shared/qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/qbs b/src/shared/qbs index 0971e0b7453..830503d0470 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 0971e0b7453439f01c72551870d8a2a140758593 +Subproject commit 830503d04708ebd6a64dfd260b35cfeea26ba60a From 8707c7bb1b95d93982ea3d20ad6af2a8f22a4d5a Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 18 Oct 2016 15:20:14 +0200 Subject: [PATCH 16/53] QbsProjectManager: Do not set up generated files for disabled products Such products are not guaranteed to have a valid build directory. Change-Id: I3e6ec211edb8fb9a13e3b785cd19b795f7adee12 Reviewed-by: Jake Petroules --- src/plugins/qbsprojectmanager/qbsnodes.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index 58dd0d23af2..28612849c0f 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -710,10 +710,12 @@ void QbsProductNode::setQbsProductData(const qbs::Project &project, const qbs::P } } - const QStringList generatedFiles - = Utils::transform(prd.generatedArtifacts(), &qbs::ArtifactData::filePath); - QbsGroupNode::setupFiles(m_generatedFilesNode, qbs::GroupData(), generatedFiles, - prd.buildDirectory(), true, true); + if (prd.isEnabled()) { + const QStringList generatedFiles + = Utils::transform(prd.generatedArtifacts(), &qbs::ArtifactData::filePath); + QbsGroupNode::setupFiles(m_generatedFilesNode, qbs::GroupData(), generatedFiles, + prd.buildDirectory(), true, true); + } addProjectNodes(toAdd); removeProjectNodes(toRemove); From cca8d6f796f1942e1044ef13c54fc7e8df8f6230 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 14 Oct 2016 16:09:16 +0200 Subject: [PATCH 17/53] CppEditor: Native dir separators in ResourcePreviewHoverHandler Change-Id: I83aaf5a0aff5f679395801ecaccad46a8ff7acb3 Reviewed-by: David Schulz --- src/plugins/cppeditor/resourcepreviewhoverhandler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp index fdb41c40f7a..7ef01db7520 100644 --- a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp +++ b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp @@ -200,7 +200,9 @@ QString ResourcePreviewHoverHandler::makeTooltip() const if (mimeType.name().startsWith("image", Qt::CaseInsensitive)) ret += QString("
").arg(m_resPath); - ret += QString("%2").arg(m_resPath).arg(m_resPath); + ret += QString("%2") + .arg(m_resPath) + .arg(QDir::toNativeSeparators(m_resPath)); } return ret; } From a97f1bd0bb93acd310469a545ff6875ada7252e9 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 18 Oct 2016 17:34:17 +0200 Subject: [PATCH 18/53] QbsProjectManager: Do not set an empty compiler name If one of the two compiler types in the Kit is not set, leave the respective value in qbs at its default. Things will likely work anyway, whereas setting an empty compiler name is guaranteed to break. Task-number: QTCREATORBUG-17109 Change-Id: I2b4153cb9a9daafb2f57659e16622e00d3921005 Reviewed-by: Jake Petroules --- src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp index 9fbeb73176f..a83e814a300 100644 --- a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp +++ b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp @@ -263,8 +263,10 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor if (toolchain.contains(QLatin1String("msvc"))) { data.insert(QLatin1String(CPP_COMPILERNAME), mainCompilerName); } else { - data.insert(QLatin1String(CPP_COMPILERNAME), cCompilerName); - data.insert(QLatin1String(CPP_CXXCOMPILERNAME), cxxCompilerName); + if (!cCompilerName.isEmpty()) + data.insert(QLatin1String(CPP_COMPILERNAME), cCompilerName); + if (!cxxCompilerName.isEmpty()) + data.insert(QLatin1String(CPP_CXXCOMPILERNAME), cxxCompilerName); } if (tcC && tcCxx && cFileInfo.absolutePath() != cxxFileInfo.absolutePath()) { From 2c8087d9baf475cc9cf3bfd3fef1807691b28a08 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Tue, 18 Oct 2016 22:53:52 +0200 Subject: [PATCH 19/53] ProjectExplorer: "Build" and "Run" icons for the projects mode tree Task-number: QTCREATORBUG-17127 Change-Id: I5db19d65eaf7bf69c39ab39bb35e7e4f34e91a6f Reviewed-by: Florian Apolloner Reviewed-by: Tobias Hunger --- .../projectexplorer/targetsettingspanel.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp index d3f557f219c..49ebd5e8564 100644 --- a/src/plugins/projectexplorer/targetsettingspanel.cpp +++ b/src/plugins/projectexplorer/targetsettingspanel.cpp @@ -34,6 +34,7 @@ #include "panelswidget.h" #include "project.h" #include "projectexplorer.h" +#include "projectexplorericons.h" #include "projectwindow.h" #include "runsettingspropertiespage.h" #include "session.h" @@ -563,8 +564,19 @@ public: case KitIdRole: return m_kitId.toSetting(); - case Qt::DecorationRole: - return Utils::Icons::EMPTY14.icon(); + case Qt::DecorationRole: { + switch (m_subIndex) { + case BuildPage: { + static const QIcon buildIcon = ProjectExplorer::Icons::BUILD_SMALL.icon(); + return buildIcon; + } + case RunPage: { + static const QIcon runIcon = Utils::Icons::RUN_SMALL.icon(); + return runIcon; + } + } + break; + } default: break; From 69663871fcb9d0e5b508e7da173604bdd1a3a65f Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 18 Oct 2016 16:35:50 +0200 Subject: [PATCH 20/53] Update documentation for connections editor We added a new tab called backends. I also updated all the screenshot, so they contain the new tab. Change-Id: Ib66ffbd3a48383f621a482241cde12caef9ca7b4 Reviewed-by: Thomas Hartmann Reviewed-by: Alessandro Portale --- doc/images/qmldesigner-backends.png | Bin 0 -> 3632 bytes doc/images/qmldesigner-bindings.png | Bin 4919 -> 3378 bytes doc/images/qmldesigner-connections.png | Bin 4606 -> 3299 bytes doc/images/qmldesigner-dynamicprops.png | Bin 4953 -> 3414 bytes .../qtquick/qtquick-connection-editor.qdoc | 51 ++++++++++++++++++ .../qtquick/qtquick-modules-with-plugins.qdoc | 3 ++ 6 files changed, 54 insertions(+) create mode 100644 doc/images/qmldesigner-backends.png diff --git a/doc/images/qmldesigner-backends.png b/doc/images/qmldesigner-backends.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e4a23d1b0c07e77e4adbb3c3c22fe68bb8f7f5 GIT binary patch literal 3632 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 literal 4919 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 E0Ky8SNdN!< diff --git a/doc/images/qmldesigner-connections.png b/doc/images/qmldesigner-connections.png index 6548e88e904fbab015a70e0bab39f696e21e759e..165385d9b2834a5541abc62820edb344cbd5a866 100644 GIT binary patch literal 3299 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 literal 4606 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 II;Vst0FeK8XaE2J literal 4953 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 rDVfB3aP|kQhm_-8!vE~ Date: Wed, 19 Oct 2016 10:40:45 +0200 Subject: [PATCH 21/53] Remove deployment of iossim tool iossim tool no longer exists and it is replaced by Xcode's simctl tool Change-Id: I4f4dbdc8b8e91663109c289b75a21dd92d966018 Reviewed-by: Christian Stenger --- scripts/deployqtHelper_mac.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/deployqtHelper_mac.sh b/scripts/deployqtHelper_mac.sh index d5b156823ae..6a5be027b61 100755 --- a/scripts/deployqtHelper_mac.sh +++ b/scripts/deployqtHelper_mac.sh @@ -129,8 +129,6 @@ if [ ! -d "$1/Contents/Frameworks/QtCore.framework" ]; then "-executable=$1/Contents/Resources/qtpromaker" \ "-executable=$1/Contents/Resources/sdktool" \ "-executable=$1/Contents/Resources/ios/iostool" \ - "-executable=$1/Contents/Resources/ios/iossim" \ - "-executable=$1/Contents/Resources/ios/iossim_1_8_2" \ "-executable=$1/Contents/Resources/buildoutputparser" \ "-executable=$1/Contents/Resources/cpaster" \ "-executable=$qbsapp" \ From 337ce07eaf4bddb06bbcece09acd9a1d5adf5c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98ystein=20Walle?= Date: Tue, 11 Oct 2016 20:56:30 +0200 Subject: [PATCH 22/53] CMake: forward-declare QDialog Without this forward declaration compiling cmakekitinformation.cpp yields a compilation error saying QDialog does not name a type. Change-Id: I55066706e9850a947cac47e6e7150928c2fc6c51 Reviewed-by: Orgad Shaneh --- src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h index 48ccf1673a8..3839750f664 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h +++ b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.h @@ -29,6 +29,7 @@ QT_BEGIN_NAMESPACE class QComboBox; +class QDialog; class QLabel; class QPlainTextEdit; class QPushButton; From ff052d713257d1c5f197a4f9cf27b6d5f0cdebeb Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 18 Oct 2016 07:35:13 +0200 Subject: [PATCH 23/53] CdbExt: Version bump Change-Id: Ia51bcb0a313ba43353b3ffe31b38ff42fabd1e8a Reviewed-by: Christian Stenger --- src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp index af259aa5460..5cf04d9441b 100644 --- a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp +++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp @@ -282,7 +282,7 @@ extern "C" HRESULT CALLBACK pid(CIDebugClient *client, PCSTR args) int token; commandTokens(args, &token); - dprintf("Qt Creator CDB extension version 4.0 %d bit.\n", + dprintf("Qt Creator CDB extension version 4.2 %d bit.\n", sizeof(void *) * 8); if (const ULONG pid = currentProcessId(client)) ExtensionContext::instance().report('R', token, 0, "pid", "%u", pid); From bc41012c7d4e552e37ae11785543b878042daab0 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 19 Oct 2016 13:29:20 +0200 Subject: [PATCH 24/53] Cdb: Fix getTypeName return value for non existing types Returning an empty null terminated char[] instead of a nullptr. This fixes usecases where the return value is implicitly converted to a std::string. Change-Id: I5a3985880632a9bcc07765f8b27329bdd1e83347 Reviewed-by: Christian Stenger Reviewed-by: David Schulz --- src/libs/qtcreatorcdbext/pytype.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libs/qtcreatorcdbext/pytype.cpp b/src/libs/qtcreatorcdbext/pytype.cpp index efa998b5cbb..9b14b6fbd8e 100644 --- a/src/libs/qtcreatorcdbext/pytype.cpp +++ b/src/libs/qtcreatorcdbext/pytype.cpp @@ -87,12 +87,14 @@ char *getTypeName(ULONG64 module, ULONG typeId) symbols->GetTypeName(module, typeId, NULL, 0, &size); if (size > 0) { typeName = new char[size]; - if (FAILED(symbols->GetTypeName(module, typeId, typeName, size, &size))) { + if (SUCCEEDED(symbols->GetTypeName(module, typeId, typeName, size, &size))) + return typeName; + else delete[] typeName; - typeName = new char[1]; - typeName[0] = 0; - } } + typeName = new char[1]; + typeName[0] = 0; + return typeName; } From 83da96189ee7226fde5410af5cb03e2e58912a76 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 19 Oct 2016 13:30:52 +0200 Subject: [PATCH 25/53] Cdb: Add python function returning all template arguments Change-Id: Ib0f2eefc63427c8b89288ec72c35c0596cd6c1d0 Reviewed-by: Christian Stenger --- src/libs/qtcreatorcdbext/pytype.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libs/qtcreatorcdbext/pytype.cpp b/src/libs/qtcreatorcdbext/pytype.cpp index 9b14b6fbd8e..7e1010a9d93 100644 --- a/src/libs/qtcreatorcdbext/pytype.cpp +++ b/src/libs/qtcreatorcdbext/pytype.cpp @@ -272,6 +272,24 @@ PyObject *type_TemplateArgument(Type *self, PyObject *args) return lookupType(innerType); } +PyObject *type_TemplateArguments(Type *self) +{ + std::vector innerTypes = innerTypesOf(getTypeName(self)); + auto templateArguments = PyList_New(0); + for (const std::string &innerType : innerTypes) { + PyObject* childValue; + try { + int integer = std::stoi(innerType); + childValue = Py_BuildValue("i", integer); + } + catch (std::invalid_argument) { + childValue = lookupType(innerType); + } + PyList_Append(templateArguments, childValue); + } + return templateArguments; +} + PyObject *type_New(PyTypeObject *type, PyObject *, PyObject *) { Type *self = reinterpret_cast(type->tp_alloc(type, 0)); @@ -315,6 +333,8 @@ static PyMethodDef typeMethods[] = { {"templateArgument", PyCFunction(type_TemplateArgument), METH_VARARGS, "Returns template argument at position"}, + {"templateArguments", PyCFunction(type_TemplateArguments), METH_NOARGS, + "Returns all template arguments."}, {NULL} /* Sentinel */ }; From 183395831a4aebce434b919b0b70fdeabf5de312 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 14 Oct 2016 13:06:35 +0200 Subject: [PATCH 26/53] QmlDesigner: cleanup DocumentManager - move get origin properties out of the static methods to reduce the code hopefully no behavior change Change-Id: Icf903f5bcaf48ab35a9db1a779c6d9e5abcf0f80 Reviewed-by: Thomas Hartmann --- .../componentcore/modelnodeoperations.cpp | 5 +- src/plugins/qmldesigner/documentmanager.cpp | 58 +++++-------------- 2 files changed, 19 insertions(+), 44 deletions(-) diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index f5e476aeaed..182b717f23b 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -670,8 +670,9 @@ void addSignalHandlerOrGotoImplementation(const SelectionContext &selectionState QString itemId = modelNode.id(); - const QString fileName = QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->fileName().toString(); - const QString typeName = QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->fileName().toFileInfo().baseName(); + const Utils::FileName currentDesignDocument = QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->fileName(); + const QString fileName = currentDesignDocument.toString(); + const QString typeName = currentDesignDocument.toFileInfo().baseName(); QStringList signalNames = cleanSignalNames(getSortedSignalNameList(selectionState.selectedModelNodes().first())); diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index 01ec2dfec66..d1aecf0ee19 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -53,13 +53,14 @@ namespace QmlDesigner { Q_LOGGING_CATEGORY(documentManagerLog, "qtc.qtquickdesigner.documentmanager") -static inline DesignDocument* currentDesignDocument() +static inline QmlDesigner::DesignDocument* designDocument() { - return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); + return QmlDesigner::QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); } -static inline void getProperties(const ModelNode &node, QHash &propertyHash) +static inline QHash getProperties(const ModelNode &node) { + QHash propertyHash; if (QmlObjectNode::isValidQmlObjectNode(node)) { foreach (const AbstractProperty &abstractProperty, node.properties()) { if (abstractProperty.isVariantProperty() @@ -79,6 +80,7 @@ static inline void getProperties(const ModelNode &node, QHash &propertyHash) @@ -111,14 +113,8 @@ static inline void applyProperties(ModelNode &node, const QHashviewManager().nextFileIsCalledInternally(); - - QHash propertyHash; - - getProperties(modelNode, propertyHash); - Core::EditorManager::openEditor(modelNode.metaInfo().componentFileName(), Core::Id(), Core::EditorManager::DoNotMakeVisible); - - ModelNode rootModelNode = currentDesignDocument()->rewriterView()->rootModelNode(); - applyProperties(rootModelNode, propertyHash); + Core::EditorManager::openEditor(modelNode.metaInfo().componentFileName(), + Core::Id(), Core::EditorManager::DoNotMakeVisible); } static void openFileComponentForDelegate(const ModelNode &modelNode) @@ -130,10 +126,6 @@ static void openComponentSourcePropertyOfLoader(const ModelNode &modelNode) { QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally(); - QHash propertyHash; - - getProperties(modelNode, propertyHash); - ModelNode componentModelNode; if (modelNode.hasNodeProperty("sourceComponent")) { @@ -149,32 +141,23 @@ static void openComponentSourcePropertyOfLoader(const ModelNode &modelNode) } Core::EditorManager::openEditor(componentModelNode.metaInfo().componentFileName(), Core::Id(), Core::EditorManager::DoNotMakeVisible); - - ModelNode rootModelNode = currentDesignDocument()->rewriterView()->rootModelNode(); - applyProperties(rootModelNode, propertyHash); } static void openSourcePropertyOfLoader(const ModelNode &modelNode) { QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally(); - QHash propertyHash; - QString componentFileName = modelNode.variantProperty("source").value().toString(); QString componentFilePath = modelNode.model()->fileUrl().resolved(QUrl::fromLocalFile(componentFileName)).toLocalFile(); - getProperties(modelNode, propertyHash); Core::EditorManager::openEditor(componentFilePath, Core::Id(), Core::EditorManager::DoNotMakeVisible); - - ModelNode rootModelNode = currentDesignDocument()->rewriterView()->rootModelNode(); - applyProperties(rootModelNode, propertyHash); } static void handleComponent(const ModelNode &modelNode) { if (modelNode.nodeSourceType() == ModelNode::NodeWithComponentSource) - currentDesignDocument()->changeToSubComponent(modelNode); + designDocument()->changeToSubComponent(modelNode); } static void handleDelegate(const ModelNode &modelNode) @@ -182,36 +165,25 @@ static void handleDelegate(const ModelNode &modelNode) if (modelNode.metaInfo().isView() && modelNode.hasNodeProperty("delegate") && modelNode.nodeProperty("delegate").modelNode().nodeSourceType() == ModelNode::NodeWithComponentSource) - currentDesignDocument()->changeToSubComponent(modelNode.nodeProperty("delegate").modelNode()); + designDocument()->changeToSubComponent(modelNode.nodeProperty("delegate").modelNode()); } static void handleTabComponent(const ModelNode &modelNode) { if (modelNode.hasNodeProperty("component") && modelNode.nodeProperty("component").modelNode().nodeSourceType() == ModelNode::NodeWithComponentSource) { - currentDesignDocument()->changeToSubComponent(modelNode.nodeProperty("component").modelNode()); + designDocument()->changeToSubComponent(modelNode.nodeProperty("component").modelNode()); } } static inline void openInlineComponent(const ModelNode &modelNode) { - - if (!modelNode.isValid() || !modelNode.metaInfo().isValid()) + if (!modelNode.metaInfo().isValid()) return; - if (!currentDesignDocument()) - return; - - QHash propertyHash; - - getProperties(modelNode, propertyHash); - handleComponent(modelNode); handleDelegate(modelNode); handleTabComponent(modelNode); - - ModelNode rootModelNode = currentDesignDocument()->rewriterView()->rootModelNode(); - applyProperties(rootModelNode, propertyHash); } static bool isFileComponent(const ModelNode &node) @@ -249,7 +221,6 @@ static bool isLoaderWithSourceComponent(const ModelNode &modelNode) } return false; - } static bool hasSourceWithFileComponent(const ModelNode &modelNode) @@ -295,7 +266,7 @@ DesignDocument *DocumentManager::currentDesignDocument() const bool DocumentManager::hasCurrentDesignDocument() const { - return m_currentDesignDocument.data(); + return !m_currentDesignDocument.isNull(); } void DocumentManager::removeEditors(const QList &editors) @@ -306,8 +277,9 @@ void DocumentManager::removeEditors(const QList &editors) void DocumentManager::goIntoComponent(const ModelNode &modelNode) { - if (modelNode.isValid() && modelNode.isComponent()) { + if (modelNode.isValid() && modelNode.isComponent() && designDocument()) { QmlDesignerPlugin::instance()->viewManager().setComponentNode(modelNode); + QHash oldProperties = getProperties(modelNode); if (isFileComponent(modelNode)) openFileComponent(modelNode); else if (hasDelegateWithFileComponent(modelNode)) @@ -318,6 +290,8 @@ void DocumentManager::goIntoComponent(const ModelNode &modelNode) openComponentSourcePropertyOfLoader(modelNode); else openInlineComponent(modelNode); + ModelNode rootModelNode = designDocument()->rewriterView()->rootModelNode(); + applyProperties(rootModelNode, oldProperties); } } From 75ff9a6fdcf809cab9ae649e04320b20a0f47f81 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 20 Oct 2016 23:36:02 +0300 Subject: [PATCH 27/53] GenericHighlighter: Update from latest KTextEditor source Change-Id: I0caf19cd7698c9934655483304314b5653b69f21 Reviewed-by: David Schulz --- .../3rdparty/generic-highlighter/alert.xml | 2 +- .../3rdparty/generic-highlighter/bash.xml | 26 +- .../3rdparty/generic-highlighter/cmake.xml | 2 +- .../3rdparty/generic-highlighter/css.xml | 1901 +++++++++-------- .../3rdparty/generic-highlighter/doxygen.xml | 10 +- .../3rdparty/generic-highlighter/dtd.xml | 2 +- .../3rdparty/generic-highlighter/html.xml | 4 +- .../3rdparty/generic-highlighter/ini.xml | 4 +- .../3rdparty/generic-highlighter/java.xml | 2 +- .../3rdparty/generic-highlighter/javadoc.xml | 2 +- .../3rdparty/generic-highlighter/makefile.xml | 2 +- .../3rdparty/generic-highlighter/perl.xml | 2 +- .../3rdparty/generic-highlighter/ruby.xml | 2 +- .../valgrind-suppression.xml | 2 +- .../3rdparty/generic-highlighter/xml.xml | 4 +- .../3rdparty/generic-highlighter/yacc.xml | 6 +- 16 files changed, 1090 insertions(+), 883 deletions(-) diff --git a/src/share/3rdparty/generic-highlighter/alert.xml b/src/share/3rdparty/generic-highlighter/alert.xml index 8ac5296fc80..3ed783b35dc 100644 --- a/src/share/3rdparty/generic-highlighter/alert.xml +++ b/src/share/3rdparty/generic-highlighter/alert.xml @@ -30,7 +30,7 @@ Introduce 3 alert levels and sort keywords according importance. Few more keywords has been added. --> - diff --git a/src/share/3rdparty/generic-highlighter/doxygen.xml b/src/share/3rdparty/generic-highlighter/doxygen.xml index 302df7146cc..d07c1650b41 100644 --- a/src/share/3rdparty/generic-highlighter/doxygen.xml +++ b/src/share/3rdparty/generic-highlighter/doxygen.xml @@ -29,7 +29,7 @@ --> - + @@ -297,7 +297,7 @@ - + @@ -339,7 +339,7 @@ - + @@ -405,7 +405,7 @@ - + diff --git a/src/share/3rdparty/generic-highlighter/dtd.xml b/src/share/3rdparty/generic-highlighter/dtd.xml index 75d07234d9b..5c39c1b5970 100644 --- a/src/share/3rdparty/generic-highlighter/dtd.xml +++ b/src/share/3rdparty/generic-highlighter/dtd.xml @@ -3,7 +3,7 @@ ]> - + diff --git a/src/share/3rdparty/generic-highlighter/html.xml b/src/share/3rdparty/generic-highlighter/html.xml index 741423f866e..d1017aad1d3 100644 --- a/src/share/3rdparty/generic-highlighter/html.xml +++ b/src/share/3rdparty/generic-highlighter/html.xml @@ -4,7 +4,7 @@ ]> - + @@ -211,7 +211,7 @@ - + diff --git a/src/share/3rdparty/generic-highlighter/ini.xml b/src/share/3rdparty/generic-highlighter/ini.xml index f6f55e2ebe2..dba0e204cbc 100644 --- a/src/share/3rdparty/generic-highlighter/ini.xml +++ b/src/share/3rdparty/generic-highlighter/ini.xml @@ -1,6 +1,6 @@ - + @@ -34,7 +34,7 @@ - + diff --git a/src/share/3rdparty/generic-highlighter/java.xml b/src/share/3rdparty/generic-highlighter/java.xml index e06ec6bd864..64c97eefd78 100644 --- a/src/share/3rdparty/generic-highlighter/java.xml +++ b/src/share/3rdparty/generic-highlighter/java.xml @@ -1,6 +1,6 @@ - + ACTIVE diff --git a/src/share/3rdparty/generic-highlighter/javadoc.xml b/src/share/3rdparty/generic-highlighter/javadoc.xml index 25eab95e111..c16cba3428b 100644 --- a/src/share/3rdparty/generic-highlighter/javadoc.xml +++ b/src/share/3rdparty/generic-highlighter/javadoc.xml @@ -1,6 +1,6 @@ - + diff --git a/src/share/3rdparty/generic-highlighter/makefile.xml b/src/share/3rdparty/generic-highlighter/makefile.xml index fbf96eae927..9baeb508ecf 100644 --- a/src/share/3rdparty/generic-highlighter/makefile.xml +++ b/src/share/3rdparty/generic-highlighter/makefile.xml @@ -8,7 +8,7 @@ diff --git a/src/share/3rdparty/generic-highlighter/perl.xml b/src/share/3rdparty/generic-highlighter/perl.xml index 2f6e823bfb6..a3c6bdb21b0 100644 --- a/src/share/3rdparty/generic-highlighter/perl.xml +++ b/src/share/3rdparty/generic-highlighter/perl.xml @@ -39,7 +39,7 @@ Enhance tr/// and y/// support. --> - + if diff --git a/src/share/3rdparty/generic-highlighter/ruby.xml b/src/share/3rdparty/generic-highlighter/ruby.xml index c4110ccd754..5c6dca335bc 100644 --- a/src/share/3rdparty/generic-highlighter/ruby.xml +++ b/src/share/3rdparty/generic-highlighter/ruby.xml @@ -31,7 +31,7 @@ - + diff --git a/src/share/3rdparty/generic-highlighter/xml.xml b/src/share/3rdparty/generic-highlighter/xml.xml index 3d92a563cd1..622c2a41e7f 100644 --- a/src/share/3rdparty/generic-highlighter/xml.xml +++ b/src/share/3rdparty/generic-highlighter/xml.xml @@ -6,7 +6,7 @@ ]> - + @@ -134,7 +134,7 @@ - + diff --git a/src/share/3rdparty/generic-highlighter/yacc.xml b/src/share/3rdparty/generic-highlighter/yacc.xml index add68e96a8d..c8b3153218b 100644 --- a/src/share/3rdparty/generic-highlighter/yacc.xml +++ b/src/share/3rdparty/generic-highlighter/yacc.xml @@ -25,7 +25,7 @@ This code is released under the LGPL as part of kdelibs/kate. ======================================================================== --> - + @@ -92,7 +92,7 @@ This code is released under the LGPL as part of kdelibs/kate. - + @@ -112,7 +112,7 @@ This code is released under the LGPL as part of kdelibs/kate. - + From 07c5cf3a83e8e69497f5146b9480499cdfc687a2 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 18 Oct 2016 18:01:57 +0200 Subject: [PATCH 28/53] Clang: Clean up diagnostic widget * Use a single QLabel - No need for all the QLabels we used. Also, a single QLabel enables selecting and copying all the diagnostics, which is handy when displayed in the info bar. * Avoid call to Utils::ToolTip::hideImmediately() if the location is clicked from the info bar. * Simplify code and API Change-Id: Ib991364e4d6f40ef02dada8ebbb90fe6ff8ae1a1 Reviewed-by: Friedemann Kleint Reviewed-by: David Schulz --- .../clangbackendipc/diagnosticcontainer.h | 5 + .../clangdiagnostictooltipwidget.cpp | 420 +++++++++++------- .../clangdiagnostictooltipwidget.h | 14 +- .../clangeditordocumentprocessor.cpp | 21 +- src/plugins/clangcodemodel/clangtextmark.cpp | 7 +- 5 files changed, 285 insertions(+), 182 deletions(-) diff --git a/src/libs/clangbackendipc/diagnosticcontainer.h b/src/libs/clangbackendipc/diagnosticcontainer.h index b9d47db04e1..677fb813d5a 100644 --- a/src/libs/clangbackendipc/diagnosticcontainer.h +++ b/src/libs/clangbackendipc/diagnosticcontainer.h @@ -144,6 +144,11 @@ public: && first.location_ == second.location_; } + friend bool operator!=(const DiagnosticContainer &first, const DiagnosticContainer &second) + { + return !(first == second); + } + private: SourceLocationContainer location_; QVector ranges_; diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp index 5b6c48c9536..1275ab81cd3 100644 --- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp +++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp @@ -28,34 +28,22 @@ #include +#include #include +#include +#include #include -#include +#include #include -#include -#include + +using namespace ClangCodeModel; +using Internal::ClangDiagnosticWidget; namespace { const char LINK_ACTION_GOTO_LOCATION[] = "#gotoLocation"; const char LINK_ACTION_APPLY_FIX[] = "#applyFix"; -const int childIndentationOnTheLeftInPixel = 10; - -QString wrapInBoldTags(const QString &text) -{ - return QStringLiteral("") + text + QStringLiteral(""); -} - -QString wrapInLink(const QString &text, const QString &target) -{ - return QStringLiteral("%2").arg(target, text); -} - -QString wrapInColor(const QString &text, const QByteArray &color) -{ - return QStringLiteral("%1").arg(text, QString::fromUtf8(color)); -} QString fileNamePrefix(const QString &mainFilePath, const ClangBackEnd::SourceLocationContainer &location) @@ -74,181 +62,293 @@ QString locationToString(const ClangBackEnd::SourceLocationContainer &location) + QString::number(location.column()); } -QString clickableLocation(const QString &mainFilePath, - const ClangBackEnd::SourceLocationContainer &location) +void openEditorAt(const ClangBackEnd::DiagnosticContainer &diagnostic) { - const QString filePrefix = fileNamePrefix(mainFilePath, location); - const QString lineColumn = locationToString(location); - const QString linkText = filePrefix + lineColumn; + const ClangBackEnd::SourceLocationContainer location = diagnostic.location(); - return wrapInLink(linkText, QLatin1String(LINK_ACTION_GOTO_LOCATION)); -} - -QString clickableFixIt(const QString &text, bool hasFixIt) -{ - if (!hasFixIt) - return text; - - QString clickableText = text; - QString nonClickableCategory; - const int colonPosition = text.indexOf(QStringLiteral(": ")); - - if (colonPosition != -1) { - nonClickableCategory = text.mid(0, colonPosition + 2); - clickableText = text.mid(colonPosition + 2); - } - - return nonClickableCategory + wrapInLink(clickableText, QLatin1String(LINK_ACTION_APPLY_FIX)); -} - -void openEditorAt(const ClangBackEnd::SourceLocationContainer &location) -{ Core::EditorManager::openEditorAt(location.filePath().toString(), int(location.line()), int(location.column() - 1)); } -void applyFixit(const QVector &fixits) +void applyFixit(const ClangBackEnd::DiagnosticContainer &diagnostic) { - ClangCodeModel::ClangFixItOperation operation(Utf8String(), fixits); + ClangCodeModel::ClangFixItOperation operation(Utf8String(), diagnostic.fixIts()); operation.perform(); } -template -LayoutType *createLayout() +class WidgetFromDiagnostics { - auto *layout = new LayoutType; - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(2); - - return layout; -} - -enum IndentType { IndentDiagnostic, DoNotIndentDiagnostic }; - -QWidget *createDiagnosticLabel(const ClangBackEnd::DiagnosticContainer &diagnostic, - const QString &mainFilePath, - IndentType indentType = DoNotIndentDiagnostic, - bool enableClickableFixits = true) -{ - const bool hasFixit = enableClickableFixits ? !diagnostic.fixIts().isEmpty() : false; - const QString diagnosticText = diagnostic.text().toString().toHtmlEscaped(); - const QString text = clickableLocation(mainFilePath, diagnostic.location()) - + QStringLiteral(": ") - + clickableFixIt(diagnosticText, hasFixit); - const ClangBackEnd::SourceLocationContainer location = diagnostic.location(); - const QVector fixits = diagnostic.fixIts(); - - auto *label = new QLabel(text); - if (indentType == IndentDiagnostic) - label->setContentsMargins(childIndentationOnTheLeftInPixel, 0, 0, 0); - label->setTextFormat(Qt::RichText); - QObject::connect(label, &QLabel::linkActivated, [location, fixits](const QString &action) { - if (action == QLatin1String(LINK_ACTION_APPLY_FIX)) - applyFixit(fixits); - else - openEditorAt(location); - - Utils::ToolTip::hideImmediately(); - }); - - return label; -} - -class MainDiagnosticWidget : public QWidget -{ - Q_OBJECT public: - MainDiagnosticWidget(const ClangBackEnd::DiagnosticContainer &diagnostic, - const ClangCodeModel::Internal::DisplayHints &displayHints) + struct DisplayHints { + bool showCategoryAndEnableOption; + bool showFileNameInMainDiagnostic; + bool enableClickableFixits; + bool limitWidth; + bool hideTooltipAfterLinkActivation; + }; + + static QWidget *create(const QVector &diagnostics, + const DisplayHints &displayHints) { - setContentsMargins(0, 0, 0, 0); - auto *mainLayout = createLayout(); + WidgetFromDiagnostics converter(displayHints); + return converter.createWidget(diagnostics); + } - const ClangBackEnd::SourceLocationContainer location = diagnostic.location(); +private: + enum class IndentMode { Indent, DoNotIndent }; - // Set up header row: category + responsible option - if (displayHints.showMainDiagnosticHeader) { - const QString category = diagnostic.category(); - const QString responsibleOption = diagnostic.enableOption(); + WidgetFromDiagnostics(const DisplayHints &displayHints) + : m_displayHints(displayHints) + { + } - auto *headerLayout = createLayout(); - headerLayout->addWidget(new QLabel(wrapInBoldTags(category)), 1); + QWidget *createWidget(const QVector &diagnostics) + { + const QString text = htmlText(diagnostics); - auto *responsibleOptionLabel = new QLabel(wrapInColor(responsibleOption, "gray")); - headerLayout->addWidget(responsibleOptionLabel, 0); - mainLayout->addLayout(headerLayout); + auto *label = new QLabel; + label->setTextFormat(Qt::RichText); + label->setText(text); + label->setTextInteractionFlags(Qt::TextBrowserInteraction); + // Using "setWordWrap(true)" alone will wrap the text already for small + // widths, so do not require word wrapping until we hit limits. + if (m_displayHints.limitWidth && label->sizeHint().width() > widthLimit()) { + label->setMaximumWidth(widthLimit()); + label->setWordWrap(true); } - // Set up main row: diagnostic text - const Utf8String mainFilePath = displayHints.showFileNameInMainDiagnostic + const TargetIdToDiagnosticTable table = m_targetIdsToDiagnostics; + const bool hideToolTipAfterLinkActivation = m_displayHints.hideTooltipAfterLinkActivation; + QObject::connect(label, &QLabel::linkActivated, [table, hideToolTipAfterLinkActivation] + (const QString &action) { + const ClangBackEnd::DiagnosticContainer diagnostic = table.value(action); + QTC_ASSERT(diagnostic != ClangBackEnd::DiagnosticContainer(), return); + + if (action.startsWith(LINK_ACTION_APPLY_FIX)) + applyFixit(diagnostic); + else + openEditorAt(diagnostic); + + if (hideToolTipAfterLinkActivation) + Utils::ToolTip::hideImmediately(); + }); + + return label; + } + + QString htmlText(const QVector &diagnostics) + { + // For debugging, add: style='border-width:1px;border-color:black' + QString text = ""; + + foreach (const ClangBackEnd::DiagnosticContainer &diagnostic, diagnostics) + text.append(tableRows(diagnostic)); + + text.append("
"); + + return text; + } + + QString tableRows(const ClangBackEnd::DiagnosticContainer &diagnostic) + { + m_mainFilePath = m_displayHints.showFileNameInMainDiagnostic ? Utf8String() - : location.filePath(); - mainLayout->addWidget(createDiagnosticLabel(diagnostic, - mainFilePath, - DoNotIndentDiagnostic, - displayHints.enableClickableFixits)); + : diagnostic.location().filePath(); - setLayout(mainLayout); + QString text; + + if (m_displayHints.showCategoryAndEnableOption) + text.append(diagnosticCategoryAndEnableOptionRow(diagnostic)); + text.append(diagnosticRow(diagnostic, IndentMode::DoNotIndent)); + text.append(diagnosticRowsForChildren(diagnostic)); + + return text; } + + static QString diagnosticCategoryAndEnableOptionRow( + const ClangBackEnd::DiagnosticContainer &diagnostic) + { + const QString text = QString::fromLatin1( + " " + " %1" + " %2" + " ") + .arg(diagnostic.category(), diagnostic.enableOption()); + + return text; + } + + QString diagnosticText(const ClangBackEnd::DiagnosticContainer &diagnostic) + { + const bool hasFixit = m_displayHints.enableClickableFixits + && !diagnostic.fixIts().isEmpty(); + const QString diagnosticText = diagnostic.text().toString().toHtmlEscaped(); + + // For debugging, add to : style='border-width:1px;border-color:red' + const QString text = QString::fromLatin1( + "
" + " " + " " + " " + " " + "
%1: %2
") + .arg(clickableLocation(diagnostic, m_mainFilePath), + clickableFixIt(diagnostic, diagnosticText, hasFixit)); + + return text; + } + + QString diagnosticRow(const ClangBackEnd::DiagnosticContainer &diagnostic, + IndentMode indentMode) + { + const QString text = QString::fromLatin1( + " " + " %2" + " ") + .arg(indentModeToHtmlStyle(indentMode), + diagnosticText(diagnostic)); + + return text; + } + + QString diagnosticRowsForChildren(const ClangBackEnd::DiagnosticContainer &diagnostic) + { + const QVector children = diagnostic.children(); + QString text; + + if (children.size() <= 10) { + text += diagnosticRowsForChildren(children.begin(), children.end()); + } else { + text += diagnosticRowsForChildren(children.begin(), children.begin() + 7); + text += ellipsisRow(); + text += diagnosticRowsForChildren(children.end() - 3, children.end()); + } + + return text; + } + + QString diagnosticRowsForChildren( + const QVector::const_iterator first, + const QVector::const_iterator last) + { + QString text; + + for (auto it = first; it != last; ++it) + text.append(diagnosticRow(*it, IndentMode::Indent)); + + return text; + } + + QString clickableLocation(const ClangBackEnd::DiagnosticContainer &diagnostic, + const QString &mainFilePath) + { + const ClangBackEnd::SourceLocationContainer location = diagnostic.location(); + + const QString filePrefix = fileNamePrefix(mainFilePath, location); + const QString lineColumn = locationToString(location); + const QString linkText = filePrefix + lineColumn; + const QString targetId = generateTargetId(LINK_ACTION_GOTO_LOCATION, diagnostic); + + return wrapInLink(linkText, targetId); + } + + QString clickableFixIt(const ClangBackEnd::DiagnosticContainer &diagnostic, + const QString &text, + bool hasFixIt) + { + if (!hasFixIt) + return text; + + QString clickableText = text; + QString nonClickableCategory; + const int colonPosition = text.indexOf(QStringLiteral(": ")); + + if (colonPosition != -1) { + nonClickableCategory = text.mid(0, colonPosition + 2); + clickableText = text.mid(colonPosition + 2); + } + + const QString targetId = generateTargetId(LINK_ACTION_APPLY_FIX, diagnostic); + + return nonClickableCategory + wrapInLink(clickableText, targetId); + } + + QString generateTargetId(const QString &targetPrefix, + const ClangBackEnd::DiagnosticContainer &diagnostic) + { + const QString idAsString = QString::number(++m_targetIdCounter); + const QString targetId = targetPrefix + idAsString; + m_targetIdsToDiagnostics.insert(targetId, diagnostic); + + return targetId; + } + + static QString wrapInLink(const QString &text, const QString &target) + { + return QStringLiteral("%2").arg(target, text); + } + + static QString ellipsisRow() + { + return QString::fromLatin1( + " " + " ..." + " ") + .arg(indentModeToHtmlStyle(IndentMode::Indent)); + } + + static QString indentModeToHtmlStyle(IndentMode indentMode) + { + return indentMode == IndentMode::Indent + ? QString("padding-left:10px") + : QString(); + } + + static int widthLimit() + { + return QApplication::desktop()->availableGeometry(QCursor::pos()).width() / 2; + } + +private: + const DisplayHints m_displayHints; + + using TargetIdToDiagnosticTable = QHash; + TargetIdToDiagnosticTable m_targetIdsToDiagnostics; + unsigned m_targetIdCounter = 0; + + QString m_mainFilePath; }; -void addChildrenToLayout(const QString &mainFilePath, - const QVector::const_iterator first, - const QVector::const_iterator last, - bool enableClickableFixits, - QLayout &boxLayout) -{ - for (auto it = first; it != last; ++it) { - boxLayout.addWidget(createDiagnosticLabel(*it, - mainFilePath, - IndentDiagnostic, - enableClickableFixits)); - } -} - -void setupChildDiagnostics(const QString &mainFilePath, - const QVector &diagnostics, - bool enableClickableFixits, - QLayout &boxLayout) -{ - if (diagnostics.size() <= 10) { - addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.end(), - enableClickableFixits, boxLayout); - } else { - addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.begin() + 7, - enableClickableFixits, boxLayout); - - auto ellipsisLabel = new QLabel(QStringLiteral("...")); - ellipsisLabel->setContentsMargins(childIndentationOnTheLeftInPixel, 0, 0, 0); - boxLayout.addWidget(ellipsisLabel); - - addChildrenToLayout(mainFilePath, diagnostics.end() - 3, diagnostics.end(), - enableClickableFixits, boxLayout); - } -} - } // anonymous namespace namespace ClangCodeModel { namespace Internal { -void addToolTipToLayout(const ClangBackEnd::DiagnosticContainer &diagnostic, - QLayout *target, - const DisplayHints &displayHints) +QWidget *ClangDiagnosticWidget::create( + const QVector &diagnostics, + const Destination &destination) { - // Set up header and text row for main diagnostic - target->addWidget(new MainDiagnosticWidget(diagnostic, displayHints)); + WidgetFromDiagnostics::DisplayHints hints; - // Set up child rows for notes - setupChildDiagnostics(diagnostic.location().filePath(), - diagnostic.children(), - displayHints.enableClickableFixits, - *target); + if (destination == ToolTip) { + hints.showCategoryAndEnableOption = true; + hints.showFileNameInMainDiagnostic = false; + hints.enableClickableFixits = true; + hints.limitWidth = true; + hints.hideTooltipAfterLinkActivation = true; + } else { // Info Bar + hints.showCategoryAndEnableOption = false; + hints.showFileNameInMainDiagnostic = true; + // Clickable fixits might change toolchain headers, so disable. + hints.enableClickableFixits = false; + hints.limitWidth = false; + hints.hideTooltipAfterLinkActivation = false; + } + + return WidgetFromDiagnostics::create(diagnostics, hints); } } // namespace Internal } // namespace ClangCodeModel - -#include "clangdiagnostictooltipwidget.moc" diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h index 839952fc774..3ea1bfb0ada 100644 --- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h +++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h @@ -34,15 +34,13 @@ QT_END_NAMESPACE namespace ClangCodeModel { namespace Internal { -struct DisplayHints { - bool showMainDiagnosticHeader = true; - bool showFileNameInMainDiagnostic = false; - bool enableClickableFixits = true; -}; +class ClangDiagnosticWidget { +public: + enum Destination { ToolTip, InfoBar }; -void addToolTipToLayout(const ClangBackEnd::DiagnosticContainer &diagnostic, - QLayout *target, - const DisplayHints &displayHints = DisplayHints()); + static QWidget *create(const QVector &diagnostics, + const Destination &destination); +}; } // namespace Internal } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 09a7b76b6f1..82f06b59949 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -263,8 +263,12 @@ void ClangEditorDocumentProcessor::addDiagnosticToolTipToLayout(uint line, uint column, QLayout *target) const { - foreach (const auto &diagnostic, m_diagnosticManager.diagnosticsAt(line, column)) - addToolTipToLayout(diagnostic, target); + using Internal::ClangDiagnosticWidget; + + const QVector diagnostics + = m_diagnosticManager.diagnosticsAt(line, column); + + target->addWidget(ClangDiagnosticWidget::create(diagnostics, ClangDiagnosticWidget::ToolTip)); } void ClangEditorDocumentProcessor::editorDocumentTimerRestarted() @@ -342,16 +346,6 @@ void ClangEditorDocumentProcessor::requestDocumentAnnotations(const QString &pro m_ipcCommunicator.requestDocumentAnnotations(fileContainer); } -static Internal::DisplayHints displayHintsForInfoBar() -{ - Internal::DisplayHints displayHints; - displayHints.showMainDiagnosticHeader = false; - displayHints.showFileNameInMainDiagnostic = true; - displayHints.enableClickableFixits = false; // Tool chain headers might be changed, so disable. - - return displayHints; -} - CppTools::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget( const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic) @@ -365,7 +359,8 @@ ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget( vbox->setContentsMargins(10, 0, 0, 2); vbox->setSpacing(2); - addToolTipToLayout(firstHeaderErrorDiagnostic, vbox, displayHintsForInfoBar()); + vbox->addWidget(ClangDiagnosticWidget::create({firstHeaderErrorDiagnostic}, + ClangDiagnosticWidget::InfoBar)); auto widget = new QWidget; widget->setLayout(vbox); diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp index 8057d66cb61..fede73fde3f 100644 --- a/src/plugins/clangcodemodel/clangtextmark.cpp +++ b/src/plugins/clangcodemodel/clangtextmark.cpp @@ -31,6 +31,7 @@ #include #include +#include #include namespace ClangCodeModel { @@ -84,7 +85,11 @@ void ClangTextMark::setIcon(ClangBackEnd::DiagnosticSeverity severity) bool ClangTextMark::addToolTipContent(QLayout *target) { - Internal::addToolTipToLayout(m_diagnostic, target, Internal::DisplayHints()); + using Internal::ClangDiagnosticWidget; + + QWidget *widget = ClangDiagnosticWidget::create({m_diagnostic}, ClangDiagnosticWidget::ToolTip); + target->addWidget(widget); + return true; } From 4e06822fc560fb13eb124ae4413976e9406bbccc Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 20 Oct 2016 14:33:42 +0200 Subject: [PATCH 29/53] Cdb: Set frame when using the python engine Change-Id: Ib84735b58f516dad14c992edba6a0c8e9005ecfc Reviewed-by: Christian Stenger --- src/plugins/debugger/cdb/cdbengine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 96727efea1f..15d82c3436b 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1209,6 +1209,8 @@ void CdbEngine::activateFrame(int index) qPrintable(frame.file), frame.line); stackHandler()->setCurrentIndex(index); gotoLocation(frame); + if (m_pythonVersion > 0x030000) + runCommand({".frame " + QString::number(index), NoFlags}); updateLocals(); } From 614689874a0478630708ce1bd6634d64a9903ab4 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 20 Oct 2016 11:59:41 +0200 Subject: [PATCH 30/53] QmlDesigner: Fix for item library search filter Without this patch the item library gets into an invalid state if the user enters edit mode with an ative search filter. When going back to design mode the item library is completely empty. This patch clears the filter, so the item library gets properly populated. Change-Id: I21f823b8db820589dedd6ba4e4855678fff49e53 Reviewed-by: Tim Jenssen --- .../qmldesigner/components/itemlibrary/itemlibraryview.cpp | 2 ++ .../qmldesigner/components/itemlibrary/itemlibrarywidget.cpp | 5 +++++ .../qmldesigner/components/itemlibrary/itemlibrarywidget.h | 2 ++ 3 files changed, 9 insertions(+) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp index 60ce7234f28..4f354746d65 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp @@ -65,6 +65,7 @@ WidgetInfo ItemLibraryView::widgetInfo() void ItemLibraryView::modelAttached(Model *model) { AbstractView::modelAttached(model); + m_widget->clearSearchFilter(); m_widget->setModel(model); updateImports(); model->attachView(m_importManagerView); @@ -75,6 +76,7 @@ void ItemLibraryView::modelAboutToBeDetached(Model *model) model->detachView(m_importManagerView); AbstractView::modelAboutToBeDetached(model); + m_widget->setModel(0); } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 5820c518ac2..039a2be448f 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -247,6 +247,11 @@ QString ItemLibraryWidget::qmlSourcesPath() return Core::ICore::resourcePath() + QStringLiteral("/qmldesigner/itemLibraryQmlSources"); } +void ItemLibraryWidget::clearSearchFilter() +{ + m_filterLineEdit->clear(); +} + void ItemLibraryWidget::reloadQmlSource() { QString itemLibraryQmlFilePath = qmlSourcesPath() + QStringLiteral("/ItemsView.qml"); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index 6a39035b53e..ca8cd82c319 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -86,6 +86,8 @@ public: void setImportsWidget(QWidget *importsWidget); static QString qmlSourcesPath(); + void clearSearchFilter(); + public slots: void setSearchFilter(const QString &searchFilter); void delayedUpdateModel(); From 8c23b49376ac625856e195ffa2f4e98f0d114ad7 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 21 Oct 2016 09:52:10 +0200 Subject: [PATCH 31/53] Clang: Shorten output prefix Change-Id: I89a48a2defa4dbee9a0a0f9206ed996ca7cc1538 Reviewed-by: David Schulz --- src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp b/src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp index ed969ec83e7..4256be360d0 100644 --- a/src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp +++ b/src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp @@ -43,8 +43,8 @@ ClangCodeModelConnectionClient::ClangCodeModelConnectionClient( ClangCodeModelClientInterface *client) : serverProxy_(client, ioDevice()) { - stdErrPrefixer().setPrefix("ClangCodeModelConnectionClient.stderr: "); - stdOutPrefixer().setPrefix("ClangCodeModelConnectionClient.stdout: "); + stdErrPrefixer().setPrefix("clangbackend.stderr: "); + stdOutPrefixer().setPrefix("clangbackend.stdout: "); } ClangCodeModelConnectionClient::~ClangCodeModelConnectionClient() From 434ecfc4f594b918bfbeb46f1e3f63d58597b5fa Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 21 Oct 2016 10:47:13 +0200 Subject: [PATCH 32/53] Clang: Log messages with time stamp Change-Id: I0bb56d319328a2773e55609d63b4ac28eea07386 Reviewed-by: Christian Kandeler --- src/plugins/clangcodemodel/clangbackendipcintegration.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 831a3bdea62..ee2d0ea43f7 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -69,6 +69,7 @@ #include +#include #include #include #include @@ -691,8 +692,10 @@ void IpcCommunicator::logRestartedDueToUnexpectedFinish() void IpcCommunicator::logError(const QString &text) { - Core::MessageManager::write(text, Core::MessageManager::Flash); - qWarning("%s", qPrintable(text)); + const QString textWithTimestamp = QDateTime::currentDateTime().toString(Qt::ISODate) + + ' ' + text; + Core::MessageManager::write(textWithTimestamp, Core::MessageManager::Flash); + qWarning("%s", qPrintable(textWithTimestamp)); } void IpcCommunicator::initializeBackendWithCurrentData() From a25a855b6e3de5b092fca4948abe71f8518c5e20 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 21 Oct 2016 10:49:14 +0200 Subject: [PATCH 33/53] Clang: Fix typo Change-Id: I1b1a59dbe041134aad3bc582b77acafa8e67e427 Reviewed-by: David Schulz --- src/tools/clangbackend/ipcsource/clangexceptions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clangbackend/ipcsource/clangexceptions.cpp b/src/tools/clangbackend/ipcsource/clangexceptions.cpp index 187ce98d1a1..62527b6ce77 100644 --- a/src/tools/clangbackend/ipcsource/clangexceptions.cpp +++ b/src/tools/clangbackend/ipcsource/clangexceptions.cpp @@ -58,7 +58,7 @@ DocumentDoesNotExistException::DocumentDoesNotExistException(const Utf8String &f + filePath + Utf8StringLiteral("' with the project part id '") + projectPartId - + Utf8StringLiteral("' does not exits!"); + + Utf8StringLiteral("' does not exists!"); } DocumentFileDoesNotExistException::DocumentFileDoesNotExistException( From ca4be197efc29c6f77f83978aa5a7e6cbe533b79 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 20 Oct 2016 08:34:55 +0000 Subject: [PATCH 34/53] Revert "Replace virtual isModified method with a getter/setter/notifier" This doesn't fix the issue with cleaning the clear state of undo stack. This introduced the issue when ui file is opened it's marked as modified. It reverts 59c90e00c1e8b18d120f5b5c15b331b1ee427ace and d0c537ca759aa7facfdd0efedac5f5385d16ddb9 Change-Id: Ifd4ff8483d6c297461632de500a4502b1fd0871f Reviewed-by: Tobias Hunger --- .../documentcontroller.cpp | 11 +++--- .../document_controller/documentcontroller.h | 1 - .../project_controller/projectcontroller.cpp | 22 ++++++------ .../project_controller/projectcontroller.h | 5 ++- .../android/androidmanifestdocument.cpp | 13 +++---- src/plugins/android/androidmanifestdocument.h | 1 + .../android/androidmanifesteditorwidget.cpp | 34 +++++++++---------- .../android/androidmanifesteditorwidget.h | 6 ++-- src/plugins/bineditor/bineditorplugin.cpp | 13 +++---- src/plugins/coreplugin/documentmanager.cpp | 3 -- src/plugins/coreplugin/idocument.cpp | 13 +------ src/plugins/coreplugin/idocument.h | 6 +--- src/plugins/designer/formwindowfile.cpp | 13 ++++--- src/plugins/designer/formwindowfile.h | 2 ++ .../modeleditor/extpropertiesmview.cpp | 4 +-- src/plugins/modeleditor/modeldocument.cpp | 11 +++--- src/plugins/modeleditor/modeldocument.h | 1 + .../resourceeditor/resourceeditorw.cpp | 34 ++++++++++++++++--- src/plugins/resourceeditor/resourceeditorw.h | 4 +++ src/plugins/scxmleditor/common/mainwidget.cpp | 5 --- src/plugins/scxmleditor/common/mainwidget.h | 1 - .../plugin_interface/scxmldocument.cpp | 8 ----- .../plugin_interface/scxmldocument.h | 2 -- .../scxmleditor/scxmleditordocument.cpp | 12 ++++--- src/plugins/scxmleditor/scxmleditordocument.h | 1 + src/plugins/texteditor/textdocument.cpp | 12 ++++--- src/plugins/texteditor/textdocument.h | 1 + src/plugins/vcsbase/submiteditorfile.cpp | 9 +++++ src/plugins/vcsbase/submiteditorfile.h | 4 +++ 29 files changed, 136 insertions(+), 116 deletions(-) diff --git a/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp b/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp index 8af722de62b..f6271ff14d3 100644 --- a/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp +++ b/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp @@ -76,20 +76,17 @@ DocumentController::DocumentController(QObject *parent) : { // project controller connect(m_projectController, &ProjectController::changed, this, &DocumentController::changed); - connect(m_projectController, &ProjectController::modificationChanged, this, &DocumentController::modificationChanged); // model controller m_modelController->setUndoController(m_undoController); - connect(m_modelController, &ModelController::modified, [this](){ - m_projectController->setModified(true); - }); + connect(m_modelController, &ModelController::modified, + m_projectController, &ProjectController::setModified); // diagram controller m_diagramController->setModelController(m_modelController); m_diagramController->setUndoController(m_undoController); - connect(m_diagramController, &DiagramController::modified, [this](){ - m_projectController->setModified(true); - }); + connect(m_diagramController, &DiagramController::modified, + m_projectController, &ProjectController::setModified); // diagram scene controller m_diagramSceneController->setModelController(m_modelController); diff --git a/src/libs/modelinglib/qmt/document_controller/documentcontroller.h b/src/libs/modelinglib/qmt/document_controller/documentcontroller.h index b9eb3a53719..d9a253773f9 100644 --- a/src/libs/modelinglib/qmt/document_controller/documentcontroller.h +++ b/src/libs/modelinglib/qmt/document_controller/documentcontroller.h @@ -61,7 +61,6 @@ public: signals: void changed(); - void modificationChanged(bool modified); void modelClipboardChanged(bool isEmpty); void diagramClipboardChanged(bool isEmpty); diff --git a/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp b/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp index 384bb52281a..9698a2f601f 100644 --- a/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp +++ b/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp @@ -43,7 +43,8 @@ ProjectIsModifiedException::ProjectIsModifiedException() } ProjectController::ProjectController(QObject *parent) - : QObject(parent) + : QObject(parent), + m_isModified(false) { } @@ -58,7 +59,7 @@ void ProjectController::newProject(const QString &fileName) rootPackage->setName(tr("Model")); m_project->setRootPackage(rootPackage); m_project->setFileName(fileName); - setModified(false); + m_isModified = false; emit fileNameChanged(m_project->fileName()); emit changed(); } @@ -67,18 +68,17 @@ void ProjectController::setFileName(const QString &fileName) { if (fileName != m_project->fileName()) { m_project->setFileName(fileName); - setModified(true); + setModified(); emit fileNameChanged(m_project->fileName()); } } -void ProjectController::setModified(bool modified) +void ProjectController::setModified() { - if (m_isModified == modified) - return; - - m_isModified = modified; - emit modificationChanged(modified); + if (!m_isModified) { + m_isModified = true; + emit changed(); + } } void ProjectController::load() @@ -89,7 +89,7 @@ void ProjectController::load() throw NoFileNameException(); ProjectSerializer serializer; serializer.load(m_project->fileName(), m_project.data()); - setModified(false); + m_isModified = false; emit changed(); } @@ -99,7 +99,7 @@ void ProjectController::save() throw NoFileNameException(); ProjectSerializer serializer; serializer.save(m_project->fileName(), m_project.data()); - setModified(false); + m_isModified = false; emit changed(); } diff --git a/src/libs/modelinglib/qmt/project_controller/projectcontroller.h b/src/libs/modelinglib/qmt/project_controller/projectcontroller.h index a4eb47f9a60..73daf2a2ac9 100644 --- a/src/libs/modelinglib/qmt/project_controller/projectcontroller.h +++ b/src/libs/modelinglib/qmt/project_controller/projectcontroller.h @@ -58,7 +58,6 @@ public: signals: void changed(); void fileNameChanged(const QString &fileName); - void modificationChanged(bool modified); public: Project *project() const { return m_project.data(); } @@ -66,7 +65,7 @@ public: void newProject(const QString &fileName); void setFileName(const QString &fileName); - void setModified(bool modified); + void setModified(); void load(); void save(); @@ -74,7 +73,7 @@ public: private: QScopedPointer m_project; - bool m_isModified = false; + bool m_isModified; }; } // namespace qmt diff --git a/src/plugins/android/androidmanifestdocument.cpp b/src/plugins/android/androidmanifestdocument.cpp index 01b1e3d8106..e3473a891b0 100644 --- a/src/plugins/android/androidmanifestdocument.cpp +++ b/src/plugins/android/androidmanifestdocument.cpp @@ -43,12 +43,8 @@ AndroidManifestDocument::AndroidManifestDocument(AndroidManifestEditorWidget *ed setId(Constants::ANDROID_MANIFEST_EDITOR_ID); setMimeType(QLatin1String(Constants::ANDROID_MANIFEST_MIME_TYPE)); setSuspendAllowed(false); - connect(editorWidget, &AndroidManifestEditorWidget::modificationChanged, - this, &Core::IDocument::setModified); - connect(this, &Core::IDocument::modificationChanged, - editorWidget, &AndroidManifestEditorWidget::setModified); - - setModified(editorWidget->isModified()); + connect(editorWidget, &AndroidManifestEditorWidget::guiChanged, + this, &Core::IDocument::changed); } bool AndroidManifestDocument::save(QString *errorString, const QString &fileName, bool autoSave) @@ -59,6 +55,11 @@ bool AndroidManifestDocument::save(QString *errorString, const QString &fileName return result; } +bool AndroidManifestDocument::isModified() const +{ + return TextDocument::isModified() || m_editorWidget->isModified(); +} + bool AndroidManifestDocument::isSaveAsAllowed() const { return false; diff --git a/src/plugins/android/androidmanifestdocument.h b/src/plugins/android/androidmanifestdocument.h index 28b8bc8306e..169047f0516 100644 --- a/src/plugins/android/androidmanifestdocument.h +++ b/src/plugins/android/androidmanifestdocument.h @@ -39,6 +39,7 @@ public: bool save(QString *errorString, const QString &fileName = QString(), bool autoSave = false) override; + bool isModified() const override; bool isSaveAsAllowed() const override; private: diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index 6c8f7670715..a2d1d8beed8 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -101,7 +101,7 @@ Project *androidProject(const Utils::FileName &fileName) AndroidManifestEditorWidget::AndroidManifestEditorWidget() : QStackedWidget(), - m_modified(false), + m_dirty(false), m_stayClean(false) { m_textEditorWidget = new AndroidManifestTextEditorWidget(this); @@ -138,7 +138,7 @@ void AndroidManifestEditorWidget::initializePage() QGroupBox *packageGroupBox = new QGroupBox(mainWidget); topLayout->addWidget(packageGroupBox); - auto setDirtyFunc = [this] { setModified(); }; + auto setDirtyFunc = [this] { setDirty(); }; packageGroupBox->setTitle(tr("Package")); { QFormLayout *formLayout = new QFormLayout(); @@ -206,7 +206,7 @@ void AndroidManifestEditorWidget::initializePage() connect(m_packageNameLineEdit, &QLineEdit::textEdited, this, &AndroidManifestEditorWidget::setPackageName); connect(m_versionCode, static_cast(&QSpinBox::valueChanged), - this, &AndroidManifestEditorWidget::setModified); + this, &AndroidManifestEditorWidget::setDirty); connect(m_versionNameLinedit, &QLineEdit::textEdited, this, setDirtyFunc); connect(m_androidMinSdkVersion, @@ -524,17 +524,17 @@ void AndroidManifestEditorWidget::updateAfterFileLoad() setActivePage(Source); } -void AndroidManifestEditorWidget::setModified(bool modified) +void AndroidManifestEditorWidget::setDirty(bool dirty) { - if (m_stayClean || modified == m_modified) + if (m_stayClean || dirty == m_dirty) return; - m_modified = modified; - emit modificationChanged(modified); + m_dirty = dirty; + emit guiChanged(); } bool AndroidManifestEditorWidget::isModified() const { - return m_modified + return m_dirty || !m_hIconPath.isEmpty() || !m_mIconPath.isEmpty() || !m_lIconPath.isEmpty(); @@ -819,7 +819,7 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc) updateAddRemovePermissionButtons(); m_stayClean = false; - m_modified = false; + m_dirty = false; } int extractVersion(const QString &string) @@ -862,7 +862,7 @@ void AndroidManifestEditorWidget::syncToEditor() m_textEditorWidget->setPlainText(result); m_textEditorWidget->document()->setModified(true); - m_modified = false; + m_dirty = false; } namespace { @@ -1253,7 +1253,7 @@ void AndroidManifestEditorWidget::setLDPIIcon() return; m_lIconPath = file; m_lIconButton->setIcon(QIcon(file)); - setModified(true); + setDirty(true); } void AndroidManifestEditorWidget::setMDPIIcon() @@ -1263,7 +1263,7 @@ void AndroidManifestEditorWidget::setMDPIIcon() return; m_mIconPath = file; m_mIconButton->setIcon(QIcon(file)); - setModified(true); + setDirty(true); } void AndroidManifestEditorWidget::setHDPIIcon() @@ -1273,12 +1273,12 @@ void AndroidManifestEditorWidget::setHDPIIcon() return; m_hIconPath = file; m_hIconButton->setIcon(QIcon(file)); - setModified(true); + setDirty(true); } void AndroidManifestEditorWidget::defaultPermissionOrFeatureCheckBoxClicked() { - setModified(true); + setDirty(true); } void AndroidManifestEditorWidget::updateAddRemovePermissionButtons() @@ -1293,7 +1293,7 @@ void AndroidManifestEditorWidget::addPermission() { m_permissionsModel->addPermission(m_permissionsComboBox->currentText()); updateAddRemovePermissionButtons(); - setModified(true); + setDirty(true); } void AndroidManifestEditorWidget::removePermission() @@ -1302,7 +1302,7 @@ void AndroidManifestEditorWidget::removePermission() if (idx.isValid()) m_permissionsModel->removePermission(idx.row()); updateAddRemovePermissionButtons(); - setModified(true); + setDirty(true); } void AndroidManifestEditorWidget::setPackageName() @@ -1312,7 +1312,7 @@ void AndroidManifestEditorWidget::setPackageName() bool valid = checkPackageName(packageName); m_packageNameWarning->setVisible(!valid); m_packageNameWarningIcon->setVisible(!valid); - setModified(true); + setDirty(true); } diff --git a/src/plugins/android/androidmanifesteditorwidget.h b/src/plugins/android/androidmanifesteditorwidget.h index 899393ca349..9dab5e8d1a3 100644 --- a/src/plugins/android/androidmanifesteditorwidget.h +++ b/src/plugins/android/androidmanifesteditorwidget.h @@ -101,10 +101,10 @@ public: Core::IEditor *editor() const; TextEditor::TextEditorWidget *textEditorWidget() const; - void setModified(bool modified = true); + void setDirty(bool dirty = true); signals: - void modificationChanged(bool modified); + void guiChanged(); protected: bool eventFilter(QObject *obj, QEvent *event); @@ -150,7 +150,7 @@ private: QString parseComment(QXmlStreamReader &reader, QXmlStreamWriter &writer); void parseUnknownElement(QXmlStreamReader &reader, QXmlStreamWriter &writer); - bool m_modified; // indicates that we need to call syncToEditor() + bool m_dirty; // indicates that we need to call syncToEditor() bool m_stayClean; int m_errorLine; int m_errorColumn; diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp index 050bbcb6971..5fcccd78386 100644 --- a/src/plugins/bineditor/bineditorplugin.cpp +++ b/src/plugins/bineditor/bineditorplugin.cpp @@ -320,6 +320,12 @@ public: } public: + bool isModified() const override + { + return isTemporary()/*e.g. memory view*/ ? false + : m_widget->isModified(); + } + bool isFileReadOnly() const override { const FileName fn = filePath(); if (fn.isEmpty()) @@ -385,12 +391,7 @@ public: connect(m_addressEdit, &QLineEdit::editingFinished, this, &BinEditor::jumpToAddress); connect(widget, &BinEditorWidget::modificationChanged, - m_file, &IDocument::setModified); - connect(m_file, &IDocument::modificationChanged, - widget, &BinEditorWidget::setModified); - - m_file->setModified(widget->isModified()); - + m_file, &IDocument::changed); updateCursorPosition(widget->cursorPosition()); } diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp index 2553b96e612..6ba6d61ca24 100644 --- a/src/plugins/coreplugin/documentmanager.cpp +++ b/src/plugins/coreplugin/documentmanager.cpp @@ -1052,7 +1052,6 @@ void DocumentManager::checkForReload() documentsToClose << document; } else if (defaultBehavior == IDocument::IgnoreAll) { // content change or removed, but settings say ignore - document->setModified(true); success = document->reload(&errorString, IDocument::FlagIgnore, type); // either the default behavior is to always ask, // or the ReloadUnmodified default behavior didn't kick in, @@ -1070,7 +1069,6 @@ void DocumentManager::checkForReload() // content change, IDocument wants to ask user if (previousReloadAnswer == ReloadNone) { // answer already given, ignore - document->setModified(true); success = document->reload(&errorString, IDocument::FlagIgnore, IDocument::TypeContents); } else if (previousReloadAnswer == ReloadAll) { // answer already given, reload @@ -1086,7 +1084,6 @@ void DocumentManager::checkForReload() break; case ReloadSkipCurrent: case ReloadNone: - document->setModified(true); success = document->reload(&errorString, IDocument::FlagIgnore, IDocument::TypeContents); break; case CloseCurrent: diff --git a/src/plugins/coreplugin/idocument.cpp b/src/plugins/coreplugin/idocument.cpp index 9023eb73eae..fefff6a701b 100644 --- a/src/plugins/coreplugin/idocument.cpp +++ b/src/plugins/coreplugin/idocument.cpp @@ -79,7 +79,6 @@ public: bool hasWriteWarning = false; bool restored = false; bool isSuspendAllowed = false; - bool isModified = false; }; } // namespace Internal @@ -201,17 +200,7 @@ bool IDocument::shouldAutoSave() const bool IDocument::isModified() const { - return d->isModified; -} - -void IDocument::setModified(bool modified) -{ - if (d->isModified == modified) - return; - - d->isModified = modified; - emit modificationChanged(modified); - emit changed(); + return false; } bool IDocument::isSaveAsAllowed() const diff --git a/src/plugins/coreplugin/idocument.h b/src/plugins/coreplugin/idocument.h index 79cc403e6f4..acb1feb58b8 100644 --- a/src/plugins/coreplugin/idocument.h +++ b/src/plugins/coreplugin/idocument.h @@ -106,9 +106,6 @@ public: bool isTemporary() const; void setTemporary(bool temporary); - bool isModified() const; - void setModified(bool modified); - virtual QString fallbackSaveAsPath() const; virtual QString fallbackSaveAsFileName() const; @@ -116,6 +113,7 @@ public: void setMimeType(const QString &mimeType); virtual bool shouldAutoSave() const; + virtual bool isModified() const; virtual bool isSaveAsAllowed() const; bool isSuspendAllowed() const; void setSuspendAllowed(bool value); @@ -138,8 +136,6 @@ signals: // For meta data changes: file name, modified state, ... void changed(); - void modificationChanged(bool modified); - // For changes in the contents of the document void contentsChanged(); diff --git a/src/plugins/designer/formwindowfile.cpp b/src/plugins/designer/formwindowfile.cpp index a6c58617fc9..44ec146b776 100644 --- a/src/plugins/designer/formwindowfile.cpp +++ b/src/plugins/designer/formwindowfile.cpp @@ -59,9 +59,6 @@ FormWindowFile::FormWindowFile(QDesignerFormWindowInterface *form, QObject *pare connect(m_formWindow->commandHistory(), &QUndoStack::indexChanged, this, &FormWindowFile::setShouldAutoSave); connect(m_formWindow.data(), &QDesignerFormWindowInterface::changed, this, &FormWindowFile::updateIsModified); - connect(this, &IDocument::modificationChanged, m_formWindow.data(), &QDesignerFormWindowInterface::setDirty); - - setModified(m_formWindow->isDirty()); m_resourceHandler = new ResourceHandler(form); connect(this, &FormWindowFile::filePathChanged, @@ -189,7 +186,10 @@ void FormWindowFile::updateIsModified() bool value = m_formWindow && m_formWindow->isDirty(); if (value) emit contentsChanged(); - setModified(value); + if (value == m_isModified) + return; + m_isModified = value; + emit changed(); } bool FormWindowFile::shouldAutoSave() const @@ -197,6 +197,11 @@ bool FormWindowFile::shouldAutoSave() const return m_shouldAutoSave; } +bool FormWindowFile::isModified() const +{ + return m_formWindow && m_formWindow->isDirty(); +} + bool FormWindowFile::isSaveAsAllowed() const { return true; diff --git a/src/plugins/designer/formwindowfile.h b/src/plugins/designer/formwindowfile.h index f12e854a2a1..7ee62bb9518 100644 --- a/src/plugins/designer/formwindowfile.h +++ b/src/plugins/designer/formwindowfile.h @@ -53,6 +53,7 @@ public: QByteArray contents() const override; bool setContents(const QByteArray &contents) override; bool shouldAutoSave() const override; + bool isModified() const override; bool isSaveAsAllowed() const override; bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; QString fallbackSaveAsFileName() const override; @@ -81,6 +82,7 @@ private: // Might actually go out of scope before the IEditor due // to deleting the WidgetHost which owns it. QPointer m_formWindow; + bool m_isModified = false; ResourceHandler *m_resourceHandler = nullptr; }; diff --git a/src/plugins/modeleditor/extpropertiesmview.cpp b/src/plugins/modeleditor/extpropertiesmview.cpp index 20376216583..529f251dca2 100644 --- a/src/plugins/modeleditor/extpropertiesmview.cpp +++ b/src/plugins/modeleditor/extpropertiesmview.cpp @@ -92,7 +92,7 @@ void ExtPropertiesMView::onConfigPathChanged(const QString &path) if (path.isEmpty()) { if (!project->configPath().isEmpty()) { project->setConfigPath(QString()); - m_projectController->setModified(true); + m_projectController->setModified(); modified = true; } } else { @@ -103,7 +103,7 @@ void ExtPropertiesMView::onConfigPathChanged(const QString &path) QString configPath = projectDir.relativeFilePath(absConfigPath.filePath()); if (configPath != project->configPath()) { project->setConfigPath(configPath); - m_projectController->setModified(true); + m_projectController->setModified(); modified = true; } } diff --git a/src/plugins/modeleditor/modeldocument.cpp b/src/plugins/modeleditor/modeldocument.cpp index 82a38f19ef8..e75ff0760e1 100644 --- a/src/plugins/modeleditor/modeldocument.cpp +++ b/src/plugins/modeleditor/modeldocument.cpp @@ -94,7 +94,7 @@ bool ModelDocument::save(QString *errorString, const QString &name, bool autoSav } if (autoSave) { - d->documentController->projectController()->setModified(true); + d->documentController->projectController()->setModified(); } else { setFilePath(Utils::FileName::fromString(d->documentController->projectController()->project()->fileName())); emit changed(); @@ -108,6 +108,11 @@ bool ModelDocument::shouldAutoSave() const return isModified(); } +bool ModelDocument::isModified() const +{ + return d->documentController ? d->documentController->projectController()->isModified() : false; +} + bool ModelDocument::isSaveAsAllowed() const { return true; @@ -135,10 +140,6 @@ Core::IDocument::OpenResult ModelDocument::load(QString *errorString, const QStr { d->documentController = ModelEditorPlugin::modelsManager()->createModel(this); connect(d->documentController, &qmt::DocumentController::changed, this, &IDocument::changed); - connect(d->documentController, &qmt::DocumentController::modificationChanged, this, &IDocument::setModified); - connect(this, &IDocument::modificationChanged, - d->documentController->projectController(), &qmt::ProjectController::setModified); - setModified(d->documentController->projectController()->isModified()); try { d->documentController->loadProject(fileName); diff --git a/src/plugins/modeleditor/modeldocument.h b/src/plugins/modeleditor/modeldocument.h index 2d0a0aafee2..f83085866ab 100644 --- a/src/plugins/modeleditor/modeldocument.h +++ b/src/plugins/modeleditor/modeldocument.h @@ -52,6 +52,7 @@ public: const QString &realFileName) override; bool save(QString *errorString, const QString &fileName, bool autoSave) override; bool shouldAutoSave() const override; + bool isModified() const override; bool isSaveAsAllowed() const override; bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; diff --git a/src/plugins/resourceeditor/resourceeditorw.cpp b/src/plugins/resourceeditor/resourceeditorw.cpp index 765aa5e1104..2058c3a2eaf 100644 --- a/src/plugins/resourceeditor/resourceeditorw.cpp +++ b/src/plugins/resourceeditor/resourceeditorw.cpp @@ -63,14 +63,10 @@ ResourceEditorDocument::ResourceEditorDocument(QObject *parent) : setId(ResourceEditor::Constants::RESOURCEEDITOR_ID); setMimeType(QLatin1String(ResourceEditor::Constants::C_RESOURCE_MIMETYPE)); connect(m_model, &RelativeResourceModel::dirtyChanged, - this, &ResourceEditorDocument::setModified); - connect(this, &IDocument::modificationChanged, - m_model, &RelativeResourceModel::setDirty); + this, &ResourceEditorDocument::dirtyChanged); connect(m_model, &ResourceModel::contentsChanged, this, &IDocument::contentsChanged); - setModified(m_model->dirty()); - if (debugResourceEditorW) qDebug() << "ResourceEditorFile::ResourceEditorFile()"; } @@ -128,16 +124,20 @@ Core::IDocument::OpenResult ResourceEditorDocument::open(QString *errorString, if (debugResourceEditorW) qDebug() << "ResourceEditorW::open: " << fileName; + setBlockDirtyChanged(true); + m_model->setFileName(realFileName); OpenResult openResult = m_model->reload(); if (openResult != OpenResult::Success) { *errorString = m_model->errorMessage(); + setBlockDirtyChanged(false); emit loaded(false); return openResult; } setFilePath(FileName::fromString(fileName)); + setBlockDirtyChanged(false); m_model->setDirty(fileName != realFileName); m_shouldAutoSave = false; @@ -155,10 +155,12 @@ bool ResourceEditorDocument::save(QString *errorString, const QString &name, boo if (actualName.isEmpty()) return false; + m_blockDirtyChanged = true; m_model->setFileName(actualName.toString()); if (!m_model->save()) { *errorString = m_model->errorMessage(); m_model->setFileName(oldFileName.toString()); + m_blockDirtyChanged = false; return false; } @@ -166,10 +168,12 @@ bool ResourceEditorDocument::save(QString *errorString, const QString &name, boo if (autoSave) { m_model->setFileName(oldFileName.toString()); m_model->setDirty(true); + m_blockDirtyChanged = false; return true; } setFilePath(actualName); + m_blockDirtyChanged = false; emit changed(); return true; @@ -209,6 +213,11 @@ void ResourceEditorDocument::setFilePath(const FileName &newName) IDocument::setFilePath(newName); } +void ResourceEditorDocument::setBlockDirtyChanged(bool value) +{ + m_blockDirtyChanged = value; +} + RelativeResourceModel *ResourceEditorDocument::model() const { return m_model; @@ -229,6 +238,11 @@ bool ResourceEditorDocument::shouldAutoSave() const return m_shouldAutoSave; } +bool ResourceEditorDocument::isModified() const +{ + return m_model->dirty(); +} + bool ResourceEditorDocument::isSaveAsAllowed() const { return true; @@ -250,6 +264,16 @@ bool ResourceEditorDocument::reload(QString *errorString, ReloadFlag flag, Chang return true; } +void ResourceEditorDocument::dirtyChanged(bool dirty) +{ + if (m_blockDirtyChanged) + return; // We emit changed() afterwards, unless it was an autosave + + if (debugResourceEditorW) + qDebug() << " ResourceEditorW::dirtyChanged" << dirty; + emit changed(); +} + void ResourceEditorW::onUndoStackChanged(bool canUndo, bool canRedo) { m_plugin->onUndoStackChanged(this, canUndo, canRedo); diff --git a/src/plugins/resourceeditor/resourceeditorw.h b/src/plugins/resourceeditor/resourceeditorw.h index 0ac7005df4f..3d8d139e3c2 100644 --- a/src/plugins/resourceeditor/resourceeditorw.h +++ b/src/plugins/resourceeditor/resourceeditorw.h @@ -58,9 +58,11 @@ public: QByteArray contents() const override; bool setContents(const QByteArray &contents) override; bool shouldAutoSave() const override; + bool isModified() const override; bool isSaveAsAllowed() const override; bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; void setFilePath(const Utils::FileName &newName) override; + void setBlockDirtyChanged(bool value); RelativeResourceModel *model() const; void setShouldAutoSave(bool save); @@ -69,8 +71,10 @@ signals: void loaded(bool success); private: + void dirtyChanged(bool); RelativeResourceModel *m_model; + bool m_blockDirtyChanged = false; bool m_shouldAutoSave = false; }; diff --git a/src/plugins/scxmleditor/common/mainwidget.cpp b/src/plugins/scxmleditor/common/mainwidget.cpp index e68b5736008..09c00c0f623 100644 --- a/src/plugins/scxmleditor/common/mainwidget.cpp +++ b/src/plugins/scxmleditor/common/mainwidget.cpp @@ -789,11 +789,6 @@ bool MainWidget::isDirty() const return m_document->changed(); } -void MainWidget::setDirty(bool dirty) -{ - m_document->setChanged(dirty); -} - void MainWidget::fitToView() { StateView *view = m_views.last(); diff --git a/src/plugins/scxmleditor/common/mainwidget.h b/src/plugins/scxmleditor/common/mainwidget.h index 64e17a97303..6b75895b0f3 100644 --- a/src/plugins/scxmleditor/common/mainwidget.h +++ b/src/plugins/scxmleditor/common/mainwidget.h @@ -87,7 +87,6 @@ public: QString contents() const; QUndoStack *undoStack() const; bool isDirty() const; - void setDirty(bool dirty); void newDocument(); void refresh(); OutputPane::WarningModel *warningModel() const; diff --git a/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp b/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp index 1ad7b9ba2f9..22cbdf4d4e7 100644 --- a/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp +++ b/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp @@ -643,14 +643,6 @@ bool ScxmlDocument::changed() const return !m_undoStack->isClean(); } -void ScxmlDocument::setChanged(bool modified) -{ - if (modified) - ; // we lack a setDirty method in QUndoStack - else - m_undoStack->setClean(); -} - ScxmlTag *ScxmlDocument::scxmlRootTag() const { ScxmlTag *tag = rootTag(); diff --git a/src/plugins/scxmleditor/plugin_interface/scxmldocument.h b/src/plugins/scxmleditor/plugin_interface/scxmldocument.h index 5d654d4d0b1..19506731f23 100644 --- a/src/plugins/scxmleditor/plugin_interface/scxmldocument.h +++ b/src/plugins/scxmleditor/plugin_interface/scxmldocument.h @@ -156,7 +156,6 @@ public: * @return - true if changed, false otherwise */ bool changed() const; - void setChanged(bool modified); /** * @brief rootTag - return rootTag of the document @@ -278,7 +277,6 @@ private: ScxmlTag *createScxmlTag(); QString m_fileName; QUndoStack *m_undoStack; - int m_cleanIndex; QVector m_tags; QHash m_nextIdHash; QHash m_idMap; diff --git a/src/plugins/scxmleditor/scxmleditordocument.cpp b/src/plugins/scxmleditor/scxmleditordocument.cpp index 97569bc7d29..d7c09b9e883 100644 --- a/src/plugins/scxmleditor/scxmleditordocument.cpp +++ b/src/plugins/scxmleditor/scxmleditordocument.cpp @@ -52,12 +52,9 @@ ScxmlEditorDocument::ScxmlEditorDocument(MainWidget *designWidget, QObject *pare // Designer needs UTF-8 regardless of settings. setCodec(QTextCodec::codecForName("UTF-8")); - connect(m_designWidget.data(), &Common::MainWidget::dirtyChanged, this, [this](bool modified){ - setModified(modified); + connect(m_designWidget.data(), &Common::MainWidget::dirtyChanged, this, [this]{ + emit changed(); }); - connect(this, &IDocument::modificationChanged, m_designWidget.data(), &Common::MainWidget::setDirty); - - setModified(m_designWidget->isDirty()); } Core::IDocument::OpenResult ScxmlEditorDocument::open(QString *errorString, const QString &fileName, const QString &realFileName) @@ -132,6 +129,11 @@ MainWidget *ScxmlEditorDocument::designWidget() const return m_designWidget; } +bool ScxmlEditorDocument::isModified() const +{ + return m_designWidget && m_designWidget->isDirty(); +} + bool ScxmlEditorDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type) { if (flag == FlagIgnore) { diff --git a/src/plugins/scxmleditor/scxmleditordocument.h b/src/plugins/scxmleditor/scxmleditordocument.h index a3211c656e9..2ccb98213d5 100644 --- a/src/plugins/scxmleditor/scxmleditordocument.h +++ b/src/plugins/scxmleditor/scxmleditordocument.h @@ -53,6 +53,7 @@ public: bool save(QString *errorString, const QString &fileName, bool autoSave) override; bool shouldAutoSave() const override; bool isSaveAsAllowed() const override; + bool isModified() const override; bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; // Internal diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index 418a0bd11a1..e3e73546443 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -236,16 +236,13 @@ void TextDocumentPrivate::updateRevisions() TextDocument::TextDocument(Id id) : d(new TextDocumentPrivate) { - connect(&d->m_document, &QTextDocument::modificationChanged, [this](bool modified) { + QObject::connect(&d->m_document, &QTextDocument::modificationChanged, [this](bool modified) { // we only want to update the block revisions when going back to the saved version, // e.g. with undo if (!modified) d->updateRevisions(); - setModified(modified); + emit changed(); }); - connect(this, &IDocument::modificationChanged, &d->m_document, &QTextDocument::setModified); - - setModified(d->m_document.isModified()); connect(&d->m_document, &QTextDocument::contentsChanged, this, &Core::IDocument::contentsChanged); @@ -598,6 +595,11 @@ bool TextDocument::isFileReadOnly() const return d->m_fileIsReadOnly; } +bool TextDocument::isModified() const +{ + return d->m_document.isModified(); +} + void TextDocument::checkPermissions() { bool previousReadOnly = d->m_fileIsReadOnly; diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 78cd3dd4b8e..6aa2e0bd7c6 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -103,6 +103,7 @@ public: bool setContents(const QByteArray &contents) override; bool shouldAutoSave() const override; bool isFileReadOnly() const override; + bool isModified() const override; bool isSaveAsAllowed() const override; void checkPermissions() override; bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; diff --git a/src/plugins/vcsbase/submiteditorfile.cpp b/src/plugins/vcsbase/submiteditorfile.cpp index 9a38537078c..9136118bf7e 100644 --- a/src/plugins/vcsbase/submiteditorfile.cpp +++ b/src/plugins/vcsbase/submiteditorfile.cpp @@ -44,6 +44,7 @@ using namespace Utils; SubmitEditorFile::SubmitEditorFile(const VcsBaseSubmitEditorParameters *parameters, VcsBaseSubmitEditor *parent) : Core::IDocument(parent), + m_modified(false), m_editor(parent) { setId(parameters->id); @@ -82,6 +83,14 @@ bool SubmitEditorFile::setContents(const QByteArray &contents) return m_editor->setFileContents(contents); } +void SubmitEditorFile::setModified(bool modified) +{ + if (m_modified == modified) + return; + m_modified = modified; + emit changed(); +} + bool SubmitEditorFile::save(QString *errorString, const QString &fileName, bool autoSave) { const FileName fName = fileName.isEmpty() ? filePath() : FileName::fromString(fileName); diff --git a/src/plugins/vcsbase/submiteditorfile.h b/src/plugins/vcsbase/submiteditorfile.h index 82263f9ef03..e2da2f72fa8 100644 --- a/src/plugins/vcsbase/submiteditorfile.h +++ b/src/plugins/vcsbase/submiteditorfile.h @@ -45,10 +45,14 @@ public: QByteArray contents() const override; bool setContents(const QByteArray &contents) override; + bool isModified() const override { return m_modified; } bool save(QString *errorString, const QString &fileName, bool autoSave) override; ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override; + void setModified(bool modified = true); + private: + bool m_modified; VcsBaseSubmitEditor *m_editor; }; From 72e19c4886066cd71cb075af0efde8f701fcfb24 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 20 Oct 2016 14:45:15 +0200 Subject: [PATCH 35/53] Fix marking files modified externally as modified It replaces 59c90e00c1e8b18d120f5b5c15b331b1ee427ace and d0c537ca759aa7facfdd0efedac5f5385d16ddb9 Task-number: QTCREATORBUG-17048 Change-Id: Ief4b1b72f2e5e7b1711be05d4ea8c03bbbf48fdf Reviewed-by: Tobias Hunger --- src/libs/utils/guard.cpp | 113 ++++++++++++++++++++++++ src/libs/utils/guard.h | 53 +++++++++++ src/libs/utils/utils-lib.pri | 6 +- src/libs/utils/utils.qbs | 2 + src/plugins/designer/formwindowfile.cpp | 17 +++- src/plugins/designer/formwindowfile.h | 2 + src/plugins/texteditor/textdocument.cpp | 38 ++++++-- src/plugins/texteditor/textdocument.h | 1 + 8 files changed, 220 insertions(+), 12 deletions(-) create mode 100644 src/libs/utils/guard.cpp create mode 100644 src/libs/utils/guard.h diff --git a/src/libs/utils/guard.cpp b/src/libs/utils/guard.cpp new file mode 100644 index 00000000000..925bdb226f9 --- /dev/null +++ b/src/libs/utils/guard.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "guard.h" +#include "qtcassert.h" + +/*! \class Utils::Guard + + \brief The Guard class implements a recursive guard with locking mechanism. + + It may be used as an alternative to QSignalBlocker. + QSignalBlocker blocks all signals of the object + which is usually not desirable. It may also block signals + which are needed internally by the object itself. + The Guard and GuardLocker classes don't block signals at all. + + When calling a object's method which may in turn emit a signal + which you are connected to, and you want to ignore + this notification, you should keep the Guard object + as your class member and declare the GuardLocker object + just before calling the mentioned method, like: + + \code + class MyClass : public QObject + { + \dots + private: + Guard updateGuard; // member of your class + }; + + \dots + + void MyClass::updateOtherObject() + { + GuardLocker updatelocker(updateGuard); + otherObject->update(); // this may trigger a signal + } + \endcode + + Inside a slot which is connected to the other's object signal + you may check if the guard is locked and ignore the further + operations in this case: + + \code + void MyClass::otherObjectUpdated() + { + if (updateGuard.isLocked) + return; + + // we didn't trigger the update + // so do update now + \dots + } + \endcode + + The GuardLock unlocks the Guard in it's destructor. + + The Guard object is recursive, you may declare many GuardLocker + objects for the same Guard instance and the Guard will be locked + as long as at least one GuardLocker object created for the Guard + is in scope. +*/ + +namespace Utils { + +Guard::Guard() +{ +} + +Guard::~Guard() +{ + QTC_CHECK(m_lockCount == 0); +} + +bool Guard::isLocked() const +{ + return m_lockCount; +} + +GuardLocker::GuardLocker(Guard &guard) + : m_guard(guard) +{ + ++m_guard.m_lockCount; +} + +GuardLocker::~GuardLocker() +{ + --m_guard.m_lockCount; +} + +} // namespace Utils diff --git a/src/libs/utils/guard.h b/src/libs/utils/guard.h new file mode 100644 index 00000000000..41bfd822887 --- /dev/null +++ b/src/libs/utils/guard.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "utils_global.h" + +namespace Utils { + +class QTCREATOR_UTILS_EXPORT Guard +{ +public: + Guard(); + ~Guard(); + bool isLocked() const; +private: + int m_lockCount = 0; + friend class GuardLocker; +}; + +class QTCREATOR_UTILS_EXPORT GuardLocker +{ +public: + GuardLocker(Guard &guard); + ~GuardLocker(); + +private: + Guard &m_guard; +}; + +} // namespace Utils diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index fc7b552ff67..8442d7c351c 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -100,7 +100,8 @@ SOURCES += $$PWD/environment.cpp \ $$PWD/icon.cpp \ $$PWD/port.cpp \ $$PWD/runextensions.cpp \ - $$PWD/utilsicons.cpp + $$PWD/utilsicons.cpp \ + $$PWD/guard.cpp win32:SOURCES += $$PWD/consoleprocess_win.cpp else:SOURCES += $$PWD/consoleprocess_unix.cpp @@ -217,7 +218,8 @@ HEADERS += \ $$PWD/smallstringvector.h \ $$PWD/smallstringlayout.h \ $$PWD/sizedarray.h \ - $$PWD/smallstringio.h + $$PWD/smallstringio.h \ + $$PWD/guard.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/projectintropage.ui \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 54a2f71b840..3bf52fc8c6b 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -114,6 +114,8 @@ Project { "flowlayout.cpp", "flowlayout.h", "functiontraits.h", + "guard.cpp", + "guard.h", "historycompleter.cpp", "historycompleter.h", "hostosinfo.h", diff --git a/src/plugins/designer/formwindowfile.cpp b/src/plugins/designer/formwindowfile.cpp index 44ec146b776..e5b6a313bef 100644 --- a/src/plugins/designer/formwindowfile.cpp +++ b/src/plugins/designer/formwindowfile.cpp @@ -183,6 +183,9 @@ void FormWindowFile::setFilePath(const FileName &newName) void FormWindowFile::updateIsModified() { + if (m_modificationChangedGuard.isLocked()) + return; + bool value = m_formWindow && m_formWindow->isDirty(); if (value) emit contentsChanged(); @@ -209,8 +212,20 @@ bool FormWindowFile::isSaveAsAllowed() const bool FormWindowFile::reload(QString *errorString, ReloadFlag flag, ChangeType type) { - if (flag == FlagIgnore) + if (flag == FlagIgnore) { + if (!m_formWindow || type != TypeContents) + return true; + const bool wasModified = m_formWindow->isDirty(); + { + Utils::GuardLocker locker(m_modificationChangedGuard); + // hack to ensure we clean the clear state in form window + m_formWindow->setDirty(false); + m_formWindow->setDirty(true); + } + if (!wasModified) + updateIsModified(); return true; + } if (type == TypePermissions) { emit changed(); } else { diff --git a/src/plugins/designer/formwindowfile.h b/src/plugins/designer/formwindowfile.h index 7ee62bb9518..a78d576ad9a 100644 --- a/src/plugins/designer/formwindowfile.h +++ b/src/plugins/designer/formwindowfile.h @@ -26,6 +26,7 @@ #pragma once #include +#include #include @@ -84,6 +85,7 @@ private: QPointer m_formWindow; bool m_isModified = false; ResourceHandler *m_resourceHandler = nullptr; + Utils::Guard m_modificationChangedGuard; }; } // namespace Internal diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index e3e73546443..dc7bd87296f 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,7 @@ public: int m_autoSaveRevision; TextMarks m_marksCache; // Marks not owned + Utils::Guard m_modificationChangedGuard; }; QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor, bool doIndent, @@ -236,14 +238,8 @@ void TextDocumentPrivate::updateRevisions() TextDocument::TextDocument(Id id) : d(new TextDocumentPrivate) { - QObject::connect(&d->m_document, &QTextDocument::modificationChanged, [this](bool modified) { - // we only want to update the block revisions when going back to the saved version, - // e.g. with undo - if (!modified) - d->updateRevisions(); - emit changed(); - }); - + connect(&d->m_document, &QTextDocument::modificationChanged, + this, &TextDocument::modificationChanged); connect(&d->m_document, &QTextDocument::contentsChanged, this, &Core::IDocument::contentsChanged); connect(&d->m_document, &QTextDocument::contentsChange, @@ -723,8 +719,21 @@ bool TextDocument::setPlainText(const QString &text) bool TextDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type) { - if (flag == FlagIgnore) + if (flag == FlagIgnore) { + if (type != TypeContents) + return true; + + const bool wasModified = document()->isModified(); + { + Utils::GuardLocker locker(d->m_modificationChangedGuard); + // hack to ensure we clean the clear state in QTextDocument + document()->setModified(false); + document()->setModified(true); + } + if (!wasModified) + modificationChanged(true); return true; + } if (type == TypePermissions) { checkPermissions(); return true; @@ -808,6 +817,17 @@ void TextDocument::ensureFinalNewLine(QTextCursor& cursor) } } +void TextDocument::modificationChanged(bool modified) +{ + if (d->m_modificationChangedGuard.isLocked()) + return; + // we only want to update the block revisions when going back to the saved version, + // e.g. with undo + if (!modified) + d->updateRevisions(); + emit changed(); +} + TextMarks TextDocument::marks() const { return d->m_marksCache; diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 6aa2e0bd7c6..30576043b40 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -151,6 +151,7 @@ private: bool reload); void cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, bool inEntireDocument); void ensureFinalNewLine(QTextCursor &cursor); + void modificationChanged(bool modified); TextDocumentPrivate *d; }; From 14148261832186e30f264a14a6d76a92bb0e2f7f Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 5 Oct 2016 17:37:00 +0200 Subject: [PATCH 36/53] Implement diff on close, on revert and on external modification Task-number: QTCREATORBUG-1531 Change-Id: I8c9a740d66eb7836b3df6850ac243260fd282b32 Reviewed-by: Tobias Hunger --- src/libs/utils/reloadpromptutils.cpp | 18 ++++- src/libs/utils/reloadpromptutils.h | 6 +- src/plugins/coreplugin/coreplugin.pro | 3 +- src/plugins/coreplugin/coreplugin.qbs | 1 + .../coreplugin/dialogs/saveitemsdialog.cpp | 52 +++++++++--- .../coreplugin/dialogs/saveitemsdialog.h | 6 +- src/plugins/coreplugin/diffservice.h | 47 +++++++++++ src/plugins/coreplugin/documentmanager.cpp | 24 +++++- .../editormanager/editormanager.cpp | 11 +++ src/plugins/diffeditor/diffeditorplugin.cpp | 81 +++++++++++++++++++ src/plugins/diffeditor/diffeditorplugin.h | 11 +++ 11 files changed, 243 insertions(+), 17 deletions(-) create mode 100644 src/plugins/coreplugin/diffservice.h diff --git a/src/libs/utils/reloadpromptutils.cpp b/src/libs/utils/reloadpromptutils.cpp index 8eec9e92e1b..798a4876a70 100644 --- a/src/libs/utils/reloadpromptutils.cpp +++ b/src/libs/utils/reloadpromptutils.cpp @@ -35,6 +35,7 @@ namespace Utils { QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName, bool modified, + bool enableDiffOption, QWidget *parent) { @@ -50,12 +51,13 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName, "The file %1 has changed outside Qt Creator. Do you want to reload it?"); } msg = msg.arg(fileName.fileName()); - return reloadPrompt(title, msg, fileName.toUserOutput(), parent); + return reloadPrompt(title, msg, fileName.toUserOutput(), enableDiffOption, parent); } QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const QString &title, const QString &prompt, const QString &details, + bool enableDiffOption, QWidget *parent) { QMessageBox msg(parent); @@ -69,7 +71,19 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const QString &title, msg.button(QMessageBox::Close)->setText(QCoreApplication::translate("Utils::reloadPrompt", "&Close")); - switch (msg.exec()) { + QPushButton *diffButton = nullptr; + if (enableDiffOption) { + diffButton = msg.addButton(QCoreApplication::translate( + "Utils::reloadPrompt", "No to All && &Diff"), + QMessageBox::NoRole); + } + + const int result = msg.exec(); + + if (msg.clickedButton() == diffButton) + return ReloadNoneAndDiff; + + switch (result) { case QMessageBox::Yes: return ReloadCurrent; case QMessageBox::YesToAll: diff --git a/src/libs/utils/reloadpromptutils.h b/src/libs/utils/reloadpromptutils.h index b01bd25b53b..8991d52b59b 100644 --- a/src/libs/utils/reloadpromptutils.h +++ b/src/libs/utils/reloadpromptutils.h @@ -40,15 +40,19 @@ enum ReloadPromptAnswer { ReloadAll, ReloadSkipCurrent, ReloadNone, + ReloadNoneAndDiff, CloseCurrent }; QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName, bool modified, + bool enableDiffOption, QWidget *parent); QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const QString &title, const QString &prompt, - const QString &details, QWidget *parent); + const QString &details, + bool enableDiffOption, + QWidget *parent); enum FileDeletedPromptAnswer { FileDeletedClose, diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index 9c8be5cfa76..6de7837acfc 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -218,7 +218,8 @@ HEADERS += corejsextensions.h \ iwelcomepage.h \ systemsettings.h \ coreicons.h \ - editormanager/documentmodel_p.h + editormanager/documentmodel_p.h \ + diffservice.h FORMS += dialogs/newdialog.ui \ dialogs/saveitemsdialog.ui \ diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index ed50f54985d..fe6b3cb75e9 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -41,6 +41,7 @@ Project { "corejsextensions.cpp", "corejsextensions.h", "coreplugin.cpp", "coreplugin.h", "designmode.cpp", "designmode.h", + "diffservice.h", "documentmanager.cpp", "documentmanager.h", "editmode.cpp", "editmode.h", "editortoolbar.cpp", "editortoolbar.h", diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp index 885b08e9346..a36ecd9d485 100644 --- a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp +++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp @@ -25,12 +25,15 @@ #include "saveitemsdialog.h" +#include #include #include #include #include +#include + #include #include #include @@ -51,6 +54,12 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent, // QDialogButtonBox's behavior for "destructive" is wrong, the "do not save" should be left-aligned const QDialogButtonBox::ButtonRole discardButtonRole = Utils::HostOsInfo::isMacHost() ? QDialogButtonBox::ResetRole : QDialogButtonBox::DestructiveRole; + + if (ExtensionSystem::PluginManager::getObject()) { + m_diffButton = m_ui.buttonBox->addButton(tr("&Diff"), discardButtonRole); + connect(m_diffButton, &QAbstractButton::clicked, this, &SaveItemsDialog::collectFilesToDiff); + } + QPushButton *discardButton = m_ui.buttonBox->addButton(tr("Do not Save"), discardButtonRole); m_ui.buttonBox->button(QDialogButtonBox::Save)->setDefault(true); m_ui.treeWidget->setFocus(); @@ -80,13 +89,13 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent, if (Utils::HostOsInfo::isMacHost()) m_ui.treeWidget->setAlternatingRowColors(true); adjustButtonWidths(); - updateSaveButton(); + updateButtons(); connect(m_ui.buttonBox->button(QDialogButtonBox::Save), &QAbstractButton::clicked, this, &SaveItemsDialog::collectItemsToSave); connect(discardButton, &QAbstractButton::clicked, this, &SaveItemsDialog::discardAll); connect(m_ui.treeWidget, &QTreeWidget::itemSelectionChanged, - this, &SaveItemsDialog::updateSaveButton); + this, &SaveItemsDialog::updateButtons); } void SaveItemsDialog::setMessage(const QString &msg) @@ -94,19 +103,27 @@ void SaveItemsDialog::setMessage(const QString &msg) m_ui.msgLabel->setText(msg); } -void SaveItemsDialog::updateSaveButton() +void SaveItemsDialog::updateButtons() { int count = m_ui.treeWidget->selectedItems().count(); - QPushButton *button = m_ui.buttonBox->button(QDialogButtonBox::Save); + QPushButton *saveButton = m_ui.buttonBox->button(QDialogButtonBox::Save); + bool buttonsEnabled = true; + QString saveText = tr("Save"); + QString diffText = tr("&Diff && Cancel"); if (count == m_ui.treeWidget->topLevelItemCount()) { - button->setEnabled(true); - button->setText(tr("Save All")); + saveText = tr("Save All"); + diffText = tr("&Diff All && Cancel"); } else if (count == 0) { - button->setEnabled(false); - button->setText(tr("Save")); + buttonsEnabled = false; } else { - button->setEnabled(true); - button->setText(tr("Save Selected")); + saveText = tr("Save Selected"); + diffText = tr("&Diff Selected && Cancel"); + } + saveButton->setEnabled(buttonsEnabled); + saveButton->setText(saveText); + if (m_diffButton) { + m_diffButton->setEnabled(buttonsEnabled); + m_diffButton->setText(diffText); } } @@ -145,6 +162,16 @@ void SaveItemsDialog::collectItemsToSave() accept(); } +void SaveItemsDialog::collectFilesToDiff() +{ + m_filesToDiff.clear(); + foreach (QTreeWidgetItem *item, m_ui.treeWidget->selectedItems()) { + if (IDocument *doc = item->data(0, Qt::UserRole).value()) + m_filesToDiff.append(doc->filePath().toString()); + } + reject(); +} + void SaveItemsDialog::discardAll() { m_ui.treeWidget->clearSelection(); @@ -156,6 +183,11 @@ QList SaveItemsDialog::itemsToSave() const return m_itemsToSave; } +QStringList SaveItemsDialog::filesToDiff() const +{ + return m_filesToDiff; +} + void SaveItemsDialog::setAlwaysSaveMessage(const QString &msg) { m_ui.saveBeforeBuildCheckBox->setText(msg); diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.h b/src/plugins/coreplugin/dialogs/saveitemsdialog.h index 623cb2e85f7..1048ca03481 100644 --- a/src/plugins/coreplugin/dialogs/saveitemsdialog.h +++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.h @@ -54,15 +54,19 @@ public: void setAlwaysSaveMessage(const QString &msg); bool alwaysSaveChecked(); QList itemsToSave() const; + QStringList filesToDiff() const; private: void collectItemsToSave(); + void collectFilesToDiff(); void discardAll(); - void updateSaveButton(); + void updateButtons(); void adjustButtonWidths(); Ui::SaveItemsDialog m_ui; QList m_itemsToSave; + QStringList m_filesToDiff; + QPushButton *m_diffButton = nullptr; }; } // namespace Internal diff --git a/src/plugins/coreplugin/diffservice.h b/src/plugins/coreplugin/diffservice.h new file mode 100644 index 00000000000..3b282170ddc --- /dev/null +++ b/src/plugins/coreplugin/diffservice.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "core_global.h" +#include + +QT_FORWARD_DECLARE_CLASS(QStringList) + +namespace Core { + +class CORE_EXPORT DiffService +{ +public: + virtual ~DiffService() {} + + virtual void diffModifiedFiles(const QStringList &fileNames) = 0; +}; + +} // namespace Core + +QT_BEGIN_NAMESPACE +Q_DECLARE_INTERFACE(Core::DiffService, "Core::DiffService") +QT_END_NAMESPACE diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp index 6ba6d61ca24..5a936731fa0 100644 --- a/src/plugins/coreplugin/documentmanager.cpp +++ b/src/plugins/coreplugin/documentmanager.cpp @@ -29,6 +29,7 @@ #include "idocument.h" #include "coreconstants.h" +#include #include #include #include @@ -38,6 +39,8 @@ #include #include +#include + #include #include #include @@ -606,6 +609,11 @@ static bool saveModifiedFilesHelper(const QList &documents, (*alwaysSave) = dia.alwaysSaveChecked(); if (failedToSave) (*failedToSave) = modifiedDocuments; + const QStringList filesToDiff = dia.filesToDiff(); + if (!filesToDiff.isEmpty()) { + if (auto diffService = ExtensionSystem::PluginManager::getObject()) + diffService->diffModifiedFiles(filesToDiff); + } return false; } if (alwaysSave) @@ -978,6 +986,7 @@ void DocumentManager::checkForReload() // handle the IDocuments QStringList errorStrings; + QStringList filesToDiff; foreach (IDocument *document, changedIDocuments) { IDocument::ChangeTrigger trigger = IDocument::TriggerInternal; IDocument::ChangeType type = IDocument::TypePermissions; @@ -1067,7 +1076,7 @@ void DocumentManager::checkForReload() // IDocument wants us to ask } else if (type == IDocument::TypeContents) { // content change, IDocument wants to ask user - if (previousReloadAnswer == ReloadNone) { + if (previousReloadAnswer == ReloadNone || previousReloadAnswer == ReloadNoneAndDiff) { // answer already given, ignore success = document->reload(&errorString, IDocument::FlagIgnore, IDocument::TypeContents); } else if (previousReloadAnswer == ReloadAll) { @@ -1076,7 +1085,8 @@ void DocumentManager::checkForReload() } else { // Ask about content change previousReloadAnswer = reloadPrompt(document->filePath(), document->isModified(), - ICore::dialogParent()); + ExtensionSystem::PluginManager::getObject(), + ICore::dialogParent()); switch (previousReloadAnswer) { case ReloadAll: case ReloadCurrent: @@ -1084,6 +1094,7 @@ void DocumentManager::checkForReload() break; case ReloadSkipCurrent: case ReloadNone: + case ReloadNoneAndDiff: success = document->reload(&errorString, IDocument::FlagIgnore, IDocument::TypeContents); break; case CloseCurrent: @@ -1091,6 +1102,9 @@ void DocumentManager::checkForReload() break; } } + if (previousReloadAnswer == ReloadNoneAndDiff) + filesToDiff.append(document->filePath().toString()); + // IDocument wants us to ask, and it's the TypeRemoved case } else { // Ask about removed file @@ -1134,6 +1148,12 @@ void DocumentManager::checkForReload() d->m_blockedIDocument = 0; } + + if (!filesToDiff.isEmpty()) { + if (auto diffService = ExtensionSystem::PluginManager::getObject()) + diffService->diffModifiedFiles(filesToDiff); + } + if (!errorStrings.isEmpty()) QMessageBox::critical(ICore::dialogParent(), tr("File Error"), errorStrings.join(QLatin1Char('\n'))); diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 7f344ecd95f..4f13bcec2b3 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -2168,11 +2169,21 @@ void EditorManagerPrivate::revertToSaved(IDocument *document) QMessageBox::Yes|QMessageBox::No, ICore::mainWindow()); msgBox.button(QMessageBox::Yes)->setText(tr("Proceed")); msgBox.button(QMessageBox::No)->setText(tr("Cancel")); + + QPushButton *diffButton = nullptr; + auto diffService = ExtensionSystem::PluginManager::getObject(); + if (diffService) + diffButton = msgBox.addButton(tr("Cancel && &Diff"), QMessageBox::RejectRole); + msgBox.setDefaultButton(QMessageBox::No); msgBox.setEscapeButton(QMessageBox::No); if (msgBox.exec() == QMessageBox::No) return; + if (diffService && msgBox.clickedButton() == diffButton) { + diffService->diffModifiedFiles(QStringList() << fileName); + return; + } } QString errorString; if (!document->reload(&errorString, IDocument::FlagReload, IDocument::TypeContents)) diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index db7936f34af..a04b4b2b862 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -211,6 +211,66 @@ void DiffAllModifiedFilesController::reload() ///////////////// +class DiffModifiedFilesController : public DiffFilesController +{ + Q_OBJECT +public: + DiffModifiedFilesController(Core::IDocument *document, const QStringList &fileNames); + +protected: + void reload(); + +private: + QStringList m_fileNames; +}; + +DiffModifiedFilesController::DiffModifiedFilesController(Core::IDocument *document, const QStringList &fileNames) : + DiffFilesController(document), m_fileNames(fileNames) +{ } + +void DiffModifiedFilesController::reload() +{ + QList fileDataList; + + foreach (const QString fileName, m_fileNames) { + TextEditor::TextDocument *textDocument = qobject_cast( + Core::DocumentModel::documentForFilePath(fileName)); + + if (textDocument && textDocument->isModified()) { + QString errorString; + Utils::TextFileFormat format = textDocument->format(); + + QString leftText; + bool leftFileExists = true; + const QString fileName = textDocument->filePath().toString(); + if (Utils::TextFileFormat::readFile(fileName, + format.codec, + &leftText, &format, &errorString) + != Utils::TextFileFormat::ReadSuccess) { + leftFileExists = false; + } + + const QString rightText = textDocument->plainText(); + + FileData fileData = diffFiles(leftText, rightText); + fileData.leftFileInfo.fileName = fileName; + fileData.rightFileInfo.fileName = fileName; + fileData.leftFileInfo.typeInfo = tr("Saved"); + fileData.rightFileInfo.typeInfo = tr("Modified"); + + if (!leftFileExists) + fileData.fileOperation = FileData::NewFile; + + fileDataList << fileData; + } + } + + setDiffFiles(fileDataList); + reloadFinished(true); +} + +///////////////// + class DiffExternalFilesController : public DiffFilesController { Q_OBJECT @@ -273,6 +333,26 @@ void DiffExternalFilesController::reload() ///////////////// +DiffEditorServiceImpl::DiffEditorServiceImpl(QObject *parent) : + QObject(parent) +{ +} + +void DiffEditorServiceImpl::diffModifiedFiles(const QStringList &fileNames) +{ + const QString documentId = QLatin1String("Diff Modified Files"); + const QString title = tr("Diff Modified Files"); + auto const document = qobject_cast( + DiffEditorController::findOrCreateDocument(documentId, title)); + if (!document) + return; + + if (!DiffEditorController::controller(document)) + new DiffModifiedFilesController(document, fileNames); + Core::EditorManager::activateEditorForDocument(document); + document->reload(); +} + bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMessage) { Q_UNUSED(arguments) @@ -309,6 +389,7 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe updateActions(); addAutoReleasedObject(new DiffEditorFactory(this)); + addAutoReleasedObject(new DiffEditorServiceImpl(this)); return true; } diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h index ba0cab24337..66485660024 100644 --- a/src/plugins/diffeditor/diffeditorplugin.h +++ b/src/plugins/diffeditor/diffeditorplugin.h @@ -27,6 +27,7 @@ #include "diffeditor_global.h" +#include #include #include @@ -37,6 +38,16 @@ namespace Core { class IEditor; } namespace DiffEditor { namespace Internal { +class DiffEditorServiceImpl : public QObject, public Core::DiffService +{ + Q_OBJECT + Q_INTERFACES(Core::DiffService) +public: + explicit DiffEditorServiceImpl(QObject *parent = nullptr); + + void diffModifiedFiles(const QStringList &fileNames) override; +}; + class DiffEditorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT From 4ae306a5e13d94c3edba94ed76643f781007779b Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 18 Oct 2016 13:14:40 +0200 Subject: [PATCH 37/53] Handle "Diff All Modified Files" action enablement Also rename it to "Diff Open Files". Task-number: QTCREATORBUG-17094 Change-Id: I370c32497fcb56cb2bd84700ef7cb4aa7ba0a573 Reviewed-by: Tobias Hunger --- .../editormanager/editormanager.cpp | 4 +- .../coreplugin/editormanager/editormanager.h | 1 + src/plugins/diffeditor/diffeditorplugin.cpp | 86 +++++++++++-------- src/plugins/diffeditor/diffeditorplugin.h | 9 +- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 4f13bcec2b3..5db180a4473 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -1906,9 +1906,9 @@ void EditorManagerPrivate::handleDocumentStateChange() IDocument *document = qobject_cast(sender()); if (!document->isModified()) document->removeAutoSaveFile(); - if (EditorManager::currentDocument() == document) { + if (EditorManager::currentDocument() == document) emit m_instance->currentDocumentStateChanged(); - } + emit m_instance->documentStateChanged(document); } void EditorManagerPrivate::editorAreaDestroyed(QObject *area) diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index 46656e51b0c..b700662b9c7 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.h +++ b/src/plugins/coreplugin/editormanager/editormanager.h @@ -179,6 +179,7 @@ public: // for tests signals: void currentEditorChanged(Core::IEditor *editor); void currentDocumentStateChanged(); + void documentStateChanged(Core::IDocument *document); void editorCreated(Core::IEditor *editor, const QString &fileName); void editorOpened(Core::IEditor *editor); void editorAboutToClose(Core::IEditor *editor); diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index a04b4b2b862..83f4ad42a54 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -44,8 +44,10 @@ #include #include +#include #include +#include #include namespace DiffEditor { @@ -68,7 +70,7 @@ DiffFilesController::DiffFilesController(Core::IDocument *document) FileData DiffFilesController::diffFiles(const QString &leftContents, const QString &rightContents) { Differ differ; - QList diffList = differ.cleanupSemantics(differ.diff(leftContents, rightContents)); + const QList diffList = differ.cleanupSemantics(differ.diff(leftContents, rightContents)); QList leftDiffList; QList rightDiffList; @@ -90,7 +92,7 @@ FileData DiffFilesController::diffFiles(const QString &leftContents, const QStri const ChunkData chunkData = DiffUtils::calculateOriginalData( outputLeftDiffList, outputRightDiffList); - FileData fileData = DiffUtils::calculateContextData(chunkData, contextLineCount(), 0); + const FileData fileData = DiffUtils::calculateContextData(chunkData, contextLineCount(), 0); return fileData; } @@ -152,23 +154,23 @@ void DiffCurrentFileController::reload() ///////////////// -class DiffAllModifiedFilesController : public DiffFilesController +class DiffOpenFilesController : public DiffFilesController { Q_OBJECT public: - DiffAllModifiedFilesController(Core::IDocument *document); + DiffOpenFilesController(Core::IDocument *document); protected: void reload(); }; -DiffAllModifiedFilesController::DiffAllModifiedFilesController(Core::IDocument *document) : +DiffOpenFilesController::DiffOpenFilesController(Core::IDocument *document) : DiffFilesController(document) { } -void DiffAllModifiedFilesController::reload() +void DiffOpenFilesController::reload() { - QList openedDocuments = + const QList openedDocuments = Core::DocumentModel::openedDocuments(); QList fileDataList; @@ -333,6 +335,13 @@ void DiffExternalFilesController::reload() ///////////////// + +static TextEditor::TextDocument *currentTextDocument() +{ + return qobject_cast( + Core::EditorManager::currentDocument()); +} + DiffEditorServiceImpl::DiffEditorServiceImpl(QObject *parent) : QObject(parent) { @@ -372,11 +381,11 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe connect(m_diffCurrentFileAction, &QAction::triggered, this, &DiffEditorPlugin::diffCurrentFile); diffContainer->addAction(diffCurrentFileCommand); - QAction *diffAllModifiedFilesAction = new QAction(tr("Diff All Modified Files"), this); - Core::Command *diffAllModifiedFilesCommand = Core::ActionManager::registerAction(diffAllModifiedFilesAction, "DiffEditor.DiffAllModifiedFiles"); - diffAllModifiedFilesCommand->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+H") : tr("Ctrl+Shift+H"))); - connect(diffAllModifiedFilesAction, &QAction::triggered, this, &DiffEditorPlugin::diffAllModifiedFiles); - diffContainer->addAction(diffAllModifiedFilesCommand); + m_diffOpenFilesAction = new QAction(tr("Diff Open Files"), this); + Core::Command *diffOpenFilesCommand = Core::ActionManager::registerAction(m_diffOpenFilesAction, "DiffEditor.DiffOpenFiles"); + diffOpenFilesCommand->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+H") : tr("Ctrl+Shift+H"))); + connect(m_diffOpenFilesAction, &QAction::triggered, this, &DiffEditorPlugin::diffOpenFiles); + diffContainer->addAction(diffOpenFilesCommand); QAction *diffExternalFilesAction = new QAction(tr("Diff External Files..."), this); Core::Command *diffExternalFilesCommand = Core::ActionManager::registerAction(diffExternalFilesAction, "DiffEditor.DiffExternalFiles"); @@ -384,9 +393,18 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe diffContainer->addAction(diffExternalFilesCommand); connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, - this, &DiffEditorPlugin::updateCurrentEditor); + this, &DiffEditorPlugin::updateDiffCurrentFileAction); + connect(Core::EditorManager::instance(), &Core::EditorManager::currentDocumentStateChanged, + this, &DiffEditorPlugin::updateDiffCurrentFileAction); + connect(Core::EditorManager::instance(), &Core::EditorManager::editorOpened, + this, &DiffEditorPlugin::updateDiffOpenFilesAction); + connect(Core::EditorManager::instance(), &Core::EditorManager::editorsClosed, + this, &DiffEditorPlugin::updateDiffOpenFilesAction); + connect(Core::EditorManager::instance(), &Core::EditorManager::documentStateChanged, + this, &DiffEditorPlugin::updateDiffOpenFilesAction); - updateActions(); + updateDiffCurrentFileAction(); + updateDiffOpenFilesAction(); addAutoReleasedObject(new DiffEditorFactory(this)); addAutoReleasedObject(new DiffEditorServiceImpl(this)); @@ -397,36 +415,28 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe void DiffEditorPlugin::extensionsInitialized() { } -void DiffEditorPlugin::updateCurrentEditor(Core::IEditor *editor) +void DiffEditorPlugin::updateDiffCurrentFileAction() { - if (m_currentTextDocument) - m_currentTextDocument->disconnect(this); - m_currentTextDocument = 0; - - if (editor) { - TextEditor::TextEditorWidget *editorWidget = qobject_cast(editor->widget()); - if (editorWidget) { - m_currentTextDocument = editorWidget->textDocument(); - connect(m_currentTextDocument.data(), &Core::IDocument::changed, - this, &DiffEditorPlugin::updateActions); - } - } - - updateActions(); + auto textDocument = currentTextDocument(); + const bool enabled = textDocument && textDocument->isModified(); + m_diffCurrentFileAction->setEnabled(enabled); } -void DiffEditorPlugin::updateActions() +void DiffEditorPlugin::updateDiffOpenFilesAction() { - const bool diffCurrentFileEnabled = m_currentTextDocument && m_currentTextDocument->isModified(); - m_diffCurrentFileAction->setEnabled(diffCurrentFileEnabled); + const bool enabled = Utils::anyOf(Core::DocumentModel::openedDocuments(), [](Core::IDocument *doc) { + return doc->isModified() && qobject_cast(doc); + }); + m_diffOpenFilesAction->setEnabled(enabled); } void DiffEditorPlugin::diffCurrentFile() { - if (!m_currentTextDocument) + auto textDocument = currentTextDocument(); + if (!textDocument) return; - const QString fileName = m_currentTextDocument->filePath().toString(); + const QString fileName = textDocument->filePath().toString(); if (fileName.isEmpty()) return; @@ -444,17 +454,17 @@ void DiffEditorPlugin::diffCurrentFile() document->reload(); } -void DiffEditorPlugin::diffAllModifiedFiles() +void DiffEditorPlugin::diffOpenFiles() { - const QString documentId = QLatin1String("Diff All Modified Files"); - const QString title = tr("Diff All Modified Files"); + const QString documentId = QLatin1String("Diff Open Files"); + const QString title = tr("Diff Open Files"); auto const document = qobject_cast( DiffEditorController::findOrCreateDocument(documentId, title)); if (!document) return; if (!DiffEditorController::controller(document)) - new DiffAllModifiedFilesController(document); + new DiffOpenFilesController(document); Core::EditorManager::activateEditorForDocument(document); document->reload(); } diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h index 66485660024..a04f4609e3e 100644 --- a/src/plugins/diffeditor/diffeditorplugin.h +++ b/src/plugins/diffeditor/diffeditorplugin.h @@ -28,7 +28,6 @@ #include "diffeditor_global.h" #include -#include #include QT_FORWARD_DECLARE_CLASS(QAction) @@ -58,10 +57,10 @@ public: void extensionsInitialized(); private slots: - void updateCurrentEditor(Core::IEditor *editor); - void updateActions(); + void updateDiffCurrentFileAction(); + void updateDiffOpenFilesAction(); void diffCurrentFile(); - void diffAllModifiedFiles(); + void diffOpenFiles(); void diffExternalFiles(); #ifdef WITH_TESTS @@ -72,7 +71,7 @@ private slots: #endif // WITH_TESTS private: QAction *m_diffCurrentFileAction; - QPointer m_currentTextDocument; + QAction *m_diffOpenFilesAction; }; } // namespace Internal From d3a743d77e1fbfa228f20f073636176b04123d69 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 18 Oct 2016 13:19:07 +0200 Subject: [PATCH 38/53] Use namespace Core in diff editor plugin Change-Id: I2409a6186d590a83ccde064c855e0261d600014e Reviewed-by: Tobias Hunger --- src/plugins/diffeditor/diffeditorplugin.cpp | 76 +++++++++++---------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 83f4ad42a54..ac697055008 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -50,6 +50,8 @@ #include #include +using namespace Core; + namespace DiffEditor { namespace Internal { @@ -57,13 +59,13 @@ class DiffFilesController : public DiffEditorController { Q_OBJECT public: - DiffFilesController(Core::IDocument *document); + DiffFilesController(IDocument *document); protected: FileData diffFiles(const QString &leftContents, const QString &rightContents); }; -DiffFilesController::DiffFilesController(Core::IDocument *document) +DiffFilesController::DiffFilesController(IDocument *document) : DiffEditorController(document) {} @@ -101,7 +103,7 @@ class DiffCurrentFileController : public DiffFilesController { Q_OBJECT public: - DiffCurrentFileController(Core::IDocument *document, const QString &fileName); + DiffCurrentFileController(IDocument *document, const QString &fileName); protected: void reload(); @@ -110,7 +112,7 @@ private: QString m_fileName; }; -DiffCurrentFileController::DiffCurrentFileController(Core::IDocument *document, const QString &fileName) : +DiffCurrentFileController::DiffCurrentFileController(IDocument *document, const QString &fileName) : DiffFilesController(document), m_fileName(fileName) { } @@ -119,7 +121,7 @@ void DiffCurrentFileController::reload() QList fileDataList; TextEditor::TextDocument *textDocument = qobject_cast( - Core::DocumentModel::documentForFilePath(m_fileName)); + DocumentModel::documentForFilePath(m_fileName)); if (textDocument && textDocument->isModified()) { QString errorString; @@ -158,24 +160,24 @@ class DiffOpenFilesController : public DiffFilesController { Q_OBJECT public: - DiffOpenFilesController(Core::IDocument *document); + DiffOpenFilesController(IDocument *document); protected: void reload(); }; -DiffOpenFilesController::DiffOpenFilesController(Core::IDocument *document) : +DiffOpenFilesController::DiffOpenFilesController(IDocument *document) : DiffFilesController(document) { } void DiffOpenFilesController::reload() { - const QList openedDocuments = - Core::DocumentModel::openedDocuments(); + const QList openedDocuments = + DocumentModel::openedDocuments(); QList fileDataList; - foreach (Core::IDocument *doc, openedDocuments) { + foreach (IDocument *doc, openedDocuments) { TextEditor::TextDocument *textDocument = qobject_cast(doc); if (textDocument && textDocument->isModified()) { @@ -217,7 +219,7 @@ class DiffModifiedFilesController : public DiffFilesController { Q_OBJECT public: - DiffModifiedFilesController(Core::IDocument *document, const QStringList &fileNames); + DiffModifiedFilesController(IDocument *document, const QStringList &fileNames); protected: void reload(); @@ -226,7 +228,7 @@ private: QStringList m_fileNames; }; -DiffModifiedFilesController::DiffModifiedFilesController(Core::IDocument *document, const QStringList &fileNames) : +DiffModifiedFilesController::DiffModifiedFilesController(IDocument *document, const QStringList &fileNames) : DiffFilesController(document), m_fileNames(fileNames) { } @@ -236,7 +238,7 @@ void DiffModifiedFilesController::reload() foreach (const QString fileName, m_fileNames) { TextEditor::TextDocument *textDocument = qobject_cast( - Core::DocumentModel::documentForFilePath(fileName)); + DocumentModel::documentForFilePath(fileName)); if (textDocument && textDocument->isModified()) { QString errorString; @@ -277,7 +279,7 @@ class DiffExternalFilesController : public DiffFilesController { Q_OBJECT public: - DiffExternalFilesController(Core::IDocument *document, const QString &leftFileName, + DiffExternalFilesController(IDocument *document, const QString &leftFileName, const QString &rightFileName); protected: @@ -288,7 +290,7 @@ private: QString m_rightFileName; }; -DiffExternalFilesController::DiffExternalFilesController(Core::IDocument *document, const QString &leftFileName, +DiffExternalFilesController::DiffExternalFilesController(IDocument *document, const QString &leftFileName, const QString &rightFileName) : DiffFilesController(document), m_leftFileName(leftFileName), m_rightFileName(rightFileName) { } @@ -297,7 +299,7 @@ void DiffExternalFilesController::reload() { QString errorString; Utils::TextFileFormat format; - format.codec = Core::EditorManager::defaultTextCodec(); + format.codec = EditorManager::defaultTextCodec(); QString leftText; bool leftFileExists = true; @@ -339,7 +341,7 @@ void DiffExternalFilesController::reload() static TextEditor::TextDocument *currentTextDocument() { return qobject_cast( - Core::EditorManager::currentDocument()); + EditorManager::currentDocument()); } DiffEditorServiceImpl::DiffEditorServiceImpl(QObject *parent) : @@ -358,7 +360,7 @@ void DiffEditorServiceImpl::diffModifiedFiles(const QStringList &fileNames) if (!DiffEditorController::controller(document)) new DiffModifiedFilesController(document, fileNames); - Core::EditorManager::activateEditorForDocument(document); + EditorManager::activateEditorForDocument(document); document->reload(); } @@ -368,39 +370,39 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe Q_UNUSED(errorMessage) //register actions - Core::ActionContainer *toolsContainer - = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS); + ActionContainer *toolsContainer + = ActionManager::actionContainer(Core::Constants::M_TOOLS); toolsContainer->insertGroup(Core::Constants::G_TOOLS_OPTIONS, Constants::G_TOOLS_DIFF); - Core::ActionContainer *diffContainer = Core::ActionManager::createMenu("Diff"); + ActionContainer *diffContainer = ActionManager::createMenu("Diff"); diffContainer->menu()->setTitle(tr("&Diff")); toolsContainer->addMenu(diffContainer, Constants::G_TOOLS_DIFF); m_diffCurrentFileAction = new QAction(tr("Diff Current File"), this); - Core::Command *diffCurrentFileCommand = Core::ActionManager::registerAction(m_diffCurrentFileAction, "DiffEditor.DiffCurrentFile"); - diffCurrentFileCommand->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+H") : tr("Ctrl+H"))); + Command *diffCurrentFileCommand = ActionManager::registerAction(m_diffCurrentFileAction, "DiffEditor.DiffCurrentFile"); + diffCurrentFileCommand->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+H") : tr("Ctrl+H"))); connect(m_diffCurrentFileAction, &QAction::triggered, this, &DiffEditorPlugin::diffCurrentFile); diffContainer->addAction(diffCurrentFileCommand); m_diffOpenFilesAction = new QAction(tr("Diff Open Files"), this); - Core::Command *diffOpenFilesCommand = Core::ActionManager::registerAction(m_diffOpenFilesAction, "DiffEditor.DiffOpenFiles"); - diffOpenFilesCommand->setDefaultKeySequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+H") : tr("Ctrl+Shift+H"))); + Command *diffOpenFilesCommand = ActionManager::registerAction(m_diffOpenFilesAction, "DiffEditor.DiffOpenFiles"); + diffOpenFilesCommand->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+Shift+H") : tr("Ctrl+Shift+H"))); connect(m_diffOpenFilesAction, &QAction::triggered, this, &DiffEditorPlugin::diffOpenFiles); diffContainer->addAction(diffOpenFilesCommand); QAction *diffExternalFilesAction = new QAction(tr("Diff External Files..."), this); - Core::Command *diffExternalFilesCommand = Core::ActionManager::registerAction(diffExternalFilesAction, "DiffEditor.DiffExternalFiles"); + Command *diffExternalFilesCommand = ActionManager::registerAction(diffExternalFilesAction, "DiffEditor.DiffExternalFiles"); connect(diffExternalFilesAction, &QAction::triggered, this, &DiffEditorPlugin::diffExternalFiles); diffContainer->addAction(diffExternalFilesCommand); - connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, + connect(EditorManager::instance(), &EditorManager::currentEditorChanged, this, &DiffEditorPlugin::updateDiffCurrentFileAction); - connect(Core::EditorManager::instance(), &Core::EditorManager::currentDocumentStateChanged, + connect(EditorManager::instance(), &EditorManager::currentDocumentStateChanged, this, &DiffEditorPlugin::updateDiffCurrentFileAction); - connect(Core::EditorManager::instance(), &Core::EditorManager::editorOpened, + connect(EditorManager::instance(), &EditorManager::editorOpened, this, &DiffEditorPlugin::updateDiffOpenFilesAction); - connect(Core::EditorManager::instance(), &Core::EditorManager::editorsClosed, + connect(EditorManager::instance(), &EditorManager::editorsClosed, this, &DiffEditorPlugin::updateDiffOpenFilesAction); - connect(Core::EditorManager::instance(), &Core::EditorManager::documentStateChanged, + connect(EditorManager::instance(), &EditorManager::documentStateChanged, this, &DiffEditorPlugin::updateDiffOpenFilesAction); updateDiffCurrentFileAction(); @@ -424,7 +426,7 @@ void DiffEditorPlugin::updateDiffCurrentFileAction() void DiffEditorPlugin::updateDiffOpenFilesAction() { - const bool enabled = Utils::anyOf(Core::DocumentModel::openedDocuments(), [](Core::IDocument *doc) { + const bool enabled = Utils::anyOf(DocumentModel::openedDocuments(), [](IDocument *doc) { return doc->isModified() && qobject_cast(doc); }); m_diffOpenFilesAction->setEnabled(enabled); @@ -450,7 +452,7 @@ void DiffEditorPlugin::diffCurrentFile() if (!DiffEditorController::controller(document)) new DiffCurrentFileController(document, fileName); - Core::EditorManager::activateEditorForDocument(document); + EditorManager::activateEditorForDocument(document); document->reload(); } @@ -465,19 +467,19 @@ void DiffEditorPlugin::diffOpenFiles() if (!DiffEditorController::controller(document)) new DiffOpenFilesController(document); - Core::EditorManager::activateEditorForDocument(document); + EditorManager::activateEditorForDocument(document); document->reload(); } void DiffEditorPlugin::diffExternalFiles() { - const QString fileName1 = QFileDialog::getOpenFileName(Core::ICore::dialogParent(), + const QString fileName1 = QFileDialog::getOpenFileName(ICore::dialogParent(), tr("Select First File for Diff"), QString()); if (fileName1.isNull()) return; - const QString fileName2 = QFileDialog::getOpenFileName(Core::ICore::dialogParent(), + const QString fileName2 = QFileDialog::getOpenFileName(ICore::dialogParent(), tr("Select Second File for Diff"), QString()); if (fileName2.isNull()) @@ -493,7 +495,7 @@ void DiffEditorPlugin::diffExternalFiles() if (!DiffEditorController::controller(document)) new DiffExternalFilesController(document, fileName1, fileName2); - Core::EditorManager::activateEditorForDocument(document); + EditorManager::activateEditorForDocument(document); document->reload(); } From 344f255fa9e0defd1613a2692075f2423b560aad Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 20 Oct 2016 16:22:46 +0200 Subject: [PATCH 39/53] Reuse the Guard class Change-Id: Ia742ab92fd7947f4d156d03e112ee32363312996 Reviewed-by: Tobias Hunger --- src/libs/utils/guard.h | 3 +++ src/plugins/diffeditor/diffeditor.cpp | 38 +++++++++------------------ src/plugins/diffeditor/diffeditor.h | 3 ++- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/src/libs/utils/guard.h b/src/libs/utils/guard.h index 41bfd822887..063825650dc 100644 --- a/src/libs/utils/guard.h +++ b/src/libs/utils/guard.h @@ -26,11 +26,13 @@ #pragma once #include "utils_global.h" +#include namespace Utils { class QTCREATOR_UTILS_EXPORT Guard { + Q_DISABLE_COPY(Guard) public: Guard(); ~Guard(); @@ -42,6 +44,7 @@ private: class QTCREATOR_UTILS_EXPORT GuardLocker { + Q_DISABLE_COPY(GuardLocker) public: GuardLocker(Guard &guard); ~GuardLocker(); diff --git a/src/plugins/diffeditor/diffeditor.cpp b/src/plugins/diffeditor/diffeditor.cpp index c2d681c13e1..0e9d7fc318d 100644 --- a/src/plugins/diffeditor/diffeditor.cpp +++ b/src/plugins/diffeditor/diffeditor.cpp @@ -69,19 +69,6 @@ static const char useDiffEditorKeyC[] = "UseDiffEditor"; using namespace TextEditor; -namespace { - -class Guard -{ -public: - Guard(int *state) : m_state(state) { ++(*state); } - ~Guard() { --(*m_state); QTC_ASSERT(*m_state >= 0, return); } -private: - int *m_state; -}; - -} // namespace - namespace DiffEditor { namespace Internal { @@ -226,7 +213,6 @@ DiffEditor::DiffEditor() , m_viewSwitcherAction(0) , m_currentViewIndex(-1) , m_currentDiffFileIndex(-1) - , m_ignoreChanges(0) , m_sync(false) , m_showDescription(true) { @@ -329,7 +315,7 @@ void DiffEditor::setDocument(QSharedPointer(doc)) DiffEditor::DiffEditor(DiffEditorDocument *doc) : DiffEditor() { - Guard guard(&m_ignoreChanges); + Utils::GuardLocker guard(m_ignoreChanges); setDocument(QSharedPointer(doc)); setupView(loadSettings()); } @@ -343,7 +329,7 @@ DiffEditor::~DiffEditor() Core::IEditor *DiffEditor::duplicate() { DiffEditor *editor = new DiffEditor(); - Guard guard(&editor->m_ignoreChanges); + Utils::GuardLocker guard(editor->m_ignoreChanges); editor->setDocument(m_document); editor->m_sync = m_sync; @@ -371,7 +357,7 @@ QWidget *DiffEditor::toolBar() void DiffEditor::documentHasChanged() { - Guard guard(&m_ignoreChanges); + Utils::GuardLocker guard(m_ignoreChanges); const QList diffFileList = m_document->diffFiles(); updateDescription(); @@ -430,7 +416,7 @@ void DiffEditor::documentHasChanged() void DiffEditor::toggleDescription() { - if (m_ignoreChanges > 0) + if (m_ignoreChanges.isLocked()) return; m_showDescription = !m_showDescription; @@ -446,7 +432,7 @@ void DiffEditor::updateDescription() m_descriptionWidget->setPlainText(description); m_descriptionWidget->setVisible(m_showDescription && !description.isEmpty()); - Guard guard(&m_ignoreChanges); + Utils::GuardLocker guard(m_ignoreChanges); m_toggleDescriptionAction->setChecked(m_showDescription); m_toggleDescriptionAction->setToolTip(m_showDescription ? tr("Hide Change Description") : tr("Show Change Description")); @@ -458,7 +444,7 @@ void DiffEditor::updateDescription() void DiffEditor::contextLineCountHasChanged(int lines) { QTC_ASSERT(!m_document->isContextLineCountForced(), return); - if (m_ignoreChanges > 0 || lines == m_document->contextLineCount()) + if (m_ignoreChanges.isLocked() || lines == m_document->contextLineCount()) return; m_document->setContextLineCount(lines); @@ -471,7 +457,7 @@ void DiffEditor::ignoreWhitespaceHasChanged() { const bool ignore = m_whitespaceButtonAction->isChecked(); - if (m_ignoreChanges > 0 || ignore == m_document->ignoreWhitespace()) + if (m_ignoreChanges.isLocked() || ignore == m_document->ignoreWhitespace()) return; m_document->setIgnoreWhitespace(ignore); saveSetting(QLatin1String(ignoreWhitespaceKeyC), ignore); @@ -494,7 +480,7 @@ void DiffEditor::prepareForReload() } { - Guard guard(&m_ignoreChanges); + Utils::GuardLocker guard(m_ignoreChanges); m_contextSpinBox->setValue(m_document->contextLineCount()); m_whitespaceButtonAction->setChecked(m_document->ignoreWhitespace()); } @@ -539,12 +525,12 @@ void DiffEditor::updateEntryToolTip() void DiffEditor::setCurrentDiffFileIndex(int index) { - if (m_ignoreChanges > 0) + if (m_ignoreChanges.isLocked()) return; QTC_ASSERT((index < 0) != (m_entriesComboBox->count() > 0), return); - Guard guard(&m_ignoreChanges); + Utils::GuardLocker guard(m_ignoreChanges); m_currentDiffFileIndex = index; currentView()->setCurrentDiffFileIndex(index); @@ -575,7 +561,7 @@ void DiffEditor::updateDiffEditorSwitcher() void DiffEditor::toggleSync() { - if (m_ignoreChanges > 0) + if (m_ignoreChanges.isLocked()) return; QTC_ASSERT(currentView(), return); @@ -669,7 +655,7 @@ void DiffEditor::setupView(IDiffView *view) saveSetting(QLatin1String(diffViewKeyC), currentView()->id().toSetting()); { - Guard guard(&m_ignoreChanges); + Utils::GuardLocker guard(m_ignoreChanges); m_toggleSyncAction->setVisible(currentView()->supportsSync()); m_toggleSyncAction->setToolTip(currentView()->syncToolTip()); m_toggleSyncAction->setText(currentView()->syncToolTip()); diff --git a/src/plugins/diffeditor/diffeditor.h b/src/plugins/diffeditor/diffeditor.h index 7539ff31d6a..bb8363187ee 100644 --- a/src/plugins/diffeditor/diffeditor.h +++ b/src/plugins/diffeditor/diffeditor.h @@ -29,6 +29,7 @@ #include #include +#include QT_BEGIN_NAMESPACE class QComboBox; @@ -103,7 +104,7 @@ private: QPair m_currentFileChunk; int m_currentViewIndex; int m_currentDiffFileIndex; - int m_ignoreChanges; + Utils::Guard m_ignoreChanges; bool m_sync; bool m_showDescription; }; From 8224c1c95df481ad34fad3f699e67db42bc8b6ea Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 19 Oct 2016 16:44:25 +0200 Subject: [PATCH 40/53] DiffEditor: fix revert chunk for diffs of modified files Apply chunk action doesn't make sense for that case, will stay disabled. Task-number: QTCREATORBUG-17136 Change-Id: Idce31b3aa9d354536a01607c10b20273158961d5 Reviewed-by: Tobias Hunger --- src/plugins/diffeditor/diffeditordocument.cpp | 11 ++-- src/plugins/diffeditor/diffeditordocument.h | 4 +- src/plugins/diffeditor/diffeditorplugin.cpp | 3 + .../diffeditor/diffeditorwidgetcontroller.cpp | 55 +++++++++++++++---- src/plugins/diffeditor/diffutils.h | 6 ++ src/plugins/texteditor/textdocument.cpp | 19 ++++++- src/plugins/texteditor/textdocument.h | 1 + 7 files changed, 81 insertions(+), 18 deletions(-) diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp index 5102df44d96..5a4d575d9c2 100644 --- a/src/plugins/diffeditor/diffeditordocument.cpp +++ b/src/plugins/diffeditor/diffeditordocument.cpp @@ -87,7 +87,9 @@ DiffEditorController *DiffEditorDocument::controller() const return m_controller; } -QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex, bool revert, bool addPrefix) const +QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex, + bool revert, bool addPrefix, + const QString &overriddenFileName) const { if (fileIndex < 0 || chunkIndex < 0) return QString(); @@ -102,9 +104,10 @@ QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex, bool revert const ChunkData &chunkData = fileData.chunks.at(chunkIndex); const bool lastChunk = (chunkIndex == fileData.chunks.count() - 1); - const QString fileName = revert - ? fileData.rightFileInfo.fileName - : fileData.leftFileInfo.fileName; + const QString fileName = !overriddenFileName.isEmpty() + ? overriddenFileName : revert + ? fileData.rightFileInfo.fileName + : fileData.leftFileInfo.fileName; QString leftPrefix, rightPrefix; if (addPrefix) { diff --git a/src/plugins/diffeditor/diffeditordocument.h b/src/plugins/diffeditor/diffeditordocument.h index 5b4771b0e71..18864711fe7 100644 --- a/src/plugins/diffeditor/diffeditordocument.h +++ b/src/plugins/diffeditor/diffeditordocument.h @@ -46,7 +46,9 @@ public: DiffEditorController *controller() const; - QString makePatch(int fileIndex, int chunkIndex, bool revert, bool addPrefix = false) const; + QString makePatch(int fileIndex, int chunkIndex, + bool revert, bool addPrefix = false, + const QString &overriddenFileName = QString()) const; void setDiffFiles(const QList &data, const QString &directory, const QString &startupFile = QString()); diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index ac697055008..4eb0a07878a 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -143,6 +143,7 @@ void DiffCurrentFileController::reload() fileData.rightFileInfo.fileName = m_fileName; fileData.leftFileInfo.typeInfo = tr("Saved"); fileData.rightFileInfo.typeInfo = tr("Modified"); + fileData.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor; if (!leftFileExists) fileData.fileOperation = FileData::NewFile; @@ -201,6 +202,7 @@ void DiffOpenFilesController::reload() fileData.rightFileInfo.fileName = fileName; fileData.leftFileInfo.typeInfo = tr("Saved"); fileData.rightFileInfo.typeInfo = tr("Modified"); + fileData.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor; if (!leftFileExists) fileData.fileOperation = FileData::NewFile; @@ -261,6 +263,7 @@ void DiffModifiedFilesController::reload() fileData.rightFileInfo.fileName = fileName; fileData.leftFileInfo.typeInfo = tr("Saved"); fileData.rightFileInfo.typeInfo = tr("Modified"); + fileData.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor; if (!leftFileExists) fileData.fileOperation = FileData::NewFile; diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp index 8c4e182b229..3e30a0d8204 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp @@ -32,6 +32,7 @@ #include #include +#include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include using namespace Core; @@ -77,27 +79,60 @@ void DiffEditorWidgetController::patch(bool revert) return; } - const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0; - const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex); const QString fileName = revert ? fileData.rightFileInfo.fileName : fileData.leftFileInfo.fileName; + const DiffFileInfo::PatchBehaviour patchBehaviour = revert + ? fileData.rightFileInfo.patchBehaviour + : fileData.leftFileInfo.patchBehaviour; const QString workingDirectory = m_document->baseDirectory().isEmpty() ? QFileInfo(fileName).absolutePath() : m_document->baseDirectory(); + const QString absFileName = QFileInfo(workingDirectory + '/' + QFileInfo(fileName).fileName()).absoluteFilePath(); - const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, revert); + if (patchBehaviour == DiffFileInfo::PatchFile) { + const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0; - if (patch.isEmpty()) - return; + const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, revert); - const QString absFileName = QFileInfo(workingDirectory + '/' + fileName).absoluteFilePath(); - FileChangeBlocker fileChangeBlocker(absFileName); - if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), - workingDirectory, strip, revert)) - m_document->reload(); + if (patch.isEmpty()) + return; + + FileChangeBlocker fileChangeBlocker(absFileName); + if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), + workingDirectory, strip, revert)) + m_document->reload(); + } else { // PatchEditor + TextEditor::TextDocument *textDocument = qobject_cast( + DocumentModel::documentForFilePath(absFileName)); + if (!textDocument) + return; + + QTemporaryFile contentsCopy; + if (!contentsCopy.open()) + return; + + contentsCopy.write(textDocument->contents()); + contentsCopy.close(); + + const QString contentsCopyFileName = contentsCopy.fileName(); + const QString contentsCopyDir = QFileInfo(contentsCopyFileName).absolutePath(); + + const QString patch = m_document->makePatch(m_contextMenuFileIndex, + m_contextMenuChunkIndex, revert, false, QFileInfo(contentsCopyFileName).fileName()); + + if (patch.isEmpty()) + return; + + if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), + contentsCopyDir, 0, revert)) { + QString errorString; + if (textDocument->reload(&errorString, contentsCopyFileName)) + m_document->reload(); + } + } } void DiffEditorWidgetController::jumpToOriginalFile(const QString &fileName, diff --git a/src/plugins/diffeditor/diffutils.h b/src/plugins/diffeditor/diffutils.h index 417309294b9..d588a52ad8f 100644 --- a/src/plugins/diffeditor/diffutils.h +++ b/src/plugins/diffeditor/diffutils.h @@ -38,12 +38,18 @@ class Diff; class DIFFEDITOR_EXPORT DiffFileInfo { public: + enum PatchBehaviour { + PatchFile, + PatchEditor + }; + DiffFileInfo() {} DiffFileInfo(const QString &file) : fileName(file) {} DiffFileInfo(const QString &file, const QString &type) : fileName(file), typeInfo(type) {} QString fileName; QString typeInfo; + PatchBehaviour patchBehaviour = PatchFile; }; class DIFFEDITOR_EXPORT TextLineData { diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index dc7bd87296f..7c1e3157ab8 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -634,7 +634,11 @@ Core::IDocument::OpenResult TextDocument::openImpl(QString *errorString, const Q readResult = read(realFileName, &content, errorString); const int chunks = content.size(); - d->m_document.setUndoRedoEnabled(reload); + // Don't call setUndoRedoEnabled(true) when reload is true and filenames are different, + // since it will reset the undo's clear index + if (!reload || fileName == realFileName) + d->m_document.setUndoRedoEnabled(reload); + QTextCursor c(&d->m_document); c.beginEditBlock(); if (reload) { @@ -663,7 +667,11 @@ Core::IDocument::OpenResult TextDocument::openImpl(QString *errorString, const Q } c.endEditBlock(); - d->m_document.setUndoRedoEnabled(true); + + // Don't call setUndoRedoEnabled(true) when reload is true and filenames are different, + // since it will reset the undo's clear index + if (!reload || fileName == realFileName) + d->m_document.setUndoRedoEnabled(true); TextDocumentLayout *documentLayout = qobject_cast(d->m_document.documentLayout()); @@ -686,6 +694,11 @@ bool TextDocument::reload(QString *errorString, QTextCodec *codec) } bool TextDocument::reload(QString *errorString) +{ + return reload(errorString, filePath().toString()); +} + +bool TextDocument::reload(QString *errorString, const QString &realFileName) { emit aboutToReload(); TextDocumentLayout *documentLayout = @@ -695,7 +708,7 @@ bool TextDocument::reload(QString *errorString) marks = documentLayout->documentClosing(); // removes text marks non-permanently const QString &file = filePath().toString(); - bool success = openImpl(errorString, file, file, /*reload =*/ true) == OpenResult::Success; + bool success = openImpl(errorString, file, realFileName, /*reload =*/ true) == OpenResult::Success; if (documentLayout) documentLayout->documentReloaded(marks, this); // re-adds text marks diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 30576043b40..4bb466382ca 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -118,6 +118,7 @@ public: OpenResult open(QString *errorString, const QString &fileName, const QString &realFileName) override; virtual bool reload(QString *errorString); + bool reload(QString *errorString, const QString &realFileName); bool setPlainText(const QString &text); QTextDocument *document() const; From 028018dcacb69167b857b4f86d0384180ef7b05a Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 21 Oct 2016 10:22:38 +0200 Subject: [PATCH 41/53] Clang: Clear left-over preambles after crash ...otherwise they accumulate in the temporary directory. Change-Id: I0841f3d168f30f559fc718d2825dd3e800515074 Reviewed-by: Tim Jenssen Reviewed-by: Christian Kandeler --- src/libs/clangbackendipc/connectionclient.cpp | 12 +++++++++--- src/libs/clangbackendipc/connectionclient.h | 5 +++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libs/clangbackendipc/connectionclient.cpp b/src/libs/clangbackendipc/connectionclient.cpp index d0ba95bc580..0ccd742fb6c 100644 --- a/src/libs/clangbackendipc/connectionclient.cpp +++ b/src/libs/clangbackendipc/connectionclient.cpp @@ -43,6 +43,7 @@ namespace ClangBackEnd { ConnectionClient::ConnectionClient() { processAliveTimer.setInterval(10000); + resetTemporaryDir(); static const bool startAliveTimer = !qEnvironmentVariableIntValue("QTC_CLANG_NO_ALIVE_TIMER"); @@ -113,9 +114,7 @@ QProcessEnvironment ConnectionClient::processEnvironment() const const QTemporaryDir &ConnectionClient::temporaryDirectory() const { - static QTemporaryDir temporaryDirectory(QDir::tempPath() + QStringLiteral("/qtc-clang-XXXXXX")); - - return temporaryDirectory; + return *temporaryDirectory_.data(); } LinePrefixer &ConnectionClient::stdErrPrefixer() @@ -147,6 +146,7 @@ void ConnectionClient::restartProcessAsynchronously() { if (!processIsStarting) { finishProcess(std::move(process_)); + resetTemporaryDir(); // clear left-over preambles startProcessAndConnectToServerAsynchronously(); } @@ -218,6 +218,12 @@ void ConnectionClient::printStandardError() qDebug("%s", stdErrPrefixer_.prefix(process_->readAllStandardError()).constData()); } +void ConnectionClient::resetTemporaryDir() +{ + const QString templatePath = QDir::tempPath() + QStringLiteral("/qtc-clang-XXXXXX"); + temporaryDirectory_.reset(new QTemporaryDir(templatePath)); +} + void ConnectionClient::connectLocalSocketConnected() { connect(&localSocket, diff --git a/src/libs/clangbackendipc/connectionclient.h b/src/libs/clangbackendipc/connectionclient.h index b3eed0703b5..74ea4cf3298 100644 --- a/src/libs/clangbackendipc/connectionclient.h +++ b/src/libs/clangbackendipc/connectionclient.h @@ -30,6 +30,8 @@ #include #include +#include +#include #include @@ -102,6 +104,8 @@ private: void printStandardOutput(); void printStandardError(); + void resetTemporaryDir(); + void connectLocalSocketConnected(); void connectLocalSocketDisconnected(); void connectProcessFinished(QProcess *process) const; @@ -121,6 +125,7 @@ private: mutable std::unique_ptr process_; QLocalSocket localSocket; + QScopedPointer temporaryDirectory_; QTimer processAliveTimer; QString processPath_; bool isAliveTimerResetted = false; From 747346900501ed83c5af85ffe2fbfbd52c59099a Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 21 Oct 2016 11:32:39 +0200 Subject: [PATCH 42/53] ClangStaticAnalyzer: Tests: Change target only if necessary ...otherwise we wait for nothing. Change-Id: Ia55d4845f8dd0fe746ee6c8ca19b5312879294d1 Reviewed-by: Christian Kandeler --- ...staticanalyzerpreconfiguredsessiontests.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp index eacaa7f4acd..462e26fe836 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp @@ -197,17 +197,19 @@ bool ClangStaticAnalyzerPreconfiguredSessionTests::switchToProjectAndTarget(Proj if (project == activeProject && target == activeProject->activeTarget()) return true; // OK, desired project/target already active. - QSignalSpy waitUntilProjectUpdated(CppModelManager::instance(), - &CppModelManager::projectPartsUpdated); - if (project != activeProject) m_sessionManager.setStartupProject(project); - m_sessionManager.setActiveTarget(project, target, ProjectExplorer::SetActive::NoCascade); - const bool waitResult = waitUntilProjectUpdated.wait(30000); - if (!waitResult) { - qWarning() << "waitUntilProjectUpdated() failed"; - return false; + if (target != project->activeTarget()) { + QSignalSpy waitUntilProjectUpdated(CppModelManager::instance(), + &CppModelManager::projectPartsUpdated); + m_sessionManager.setActiveTarget(project, target, ProjectExplorer::SetActive::NoCascade); + + const bool waitResult = waitUntilProjectUpdated.wait(30000); + if (!waitResult) { + qWarning() << "waitUntilProjectUpdated() failed"; + return false; + } } return true; From e6b23dc2e5b7a76a800555b178fb1d2ae8351f96 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 21 Oct 2016 11:11:33 +0200 Subject: [PATCH 43/53] clangcodemodel: Use forward slashes for CLANG_RESOURCE_DIR define Adapt qmake and qbs files, fixing warnings on Windows: clangutils.cpp(78): warning C4129: 'o': unrecognized character escape sequence clangutils.cpp(78): warning C4129: 'L': unrecognized character escape sequence clangutils.cpp(78): warning C4129: 'l': unrecognized character escape sequence Change-Id: I7a5fe674665437582457645f2a081e1e38d5df77 Reviewed-by: Christian Kandeler --- qbs/modules/libclang/functions.js | 5 +++-- src/plugins/clangcodemodel/clangcodemodel.pro | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js index e09ebef1ee5..3027aff4ede 100644 --- a/qbs/modules/libclang/functions.js +++ b/qbs/modules/libclang/functions.js @@ -1,5 +1,6 @@ var Environment = loadExtension("qbs.Environment") var File = loadExtension("qbs.File") +var FileInfo = loadExtension("qbs.FileInfo") var MinimumLLVMVersion = "3.8.0" var Process = loadExtension("qbs.Process") @@ -57,12 +58,12 @@ function llvmConfig(qbs, qtcFunctions) function includeDir(llvmConfig) { - return readOutput(llvmConfig, ["--includedir"]) + return FileInfo.toNativeSeparators(readOutput(llvmConfig, ["--includedir"])); } function libDir(llvmConfig) { - return readOutput(llvmConfig, ["--libdir"]) + return FileInfo.toNativeSeparators(readOutput(llvmConfig, ["--libdir"])); } function version(llvmConfig) diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro index ff3ce0aea49..0d9b5ee96b7 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.pro +++ b/src/plugins/clangcodemodel/clangcodemodel.pro @@ -3,7 +3,8 @@ include(../../shared/clang/clang_installation.pri) # The following defines are used to determine the clang include path for intrinsics. DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\" -DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include\\\"\"" +CLANG_RESOURCE_DIR=$$clean_path($${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include) +DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${CLANG_RESOURCE_DIR}\\\"\"" SOURCES += \ clangactivationsequencecontextprocessor.cpp \ From 19e026d7dba9ab41023547002ecc06f431dba02a Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 21 Oct 2016 15:01:25 +0200 Subject: [PATCH 44/53] Clang: Fix using forward slashes for CLANG_RESOURCE_DIR in qbs Change-Id: I251567529ec33ef76043006c68749724208cc811 Reviewed-by: Friedemann Kleint Reviewed-by: Christian Kandeler --- qbs/modules/libclang/functions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js index 3027aff4ede..49f2512423d 100644 --- a/qbs/modules/libclang/functions.js +++ b/qbs/modules/libclang/functions.js @@ -58,12 +58,12 @@ function llvmConfig(qbs, qtcFunctions) function includeDir(llvmConfig) { - return FileInfo.toNativeSeparators(readOutput(llvmConfig, ["--includedir"])); + return FileInfo.fromNativeSeparators(readOutput(llvmConfig, ["--includedir"])); } function libDir(llvmConfig) { - return FileInfo.toNativeSeparators(readOutput(llvmConfig, ["--libdir"])); + return FileInfo.fromNativeSeparators(readOutput(llvmConfig, ["--libdir"])); } function version(llvmConfig) From 9844cd242e1e517d02876fbbcc622775f3cb4bd4 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Wed, 19 Oct 2016 13:48:40 +0200 Subject: [PATCH 45/53] QmlDesigner: space only cleanups Change-Id: I959208b27694ff3c75650a3f482a0a975ca6e769 Reviewed-by: Thomas Hartmann --- .../qmldesigner/components/integration/designdocument.cpp | 2 +- .../qmldesigner/designercore/model/basetexteditmodifier.cpp | 1 - .../qmldesigner/designercore/model/componenttextmodifier.cpp | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index 7004107a645..28630440521 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -134,7 +134,7 @@ static ComponentTextModifier *createComponentTextModifier(TextModifier *original componentEndOffset = componentStartOffset + rewriterView->nodeLength(componentNode); } - return new ComponentTextModifier (originalModifier, componentStartOffset, componentEndOffset, rootStartOffset); + return new ComponentTextModifier(originalModifier, componentStartOffset, componentEndOffset, rootStartOffset); } bool DesignDocument::loadInFileComponent(const ModelNode &componentNode) diff --git a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp index 1324e5a7b25..2bcfcd7bbae 100644 --- a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp @@ -134,7 +134,6 @@ bool BaseTextEditModifier::moveToComponent(int nodeOffset) QmlJSEditor::ComponentFromObjectDef::perform(document->filePath().toString(), object); return true; - } } return false; diff --git a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp index 45d6ddc2b00..a0f9ae96813 100644 --- a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp @@ -26,6 +26,7 @@ #include "componenttextmodifier.h" using namespace QmlDesigner; + ComponentTextModifier::ComponentTextModifier(TextModifier *originalModifier, int componentStartOffset, int componentEndOffset, int rootStartOffset) : m_originalModifier(originalModifier), m_componentStartOffset(componentStartOffset), From 81bdb9cdf9b6acdf13e9c44b3d6cf50207fd6370 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Wed, 19 Oct 2016 13:49:35 +0200 Subject: [PATCH 46/53] QmlDesigner: add getLineInDocument() for convenience Change-Id: I34f788e320fe4c38e3dbb55ba6d0bc1b8d9ba59a Reviewed-by: Thomas Hartmann --- .../qmldesigner/designercore/include/textmodifier.h | 1 + .../qmldesigner/designercore/model/textmodifier.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/include/textmodifier.h b/src/plugins/qmldesigner/designercore/include/textmodifier.h index 98a9d671a77..c5d494e0e56 100644 --- a/src/plugins/qmldesigner/designercore/include/textmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/textmodifier.h @@ -74,6 +74,7 @@ public: virtual QTextDocument *textDocument() const = 0; virtual QString text() const = 0; virtual QTextCursor textCursor() const = 0; + static int getLineInDocument(QTextDocument* document, int offset); virtual void deactivateChangeSignals() = 0; virtual void reactivateChangeSignals() = 0; diff --git a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp index 3434b21497f..8b5ea35ff1c 100644 --- a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp @@ -26,6 +26,7 @@ #include "textmodifier.h" #include +#include using namespace QmlDesigner; @@ -33,6 +34,14 @@ TextModifier::~TextModifier() { } +int TextModifier::getLineInDocument(QTextDocument *document, int offset) +{ + int line = -1; + int column = -1; + TextEditor::Convenience::convertPosition(document, offset, &line, &column); + return line; +} + QmlJS::Snapshot TextModifier::qmljsSnapshot() { QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); From 29c58eabed94f72607cf24a921e2a7fa5a64ee5d Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Wed, 19 Oct 2016 13:54:20 +0200 Subject: [PATCH 47/53] QmlDesigner: refactor indent feature * add indentLines() method * refactor indent to use indentLines() Change-Id: Ie36c7ab6217c31e9e3913a4dd5da2196364200c8 Reviewed-by: Thomas Hartmann --- .../include/basetexteditmodifier.h | 1 + .../include/componenttextmodifier.h | 1 + .../include/plaintexteditmodifier.h | 7 ++- .../designercore/include/textmodifier.h | 1 + .../model/basetexteditmodifier.cpp | 58 +++++++++---------- .../model/componenttextmodifier.cpp | 4 ++ 6 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h b/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h index e5b1bd368cd..e20566724bf 100644 --- a/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/basetexteditmodifier.h @@ -41,6 +41,7 @@ class QMLDESIGNERCORE_EXPORT BaseTextEditModifier: public PlainTextEditModifier public: BaseTextEditModifier(TextEditor::TextEditorWidget *textEdit); + void indentLines(int startLine, int endLine) override; void indent(int offset, int length) override; int indentDepth() const override; diff --git a/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h b/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h index 194ebd2d5bb..01b8f63e539 100644 --- a/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/componenttextmodifier.h @@ -39,6 +39,7 @@ public: void replace(int offset, int length, const QString& replacement) override; void move(const MoveInfo &moveInfo) override; void indent(int offset, int length) override; + void indentLines(int startLine, int endLine) override; int indentDepth() const override; diff --git a/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h b/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h index cd866c94691..210f2c30408 100644 --- a/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h @@ -58,6 +58,7 @@ public: void replace(int offset, int length, const QString &replacement) override; void move(const MoveInfo &moveInfo) override; void indent(int offset, int length) override = 0; + void indentLines(int startLine, int endLine) override = 0; int indentDepth() const override = 0; @@ -102,10 +103,12 @@ public: : PlainTextEditModifier(textEdit) {} - virtual void indent(int /*offset*/, int /*length*/) + void indent(int /*offset*/, int /*length*/) override + {} + void indentLines(int /*offset*/, int /*length*/) override {} - virtual int indentDepth() const + int indentDepth() const override { return 0; } }; diff --git a/src/plugins/qmldesigner/designercore/include/textmodifier.h b/src/plugins/qmldesigner/designercore/include/textmodifier.h index c5d494e0e56..d0c4cebeb4d 100644 --- a/src/plugins/qmldesigner/designercore/include/textmodifier.h +++ b/src/plugins/qmldesigner/designercore/include/textmodifier.h @@ -64,6 +64,7 @@ public: virtual void replace(int offset, int length, const QString& replacement) = 0; virtual void move(const MoveInfo &moveInfo) = 0; virtual void indent(int offset, int length) = 0; + virtual void indentLines(int startLine, int endLine) = 0; virtual int indentDepth() const = 0; diff --git a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp index 2bcfcd7bbae..ab68cc16054 100644 --- a/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/basetexteditmodifier.cpp @@ -43,41 +43,41 @@ BaseTextEditModifier::BaseTextEditModifier(TextEditor::TextEditorWidget *textEdi { } +void BaseTextEditModifier::indentLines(int startLine, int endLine) +{ + if (startLine < 0) + return; + TextEditor::TextEditorWidget *baseTextEditorWidget = qobject_cast(plainTextEdit()); + if (!baseTextEditorWidget) + return; + + QTextDocument *textDocument = plainTextEdit()->document(); + TextEditor::TextDocument *baseTextEditorDocument = baseTextEditorWidget->textDocument(); + TextEditor::TabSettings tabSettings = baseTextEditorDocument->tabSettings(); + QTextCursor tc(textDocument); + + tc.beginEditBlock(); + for (int i = startLine; i <= endLine; i++) { + QTextBlock start = textDocument->findBlockByNumber(i); + + if (start.isValid()) { + QmlJSEditor::Internal::Indenter indenter; + indenter.indentBlock(textDocument, start, QChar::Null, tabSettings); + } + } + tc.endEditBlock(); +} + void BaseTextEditModifier::indent(int offset, int length) { if (length == 0 || offset < 0 || offset + length >= text().length()) return; - if (TextEditor::TextEditorWidget *baseTextEditorWidget = qobject_cast(plainTextEdit())) { + int startLine = getLineInDocument(textDocument(), offset); + int endLine = getLineInDocument(textDocument(), offset + length); - TextEditor::TextDocument *baseTextEditorDocument = baseTextEditorWidget->textDocument(); - QTextDocument *textDocument = baseTextEditorWidget->document(); - - int startLine = -1; - int endLine = -1; - int column; - - baseTextEditorWidget->convertPosition(offset, &startLine, &column); //get line - baseTextEditorWidget->convertPosition(offset + length, &endLine, &column); //get line - - QTextDocument *doc = baseTextEditorDocument->document(); - QTextCursor tc(doc); - tc.beginEditBlock(); - - if (startLine > 0) { - TextEditor::TabSettings tabSettings = baseTextEditorDocument->tabSettings(); - for (int i = startLine; i <= endLine; i++) { - QTextBlock start = textDocument->findBlockByNumber(i); - - if (start.isValid()) { - QmlJSEditor::Internal::Indenter indenter; - indenter.indentBlock(textDocument, start, QChar::Null, tabSettings); - } - } - } - - tc.endEditBlock(); - } + if (startLine > -1 && endLine > -1) + indentLines(startLine, endLine); } int BaseTextEditModifier::indentDepth() const diff --git a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp index a0f9ae96813..ebdc6210f26 100644 --- a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp @@ -56,6 +56,10 @@ void ComponentTextModifier::move(const MoveInfo &moveInfo) void ComponentTextModifier::indent(int offset, int length) { m_originalModifier->indent(offset, length); + +void ComponentTextModifier::indentLines(int startLine, int endLine) +{ + m_originalModifier->indentLines(startLine, endLine); } int ComponentTextModifier::indentDepth() const From b099ab92d881c63fae43be7e3887179239504ec7 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 21 Oct 2016 17:55:36 +0200 Subject: [PATCH 48/53] QmlDesigner.PropertyEditor: Fixing url editor Task-number: QTCREATORBUG-11380 Change-Id: I00cdcc8626e2e178b9fff8d11b26f87d9aad03a8 Reviewed-by: Tim Jenssen --- .../HelperWidgets/UrlChooser.qml | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/UrlChooser.qml index c0e10a1ee4c..f6bcae25a3d 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/UrlChooser.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/UrlChooser.qml @@ -56,7 +56,7 @@ RowLayout { x: 2 anchors.verticalCenter: parent.verticalCenter backendValue: urlChooser.backendValue - visible: comboBox.enabled + visible: urlChooser.enabled } property bool isComplete: false @@ -92,16 +92,25 @@ RowLayout { setCurrentText(textValue) } + onAccepted: { + if (!comboBox.isComplete) + return; - onCurrentTextChanged: { + if (backendValue.value !== currentText) + backendValue.value = currentText; + } + + onActivated: { + var cText = textAt(index) + print(cText) if (backendValue === undefined) return; if (!comboBox.isComplete) return; - if (backendValue.value !== currentText) - backendValue.value = currentText; + if (backendValue.value !== cText) + backendValue.value = cText; } Component.onCompleted: { @@ -158,7 +167,8 @@ RowLayout { onClicked: { darkPanel.opacity = 1 fileModel.openFileDialog() - backendValue.value = fileModel.fileName + if (fileModel.fileName != "") + backendValue.value = fileModel.fileName darkPanel.opacity = 0 } } From f5b3dcfc8337c47da570fae4a217f40b22a20750 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 21 Oct 2016 18:50:18 +0200 Subject: [PATCH 49/53] compile fix Change-Id: Idb8e01dc2895621cf94ba047a41eef5ca0474089 Reviewed-by: Tim Jenssen --- .../qmldesigner/designercore/model/componenttextmodifier.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp index ebdc6210f26..a91e47e61e3 100644 --- a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp @@ -56,6 +56,7 @@ void ComponentTextModifier::move(const MoveInfo &moveInfo) void ComponentTextModifier::indent(int offset, int length) { m_originalModifier->indent(offset, length); +} void ComponentTextModifier::indentLines(int startLine, int endLine) { From b2b6c6029309e7802aa324ac85b6981ebf9f215d Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 17 Oct 2016 16:11:47 +0200 Subject: [PATCH 50/53] Add changes file for 4.2 Change-Id: I56f97306de5d3280ade60cc335b55c2e79f89bad Reviewed-by: Leena Miettinen --- dist/changes-4.2.0.md | 142 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 dist/changes-4.2.0.md diff --git a/dist/changes-4.2.0.md b/dist/changes-4.2.0.md new file mode 100644 index 00000000000..d44ae8a81fa --- /dev/null +++ b/dist/changes-4.2.0.md @@ -0,0 +1,142 @@ +Qt Creator version 4.2 contains bug fixes and new features. + +The most important changes are listed in this document. For a complete +list of changes, see the Git log for the Qt Creator sources that +you can check out from the public Git repository. For example: + + git clone git://code.qt.io/qt-creator/qt-creator.git + git log --cherry-pick --pretty=oneline origin/4.1..v4.2.0 + +General + +* Added experimental editor for Qt SCXML +* Added pattern substitution for variable expansion + `%{variable/pattern/replacement}` (and `%{variable//pattern/replacement}` + for replacing multiple matches) +* Added default values for variable expansion (`%{variable:-default}`) +* Added Help > System Information for bug reporting purposes + (QTCREATORBUG-16135) +* Added option to hide the central widget in Debug mode + +Welcome + +* Added keyboard shortcuts for opening recent sessions and projects +* Improved performance when many sessions are shown + +Editing + +* Added action for selecting word under cursor (QTCREATORBUG-641) +* Fixed highlighting of Markdown files + (QTCREATORBUG-16304) + +Help + +* Added option to open link and current page in window (QTCREATORBUG-16842) + +All Projects + +* Reworked Projects mode UI +* Grouped all device options into one options category +* Added support for toolchains for different languages (currently C and C++) + +QMake Projects + +* Removed Qt Labs Controls wizard which is superseded by Qt Quick Controls 2 +* Fixed `Open with Designer` and `Open with Linguist` for mobile and embedded Qt + (QTCREATORBUG-16558) +* Fixed Add Library wizard when selecting library from absolute path or + different drive (QTCREATORBUG-8413, QTCREATORBUG-15732, QTCREATORBUG-16688) + +CMake Projects + +* Added support for CMake specific snippets +* Added support for platforms and toolsets +* Added warning for unsupported CMake versions +* Added drop down for selecting predefined values for properties +* Improved performance of opening project (QTCREATORBUG-16930) +* Made it possible to select CMake application on macOS +* Fixed that all unknown build target types were mapped to `ExecutableType` + +Qbs Projects + +* Made generated files available in project tree (QTCREATORBUG-15978) + +C++ Support + +* Added preview of images to tool tip on Qt resource URLs +* Added option to skip big files when indexing (QTCREATORBUG-16712) +* Added notification for parsing errors in headers +* Fixed `Move Definition to Class` for functions in template class and + template member functions (QTCREATORBUG-14354) +* Fixed issues with `Add Declaration`, `Add Definition`, and + `Move Definition Outside Class` for template functions +* Clang Code Model + * Improved responsiveness of completion and highlighting + +Debugging + +* Added pretty printing of `QRegExp` captures +* Added pretty printing of `QStaticStringData` +* Improved pretty printing of QV4 types +* Made display of maps more compact +* Fixed pretty printing of `QFixed` +* LLDB + * Added support for Qt Creator variables `%{...}` in startup commands + +QML Profiler + +* Added option to show memory usage and allocations as flame graph +* Added option to show vertical orientation lines in timeline + (click the time ruler) + +Qt Quick Designer + +* Added completion expression editor +* Added menu for editing `when` condition of states +* Added editor for managing C++ backend objects +* Added reformatting of `.ui.qml` files on save +* Added support for exporting single properties +* Added support for padding (Qt Quick 2.6) +* Added support for elide and various font properties to text items +* Fixed that it was not possible to give extracted components + the file extension `.ui.qml` +* Fixed that switching from Qt Quick Designer failed to commit pending changes + (QTCREATORBUG-14830) +* Fixed issues with pressing escape + +Diff Viewer + +* Added local diff for modified files in Qt Creator (`Diff` > + `Diff Current File`, `Diff` > `Diff All Modified Files`) + (QTCREATORBUG-9732) +* Fixed that reload prompt was shown when reverting change + +Version Control Systems + +* Gerrit + * Fixed pushing to Gerrit when remote repository is empty + (QTCREATORBUG-16780) + +Test Integration + +* Added option to disable crash handler when debugging +* Fixed that results were not shown when debugging (QTCREATORBUG-16693) +* Fixed that progress indicator sometimes did not stop + +Model Editor + +* Added zooming +* Added synchronization of selected diagram in diagram browser + +Platform Specific + +Android + +* Improved stability of determination if application is running +* Fixed that running without deployment did not start emulator + (QTCREATORBUG-10237) +* Fixed that permission model downgrade was not detected as error + (QTCREATORBUG-16630) +* Fixed handling of minimum required API level (QTCREATORBUG-16740) + +Credits for these changes go to: From ff4435c4da459104795e3bf17d8e51cb84d3e592 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 19 Oct 2016 16:36:18 +0200 Subject: [PATCH 51/53] Doc: Describe the Help > System Information menu item Change-Id: I95a179b9414a2b417d6f8d03a3dce51f8a2f733b Reviewed-by: Eike Ziller --- doc/src/qtcreator.qdoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/src/qtcreator.qdoc b/doc/src/qtcreator.qdoc index 1f22d1d0ddd..20d07b2b6b3 100644 --- a/doc/src/qtcreator.qdoc +++ b/doc/src/qtcreator.qdoc @@ -124,6 +124,9 @@ \row \li {4,1} \note To report bugs and suggestions to the Qt Bug Tracker, select \uicontrol {Help > Report Bug}. + To copy and paste detailed information about your system to the + bug report, select \uicontrol Help > + \uicontrol {System Information}. You can also join the \QC mailing list at: \l{http://lists.qt-project.org/mailman/listinfo/} From f69518641f4050ff06e22bd0d7c2ffb5fbd3e50d Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 21 Oct 2016 19:01:34 +0200 Subject: [PATCH 52/53] QmlDesigner.PropertyEditor: Fix gradient editor Task-number: QTCREATORBUG-16404 Change-Id: I2d36c8c6170f1b8471271118b1b9e32ff61043ba Reviewed-by: Tim Jenssen --- .../propertyEditorQmlSources/HelperWidgets/ColorEditor.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorEditor.qml index 007de033723..baf54c818da 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorEditor.qml @@ -123,6 +123,7 @@ Column { if (supportGradient && gradientLine.hasGradient) { colorEditor.color = gradientLine.currentColor gradientLine.currentColor = color + textField.text = colorEditor.color } gradientLine.isInValidState = true } From 0f5f0c138ca5812256f678592198ed4eddc24f25 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 21 Oct 2016 13:53:01 +0200 Subject: [PATCH 53/53] QmlDesigner: Hotfix for ColorButton Instead of a shader I use canvas. I had to rotate the color box to be able to use gradients. This is working around QTBUG-56639. Change-Id: Id321311713029d8aa66e068b02361d86debfa666 Reviewed-by: Alessandro Portale --- .../HelperWidgets/ColorButton.qml | 76 ++++++------------- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml index 80272e25c34..203e692a82f 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml @@ -133,62 +133,35 @@ Item { fillMode: Image.Tile // note we smoothscale the shader from a smaller version to improve performance - ShaderEffect { - id: map + Canvas { + id: hubeBox opacity: colorButton.alpha - scale: surround.width / width; - layer.enabled: true - layer.smooth: true anchors.fill: parent property real hue: colorButton.hue + onHueChanged: requestPaint() - fragmentShader: " - varying mediump vec2 qt_TexCoord0; - uniform highp float qt_Opacity; - uniform highp float hue; + onPaint: { + var ctx = hubeBox.getContext('2d') - highp float hueToIntensity(highp float v1, highp float v2, highp float h) { - h = fract(h); - if (h < 1.0 / 6.0) - return v1 + (v2 - v1) * 6.0 * h; - else if (h < 1.0 / 2.0) - return v2; - else if (h < 2.0 / 3.0) - return v1 + (v2 - v1) * 6.0 * (2.0 / 3.0 - h); + ctx.save() - return v1; - } + ctx.clearRect(0, 0, hubeBox.width, hubeBox.height); - highp vec3 HSLtoRGB(highp vec3 color) { - highp float h = color.x; - highp float l = color.z; - highp float s = color.y; + for (var row = 0; row < hubeBox.height; row++){ + var gradient = ctx.createLinearGradient(0, 0, hubeBox.width,0); + var l = Math.abs(row - hubeBox.height) / hubeBox.height - if (s < 1.0 / 256.0) - return vec3(l, l, l); + gradient.addColorStop(0, Qt.hsla(hubeBox.hue, 0, l, 1)); + gradient.addColorStop(1, Qt.hsla(hubeBox.hue, 1, l, 1)); - highp float v1; - highp float v2; - if (l < 0.5) - v2 = l * (1.0 + s); - else - v2 = (l + s) - (s * l); + ctx.fillStyle = gradient; + ctx.fillRect(0, row, hubeBox.width, 1); + } - v1 = 2.0 * l - v2; + ctx.restore() - highp float d = 1.0 / 3.0; - highp float r = hueToIntensity(v1, v2, h + d); - highp float g = hueToIntensity(v1, v2, h); - highp float b = hueToIntensity(v1, v2, h - d); - return vec3(r, g, b); - } + } - void main() { - lowp vec4 c = vec4(1.0); - c.rgb = HSLtoRGB(vec3(hue, 1.0 - qt_TexCoord0.t, qt_TexCoord0.s)); - gl_FragColor = c * qt_Opacity; - } - " } Canvas { @@ -215,9 +188,8 @@ Item { context.clearRect(0, 0, canvas.width, canvas.height); - var yy = canvas.height - colorButton.saturation * canvas.height - - var xx = colorButton.lightness * canvas.width + var yy = canvas.height -colorButton.lightness * canvas.height + var xx = colorButton.saturation * canvas.width ctx.strokeStyle = canvas.strokeStyle ctx.lineWidth = 1 @@ -245,13 +217,9 @@ Item { if (pressed) { var xx = Math.max(0, Math.min(mouse.x, parent.width)) var yy = Math.max(0, Math.min(mouse.y, parent.height)) - //saturationSlider.value = 1.0 - yy / parent.height - //lightnessSlider.value = xx / parent.width - //var myHue = colorButton.hue - colorButton.saturation = 1.0 - yy / parent.height; - colorButton.lightness = xx / parent.width; - //colorButton.hue = myHue - //colorButton.color = Qt.hsla(colorButton.hue, 1.0 - yy / parent.height, xx / parent.width, colorButton.alpha) + + colorButton.lightness = 1.0 - yy / parent.height; + colorButton.saturation = xx / parent.width; } } onPressed: positionChanged(mouse)