diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp index b61f211147d..bb186b9d5e4 100644 --- a/src/plugins/projectexplorer/targetsettingspanel.cpp +++ b/src/plugins/projectexplorer/targetsettingspanel.cpp @@ -709,6 +709,10 @@ TargetGroupItemPrivate::TargetGroupItemPrivate(TargetGroupItem *q, Project *proj TargetGroupItemPrivate::~TargetGroupItemPrivate() { disconnect(); + + delete m_noKitLabel; + delete m_configurePage; + delete m_configuredPage; } QVariant TargetGroupItem::data(int column, int role) const diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 69a9fd02d1d..d0cdf78780a 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -86,8 +86,6 @@ namespace Internal { // -------------------------------------------------------------------- static const char CONFIG_CPP_MODULE[] = "cpp"; -static const char CONFIG_CXXFLAGS[] = "cxxFlags"; -static const char CONFIG_CFLAGS[] = "cFlags"; static const char CONFIG_DEFINES[] = "defines"; static const char CONFIG_INCLUDEPATHS[] = "includePaths"; static const char CONFIG_SYSTEM_INCLUDEPATHS[] = "systemIncludePaths"; diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 8978fff35af..b3035b93f16 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -55,7 +54,9 @@ #include #include #include -#include +#include + +#include using namespace Core; using namespace QtSupport; @@ -1519,10 +1520,11 @@ FileName BaseQtVersion::mkspecFromVersionInfo(const QHash &ver if (temp.size() == 2) { QString possibleFullPath = QString::fromLocal8Bit(temp.at(1).trimmed().constData()); if (possibleFullPath.contains(QLatin1Char('$'))) { // QTBUG-28792 - const QRegExp rex(QLatin1String("\\binclude\\(([^)]+)/qmake\\.conf\\)")); - if (rex.indexIn(QString::fromLocal8Bit(f2.readAll())) != -1) { + const QRegularExpression rex(QLatin1String("\\binclude\\(([^)]+)/qmake\\.conf\\)")); + const QRegularExpressionMatch match = rex.match(QString::fromLocal8Bit(f2.readAll())); + if (match.hasMatch()) { possibleFullPath = mkspecFullPath.toString() + QLatin1Char('/') - + rex.cap(1); + + match.captured(1); } } // We sometimes get a mix of different slash styles here... @@ -1739,12 +1741,147 @@ FileNameList BaseQtVersion::qtCorePaths(const QHash &versionInf return dynamicLibs; } +static QByteArray scanQtBinaryForBuildString(const FileName &library) +{ + QFile lib(library.toString()); + QByteArray buildString; + + if (lib.open(QIODevice::ReadOnly)) { + const QByteArray startNeedle = "Qt "; + const QByteArray buildNeedle = " build; by "; + const size_t oneMiB = 1024 * 1024; + const size_t keepSpace = 4096; + const size_t bufferSize = oneMiB + keepSpace; + QByteArray buffer(bufferSize, '\0'); + + char *const readStart = buffer.data() + keepSpace; + auto readStartIt = buffer.begin() + keepSpace; + const auto copyStartIt = readStartIt + (oneMiB - keepSpace); + + while (!lib.atEnd()) { + const int read = lib.read(readStart, static_cast(oneMiB)); + const auto readEndIt = readStart + read; + auto currentIt = readStartIt; + + forever { + const auto qtFoundIt = std::search(currentIt, readEndIt, + startNeedle.begin(), startNeedle.end()); + if (qtFoundIt == readEndIt) + break; + + currentIt = qtFoundIt + 1; + + // Found "Qt ", now find the next '\0'. + const auto nullFoundIt = std::find(qtFoundIt, readEndIt, '\0'); + if (nullFoundIt == readEndIt) + break; + + // String much too long? + const size_t len = std::distance(qtFoundIt, nullFoundIt); + if (len > keepSpace) + continue; + + // Does it contain " build; by "? + const auto buildByFoundIt = std::search(qtFoundIt, nullFoundIt, + buildNeedle.begin(), buildNeedle.end()); + if (buildByFoundIt == nullFoundIt) + continue; + + buildString = QByteArray(qtFoundIt, len); + break; + } + + if (!buildString.isEmpty() || readEndIt != buffer.constEnd()) + break; + + std::move(copyStartIt, readEndIt, buffer.begin()); // Copy last section to front. + } + } + return buildString; +} + +static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &probableAbi) +{ + if (buildString.isEmpty() + || buildString.count() > 4096) + return Abi(); + + const QRegularExpression buildStringMatcher("^Qt " + "([\\d\\.a-zA-Z]*) " // Qt version + "\\(" + "([a-z\\d_]*)-" // CPU + "(big|little)_endian-" + "([a-z]+(?:32|64))" // pointer information + "(?:-(qreal|))?" // extra information like -qreal + "(?:-([^-]+))? " // ABI information + "(shared|static) (?:\\(dynamic\\) )?" + "(debug|release)" + " build; by " + "(.*)" // compiler with extra info + "\\)$"); + + QTC_ASSERT(buildStringMatcher.isValid(), qWarning() << buildStringMatcher.errorString()); + const QRegularExpressionMatch match = buildStringMatcher.match(QString::fromUtf8(buildString)); + QTC_ASSERT(match.hasMatch(), return Abi()); + + // const QString qtVersion = match.captured(1); + // const QString cpu = match.captured(2); + // const bool littleEndian = (match.captured(3) == "little"); + // const QString pointer = match.captured(4); + // const QString extra = match.captured(5); + // const QString abiString = match.captured(6); + // const QString linkage = match.captured(7); + // const QString buildType = match.captured(8); + const QString compiler = match.captured(9); + + Abi::Architecture arch = probableAbi.architecture(); + Abi::OS os = probableAbi.os(); + Abi::OSFlavor flavor = probableAbi.osFlavor(); + Abi::BinaryFormat format = probableAbi.binaryFormat(); + unsigned char wordWidth = probableAbi.wordWidth(); + + if (compiler.startsWith("GCC ") && os == Abi::WindowsOS) { + flavor = Abi::WindowsMSysFlavor; + } else if (compiler.startsWith("MSVC 2005") && os == Abi::WindowsOS) { + flavor = Abi::WindowsMsvc2005Flavor; + } else if (compiler.startsWith("MSVC 2008") && os == Abi::WindowsOS) { + flavor = Abi::WindowsMsvc2008Flavor; + } else if (compiler.startsWith("MSVC 2010") && os == Abi::WindowsOS) { + flavor = Abi::WindowsMsvc2010Flavor; + } else if (compiler.startsWith("MSVC 2012") && os == Abi::WindowsOS) { + flavor = Abi::WindowsMsvc2012Flavor; + } else if (compiler.startsWith("MSVC 2015") && os == Abi::WindowsOS) { + flavor = Abi::WindowsMsvc2015Flavor; + } else if (compiler.startsWith("MSVC 2017") && os == Abi::WindowsOS) { + flavor = Abi::WindowsMsvc2017Flavor; + } + + return Abi(arch, os, flavor, format, wordWidth); +} + +static Abi scanQtBinaryForBuildStringAndRefineAbi(const FileName &library, + const Abi &probableAbi) +{ + static QHash results; + + if (!results.contains(library)) { + const QByteArray buildString = scanQtBinaryForBuildString(library); + results.insert(library, refineAbiFromBuildString(buildString, probableAbi)); + } + return results.value(library); +} + QList BaseQtVersion::qtAbisFromLibrary(const FileNameList &coreLibraries) { QList res; - foreach (const FileName &library, coreLibraries) - foreach (const Abi &abi, Abi::abisOfBinary(library)) - if (!res.contains(abi)) - res.append(abi); + foreach (const FileName &library, coreLibraries) { + for (Abi abi : Abi::abisOfBinary(library)) { + Abi tmp = abi; + if (abi.osFlavor() == Abi::UnknownFlavor) + tmp = scanQtBinaryForBuildStringAndRefineAbi(library, abi); + if (!res.contains(tmp)) + res.append(tmp); + } + } return res; } diff --git a/src/plugins/remotelinux/genericdirectuploadservice.cpp b/src/plugins/remotelinux/genericdirectuploadservice.cpp index e72e77e07b3..9839adccb7f 100644 --- a/src/plugins/remotelinux/genericdirectuploadservice.cpp +++ b/src/plugins/remotelinux/genericdirectuploadservice.cpp @@ -191,6 +191,8 @@ void GenericDirectUploadService::handleUploadFinished(SftpJobId jobId, const QSt this, &GenericDirectUploadService::handleStdOutData); connect(d->chmodProc.data(), &SshRemoteProcess::readyReadStandardError, this, &GenericDirectUploadService::handleStdErrData); + connect(d->chmodProc.data(), &SshRemoteProcess::readChannelFinished, + this, &GenericDirectUploadService::handleReadChannelFinished); d->chmodProc->start(); } else { uploadNextFile(); @@ -275,6 +277,8 @@ void GenericDirectUploadService::handleMkdirFinished(int exitStatus) this, &GenericDirectUploadService::handleStdOutData); connect(d->lnProc.data(), &SshRemoteProcess::readyReadStandardError, this, &GenericDirectUploadService::handleStdErrData); + connect(d->lnProc.data(), &SshRemoteProcess::readChannelFinished, + this, &GenericDirectUploadService::handleReadChannelFinished); d->lnProc->start(); } else { const SftpJobId job = d->uploader->uploadFile(df.localFilePath().toString(), @@ -310,6 +314,13 @@ void GenericDirectUploadService::handleStdErrData() emit stdErrData(QString::fromUtf8(process->readAllStandardError())); } +void GenericDirectUploadService::handleReadChannelFinished() +{ + SshRemoteProcess * const process = qobject_cast(sender()); + if (process && process->atEnd()) + process->close(); +} + void GenericDirectUploadService::stopDeployment() { QTC_ASSERT(d->state == InitializingSftp || d->state == Uploading, setFinished(); return); @@ -383,6 +394,8 @@ void GenericDirectUploadService::uploadNextFile() this, &GenericDirectUploadService::handleStdOutData); connect(d->mkdirProc.data(), &SshRemoteProcess::readyReadStandardError, this, &GenericDirectUploadService::handleStdErrData); + connect(d->mkdirProc.data(), &SshRemoteProcess::readChannelFinished, + this, &GenericDirectUploadService::handleReadChannelFinished); emit progressMessage(tr("Uploading file \"%1\"...") .arg(df.localFilePath().toUserOutput())); d->mkdirProc->start(); diff --git a/src/plugins/remotelinux/genericdirectuploadservice.h b/src/plugins/remotelinux/genericdirectuploadservice.h index e10f8a0b569..853b274af75 100644 --- a/src/plugins/remotelinux/genericdirectuploadservice.h +++ b/src/plugins/remotelinux/genericdirectuploadservice.h @@ -68,6 +68,7 @@ private: void handleChmodFinished(int exitStatus); void handleStdOutData(); void handleStdErrData(); + void handleReadChannelFinished(); void checkDeploymentNeeded(const ProjectExplorer::DeployableFile &file) const; void setFinished(); diff --git a/src/shared/help/bookmarkmanager.cpp b/src/shared/help/bookmarkmanager.cpp index 4d17c9f8eca..f66ba076a40 100644 --- a/src/shared/help/bookmarkmanager.cpp +++ b/src/shared/help/bookmarkmanager.cpp @@ -443,6 +443,10 @@ void BookmarkWidget::setup() treeView->setDropIndicatorShown(true); treeView->viewport()->installEventFilter(this); treeView->setContextMenuPolicy(Qt::CustomContextMenu); + // work around crash on Windows with drag & drop + // in combination with proxy model and ResizeToContents section resize mode + treeView->header()->setSectionResizeMode(QHeaderView::Stretch); + connect(treeView, &TreeView::expanded, this, &BookmarkWidget::expand); connect(treeView, &TreeView::collapsed, this, &BookmarkWidget::expand);