Merge "Merge remote-tracking branch 'origin/4.3'"

This commit is contained in:
Eike Ziller
2017-05-15 13:32:48 +00:00
committed by The Qt Project
39 changed files with 168 additions and 88 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -504,20 +504,32 @@
\section2 To-Do Entries \section2 To-Do Entries
The \uicontrol {To-Do Entries} pane lists the BUG, FIXME, NOTE, TODO, and The \uicontrol {To-Do Entries} pane lists the BUG, FIXME, NOTE, TODO, and
WARNING keywords from the current file or from all project files. The WARNING keywords from the current file, from all project files, or from a
keywords are organized into information, warning, and error categories. subproject. Click the icons on the toolbar to show only the selected
keywords.
\image qtcreator-todo-pane.png \image qtcreator-todo-pane.png
To add keywords, select \uicontrol Tools > \uicontrol Options > To add keywords, select \uicontrol Tools > \uicontrol Options >
\uicontrol {To-Do} > \uicontrol Add. \uicontrol {To-Do} > \uicontrol Add. Set an icon and a line background color
Set an icon and a line background color for the keyword. To change the icons for the keyword.
and colors set for an existing keyword, select \uicontrol Edit.
To determine whether the keywords in the whole project or in the current \image qtcreator-todo-options.png
file are displayed by default, select \uicontrol {Scanning scope}.
To exclude files from scanning, select \uicontrol {To-Do} in the To change the icon and line background color of the selected keyword, select
\uicontrol Edit.
To remove the selected keyword, select \uicontrol Remove.
To reset the list to predefined keywords, select \uicontrol Reset. All your
changes will be permanently lost.
To determine whether the keywords in the whole project, in the current file,
or in a subproject are displayed by default, select the appropriate option
in the \uicontrol {Scanning scope} group.
To exclude files from scanning, select \uicontrol {Project Settings} >
\uicontrol {To-Do} in the
\uicontrol Projects mode. Select \uicontrol Add and enter a regular \uicontrol Projects mode. Select \uicontrol Add and enter a regular
expression that matches the path to files to exclude. Use a forward slash expression that matches the path to files to exclude. Use a forward slash
(/) as a separator in the path also on Windows. (/) as a separator in the path also on Windows.

View File

@@ -1320,12 +1320,12 @@ class DumperBase:
derefValue.name = '*' derefValue.name = '*'
self.putItem(derefValue) self.putItem(derefValue)
self.currentChildType = savedCurrentChildType self.currentChildType = savedCurrentChildType
self.putAddress(value.address())
def putFormattedPointerX(self, value): def putFormattedPointerX(self, value):
self.putOriginalAddress(value.address()) self.putOriginalAddress(value.address())
#warn("PUT FORMATTED: %s" % value) #warn("PUT FORMATTED: %s" % value)
pointer = value.pointer() pointer = value.pointer()
self.putAddress(pointer)
#warn('POINTER: 0x%x' % pointer) #warn('POINTER: 0x%x' % pointer)
if pointer == 0: if pointer == 0:
#warn('NULL POINTER') #warn('NULL POINTER')

0
share/qtcreator/translations/qtcreator_da.ts Executable file → Normal file
View File

View File

@@ -280,6 +280,9 @@ void loadFonts()
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if (Utils::HostOsInfo::isLinuxHost())
QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/QtCreator-XXXXXX"); Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/QtCreator-XXXXXX");
const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable(); const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable();

View File

@@ -99,7 +99,7 @@ static bool isQtReservedWord(const char *name, int size)
size -= 2; size -= 2;
switch (size) { switch (size) {
case 1: case 1:
return name[2] == 'D' || name[2] == 'Q'; return name[0] == 'D' || name[0] == 'Q';
case 4: case 4:
return same(name, "SLOT", size) || same(name, "EMIT", size); return same(name, "SLOT", size) || same(name, "EMIT", size);
case 5: case 5:

View File

@@ -25,13 +25,19 @@
#include "temporarydirectory.h" #include "temporarydirectory.h"
#include "qtcassert.h" #include <QtCore/QCoreApplication>
#include <memory> #include "qtcassert.h"
namespace Utils { namespace Utils {
static std::unique_ptr<QTemporaryDir> m_masterTemporaryDir; static QTemporaryDir* m_masterTemporaryDir = nullptr;
static void cleanupMasterTemporaryDir()
{
delete m_masterTemporaryDir;
m_masterTemporaryDir = nullptr;
}
TemporaryDirectory::TemporaryDirectory(const QString &pattern) : TemporaryDirectory::TemporaryDirectory(const QString &pattern) :
QTemporaryDir(m_masterTemporaryDir->path() + '/' + pattern) QTemporaryDir(m_masterTemporaryDir->path() + '/' + pattern)
@@ -41,12 +47,16 @@ TemporaryDirectory::TemporaryDirectory(const QString &pattern) :
QTemporaryDir *TemporaryDirectory::masterTemporaryDirectory() QTemporaryDir *TemporaryDirectory::masterTemporaryDirectory()
{ {
return m_masterTemporaryDir.get(); return m_masterTemporaryDir;
} }
void TemporaryDirectory::setMasterTemporaryDirectory(const QString &pattern) void TemporaryDirectory::setMasterTemporaryDirectory(const QString &pattern)
{ {
m_masterTemporaryDir = std::make_unique<QTemporaryDir>(pattern); if (m_masterTemporaryDir)
cleanupMasterTemporaryDir();
else
qAddPostRoutine(cleanupMasterTemporaryDir);
m_masterTemporaryDir = new QTemporaryDir(pattern);
} }
QString TemporaryDirectory::masterDirectoryPath() QString TemporaryDirectory::masterDirectoryPath()

View File

@@ -33,7 +33,7 @@ namespace Utils {
// Documentation inside. // Documentation inside.
class QTCREATOR_UTILS_EXPORT TextFieldCheckBox : public QCheckBox { class QTCREATOR_UTILS_EXPORT TextFieldCheckBox : public QCheckBox {
Q_PROPERTY(QString text READ text WRITE setText) Q_PROPERTY(QString compareText READ text WRITE setText)
Q_PROPERTY(QString trueText READ trueText WRITE setTrueText) Q_PROPERTY(QString trueText READ trueText WRITE setTrueText)
Q_PROPERTY(QString falseText READ falseText WRITE setFalseText) Q_PROPERTY(QString falseText READ falseText WRITE setFalseText)
Q_OBJECT Q_OBJECT

View File

@@ -33,7 +33,7 @@ namespace Utils {
// Documentation inside. // Documentation inside.
class QTCREATOR_UTILS_EXPORT TextFieldComboBox : public QComboBox { class QTCREATOR_UTILS_EXPORT TextFieldComboBox : public QComboBox {
Q_PROPERTY(QString text READ text WRITE setText) Q_PROPERTY(QString indexText READ text WRITE setText)
Q_OBJECT Q_OBJECT
public: public:
explicit TextFieldComboBox(QWidget *parent = 0); explicit TextFieldComboBox(QWidget *parent = 0);

View File

@@ -55,6 +55,8 @@ static Q_LOGGING_CATEGORY(LOG, "qtc.autotest.testcodeparser")
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
using namespace ProjectExplorer;
TestCodeParser::TestCodeParser(TestTreeModel *parent) TestCodeParser::TestCodeParser(TestTreeModel *parent)
: QObject(parent), : QObject(parent),
m_model(parent) m_model(parent)
@@ -100,7 +102,7 @@ void TestCodeParser::setState(State state)
} }
m_parserState = state; m_parserState = state;
if (m_parserState == Idle && ProjectExplorer::SessionManager::startupProject()) { if (m_parserState == Idle && SessionManager::startupProject()) {
if (m_fullUpdatePostponed || m_dirty) { if (m_fullUpdatePostponed || m_dirty) {
emitUpdateTestTree(); emitUpdateTestTree();
} else if (m_partialUpdatePostponed) { } else if (m_partialUpdatePostponed) {
@@ -160,7 +162,7 @@ void TestCodeParser::updateTestTree(ITestParser *parser)
return; return;
} }
if (!ProjectExplorer::SessionManager::startupProject()) if (!SessionManager::startupProject())
return; return;
m_fullUpdatePostponed = false; m_fullUpdatePostponed = false;
@@ -201,10 +203,10 @@ void TestCodeParser::onDocumentUpdated(const QString &fileName)
if (m_codeModelParsing || m_fullUpdatePostponed) if (m_codeModelParsing || m_fullUpdatePostponed)
return; return;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); Project *project = SessionManager::startupProject();
if (!project) if (!project)
return; return;
if (!project->files(ProjectExplorer::Project::SourceFiles).contains(fileName)) if (!SessionManager::projectContainsFile(project, Utils::FileName::fromString(fileName)))
return; return;
scanForTests(QStringList(fileName)); scanForTests(QStringList(fileName));
@@ -222,7 +224,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document)
onDocumentUpdated(fileName); onDocumentUpdated(fileName);
} }
void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *project) void TestCodeParser::onStartupProjectChanged(Project *project)
{ {
if (m_parserState == FullParse || m_parserState == PartialParse) { if (m_parserState == FullParse || m_parserState == PartialParse) {
qCDebug(LOG) << "Canceling scanForTest (startup project changed)"; qCDebug(LOG) << "Canceling scanForTest (startup project changed)";
@@ -233,9 +235,9 @@ void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *project)
emitUpdateTestTree(); emitUpdateTestTree();
} }
void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) void TestCodeParser::onProjectPartsUpdated(Project *project)
{ {
if (project != ProjectExplorer::SessionManager::startupProject()) if (project != SessionManager::startupProject())
return; return;
if (m_codeModelParsing) if (m_codeModelParsing)
m_fullUpdatePostponed = true; m_fullUpdatePostponed = true;
@@ -334,12 +336,12 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars
m_reparseTimerTimedOut = false; m_reparseTimerTimedOut = false;
m_postponedFiles.clear(); m_postponedFiles.clear();
bool isFullParse = fileList.isEmpty(); bool isFullParse = fileList.isEmpty();
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); Project *project = SessionManager::startupProject();
if (!project) if (!project)
return; return;
QStringList list; QStringList list;
if (isFullParse) { if (isFullParse) {
list = project->files(ProjectExplorer::Project::SourceFiles); list = project->files(Project::SourceFiles);
if (list.isEmpty()) { if (list.isEmpty()) {
// at least project file should be there, but might happen if parsing current project // at least project file should be there, but might happen if parsing current project
// takes too long, especially when opening sessions holding multiple projects // takes too long, especially when opening sessions holding multiple projects

View File

@@ -401,7 +401,8 @@ void ServerModeReader::handleProgress(int min, int cur, int max, const QString &
void ServerModeReader::handleSignal(const QString &signal, const QVariantMap &data) void ServerModeReader::handleSignal(const QString &signal, const QVariantMap &data)
{ {
Q_UNUSED(data); Q_UNUSED(data);
if (signal == "dirty") // CMake on Windows sends false dirty signals on each edit (QTCREATORBUG-17944)
if (!HostOsInfo::isWindowsHost() && signal == "dirty")
emit dirty(); emit dirty();
} }
@@ -706,14 +707,15 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
} }
// Split up files in groups (based on location): // Split up files in groups (based on location):
const bool inSourceBuild = (m_parameters.buildDirectory == m_parameters.sourceDirectory);
QList<FileNode *> sourceFileNodes; QList<FileNode *> sourceFileNodes;
QList<FileNode *> buildFileNodes; QList<FileNode *> buildFileNodes;
QList<FileNode *> otherFileNodes; QList<FileNode *> otherFileNodes;
foreach (FileNode *fn, toList) { foreach (FileNode *fn, toList) {
if (fn->filePath().isChildOf(m_parameters.sourceDirectory)) if (fn->filePath().isChildOf(m_parameters.buildDirectory) && !inSourceBuild)
sourceFileNodes.append(fn);
else if (fn->filePath().isChildOf(m_parameters.buildDirectory))
buildFileNodes.append(fn); buildFileNodes.append(fn);
else if (fn->filePath().isChildOf(m_parameters.sourceDirectory))
sourceFileNodes.append(fn);
else else
otherFileNodes.append(fn); otherFileNodes.append(fn);
} }

View File

@@ -34,8 +34,8 @@
#include <QJsonValue> #include <QJsonValue>
#include <QJsonObject> #include <QJsonObject>
static const char urlC[] = "http://pastebin.ca/"; static const char urlC[] = "https://pastebin.ca/";
static const char internalUrlC[] = "http://pbin.ca/"; static const char internalUrlC[] = "https://pbin.ca/";
static const char protocolNameC[] = "Pastebin.Ca"; static const char protocolNameC[] = "Pastebin.Ca";
static inline QByteArray expiryValue(int expiryDays) static inline QByteArray expiryValue(int expiryDays)

View File

@@ -197,8 +197,9 @@ public:
void updateDebugger(const DebuggerItem &item); void updateDebugger(const DebuggerItem &item);
void apply(); void apply();
void cancel(); void cancel();
DebuggerTreeItem *currentTreeItem();
DebuggerTreeItem *m_currentTreeItem = nullptr; QPersistentModelIndex m_currentIndex;
}; };
template <class Predicate> template <class Predicate>
@@ -287,8 +288,13 @@ void DebuggerItemModel::cancel()
void DebuggerItemModel::setCurrentIndex(const QModelIndex &index) void DebuggerItemModel::setCurrentIndex(const QModelIndex &index)
{ {
TreeItem *treeItem = itemForIndex(index); m_currentIndex = index;
m_currentTreeItem = treeItem && treeItem->level() == 2 ? static_cast<DebuggerTreeItem *>(treeItem) : 0; }
DebuggerTreeItem *DebuggerItemModel::currentTreeItem()
{
TreeItem *treeItem = itemForIndex(m_currentIndex);
return treeItem && treeItem->level() == 2 ? static_cast<DebuggerTreeItem *>(treeItem) : nullptr;
} }
DebuggerItemConfigWidget::DebuggerItemConfigWidget() DebuggerItemConfigWidget::DebuggerItemConfigWidget()
@@ -514,10 +520,11 @@ public:
void DebuggerConfigWidget::cloneDebugger() void DebuggerConfigWidget::cloneDebugger()
{ {
if (!d->m_model->m_currentTreeItem) DebuggerTreeItem *treeItem = d->m_model->currentTreeItem();
if (!treeItem)
return; return;
DebuggerItem *item = &d->m_model->m_currentTreeItem->m_item; DebuggerItem *item = &treeItem->m_item;
DebuggerItem newItem; DebuggerItem newItem;
newItem.createId(); newItem.createId();
newItem.setCommand(item->command()); newItem.setCommand(item->command());
@@ -542,9 +549,10 @@ void DebuggerConfigWidget::addDebugger()
void DebuggerConfigWidget::removeDebugger() void DebuggerConfigWidget::removeDebugger()
{ {
QTC_ASSERT(d->m_model->m_currentTreeItem, return); DebuggerTreeItem *treeItem = d->m_model->currentTreeItem();
d->m_model->m_currentTreeItem->m_removed = !d->m_model->m_currentTreeItem->m_removed; QTC_ASSERT(treeItem, return);
d->m_model->m_currentTreeItem->update(); treeItem->m_removed = !treeItem->m_removed;
treeItem->update();
updateButtons(); updateButtons();
} }
@@ -556,7 +564,7 @@ void DebuggerConfigWidget::currentDebuggerChanged(const QModelIndex &newCurrent)
void DebuggerConfigWidget::updateButtons() void DebuggerConfigWidget::updateButtons()
{ {
DebuggerTreeItem *titem = d->m_model->m_currentTreeItem; DebuggerTreeItem *titem = d->m_model->currentTreeItem();
DebuggerItem *item = titem ? &titem->m_item : nullptr; DebuggerItem *item = titem ? &titem->m_item : nullptr;
m_itemConfigWidget->load(item); m_itemConfigWidget->load(item);

View File

@@ -230,6 +230,7 @@ public:
~QueryContext(); ~QueryContext();
void start(); void start();
void terminate();
signals: signals:
void resultRetrieved(const QByteArray &); void resultRetrieved(const QByteArray &);
@@ -242,7 +243,6 @@ private:
void timeout(); void timeout();
void errorTermination(const QString &msg); void errorTermination(const QString &msg);
void terminate();
QProcess m_process; QProcess m_process;
QTimer m_timer; QTimer m_timer;
@@ -498,10 +498,8 @@ QStandardItem *GerritModel::itemForNumber(int number) const
void GerritModel::refresh(const QSharedPointer<GerritServer> &server, const QString &query) void GerritModel::refresh(const QSharedPointer<GerritServer> &server, const QString &query)
{ {
if (m_query) { if (m_query)
qWarning("%s: Another query is still running", Q_FUNC_INFO); m_query->terminate();
return;
}
clearData(); clearData();
m_server = server; m_server = server;
@@ -655,7 +653,7 @@ static GerritChangePtr parseSshOutput(const QJsonObject &object)
{ {
"value": 0, "value": 0,
"_account_id": 1000528, "_account_id": 1000528,
"name": "André Hartmann", "name": "Andre Hartmann",
"email": "aha_1980@gmx.de" "email": "aha_1980@gmx.de"
}, },
{ {
@@ -684,7 +682,7 @@ static GerritChangePtr parseSshOutput(const QJsonObject &object)
{ {
"value": 0, "value": 0,
"_account_id": 1000528, "_account_id": 1000528,
"name": "André Hartmann", "name": "Andre Hartmann",
"email": "aha_1980@gmx.de" "email": "aha_1980@gmx.de"
}, },
{ {

View File

@@ -248,6 +248,7 @@ class IosDeviceToolHandlerPrivate : public IosToolHandlerPrivate
{ {
public: public:
explicit IosDeviceToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q); explicit IosDeviceToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q);
~IosDeviceToolHandlerPrivate();
// IosToolHandlerPrivate overrides // IosToolHandlerPrivate overrides
public: public:
@@ -656,8 +657,11 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de
: IosToolHandlerPrivate(devType, q) : IosToolHandlerPrivate(devType, q)
{ {
auto deleter = [](QProcess *p) { auto deleter = [](QProcess *p) {
if (p->state() != QProcess::NotRunning) {
p->kill(); p->kill();
p->waitForFinished(10000); if (!p->waitForFinished(2000))
p->terminate();
}
delete p; delete p;
}; };
process = std::shared_ptr<QProcess>(new QProcess, deleter); process = std::shared_ptr<QProcess>(new QProcess, deleter);
@@ -696,6 +700,20 @@ IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &de
QObject::connect(&killTimer, &QTimer::timeout, std::bind(&IosDeviceToolHandlerPrivate::killProcess, this)); QObject::connect(&killTimer, &QTimer::timeout, std::bind(&IosDeviceToolHandlerPrivate::killProcess, this));
} }
IosDeviceToolHandlerPrivate::~IosDeviceToolHandlerPrivate()
{
if (isRunning()) {
// Disconnect the signals to avoid notifications while destructing.
// QTCREATORBUG-18147
process->disconnect();
// Quit ios-tool gracefully before kill is executed.
process->write("k\n\r");
process->closeWriteChannel();
// Give some time to ios-tool to finish.
process->waitForFinished(2000);
}
}
void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath, void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath,
const QString &deviceId, int timeout) const QString &deviceId, int timeout)
{ {

View File

@@ -689,7 +689,7 @@ void CheckBoxField::setup(JsonFieldPage *page, const QString &name)
auto w = static_cast<TextFieldCheckBox *>(widget()); auto w = static_cast<TextFieldCheckBox *>(widget());
QObject::connect(w, &TextFieldCheckBox::clicked, QObject::connect(w, &TextFieldCheckBox::clicked,
page, [this, page]() { m_isModified = true; page->completeChanged();}); page, [this, page]() { m_isModified = true; page->completeChanged();});
page->registerFieldWithName(name, w, "text", SIGNAL(textChanged(QString))); page->registerFieldWithName(name, w, "compareText", SIGNAL(textChanged(QString)));
} }
bool CheckBoxField::validate(MacroExpander *expander, QString *message) bool CheckBoxField::validate(MacroExpander *expander, QString *message)
@@ -822,7 +822,7 @@ QWidget *ComboBoxField::createWidget(const QString &displayName, JsonFieldPage *
void ComboBoxField::setup(JsonFieldPage *page, const QString &name) void ComboBoxField::setup(JsonFieldPage *page, const QString &name)
{ {
auto w = static_cast<TextFieldComboBox *>(widget()); auto w = static_cast<TextFieldComboBox *>(widget());
page->registerFieldWithName(name, w, "text", SIGNAL(text4Changed(QString))); page->registerFieldWithName(name, w, "indexText", SIGNAL(text4Changed(QString)));
QObject::connect(w, &TextFieldComboBox::text4Changed, QObject::connect(w, &TextFieldComboBox::text4Changed,
page, [page](QString) { page->completeChanged(); }); page, [page](QString) { page->completeChanged(); });
} }

View File

@@ -3312,6 +3312,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath)
{ {
const QString oldFilePath = node->filePath().toFileInfo().absoluteFilePath(); const QString oldFilePath = node->filePath().toFileInfo().absoluteFilePath();
FolderNode *folderNode = node->parentFolderNode(); FolderNode *folderNode = node->parentFolderNode();
QTC_ASSERT(folderNode, return);
const QString projectFileName = folderNode->managingProject()->filePath().fileName(); const QString projectFileName = folderNode->managingProject()->filePath().fileName();
if (oldFilePath == newFilePath) if (oldFilePath == newFilePath)

View File

@@ -175,7 +175,7 @@ class PROJECTEXPLORER_EXPORT Runnable
public: public:
Runnable() = default; Runnable() = default;
Runnable(const Runnable &other) : d(other.d->clone()) { } Runnable(const Runnable &other) : d(other.d ? other.d->clone() : nullptr) { }
Runnable(Runnable &&other) : d(std::move(other.d)) {} Runnable(Runnable &&other) : d(std::move(other.d)) {}
template <class T> Runnable(const T &data) : d(new Model<T>(data)) {} template <class T> Runnable(const T &data) : d(new Model<T>(data)) {}
@@ -215,7 +215,7 @@ class PROJECTEXPLORER_EXPORT Connection
public: public:
Connection() = default; Connection() = default;
Connection(const Connection &other) : d(other.d->clone()) { } Connection(const Connection &other) : d(other.d ? other.d->clone() : nullptr) { }
Connection(Connection &&other) /* MSVC 2013 doesn't want = default */ : d(std::move(other.d)) {} Connection(Connection &&other) /* MSVC 2013 doesn't want = default */ : d(std::move(other.d)) {}
template <class T> Connection(const T &data) : d(new Model<T>(data)) {} template <class T> Connection(const T &data) : d(new Model<T>(data)) {}

View File

@@ -74,7 +74,6 @@ namespace ProjectExplorer {
class SessionManagerPrivate class SessionManagerPrivate
{ {
public: public:
bool projectContainsFile(Project *p, const FileName &fileName) const;
void restoreValues(const PersistentSettingsReader &reader); void restoreValues(const PersistentSettingsReader &reader);
void restoreDependencies(const PersistentSettingsReader &reader); void restoreDependencies(const PersistentSettingsReader &reader);
void restoreStartupProject(const PersistentSettingsReader &reader); void restoreStartupProject(const PersistentSettingsReader &reader);
@@ -658,19 +657,19 @@ Project *SessionManager::projectForFile(const Utils::FileName &fileName)
{ {
const QList<Project *> &projectList = projects(); const QList<Project *> &projectList = projects();
foreach (Project *p, projectList) { foreach (Project *p, projectList) {
if (d->projectContainsFile(p, fileName)) if (projectContainsFile(p, fileName))
return p; return p;
} }
return nullptr; return nullptr;
} }
bool SessionManagerPrivate::projectContainsFile(Project *p, const Utils::FileName &fileName) const bool SessionManager::projectContainsFile(Project *p, const Utils::FileName &fileName)
{ {
if (!m_projectFileCache.contains(p)) if (!d->m_projectFileCache.contains(p))
m_projectFileCache.insert(p, p->files(Project::AllFiles)); d->m_projectFileCache.insert(p, p->files(Project::AllFiles));
return m_projectFileCache.value(p).contains(fileName.toString()); return d->m_projectFileCache.value(p).contains(fileName.toString());
} }
void SessionManager::configureEditor(IEditor *editor, const QString &fileName) void SessionManager::configureEditor(IEditor *editor, const QString &fileName)
@@ -686,7 +685,7 @@ void SessionManager::configureEditor(IEditor *editor, const QString &fileName)
void SessionManager::configureEditors(Project *project) void SessionManager::configureEditors(Project *project)
{ {
foreach (IDocument *document, DocumentModel::openedDocuments()) { foreach (IDocument *document, DocumentModel::openedDocuments()) {
if (d->projectContainsFile(project, document->filePath())) { if (projectContainsFile(project, document->filePath())) {
foreach (IEditor *editor, DocumentModel::editorsForDocument(document)) { foreach (IEditor *editor, DocumentModel::editorsForDocument(document)) {
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) { if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) {
project->editorConfiguration()->configureEditor(textEditor); project->editorConfiguration()->configureEditor(textEditor);

View File

@@ -115,6 +115,7 @@ public:
static Project *projectForNode(Node *node); static Project *projectForNode(Node *node);
static Node *nodeForFile(const Utils::FileName &fileName); static Node *nodeForFile(const Utils::FileName &fileName);
static Project *projectForFile(const Utils::FileName &fileName); static Project *projectForFile(const Utils::FileName &fileName);
static bool projectContainsFile(Project *p, const Utils::FileName &fileName);
static QStringList projectsForSessionName(const QString &session); static QStringList projectsForSessionName(const QString &session);

View File

@@ -738,7 +738,7 @@ void QbsProject::updateDocuments(const QSet<QString> &files)
foreach (IDocument *doc, currentDocuments) { foreach (IDocument *doc, currentDocuments) {
if (filesToRemove.contains(doc->filePath().toString())) { if (filesToRemove.contains(doc->filePath().toString())) {
m_qbsDocuments.remove(doc); m_qbsDocuments.remove(doc);
delete doc; doc->deleteLater();
} }
} }
QSet<IDocument *> toAdd; QSet<IDocument *> toAdd;

View File

@@ -262,6 +262,7 @@ DesktopQmakeRunConfigurationWidget::DesktopQmakeRunConfigurationWidget(DesktopQm
this, &DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange); this, &DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange);
Core::VariableChooser::addSupportForChildWidgets(this, m_qmakeRunConfiguration->macroExpander()); Core::VariableChooser::addSupportForChildWidgets(this, m_qmakeRunConfiguration->macroExpander());
effectiveTargetInformationChanged();
} }
void DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange() void DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange()

View File

@@ -84,9 +84,11 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, Node *node) const
const FolderNode *folderNode = this; const FolderNode *folderNode = this;
const QmakeProFileNode *proFileNode; const QmakeProFileNode *proFileNode;
while (!(proFileNode = dynamic_cast<const QmakeProFileNode*>(folderNode))) while (!(proFileNode = dynamic_cast<const QmakeProFileNode*>(folderNode))) {
folderNode = folderNode->parentFolderNode(); folderNode = folderNode->parentFolderNode();
Q_ASSERT(proFileNode); QTC_ASSERT(folderNode, return false);
}
QTC_ASSERT(proFileNode, return false);
const QmakeProFile *pro = proFileNode->proFile(); const QmakeProFile *pro = proFileNode->proFile();
switch (pro ? pro->projectType() : ProjectType::Invalid) { switch (pro ? pro->projectType() : ProjectType::Invalid) {

View File

@@ -204,7 +204,7 @@ QmakeProFileNode *QmakeNodeTreeBuilder::buildTree(QmakeProject *project)
{ {
// Remove qmake implementation details that litter up the project data: // Remove qmake implementation details that litter up the project data:
Target *t = project->activeTarget(); Target *t = project->activeTarget();
Kit *k = t ? t->kit() : nullptr; Kit *k = t ? t->kit() : KitManager::defaultKit();
BaseQtVersion *qt = k ? QtKitInformation::qtVersion(k) : nullptr; BaseQtVersion *qt = k ? QtKitInformation::qtVersion(k) : nullptr;
const FileNameList toExclude = qt ? qt->directoriesToIgnoreInProjectTree() : FileNameList(); const FileNameList toExclude = qt ? qt->directoriesToIgnoreInProjectTree() : FileNameList();

View File

@@ -611,6 +611,7 @@ QStringList QmakeProject::filesGeneratedFrom(const QString &input) const
if (const FileNode *file = fileNodeOf(rootProjectNode(), FileName::fromString(input))) { if (const FileNode *file = fileNodeOf(rootProjectNode(), FileName::fromString(input))) {
const QmakeProFileNode *pro = static_cast<QmakeProFileNode *>(file->parentFolderNode()); const QmakeProFileNode *pro = static_cast<QmakeProFileNode *>(file->parentFolderNode());
QTC_ASSERT(pro, return {});
if (const QmakeProFile *proFile = pro->proFile()) if (const QmakeProFile *proFile = pro->proFile())
return Utils::transform(proFile->generatedFiles(FileName::fromString(pro->buildDir()), return Utils::transform(proFile->generatedFiles(FileName::fromString(pro->buildDir()),
file->filePath(), file->fileType()), file->filePath(), file->fileType()),

View File

@@ -147,9 +147,15 @@ ScrollView {
} }
onMouseExited: { onMouseExited: {
if (tooltip.hoveredNode === flamegraphItem) if (tooltip.hoveredNode === flamegraphItem) {
// Keep the window around until something else is hovered or selected.
if (tooltip.selectedNode === null
|| tooltip.selectedNode.typeId !== root.selectedTypeId) {
tooltip.selectedNode = flamegraphItem;
}
tooltip.hoveredNode = null; tooltip.hoveredNode = null;
} }
}
onClicked: { onClicked: {
if (flamegraphItem.FlameGraph.dataValid) { if (flamegraphItem.FlameGraph.dataValid) {

View File

@@ -114,6 +114,8 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag
break; break;
case QmlProfilerModelManager::ClearingData: case QmlProfilerModelManager::ClearingData:
d->m_zoomControl->clear(); d->m_zoomControl->clear();
if (!d->m_suspendedModels.isEmpty())
break; // Models are suspended already. AcquiringData was aborted.
// Fall through // Fall through
case QmlProfilerModelManager::AcquiringData: case QmlProfilerModelManager::AcquiringData:
// Temporarily remove the models, while we're changing them // Temporarily remove the models, while we're changing them

View File

@@ -287,6 +287,7 @@ void ResourceEditorPlugin::removeFileContextMenu()
QTC_ASSERT(rfn, return); QTC_ASSERT(rfn, return);
QString path = rfn->filePath().toString(); QString path = rfn->filePath().toString();
FolderNode *parent = rfn->parentFolderNode(); FolderNode *parent = rfn->parentFolderNode();
QTC_ASSERT(parent, return);
if (!parent->removeFiles(QStringList() << path)) if (!parent->removeFiles(QStringList() << path))
QMessageBox::warning(Core::ICore::mainWindow(), QMessageBox::warning(Core::ICore::mainWindow(),
tr("File Removal Failed"), tr("File Removal Failed"),

View File

@@ -70,8 +70,9 @@ public:
{ {
if (type == TypePermissions) if (type == TypePermissions)
return true; return true;
auto newNode = new ResourceTopLevelNode(m_node->filePath(), false, m_node->contents(), FolderNode *parent = m_node->parentFolderNode();
m_node->parentFolderNode()); QTC_ASSERT(parent, return false);
auto newNode = new ResourceTopLevelNode(m_node->filePath(), false, m_node->contents(), parent);
m_node->parentFolderNode()->replaceSubtree(m_node, newNode); m_node->parentFolderNode()->replaceSubtree(m_node, newNode);
return true; return true;
} }

View File

@@ -212,6 +212,7 @@
:popupFrame_Proposal_QListView {container=':popupFrame_TextEditor::GenericProposalWidget' type='QListView' unnamed='1' visible='1'} :popupFrame_Proposal_QListView {container=':popupFrame_TextEditor::GenericProposalWidget' type='QListView' unnamed='1' visible='1'}
:popupFrame_TextEditor::GenericProposalWidget {name='m_popupFrame' type='TextEditor::GenericProposalWidget' visible='1'} :popupFrame_TextEditor::GenericProposalWidget {name='m_popupFrame' type='TextEditor::GenericProposalWidget' visible='1'}
:projectComboBox_QComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='QComboBox' visible='1'} :projectComboBox_QComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='QComboBox' visible='1'}
:projectComboBox_Utils::TreeViewComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='Utils::TreeViewComboBox' visible='1'}
:qdesigner_internal::WidgetBoxCategoryListView {container=':Widget Box_qdesigner_internal::WidgetBoxTreeWidget' occurrence='3' type='qdesigner_internal::WidgetBoxCategoryListView' unnamed='1' visible='1'} :qdesigner_internal::WidgetBoxCategoryListView {container=':Widget Box_qdesigner_internal::WidgetBoxTreeWidget' occurrence='3' type='qdesigner_internal::WidgetBoxCategoryListView' unnamed='1' visible='1'}
:qmakeCallEdit {container=':Qt Creator.scrollArea_QScrollArea' text?='<b>qmake:</b> qmake*' type='QLabel' unnamed='1' visible='1'} :qmakeCallEdit {container=':Qt Creator.scrollArea_QScrollArea' text?='<b>qmake:</b> qmake*' type='QLabel' unnamed='1' visible='1'}
:qt_tabwidget_stackedwidget.Core__Internal__GeneralSettings_QWidget {container=':Options.qt_tabwidget_stackedwidget_QStackedWidget' name='Core__Internal__GeneralSettings' type='QWidget' visible='1'} :qt_tabwidget_stackedwidget.Core__Internal__GeneralSettings_QWidget {container=':Options.qt_tabwidget_stackedwidget_QStackedWidget' name='Core__Internal__GeneralSettings' type='QWidget' visible='1'}

View File

@@ -749,12 +749,13 @@ def compareProjectTree(rootObject, dataset):
# creates C++ file(s) and adds them to the current project if one is open # creates C++ file(s) and adds them to the current project if one is open
# name name of the created object: filename for files, classname for classes # name name of the created object: filename for files, classname for classes
# template "C++ Class", "C++ Header File" or "C++ Source File" # template "C++ Class", "C++ Header File" or "C++ Source File"
# projectName None or name of open project that the files will be added to
# forceOverwrite bool: force overwriting existing files? # forceOverwrite bool: force overwriting existing files?
# addToVCS name of VCS to add the file(s) to # addToVCS name of VCS to add the file(s) to
# newBasePath path to create the file(s) at # newBasePath path to create the file(s) at
# expectedSourceName expected name of created source file # expectedSourceName expected name of created source file
# expectedHeaderName expected name of created header file # expectedHeaderName expected name of created header file
def addCPlusPlusFileToCurrentProject(name, template, forceOverwrite=False, addToVCS="<None>", def addCPlusPlusFile(name, template, projectName, forceOverwrite=False, addToVCS="<None>",
newBasePath=None, expectedSourceName=None, expectedHeaderName=None): newBasePath=None, expectedSourceName=None, expectedHeaderName=None):
if name == None: if name == None:
test.fatal("File must have a name - got None.") test.fatal("File must have a name - got None.")
@@ -785,6 +786,14 @@ def addCPlusPlusFileToCurrentProject(name, template, forceOverwrite=False, addTo
test.compare(str(waitForObject("{name='HdrFileName' type='QLineEdit' visible='1'}").text), test.compare(str(waitForObject("{name='HdrFileName' type='QLineEdit' visible='1'}").text),
expectedHeaderName) expectedHeaderName)
clickButton(waitForObject(":Next_QPushButton")) clickButton(waitForObject(":Next_QPushButton"))
projectComboBox = waitForObjectExists(":projectComboBox_Utils::TreeViewComboBox")
test.compare(projectComboBox.enabled, projectName != None,
"Project combo box must be enabled when a project is open")
projectNameToDisplay = "<None>"
if projectName:
projectNameToDisplay = projectName
test.compare(str(projectComboBox.currentText), projectNameToDisplay,
"The right project must be selected")
fileExistedBefore = False fileExistedBefore = False
if template == "C++ Class": if template == "C++ Class":
fileExistedBefore = (os.path.exists(os.path.join(basePath, name.lower() + ".cpp")) fileExistedBefore = (os.path.exists(os.path.join(basePath, name.lower() + ".cpp"))

View File

@@ -100,7 +100,9 @@ def switchToBuildOrRunSettingsFor(targetCount, currentTarget, projectSettings):
if not test.verify(not str(findObject(currentTargetIndex).toolTip).startswith(clickToActivate), if not test.verify(not str(findObject(currentTargetIndex).toolTip).startswith(clickToActivate),
"Verifying target '%s' is enabled." % targets[currentTarget]): "Verifying target '%s' is enabled." % targets[currentTarget]):
return False return False
mouseClick(waitForObject(currentTargetIndex)) index = waitForObject(currentTargetIndex)
treeView.scrollTo(index)
mouseClick(index)
if projectSettings == ProjectSettings.BUILD: if projectSettings == ProjectSettings.BUILD:
settingsIndex = getQModelIndexStr("text='Build'", currentTargetIndex) settingsIndex = getQModelIndexStr("text='Build'", currentTargetIndex)

View File

@@ -27,7 +27,7 @@ source("../../shared/qtcreator.py")
# test Qt Creator version information from file and dialog # test Qt Creator version information from file and dialog
def getQtCreatorVersionFromDialog(): def getQtCreatorVersionFromDialog():
chk = re.search("(?<=Qt Creator)\s\d+.\d+.\d+\S*", chk = re.search("(?<=Qt Creator)\s\d+.\d+.\d+[-\w]*",
str(waitForObject("{text?='*Qt Creator*' type='QLabel' unnamed='1' visible='1' " str(waitForObject("{text?='*Qt Creator*' type='QLabel' unnamed='1' visible='1' "
"window=':About Qt Creator_Core::Internal::VersionDialog'}").text)) "window=':About Qt Creator_Core::Internal::VersionDialog'}").text))
try: try:

View File

@@ -42,7 +42,7 @@ def main():
if not testRenameMacroAfterSourceModification(): if not testRenameMacroAfterSourceModification():
return return
headerName = "anothertestfile.h" headerName = "anothertestfile.h"
addCPlusPlusFileToCurrentProject(headerName, "C++ Header File", addCPlusPlusFile(headerName, "C++ Header File", "testfiles.pro",
expectedHeaderName=headerName) expectedHeaderName=headerName)
if not testRenameMacroAfterSourceMoving(): if not testRenameMacroAfterSourceMoving():
return return

View File

@@ -34,7 +34,7 @@ def main():
startApplication("qtcreator" + SettingsPath) startApplication("qtcreator" + SettingsPath)
if not startedWithoutPluginError(): if not startedWithoutPluginError():
return return
addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", newBasePath=basePath, addCPlusPlusFile(newClassName, "C++ Class", None, newBasePath=basePath,
expectedSourceName=sourceFileName, expectedSourceName=sourceFileName,
expectedHeaderName=headerFileName) expectedHeaderName=headerFileName)
@@ -77,16 +77,16 @@ def main():
def overwritten(filename): def overwritten(filename):
return notOverwrittenComment not in readFile(os.path.join(basePath, filename)) return notOverwrittenComment not in readFile(os.path.join(basePath, filename))
addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", False, newBasePath=basePath, addCPlusPlusFile(newClassName, "C++ Class", None, False,
expectedSourceName=sourceFileName, newBasePath=basePath, expectedSourceName=sourceFileName,
expectedHeaderName=headerFileName) expectedHeaderName=headerFileName)
test.verify(not waitFor("overwritten(sourceFileName)", 2000), test.verify(not waitFor("overwritten(sourceFileName)", 2000),
"Source file should not be overwritten.") "Source file should not be overwritten.")
test.verify(not waitFor("overwritten(headerFileName)", 500), test.verify(not waitFor("overwritten(headerFileName)", 500),
"Header file should not be overwritten.") "Header file should not be overwritten.")
addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", True, newBasePath=basePath, addCPlusPlusFile(newClassName, "C++ Class", None, True,
expectedSourceName=sourceFileName, newBasePath=basePath, expectedSourceName=sourceFileName,
expectedHeaderName=headerFileName) expectedHeaderName=headerFileName)
test.verify(waitFor("overwritten(sourceFileName)", 2000), test.verify(waitFor("overwritten(sourceFileName)", 2000),
"Source file should be overwritten.") "Source file should be overwritten.")

View File

@@ -43,8 +43,8 @@ def main():
return return
test.log("Start parsing project") test.log("Start parsing project")
rootNodeTemplate = "{column='0' container=':Qt Creator_Utils::NavigationTreeView' text~='%s( \[\S+\])?' type='QModelIndex'}" rootNodeTemplate = "{column='0' container=':Qt Creator_Utils::NavigationTreeView' text~='%s( \[\S+\])?' type='QModelIndex'}"
ntwObject = waitForObject(rootNodeTemplate % "qtcreator.qbs") ntwObject = waitForObject(rootNodeTemplate % "Qt Creator", 200000)
if waitFor("ntwObject.model().rowCount(ntwObject) > 2", 200000): # No need to wait for C++-parsing if waitFor("ntwObject.model().rowCount(ntwObject) > 2", 20000): # No need to wait for C++-parsing
test.log("Parsing project done") # we only need the project test.log("Parsing project done") # we only need the project
else: else:
test.warning("Parsing project timed out") test.warning("Parsing project timed out")

View File

@@ -175,8 +175,8 @@ def main():
commitMessages = [commit("Initial Commit", "Committed 5 file(s).")] commitMessages = [commit("Initial Commit", "Committed 5 file(s).")]
clickButton(waitForObject(":*Qt Creator.Clear_QToolButton")) clickButton(waitForObject(":*Qt Creator.Clear_QToolButton"))
headerName = "pointless_header.h" headerName = "pointless_header.h"
addCPlusPlusFileToCurrentProject(headerName, "C++ Header File", addToVCS="Git", addCPlusPlusFile(headerName, "C++ Header File", projectName + ".pro",
expectedHeaderName=headerName) addToVCS="Git", expectedHeaderName=headerName)
commitMessages.insert(0, commit("Added pointless header file", "Committed 2 file(s).")) commitMessages.insert(0, commit("Added pointless header file", "Committed 2 file(s)."))
readmeName = "README.txt" readmeName = "README.txt"
addEmptyFileOutsideProject(readmeName) addEmptyFileOutsideProject(readmeName)