Commit b6876586 authored by Eike Ziller's avatar Eike Ziller

Merge remote-tracking branch 'origin/3.1'

Conflicts:
	qtcreator.pri
	qtcreator.qbs
	src/plugins/cpptools/cppcompletion_test.cpp

Change-Id: Ic5e75b3ef164de664a1449ffa8579beaf5b02521
parents 49bbd218 780c21a1
doc/images/qtcreator-qml-performance-monitor.png

80.9 KB | W: | H:

doc/images/qtcreator-qml-performance-monitor.png

80.5 KB | W: | H:

doc/images/qtcreator-qml-performance-monitor.png
doc/images/qtcreator-qml-performance-monitor.png
doc/images/qtcreator-qml-performance-monitor.png
doc/images/qtcreator-qml-performance-monitor.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -62,14 +62,13 @@
the QML Profiler immediately begins to collect data. This is indicated by
the time running in the \gui Elapsed field.
Data is collected until you select the
\inlineimage qtcreator-debug-button-stop.png
(\gui Stop) button. Data collection
Data is collected until you select the \gui {Enable Profiling} button. Data
collection
takes time, and therefore, there might be a delay
before the data is displayed.
Do not use application commands to exit the application, because data is
sent to the QML Profiler when you select the \gui Stop button.
sent to the QML Profiler when you select the \gui {Enable Profiling} button.
The application continues to run for some seconds, after which it is stopped
automatically. If you exit the application, the data is not sent.
......@@ -114,6 +113,8 @@
\li Signal handling
\li Executing JavaScript behind bindings and signal handlers
\li Summary of the recorded period
\endlist
......@@ -171,14 +172,36 @@
Click the binding to move the cursor in the code editor to the part of the
code where the binding is called.
\section2 Evaluating JavaScript Events
On the \gui JavaScript row, you can see the time spent executing the actual
JavaScript behind bindings and signal handlers. It lists all the JavaScript
functions you may be using to evaluate bindings or handle signals.
This information is displayed for applications that use the V4 engine and
are built with Qt 5.3, or later.
For applications that use the V8 engine and are built with Qt 5.0 or 5.1,
you can view information about JavaScript events in the \gui JavaScript
view.
\section1 Viewing Events
The \gui Events view displays the number of times each binding is called
and the time the calls take. This allows you to examine which events you
need to optimize. A high number of calls might indicate that a binding is
called unnecessarily. Click on a binding to move to it in the source code
The \gui Events view displays the number of times each binding, create,
compile, JavaScript, or signal event is triggered and the average time it
takes. This allows you to examine which events you need to optimize. A high
number of occurrences might indicate that an event is triggered
unnecessarily. To view the median, longest, and shortest time for the
occurrences, select \gui {Extended Event Statistics} in the context menu.
Click on an event to move to it in the source code
in the code editor.
JavaScript events often duplicate bindings or signals, so you can show and
hide them by selecting \gui {Show JavaScript Events} in the context menu.
To show and hide QML events (\gui Create, \gui Compile, and \gui Signal),
select \gui {Show QML Events}.
\image qtcreator-analyzer-bindings.png "Events view"
The \gui Callers and \gui Callees panes show dependencies between events.
......@@ -188,7 +211,7 @@
The \gui Callees pane summarizes the QML events that a binding triggers.
This tells you which QML events are affected if you change a binding.
Click on a binding to move to it in the source code in the code editor.
Click on an event to move to it in the source code in the code editor.
When you select an event in the \gui Timeline view, information about it is
displayed in the \gui Events view. To view an event range in the \gui Events
......@@ -198,11 +221,6 @@
To copy the contents of one view or row to the clipboard, select
\gui {Copy Table} or \gui {Copy Row} in the context menu.
You can view similar information about JavaScript events in the
\gui JavaScript view.
\image qml-profiler-javascript.png "JavaScript view"
\section2 Viewing More Data
The QML JavaScript engine optimizes trivial bindings. The QML Profiler
......
......@@ -500,6 +500,18 @@ class DumperBase:
self.putType(type)
self.putNumChild(0)
def putCallItem(self, name, value, func, *args):
try:
result = self.callHelper(value, func, args)
with SubItem(self, name):
self.putItem(result)
except:
with SubItem(self, name):
self.putValue("<not callable>")
self.putNumChild(0)
def call(self, value, func, *args):
return self.callHelper(value, func, args)
def putMapName(self, value, index = -1):
ns = self.qtNamespace()
......@@ -1025,15 +1037,15 @@ class DumperBase:
addr += 1
return result
def generateQListChildren(self, value):
base = self.extractPointer(value)
def listChildrenGenerator(self, addr, typeName):
innerType = self.lookupType(self.qtNamespace() + typeName)
base = self.extractPointer(addr)
begin = self.extractInt(base + 8)
end = self.extractInt(base + 12)
array = base + 16
if self.qtVersion() < 0x50000:
array += self.ptrSize()
size = end - begin
innerType = self.templateArgument(value.type, 0)
innerSize = innerType.sizeof
stepSize = self.ptrSize()
addr = array + begin * stepSize
......@@ -1072,19 +1084,9 @@ class DumperBase:
# Dynamic properties.
if extraData:
propertyNames = extraData + ptrSize
propertyValues = extraData + 2 * ptrSize
ns = self.qtNamespace()
typ = self.lookupType(ns + "QList<" + ns + "QByteArray>")
names = self.createValue(propertyNames, typ)
typ = self.lookupType(ns + "QList<" + ns + "QVariant>")
values = self.createValue(propertyValues, typ)
for (k, v) in zip(self.generateQListChildren(names),
self.generateQListChildren(values)) :
names = self.listChildrenGenerator(extraData + ptrSize, "QByteArray")
values = self.listChildrenGenerator(extraData + 2 * ptrSize, "QVariant")
for (k, v) in zip(names, values):
with SubItem(self, propertyCount):
self.put('key="%s",' % self.encodeByteArray(k))
self.put('keyencoded="%s",' % Hex2EncodedLatin1)
......
......@@ -575,7 +575,7 @@ class Dumper(DumperBase):
def parseAndEvaluate(self, exp):
return gdb.parse_and_eval(exp)
def call2(self, value, func, args):
def callHelper(self, value, func, args):
# args is a tuple.
arg = ""
for i in range(len(args)):
......@@ -602,9 +602,6 @@ class Dumper(DumperBase):
gdb.parse_and_eval("free(0x%x)" % ptr)
return result
def call(self, value, func, *args):
return self.call2(value, func, args)
def childWithName(self, value, name):
try:
return value[name]
......@@ -1054,11 +1051,6 @@ class Dumper(DumperBase):
i = toInteger(i)
self.putSubItem(i, (base + i).dereference())
def putCallItem(self, name, value, func, *args):
result = self.call2(value, func, args)
with SubItem(self, name):
self.putItem(result)
def isFunctionType(self, type):
return type.code == MethodCode or type.code == FunctionCode
......
......@@ -144,7 +144,7 @@ def impl_SBValue__add__(self, offset):
def impl_SBValue__sub__(self, other):
if self.GetType().IsPointerType():
if isinstance(other, int) or isinstance(other, long):
address = self.GetValueAsUnsigned() - offset.GetValueAsSigned()
address = self.GetValueAsUnsigned() - other
address = address & 0xFFFFFFFFFFFFFFFF # Force unsigned
return self.CreateValueFromAddress(None, address, self.GetType())
if other.GetType().IsPointerType():
......@@ -372,7 +372,7 @@ class Dumper(DumperBase):
return ns + "Qt::" + enumType + "(" \
+ ns + "Qt::" + enumType + "::" + enumValue + ")"
def call2(self, value, func, args):
def callHelper(self, value, func, args):
# args is a tuple.
arg = ','.join(args)
#warn("CALL: %s -> %s(%s)" % (value, func, arg))
......@@ -398,9 +398,6 @@ class Dumper(DumperBase):
frame = thread.GetFrameAtIndex(0)
return frame.EvaluateExpression(expr)
def call(self, value, func, *args):
return self.call2(value, func, args)
def checkPointer(self, p, align = 1):
if not self.isNull(p):
p.Dereference()
......@@ -449,13 +446,21 @@ class Dumper(DumperBase):
qtNamespace = name[:name.find('qVersion')]
self.qtNamespace = lambda: qtNamespace
res = ""
try:
res = self.parseAndEvaluate(name + '()')
except:
res = self.parseAndEvaluate('((const char*())%s)()' % name)
version = str(res)
options = lldb.SBExpressionOptions()
res = self.target.EvaluateExpression(name + '()', options)
if not res.IsValid() or not res.GetType().IsPointerType():
exp = '((const char*())%s)()' % name
res = self.target.EvaluateExpression(exp, options)
if not res.IsValid() or not res.GetType().IsPointerType():
exp = '((const char*())_Z8qVersionv)()'
res = self.target.EvaluateExpression(exp, options)
if not res.IsValid() or not res.GetType().IsPointerType():
continue
version = str(res)
if version.count('.') != 2:
continue
......@@ -604,11 +609,6 @@ class Dumper(DumperBase):
addr = int(address) & 0xFFFFFFFFFFFFFFFF
return self.context.CreateValueFromAddress(None, addr, referencedType)
def putCallItem(self, name, value, func, *args):
result = self.call2(value, func, args)
with SubItem(self, name):
self.putItem(result)
def childRange(self):
if self.currentMaxNumChild is None:
return xrange(0, self.currentNumChild)
......
......@@ -179,6 +179,7 @@ def qdump__QModelIndex(d, value):
% (mm_, row, column, mi_))
d.putItem(mi2)
i = i + 1
d.putFields(value)
#d.putCallItem("parent", val, "parent")
#with SubItem(d, "model"):
# d.putValue(m)
......@@ -203,6 +204,7 @@ def qdump__QDate(d, value):
d.enumExpression("DateFormat", "SystemLocaleDate"))
d.putCallItem("(Locale)", value, "toString",
d.enumExpression("DateFormat", "LocaleDate"))
d.putFields(value)
else:
d.putValue("(invalid)")
d.putNumChild(0)
......@@ -224,6 +226,7 @@ def qdump__QTime(d, value):
d.enumExpression("DateFormat", "SystemLocaleDate"))
d.putCallItem("(Locale)", value, "toString",
d.enumExpression("DateFormat", "LocaleDate"))
d.putFields(value)
else:
d.putValue("(invalid)")
d.putNumChild(0)
......@@ -312,6 +315,7 @@ def qdump__QDateTime(d, value):
d.enumExpression("TimeSpec", "UTC"))
d.putCallItem("toLocalTime", value, "toTimeSpec",
d.enumExpression("TimeSpec", "LocalTime"))
d.putFields(value)
else:
d.putValue("(invalid)")
d.putNumChild(0)
......@@ -404,17 +408,25 @@ def qdump__QDir(d, value):
with SubItem(d, "entryList"):
typ = d.lookupType(ns + "QStringList")
d.putItem(d.createValue(privAddress + filesOffset, typ))
d.putFields(value)
def qdump__QFile(d, value):
# 9fc0965 changes the layout of the private structure
qtVersion = d.qtVersion()
if qtVersion >= 0x050200:
offset = 176 if d.is32bit() else 272
is32bit = d.is32bit()
if qtVersion > 0x050200:
if d.isWindowsTarget():
offset = 180 if is32bit else 272
else:
offset = 176 if is32bit else 272
elif qtVersion >= 0x050000:
offset = 180 if d.is32bit() else 280
offset = 176 if is32bit else 280
else:
offset = 140 if d.is32bit() else 232
if d.isWindowsTarget():
offset = 144 if is32bit else 232
else:
offset = 140 if is32bit else 232
privAddress = d.extractPointer(d.addressOf(value) + d.ptrSize())
fileNameAddress = privAddress + offset
d.putStringValueByAddress(fileNameAddress)
......@@ -503,6 +515,7 @@ def qdump__QFileInfo(d, value):
d.putCallItem("created", value, "created")
d.putCallItem("lastModified", value, "lastModified")
d.putCallItem("lastRead", value, "lastRead")
d.putFields(value)
def qdump__QFixed(d, value):
......@@ -604,13 +617,16 @@ def qdump__QHash(d, value):
d.putNumChild(size)
if d.isExpanded():
numBuckets = int(d_ptr.dereference()["numBuckets"])
nodePtr = hashDataFirstNode(d_ptr, numBuckets)
innerType = e_ptr.dereference().type
isCompact = d.isMapCompact(keyType, valueType)
childType = valueType if isCompact else innerType
with Children(d, size, maxNumChild=1000, childType=childType):
for i in d.childRange():
it = nodePtr.dereference().cast(innerType)
if i == 0:
node = hashDataFirstNode(d_ptr, numBuckets)
else:
node = hashDataNextNode(node, numBuckets)
it = node.dereference().cast(innerType)
with SubItem(d, i):
if isCompact:
key = it["key"]
......@@ -623,7 +639,6 @@ def qdump__QHash(d, value):
d.putType(valueType)
else:
d.putItem(it)
nodePtr = hashDataNextNode(nodePtr, numBuckets)
def qdump__QHashNode(d, value):
......@@ -912,6 +927,7 @@ def qdump__QLocale(d, value):
d.putCallItem("zeroDigit", value, "zeroDigit")
d.putCallItem("groupSeparator", value, "groupSeparator")
d.putCallItem("negativeSign", value, "negativeSign")
d.putFields(value)
def qdump__QMapNode(d, value):
......@@ -1676,10 +1692,13 @@ def qdump__QSet(d, value):
hashDataType = d_ptr.type
nodeTypePtr = d_ptr.dereference()["fakeNext"].type
numBuckets = int(d_ptr.dereference()["numBuckets"])
node = hashDataFirstNode(d_ptr, numBuckets)
innerType = e_ptr.dereference().type
with Children(d, size, maxNumChild=1000, childType=innerType):
for i in d.childRange():
if i == 0:
node = hashDataFirstNode(d_ptr, numBuckets)
else:
node = hashDataNextNode(node, numBuckets)
it = node.dereference().cast(innerType)
with SubItem(d, i):
key = it["key"]
......@@ -1688,7 +1707,6 @@ def qdump__QSet(d, value):
# for Qt4 optimized int keytype
key = it[1]["key"]
d.putItem(key)
node = hashDataNextNode(node, numBuckets)
def qdump__QSharedData(d, value):
......@@ -1797,6 +1815,7 @@ def qdump__QTextCodec(d, value):
with Children(d):
d.putCallItem("name", value, "name")
d.putCallItem("mibEnum", value, "mibEnum")
d.putFields(value)
def qdump__QTextCursor(d, value):
......@@ -1814,6 +1833,7 @@ def qdump__QTextCursor(d, value):
d.putIntItem("position", d.extractInt(positionAddress))
d.putIntItem("anchor", d.extractInt(positionAddress + d.intSize()))
d.putCallItem("selected", value, "selectedText")
d.putFields(value)
def qdump__QTextDocument(d, value):
......@@ -1826,6 +1846,7 @@ def qdump__QTextDocument(d, value):
d.putCallItem("lineCount", value, "lineCount")
d.putCallItem("revision", value, "revision")
d.putCallItem("toPlainText", value, "toPlainText")
d.putFields(value)
def qform__QUrl():
......@@ -1854,6 +1875,7 @@ def qdump__QUrl(d, value):
d.putCallItem("query", value, "encodedQuery")
d.putCallItem("fragment", value, "fragment")
d.putCallItem("port", value, "port")
d.putFields(value)
else:
# QUrlPrivate:
# - QAtomicInt ref;
......
......@@ -138,7 +138,7 @@ Column {
onAccepted: {
colorEditor.color = textField.text
}
Layout.preferredWidth: 80
Layout.fillWidth: true
}
ColorCheckButton {
id: checkButton
......
......@@ -86,7 +86,7 @@ Controls.TextField {
padding.top: 3
padding.bottom: 1
padding.left: 16
padding.right: 16
padding.right: lineEdit.showTranslateCheckBox ? 16 : 1
placeholderTextColor: "gray"
background: Rectangle {
implicitWidth: 100
......
......@@ -1257,6 +1257,7 @@ void ClassOrNamespace::NestedClassInstantiator::instantiate(ClassOrNamespace *en
}
}
nestedClassOrNamespaceInstantiation->_parent = enclosingTemplateClassInstantiation;
instantiate(nestedClassOrNamespace, nestedClassOrNamespaceInstantiation);
enclosingTemplateClassInstantiation->_classOrNamespaces[nestedName] =
......
......@@ -186,7 +186,7 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
d->maximumTime = qMax(time, d->maximumTime);
}
} else if (messageType == Complete) {
emit complete();
emit complete(d->maximumTime);
} else if (messageType == SceneGraphFrame) {
int sgEventType;
int count = 0;
......
......@@ -97,7 +97,7 @@ public slots:
void sendRecordingStatus();
signals:
void complete();
void complete(qint64 maximumTime);
void gap(qint64 time);
void event(int event, qint64 time);
void traceFinished( qint64 time );
......
......@@ -172,4 +172,22 @@ QTCREATOR_UTILS_EXPORT bool is64BitWindowsBinary(const QString &binaryIn)
#endif
}
WindowsCrashDialogBlocker::WindowsCrashDialogBlocker()
#ifdef Q_OS_WIN
: silenceErrorMode(SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS),
originalErrorMode(SetErrorMode(silenceErrorMode))
#endif
{
}
WindowsCrashDialogBlocker::~WindowsCrashDialogBlocker()
{
#ifdef Q_OS_WIN
unsigned int errorMode = SetErrorMode(originalErrorMode);
// someone else messed with the error mode in between? Better not touch ...
QTC_ASSERT(errorMode == silenceErrorMode, SetErrorMode(errorMode));
#endif
}
} // namespace Utils
......@@ -49,6 +49,23 @@ QTCREATOR_UTILS_EXPORT bool is64BitWindowsSystem();
// Check for a 64bit binary.
QTCREATOR_UTILS_EXPORT bool is64BitWindowsBinary(const QString &binary);
//
// RAII class to temporarily prevent windows crash messages from popping up using the
// application-global (!) error mode.
//
// Useful primarily for QProcess launching, since the setting will be inherited.
//
class QTCREATOR_UTILS_EXPORT WindowsCrashDialogBlocker {
public:
WindowsCrashDialogBlocker();
~WindowsCrashDialogBlocker();
#ifdef Q_OS_WIN
private:
const unsigned int silenceErrorMode;
const unsigned int originalErrorMode;
#endif // Q_OS_WIN
};
} // namespace Utils
#endif // WINUTILS_H
......@@ -529,7 +529,7 @@ QAbstractItemModel *AndroidDeployQtStep::keystoreCertificates()
if (!m_keystorePasswd.length())
return 0;
params << m_keystorePasswd;
params << QLatin1String("-J\"-Duser.language=en\"");
params << QLatin1String("-J-Duser.language=en");
keytoolProc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), params);
if (!keytoolProc.waitForStarted() || !keytoolProc.waitForFinished()) {
QMessageBox::critical(0, tr("Error"),
......
......@@ -1291,7 +1291,7 @@ void AndroidManifestEditorWidget::setHDPIIcon()
void AndroidManifestEditorWidget::defaultPermissionCheckBoxClicked()
{
if (m_defaultPermissonsCheckBox->checkState() == Qt::PartiallyChecked)
m_defaultPermissonsCheckBox->setChecked(Qt::Checked);
m_defaultPermissonsCheckBox->setChecked(true);
setDirty(true);
}
......
......@@ -364,7 +364,7 @@ QAbstractItemModel *AndroidPackageCreationStep::keystoreCertificates()
if (!m_keystorePasswd.length())
return 0;
params << m_keystorePasswd;
params << QLatin1String("-J\"-Duser.language=en\"");
params << QLatin1String("-J-Duser.language=en");
keytoolProc.start(AndroidConfigurations::currentConfig().keytoolPath().toString(), params);
if (!keytoolProc.waitForStarted() || !keytoolProc.waitForFinished()) {
QMessageBox::critical(0, tr("Error"),
......
......@@ -125,6 +125,13 @@ void AndroidQtVersion::addToEnvironment(const ProjectExplorer::Kit *k, Utils::En
AndroidConfigurations::currentConfig().bestNdkPlatformMatch(AndroidManager::buildTargetSDK(target)));
}
Utils::Environment AndroidQtVersion::qmakeRunEnvironment() const
{
Utils::Environment env = Utils::Environment::systemEnvironment();
env.set(QLatin1String("ANDROID_NDK_ROOT"), AndroidConfigurations::currentConfig().ndkLocation().toUserOutput());
return env;
}
QString AndroidQtVersion::description() const
{
//: Qt Version is meant for Android
......
......@@ -53,6 +53,7 @@ public:
QList<ProjectExplorer::Abi> detectQtAbis() const;
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const;
Utils::Environment qmakeRunEnvironment() const;
Core::FeatureSet availableFeatures() const;
QString platformName() const;
......
......@@ -49,6 +49,7 @@ namespace {
}
static const char kKeyboardSettingsKey[] = "KeyboardShortcuts";
static const char kKeyboardSettingsTransferredKey[] = "OldSettingsTransferred";
using namespace Core;
using namespace Core::Internal;
......@@ -505,10 +506,16 @@ static const char oldSequenceKey[] = "Keysequence";
void ActionManagerPrivate::initialize()
{
// TODO remove me after some period after 3.1
// TODO also remove the old settings after some period after 3.1
// settings->remove(QLatin1String(oldSettingsGroup));
// settings->contains(QLatin1String(kKeyboardSettingsKey) + QLatin1Char('/')
// + QLatin1String(kKeyboardSettingsTransferredKey))
// check if settings in old style (pre 3.1) exist
QSettings *settings = Core::ICore::settings();
if (settings->contains(QLatin1String(kKeyboardSettingsKey)))
if (settings->contains(QLatin1String(kKeyboardSettingsKey) + QLatin1Char('/')
+ QLatin1String(kKeyboardSettingsTransferredKey))) {
return;
}
// move old settings style to new settings style
QMap<Id, QKeySequence> shortcutMap;
const int shortcuts = settings->beginReadArray(QLatin1String(oldSettingsGroup));
......@@ -521,14 +528,13 @@ void ActionManagerPrivate::initialize()
settings->endArray();
// write settings in new style
settings->beginGroup(QLatin1String(kKeyboardSettingsKey));
settings->setValue(QLatin1String(kKeyboardSettingsTransferredKey), true);
QMapIterator<Id, QKeySequence> it(shortcutMap);
while (it.hasNext()) {
it.next();
settings->setValue(it.key().toString(), it.value().toString());
}
settings->endGroup();
// remove old settings
settings->remove(QLatin1String(oldSettingsGroup));
}
void ActionManagerPrivate::saveSettings(QSettings *settings)
......
......@@ -337,6 +337,8 @@ void FindToolBar::updateFindAction()
m_findInDocumentAction->setEnabled(enabled);
m_findNextSelectedAction->setEnabled(enabled);
m_findPreviousSelectedAction->setEnabled(enabled);
if (QApplication::clipboard()->supportsFindBuffer())
m_enterFindStringAction->setEnabled(enabled);
}
void FindToolBar::updateToolBar()
......@@ -358,8 +360,6 @@ void FindToolBar::updateToolBar()
m_wholeWordAction->setEnabled(enabled);
m_regularExpressionAction->setEnabled(enabled);
m_preserveCaseAction->setEnabled(replaceEnabled && !hasFindFlag(FindRegularExpression));
if (QApplication::clipboard()->supportsFindBuffer())
m_enterFindStringAction->setEnabled(enabled);
bool replaceFocus = m_ui.replaceEdit->hasFocus();
m_ui.findEdit->setEnabled(enabled);
m_ui.findLabel->setEnabled(enabled);
......@@ -516,6 +516,7 @@ void FindToolBar::invokeResetIncrementalSearch()
void FindToolBar::putSelectionToFindClipboard()