forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/7.0'
Conflicts: src/plugins/webassembly/webassemblytoolchain.cpp Change-Id: Ia75c783e3ecab1f97de2b5c73a0979c49da82009
This commit is contained in:
@@ -479,7 +479,8 @@ bool checkParameters(const QSsh::SshConnectionParameters ¶ms)
|
||||
|
||||
void printSetupHelp()
|
||||
{
|
||||
qInfo() << "In order to run this test properly it requires some setup (example for fedora):\n"
|
||||
qInfo() << "\n\n"
|
||||
"In order to run this test properly it requires some setup (example for fedora):\n"
|
||||
"1. Run a server on the host to connect to:\n"
|
||||
" systemctl start sshd\n"
|
||||
"2. Create your own ssh key (needed only once). For fedora it needs ecdsa type:\n"
|
||||
|
||||
@@ -111,6 +111,7 @@ namespace Internal {
|
||||
void popupRequested(bool focus);
|
||||
void handleExpandCollapseToolButton(bool checked);
|
||||
void updateFilterButton();
|
||||
QList<QWidget *> toolBarWidgets();
|
||||
|
||||
SearchResultWindow *q;
|
||||
QList<Internal::SearchResultWidget *> m_searchResultWidgets;
|
||||
@@ -120,9 +121,9 @@ namespace Internal {
|
||||
QAction *m_expandCollapseAction;
|
||||
static const bool m_initiallyExpand;
|
||||
QWidget *m_spacer;
|
||||
QLabel *m_historyLabel;
|
||||
QLabel *m_historyLabel = nullptr;
|
||||
QWidget *m_spacer2;
|
||||
QComboBox *m_recentSearchesBox;
|
||||
QComboBox *m_recentSearchesBox = nullptr;
|
||||
QStackedWidget *m_widget;
|
||||
QList<SearchResult *> m_searchResults;
|
||||
int m_currentIndex;
|
||||
@@ -139,20 +140,13 @@ namespace Internal {
|
||||
m_expandCollapseButton(nullptr),
|
||||
m_expandCollapseAction(new QAction(tr("Expand All"), window)),
|
||||
m_spacer(new QWidget),
|
||||
m_historyLabel(new QLabel(tr("History:"))),
|
||||
m_spacer2(new QWidget),
|
||||
m_recentSearchesBox(new QComboBox),
|
||||
m_widget(new QStackedWidget),
|
||||
m_currentIndex(0),
|
||||
m_tabWidth(8)
|
||||
{
|
||||
m_spacer->setMinimumWidth(30);
|
||||
m_spacer2->setMinimumWidth(5);
|
||||
m_recentSearchesBox->setProperty("drawleftborder", true);
|
||||
m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
m_recentSearchesBox->addItem(tr("New Search"));
|
||||
connect(m_recentSearchesBox, QOverload<int>::of(&QComboBox::activated),
|
||||
this, &SearchResultWindowPrivate::setCurrentIndexWithFocus);
|
||||
|
||||
m_widget->setWindowTitle(q->displayName());
|
||||
|
||||
@@ -194,6 +188,7 @@ namespace Internal {
|
||||
|
||||
void SearchResultWindowPrivate::setCurrentIndex(int index, bool focus)
|
||||
{
|
||||
QTC_ASSERT(m_recentSearchesBox, return );
|
||||
if (isSearchVisible())
|
||||
m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(false);
|
||||
m_currentIndex = index;
|
||||
@@ -217,6 +212,7 @@ namespace Internal {
|
||||
|
||||
void SearchResultWindowPrivate::moveWidgetToTop()
|
||||
{
|
||||
QTC_ASSERT(m_recentSearchesBox, return );
|
||||
auto widget = qobject_cast<SearchResultWidget *>(sender());
|
||||
QTC_ASSERT(widget, return);
|
||||
const int index = m_searchResultWidgets.indexOf(widget);
|
||||
@@ -458,8 +454,7 @@ QWidget *SearchResultWindow::outputWidget(QWidget *)
|
||||
*/
|
||||
QList<QWidget*> SearchResultWindow::toolBarWidgets() const
|
||||
{
|
||||
return {d->m_expandCollapseButton, d->m_filterButton, d->m_newSearchButton, d->m_spacer,
|
||||
d->m_historyLabel, d->m_spacer2, d->m_recentSearchesBox};
|
||||
return d->toolBarWidgets();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -497,16 +492,19 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label,
|
||||
PreserveCaseMode preserveCaseMode,
|
||||
const QString &cfgGroup)
|
||||
{
|
||||
if (d->m_searchResults.size() >= MAX_SEARCH_HISTORY) {
|
||||
if (d->m_currentIndex >= d->m_recentSearchesBox->count() - 1) {
|
||||
// temporarily set the index to the last but one existing
|
||||
d->m_currentIndex = d->m_recentSearchesBox->count() - 2;
|
||||
if (QTC_GUARD(d->m_recentSearchesBox)) {
|
||||
if (d->m_searchResults.size() >= MAX_SEARCH_HISTORY) {
|
||||
if (d->m_currentIndex >= d->m_recentSearchesBox->count() - 1) {
|
||||
// temporarily set the index to the last but one existing
|
||||
d->m_currentIndex = d->m_recentSearchesBox->count() - 2;
|
||||
}
|
||||
d->m_searchResultWidgets.last()->notifyVisibilityChanged(false);
|
||||
// widget first, because that might send interesting signals to SearchResult
|
||||
delete d->m_searchResultWidgets.takeLast();
|
||||
delete d->m_searchResults.takeLast();
|
||||
d->m_recentSearchesBox->removeItem(d->m_recentSearchesBox->count() - 1);
|
||||
}
|
||||
d->m_searchResultWidgets.last()->notifyVisibilityChanged(false);
|
||||
// widget first, because that might send interesting signals to SearchResult
|
||||
delete d->m_searchResultWidgets.takeLast();
|
||||
delete d->m_searchResults.takeLast();
|
||||
d->m_recentSearchesBox->removeItem(d->m_recentSearchesBox->count()-1);
|
||||
d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm));
|
||||
}
|
||||
auto widget = new SearchResultWidget;
|
||||
connect(widget, &SearchResultWidget::filterInvalidated, this, [this, widget] {
|
||||
@@ -532,7 +530,6 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label,
|
||||
widget->setInfo(label, toolTip, searchTerm);
|
||||
auto result = new SearchResult(widget);
|
||||
d->m_searchResults.prepend(result);
|
||||
d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm));
|
||||
if (d->m_currentIndex > 0)
|
||||
++d->m_currentIndex; // so setCurrentIndex still knows about the right "currentIndex" and its widget
|
||||
d->setCurrentIndexWithFocus(1);
|
||||
@@ -544,8 +541,10 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label,
|
||||
*/
|
||||
void SearchResultWindow::clearContents()
|
||||
{
|
||||
for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i)
|
||||
d->m_recentSearchesBox->removeItem(i);
|
||||
if (QTC_GUARD(d->m_recentSearchesBox)) {
|
||||
for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i)
|
||||
d->m_recentSearchesBox->removeItem(i);
|
||||
}
|
||||
foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
|
||||
widget->notifyVisibilityChanged(false);
|
||||
qDeleteAll(d->m_searchResultWidgets);
|
||||
@@ -642,6 +641,29 @@ void SearchResultWindowPrivate::updateFilterButton()
|
||||
&& m_searchResultWidgets.at(visibleSearchIndex())->hasFilter());
|
||||
}
|
||||
|
||||
QList<QWidget *> SearchResultWindowPrivate::toolBarWidgets()
|
||||
{
|
||||
if (!m_historyLabel)
|
||||
m_historyLabel = new QLabel(tr("History:"));
|
||||
if (!m_recentSearchesBox) {
|
||||
m_recentSearchesBox = new QComboBox;
|
||||
m_recentSearchesBox->setProperty("drawleftborder", true);
|
||||
m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
m_recentSearchesBox->addItem(tr("New Search"));
|
||||
connect(m_recentSearchesBox,
|
||||
QOverload<int>::of(&QComboBox::activated),
|
||||
this,
|
||||
&SearchResultWindowPrivate::setCurrentIndexWithFocus);
|
||||
}
|
||||
return {m_expandCollapseButton,
|
||||
m_filterButton,
|
||||
m_newSearchButton,
|
||||
m_spacer,
|
||||
m_historyLabel,
|
||||
m_spacer2,
|
||||
m_recentSearchesBox};
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
|
||||
@@ -684,7 +684,7 @@ Toolchains KitDetectorPrivate::autoDetectToolChains()
|
||||
emit q->logOutput('\n' + tr("Searching toolchains..."));
|
||||
for (ToolChainFactory *factory : factories) {
|
||||
emit q->logOutput(tr("Searching toolchains of type %1").arg(factory->displayName()));
|
||||
const ToolchainDetector detector(alreadyKnown, m_device);
|
||||
const ToolchainDetector detector(alreadyKnown, m_device, m_searchPaths);
|
||||
const Toolchains newToolChains = factory->autoDetect(detector);
|
||||
for (ToolChain *toolChain : newToolChains) {
|
||||
emit q->logOutput(tr("Found \"%1\"").arg(toolChain->compilerCommand().toUserOutput()));
|
||||
@@ -1495,6 +1495,12 @@ QByteArray DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) cons
|
||||
QTC_ASSERT(m_shell && m_shell->isRunning(), return {});
|
||||
QMutexLocker l(&m_shellMutex);
|
||||
m_shell->readAllStandardOutput(); // clean possible left-overs
|
||||
const QByteArray oldError = m_shell->readAllStandardError(); // clean possible left-overs
|
||||
if (!oldError.isEmpty()) {
|
||||
LOG("Unexpected old stderr: " << oldError);
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
|
||||
const QByteArray markerWithNewLine("___QC_DOCKER_" + randomHex() + "_OUTPUT_MARKER___\n");
|
||||
m_shell->write(cmd.toUserOutput().toUtf8() + "\necho -n \"" + markerWithNewLine + "\"\n");
|
||||
QByteArray output;
|
||||
@@ -1506,6 +1512,11 @@ QByteArray DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) cons
|
||||
LOG("Run command in shell:" << cmd.toUserOutput() << "output size:" << output.size());
|
||||
if (QTC_GUARD(output.endsWith(markerWithNewLine)))
|
||||
output.chop(markerWithNewLine.size());
|
||||
const QByteArray currentError = m_shell->readAllStandardError();
|
||||
if (!currentError.isEmpty()) {
|
||||
LOG("Unexpected current stderr: " << currentError);
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -365,7 +365,7 @@ static ToolChain *iarToolChain(const FilePath &path, Id language)
|
||||
== BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
|
||||
});
|
||||
if (iarFactory) {
|
||||
Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}));
|
||||
Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}, {}));
|
||||
if (detected.isEmpty())
|
||||
detected = iarFactory->detectForImport({path, language});
|
||||
for (auto tc : detected) {
|
||||
|
||||
@@ -1090,10 +1090,11 @@ Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd)
|
||||
return {};
|
||||
}
|
||||
|
||||
static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
||||
static FilePaths findCompilerCandidates(const ToolchainDetector &detector,
|
||||
const QString &compilerName,
|
||||
bool detectVariants)
|
||||
{
|
||||
const IDevice::ConstPtr device = detector.device;
|
||||
const QFileInfo fi(compilerName);
|
||||
if (device.isNull() && fi.isAbsolute() && fi.isFile())
|
||||
return {FilePath::fromString(compilerName)};
|
||||
@@ -1119,7 +1120,9 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
||||
|
||||
if (!device.isNull()) {
|
||||
// FIXME: Merge with block below
|
||||
FilePaths searchPaths = device->systemEnvironment().path();
|
||||
FilePaths searchPaths = detector.searchPaths;
|
||||
if (searchPaths.isEmpty())
|
||||
searchPaths = device->systemEnvironment().path();
|
||||
for (const FilePath &deviceDir : qAsConst(searchPaths)) {
|
||||
static const QRegularExpression regexp(binaryRegexp);
|
||||
const auto callBack = [&compilerPaths, compilerName](const FilePath &candidate) {
|
||||
@@ -1135,16 +1138,19 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
||||
}
|
||||
} else {
|
||||
// The normal, local host case.
|
||||
FilePaths searchPaths = Environment::systemEnvironment().path();
|
||||
searchPaths << gnuSearchPathsFromRegistry();
|
||||
searchPaths << atmelSearchPathsFromRegistry();
|
||||
searchPaths << renesasRl78SearchPathsFromRegistry();
|
||||
if (HostOsInfo::isAnyUnixHost()) {
|
||||
FilePath ccachePath = "/usr/lib/ccache/bin";
|
||||
if (!ccachePath.exists())
|
||||
ccachePath = "/usr/lib/ccache";
|
||||
if (ccachePath.exists() && !searchPaths.contains(ccachePath))
|
||||
searchPaths << ccachePath;
|
||||
FilePaths searchPaths = detector.searchPaths;
|
||||
if (searchPaths.isEmpty()) {
|
||||
searchPaths = Environment::systemEnvironment().path();
|
||||
searchPaths << gnuSearchPathsFromRegistry();
|
||||
searchPaths << atmelSearchPathsFromRegistry();
|
||||
searchPaths << renesasRl78SearchPathsFromRegistry();
|
||||
if (HostOsInfo::isAnyUnixHost()) {
|
||||
FilePath ccachePath = "/usr/lib/ccache/bin";
|
||||
if (!ccachePath.exists())
|
||||
ccachePath = "/usr/lib/ccache";
|
||||
if (ccachePath.exists() && !searchPaths.contains(ccachePath))
|
||||
searchPaths << ccachePath;
|
||||
}
|
||||
}
|
||||
for (const FilePath &dir : qAsConst(searchPaths)) {
|
||||
static const QRegularExpression regexp(binaryRegexp);
|
||||
@@ -1173,7 +1179,7 @@ Toolchains GccToolChainFactory::autoDetectToolchains(
|
||||
const ToolchainChecker &checker) const
|
||||
{
|
||||
const FilePaths compilerPaths =
|
||||
findCompilerCandidates(detector.device, compilerName, detectVariants == DetectVariants::Yes);
|
||||
findCompilerCandidates(detector, compilerName, detectVariants == DetectVariants::Yes);
|
||||
Toolchains existingCandidates = filtered(detector.alreadyKnown,
|
||||
[language](const ToolChain *tc) { return tc->language() == language; });
|
||||
Toolchains result;
|
||||
@@ -1748,7 +1754,7 @@ Toolchains ClangToolChainFactory::autoDetect(const ToolchainDetector &detector)
|
||||
const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix();
|
||||
tcs.append(autoDetectToolchains(clang.toString(), DetectVariants::No,
|
||||
Constants::C_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||
ToolchainDetector(known, detector.device)));
|
||||
ToolchainDetector(known, detector.device, detector.searchPaths)));
|
||||
}
|
||||
|
||||
return tcs;
|
||||
|
||||
@@ -673,8 +673,10 @@ void ToolChainFactory::setUserCreatable(bool userCreatable)
|
||||
m_userCreatable = userCreatable;
|
||||
}
|
||||
|
||||
ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown, const IDevice::ConstPtr &device)
|
||||
: alreadyKnown(alreadyKnown), device(device)
|
||||
ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown,
|
||||
const IDevice::ConstPtr &device,
|
||||
const FilePaths &searchPaths)
|
||||
: alreadyKnown(alreadyKnown), device(device), searchPaths(searchPaths)
|
||||
{}
|
||||
|
||||
BadToolchain::BadToolchain(const Utils::FilePath &filePath)
|
||||
|
||||
@@ -250,13 +250,16 @@ public:
|
||||
class PROJECTEXPLORER_EXPORT ToolchainDetector
|
||||
{
|
||||
public:
|
||||
ToolchainDetector(const Toolchains &alreadyKnown, const IDevice::ConstPtr &device);
|
||||
ToolchainDetector(const Toolchains &alreadyKnown,
|
||||
const IDevice::ConstPtr &device,
|
||||
const Utils::FilePaths &searchPaths);
|
||||
|
||||
bool isBadToolchain(const Utils::FilePath &toolchain) const;
|
||||
void addBadToolchain(const Utils::FilePath &toolchain) const;
|
||||
|
||||
const Toolchains alreadyKnown;
|
||||
const IDevice::ConstPtr device;
|
||||
const Utils::FilePaths searchPaths; // If empty use device path and/or magic.
|
||||
};
|
||||
|
||||
class PROJECTEXPLORER_EXPORT ToolChainFactory
|
||||
|
||||
@@ -412,7 +412,7 @@ void ToolChainOptionsWidget::redetectToolchains()
|
||||
QSet<ToolChain *> toDelete;
|
||||
ToolChainManager::resetBadToolchains();
|
||||
for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
|
||||
const ToolchainDetector detector(knownTcs, {}); // FIXME: Pass device.
|
||||
const ToolchainDetector detector(knownTcs, {}, {}); // FIXME: Pass device and search paths
|
||||
for (ToolChain * const tc : f->autoDetect(detector)) {
|
||||
if (knownTcs.contains(tc) || toDelete.contains(tc))
|
||||
continue;
|
||||
|
||||
@@ -205,7 +205,7 @@ Toolchains ToolChainSettingsAccessor::restoreToolChains(QWidget *parent) const
|
||||
= Utils::filtered(userFileTcs, &ToolChain::isAutoDetected);
|
||||
// FIXME: Use real device?
|
||||
const Toolchains autodetectedTcs =
|
||||
autoDetectToolChains(ToolchainDetector(autodetectedUserFileTcs, {}));
|
||||
autoDetectToolChains(ToolchainDetector(autodetectedUserFileTcs, {}, {}));
|
||||
|
||||
// merge tool chains and register those that we need to keep:
|
||||
const ToolChainOperations ops = mergeToolChainLists(systemFileTcs, userFileTcs, autodetectedTcs);
|
||||
|
||||
@@ -213,34 +213,38 @@ void AssetsLibraryWidget::handleAddAsset()
|
||||
addResources({});
|
||||
}
|
||||
|
||||
void AssetsLibraryWidget::handleExtFilesDrop(const QStringList &filesPaths, const QString &targetDirPath)
|
||||
void AssetsLibraryWidget::handleExtFilesDrop(const QStringList &simpleFilesPaths,
|
||||
const QStringList &complexFilesPaths,
|
||||
const QString &targetDirPath)
|
||||
{
|
||||
QStringList assetPaths;
|
||||
QStringList otherPaths; // as of now 3D models, and 3D Studio presentations
|
||||
std::tie(assetPaths, otherPaths) = Utils::partition(filesPaths, [](const QString &path) {
|
||||
QString suffix = "*." + path.split('.').last().toLower();
|
||||
return AssetsLibraryModel::supportedSuffixes().contains(suffix);
|
||||
});
|
||||
|
||||
AddFilesResult result = ModelNodeOperations::addFilesToProject(assetPaths, targetDirPath);
|
||||
if (result == AddFilesResult::Failed) {
|
||||
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"),
|
||||
tr("Could not add %1 to project.")
|
||||
.arg(filesPaths.join(' ')));
|
||||
if (!simpleFilesPaths.isEmpty()) {
|
||||
if (targetDirPath.isEmpty()) {
|
||||
addResources(simpleFilesPaths);
|
||||
} else {
|
||||
AddFilesResult result = ModelNodeOperations::addFilesToProject(simpleFilesPaths,
|
||||
targetDirPath);
|
||||
if (result == AddFilesResult::Failed) {
|
||||
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"),
|
||||
tr("Could not add %1 to project.")
|
||||
.arg(simpleFilesPaths.join(' ')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!otherPaths.empty())
|
||||
addResources(otherPaths);
|
||||
if (!complexFilesPaths.empty())
|
||||
addResources(complexFilesPaths);
|
||||
}
|
||||
|
||||
QSet<QString> AssetsLibraryWidget::supportedDropSuffixes()
|
||||
QSet<QString> AssetsLibraryWidget::supportedAssetSuffixes(bool complex)
|
||||
{
|
||||
const QList<AddResourceHandler> handlers = QmlDesignerPlugin::instance()->viewManager()
|
||||
.designerActionManager().addResourceHandler();
|
||||
|
||||
QSet<QString> suffixes;
|
||||
for (const AddResourceHandler &handler : handlers)
|
||||
suffixes.insert(handler.filter);
|
||||
for (const AddResourceHandler &handler : handlers) {
|
||||
if (AssetsLibraryModel::supportedSuffixes().contains(handler.filter) != complex)
|
||||
suffixes.insert(handler.filter);
|
||||
}
|
||||
|
||||
return suffixes;
|
||||
}
|
||||
|
||||
@@ -80,8 +80,10 @@ public:
|
||||
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
|
||||
Q_INVOKABLE void handleAddAsset();
|
||||
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
||||
Q_INVOKABLE void handleExtFilesDrop(const QStringList &filesPaths, const QString &targetDirPath);
|
||||
Q_INVOKABLE QSet<QString> supportedDropSuffixes();
|
||||
Q_INVOKABLE void handleExtFilesDrop(const QStringList &simpleFilesPaths,
|
||||
const QStringList &complexFilesPaths,
|
||||
const QString &targetDirPath = {});
|
||||
Q_INVOKABLE QSet<QString> supportedAssetSuffixes(bool complex);
|
||||
|
||||
signals:
|
||||
void itemActivated(const QString &itemName);
|
||||
|
||||
@@ -360,9 +360,9 @@ void Edit3DView::createEdit3DActions()
|
||||
|
||||
m_showParticleEmitterAction = new Edit3DAction(
|
||||
QmlDesigner::Constants::EDIT3D_EDIT_SHOW_PARTICLE_EMITTER, View3DActionCommand::ShowParticleEmitter,
|
||||
QCoreApplication::translate("ShowParticleEmitterAction", "Always Show Particle Emitters"),
|
||||
QCoreApplication::translate("ShowParticleEmitterAction", "Always Show Particle Emitters And Attractors"),
|
||||
QKeySequence(Qt::Key_M), true, false, {}, {}, nullptr,
|
||||
QCoreApplication::translate("ShowParticleEmitterAction", "Toggle between always showing the particle emitter visualization and only showing it when the emitter is selected."));
|
||||
QCoreApplication::translate("ShowParticleEmitterAction", "Toggle between always showing the particle emitter and attractor visualizations and only showing them when the emitter or attractor is selected."));
|
||||
|
||||
SelectionContextOperation resetTrigger = [this](const SelectionContext &) {
|
||||
m_particlesPlayAction->action()->setEnabled(particlemode);
|
||||
|
||||
@@ -170,6 +170,8 @@ private: // functions
|
||||
|
||||
NodeInstance loadNode(const ModelNode &node);
|
||||
|
||||
void clearErrors();
|
||||
|
||||
void removeAllInstanceNodeRelationships();
|
||||
|
||||
void removeRecursiveChildRelationship(const ModelNode &removedNode);
|
||||
|
||||
@@ -326,10 +326,17 @@ void NodeInstanceView::endPuppetTransaction()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NodeInstanceView::clearErrors()
|
||||
{
|
||||
for (NodeInstance &instance : instances()) {
|
||||
instance.setError({});
|
||||
}
|
||||
}
|
||||
|
||||
void NodeInstanceView::restartProcess()
|
||||
{
|
||||
if (rootNodeInstance().isValid())
|
||||
rootNodeInstance().setError({});
|
||||
clearErrors();
|
||||
emitInstanceErrorChange({});
|
||||
emitDocumentMessage({}, {});
|
||||
|
||||
@@ -556,10 +563,11 @@ void NodeInstanceView::nodeReparented(const ModelNode &node, const NodeAbstractP
|
||||
m_nodeInstanceServer->reparentInstances(
|
||||
createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent));
|
||||
|
||||
// Reset puppet when particle emitter is reparented to work around issue in
|
||||
// Reset puppet when particle emitter/affector is reparented to work around issue in
|
||||
// autodetecting the particle system it belongs to. QTBUG-101157
|
||||
if (node.isSubclassOf("QtQuick.Particles3D.ParticleEmitter3D")
|
||||
&& node.property("system").toBindingProperty().expression().isEmpty()) {
|
||||
if ((node.isSubclassOf("QtQuick.Particles3D.ParticleEmitter3D")
|
||||
|| node.isSubclassOf("QtQuick.Particles3D.Affector3D"))
|
||||
&& node.property("system").toBindingProperty().expression().isEmpty()) {
|
||||
resetPuppet();
|
||||
}
|
||||
}
|
||||
@@ -957,6 +965,8 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
|
||||
}
|
||||
}
|
||||
|
||||
clearErrors();
|
||||
|
||||
nodeList = filterNodesForSkipItems(nodeList);
|
||||
|
||||
QList<VariantProperty> variantPropertyList;
|
||||
|
||||
@@ -767,12 +767,16 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
|
||||
const ObjectValue *objectValue = getObjectValue();
|
||||
if (objectValue) {
|
||||
const CppComponentValue *qmlValue = value_cast<CppComponentValue>(objectValue);
|
||||
|
||||
if (qmlValue) {
|
||||
if (m_majorVersion == -1 && m_minorVersion == -1) {
|
||||
m_majorVersion = qmlValue->componentVersion().majorVersion();
|
||||
m_minorVersion = qmlValue->componentVersion().minorVersion();
|
||||
m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + qmlValue->className().toUtf8();
|
||||
} else if (m_majorVersion == qmlValue->componentVersion().majorVersion() && m_minorVersion == qmlValue->componentVersion().minorVersion()) {
|
||||
m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.'
|
||||
+ qmlValue->className().toUtf8();
|
||||
|
||||
} else if (m_majorVersion == qmlValue->componentVersion().majorVersion()
|
||||
&& m_minorVersion == qmlValue->componentVersion().minorVersion()) {
|
||||
m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + qmlValue->className().toUtf8();
|
||||
} else {
|
||||
return;
|
||||
@@ -780,10 +784,16 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
|
||||
} else {
|
||||
m_isFileComponent = true;
|
||||
const Imports *imports = context()->imports(document());
|
||||
ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data());
|
||||
if (importInfo.isValid() && importInfo.type() == ImportType::Library) {
|
||||
m_majorVersion = importInfo.version().majorVersion();
|
||||
m_minorVersion = importInfo.version().minorVersion();
|
||||
const ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data());
|
||||
if (importInfo.isValid()) {
|
||||
if (importInfo.type() == ImportType::Library) {
|
||||
m_majorVersion = importInfo.version().majorVersion();
|
||||
m_minorVersion = importInfo.version().minorVersion();
|
||||
}
|
||||
bool prepandName = (importInfo.type() == ImportType::Library || importInfo.type() == ImportType::Directory)
|
||||
&& !m_qualfiedTypeName.contains('.');
|
||||
if (prepandName)
|
||||
m_qualfiedTypeName.prepend(importInfo.name().toUtf8() + '.');
|
||||
}
|
||||
}
|
||||
m_objectValue = objectValue;
|
||||
|
||||
@@ -260,7 +260,9 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings)
|
||||
#else
|
||||
const auto showDebugSettings = settings.value(DesignerSettingsKey::SHOW_DEBUG_SETTINGS).toBool();
|
||||
#endif
|
||||
m_ui.debugGroupBox->setVisible(!standaloneMode || showDebugSettings);
|
||||
const bool showAdvancedFeatures = !standaloneMode || showDebugSettings;
|
||||
m_ui.emulationGroupBox->setVisible(showAdvancedFeatures);
|
||||
m_ui.debugGroupBox->setVisible(showAdvancedFeatures);
|
||||
m_ui.featureTimelineEditorCheckBox->setVisible(standaloneMode);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,11 @@ void FileSystemAccessTest::initTestCase()
|
||||
QVERIFY(!newDev.isNull());
|
||||
devMgr->addDevice(newDev);
|
||||
}
|
||||
if (filePath.exists()) // Do initial cleanup after possible leftovers from previously failed test
|
||||
QVERIFY(filePath.removeRecursively());
|
||||
QVERIFY(!filePath.exists());
|
||||
QVERIFY(filePath.createDir());
|
||||
QVERIFY(filePath.exists());
|
||||
}
|
||||
|
||||
void FileSystemAccessTest::cleanupTestCase()
|
||||
@@ -106,7 +110,43 @@ void FileSystemAccessTest::cleanupTestCase()
|
||||
QVERIFY(baseFilePath().removeRecursively());
|
||||
}
|
||||
|
||||
void FileSystemAccessTest::testDirStatuses()
|
||||
void FileSystemAccessTest::testCreateRemoteFile_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("data");
|
||||
|
||||
QTest::newRow("Spaces") << QByteArray("Line with spaces");
|
||||
QTest::newRow("Newlines") << QByteArray("Some \n\n newlines \n");
|
||||
QTest::newRow("Carriage return") << QByteArray("Line with carriage \r return");
|
||||
QTest::newRow("Tab") << QByteArray("Line with \t tab");
|
||||
QTest::newRow("Apostrophe") << QByteArray("Line with apostrophe's character");
|
||||
QTest::newRow("Quotation marks") << QByteArray("Line with \"quotation marks\"");
|
||||
QTest::newRow("Backslash 1") << QByteArray("Line with \\ backslash");
|
||||
QTest::newRow("Backslash 2") << QByteArray("Line with \\\" backslash");
|
||||
QTest::newRow("Command output") << QByteArray("The date is: $(date +%D)");
|
||||
|
||||
const int charSize = sizeof(char) * 0x100;
|
||||
QByteArray charString(charSize, Qt::Uninitialized);
|
||||
char *data = charString.data();
|
||||
for (int c = 0; c < charSize; ++c)
|
||||
data[c] = c;
|
||||
QTest::newRow("All Characters") << charString;
|
||||
}
|
||||
|
||||
void FileSystemAccessTest::testCreateRemoteFile()
|
||||
{
|
||||
QFETCH(QByteArray, data);
|
||||
|
||||
const FilePath testFilePath = baseFilePath() / "test_file";
|
||||
|
||||
QVERIFY(!testFilePath.exists());
|
||||
QVERIFY(testFilePath.writeFileContents(data));
|
||||
QVERIFY(testFilePath.exists());
|
||||
QCOMPARE(testFilePath.fileContents(), data);
|
||||
QVERIFY(testFilePath.removeFile());
|
||||
QVERIFY(!testFilePath.exists());
|
||||
}
|
||||
|
||||
void FileSystemAccessTest::testDirStatus()
|
||||
{
|
||||
FilePath filePath = baseFilePath();
|
||||
QVERIFY(filePath.exists());
|
||||
@@ -142,7 +182,7 @@ void FileSystemAccessTest::testBytesAvailable()
|
||||
|
||||
void FileSystemAccessTest::testFileActions()
|
||||
{
|
||||
FilePath testFilePath = createFile("test");
|
||||
const FilePath testFilePath = createFile("test");
|
||||
QVERIFY(testFilePath.exists());
|
||||
QVERIFY(testFilePath.isFile());
|
||||
|
||||
@@ -153,15 +193,17 @@ void FileSystemAccessTest::testFileActions()
|
||||
QVERIFY(testFilePath.isReadableFile());
|
||||
QVERIFY(testFilePath.isExecutableFile());
|
||||
|
||||
QByteArray content("Test");
|
||||
const QByteArray content("Test");
|
||||
testFilePath.writeFileContents(content);
|
||||
// ToDo: remove ".contains", make fileContents exact equal content
|
||||
QVERIFY(testFilePath.fileContents().contains(content));
|
||||
QCOMPARE(testFilePath.fileContents(), content);
|
||||
|
||||
QVERIFY(testFilePath.renameFile(baseFilePath() / "test1"));
|
||||
const FilePath newTestFilePath = baseFilePath() / "test1";
|
||||
// It is Ok that FilePath doesn't change itself after rename.
|
||||
FilePath newTestFilePath = baseFilePath() / "test1";
|
||||
// FilePath::renameFile() is a const method!
|
||||
QVERIFY(testFilePath.renameFile(newTestFilePath));
|
||||
QVERIFY(!testFilePath.exists());
|
||||
QVERIFY(newTestFilePath.exists());
|
||||
QCOMPARE(newTestFilePath.fileContents(), content);
|
||||
QVERIFY(!testFilePath.removeFile());
|
||||
QVERIFY(newTestFilePath.exists());
|
||||
QVERIFY(newTestFilePath.removeFile());
|
||||
|
||||
@@ -45,12 +45,15 @@ class FileSystemAccessTest : public QObject
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
|
||||
void testDirStatuses();
|
||||
void testCreateRemoteFile_data();
|
||||
void testCreateRemoteFile();
|
||||
void testDirStatus();
|
||||
void testBytesAvailable();
|
||||
void testFileActions();
|
||||
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
TestLinuxDeviceFactory m_testLinuxDeviceFactory;
|
||||
bool m_skippedAtWhole = false;
|
||||
|
||||
@@ -232,11 +232,14 @@ public:
|
||||
bool runInShell(const CommandLine &cmd, const QByteArray &data = {})
|
||||
{
|
||||
QTC_ASSERT(m_shell, return false);
|
||||
const QByteArray prefix = !data.isEmpty() ? QByteArray("echo " + data + " | ")
|
||||
: QByteArray("");
|
||||
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
||||
|
||||
m_shell->readAllStandardOutput(); // clean possible left-overs
|
||||
m_shell->write(prefix + cmd.toUserOutput().toUtf8() + "\necho $?\n");
|
||||
const QByteArray prefix = !data.isEmpty()
|
||||
? QByteArray("echo '" + data.toBase64() + "' | base64 -d | ") : QByteArray("");
|
||||
const QByteArray suffix = QByteArray(" > /dev/null 2>&1\necho $?\n");
|
||||
const QByteArray command = prefix + cmd.toUserOutput().toUtf8() + suffix;
|
||||
|
||||
m_shell->write(command);
|
||||
DEBUG("RUN1 " << cmd.toUserOutput());
|
||||
m_shell->waitForReadyRead();
|
||||
const QByteArray output = m_shell->readAllStandardOutput();
|
||||
@@ -244,18 +247,19 @@ public:
|
||||
bool ok = false;
|
||||
const int result = output.toInt(&ok);
|
||||
LOG("Run command in shell:" << cmd.toUserOutput() << "result: " << output << " ==>" << result);
|
||||
return ok && result == 0;
|
||||
QTC_ASSERT(ok, return false);
|
||||
return !result;
|
||||
}
|
||||
|
||||
QByteArray outputForRunInShell(const QString &cmd)
|
||||
{
|
||||
QTC_ASSERT(m_shell, return {});
|
||||
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
||||
|
||||
static int val = 0;
|
||||
const QByteArray delim = QString::number(++val, 16).toUtf8();
|
||||
|
||||
DEBUG("RUN2 " << cmd);
|
||||
m_shell->readAllStandardOutput(); // clean possible left-overs
|
||||
const QByteArray marker = "___QTC___" + delim + "_OUTPUT_MARKER___";
|
||||
DEBUG(" CMD: " << cmd.toUtf8() + "\necho " + marker + "\n");
|
||||
m_shell->write(cmd.toUtf8() + "\necho " + marker + "\n");
|
||||
@@ -342,11 +346,9 @@ LinuxDevice::LinuxDevice()
|
||||
proc->start();
|
||||
});
|
||||
|
||||
if (Utils::HostOsInfo::isAnyUnixHost()) {
|
||||
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
|
||||
device->openTerminal(Environment(), FilePath());
|
||||
}});
|
||||
}
|
||||
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
|
||||
device->openTerminal(Environment(), FilePath());
|
||||
}});
|
||||
}
|
||||
|
||||
LinuxDevice::~LinuxDevice()
|
||||
@@ -734,9 +736,6 @@ QByteArray LinuxDevice::fileContents(const FilePath &filePath, qint64 limit, qin
|
||||
bool LinuxDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const
|
||||
{
|
||||
QTC_ASSERT(handlesFile(filePath), return {});
|
||||
|
||||
// This following would be the generic Unix solution.
|
||||
// But it doesn't pass input. FIXME: Why?
|
||||
return d->runInShell({"dd", {"of=" + filePath.path()}}, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ void WebAssemblyToolChain::registerToolChains()
|
||||
};
|
||||
|
||||
// Create new toolchains and register them
|
||||
ToolchainDetector detector({}, {});
|
||||
ToolchainDetector detector({}, {}, {});
|
||||
const Toolchains toolchains = doAutoDetect(detector);
|
||||
for (auto toolChain : toolchains)
|
||||
ToolChainManager::registerToolChain(toolChain);
|
||||
|
||||
Reference in New Issue
Block a user