Merge remote-tracking branch 'origin/6.0'

Change-Id: If773f217a9708ce0ad0b8adeefe3266ba0371a32
This commit is contained in:
Eike Ziller
2021-09-29 12:54:38 +02:00
134 changed files with 1422 additions and 1037 deletions

70
dist/changes-5.0.2.md vendored Normal file
View File

@@ -0,0 +1,70 @@
Qt Creator 5.0.2
================
Qt Creator version 5.0.2 contains bug fixes.
The most important changes are listed in this document. For a complete list of
changes, see the Git log for the Qt Creator sources that you can check out from
the public Git repository. For example:
git clone git://code.qt.io/qt-creator/qt-creator.git
git log --cherry-pick --pretty=oneline origin/v5.0.1..v5.0.2
Help
----
* Fixed that Qt 5 context help was shown even if Qt 6 documentation is available
(QTCREATORBUG-26292)
Projects
--------
* Fixed canceling of builds (QTCREATORBUG-26271)
### CMake
* Changed the `File System` special node to be shown only on parsing failure
(QTCREATORBUG-25994, QTCREATORBUG-25974)
* Fixed loading of projects without targets (QTCREATORBUG-25509)
* Fixed that no targets where shown in added build step (QTCREATORBUG-25759)
* Fixed that `ninja` could not be found after changing Qt installation location
(QTCREATORBUG-26289)
Debugging
---------
### GDB
* Fixed debugging of terminal applications with GDB < 10 (QTCREATORBUG-26299)
Platforms
---------
### macOS
* Fixed issue with absolute RPATH in `clazy-standalone` (QTCREATORBUG-26196)
### Android
* Fixed that wrong deployment file could be used (QTCREATORBUG-25793)
Credits for these changes go to:
--------------------------------
Alessandro Portale
Assam Boudjelthia
Christian Kandeler
Christian Stenger
Cristian Adam
Eike Ziller
Henning Gruendl
Ivan Komissarov
Jaroslaw Kobus
Johanna Vanhatapio
Kai Köhne
Knud Dollereder
Leena Miettinen
Mahmoud Badri
Marco Bubke
Orgad Shaneh
Robert Löhning
Thomas Hartmann

Binary file not shown.

Before

Width:  |  Height:  |  Size: 604 B

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 677 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Auto Test Project",
"trDisplayCategory": "Other Project",
"icon": "autotest.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureDesktop" ],
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Python Class",
"trDisplayCategory": "Python",
"icon": "../../files/python/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Nim File",
"trDisplayCategory": "Nim",
"icon": "../../projects/nim/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}",
"options": { "key": "DefaultSuffix", "value": "nim" },

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Nim Script File",
"trDisplayCategory": "Nim",
"icon": "../../projects/nim/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0}",
"options": { "key": "DefaultSuffix", "value": "nims" },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 592 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Python File",
"trDisplayCategory": "Python",
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options": { "key": "DefaultSuffix", "value": "%{JS: Util.preferredSuffix('text/x-python')}" },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 B

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 983 B

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Console Application",
"trDisplayCategory": "Application (Qt)",
"icon": "../../global/consoleapplication.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0}",

View File

@@ -7,6 +7,7 @@
"trDisplayName": "C++ Library",
"trDisplayCategory": "Library",
"icon": "../../global/lib.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -8,6 +8,7 @@
"trDisplayCategory": "Non-Qt Project",
"featuresRequired": [ "ToolChain.Nim.NimToolChain" ],
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Nim') >= 0 }",
"options":

View File

@@ -10,6 +10,7 @@
"ToolChain.Nim.NimToolChain"
],
"icon":"../nim/icon.png",
"iconKind": "Themed",
"enabled":"%{JS: value('Plugins').indexOf('Nim') >= 0 }",
"options":[
{

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Plain C Application",
"trDisplayCategory": "Non-Qt Project",
"icon": "../../global/consoleapplication.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}",
"options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Plain C++ Application",
"trDisplayCategory": "Non-Qt Project",
"icon": "../../global/consoleapplication.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0 && (value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0)}",
"options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Empty qmake Project",
"trDisplayCategory": "Other Project",
"icon": "../../../global/guiapplication.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 B

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Empty",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 855 B

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 849 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Window",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Qt Quick Application - Empty",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options":

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt for Python - Window (UI file)",
"trDisplayCategory": "Application (Qt for Python)",
"icon": "../icons/icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Python') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Quick 2 Extension Plugin",
"trDisplayCategory": "Library",
"icon": "lib.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick", "QtSupport.Wizards.FeatureQtQuick.2" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Quick Application",
"trDisplayCategory": "Application (Qt)",
"icon": "icon.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.6" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Quick UI Prototype",
"trDisplayCategory": "Other Project",
"icon": "qtquickuiprototype.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Widgets Application",
"trDisplayCategory": "Application (Qt)",
"icon": "../../global/guiapplication.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt" ],
"enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0 || value('Plugins').indexOf('QbsProjectManager') >= 0 || value('Plugins').indexOf('MesonProjectManager') >= 0}",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Bazaar Clone (Or Branch)",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Bazaar') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "CVS Checkout",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('CVS') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Git Clone",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Git') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Mercurial Clone",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Mercurial') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Subversion Checkout",
"trDisplayCategory": "Import Project",
"icon": "icon.png",
"iconKind": "Themed",
"enabled": "%{JS: value('Plugins').indexOf('Subversion') >= 0}",
"options":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -7,6 +7,7 @@
"trDisplayName": "Qt Creator Plugin",
"trDisplayCategory": "Library",
"icon": "qtcreatorplugin.png",
"iconKind": "Themed",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt", "QtSupport.Wizards.FeatureDesktop" ],
"enabled": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}",

View File

@@ -12,7 +12,7 @@ install(
add_qtc_executable(qtcreator
DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils QtcSsh shared_qtsingleapplication app_version
DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils shared_qtsingleapplication app_version
SOURCES
main.cpp
../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h

View File

@@ -17,7 +17,7 @@ include(../rpath.pri)
include(../libs/qt-breakpad/qtbreakpad.pri)
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils) -l$$qtLibraryName(QtcSsh)
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils)
win32 {
# We need the version in two separate formats for the .rc file

View File

@@ -46,7 +46,6 @@ QtcProduct {
Depends { name: "app_version_header" }
Depends { name: "Qt"; submodules: ["widgets", "network"] }
Depends { name: "Utils" }
Depends { name: "QtcSsh" }
Depends { name: "ExtensionSystem" }
files: [

View File

@@ -32,16 +32,13 @@
#include <extensionsystem/pluginspec.h>
#include <qtsingleapplication.h>
#include <ssh/sshconnectionmanager.h>
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/launcherinterface.h>
#include <utils/optional.h>
#include <utils/processreaper.h>
#include <utils/qtcsettings.h>
#include <utils/singleton.h>
#include <utils/temporarydirectory.h>
#include <QDebug>
@@ -537,10 +534,7 @@ int main(int argc, char **argv)
QCoreApplication::setOrganizationName(QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR));
QGuiApplication::setApplicationDisplayName(Core::Constants::IDE_DISPLAY_NAME);
Utils::ProcessReaper processReaper;
Utils::LauncherInterface::startLauncher();
auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); });
QSsh::SshConnectionManager sshConnectionManager;
auto cleanup = qScopeGuard([] { Utils::Singleton::deleteAll(); });
const QStringList pluginArguments = app.arguments();

View File

@@ -53,16 +53,11 @@ bool operator!=(const UnacquiredConnection &c1, const UnacquiredConnection &c2)
return !(c1 == c2);
}
static class SshConnectionManagerPrivate *s_instance = nullptr;
class SshConnectionManagerPrivate : public QObject
{
public:
SshConnectionManagerPrivate()
{
QTC_ASSERT(s_instance == nullptr, return);
s_instance = this;
connect(&m_removalTimer, &QTimer::timeout,
this, &SshConnectionManagerPrivate::removeInactiveConnections);
m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
@@ -70,8 +65,6 @@ public:
~SshConnectionManagerPrivate() override
{
QTC_ASSERT(s_instance == this, return);
for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) {
disconnect(connection.connection, nullptr, this, nullptr);
delete connection.connection;
@@ -79,8 +72,6 @@ public:
QTC_CHECK(m_acquiredConnections.isEmpty());
QTC_CHECK(m_deprecatedConnections.isEmpty());
s_instance = nullptr;
}
SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
@@ -213,6 +204,7 @@ private:
SshConnectionManager::SshConnectionManager()
: d(new Internal::SshConnectionManagerPrivate())
{
QTC_CHECK(QThread::currentThread() == qApp->thread());
}
SshConnectionManager::~SshConnectionManager()
@@ -222,20 +214,17 @@ SshConnectionManager::~SshConnectionManager()
SshConnection *SshConnectionManager::acquireConnection(const SshConnectionParameters &sshParams)
{
QTC_ASSERT(Internal::s_instance, return nullptr);
return Internal::s_instance->acquireConnection(sshParams);
return instance()->d->acquireConnection(sshParams);
}
void SshConnectionManager::releaseConnection(SshConnection *connection)
{
QTC_ASSERT(Internal::s_instance, return);
Internal::s_instance->releaseConnection(connection);
instance()->d->releaseConnection(connection);
}
void SshConnectionManager::forceNewConnection(const SshConnectionParameters &sshParams)
{
QTC_ASSERT(Internal::s_instance, return);
Internal::s_instance->forceNewConnection(sshParams);
instance()->d->forceNewConnection(sshParams);
}
} // namespace QSsh

View File

@@ -27,6 +27,9 @@
#include "ssh_global.h"
#include <utils/launcherinterface.h>
#include <utils/singleton.h>
namespace QSsh {
class SshConnection;
@@ -35,18 +38,21 @@ class SshConnectionParameters;
namespace Internal { class SshConnectionManagerPrivate; }
class QSSH_EXPORT SshConnectionManager final
: public Utils::SingletonWithOptionalDependencies<SshConnectionManager,
Utils::LauncherInterface>
{
public:
SshConnectionManager();
~SshConnectionManager();
static SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
static void releaseConnection(SshConnection *connection);
// Make sure the next acquireConnection with the given parameters will return a new connection.
static void forceNewConnection(const SshConnectionParameters &sshParams);
private:
SshConnectionManager();
~SshConnectionManager();
Internal::SshConnectionManagerPrivate *d;
friend class Utils::SingletonWithOptionalDependencies<SshConnectionManager, Utils::LauncherInterface>;
};
} // namespace QSsh

View File

@@ -144,6 +144,7 @@ add_qtc_library(Utils
settingsutils.h
shellcommand.cpp shellcommand.h
shellcommandpage.cpp shellcommandpage.h
singleton.cpp singleton.h
sizedarray.h
smallstring.h
smallstringfwd.h

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 241 B

View File

@@ -28,7 +28,6 @@
#include "filepath.h"
#include "launcherpackets.h"
#include "launchersocket.h"
#include "processreaper.h"
#include "qtcassert.h"
#include <QCoreApplication>
@@ -42,7 +41,6 @@
#endif
namespace Utils {
namespace Internal {
class LauncherProcess : public QProcess
@@ -185,92 +183,73 @@ void LauncherInterfacePrivate::handleProcessStderr()
using namespace Utils::Internal;
static QMutex s_instanceMutex;
static LauncherInterface *s_instance = nullptr;
static QString s_pathToLauncher;
static std::atomic_bool s_started = false;
LauncherInterface::LauncherInterface()
: m_private(new LauncherInterfacePrivate())
{
m_private->moveToThread(&m_thread);
connect(m_private, &LauncherInterfacePrivate::errorOccurred,
this, &LauncherInterface::errorOccurred);
connect(&m_thread, &QThread::finished, m_private, &QObject::deleteLater);
QObject::connect(&m_thread, &QThread::finished, m_private, &QObject::deleteLater);
m_thread.start();
}
m_thread.moveToThread(qApp->thread());
LauncherInterface::~LauncherInterface()
{
m_thread.quit();
m_thread.wait();
}
// Called from main thread
void LauncherInterface::startLauncher(const QString &pathToLauncher)
{
QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance == nullptr, return);
s_instance = new LauncherInterface();
LauncherInterfacePrivate *p = s_instance->m_private;
p->setPathToLauncher(pathToLauncher);
const FilePath launcherFilePath = FilePath::fromString(p->launcherFilePath())
m_private->setPathToLauncher(s_pathToLauncher);
const FilePath launcherFilePath = FilePath::fromString(m_private->launcherFilePath())
.cleanPath().withExecutableSuffix();
auto launcherIsNotExecutable = [&launcherFilePath]() {
qWarning() << "The Creator's process launcher"
<< launcherFilePath << "is not executable.";
};
QTC_ASSERT(launcherFilePath.isExecutableFile(), launcherIsNotExecutable(); return);
s_started = true;
// Call in launcher's thread.
QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStart);
QMetaObject::invokeMethod(m_private, &LauncherInterfacePrivate::doStart);
}
// Called from main thread
void LauncherInterface::stopLauncher()
LauncherInterface::~LauncherInterface()
{
QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return);
LauncherInterfacePrivate *p = s_instance->m_private;
LauncherInterfacePrivate *p = instance()->m_private;
// Call in launcher's thread.
QMetaObject::invokeMethod(p, &LauncherInterfacePrivate::doStop, Qt::BlockingQueuedConnection);
delete s_instance;
s_instance = nullptr;
m_thread.quit();
m_thread.wait();
}
void LauncherInterface::setPathToLauncher(const QString &pathToLauncher)
{
s_pathToLauncher = pathToLauncher;
}
bool LauncherInterface::isStarted()
{
QMutexLocker locker(&s_instanceMutex);
return s_instance != nullptr;
return s_started;
}
bool LauncherInterface::isReady()
{
QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return false);
return s_instance->m_private->socket()->isReady();
return instance()->m_private->socket()->isReady();
}
void LauncherInterface::sendData(const QByteArray &data)
{
QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return);
s_instance->m_private->socket()->sendData(data);
instance()->m_private->socket()->sendData(data);
}
Utils::Internal::CallerHandle *LauncherInterface::registerHandle(QObject *parent, quintptr token,
ProcessMode mode)
{
QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return nullptr);
return s_instance->m_private->socket()->registerHandle(parent, token, mode);
return instance()->m_private->socket()->registerHandle(parent, token, mode);
}
void LauncherInterface::unregisterHandle(quintptr token)
{
QMutexLocker locker(&s_instanceMutex);
QTC_ASSERT(s_instance != nullptr, return);
s_instance->m_private->socket()->unregisterHandle(token);
instance()->m_private->socket()->unregisterHandle(token);
}
} // namespace Utils

View File

@@ -27,9 +27,10 @@
#include "utils_global.h"
#include "processreaper.h"
#include "processutils.h"
#include "singleton.h"
#include <QObject>
#include <QThread>
namespace Utils {
@@ -40,15 +41,11 @@ class LauncherInterfacePrivate;
class ProcessLauncherImpl;
}
class QTCREATOR_UTILS_EXPORT LauncherInterface : public QObject
class QTCREATOR_UTILS_EXPORT LauncherInterface final
: public SingletonWithOptionalDependencies<LauncherInterface, ProcessReaper>
{
Q_OBJECT
public:
static void startLauncher(const QString &pathToLauncher = {});
static void stopLauncher();
signals:
void errorOccurred(const QString &error);
static void setPathToLauncher(const QString &pathToLauncher);
private:
friend class Utils::Internal::CallerHandle;
@@ -63,10 +60,11 @@ private:
static void unregisterHandle(quintptr token);
LauncherInterface();
~LauncherInterface() override;
~LauncherInterface();
QThread m_thread;
Internal::LauncherInterfacePrivate *m_private;
friend class SingletonWithOptionalDependencies<LauncherInterface, ProcessReaper>;
};
} // namespace Utils

View File

@@ -36,8 +36,6 @@ using namespace Utils;
namespace Utils {
namespace Internal {
static ProcessReaper *d = nullptr;
class Reaper final : public QObject
{
public:
@@ -57,7 +55,7 @@ private:
Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
{
d->m_reapers.append(this);
ProcessReaper::instance()->m_reapers.append(this);
m_iterationTimer.setInterval(timeoutMs);
m_iterationTimer.setSingleShot(true);
@@ -68,7 +66,7 @@ Reaper::Reaper(QProcess *p, int timeoutMs) : m_process(p)
Reaper::~Reaper()
{
d->m_reapers.removeOne(this);
ProcessReaper::instance()->m_reapers.removeOne(this);
}
int Reaper::timeoutMs() const
@@ -112,15 +110,8 @@ void Reaper::nextIteration()
} // namespace Internal
ProcessReaper::ProcessReaper()
{
QTC_ASSERT(Internal::d == nullptr, return);
Internal::d = this;
}
ProcessReaper::~ProcessReaper()
{
QTC_ASSERT(Internal::d == this, return);
while (!m_reapers.isEmpty()) {
int alreadyWaited = 0;
QList<Internal::Reaper *> toDelete;
@@ -145,8 +136,6 @@ ProcessReaper::~ProcessReaper()
qDeleteAll(toDelete);
toDelete.clear();
}
Internal::d = nullptr;
}
void ProcessReaper::reap(QProcess *process, int timeoutMs)
@@ -175,8 +164,6 @@ void ProcessReaper::reap(QProcess *process, int timeoutMs)
return;
}
QTC_ASSERT(Internal::d, return);
new Internal::Reaper(process, timeoutMs);
}

View File

@@ -27,6 +27,8 @@
#include "utils_global.h"
#include "singleton.h"
#include <QList>
QT_BEGIN_NAMESPACE
@@ -38,15 +40,16 @@ namespace Utils {
namespace Internal { class Reaper; }
class QTCREATOR_UTILS_EXPORT ProcessReaper final
: public SingletonWithOptionalDependencies<ProcessReaper>
{
public:
ProcessReaper();
~ProcessReaper();
static void reap(QProcess *process, int timeoutMs = 500);
private:
ProcessReaper() = default;
~ProcessReaper();
QList<Internal::Reaper *> m_reapers;
friend class Internal::Reaper;
friend class SingletonWithOptionalDependencies<ProcessReaper>;
};
} // namespace Utils

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qtcassert.h"
#include "singleton.h"
#include <QCoreApplication>
#include <QList>
#include <QThread>
#include <unordered_map>
using namespace Utils;
namespace Utils {
// The order of elements reflects dependencies, i.e.
// if B requires A then B will follow A on this list
static QList<Singleton *> s_singletonList;
static QMutex s_mutex;
static std::unordered_map<std::type_index, SingletonStaticData> s_staticDataList;
Singleton::~Singleton()
{
QMutexLocker locker(&s_mutex);
s_singletonList.removeAll(this);
}
void Singleton::addSingleton(Singleton *singleton)
{
QMutexLocker locker(&s_mutex);
s_singletonList.append(singleton);
}
SingletonStaticData &Singleton::staticData(std::type_index index)
{
QMutexLocker locker(&s_mutex);
return s_staticDataList[index];
}
// Note: it's caller responsibility to ensure that this function is being called when all other
// threads don't use any singleton. As a good practice: finish all other threads that were using
// singletons before this function is called.
// Some singletons (currently e.g. SshConnectionManager) can work only in main thread,
// so this method should be called from main thread only.
void Singleton::deleteAll()
{
QTC_ASSERT(QThread::currentThread() == qApp->thread(), return);
QList<Singleton *> oldList;
{
QMutexLocker locker(&s_mutex);
oldList = s_singletonList;
s_singletonList = {};
}
// Keep the reverse order when deleting
while (!oldList.isEmpty())
delete oldList.takeLast();
}
} // namespace Utils

106
src/libs/utils/singleton.h Normal file
View File

@@ -0,0 +1,106 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "utils_global.h"
#include <QMutex>
#include <QMutexLocker>
#include <type_traits>
#include <typeindex>
namespace Utils {
class Singleton;
struct SingletonStaticData
{
Singleton *m_instance = nullptr;
QMutex m_mutex;
};
class QTCREATOR_UTILS_EXPORT Singleton
{
Q_DISABLE_COPY_MOVE(Singleton)
public:
static void deleteAll();
private:
template <typename SingletonSubClass, typename ...Dependencies>
friend class SingletonWithOptionalDependencies;
Singleton() = default;
virtual ~Singleton();
static void addSingleton(Singleton *singleton);
static SingletonStaticData &staticData(std::type_index index);
};
template <typename SingletonSubClass, typename ...Dependencies>
class SingletonWithOptionalDependencies : public Singleton
{
public:
Q_DISABLE_COPY_MOVE(SingletonWithOptionalDependencies)
static SingletonSubClass *instance()
{
SingletonStaticData &data = staticData();
QMutexLocker locker(&data.m_mutex);
if (data.m_instance == nullptr) {
// instantiate all dependencies first
if constexpr (sizeof...(Dependencies))
instantiateDependencies<Dependencies...>();
data.m_instance = new SingletonSubClass;
// put instance into static list of registered instances
addSingleton(data.m_instance);
}
return static_cast<SingletonSubClass *>(data.m_instance);
}
protected:
SingletonWithOptionalDependencies() = default;
~SingletonWithOptionalDependencies() override
{
SingletonStaticData &data = staticData();
QMutexLocker locker(&data.m_mutex);
if (data.m_instance == this)
data.m_instance = nullptr;
}
private:
template <typename ...Dependency> static void instantiateDependencies()
{
static_assert ((... && std::is_base_of_v<Singleton, Dependency>),
"All Dependencies must derive from SingletonWithOptionalDependencies class.");
(..., Dependency::instance());
}
static SingletonStaticData &staticData()
{
static SingletonStaticData &data = Singleton::staticData(std::type_index(typeid(SingletonSubClass)));
return data;
}
};
} // namespace Utils

View File

@@ -143,6 +143,7 @@ SOURCES += \
$$PWD/link.cpp \
$$PWD/linecolumn.cpp \
$$PWD/multitextcursor.cpp \
$$PWD/singleton.cpp
HEADERS += \
$$PWD/environmentfwd.h \
@@ -307,8 +308,9 @@ HEADERS += \
$$PWD/launcherinterface.h \
$$PWD/launcherpackets.h \
$$PWD/launchersocket.h \
$$PWD/qtcsettings.h
$$PWD/qtcsettings.h \
$$PWD/multitextcursor.h \
$$PWD/singleton.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \

View File

@@ -264,6 +264,8 @@ Project {
"shellcommand.h",
"shellcommandpage.cpp",
"shellcommandpage.h",
"singleton.cpp",
"singleton.h",
"sizedarray.h",
"smallstring.h",
"smallstringiterator.h",

View File

@@ -119,6 +119,7 @@ static CreateAvdInfo createAvdCommand(const AndroidConfig &config, const CreateA
qCDebug(avdManagerLog)
<< "Running AVD Manager command:" << CommandLine(avdManagerTool, arguments).toUserOutput();
QProcess proc;
proc.setEnvironment(AndroidConfigurations::toolsEnvironment(config).toStringList());
proc.start(avdManagerTool.toString(), arguments);
if (!proc.waitForStarted()) {
result.error = QApplication::translate("AndroidAvdManager",

View File

@@ -604,50 +604,20 @@ AndroidDeviceFactory::AndroidDeviceFactory()
IDevice::Ptr AndroidDeviceFactory::create() const
{
AndroidSdkManager sdkManager = AndroidSdkManager(m_androidConfig);
const CreateAvdInfo info = AvdDialog::gatherCreateAVDInfo(Core::ICore::dialogParent(),
&sdkManager, m_androidConfig);
if (!info.isValid()) {
if (!info.cancelled) {
AndroidDeviceWidget::criticalDialog(
QObject::tr("The returned device info is invalid."));
}
return nullptr;
AvdDialog dialog = AvdDialog(m_androidConfig, Core::ICore::dialogParent());
if (dialog.exec() != QDialog::Accepted)
return ProjectExplorer::IDevice::Ptr();
const ProjectExplorer::IDevice::Ptr dev = dialog.device();
const AndroidDevice *androidDev = static_cast<AndroidDevice*>(dev.data());
if (androidDev) {
qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".",
qPrintable(androidDev->avdName()));
} else {
AndroidDeviceWidget::criticalDialog(
QObject::tr("The device info returned from AvdDialog is invalid."));
}
const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig);
QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher;
createAvdFutureWatcher.setFuture(avdManager.createAvd(info));
QEventLoop loop;
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::finished,
&loop, &QEventLoop::quit);
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::canceled,
&loop, &QEventLoop::quit);
loop.exec(QEventLoop::ExcludeUserInputEvents);
QFuture<CreateAvdInfo> future = createAvdFutureWatcher.future();
if (!(future.isResultReadyAt(0) && future.result().isValid())) {
AndroidDeviceWidget::criticalDialog(QObject::tr("The device info returned by "
"avdmanager tool is invalid for the device name \"%1\".").arg(info.name));
return nullptr;
}
const CreateAvdInfo newAvdInfo = createAvdFutureWatcher.result();
AndroidDevice *dev = new AndroidDevice();
const Utils::Id deviceId = AndroidDevice::idFromAvdInfo(newAvdInfo);
dev->setupId(IDevice::AutoDetected, deviceId);
dev->setMachineType(IDevice::Emulator);
dev->setDisplayName(newAvdInfo.name);
dev->setDeviceState(IDevice::DeviceConnected);
dev->setExtraData(Constants::AndroidAvdName, newAvdInfo.name);
dev->setExtraData(Constants::AndroidCpuAbi, {newAvdInfo.abi});
dev->setExtraData(Constants::AndroidSdk, newAvdInfo.systemImage->apiLevel());
dev->setExtraData(Constants::AndroidAvdSdcard, QString("%1 MB").arg(newAvdInfo.sdcardSize));
dev->setExtraData(Constants::AndroidAvdDevice, newAvdInfo.deviceDefinition);
qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".", qPrintable(newAvdInfo.name));
return IDevice::Ptr(dev);
}

View File

@@ -694,7 +694,7 @@ bool SdkManagerOutputParser::parseAbstractData(SdkManagerOutputParser::GenericPa
for (const auto &key: qAsConst(keys)) {
if (valueForKey(key, line, &value)) {
if (key == installLocationKey)
output.installedLocation = Utils::FilePath::fromString(value);
output.installedLocation = Utils::FilePath::fromUserInput(value);
else if (key == revisionKey)
output.revision = QVersionNumber::fromString(value);
else if (key == descriptionKey)

View File

@@ -241,7 +241,7 @@ void AndroidSettingsWidget::updateNdkList()
const auto installedPkgs = m_sdkManager.installedNdkPackages();
for (const Ndk *ndk : installedPkgs) {
m_ui.ndkListWidget->addItem(new QListWidgetItem(Icons::LOCKED.icon(),
ndk->installedLocation().toString()));
ndk->installedLocation().toUserOutput()));
}
const auto customNdks = m_androidConfig.getCustomNdkList();

View File

@@ -26,6 +26,8 @@
#include "avddialog.h"
#include "androidsdkmanager.h"
#include "androidavdmanager.h"
#include "androiddevice.h"
#include "androidconstants.h"
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
@@ -33,6 +35,7 @@
#include <utils/utilsicons.h>
#include <utils/qtcassert.h>
#include <QFutureWatcher>
#include <QKeyEvent>
#include <QMessageBox>
#include <QToolTip>
@@ -46,29 +49,35 @@ namespace {
static Q_LOGGING_CATEGORY(avdDialogLog, "qtc.android.avdDialog", QtWarningMsg)
}
AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStringList &abis,
const AndroidConfig &config, QWidget *parent) :
QDialog(parent),
m_sdkManager(sdkManager),
m_minApiLevel(minApiLevel),
m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")),
m_androidConfig(config)
AvdDialog::AvdDialog(const AndroidConfig &config, QWidget *parent)
: QDialog(parent),
m_sdkManager(m_androidConfig),
m_allowedNameChars(QLatin1String("[a-z|A-Z|0-9|._-]*")),
m_androidConfig(config)
{
QTC_CHECK(m_sdkManager);
m_avdDialog.setupUi(this);
m_hideTipTimer.setInterval(2000);
m_hideTipTimer.setSingleShot(true);
if (abis.isEmpty()) {
m_avdDialog.abiComboBox->addItems(QStringList({
ProjectExplorer::Constants::ANDROID_ABI_X86,
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI,
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A}));
} else {
m_avdDialog.abiComboBox->addItems(abis);
}
connect(&m_hideTipTimer, &QTimer::timeout, this, &Utils::ToolTip::hide);
connect(m_avdDialog.deviceDefinitionTypeComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AvdDialog::updateDeviceDefinitionComboBox);
connect(m_avdDialog.abiComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AvdDialog::updateApiLevelComboBox);
deviceTypeToStringMap.insert(AvdDialog::Phone, "Phone");
deviceTypeToStringMap.insert(AvdDialog::Tablet, "Tablet");
deviceTypeToStringMap.insert(AvdDialog::Automotive, "Automotive");
deviceTypeToStringMap.insert(AvdDialog::TV, "TV");
deviceTypeToStringMap.insert(AvdDialog::Wear, "Wear");
m_avdDialog.abiComboBox->addItems(QStringList({
ProjectExplorer::Constants::ANDROID_ABI_X86,
ProjectExplorer::Constants::ANDROID_ABI_X86_64,
ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A,
ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A}));
auto v = new QRegularExpressionValidator(m_allowedNameChars, this);
m_avdDialog.nameLineEdit->setValidator(v);
@@ -77,46 +86,70 @@ AvdDialog::AvdDialog(int minApiLevel, AndroidSdkManager *sdkManager, const QStri
m_avdDialog.warningText->setType(Utils::InfoLabel::Warning);
m_avdDialog.warningText->setElideMode(Qt::ElideNone);
connect(&m_hideTipTimer, &QTimer::timeout, this, []() { Utils::ToolTip::hide(); });
parseDeviceDefinitionsList();
for (const QString &type : DeviceTypeToStringMap)
for (const QString &type : deviceTypeToStringMap)
m_avdDialog.deviceDefinitionTypeComboBox->addItem(type);
connect(m_avdDialog.deviceDefinitionTypeComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&AvdDialog::updateDeviceDefinitionComboBox);
connect(m_avdDialog.abiComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &AvdDialog::updateApiLevelComboBox);
m_avdDialog.deviceDefinitionTypeComboBox->setCurrentIndex(1); // Set Phone type as default index
updateApiLevelComboBox();
}
int AvdDialog::exec()
{
const int execResult = QDialog::exec();
if (execResult == QDialog::Accepted) {
CreateAvdInfo result;
result.systemImage = systemImage();
result.name = name();
result.abi = abi();
result.deviceDefinition = deviceDefinition();
result.sdcardSize = sdcardSize();
result.overwrite = m_avdDialog.overwriteCheckBox->isChecked();
const AndroidAvdManager avdManager = AndroidAvdManager(m_androidConfig);
QFutureWatcher<CreateAvdInfo> createAvdFutureWatcher;
createAvdFutureWatcher.setFuture(avdManager.createAvd(result));
QEventLoop loop;
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::finished,
&loop, &QEventLoop::quit);
QObject::connect(&createAvdFutureWatcher, &QFutureWatcher<CreateAvdInfo>::canceled,
&loop, &QEventLoop::quit);
loop.exec(QEventLoop::ExcludeUserInputEvents);
const QFuture<CreateAvdInfo> future = createAvdFutureWatcher.future();
if (future.isResultReadyAt(0))
m_createdAvdInfo = future.result();
}
return execResult;
}
bool AvdDialog::isValid() const
{
return !name().isEmpty() && systemImage() && systemImage()->isValid() && !abi().isEmpty();
}
CreateAvdInfo AvdDialog::gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager,
const AndroidConfig &config, int minApiLevel, const QStringList &abis)
ProjectExplorer::IDevice::Ptr AvdDialog::device() const
{
CreateAvdInfo result;
AvdDialog d(minApiLevel, sdkManager, abis, config, parent);
result.cancelled = (d.exec() != QDialog::Accepted);
if (result.cancelled || !d.isValid())
return result;
AndroidDevice *dev = new AndroidDevice();
const Utils::Id deviceId = AndroidDevice::idFromAvdInfo(m_createdAvdInfo);
using namespace ProjectExplorer;
dev->setupId(IDevice::AutoDetected, deviceId);
dev->setMachineType(IDevice::Emulator);
dev->setDisplayName(m_createdAvdInfo.name);
dev->setDeviceState(IDevice::DeviceConnected);
dev->setExtraData(Constants::AndroidAvdName, m_createdAvdInfo.name);
dev->setExtraData(Constants::AndroidCpuAbi, {m_createdAvdInfo.abi});
if (!m_createdAvdInfo.systemImage) {
qCWarning(avdDialogLog) << "System image of the created AVD is nullptr";
return IDevice::Ptr();
}
dev->setExtraData(Constants::AndroidSdk, m_createdAvdInfo.systemImage->apiLevel());
dev->setExtraData(Constants::AndroidAvdSdcard, QString("%1 MB")
.arg(m_createdAvdInfo.sdcardSize));
dev->setExtraData(Constants::AndroidAvdDevice, m_createdAvdInfo.deviceDefinition);
result.systemImage = d.systemImage();
result.name = d.name();
result.abi = d.abi();
result.deviceDefinition = d.deviceDefinition();
result.sdcardSize = d.sdcardSize();
result.overwrite = d.m_avdDialog.overwriteCheckBox->isChecked();
return result;
return IDevice::Ptr(dev);
}
AvdDialog::DeviceType AvdDialog::tagToDeviceType(const QString &type_tag)
@@ -175,7 +208,7 @@ void AvdDialog::parseDeviceDefinitionsList()
void AvdDialog::updateDeviceDefinitionComboBox()
{
DeviceType curDeviceType = DeviceTypeToStringMap.key(
DeviceType curDeviceType = deviceTypeToStringMap.key(
m_avdDialog.deviceDefinitionTypeComboBox->currentText());
m_avdDialog.deviceDefinitionComboBox->clear();
@@ -215,8 +248,8 @@ int AvdDialog::sdcardSize() const
void AvdDialog::updateApiLevelComboBox()
{
SystemImageList installedSystemImages = m_sdkManager->installedSystemImages();
DeviceType curDeviceType = DeviceTypeToStringMap.key(
SystemImageList installedSystemImages = m_sdkManager.installedSystemImages();
DeviceType curDeviceType = deviceTypeToStringMap.key(
m_avdDialog.deviceDefinitionTypeComboBox->currentText());
QString selectedAbi = abi();
@@ -250,8 +283,7 @@ void AvdDialog::updateApiLevelComboBox()
m_avdDialog.warningText->setVisible(true);
m_avdDialog.warningText->setText(
tr("Cannot create a new AVD. No suitable Android system image is installed.<br/>"
"Install a system image of at least API version %1 from the SDK Manager tab.")
.arg(m_minApiLevel));
"Install a system image for the intended Android version from the SDK Manager."));
m_avdDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else if (filteredList.isEmpty()) {
m_avdDialog.targetApiComboBox->setEnabled(false);

View File

@@ -41,21 +41,27 @@ class AvdDialog : public QDialog
{
Q_OBJECT
public:
explicit AvdDialog(int minApiLevel,
AndroidSdkManager *sdkManager,
const QStringList &abis,
const AndroidConfig &config,
QWidget *parent = nullptr);
explicit AvdDialog(const AndroidConfig &config, QWidget *parent = nullptr);
int exec() override;
enum DeviceType { TV, Phone, Wear, Tablet, Automotive, PhoneOrTablet };
enum DeviceType { Phone, Tablet, Automotive, TV, Wear, PhoneOrTablet };
const QMap<DeviceType, QString> DeviceTypeToStringMap{
{TV, "TV"},
{Phone, "Phone"},
{Wear, "Wear"},
{Tablet, "Tablet"},
{Automotive, "Automotive"}
};
ProjectExplorer::IDevice::Ptr device() const;
const SystemImage *systemImage() const;
QString name() const;
QString abi() const;
QString deviceDefinition() const;
int sdcardSize() const;
bool isValid() const;
private:
void parseDeviceDefinitionsList();
void updateDeviceDefinitionComboBox();
void updateApiLevelComboBox();
bool eventFilter(QObject *obj, QEvent *event) override;
static AvdDialog::DeviceType tagToDeviceType(const QString &type_tag);
struct DeviceDefinitionStruct
{
@@ -64,30 +70,14 @@ public:
DeviceType deviceType;
};
const SystemImage *systemImage() const;
QString name() const;
QString abi() const;
QString deviceDefinition() const;
int sdcardSize() const;
bool isValid() const;
static AvdDialog::DeviceType tagToDeviceType(const QString &type_tag);
static CreateAvdInfo gatherCreateAVDInfo(QWidget *parent, AndroidSdkManager *sdkManager,
const AndroidConfig &config,
int minApiLevel = 0, const QStringList &abis = {});
private:
void parseDeviceDefinitionsList();
void updateDeviceDefinitionComboBox();
void updateApiLevelComboBox();
bool eventFilter(QObject *obj, QEvent *event) override;
Ui::AddNewAVDDialog m_avdDialog;
AndroidSdkManager *m_sdkManager;
int m_minApiLevel;
AndroidSdkManager m_sdkManager;
CreateAvdInfo m_createdAvdInfo;
QTimer m_hideTipTimer;
QRegularExpression m_allowedNameChars;
QList<DeviceDefinitionStruct> m_deviceDefinitionsList;
AndroidConfig m_androidConfig;
QMap<AvdDialog::DeviceType, QString> deviceTypeToStringMap;
};
}
}

View File

@@ -568,7 +568,7 @@ void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath
bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
{
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions)
foreach (const QString &preprocessorCompletion, preprocessorCompletions())
addCompletionItem(preprocessorCompletion,
Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro));

File diff suppressed because it is too large Load Diff

View File

@@ -77,6 +77,7 @@ public:
const LanguageServerProtocol::DocumentUri &uri);
void enableTesting();
bool testingEnabled() const;
signals:
void indexingFinished();
@@ -90,12 +91,15 @@ signals:
private:
void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params) override;
void handleDocumentOpened(TextEditor::TextDocument *doc) override;
void handleDocumentClosed(TextEditor::TextDocument *doc) override;
class Private;
class FollowSymbolData;
class VirtualFunctionAssistProcessor;
class VirtualFunctionAssistProvider;
class ClangdFunctionHintProcessor;
class ClangdCompletionAssistProcessor;
class ClangdCompletionAssistProvider;
Private * const d;
};

View File

@@ -77,6 +77,7 @@ using Range = std::tuple<int, int, int>;
} // namespace ClangCodeModel
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Tests::Range)
Q_DECLARE_METATYPE(IAssistProposal *)
namespace ClangCodeModel {
namespace Internal {
@@ -392,7 +393,7 @@ void ClangdTestFollowSymbol::test()
timer.stop();
QCOMPARE(actualLink.targetFilePath, filePath(targetFile));
QEXPECT_FAIL("union member ref", "FIXME: clangd points to union", Abort);
QEXPECT_FAIL("union member ref", "https://github.com/clangd/clangd/issues/877", Abort);
QCOMPARE(actualLink.targetLine, targetLine);
QCOMPARE(actualLink.targetColumn + 1, targetColumn);
}
@@ -1274,7 +1275,7 @@ void ClangdTestHighlighting::test()
const TextEditor::HighlightingResults results = findResults();
QEXPECT_FAIL("typedef as underlying type in enum declaration",
"FIXME: clangd does not report this symbol",
"https://github.com/clangd/clangd/issues/878",
Abort);
QEXPECT_FAIL("Q_PROPERTY (property name)", "FIXME: How to do this?", Abort);
QEXPECT_FAIL("Q_PROPERTY (getter)", "FIXME: How to do this?", Abort);
@@ -1461,20 +1462,19 @@ void ClangdTestCompletion::testCompletePreprocessorKeywords()
ProposalModelPtr proposal;
getProposal("preprocessorKeywordsCompletion.cpp", proposal);
QVERIFY(proposal);
QVERIFY(hasItem(proposal, " ifdef macro"));
QVERIFY(hasItem(proposal, "ifdef"));
QVERIFY(!hasSnippet(proposal, "class "));
proposal.clear();
getProposal("preprocessorKeywordsCompletion2.cpp", proposal);
QVERIFY(proposal);
QVERIFY(hasItem(proposal, " endif"));
QVERIFY(hasItem(proposal, "endif"));
QVERIFY(!hasSnippet(proposal, "class "));
proposal.clear();
getProposal("preprocessorKeywordsCompletion3.cpp", proposal);
QVERIFY(proposal);
QEXPECT_FAIL("", "TODO: Fix in clangd", Continue);
QVERIFY(hasItem(proposal, " endif"));
QVERIFY(hasItem(proposal, "endif"));
QVERIFY(!hasSnippet(proposal, "class "));
}
@@ -1885,7 +1885,7 @@ void ClangdTestCompletion::getProposal(const QString &fileName,
connect(client(), &ClangdClient::proposalReady, &loop, [&proposal, &loop](IAssistProposal *p) {
proposal = p;
loop.quit();
});
}, Qt::QueuedConnection);
editor->editorWidget()->invokeAssist(Completion, nullptr);
timer.start(5000);
loop.exec();

View File

@@ -34,6 +34,7 @@
#include <extensionsystem/pluginmanager.h>
#include <utils/fileutils.h>
#include <utils/icon.h>
#include <utils/qtcassert.h>
#include <utils/wizard.h>
@@ -369,6 +370,11 @@ void IWizardFactory::requestNewItemDialog(const QString &title,
s_reopenData.setData(title, factories, defaultLocation, extraVariables);
}
QIcon IWizardFactory::themedIcon(const Utils::FilePath &iconMaskPath)
{
return Utils::Icon({{iconMaskPath, Theme::PanelTextColorDark}}, Icon::Tint).icon();
}
void IWizardFactory::destroyFeatureProvider()
{
qDeleteAll(s_providerList);
@@ -427,7 +433,8 @@ void IWizardFactory::initialize()
static QIcon iconWithText(const QIcon &icon, const QString &text)
{
if (icon.isNull()) {
static const QIcon fallBack(":/utils/images/wizardicon-file.png");
static const QIcon fallBack =
IWizardFactory::themedIcon(":/utils/images/wizardicon-file.png");
return iconWithText(fallBack, text);
}
@@ -445,6 +452,7 @@ static QIcon iconWithText(const QIcon &icon, const QString &text)
font.setPixelSize(fontSize);
font.setStretch(85);
QPainter p(&pixmap);
p.setPen(Utils::creatorTheme()->color(Theme::PanelTextColorDark));
p.setFont(font);
QTextOption textOption(Qt::AlignHCenter | Qt::AlignBottom);
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

View File

@@ -115,6 +115,8 @@ public:
const Utils::FilePath &defaultLocation,
const QVariantMap &extraVariables);
static QIcon themedIcon(const Utils::FilePath &iconMaskPath);
protected:
static QSet<Utils::Id> pluginFeatures();
static QSet<Utils::Id> availableFeatures(Utils::Id platformId);

View File

@@ -37,6 +37,7 @@
#include <utils/qtcassert.h>
#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QDockWidget>
#include <QFormLayout>
@@ -288,7 +289,8 @@ void ManhattanStyle::polish(QWidget *widget)
if (qobject_cast<QToolButton*>(widget) || qobject_cast<QLineEdit*>(widget)) {
widget->setAttribute(Qt::WA_Hover);
widget->setMaximumHeight(height - 2);
} else if (qobject_cast<QLabel*>(widget)) {
} else if (qobject_cast<QLabel*>(widget) || qobject_cast<QSpinBox*>(widget)
|| qobject_cast<QCheckBox*>(widget)) {
widget->setPalette(panelPalette(widget->palette(), lightColored(widget)));
} else if (widget->property("panelwidget_singlerow").toBool()) {
widget->setFixedHeight(height);
@@ -303,10 +305,6 @@ void ManhattanStyle::polish(QWidget *widget)
widget->setPalette(palette);
widget->setMaximumHeight(height - 2);
widget->setAttribute(Qt::WA_Hover);
} else if (qobject_cast<QSpinBox*>(widget)) {
const bool isLightColored = lightColored(widget);
QPalette palette = panelPalette(widget->palette(), isLightColored);
widget->setPalette(palette);
}
}
}

View File

@@ -1302,7 +1302,7 @@ void InternalCppCompletionAssistProcessor::completeInclude(const QString &realPa
void InternalCppCompletionAssistProcessor::completePreprocessor()
{
foreach (const QString &preprocessorCompletion, m_preprocessorCompletions)
foreach (const QString &preprocessorCompletion, preprocessorCompletions())
addCompletionItem(preprocessorCompletion);
if (objcKeywordsWanted())

View File

@@ -41,20 +41,24 @@ using namespace CPlusPlus;
namespace CppEditor {
CppCompletionAssistProcessor::CppCompletionAssistProcessor(int snippetItemOrder)
: m_preprocessorCompletions(
QStringList({"define", "error", "include", "line", "pragma", "pragma once",
"pragma omp atomic", "pragma omp parallel", "pragma omp for",
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
"pragma omp master", "pragma omp critical", "pragma omp barrier",
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
"ifndef", "elif", "else", "endif"}))
, m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
: m_snippetCollector(QLatin1String(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID),
QIcon(QLatin1String(":/texteditor/images/snippet.png")),
snippetItemOrder)
{
}
const QStringList CppCompletionAssistProcessor::preprocessorCompletions()
{
static QStringList list{"define", "error", "include", "line", "pragma", "pragma once",
"pragma omp atomic", "pragma omp parallel", "pragma omp for",
"pragma omp ordered", "pragma omp parallel for", "pragma omp section",
"pragma omp sections", "pragma omp parallel sections", "pragma omp single",
"pragma omp master", "pragma omp critical", "pragma omp barrier",
"pragma omp flush", "pragma omp threadprivate", "undef", "if", "ifdef",
"ifndef", "elif", "else", "endif"};
return list;
}
void CppCompletionAssistProcessor::addSnippets()
{
m_completions.append(m_snippetCollector.collect());

View File

@@ -45,6 +45,8 @@ class CPPEDITOR_EXPORT CppCompletionAssistProcessor : public TextEditor::IAssist
public:
explicit CppCompletionAssistProcessor(int snippetItemOrder = 0);
static const QStringList preprocessorCompletions();
protected:
void addSnippets();
@@ -60,7 +62,6 @@ protected:
int m_positionForProposal = -1;
QList<TextEditor::AssistProposalItemInterface *> m_completions;
QStringList m_preprocessorCompletions;
TextEditor::IAssistProposal *m_hintProposal = nullptr;
private:

View File

@@ -55,7 +55,7 @@ class SourcePathMappingModel;
enum { SourceColumn, TargetColumn, ColumnCount };
using Mapping = QPair<QString, QString>;
using Mapping = QPair<FilePath, FilePath>;
class DebuggerSourcePathMappingWidget : public QGroupBox
{
@@ -79,7 +79,7 @@ private:
void updateEnabled();
QString editSourceField() const;
QString editTargetField() const;
void setEditFieldMapping(const QPair<QString, QString> &m);
void setEditFieldMapping(const Mapping &m);
int currentRow() const;
void setCurrentRow(int r);
@@ -162,9 +162,9 @@ SourcePathMap SourcePathMappingModel::sourcePathMap() const
SourcePathMap rc;
const int rows = rowCount();
for (int r = 0; r < rows; ++r) {
const QPair<QString, QString> m = mappingAt(r); // Skip placeholders.
const Mapping m = mappingAt(r); // Skip placeholders.
if (!m.first.isEmpty() && !m.second.isEmpty())
rc.insert(m.first, m.second);
rc.insert(m.first.toString(), m.second.toString());
}
return rc;
}
@@ -176,17 +176,17 @@ bool SourcePathMappingModel::isNewPlaceHolder(const Mapping &m) const
const QChar greaterThan('>');
return m.first.isEmpty() || m.first.startsWith(lessThan)
|| m.first.endsWith(greaterThan)
|| m.first == m_newSourcePlaceHolder
|| m.first.toString() == m_newSourcePlaceHolder
|| m.second.isEmpty() || m.second.startsWith(lessThan)
|| m.second.endsWith(greaterThan)
|| m.second == m_newTargetPlaceHolder;
|| m.second.toString() == m_newTargetPlaceHolder;
}
// Return raw, unfixed mapping
Mapping SourcePathMappingModel::rawMappingAt(int row) const
{
return Mapping(QDir::fromNativeSeparators(item(row, SourceColumn)->text()),
QDir::fromNativeSeparators(item(row, TargetColumn)->text()));
return Mapping(FilePath::fromUserInput(item(row, SourceColumn)->text()),
FilePath::fromUserInput(item(row, TargetColumn)->text()));
}
// Return mapping, empty if it is the place holder.
@@ -337,15 +337,14 @@ QString DebuggerSourcePathMappingWidget::editTargetField() const
void DebuggerSourcePathMappingWidget::setEditFieldMapping(const Mapping &m)
{
m_sourceLineEdit->setText(m.first);
m_targetChooser->setPath(m.second);
m_sourceLineEdit->setText(m.first.toUserOutput());
m_targetChooser->setFilePath(m.second);
}
void DebuggerSourcePathMappingWidget::slotCurrentRowChanged
(const QModelIndex &current, const QModelIndex &)
{
setEditFieldMapping(current.isValid()
? m_model->mappingAt(current.row()) : Mapping());
setEditFieldMapping(current.isValid() ? m_model->mappingAt(current.row()) : Mapping());
updateEnabled();
}

View File

@@ -145,6 +145,8 @@ RemoteDialog::RemoteDialog(QWidget *parent) :
connect(m_ui->remoteView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &RemoteDialog::updateButtonState);
connect(m_remoteModel, &RemoteModel::refreshed,
this, &RemoteDialog::updateButtonState);
updateButtonState();
}

View File

@@ -199,6 +199,7 @@ bool RemoteModel::refresh(const FilePath &workingDirectory, QString *errorMessag
m_remotes.push_back(newRemote);
}
endResetModel();
emit refreshed();
return true;
}

View File

@@ -65,6 +65,9 @@ public:
Utils::FilePath workingDirectory() const;
int findRemoteByName(const QString &name) const;
signals:
void refreshed();
protected:
class Remote {
public:

View File

@@ -394,6 +394,7 @@ void Client::openDocument(TextEditor::TextDocument *document)
m_documentVersions[filePath] = 0;
item.setVersion(m_documentVersions[filePath]);
sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)));
handleDocumentOpened(document);
const Client *currentClient = LanguageClientManager::clientForDocument(document);
if (currentClient == this) {
@@ -1047,22 +1048,6 @@ SymbolStringifier Client::symbolStringifier() const
return m_symbolStringifier;
}
void Client::setCompletionProposalHandler(const ProposalHandler &handler)
{
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(
m_clientProviders.completionAssistProvider)) {
provider->setProposalHandler(handler);
}
}
void Client::setFunctionHintProposalHandler(const ProposalHandler &handler)
{
if (const auto provider = qobject_cast<FunctionHintAssistProvider *>(
m_clientProviders.functionHintProvider)) {
provider->setProposalHandler(handler);
}
}
void Client::setSnippetsGroup(const QString &group)
{
if (const auto provider = qobject_cast<LanguageClientCompletionAssistProvider *>(

View File

@@ -185,8 +185,6 @@ public:
void setSemanticTokensHandler(const SemanticTokensHandler &handler);
void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier);
LanguageServerProtocol::SymbolStringifier symbolStringifier() const;
void setCompletionProposalHandler(const ProposalHandler &handler);
void setFunctionHintProposalHandler(const ProposalHandler &handler);
void setSnippetsGroup(const QString &group);
void setCompletionAssistProvider(LanguageClientCompletionAssistProvider *provider);
@@ -240,6 +238,7 @@ private:
void rehighlight();
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}
using ContentHandler = std::function<void(const QByteArray &, QTextCodec *, QString &,
LanguageServerProtocol::ResponseHandlers,

Some files were not shown because too many files have changed in this diff Show More