aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThe Qt Project <[email protected]>2024-11-20 09:05:36 +0000
committerThe Qt Project <[email protected]>2024-11-20 09:05:36 +0000
commitceeeba5667948920fe62c06579ea9c670c55f1fe (patch)
tree79416c5841a49770a046965c0be02e03ae80cb06 /src
parent2af6e0e9843b1673c390f234c04590733b94da20 (diff)
parentf4e75e1acbd1b44fc066fccc5e3f78409fa309f0 (diff)
Merge "Merge remote-tracking branch 'origin/15.0'"
Diffstat (limited to 'src')
-rw-r--r--src/app/main.cpp7
-rw-r--r--src/libs/3rdparty/libptyqt/conptyprocess.cpp67
-rw-r--r--src/libs/utils/fileutils.cpp2
-rw-r--r--src/libs/utils/icondisplay.cpp6
-rw-r--r--src/libs/utils/mimetypes2/mimedatabase.cpp21
-rw-r--r--src/libs/utils/qtcprocess.cpp11
-rw-r--r--src/libs/utils/stringutils.cpp206
-rw-r--r--src/plugins/axivion/axivionplugin.cpp11
-rw-r--r--src/plugins/coreplugin/icore.cpp10
-rw-r--r--src/plugins/coreplugin/iversioncontrol.h1
-rw-r--r--src/plugins/coreplugin/outputwindow.cpp29
-rw-r--r--src/plugins/coreplugin/outputwindow.h6
-rw-r--r--src/plugins/coreplugin/secretaspect.cpp8
-rw-r--r--src/plugins/cppeditor/cppfollowsymbolundercursor.cpp7
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp2
-rw-r--r--src/plugins/cppeditor/insertionpointlocator.cpp7
-rw-r--r--src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp2
-rw-r--r--src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp17
-rw-r--r--src/plugins/cppeditor/symbolfinder.h4
-rw-r--r--src/plugins/extensionmanager/extensionmanagerwidget.cpp37
-rw-r--r--src/plugins/git/gitclient.cpp42
-rw-r--r--src/plugins/git/gitclient.h1
-rw-r--r--src/plugins/git/gitplugin.cpp5
-rw-r--r--src/plugins/git/gitplugin.h1
-rw-r--r--src/plugins/lua/bindings/texteditor.cpp6
-rw-r--r--src/plugins/projectexplorer/kitmanagerconfigwidget.cpp5
-rw-r--r--src/plugins/projectexplorer/kitmanagerconfigwidget.h1
-rw-r--r--src/plugins/projectexplorer/kitoptionspage.cpp2
-rw-r--r--src/plugins/projectexplorer/projectmodels.cpp15
-rw-r--r--src/plugins/projectexplorer/projectmodels.h1
-rw-r--r--src/plugins/projectexplorer/toolchainoptionspage.cpp2
-rw-r--r--src/plugins/python/pythoneditor.cpp3
-rw-r--r--src/plugins/python/pythonlanguageclient.cpp4
-rw-r--r--src/plugins/qmlprofiler/quick3dframeview.cpp6
-rw-r--r--src/plugins/remotelinux/filesystemaccess_test.cpp21
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.cpp11
-rw-r--r--src/plugins/vcsbase/commonvcssettings.cpp7
-rw-r--r--src/plugins/vcsbase/commonvcssettings.h7
m---------src/shared/qbs0
39 files changed, 422 insertions, 179 deletions
diff --git a/src/app/main.cpp b/src/app/main.cpp
index f090c3e2d35..9617037e3e6 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -933,8 +933,13 @@ int main(int argc, char **argv)
// shutdown plugin manager on the exit
QObject::connect(&app, &QCoreApplication::aboutToQuit, &pluginManager, &PluginManager::shutdown);
- if (Utils::HostOsInfo::isWindowsHost()) // Workaround for QTBUG-130696 and QTCREATORBUG-31890
+ if (Utils::HostOsInfo::isWindowsHost()) {
+ // Workaround for QTBUG-130696 and QTCREATORBUG-31890
QApplication::setEffectEnabled(Qt::UI_FadeMenu, false);
+ // Disable menu animation which just looks bad
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
+ }
+
return restarter.restartOrExit(app.exec());
}
diff --git a/src/libs/3rdparty/libptyqt/conptyprocess.cpp b/src/libs/3rdparty/libptyqt/conptyprocess.cpp
index c957e0bdd9e..d8f0608ef16 100644
--- a/src/libs/3rdparty/libptyqt/conptyprocess.cpp
+++ b/src/libs/3rdparty/libptyqt/conptyprocess.cpp
@@ -988,8 +988,11 @@ bool ConPtyProcess::startProcess(const QString &executable,
GetExitCodeProcess(hEvent, &exitCode);
m_exitCode = exitCode;
// Do not respawn if the object is about to be destructed
- if (!m_aboutToDestruct)
- emit notifier()->aboutToClose();
+ if (!m_aboutToDestruct) {
+ ConptyClosePseudoConsole(m_ptyHandler);
+ m_ptyHandler = INVALID_HANDLE_VALUE;
+ emit notifier() -> aboutToClose();
+ }
m_shellCloseWaitNotifier->setEnabled(false);
}, Qt::QueuedConnection);
@@ -1028,7 +1031,7 @@ bool ConPtyProcess::startProcess(const QString &executable,
bool ConPtyProcess::resize(qint16 cols, qint16 rows)
{
- if (m_ptyHandler == nullptr)
+ if (m_ptyHandler == INVALID_HANDLE_VALUE)
{
return false;
}
@@ -1047,49 +1050,45 @@ bool ConPtyProcess::resize(qint16 cols, qint16 rows)
bool ConPtyProcess::kill()
{
- bool exitCode = false;
-
if (m_ptyHandler != INVALID_HANDLE_VALUE) {
m_aboutToDestruct = true;
// Close ConPTY - this will terminate client process if running
WindowsContext::instance().closePseudoConsole(m_ptyHandler);
+ }
- // Clean-up the pipes
- if (INVALID_HANDLE_VALUE != m_hPipeOut)
- CloseHandle(m_hPipeOut);
- if (INVALID_HANDLE_VALUE != m_hPipeIn)
- CloseHandle(m_hPipeIn);
-
- if (m_readThread) {
- m_readThread->requestInterruption();
- if (!m_readThread->wait(1000))
- m_readThread->terminate();
- m_readThread->deleteLater();
- m_readThread = nullptr;
- }
-
- delete m_shellCloseWaitNotifier;
- m_shellCloseWaitNotifier = nullptr;
+ // Clean-up the pipes
+ if (INVALID_HANDLE_VALUE != m_hPipeOut)
+ CloseHandle(m_hPipeOut);
+ if (INVALID_HANDLE_VALUE != m_hPipeIn)
+ CloseHandle(m_hPipeIn);
+
+ if (m_readThread) {
+ m_readThread->requestInterruption();
+ if (!m_readThread->wait(1000))
+ m_readThread->terminate();
+ m_readThread->deleteLater();
+ m_readThread = nullptr;
+ }
- m_pid = 0;
- m_ptyHandler = INVALID_HANDLE_VALUE;
- m_hPipeIn = INVALID_HANDLE_VALUE;
- m_hPipeOut = INVALID_HANDLE_VALUE;
+ delete m_shellCloseWaitNotifier;
+ m_shellCloseWaitNotifier = nullptr;
- CloseHandle(m_shellProcessInformation.hThread);
- CloseHandle(m_shellProcessInformation.hProcess);
+ m_pid = 0;
+ m_ptyHandler = INVALID_HANDLE_VALUE;
+ m_hPipeIn = INVALID_HANDLE_VALUE;
+ m_hPipeOut = INVALID_HANDLE_VALUE;
- // Cleanup attribute list
- if (m_shellStartupInfo.lpAttributeList) {
- DeleteProcThreadAttributeList(m_shellStartupInfo.lpAttributeList);
- HeapFree(GetProcessHeap(), 0, m_shellStartupInfo.lpAttributeList);
- }
+ CloseHandle(m_shellProcessInformation.hThread);
+ CloseHandle(m_shellProcessInformation.hProcess);
- exitCode = true;
+ // Cleanup attribute list
+ if (m_shellStartupInfo.lpAttributeList) {
+ DeleteProcThreadAttributeList(m_shellStartupInfo.lpAttributeList);
+ HeapFree(GetProcessHeap(), 0, m_shellStartupInfo.lpAttributeList);
}
- return exitCode;
+ return true;
}
IPtyProcess::PtyType ConPtyProcess::type()
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index ef87925be0e..c47c648c88a 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -731,7 +731,7 @@ Result FileUtils::copyIfDifferent(const FilePath &srcFilePath, const FilePath &t
if (srcModified == tgtModified) {
// TODO: Create FilePath::hashFromContents() and compare hashes.
const expected_str<QByteArray> srcContents = srcFilePath.fileContents();
- const expected_str<QByteArray> tgtContents = srcFilePath.fileContents();
+ const expected_str<QByteArray> tgtContents = tgtFilePath.fileContents();
if (srcContents && srcContents == tgtContents)
return Result::Ok;
}
diff --git a/src/libs/utils/icondisplay.cpp b/src/libs/utils/icondisplay.cpp
index 1c9f9f6520f..93999708905 100644
--- a/src/libs/utils/icondisplay.cpp
+++ b/src/libs/utils/icondisplay.cpp
@@ -15,7 +15,6 @@ namespace Utils
class IconDisplayPrivate
{
public:
- QSize m_iconSize;
QIcon m_icon;
};
@@ -52,7 +51,10 @@ QSize IconDisplay::sizeHint() const
if (d->m_icon.isNull())
return {};
- return d->m_icon.availableSizes().first();
+ if (auto sizes = d->m_icon.availableSizes(); !sizes.isEmpty())
+ return sizes.first();
+
+ return {};
}
void IconDisplay::setIcon(const Icon &icon)
diff --git a/src/libs/utils/mimetypes2/mimedatabase.cpp b/src/libs/utils/mimetypes2/mimedatabase.cpp
index 68d513b5ff9..ff6346dae3d 100644
--- a/src/libs/utils/mimetypes2/mimedatabase.cpp
+++ b/src/libs/utils/mimetypes2/mimedatabase.cpp
@@ -126,6 +126,27 @@ void MimeDatabasePrivate::loadProviders()
if (!m_additionalData.contains("utilslib.mimetypes")) {
m_additionalData.insert("utilslib.mimetypes", QByteArray(R"--(<?xml version="1.0"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <mime-type type="text/plain">
+ <magic priority="20">
+ <match value="This is TeX," type="string" offset="0"/>
+ <match value="This is METAFONT," type="string" offset="0"/>
+ <match value="/*" type="string" offset="0"/>
+ <match value="//" type="string" offset="0"/>
+ <match value=";;" type="string" offset="0"/>
+ <!-- UTF-16BE BOM -->
+ <match value="\xfe\xff" type="string" offset="0"/>
+ <!-- UTF-16LE BOM -->
+ <match value="\xff\xfe" type="string" offset="0"/>
+ <!-- UTF-8 BOM -->
+ <match value="\xef\xbb\xbf" type="string" offset="0"/>
+ </magic>
+
+ <glob pattern="*.txt"/>
+ <glob pattern="*.text"/>
+ <glob pattern="*.def"/>
+ <glob pattern="*.list"/>
+ <glob pattern="*.in"/>
+ </mime-type>
<mime-type type="application/x-compressed-tar">
<comment>Tar archive (gzip-compressed)</comment>
<sub-class-of type="application/gzip"/>
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
index af4833c3ff2..4bcaad92a15 100644
--- a/src/libs/utils/qtcprocess.cpp
+++ b/src/libs/utils/qtcprocess.cpp
@@ -403,13 +403,22 @@ public:
static_cast<Pty::PtyInputFlag>(m_inputFlags.toInt()));
}
- emit readyRead(m_ptyProcess->readAll(), {});
+ const QByteArray data = m_ptyProcess->readAll();
+ if (!data.isEmpty())
+ emit readyRead(data, {});
});
connect(m_ptyProcess->notifier(), &QIODevice::aboutToClose, this, [this] {
if (m_ptyProcess) {
const ProcessResultData result
= {m_ptyProcess->exitCode(), QProcess::NormalExit, QProcess::UnknownError, {}};
+
+ const QByteArray restOfOutput = m_ptyProcess->readAll();
+ if (!restOfOutput.isEmpty()) {
+ emit readyRead(restOfOutput, {});
+ m_ptyProcess->notifier()->disconnect();
+ }
+
emit done(result);
return;
}
diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp
index 2aa2f760427..dae35b817ba 100644
--- a/src/libs/utils/stringutils.cpp
+++ b/src/libs/utils/stringutils.cpp
@@ -106,100 +106,132 @@ QTCREATOR_UTILS_EXPORT bool readMultiLineString(const QJsonValue &value, QString
return true;
}
+enum class Base { Dec, Hex };
+
+static bool isHex(const QChar &c)
+{
+ return (c >= 'a' && c <= 'f') || (c >= 'A' && c < 'F');
+}
+
+static bool isDigit(const QChar &c, Base base)
+{
+ if (base == Base::Hex && isHex(c))
+ return true;
+ return c.isDigit();
+}
+
+static int trailingNumber(const QString &line, Base base = Base::Dec)
+{
+ int lastNumberPos = line.size();
+ while (lastNumberPos > 0) {
+ if (!isDigit(line.at(lastNumberPos - 1), base))
+ break;
+ --lastNumberPos;
+ }
+ bool ok = true;
+ const int port = line.mid(lastNumberPos).toInt(&ok, base == Base::Dec ? 10 : 16);
+ return ok ? port : -1;
+}
+
+/*
+
+Parsing algo is simple:
+Depending on the value of 1st column we detect whether it's Win, Mac / Android / Qnx, or Linux
+output.
+
+In case of Win or Linux, we select the 2nd column for port parsing, otherwise we select
+the 4th column.
+
+For selected column we parse the trailing digits. In case of Linux we take into account hex digits.
+
+Expected output (see tst_StringUtils::testParseUsedPortFromNetstatOutput_data()):
+
+ === Windows ===
+
+ Active Connections
+
+ Proto Local Address Foreign Address State
+ TCP 0.0.0.0:80 0.0.0.0:0 LISTENING
+ TCP 0.0.0.0:113 0.0.0.0:0 LISTENING
+ [...]
+ TCP 10.9.78.4:14714 0.0.0.0:0 LISTENING
+ TCP 10.9.78.4:50233 12.13.135.180:993 ESTABLISHED
+ [...]
+ TCP [::]:445 [::]:0 LISTENING
+ TCP 192.168.0.80:51905 169.55.74.50:443 ESTABLISHED
+ UDP [fe80::880a:2932:8dff:a858%6]:1900 *:*
+
+ === Mac ===
+
+ Active Internet connections (including servers)
+ Proto Recv-Q Send-Q Local Address Foreign Address (state)
+ tcp4 0 0 192.168.1.12.55687 88.198.14.66.443 ESTABLISHED
+ tcp6 0 0 2a01:e34:ee42:d0.55684 2a02:26f0:ff::5c.443 ESTABLISHED
+ [...]
+ tcp4 0 0 *.631 *.* LISTEN
+ tcp6 0 0 *.631 *.* LISTEN
+ [...]
+ udp4 0 0 192.168.79.1.123 *.*
+ udp4 0 0 192.168.8.1.123 *.*
+
+ === QNX ===
+
+ Active Internet connections (including servers)
+ Proto Recv-Q Send-Q Local Address Foreign Address State
+ tcp 0 0 10.9.7.5.22 10.9.7.4.46592 ESTABLISHED
+ tcp 0 0 *.8000 *.* LISTEN
+ tcp 0 0 *.22 *.* LISTEN
+ udp 0 0 *.* *.*
+ udp 0 0 *.* *.*
+ Active Internet6 connections (including servers)
+ Proto Recv-Q Send-Q Local Address Foreign Address (state)
+ tcp6 0 0 *.22 *.* LISTEN
+
+ === Android ===
+
+ tcp 0 0 10.0.2.16:49088 142.250.180.74:443 ESTABLISHED
+ tcp 0 0 10.0.2.16:48380 142.250.186.196:443 CLOSE_WAIT
+ tcp6 0 0 [::]:5555 [::]:* LISTEN
+ tcp6 0 0 ::ffff:127.0.0.1:39417 [::]:* LISTEN
+ tcp6 0 0 ::ffff:10.0.2.16:35046 ::ffff:142.250.203.:443 ESTABLISHED
+ tcp6 0 0 ::ffff:127.0.0.1:46265 ::ffff:127.0.0.1:33155 TIME_WAIT
+ udp 0 0 10.0.2.16:50950 142.250.75.14:443 ESTABLISHED
+ udp 2560 0 10.0.2.16:68 10.0.2.2:67 ESTABLISHED
+ udp 0 0 0.0.0.0:5353 0.0.0.0:*
+ udp6 0 0 [::]:36662 [::]:*
+
+ === Linux ===
+
+ sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt ...
+ 0: 00000000:2805 00000000:0000 0A 00000000:00000000 00:00000000 00000000 ...
+*/
QTCREATOR_UTILS_EXPORT int parseUsedPortFromNetstatOutput(const QByteArray &line)
{
- const QByteArray trimmed = line.trimmed();
- int base = 0;
- QByteArray portString;
-
- if (trimmed.startsWith("TCP") || trimmed.startsWith("UDP")) {
- // Windows. Expected output is something like
- //
- // Active Connections
- //
- // Proto Local Address Foreign Address State
- // TCP 0.0.0.0:80 0.0.0.0:0 LISTENING
- // TCP 0.0.0.0:113 0.0.0.0:0 LISTENING
- // [...]
- // TCP 10.9.78.4:14714 0.0.0.0:0 LISTENING
- // TCP 10.9.78.4:50233 12.13.135.180:993 ESTABLISHED
- // [...]
- // TCP [::]:445 [::]:0 LISTENING
- // TCP 192.168.0.80:51905 169.55.74.50:443 ESTABLISHED
- // UDP [fe80::880a:2932:8dff:a858%6]:1900 *:*
- const int firstBracketPos = trimmed.indexOf('[');
- int colonPos = -1;
- if (firstBracketPos == -1) {
- colonPos = trimmed.indexOf(':'); // IPv4
- } else {
- // jump over host part
- const int secondBracketPos = trimmed.indexOf(']', firstBracketPos + 1);
- colonPos = trimmed.indexOf(':', secondBracketPos);
- }
- const int firstDigitPos = colonPos + 1;
- const int spacePos = trimmed.indexOf(' ', firstDigitPos);
- if (spacePos < 0)
- return -1;
- const int len = spacePos - firstDigitPos;
- base = 10;
- portString = trimmed.mid(firstDigitPos, len);
- } else if (trimmed.startsWith("tcp") || trimmed.startsWith("udp")) {
- // macOS. Expected output is something like
- //
- // Active Internet connections (including servers)
- // Proto Recv-Q Send-Q Local Address Foreign Address (state)
- // tcp4 0 0 192.168.1.12.55687 88.198.14.66.443 ESTABLISHED
- // tcp6 0 0 2a01:e34:ee42:d0.55684 2a02:26f0:ff::5c.443 ESTABLISHED
- // [...]
- // tcp4 0 0 *.631 *.* LISTEN
- // tcp6 0 0 *.631 *.* LISTEN
- // [...]
- // udp4 0 0 192.168.79.1.123 *.*
- // udp4 0 0 192.168.8.1.123 *.*
- int firstDigitPos = -1;
- int spacePos = -1;
- if (trimmed[3] == '6') {
- // IPV6
- firstDigitPos = trimmed.indexOf('.') + 1;
- spacePos = trimmed.indexOf(' ', firstDigitPos);
- } else {
- // IPV4
- firstDigitPos = trimmed.indexOf('.') + 1;
- spacePos = trimmed.indexOf(' ', firstDigitPos);
- firstDigitPos = trimmed.lastIndexOf('.', spacePos) + 1;
- }
- if (spacePos < 0)
- return -1;
- base = 10;
- portString = trimmed.mid(firstDigitPos, spacePos - firstDigitPos);
- if (portString == "*")
+ const QStringList columns = QString::fromUtf8(line).split(' ', Qt::SkipEmptyParts);
+ if (columns.size() < 3)
+ return -1;
+
+ const QString firstColumn = columns.first();
+ QString columnToParse;
+ Base base = Base::Dec;
+
+ if (firstColumn.startsWith("TCP") || firstColumn.startsWith("UDP")) { // Windows
+ columnToParse = columns.at(1);
+ } else if (firstColumn.startsWith("tcp") || firstColumn.startsWith("udp")) { // Mac, Android, Qnx
+ if (columns.size() < 4)
return -1;
+ columnToParse = columns.at(3);
+ } else if (firstColumn.size() > 1 && firstColumn.at(1) == ':') { // Linux
+ columnToParse = columns.at(1);
+ base = Base::Hex;
} else {
- // Expected output on Linux something like
- //
- // sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt ...
- // 0: 00000000:2805 00000000:0000 0A 00000000:00000000 00:00000000 00000000 ...
- //
- const int firstColonPos = trimmed.indexOf(':');
- if (firstColonPos < 0)
- return -1;
- const int secondColonPos = trimmed.indexOf(':', firstColonPos + 1);
- if (secondColonPos < 0)
- return -1;
- const int spacePos = trimmed.indexOf(' ', secondColonPos + 1);
- if (spacePos < 0)
- return -1;
- const int len = spacePos - secondColonPos - 1;
- base = 16;
- portString = trimmed.mid(secondColonPos + 1, len);
+ return -1;
}
- bool ok = true;
- const int port = portString.toInt(&ok, base);
- if (!ok) {
+ const int port = trailingNumber(columnToParse, base);
+ if (port == -1) {
qWarning("%s: Unexpected string '%s' is not a port. Tried to read from '%s'",
- Q_FUNC_INFO, line.data(), portString.data());
- return -1;
+ Q_FUNC_INFO, line.data(), columnToParse.toUtf8().data());
}
return port;
}
diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp
index d8f5044ad36..a683eda32a3 100644
--- a/src/plugins/axivion/axivionplugin.cpp
+++ b/src/plugins/axivion/axivionplugin.cpp
@@ -44,6 +44,7 @@
#include <QNetworkReply>
#include <QUrlQuery>
+#include <cmath>
#include <memory>
constexpr char s_axivionTextMarkId[] = "AxivionTextMark";
@@ -79,8 +80,14 @@ QString anyToSimpleString(const Dto::Any &any)
return any.getString();
if (any.isBool())
return QString("%1").arg(any.getBool());
- if (any.isDouble())
- return QString::number(any.getDouble());
+ if (any.isDouble()) {
+ const double value = any.getDouble();
+ double intPart;
+ const double fragPart = std::modf(value, &intPart);
+ if (fragPart != 0)
+ return QString::number(value);
+ return QString::number(value, 'f', 0);
+ }
if (any.isNull())
return QString(); // or NULL??
if (any.isList()) {
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index e511b2f4a52..617ece82771 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -827,6 +827,16 @@ QMainWindow *ICore::mainWindow()
/*!
Returns a widget pointer suitable to use as parent for QDialogs.
+
+ Especially for modal dialogs it is important to use the current modal
+ dialog as a parent (if there is one) for the new dialog, because
+ otherwise the new dialog can open behind the old one, while also
+ blocking interaction with that. Using dialogParent() ensures this.
+
+ Also use dialogParent() for non-modal dialogs that do not need any
+ specific lifetime management. If you need to control the lifetime of
+ a non-modal dialog (for example because another part of the
+ application depends on it), use a more specific parent instead.
*/
QWidget *ICore::dialogParent()
{
diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index f04883446aa..6d32e8e1d8a 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -243,6 +243,7 @@ signals:
void repositoryChanged(const Utils::FilePath &repository);
void filesChanged(const QStringList &files);
void updateFileStatus(const Utils::FilePath &repository, const QStringList &files);
+ void clearFileStatus(const Utils::FilePath &repository);
void configurationChanged();
private:
diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp
index 565e996c483..e6f9fad6712 100644
--- a/src/plugins/coreplugin/outputwindow.cpp
+++ b/src/plugins/coreplugin/outputwindow.cpp
@@ -23,6 +23,7 @@
#include <QCursor>
#include <QElapsedTimer>
#include <QHash>
+#include <QLoggingCategory>
#include <QMenu>
#include <QMimeData>
#include <QPair>
@@ -47,8 +48,9 @@ const int minChunkSize = 1000;
const auto defaultInterval = 10ms;
const auto maxInterval = 1000ms;
-namespace Core {
+static Q_LOGGING_CATEGORY(chunkLog, "qtc.core.outputChunking", QtWarningMsg)
+namespace Core {
namespace Internal {
class OutputWindowPrivate
@@ -515,11 +517,14 @@ void OutputWindow::handleNextOutputChunk()
}
}
+ qCDebug(chunkLog) << "next queued chunk has" << chunk.first.size() << "bytes";
if (actualChunkSize == chunk.first.size()) {
- handleOutputChunk(chunk.first, chunk.second);
+ qCDebug(chunkLog) << "chunk can be written in one go";
+ handleOutputChunk(chunk.first, chunk.second, ChunkCompleteness::Complete);
d->queuedOutput.removeFirst();
} else {
- handleOutputChunk(chunk.first.left(actualChunkSize), chunk.second);
+ qCDebug(chunkLog) << "chunk needs to be split";
+ handleOutputChunk(chunk.first.left(actualChunkSize), chunk.second, ChunkCompleteness::Split);
chunk.first.remove(0, actualChunkSize);
}
if (!d->queuedOutput.isEmpty())
@@ -530,7 +535,8 @@ void OutputWindow::handleNextOutputChunk()
}
}
-void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format)
+void OutputWindow::handleOutputChunk(
+ const QString &output, OutputFormat format, ChunkCompleteness completeness)
{
QString out = output;
if (out.size() > d->maxCharCount) {
@@ -562,9 +568,18 @@ void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format)
formatterTimer.start();
d->formatter.appendMessage(out, format);
++d->formatterCalls;
+ qCDebug(chunkLog) << "formatter took" << formatterTimer.elapsed() << "ms";
if (formatterTimer.elapsed() > d->queueTimer.interval()) {
d->queueTimer.setInterval(std::min(maxInterval, d->queueTimer.intervalAsDuration() * 2));
d->chunkSize = std::max(minChunkSize, d->chunkSize / 2);
+ qCDebug(chunkLog) << "increasing interval to" << d->queueTimer.interval()
+ << "ms and lowering chunk size to" << d->chunkSize << "bytes";
+ } else if (completeness == ChunkCompleteness::Split
+ && formatterTimer.elapsed() < d->queueTimer.interval() / 2) {
+ d->queueTimer.setInterval(std::max(1ms, d->queueTimer.intervalAsDuration() * 2 / 3));
+ d->chunkSize = d->chunkSize * 1.5;
+ qCDebug(chunkLog) << "lowering interval to" << d->queueTimer.interval()
+ << "ms and increasing chunk size to" << d->chunkSize << "bytes";
}
if (d->scrollToBottom) {
@@ -594,6 +609,8 @@ void OutputWindow::discardExcessiveOutput()
d->queuedSizeHistory.clear();
d->queuedSizeHistory << queuedSize;
bool discard = d->queuedSizeHistory.size() > int(10) && queuedSize > 5 * d->chunkSize;
+ if (discard)
+ qCDebug(chunkLog) << "discarding output due to size";
// Criterion 2: Are we too slow?
// If it would take longer than a minute to print the pending output and we have
@@ -601,6 +618,8 @@ void OutputWindow::discardExcessiveOutput()
if (!discard) {
discard = d->formatterCalls >= 10
&& (queuedSize / d->chunkSize) * d->queueTimer.intervalAsDuration() > 60s;
+ if (discard)
+ qCDebug(chunkLog) << "discarding output due to time";
}
if (discard) {
@@ -733,7 +752,7 @@ void OutputWindow::flush()
}
d->queueTimer.stop();
for (const auto &chunk : std::as_const(d->queuedOutput))
- handleOutputChunk(chunk.first, chunk.second);
+ handleOutputChunk(chunk.first, chunk.second, ChunkCompleteness::Complete);
d->queuedOutput.clear();
d->formatter.flush();
}
diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h
index dc5bde19f8f..1ecd5abff74 100644
--- a/src/plugins/coreplugin/outputwindow.h
+++ b/src/plugins/coreplugin/outputwindow.h
@@ -98,7 +98,11 @@ private:
void enableUndoRedo();
void filterNewContent();
void handleNextOutputChunk();
- void handleOutputChunk(const QString &output, Utils::OutputFormat format);
+
+ enum class ChunkCompleteness { Complete, Split };
+ void handleOutputChunk(
+ const QString &output, Utils::OutputFormat format, ChunkCompleteness completeness);
+
void discardExcessiveOutput();
void discardPendingToolOutput();
void updateAutoScroll();
diff --git a/src/plugins/coreplugin/secretaspect.cpp b/src/plugins/coreplugin/secretaspect.cpp
index 3017f6458bb..4e70380affd 100644
--- a/src/plugins/coreplugin/secretaspect.cpp
+++ b/src/plugins/coreplugin/secretaspect.cpp
@@ -76,8 +76,9 @@ void SecretAspect::readSecret(const std::function<void(Utils::expected_str<QStri
qWarning() << "No Keychain available, reading from plaintext";
qtcSettings()->beginGroup("Secrets");
auto value = qtcSettings()->value(settingsKey());
- d->callReadCallbacks(fromSettingsValue(value).toString());
qtcSettings()->endGroup();
+
+ d->callReadCallbacks(fromSettingsValue(value).toString());
return;
}
@@ -126,7 +127,7 @@ void SecretAspect::writeSettings() const
if (!QKeychain::isAvailable()) {
qtcSettings()->beginGroup("Secrets");
- qtcSettings()->setValue(settingsKey(), toSettingsValue(variantValue()));
+ qtcSettings()->setValue(settingsKey(), toSettingsValue(d->value));
qtcSettings()->endGroup();
d->wasEdited = false;
return;
@@ -198,8 +199,7 @@ void SecretAspect::addToLayoutImpl(Layouting::Layout &parent)
}));
connect(showPasswordButton, &ShowPasswordButton::toggled, edit, [showPasswordButton, edit] {
- edit->setEchoMode(
- showPasswordButton->isChecked() ? QLineEdit::Normal : QLineEdit::PasswordEchoOnEdit);
+ edit->setEchoMode(showPasswordButton->isChecked() ? QLineEdit::Normal : QLineEdit::Password);
});
connect(edit, &FancyLineEdit::textChanged, this, [this](const QString &text) {
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
index f61f0276410..9aa99a8c479 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
+++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
@@ -333,7 +333,7 @@ Link attemptDeclDef(const QTextCursor &cursor, Snapshot snapshot,
if (decl->postfix_declarator_list && decl->postfix_declarator_list->value)
funcDecl = decl->postfix_declarator_list->value->asFunctionDeclarator();
if (funcDecl)
- target = symbolFinder->findMatchingDefinition(funcDecl->symbol, snapshot);
+ target = symbolFinder->findMatchingDefinition(funcDecl->symbol, snapshot, false);
else if (simpleDecl->symbols)
target = symbolFinder->findMatchingVarDefinition(simpleDecl->symbols->value, snapshot);
}
@@ -365,7 +365,7 @@ Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *s
if (!symbol->type()->asFunctionType())
return nullptr; // not a function declaration
- return symbolFinder->findMatchingDefinition(symbol, snapshot);
+ return symbolFinder->findMatchingDefinition(symbol, snapshot, false);
}
bool maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor)
@@ -816,7 +816,8 @@ void FollowSymbolUnderCursor::switchDeclDef(
// Link to function definition/declaration
Utils::Link symbolLink;
if (functionDeclarationSymbol) {
- Symbol *symbol = symbolFinder->findMatchingDefinition(functionDeclarationSymbol, snapshot);
+ Symbol *symbol
+ = symbolFinder->findMatchingDefinition(functionDeclarationSymbol, snapshot, false);
if (symbol)
symbolLink = symbol->toLink();
} else if (declarationSymbol) {
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
index 7ae02294588..7575b00caf2 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
+++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
@@ -131,7 +131,7 @@ public:
private:
Function *maybeDefinitionFor(Function *func) const
{
- if (Function *definition = m_finder.findMatchingDefinition(func, m_params.snapshot))
+ if (Function *definition = m_finder.findMatchingDefinition(func, m_params.snapshot, true))
return definition;
return func;
}
diff --git a/src/plugins/cppeditor/insertionpointlocator.cpp b/src/plugins/cppeditor/insertionpointlocator.cpp
index e957ae77bf9..b0d2414f44b 100644
--- a/src/plugins/cppeditor/insertionpointlocator.cpp
+++ b/src/plugins/cppeditor/insertionpointlocator.cpp
@@ -562,7 +562,7 @@ static InsertionLocation nextToSurroundingDefinitions(Symbol *declaration,
if (s->isGenerated() || !(surroundingFunctionDecl = isNonVirtualFunctionDeclaration(s)))
continue;
if ((definitionFunction = symbolFinder.findMatchingDefinition(surroundingFunctionDecl,
- changes.snapshot())))
+ changes.snapshot(), true)))
{
if (destinationFile.isEmpty() || destinationFile == definitionFunction->filePath()) {
prefix = QLatin1String("\n\n");
@@ -578,9 +578,8 @@ static InsertionLocation nextToSurroundingDefinitions(Symbol *declaration,
surroundingFunctionDecl = isNonVirtualFunctionDeclaration(s);
if (!surroundingFunctionDecl)
continue;
- if ((definitionFunction = symbolFinder.findMatchingDefinition(surroundingFunctionDecl,
- changes.snapshot())))
- {
+ if ((definitionFunction = symbolFinder.findMatchingDefinition(
+ surroundingFunctionDecl, changes.snapshot(), true))) {
if (destinationFile.isEmpty() || destinationFile == definitionFunction->filePath()) {
suffix = QLatin1String("\n\n");
break;
diff --git a/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp b/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp
index aa475c4f124..0f9f8461380 100644
--- a/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp
+++ b/src/plugins/cppeditor/quickfixes/insertfunctiondefinition.cpp
@@ -345,7 +345,7 @@ private:
QList<Symbol *> unimplemented;
SymbolFinder symbolFinder;
for (Symbol * const s : std::as_const(m_declarations)) {
- if (!symbolFinder.findMatchingDefinition(s, snapshot()))
+ if (!symbolFinder.findMatchingDefinition(s, snapshot(), true))
unimplemented << s;
}
if (unimplemented.isEmpty())
diff --git a/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp b/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp
index 6b982decc78..2d7dd65a2bc 100644
--- a/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp
+++ b/src/plugins/cppeditor/quickfixes/movefunctiondefinition.cpp
@@ -1384,6 +1384,23 @@ auto Derived::func() const && noexcept -> void {}
QuickFixOperationTest(testDocuments, &factory);
}
+ void testUnimplementedOverload()
+ {
+ const QByteArray original =
+ "struct S {\n"
+ " S();\n"
+ " @S(const S &) {}\n"
+ "};\n";
+ const QByteArray expected =
+ "struct S {\n"
+ " S();\n"
+ " S(const S &);\n"
+ "};\n\n"
+ "S::S(const S &) {}\n";
+
+ MoveFuncDefOutside factory;
+ QuickFixOperationTest(singleDocument(original, expected), &factory);
+ }
};
class MoveAllFuncDefOutsideTest : public QObject
diff --git a/src/plugins/cppeditor/symbolfinder.h b/src/plugins/cppeditor/symbolfinder.h
index 10591b38d4f..37481a08158 100644
--- a/src/plugins/cppeditor/symbolfinder.h
+++ b/src/plugins/cppeditor/symbolfinder.h
@@ -13,8 +13,6 @@
#include <QSet>
#include <QStringList>
-#include <set>
-
namespace CPlusPlus {
class Class;
class Declaration;
@@ -33,7 +31,7 @@ public:
CPlusPlus::Function *findMatchingDefinition(CPlusPlus::Symbol *symbol,
const CPlusPlus::Snapshot &snapshot,
- bool strict = false);
+ bool strict);
QList<CPlusPlus::Function *> findMatchingDefinitions(
CPlusPlus::Symbol *declaration, const CPlusPlus::Snapshot &snapshot, bool strict,
diff --git a/src/plugins/extensionmanager/extensionmanagerwidget.cpp b/src/plugins/extensionmanager/extensionmanagerwidget.cpp
index 0c367adc5ea..a6a284d80fd 100644
--- a/src/plugins/extensionmanager/extensionmanagerwidget.cpp
+++ b/src/plugins/extensionmanager/extensionmanagerwidget.cpp
@@ -32,7 +32,9 @@
#include <utils/infolabel.h>
#include <utils/layoutbuilder.h>
#include <utils/markdownbrowser.h>
+#include <utils/mimeutils.h>
#include <utils/networkaccessmanager.h>
+#include <utils/stringutils.h>
#include <utils/styledbar.h>
#include <utils/stylehelper.h>
#include <utils/temporarydirectory.h>
@@ -243,6 +245,17 @@ private:
const char kRestartSetting[] = "RestartAfterPluginEnabledChanged";
+// Copy paste from Core::Internal::CorePlugin::loadMimeFromPlugin
+// TODO make code usable by other plugins.
+static void loadMimeFromPlugin(const ExtensionSystem::PluginSpec *plugin)
+{
+ const QJsonObject metaData = plugin->metaData();
+ const QJsonValue mimetypes = metaData.value("Mimetypes");
+ QString mimetypeString;
+ if (Utils::readMultiLineString(mimetypes, &mimetypeString))
+ Utils::addMimeTypes(plugin->name() + ".mimetypes", mimetypeString.trimmed().toUtf8());
+}
+
class PluginStatusWidget : public QWidget
{
public:
@@ -266,17 +279,19 @@ public:
return;
const bool doIt = m_pluginView.data().setPluginsEnabled({spec}, checked);
if (doIt) {
- if (!ICore::infoBar()->canInfoBeAdded(kRestartSetting))
- return;
-
- Utils::InfoBarEntry info(
- kRestartSetting,
- Core::Tr::tr("Plugin changes will take effect after restart."));
- info.addCustomButton(Tr::tr("Restart Now"), [] {
- ICore::infoBar()->removeInfo(kRestartSetting);
- QTimer::singleShot(0, ICore::instance(), &ICore::restart);
- });
- ICore::infoBar()->addInfo(info);
+ if (checked && spec->isEffectivelySoftloadable()) {
+ ExtensionSystem::PluginManager::loadPluginsAtRuntime({spec});
+ loadMimeFromPlugin(spec);
+ } else if (ICore::infoBar()->canInfoBeAdded(kRestartSetting)) {
+ Utils::InfoBarEntry info(
+ kRestartSetting,
+ Core::Tr::tr("Plugin changes will take effect after restart."));
+ info.addCustomButton(Tr::tr("Restart Now"), [] {
+ ICore::infoBar()->removeInfo(kRestartSetting);
+ QTimer::singleShot(0, ICore::instance(), &ICore::restart);
+ });
+ ICore::infoBar()->addInfo(info);
+ }
ExtensionSystem::PluginManager::writeSettings();
} else {
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 0b35a79e310..f80ed6bd858 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -38,6 +38,7 @@
#include <utils/temporaryfile.h>
#include <utils/theme/theme.h>
+#include <vcsbase/commonvcssettings.h>
#include <vcsbase/submitfilemodel.h>
#include <vcsbase/vcsbasediffeditorcontroller.h>
#include <vcsbase/vcsbaseeditor.h>
@@ -805,15 +806,27 @@ GitClient &gitClient()
GitClient::GitClient()
: VcsBase::VcsBaseClientImpl(&Internal::settings())
- , m_timer(new QTimer)
{
m_gitQtcEditor = QString::fromLatin1("\"%1\" -client -block -pid %2")
.arg(QCoreApplication::applicationFilePath())
.arg(QCoreApplication::applicationPid());
- connect(m_timer.get(), &QTimer::timeout, this, &GitClient::updateModificationInfos);
- using namespace std::chrono_literals;
- m_timer->setInterval(10s);
+ if (VcsBase::Internal::commonSettings().vcsShowStatus())
+ setupTimer();
+ connect(&VcsBase::Internal::commonSettings().vcsShowStatus, &Utils::BaseAspect::changed,
+ [this] {
+ bool enable = VcsBase::Internal::commonSettings().vcsShowStatus();
+ QTC_CHECK(enable == bool(!m_timer));
+ if (enable) {
+ setupTimer();
+ } else {
+ m_timer.reset();
+ for (auto fp : std::as_const(m_modifInfos)) {
+ m_modifInfos[fp.rootPath].modifiedFiles.clear();
+ emitClearFileStatus(fp.rootPath);
+ }
+ }
+ });
}
GitClient::~GitClient() = default;
@@ -904,7 +917,7 @@ void GitClient::stopMonitoring(const Utils::FilePath &path)
for (const FilePath &subModule : subPaths)
m_modifInfos.remove(subModule);
m_modifInfos.remove(directory);
- if (m_modifInfos.isEmpty())
+ if (m_modifInfos.isEmpty() && m_timer)
m_timer->stop();
}
@@ -918,8 +931,10 @@ void GitClient::monitorDirectory(const Utils::FilePath &path)
const QList<FilePath> subPaths = submoduleDataToAbsolutePath(submoduleList(directory), directory);
for (const FilePath &subModule : subPaths)
m_modifInfos.insert(subModule, {subModule, {}});
- if (!m_timer->isActive())
- m_timer->start();
+
+ if (!m_timer)
+ return;
+
updateModificationInfos();
}
@@ -971,7 +986,8 @@ void GitClient::updateModificationInfos()
emitFileStatusChanged(info.rootPath, statusChangedFiles);
};
- vcsExecWithHandler(path, {"status", "-s", "--porcelain"}, this, command, RunFlags::NoOutput);
+ vcsExecWithHandler(path, {"status", "-s", "--porcelain", "--ignore-submodules"},
+ this, command, RunFlags::NoOutput);
}
}
@@ -3894,6 +3910,16 @@ ColorNames GitClient::colorNames()
return result;
}
+void GitClient::setupTimer()
+{
+ QTC_ASSERT(!m_timer, return);
+ m_timer.reset(new QTimer);
+ connect(m_timer.get(), &QTimer::timeout, this, &GitClient::updateModificationInfos);
+ using namespace std::chrono_literals;
+ m_timer->setInterval(10s);
+ m_timer->start();
+}
+
} // Git::Internal
#include "gitclient.moc"
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 1429469ca79..ca2ed56d78d 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -406,6 +406,7 @@ private:
QString msgBoxText, const QString &buttonName,
const QString &gitCommand, ContinueCommandMode continueMode);
+ void setupTimer();
mutable Utils::FilePath m_gitVersionForBinary;
mutable QVersionNumber m_cachedGitVersion;
mutable QMap<Utils::FilePath, Utils::FilePath> m_gitExecutableCache;
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 38b3b344710..fc0d69bef60 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -1909,6 +1909,11 @@ void emitFileStatusChanged(const FilePath &repository, const QStringList &files)
emit dd->updateFileStatus(repository, files);
}
+void emitClearFileStatus(const FilePath &repository)
+{
+ emit dd->clearFileStatus(repository);
+}
+
void startRebaseFromCommit(const FilePath &workingDirectory, const QString &commit)
{
dd->startRebaseFromCommit(workingDirectory, commit);
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index a6658fbf8d4..705807bbacc 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -23,6 +23,7 @@ bool isCommitEditorOpen();
void emitFilesChanged(const QStringList &);
void emitRepositoryChanged(const Utils::FilePath &);
void emitFileStatusChanged(const Utils::FilePath &repository, const QStringList &files);
+void emitClearFileStatus(const Utils::FilePath &repository);
void startRebaseFromCommit(const Utils::FilePath &workingDirectory, const QString &commit);
void manageRemotes();
void initRepository();
diff --git a/src/plugins/lua/bindings/texteditor.cpp b/src/plugins/lua/bindings/texteditor.cpp
index 2fc4e3b0e88..0ca9a7f4e93 100644
--- a/src/plugins/lua/bindings/texteditor.cpp
+++ b/src/plugins/lua/bindings/texteditor.cpp
@@ -52,6 +52,12 @@ TextEditor::TextEditorWidget *getSuggestionReadyEditorWidget(TextEditor::TextDoc
std::unique_ptr<EmbeddedWidgetInterface> addEmbeddedWidget(
BaseTextEditor *editor, QWidget *widget, std::variant<int, Position> cursorPosition)
{
+ if (!widget)
+ throw sol::error("No widget provided");
+
+ if (!editor)
+ throw sol::error("No editor provided");
+
if (!editor->textDocument() || !editor->textDocument()->document())
throw sol::error("No text document set");
diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
index cecd14b9c3a..73c7dac7588 100644
--- a/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
+++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.cpp
@@ -144,6 +144,11 @@ QIcon KitManagerConfigWidget::displayIcon() const
return m_modifiedKit->displayIcon();
}
+void KitManagerConfigWidget::clearCachedDisplayName()
+{
+ m_cachedDisplayName.clear();
+}
+
void KitManagerConfigWidget::setFocusToName()
{
m_nameEdit->selectAll();
diff --git a/src/plugins/projectexplorer/kitmanagerconfigwidget.h b/src/plugins/projectexplorer/kitmanagerconfigwidget.h
index d23ab59cb70..a2aaec581b8 100644
--- a/src/plugins/projectexplorer/kitmanagerconfigwidget.h
+++ b/src/plugins/projectexplorer/kitmanagerconfigwidget.h
@@ -32,6 +32,7 @@ public:
QString displayName() const;
QIcon displayIcon() const;
+ void clearCachedDisplayName(); // FIXME: Remove cached name?
void setFocusToName();
void apply();
diff --git a/src/plugins/projectexplorer/kitoptionspage.cpp b/src/plugins/projectexplorer/kitoptionspage.cpp
index 2cdc1451757..37a74517246 100644
--- a/src/plugins/projectexplorer/kitoptionspage.cpp
+++ b/src/plugins/projectexplorer/kitoptionspage.cpp
@@ -143,6 +143,7 @@ public:
void setHasUniqueName(bool on)
{
m_hasUniqueName = on;
+ update();
}
void ensureWidget();
@@ -354,6 +355,7 @@ Kit *KitModel::markForAddition(Kit *baseKit)
} else {
k->setup();
}
+ node->widget()->clearCachedDisplayName();
k->setUnexpandedDisplayName(newName);
if (!m_defaultNode)
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index 833643197de..ace041c9e75 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -463,6 +463,7 @@ void FlatModel::handleProjectAdded(Project *project)
if (vc) {
vc->monitorDirectory(rootPath);
connect(vc, &IVersionControl::updateFileStatus, this, &FlatModel::updateVCStatusFor);
+ connect(vc, &IVersionControl::clearFileStatus, this, &FlatModel::clearVCStatusFor);
}
addOrRebuildProjectModel(project);
@@ -485,6 +486,20 @@ void FlatModel::updateVCStatusFor(const Utils::FilePath root, const QStringList
});
}
+void FlatModel::clearVCStatusFor(const Utils::FilePath &root)
+{
+ ProjectTree::forEachNode([this, root](Node *n) {
+ FileNode *fileNode = n->asFileNode();
+ if (!fileNode)
+ return;
+ if (fileNode->filePath().isChildOf(root)) {
+ fileNode->resetModificationState();
+ const QModelIndex index = indexForNode(fileNode);
+ emit dataChanged(index, index, {Qt::ForegroundRole});
+ }
+ });
+}
+
void FlatModel::handleProjectRemoved(Project *project)
{
destroyItem(nodeForProject(project));
diff --git a/src/plugins/projectexplorer/projectmodels.h b/src/plugins/projectexplorer/projectmodels.h
index a07279388a4..8cee63309bc 100644
--- a/src/plugins/projectexplorer/projectmodels.h
+++ b/src/plugins/projectexplorer/projectmodels.h
@@ -86,6 +86,7 @@ private:
void addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<Node *> *seen);
bool trimEmptyDirectories(WrapperNode *parent);
void updateVCStatusFor(const Utils::FilePath root, const QStringList &files);
+ void clearVCStatusFor(const Utils::FilePath &root);
ExpandData expandDataForNode(const Node *node) const;
void loadExpandData();
diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp
index 8fe63773ecc..c3f09d1fecd 100644
--- a/src/plugins/projectexplorer/toolchainoptionspage.cpp
+++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp
@@ -101,6 +101,8 @@ public:
ToolchainTreeItem(bundle), changed(c), m_parentWidget(parentWidget)
{}
+ ~ExtendedToolchainTreeItem() override { delete m_widget; }
+
QVariant data(int column, int role) const override
{
switch (role) {
diff --git a/src/plugins/python/pythoneditor.cpp b/src/plugins/python/pythoneditor.cpp
index 64ad03052d7..5854b92d3de 100644
--- a/src/plugins/python/pythoneditor.cpp
+++ b/src/plugins/python/pythoneditor.cpp
@@ -297,7 +297,8 @@ PythonDocument::PythonDocument()
void PythonDocument::updateCurrentPython()
{
- updatePython(detectPython(filePath()));
+ if (Core::DocumentModel::entryForDocument(this))
+ updatePython(detectPython(filePath()));
}
void PythonDocument::updatePython(const FilePath &python)
diff --git a/src/plugins/python/pythonlanguageclient.cpp b/src/plugins/python/pythonlanguageclient.cpp
index 3c05b8f87ed..bbfb5c75474 100644
--- a/src/plugins/python/pythonlanguageclient.cpp
+++ b/src/plugins/python/pythonlanguageclient.cpp
@@ -334,8 +334,10 @@ void PyLSConfigureAssistant::installPythonLanguageServer(const FilePath &python,
void PyLSConfigureAssistant::openDocument(const FilePath &python, TextEditor::TextDocument *document)
{
resetEditorInfoBar(document);
- if (!PythonSettings::pylsEnabled() || !python.exists())
+ if (!PythonSettings::pylsEnabled() || !python.exists()
+ || !Core::DocumentModel::entryForDocument(document)) {
return;
+ }
if (auto client = pythonClients().value(python)) {
LanguageClientManager::openDocumentWithClient(document, client);
diff --git a/src/plugins/qmlprofiler/quick3dframeview.cpp b/src/plugins/qmlprofiler/quick3dframeview.cpp
index 3d0141d0ed9..64f51c9970f 100644
--- a/src/plugins/qmlprofiler/quick3dframeview.cpp
+++ b/src/plugins/qmlprofiler/quick3dframeview.cpp
@@ -54,13 +54,13 @@ Quick3DFrameView::Quick3DFrameView(QmlProfilerModelManager *profilerModelManager
connect(m_compareFrameView.get(), &Quick3DMainView::gotoSourceLocation,
this, &Quick3DFrameView::gotoSourceLocation);
- auto groupLayout = new QVBoxLayout(this);
+ auto groupLayout = new QVBoxLayout;
groupLayout->setContentsMargins(0,0,0,0);
groupLayout->setSpacing(0);
- auto hMainLayout = new QHBoxLayout(this);
+ auto hMainLayout = new QHBoxLayout;
hMainLayout->setContentsMargins(0,0,0,0);
hMainLayout->setSpacing(0);
- auto hFrameLayout = new QHBoxLayout(this);
+ auto hFrameLayout = new QHBoxLayout;
hFrameLayout->setContentsMargins(0,0,0,0);
hFrameLayout->setSpacing(0);
auto view3DComboBox = new QComboBox(this);
diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp
index f5f1fe091f1..4a411c1f456 100644
--- a/src/plugins/remotelinux/filesystemaccess_test.cpp
+++ b/src/plugins/remotelinux/filesystemaccess_test.cpp
@@ -129,6 +129,27 @@ void FileSystemAccessTest::initTestCase()
QVERIFY(m_localRemoteDestDir.exists());
QVERIFY(m_remoteLocalDestDir.exists());
QVERIFY(m_remoteRemoteDestDir.exists());
+
+ const FilePath localPath = localTempDir / "sourceChildDir" / "grandchildDir";
+ const FilePath remotePath = remoteTempDir / "destChildDir" / "grandchildDir";
+ if (localPath.exists())
+ localPath.parentDir().removeRecursively();
+ if (remotePath.exists())
+ remotePath.parentDir().removeRecursively();
+ QVERIFY(!localPath.exists());
+ QVERIFY(!remotePath.exists());
+ QVERIFY(!localPath.parentDir().exists());
+ QVERIFY(!remotePath.parentDir().exists());
+ QVERIFY(localPath.ensureWritableDir());
+ QVERIFY(remotePath.ensureWritableDir());
+ QVERIFY(localPath.exists());
+ QVERIFY(remotePath.exists());
+ QVERIFY(localPath.parentDir().removeRecursively());
+ QVERIFY(remotePath.parentDir().removeRecursively());
+ QVERIFY(!localPath.exists());
+ QVERIFY(!remotePath.exists());
+ QVERIFY(!localPath.parentDir().exists());
+ QVERIFY(!remotePath.parentDir().exists());
}
void FileSystemAccessTest::cleanupTestCase()
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp
index 1cab9f82924..83eb9c7d13d 100644
--- a/src/plugins/texteditor/codeassist/codeassistant.cpp
+++ b/src/plugins/texteditor/codeassist/codeassistant.cpp
@@ -367,9 +367,14 @@ QString CodeAssistantPrivate::proposalPrefix() const
void CodeAssistantPrivate::invalidateCurrentRequestData()
{
m_processor = nullptr;
- disconnect(
- m_requestProvider, &QObject::destroyed, this, &CodeAssistantPrivate::cancelCurrentRequest);
- m_requestProvider = nullptr;
+ if (m_requestProvider) {
+ disconnect(
+ m_requestProvider,
+ &QObject::destroyed,
+ this,
+ &CodeAssistantPrivate::cancelCurrentRequest);
+ m_requestProvider = nullptr;
+ }
m_receivedContentWhileWaiting = false;
}
diff --git a/src/plugins/vcsbase/commonvcssettings.cpp b/src/plugins/vcsbase/commonvcssettings.cpp
index 5f009487108..f546ae4154b 100644
--- a/src/plugins/vcsbase/commonvcssettings.cpp
+++ b/src/plugins/vcsbase/commonvcssettings.cpp
@@ -80,9 +80,16 @@ CommonVcsSettings::CommonVcsSettings()
lineWrapWidth.setSuffix(Tr::tr(" characters"));
lineWrapWidth.setDefaultValue(72);
+ vcsShowStatus.setSettingsKey("ShowVcsStatus");
+ vcsShowStatus.setDefaultValue(false);
+ vcsShowStatus.setLabelText(Tr::tr("Show VCS file status"));
+ vcsShowStatus.setToolTip(Tr::tr("Request file status updates from files and reflect them "
+ "on the project tree."));
+
setLayouter([this] {
using namespace Layouting;
return Column {
+ vcsShowStatus, br,
Row { lineWrap, lineWrapWidth, st },
Form {
submitMessageCheckScript, br,
diff --git a/src/plugins/vcsbase/commonvcssettings.h b/src/plugins/vcsbase/commonvcssettings.h
index ced68d31b97..da962bca643 100644
--- a/src/plugins/vcsbase/commonvcssettings.h
+++ b/src/plugins/vcsbase/commonvcssettings.h
@@ -3,11 +3,13 @@
#pragma once
+#include "vcsbase_global.h"
+
#include <utils/aspects.h>
namespace VcsBase::Internal {
-class CommonVcsSettings final : public Utils::AspectContainer
+class VCSBASE_EXPORT CommonVcsSettings final : public Utils::AspectContainer
{
public:
CommonVcsSettings();
@@ -22,8 +24,9 @@ public:
Utils::BoolAspect lineWrap{this};
Utils::IntegerAspect lineWrapWidth{this};
+ Utils::BoolAspect vcsShowStatus{this};
};
-CommonVcsSettings &commonSettings();
+VCSBASE_EXPORT CommonVcsSettings &commonSettings();
} // VcsBase::Internal
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject 862deed5ec60c36c603d5ac84546804ea67cc67
+Subproject e44a761b3b2081bb3ac4ee320d868310bd37312