Merge remote-tracking branch 'origin/5.0'

Change-Id: I8ecb4ab5cb5754e26de3c446abed2386c42305d6
This commit is contained in:
hjk
2021-07-16 09:56:01 +02:00
37 changed files with 817 additions and 76 deletions

View File

@@ -67,6 +67,18 @@ if [ -d "$assetimporterSrcDir" ]; then
fi fi
fi fi
# workaround for Qt 6.2:
# - QTBUG-94796 macdeployqt does not deploy /Contents/PlugIns/sqldrivers/libqsqlite.dylib anymore
sqldriversDestDir="$app_path/Contents/PlugIns/sqldrivers"
sqldriversSrcDir="$plugin_src/sqldrivers"
if [ -d "$sqldriversSrcDir" ]; then
if [ ! -d "$sqldriversDestDir" ]; then
echo "- Copying sqlitedriver plugin"
mkdir -p "$sqldriversDestDir"
cp "$sqldriversSrcDir/libqsqlite.dylib" "$sqldriversDestDir/libqsqlite.dylib"
fi
fi
# copy Qt Quick 2 imports # copy Qt Quick 2 imports
imports2Dir="$app_path/Contents/Imports/qtquick2" imports2Dir="$app_path/Contents/Imports/qtquick2"
if [ -d "$quick2_src" ]; then if [ -d "$quick2_src" ]; then

View File

@@ -32,17 +32,13 @@ set(TRACING_CPP_SOURCES
tracing_global.h tracing_global.h
) )
add_qtc_library(Tracing
FEATURE_INFO
DEPENDS Utils Qt5::Qml Qt5::Quick
PUBLIC_DEPENDS Qt5::Widgets
SOURCES
${TEST_SOURCES}
)
if(${Qt5_VERSION} VERSION_LESS "6.2.0") if(${Qt5_VERSION} VERSION_LESS "6.2.0")
extend_qtc_library(Tracing add_qtc_library(Tracing
FEATURE_INFO
DEPENDS Utils Qt5::Qml Qt5::Quick
PUBLIC_DEPENDS Qt5::Widgets
SOURCES SOURCES
${TEST_SOURCES}
${TRACING_CPP_SOURCES} ${TRACING_CPP_SOURCES}
qml/tracing.qrc qml/tracing.qrc
) )
@@ -51,6 +47,14 @@ else() # < Qt 6.2
return() return()
endif() endif()
add_qtc_library(Tracing
FEATURE_INFO
DEPENDS Utils Qt5::Qml Qt5::Quick
PUBLIC_DEPENDS Qt5::Widgets
SOURCES
${TEST_SOURCES}
)
set(TRACING_QML_FILES set(TRACING_QML_FILES
qml/ButtonsBar.qml qml/ButtonsBar.qml
qml/CategoryLabel.qml qml/CategoryLabel.qml

View File

@@ -72,7 +72,7 @@ Item {
DropArea { DropArea {
id: dropArea id: dropArea
onPositionChanged: { onPositionChanged: (drag) => {
var sourceIndex = drag.source.visualIndex; var sourceIndex = drag.source.visualIndex;
if (drag.source.y === 0) { if (drag.source.y === 0) {
// special case for first position: Always swap, no matter if upper border touched. // special case for first position: Always swap, no matter if upper border touched.
@@ -129,7 +129,7 @@ Item {
labelContainer.selectNextBySelectionId(label.id); labelContainer.selectNextBySelectionId(label.id);
} }
} }
onSetRowHeight: { onSetRowHeight: (newHeight) => {
labelsArea.parentModel.setExpandedRowHeight(index + 1, newHeight); labelsArea.parentModel.setExpandedRowHeight(index + 1, newHeight);
loader.height = labelsArea.parentModel.rowHeight(index + 1); loader.height = labelsArea.parentModel.rowHeight(index + 1);
} }

View File

@@ -151,8 +151,12 @@ Rectangle {
zoomer: zoomControl zoomer: zoomControl
reverseSelect: shiftPressed reverseSelect: shiftPressed
onMoveCategories: content.moveCategories(sourceIndex, targetIndex) onMoveCategories: (sourceIndex, targetIndex) => {
onSelectItem: content.select(modelIndex, eventIndex) content.moveCategories(sourceIndex, targetIndex)
}
onSelectItem: (modelIndex, eventIndex) => {
content.select(modelIndex, eventIndex)
}
} }
TimeDisplay { TimeDisplay {
@@ -206,7 +210,7 @@ Rectangle {
onWidthChanged: selectionRange.update(); onWidthChanged: selectionRange.update();
onPropagateSelection: { onPropagateSelection: (newModel, newItem) => {
if (lockItemSelection || (newModel === selectedModel && newItem === selectedItem)) if (lockItemSelection || (newModel === selectedModel && newItem === selectedItem))
return; return;

View File

@@ -168,10 +168,10 @@ Rectangle {
} }
} }
onPressed: { onPressed: (mouse) => {
jumpTo(mouse.x); jumpTo(mouse.x);
} }
onPositionChanged: { onPositionChanged: (mouse) => {
jumpTo(mouse.x); jumpTo(mouse.x);
} }
} }

View File

@@ -115,14 +115,14 @@ Flickable {
categories.selectItem(index, eventId) categories.selectItem(index, eventId)
} }
onSelectNextBySelectionId: { onSelectNextBySelectionId: (selectionId) => {
categories.selectItem(index, modelData.nextItemBySelectionId( categories.selectItem(index, modelData.nextItemBySelectionId(
selectionId, zoomer.rangeStart, selectionId, zoomer.rangeStart,
categories.selectedModel === index ? categories.selectedItem : categories.selectedModel === index ? categories.selectedItem :
-1)); -1));
} }
onSelectPrevBySelectionId: { onSelectPrevBySelectionId: (selectionId) => {
categories.selectItem(index, modelData.prevItemBySelectionId( categories.selectItem(index, modelData.prevItemBySelectionId(
selectionId, zoomer.rangeStart, selectionId, zoomer.rangeStart,
categories.selectedModel === index ? categories.selectedItem : categories.selectedModel === index ? categories.selectedItem :

View File

@@ -44,7 +44,7 @@ Item {
anchors.right: parent.right anchors.right: parent.right
height: scaleHeight height: scaleHeight
onClicked: { onClicked: (mouse) => {
rulersModel.append({ rulersModel.append({
timestamp: (mouse.x + contentX) * viewTimePerPixel + windowStart timestamp: (mouse.x + contentX) * viewTimePerPixel + windowStart
}); });

View File

@@ -71,6 +71,7 @@ add_qtc_library(Utils
htmldocextractor.cpp htmldocextractor.h htmldocextractor.cpp htmldocextractor.h
icon.cpp icon.h icon.cpp icon.h
id.cpp id.h id.cpp id.h
indexedcontainerproxyconstiterator.h
infobar.cpp infobar.h infobar.cpp infobar.h
infolabel.cpp infolabel.h infolabel.cpp infolabel.h
itemviews.cpp itemviews.h itemviews.cpp itemviews.h

View File

@@ -390,7 +390,9 @@ FilePath FilePath::resolvePath(const QString &fileName) const
{ {
if (FileUtils::isAbsolutePath(fileName)) if (FileUtils::isAbsolutePath(fileName))
return FilePath::fromString(QDir::cleanPath(fileName)); return FilePath::fromString(QDir::cleanPath(fileName));
return FilePath::fromString(QDir::cleanPath(toString() + QLatin1Char('/') + fileName)); FilePath result = *this;
result.setPath(QDir::cleanPath(m_data + '/' + fileName));
return result;
} }
FilePath FilePath::cleanPath() const FilePath FilePath::cleanPath() const

View File

@@ -0,0 +1,188 @@
/****************************************************************************
**
** 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 <QtGlobal>
#include <type_traits>
namespace Utils {
/// A class useful for the implementation of the -> operator of proxy iterators.
template <typename Reference>
struct ArrowProxy {
Reference r;
Reference *operator->() {
return &r;
}
};
/// Random-access const iterator over elements of a container providing an overloaded operator[]
/// (which may return a proxy object, like std::vector<bool>, rather than a reference).
template <typename Container>
class IndexedContainerProxyConstIterator
{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename std::make_signed<typename Container::size_type>::type difference_type;
typedef typename Container::value_type value_type;
typedef value_type reference;
typedef ArrowProxy<reference> pointer;
typedef typename Container::size_type size_type;
IndexedContainerProxyConstIterator()
: m_container(nullptr), m_index(0)
{}
IndexedContainerProxyConstIterator(const Container &container, size_type index)
: m_container(&container), m_index(index)
{}
reference operator*() const
{
Q_ASSERT(m_container);
return (*m_container)[m_index];
}
pointer operator->() const
{
Q_ASSERT(m_container);
return pointer{(*m_container)[m_index]};
}
reference operator[](difference_type j) const
{
Q_ASSERT(m_container);
return (*m_container)[m_index + j];
}
bool operator==(const IndexedContainerProxyConstIterator &other) const
{
Q_ASSERT(m_container == other.m_container);
return m_index == other.m_index;
}
bool operator!=(const IndexedContainerProxyConstIterator &other) const
{
Q_ASSERT(m_container == other.m_container);
return m_index != other.m_index;
}
bool operator<(const IndexedContainerProxyConstIterator &other) const
{
Q_ASSERT(m_container == other.m_container);
return m_index < other.m_index;
}
bool operator<=(const IndexedContainerProxyConstIterator &other) const
{
Q_ASSERT(m_container == other.m_container);
return m_index <= other.m_index;
}
bool operator>(const IndexedContainerProxyConstIterator &other) const
{
Q_ASSERT(m_container == other.m_container);
return m_index > other.m_index;
}
bool operator>=(const IndexedContainerProxyConstIterator &other) const
{
Q_ASSERT(m_container == other.m_container);
return m_index >= other.m_index;
}
IndexedContainerProxyConstIterator &operator++()
{
++m_index;
return *this;
}
IndexedContainerProxyConstIterator operator++(int)
{
IndexedContainerProxyConstIterator copy(*this);
++m_index;
return copy;
}
IndexedContainerProxyConstIterator &operator--()
{
--m_index;
return *this;
}
IndexedContainerProxyConstIterator operator--(int)
{
IndexedContainerProxyConstIterator copy(*this);
--m_index;
return copy;
}
IndexedContainerProxyConstIterator &operator+=(difference_type j)
{
m_index += j;
return *this;
}
IndexedContainerProxyConstIterator &operator-=(difference_type j)
{
m_index -= j;
return *this;
}
IndexedContainerProxyConstIterator operator+(difference_type j) const
{
IndexedContainerProxyConstIterator result(*this);
result += j;
return result;
}
IndexedContainerProxyConstIterator operator-(difference_type j) const
{
IndexedContainerProxyConstIterator result(*this);
result -= j;
return result;
}
friend IndexedContainerProxyConstIterator operator+(
difference_type j, const IndexedContainerProxyConstIterator &other)
{
return other + j;
}
difference_type operator-(const IndexedContainerProxyConstIterator &other) const
{
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
}
private:
const Container *m_container;
size_type m_index;
};
} // namespace Utils

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include "utils_global.h" #include "utils_global.h"
#include "indexedcontainerproxyconstiterator.h"
#include <QAbstractItemModel> #include <QAbstractItemModel>
@@ -119,6 +120,15 @@ public:
}); });
} }
using value_type = ChildType *;
using const_iterator = IndexedContainerProxyConstIterator<TypedTreeItem>;
using size_type = int;
ChildType *operator[](int index) const { return childAt(index); }
int size() const { return childCount(); }
const_iterator begin() const { return const_iterator(*this, 0); }
const_iterator end() const { return const_iterator(*this, size()); }
template <typename Predicate> template <typename Predicate>
void forAllChildren(const Predicate &pred) const { void forAllChildren(const Predicate &pred) const {
const auto pred0 = [pred](TreeItem *treeItem) { pred(static_cast<ChildType *>(treeItem)); }; const auto pred0 = [pred](TreeItem *treeItem) { pred(static_cast<ChildType *>(treeItem)); };

View File

@@ -153,6 +153,7 @@ HEADERS += \
$$PWD/environmentfwd.h \ $$PWD/environmentfwd.h \
$$PWD/genericconstants.h \ $$PWD/genericconstants.h \
$$PWD/globalfilechangeblocker.h \ $$PWD/globalfilechangeblocker.h \
$$PWD/indexedcontainerproxyconstiterator.h \
$$PWD/benchmarker.h \ $$PWD/benchmarker.h \
$$PWD/displayname.h \ $$PWD/displayname.h \
$$PWD/environment.h \ $$PWD/environment.h \

View File

@@ -149,6 +149,7 @@ Project {
"icon.h", "icon.h",
"id.cpp", "id.cpp",
"id.h", "id.h",
"indexedcontainerproxyconstiterator.h",
"infobar.cpp", "infobar.cpp",
"infobar.h", "infobar.h",
"infolabel.cpp", "infolabel.cpp",

View File

@@ -101,7 +101,9 @@ QList<LocatorFilterEntry> MenuBarFilter::matchesForAction(QAction *action,
QList<LocatorFilterEntry> entries; QList<LocatorFilterEntry> entries;
if (!m_enabledActions.contains(action)) if (!m_enabledActions.contains(action))
return entries; return entries;
const QString text = Utils::stripAccelerator(action->text()); const QString whatsThis = action->whatsThis();
const QString text = Utils::stripAccelerator(action->text())
+ (whatsThis.isEmpty() ? QString() : QString(" (" + whatsThis + ")"));
if (QMenu *menu = action->menu()) { if (QMenu *menu = action->menu()) {
if (processedMenus.contains(menu)) if (processedMenus.contains(menu))
return entries; return entries;

View File

@@ -432,8 +432,7 @@ void DebuggerItemConfigWidget::binaryPathHasChanged()
return; return;
DebuggerItem tmp; DebuggerItem tmp;
QFileInfo fi = QFileInfo(m_binaryChooser->filePath().toString()); if (m_binaryChooser->filePath().isExecutableFile()) {
if (fi.isExecutable()) {
tmp = item(); tmp = item();
tmp.reinitializeFromFile(); tmp.reinitializeFromFile();
} }
@@ -800,7 +799,7 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers(const FilePath &de
const QString name = detectionSource.isEmpty() ? tr("System %1 at %2") : tr("Detected %1 at %2"); const QString name = detectionSource.isEmpty() ? tr("System %1 at %2") : tr("Detected %1 at %2");
item.setUnexpandedDisplayName(name.arg(item.engineTypeName()).arg(command.toUserOutput())); item.setUnexpandedDisplayName(name.arg(item.engineTypeName()).arg(command.toUserOutput()));
m_model->addDebugger(item); m_model->addDebugger(item);
logMessages.append(tr("Found: \"%1\"").arg(name)); logMessages.append(tr("Found: \"%1\"").arg(command.toUserOutput()));
} }
if (logMessage) if (logMessage)
*logMessage = logMessages.join('\n'); *logMessage = logMessages.join('\n');

View File

@@ -49,6 +49,7 @@
#include <utils/basetreeview.h> #include <utils/basetreeview.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/utilsicons.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/overridecursor.h> #include <utils/overridecursor.h>
#include <utils/port.h> #include <utils/port.h>
@@ -69,6 +70,7 @@
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QPushButton> #include <QPushButton>
#include <QTextBrowser> #include <QTextBrowser>
#include <QToolButton>
#include <QThread> #include <QThread>
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
@@ -312,6 +314,14 @@ public:
QFileSystemWatcher m_mergedDirWatcher; QFileSystemWatcher m_mergedDirWatcher;
Environment m_cachedEnviroment; Environment m_cachedEnviroment;
enum LocalAccessState
{
NotEvaluated,
NoDaemon,
Accessible,
NotAccessible
} m_accessible = NotEvaluated;
}; };
class DockerDeviceWidget final : public IDeviceWidget class DockerDeviceWidget final : public IDeviceWidget
@@ -337,6 +347,17 @@ public:
m_repoLineEdit->setText(data.repo); m_repoLineEdit->setText(data.repo);
m_repoLineEdit->setEnabled(false); m_repoLineEdit->setEnabled(false);
auto daemonStateLabel = new QLabel(tr("Daemon state:"));
m_daemonReset = new QToolButton;
m_daemonReset->setIcon(Icons::INFO.icon());
m_daemonReset->setToolTip(tr("Daemon state not evaluated."));
connect(m_daemonReset, &QToolButton::clicked, this, [this, dockerDevice] {
dockerDevice->resetDaemonState();
m_daemonReset->setIcon(Icons::INFO.icon());
m_daemonReset->setToolTip(tr("Daemon state not evaluated."));
});
m_runAsOutsideUser = new QCheckBox(tr("Run as outside user")); m_runAsOutsideUser = new QCheckBox(tr("Run as outside user"));
m_runAsOutsideUser->setToolTip(tr("Use user ID and group ID of the user running Qt Creator " m_runAsOutsideUser->setToolTip(tr("Use user ID and group ID of the user running Qt Creator "
"in the Docker container.")); "in the Docker container."));
@@ -369,6 +390,16 @@ public:
logView->clear(); logView->clear();
dockerDevice->tryCreateLocalFileAccess(); dockerDevice->tryCreateLocalFileAccess();
m_kitItemDetector.autoDetect(id); m_kitItemDetector.autoDetect(id);
if (!dockerDevice->isDaemonRunning()) {
logView->append(tr("Docker daemon appears to be not running."));
m_daemonReset->setToolTip(tr("Daemon not running. Push to reset the state."));
m_daemonReset->setIcon(Icons::CRITICAL.icon());
} else {
m_daemonReset->setToolTip(tr("Docker daemon running."));
m_daemonReset->setIcon(Icons::OK.icon());
}
}); });
connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, id = data.id()] { connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, id = data.id()] {
@@ -381,6 +412,7 @@ public:
Form { Form {
idLabel, m_idLineEdit, Break(), idLabel, m_idLineEdit, Break(),
repoLabel, m_repoLineEdit, Break(), repoLabel, m_repoLineEdit, Break(),
daemonStateLabel, m_daemonReset, Break(),
m_runAsOutsideUser, Break(), m_runAsOutsideUser, Break(),
tr("Paths to mount:"), m_pathsLineEdit, Break(), tr("Paths to mount:"), m_pathsLineEdit, Break(),
Column { Column {
@@ -397,6 +429,7 @@ public:
private: private:
QLineEdit *m_idLineEdit; QLineEdit *m_idLineEdit;
QLineEdit *m_repoLineEdit; QLineEdit *m_repoLineEdit;
QToolButton *m_daemonReset;
QCheckBox *m_runAsOutsideUser; QCheckBox *m_runAsOutsideUser;
QLineEdit *m_pathsLineEdit; QLineEdit *m_pathsLineEdit;
@@ -648,7 +681,7 @@ void DockerDevice::tryCreateLocalFileAccess() const
void DockerDevicePrivate::stopCurrentContainer() void DockerDevicePrivate::stopCurrentContainer()
{ {
if (m_container.isEmpty()) if (m_container.isEmpty() || m_accessible == NoDaemon)
return; return;
QtcProcess proc; QtcProcess proc;
@@ -662,7 +695,7 @@ void DockerDevicePrivate::stopCurrentContainer()
void DockerDevicePrivate::tryCreateLocalFileAccess() void DockerDevicePrivate::tryCreateLocalFileAccess()
{ {
if (!m_container.isEmpty()) if (!m_container.isEmpty() || m_accessible == NoDaemon)
return; return;
QString tempFileName; QString tempFileName;
@@ -701,6 +734,14 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
LOG("RES: " << m_shell->result() LOG("RES: " << m_shell->result()
<< " STDOUT: " << m_shell->readAllStandardOutput() << " STDOUT: " << m_shell->readAllStandardOutput()
<< " STDERR: " << m_shell->readAllStandardError()); << " STDERR: " << m_shell->readAllStandardError());
if (m_shell->exitCode() != 0) {
m_accessible = NoDaemon;
LOG("DOCKER DAEMON NOT RUNNING?");
MessageManager::writeFlashing(tr("Docker Daemon appears to be not running. "
"Verify daemon is up and running and reset the "
"docker daemon on the docker device settings page "
"or restart Qt Creator."));
}
} }
m_container.clear(); m_container.clear();
}); });
@@ -723,10 +764,11 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
break; break;
} }
} }
if (i == 20) { if (i == 20 || m_accessible == NoDaemon) {
qWarning("Docker cid file empty."); qWarning("Docker cid file empty.");
return; // No return; // No
} }
qApp->processEvents(); // FIXME turn this for-loop into QEventLoop
QThread::msleep(100); QThread::msleep(100);
} }
@@ -753,11 +795,13 @@ void DockerDevicePrivate::tryCreateLocalFileAccess()
// of using wsl or a named pipe. // of using wsl or a named pipe.
// TODO investigate how to make it possible nevertheless. // TODO investigate how to make it possible nevertheless.
m_mergedDir.clear(); m_mergedDir.clear();
m_accessible = NotAccessible;
MessageManager::writeSilently(tr("This is expected on Windows.")); MessageManager::writeSilently(tr("This is expected on Windows."));
return; return;
} }
} }
m_accessible = Accessible;
m_mergedDirWatcher.addPath(m_mergedDir); m_mergedDirWatcher.addPath(m_mergedDir);
} }
@@ -766,6 +810,24 @@ bool DockerDevice::hasLocalFileAccess() const
return !d->m_mergedDir.isEmpty(); return !d->m_mergedDir.isEmpty();
} }
bool DockerDevice::isDaemonRunning() const
{
switch (d->m_accessible) {
case DockerDevicePrivate::NoDaemon:
return false;
case DockerDevicePrivate::NotEvaluated: // FIXME?
case DockerDevicePrivate::Accessible:
case DockerDevicePrivate::NotAccessible:
return true;
}
return false;
}
void DockerDevice::resetDaemonState()
{
d->m_accessible = DockerDevicePrivate::NotEvaluated;
}
void DockerDevice::setMounts(const QStringList &mounts) const void DockerDevice::setMounts(const QStringList &mounts) const
{ {
d->m_data.mounts = mounts; d->m_data.mounts = mounts;
@@ -1183,7 +1245,7 @@ bool DockerDevice::writeFileContents(const Utils::FilePath &filePath, const QByt
void DockerDevice::runProcess(QtcProcess &process) const void DockerDevice::runProcess(QtcProcess &process) const
{ {
tryCreateLocalFileAccess(); tryCreateLocalFileAccess();
if (d->m_container.isEmpty()) { if (d->m_container.isEmpty() || d->m_accessible == DockerDevicePrivate::NoDaemon) {
LOG("No container set to run " << process.commandLine().toUserOutput()); LOG("No container set to run " << process.commandLine().toUserOutput());
QTC_CHECK(false); QTC_CHECK(false);
process.setResult(QtcProcess::StartFailed); process.setResult(QtcProcess::StartFailed);
@@ -1237,6 +1299,8 @@ void DockerDevicePrivate::fetchSystemEnviroment()
int DockerDevicePrivate::runSynchronously(const CommandLine &cmd) const int DockerDevicePrivate::runSynchronously(const CommandLine &cmd) const
{ {
if (m_accessible == NoDaemon)
return -1;
CommandLine dcmd{"docker", {"exec", m_container}}; CommandLine dcmd{"docker", {"exec", m_container}};
dcmd.addArgs(cmd); dcmd.addArgs(cmd);

View File

@@ -107,6 +107,8 @@ public:
void tryCreateLocalFileAccess() const; void tryCreateLocalFileAccess() const;
bool hasLocalFileAccess() const; bool hasLocalFileAccess() const;
bool isDaemonRunning() const;
void resetDaemonState();
void setMounts(const QStringList &mounts) const; void setMounts(const QStringList &mounts) const;
Utils::FilePath mapToLocalAccess(const Utils::FilePath &filePath) const; Utils::FilePath mapToLocalAccess(const Utils::FilePath &filePath) const;

View File

@@ -38,16 +38,12 @@ set(PERFPROFILER_CPP_SOURCES
perftracepointdialog.cpp perftracepointdialog.h perftracepointdialog.ui perftracepointdialog.cpp perftracepointdialog.h perftracepointdialog.ui
) )
add_qtc_plugin(PerfProfiler
DEPENDS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
SOURCES
${TEST_SOURCES}
)
if(${Qt5_VERSION} VERSION_LESS "6.2.0") if(${Qt5_VERSION} VERSION_LESS "6.2.0")
extend_qtc_plugin(PerfProfiler add_qtc_plugin(PerfProfiler
DEPENDS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
SOURCES SOURCES
${TEST_SOURCES}
${PERFPROFILER_CPP_SOURCES} ${PERFPROFILER_CPP_SOURCES}
perfprofiler.qrc perfprofiler.qrc
) )
@@ -56,6 +52,13 @@ else() # < Qt 6.2
return() return()
endif() endif()
add_qtc_plugin(PerfProfiler
DEPENDS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
SOURCES
${TEST_SOURCES}
)
qt_add_resources(PerfProfiler perfprofiler qt_add_resources(PerfProfiler perfprofiler
PREFIX "/perfprofiler" PREFIX "/perfprofiler"
tracepoints.sh tracepoints.sh

View File

@@ -1861,7 +1861,10 @@ static void detectCppBuildTools2015(QList<ToolChain *> *list)
QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown, QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown,
const IDevice::Ptr &device) const IDevice::Ptr &device)
{ {
Q_UNUSED(device) if (!device.isNull()) {
// FIXME currently no support for msvc toolchains on a device
return {};
}
QList<ToolChain *> results; QList<ToolChain *> results;
@@ -1969,8 +1972,10 @@ QList<ToolChain *> ClangClToolChainFactory::autoDetect(const QList<ToolChain *>
const IDevice::Ptr &device) const IDevice::Ptr &device)
{ {
Q_UNUSED(alreadyKnown) Q_UNUSED(alreadyKnown)
Q_UNUSED(device) // FIXME: Use it. if (!device.isNull()) {
// FIXME currently no support for msvc toolchains on a device
return {};
}
#ifdef Q_OS_WIN64 #ifdef Q_OS_WIN64
const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM"; const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM";
#else #else

View File

@@ -1140,36 +1140,48 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// deploy session // deploy session
dd->m_deploySessionAction = new QAction(tr("Deploy"), this); dd->m_deploySessionAction = new QAction(tr("Deploy"), this);
dd->m_deploySessionAction->setWhatsThis(tr("Deploy All Projects"));
cmd = ActionManager::registerAction(dd->m_deploySessionAction, Constants::DEPLOYSESSION); cmd = ActionManager::registerAction(dd->m_deploySessionAction, Constants::DEPLOYSESSION);
cmd->setDescription(dd->m_deploySessionAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS); mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD); msessionContextMenu->addAction(cmd, Constants::G_SESSION_BUILD);
// rebuild session action // rebuild session action
dd->m_rebuildSessionAction = new QAction(Icons::REBUILD.icon(), tr("Rebuild"), dd->m_rebuildSessionAction = new QAction(Icons::REBUILD.icon(), tr("Rebuild"),
this); this);
dd->m_rebuildSessionAction->setWhatsThis(tr("Rebuild All Projects"));
cmd = ActionManager::registerAction(dd->m_rebuildSessionAction, Constants::REBUILDSESSION); cmd = ActionManager::registerAction(dd->m_rebuildSessionAction, Constants::REBUILDSESSION);
cmd->setDescription(dd->m_rebuildSessionAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS); mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD); msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD);
dd->m_rebuildSessionForAllConfigsAction dd->m_rebuildSessionForAllConfigsAction
= new QAction(Icons::REBUILD.icon(), tr("Rebuild"), = new QAction(Icons::REBUILD.icon(), tr("Rebuild"),
this); this);
dd->m_rebuildSessionForAllConfigsAction->setWhatsThis(
tr("Rebuild All Projects for All Configurations"));
cmd = ActionManager::registerAction(dd->m_rebuildSessionForAllConfigsAction, cmd = ActionManager::registerAction(dd->m_rebuildSessionForAllConfigsAction,
Constants::REBUILDSESSIONALLCONFIGS); Constants::REBUILDSESSIONALLCONFIGS);
cmd->setDescription(dd->m_rebuildSessionForAllConfigsAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS_ALLCONFIGURATIONS); mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS_ALLCONFIGURATIONS);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD); msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD);
// clean session // clean session
dd->m_cleanSessionAction = new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"), dd->m_cleanSessionAction = new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"),
this); this);
dd->m_cleanSessionAction->setWhatsThis(tr("Clean All Projects"));
cmd = ActionManager::registerAction(dd->m_cleanSessionAction, Constants::CLEANSESSION); cmd = ActionManager::registerAction(dd->m_cleanSessionAction, Constants::CLEANSESSION);
cmd->setDescription(dd->m_cleanSessionAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS); mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD); msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD);
dd->m_cleanSessionForAllConfigsAction = new QAction(Utils::Icons::CLEAN.icon(), dd->m_cleanSessionForAllConfigsAction = new QAction(Utils::Icons::CLEAN.icon(),
tr("Clean"), this); tr("Clean"), this);
dd->m_cleanSessionForAllConfigsAction->setWhatsThis(
tr("Clean All Projects for All Configurations"));
cmd = ActionManager::registerAction(dd->m_cleanSessionForAllConfigsAction, cmd = ActionManager::registerAction(dd->m_cleanSessionForAllConfigsAction,
Constants::CLEANSESSIONALLCONFIGS); Constants::CLEANSESSIONALLCONFIGS);
cmd->setDescription(dd->m_cleanSessionForAllConfigsAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS_ALLCONFIGURATIONS); mbuild->addAction(cmd, Constants::G_BUILD_ALLPROJECTS_ALLCONFIGURATIONS);
msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD); msessionContextMenu->addAction(cmd, Constants::G_SESSION_REBUILD);
@@ -1215,39 +1227,45 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// deploy action // deploy action
dd->m_deployAction = new QAction(tr("Deploy"), this); dd->m_deployAction = new QAction(tr("Deploy"), this);
dd->m_deployAction->setWhatsThis(tr("Deploy Project"));
cmd = ActionManager::registerAction(dd->m_deployAction, Constants::DEPLOY); cmd = ActionManager::registerAction(dd->m_deployAction, Constants::DEPLOY);
cmd->setAttribute(Command::CA_UpdateText); cmd->setAttribute(Command::CA_UpdateText);
cmd->setDescription(dd->m_deployAction->text()); cmd->setDescription(dd->m_deployAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_PROJECT); mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
// rebuild action // rebuild action
dd->m_rebuildAction = new QAction(Icons::REBUILD.icon(), tr("Rebuild"), this); dd->m_rebuildAction = new QAction(Icons::REBUILD.icon(), tr("Rebuild"), this);
dd->m_rebuildAction->setWhatsThis(tr("Rebuild Project"));
cmd = ActionManager::registerAction(dd->m_rebuildAction, Constants::REBUILD); cmd = ActionManager::registerAction(dd->m_rebuildAction, Constants::REBUILD);
cmd->setAttribute(Command::CA_UpdateText); cmd->setAttribute(Command::CA_UpdateText);
cmd->setDescription(dd->m_rebuildAction->text()); cmd->setDescription(dd->m_rebuildAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_PROJECT); mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
dd->m_rebuildProjectForAllConfigsAction dd->m_rebuildProjectForAllConfigsAction
= new QAction(Icons::REBUILD.icon(), tr("Rebuild"), this); = new QAction(Icons::REBUILD.icon(), tr("Rebuild"), this);
dd->m_rebuildProjectForAllConfigsAction->setWhatsThis(
tr("Rebuild Project for All Configurations"));
cmd = ActionManager::registerAction(dd->m_rebuildProjectForAllConfigsAction, cmd = ActionManager::registerAction(dd->m_rebuildProjectForAllConfigsAction,
Constants::REBUILDALLCONFIGS); Constants::REBUILDALLCONFIGS);
cmd->setAttribute(Command::CA_UpdateText); cmd->setAttribute(Command::CA_UpdateText);
cmd->setDescription(dd->m_rebuildProjectForAllConfigsAction->text()); cmd->setDescription(dd->m_rebuildProjectForAllConfigsAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_PROJECT_ALLCONFIGURATIONS); mbuild->addAction(cmd, Constants::G_BUILD_PROJECT_ALLCONFIGURATIONS);
// clean action // clean action
dd->m_cleanAction = new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"), this); dd->m_cleanAction = new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"), this);
dd->m_cleanAction->setWhatsThis(tr("Clean Project"));
cmd = ActionManager::registerAction(dd->m_cleanAction, Constants::CLEAN); cmd = ActionManager::registerAction(dd->m_cleanAction, Constants::CLEAN);
cmd->setAttribute(Command::CA_UpdateText); cmd->setAttribute(Command::CA_UpdateText);
cmd->setDescription(dd->m_cleanAction->text()); cmd->setDescription(dd->m_cleanAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_PROJECT); mbuild->addAction(cmd, Constants::G_BUILD_PROJECT);
dd->m_cleanProjectForAllConfigsAction dd->m_cleanProjectForAllConfigsAction
= new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"), this); = new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"), this);
dd->m_cleanProjectForAllConfigsAction->setWhatsThis(tr("Clean Project for All Configurations"));
cmd = ActionManager::registerAction(dd->m_cleanProjectForAllConfigsAction, cmd = ActionManager::registerAction(dd->m_cleanProjectForAllConfigsAction,
Constants::CLEANALLCONFIGS); Constants::CLEANALLCONFIGS);
cmd->setAttribute(Command::CA_UpdateText); cmd->setAttribute(Command::CA_UpdateText);
cmd->setDescription(dd->m_cleanProjectForAllConfigsAction->text()); cmd->setDescription(dd->m_cleanProjectForAllConfigsAction->whatsThis());
mbuild->addAction(cmd, Constants::G_BUILD_PROJECT_ALLCONFIGURATIONS); mbuild->addAction(cmd, Constants::G_BUILD_PROJECT_ALLCONFIGURATIONS);
// cancel build action // cancel build action

View File

@@ -61,6 +61,7 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <functional> #include <functional>
#include <iterator>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
@@ -69,6 +70,28 @@ using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
/// An output iterator whose assignment operator appends a clone of the operand to the list of
/// children of the WrapperNode passed to the constructor.
class Appender : public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
explicit Appender(WrapperNode *parent) : m_parent(parent) {}
Appender &operator=(const WrapperNode *node)
{
if (node)
m_parent->appendClone(*node);
return *this;
}
Appender &operator*() { return *this; }
Appender &operator++() { return *this; }
Appender &operator++(int) { return *this; }
private:
WrapperNode *m_parent;
};
bool compareNodes(const Node *n1, const Node *n2) bool compareNodes(const Node *n1, const Node *n2)
{ {
if (n1->priority() > n2->priority()) if (n1->priority() > n2->priority())
@@ -82,9 +105,7 @@ bool compareNodes(const Node *n1, const Node *n2)
const int filePathResult = caseFriendlyCompare(n1->filePath().toString(), const int filePathResult = caseFriendlyCompare(n1->filePath().toString(),
n2->filePath().toString()); n2->filePath().toString());
if (filePathResult != 0) return filePathResult < 0;
return filePathResult < 0;
return n1 < n2; // sort by pointer value
} }
static bool sortWrapperNodes(const WrapperNode *w1, const WrapperNode *w2) static bool sortWrapperNodes(const WrapperNode *w1, const WrapperNode *w2)
@@ -92,6 +113,71 @@ static bool sortWrapperNodes(const WrapperNode *w1, const WrapperNode *w2)
return compareNodes(w1->m_node, w2->m_node); return compareNodes(w1->m_node, w2->m_node);
} }
/// Appends to `dest` clones of children of `first` and `second`, removing duplicates (recursively).
///
/// \param first, second
/// Nodes with children sorted by sortWrapperNodes.
/// \param dest
/// Node to which to append clones of children of `first` and `second`, with duplicates removed.
static void appendMergedChildren(const WrapperNode *first, const WrapperNode *second, WrapperNode *dest)
{
setUnionMerge(first->begin(), first->end(),
second->begin(), second->end(),
Appender(dest),
[dest](const WrapperNode *childOfFirst, const WrapperNode *childOfSecond)
-> const WrapperNode * {
if (childOfSecond->hasChildren()) {
if (childOfFirst->hasChildren()) {
WrapperNode *mergeResult = new WrapperNode(childOfFirst->m_node);
dest->appendChild(mergeResult);
appendMergedChildren(childOfFirst, childOfSecond, mergeResult);
// mergeResult has already been appended to the parent's list of
// children -- there's no need for the Appender to do it again.
// That's why we return a null pointer.
return nullptr;
} else {
return childOfSecond;
}
} else {
return childOfFirst;
}
},
sortWrapperNodes);
}
/// Given a node `parent` with children sorted by the criteria defined in sortWrapperNodes(), merge
/// any children that are equal according to those criteria.
static void mergeDuplicates(WrapperNode *parent)
{
// We assume all descendants of 'parent' are sorted
int childIndex = 0;
while (childIndex + 1 < parent->childCount()) {
const WrapperNode *child = parent->childAt(childIndex);
const WrapperNode *nextChild = parent->childAt(childIndex + 1);
Q_ASSERT_X(!sortWrapperNodes(nextChild, child), __func__, "Children are not sorted");
if (!sortWrapperNodes(child, nextChild)) {
// child and nextChild must have the same priorities, display names and folder paths.
// Replace them by a single node 'mergeResult` containing the union of their children.
auto mergeResult = new WrapperNode(child->m_node);
parent->insertChild(childIndex, mergeResult);
appendMergedChildren(child, nextChild, mergeResult);
// Now we can remove the original children
parent->removeChildAt(childIndex + 2);
parent->removeChildAt(childIndex + 1);
} else {
++childIndex;
}
}
}
void WrapperNode::appendClone(const WrapperNode &node)
{
WrapperNode *clone = new WrapperNode(node.m_node);
appendChild(clone);
for (const WrapperNode *child : node)
clone->appendClone(*child);
}
FlatModel::FlatModel(QObject *parent) FlatModel::FlatModel(QObject *parent)
: TreeModel<WrapperNode, WrapperNode>(new WrapperNode(nullptr), parent) : TreeModel<WrapperNode, WrapperNode>(new WrapperNode(nullptr), parent)
{ {
@@ -393,6 +479,8 @@ void FlatModel::saveExpandData()
void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<Node *> *seen) void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<Node *> *seen)
{ {
bool hasHiddenSourcesOrHeaders = false;
for (Node *node : folderNode->nodes()) { for (Node *node : folderNode->nodes()) {
if (m_filterGeneratedFiles && node->isGenerated()) if (m_filterGeneratedFiles && node->isGenerated())
continue; continue;
@@ -403,8 +491,10 @@ void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<
if (!m_showSourceGroups) { if (!m_showSourceGroups) {
if (subFolderNode->isVirtualFolderType()) { if (subFolderNode->isVirtualFolderType()) {
auto vnode = static_cast<VirtualFolderNode *>(subFolderNode); auto vnode = static_cast<VirtualFolderNode *>(subFolderNode);
if (vnode->isSourcesOrHeaders()) if (vnode->isSourcesOrHeaders()) {
isHidden = true; isHidden = true;
hasHiddenSourcesOrHeaders = true;
}
} }
} }
if (!isHidden && !seen->contains(subFolderNode)) { if (!isHidden && !seen->contains(subFolderNode)) {
@@ -423,6 +513,11 @@ void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<
} }
} }
} }
if (hasHiddenSourcesOrHeaders) {
parent->sortChildren(&sortWrapperNodes);
mergeDuplicates(parent);
}
} }
bool FlatModel::trimEmptyDirectories(WrapperNode *parent) bool FlatModel::trimEmptyDirectories(WrapperNode *parent)

View File

@@ -52,6 +52,8 @@ class WrapperNode : public Utils::TypedTreeItem<WrapperNode>
public: public:
explicit WrapperNode(Node *node) : m_node(node) {} explicit WrapperNode(Node *node) : m_node(node) {}
Node *m_node = nullptr; Node *m_node = nullptr;
void appendClone(const WrapperNode &node);
}; };
class FlatModel : public Utils::TreeModel<WrapperNode, WrapperNode> class FlatModel : public Utils::TreeModel<WrapperNode, WrapperNode>

View File

@@ -361,7 +361,7 @@ public:
void setIsSourcesOrHeaders(bool on) { m_isSourcesOrHeaders = on; } void setIsSourcesOrHeaders(bool on) { m_isSourcesOrHeaders = on; }
private: private:
bool m_isSourcesOrHeaders; // "Sources" or "Headers" bool m_isSourcesOrHeaders = false; // "Sources" or "Headers"
}; };
// Documentation inside. // Documentation inside.

View File

@@ -190,9 +190,11 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
this, &QbsProjectManagerPlugin::cleanProductContextMenu); this, &QbsProjectManagerPlugin::cleanProductContextMenu);
m_cleanProduct = new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"), this); m_cleanProduct = new QAction(Utils::Icons::CLEAN.icon(), tr("Clean"), this);
m_cleanProduct->setWhatsThis(tr("Clean Product"));
command = Core::ActionManager::registerAction(m_cleanProduct, Constants::ACTION_CLEAN_PRODUCT); command = Core::ActionManager::registerAction(m_cleanProduct, Constants::ACTION_CLEAN_PRODUCT);
command->setAttribute(Core::Command::CA_Hide); command->setAttribute(Core::Command::CA_Hide);
command->setAttribute(Core::Command::CA_UpdateText); command->setAttribute(Core::Command::CA_UpdateText);
command->setDescription(m_cleanProduct->whatsThis());
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PRODUCT); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PRODUCT);
connect(m_cleanProduct, &QAction::triggered, this, &QbsProjectManagerPlugin::cleanProduct); connect(m_cleanProduct, &QAction::triggered, this, &QbsProjectManagerPlugin::cleanProduct);
@@ -205,10 +207,12 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
this, &QbsProjectManagerPlugin::rebuildProductContextMenu); this, &QbsProjectManagerPlugin::rebuildProductContextMenu);
m_rebuildProduct = new QAction(ProjectExplorer::Icons::REBUILD.icon(), tr("Rebuild"), this); m_rebuildProduct = new QAction(ProjectExplorer::Icons::REBUILD.icon(), tr("Rebuild"), this);
m_rebuildProduct->setWhatsThis(tr("Rebuild Product"));
command = Core::ActionManager::registerAction(m_rebuildProduct, command = Core::ActionManager::registerAction(m_rebuildProduct,
Constants::ACTION_REBUILD_PRODUCT); Constants::ACTION_REBUILD_PRODUCT);
command->setAttribute(Core::Command::CA_Hide); command->setAttribute(Core::Command::CA_Hide);
command->setAttribute(Core::Command::CA_UpdateText); command->setAttribute(Core::Command::CA_UpdateText);
command->setDescription(m_rebuildProduct->whatsThis());
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PRODUCT); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PRODUCT);
connect(m_rebuildProduct, &QAction::triggered, this, &QbsProjectManagerPlugin::rebuildProduct); connect(m_rebuildProduct, &QAction::triggered, this, &QbsProjectManagerPlugin::rebuildProduct);

View File

@@ -377,11 +377,9 @@ QVariant QmakeProFileNode::data(Utils::Id role) const
if (role == Android::Constants::AndroidSoLibPath) { if (role == Android::Constants::AndroidSoLibPath) {
TargetInformation info = targetInformation(); TargetInformation info = targetInformation();
QStringList res = {info.buildDir.toString()}; QStringList res = {info.buildDir.toString()};
Utils::FilePath destDir = info.destDir; FilePath destDir = info.destDir;
if (!destDir.isEmpty()) { if (!destDir.isEmpty()) {
if (destDir.toFileInfo().isRelative()) destDir = info.buildDir.resolvePath(destDir.path());
destDir = Utils::FilePath::fromString(QDir::cleanPath(info.buildDir.toString()
+ '/' + destDir.toString()));
res.append(destDir.toString()); res.append(destDir.toString());
} }
res.removeDuplicates(); res.removeDuplicates();

View File

@@ -246,19 +246,21 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString
d->m_rebuildSubProjectAction = new QAction(Icons::REBUILD.icon(), tr("Rebuild"), d->m_rebuildSubProjectAction = new QAction(Icons::REBUILD.icon(), tr("Rebuild"),
this); this);
d->m_rebuildSubProjectAction->setWhatsThis(tr("Rebuild Subproject"));
command = ActionManager::registerAction(d->m_rebuildSubProjectAction, Constants::REBUILDSUBDIR, projectContext); command = ActionManager::registerAction(d->m_rebuildSubProjectAction, Constants::REBUILDSUBDIR, projectContext);
command->setAttribute(Command::CA_Hide); command->setAttribute(Command::CA_Hide);
command->setAttribute(Command::CA_UpdateText); command->setAttribute(Command::CA_UpdateText);
command->setDescription(d->m_rebuildSubProjectAction->text()); command->setDescription(d->m_rebuildSubProjectAction->whatsThis());
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_SUBPROJECT); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_SUBPROJECT);
connect(d->m_rebuildSubProjectAction, &QAction::triggered, connect(d->m_rebuildSubProjectAction, &QAction::triggered,
d, &QmakeProjectManagerPluginPrivate::rebuildSubDirContextMenu); d, &QmakeProjectManagerPluginPrivate::rebuildSubDirContextMenu);
d->m_cleanSubProjectAction = new QAction(Utils::Icons::CLEAN.icon(),tr("Clean"), this); d->m_cleanSubProjectAction = new QAction(Utils::Icons::CLEAN.icon(),tr("Clean"), this);
d->m_cleanSubProjectAction->setWhatsThis(tr("Clean Subproject"));
command = ActionManager::registerAction(d->m_cleanSubProjectAction, Constants::CLEANSUBDIR, projectContext); command = ActionManager::registerAction(d->m_cleanSubProjectAction, Constants::CLEANSUBDIR, projectContext);
command->setAttribute(Command::CA_Hide); command->setAttribute(Command::CA_Hide);
command->setAttribute(Command::CA_UpdateText); command->setAttribute(Command::CA_UpdateText);
command->setDescription(d->m_cleanSubProjectAction->text()); command->setDescription(d->m_cleanSubProjectAction->whatsThis());
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_SUBPROJECT); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_SUBPROJECT);
connect(d->m_cleanSubProjectAction, &QAction::triggered, connect(d->m_cleanSubProjectAction, &QAction::triggered,
d, &QmakeProjectManagerPluginPrivate::cleanSubDirContextMenu); d, &QmakeProjectManagerPluginPrivate::cleanSubDirContextMenu);

View File

@@ -69,16 +69,12 @@ set(QMLPROFILER_CPP_SOURCES
scenegraphtimelinemodel.cpp scenegraphtimelinemodel.h scenegraphtimelinemodel.cpp scenegraphtimelinemodel.h
) )
add_qtc_plugin(QmlProfiler
DEPENDS QmlDebug QmlJS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport TextEditor
SOURCES
${TEST_SOURCES}
)
if(${Qt5_VERSION} VERSION_LESS "6.2.0") if(${Qt5_VERSION} VERSION_LESS "6.2.0")
extend_qtc_plugin(QmlProfiler add_qtc_plugin(QmlProfiler
DEPENDS QmlDebug QmlJS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport TextEditor
SOURCES SOURCES
${TEST_SOURCES}
${QMLPROFILER_CPP_SOURCES} ${QMLPROFILER_CPP_SOURCES}
qml/qmlprofiler.qrc qml/qmlprofiler.qrc
) )
@@ -87,6 +83,13 @@ else() # < Qt 6.2
return() return()
endif() endif()
add_qtc_plugin(QmlProfiler
DEPENDS QmlDebug QmlJS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport TextEditor
SOURCES
${TEST_SOURCES}
)
set(QMLPROFILER_QML_FILES set(QMLPROFILER_QML_FILES
qml/QmlProfilerFlameGraphView.qml qml/QmlProfilerFlameGraphView.qml
) )

View File

@@ -272,14 +272,14 @@ void tst_TestCore::loadEmptyCoreModel()
QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode())); QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode()));
} }
void tst_TestCore::testRewriterView() void tst_TestCore::testRewriterView2()
{ {
try { try {
QPlainTextEdit textEdit; QPlainTextEdit textEdit;
textEdit.setPlainText("import QtQuick 2.15;\n\nItem {\n}\n"); textEdit.setPlainText("import QtQuick 2.15;\n\nRectangle {\n}\n");
NotIndentingTextEditModifier textModifier(&textEdit); NotIndentingTextEditModifier textModifier(&textEdit);
QScopedPointer<Model> model(Model::create("QtQuick.Item")); QScopedPointer<Model> model(Model::create("QtQuick.Rectangle", 2, 1));
QVERIFY(model.data()); QVERIFY(model.data());
QScopedPointer<TestView> view(new TestView(model.data())); QScopedPointer<TestView> view(new TestView(model.data()));
@@ -292,15 +292,20 @@ void tst_TestCore::testRewriterView()
testRewriterView->setTextModifier(&textModifier); testRewriterView->setTextModifier(&textModifier);
model->attachView(testRewriterView.data()); model->attachView(testRewriterView.data());
ModelNode childNode(addNodeListChild(rootModelNode, "QtQuick.Rectangle", 1, 0, "data")); while (testRewriterView->hasIncompleteTypeInformation()) {
QApplication::processEvents(QEventLoop::AllEvents, 1000);
}
ModelNode childNode(addNodeListChild(rootModelNode, "QtQuick.Rectangle", 2, 11, "data"));
QVERIFY(childNode.isValid()); QVERIFY(childNode.isValid());
childNode.setIdWithoutRefactoring("childNode"); childNode.setIdWithoutRefactoring("childNode");
ModelNode childNode2(addNodeListChild(childNode, "QtQuick.Rectangle", 1, 0, "data")); ModelNode childNode2(addNodeListChild(childNode, "QtQuick.Rectangle", 2, 11, "data"));
childNode2.setIdWithoutRefactoring("childNode2"); childNode2.setIdWithoutRefactoring("childNode2");
ModelNode childNode3(addNodeListChild(childNode2, "QtQuick.Rectangle", 1, 0, "data")); ModelNode childNode3(addNodeListChild(childNode2, "QtQuick.Rectangle", 2, 11, "data"));
childNode3.setIdWithoutRefactoring("childNode3"); childNode3.setIdWithoutRefactoring("childNode3");
ModelNode childNode4(addNodeListChild(childNode3, "QtQuick.Rectangle", 1, 0, "data")); ModelNode childNode4(addNodeListChild(childNode3, "QtQuick.Rectangle", 2, 11, "data"));
childNode4.setIdWithoutRefactoring("childNode4"); childNode4.setIdWithoutRefactoring("childNode4");
QVERIFY(childNode.isValid()); QVERIFY(childNode.isValid());
@@ -326,7 +331,7 @@ void tst_TestCore::testRewriterView()
testRewriterView->modelToTextMerger()->applyChanges(); testRewriterView->modelToTextMerger()->applyChanges();
childNode = addNodeListChild(rootModelNode, "QtQuick.Rectangle", 2, 0, "data"); childNode = addNodeListChild(rootModelNode, "QtQuick.Rectangle", 2, 11, "data");
QVERIFY(testRewriterView->modelToTextMerger()->isNodeScheduledForAddition(childNode)); QVERIFY(testRewriterView->modelToTextMerger()->isNodeScheduledForAddition(childNode));
testRewriterView->modelToTextMerger()->applyChanges(); testRewriterView->modelToTextMerger()->applyChanges();
@@ -334,6 +339,93 @@ void tst_TestCore::testRewriterView()
childNode.variantProperty("x").setValue(70); childNode.variantProperty("x").setValue(70);
childNode.variantProperty("y").setValue(90); childNode.variantProperty("y").setValue(90);
QCOMPARE(testRewriterView->modelToTextMerger()
->findAddedVariantProperty(childNode.variantProperty("x"))
.value(),
QVariant(70));
QCOMPARE(testRewriterView->modelToTextMerger()
->findAddedVariantProperty(childNode.variantProperty("y"))
.value(),
QVariant(90));
model->detachView(testRewriterView.data());
} catch (Exception &e) {
QFAIL(qPrintable(e.description()));
}
}
void tst_TestCore::testRewriterView()
{
try {
const QLatin1String qmlString("import QtQuick 2.15\n"
"Rectangle {\n"
"}\n");
QPlainTextEdit textEdit;
textEdit.setPlainText(qmlString);
NotIndentingTextEditModifier textModifier(&textEdit);
QScopedPointer<Model> model(Model::create("QtQuick.Item", 2, 15));
QVERIFY(model.data());
QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView());
testRewriterView->setTextModifier(&textModifier);
testRewriterView->setCheckSemanticErrors(true);
model->attachView(testRewriterView.data());
while (testRewriterView->hasIncompleteTypeInformation()) {
QApplication::processEvents(QEventLoop::AllEvents, 1000);
}
textEdit.setPlainText(qmlString);
ModelNode rootModelNode = testRewriterView->rootModelNode();
ModelNode childNode(addNodeListChild(rootModelNode, "QtQuick.Rectangle", 2, 11, "data"));
QVERIFY(childNode.isValid());
childNode.setIdWithoutRefactoring("childNode");
ModelNode childNode2(addNodeListChild(childNode, "QtQuick.Rectangle", 2, 11, "data"));
childNode2.setIdWithoutRefactoring("childNode2");
ModelNode childNode3(addNodeListChild(childNode2, "QtQuick.Rectangle", 2, 11, "data"));
childNode3.setIdWithoutRefactoring("childNode3");
ModelNode childNode4(addNodeListChild(childNode3, "QtQuick.Rectangle", 2, 11, "data"));
childNode4.setIdWithoutRefactoring("childNode4");
QVERIFY(childNode.isValid());
QVERIFY(childNode2.isValid());
QVERIFY(childNode3.isValid());
QVERIFY(childNode4.isValid());
testRewriterView->setModificationGroupActive(true);
childNode.destroy();
QVERIFY(!childNode.isValid());
QVERIFY(!childNode2.isValid());
QVERIFY(!childNode3.isValid());
QVERIFY(!childNode4.isValid());
QVERIFY(testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode));
QVERIFY(!testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode2));
QVERIFY(!testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode3));
QVERIFY(!testRewriterView->modelToTextMerger()->isNodeScheduledForRemoval(childNode4));
QVERIFY(!rootModelNode.hasProperty("data"));
testRewriterView->modelToTextMerger()->applyChanges();
childNode = addNodeListChild(rootModelNode, "QtQuick.Rectangle", 2, 11, "data");
QVERIFY(testRewriterView->modelToTextMerger()->isNodeScheduledForAddition(childNode));
QVERIFY(childNode.isValid());
testRewriterView->modelToTextMerger()->applyChanges();
QVERIFY(childNode.isValid());
childNode.variantProperty("x").setValue(70);
childNode.variantProperty("y").setValue(90);
QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("x")).value(), QVariant(70)); QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("x")).value(), QVariant(70));
QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("y")).value(), QVariant(90)); QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("y")).value(), QVariant(90));

View File

@@ -95,6 +95,7 @@ private slots:
// unit tests Rewriter // unit tests Rewriter
// //
void testRewriterView(); void testRewriterView();
void testRewriterView2();
void testRewriterErrors(); void testRewriterErrors();
void testRewriterChangeId(); void testRewriterChangeId();
void testRewriterRemoveId(); void testRewriterRemoveId();

View File

@@ -1,19 +1,20 @@
add_qtc_test(tst_tracing_flamegraphview
DEPENDS Tracing Qt5::QuickWidgets Qt5::Quick Utils
)
set(TSTFLAMEGRAPHVIEW_CPP_SOURCES set(TSTFLAMEGRAPHVIEW_CPP_SOURCES
testflamegraphmodel.h testflamegraphmodel.h
tst_flamegraphview.cpp tst_flamegraphview.cpp
) )
if(${Qt5_VERSION} VERSION_LESS "6.2.0") if(${Qt5_VERSION} VERSION_LESS "6.2.0")
extend_qtc_test(tst_tracing_flamegraphview add_qtc_test(tst_tracing_flamegraphview
DEPENDS Tracing Qt5::QuickWidgets Qt5::Quick Utils
SOURCES SOURCES
${TSTFLAMEGRAPHVIEW_CPP_SOURCES} ${TSTFLAMEGRAPHVIEW_CPP_SOURCES}
flamegraphview.qrc flamegraphview.qrc
) )
else() # < Qt 6.2 else() # < Qt 6.2
add_qtc_test(tst_tracing_flamegraphview
DEPENDS Tracing Qt5::QuickWidgets Qt5::Quick Utils
)
qt_add_qml_module(tst_tracing_flamegraphview qt_add_qml_module(tst_tracing_flamegraphview
URI "QtCreator.TstTracingFlameGraphView" URI "QtCreator.TstTracingFlameGraphView"
VERSION "1.0" VERSION "1.0"

View File

@@ -1,6 +1,7 @@
add_subdirectory(ansiescapecodehandler) add_subdirectory(ansiescapecodehandler)
add_subdirectory(fileutils) add_subdirectory(fileutils)
add_subdirectory(fuzzymatcher) add_subdirectory(fuzzymatcher)
add_subdirectory(indexedcontainerproxyconstiterator)
add_subdirectory(persistentsettings) add_subdirectory(persistentsettings)
add_subdirectory(qtcprocess) add_subdirectory(qtcprocess)
add_subdirectory(settings) add_subdirectory(settings)

View File

@@ -0,0 +1,4 @@
add_qtc_test(tst_utils_indexedcontainerproxyconstiterator
DEPENDS Utils
SOURCES tst_indexedcontainerproxyconstiterator.cpp
)

View File

@@ -0,0 +1,4 @@
QTC_LIB_DEPENDS += utils
include(../../qttest.pri)
SOURCES += tst_indexedcontainerproxyconstiterator.cpp

View File

@@ -0,0 +1,7 @@
import qbs
QtcAutotest {
name: "IndexedContainerProxyConstIterator autotest"
Depends { name: "Utils" }
files: "tst_indexedcontainerproxyconstiterator.cpp"
}

View File

@@ -0,0 +1,209 @@
/****************************************************************************
**
** 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 <utils/indexedcontainerproxyconstiterator.h>
#include <QtTest>
#include <string>
#include <vector>
using namespace Utils;
class tst_IndexedContainerProxyConstIterator : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void testConstruction();
void testDereference();
void testIndexing();
void testComparisons();
void testIncrement();
void testDecrement();
void testPlus();
void testMinus();
void testIteration();
private:
using StringContainer = std::vector<std::string>;
using StringIterator = IndexedContainerProxyConstIterator<StringContainer>;
StringContainer strings;
using BoolContainer = std::vector<bool>;
using BoolIterator = IndexedContainerProxyConstIterator<BoolContainer>;
BoolContainer bools;
};
void tst_IndexedContainerProxyConstIterator::initTestCase()
{
strings = {"abc", "defgh", "ijk"};
bools = {false, true, false};
}
void tst_IndexedContainerProxyConstIterator::testConstruction()
{
StringIterator strIt(strings, 0);
QCOMPARE(*strIt, "abc");
StringIterator strIt2(strings, 1);
QCOMPARE(*strIt2, "defgh");
BoolIterator boolIt(bools, 0);
QCOMPARE(*boolIt, false);
BoolIterator boolIt2(bools, 1);
QCOMPARE(*boolIt2, true);
}
void tst_IndexedContainerProxyConstIterator::testDereference()
{
StringIterator strIt(strings, 0);
QCOMPARE(*strIt, "abc");
QCOMPARE(strIt->length(), 3);
BoolIterator boolIt(bools, 0);
QCOMPARE(*boolIt, false);
}
void tst_IndexedContainerProxyConstIterator::testIndexing()
{
StringIterator strIt(strings, 0);
QCOMPARE(strIt[2], "ijk");
BoolIterator boolIt(bools, 0);
QCOMPARE(boolIt[2], false);
}
void tst_IndexedContainerProxyConstIterator::testComparisons()
{
StringIterator strIt(strings, 0);
StringIterator strIt2(strings, 0);
StringIterator strIt3(strings, 1);
QVERIFY(strIt == strIt);
QVERIFY(!(strIt != strIt));
QVERIFY(!(strIt < strIt));
QVERIFY(strIt <= strIt);
QVERIFY(!(strIt > strIt));
QVERIFY(strIt >= strIt);
QVERIFY(strIt == strIt2);
QVERIFY(!(strIt != strIt2));
QVERIFY(!(strIt < strIt2));
QVERIFY(strIt <= strIt2);
QVERIFY(!(strIt > strIt2));
QVERIFY(strIt >= strIt2);
QVERIFY(!(strIt == strIt3));
QVERIFY(strIt != strIt3);
QVERIFY(strIt < strIt3);
QVERIFY(strIt <= strIt3);
QVERIFY(!(strIt > strIt3));
QVERIFY(!(strIt >= strIt3));
QVERIFY(!(strIt3 == strIt));
QVERIFY(strIt3 != strIt);
QVERIFY(!(strIt3 < strIt));
QVERIFY(!(strIt3 <= strIt));
QVERIFY(strIt3 > strIt);
QVERIFY(strIt3 >= strIt);
}
void tst_IndexedContainerProxyConstIterator::testIncrement()
{
StringIterator strIt(strings, 0);
QCOMPARE(*(++strIt), "defgh");
QCOMPARE(*(strIt++), "defgh");
QCOMPARE(*strIt, "ijk");
BoolIterator boolIt(bools, 0);
QCOMPARE(*(++boolIt), true);
QCOMPARE(*(boolIt++), true);
QCOMPARE(*boolIt, false);
}
void tst_IndexedContainerProxyConstIterator::testDecrement()
{
StringIterator strIt(strings, 3);
QCOMPARE(*(--strIt), "ijk");
QCOMPARE(*(strIt--), "ijk");
QCOMPARE(*strIt, "defgh");
BoolIterator boolIt(bools, 3);
QCOMPARE(*(--boolIt), false);
QCOMPARE(*(boolIt--), false);
QCOMPARE(*boolIt, true);
}
void tst_IndexedContainerProxyConstIterator::testPlus()
{
StringIterator strIt(strings, 1);
QCOMPARE(*(strIt + 1), "ijk");
QCOMPARE(*(1 + strIt), "ijk");
strIt += 1;
QCOMPARE(*strIt, "ijk");
BoolIterator boolIt(bools, 1);
QCOMPARE(*(boolIt + 1), false);
QCOMPARE(*(1 + boolIt), false);
boolIt += 1;
QCOMPARE(*boolIt, false);
}
void tst_IndexedContainerProxyConstIterator::testMinus()
{
StringIterator strIt(strings, 1);
QCOMPARE(*(strIt - 1), "abc");
strIt -= 1;
QCOMPARE(*strIt, "abc");
BoolIterator boolIt(bools, 1);
QCOMPARE(*(boolIt - 1), false);
boolIt -= 1;
QCOMPARE(*boolIt, false);
}
void tst_IndexedContainerProxyConstIterator::testIteration()
{
StringIterator strBegin(strings, 0);
StringIterator strEnd(strings, strings.size());
StringContainer stringsCopy;
for (StringIterator it = strBegin; it != strEnd; ++it)
stringsCopy.push_back(*it);
QCOMPARE(stringsCopy, strings);
BoolIterator boolBegin(bools, 0);
BoolIterator boolEnd(bools, bools.size());
BoolContainer boolsCopy;
for (BoolIterator it = boolBegin; it != boolEnd; ++it)
boolsCopy.push_back(*it);
QCOMPARE(boolsCopy, bools);
}
QTEST_MAIN(tst_IndexedContainerProxyConstIterator)
#include "tst_indexedcontainerproxyconstiterator.moc"

View File

@@ -4,6 +4,7 @@ SUBDIRS = \
fileutils \ fileutils \
ansiescapecodehandler \ ansiescapecodehandler \
fuzzymatcher \ fuzzymatcher \
indexedcontainerproxyconstiterator \
persistentsettings \ persistentsettings \
qtcprocess \ qtcprocess \
settings \ settings \

View File

@@ -6,6 +6,7 @@ Project {
"fileutils/fileutils.qbs", "fileutils/fileutils.qbs",
"ansiescapecodehandler/ansiescapecodehandler.qbs", "ansiescapecodehandler/ansiescapecodehandler.qbs",
"fuzzymatcher/fuzzymatcher.qbs", "fuzzymatcher/fuzzymatcher.qbs",
"indexedcontainerproxyconstiterator/indexedcontainerproxyconstiterator.qbs",
"persistentsettings/persistentsettings.qbs", "persistentsettings/persistentsettings.qbs",
"qtcprocess/qtcprocess.qbs", "qtcprocess/qtcprocess.qbs",
"settings/settings.qbs", "settings/settings.qbs",