diff options
author | Eike Ziller <eike.ziller@qt.io> | 2018-02-23 10:56:52 +0100 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2018-02-23 10:56:52 +0100 |
commit | 7c3cfa166d6b54c792f1c452a162bd7842becd52 (patch) | |
tree | 404f58894cfebcf6fb62e9eab60b3fb33a3f6f44 | |
parent | 31a55b02477fa0c6b9b9fca7e26ebc6951c3be30 (diff) | |
parent | 09a7247bfc08e5d8e027493909c2acb448a0bd8e (diff) |
Merge remote-tracking branch 'origin/4.6'
Conflicts:
src/plugins/coreplugin/helpmanager.cpp
Change-Id: I2feb60ec0afb2f22f75dc137a01c3fa217b299d8
85 files changed, 1106 insertions, 386 deletions
diff --git a/dist/clang/patches/200_D36390_Fix-overloaded-static-functions-in-SemaCodeComplete.patch b/dist/clang/patches/200_D36390_Fix-overloaded-static-functions-in-SemaCodeComplete.patch new file mode 100644 index 0000000000..3e5bfe553f --- /dev/null +++ b/dist/clang/patches/200_D36390_Fix-overloaded-static-functions-in-SemaCodeComplete.patch @@ -0,0 +1,148 @@ +--- a/include/clang/Sema/Sema.h ++++ b/include/clang/Sema/Sema.h +@@ -2707,7 +2707,8 @@ + OverloadCandidateSet &CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, + bool SuppressUserConversions = false, +- bool PartialOverloading = false); ++ bool PartialOverloading = false, ++ bool FirstArgumentIsBase = false); + void AddMethodCandidate(DeclAccessPair FoundDecl, + QualType ObjectType, + Expr::Classification ObjectClassification, +--- a/lib/Sema/SemaCodeComplete.cpp ++++ b/lib/Sema/SemaCodeComplete.cpp +@@ -4396,9 +4396,11 @@ + ArgExprs.append(Args.begin(), Args.end()); + UnresolvedSet<8> Decls; + Decls.append(UME->decls_begin(), UME->decls_end()); ++ const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); + AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, + /*SuppressUsedConversions=*/false, +- /*PartialOverloading=*/true); ++ /*PartialOverloading=*/true, ++ FirstArgumentIsBase); + } else { + FunctionDecl *FD = nullptr; + if (auto MCE = dyn_cast<MemberExpr>(NakedFn)) +--- a/lib/Sema/SemaOverload.cpp ++++ b/lib/Sema/SemaOverload.cpp +@@ -6343,24 +6343,36 @@ + OverloadCandidateSet& CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs, + bool SuppressUserConversions, +- bool PartialOverloading) { ++ bool PartialOverloading, ++ bool FirstArgumentIsBase) { + for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { + NamedDecl *D = F.getDecl()->getUnderlyingDecl(); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { ++ ArrayRef<Expr *> FunctionArgs = Args; + if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { + QualType ObjectType; + Expr::Classification ObjectClassification; +- if (Expr *E = Args[0]) { +- // Use the explit base to restrict the lookup: +- ObjectType = E->getType(); +- ObjectClassification = E->Classify(Context); +- } // .. else there is an implit base. ++ if (Args.size() > 0) { ++ if (Expr *E = Args[0]) { ++ // Use the explit base to restrict the lookup: ++ ObjectType = E->getType(); ++ ObjectClassification = E->Classify(Context); ++ } // .. else there is an implit base. ++ FunctionArgs = Args.slice(1); ++ } + AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), + cast<CXXMethodDecl>(FD)->getParent(), ObjectType, +- ObjectClassification, Args.slice(1), CandidateSet, ++ ObjectClassification, FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); + } else { +- AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, ++ // Slice the first argument (which is the base) when we access ++ // static method as non-static ++ if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && ++ !isa<CXXConstructorDecl>(FD)))) { ++ assert(cast<CXXMethodDecl>(FD)->isStatic()); ++ FunctionArgs = Args.slice(1); ++ } ++ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); + } + } else { +--- a/test/Index/complete-call.cpp ++++ b/test/Index/complete-call.cpp +@@ -94,6 +94,24 @@ + s.foo_7(42,); + } + ++struct Bar { ++ static void foo_1(); ++ void foo_1(float); ++ static void foo_1(int); ++}; ++ ++void test() { ++ Bar::foo_1(); ++ Bar b; ++ b.foo_1(); ++} ++ ++struct Bar2 : public Bar { ++ Bar2() { ++ Bar::foo_1(); ++ } ++}; ++ + // RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s + // CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) + // CHECK-CC1: Completion contexts: +@@ -803,3 +821,46 @@ + // CHECK-CC59-NEXT: Class name + // CHECK-CC59-NEXT: Nested name specifier + // CHECK-CC59-NEXT: Objective-C interface ++ ++// RUN: c-index-test -code-completion-at=%s:104:14 %s | FileCheck -check-prefix=CHECK-CC60 %s ++// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) ++// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) ++// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) ++// CHECK-CC60: Completion contexts: ++// CHECK-CC60-NEXT: Any type ++// CHECK-CC60-NEXT: Any value ++// CHECK-CC60-NEXT: Enum tag ++// CHECK-CC60-NEXT: Union tag ++// CHECK-CC60-NEXT: Struct tag ++// CHECK-CC60-NEXT: Class name ++// CHECK-CC60-NEXT: Nested name specifier ++// CHECK-CC60-NEXT: Objective-C interface ++ ++// RUN: c-index-test -code-completion-at=%s:106:11 %s | FileCheck -check-prefix=CHECK-CC61 %s ++// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) ++// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) ++// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) ++// CHECK-CC61: Completion contexts: ++// CHECK-CC61-NEXT: Any type ++// CHECK-CC61-NEXT: Any value ++// CHECK-CC61-NEXT: Enum tag ++// CHECK-CC61-NEXT: Union tag ++// CHECK-CC61-NEXT: Struct tag ++// CHECK-CC61-NEXT: Class name ++// CHECK-CC61-NEXT: Nested name specifier ++// CHECK-CC61-NEXT: Objective-C interface ++ ++// RUN: c-index-test -code-completion-at=%s:111:16 %s | FileCheck -check-prefix=CHECK-CC62 %s ++// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) ++// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) ++// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) ++// CHECK-CC62: Completion contexts: ++// CHECK-CC62-NEXT: Any type ++// CHECK-CC62-NEXT: Any value ++// CHECK-CC62-NEXT: Enum tag ++// CHECK-CC62-NEXT: Union tag ++// CHECK-CC62-NEXT: Struct tag ++// CHECK-CC62-NEXT: Class name ++// CHECK-CC62-NEXT: Nested name specifier ++// CHECK-CC62-NEXT: Objective-C interface ++ diff --git a/dist/clang/patches/210_D43453_Fix-overloaded-static-functions-for-templates.patch b/dist/clang/patches/210_D43453_Fix-overloaded-static-functions-for-templates.patch new file mode 100644 index 0000000000..2296904f7d --- /dev/null +++ b/dist/clang/patches/210_D43453_Fix-overloaded-static-functions-for-templates.patch @@ -0,0 +1,168 @@ +diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp +index 1b07ec60ce..46ed08d1cf 100644 +--- a/lib/Sema/SemaOverload.cpp ++++ b/lib/Sema/SemaOverload.cpp +@@ -6371,57 +6371,54 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, + bool FirstArgumentIsBase) { + for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { + NamedDecl *D = F.getDecl()->getUnderlyingDecl(); +- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +- ArrayRef<Expr *> FunctionArgs = Args; +- if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { +- QualType ObjectType; +- Expr::Classification ObjectClassification; +- if (Args.size() > 0) { +- if (Expr *E = Args[0]) { +- // Use the explit base to restrict the lookup: +- ObjectType = E->getType(); +- ObjectClassification = E->Classify(Context); +- } // .. else there is an implit base. +- FunctionArgs = Args.slice(1); +- } +- AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), +- cast<CXXMethodDecl>(FD)->getParent(), ObjectType, +- ObjectClassification, FunctionArgs, CandidateSet, +- SuppressUserConversions, PartialOverloading); +- } else { +- // Slice the first argument (which is the base) when we access +- // static method as non-static +- if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && +- !isa<CXXConstructorDecl>(FD)))) { +- assert(cast<CXXMethodDecl>(FD)->isStatic()); +- FunctionArgs = Args.slice(1); +- } +- AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, +- SuppressUserConversions, PartialOverloading); +- } +- } else { +- FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); +- if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && +- !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) { +- QualType ObjectType; +- Expr::Classification ObjectClassification; ++ ArrayRef<Expr *> FunctionArgs = Args; ++ ++ FunctionTemplateDecl *FunTmpl = nullptr; ++ FunctionDecl *FD = dyn_cast<FunctionDecl>(D); ++ ++ const bool IsTemplate = FD ? false : true; ++ if (IsTemplate) { ++ FunTmpl = cast<FunctionTemplateDecl>(D); ++ FD = FunTmpl->getTemplatedDecl(); ++ } ++ ++ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { ++ QualType ObjectType; ++ Expr::Classification ObjectClassification; ++ if (Args.size() > 0) { + if (Expr *E = Args[0]) { +- // Use the explit base to restrict the lookup: ++ // Use the explicit base to restrict the lookup: + ObjectType = E->getType(); + ObjectClassification = E->Classify(Context); + } // .. else there is an implit base. ++ FunctionArgs = Args.slice(1); ++ } ++ if (IsTemplate) + AddMethodTemplateCandidate( +- FunTmpl, F.getPair(), +- cast<CXXRecordDecl>(FunTmpl->getDeclContext()), +- ExplicitTemplateArgs, ObjectType, ObjectClassification, +- Args.slice(1), CandidateSet, SuppressUserConversions, +- PartialOverloading); +- } else { +- AddTemplateOverloadCandidate(FunTmpl, F.getPair(), +- ExplicitTemplateArgs, Args, +- CandidateSet, SuppressUserConversions, +- PartialOverloading); ++ FunTmpl, F.getPair(), cast<CXXRecordDecl>(FD), ExplicitTemplateArgs, ++ ObjectType, ObjectClassification, FunctionArgs, CandidateSet, ++ SuppressUserConversions, PartialOverloading); ++ else ++ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), ++ cast<CXXMethodDecl>(FD)->getParent(), ObjectType, ++ ObjectClassification, FunctionArgs, CandidateSet, ++ SuppressUserConversions, PartialOverloading); ++ } else { ++ // Slice the first argument (which is the base) when we access ++ // static method as non-static ++ if (Args.size() > 0 && ++ (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && ++ !isa<CXXConstructorDecl>(FD)))) { ++ assert(cast<CXXMethodDecl>(FD)->isStatic()); ++ FunctionArgs = Args.slice(1); + } ++ if (IsTemplate) ++ AddTemplateOverloadCandidate( ++ FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs, ++ CandidateSet, SuppressUserConversions, PartialOverloading); ++ else ++ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, ++ SuppressUserConversions, PartialOverloading); + } + } + } +diff --git a/test/Index/complete-call.cpp b/test/Index/complete-call.cpp +index ca116485ac..35f2009066 100644 +--- a/test/Index/complete-call.cpp ++++ b/test/Index/complete-call.cpp +@@ -112,6 +112,33 @@ struct Bar2 : public Bar { + } + }; + ++struct BarTemplates { ++ static void foo_1() {} ++ void foo_1(float) {} ++ static void foo_1(int) {} ++ ++ template<class T1, class T2> ++ static void foo_1(T1 a, T2 b) { a + b; } ++ ++ template<class T1, class T2> ++ void foo_1(T1 a, T2 b, float c) { a + b + c; } ++ ++ template<class T1, class T2> ++ static void foo_1(T2 a, int b, T1 c) { a + b + c; } ++}; ++ ++void testTemplates() { ++ BarTemplates::foo_1(); ++ BarTemplates b; ++ b.foo_1(); ++} ++ ++struct Bar2Template : public BarTemplates { ++ Bar2Template() { ++ BarTemplates::foo_1(); ++ } ++}; ++ + // RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s + // CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) + // CHECK-CC1: Completion contexts: +@@ -864,3 +891,25 @@ struct Bar2 : public Bar { + // CHECK-CC62-NEXT: Nested name specifier + // CHECK-CC62-NEXT: Objective-C interface + ++// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s ++// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) ++// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) ++// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) ++// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) ++// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) ++// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) ++ ++// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s ++// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) ++// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) ++// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) ++// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) ++// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) ++ ++// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s ++// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) ++// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) ++// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) ++// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) ++// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) ++// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) diff --git a/dist/clang/patches/README.md b/dist/clang/patches/README.md index 517df553b3..86e84e74de 100644 --- a/dist/clang/patches/README.md +++ b/dist/clang/patches/README.md @@ -112,3 +112,20 @@ Significantly reduces problems when saving a header file on Windows. Builds Clazy as an LLVM part and forces link for Clazy plugin registry entry. +##### 200_D36390_Fix-overloaded-static-functions-in-SemaCodeComplete.patch + +* <https://reviews.llvm.org/D36390> +* <https://bugs.llvm.org/show_bug.cgi?id=33904> + +Fix overloaded static functions in SemaCodeComplete + +Happens when static function is accessed via the class variable. +That leads to incorrect overloads number because the variable is considered as the first argument. + +##### 210_D43453_Fix-overloaded-static-functions-for-templates.patch + +* <https://reviews.llvm.org/D43453> + +Fix overloaded static functions for templates + +Apply almost the same fix as D36390 but for templates diff --git a/doc/images/qtcreator-clang-code-model-options.png b/doc/images/qtcreator-clang-code-model-options.png Binary files differindex 1c35af1fb0..99351af363 100644 --- a/doc/images/qtcreator-clang-code-model-options.png +++ b/doc/images/qtcreator-clang-code-model-options.png diff --git a/doc/images/qtcreator-clang-tidy.png b/doc/images/qtcreator-clang-tidy.png Binary files differnew file mode 100644 index 0000000000..156eb23d9d --- /dev/null +++ b/doc/images/qtcreator-clang-tidy.png diff --git a/doc/images/qtcreator-clazy.png b/doc/images/qtcreator-clazy.png Binary files differnew file mode 100644 index 0000000000..5b59b0d15a --- /dev/null +++ b/doc/images/qtcreator-clazy.png diff --git a/doc/src/editors/creator-clang-codemodel.qdoc b/doc/src/editors/creator-clang-codemodel.qdoc index 673159fd90..239fe842aa 100644 --- a/doc/src/editors/creator-clang-codemodel.qdoc +++ b/doc/src/editors/creator-clang-codemodel.qdoc @@ -93,27 +93,68 @@ \li Code completion \li Syntactic and semantic highlighting \li Diagnostics + \li Clang-Tidy checks + \li Clazy checks \li Tooltips - \li Clang-Tidy and Clazy checks \li Renaming of local symbols \endlist To use the plugin, you must activate it and configure it in \QC. - \section1 Using Clang-Tidy and Clazy + \section1 Code Model Warnings - \l{https://clang.llvm.org/extra/clang-tidy/}{Clang-Tidy} and - \l{https://github.com/KDE/clazy/blob/master/README.md}{Clazy} are delivered - as parts of the Clang library delivered with \QC. + The predefined configurations request Clang warnings at the following + levels: - Clang-Tidy provides an extensible framework for diagnosing and fixing - typical programming errors, such as style violations, interface misuse, or - issues that can be found via static analysis. + \list + + \li \uicontrol {Pedantic Warnings} uses the \c -Wpendantic option that + requests all the warnings demanded by strict ISO C and ISO C++. + + \li \uicontrol {Warnings for Questionable Constructs} combines the + \c -Wall and \c -Wextra options to request all warnings about easily + avoidable questionable constructions and some additional warnings. + + \li \uicontrol {Warnings for Almost Everything} uses the \c -Weverything + option with negative options to suppress some warnings. + + \endlist + + You can edit the predefined configurations to request specific warnings + beginning with \c -W. Each of these warnings also has a negative version + that begins with \c -Wno. + + Keep in mind that some options turn on other options. For more information, + see \l{https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html} + {Options to Request or Suppress Warnings} or the GCC or Clang manual pages. + + \section1 Using Clang-Tidy Checks - Clazy helps Clang understand Qt semantics. It prints out Qt related compiler - warnings, ranging from unnecessary memory allocation to misuse of API and - provides refactoring actions for fixing some of the issues. + \l{https://clang.llvm.org/extra/clang-tidy/}{Clang-Tidy} is delivered + as a part of the Clang library delivered with \QC. It provides diagnostics + and fixes for typical programming errors, such as style violations, + interface misuse, or issues that can be found via static analysis. + + \QC integrates the fixes and diagnostics into the Clang library, and + therefore they cannot be easily changed or extended when used with \QC. + + \section1 Using Clazy + + \l{https://github.com/KDE/clazy/blob/master/README.md}{Clazy} is delivered + as a part of the Clang library delivered with \QC. It helps Clang understand + Qt semantics. It prints out Qt related compiler warnings, ranging from + unnecessary memory allocation to misuse of API and provides refactoring + actions for fixing some of the issues. + + The Clazy checks are divided into levels from 0 to 3. Each level adds checks + to the previous level. The checks at level 0 are very stable and provide + hardly any false positives, while the checks at level 3 can be considered + experimental. + + For more information about the checks run at each level, see + \l{https://github.com/KDE/clazy/blob/master/README.md#list-of-checks} + {List of Checks} in the Clazy documentation. \section1 Activating Clang Code Model @@ -159,44 +200,31 @@ edit the value for the \uicontrol {Do not index files greater than} check box. To index all files, deselect the check box. - \li In the \uicontrol {Clang Code Model Warnings} group, configure the - diagnostics that Clang should issue. + \li In \uicontrol {Clang Dianostics}, select one of the predefined + configurations, or select \uicontrol Copy to create a copy of a + configuration and edit it to fit your needs. \list - \li In the \uicontrol {Configuration to use} list, select one of - the predefined configurations, or select \uicontrol Copy to - create a copy of a configuration and edit it to fit your - needs. + \li In the \uicontrol Clang tab, edit the predefined + configuration to request specific warnings. - \li \uicontrol {Pedantic Warnings} uses the \c -Wpendantic - option that requests all the warnings demanded by strict - ISO C and ISO C++. + \li In the \uicontrol {Clang-Tidy} tab, select the checks to + perform. - \li \uicontrol {Warnings for Questionable Constructs} combines - the \c -Wall and \c -Wextra options to request all warnings - about easily avoidable questionable constructions and some - additional warnings. + \image qtcreator-clang-tidy.png - \li \uicontrol {Warnings for Almost Everything} uses the \c - -Weverything option with negative options to suppress some - warnings. + \li In the \uicontrol Clazy tab, select the level of Clazy + checks to perform. - \endlist - - You can edit the predefined configurations to request specific - warnings beginning with \c -W. Each of these warnings also has a - negative version that begins with \c -Wno. Keep in mind that some - options turn on other options. For more information, see - \l{https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html} - {Options to Request or Suppress Warnings} or the GCC or Clang - manual pages. + \image qtcreator-clazy.png - \li In the \uicontrol {Clang Plugins} field, select the Clang-Tidy and - Clazy checks to perform. + \endlist \endlist + \section1 Specifying Clang Settings at Project Level + You can specify Clang settings at project level in the build settings of the project by selecting \uicontrol Projects > \uicontrol {Clang Code Model}. In addition to configuring the diagnostics, diff --git a/scripts/qdoc2tasks.pl b/scripts/qdoc2tasks.pl index 244a0a13a4..2e0eb8a523 100755 --- a/scripts/qdoc2tasks.pl +++ b/scripts/qdoc2tasks.pl @@ -38,15 +38,32 @@ qdoc2tasks.pl - Convert qdoc warnings into Qt Creator task files. use strict; use warnings; +my $lastDiagnostic; + while (my $line = <STDIN>) { chomp($line); # --- extract file name based matching: # Qt 5.10: D:/.../qaxbase.cpp:3231: warning: Cannot tie this documentation to anything # Qt 5.11: D:/.../qaxbase.cpp:3231: (qdoc) warning: Cannot tie this documentation to anything if ($line =~ /^(..[^:]*):(\d+): (?:\(qdoc\) )?warning: (.*)$/) { + if (defined($lastDiagnostic)) { + print $lastDiagnostic, "\n"; + $lastDiagnostic = undef; + } my $fileName = $1; my $lineNumber = $2; my $text = $3; - print $fileName, "\t", $lineNumber, "\twarn\t", $text,"\n"; + my $message = $fileName . "\t" . $lineNumber . "\twarn\t" . $text; + if (index($message, 'clang found diagnostics parsing') >= 0) { + $lastDiagnostic = $message; + } else { + print $message, "\n"; + } + } elsif (defined($lastDiagnostic) && $line =~ /^ /) { + $line =~ s/^\s+//; + $line =~ s/\s+$//; + $lastDiagnostic .= ' ' . $line; } } + +print $lastDiagnostic, "\n" if defined($lastDiagnostic); diff --git a/scripts/sphinx2tasks.pl b/scripts/sphinx2tasks.pl new file mode 100755 index 0000000000..e170cd2c47 --- /dev/null +++ b/scripts/sphinx2tasks.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl + +############################################################################ +# +# Copyright (C) 2018 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. +# +############################################################################ + +=head1 NAME + +sphinx2tasks.pl - Convert sphinx (Python documentation) warnings into Qt Creator task files. + +=head1 SYNOPSIS + + sphinx2tasks.pl < logfile > taskfile + +=cut + +use strict; +use warnings; + +while (my $line = <STDIN>) { + chomp($line); + # Strip terminal control characters + my $len = length($line); + $line = substr($line, 5, $len - 17) if ($len > 0 && ord(substr($line, 0, 1)) == 0x1B); + # --- extract file name based matching: + # file.rst:698: WARNING: undefined label: xquer (if the link....) + if ($line =~ /^[^\/]*([^:]+\.rst):(\d*): WARNING: (.*)$/) { + my $fileName = $1; + my $lineNumber = $2 eq '' ? '1' : $2; + my $text = $3; + print $fileName, "\t", $lineNumber, "\twarn\t", $text,"\n"; + } +} diff --git a/share/qtcreator/qml-type-descriptions/qt5QtQuick2-bundle.json b/share/qtcreator/qml-type-descriptions/qt5QtQuick2-bundle.json index c69c90e12a..4742c51070 100644 --- a/share/qtcreator/qml-type-descriptions/qt5QtQuick2-bundle.json +++ b/share/qtcreator/qml-type-descriptions/qt5QtQuick2-bundle.json @@ -16,6 +16,13 @@ "Qt.labs.settings 1.0", "Qt.labs.platform 1.0", "Qt.WebSockets 1.0", + "Qt3D.Animation 2.9", + "Qt3D.Core 2.0", + "Qt3D.Extras 2.0", + "Qt3D.Input 2.0", + "Qt3D.Logic 2.0", + "Qt3D.Render 2.0", + "Qt3D.Scene2D 2.9", "QtAudioEngine 1.0", "QtBluetooth 5.0", "QtBluetooth 5.2", diff --git a/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp b/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp index a798c1c4cb..35c56d02d2 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp +++ b/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate_56.cpp @@ -35,6 +35,9 @@ #include <QQmlComponent> #include <QFileInfo> +#include <private/qabstractfileengine_p.h> +#include <private/qfsfileengine_p.h> + #include <private/qquickdesignersupport_p.h> #include <private/qquickdesignersupportmetainfo_p.h> #include <private/qquickdesignersupportitems_p.h> @@ -419,9 +422,57 @@ ComponentCompleteDisabler::~ComponentCompleteDisabler() DesignerSupport::enableComponentComplete(); } +class QrcEngineHandler : public QAbstractFileEngineHandler +{ +public: + QAbstractFileEngine *create(const QString &fileName) const; +}; + +QAbstractFileEngine *QrcEngineHandler::create(const QString &fileName) const +{ + if (fileName.startsWith(":/qt-project.org")) + return nullptr; + + if (fileName.startsWith(":/qtquickplugin")) + return nullptr; + + if (fileName.startsWith(":/")) { + const QStringList searchPaths = qmlDesignerRCPath().split(';'); + foreach (const QString &qrcPath, searchPaths) { + const QStringList qrcDefintion = qrcPath.split('='); + if (qrcDefintion.count() == 2) { + QString fixedPath = fileName; + fixedPath.replace(":" + qrcDefintion.first(), qrcDefintion.last() + '/'); + + if (QFileInfo::exists(fixedPath)) { + fixedPath.replace("//", "/"); + fixedPath.replace('\\', '/'); + return new QFSFileEngine(fixedPath); + } + } + } + } + + return nullptr; +} + +static QrcEngineHandler* s_qrcEngineHandler = nullptr; + +class EngineHandlerDeleter +{ +public: + EngineHandlerDeleter() + {} + ~EngineHandlerDeleter() + { delete s_qrcEngineHandler; } +}; + void registerFixResourcePathsForObjectCallBack() { - QQuickDesignerSupportItems::registerFixResourcePathsForObjectCallBack(&fixResourcePathsForObject); + static EngineHandlerDeleter deleter; + + if (!s_qrcEngineHandler) + s_qrcEngineHandler = new QrcEngineHandler(); } } // namespace QmlPrivateGate diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme index 545d662548..6b16c8a891 100644 --- a/share/qtcreator/themes/dark.creatortheme +++ b/share/qtcreator/themes/dark.creatortheme @@ -162,6 +162,7 @@ Welcome_ButtonBackgroundColor=normalBackground Welcome_DividerColor=ff555555 Welcome_HoverColor=ff444444 Welcome_LinkColor=ff78bb39 +Welcome_DisabledLinkColor=textDisabled Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground diff --git a/share/qtcreator/themes/default.creatortheme b/share/qtcreator/themes/default.creatortheme index e93d682b9f..c5cf6b9c23 100644 --- a/share/qtcreator/themes/default.creatortheme +++ b/share/qtcreator/themes/default.creatortheme @@ -154,6 +154,7 @@ Welcome_ButtonBackgroundColor=ffdfdfdf Welcome_DividerColor=ffd6d6d6 Welcome_HoverColor=ffe8e8e8 Welcome_LinkColor=ff5caa15 +Welcome_DisabledLinkColor=textDisabled Timeline_TextColor=darkText Timeline_BackgroundColor1=ffffffff diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme index f966634f53..f433bcb098 100644 --- a/share/qtcreator/themes/flat-dark.creatortheme +++ b/share/qtcreator/themes/flat-dark.creatortheme @@ -167,6 +167,7 @@ Welcome_ButtonBackgroundColor=normalBackground Welcome_DividerColor=ff555555 Welcome_HoverColor=ff444444 Welcome_LinkColor=ff7fc63c +Welcome_DisabledLinkColor=textDisabled Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme index 3946b312dd..1975996d23 100644 --- a/share/qtcreator/themes/flat-light.creatortheme +++ b/share/qtcreator/themes/flat-light.creatortheme @@ -165,6 +165,7 @@ Welcome_ButtonBackgroundColor=normalBackground Welcome_DividerColor=ffd6d6d6 Welcome_HoverColor=fff6f6f6 Welcome_LinkColor=ff5caa15 +Welcome_DisabledLinkColor=textDisabled Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme index 29226c044d..d6864c5abd 100644 --- a/share/qtcreator/themes/flat.creatortheme +++ b/share/qtcreator/themes/flat.creatortheme @@ -163,6 +163,7 @@ Welcome_ButtonBackgroundColor=normalBackground Welcome_DividerColor=ffd6d6d6 Welcome_HoverColor=fff6f6f6 Welcome_LinkColor=ff5caa15 +Welcome_DisabledLinkColor=textDisabled Timeline_TextColor=text Timeline_BackgroundColor1=normalBackground diff --git a/share/qtcreator/translations/extract-snippets.xq b/share/qtcreator/translations/extract-snippets.xq new file mode 100644 index 0000000000..0b7e52d476 --- /dev/null +++ b/share/qtcreator/translations/extract-snippets.xq @@ -0,0 +1,9 @@ +let $prefix := string("QT_TRANSLATE_NOOP3("TextEditor::Internal::Snippets", "") +let $midfix := string("", "") +let $suffix := concat("")", codepoints-to-string(10)) +for $file in tokenize($files, string("\|")) + for $snippet in (doc($file)/*/snippet) + let $group := fn:concat(string("group:'"), data($snippet/@group), string("' ")) + let $trigger := fn:concat(string("trigger:'"), data($snippet/@trigger), string("'")) + where ($snippet/@complement) + return fn:concat($prefix, data($snippet/@complement), $midfix, $group, $trigger, $suffix) diff --git a/share/qtcreator/translations/translations.pro b/share/qtcreator/translations/translations.pro index 5f752f2855..9a3e296dda 100644 --- a/share/qtcreator/translations/translations.pro +++ b/share/qtcreator/translations/translations.pro @@ -27,6 +27,7 @@ JSONWIZARD_TR_H = $$OUT_PWD/jsonwizard_tr.h QMLWIZARD_TR_H = $$OUT_PWD/qmlwizard_tr.h QTQUICKWIZARD_TR_H = $$OUT_PWD/qtquickwizard_tr.h EXTERNALTOOLS_TR_H = $$OUT_PWD/externaltools_tr.h +SNIPPETS_TR_H = $$OUT_PWD/snippets_tr.h win32: \ PREFIX = "file:///" @@ -48,12 +49,16 @@ QTQUICKWIZARD_FILES = \"$$join(QTQUICKWIZARD_FILES, "|$$PREFIX", "$$PREFIX")\" for(file, $$list($$files($$IDE_SOURCE_TREE/src/share/qtcreator/externaltools/*))):EXTERNALTOOLS_FILES += $$files($$file) EXTERNALTOOLS_FILES = \"$$join(EXTERNALTOOLS_FILES, "|$$PREFIX", "$$PREFIX")\" +for(file, $$list($$files($$IDE_SOURCE_TREE/share/qtcreator/snippets/*))):SNIPPETS_FILES += $$files($$file) +SNIPPETS_FILES = \"$$join(SNIPPETS_FILES, "|$$PREFIX", "$$PREFIX")\" + extract.commands += \ $$XMLPATTERNS -output $$MIME_TR_H -param files=$$MIMETYPES_FILES $$PWD/extract-mimetypes.xq $$escape_expand(\\n\\t) \ $$XMLPATTERNS -output $$CUSTOMWIZARD_TR_H -param files=$$CUSTOMWIZARD_FILES $$PWD/extract-customwizards.xq $$escape_expand(\\n\\t) \ $$XMLPATTERNS -output $$QMLWIZARD_TR_H -param files=$$QMLWIZARD_FILES $$PWD/extract-qmlwizards.xq $$escape_expand(\\n\\t) \ $$XMLPATTERNS -output $$QTQUICKWIZARD_TR_H -param files=$$QTQUICKWIZARD_FILES $$PWD/extract-qtquickwizards.xq $$escape_expand(\\n\\t) \ $$XMLPATTERNS -output $$EXTERNALTOOLS_TR_H -param files=$$EXTERNALTOOLS_FILES $$PWD/extract-externaltools.xq $$escape_expand(\\n\\t) \ + $$XMLPATTERNS -output $$SNIPPETS_TR_H -param files=$$SNIPPETS_FILES $$PWD/extract-snippets.xq $$escape_expand(\\n\\t) \ $(QMAKE) -o Makefile.jsonwizard JSONWIZARD_TR_H=\"$$JSONWIZARD_TR_H\" TOP_LEVEL=\"$$IDE_SOURCE_TREE/share/qtcreator/templates/wizards\" $$PWD/jsonwizard_tr.pro QMAKE_EXTRA_TARGETS += extract @@ -77,12 +82,12 @@ files = $$files($$PWD/*_??.ts) $$PWD/qtcreator_untranslated.ts for(file, files) { lang = $$replace(file, .*_([^/]*)\\.ts, \\1) v = ts-$${lang}.commands - $$v = cd $$wd && $$LUPDATE $$include_options $$sources $$MIME_TR_H $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$QMLWIZARD_TR_H $$QTQUICKWIZARD_TR_H $$EXTERNALTOOLS_TR_H -ts $$file + $$v = cd $$wd && $$LUPDATE $$include_options $$sources $$MIME_TR_H $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$QMLWIZARD_TR_H $$QTQUICKWIZARD_TR_H $$EXTERNALTOOLS_TR_H $$SNIPPETS_TR_H -ts $$file v = ts-$${lang}.depends $$v = extract QMAKE_EXTRA_TARGETS += ts-$$lang } -ts-all.commands = cd $$wd && $$LUPDATE $$include_options $$sources $$MIME_TR_H $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$QMLWIZARD_TR_H $$QTQUICKWIZARD_TR_H $$EXTERNALTOOLS_TR_H -ts $$files +ts-all.commands = cd $$wd && $$LUPDATE $$include_options $$sources $$MIME_TR_H $$CUSTOMWIZARD_TR_H $$JSONWIZARD_TR_H $$QMLWIZARD_TR_H $$QTQUICKWIZARD_TR_H $$EXTERNALTOOLS_TR_H SNIPPETS_TR_H -ts $$files ts-all.depends = extract QMAKE_EXTRA_TARGETS += ts-all diff --git a/src/libs/timeline/qml/RangeDetails.qml b/src/libs/timeline/qml/RangeDetails.qml index 9b9ff77d7f..f47e9e4c04 100644 --- a/src/libs/timeline/qml/RangeDetails.qml +++ b/src/libs/timeline/qml/RangeDetails.qml @@ -50,7 +50,7 @@ Item { signal toggleSelectionLocked signal clearSelection - width: col.width + 25 + width: col.width + 20 height: hasContents ? contentArea.height + titleBar.height : 0 function hide() { @@ -75,9 +75,11 @@ Item { ListModel { id: eventInfo + property bool ready: false } function showInfo(model, item) { + eventInfo.ready = false; // make sure we don't accidentally save the old text for the new event noteEdit.focus = false; @@ -94,6 +96,7 @@ Item { eventInfo.append({content : eventData[k]}); } } + eventInfo.ready = true; hasContents = eventInfo.count > 0; var location = timelineModel.location(selectedItem) @@ -175,21 +178,20 @@ Item { y: 5 spacing: 5 columns: 2 - property int minimumWidth: { + property int minimumWidth: 150 + + onChildrenChanged: { // max(width of longest label * 2, 150) var result = 150; for (var i = 0; i < children.length; i += 2) result = Math.max(children[i].implicitWidth * 2 + spacing, result); - return result + 20; - } - - onMinimumWidthChanged: { + minimumWidth = result + 20; if (dragHandle.x < minimumWidth) dragHandle.x = minimumWidth; } Repeater { - model: eventInfo + model: eventInfo.ready ? eventInfo : 0 Detail { valueWidth: (dragHandle.x - col.minimumWidth / 2 - col.spacing) isLabel: index % 2 === 0 diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp index b70ea7b07c..468bccc348 100644 --- a/src/libs/utils/stylehelper.cpp +++ b/src/libs/utils/stylehelper.cpp @@ -114,16 +114,10 @@ QColor StyleHelper::m_requestedBaseColor; QColor StyleHelper::baseColor(bool lightColored) { + static const QColor windowColor = QApplication::palette().color(QPalette::Window); static const bool windowColorAsBase = creatorTheme()->flag(Theme::WindowColorAsBase); - if (windowColorAsBase) { - static const QColor windowColor = QApplication::palette().color(QPalette::Window); - return windowColor; - } - if (!lightColored) - return m_baseColor; - else - return m_baseColor.lighter(230); + return (lightColored || windowColorAsBase) ? windowColor : m_baseColor; } QColor StyleHelper::highlightColor(bool lightColored) diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h index ea69e2fae7..26e9098158 100644 --- a/src/libs/utils/theme/theme.h +++ b/src/libs/utils/theme/theme.h @@ -252,6 +252,7 @@ public: Welcome_DividerColor, Welcome_LinkColor, Welcome_HoverColor, + Welcome_DisabledLinkColor, /* Timeline Library */ Timeline_TextColor, diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index 05bea3a3cf..a6b22a7b19 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -326,7 +326,7 @@ void QtTestOutputReader::processPlainTextOutput(const QByteArray &outputLine) static QRegExp finish("^[*]{9} Finished testing of (.*) [*]{9}$"); static QRegExp result("^(PASS |FAIL! |XFAIL |XPASS |SKIP |BPASS |BFAIL |RESULT " - "|INFO |QWARN |WARNING|QDEBUG ): (.*)$"); + "|INFO |QWARN |WARNING|QDEBUG |QSYSTEM): (.*)$"); static QRegExp benchDetails("^\\s+([\\d,.]+ .* per iteration \\(total: [\\d,.]+, iterations: \\d+\\))$"); static QRegExp locationUnix("^ Loc: \\[(.*)\\]$"); diff --git a/src/plugins/autotest/testresult.cpp b/src/plugins/autotest/testresult.cpp index 96db2b10c6..b93aa50849 100644 --- a/src/plugins/autotest/testresult.cpp +++ b/src/plugins/autotest/testresult.cpp @@ -85,7 +85,7 @@ Result::Type TestResult::resultFromString(const QString &resultString) return Result::MessageWarn; if (resultString == "qfatal") return Result::MessageFatal; - if (resultString == "system") + if ((resultString == "system") || (resultString == "qsystem")) return Result::MessageSystem; if (resultString == "bpass") return Result::BlacklistedPass; diff --git a/src/plugins/autotest/testresultmodel.cpp b/src/plugins/autotest/testresultmodel.cpp index 94aa6d4c31..ce15f7ec9c 100644 --- a/src/plugins/autotest/testresultmodel.cpp +++ b/src/plugins/autotest/testresultmodel.cpp @@ -114,7 +114,6 @@ void TestResultItem::updateResult(bool &changed, Result::Type addedChildType) switch (addedChildType) { case Result::Fail: case Result::MessageFatal: - case Result::MessageSystem: case Result::UnexpectedPass: case Result::MessageTestCaseFail: newResult = (old == Result::MessageTestCaseSuccessWarn) ? Result::MessageTestCaseFailWarn @@ -125,6 +124,7 @@ void TestResultItem::updateResult(bool &changed, Result::Type addedChildType) break; case Result::ExpectedFail: case Result::MessageWarn: + case Result::MessageSystem: case Result::Skip: case Result::BlacklistedFail: case Result::BlacklistedPass: @@ -377,12 +377,16 @@ void TestResultFilterModel::toggleTestResultType(Result::Type type) m_enabled.remove(Result::MessageTestCaseEnd); if (type == Result::MessageDebug) m_enabled.remove(Result::MessageInfo); + if (type == Result::MessageWarn) + m_enabled.remove(Result::MessageSystem); } else { m_enabled.insert(type); if (type == Result::MessageInternal) m_enabled.insert(Result::MessageTestCaseEnd); if (type == Result::MessageDebug) m_enabled.insert(Result::MessageInfo); + if (type == Result::MessageWarn) + m_enabled.insert(Result::MessageSystem); } invalidateFilter(); } diff --git a/src/plugins/bookmarks/bookmarkfilter.h b/src/plugins/bookmarks/bookmarkfilter.h index e665cc2f5d..ff378d9a90 100644 --- a/src/plugins/bookmarks/bookmarkfilter.h +++ b/src/plugins/bookmarks/bookmarkfilter.h @@ -34,6 +34,7 @@ class BookmarkManager; class BookmarkFilter : public Core::ILocatorFilter { + Q_OBJECT public: explicit BookmarkFilter(BookmarkManager *manager); QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future, diff --git a/src/plugins/clangcodemodel/clangrefactoringengine.cpp b/src/plugins/clangcodemodel/clangrefactoringengine.cpp index c9ddef546f..ff082e0a7a 100644 --- a/src/plugins/clangcodemodel/clangrefactoringengine.cpp +++ b/src/plugins/clangcodemodel/clangrefactoringengine.cpp @@ -47,32 +47,30 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data, if (!processor) return defaultCallback(); - QFuture<CppTools::CursorInfo> future = processor->requestLocalReferences(data.cursor()); - if (future.isCanceled()) + QFuture<CppTools::CursorInfo> cursorFuture = processor->requestLocalReferences(data.cursor()); + if (cursorFuture.isCanceled()) return defaultCallback(); - // QFuture::waitForFinished seems to block completely, not even - // allowing to process events from QLocalSocket. - while (!future.isFinished()) { - if (future.isCanceled()) + QObject::connect(&m_watcher, &FutureCursorWatcher::finished, [=]() { + const CppTools::CursorInfo info = m_watcher.result(); + if (info.useRanges.empty()) return defaultCallback(); - QTC_ASSERT(startRevision == data.cursor().document()->revision(), return;); - QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); - } + QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor()); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, + info.useRanges.first().length); + const QString symbolName = cursor.selectedText(); + ClangBackEnd::SourceLocationsContainer container; + for (auto& use : info.useRanges) { + container.insertSourceLocation(ClangBackEnd::FilePathId(), + use.line, + use.column, + use.length); + } + renameSymbolsCallback(symbolName, container, data.cursor().document()->revision()); + }); - const CppTools::CursorInfo info = future.result(); - if (info.useRanges.empty()) - return defaultCallback(); - - QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor()); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, - info.useRanges.first().length); - const QString symbolName = cursor.selectedText(); - ClangBackEnd::SourceLocationsContainer container; - for (auto& use : info.useRanges) - container.insertSourceLocation(ClangBackEnd::FilePathId(), use.line, use.column, use.length); - renameSymbolsCallback(symbolName, container, data.cursor().document()->revision()); + m_watcher.setFuture(cursorFuture); } } diff --git a/src/plugins/clangcodemodel/clangrefactoringengine.h b/src/plugins/clangcodemodel/clangrefactoringengine.h index 300ca4e72f..10ad96aa0d 100644 --- a/src/plugins/clangcodemodel/clangrefactoringengine.h +++ b/src/plugins/clangcodemodel/clangrefactoringengine.h @@ -26,6 +26,9 @@ #pragma once #include <cpptools/refactoringengineinterface.h> +#include <cpptools/cppcursorinfo.h> + +#include <QFutureWatcher> namespace ClangBackEnd { class RefactoringClientInterface; @@ -49,6 +52,10 @@ public: { return Link(); } + +private: + using FutureCursorWatcher = QFutureWatcher<CppTools::CursorInfo>; + FutureCursorWatcher m_watcher; }; } // namespace ClangRefactoring diff --git a/src/plugins/coreplugin/editormanager/documentmodel.cpp b/src/plugins/coreplugin/editormanager/documentmodel.cpp index fb6bf68949..fae56815ca 100644 --- a/src/plugins/coreplugin/editormanager/documentmodel.cpp +++ b/src/plugins/coreplugin/editormanager/documentmodel.cpp @@ -76,9 +76,8 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry) fixedPath = DocumentManager::filePathKey(fileName.toString(), DocumentManager::ResolveLinks); // replace a non-loaded entry (aka 'suspended') if possible - int previousIndex = indexOfFilePath(fileName); - if (previousIndex >= 0) { - DocumentModel::Entry *previousEntry = m_entries.at(previousIndex); + DocumentModel::Entry *previousEntry = DocumentModel::entryForFilePath(fileName); + if (previousEntry) { const bool replace = !entry->isSuspended && previousEntry->isSuspended; if (replace) { previousEntry->isSuspended = false; @@ -180,13 +179,16 @@ QIcon DocumentModelPrivate::lockedIcon() return icon; } -int DocumentModelPrivate::indexOfFilePath(const Utils::FileName &filePath) const +Utils::optional<int> DocumentModelPrivate::indexOfFilePath(const Utils::FileName &filePath) const { if (filePath.isEmpty()) - return -1; + return Utils::nullopt; const QString fixedPath = DocumentManager::filePathKey(filePath.toString(), DocumentManager::ResolveLinks); - return m_entries.indexOf(m_entryByFixedPath.value(fixedPath)); + const int index = m_entries.indexOf(m_entryByFixedPath.value(fixedPath)); + if (index < 0) + return Utils::nullopt; + return index; } void DocumentModelPrivate::removeDocument(int idx) @@ -210,11 +212,14 @@ void DocumentModelPrivate::removeDocument(int idx) delete entry; } -int DocumentModelPrivate::indexOfDocument(IDocument *document) const +Utils::optional<int> DocumentModelPrivate::indexOfDocument(IDocument *document) const { - return Utils::indexOf(m_entries, [&document](DocumentModel::Entry *entry) { + const int index = Utils::indexOf(m_entries, [&document](DocumentModel::Entry *entry) { return entry->document == document; }); + if (index < 0) + return Utils::nullopt; + return index; } Qt::ItemFlags DocumentModelPrivate::flags(const QModelIndex &index) const @@ -292,14 +297,14 @@ void DocumentModelPrivate::itemChanged() { IDocument *document = qobject_cast<IDocument *>(sender()); - int idx = indexOfDocument(document); - if (idx < 0) + const Utils::optional<int> idx = indexOfDocument(document); + if (!idx) return; const QString fileName = document->filePath().toString(); QString fixedPath; if (!fileName.isEmpty()) fixedPath = DocumentManager::filePathKey(fileName, DocumentManager::ResolveLinks); - DocumentModel::Entry *entry = m_entries.at(idx); + DocumentModel::Entry *entry = m_entries.at(idx.value()); bool found = false; // The entry's fileName might have changed, so find the previous fileName that was associated // with it and remove it, then add the new fileName. @@ -316,8 +321,8 @@ void DocumentModelPrivate::itemChanged() } if (!found && !fixedPath.isEmpty()) m_entryByFixedPath[fixedPath] = entry; - if (!disambiguateDisplayNames(m_entries.at(idx))) { - QModelIndex mindex = index(idx + 1/*<no document>*/, 0); + if (!disambiguateDisplayNames(m_entries.at(idx.value()))) { + QModelIndex mindex = index(idx.value() + 1/*<no document>*/, 0); emit dataChanged(mindex, mindex); } } @@ -507,11 +512,16 @@ QList<IEditor *> DocumentModel::editorsForDocuments(const QList<IDocument *> &do return result; } -int DocumentModel::indexOfDocument(IDocument *document) +Utils::optional<int> DocumentModel::indexOfDocument(IDocument *document) { return d->indexOfDocument(document); } +Utils::optional<int> DocumentModel::indexOfFilePath(const Utils::FileName &filePath) +{ + return d->indexOfFilePath(filePath); +} + DocumentModel::Entry *DocumentModel::entryForDocument(IDocument *document) { return Utils::findOrDefault(d->m_entries, @@ -520,10 +530,10 @@ DocumentModel::Entry *DocumentModel::entryForDocument(IDocument *document) DocumentModel::Entry *DocumentModel::entryForFilePath(const Utils::FileName &filePath) { - const int index = d->indexOfFilePath(filePath); - if (index < 0) + const Utils::optional<int> index = d->indexOfFilePath(filePath); + if (!index) return nullptr; - return d->m_entries.at(index); + return d->m_entries.at(index.value()); } QList<IDocument *> DocumentModel::openedDocuments() @@ -533,10 +543,10 @@ QList<IDocument *> DocumentModel::openedDocuments() IDocument *DocumentModel::documentForFilePath(const QString &filePath) { - const int index = d->indexOfFilePath(Utils::FileName::fromString(filePath)); - if (index < 0) - return 0; - return d->m_entries.at(index)->document; + const Utils::optional<int> index = d->indexOfFilePath(Utils::FileName::fromString(filePath)); + if (!index) + return nullptr; + return d->m_entries.at(index.value())->document; } QList<IEditor *> DocumentModel::editorsForFilePath(const QString &filePath) @@ -560,11 +570,14 @@ int DocumentModel::entryCount() return d->m_entries.count(); } -int DocumentModel::rowOfDocument(IDocument *document) +Utils::optional<int> DocumentModel::rowOfDocument(IDocument *document) { if (!document) return 0 /*<no document>*/; - return indexOfDocument(document) + 1/*<no document>*/; + const Utils::optional<int> index = indexOfDocument(document); + if (index) + return index.value() + 1/*correction for <no document>*/; + return Utils::nullopt; } QList<DocumentModel::Entry *> DocumentModel::entries() diff --git a/src/plugins/coreplugin/editormanager/documentmodel.h b/src/plugins/coreplugin/editormanager/documentmodel.h index e0b14ed3aa..09bb465272 100644 --- a/src/plugins/coreplugin/editormanager/documentmodel.h +++ b/src/plugins/coreplugin/editormanager/documentmodel.h @@ -29,6 +29,7 @@ #include "../id.h" #include <utils/fileutils.h> +#include <utils/optional.h> QT_BEGIN_NAMESPACE class QAbstractItemModel; @@ -63,11 +64,12 @@ public: }; static Entry *entryAtRow(int row); - static int rowOfDocument(IDocument *document); + static Utils::optional<int> rowOfDocument(IDocument *document); static int entryCount(); static QList<Entry *> entries(); - static int indexOfDocument(IDocument *document); + static Utils::optional<int> indexOfDocument(IDocument *document); + static Utils::optional<int> indexOfFilePath(const Utils::FileName &filePath); static Entry *entryForDocument(IDocument *document); static Entry *entryForFilePath(const Utils::FileName &filePath); static QList<IDocument *> openedDocuments(); diff --git a/src/plugins/coreplugin/editormanager/documentmodel_p.h b/src/plugins/coreplugin/editormanager/documentmodel_p.h index 98223e63ed..ae6ff016fa 100644 --- a/src/plugins/coreplugin/editormanager/documentmodel_p.h +++ b/src/plugins/coreplugin/editormanager/documentmodel_p.h @@ -58,8 +58,8 @@ public: void addEntry(DocumentModel::Entry *entry); void removeDocument(int idx); - int indexOfFilePath(const Utils::FileName &filePath) const; - int indexOfDocument(IDocument *document) const; + Utils::optional<int> indexOfFilePath(const Utils::FileName &filePath) const; + Utils::optional<int> indexOfDocument(IDocument *document) const; bool disambiguateDisplayNames(DocumentModel::Entry *entry); diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp index b46c71f772..4d6dc67623 100644 --- a/src/plugins/coreplugin/editormanager/editorview.cpp +++ b/src/plugins/coreplugin/editormanager/editorview.cpp @@ -268,11 +268,10 @@ void EditorView::updateEditorHistory(IEditor *editor, QList<EditLocation> &histo location.state = QVariant(state); for (int i = 0; i < history.size(); ++i) { - if (history.at(i).document == 0 - || history.at(i).document == document - ){ + const EditLocation &item = history.at(i); + if (item.document == document + || !DocumentModel::indexOfFilePath(FileName::fromString(item.fileName))) { history.removeAt(i--); - continue; } } history.prepend(location); diff --git a/src/plugins/coreplugin/editormanager/openeditorsview.cpp b/src/plugins/coreplugin/editormanager/openeditorsview.cpp index 72622a4a75..1a7e0d618c 100644 --- a/src/plugins/coreplugin/editormanager/openeditorsview.cpp +++ b/src/plugins/coreplugin/editormanager/openeditorsview.cpp @@ -30,6 +30,7 @@ #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/command.h> +#include <utils/qtcassert.h> #include <QApplication> #include <QMenu> @@ -70,15 +71,15 @@ OpenEditorsWidget::~OpenEditorsWidget() void OpenEditorsWidget::updateCurrentItem(IEditor *editor) { - IDocument *document = editor ? editor->document() : 0; - QModelIndex index = m_model->index(DocumentModel::indexOfDocument(document), 0); - if (!index.isValid()) { + if (!editor) { clearSelection(); return; } - setCurrentIndex(index); + const Utils::optional<int> index = DocumentModel::indexOfDocument(editor->document()); + if (QTC_GUARD(index)) + setCurrentIndex(m_model->index(index.value(), 0)); selectionModel()->select(currentIndex(), - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); scrollTo(currentIndex()); } diff --git a/src/plugins/coreplugin/editortoolbar.cpp b/src/plugins/coreplugin/editortoolbar.cpp index b41245cd25..3383325e4c 100644 --- a/src/plugins/coreplugin/editortoolbar.cpp +++ b/src/plugins/coreplugin/editortoolbar.cpp @@ -320,7 +320,9 @@ void EditorToolBar::setMenuProvider(const EditorToolBar::MenuProvider &provider) void EditorToolBar::setCurrentEditor(IEditor *editor) { IDocument *document = editor ? editor->document() : 0; - d->m_editorList->setCurrentIndex(DocumentModel::rowOfDocument(document)); + const Utils::optional<int> index = DocumentModel::rowOfDocument(document); + if (QTC_GUARD(index)) + d->m_editorList->setCurrentIndex(index.value()); // If we never added the toolbar from the editor, we will never change // the editor, so there's no need to update the toolbar either. @@ -332,8 +334,11 @@ void EditorToolBar::setCurrentEditor(IEditor *editor) void EditorToolBar::updateEditorListSelection(IEditor *newSelection) { - if (newSelection) - d->m_editorList->setCurrentIndex(DocumentModel::rowOfDocument(newSelection->document())); + if (newSelection) { + const Utils::optional<int> index = DocumentModel::rowOfDocument(newSelection->document()); + if (QTC_GUARD(index)) + d->m_editorList->setCurrentIndex(index.value()); + } } void EditorToolBar::changeActiveEditor(int row) @@ -403,7 +408,9 @@ void EditorToolBar::updateDocumentStatus(IDocument *document) return; } - d->m_editorList->setCurrentIndex(DocumentModel::rowOfDocument(document)); + const Utils::optional<int> index = DocumentModel::rowOfDocument(document); + if (QTC_GUARD(index)) + d->m_editorList->setCurrentIndex(index.value()); if (document->filePath().isEmpty()) { d->m_lockButton->setIcon(QIcon()); diff --git a/src/plugins/coreplugin/find/findtoolbar.cpp b/src/plugins/coreplugin/find/findtoolbar.cpp index 5ca9833343..793b2990f8 100644 --- a/src/plugins/coreplugin/find/findtoolbar.cpp +++ b/src/plugins/coreplugin/find/findtoolbar.cpp @@ -973,16 +973,12 @@ void FindToolBar::setBackward(bool backward) void FindToolBar::setLightColoredIcon(bool lightColored) { if (lightColored) { - m_ui.findNextButton->setIcon(QIcon()); - m_ui.findNextButton->setArrowType(Qt::RightArrow); - m_ui.findPreviousButton->setIcon(QIcon()); - m_ui.findPreviousButton->setArrowType(Qt::LeftArrow); + m_ui.findNextButton->setIcon(Utils::Icons::NEXT.icon()); + m_ui.findPreviousButton->setIcon(Utils::Icons::PREV.icon()); m_ui.close->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon()); } else { m_ui.findNextButton->setIcon(Utils::Icons::NEXT_TOOLBAR.icon()); - m_ui.findNextButton->setArrowType(Qt::NoArrow); m_ui.findPreviousButton->setIcon(Utils::Icons::PREV_TOOLBAR.icon()); - m_ui.findPreviousButton->setArrowType(Qt::NoArrow); m_ui.close->setIcon(Utils::Icons::CLOSE_TOOLBAR.icon()); } } diff --git a/src/plugins/coreplugin/helpmanager.cpp b/src/plugins/coreplugin/helpmanager.cpp index 76d5aa787f..438314e7a1 100644 --- a/src/plugins/coreplugin/helpmanager.cpp +++ b/src/plugins/coreplugin/helpmanager.cpp @@ -157,6 +157,7 @@ void HelpManager::registerDocumentationNow(QFutureInterface<bool> &futureInterfa QHelpEngineCore helpEngine(collectionFilePath()); bool docsChanged = false; + QStringList nameSpaces = d->m_helpEngine->registeredDocumentations(); for (const QString &file : files) { if (futureInterface.isCanceled()) break; @@ -164,8 +165,9 @@ void HelpManager::registerDocumentationNow(QFutureInterface<bool> &futureInterfa const QString &nameSpace = helpEngine.namespaceName(file); if (nameSpace.isEmpty()) continue; - if (!helpEngine.registeredDocumentations().contains(nameSpace)) { + if (!nameSpaces.contains(nameSpace)) { if (helpEngine.registerDocumentation(file)) { + nameSpaces.append(nameSpace); docsChanged = true; } else { qWarning() << "Error registering namespace '" << nameSpace diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp index 4a68fa4110..add7b8c753 100644 --- a/src/plugins/coreplugin/manhattanstyle.cpp +++ b/src/plugins/coreplugin/manhattanstyle.cpp @@ -288,6 +288,12 @@ void ManhattanStyle::polish(QWidget *widget) } else if (qobject_cast<QStatusBar*>(widget)) { widget->setFixedHeight(StyleHelper::navigationWidgetHeight() + 2); } else if (qobject_cast<QComboBox*>(widget)) { + const bool isLightColored = lightColored(widget); + QPalette palette = panelPalette(widget->palette(), isLightColored); + if (!isLightColored) + palette.setBrush(QPalette::All, QPalette::Foreground, + creatorTheme()->color(Theme::ComboBoxTextColor)); + widget->setPalette(palette); widget->setMaximumHeight(StyleHelper::navigationWidgetHeight() - 2); widget->setAttribute(Qt::WA_Hover); } @@ -730,9 +736,9 @@ void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *opt painter->setPen(StyleHelper::toolBarDropShadowColor()); painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text); } - painter->setPen(creatorTheme()->color((option->state & State_Enabled) - ? Theme::ComboBoxTextColor - : Theme::IconsDisabledColor)); + painter->setPen((option->state & State_Enabled) + ? option->palette.color(QPalette::Foreground) + : creatorTheme()->color(Theme::IconsDisabledColor)); painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text); painter->restore(); diff --git a/src/plugins/coreplugin/menubarfilter.h b/src/plugins/coreplugin/menubarfilter.h index 9251df7da2..c7b137e6a9 100644 --- a/src/plugins/coreplugin/menubarfilter.h +++ b/src/plugins/coreplugin/menubarfilter.h @@ -37,6 +37,7 @@ namespace Internal { class MenuBarFilter : public ILocatorFilter { + Q_OBJECT public: MenuBarFilter(); diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp index fe66ed5c7d..e7705f7460 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp @@ -255,7 +255,13 @@ void ClangDiagnosticConfigsWidget::syncOtherWidgetsToComboBox() ? m_notAcceptedOptions.value(config.id()) : config.clangOptions().join(QLatin1Char(' ')); setDiagnosticOptions(options); - m_clangBaseChecks->diagnosticOptionsTextEdit->setReadOnly(config.isReadOnly()); + m_clangBaseChecksWidget->setEnabled(!config.isReadOnly()); + + if (config.isReadOnly()) { + m_ui->infoIcon->setPixmap(Utils::Icons::INFO.pixmap()); + m_ui->infoLabel->setText(tr("Copy this configuration to customize it.")); + m_ui->infoLabel->setStyleSheet(QString()); + } syncClangTidyWidgets(config); syncClazyWidgets(config); @@ -326,14 +332,13 @@ void ClangDiagnosticConfigsWidget::setDiagnosticOptions(const QString &options) { if (options != m_clangBaseChecks->diagnosticOptionsTextEdit->document()->toPlainText()) { disconnectDiagnosticOptionsChanged(); - m_clangBaseChecks->diagnosticOptionsTextEdit->document()->setPlainText(options); - const QString errorMessage - = validateDiagnosticOptions(normalizeDiagnosticInputOptions(options)); - updateValidityWidgets(errorMessage); - connectDiagnosticOptionsChanged(); } + + const QString errorMessage + = validateDiagnosticOptions(normalizeDiagnosticInputOptions(options)); + updateValidityWidgets(errorMessage); } void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMessage) @@ -350,9 +355,9 @@ void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMes styleSheet = "color: red;"; } - m_ui->validationResultIcon->setPixmap(icon->pixmap()); - m_ui->validationResultLabel->setText(validationResult); - m_ui->validationResultLabel->setStyleSheet(styleSheet); + m_ui->infoIcon->setPixmap(icon->pixmap()); + m_ui->infoLabel->setText(validationResult); + m_ui->infoLabel->setStyleSheet(styleSheet); } void ClangDiagnosticConfigsWidget::connectClangTidyItemChanged() diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.ui b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui index fdb0d07262..5e064be723 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigswidget.ui +++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui @@ -47,16 +47,16 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QLabel" name="validationResultIcon"> + <widget class="QLabel" name="infoIcon"> <property name="text"> - <string>ValidationIcon</string> + <string>InfoIcon</string> </property> </widget> </item> <item> - <widget class="QLabel" name="validationResultLabel"> + <widget class="QLabel" name="infoLabel"> <property name="text"> - <string>ValidationText</string> + <string>InfoText</string> </property> </widget> </item> diff --git a/src/plugins/diffeditor/diffeditor.cpp b/src/plugins/diffeditor/diffeditor.cpp index 0fbb63f27b..c054622389 100644 --- a/src/plugins/diffeditor/diffeditor.cpp +++ b/src/plugins/diffeditor/diffeditor.cpp @@ -289,12 +289,12 @@ DiffEditor::DiffEditor() connect(m_viewSwitcherAction, &QAction::triggered, this, [this]() { showDiffView(nextView()); }); } -void DiffEditor::setDocument(QSharedPointer<DiffEditorDocument>(doc)) +void DiffEditor::setDocument(QSharedPointer<DiffEditorDocument> doc) { QTC_ASSERT(m_document.isNull(), return); QTC_ASSERT(doc, return); - m_document = QSharedPointer<DiffEditorDocument>(doc); + m_document = doc; connect(m_descriptionWidget, &DescriptionEditorWidget::requestBranchList, m_document.data(), &DiffEditorDocument::requestMoreInformation); diff --git a/src/plugins/diffeditor/diffeditor.h b/src/plugins/diffeditor/diffeditor.h index 4522a786a3..53032827be 100644 --- a/src/plugins/diffeditor/diffeditor.h +++ b/src/plugins/diffeditor/diffeditor.h @@ -25,8 +25,6 @@ #pragma once -#include "diffeditorcontroller.h" - #include <coreplugin/editormanager/ieditor.h> #include <coreplugin/idocument.h> #include <utils/guard.h> diff --git a/src/plugins/diffeditor/diffeditorcontroller.cpp b/src/plugins/diffeditor/diffeditorcontroller.cpp index c64da4562d..bb2738b985 100644 --- a/src/plugins/diffeditor/diffeditorcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorcontroller.cpp @@ -71,9 +71,10 @@ QString DiffEditorController::revisionFromDescription() const return m_document->description().mid(7, 12); } -QString DiffEditorController::makePatch(PatchOptions options) const +QString DiffEditorController::makePatch(int fileIndex, int chunkIndex, + PatchOptions options) const { - return m_document->makePatch(m_diffFileIndex, m_chunkIndex, + return m_document->makePatch(fileIndex, chunkIndex, options & Revert, options & AddPrefix); } @@ -152,11 +153,27 @@ void DiffEditorController::reloadFinished(bool success) m_isReloading = false; } -void DiffEditorController::requestChunkActions(QMenu *menu, int diffFileIndex, int chunkIndex) +void DiffEditorController::requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex) { - m_diffFileIndex = diffFileIndex; - m_chunkIndex = chunkIndex; - emit chunkActionsRequested(menu, diffFileIndex >= 0 && chunkIndex >= 0); + emit chunkActionsRequested(menu, fileIndex, chunkIndex); +} + +bool DiffEditorController::chunkExists(int fileIndex, int chunkIndex) const +{ + if (!m_document) + return false; + + if (fileIndex < 0 || chunkIndex < 0) + return false; + + if (fileIndex >= m_document->diffFiles().count()) + return false; + + const FileData fileData = m_document->diffFiles().at(fileIndex); + if (chunkIndex >= fileData.chunks.count()) + return false; + + return true; } } // namespace DiffEditor diff --git a/src/plugins/diffeditor/diffeditorcontroller.h b/src/plugins/diffeditor/diffeditorcontroller.h index ebe1151ce1..e5d5ca7418 100644 --- a/src/plugins/diffeditor/diffeditorcontroller.h +++ b/src/plugins/diffeditor/diffeditorcontroller.h @@ -59,16 +59,18 @@ public: AddPrefix = 2 }; Q_DECLARE_FLAGS(PatchOptions, PatchOption) - QString makePatch(PatchOptions options) const; + QString makePatch(int fileIndex, int chunkIndex, PatchOptions options) const; static Core::IDocument *findOrCreateDocument(const QString &vcsId, const QString &displayName); static DiffEditorController *controller(Core::IDocument *document); void branchesReceived(const QString &branches); + void requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex); + bool chunkExists(int fileIndex, int chunkIndex) const; signals: - void chunkActionsRequested(QMenu *menu, bool isValid); + void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex); void requestInformationForCommit(const QString &revision); protected: @@ -87,15 +89,14 @@ protected: private: void requestMoreInformation(); - void requestChunkActions(QMenu *menu, int diffFileIndex, int chunkIndex); Internal::DiffEditorDocument *const m_document; bool m_isReloading = false; - int m_diffFileIndex = -1; - int m_chunkIndex = -1; friend class Internal::DiffEditorDocument; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(DiffEditorController::PatchOptions) + } // namespace DiffEditor diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp index c1896f969b..0845f3ef03 100644 --- a/src/plugins/diffeditor/diffeditordocument.cpp +++ b/src/plugins/diffeditor/diffeditordocument.cpp @@ -71,8 +71,6 @@ void DiffEditorDocument::setController(DiffEditorController *controller) m_controller = controller; if (m_controller) { - connect(this, &DiffEditorDocument::chunkActionsRequested, - m_controller, &DiffEditorController::requestChunkActions); connect(this, &DiffEditorDocument::requestMoreInformation, m_controller, &DiffEditorController::requestMoreInformation); } diff --git a/src/plugins/diffeditor/diffeditordocument.h b/src/plugins/diffeditor/diffeditordocument.h index db0d3f04a3..2a5293dfaf 100644 --- a/src/plugins/diffeditor/diffeditordocument.h +++ b/src/plugins/diffeditor/diffeditordocument.h @@ -90,7 +90,6 @@ signals: void temporaryStateChanged(); void documentChanged(); void descriptionChanged(); - void chunkActionsRequested(QMenu *menu, int diffFileIndex, int chunkIndex); void requestMoreInformation(); private: diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp index 66977ec065..c4a826bfe9 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp @@ -25,6 +25,7 @@ #include "diffeditorwidgetcontroller.h" #include "diffeditorconstants.h" +#include "diffeditorcontroller.h" #include "diffeditordocument.h" #include <coreplugin/documentmanager.h> @@ -122,11 +123,14 @@ void DiffEditorWidgetController::hideProgress() m_progressIndicator->hide(); } -void DiffEditorWidgetController::patch(bool revert) +void DiffEditorWidgetController::patch(bool revert, int fileIndex, int chunkIndex) { if (!m_document) return; + if (!chunkExists(fileIndex, chunkIndex)) + return; + const QString title = revert ? tr("Revert Chunk") : tr("Apply Chunk"); const QString question = revert ? tr("Would you like to revert the chunk?") @@ -138,7 +142,7 @@ void DiffEditorWidgetController::patch(bool revert) return; } - const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex); + const FileData fileData = m_contextFileData.at(fileIndex); const QString fileName = revert ? fileData.rightFileInfo.fileName : fileData.leftFileInfo.fileName; @@ -154,7 +158,7 @@ void DiffEditorWidgetController::patch(bool revert) if (patchBehaviour == DiffFileInfo::PatchFile) { const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0; - const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, revert); + const QString patch = m_document->makePatch(fileIndex, chunkIndex, revert); if (patch.isEmpty()) return; @@ -179,8 +183,8 @@ void DiffEditorWidgetController::patch(bool revert) 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()); + const QString patch = m_document->makePatch(fileIndex, + chunkIndex, revert, false, QFileInfo(contentsCopyFileName).fileName()); if (patch.isEmpty()) return; @@ -218,64 +222,59 @@ void DiffEditorWidgetController::setFontSettings(const FontSettings &fontSetting m_rightCharFormat = fontSettings.toTextCharFormat(C_DIFF_DEST_CHAR); } -void DiffEditorWidgetController::addCodePasterAction(QMenu *menu) +void DiffEditorWidgetController::addCodePasterAction(QMenu *menu, int fileIndex, int chunkIndex) { if (ExtensionSystem::PluginManager::getObject<CodePaster::Service>()) { // optional code pasting service QAction *sendChunkToCodePasterAction = menu->addAction(tr("Send Chunk to CodePaster...")); - connect(sendChunkToCodePasterAction, &QAction::triggered, - this, &DiffEditorWidgetController::slotSendChunkToCodePaster); + connect(sendChunkToCodePasterAction, &QAction::triggered, [this, fileIndex, chunkIndex]() { + sendChunkToCodePaster(fileIndex, chunkIndex); + }); } } -bool DiffEditorWidgetController::setAndVerifyIndexes(QMenu *menu, - int diffFileIndex, int chunkIndex) +bool DiffEditorWidgetController::chunkExists(int fileIndex, int chunkIndex) const { if (!m_document) return false; - m_contextMenuFileIndex = diffFileIndex; - m_contextMenuChunkIndex = chunkIndex; - - if (m_contextMenuFileIndex < 0 || m_contextMenuChunkIndex < 0) - return false; - - if (m_contextMenuFileIndex >= m_contextFileData.count()) - return false; - - const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex); - if (m_contextMenuChunkIndex >= fileData.chunks.count()) - return false; - - m_document->chunkActionsRequested(menu, diffFileIndex, chunkIndex); + if (DiffEditorController *controller = m_document->controller()) + return controller->chunkExists(fileIndex, chunkIndex); - return true; + return false; } -bool DiffEditorWidgetController::fileNamesAreDifferent() const +bool DiffEditorWidgetController::fileNamesAreDifferent(int fileIndex) const { - const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex); + const FileData fileData = m_contextFileData.at(fileIndex); return fileData.leftFileInfo.fileName != fileData.rightFileInfo.fileName; } -void DiffEditorWidgetController::addApplyAction(QMenu *menu, int diffFileIndex, - int chunkIndex) +void DiffEditorWidgetController::addApplyAction(QMenu *menu, int fileIndex, int chunkIndex) { QAction *applyAction = menu->addAction(tr("Apply Chunk...")); - connect(applyAction, &QAction::triggered, this, &DiffEditorWidgetController::slotApplyChunk); - applyAction->setEnabled(setAndVerifyIndexes(menu, diffFileIndex, chunkIndex) - && fileNamesAreDifferent()); + connect(applyAction, &QAction::triggered, [this, fileIndex, chunkIndex]() { + patch(false, fileIndex, chunkIndex); + }); + applyAction->setEnabled(chunkExists(fileIndex, chunkIndex) && fileNamesAreDifferent(fileIndex)); } -void DiffEditorWidgetController::addRevertAction(QMenu *menu, int diffFileIndex, - int chunkIndex) +void DiffEditorWidgetController::addRevertAction(QMenu *menu, int fileIndex, int chunkIndex) { QAction *revertAction = menu->addAction(tr("Revert Chunk...")); - connect(revertAction, &QAction::triggered, this, &DiffEditorWidgetController::slotRevertChunk); - revertAction->setEnabled(setAndVerifyIndexes(menu, diffFileIndex, chunkIndex)); + connect(revertAction, &QAction::triggered, [this, fileIndex, chunkIndex]() { + patch(true, fileIndex, chunkIndex); + }); + revertAction->setEnabled(chunkExists(fileIndex, chunkIndex)); } -void DiffEditorWidgetController::slotSendChunkToCodePaster() +void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int chunkIndex) +{ + if (DiffEditorController *controller = m_document->controller()) + controller->requestChunkActions(menu, fileIndex, chunkIndex); +} + +void DiffEditorWidgetController::sendChunkToCodePaster(int fileIndex, int chunkIndex) { if (!m_document) return; @@ -284,7 +283,7 @@ void DiffEditorWidgetController::slotSendChunkToCodePaster() auto pasteService = ExtensionSystem::PluginManager::getObject<CodePaster::Service>(); QTC_ASSERT(pasteService, return); - const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false); + const QString patch = m_document->makePatch(fileIndex, chunkIndex, false); if (patch.isEmpty()) return; @@ -292,15 +291,5 @@ void DiffEditorWidgetController::slotSendChunkToCodePaster() pasteService->postText(patch, Constants::DIFF_EDITOR_MIMETYPE); } -void DiffEditorWidgetController::slotApplyChunk() -{ - patch(false); -} - -void DiffEditorWidgetController::slotRevertChunk() -{ - patch(true); -} - } // namespace Internal } // namespace DiffEditor diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.h b/src/plugins/diffeditor/diffeditorwidgetcontroller.h index f5b605936c..c0c1be9548 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.h +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.h @@ -52,13 +52,13 @@ public: void setDocument(DiffEditorDocument *document); DiffEditorDocument *document() const; - void patch(bool revert); void jumpToOriginalFile(const QString &fileName, int lineNumber, int columnNumber); void setFontSettings(const TextEditor::FontSettings &fontSettings); - void addCodePasterAction(QMenu *menu); - void addApplyAction(QMenu *menu, int diffFileIndex, int chunkIndex); - void addRevertAction(QMenu *menu, int diffFileIndex, int chunkIndex); + void addCodePasterAction(QMenu *menu, int fileIndex, int chunkIndex); + void addApplyAction(QMenu *menu, int fileIndex, int chunkIndex); + void addRevertAction(QMenu *menu, int fileIndex, int chunkIndex); + void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex); bool m_ignoreCurrentIndexChange = false; QList<FileData> m_contextFileData; // ultimate data to be shown @@ -71,11 +71,10 @@ public: QTextCharFormat m_rightCharFormat; private: - void slotSendChunkToCodePaster(); - void slotApplyChunk(); - void slotRevertChunk(); - bool setAndVerifyIndexes(QMenu *menu, int diffFileIndex, int chunkIndex); - bool fileNamesAreDifferent() const; + void patch(bool revert, int fileIndex, int chunkIndex); + void sendChunkToCodePaster(int fileIndex, int chunkIndex); + bool chunkExists(int fileIndex, int chunkIndex) const; + bool fileNamesAreDifferent(int fileIndex) const; void scheduleShowProgress(); void showProgress(); @@ -85,9 +84,6 @@ private: DiffEditorDocument *m_document = nullptr; - int m_contextMenuFileIndex = -1; - int m_contextMenuChunkIndex = -1; - Utils::ProgressIndicator *m_progressIndicator = nullptr; QTimer m_timer; }; diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp index f42acfe8da..81942a9a66 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp @@ -1059,59 +1059,79 @@ void SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested( } void SideBySideDiffEditorWidget::slotLeftContextMenuRequested(QMenu *menu, - int diffFileIndex, + int fileIndex, int chunkIndex) { menu->addSeparator(); - m_controller.addCodePasterAction(menu); - m_controller.addApplyAction(menu, diffFileIndex, chunkIndex); + m_controller.addCodePasterAction(menu, fileIndex, chunkIndex); + m_controller.addApplyAction(menu, fileIndex, chunkIndex); + m_controller.addExtraActions(menu, fileIndex, chunkIndex); } void SideBySideDiffEditorWidget::slotRightContextMenuRequested(QMenu *menu, - int diffFileIndex, + int fileIndex, int chunkIndex) { menu->addSeparator(); - m_controller.addCodePasterAction(menu); - m_controller.addRevertAction(menu, diffFileIndex, chunkIndex); + m_controller.addCodePasterAction(menu, fileIndex, chunkIndex); + m_controller.addRevertAction(menu, fileIndex, chunkIndex); + m_controller.addExtraActions(menu, fileIndex, chunkIndex); } void SideBySideDiffEditorWidget::leftVSliderChanged() { + if (m_controller.m_ignoreCurrentIndexChange) + return; + m_rightEditor->verticalScrollBar()->setValue(m_leftEditor->verticalScrollBar()->value()); } void SideBySideDiffEditorWidget::rightVSliderChanged() { + if (m_controller.m_ignoreCurrentIndexChange) + return; + m_leftEditor->verticalScrollBar()->setValue(m_rightEditor->verticalScrollBar()->value()); } void SideBySideDiffEditorWidget::leftHSliderChanged() { + if (m_controller.m_ignoreCurrentIndexChange) + return; + if (m_horizontalSync) m_rightEditor->horizontalScrollBar()->setValue(m_leftEditor->horizontalScrollBar()->value()); } void SideBySideDiffEditorWidget::rightHSliderChanged() { + if (m_controller.m_ignoreCurrentIndexChange) + return; + if (m_horizontalSync) m_leftEditor->horizontalScrollBar()->setValue(m_rightEditor->horizontalScrollBar()->value()); } void SideBySideDiffEditorWidget::leftCursorPositionChanged() { + if (m_controller.m_ignoreCurrentIndexChange) + return; + + handlePositionChange(m_leftEditor, m_rightEditor); leftVSliderChanged(); leftHSliderChanged(); - handlePositionChange(m_leftEditor, m_rightEditor); } void SideBySideDiffEditorWidget::rightCursorPositionChanged() { + if (m_controller.m_ignoreCurrentIndexChange) + return; + + handlePositionChange(m_rightEditor, m_leftEditor); rightVSliderChanged(); rightHSliderChanged(); - handlePositionChange(m_rightEditor, m_leftEditor); } void SideBySideDiffEditorWidget::handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest) @@ -1129,6 +1149,8 @@ void SideBySideDiffEditorWidget::handlePositionChange(SideDiffEditorWidget *sour void SideBySideDiffEditorWidget::syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest) { + const int oldHSliderPos = dest->horizontalScrollBar()->value(); + const QTextCursor sourceCursor = source->textCursor(); const int sourceLine = sourceCursor.blockNumber(); const int sourceColumn = sourceCursor.positionInBlock(); @@ -1139,6 +1161,7 @@ void SideBySideDiffEditorWidget::syncCursor(SideDiffEditorWidget *source, SideDi destCursor.setPosition(destPosition); dest->setTextCursor(destCursor); + dest->horizontalScrollBar()->setValue(oldHSliderPos); } } // namespace Internal diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h index ba5c8ef550..c315cec975 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h @@ -85,9 +85,9 @@ private: int lineNumber, int columnNumber); void slotRightJumpToOriginalFileRequested(int diffFileIndex, int lineNumber, int columnNumber); - void slotLeftContextMenuRequested(QMenu *menu, int diffFileIndex, + void slotLeftContextMenuRequested(QMenu *menu, int fileIndex, int chunkIndex); - void slotRightContextMenuRequested(QMenu *menu, int diffFileIndex, + void slotRightContextMenuRequested(QMenu *menu, int fileIndex, int chunkIndex); void leftVSliderChanged(); void rightVSliderChanged(); diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp index dbea4cbfb9..54ca275a58 100644 --- a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp +++ b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp @@ -190,14 +190,15 @@ void UnifiedDiffEditorWidget::contextMenuEvent(QContextMenuEvent *e) } void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu, - int diffFileIndex, + int fileIndex, int chunkIndex) { menu->addSeparator(); - m_controller.addCodePasterAction(menu); - m_controller.addApplyAction(menu, diffFileIndex, chunkIndex); - m_controller.addRevertAction(menu, diffFileIndex, chunkIndex); + m_controller.addCodePasterAction(menu, fileIndex, chunkIndex); + m_controller.addApplyAction(menu, fileIndex, chunkIndex); + m_controller.addRevertAction(menu, fileIndex, chunkIndex); + m_controller.addExtraActions(menu, fileIndex, chunkIndex); } void UnifiedDiffEditorWidget::clear(const QString &message) diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.h b/src/plugins/diffeditor/unifieddiffeditorwidget.h index d3206a8ee2..33ca371277 100644 --- a/src/plugins/diffeditor/unifieddiffeditorwidget.h +++ b/src/plugins/diffeditor/unifieddiffeditorwidget.h @@ -96,7 +96,7 @@ private: int chunkIndexForBlockNumber(int blockNumber) const; void jumpToOriginalFile(const QTextCursor &cursor); void addContextMenuActions(QMenu *menu, - int diffFileIndex, + int fileIndex, int chunkIndex); // block number, visual line number. diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 11c914c97b..0f07a30f6f 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -72,6 +72,7 @@ #include <utils/hostosinfo.h> #include <utils/qtcassert.h> #include <utils/pathchooser.h> +#include <utils/qtcassert.h> #include <utils/savedaction.h> #include <utils/stylehelper.h> @@ -2120,9 +2121,12 @@ void FakeVimPluginPrivate::highlightMatches(FakeVimHandler *, const QString &nee int FakeVimPluginPrivate::currentFile() const { IEditor *editor = EditorManager::currentEditor(); - if (!editor) - return -1; - return DocumentModel::indexOfDocument(editor->document()); + if (editor) { + const Utils::optional<int> index = DocumentModel::indexOfDocument(editor->document()); + if (QTC_GUARD(index)) + return index.value(); + } + return -1; } void FakeVimPluginPrivate::switchToFile(int n) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 5e7ee1e226..f642f8ba7e 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -596,56 +596,49 @@ QTextCodec *GitClient::codecFor(GitClient::CodecType codecType, const QString &s return nullptr; } -void GitClient::slotChunkActionsRequested(QMenu *menu, bool isValid) +void GitClient::chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex) { + QPointer<DiffEditor::DiffEditorController> diffController + = qobject_cast<DiffEditorController *>(sender()); + + auto stageChunk = [this](QPointer<DiffEditor::DiffEditorController> diffController, + int fileIndex, int chunkIndex, bool revert) { + if (diffController.isNull()) + return; + + DiffEditorController::PatchOptions options = DiffEditorController::AddPrefix; + if (revert) + options |= DiffEditorController::Revert; + const QString patch = diffController->makePatch(fileIndex, chunkIndex, options); + stage(diffController, patch, revert); + }; + menu->addSeparator(); QAction *stageChunkAction = menu->addAction(tr("Stage Chunk")); - connect(stageChunkAction, &QAction::triggered, this, &GitClient::slotStageChunk); + connect(stageChunkAction, &QAction::triggered, + [this, stageChunk, diffController, fileIndex, chunkIndex]() { + stageChunk(diffController, fileIndex, chunkIndex, false); + }); QAction *unstageChunkAction = menu->addAction(tr("Unstage Chunk")); - connect(unstageChunkAction, &QAction::triggered, this, &GitClient::slotUnstageChunk); - - m_contextController = qobject_cast<DiffEditorController *>(sender()); + connect(unstageChunkAction, &QAction::triggered, + [this, stageChunk, diffController, fileIndex, chunkIndex]() { + stageChunk(diffController, fileIndex, chunkIndex, true); + }); - if (!isValid || !m_contextController) { + if (!diffController || !diffController->chunkExists(fileIndex, chunkIndex)) { stageChunkAction->setEnabled(false); unstageChunkAction->setEnabled(false); } } -void GitClient::slotStageChunk() -{ - if (m_contextController.isNull()) - return; - - DiffEditorController::PatchOptions options = DiffEditorController::AddPrefix; - const QString patch = m_contextController->makePatch(options); - if (patch.isEmpty()) - return; - - stage(patch, false); -} - -void GitClient::slotUnstageChunk() -{ - if (m_contextController.isNull()) - return; - - DiffEditorController::PatchOptions options = DiffEditorController::AddPrefix; - options |= DiffEditorController::Revert; - const QString patch = m_contextController->makePatch(options); - if (patch.isEmpty()) - return; - - stage(patch, true); -} - -void GitClient::stage(const QString &patch, bool revert) +void GitClient::stage(DiffEditor::DiffEditorController *diffController, + const QString &patch, bool revert) { Utils::TemporaryFile patchFile("git-patchfile"); if (!patchFile.open()) return; - const QString baseDir = m_contextController->baseDirectory(); + const QString baseDir = diffController->baseDirectory(); QTextCodec *codec = EditorManager::defaultTextCodec(); const QByteArray patchData = codec ? codec->fromUnicode(patch) : patch.toLocal8Bit(); @@ -666,7 +659,7 @@ void GitClient::stage(const QString &patch, bool revert) } else { VcsOutputWindow::appendError(errorMessage); } - m_contextController->requestReload(); + diffController->requestReload(); } else { VcsOutputWindow::appendError(errorMessage); } @@ -685,7 +678,7 @@ void GitClient::requestReload(const QString &documentId, const QString &source, QTC_ASSERT(controller, return); connect(controller, &DiffEditorController::chunkActionsRequested, - this, &GitClient::slotChunkActionsRequested, Qt::DirectConnection); + this, &GitClient::chunkActionsRequested, Qt::DirectConnection); connect(controller, &DiffEditorController::requestInformationForCommit, this, &GitClient::branchesForCommit); diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index d98d46d490..206a3c7b7b 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -329,12 +329,11 @@ public: private: void finishSubmoduleUpdate(); - void slotChunkActionsRequested(QMenu *menu, bool isValid); - void slotStageChunk(); - void slotUnstageChunk(); + void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex); void branchesForCommit(const QString &revision); - void stage(const QString &patch, bool revert); + void stage(DiffEditor::DiffEditorController *diffController, + const QString &patch, bool revert); enum CodecType { CodecSource, CodecLogOutput, CodecNone }; QTextCodec *codecFor(CodecType codecType, const QString &source = QString()) const; @@ -378,7 +377,6 @@ private: QMap<QString, StashInfo> m_stashInfo; QStringList m_updatedSubmodules; bool m_disableEditor; - QPointer<DiffEditor::DiffEditorController> m_contextController; QFutureSynchronizer<void> m_synchronizer; // for commit updates }; diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 8d8015fa4f..02d4902749 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -81,6 +81,7 @@ const char C_FOLDERNAVIGATIONWIDGET[] = "ProjectExplorer.FolderNavigationWidget" const char kSettingsBase[] = "FolderNavigationWidget."; const char kHiddenFilesKey[] = ".HiddenFilesFilter"; const char kSyncKey[] = ".SyncWithEditor"; +const char kShowBreadCrumbs[] = ".ShowBreadCrumbs"; namespace ProjectExplorer { namespace Internal { @@ -202,7 +203,7 @@ bool FolderNavigationModel::setData(const QModelIndex &index, const QVariant &va if (!failedNodes.isEmpty()) { const QString projects = projectNames(failedNodes).join(", "); const QString errorMessage - = tr("The file \"%1\" was renamed to \"%2\", " + = FolderNavigationWidget::tr("The file \"%1\" was renamed to \"%2\", " "but the following projects could not be automatically changed: %3") .arg(beforeFilePath, afterFilePath, projects); QTimer::singleShot(0, Core::ICore::instance(), [errorMessage] { @@ -246,6 +247,7 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent m_listView(new Utils::NavigationTreeView(this)), m_fileSystemModel(new FolderNavigationModel(this)), m_filterHiddenFilesAction(new QAction(tr("Show Hidden Files"), this)), + m_showBreadCrumbsAction(new QAction(tr("Show Bread Crumbs"), this)), m_toggleSync(new QToolButton(this)), m_rootSelector(new QComboBox), m_crumbLabel(new DelayedFileCrumbLabel(this)) @@ -266,6 +268,8 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent m_fileSystemModel->setRootPath(QString()); m_filterHiddenFilesAction->setCheckable(true); setHiddenFilesFilter(false); + m_showBreadCrumbsAction->setCheckable(true); + setShowBreadCrumbs(true); m_listView->setIconSize(QSize(16,16)); m_listView->setModel(m_fileSystemModel); m_listView->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -320,8 +324,14 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent &QAction::toggled, this, &FolderNavigationWidget::setHiddenFilesFilter); - connect(m_toggleSync, &QAbstractButton::clicked, - this, &FolderNavigationWidget::toggleAutoSynchronization); + connect(m_showBreadCrumbsAction, + &QAction::toggled, + this, + &FolderNavigationWidget::setShowBreadCrumbs); + connect(m_toggleSync, + &QAbstractButton::clicked, + this, + &FolderNavigationWidget::toggleAutoSynchronization); connect(m_rootSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, @@ -348,6 +358,12 @@ void FolderNavigationWidget::toggleAutoSynchronization() setAutoSynchronization(!m_autoSync); } +void FolderNavigationWidget::setShowBreadCrumbs(bool show) +{ + m_showBreadCrumbsAction->setChecked(show); + m_crumbLabel->setVisible(show); +} + static bool itemLessThan(QComboBox *combo, int index, const FolderNavigationWidgetFactory::RootDirectory &directory) @@ -582,7 +598,13 @@ void FolderNavigationWidget::setCrumblePath(const QModelIndex &index, const QMod // try to fix scroll position, otherwise delay layouting QScrollBar *bar = m_listView->verticalScrollBar(); const int newBarValue = bar ? bar->value() + diff : 0; - if (bar && bar->minimum() <= newBarValue && bar->maximum() >= newBarValue) { + const QRect currentItemRect = m_listView->visualRect(index); + const int currentItemVStart = currentItemRect.y(); + const int currentItemVEnd = currentItemVStart + currentItemRect.height(); + const bool currentItemStillVisibleAsBefore = (diff < 0 || currentItemVStart > diff + || currentItemVEnd <= 0); + if (bar && bar->minimum() <= newBarValue && bar->maximum() >= newBarValue + && currentItemStillVisibleAsBefore) { // we need to set the scroll bar when the layout request from the crumble path is // handled, otherwise it will flicker m_crumbLabel->setScrollBarOnce(bar, newBarValue); @@ -669,6 +691,11 @@ bool FolderNavigationWidget::hiddenFilesFilter() const return m_filterHiddenFilesAction->isChecked(); } +bool FolderNavigationWidget::isShowingBreadCrumbs() const +{ + return m_showBreadCrumbsAction->isChecked(); +} + QStringList FolderNavigationWidget::projectFilesInDirectory(const QString &path) { QDir dir(path); @@ -722,11 +749,12 @@ Core::NavigationView FolderNavigationWidgetFactory::createWidget() n.widget = fnw; auto filter = new QToolButton; filter->setIcon(Utils::Icons::FILTER.icon()); - filter->setToolTip(tr("Filter Files")); + filter->setToolTip(tr("Options")); filter->setPopupMode(QToolButton::InstantPopup); filter->setProperty("noArrow", true); auto filterMenu = new QMenu(filter); filterMenu->addAction(fnw->m_filterHiddenFilesAction); + filterMenu->addAction(fnw->m_showBreadCrumbsAction); filter->setMenu(filterMenu); n.dockToolBarWidgets << filter << fnw->m_toggleSync; return n; @@ -739,6 +767,7 @@ void FolderNavigationWidgetFactory::saveSettings(QSettings *settings, int positi const QString base = kSettingsBase + QString::number(position); settings->setValue(base + kHiddenFilesKey, fnw->hiddenFilesFilter()); settings->setValue(base + kSyncKey, fnw->autoSynchronization()); + settings->setValue(base + kShowBreadCrumbs, fnw->isShowingBreadCrumbs()); } void FolderNavigationWidgetFactory::restoreSettings(QSettings *settings, int position, QWidget *widget) @@ -748,6 +777,7 @@ void FolderNavigationWidgetFactory::restoreSettings(QSettings *settings, int pos const QString base = kSettingsBase + QString::number(position); fnw->setHiddenFilesFilter(settings->value(base + kHiddenFilesKey, false).toBool()); fnw->setAutoSynchronization(settings->value(base + kSyncKey, true).toBool()); + fnw->setShowBreadCrumbs(settings->value(base + kShowBreadCrumbs, true).toBool()); } void FolderNavigationWidgetFactory::insertRootDirectory(const RootDirectory &directory) @@ -821,6 +851,7 @@ int DelayedFileCrumbLabel::immediateHeightForWidth(int w) const int DelayedFileCrumbLabel::heightForWidth(int w) const { + static const int doubleDefaultInterval = 800; static QHash<int, int> oldHeight; setScrollBarOnce(); int newHeight = Utils::FileCrumbLabel::heightForWidth(w); @@ -828,11 +859,13 @@ int DelayedFileCrumbLabel::heightForWidth(int w) const oldHeight.insert(w, newHeight); } else if (oldHeight.value(w) != newHeight){ auto that = const_cast<DelayedFileCrumbLabel *>(this); - QTimer::singleShot(QApplication::doubleClickInterval(), that, [that, w, newHeight] { - oldHeight.insert(w, newHeight); - that->m_delaying = false; - that->updateGeometry(); - }); + QTimer::singleShot(std::max(2 * QApplication::doubleClickInterval(), doubleDefaultInterval), + that, + [that, w, newHeight] { + oldHeight.insert(w, newHeight); + that->m_delaying = false; + that->updateGeometry(); + }); } return oldHeight.value(w); } diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h index 7cf9900fb8..2d1012edbd 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.h +++ b/src/plugins/projectexplorer/foldernavigationwidget.h @@ -99,9 +99,11 @@ public: bool autoSynchronization() const; bool hiddenFilesFilter() const; + bool isShowingBreadCrumbs() const; void setAutoSynchronization(bool sync); void toggleAutoSynchronization(); + void setShowBreadCrumbs(bool show); void insertRootDirectory(const FolderNavigationWidgetFactory::RootDirectory &directory); void removeRootDirectory(const QString &id); @@ -129,6 +131,7 @@ private: Utils::NavigationTreeView *m_listView = nullptr; QFileSystemModel *m_fileSystemModel = nullptr; QAction *m_filterHiddenFilesAction = nullptr; + QAction *m_showBreadCrumbsAction = nullptr; bool m_autoSync = false; QToolButton *m_toggleSync = nullptr; QComboBox *m_rootSelector = nullptr; diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index 9e84525c8c..e76ccaa3aa 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -336,8 +336,9 @@ public: const QString &action = actions.at(i); const int ww = fm.width(action); const QRect actionRect(xx, yy - 10, ww, 15); - const bool isActive = actionRect.contains(mousePos); - painter->setPen(linkColor); + const bool isForcedDisabled = (i != 0 && sessionName == "default"); + const bool isActive = actionRect.contains(mousePos) && !isForcedDisabled; + painter->setPen(isForcedDisabled ? disabledLinkColor : linkColor); painter->setFont(sizedFont(12, option.widget, isActive)); painter->drawText(xx, yy, action); if (i < 2) { @@ -404,6 +405,7 @@ private: const QColor hoverColor = themeColor(Theme::Welcome_HoverColor); const QColor textColor = themeColor(Theme::Welcome_TextColor); const QColor linkColor = themeColor(Theme::Welcome_LinkColor); + const QColor disabledLinkColor = themeColor(Theme::Welcome_DisabledLinkColor); const QColor backgroundColor = themeColor(Theme::Welcome_BackgroundColor); const QColor foregroundColor1 = themeColor(Theme::Welcome_ForegroundPrimaryColor); // light-ish. const QColor foregroundColor2 = themeColor(Theme::Welcome_ForegroundSecondaryColor); // blacker. diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index 5f877b53c0..e882df9363 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -338,7 +338,10 @@ void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, if (isInStackedContainer) showPlaceHolder = qmlItemNode().instanceIsRenderPixmapNull() && isContentVisible(); - painter->setClipRegion(boundingRect().toRect()); + QRegion clipRegion = painter->clipRegion(); + if (clipRegion.contains(m_selectionBoundingRect.toRect().topLeft()) + && clipRegion.contains(m_selectionBoundingRect.toRect().bottomRight())) + painter->setClipRegion(boundingRect().toRect()); painter->setClipping(true); if (!hideCompletely) { diff --git a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp index d44bcfc3d3..6201fec182 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp @@ -134,7 +134,10 @@ void FileResourcesModel::openFileDialog() if (!QFileInfo::exists(path)) path = modelPath; - QString newFile = QFileDialog::getOpenFileName(Core::ICore::mainWindow(), tr("Open File"), path, m_filter); + QString newFile = QFileDialog::getOpenFileName(Core::ICore::dialogParent(), + tr("Open File"), + path, + m_filter); if (!newFile.isEmpty()) { setFileNameStr(newFile); diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp index 9ed536304f..0c1976638a 100644 --- a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp +++ b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp @@ -49,6 +49,7 @@ #include <texteditor/texteditorconstants.h> #include <qmljseditor/qmljseditordocument.h> +#include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsreformatter.h> #include <utils/changeset.h> @@ -272,7 +273,26 @@ void TextEditorView::reformatFile() && document->filePath().toString().endsWith(".ui.qml") && DesignerSettings::getValue(DesignerSettingsKey::REFORMAT_UI_QML_FILES).toBool()) { - const QString &newText = QmlJS::reformat(document->semanticInfo().document); + QmlJS::Document::Ptr currentDocument(document->semanticInfo().document); + QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot(); + + if (document->isSemanticInfoOutdated()) { + QmlJS::Document::MutablePtr latestDocument; + + const QString fileName = document->filePath().toString(); + latestDocument = snapshot.documentFromSource(QString::fromUtf8(document->contents()), + fileName, + QmlJS::ModelManagerInterface::guessLanguageOfFile(fileName)); + latestDocument->parseQml(); + snapshot.insert(latestDocument); + + currentDocument = latestDocument; + } + + if (!currentDocument->isParsedCorrectly()) + return; + + const QString &newText = QmlJS::reformat(currentDocument); QTextCursor tc(document->document()); Utils::ChangeSet changeSet; diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index e5ec89524a..1e3a3b6d7b 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -81,6 +81,7 @@ static inline QHash<PropertyName, QVariant> getProperties(const ModelNode &node) propertyHash.remove("opacity"); } } + return propertyHash; } @@ -326,6 +327,21 @@ Utils::FileName DocumentManager::currentFilePath() return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->fileName(); } +Utils::FileName DocumentManager::currentProjectDirPath() +{ + QTC_ASSERT(QmlDesignerPlugin::instance(), return {}); + + if (!QmlDesignerPlugin::instance()->currentDesignDocument()) + return {}; + + Utils::FileName qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName(); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName); + if (!project) + return {}; + + return project->projectDirectory(); +} + QStringList DocumentManager::isoIconsQmakeVariableValue(const QString &proPath) { ProjectExplorer::Node *node = ProjectExplorer::ProjectTree::nodeForFile(Utils::FileName::fromString(proPath)); @@ -463,5 +479,22 @@ bool DocumentManager::addResourceFileToIsoProject(const QString &resourceFilePro return true; } +bool DocumentManager::belongsToQmakeProject() +{ + QTC_ASSERT(QmlDesignerPlugin::instance(), return false); + + if (!QmlDesignerPlugin::instance()->currentDesignDocument()) + return false; + + Utils::FileName qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName(); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName); + if (!project) + return false; + + ProjectExplorer::Node *rootNode = project->rootProjectNode(); + QmakeProjectManager::QmakeProFileNode *proNode = dynamic_cast<QmakeProjectManager::QmakeProFileNode*>(rootNode); + return proNode; +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/documentmanager.h b/src/plugins/qmldesigner/documentmanager.h index 7e4da75187..d62ee85348 100644 --- a/src/plugins/qmldesigner/documentmanager.h +++ b/src/plugins/qmldesigner/documentmanager.h @@ -56,6 +56,7 @@ public: static bool createFile(const QString &filePath, const QString &contents); static void addFileToVersionControl(const QString &directoryPath, const QString &newFilePath); static Utils::FileName currentFilePath(); + static Utils::FileName currentProjectDirPath(); static QStringList isoIconsQmakeVariableValue(const QString &proPath); static bool setIsoIconsQmakeVariableValue(const QString &proPath, const QStringList &value); @@ -63,6 +64,7 @@ public: QString *resourceFileProPath, const QString &isoIconsQrcFile); static bool isoProFileSupportsAddingExistingFiles(const QString &resourceFileProPath); static bool addResourceFileToIsoProject(const QString &resourceFileProPath, const QString &resourceFilePath); + static bool belongsToQmakeProject(); private: QHash<Core::IEditor *,QPointer<DesignDocument> > m_designDocumentHash; diff --git a/src/plugins/qtsupport/images/icons/androidapp.png b/src/plugins/qtsupport/images/icons/androidapp.png Binary files differdeleted file mode 100644 index 31b4e85059..0000000000 --- a/src/plugins/qtsupport/images/icons/androidapp.png +++ /dev/null diff --git a/src/plugins/qtsupport/images/icons/buildrun.png b/src/plugins/qtsupport/images/icons/buildrun.png Binary files differdeleted file mode 100644 index 0df693f5d2..0000000000 --- a/src/plugins/qtsupport/images/icons/buildrun.png +++ /dev/null diff --git a/src/plugins/qtsupport/images/icons/ddays13.png b/src/plugins/qtsupport/images/icons/ddays13.png Binary files differdeleted file mode 100644 index 978c5a9465..0000000000 --- a/src/plugins/qtsupport/images/icons/ddays13.png +++ /dev/null diff --git a/src/plugins/qtsupport/images/icons/ddays14.png b/src/plugins/qtsupport/images/icons/ddays14.png Binary files differdeleted file mode 100644 index c7882906df..0000000000 --- a/src/plugins/qtsupport/images/icons/ddays14.png +++ /dev/null diff --git a/src/plugins/qtsupport/images/icons/qteventicon.png b/src/plugins/qtsupport/images/icons/qteventicon.png Binary files differnew file mode 100644 index 0000000000..b3ba23cbe3 --- /dev/null +++ b/src/plugins/qtsupport/images/icons/qteventicon.png diff --git a/src/plugins/qtsupport/images/icons/qtquick.png b/src/plugins/qtsupport/images/icons/qtquick.png Binary files differdeleted file mode 100644 index bee3130e8d..0000000000 --- a/src/plugins/qtsupport/images/icons/qtquick.png +++ /dev/null diff --git a/src/plugins/qtsupport/images/icons/qwidget.png b/src/plugins/qtsupport/images/icons/qwidget.png Binary files differdeleted file mode 100644 index 31df758036..0000000000 --- a/src/plugins/qtsupport/images/icons/qwidget.png +++ /dev/null diff --git a/src/plugins/qtsupport/images/icons/tutorialicon.png b/src/plugins/qtsupport/images/icons/tutorialicon.png Binary files differindex c34f23164e..955d29d92c 100644 --- a/src/plugins/qtsupport/images/icons/tutorialicon.png +++ b/src/plugins/qtsupport/images/icons/tutorialicon.png diff --git a/src/plugins/qtsupport/images/icons/videotutorialicon.png b/src/plugins/qtsupport/images/icons/videotutorialicon.png Binary files differindex 71b5a91cf2..b3e88de859 100644 --- a/src/plugins/qtsupport/images/icons/videotutorialicon.png +++ b/src/plugins/qtsupport/images/icons/videotutorialicon.png diff --git a/src/plugins/qtsupport/images/icons/worldsummit15.png b/src/plugins/qtsupport/images/icons/worldsummit15.png Binary files differdeleted file mode 100644 index 728389cad1..0000000000 --- a/src/plugins/qtsupport/images/icons/worldsummit15.png +++ /dev/null diff --git a/src/plugins/qtsupport/images/icons/worldsummit16.png b/src/plugins/qtsupport/images/icons/worldsummit16.png Binary files differdeleted file mode 100644 index e7883c847c..0000000000 --- a/src/plugins/qtsupport/images/icons/worldsummit16.png +++ /dev/null diff --git a/src/plugins/qtsupport/qtcreator_tutorials.xml b/src/plugins/qtsupport/qtcreator_tutorials.xml index d018570278..264813a594 100644 --- a/src/plugins/qtsupport/qtcreator_tutorials.xml +++ b/src/plugins/qtsupport/qtcreator_tutorials.xml @@ -1,140 +1,169 @@ <?xml version="1.0" encoding="utf-8"?> <instructionals module="Qt"> <tutorials> - <tutorial imageUrl=":qtsupport/images/icons/buildrun.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/creator-build-example-application.html" projectPath="" name="Building and Running an Example Application"> + <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/creator-build-example-application.html" projectPath="" name="Help: Build and Run Examples"> <description><![CDATA[Testing that your installation is successful by opening an existing example application project.]]></description> - <tags>qt creator,build,compile</tags> + <tags>qt creator,build,compile,help</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/qwidget.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/creator-writing-program.html" projectPath="" name="Creating a Qt Widget Based Application"> + <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/creator-writing-program.html" projectPath="" name="Help: Create Qt Widget-Based Applications"> <description><![CDATA[Using Qt Creator to create a small Qt application, Text Finder.]]></description> - <tags>qt creator,qt designer,widgets,c++,text</tags> + <tags>qt creator,qt designer,widgets,c++,text,help</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtdoc/qtdoc/gettingstartedqt.html" projectPath="" name="Getting Started Programming with Qt Widgets"> + <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtdoc/qtdoc/gettingstartedqt.html" projectPath="" name="Help: Program with Qt Widgets"> <description><![CDATA[Developing Qt applications using C++ and the Qt Widgets module.]]></description> - <tags>qt,qt creator,qt designer,widgets,c++</tags> + <tags>qt,qt creator,qt designer,widgets,c++,help</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/qtquick.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/qtcreator-transitions-example.html" projectPath="" name="Creating a Qt Quick Application"> + <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/qtcreator-transitions-example.html" projectPath="" name="Help: Create Qt Quick Applications"> <description><![CDATA[Using basic QML elements and learning about basic concepts of Qt Quick.]]></description> - <tags>qt creator,qt quick designer,qt quick,qml,states,transitions</tags> + <tags>qt creator,qt quick designer,qt quick,qml,states,transitions,help</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/androidapp.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/qtcreator-accelbubble-example.html" projectPath="" name="Creating a Mobile Application"> + <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtcreator/doc/qtcreator-accelbubble-example.html" projectPath="" name="Help: Create Mobile Qt Applications"> <description><![CDATA[Developing Qt Quick applications for Android and iOS devices using Qt Quick Controls.]]></description> - <tags>qt creator,qt quick designer,qml,android,ios,controls</tags> + <tags>qt creator,qt quick designer,qml,android,ios,controls,help</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtdoc/qtdoc/gettingstartedqml.html" projectPath="" name="Getting Started Programming with Qt Quick"> + <tutorial imageUrl=":qtsupport/images/icons/tutorialicon.png" difficulty="" docUrl="qthelp://org.qt-project.qtdoc/qtdoc/gettingstartedqml.html" projectPath="" name="Help: Program with Qt Quick"> <description><![CDATA[Developing Qt Quick applications using QML and C++.]]></description> - <tags>qt quick,qml,c++</tags> + <tags>qt quick,qml,c++,help</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Digital Instrument Cluster with Qt Quick Designer and Qt Safe Renderer" isVideo="true" videoUrl="https://www.youtube.com/watch?v=9RxxsOCeZHk" videoLength="4:06"> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Digital Instrument Cluster and Qt Safe Renderer" isVideo="true" videoUrl="https://www.youtube.com/watch?v=9RxxsOCeZHk" videoLength="4:06"> <description><![CDATA[Creating a digital instrument cluster with Qt Quick Designer and Qt Safe Renderer.]]></description> - <tags>qt creator,qt quick,automotive,safe renderer,controls</tags> + <tags>qt creator,qt quick,automotive,safe renderer,controls,video</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=PercN_GtVJA" videoLength="3:01"> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt for Device Creation - Overview" isVideo="true" videoUrl="https://www.youtube.com/watch?v=PercN_GtVJA" videoLength="3:01"> <description><![CDATA[Creating a Qt widget based application.]]></description> - <tags>qt creator,embedded,device creation</tags> + <tags>qt creator,embedded,device creation,video</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Getting Started with Qt for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=QFWPw4UWL9E" videoLength="8:30"> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt for Device Creation - Getting Started" isVideo="true" videoUrl="https://www.youtube.com/watch?v=QFWPw4UWL9E" videoLength="8:30"> <description><![CDATA[Using Qt Creator to deploy applications to an embedded device.]]></description> - <tags>qt creator,embedded,device creation</tags> + <tags>qt creator,embedded,device creation,video</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt Quick Designer - The Coffee Machine" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3YPM_tStM" videoLength="3:06"> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Quick Designer - The Coffee Machine" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3YPM_tStM" videoLength="3:06"> <description><![CDATA[Creating a UI for embedded devices.]]></description> - <tags>qt creator,qt quick,embedded</tags> + <tags>qt creator,qt quick,embedded,video,controls</tags> </tutorial> - - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Getting started with Qt: Hello Widget World " isVideo="true" videoUrl="https://www.youtube.com/watch?v=TIUTO8GjSGo" videoLength="9:10"> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Getting Started - Hello Widget World " isVideo="true" videoUrl="https://www.youtube.com/watch?v=TIUTO8GjSGo" videoLength="9:10"> <description><![CDATA[Creating a Qt widget based application.]]></description> - <tags>qt creator,widgets</tags> + <tags>qt creator,widgets,video</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Getting started with Qt: Hello Quick World" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nepoVgVvWEI" videoLength="13:28"> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Getting Started - Hello Quick World" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nepoVgVvWEI" videoLength="13:28"> <description><![CDATA[Creating a Qt Quick application.]]></description> - <tags>qt creator,qt quick</tags> + <tags>qt creator,qt quick,video</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt SCXML and State Machine Tooling in Qt Creator" isVideo="true" videoUrl="https://youtu.be/9xqhq9nDiOg" videoLength="4:53"> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt SCXML and Tooling in Qt Creator" isVideo="true" videoUrl="https://youtu.be/9xqhq9nDiOg" videoLength="4:53"> <description><![CDATA[Creating state machines.]]></description> - <tags>qt creator,SCXML</tags> + <tags>qt creator,SCXML,video</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="Introduction to Qt Creator" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nGFmjOiT22Y" videoLength="50:36"> - <description><![CDATA[Getting started with using Qt Creator for cross-platform development.]]></description> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Using C++ Models in QML" isVideo="true" videoUrl="https://www.youtube.com/watch?v=9BcAYDlpuT8" videoLength="49:48"> + <description><![CDATA[Creating and using a C++ model in QML.]]></description> + <tags>qt creator,qt quick,c++,video</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Creator - Overview" isVideo="true" videoUrl="https://youtu.be/zAqSiIGdj8M" videoLength="2:06"> + <description><![CDATA[Overview of Qt Creator.]]></description> <tags>qt creator</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="Custom Qt Creator Wizards" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3DuCgFamo" videoLength="27:21"> + + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Getting Started" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nGFmjOiT22Y" videoLength="50:36"> + <description><![CDATA[Getting started with using Qt Creator for cross-platform development.]]></description> + <tags>qt creator,talk,2015</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Custom Wizards" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3DuCgFamo" videoLength="27:21"> <description><![CDATA[Adding custom file and project creation wizards to Qt Creator.]]></description> - <tags>qt creator,wizard</tags> + <tags>qt creator,wizard,talk,2015</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/ddays13.png" difficulty="" projectPath="" name="Extending Qt Creator Without Writing Code" isVideo="true" videoUrl="http://www.youtube.com/watch?v=DP0lMoLVneY" videoLength="59:49"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Extending Without Writing Code" isVideo="true" videoUrl="http://www.youtube.com/watch?v=DP0lMoLVneY" videoLength="59:49"> <description><![CDATA[Customizing Qt Creator to fit your own or your customers' purposes.]]></description> - <tags>qt creator,configuration</tags> + <tags>qt creator,configuration,talk,2013</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/ddays13.png" difficulty="" projectPath="" name="Qt Creator Plugin Development" isVideo="true" videoUrl="http://www.youtube.com/watch?v=6AEYgVPjl-s" videoLength="59:49"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Plugin Development" isVideo="true" videoUrl="http://www.youtube.com/watch?v=6AEYgVPjl-s" videoLength="59:49"> <description><![CDATA[Adding plugins to Qt Creator.]]></description> - <tags>qt creator,plugins</tags> + <tags>qt creator,plugins,talk,2013</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/ddays14.png" difficulty="" projectPath="" name="Using the QML Profiler" isVideo="true" videoUrl="https://www.youtube.com/watch?v=TiJiF0MOOFc" videoLength="55:12"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - QML Profiler" isVideo="true" videoUrl="https://www.youtube.com/watch?v=TiJiF0MOOFc" videoLength="55:12"> <description><![CDATA[Monitoring the performance of a Qt Quick application.]]></description> - <tags>qt quick,qt creator,qml profiler</tags> + <tags>qt quick,qt creator,qml profiler,talk,2014</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="CPU Usage Analyzer for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=G0AbgVHGdXI" videoLength="22:30"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - CPU Usage Analyzer" isVideo="true" videoUrl="https://www.youtube.com/watch?v=G0AbgVHGdXI" videoLength="22:30"> <description><![CDATA[Using the Linux perf tool to generate data for code analysis.]]></description> - <tags>qt creator,cpu usage analyzer,perf,embedded,device creation</tags> + <tags>qt creator,cpu usage analyzer,perf,embedded,device creation,talk,2015</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Qt SCXML: State Machines Made Easier" isVideo="true" videoUrl="https://youtu.be/X0kEkB0ewyw" videoLength="42:22"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - SCXML Editor" isVideo="true" videoUrl="https://youtu.be/X0kEkB0ewyw" videoLength="42:22"> <description><![CDATA[Using the Qt SCXML module and Qt Creator SCXML editor.]]></description> - <tags>qt creator,SCXML</tags> + <tags>qt creator,scxml,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="Effective Multi-Platform Development with Qt Creator, Qbs, and QEMU" isVideo="true" videoUrl="https://www.youtube.com/watch?v=v4glCQt2jE0" videoLength="19:08"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Multi-Platform Development" isVideo="true" videoUrl="https://www.youtube.com/watch?v=v4glCQt2jE0" videoLength="19:08"> <description><![CDATA[Using Qt Creator, Qbs, and QEMU for application development.]]></description> - <tags>qt creator,qbs,qemu</tags> + <tags>qt creator,qbs,qemu,talk,2015</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="All about Qt on Android" isVideo="true" videoUrl="https://youtu.be/dmKNxyi_YNk" videoLength="31:20"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt on Android - Overview" isVideo="true" videoUrl="https://youtu.be/dmKNxyi_YNk" videoLength="31:20"> <description><![CDATA[Developing Qt applications for Android devices.]]></description> - <tags>qt creator,android</tags> - </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Meet Qt Creator" isVideo="true" videoUrl="https://youtu.be/zAqSiIGdj8M" videoLength="2:06"> - <description><![CDATA[Overview of Qt Creator.]]></description> - <tags>qt creator</tags> + <tags>qt creator,android,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Qt on iOS A to Z" isVideo="true" videoUrl="https://youtu.be/T_13aX5NTPk" videoLength="1:00:13"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt on iOS - Overview" isVideo="true" videoUrl="https://youtu.be/T_13aX5NTPk" videoLength="1:00:13"> <description><![CDATA[Developing Qt applications for iOS.]]></description> - <tags>qt creator,ios</tags> + <tags>qt creator,ios,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/ddays13.png" difficulty="" projectPath="" name="Qt Creator for Bare Metal Development" isVideo="true" videoUrl="http://www.youtube.com/watch?v=hrKz63Q_Rf0" videoLength="9:35"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Bare Metal Development" isVideo="true" videoUrl="http://www.youtube.com/watch?v=hrKz63Q_Rf0" videoLength="9:35"> <description><![CDATA[Developing Qt Applications for Bare Metal devices.]]></description> - <tags>qt creator,baremetal</tags> + <tags>qt creator,baremetal,talk,2013</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Integrating Universal Windows Platform to Qt" isVideo="true" videoUrl="https://youtu.be/tpNdw2Cs4KY" videoLength="47:38"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt on Universal Windows Platform" isVideo="true" videoUrl="https://youtu.be/tpNdw2Cs4KY" videoLength="47:38"> <description><![CDATA[Qt support for Universal Windows Platform on desktop, mobile, and embedded devices.]]></description> - <tags>windows</tags> + <tags>uwp,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Developing UIs with Qt Quick Controls 2" isVideo="true" videoUrl="https://youtu.be/ozpSl7WbVt4" videoLength="23:13"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Quick Controls 2 - Overview" isVideo="true" videoUrl="https://youtu.be/ozpSl7WbVt4" videoLength="23:13"> <description><![CDATA[Using Qt Quick Controls 2 to create UIs.]]></description> - <tags>qt quick designer,controls</tags> + <tags>ui,qt quick designer,controls,ui,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Overview of GUI technologies in Qt" isVideo="true" videoUrl="https://youtu.be/WIRRoPxIerc" videoLength="40:45"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: GUI technologies in Qt" isVideo="true" videoUrl="https://youtu.be/WIRRoPxIerc" videoLength="40:45"> <description><![CDATA[Overview of UI technologies that can be used with Qt.]]></description> - <tags>qt quick,ui,widgets</tags> + <tags>qt quick,ui,widgets,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Qt on Your Wrist – Qt on Android Wear" isVideo="true" videoUrl="https://youtu.be/Rd187QxihRo" videoLength="8:08"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt on Android Wear" isVideo="true" videoUrl="https://youtu.be/Rd187QxihRo" videoLength="8:08"> <description><![CDATA[Running Qt apps on Android Wear devices.]]></description> - <tags>qt creator,android</tags> + <tags>qt creator,android,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Qt on macOS Updates" isVideo="true" videoUrl="https://youtu.be/qfyxXxeC73Y" videoLength="25:51"> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt on macOS - Updates" isVideo="true" videoUrl="https://youtu.be/qfyxXxeC73Y" videoLength="25:51"> <description><![CDATA[Using Qt with macOS native windows.]]></description> - <tags>macos</tags> + <tags>macos,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="Qt's Web Offering - An Overview" isVideo="true" videoUrl="https://www.youtube.com/watch?v=XW-oTBCj1JQ" videoLength="23:32"> - <description><![CDATA[Overview of the Qt modules that provide functions for embedding web content into applications.]]></description> - <tags>qt webengine</tags> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Multi-Platform and Screen Resolution" isVideo="true" videoUrl="https://youtu.be/qclquZ99ZVQ" videoLength="27:44"> + <description><![CDATA[Best practices for an efficient app lifecycle.]]></description> + <tags>qt,qt quick,screen resolution,ui,talk,2016</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="New Possibilities with Qt WebEngine" isVideo="true" videoUrl="https://youtu.be/E7CIIHT_jCk" videoLength="22:29"> - <description><![CDATA[Using the Qt WebEngine module.]]></description> - <tags>qt webengine</tags> + + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Mobile Applications - Tips and Examples" isVideo="true" videoUrl="https://www.youtube.com/watch?v=OqqarK73I9E" videoLength="53:57"> + <description><![CDATA[Technical tips and examples for developing and testing mobile apps.]]></description> + <tags>android,ios,talk,2017</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Developing for Multiple Screen Resolutions and Platforms" isVideo="true" videoUrl="https://youtu.be/qclquZ99ZVQ" videoLength="27:44"> - <description><![CDATA[Best practices for an efficient app lifecycle.]]></description> - <tags>qt,qt quick,screen resolution</tags> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt in Medical Devices - Overview" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Xe5xebP9w94" videoLength="24:53"> + <description><![CDATA[Developing UX and UI for medical devices.]]></description> + <tags>medical,ui,talk,2017</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Mobile Applications - Reducing Size" isVideo="true" videoUrl="https://www.youtube.com/watch?v=3o2Wo4YzlII" videoLength="23:41"> + <description><![CDATA[Making Android and iOS apps smaller.]]></description> + <tags>android,ios,talk,2017</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Automotive Suite - Overview" isVideo="true" videoUrl="https://www.youtube.com/watch?v=7FqG2lpJ1KE" videoLength="23:38"> + <description><![CDATA[Introducing Qt Application Manager plugin in Qt Creator.]]></description> + <tags>automotive,application manager,talk,2017</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Embedded Devices - Virtual Keyboards" isVideo="true" videoUrl="https://www.youtube.com/watch?v=g0X2IZ9ZCTA" videoLength="19:32"> + <description><![CDATA[Support text input via virtual keyboards on embedded devices.]]></description> + <tags>embedded,virtual keyboard,talk,2017</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Quick Controls 2 - Mobile Business Applications" isVideo="true" videoUrl="https://www.youtube.com/watch?v=au3brB7lNms" videoLength="23:33"> + <description><![CDATA[Creating mobile business apps using Qt Quick Controls 2.]]></description> + <tags>android,ios,qt quick,controls,talk,2017</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Automotive Suite - Qt IVI" isVideo="true" videoUrl="https://www.youtube.com/watch?v=CVhVAK10TDw" videoLength="46:41"> + <description><![CDATA[Integrating and testing vehicle functions with Qt Automotive Suite.]]></description> + <tags>automotive,ivi,talk,2017</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt 3D - Simple and Skeletal Animations" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Cj5enhBlL28" videoLength=""> + <description><![CDATA[Using the new animation subsystem of Qt 3D.]]></description> + <tags>talk,2017</tags> </tutorial> </tutorials> </instructionals> diff --git a/src/plugins/qtsupport/qtsupport.qrc b/src/plugins/qtsupport/qtsupport.qrc index 50d90e55d8..03d8dbc7e8 100644 --- a/src/plugins/qtsupport/qtsupport.qrc +++ b/src/plugins/qtsupport/qtsupport.qrc @@ -6,15 +6,8 @@ <file>images/dark_qt_qrc.png</file> <file>images_areaofinterest.xml</file> <file>qtcreator_tutorials.xml</file> - <file>images/icons/androidapp.png</file> - <file>images/icons/buildrun.png</file> - <file>images/icons/ddays13.png</file> - <file>images/icons/ddays14.png</file> - <file>images/icons/qtquick.png</file> - <file>images/icons/qwidget.png</file> <file>images/icons/tutorialicon.png</file> - <file>images/icons/worldsummit15.png</file> - <file>images/icons/worldsummit16.png</file> <file>images/icons/videotutorialicon.png</file> + <file>images/icons/qteventicon.png</file> </qresource> </RCC> diff --git a/src/plugins/texteditor/snippets/snippetscollection.cpp b/src/plugins/texteditor/snippets/snippetscollection.cpp index 5756a01f66..660ac0746c 100644 --- a/src/plugins/texteditor/snippets/snippetscollection.cpp +++ b/src/plugins/texteditor/snippets/snippetscollection.cpp @@ -44,6 +44,13 @@ using namespace TextEditor; using namespace Internal; +/* TRANSLATOR TextEditor::Internal::Snippets + + Snippets are text fragments that can be inserted into an editor via the usual completion + mechanics using a trigger text. The translated text (trigger variant) is used to + disambiguate between snippets with the same trigger. +*/ + namespace { static bool snippetComp(const Snippet &a, const Snippet &b) @@ -359,7 +366,10 @@ QList<Snippet> SnippetsCollection::readXML(const QString &fileName, const QStrin if (isGroupKnown(groupId) && (snippetId.isEmpty() || snippetId == id)) { Snippet snippet(groupId, id); snippet.setTrigger(atts.value(kTrigger).toString()); - snippet.setComplement(atts.value(kComplement).toString()); + snippet.setComplement(QCoreApplication::translate( + "TextEditor::Internal::Snippets", + atts.value(kComplement).toString().toLatin1(), + atts.value(kId).toString().toLatin1())); snippet.setIsRemoved(toBool(atts.value(kRemoved).toString())); snippet.setIsModified(toBool(atts.value(kModified).toString())); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 8aa3dc847f..5b7a0b27ba 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -435,7 +435,7 @@ struct PaintEventData const QRect eventRect; qreal rightMargin = -1; const QTextDocument *doc; - const TextDocumentLayout *documentLayout; + TextDocumentLayout *documentLayout; const int documentWidth; const QTextCursor textCursor; const QTextBlock textCursorBlock; @@ -502,7 +502,8 @@ public: bool expanded, bool active, bool hovered) const; - bool updateAnnotationBounds(TextBlockUserData *blockUserData, bool annotationsVisible); + bool updateAnnotationBounds(TextBlockUserData *blockUserData, TextDocumentLayout *layout, + bool annotationsVisible); void updateLineAnnotation(const PaintEventData &data, const PaintEventBlockData &blockData, QPainter &painter); void paintRightMarginArea(PaintEventData &data, QPainter &painter) const; @@ -1476,6 +1477,16 @@ void TextEditorWidget::gotoBlockEndWithSelection() } } +void TextEditorWidget::gotoDocumentStart() +{ + moveCursor(QTextCursor::Start); +} + +void TextEditorWidget::gotoDocumentEnd() +{ + moveCursor(QTextCursor::End); +} + void TextEditorWidget::gotoLineStart() { d->handleHomeKey(false); @@ -4008,7 +4019,9 @@ QRectF TextEditorWidgetPrivate::getLastLineLineRect(const QTextBlock &block) return line.naturalTextRect().translated(contentOffset.x(), top).adjusted(0, 0, -1, -1); } -bool TextEditorWidgetPrivate::updateAnnotationBounds(TextBlockUserData *blockUserData, bool annotationsVisible) +bool TextEditorWidgetPrivate::updateAnnotationBounds(TextBlockUserData *blockUserData, + TextDocumentLayout *layout, + bool annotationsVisible) { const bool additionalHeightNeeded = annotationsVisible && m_displaySettings.m_annotationAlignment == AnnotationAlignment::BetweenLines; @@ -4017,6 +4030,7 @@ bool TextEditorWidgetPrivate::updateAnnotationBounds(TextBlockUserData *blockUse return false; blockUserData->setAdditionalAnnotationHeight(additionalHeight); q->viewport()->update(); + layout->emitDocumentSizeChanged(); return true; } @@ -4039,8 +4053,10 @@ void TextEditorWidgetPrivate::updateLineAnnotation(const PaintEventData &data, return !mark->lineAnnotation().isEmpty(); }); - if (updateAnnotationBounds(blockUserData, annotationsVisible) || !annotationsVisible) + if (updateAnnotationBounds(blockUserData, data.documentLayout, annotationsVisible) + || !annotationsVisible) { return; + } const QRectF lineRect = getLastLineLineRect(data.block); if (lineRect.isNull()) diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index d15db70c7f..c08187ed4d 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -381,6 +381,8 @@ public: void gotoBlockStartWithSelection(); void gotoBlockEndWithSelection(); + void gotoDocumentStart(); + void gotoDocumentEnd(); void gotoLineStart(); void gotoLineStartWithSelection(); void gotoLineEnd(); diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp index 6682dcb475..6c39209ffe 100644 --- a/src/plugins/texteditor/texteditoractionhandler.cpp +++ b/src/plugins/texteditor/texteditoractionhandler.cpp @@ -432,6 +432,10 @@ void TextEditorActionHandlerPrivate::createActions() tr("Select Word Under Cursor")); // register GOTO Actions + registerAction(GOTO_DOCUMENT_START, + [] (TextEditorWidget *w) { w->gotoDocumentStart(); }, true, tr("Go to Document Start")); + registerAction(GOTO_DOCUMENT_END, + [] (TextEditorWidget *w) { w->gotoDocumentEnd(); }, true, tr("Go to Document End")); registerAction(GOTO_LINE_START, [] (TextEditorWidget *w) { w->gotoLineStart(); }, true, tr("Go to Line Start")); registerAction(GOTO_LINE_END, diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index 0fd1c706c9..e7024614e5 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -158,6 +158,8 @@ const char DELETE_START_OF_LINE[] = "TextEditor.DeleteStartOfLine"; const char DELETE_START_OF_WORD_CAMEL_CASE[] = "TextEditor.DeleteStartOfWordCamelCase"; const char SELECT_ENCODING[] = "TextEditor.SelectEncoding"; const char REWRAP_PARAGRAPH[] = "TextEditor.RewrapParagraph"; +const char GOTO_DOCUMENT_START[] = "TextEditor.GotoDocumentStart"; +const char GOTO_DOCUMENT_END[] = "TextEditor.GotoDocumentEnd"; const char GOTO_LINE_START[] = "TextEditor.GotoLineStart"; const char GOTO_LINE_END[] = "TextEditor.GotoLineEnd"; const char GOTO_NEXT_LINE[] = "TextEditor.GotoNextLine"; diff --git a/src/shared/qbs b/src/shared/qbs -Subproject 7a17be47f5e93f46e118950d5410e73bc6476ab +Subproject 153b9d8b4117bcf8e0b10f7368991e4d4f676a5 diff --git a/tests/manual/ssh/remoteprocess/argumentscollector.cpp b/tests/manual/ssh/remoteprocess/argumentscollector.cpp index 9e70519efe..cc9839363a 100644 --- a/tests/manual/ssh/remoteprocess/argumentscollector.cpp +++ b/tests/manual/ssh/remoteprocess/argumentscollector.cpp @@ -49,7 +49,7 @@ SshConnectionParameters ArgumentsCollector::collect(bool &success) const bool timeoutGiven = false; bool proxySettingGiven = false; int pos; - int port; + int port = 22; for (pos = 1; pos < m_arguments.count() - 1; ++pos) { QString host; diff --git a/tests/manual/ssh/sftp/argumentscollector.cpp b/tests/manual/ssh/sftp/argumentscollector.cpp index 5f223955ed..be8cb743b0 100644 --- a/tests/manual/ssh/sftp/argumentscollector.cpp +++ b/tests/manual/ssh/sftp/argumentscollector.cpp @@ -48,7 +48,7 @@ Parameters ArgumentsCollector::collect(bool &success) const bool bigFileSizeGiven = false; bool proxySettingGiven = false; int pos; - int port; + int port = 22; for (pos = 1; pos < m_arguments.count() - 1; ++pos) { QString host; QString user; diff --git a/tests/manual/ssh/tunnel/argumentscollector.cpp b/tests/manual/ssh/tunnel/argumentscollector.cpp index d49e016396..15d73901d2 100644 --- a/tests/manual/ssh/tunnel/argumentscollector.cpp +++ b/tests/manual/ssh/tunnel/argumentscollector.cpp @@ -51,7 +51,7 @@ SshConnectionParameters ArgumentsCollector::collect(bool &success) const bool timeoutGiven = false; bool proxySettingGiven = false; int pos; - int port; + int port = 22; for (pos = 1; pos < m_arguments.count() - 1; ++pos) { QString user; diff --git a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py index b47da5d58d..6338fdb94e 100644 --- a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py +++ b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py @@ -42,7 +42,7 @@ def main(): test.fatal("Failed to activate kit %s" % kit) continue test.log("Running project Qt Quick UI Prototype (%s)" % kit) - qmlViewer = modifyRunSettingsForHookIntoQtQuickUI(2, 1, workingDir, projectName, 11223, quick) + qmlViewer = modifyRunSettingsForHookIntoQtQuickUI(1, 0, workingDir, projectName, 11223, quick) if qmlViewer!=None: qmlViewerPath = os.path.dirname(qmlViewer) qmlViewer = os.path.basename(qmlViewer) |