Merge remote-tracking branch 'origin/4.4'

Conflicts:
	src/plugins/projectexplorer/projectexplorer.cpp

Change-Id: I7881fc51021c49b792a384ad9f8a4f71fc457ce2
This commit is contained in:
Eike Ziller
2017-09-04 16:12:34 +02:00
29 changed files with 319 additions and 59 deletions

View File

@@ -72,10 +72,14 @@
\li \l{http://developer.android.com/sdk/index.html}{Android SDK Tools} \li \l{http://developer.android.com/sdk/index.html}{Android SDK Tools}
After installing the Tools, you can use the The following Android SDK packages and tools are required for
\l{https://developer.android.com/studio/command-line/sdkmanager.html} development:
{sdkmanager} to get the API and tools packages required for
development. \list
\li Platform tools
\li Build tools
\li At least one SDK platform
\endlist
\li On Windows, you also need the following: \li On Windows, you also need the following:
@@ -98,13 +102,33 @@
\section1 Setting Up the Development Environment \section1 Setting Up the Development Environment
You must download and install the latest Android NDK and SDK, and update the You must download and install the latest Android NDK and SDK, and then
SDK to get the build and platform tools needed for development. Since update or install the tools and packages needed for development. The SDK
SDK tools version 25.3.0, \QC, you must use the tool used to update and install the other SDK tools and packages depends on
\l{https://developer.android.com/studio/command-line/sdkmanager.html} the Android SDK Tools version that you have installed:
{sdkmanager} command line tool for SDK package management and the
\l{https://developer.android.com/studio/command-line/avdmanager.html} \list
{avdmanager} tool for Android Virtual Device (AVD) management.
\li Android SDK Tools version 25.2.5, or earlier
Use the
\l{https://developer.android.com/studio/tools/help/android.html}
{android} tool that comes with the SDK Tools package. For example,
on Ubuntu the following command starts the SDK update:
\code
./android update sdk
\endcode
\li Android SDK Tools version 25.3.0, or later
Use the
\l{https://developer.android.com/studio/command-line/sdkmanager.html}
{sdkmanager} command line tool for SDK package management and the
\l{https://developer.android.com/studio/command-line/avdmanager.html}
{avdmanager} tool for Android Virtual Device (AVD) management.
\endlist
In addition, you must install Qt for Android as part of Qt 5.2, or later. In addition, you must install Qt for Android as part of Qt 5.2, or later.

View File

@@ -1090,7 +1090,7 @@
size = value["_size"].integer() size = value["_size"].integer()
d.putItemCount(size) d.putItemCount(size)
if d.isExpanded(): if d.isExpanded():
d.putArrayData(value.type[0], value["_array"], size) d.putArrayData(value["_array"], size, value.type[0])
\endcode \endcode
\note To create dumper functions usable with both LLDB and GDB backends, \note To create dumper functions usable with both LLDB and GDB backends,
@@ -1211,7 +1211,7 @@
\endlist \endlist
\li \c{putArrayData(self, type, address, itemCount)} - Creates the \li \c{putArrayData(self, address, itemCount, type)} - Creates the
number of children specified by \c itemCount of the type \c type of number of children specified by \c itemCount of the type \c type of
an array-like object located at \c address. an array-like object located at \c address.

View File

@@ -32,7 +32,7 @@
\title Connecting iOS Devices \title Connecting iOS Devices
You can connect iOS devices to a Mac computer with a USB cable to You can connect iOS devices to your local machine with a USB cable to
run applications built for them from \QC. run applications built for them from \QC.
To be able to use \QC on \macos, you must install Xcode, and therefore, To be able to use \QC on \macos, you must install Xcode, and therefore,
@@ -52,7 +52,7 @@
{enroll in the Apple Developer Program}. The certificate is copied to {enroll in the Apple Developer Program}. The certificate is copied to
the device when you configure the device. the device when you configure the device.
The first time you connect the device to the Mac, you are asked to enable The first time you connect the device to your local machine, you are asked to enable
developer mode on the device. The next time you connect the device, \QC developer mode on the device. The next time you connect the device, \QC
detects it automatically. To disable automatic connections to a device that detects it automatically. To disable automatic connections to a device that
you do not use for development, select \uicontrol Preferences > you do not use for development, select \uicontrol Preferences >
@@ -69,7 +69,7 @@
\li Make sure that you have Xcode and Qt for iOS installed. \li Make sure that you have Xcode and Qt for iOS installed.
\li Connect the device to the Mac computer with a USB cable. \li Connect the device to your local machine with a USB cable.
\li Start Xcode to configure the device. \li Start Xcode to configure the device.
@@ -96,6 +96,11 @@
\image qtcreator-build-settings-ios.png "iOS build settings" \image qtcreator-build-settings-ios.png "iOS build settings"
\li Select the \uicontrol {Automatically manage signing} check box
to automatically select the provisioning profile and signing
certificate on your local machine that matches the entitlements
and the bundle identifier of the iOS device.
\endlist \endlist
\li Select \uicontrol Run to specify run settings. \li Select \uicontrol Run to specify run settings.
@@ -112,13 +117,13 @@
\note If you cannot deploy applications, because a provisioning profile is \note If you cannot deploy applications, because a provisioning profile is
missing, check that provisioning profiles are listed in Xcode by selecting missing, check that provisioning profiles are listed in Xcode by selecting
\uicontrol Xcode > \uicontrol Preferences > \uicontrol Accounts > \uicontrol Xcode > \uicontrol Preferences > \uicontrol Accounts. For more
\uicontrol {View Details}. For more information about how to acquire and information about how to acquire and install a provisioning profile, see
install a provisioning profile, see Apple documentation. Apple documentation.
\section1 Viewing Device Connection Status \section1 Viewing Device Connection Status
When you connect an iOS device to a Mac computer with USB, \QC When you connect an iOS device to your local machine with USB, \QC
automatically detects the device if you have configured it by using Xcode. automatically detects the device if you have configured it by using Xcode.
To view information about the connected device, select \uicontrol Preferences > To view information about the connected device, select \uicontrol Preferences >
\uicontrol Devices. \uicontrol Devices.
@@ -186,7 +191,7 @@
\li In the \uicontrol {Device type} field, select the device type from \li In the \uicontrol {Device type} field, select the device type from
a list of devices supported by the Xcode version set as current on a list of devices supported by the Xcode version set as current on
the Mac computer. your local machine.
\li In the \uicontrol {OS version} field, select an OS version from a \li In the \uicontrol {OS version} field, select an OS version from a
list of OS versions supported by the selected device and the current list of OS versions supported by the selected device and the current

View File

@@ -35,7 +35,7 @@ namespace Internal {
TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi, TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi,
QProcess *app) const QProcess *app) const
{ {
return new GTestOutputReader(fi, app, buildDirectory()); return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
} }
QStringList GTestConfiguration::argumentsForTestRunner() const QStringList GTestConfiguration::argumentsForTestRunner() const

View File

@@ -25,6 +25,8 @@
#include "gtestoutputreader.h" #include "gtestoutputreader.h"
#include "gtestresult.h" #include "gtestresult.h"
#include "../testtreemodel.h"
#include "../testtreeitem.h"
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
@@ -39,9 +41,11 @@ static QString constructSourceFilePath(const QString &path, const QString &fileP
} }
GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface, GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory) QProcess *testApplication, const QString &buildDirectory,
const QString &projectFile)
: TestOutputReader(futureInterface, testApplication, buildDirectory) : TestOutputReader(futureInterface, testApplication, buildDirectory)
, m_executable(testApplication ? testApplication->program() : QString()) , m_executable(testApplication ? testApplication->program() : QString())
, m_projectFile(projectFile)
{ {
} }
@@ -94,8 +98,9 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
m_futureInterface.reportResult(TestResultPtr(testResult)); m_futureInterface.reportResult(TestResultPtr(testResult));
m_currentTestName.clear(); m_currentTestName.clear();
m_currentTestSet.clear(); m_currentTestSet.clear();
m_normalizedCurrentTestSet.clear();
} else if (newTestStarts.exactMatch(line)) { } else if (newTestStarts.exactMatch(line)) {
m_currentTestName = newTestStarts.cap(1); setCurrentTestName(newTestStarts.cap(1));
TestResultPtr testResult = TestResultPtr(createDefaultResult()); TestResultPtr testResult = TestResultPtr(createDefaultResult());
testResult->setResult(Result::MessageTestCaseStart); testResult->setResult(Result::MessageTestCaseStart);
if (m_iteration > 1) { if (m_iteration > 1) {
@@ -106,7 +111,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
} }
m_futureInterface.reportResult(testResult); m_futureInterface.reportResult(testResult);
} else if (newTestSetStarts.exactMatch(line)) { } else if (newTestSetStarts.exactMatch(line)) {
m_currentTestSet = newTestSetStarts.cap(1); setCurrentTestSet(newTestSetStarts.cap(1));
TestResultPtr testResult = TestResultPtr(new GTestResult); TestResultPtr testResult = TestResultPtr(new GTestResult);
testResult->setResult(Result::MessageCurrentTest); testResult->setResult(Result::MessageCurrentTest);
testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet)); testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet));
@@ -155,13 +160,87 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
} }
} }
void GTestOutputReader::setCurrentTestSet(const QString &testSet)
{
m_currentTestSet = testSet;
m_normalizedCurrentTestSet = normalizeName(testSet);
}
void GTestOutputReader::setCurrentTestName(const QString &testName)
{
m_currentTestName = testName;
m_normalizedTestName = normalizeTestName(testName);
}
QString GTestOutputReader::normalizeName(const QString &name) const
{
static QRegExp parameterIndex("/\\d+");
QString nameWithoutParameterIndices = name;
nameWithoutParameterIndices.remove(parameterIndex);
return nameWithoutParameterIndices.split('/').last();
}
QString GTestOutputReader::normalizeTestName(const QString &testname) const
{
QString nameWithoutTypeParam = testname.split(',').first();
return normalizeName(nameWithoutTypeParam);
}
GTestResult *GTestOutputReader::createDefaultResult() const GTestResult *GTestOutputReader::createDefaultResult() const
{ {
GTestResult *result = new GTestResult(m_executable, m_currentTestName); GTestResult *result = new GTestResult(m_executable, m_currentTestName);
result->setTestSetName(m_currentTestSet); result->setTestSetName(m_currentTestSet);
result->setIteration(m_iteration); result->setIteration(m_iteration);
const TestTreeItem *testItem = findTestTreeItemForCurrentLine();
if (testItem && testItem->line()) {
result->setFileName(testItem->filePath());
result->setLine(static_cast<int>(testItem->line()));
}
return result; return result;
} }
const TestTreeItem *GTestOutputReader::findTestTreeItemForCurrentLine() const
{
const auto item = TestTreeModel::instance()->findNonRooItem([&](const Utils::TreeItem *item) {
const TestTreeItem &treeItem = static_cast<const TestTreeItem &>(*item);
return matches(treeItem);
});
return static_cast<const TestTreeItem *>(item);
}
bool GTestOutputReader::matches(const TestTreeItem &treeItem) const
{
if (treeItem.proFile() != m_projectFile)
return false;
if (m_currentTestSet.isEmpty())
return matchesTestCase(treeItem);
return matchesTestFunctionOrSet(treeItem);
}
bool GTestOutputReader::matchesTestFunctionOrSet(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestFunctionOrSet)
return false;
const QString testItemTestSet = treeItem.parentItem()->name() + '.' + treeItem.name();
return testItemTestSet == m_normalizedCurrentTestSet;
}
bool GTestOutputReader::matchesTestCase(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestCase)
return false;
return treeItem.name() == m_normalizedTestName;
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -33,6 +33,7 @@ namespace Autotest {
namespace Internal { namespace Internal {
class GTestResult; class GTestResult;
class TestTreeItem;
class GTestOutputReader : public TestOutputReader class GTestOutputReader : public TestOutputReader
{ {
@@ -40,16 +41,29 @@ class GTestOutputReader : public TestOutputReader
public: public:
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface, GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
QProcess *testApplication, const QString &buildDirectory); QProcess *testApplication, const QString &buildDirectory,
const QString &projectFile);
protected: protected:
void processOutput(const QByteArray &outputLine) override; void processOutput(const QByteArray &outputLine) override;
private: private:
void setCurrentTestSet(const QString &testSet);
void setCurrentTestName(const QString &testName);
QString normalizeName(const QString &name) const;
QString normalizeTestName(const QString &testname) const;
GTestResult *createDefaultResult() const; GTestResult *createDefaultResult() const;
const TestTreeItem *findTestTreeItemForCurrentLine() const;
bool matches(const TestTreeItem &treeItem) const;
bool matchesTestFunctionOrSet(const TestTreeItem &treeItem) const;
bool matchesTestCase(const TestTreeItem &treeItem) const;
QString m_executable; QString m_executable;
QString m_projectFile;
QString m_currentTestName; QString m_currentTestName;
QString m_normalizedTestName;
QString m_currentTestSet; QString m_currentTestSet;
QString m_normalizedCurrentTestSet;
QString m_description; QString m_description;
int m_iteration = 1; int m_iteration = 1;
}; };

View File

@@ -73,6 +73,7 @@ public:
QString executableFilePath() const; QString executableFilePath() const;
QString workingDirectory() const; QString workingDirectory() const;
QString buildDirectory() const { return m_buildDir; } QString buildDirectory() const { return m_buildDir; }
QString projectFile() const { return m_projectFile; }
QString displayName() const { return m_displayName; } QString displayName() const { return m_displayName; }
Utils::Environment environment() const { return m_environment; } Utils::Environment environment() const { return m_environment; }
ProjectExplorer::Project *project() const { return m_project.data(); } ProjectExplorer::Project *project() const { return m_project.data(); }

View File

@@ -36,6 +36,7 @@ ClangQueryExampleTextEditorWidget::ClangQueryExampleTextEditorWidget(QWidget *pa
{ {
m_syntaxHighlighter = new ClangQueryExampleHighlighter; m_syntaxHighlighter = new ClangQueryExampleHighlighter;
textDocument()->setSyntaxHighlighter(m_syntaxHighlighter); textDocument()->setSyntaxHighlighter(m_syntaxHighlighter);
textDocument()->setPlainText("class Foo {\n void function() { int local; }\n int field;\n};");
} }
ClangQueryExampleHighlighter *ClangQueryExampleTextEditorWidget::syntaxHighlighter() const ClangQueryExampleHighlighter *ClangQueryExampleTextEditorWidget::syntaxHighlighter() const

View File

@@ -6,14 +6,29 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1241</width> <width>512</width>
<height>471</height> <height>390</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>512</width>
<height>0</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@@ -30,20 +45,32 @@
<widget class="ClangRefactoring::ClangQueryExampleTextEditorWidget" name="exampleSourceTextEdit"> <widget class="ClangRefactoring::ClangQueryExampleTextEditorWidget" name="exampleSourceTextEdit">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>1</horstretch>
<verstretch>3</verstretch> <verstretch>3</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="placeholderText">
<string notr="true">class Foo { void function() { int x; } };</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="ClangRefactoring::ClangQueryTextEditorWidget" name="queryTextEdit"> <widget class="ClangRefactoring::ClangQueryTextEditorWidget" name="queryTextEdit">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>1</horstretch>
<verstretch>1</verstretch> <verstretch>1</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>700</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string notr="true">functionDecl()</string>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@@ -38,6 +38,7 @@ ClangQueryTextEditorWidget::ClangQueryTextEditorWidget(QWidget *parent)
m_hoverHandler(std::make_unique<ClangQueryHoverHandler>(m_syntaxHighlighter)) m_hoverHandler(std::make_unique<ClangQueryHoverHandler>(m_syntaxHighlighter))
{ {
textDocument()->setSyntaxHighlighter(m_syntaxHighlighter); textDocument()->setSyntaxHighlighter(m_syntaxHighlighter);
textDocument()->setPlainText("functionDecl()");
addHoverHandler(m_hoverHandler.get()); addHoverHandler(m_hoverHandler.get());
} }

View File

@@ -746,7 +746,8 @@ QList<ILocatorFilter *> LocatorWidget::filtersFor(const QString &text, QString &
break; break;
} }
const int whiteSpace = text.indexOf(QChar::Space, firstNonSpace); const int whiteSpace = text.indexOf(QChar::Space, firstNonSpace);
const QList<ILocatorFilter *> filters = Locator::filters(); const QList<ILocatorFilter *> filters = Utils::filtered(Locator::filters(),
&ILocatorFilter::isEnabled);
if (whiteSpace >= 0) { if (whiteSpace >= 0) {
const QString prefix = text.mid(firstNonSpace, whiteSpace - firstNonSpace).toLower(); const QString prefix = text.mid(firstNonSpace, whiteSpace - firstNonSpace).toLower();
QList<ILocatorFilter *> prefixFilters; QList<ILocatorFilter *> prefixFilters;

View File

@@ -31,6 +31,8 @@
#include "../projectnodes.h" #include "../projectnodes.h"
#include "../session.h" #include "../session.h"
#include "../projecttree.h"
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
@@ -125,10 +127,19 @@ void JsonSummaryPage::initializePage()
}); });
} }
Node *contextNode = m_wizard->value(QLatin1String(Constants::PREFERRED_PROJECT_NODE)) // Use static cast from void * to avoid qobject_cast (which needs a valid object) in value()
.value<Node *>(); // in the following code:
initializeProjectTree(contextNode, files, kind, auto contextNode = findWizardContextNode(static_cast<Node *>(m_wizard->value(Constants::PREFERRED_PROJECT_NODE).value<void *>()));
isProject ? AddSubProject : AddNewFile); const ProjectAction currentAction = isProject ? AddSubProject : AddNewFile;
initializeProjectTree(contextNode, files, kind, currentAction);
// Refresh combobox on project tree changes:
connect(ProjectTree::instance(), &ProjectTree::treeChanged,
this, [this, files, kind, currentAction]() {
initializeProjectTree(findWizardContextNode(currentNode()), files, kind, currentAction);
});
bool hideProjectUi = JsonWizard::boolFromVariant(m_hideProjectUiValue, m_wizard->expander()); bool hideProjectUi = JsonWizard::boolFromVariant(m_hideProjectUiValue, m_wizard->expander());
setProjectUiVisible(!hideProjectUi); setProjectUiVisible(!hideProjectUi);
@@ -207,6 +218,23 @@ void JsonSummaryPage::summarySettingsHaveChanged()
updateProjectData(currentNode()); updateProjectData(currentNode());
} }
Node *JsonSummaryPage::findWizardContextNode(Node *contextNode) const
{
if (contextNode && !ProjectTree::hasNode(contextNode)) {
contextNode = nullptr;
// Static cast from void * to avoid qobject_cast (which needs a valid object) in value().
auto project = static_cast<Project *>(m_wizard->value(Constants::PROJECT_POINTER).value<void *>());
if (SessionManager::projects().contains(project) && project->rootProjectNode()) {
const QString path = m_wizard->value(Constants::PREFERRED_PROJECT_NODE_PATH).toString();
contextNode = project->rootProjectNode()->findNode([path](const Node *n) {
return path == n->filePath().toString();
});
}
}
return contextNode;
}
void JsonSummaryPage::updateFileList() void JsonSummaryPage::updateFileList()
{ {
m_fileList = m_wizard->generateFileList(); m_fileList = m_wizard->generateFileList();

View File

@@ -33,6 +33,7 @@
namespace ProjectExplorer { namespace ProjectExplorer {
class FolderNode; class FolderNode;
class Node;
// Documentation inside. // Documentation inside.
class JsonSummaryPage : public Internal::ProjectWizardPage class JsonSummaryPage : public Internal::ProjectWizardPage
@@ -52,6 +53,7 @@ public:
void summarySettingsHaveChanged(); void summarySettingsHaveChanged();
private: private:
Node *findWizardContextNode(Node *contextNode) const;
void updateFileList(); void updateFileList();
void updateProjectData(FolderNode *node); void updateProjectData(FolderNode *node);

View File

@@ -3132,10 +3132,14 @@ void ProjectExplorerPluginPrivate::addNewFile()
QString location = directoryFor(currentNode); QString location = directoryFor(currentNode);
QVariantMap map; QVariantMap map;
map.insert(QLatin1String(Constants::PREFERRED_PROJECT_NODE), QVariant::fromValue(currentNode)); // store void pointer to avoid QVariant to use qobject_cast, which might core-dump when trying
if (ProjectTree::currentProject()) { // to access meta data on an object that get deleted in the meantime:
QList<Id> profileIds = Utils::transform(ProjectTree::currentProject()->targets(), &Target::id); map.insert(QLatin1String(Constants::PREFERRED_PROJECT_NODE), QVariant::fromValue(static_cast<void *>(currentNode)));
map.insert(Constants::PREFERRED_PROJECT_NODE_PATH, currentNode->filePath().toString());
if (Project *p = ProjectTree::currentProject()) {
QList<Id> profileIds = Utils::transform(p->targets(), &Target::id);
map.insert(QLatin1String(Constants::PROJECT_KIT_IDS), QVariant::fromValue(profileIds)); map.insert(QLatin1String(Constants::PROJECT_KIT_IDS), QVariant::fromValue(profileIds));
map.insert(Constants::PROJECT_POINTER, QVariant::fromValue(static_cast<void *>(p)));
} }
ICore::showNewItemDialog(tr("New File", "Title of dialog"), ICore::showNewItemDialog(tr("New File", "Title of dialog"),
Utils::filtered(IWizardFactory::allWizardFactories(), Utils::filtered(IWizardFactory::allWizardFactories(),
@@ -3204,7 +3208,8 @@ void ProjectExplorerPluginPrivate::addExistingDirectory()
void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStringList &filePaths) void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStringList &filePaths)
{ {
if (!folderNode) // can happen when project is not yet parsed // can happen when project is not yet parsed or finished parsing while the dialog was open:
if (!folderNode || !ProjectTree::hasNode(folderNode))
return; return;
const QString dir = directoryFor(folderNode); const QString dir = directoryFor(folderNode);

View File

@@ -127,6 +127,8 @@ const char IMPORT_WIZARD_CATEGORY_DISPLAY[] = QT_TRANSLATE_NOOP("ProjectExplorer
// Wizard extra values // Wizard extra values
const char PREFERRED_PROJECT_NODE[] = "ProjectExplorer.PreferredProjectNode"; const char PREFERRED_PROJECT_NODE[] = "ProjectExplorer.PreferredProjectNode";
const char PREFERRED_PROJECT_NODE_PATH[] = "ProjectExplorer.PreferredProjectPath";
const char PROJECT_POINTER[] = "ProjectExplorer.Project";
const char PROJECT_KIT_IDS[] = "ProjectExplorer.Profile.Ids"; const char PROJECT_KIT_IDS[] = "ProjectExplorer.Profile.Ids";
// Build step lists ids: // Build step lists ids:

View File

@@ -41,6 +41,7 @@
#include <texteditor/tabsettings.h> #include <texteditor/tabsettings.h>
#include <texteditor/storagesettings.h> #include <texteditor/storagesettings.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/editorconfiguration.h> #include <projectexplorer/editorconfiguration.h>
#include <utils/mimetypes/mimedatabase.h> #include <utils/mimetypes/mimedatabase.h>
# #
@@ -120,7 +121,8 @@ void ProjectFileWizardExtension::firstExtensionPageShown(
QStringList filePaths; QStringList filePaths;
ProjectAction projectAction; ProjectAction projectAction;
if (m_context->wizard->kind()== IWizardFactory::ProjectWizard) { const IWizardFactory::WizardKind kind = m_context->wizard->kind();
if (kind == IWizardFactory::ProjectWizard) {
projectAction = AddSubProject; projectAction = AddSubProject;
filePaths << generatedProjectFilePath(files); filePaths << generatedProjectFilePath(files);
} else { } else {
@@ -128,13 +130,38 @@ void ProjectFileWizardExtension::firstExtensionPageShown(
filePaths = Utils::transform(files, &GeneratedFile::path); filePaths = Utils::transform(files, &GeneratedFile::path);
} }
Node *contextNode = extraValues.value(QLatin1String(Constants::PREFERRED_PROJECT_NODE)).value<Node *>(); // Static cast from void * to avoid qobject_cast (which needs a valid object) in value().
auto contextNode = static_cast<Node *>(extraValues.value(QLatin1String(Constants::PREFERRED_PROJECT_NODE)).value<void *>());
auto project = static_cast<Project *>(extraValues.value(Constants::PROJECT_POINTER).value<void *>());
const QString path = extraValues.value(Constants::PREFERRED_PROJECT_NODE_PATH).toString();
m_context->page->initializeProjectTree(contextNode, filePaths, m_context->wizard->kind(), m_context->page->initializeProjectTree(findWizardContextNode(contextNode, project, path),
filePaths, m_context->wizard->kind(),
projectAction); projectAction);
// Refresh combobox on project tree changes:
connect(ProjectTree::instance(), &ProjectTree::treeChanged,
m_context->page, [this, project, path, filePaths, kind, projectAction]() {
m_context->page->initializeProjectTree(
findWizardContextNode(m_context->page->currentNode(), project, path), filePaths,
kind, projectAction);
});
m_context->page->initializeVersionControls(); m_context->page->initializeVersionControls();
} }
Node *ProjectFileWizardExtension::findWizardContextNode(Node *contextNode, Project *project,
const QString &path)
{
if (contextNode && !ProjectTree::hasNode(contextNode)) {
if (SessionManager::projects().contains(project) && project->rootProjectNode()) {
contextNode = project->rootProjectNode()->findNode([path](const Node *n) {
return path == n->filePath().toString();
});
}
}
return contextNode;
}
QList<QWizardPage *> ProjectFileWizardExtension::extensionPages(const IWizardFactory *wizard) QList<QWizardPage *> ProjectFileWizardExtension::extensionPages(const IWizardFactory *wizard)
{ {
if (!m_context) if (!m_context)

View File

@@ -31,6 +31,8 @@
namespace ProjectExplorer { namespace ProjectExplorer {
class FolderNode; class FolderNode;
class Node;
class Project;
namespace Internal { namespace Internal {
@@ -52,6 +54,7 @@ public slots:
void firstExtensionPageShown(const QList<Core::GeneratedFile> &files, const QVariantMap &extraValues) override; void firstExtensionPageShown(const QList<Core::GeneratedFile> &files, const QVariantMap &extraValues) override;
private: private:
Node *findWizardContextNode(Node *contextNode, Project *project, const QString &path);
bool processProject(const QList<Core::GeneratedFile> &files, bool processProject(const QList<Core::GeneratedFile> &files,
bool *removeOpenProjectAttribute, QString *errorMessage); bool *removeOpenProjectAttribute, QString *errorMessage);

View File

@@ -72,10 +72,15 @@ ProjectTree::ProjectTree(QObject *parent) : QObject(parent)
connect(SessionManager::instance(), &SessionManager::projectAdded, connect(SessionManager::instance(), &SessionManager::projectAdded,
this, &ProjectTree::sessionChanged); this, &ProjectTree::sessionChanged);
connect(SessionManager::instance(), &SessionManager::projectAdded,
this, &ProjectTree::treeChanged);
connect(SessionManager::instance(), &SessionManager::projectRemoved, connect(SessionManager::instance(), &SessionManager::projectRemoved,
this, &ProjectTree::sessionChanged); this, &ProjectTree::sessionChanged);
connect(SessionManager::instance(), &SessionManager::projectRemoved,
this, &ProjectTree::treeChanged);
connect(SessionManager::instance(), &SessionManager::startupProjectChanged, connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
this, &ProjectTree::sessionChanged); this, &ProjectTree::sessionChanged);
connect(this, &ProjectTree::subtreeChanged, this, &ProjectTree::treeChanged);
} }
ProjectTree::~ProjectTree() ProjectTree::~ProjectTree()
@@ -253,7 +258,8 @@ void ProjectTree::updateContext()
void ProjectTree::emitSubtreeChanged(FolderNode *node) void ProjectTree::emitSubtreeChanged(FolderNode *node)
{ {
emit s_instance->subtreeChanged(node); if (hasNode(node))
emit s_instance->subtreeChanged(node);
} }
void ProjectTree::collapseAll() void ProjectTree::collapseAll()
@@ -369,6 +375,13 @@ void ProjectTree::applyTreeManager(FolderNode *folder)
f(folder); f(folder);
} }
bool ProjectTree::hasNode(const Node *node)
{
return Utils::contains(SessionManager::projects(), [node](const Project *p) {
return p && p->rootProjectNode() && p->rootProjectNode()->findNode([node](const Node *n) { return n == node; });
});
}
void ProjectTree::hideContextMenu() void ProjectTree::hideContextMenu()
{ {
m_focusForContextMenu = nullptr; m_focusForContextMenu = nullptr;

View File

@@ -68,6 +68,8 @@ public:
static void registerTreeManager(const TreeManagerFunction &treeChange); static void registerTreeManager(const TreeManagerFunction &treeChange);
static void applyTreeManager(FolderNode *folder); static void applyTreeManager(FolderNode *folder);
static bool hasNode(const Node *node);
void collapseAll(); void collapseAll();
// for nodes to emit signals, do not call unless you are a node // for nodes to emit signals, do not call unless you are a node
@@ -83,6 +85,9 @@ signals:
void aboutToShowContextMenu(ProjectExplorer::Project *project, void aboutToShowContextMenu(ProjectExplorer::Project *project,
ProjectExplorer::Node *node); ProjectExplorer::Node *node);
// Emitted on any change to the tree
void treeChanged();
private: private:
void sessionChanged(); void sessionChanged();
void update(); void update();

View File

@@ -152,8 +152,8 @@ bool AbstractFormEditorTool::selectedItemCursorInMovableArea(const QPointF &pos)
QRectF boundingRect = boundingRectInSceneSpace.boundingRect(); QRectF boundingRect = boundingRectInSceneSpace.boundingRect();
QRectF innerRect = boundingRect; QRectF innerRect = boundingRect;
innerRect.adjust(10, 10, -10, -10); innerRect.adjust(2, 2, -2, -2);
boundingRect.adjust(-10, -20, 10, 10); boundingRect.adjust(-2, -20, 2, 2);
return !innerRect.contains(pos) && boundingRect.contains(pos); return !innerRect.contains(pos) && boundingRect.contains(pos);
} }

View File

@@ -224,14 +224,14 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
if (role == Qt::CheckStateRole) if (role == Qt::CheckStateRole)
return currentQmlObjectNode.isAliasExported() ? Qt::Checked : Qt::Unchecked; return currentQmlObjectNode.isAliasExported() ? Qt::Checked : Qt::Unchecked;
else if (role == Qt::ToolTipRole) else if (role == Qt::ToolTipRole)
return tr("Toggles the visibility of this item in the form editor.\n" return tr("Toggles whether this item is exported as an "
"This is independent of the visibility property in QML."); "alias property of the root item.");
} else if (index.column() == 2) { //visible } else if (index.column() == 2) { //visible
if (role == Qt::CheckStateRole) if (role == Qt::CheckStateRole)
return m_view->isNodeInvisible(modelNode) ? Qt::Unchecked : Qt::Checked; return m_view->isNodeInvisible(modelNode) ? Qt::Unchecked : Qt::Checked;
else if (role == Qt::ToolTipRole) else if (role == Qt::ToolTipRole)
return tr("Toggles whether this item is exported as an " return tr("Toggles the visibility of this item in the form editor.\n"
"alias property of the root item."); "This is independent of the visibility property in QML.");
} }
return QVariant(); return QVariant();

View File

@@ -792,7 +792,6 @@ static bool isBlacklistImport(const ImportKey &importKey)
|| importKey.libraryQualifiedPath() == QStringLiteral("Qt.WebSockets") || importKey.libraryQualifiedPath() == QStringLiteral("Qt.WebSockets")
|| importKey.libraryQualifiedPath() == QStringLiteral("QtWebkit") || importKey.libraryQualifiedPath() == QStringLiteral("QtWebkit")
|| importKey.libraryQualifiedPath() == QStringLiteral("QtLocation") || importKey.libraryQualifiedPath() == QStringLiteral("QtLocation")
|| importKey.libraryQualifiedPath() == QStringLiteral("QtWebEngine")
|| importKey.libraryQualifiedPath() == QStringLiteral("QtWebChannel") || importKey.libraryQualifiedPath() == QStringLiteral("QtWebChannel")
|| importKey.libraryQualifiedPath() == QStringLiteral("QtWinExtras") || importKey.libraryQualifiedPath() == QStringLiteral("QtWinExtras")
|| importKey.libraryQualifiedPath() == QStringLiteral("QtPurchasing") || importKey.libraryQualifiedPath() == QStringLiteral("QtPurchasing")

View File

@@ -92,8 +92,8 @@ void LocalQmlProfilerRunnerTest::testRunner()
runControl->initiateStart(); runControl->initiateStart();
QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 10000); QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 20000);
QTRY_VERIFY_WITH_TIMEOUT(!started, 10000); QTRY_VERIFY_WITH_TIMEOUT(!started, 20000);
QCOMPARE(stopCount, 1); QCOMPARE(stopCount, 1);
QCOMPARE(runCount, 0); QCOMPARE(runCount, 0);
@@ -113,8 +113,8 @@ void LocalQmlProfilerRunnerTest::testRunner()
connectRunner(); connectRunner();
runControl->initiateStart(); runControl->initiateStart();
QTRY_VERIFY_WITH_TIMEOUT(running, 10000); QTRY_VERIFY_WITH_TIMEOUT(running, 20000);
QTRY_VERIFY_WITH_TIMEOUT(!running, 10000); QTRY_VERIFY_WITH_TIMEOUT(!running, 20000);
QCOMPARE(startCount, 2); QCOMPARE(startCount, 2);
QCOMPARE(stopCount, 2); QCOMPARE(stopCount, 2);
QCOMPARE(runCount, 1); QCOMPARE(runCount, 1);
@@ -133,9 +133,9 @@ void LocalQmlProfilerRunnerTest::testRunner()
connectRunner(); connectRunner();
runControl->initiateStart(); runControl->initiateStart();
QTRY_VERIFY_WITH_TIMEOUT(running, 10000); QTRY_VERIFY_WITH_TIMEOUT(running, 20000);
runControl->initiateStop(); runControl->initiateStop();
QTRY_VERIFY_WITH_TIMEOUT(!running, 10000); QTRY_VERIFY_WITH_TIMEOUT(!running, 20000);
QCOMPARE(startCount, 3); QCOMPARE(startCount, 3);
QCOMPARE(stopCount, 3); QCOMPARE(stopCount, 3);
QCOMPARE(runCount, 2); QCOMPARE(runCount, 2);

View File

@@ -34,7 +34,10 @@
<description><![CDATA[Creating a Qt widget based application.]]></description> <description><![CDATA[Creating a Qt widget based application.]]></description>
<tags>qt creator,embedded,device creation</tags> <tags>qt creator,embedded,device creation</tags>
</tutorial> </tutorial>
<tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Getting Started with Qt for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=QFWPw4UWL9E" videoLength="8:30">
<description><![CDATA[Using Qt Creator to deploy applications to an embedded device.]]></description>
<tags>qt creator,embedded,device creation</tags>
</tutorial>
<tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt Quick Designer - The Coffee Machine" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3YPM_tStM" videoLength="3:06"> <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt Quick Designer - The Coffee Machine" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3YPM_tStM" videoLength="3:06">
<description><![CDATA[Creating a UI for embedded devices.]]></description> <description><![CDATA[Creating a UI for embedded devices.]]></description>
<tags>qt creator,qt quick,embedded</tags> <tags>qt creator,qt quick,embedded</tags>

View File

@@ -270,6 +270,7 @@ ResourceTopLevelNode::ResourceTopLevelNode(const FileName &filePath, bool genera
setIsGenerated(generated); setIsGenerated(generated);
setIcon(FileIconProvider::icon(filePath.toString())); setIcon(FileIconProvider::icon(filePath.toString()));
setPriority(Node::DefaultFilePriority); setPriority(Node::DefaultFilePriority);
setListInProject(true);
if (!filePath.isEmpty()) { if (!filePath.isEmpty()) {
QFileInfo fi = filePath.toFileInfo(); QFileInfo fi = filePath.toFileInfo();
if (fi.isFile() && fi.isReadable()) { if (fi.isFile() && fi.isReadable()) {

View File

@@ -72,4 +72,13 @@ QtcTool {
"savefile.cpp", "savefile.h" "savefile.cpp", "savefile.h"
] ]
} }
Group {
name: "Utils/macOS"
condition: qbs.targetOS.contains("macos")
prefix: libsDir + "/utils/"
files: [
"fileutils_mac.h",
"fileutils_mac.mm",
]
}
} }

View File

@@ -233,6 +233,16 @@ void tst_StringUtils::testParseUsedPortFromNetstatOutput_data()
// Linux // Linux
QTest::newRow("Linux1") << "sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt ..." << -1; QTest::newRow("Linux1") << "sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt ..." << -1;
QTest::newRow("Linux2") << "0: 00000000:2805 00000000:0000 0A 00000000:00000000 00:00000000 00000000 ..." << 10245; QTest::newRow("Linux2") << "0: 00000000:2805 00000000:0000 0A 00000000:00000000 00:00000000 00000000 ..." << 10245;
// Mac
QTest::newRow("Mac1") << "Active Internet connections (including servers)" << -1;
QTest::newRow("Mac2") << "Proto Recv-Q Send-Q Local Address Foreign Address (state)" << -1;
QTest::newRow("Mac3") << "tcp4 0 0 192.168.1.12.55687 88.198.14.66.443 ESTABLISHED" << 55687;
QTest::newRow("Mac4") << "tcp6 0 0 2a01:e34:ee42:d0.55684 2a02:26f0:ff::5c.443 ESTABLISHED" << 55684;
QTest::newRow("Mac5") << "tcp4 0 0 *.631 *.* LISTEN" << 631;
QTest::newRow("Mac6") << "tcp6 0 0 *.631 *.* LISTEN" << 631;
QTest::newRow("Mac7") << "udp4 0 0 192.168.79.1.123 *.*" << 123;
QTest::newRow("Mac9") << "udp4 0 0 192.168.8.1.123 *.*" << 123;
} }
QTEST_MAIN(tst_StringUtils) QTEST_MAIN(tst_StringUtils)

View File

@@ -380,13 +380,13 @@ def openDocument(treeElement):
except: except:
treeElement = addBranchWildcardToRoot(treeElement) treeElement = addBranchWildcardToRoot(treeElement)
item = waitForObjectItem(navigator, treeElement) item = waitForObjectItem(navigator, treeElement)
expected = str(item.text).split("/")[-1]
for _ in range(2): for _ in range(2):
# Expands items as needed what might make scrollbars appear. # Expands items as needed what might make scrollbars appear.
# These might cover the item to click. # These might cover the item to click.
# In this case, do it again to hit the item then. # In this case, do it again to hit the item then.
doubleClickItem(navigator, treeElement, 5, 5, 0, Qt.LeftButton) doubleClickItem(navigator, treeElement, 5, 5, 0, Qt.LeftButton)
mainWindow = waitForObject(":Qt Creator_Core::Internal::MainWindow") mainWindow = waitForObject(":Qt Creator_Core::Internal::MainWindow")
expected = str(item.text).split("/")[-1]
if waitFor("str(mainWindow.windowTitle).startswith(expected + ' ')", 5000): if waitFor("str(mainWindow.windowTitle).startswith(expected + ' ')", 5000):
return True return True
test.log("Expected file (%s) was not being opened in openDocument()" % expected) test.log("Expected file (%s) was not being opened in openDocument()" % expected)