diff --git a/dist/changes-4.3.0.md b/dist/changes-4.3.0.md index b133f9f5578..00ba10a041e 100644 --- a/dist/changes-4.3.0.md +++ b/dist/changes-4.3.0.md @@ -13,10 +13,19 @@ General (experimental `SilverSearcher` plugin) * Added exclusion patterns to `Advanced Find` and custom locator filters * Added navigation pane on right side of edit mode +* Fixed wrong UI colors after suspend (QTCREATORBUG-14929) +* Fixed crash with invalid themes (QTCREATORBUG-17517) + +Help + +* Fixed that help bookmarks got lost (QTCREATORBUG-17537) Editing * Added optional shortcut for duplicating current selection +* Adapted to changes of code pasting services + (QTCREATORBUG-17942, QTCREATORBUG-18192) +* Fixed freeze when highlighting `Kconfig` file (QTCREATORBUG-14611) All Projects @@ -29,6 +38,7 @@ QMake Projects * Fixed wrong warning when specifying absolute path to mkspec (QTCREATORBUG-17237) +* Fixed deployment of symlinks for versioned shared libraries CMake Projects @@ -39,6 +49,7 @@ CMake Projects * Added header files to project tree, even if not listed explicitly in project files * Added import of configuration of existing builds +* Fixed `Build > Clean` Generic Projects @@ -62,6 +73,9 @@ QML Support * Added option to automatically format QML files on save * Added menu item for adding expression evaluators from QML code editor (QTCREATORBUG-17754) +* Fixed reformatting of signals (QTCREATORBUG-17886) +* Fixed issues with jumping text cursor while editing + (QTCREATORBUG-15680, QTCREATORBUG-17413) Nim Support @@ -72,11 +86,15 @@ Nim Support Debugging -* Added pretty printing of `unordered_multi(set|map)` +* Added pretty printing of `unordered_multi(set|map)`, `boost::variant` and + `QLazilyAllocated` * Fixed that expression evaluators were not evaluated when added (QTCREATORBUG-17763) * QML * Fixed accessing items by `id` in `Debugger Console` (QTCREATORBUG-17177) +* GDB + * Fixed issue with templated types that are pretty printed differently + depending on argument type (`std::vector` versus `std::vector`) * CDB * Changed to Python based pretty printing backend, resulting in faster startup and more, faster, and unified pretty printers @@ -88,6 +106,7 @@ QML Profiler * Improved error and progress reporting for loading and saving trace files * Fixed pixmap cache size information when loading profile (QTCREATORBUG-17424) +* Fixed UI issues (QTCREATORBUG-17939, QTCREATORBUG-17937) Qt Quick Designer @@ -98,8 +117,13 @@ Qt Quick Designer * Added support for `qsTranslate` (QTCREATORBUG-17714) * Added actions for adding items, selecting visible item, and adding tab bar to stacked containers +* Fixed that `Dialog` was not allowed in `.ui.qml` files * Fixed that error messages could be shown twice * Fixed handling of escaped unicode characters (QTCREATORBUG-12616) +* Fixed that document needed to be manually re-opened after type information + became available +* Fixed crash when root item is layout +* Fixed that expressions were not shown in URL input field (QTCREATORBUG-13328) Version Control Systems @@ -138,16 +162,28 @@ Windows * Fixed that it was not possible to save files with arbitrary extension (QTCREATORBUG-15862) +* Fixed ABI detection for Clang +* Fixed that ABI of MSVC2017 was considered different from ABI of MSVC2015 + (QTCREATORBUG-17740) + +Linux + +* Worked around issue that Unity menu bar vanished after editing main window in + Design mode (QTCREATORBUG-17519) Android * Improved package signing (QTCREATORBUG-17545, QTCREATORBUG-17304) +* Fixed issues with new Android SDK (25.3.1) + (QTCREATORBUG-17814, QTCREATORBUG-18013) +* Fixed debugging of release builds iOS * Added option to select developer team and provisioning profile used for signing (QTCREATORBUG-16936) * Fixed that starting simulator blocked Qt Creator +* Fixed `Run Without Deployment` on Simulator (QTCREATORBUG-18107) Remote Linux diff --git a/doc/images/qtcreator-options-android1.png b/doc/images/qtcreator-options-android1.png index 1360b49cb61..a6086790f5b 100644 Binary files a/doc/images/qtcreator-options-android1.png and b/doc/images/qtcreator-options-android1.png differ diff --git a/doc/src/android/androiddev.qdoc b/doc/src/android/androiddev.qdoc index 247009d6f01..5d57ce1beb3 100644 --- a/doc/src/android/androiddev.qdoc +++ b/doc/src/android/androiddev.qdoc @@ -69,12 +69,25 @@ \endlist \li A tool chain for building applications for Android devices provided - by the - \l{http://developer.android.com/sdk/index.html}{Android SDK} and - \l{http://developer.android.com/tools/sdk/ndk/index.html} + by the \l{http://developer.android.com/tools/sdk/ndk/index.html} {Android NDK} from Google. - \note Android Studio is currently not supported by \QC. + \li \l{http://developer.android.com/sdk/index.html}{Android SDK Tools} + + After installing the Tools, update the Android SDK to get the API + and tools packages required for development. You can use the + \l{http://developer.android.com/tools/help/android.html}{android} + tool that comes with the SDK Tools package. For example, on Ubuntu + the following command starts the SDK update: + + \code + ./android update sdk + \endcode + + \note The android tool is deprecated since SDK tools version 25.3.0. + Consider using + \l{https://developer.android.com/studio/command-line/sdkmanager.html} + {sdkmanager} instead. \li On Windows, you also need the following: @@ -95,18 +108,6 @@ \endlist - After installing these tools, update the Android SDK to get the API - and tools packages required for development. You can use the - \l{http://developer.android.com/tools/help/android.html}{android} tool - that comes with the SDK Tools package. For example, on Ubuntu the - following command starts the - \l{http://developer.android.com/sdk/installing/adding-packages.html} - {Android SDK Manager}, where you can select the packages to install: - - \code - ./android update sdk - \endcode - \section1 Selecting the APK Build Tool On Android, applications are distributed in specially structured type of ZIP @@ -117,7 +118,7 @@ \li It is 25 to 50 percent faster than Ant when rebuilding packages. - \li It is integrated with Android Studio. + \li It is delivered with Qt 5.9. \li It supports easily adding Android Extras libraries, such as Google Play services or Android extension files (.obb) to your @@ -125,6 +126,10 @@ \endlist + \note Android SDK tools version 25.3.0 onwards do not contain Ant scripts + anymore. Therefore, Gradle builds are forced and you must use Qt 5.9 or + later when using these tools versions. + \section1 Setting Up the Development Environment You must download and install the latest Android NDK and SDK, and update the diff --git a/doc/src/projects/creator-projects-targets.qdoc b/doc/src/projects/creator-projects-targets.qdoc index 9617b8addcd..e3366e84895 100644 --- a/doc/src/projects/creator-projects-targets.qdoc +++ b/doc/src/projects/creator-projects-targets.qdoc @@ -126,7 +126,8 @@ CMake tools to the list. For more information, see \l{Adding CMake Tools}. - \li In the \uicontrol {CMake Generator} field, select the CMake + \li In the \uicontrol {CMake generator} field, select \uicontrol Change + to edit the CMake Generator to use for producing project files. Only the generators with names beginning with the string \uicontrol CodeBlocks produce all the necessary data for the \QC code model. \QC displays a diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 85e57e2af62..a468419819b 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -1390,7 +1390,7 @@ class DumperBase: n = (10, 100, 1000, 10000)[displayFormat - Array10Format] self.putType(typeName) self.putItemCount(n) - self.putArrayData(value.address(), n, innerType) + self.putArrayData(value.pointer(), n, innerType) return if innerType.code == TypeCodeFunction: diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp index 69f2694815b..9579699af19 100644 --- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp +++ b/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp @@ -6,6 +6,8 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; return app.exec(); } diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp index a15a1f0b569..31af279601e 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp @@ -10,6 +10,8 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; return app.exec(); } diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp index e08a85e3fde..cabbb206e3c 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp +++ b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp @@ -11,6 +11,8 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; return app.exec(); } diff --git a/src/app/main.cpp b/src/app/main.cpp index 315108195a5..d7c92a6c92f 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -220,6 +220,25 @@ static inline QStringList getPluginPaths() return rc; } +static void setupInstallSettings() +{ + // Check if the default install settings contain a setting for the actual install settings. + // This can be an absolute path, or a path relative to applicationDirPath(). + // The result is interpreted like -settingspath, but for SystemScope + static const char kInstallSettingsKey[] = "Settings/InstallSettings"; + QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope, + QCoreApplication::applicationDirPath() + '/' + RELATIVE_DATA_PATH); + QSettings installSettings(QSettings::IniFormat, QSettings::UserScope, + QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR), + QLatin1String("QtCreator")); + if (installSettings.contains(kInstallSettingsKey)) { + QString installSettingsPath = installSettings.value(kInstallSettingsKey).toString(); + if (QDir::isRelativePath(installSettingsPath)) + installSettingsPath = QCoreApplication::applicationDirPath() + '/' + installSettingsPath; + QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope, installSettingsPath); + } +} + static QSettings *createUserSettings() { return new QSettings(QSettings::IniFormat, QSettings::UserScope, @@ -363,9 +382,8 @@ int main(int argc, char **argv) QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, settingsPath); // Must be done before any QSettings class is created - QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope, - QCoreApplication::applicationDirPath() + '/' + RELATIVE_DATA_PATH); QSettings::setDefaultFormat(QSettings::IniFormat); + setupInstallSettings(); // plugin manager takes control of this settings object QSettings *settings = userSettings(); diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index bd7073ead8f..911b46d9067 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -569,7 +569,6 @@ public: "ShaderEffect", "ShaderEffectSource", "Component", - "Loader", "Transition", "PropertyAnimation", "SequentialAnimation", diff --git a/src/libs/utils/mapreduce.h b/src/libs/utils/mapreduce.h index 8c5452f79dc..81f8968d3fe 100644 --- a/src/libs/utils/mapreduce.h +++ b/src/libs/utils/mapreduce.h @@ -57,17 +57,20 @@ protected: public: MapReduceBase(QFutureInterface futureInterface, ForwardIterator begin, ForwardIterator end, MapFunction &&map, State &state, ReduceFunction &&reduce, - MapReduceOption option, int size) + MapReduceOption option, QThreadPool *pool, int size) : m_futureInterface(futureInterface), m_iterator(begin), m_end(end), m_map(std::forward(map)), m_state(state), m_reduce(std::forward(reduce)), + m_threadPool(pool), m_handleProgress(size >= 0), m_size(size), m_option(option) { + if (!m_threadPool) + m_threadPool = new QThreadPool(this); if (m_handleProgress) // progress is handled by us m_futureInterface.setProgressRange(0, MAX_PROGRESS); connect(&m_selfWatcher, &QFutureWatcher::canceled, @@ -88,7 +91,8 @@ protected: bool schedule() { bool didSchedule = false; - while (m_iterator != m_end && m_mapWatcher.size() < QThread::idealThreadCount()) { + while (m_iterator != m_end + && m_mapWatcher.size() < std::max(m_threadPool->maxThreadCount(), 1)) { didSchedule = true; auto watcher = new QFutureWatcher(); connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { @@ -103,7 +107,7 @@ protected: m_mapWatcher.append(watcher); m_watcherIndex.append(m_currentIndex); ++m_currentIndex; - watcher->setFuture(runAsync(&m_threadPool, std::cref(m_map), + watcher->setFuture(runAsync(m_threadPool, std::cref(m_map), ItemReferenceWrapper(*m_iterator))); ++m_iterator; } @@ -165,7 +169,7 @@ protected: State &m_state; ReduceFunction m_reduce; QEventLoop m_loop; - QThreadPool m_threadPool; // for reusing threads + QThreadPool *m_threadPool; // for reusing threads QList *> m_mapWatcher; QList m_watcherIndex; int m_currentIndex = 0; @@ -182,9 +186,10 @@ class MapReduce : public MapReduceBase; public: MapReduce(QFutureInterface futureInterface, ForwardIterator begin, ForwardIterator end, - MapFunction &&map, State &state, ReduceFunction &&reduce, MapReduceOption option, int size) + MapFunction &&map, State &state, ReduceFunction &&reduce, MapReduceOption option, + QThreadPool *pool, int size) : BaseType(futureInterface, begin, end, std::forward(map), state, - std::forward(reduce), option, size) + std::forward(reduce), option, pool, size) { } @@ -230,9 +235,10 @@ class MapReduce; public: MapReduce(QFutureInterface futureInterface, ForwardIterator begin, ForwardIterator end, - MapFunction &&map, State &state, ReduceFunction &&reduce, MapReduceOption option, int size) + MapFunction &&map, State &state, ReduceFunction &&reduce, MapReduceOption option, + QThreadPool *pool, int size) : BaseType(futureInterface, begin, end, std::forward(map), state, - std::forward(reduce), option, size) + std::forward(reduce), option, pool, size) { } @@ -274,13 +280,13 @@ template &futureInterface, ForwardIterator begin, ForwardIterator end, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, - MapReduceOption option, int size) + MapReduceOption option, QThreadPool *pool, int size) { auto state = callWithMaybeFutureInterface (futureInterface, std::forward(init)); MapReduce::type, MapFunction, decltype(state), ReduceResult, ReduceFunction> mr(futureInterface, begin, end, std::forward(map), state, - std::forward(reduce), option, size); + std::forward(reduce), option, pool, size); mr.exec(); callWithMaybeFutureInterface&> (futureInterface, std::forward(cleanup), state); @@ -291,13 +297,13 @@ template &futureInterface, Container &&container, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, - MapReduceOption option) + MapReduceOption option, QThreadPool *pool) { blockingIteratorMapReduce(futureInterface, std::begin(container), std::end(container), std::forward(init), std::forward(map), std::forward(reduce), std::forward(cleanup), - option, static_cast(container.size())); + option, pool, static_cast(container.size())); } template &futureInterfa std::reference_wrapper containerWrapper, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, - MapReduceOption option) + MapReduceOption option, QThreadPool *pool) { blockingContainerMapReduce(futureInterface, containerWrapper.get(), std::forward(init), std::forward(map), std::forward(reduce), std::forward(cleanup), - option); + option, pool); } template @@ -371,7 +377,7 @@ QFuture mapReduce(ForwardIterator begin, ForwardIterator end, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, MapReduceOption option = MapReduceOption::Unordered, - QThread::Priority priority = QThread::InheritPriority, + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority, int size = -1) { return runAsync(priority, @@ -384,7 +390,7 @@ mapReduce(ForwardIterator begin, ForwardIterator end, InitFunction &&init, MapFu std::decay_t>, begin, end, std::forward(init), std::forward(map), std::forward(reduce), std::forward(cleanup), - option, size); + option, pool, size); } /*! @@ -443,7 +449,7 @@ QFuture mapReduce(Container &&container, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, MapReduceOption option = MapReduceOption::Unordered, - QThread::Priority priority = QThread::InheritPriority) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority) { return runAsync(priority, Internal::blockingContainerMapReduce< @@ -456,7 +462,7 @@ mapReduce(Container &&container, InitFunction &&init, MapFunction &&map, std::forward(container), std::forward(init), std::forward(map), std::forward(reduce), std::forward(cleanup), - option); + option, pool); } template mapReduce(std::reference_wrapper containerWrapper, InitFunction &&init, MapFunction &&map, ReduceFunction &&reduce, CleanUpFunction &&cleanup, MapReduceOption option = MapReduceOption::Unordered, - QThread::Priority priority = QThread::InheritPriority) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority) { return runAsync(priority, Internal::blockingContainerRefMapReduce< @@ -479,7 +485,7 @@ mapReduce(std::reference_wrapper containerWrapper, InitFunction &&ini containerWrapper, std::forward(init), std::forward(map), std::forward(reduce), std::forward(cleanup), - option); + option, pool); } template mapReduce(ForwardIterator begin, ForwardIterator end, MapFunction &&map, State &&initialState, ReduceFunction &&reduce, MapReduceOption option = MapReduceOption::Unordered, - QThread::Priority priority = QThread::InheritPriority, int size = -1) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority, + int size = -1) { return mapReduce(begin, end, Internal::StateWrapper(std::forward(initialState)), std::forward(map), Internal::ReduceWrapper(std::forward(reduce)), &Internal::cleanupReportingState, - option, priority, size); + option, pool, priority, size); } template mapReduce(Container &&container, MapFunction &&map, State &&initialState, ReduceFunction &&reduce, MapReduceOption option = MapReduceOption::Unordered, - QThread::Priority priority = QThread::InheritPriority) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority) { return mapReduce(std::forward(container), Internal::StateWrapper(std::forward(initialState)), std::forward(map), Internal::ReduceWrapper(std::forward(reduce)), &Internal::cleanupReportingState, - option, priority); + option, pool, priority); } template (map), std::forward(initialState), std::forward(reduce), - option, priority, size).result(); + option, pool, priority, size).result(); } template (container), std::forward(map), std::forward(initialState), std::forward(reduce), - option, priority).result(); + option, pool, priority).result(); } template map(ForwardIterator begin, ForwardIterator end, MapFunction &&map, MapReduceOption option = MapReduceOption::Ordered, - QThread::Priority priority = QThread::InheritPriority, int size = -1) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority, + int size = -1) { return mapReduce(begin, end, &Internal::dummyInit, std::forward(map), Internal::DummyReduce(), &Internal::dummyCleanup, - option, priority, size); + option, pool, priority, size); } template ::type> QFuture map(Container &&container, MapFunction &&map, MapReduceOption option = MapReduceOption::Ordered, - QThread::Priority priority = QThread::InheritPriority) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority) { return mapReduce(std::forward(container), Internal::dummyInit, std::forward(map), Internal::DummyReduce(), Internal::dummyCleanup, - option, priority); + option, pool, priority); } template class ResultContainer, typename ForwardIterator, typename MapFunction, @@ -578,11 +587,11 @@ Q_REQUIRED_RESULT ResultContainer mapped(ForwardIterator begin, ForwardIterator end, MapFunction &&mapFun, MapReduceOption option = MapReduceOption::Ordered, - QThread::Priority priority = QThread::InheritPriority, int size = -1) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority, int size = -1) { return Utils::transform(map(begin, end, std::forward(mapFun), - option, priority, size).results(), + option, pool, priority, size).results(), [](const MapResult &r) { return r; }); } @@ -592,11 +601,11 @@ Q_REQUIRED_RESULT ResultContainer mapped(Container &&container, MapFunction &&mapFun, MapReduceOption option = MapReduceOption::Ordered, - QThread::Priority priority = QThread::InheritPriority) + QThreadPool *pool = nullptr, QThread::Priority priority = QThread::InheritPriority) { return Utils::transform(map(container, std::forward(mapFun), - option, priority).results(), + option, pool, priority).results(), [](const MapResult &r) { return r; }); } diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 1287f4946fa..0aa9b46740b 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -1001,9 +1001,16 @@ void AndroidConfigurations::removeOldToolChains() void AndroidConfigurations::updateAutomaticKitList() { - const QList existingKits = Utils::filtered(KitManager::kits(), [](const Kit *k) { - return k->isAutoDetected() && !k->isSdkProvided() - && DeviceTypeKitInformation::deviceTypeId(k) == Core::Id(Constants::ANDROID_DEVICE_TYPE); + const QList existingKits = Utils::filtered(KitManager::kits(), [](Kit *k) { + Core::Id deviceTypeId = DeviceTypeKitInformation::deviceTypeId(k); + if (k->isAutoDetected() && !k->isSdkProvided() + && deviceTypeId == Core::Id(Constants::ANDROID_DEVICE_TYPE)) { + if (!QtSupport::QtKitInformation::qtVersion(k)) + KitManager::deregisterKit(k); // Remove autoDetected kits without Qt. + else + return true; + } + return false; }); // Update code for 3.0 beta, which shipped with a bug for the debugger settings @@ -1044,7 +1051,6 @@ void AndroidConfigurations::updateAutomaticKitList() } // register new kits - QList newKits; const QList tmp = ToolChainManager::toolChains([](const ToolChain *tc) { return tc->isAutoDetected() && tc->isValid() @@ -1061,19 +1067,27 @@ void AndroidConfigurations::updateAutomaticKitList() [tc](AndroidToolChain *otherTc) { return tc->targetAbi() == otherTc->targetAbi(); }); + + auto initBasicKitData = [allLanguages, device](Kit *k, const QtSupport::BaseQtVersion *qt) { + k->setAutoDetected(true); + k->setAutoDetectionSource("AndroidConfiguration"); + DeviceTypeKitInformation::setDeviceTypeId(k, Core::Id(Constants::ANDROID_DEVICE_TYPE)); + for (AndroidToolChain *tc : allLanguages) + ToolChainKitInformation::setToolChain(k, tc); + QtSupport::QtKitInformation::setQtVersion(k, qt); + DeviceKitInformation::setDevice(k, device); + }; + for (const QtSupport::BaseQtVersion *qt : qtVersionsForArch.value(tc->targetAbi())) { Kit *newKit = new Kit; - newKit->setAutoDetected(true); - newKit->setAutoDetectionSource("AndroidConfiguration"); - DeviceTypeKitInformation::setDeviceTypeId(newKit, Core::Id(Constants::ANDROID_DEVICE_TYPE)); - for (AndroidToolChain *tc : allLanguages) - ToolChainKitInformation::setToolChain(newKit, tc); - QtSupport::QtKitInformation::setQtVersion(newKit, qt); - DeviceKitInformation::setDevice(newKit, device); - - auto findExistingKit = [newKit](const Kit *k) { return matchKits(newKit, k); }; - Kit *existingKit = Utils::findOrDefault(existingKits, findExistingKit); + initBasicKitData(newKit, qt); + Kit *existingKit = Utils::findOrDefault(existingKits, [newKit](const Kit *k) { + return matchKits(newKit, k); + }); if (existingKit) { + // Existing kit found. + // Update the existing kit with new data. + initBasicKitData(existingKit, qt); KitManager::deleteKit(newKit); newKit = existingKit; } diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index 6f444da8b4b..907b61be0f5 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -58,7 +58,8 @@ using namespace ProjectExplorer; TestCodeParser::TestCodeParser(TestTreeModel *parent) : QObject(parent), - m_model(parent) + m_model(parent), + m_threadPool(new QThreadPool(this)) { // connect to ProgressManager to postpone test parsing when CppModelManager is parsing auto progressManager = qobject_cast(Core::ProgressManager::instance()); @@ -77,6 +78,7 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent) connect(this, &TestCodeParser::parsingFinished, this, &TestCodeParser::releaseParserInternals); m_reparseTimer.setSingleShot(true); connect(&m_reparseTimer, &QTimer::timeout, this, &TestCodeParser::parsePostponedFiles); + m_threadPool->setMaxThreadCount(std::max(QThread::idealThreadCount()/4, 1)); } TestCodeParser::~TestCodeParser() @@ -403,6 +405,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars parseFileForTests(codeParsers, fi, file); }, Utils::MapReduceOption::Unordered, + m_threadPool, QThread::LowestPriority); m_futureWatcher.setFuture(future); if (list.size() > 5) { diff --git a/src/plugins/autotest/testcodeparser.h b/src/plugins/autotest/testcodeparser.h index 6286600c335..e06563d18a6 100644 --- a/src/plugins/autotest/testcodeparser.h +++ b/src/plugins/autotest/testcodeparser.h @@ -38,6 +38,10 @@ namespace Core { class Id; } +QT_BEGIN_NAMESPACE +class QThreadPool; +QT_END_NAMESPACE + namespace Autotest { namespace Internal { @@ -106,6 +110,7 @@ private: QVector m_testCodeParsers; // ptrs are still owned by TestFrameworkManager QTimer m_reparseTimer; ITestParser *m_updateParser = nullptr; + QThreadPool *m_threadPool = nullptr; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index f4769fe0ceb..0bfcac1d68e 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -309,7 +309,16 @@ void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QListfilePath().isChildOf(inc); }); }); - QList fileNodes = m_files + Utils::transform(missingHeaders, [](const FileNode *fn) { return fn->clone(); }); + // filter duplicates: + auto alreadySeen = QSet::fromList(Utils::transform(m_files, &FileNode::filePath)); + const QList unseenMissingHeaders = Utils::filtered(missingHeaders, [&alreadySeen](const FileNode *fn) { + const int count = alreadySeen.count(); + alreadySeen.insert(fn->filePath()); + return (alreadySeen.count() != count); + }); + + const QList fileNodes = m_files + + Utils::transform(unseenMissingHeaders, [](const FileNode *fn) { return fn->clone(); }); root->addNestedNodes(fileNodes, m_parameters.sourceDirectory); m_files.clear(); // Some of the FileNodes in files() were deleted! diff --git a/src/plugins/cpaster/pastebindotcaprotocol.cpp b/src/plugins/cpaster/pastebindotcaprotocol.cpp index b6fac76b6c1..50d545300e7 100644 --- a/src/plugins/cpaster/pastebindotcaprotocol.cpp +++ b/src/plugins/cpaster/pastebindotcaprotocol.cpp @@ -74,9 +74,9 @@ unsigned PasteBinDotCaProtocol::capabilities() const void PasteBinDotCaProtocol::fetch(const QString &id) { QTC_ASSERT(!m_fetchReply, return); - const QString url = QLatin1String(urlC); + const QString url = QLatin1String(internalUrlC); const QString rawPostFix = QLatin1String("raw/"); - // Create link as ""http://pastebin.ca/raw/[id]" + // Create link as ""http://pbin.ca/raw/[id]" // If we get a complete URL, just insert 'raw', else build URL. QString link = id; if (link.startsWith(url)) { diff --git a/src/plugins/cppeditor/cppincludehierarchy.cpp b/src/plugins/cppeditor/cppincludehierarchy.cpp index 9512b2ddcf3..03094c3d79b 100644 --- a/src/plugins/cppeditor/cppincludehierarchy.cpp +++ b/src/plugins/cppeditor/cppincludehierarchy.cpp @@ -322,6 +322,14 @@ private: return result; } + Result findStep(const QString &txt, FindFlags findFlags) override + { + m_model->setSearching(true); + Result result = ItemViewFind::findStep(txt, findFlags); + m_model->setSearching(false); + return result; + } + CppIncludeHierarchyModel *m_model; // Not owned. }; diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index d0da2990fe0..f8ed59b89a0 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -370,7 +370,7 @@ void AbstractProcessStep::taskAdded(const Task &task, int linkedOutputLines, int Task editable(task); QString filePath = task.file.toString(); - if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) { + if (!filePath.isEmpty() && !filePath.startsWith('<') && !QDir::isAbsolutePath(filePath)) { // We have no save way to decide which file in which subfolder // is meant. Therefore we apply following heuristics: // 1. Check if file is unique in whole project diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 4a5dced3c9e..a190434efdf 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -118,6 +118,7 @@ HeaderPathsCache::Cache HeaderPathsCache::cache() const } MacroCache::MacroCache(const MacroCache &other) + : MacroCache() { QMutexLocker locker(&m_mutex); m_cache = other.cache(); diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 86c3b32c1e4..af5c567f481 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -499,30 +499,60 @@ static QString winExpandDelayedEnvReferences(QString in, const Utils::Environmen return in; } -Utils::Environment MsvcToolChain::readEnvironmentSetting(const Utils::Environment& env) const +QList MsvcToolChain::environmentModifications() const { - Utils::Environment result; + const Utils::Environment inEnv = Utils::Environment::systemEnvironment(); + Utils::Environment outEnv; QMap envPairs; - if (!generateEnvironmentSettings(env, m_vcvarsBat, m_varsBatArg, envPairs)) - return env; + if (!generateEnvironmentSettings(inEnv, m_vcvarsBat, m_varsBatArg, envPairs)) + return QList(); // Now loop through and process them - QMap::const_iterator envIter; - for (envIter = envPairs.constBegin(); envIter!=envPairs.constEnd(); ++envIter) { - const QString expandedValue = winExpandDelayedEnvReferences(envIter.value(), env); + for (auto envIter = envPairs.cbegin(), eend = envPairs.cend(); envIter != eend; ++envIter) { + const QString expandedValue = winExpandDelayedEnvReferences(envIter.value(), inEnv); if (!expandedValue.isEmpty()) - result.set(envIter.key(), expandedValue); + outEnv.set(envIter.key(), expandedValue); } if (debug) { - const QStringList newVars = result.toStringList(); - const QStringList oldVars = env.toStringList(); + const QStringList newVars = outEnv.toStringList(); + const QStringList oldVars = inEnv.toStringList(); QDebug nsp = qDebug().nospace(); foreach (const QString &n, newVars) { if (!oldVars.contains(n)) nsp << n << '\n'; } } + + QList diff = inEnv.diff(outEnv); + for (int i = diff.size() - 1; i >= 0; --i) { + if (diff.at(i).name.startsWith(QLatin1Char('='))) { // Exclude "=C:", "=EXITCODE" + diff.removeAt(i); + } else { + // Fix the append/prepend cases to "FOO=${FOO};newValue" (see Environment::modify) + Utils::EnvironmentItem &e = diff[i]; + if (!e.unset) { + const auto oldIt = inEnv.constFind(e.name); + if (oldIt != inEnv.constEnd()) { + const int index = e.value.indexOf(oldIt.value()); + if (index != -1) { + e.value.replace(index, oldIt.value().size(), + QStringLiteral("${") + e.name + QLatin1Char('}')); + } + } + } + } + } + + return diff; +} + +Utils::Environment MsvcToolChain::readEnvironmentSetting(const Utils::Environment& env) const +{ + if (m_environmentModifications.isEmpty()) + m_environmentModifications = environmentModifications(); + Utils::Environment result = env; + result.modify(m_environmentModifications); return result; } diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index e7973800c3a..fd341177eb3 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -86,6 +86,10 @@ protected: const Utils::Environment &env) const override; private: + QList environmentModifications() const; + + mutable QList m_environmentModifications; + QString m_varsBatArg; // Argument }; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 6e1b11d1bec..f40359e2805 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -926,7 +926,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd->m_cancelBuildAction = new QAction(Utils::Icons::STOP_SMALL.icon(), tr("Cancel Build"), this); cmd = ActionManager::registerAction(dd->m_cancelBuildAction, Constants::CANCELBUILD); - cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Backspace"))); + cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+Backspace") : tr("Alt+Backspace"))); mbuild->addAction(cmd, Constants::G_BUILD_CANCEL); // run action diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 38f41bcc3db..aa619aa4263 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -362,13 +363,10 @@ static QList scanForFilesRecursively(const Utils::FileName &director const Utils::FileName entryName = Utils::FileName::fromString(entry.absoluteFilePath()); if (!vcsControl || !vcsControl->isVcsFileOrDirectory(entryName)) { - if (entry.isDir()) { + if (entry.isDir()) result.append(scanForFilesRecursively(entryName, factory, visited, future, progress, progressIncrement)); - } else { - FileNode *node = factory(entryName); - if (node) - result.append(node); - } + else if (FileNode *node = factory(entryName)) + result.append(node); } if (future) { progress += progressIncrement; @@ -610,7 +608,7 @@ bool FolderNode::replaceSubtree(Node *oldNode, Node *newNode) } else { removeNode(oldNode); // Happens e.g. when project is shutting down } - delete oldNode; + QTimer::singleShot(0, [oldNode]() { delete oldNode; }); } ProjectTree::emitSubtreeChanged(this); return true; diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp index 17dc57a128c..5510be69831 100644 --- a/src/plugins/projectexplorer/projectwizardpage.cpp +++ b/src/plugins/projectexplorer/projectwizardpage.cpp @@ -456,6 +456,11 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const QStringList & } root->prependChild(createNoneNode(&selector)); + // Set combobox to context node: + auto predicate = [context](TreeItem *ti) { return static_cast(ti)->node() == context; }; + TreeItem *contextItem = root->findAnyChild(predicate); + m_ui->projectComboBox->setCurrentIndex(m_model.indexForItem(contextItem)); + setAdditionalInfo(selector.deployingProjects()); setBestNode(selector.bestChoice()); setAddingSubProject(action == AddSubProject); diff --git a/src/plugins/projectexplorer/sessiondialog.cpp b/src/plugins/projectexplorer/sessiondialog.cpp index a1bae82fc2c..7b926a11109 100644 --- a/src/plugins/projectexplorer/sessiondialog.cpp +++ b/src/plugins/projectexplorer/sessiondialog.cpp @@ -146,7 +146,7 @@ SessionDialog::SessionDialog(QWidget *parent) : QDialog(parent) void SessionDialog::setAutoLoadSession(bool check) { - m_ui.autoLoadCheckBox->setChecked(check ? Qt::Checked : Qt::Unchecked); + m_ui.autoLoadCheckBox->setChecked(check); } bool SessionDialog::autoLoadSession() const diff --git a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp index 4b85e30b0e5..3420fca5109 100644 --- a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp +++ b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp @@ -74,7 +74,8 @@ void QmakeKitInformation::setup(Kit *k) if (!version) return; - if (version->type() == "Boot2Qt.QtVersionType") // HACK: Ignore boot2Qt kits! + // HACK: Ignore Boot2Qt kits! + if (version->type() == "Boot2Qt.QtVersionType" || version->type() == "Qdb.EmbeddedLinuxQt") return; FileName spec = QmakeKitInformation::mkspec(k); diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp index abe1b3545b6..fea0898dde7 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp @@ -179,8 +179,13 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const Fi vfolder->addNode(resourceNode); } } else { - for (const FileName &fn : newFilePaths) + for (const FileName &fn : newFilePaths) { + // Qmake will flag everything in SOURCES as source, even when the + // qt quick compiler moves qrc files into it:-/ Get better data based on + // the filename. + type = FileNode::fileTypeForFileName(fn); vfolder->addNestedNode(new FileNode(fn, type, false)); + } for (FolderNode *fn : vfolder->folderNodes()) fn->compress(); } diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index c7ff2a2765f..c241189d9e1 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -1281,12 +1281,18 @@ void QmakeProject::testToolChain(ToolChain *tc, const Utils::FileName &path) con if (!env.isSameExecutable(path.toString(), expected.toString())) { const QPair pair = qMakePair(expected, path); if (!m_toolChainWarnings.contains(pair)) { - TaskHub::addTask(Task(Task::Warning, - QCoreApplication::translate("QmakeProjectManager", "\"%1\" is used by qmake, but \"%2\" is configured in the kit.\n" - "Please update your kit or choose a mkspec for qmake that matches your target environment better."). - arg(path.toUserOutput()).arg(expected.toUserOutput()), - Utils::FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); - m_toolChainWarnings.insert(pair); + // Suppress warnings on Apple machines where compilers in /usr/bin point into Xcode. + // This will suppress some valid warnings, but avoids annoying Apple users with + // spurious warnings all the time! + if (!pair.first.toString().startsWith("/usr/bin/") + || !pair.second.toString().contains("/Contents/Developer/Toolchains/")) { + TaskHub::addTask(Task(Task::Warning, + QCoreApplication::translate("QmakeProjectManager", "\"%1\" is used by qmake, but \"%2\" is configured in the kit.\n" + "Please update your kit or choose a mkspec for qmake that matches your target environment better."). + arg(path.toUserOutput()).arg(expected.toUserOutput()), + Utils::FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + m_toolChainWarnings.insert(pair); + } } } } diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 6e5b3e4a119..bc8047d4749 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -111,13 +111,18 @@ void DesignerActionManager::polishActions() const [](ActionInterface *action) { return action->type() != ActionInterface::ContextMenu; }); Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR); + Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR); + + Core::Context qmlDesignerUIContext; + qmlDesignerUIContext.add(qmlDesignerFormEditorContext); + qmlDesignerUIContext.add(qmlDesignerNavigatorContext); for (auto *action : actions) { if (!action->menuId().isEmpty()) { const QString id = QString("QmlDesigner.%1").arg(QString::fromLatin1(action->menuId())); - Core::Command *cmd = Core::ActionManager::registerAction(action->action(), id.toLatin1().constData(), qmlDesignerFormEditorContext); + Core::Command *cmd = Core::ActionManager::registerAction(action->action(), id.toLatin1().constData(), qmlDesignerUIContext); cmd->setDefaultKeySequence(action->action()->shortcut()); cmd->setDescription(action->action()->toolTip()); @@ -698,7 +703,7 @@ void DesignerActionManager::createDefaultDesignerActions() {":/utils/images/iconoverlay_reset.png", Utils::Theme::IconsStopToolBarColor}}).icon(), resetSizeToolTip, editCategory, - QKeySequence("Ctrl+f"), + QKeySequence("shift+s"), 180, &resetSize, &selectionNotEmptyAndHasWidthOrHeightProperty)); @@ -726,7 +731,7 @@ void DesignerActionManager::createDefaultDesignerActions() Utils::Icon({{":/qmldesigner/images/anchor_fill.png", Utils::Theme::IconsBaseColor}}).icon(), anchorsFillToolTip, anchorsCategory, - QKeySequence(QKeySequence("Ctrl+f")), + QKeySequence(QKeySequence("shift+f")), 200, &anchorsFill, &singleSelectionItemIsNotAnchoredAndSingleSelectionNotRoot)); @@ -738,7 +743,7 @@ void DesignerActionManager::createDefaultDesignerActions() {":/utils/images/iconoverlay_reset.png", Utils::Theme::IconsStopToolBarColor}}).icon(), anchorsResetToolTip, anchorsCategory, - QKeySequence(QKeySequence("Ctrl+Shift+f")), + QKeySequence(QKeySequence("Ctrl+Shift+r")), 180, &anchorsReset, &singleSelectionItemIsAnchored)); @@ -819,7 +824,7 @@ void DesignerActionManager::createDefaultDesignerActions() removeLayoutCommandId, removeLayoutDisplayName, layoutCategory, - QKeySequence("Ctrl+Shift+u"), + QKeySequence(), 110, &removeLayout, &isLayout, @@ -899,7 +904,7 @@ void DesignerActionManager::createDefaultDesignerActions() Utils::Icon({{":/qmldesigner/icon/designeractions/images/grid.png", Utils::Theme::IconsBaseColor}}).icon(), layoutGridLayoutToolTip, layoutCategory, - QKeySequence("Ctrl+h"), + QKeySequence("shift+g"), 60, &layoutGridLayout, &selectionCanBeLayoutedAndQtQuickLayoutPossible)); @@ -932,7 +937,7 @@ void DesignerActionManager::createDefaultDesignerActions() goIntoComponentCommandId, goIntoComponentDisplayName, rootCategory, - QKeySequence(), + QKeySequence(Qt::Key_F2), priorityGoIntoComponent, &goIntoComponentOperation, &selectionIsComponent)); diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index f71c6877114..c6fe7694edb 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -922,11 +922,12 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH // maybe the project environment (kit, ...) changed, so we need to clean old caches NodeMetaInfo::clearCache(); - m_qrcMapping.clear(); - m_rewriterView->clearErrorAndWarnings(); - const QUrl url = m_rewriterView->model()->fileUrl(); + m_qrcMapping.clear(); + addIsoIconQrcMapping(url); + m_rewriterView->clearErrorAndWarnings(); + setActive(true); m_rewriterView->setIncompleteTypeInformation(false); @@ -2039,6 +2040,17 @@ void TextToModelMerger::populateQrcMapping(const QString &filePath) } } +void TextToModelMerger::addIsoIconQrcMapping(const QUrl &fileUrl) +{ + QDir dir(fileUrl.toLocalFile()); + do { + if (!dir.entryList({"*.pro"}, QDir::Files).isEmpty()) { + m_qrcMapping.insert({"/iso-icons", dir.absolutePath() + "/iso-icons"}); + return; + } + } while (dir.cdUp()); +} + void TextToModelMerger::setupComponentDelayed(const ModelNode &node, bool synchron) { if (synchron) { diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h index c7176afd629..4eebae3b858 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h @@ -141,6 +141,7 @@ private: void collectSemanticErrorsAndWarnings(QList *errors, QList *warnings); void populateQrcMapping(const QString &filePath); + void addIsoIconQrcMapping(const QUrl &fileUrl); static QString textAt(const QmlJS::Document::Ptr &doc, const QmlJS::AST::SourceLocation &location); diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index ad9f82814a9..929a0bda47d 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -148,9 +148,9 @@ static void openSourcePropertyOfLoader(const ModelNode &modelNode) QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally(); QString componentFileName = modelNode.variantProperty("source").value().toString(); - QString componentFilePath = modelNode.model()->fileUrl().resolved(QUrl::fromLocalFile(componentFileName)).toLocalFile(); - Core::EditorManager::openEditor(componentFilePath, Core::Id(), Core::EditorManager::DoNotMakeVisible); + QFileInfo fileInfo(modelNode.model()->fileUrl().toLocalFile()); + Core::EditorManager::openEditor(fileInfo.absolutePath() + "/" + componentFileName, Core::Id(), Core::EditorManager::DoNotMakeVisible); } diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp index 0e1889d0582..864d4046f4d 100644 --- a/src/plugins/qmldesigner/shortcutmanager.cpp +++ b/src/plugins/qmldesigner/shortcutmanager.cpp @@ -86,7 +86,6 @@ ShortCutManager::ShortCutManager() m_restoreDefaultViewAction(tr("&Restore Default View"), 0), m_toggleLeftSidebarAction(tr("Toggle &Left Sidebar"), 0), m_toggleRightSidebarAction(tr("Toggle &Right Sidebar"), 0), - m_goIntoComponentAction(tr("&Go into Component"), 0), m_switchTextFormAction(tr("Switch Text/Design"), 0), m_escapeAction(this) { @@ -119,8 +118,6 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex QmlDesignerPlugin::instance()->mainWidget(), &Internal::DesignModeWidget::restoreDefaultView); - connect(&m_goIntoComponentAction, &QAction::triggered, this, &ShortCutManager::goIntoComponent); - connect(&m_toggleLeftSidebarAction, &QAction::triggered, QmlDesignerPlugin::instance()->mainWidget(), @@ -188,11 +185,6 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex command = Core::ActionManager::registerAction(&m_redoAction, Core::Constants::REDO, qmlDesignerMainContext); designerActionManager.addCreatorCommand(command, ComponentCoreConstants::editCategory, 300, Utils::Icons::REDO_TOOLBAR.icon()); - //GoIntoComponent - command = Core::ActionManager::registerAction(&m_goIntoComponentAction, - Constants::GO_INTO_COMPONENT, qmlDesignerMainContext); - command->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); - //Edit Menu m_deleteAction.setIcon(QIcon::fromTheme(QLatin1String("edit-cut"), Utils::Icons::EDIT_CLEAR_TOOLBAR.icon())); @@ -235,7 +227,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex command = Core::ActionManager::registerAction(&m_collapseExpandStatesAction, Constants::TOGGLE_STATES_EDITOR, qmlDesignerMainContext); command->setAttribute(Core::Command::CA_Hide); - command->setDefaultKeySequence(QKeySequence("Ctrl+Shift+s")); + command->setDefaultKeySequence(QKeySequence("Ctrl+Alt+s")); viewsMenu->addAction(command); command = Core::ActionManager::registerAction(&m_restoreDefaultViewAction, Constants::RESTORE_DEFAULT_VIEW, qmlDesignerMainContext); diff --git a/src/plugins/qmldesigner/shortcutmanager.h b/src/plugins/qmldesigner/shortcutmanager.h index c5fbe89feff..3c3999b2a7f 100644 --- a/src/plugins/qmldesigner/shortcutmanager.h +++ b/src/plugins/qmldesigner/shortcutmanager.h @@ -89,7 +89,6 @@ private: QAction m_restoreDefaultViewAction; QAction m_toggleLeftSidebarAction; QAction m_toggleRightSidebarAction; - QAction m_goIntoComponentAction; QAction m_switchTextFormAction; QAction m_escapeAction; }; diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp index 7bfb5f18853..01a8b1e0a2c 100644 --- a/src/plugins/qtsupport/exampleslistmodel.cpp +++ b/src/plugins/qtsupport/exampleslistmodel.cpp @@ -111,7 +111,7 @@ ExampleSetModel::ExampleSetModel() } } -void ExampleSetModel::recreateModel() +void ExampleSetModel::recreateModel(const QList &qtVersions) { beginResetModel(); clear(); @@ -129,7 +129,7 @@ void ExampleSetModel::recreateModel() extraManifestDirs.insert(set.manifestPath); } - foreach (BaseQtVersion *version, QtVersionManager::versions()) { + foreach (BaseQtVersion *version, qtVersions) { // sanitize away qt versions that have already been added through extra sets if (extraManifestDirs.contains(version->documentationPath())) { if (debugExamples()) { @@ -484,7 +484,7 @@ void ExampleSetModel::updateQtVersionList() if (defaultVersion && versions.contains(defaultVersion)) versions.move(versions.indexOf(defaultVersion), 0); - recreateModel(); + recreateModel(versions); int currentIndex = m_selectedExampleSetIndex; if (currentIndex < 0) // reset from settings @@ -494,7 +494,7 @@ void ExampleSetModel::updateQtVersionList() if (currentType == ExampleSetModel::InvalidExampleSet) { // select examples corresponding to 'highest' Qt version - BaseQtVersion *highestQt = findHighestQtVersion(); + BaseQtVersion *highestQt = findHighestQtVersion(versions); currentIndex = indexForQtVersion(highestQt); } else if (currentType == ExampleSetModel::QtExampleSet) { // try to select the previously selected Qt version, or @@ -502,17 +502,16 @@ void ExampleSetModel::updateQtVersionList() int currentQtId = getQtId(currentIndex); BaseQtVersion *newQtVersion = QtVersionManager::version(currentQtId); if (!newQtVersion) - newQtVersion = findHighestQtVersion(); + newQtVersion = findHighestQtVersion(versions); currentIndex = indexForQtVersion(newQtVersion); } // nothing to do for extra example sets selectExampleSet(currentIndex); emit selectedExampleSetChanged(currentIndex); } -BaseQtVersion *ExampleSetModel::findHighestQtVersion() const +BaseQtVersion *ExampleSetModel::findHighestQtVersion(const QList &versions) const { BaseQtVersion *newVersion = nullptr; - const QList versions = QtVersionManager::versions(); for (BaseQtVersion *version : versions) { if (!newVersion) { newVersion = version; diff --git a/src/plugins/qtsupport/exampleslistmodel.h b/src/plugins/qtsupport/exampleslistmodel.h index e98c5844bb9..e6d1a252c99 100644 --- a/src/plugins/qtsupport/exampleslistmodel.h +++ b/src/plugins/qtsupport/exampleslistmodel.h @@ -74,10 +74,10 @@ private: int getQtId(int index) const; int getExtraExampleSetIndex(int index) const; - BaseQtVersion *findHighestQtVersion() const; + BaseQtVersion *findHighestQtVersion(const QList &versions) const; int indexForQtVersion(BaseQtVersion *qtVersion) const; - void recreateModel(); + void recreateModel(const QList &qtVersions); void updateQtVersionList(); void qtVersionManagerLoaded(); diff --git a/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp b/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp index 41432ba29bf..c9910d5d09b 100644 --- a/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp +++ b/src/plugins/remotelinux/remotelinuxenvironmentaspect.cpp @@ -26,6 +26,22 @@ #include "remotelinuxenvironmentaspect.h" #include "remotelinuxenvironmentaspectwidget.h" +#include "utils/algorithm.h" + +static const char DISPLAY_KEY[] = "DISPLAY"; +static const char VERSION_KEY[] = "RemoteLinux.EnvironmentAspect.Version"; +static const int ENVIRONMENTASPECT_VERSION = 1; // Version was introduced in 4.3 with the value 1 + +namespace { + +bool displayAlreadySet(const QList &changes) +{ + return Utils::contains(changes, [](const Utils::EnvironmentItem &item) { + return item.name == DISPLAY_KEY; + }); +} + +} // anonymous namespace namespace RemoteLinux { @@ -35,18 +51,15 @@ namespace RemoteLinux { RemoteLinuxEnvironmentAspect::RemoteLinuxEnvironmentAspect(ProjectExplorer::RunConfiguration *rc) : ProjectExplorer::EnvironmentAspect(rc) -{ } +{ + setRunConfigWidgetCreator([this] { return new RemoteLinuxEnvironmentAspectWidget(this); }); +} RemoteLinuxEnvironmentAspect *RemoteLinuxEnvironmentAspect::create(ProjectExplorer::RunConfiguration *parent) const { return new RemoteLinuxEnvironmentAspect(parent); } -ProjectExplorer::RunConfigWidget *RemoteLinuxEnvironmentAspect::createConfigurationWidget() -{ - return new RemoteLinuxEnvironmentAspectWidget(this); -} - QList RemoteLinuxEnvironmentAspect::possibleBaseEnvironments() const { return QList() << static_cast(RemoteBaseEnvironment) @@ -67,9 +80,6 @@ Utils::Environment RemoteLinuxEnvironmentAspect::baseEnvironment() const Utils::Environment env; if (baseEnvironmentBase() == static_cast(RemoteBaseEnvironment)) env = m_remoteEnvironment; - const QString displayKey = QLatin1String("DISPLAY"); - if (!env.hasKey(displayKey)) - env.appendOrSet(displayKey, QLatin1String(":0.0")); return env; } @@ -96,5 +106,29 @@ QString RemoteLinuxEnvironmentAspect::userEnvironmentChangesAsString() const return env.mid(0, env.size() - 1); } +void RemoteLinuxEnvironmentAspect::fromMap(const QVariantMap &map) +{ + ProjectExplorer::EnvironmentAspect::fromMap(map); + + const auto version = map.value(QLatin1String(VERSION_KEY), 0).toInt(); + if (version == 0) { + // In Qt Creator versions prior to 4.3 RemoteLinux included DISPLAY=:0.0 in the base + // environment, if DISPLAY was not set. In order to keep existing projects expecting + // that working, add the DISPLAY setting to user changes in them. New projects will + // have version 1 and will not get DISPLAY set. + auto changes = userEnvironmentChanges(); + if (!displayAlreadySet(changes)) { + changes.append(Utils::EnvironmentItem(QLatin1String(DISPLAY_KEY), QLatin1String(":0.0"))); + setUserEnvironmentChanges(changes); + } + } +} + +void RemoteLinuxEnvironmentAspect::toMap(QVariantMap &map) const +{ + ProjectExplorer::EnvironmentAspect::toMap(map); + map.insert(QLatin1String(VERSION_KEY), ENVIRONMENTASPECT_VERSION); +} + } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinuxenvironmentaspect.h b/src/plugins/remotelinux/remotelinuxenvironmentaspect.h index 02a4cbf1191..227d751906e 100644 --- a/src/plugins/remotelinux/remotelinuxenvironmentaspect.h +++ b/src/plugins/remotelinux/remotelinuxenvironmentaspect.h @@ -30,7 +30,6 @@ #include namespace RemoteLinux { -class RemoteLinuxEnvironmentAspectWidget; class REMOTELINUX_EXPORT RemoteLinuxEnvironmentAspect : public ProjectExplorer::EnvironmentAspect { @@ -38,18 +37,21 @@ class REMOTELINUX_EXPORT RemoteLinuxEnvironmentAspect : public ProjectExplorer:: public: RemoteLinuxEnvironmentAspect(ProjectExplorer::RunConfiguration *rc); - RemoteLinuxEnvironmentAspect *create(ProjectExplorer::RunConfiguration *parent) const; - ProjectExplorer::RunConfigWidget *createConfigurationWidget(); + RemoteLinuxEnvironmentAspect *create(ProjectExplorer::RunConfiguration *parent) const override; - QList possibleBaseEnvironments() const; - QString baseEnvironmentDisplayName(int base) const; - Utils::Environment baseEnvironment() const; + QList possibleBaseEnvironments() const override; + QString baseEnvironmentDisplayName(int base) const override; + Utils::Environment baseEnvironment() const override; Utils::Environment remoteEnvironment() const; void setRemoteEnvironment(const Utils::Environment &env); QString userEnvironmentChangesAsString() const; +protected: + void fromMap(const QVariantMap &map) override; + void toMap(QVariantMap &map) const override; + private: enum BaseEnvironmentBase { CleanBaseEnvironment = 0, diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp index 20f67b2eecd..cb7b5be887b 100644 --- a/src/plugins/resourceeditor/resourcenode.cpp +++ b/src/plugins/resourceeditor/resourcenode.cpp @@ -146,7 +146,6 @@ static bool addFilesToResource(const FileName &resourceFile, } } - FileChangeBlocker changeGuard(resourceFile.toString()); file.save(); return true; @@ -270,12 +269,15 @@ ResourceTopLevelNode::ResourceTopLevelNode(const FileName &filePath, bool genera { setIsGenerated(generated); setIcon(FileIconProvider::icon(filePath.toString())); - if (contents.isEmpty()) { - m_document = new ResourceFileWatcher(this); - DocumentManager::addDocument(m_document); + setPriority(Node::DefaultFilePriority); + if (!filePath.isEmpty()) { + QFileInfo fi = filePath.toFileInfo(); + if (fi.isFile() && fi.isReadable()) { + m_document = new ResourceFileWatcher(this); + DocumentManager::addDocument(m_document); + } } else { m_contents = contents; - m_document = nullptr; } FileName base = parent->filePath(); @@ -416,7 +418,6 @@ bool ResourceTopLevelNode::addPrefix(const QString &prefix, const QString &lang) int index = file.addPrefix(prefix, lang); if (index == -1) return false; - FileChangeBlocker changeGuard(filePath().toString()); file.save(); return true; @@ -431,7 +432,6 @@ bool ResourceTopLevelNode::removePrefix(const QString &prefix, const QString &la if (file.prefix(i) == prefix && file.lang(i) == lang) { file.removePrefix(i); - FileChangeBlocker changeGuard(filePath().toString()); file.save(); return true; } @@ -456,7 +456,6 @@ bool ResourceTopLevelNode::removeNonExistingFiles() } } - FileChangeBlocker changeGuard(filePath().toString()); file.save(); return true; } @@ -551,7 +550,6 @@ bool ResourceFolderNode::removeFiles(const QStringList &filePaths, QStringList * file.removeFile(index, j); --j; } - FileChangeBlocker changeGuard(m_topLevelNode->filePath().toString()); file.save(); return true; @@ -590,7 +588,6 @@ bool ResourceFolderNode::renameFile(const QString &filePath, const QString &newF for (int j = 0; j < file.fileCount(index); ++j) { if (file.file(index, j) == filePath) { file.replaceFile(index, j, newFilePath); - FileChangeBlocker changeGuard(m_topLevelNode->filePath().toString()); file.save(); return true; } @@ -611,7 +608,6 @@ bool ResourceFolderNode::renamePrefix(const QString &prefix, const QString &lang if (!file.replacePrefixAndLang(index, prefix, lang)) return false; - FileChangeBlocker changeGuard(m_topLevelNode->filePath().toString()); file.save(); return true; } diff --git a/src/plugins/resourceeditor/resourcenode.h b/src/plugins/resourceeditor/resourcenode.h index f1377eaa147..e2f84e005a7 100644 --- a/src/plugins/resourceeditor/resourcenode.h +++ b/src/plugins/resourceeditor/resourcenode.h @@ -56,7 +56,7 @@ public: QString contents() const { return m_contents; } private: - Internal::ResourceFileWatcher *m_document; + Internal::ResourceFileWatcher *m_document = nullptr; QString m_contents; }; diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp index 14a6f6bf635..8598a6c798b 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsoutputwindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -434,12 +435,12 @@ static inline QString formatArguments(const QStringList &args) if (i) str << ' '; if (arg.startsWith(QString::fromLatin1(passwordOptionC) + QLatin1Char('='))) { - str << "--password=********"; + str << Utils::QtcProcess::quoteArg("--password=********"); continue; } - str << arg; + str << Utils::QtcProcess::quoteArg(arg); if (arg == QLatin1String(passwordOptionC)) { - str << " ********"; + str << ' ' << Utils::QtcProcess::quoteArg("********"); i++; } } @@ -451,7 +452,7 @@ QString VcsOutputWindow::msgExecutionLogEntry(const QString &workingDir, const QStringList &arguments) { const QString args = formatArguments(arguments); - const QString nativeExecutable = executable.toUserOutput(); + const QString nativeExecutable = Utils::QtcProcess::quoteArg(executable.toUserOutput()); if (workingDir.isEmpty()) return tr("Running: %1 %2").arg(nativeExecutable, args) + QLatin1Char('\n'); return tr("Running in %1: %2 %3"). diff --git a/src/share/3rdparty/generic-highlighter/makefile.xml b/src/share/3rdparty/generic-highlighter/makefile.xml index 30e27022db4..147070f3d40 100644 --- a/src/share/3rdparty/generic-highlighter/makefile.xml +++ b/src/share/3rdparty/generic-highlighter/makefile.xml @@ -350,10 +350,6 @@ - - - - diff --git a/src/shared/qbs b/src/shared/qbs index 13089719966..da5e38c5618 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 130897199664f52d737ad4f3e24df19ccfbdee93 +Subproject commit da5e38c5618b1ebc81f0049af3b959a65b90539a diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index a699586edba..1342e0c8e08 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -473,6 +473,13 @@ struct RequiredMessage QString message; }; +struct DumperOptions +{ + DumperOptions(const QString &opts = QString()) : options(opts) {} + + QString options; +}; + struct Check { Check() {} @@ -699,6 +706,12 @@ public: return *this; } + const Data &operator+(const DumperOptions &options) const + { + dumperOptions += options.options; + return *this; + } + const Data &operator+(const Profile &profile) const { profileExtra += profile.contents; @@ -921,6 +934,7 @@ public: mutable QString mainFile = "main.cpp"; mutable QString projectFile = "doit.pro"; + mutable QString dumperOptions; mutable QString profileExtra; mutable QString includes; mutable QString code; @@ -1442,6 +1456,10 @@ void tst_Dumpers::dumper() QStringList args; QString cmds; + QString dumperOptions = data.dumperOptions; + if (!dumperOptions.isEmpty() && !dumperOptions.endsWith(',')) + dumperOptions += ','; + if (m_debuggerEngine == GdbEngine) { const QFileInfo gdbBinaryFile(exe); const QString uninstalledData = gdbBinaryFile.absolutePath() @@ -1465,7 +1483,7 @@ void tst_Dumpers::dumper() "python theDumper.setupDumpers()\n" "run " + nograb + "\n" "up " + QString::number(data.skipLevels) + "\n" - "python theDumper.fetchVariables({" + "python theDumper.fetchVariables({" + dumperOptions + "'token':2,'fancy':1,'forcens':1," "'autoderef':1,'dyntype':1,'passexceptions':1," "'testing':1,'qobjectnames':1," @@ -5320,6 +5338,18 @@ void tst_Dumpers::dumper_data() + Check("a2.3", "[3]", "100", "char"); + QTest::newRow("Array10Format") + << Data("", + "int arr[4] = { 1, 2, 3, 4};\n" + "int *nums = new int[4] { 1, 2, 3, 4};\n") + + + NoLldbEngine // FIXME: DumperOptions not handled yet. + + DumperOptions("'formats':{'local.nums':12}") // Array10Format + + + Check("arr.1", "[1]", "2", "int") + + Check("nums.1", "[1]", "2", "int"); + + QTest::newRow("ArrayQt") << Data("#include \n" "#include \n" + fooData, diff --git a/tests/auto/mapreduce/tst_mapreduce.cpp b/tests/auto/mapreduce/tst_mapreduce.cpp index 413d8753602..5fb8cb44b00 100644 --- a/tests/auto/mapreduce/tst_mapreduce.cpp +++ b/tests/auto/mapreduce/tst_mapreduce.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #if !defined(Q_CC_MSVC) || _MSC_VER >= 1900 // MSVC2015 @@ -58,6 +59,7 @@ static void returnxxThroughFutureInterface(QFutureInterface &fi, int x) void tst_MapReduce::mapReduce() { + QThreadPool pool; const auto initWithFutureInterface = [](QFutureInterface &fi) -> double { fi.reportResult(0.); return 0.; @@ -102,6 +104,16 @@ void tst_MapReduce::mapReduce() Utils::sort(results); // mapping order is undefined QCOMPARE(results, QList({0., 1., 4., 9., 16., 25., 27.5})); } + { + // reduce with threadpool + QList results = Utils::mapReduce(QList({1, 2, 3, 4, 5}), + initWithFutureInterface, returnxx, + reduceWithReturn, cleanupWithFutureInterface, + Utils::MapReduceOption::Unordered, &pool) + .results(); + Utils::sort(results); // mapping order is undefined + QCOMPARE(results, QList({0., 1., 4., 9., 16., 25., 27.5})); + } { // lvalue ref container QList container({1, 2, 3, 4, 5}); @@ -121,6 +133,15 @@ void tst_MapReduce::mapReduce() Utils::MapReduceOption::Ordered).results(), QList({0., 1., 4., 9., 16., 25., 27.5})); } + { + // std::cref with threadpool + QList container({1, 2, 3, 4, 5}); + QCOMPARE(Utils::mapReduce(std::cref(container), + initWithFutureInterface, returnxx, + reduceWithReturn, cleanupWithFutureInterface, + Utils::MapReduceOption::Ordered, &pool).results(), + QList({0., 1., 4., 9., 16., 25., 27.5})); + } { // std::ref QList container({1, 2, 3, 4, 5}); @@ -151,6 +172,17 @@ void tst_MapReduce::mapReduce() Utils::MapReduceOption::Ordered).result(), 1.5); } + { + // simplified map reduce without init and cleanup with threadpool + QCOMPARE(Utils::mapReduce(QList({QLatin1String("blubb"), QLatin1String("foo"), QLatin1String("blah")}), + [](const QString &val) { return val.size(); }, + 90., + [](double &state, int val) { + state /= double(val); + }, + Utils::MapReduceOption::Ordered, &pool).result(), + 1.5); + } { // simplified map reduce // std::cref @@ -161,7 +193,16 @@ void tst_MapReduce::mapReduce() } { // simplified map reduce - // std::cref + // std::cref with threadpool + QList container({1, 2, 3}); + QCOMPARE(Utils::mapReduce(std::cref(container), [](int val) { return 2*val; }, 10, + [](int &state, int val) { state += val; }, + Utils::MapReduceOption::Unordered, &pool).result(), + 22); + } + { + // simplified map reduce + // std::ref QList container({1, 2, 3}); QCOMPARE(Utils::mapReduce(std::ref(container), [](int &val) { return 2*val; }, 10, [](int &state, int val) { state += val; }).result(), @@ -173,6 +214,14 @@ void tst_MapReduce::mapReduce() [](int &state, int val) { state += val; }), 22); } + { + // blocking mapReduce = mappedReduced + // with threadpool + QCOMPARE(Utils::mappedReduced(QList({1, 2, 3}), [](int &val) { return 2*val; }, 10, + [](int &state, int val) { state += val; }, + Utils::MapReduceOption::Unordered, &pool), + 22); + } } void tst_MapReduce::mapReduceRvalueContainer() @@ -214,7 +263,8 @@ void tst_MapReduce::map() QCOMPARE(container, QList({4, 10, 2})); Utils::map(container.begin(), container.end(), [](int &x) { x *= 2; }, - Utils::MapReduceOption::Unordered, QThread::InheritPriority, 3).waitForFinished(); + Utils::MapReduceOption::Unordered, + nullptr, QThread::InheritPriority, 3).waitForFinished(); QCOMPARE(container, QList({8, 20, 4})); } diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp index 425ce874afd..3bbe0d55201 100644 --- a/tests/manual/debugger/simple/simple_test_app.cpp +++ b/tests/manual/debugger/simple/simple_test_app.cpp @@ -6106,14 +6106,16 @@ namespace qjson { }; QJsonArray arr; for (unsigned int i = 0; i < 32; ++i) { - arr.append(QJsonValue(qint64(quint64(1) << i) - 1)); - arr.append(QJsonValue(qint64(quint64(1) << i))); - arr.append(QJsonValue(qint64(quint64(1) << i) + 1)); + const qint64 bit = 1ll << i; + arr.append(QJsonValue(bit - 1)); + arr.append(QJsonValue(bit)); + arr.append(QJsonValue(bit + 1)); } for (unsigned int i = 0; i < 32; ++i) { - arr.append(QJsonValue(-qint64(quint64(1) << i) + 1)); - arr.append(QJsonValue(-qint64(quint64(1) << i))); - arr.append(QJsonValue(-qint64(quint64(1) << i) - 1)); + const qint64 bit = -(1ll << i); + arr.append(QJsonValue(bit + 1)); + arr.append(QJsonValue(bit)); + arr.append(QJsonValue(bit - 1)); } BREAK_HERE; // Check v -1 QJsonValue. diff --git a/tests/system/objects.map b/tests/system/objects.map index e855d701b52..e9cd3f8c4ab 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -39,11 +39,6 @@ :Cannot Open Project_QTextEdit {type='QTextEdit' unnamed='1' visible='1' window=':Cannot Open Project_QMessageBox'} :Close Debugging Session.Yes_QPushButton {text='Yes' type='QPushButton' unnamed='1' visible='1' window=':Close Debugging Session_Utils::CheckableMessageBox'} :Close Debugging Session_Utils::CheckableMessageBox {type='Utils::CheckableMessageBox' unnamed='1' visible='1' windowTitle='Close Debugging Session'} -:CodePaster__Internal__PasteSelectDialog.Cancel_QPushButton {text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':CodePaster__Internal__PasteSelectDialog_CodePaster::PasteSelectDialog'} -:CodePaster__Internal__PasteSelectDialog.OK_QPushButton {text='OK' type='QPushButton' unnamed='1' visible='1' window=':CodePaster__Internal__PasteSelectDialog_CodePaster::PasteSelectDialog'} -:CodePaster__Internal__PasteSelectDialog.listWidget_QListWidget {name='listWidget' type='QListWidget' visible='1' window=':CodePaster__Internal__PasteSelectDialog_CodePaster::PasteSelectDialog'} -:CodePaster__Internal__PasteSelectDialog.protocolBox_QComboBox {name='protocolBox' type='QComboBox' visible='1' window=':CodePaster__Internal__PasteSelectDialog_CodePaster::PasteSelectDialog'} -:CodePaster__Internal__PasteSelectDialog_CodePaster::PasteSelectDialog {name='CodePaster__Internal__PasteSelectDialog' type='CodePaster::PasteSelectDialog' visible='1'} :Core__Internal__GeneralSettings.User Interface_QGroupBox {container=':qt_tabwidget_stackedwidget.Core__Internal__GeneralSettings_QWidget' name='interfaceBox' title='User Interface' type='QGroupBox' visible='1'} :CppCompiler:_QComboBox {container=':qt_tabwidget_stackedwidget_QWidget' leftWidget=':CppCompiler:_QLabel' type='QComboBox' unnamed='1' visible='1'} :CppCompiler:_QLabel {container=':qt_tabwidget_stackedwidget_QWidget' text='C++:' type='QLabel' unnamed='1' visible='1'} @@ -112,6 +107,12 @@ :Options.qt_tabwidget_tabbar_QTabBar {name='qt_tabwidget_tabbar' type='QTabBar' visible='1' window=':Options_Core::Internal::SettingsDialog'} :Options_Core::Internal::SettingsDialog {type='Core::Internal::SettingsDialog' unnamed='1' visible='1' windowTitle~='(Options|Preferences)'} :Options_QListView {type='QListView' unnamed='1' visible='1' window=':Options_Core::Internal::SettingsDialog'} +:PasteSelectDialog.Cancel_QPushButton {text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':PasteSelectDialog_CodePaster::PasteSelectDialog'} +:PasteSelectDialog.OK_QPushButton {text='OK' type='QPushButton' unnamed='1' visible='1' window=':PasteSelectDialog_CodePaster::PasteSelectDialog'} +:PasteSelectDialog.listWidget_QListWidget {name='listWidget' type='QListWidget' visible='1' window=':PasteSelectDialog_CodePaster::PasteSelectDialog'} +:PasteSelectDialog.pasteEdit_QLineEdit {name='pasteEdit' type='QLineEdit' visible='1' window=':PasteSelectDialog_CodePaster::PasteSelectDialog'} +:PasteSelectDialog.protocolBox_QComboBox {name='protocolBox' type='QComboBox' visible='1' window=':PasteSelectDialog_CodePaster::PasteSelectDialog'} +:PasteSelectDialog_CodePaster::PasteSelectDialog {name='CodePaster__Internal__PasteSelectDialog' type='CodePaster::PasteSelectDialog' visible='1'} :Path.Utils_BaseValidatingLineEdit {container=':qt_tabwidget_stackedwidget_QWidget' name='LineEdit' type='Utils::FancyLineEdit' visible='1'} :Projects.ProjectNavigationTreeView {container=':*Qt Creator.ProjectSelectorDockWidget_QDockWidget' name='ProjectNavigation' type='Utils::BaseTreeView' visible='1'} :QML Debugging.No_QPushButton {text='No' type='QPushButton' unnamed='1' visible='1' window=':QML Debugging_QMessageBox'} diff --git a/tests/system/suite_tools/tst_codepasting/test.py b/tests/system/suite_tools/tst_codepasting/test.py index 037b0f20906..937a2131abb 100644 --- a/tests/system/suite_tools/tst_codepasting/test.py +++ b/tests/system/suite_tools/tst_codepasting/test.py @@ -26,116 +26,153 @@ source("../../shared/qtcreator.py") import random +# Be careful with Pastebin.Com, there are only 10 pastes per 24h +# for all machines using the same IP-address like you. +skipPastingToPastebinCom = True + +NAME_KDE = "Paste.KDE.Org" +NAME_PBCA = "Pastebin.Ca" +NAME_PBCOM = "Pastebin.Com" + def invalidPasteId(protocol): - if protocol == 'Paste.KDE.Org': + if protocol == NAME_KDE: return None else: return -1 +def pasteFile(sourceFile, protocol): + aut = currentApplicationContext() + invokeMenuItem("File", "Open File or Project...") + selectFromFileDialog(sourceFile) + editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") + type(editor, "") + typeLines(editor, "// tst_codepasting %s" % datetime.utcnow()) + sourceText = editor.plainText + invokeMenuItem("Tools", "Code Pasting", "Paste Snippet...") + selectFromCombo(":Send to Codepaster.protocolBox_QComboBox", protocol) + pasteEditor = waitForObject(":stackedWidget.plainTextEdit_QPlainTextEdit") + test.compare(pasteEditor.plainText, sourceText, "Verify that dialog shows text from the editor") + description = "Description %s" % datetime.utcnow() + type(waitForObject(":uiDescription_QLineEdit"), description) + typeLines(pasteEditor, "// tst_codepasting %s" % datetime.utcnow()) + pastedText = str(pasteEditor.plainText) + expiry = waitForObject(":Send to Codepaster.qt_spinbox_lineedit_QLineEdit") + expiryDays = random.randint(1, 10) + replaceEditorContent(expiry, "%d" % expiryDays) + test.log("Using expiry of %d days." % expiryDays) + # make sure to read all former errors (they won't get read twice) + aut.readStderr() + clickButton(waitForObject(":Send to Codepaster.Paste_QPushButton")) + outputWindow = waitForObject(":Qt Creator_Core::OutputWindow") + waitFor("'https://' in str(outputWindow.plainText)", 20000) + try: + output = str(outputWindow.plainText).splitlines()[-1] + except: + output = "" + stdErrOut = aut.readStderr() + match = re.search("^%s protocol error: (.*)$" % protocol, stdErrOut, re.MULTILINE) + if match: + pasteId = invalidPasteId(protocol) + if "Internal Server Error" in match.group(1): + test.warning("Server Error - trying to continue...") + else: + test.fail("%s protocol error: %s" % (protocol, match.group(1))) + elif output.strip() == "": + pasteId = invalidPasteId(protocol) + elif "Post limit, maximum pastes per 24h reached" in output: + test.warning("Maximum pastes per day exceeded.") + pasteId = None + else: + pasteId = output.rsplit("/", 1)[1] + clickButton(waitForObject(":*Qt Creator.Clear_QToolButton")) + invokeMenuItem('File', 'Revert "main.cpp" to Saved') + clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) + snooze(1) # "Close All" might be disabled + invokeMenuItem("File", "Close All") + return pasteId, description, pastedText + +def fetchSnippet(protocol, description, pasteId, skippedPasting): + foundSnippet = True + invokeMenuItem("Tools", "Code Pasting", "Fetch Snippet...") + selectFromCombo(":PasteSelectDialog.protocolBox_QComboBox", protocol) + pasteModel = waitForObject(":PasteSelectDialog.listWidget_QListWidget").model() + waitFor("pasteModel.rowCount() > 1", 20000) + if (not skippedPasting and not protocol == NAME_PBCA + and not any(map(lambda str:pasteId in str, dumpItems(pasteModel)))): + test.warning("Fetching too fast for server of %s - waiting 3s and trying to refresh." % protocol) + snooze(3) + clickButton("{text='Refresh' type='QPushButton' unnamed='1' visible='1' " + "window=':PasteSelectDialog_CodePaster::PasteSelectDialog'}") + waitFor("pasteModel.rowCount() == 1", 1000) + waitFor("pasteModel.rowCount() > 1", 20000) + if protocol == NAME_PBCA: + description = description[:32] + if pasteId == -1: + try: + pasteLine = filter(lambda str:description in str, dumpItems(pasteModel))[0] + pasteId = pasteLine.split(" ", 1)[0] + except: + test.fail("Could not find description line in list of pastes from %s" % protocol) + clickButton(waitForObject(":PasteSelectDialog.Cancel_QPushButton")) + return pasteId + else: + try: + pasteLine = filter(lambda str:pasteId in str, dumpItems(pasteModel))[0] + if protocol in (NAME_PBCA, NAME_PBCOM): + test.verify(description in pasteLine, + "Verify that line in list of pastes contains the description") + except: + if protocol == NAME_PBCA: + test.xfail("%s does not list the pasted snippet on time" % NAME_PBCA) + elif not skippedPasting: + test.fail("Could not find id '%s' in list of pastes from %s" % (pasteId, protocol)) + foundSnippet = False + replaceEditorContent(waitForObject(":PasteSelectDialog.pasteEdit_QLineEdit"), pasteId) + if foundSnippet: + pasteLine = pasteLine.replace(".", "\\.") + waitForObjectItem(":PasteSelectDialog.listWidget_QListWidget", pasteLine) + clickItem(":PasteSelectDialog.listWidget_QListWidget", pasteLine, 5, 5, 0, Qt.LeftButton) + clickButton(waitForObject(":PasteSelectDialog.OK_QPushButton")) + return pasteId + def main(): startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): return - protocolsToTest = ["Paste.KDE.Org"] # , "Pastebin.Ca"] - # Be careful with Pastebin.Com, there are only 10 pastes per 24h - # for all machines using the same IP-address like you. - # protocolsToTest += ["Pastebin.Com"] + protocolsToTest = [NAME_KDE, NAME_PBCA, NAME_PBCOM] sourceFile = os.path.join(os.getcwd(), "testdata", "main.cpp") - aut = currentApplicationContext() # make sure General Messages is open openGeneralMessages() clickButton(waitForObject(":*Qt Creator.Clear_QToolButton")) for protocol in protocolsToTest: - invokeMenuItem("File", "Open File or Project...") - selectFromFileDialog(sourceFile) - editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") - type(editor, "") - typeLines(editor, "// tst_codepasting %s" % datetime.utcnow()) - sourceText = editor.plainText - invokeMenuItem("Tools", "Code Pasting", "Paste Snippet...") - selectFromCombo(":Send to Codepaster.protocolBox_QComboBox", protocol) - pasteEditor = waitForObject(":stackedWidget.plainTextEdit_QPlainTextEdit") - test.compare(pasteEditor.plainText, sourceText, "Verify that dialog shows text from the editor") - description = "Description %s" % datetime.utcnow() - type(waitForObject(":uiDescription_QLineEdit"), description) - typeLines(pasteEditor, "// tst_codepasting %s" % datetime.utcnow()) - pastedText = str(pasteEditor.plainText) - expiry = waitForObject(":Send to Codepaster.qt_spinbox_lineedit_QLineEdit") - expiryDays = random.randint(1, 10) - replaceEditorContent(expiry, "%d" % expiryDays) - test.log("Using expiry of %d days." % expiryDays) - # make sure to read all former errors (they won't get read twice) - aut.readStderr() - clickButton(waitForObject(":Send to Codepaster.Paste_QPushButton")) - outputWindow = waitForObject(":Qt Creator_Core::OutputWindow") - waitFor("'http://' in str(outputWindow.plainText)", 20000) - try: - output = str(outputWindow.plainText).splitlines()[-1] - except: - output = "" - stdErrOut = aut.readStderr() - match = re.search("^%s protocol error: (.*)$" % protocol, stdErrOut, re.MULTILINE) - if match: - pasteId = invalidPasteId(protocol) - if "Internal Server Error" in match.group(1): - test.warning("Server Error - trying to continue...") - else: - test.fail("%s protocol error: %s" % (protocol, match.group(1))) - elif output.strip() == "": - pasteId = invalidPasteId(protocol) - elif "Post limit, maximum pastes per 24h reached" in output: - test.warning("Maximum pastes per day exceeded.") - pasteId = None + skippedPasting = True + description = "Paste from 2017-05-11" + if protocol == NAME_KDE: + pasteId = "pyy2xvjh7" # valid for one year + pastedText = readFile(os.path.join(os.getcwd(), "testdata", "main-prepasted.cpp")) + elif skipPastingToPastebinCom and protocol == NAME_PBCOM: + pasteId = "8XHP0ZgH" + pastedText = readFile(os.path.join(os.getcwd(), "testdata", "main-prepasted.cpp")) else: - pasteId = output.rsplit("/", 1)[1] - clickButton(waitForObject(":*Qt Creator.Clear_QToolButton")) - invokeMenuItem('File', 'Revert "main.cpp" to Saved') - clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) - snooze(1) # "Close All" might be disabled - invokeMenuItem("File", "Close All") - if not pasteId: - test.fatal("Could not get id of paste to %s" % protocol) - continue - invokeMenuItem("Tools", "Code Pasting", "Fetch Snippet...") - selectFromCombo(":CodePaster__Internal__PasteSelectDialog.protocolBox_QComboBox", protocol) - pasteModel = waitForObject(":CodePaster__Internal__PasteSelectDialog.listWidget_QListWidget").model() - waitFor("pasteModel.rowCount() > 1", 20000) - if (pasteId not in dumpItems(pasteModel)): - test.warning("Fetching too fast for server of %s - waiting 3s and trying to refresh." - % protocol) - snooze(3) - clickButton("{text='Refresh' type='QPushButton' unnamed='1' visible='1' " - "window=':CodePaster__Internal__PasteSelectDialog_CodePaster::PasteSelectDialog'}") - waitFor("pasteModel.rowCount() == 1", 1000) - waitFor("pasteModel.rowCount() > 1", 20000) - if protocol == 'Pastebin.Ca': - description = description[:32] + skippedPasting = False + pasteId, description, pastedText = pasteFile(sourceFile, protocol) + if not pasteId: + test.fatal("Could not get id of paste to %s" % protocol) + continue + pasteId = fetchSnippet(protocol, description, pasteId, skippedPasting) if pasteId == -1: - try: - pasteLine = filter(lambda str: description in str, dumpItems(pasteModel))[0] - pasteId = pasteLine.split(" ", 1)[0] - except: - test.fail("Could not find description line in list of pastes from %s" % protocol) - clickButton(waitForObject(":CodePaster__Internal__PasteSelectDialog.Cancel_QPushButton")) - continue - else: - try: - pasteLine = filter(lambda str: pasteId in str, dumpItems(pasteModel))[0] - except: - test.fail("Could not find id '%s' in list of pastes from %s" % (pasteId, protocol)) - clickButton(waitForObject(":CodePaster__Internal__PasteSelectDialog.Cancel_QPushButton")) - continue - if protocol.startswith("Pastebin."): - test.verify(description in pasteLine, "Verify that line in list of pastes contains the description") - pasteLine = pasteLine.replace(".", "\\.") - waitForObjectItem(":CodePaster__Internal__PasteSelectDialog.listWidget_QListWidget", pasteLine) - clickItem(":CodePaster__Internal__PasteSelectDialog.listWidget_QListWidget", pasteLine, 5, 5, 0, Qt.LeftButton) - clickButton(waitForObject(":CodePaster__Internal__PasteSelectDialog.OK_QPushButton")) + continue filenameCombo = waitForObject(":Qt Creator_FilenameQComboBox") waitFor("not filenameCombo.currentText.isEmpty()", 20000) - editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") + try: + editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") + except: + outputWindow = waitForObject(":Qt Creator_Core::OutputWindow") + test.fail("Could not find editor with snippet", str(outputWindow.plainText)) + clickButton(waitForObject(":*Qt Creator.Clear_QToolButton")) + continue test.compare(filenameCombo.currentText, "%s: %s" % (protocol, pasteId), "Verify title of editor") - if protocol == "Pastebin.Com" and pastedText.endswith("\n"): + if protocol == NAME_PBCOM and pastedText.endswith("\n"): pastedText = pastedText[:-1] test.compare(editor.plainText, pastedText, "Verify that pasted and fetched texts are the same") invokeMenuItem("File", "Close All") diff --git a/tests/system/suite_tools/tst_codepasting/testdata/main-prepasted.cpp b/tests/system/suite_tools/tst_codepasting/testdata/main-prepasted.cpp new file mode 100644 index 00000000000..52b2c4914ea --- /dev/null +++ b/tests/system/suite_tools/tst_codepasting/testdata/main-prepasted.cpp @@ -0,0 +1,13 @@ +// tst_codepasting 2017-05-11 10:18:48.025820 +// tst_codepasting 2017-05-11 10:18:45.661681 +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +}