diff --git a/dist/changes-4.8.0.md b/dist/changes-4.8.0.md index a3602db43fb..a895b109785 100644 --- a/dist/changes-4.8.0.md +++ b/dist/changes-4.8.0.md @@ -15,6 +15,9 @@ General exist * Fixed menu items shown in menu locator filter (QTCREATORBUG-20071, QTCREATORBUG-20626) +* Fixed crash at shutdown when multiple windows are open (QTCREATORBUG-21221) +* Fixed that items could appear empty in `Issues` pane (QTCREATORBUG-20542) +* Fixed Qt Quick wizards when building Qt Creator with Qt 5.12 Editing @@ -23,6 +26,7 @@ Editing (QTCREATORBUG-20284) * Added support for the pastecode.xyz code pasting service * Made it possible to change default editors in MIME type settings +* Fixed issue with input methods (QTCREATORBUG-21483) All Projects @@ -42,6 +46,9 @@ All Projects QMake Projects +* Made it possible to add libraries for other target platforms in + `Add Library` wizard (QTCREATORBUG-17995) +* Fixed crash while parsing (QTCREATORBUG-21416) * Fixed that `make qmake_all` was run in top-level project directory even when building sub-project (QTCREATORBUG-20823) @@ -60,25 +67,39 @@ C++ Support * Added experimental plugin `Cppcheck` for integration of [cppcheck](http://cppcheck.sourceforge.net) diagnostics * Added highlighting style for punctuation tokens (QTCREATORBUG-20666) +* Fixed issues with detecting language version (QTCREATORBUG-20884) +* Fixed crash when code model prints message about too large files + (QTCREATORBUG-21481) +* Fixed function extraction from nested classes (QTCREATORBUG-7271) +* Fixed handling of `-B` option (QTCREATORBUG-21424) * Clang Code Model + * Switched to Clang 7.0 * Added `Follow Symbol` for `auto` keyword (QTCREATORBUG-17191) * Added function overloads to tooltip in completion popup * Added `Build` > `Generate Compilation Database` * Fixed that braced initialization did not provide constructor completion (QTCREATORBUG-20957) * Fixed local references for operator arguments (QTCREATORBUG-20966) + * Fixed support for generated UI headers (QTCREATORBUG-15187, + QTCREATORBUG-17002) + * Fixed crash when removing diagnostics configuration (QTCREATORBUG-21273) QML Support * Fixed indentation in object literals with ternary operator (QTCREATORBUG-7103) * Fixed that symbols from closed projects were still shown in Locator (QTCREATORBUG-13459) +* Fixed crash when building Qt Creator with Qt 5.12 (QTCREATORBUG-21510) +* Fixed that `.mjs` files were not opened in JavaScript editor + (QTCREATORBUG-21517) Debugging * Added support for multiple simultaneous debugger runs +* Added pretty printing of `QEvent` and `QKeyEvent` * Fixed automatic detection of debugging information for Qt from binary installer (QTCREATORBUG-20693) +* Fixed display of short unsigned integers (QTCREATORBUG-21038) * GDB * Fixed startup issue with localized debugger output (QTCREATORBUG-20765) * Fixed disassembler view for newer GCC @@ -86,16 +107,21 @@ Debugging * Added option to suppress task entries for exceptions (QTCREATORBUG-20915) * LLDB * Fixed instruction-wise stepping + * Fixed startup with complex command line arguments (QTCREATORBUG-21433) + * Fixed pretty printing of bitfields Qt Quick Designer +* Added support for enums in `.metainfo` files * Fixed wrong property propagation from parent to child +* Fixed invalid access to network paths (QTCREATORBUG-21372) Version Control Systems * Git * Added navigation pane that shows branches * Added option for copy/move detection to `git blame` (QTCREATORBUG-20462) + * Added support for GitHub and GitLab remotes * Improved behavior if no merge tool is configured * Fixed that `git pull` blocked Qt Creator (QTCREATORBUG-13279) * Fixed handling of `file://` remotes (QTCREATORBUG-20618) @@ -127,16 +153,28 @@ Android * Added support for command line arguments * Added support for environment variables +* Added support for API level 28 +* Added auto-detection of Clang toolchains (QTCREATORBUG-11846) +* Removed auto-detection of GCC toolchains * Fixed connecting to debugger for API level 24 and later +Remote Linux + +* Updated to Botan 2.8 +* Fixed SSH connections in AES-CBC mode (QTCREATORBUG-21387) + Credits for these changes go to: Alessandro Portale Alexandru Croitor Alexis Jeandet +Allan Sandfeld Jensen Andre Hartmann André Pönitz +Benjamin Balga +BogDan Vatra Christian Kandeler Christian Stenger +Daniel Levin Daniel Trevitz David Schulz Eike Ziller @@ -146,6 +184,8 @@ Ivan Donchevskii Jaroslaw Kobus Jochen Becher Jörg Bornemann +Knud Dollereder +Laurent Montel Leena Miettinen Marco Benelli Marco Bubke @@ -157,7 +197,10 @@ Oliver Wolff Orgad Shaneh Razi Alavizadeh Robert Löhning +Sergey Belyashov Sergey Morozov +Tasuku Suzuki +Thiago Macieira Thomas Hartmann Tim Jenssen Tobias Hunger diff --git a/doc/src/editors/creator-only/creator-mime-types.qdoc b/doc/src/editors/creator-only/creator-mime-types.qdoc index 553f47778c2..eb796422dd3 100644 --- a/doc/src/editors/creator-only/creator-mime-types.qdoc +++ b/doc/src/editors/creator-only/creator-mime-types.qdoc @@ -105,6 +105,16 @@ \endlist + Even if an alternative editor is not listed for a MIME type, you can still + change the editor that is used to open the files of a particular type. + Remove the filename extension from the current MIME type and add it to a + MIME type that is handled by the editor you want to use. For example, to + edit Linux kernel device tree source (.dts) files with the text editor, + delete the pattern \c {*.dts} from the MIME type \c {audio/vnd.dts} (where + it represents the digital surround audio file format), and add it to the + \c {text/plain} MIME type. You can use the \uicontrol Filter field to find + the MIME type that currently contains a filename extension. + To revert the changes you have made to the MIME type definitions, select \uicontrol {Reset MIME Types}. To revert the changes you have made to the default editors, select \uicontrol {Reset Handlers}. diff --git a/scripts/createSourcePackages.py b/scripts/createSourcePackages.py index af99704ac3f..1385de943aa 100755 --- a/scripts/createSourcePackages.py +++ b/scripts/createSourcePackages.py @@ -99,7 +99,9 @@ def main(): args = parse_arguments() base_repo_name = args.name if args.name else "qtcreator" if not args.name and not args.modules: # default Qt Creator repository - args.modules = [os.path.join('src', 'shared', 'qbs')] + qbs_path = os.path.join('src', 'shared', 'qbs') + if os.path.exists(os.path.join(args.repo, qbs_path)): + args.modules = [qbs_path] repos = [(base_repo_name, args.repo, '')] for module in args.modules: repos += [(module, os.path.join(args.repo, module), module + os.sep)] diff --git a/src/libs/3rdparty/cplusplus/Control.cpp b/src/libs/3rdparty/cplusplus/Control.cpp index afdd6790560..a5601bf6205 100644 --- a/src/libs/3rdparty/cplusplus/Control.cpp +++ b/src/libs/3rdparty/cplusplus/Control.cpp @@ -74,7 +74,11 @@ template <> struct Compare { bool operator()(const ReferenceType &ty, const ReferenceType &otherTy) const { - return ty.elementType() < otherTy.elementType(); + if (ty.elementType() < otherTy.elementType()) + return true; + if (ty.elementType() == otherTy.elementType()) + return (int)ty.isRvalueReference() < (int)otherTy.isRvalueReference(); + return false; } }; diff --git a/src/libs/qmldebug/baseenginedebugclient.cpp b/src/libs/qmldebug/baseenginedebugclient.cpp index 2b7e788feb2..86f54741fc9 100644 --- a/src/libs/qmldebug/baseenginedebugclient.cpp +++ b/src/libs/qmldebug/baseenginedebugclient.cpp @@ -152,7 +152,7 @@ void BaseEngineDebugClient::decode(QDataStream &ds, int contextCount; ds >> contextCount; - for (int ii = 0; ii < contextCount; ++ii) { + for (int ii = 0; ii < contextCount && !ds.atEnd(); ++ii) { c.m_contexts.append(ContextReference()); decode(ds, c.m_contexts.last()); } @@ -160,7 +160,7 @@ void BaseEngineDebugClient::decode(QDataStream &ds, int objectCount; ds >> objectCount; - for (int ii = 0; ii < objectCount; ++ii) { + for (int ii = 0; ii < objectCount && !ds.atEnd(); ++ii) { ObjectReference obj; decode(ds, obj, true); obj.m_contextDebugId = c.m_debugId; diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index a52c63d3702..47c8fe1f0bf 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -405,6 +405,9 @@ FileName AndroidConfig::clangPath() const { FileName clangPath = m_ndkLocation; clangPath.appendPath("toolchains/llvm/prebuilt/"); + FileName oldNdkClangPath = m_ndkLocation; + oldNdkClangPath.appendPath("toolchains/llvm-3.6/prebuilt/"); + const QVector clangSearchPaths{clangPath, oldNdkClangPath}; // detect toolchain host QStringList hostPatterns; @@ -421,20 +424,30 @@ FileName AndroidConfig::clangPath() const default: /* unknown host */ return FileName(); } - QDirIterator iter(clangPath.toString(), hostPatterns, QDir::Dirs); - if (iter.hasNext()) { - iter.next(); - return clangPath.appendPath(iter.fileName()) - .appendPath(HostOsInfo::withExecutableSuffix("bin/clang")); + for (const FileName &path : clangSearchPaths) { + QDirIterator iter(path.toString(), hostPatterns, QDir::Dirs); + if (iter.hasNext()) { + iter.next(); + FileName found = path; + return found.appendPath(iter.fileName()) + .appendPath(HostOsInfo::withExecutableSuffix("bin/clang")); + } } - return clangPath; + return {}; } -FileName AndroidConfig::gdbPath() const +FileName AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi) const { FileName path = m_ndkLocation; path.appendPath(QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(), QTC_HOST_EXE_SUFFIX)); + if (path.exists()) + return path; + // fallback for old NDKs (e.g. 10e) + path = m_ndkLocation; + path.appendPath( + QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4") + .arg(toolchainPrefix(abi), toolchainHost(), toolsPrefix(abi), QTC_HOST_EXE_SUFFIX)); return path; } @@ -991,6 +1004,26 @@ void AndroidConfigurations::removeOldToolChains() } } +static QVariant findOrRegisterDebugger(ToolChain *tc) +{ + const FileName command = tc->suggestedDebugger(); + // check if the debugger is already registered, but ignoring the display name + const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(command); + if (existing && existing->engineType() == Debugger::GdbEngineType && existing->isAutoDetected() + && existing->abis() == QList{tc->targetAbi()}) + return existing->id(); + // debugger not found, register a new one + Debugger::DebuggerItem debugger; + debugger.setCommand(tc->suggestedDebugger()); + debugger.setEngineType(Debugger::GdbEngineType); + debugger.setUnexpandedDisplayName( + AndroidConfigurations::tr("Android Debugger for %1").arg(tc->displayName())); + debugger.setAutoDetected(true); + debugger.setAbi(tc->targetAbi()); + debugger.reinitializeFromFile(); + return Debugger::DebuggerItemManager::registerDebugger(debugger); +} + void AndroidConfigurations::updateAutomaticKitList() { const QList existingKits = Utils::filtered(KitManager::kits(), [](Kit *k) { @@ -1065,15 +1098,7 @@ void AndroidConfigurations::updateAutomaticKitList() toSetup = existingKit; } - Debugger::DebuggerItem debugger; - debugger.setCommand(tc->suggestedDebugger()); - debugger.setEngineType(Debugger::GdbEngineType); - debugger.setUnexpandedDisplayName(tr("Android Debugger for %1").arg(tc->displayName())); - debugger.setAutoDetected(true); - debugger.setAbi(tc->targetAbi()); - debugger.reinitializeFromFile(); - QVariant id = Debugger::DebuggerItemManager::registerDebugger(debugger); - Debugger::DebuggerKitInformation::setDebugger(toSetup, id); + Debugger::DebuggerKitInformation::setDebugger(toSetup, findOrRegisterDebugger(tc)); AndroidGdbServerKitInformation::setGdbSever(toSetup, currentConfig().gdbServer(tc->targetAbi())); toSetup->makeSticky(); diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index dff705bb1cd..70d97c129c5 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -134,7 +134,7 @@ public: Utils::FileName aaptToolPath() const; Utils::FileName clangPath() const; - Utils::FileName gdbPath() const; + Utils::FileName gdbPath(const ProjectExplorer::Abi &abi) const; Utils::FileName makePath() const; Utils::FileName keytoolPath() const; diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 7bbe33d0878..68c9227bf1d 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -253,9 +253,10 @@ bool AndroidRunnerWorker::uploadFile(const QString &from, const QString &to, con return false; runAdb({"shell", "run-as", m_packageName, "rm", to}); const QByteArray data = f.readAll(); + QString output; const bool res = runAdb({"shell", "run-as", m_packageName, QString("sh -c 'base64 -d > %1'").arg(to)}, - nullptr, data.toBase64()); - if (!res) + &output, data.toBase64()); + if (!res || output.contains("base64: not found")) return false; return runAdb({"shell", "run-as", m_packageName, "chmod", flags, to}); } @@ -400,13 +401,30 @@ void AndroidRunnerWorker::asyncStartHelper() // e.g. on Android 8 with NDK 10e runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir.trimmed()}); + QString gdbServerExecutable; + QString gdbServerPrefix = "./lib/"; if (m_gdbserverPath.isEmpty() || !uploadFile(m_gdbserverPath, "gdbserver")) { - emit remoteProcessFinished(tr("Cannot find/copy C++ debug server.")); - return; + // upload failed - check for old devices + QString output; + if (runAdb({"shell", "run-as", m_packageName, "ls", "lib/"}, &output)) { + for (const auto &line: output.split('\n')) { + if (line.indexOf("gdbserver") != -1/* || line.indexOf("lldb-server") != -1*/) { + gdbServerExecutable = line.trimmed(); + break; + } + } + } + if (gdbServerExecutable.isEmpty()) { + emit remoteProcessFinished(tr("Cannot find/copy C++ debug server.")); + return; + } + } else { + gdbServerPrefix = "./"; + gdbServerExecutable = "gdbserver"; } QString debuggerServerErr; - if (!startDebuggerServer(packageDir, &debuggerServerErr)) { + if (!startDebuggerServer(packageDir, gdbServerPrefix, gdbServerExecutable, &debuggerServerErr)) { emit remoteProcessFinished(debuggerServerErr); return; } @@ -450,16 +468,19 @@ void AndroidRunnerWorker::asyncStartHelper() } } -bool AndroidRunnerWorker::startDebuggerServer(QString packageDir, QString *errorStr) +bool AndroidRunnerWorker::startDebuggerServer(const QString &packageDir, + const QString &gdbServerPrefix, + const QString &gdbServerExecutable, + QString *errorStr) { QString gdbServerSocket = packageDir + "/debug-socket"; - runAdb({"shell", "run-as", m_packageName, "killall", "gdbserver"}); + runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable}); runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket}); QString gdbProcessErr; QStringList gdbServerArgs = selector(); - gdbServerArgs << "shell" << "run-as" << m_packageName << "./gdbserver" << "--multi" - << "+" + gdbServerSocket; + gdbServerArgs << "shell" << "run-as" << m_packageName << gdbServerPrefix + gdbServerExecutable + << "--multi" << "+" + gdbServerSocket; m_gdbServerProcess.reset(AndroidManager::runAdbCommandDetached(gdbServerArgs, &gdbProcessErr)); if (!m_gdbServerProcess) { diff --git a/src/plugins/android/androidrunnerworker.h b/src/plugins/android/androidrunnerworker.h index 6f166ea7c27..d61dadf453c 100644 --- a/src/plugins/android/androidrunnerworker.h +++ b/src/plugins/android/androidrunnerworker.h @@ -73,7 +73,8 @@ signals: protected: void asyncStartHelper(); - bool startDebuggerServer(QString packageDir, QString *errorStr = nullptr); + bool startDebuggerServer(const QString &packageDir, const QString &gdbServerPrefix, + const QString &gdbServerExecutable, QString *errorStr = nullptr); enum class JDBState { Idle, diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 280e1d69849..dd8d4ccfb29 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -109,7 +109,7 @@ void AndroidToolChain::addToEnvironment(Environment &env) const FileName AndroidToolChain::suggestedDebugger() const { // TODO: Make use of LLDB if available. - return AndroidConfigurations::currentConfig().gdbPath(); + return AndroidConfigurations::currentConfig().gdbPath(targetAbi()); } FileName AndroidToolChain::suggestedGdbServer() const diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp index 5eb162d6a77..053af7d8ae7 100644 --- a/src/plugins/coreplugin/documentmanager.cpp +++ b/src/plugins/coreplugin/documentmanager.cpp @@ -1195,8 +1195,8 @@ void DocumentManager::checkForReload() if (previousDeletedAnswer != FileDeletedCloseAll) { previousDeletedAnswer = fileDeletedPrompt(document->filePath().toString(), - trigger == IDocument::TriggerExternal, - QApplication::activeWindow()); + trigger == IDocument::TriggerExternal, + ICore::dialogParent()); } switch (previousDeletedAnswer) { case FileDeletedSave: diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp index 55c9c6d9ed5..d802e672505 100644 --- a/src/plugins/cpptools/builtineditordocumentparser.cpp +++ b/src/plugins/cpptools/builtineditordocumentparser.cpp @@ -50,8 +50,10 @@ static QByteArray overwrittenToolchainDefines(const ProjectPart &projectPart) return defines; } -BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath) +BuiltinEditorDocumentParser::BuiltinEditorDocumentParser(const QString &filePath, + int fileSizeLimitInMb) : BaseEditorDocumentParser(filePath) + , m_fileSizeLimitInMb(fileSizeLimitInMb) { qRegisterMetaType("CPlusPlus::Snapshot"); } @@ -191,6 +193,7 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface &futur if (releaseSourceAndAST_) doc->releaseSourceAndAST(); }); + sourceProcessor.setFileSizeLimitInMb(m_fileSizeLimitInMb); sourceProcessor.setCancelChecker([future]() { return future.isCanceled(); }); diff --git a/src/plugins/cpptools/builtineditordocumentparser.h b/src/plugins/cpptools/builtineditordocumentparser.h index 7793ebfbe41..3f53ae765ed 100644 --- a/src/plugins/cpptools/builtineditordocumentparser.h +++ b/src/plugins/cpptools/builtineditordocumentparser.h @@ -39,7 +39,7 @@ class CPPTOOLS_EXPORT BuiltinEditorDocumentParser : public BaseEditorDocumentPar Q_OBJECT public: - BuiltinEditorDocumentParser(const QString &filePath); + BuiltinEditorDocumentParser(const QString &filePath, int fileSizeLimitInMb = -1); bool releaseSourceAndAST() const; void setReleaseSourceAndAST(bool release); @@ -79,6 +79,8 @@ private: bool m_releaseSourceAndAST = true; ExtraState m_extraState; + + const int m_fileSizeLimitInMb = -1; }; } // namespace CppTools diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp index daf7ebf762f..42daa679638 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.cpp +++ b/src/plugins/cpptools/builtineditordocumentprocessor.cpp @@ -163,7 +163,8 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor( TextEditor::TextDocument *document, bool enableSemanticHighlighter) : BaseEditorDocumentProcessor(document->document(), document->filePath().toString()) - , m_parser(new BuiltinEditorDocumentParser(document->filePath().toString())) + , m_parser(new BuiltinEditorDocumentParser(document->filePath().toString(), + indexerFileSizeLimitInMb())) , m_codeWarningsUpdated(false) , m_semanticHighlighter(enableSemanticHighlighter ? new CppTools::SemanticHighlighter(document) diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 1529cb445fa..085e6fe132c 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -84,6 +84,7 @@ QStringList CompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind, undefineClangVersionMacrosForMsvc(); undefineCppLanguageFeatureMacrosForMsvc2015(); addDefineFunctionMacrosMsvc(); + addBoostWorkaroundMacros(); addToolchainFlags(); addPrecompiledHeaderOptions(pchUsage); @@ -560,6 +561,14 @@ void CompilerOptionsBuilder::addDefineFunctionMacrosMsvc() addMacros({{"__FUNCSIG__", "\"\""}, {"__FUNCTION__", "\"\""}, {"__FUNCDNAME__", "\"\""}}); } +void CompilerOptionsBuilder::addBoostWorkaroundMacros() +{ + if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID + && m_projectPart.toolchainType != ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) { + addMacros({{"BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING", "(39, 1, true, \"T = \")"}}); + } +} + QString CompilerOptionsBuilder::includeDirOptionForPath(const QString &path) const { if (m_useSystemHeader == UseSystemHeader::No diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h index 67a7345a306..66202e72d69 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.h +++ b/src/plugins/cpptools/compileroptionsbuilder.h @@ -87,6 +87,7 @@ public: void addMsvcCompatibilityVersion(); void undefineCppLanguageFeatureMacrosForMsvc2015(); void addDefineFunctionMacrosMsvc(); + void addBoostWorkaroundMacros(); void addProjectConfigFileInclude(); void undefineClangVersionMacrosForMsvc(); diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index a68ba45c3ec..a0602851ea6 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -115,6 +115,7 @@ public: void registerPerspective(Perspective *perspective); void resetCurrentPerspective(); int indexInChooser(Perspective *perspective) const; + void fixupLayoutIfNeeded(); DebuggerMainWindow *q = nullptr; Perspective *m_currentPerspective = nullptr; @@ -357,6 +358,8 @@ void DebuggerMainWindowPrivate::resetCurrentPerspective() } depopulateCurrentPerspective(); populateCurrentPerspective(); + if (m_currentPerspective) + m_currentPerspective->d->saveLayout(); } int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const @@ -364,6 +367,30 @@ int DebuggerMainWindowPrivate::indexInChooser(Perspective *perspective) const return perspective ? m_perspectiveChooser->findData(perspective->d->m_id) : -1; } +void DebuggerMainWindowPrivate::fixupLayoutIfNeeded() +{ + // Evil workaround for QTCREATORBUG-21455: In some so far unknown situation + // the saveLayout/restoreLayout process leads to a situation where some docks + // does not end up below the perspective toolbar even though they were there + // initially, leading to an awkward dock layout. + // This here tries to detect the situation (no other dock directly below the + // toolbar) and "corrects" that by restoring the default layout. + const QRect toolbarRect = m_toolBarDock->geometry(); + const int targetX = toolbarRect.left(); + const int targetY = toolbarRect.bottom(); + + const QList docks = q->dockWidgets(); + for (QDockWidget *dock : docks) { + const QRect dockRect = dock->geometry(); + // 10 for some decoration wiggle room. Found something below? Good. + if (targetX == dockRect.left() && qAbs(targetY - dockRect.top()) < 10) + return; + } + + qDebug() << "Scrambled dock layout found. Resetting it."; + resetCurrentPerspective(); +} + void DebuggerMainWindowPrivate::selectPerspective(Perspective *perspective) { QTC_ASSERT(perspective, return); @@ -381,8 +408,10 @@ void DebuggerMainWindowPrivate::selectPerspective(Perspective *perspective) populateCurrentPerspective(); - if (m_currentPerspective) + if (m_currentPerspective) { m_currentPerspective->d->restoreLayout(); + fixupLayoutIfNeeded(); + } int index = indexInChooser(m_currentPerspective); if (index == -1) { @@ -450,6 +479,8 @@ void DebuggerMainWindowPrivate::populateCurrentPerspective() ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd); } + m_currentPerspective->d->showToolBar(); + // Pre-arrange dock widgets. for (const DockOperation &op : m_currentPerspective->d->m_dockOperations) { QTC_ASSERT(op.widget, continue); @@ -483,8 +514,6 @@ void DebuggerMainWindowPrivate::populateCurrentPerspective() dock->setVisible(op.visibleByDefault); } - m_currentPerspective->d->showToolBar(); - QWidget *central = m_currentPerspective->centralWidget(); m_centralWidgetStack->addWidget(central ? central : m_editorPlaceHolder); q->showCentralWidgetAction()->setText(central ? central->windowTitle() diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index db8395281ad..c7b34e02ab6 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -757,6 +757,7 @@ void GdbEngine::runCommand(const DebuggerCommand &command) if (state() == InferiorRunOk) { showStatusMessage(tr("Stopping temporarily."), 1000); m_onStop.append(cmd, wantContinue); + setState(InferiorStopRequested); interruptInferior(); return; } diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp index 036505dc99f..3cc82f5c459 100644 --- a/src/plugins/git/gerrit/gerritplugin.cpp +++ b/src/plugins/git/gerrit/gerritplugin.cpp @@ -317,11 +317,11 @@ void GerritPlugin::addToLocator(CommandLocator *locator) void GerritPlugin::push(const QString &topLevel) { // QScopedPointer is required to delete the dialog when leaving the function - GerritPushDialog dialog(topLevel, m_reviewers, m_parameters, ICore::mainWindow()); + GerritPushDialog dialog(topLevel, m_reviewers, m_parameters, ICore::dialogParent()); const QString initErrorMessage = dialog.initErrorMessage(); if (!initErrorMessage.isEmpty()) { - QMessageBox::warning(ICore::mainWindow(), tr("Initialization Failed"), initErrorMessage); + QMessageBox::warning(ICore::dialogParent(), tr("Initialization Failed"), initErrorMessage); return; } @@ -348,7 +348,7 @@ void GerritPlugin::openView() if (!ICore::showOptionsDialog("Gerrit")) return; } - GerritDialog *gd = new GerritDialog(m_parameters, m_server, currentRepository(), ICore::mainWindow()); + GerritDialog *gd = new GerritDialog(m_parameters, m_server, currentRepository(), ICore::dialogParent()); gd->setModal(false); connect(gd, &GerritDialog::fetchDisplay, this, [this](const QSharedPointer &change) { fetch(change, FetchDisplay); }); @@ -431,7 +431,7 @@ void GerritPlugin::fetch(const QSharedPointer &change, int mode) if (!verifiedRepository) { QMessageBox::StandardButton answer = QMessageBox::question( - ICore::mainWindow(), tr("Remote Not Verified"), + ICore::dialogParent(), tr("Remote Not Verified"), tr("Change host %1\nand project %2\n\nwere not verified among remotes" " in %3. Select different folder?") .arg(m_server->host, diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp index e9dee455658..9e85606c76f 100644 --- a/src/plugins/git/gerrit/gerritserver.cpp +++ b/src/plugins/git/gerrit/gerritserver.cpp @@ -301,7 +301,7 @@ bool GerritServer::resolveRoot() return setupAuthentication(); case CertificateError: if (QMessageBox::question( - Core::ICore::mainWindow(), + Core::ICore::dialogParent(), QCoreApplication::translate( "Gerrit::Internal::GerritDialog", "Certificate Error"), QCoreApplication::translate( diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index f06acb85559..e5b63feb22f 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1144,7 +1144,7 @@ QStringList GitClient::setupCheckoutArguments(const QString &workingDirectory, return arguments; if (Utils::CheckableMessageBox::doNotAskAgainQuestion( - ICore::mainWindow() /*parent*/, + ICore::dialogParent() /*parent*/, tr("Create Local Branch") /*title*/, tr("Would you like to create a local branch?") /*message*/, ICore::settings(), "Git.CreateLocalBranchOnCheckout" /*setting*/, @@ -1181,7 +1181,7 @@ QStringList GitClient::setupCheckoutArguments(const QString &workingDirectory, } } - BranchAddDialog branchAddDialog(localBranches, true, ICore::mainWindow()); + BranchAddDialog branchAddDialog(localBranches, true, ICore::dialogParent()); branchAddDialog.setTrackedBranchName(remoteBranch, true); if (branchAddDialog.exec() != QDialog::Accepted) @@ -1207,7 +1207,7 @@ void GitClient::reset(const QString &workingDirectory, const QString &argument, if (argument == "--hard") { if (gitStatus(workingDirectory, StatusMode(NoUntracked | NoSubmodules)) != StatusUnchanged) { if (QMessageBox::question( - Core::ICore::mainWindow(), tr("Reset"), + Core::ICore::dialogParent(), tr("Reset"), tr("All changes in working directory will be discarded. Are you sure?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) { @@ -1660,7 +1660,7 @@ QString GitClient::synchronousStash(const QString &workingDirectory, const QStri message = creatorStashMessage(messageKeyword); do { if ((flags & StashPromptDescription)) { - if (!inputText(ICore::mainWindow(), + if (!inputText(ICore::dialogParent(), tr("Stash Description"), tr("Description:"), &message)) break; } @@ -2058,7 +2058,7 @@ void GitClient::updateSubmodulesIfNeeded(const QString &workingDirectory, bool p if (!updateNeeded) return; - if (prompt && QMessageBox::question(ICore::mainWindow(), tr("Submodules Found"), + if (prompt && QMessageBox::question(ICore::dialogParent(), tr("Submodules Found"), tr("Would you like to update submodules?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { return; @@ -2226,7 +2226,7 @@ void GitClient::continuePreviousGitCommand(const QString &workingDirectory, } QMessageBox msgBox(QMessageBox::Question, msgBoxTitle, msgBoxText, - QMessageBox::NoButton, ICore::mainWindow()); + QMessageBox::NoButton, ICore::dialogParent()); if (hasChanges || isRebase) msgBox.addButton(hasChanges ? buttonName : tr("Skip"), QMessageBox::AcceptRole); msgBox.addButton(QMessageBox::Abort); @@ -2808,7 +2808,7 @@ GitClient::RevertResult GitClient::revertI(QStringList files, // Ask to revert (to do: Handle lists with a selection dialog) const QMessageBox::StandardButton answer - = QMessageBox::question(ICore::mainWindow(), + = QMessageBox::question(ICore::dialogParent(), tr("Revert"), tr("The file has been changed. Do you want to revert it?"), QMessageBox::Yes | QMessageBox::No, @@ -2950,7 +2950,7 @@ void GitClient::handleMergeConflicts(const QString &workingDir, const QString &c message = tr("Conflicts detected."); } QMessageBox mergeOrAbort(QMessageBox::Question, tr("Conflicts Detected"), message, - QMessageBox::NoButton, ICore::mainWindow()); + QMessageBox::NoButton, ICore::dialogParent()); QPushButton *mergeToolButton = mergeOrAbort.addButton(tr("Run &Merge Tool"), QMessageBox::AcceptRole); const QString mergeTool = readConfigValue(workingDir, "merge.tool"); @@ -3304,7 +3304,7 @@ void GitClient::StashInfo::stashPrompt(const QString &command, const QString &st QMessageBox msgBox(QMessageBox::Question, tr("Uncommitted Changes Found"), tr("What would you like to do with local changes in:") + "\n\n" + QDir::toNativeSeparators(m_workingDir) + '\"', - QMessageBox::NoButton, ICore::mainWindow()); + QMessageBox::NoButton, ICore::dialogParent()); msgBox.setDetailedText(statusOutput); diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index eee8f57c147..924f1da5e22 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -797,7 +797,7 @@ void GitPlugin::resetRepository() QTC_ASSERT(state.hasTopLevel(), return); QString topLevel = state.topLevel(); - LogChangeDialog dialog(true, ICore::mainWindow()); + LogChangeDialog dialog(true, ICore::dialogParent()); ResetItemDelegate delegate(dialog.widget()); dialog.setWindowTitle(tr("Undo Changes to %1").arg(QDir::toNativeSeparators(topLevel))); if (dialog.runDialog(topLevel, QString(), LogChangeWidget::IncludeRemotes)) @@ -822,7 +822,7 @@ void GitPlugin::startRebase() const QString topLevel = state.topLevel(); if (topLevel.isEmpty() || !m_gitClient->canRebase(topLevel)) return; - LogChangeDialog dialog(false, ICore::mainWindow()); + LogChangeDialog dialog(false, ICore::dialogParent()); RebaseItemDelegate delegate(dialog.widget()); dialog.setWindowTitle(tr("Interactive Rebase")); if (!dialog.runDialog(topLevel)) @@ -836,7 +836,7 @@ void GitPlugin::startChangeRelatedAction(const Id &id) const VcsBasePluginState state = currentState(); ChangeSelectionDialog dialog(state.hasTopLevel() ? state.topLevel() : PathChooser::homePath(), - id, ICore::mainWindow()); + id, ICore::dialogParent()); int result = dialog.exec(); @@ -1234,7 +1234,7 @@ void GitPlugin::applyPatch(const QString &workingDirectory, QString file) // Prompt for file if (file.isEmpty()) { const QString filter = tr("Patches (*.patch *.diff)"); - file = QFileDialog::getOpenFileName(ICore::mainWindow(), tr("Choose Patch"), QString(), filter); + file = QFileDialog::getOpenFileName(ICore::dialogParent(), tr("Choose Patch"), QString(), filter); if (file.isEmpty()) { m_gitClient->endStashScope(workingDirectory); return; @@ -1302,7 +1302,7 @@ template dialog->show(); dialog->raise(); } else { - dialog = new NonModalDialog(ICore::mainWindow()); + dialog = new NonModalDialog(ICore::dialogParent()); dialog->refresh(topLevel, true); dialog->show(); } diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 4847d8863e0..d2ccce72dcf 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -527,7 +527,8 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags, // // For _MSV_VER values, see https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017. // -LanguageVersion MsvcToolChain::msvcLanguageVersion(const Core::Id &language, +LanguageVersion MsvcToolChain::msvcLanguageVersion(const QStringList & /*cxxflags*/, + const Core::Id &language, const Macros ¯os) const { int mscVer = -1; @@ -1368,6 +1369,10 @@ void ClangClToolChain::resetMsvcToolChain(const MsvcToolChain *base) m_abi = base->targetAbi(); m_vcvarsBat = base->varsBat(); setVarsBatArg(base->varsBatArg()); + + initEnvModWatcher(Utils::runAsync(envModThreadPool(), + &ClangClToolChain::environmentModifications, + m_vcvarsBat, base->varsBatArg())); } bool ClangClToolChain::operator ==(const ToolChain &other) const @@ -1382,6 +1387,9 @@ bool ClangClToolChain::operator ==(const ToolChain &other) const Macros ClangClToolChain::msvcPredefinedMacros(const QStringList cxxflags, const Utils::Environment &env) const { + if (!cxxflags.contains("--driver-mode=g++")) + return MsvcToolChain::msvcPredefinedMacros(cxxflags, env); + Utils::SynchronousProcess cpp; cpp.setEnvironment(env.toStringList()); cpp.setWorkingDirectory(Utils::TemporaryDirectory::masterDirectoryPath()); @@ -1400,10 +1408,13 @@ Macros ClangClToolChain::msvcPredefinedMacros(const QStringList cxxflags, return Macro::toMacros(response.allRawOutput()); } -LanguageVersion ClangClToolChain::msvcLanguageVersion(const Core::Id &language, +LanguageVersion ClangClToolChain::msvcLanguageVersion(const QStringList &cxxflags, + const Core::Id &language, const Macros ¯os) const { - return ToolChain::languageVersion(language, macros); + if (cxxflags.contains("--driver-mode=g++")) + return ToolChain::languageVersion(language, macros); + return MsvcToolChain::msvcLanguageVersion(cxxflags, language, macros); } // -------------------------------------------------------------------------- diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index eff342481ac..3b4f5bde5c6 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -139,10 +139,10 @@ protected: // Function must be thread-safe! virtual Macros msvcPredefinedMacros(const QStringList cxxflags, const Utils::Environment &env) const; - virtual LanguageVersion msvcLanguageVersion(const Core::Id &language, + virtual LanguageVersion msvcLanguageVersion(const QStringList &cxxflags, + const Core::Id &language, const Macros ¯os) const; -private: struct GenerateEnvResult { Utils::optional error; @@ -151,6 +151,8 @@ private: static void environmentModifications(QFutureInterface &future, QString vcvarsBat, QString varsBatArg); void initEnvModWatcher(const QFuture &future); + +private: void updateEnvironmentModifications(QList modifications); mutable QList m_environmentModifications; @@ -198,7 +200,8 @@ public: void resetMsvcToolChain(const MsvcToolChain *base = nullptr); Macros msvcPredefinedMacros(const QStringList cxxflags, const Utils::Environment &env) const override; - LanguageVersion msvcLanguageVersion(const Core::Id &language, + LanguageVersion msvcLanguageVersion(const QStringList &cxxflags, + const Core::Id &language, const Macros ¯os) const override; bool operator ==(const ToolChain &) const override; diff --git a/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp index a44bbadcdaf..50ad27afe8e 100644 --- a/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp @@ -60,7 +60,7 @@ void ResizeHandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * painter->setPen(pen); painter->setRenderHint(QPainter::Antialiasing, false); painter->setBrush(QColor(255, 255, 255)); - painter->drawRect(QRectF(-2., -2., 4., 4.)); + painter->drawRect(QRectF(-3., -3., 5., 5.)); painter->restore(); } diff --git a/tests/system/suite_WELP/tst_WELP01/test.py b/tests/system/suite_WELP/tst_WELP01/test.py index 49c5876d940..ce07f4fdaf3 100755 --- a/tests/system/suite_WELP/tst_WELP01/test.py +++ b/tests/system/suite_WELP/tst_WELP01/test.py @@ -156,7 +156,7 @@ def main(): for (qType, prop, info) in expect: test.verify(checkIfObjectExists(search % (qType, prop)), "Verifying whether %s is shown" % info) - checkTableViewForContent(search % (expect[0][0], expect[0][1]), "Help: Create .*", "Tutorials", + checkTableViewForContent(search % (expect[0][0], expect[0][1]), "Help: Creating .*", "Tutorials", "Verifying that at least one tutorial is displayed.") # exit Qt Creator invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_WELP/tst_WELP04/test.py b/tests/system/suite_WELP/tst_WELP04/test.py index 27e3f5d007d..f66efba6c57 100644 --- a/tests/system/suite_WELP/tst_WELP04/test.py +++ b/tests/system/suite_WELP/tst_WELP04/test.py @@ -50,11 +50,13 @@ def main(): tutorial = findExampleOrTutorial(tableView, ".*", True) test.verify(tutorial is None, "Verifying: 'Tutorials' topic is opened and nothing is shown.") - bnr = "Help: Build and Run Examples" + bnr = "Help: Building and Running an Example" replaceEditorContent(searchTutorials, bnr.lower()) waitFor('findExampleOrTutorial(tableView, "%s.*") is not None' % bnr, 3000) tutorial = findExampleOrTutorial(tableView, "%s.*" % bnr, True) test.verify(tutorial is not None, "Verifying: Expected Text tutorial is shown.") + # clicking before documentation was updated will open the tutorial in browser + progressBarWait(warn=False) # select a text tutorial mouseClick(tutorial) test.verify("Building and Running an Example" in diff --git a/tests/system/suite_qtquick/tst_qml_outline/test.py b/tests/system/suite_qtquick/tst_qml_outline/test.py index b55cfaf367d..4c0c5e8a037 100644 --- a/tests/system/suite_qtquick/tst_qml_outline/test.py +++ b/tests/system/suite_qtquick/tst_qml_outline/test.py @@ -140,8 +140,12 @@ def verifyOutline(outlinePseudoTree, datasetFileName): return for counter, (expectedItem, foundItem) in enumerate(zip(expected, outlinePseudoTree)): if expectedItem != foundItem: - test.fail("Mismatch in element number %d for '%s'" % (counter + 1, fileName), - "%s != %s" % (str(expectedItem), str(foundItem))) + if JIRA.isBugStillOpen(21335) and expectedItem[:-1] == foundItem[:-1]: + test.xfail("Mismatch in element number %d for '%s'" % (counter + 1, fileName), + "%s != %s" % (str(expectedItem), str(foundItem))) + else: + test.fail("Mismatch in element number %d for '%s'" % (counter + 1, fileName), + "%s != %s" % (str(expectedItem), str(foundItem))) return test.passes("All nodes (%d) inside outline match expected nodes for '%s'." % (len(expected), fileName))