From 4b6c5536d78b177d36c282855ef24672c1624d61 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 2 Apr 2015 08:49:52 +0200 Subject: [PATCH 01/38] Add change log entry Change-Id: I1298cf303d05cf59d3f21da6c602af4e0abe8e3f Reviewed-by: Leena Miettinen --- dist/changes-3.4.0 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dist/changes-3.4.0 b/dist/changes-3.4.0 index 871cf69860e..a4c9105a109 100644 --- a/dist/changes-3.4.0 +++ b/dist/changes-3.4.0 @@ -129,6 +129,8 @@ Version Control Systems (QTCREATORBUG-13979) * Perforce * Improved repository log (QTCREATORBUG-13526) + * Bazaar + * Fixed committing (QTCREATORBUG-13878) FakeVim * Fixed target column for various commands From 14eb13e995d6f977f0492fb1d2435eb01256736d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 26 Mar 2015 11:55:29 +0100 Subject: [PATCH 02/38] Timeline: Enforce a minimum width for detail windows. We don't want to resize them to absurd dimensions. Change-Id: I7f824919052c6740f291d2b0266fd009da99fd53 Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann Reviewed-by: Eike Ziller --- src/libs/timeline/qml/RangeDetails.qml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libs/timeline/qml/RangeDetails.qml b/src/libs/timeline/qml/RangeDetails.qml index a8903863666..c0a765d3dbe 100644 --- a/src/libs/timeline/qml/RangeDetails.qml +++ b/src/libs/timeline/qml/RangeDetails.qml @@ -201,6 +201,17 @@ Item { y: 5 spacing: 5 columns: 2 + property int minimumWidth: { + var result = 150; + for (var i = 0; i < children.length; ++i) + result = Math.max(children[i].x, result); + return result + 20; + } + + onMinimumWidthChanged: { + if (dragHandle.x < minimumWidth) + dragHandle.x = minimumWidth; + } Repeater { model: eventInfo @@ -310,6 +321,7 @@ Item { MouseArea { anchors.fill: parent drag.target: parent + drag.minimumX: col.minimumWidth drag.axis: Drag.XAxis cursorShape: Qt.SizeHorCursor } From ccbe4ee0f8bb834816561721bacd28db19839b80 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 26 Mar 2015 12:01:18 +0100 Subject: [PATCH 03/38] Timeline: Properly position range detail window titles. This way they get elided correctly. Change-Id: I924679bd0f985f621fc62b152f3a4536e48e4492 Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann Reviewed-by: Eike Ziller --- src/libs/timeline/qml/RangeDetails.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/timeline/qml/RangeDetails.qml b/src/libs/timeline/qml/RangeDetails.qml index c0a765d3dbe..6138e658a83 100644 --- a/src/libs/timeline/qml/RangeDetails.qml +++ b/src/libs/timeline/qml/RangeDetails.qml @@ -178,7 +178,8 @@ Item { height: 18 y: 2 verticalAlignment: Text.AlignVCenter - width: parent.width + anchors.left: parent.left + anchors.right: editIcon.left color: "white" renderType: Text.NativeRendering elide: Text.ElideRight From b1ee6ee80cc50929374a6f051151ed144c4f2d80 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 1 Apr 2015 16:49:38 +0200 Subject: [PATCH 04/38] QmlProfiler: Show a message when V8 profiler is not supported People frequently wonder why the V8 pane is empty and disabled. This change makes it more explicit. Change-Id: I381bff072840dde1fdd038b3d00dd3a400261bc9 Reviewed-by: Joerg Bornemann Reviewed-by: Eike Ziller --- .../qmlprofiler/qmlprofilerstatewidget.cpp | 53 +++++++++---------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp b/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp index 4fe735257ae..9d4dc87c220 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp @@ -187,57 +187,52 @@ void QmlProfilerStateWidget::paintEvent(QPaintEvent *event) } -void QmlProfilerStateWidget::updateDisplay() +void QmlProfilerStateWidget::showText(const QString &text, bool showProgress) { - // When datamodel is acquiring data - if (!d->loadingDone && !d->emptyList && !d->appKilled) { - setVisible(true); - d->text->setText(tr("Loading data")); + setVisible(true); + if (showProgress) { if (d->isRecording) { d->isRecording = false; d->estimatedProfilingTime = d->profilingTimer.elapsed(); emit newTimeEstimation(d->estimatedProfilingTime); } d->progressBar->setValue(d->m_modelManager->progress() * 1000); - d->progressBar->setVisible(true); - resize(300,70); - reposition(); + } + d->progressBar->setVisible(showProgress); + d->text->setText(text); + resize(showProgress ? 300 : 200, 70); + reposition(); +} + +void QmlProfilerStateWidget::updateDisplay() +{ + // When datamodel is acquiring data + if (!d->loadingDone && !d->emptyList && !d->appKilled) { + showText(tr("Loading data"), true); return; } // When application is being profiled if (d->isRecording) { - setVisible(true); - d->progressBar->setVisible(false); - d->text->setText(tr("Profiling application")); - resize(200,70); - reposition(); + showText(tr("Profiling application")); return; } // After profiling, there is an empty trace if (d->traceAvailable && d->loadingDone && d->emptyList) { - setVisible(true); - d->progressBar->setVisible(false); - d->text->setText(tr("No QML events recorded")); - resize(200,70); - reposition(); + showText(tr("No QML events recorded")); + return; + } + + // View is not supported for this kind of application + if (d->traceAvailable && d->loadingDone && !parentWidget()->isEnabled()) { + showText(tr("Not supported for this application")); return; } // Application died before all data could be read if (!d->loadingDone && !d->emptyList && d->appKilled) { - setVisible(true); - d->text->setText(tr("Application stopped before loading all data")); - if (d->isRecording) { - d->isRecording = false; - d->estimatedProfilingTime = d->profilingTimer.elapsed(); - emit newTimeEstimation(d->estimatedProfilingTime); - } - d->progressBar->setValue(d->m_modelManager->progress() * 1000); - d->progressBar->setVisible(true); - resize(300,70); - reposition(); + showText(tr("Application stopped before loading all data"), true); return; } From 879bb9adcf9a73f542af46adb44ccf58407fb3c8 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 2 Apr 2015 12:27:19 +0200 Subject: [PATCH 05/38] Debugger: Remove comment on broken GDB 7.2 We require 7.5.1 now, so the case is uninteresting. Change-Id: I40bf1c3d531b83998a45e7476ed48397b23b4ae6 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/qttypes.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 28489889ebb..59a0829d9d5 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -549,27 +549,6 @@ def qdump__QFiniteStack(d, value): if d.isExpanded(): d.putPlotData(value["_array"], size, d.templateArgument(value.type, 0)) -# Stock gdb 7.2 seems to have a problem with types here: -# -# echo -e "namespace N { struct S { enum E { zero, one, two }; }; }\n"\ -# "int main() { N::S::E x = N::S::one;\n return x; }" >> main.cpp -# g++ -g main.cpp -# gdb-7.2 -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \ -# -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q' -# gdb-7.1 -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \ -# -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q' -# gdb-cvs -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \ -# -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q' -# -# gives as of 2010-11-02 -# -# type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n -# Traceback (most recent call last): File "", line 1, -# in RuntimeError: No type named N::S::E. -# type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n N::S::E -# type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n N::S::E -# -# i.e. there's something broken in stock 7.2 that is was ok in 7.1 and is ok later. def qdump__QFlags(d, value): i = value["i"] From e152e06f429b72c4e66243f9da44731c2963cef3 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 2 Apr 2015 12:30:10 +0200 Subject: [PATCH 06/38] QmlProfiler: Fix missing declaration Change-Id: If783fe330bccd19140dd916c42dfe7f424b68a85 Reviewed-by: Ulf Hermann --- src/plugins/qmlprofiler/qmlprofilerstatewidget.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/qmlprofiler/qmlprofilerstatewidget.h b/src/plugins/qmlprofiler/qmlprofilerstatewidget.h index 7fbde30aa1f..9272cce1b01 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatewidget.h +++ b/src/plugins/qmlprofiler/qmlprofilerstatewidget.h @@ -48,6 +48,7 @@ public: ~QmlProfilerStateWidget(); private slots: + void showText(const QString &text, bool showProgress = false); void updateDisplay(); void dataStateChanged(); void profilerStateChanged(); From 3e82dcad4435a9c0747f6880aaa7e0a968156780 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 2 Apr 2015 12:28:55 +0200 Subject: [PATCH 07/38] Cdbext: Dump "(null)" for an uninitialized QTimeZone. Change-Id: I13c0541bad047aa872bdb04f50e6cd0557a40f1a Reviewed-by: Christian Stenger --- src/libs/qtcreatorcdbext/symbolgroupvalue.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index 17df7e30c2c..a8fef4a3a3b 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -2212,7 +2212,9 @@ static bool dumpQTime(const SymbolGroupValue &v, std::wostream &str, int *encodi static bool dumpQTimeZone(const SymbolGroupValue &v, std::wostream &str, int *encoding) { - return dumpQByteArrayFromQPrivateClass(v, QPDM_qSharedDataPadded, SymbolGroupValue::pointerSize(), str, encoding); + if (!dumpQByteArrayFromQPrivateClass(v, QPDM_qSharedDataPadded, SymbolGroupValue::pointerSize(), str, encoding)) + str << L"(null)"; + return true; } // Convenience to dump a QTimeZone from the unexported private class of a Qt class. From 3658bdac898c94a10eef2f04546c459eab424a5c Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 1 Apr 2015 17:19:43 +0200 Subject: [PATCH 08/38] Debugger: Use primitive internal widget instead of matplotview This practically removes any functionality beyond plain plot display, but does that at least reliably, cross-platform, without dependency on 3rd party python packages. Change-Id: Iaff2f78595394522f32264c642df20dd48b83f8b Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 247 +++++++----------------- share/qtcreator/debugger/gdbbridge.py | 2 - share/qtcreator/debugger/qttypes.py | 17 +- share/qtcreator/debugger/stdtypes.py | 8 +- src/plugins/debugger/debuggerprotocol.h | 3 +- src/plugins/debugger/imageviewer.cpp | 85 +++++++- src/plugins/debugger/imageviewer.h | 25 ++- src/plugins/debugger/watchdata.cpp | 57 +++++- src/plugins/debugger/watchdata.h | 6 + src/plugins/debugger/watchhandler.cpp | 202 +++++++++++-------- 10 files changed, 356 insertions(+), 296 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 584c35e1389..78f48db03d6 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -36,13 +36,6 @@ import re import time import importlib -try: - import subprocess - hasSubprocess = True -except: - hasSubprocess = False - hasPlot = False - if sys.version_info[0] >= 3: xrange = range toInteger = int @@ -105,81 +98,53 @@ WatchpointAtExpression, \ BreakpointOnQmlSignalEmit, \ BreakpointAtJavaScriptThrow, \ = range(0, 14) -# -# matplot based display for array-like structures. -# -try: - import matplotlib - hasPlot = True -except: - hasPlot = False -if hasSubprocess and hasPlot: - matplotFigure = {} - matplotCount = 0 - matplotProc = None - devNull = None +# Encodings. Keep that synchronized with DebuggerEncoding in debuggerprotocol.h +Unencoded8Bit, \ +Base64Encoded8BitWithQuotes, \ +Base64Encoded16BitWithQuotes, \ +Base64Encoded32BitWithQuotes, \ +Base64Encoded16Bit, \ +Base64Encoded8Bit, \ +Hex2EncodedLatin1, \ +Hex4EncodedLittleEndian, \ +Hex8EncodedLittleEndian, \ +Hex2EncodedUtf8, \ +Hex8EncodedBigEndian, \ +Hex4EncodedBigEndian, \ +Hex4EncodedLittleEndianWithoutQuotes, \ +Hex2EncodedLocal8Bit, \ +JulianDate, \ +MillisecondsSinceMidnight, \ +JulianDateAndMillisecondsSinceMidnight, \ +Hex2EncodedInt1, \ +Hex2EncodedInt2, \ +Hex2EncodedInt4, \ +Hex2EncodedInt8, \ +Hex2EncodedUInt1, \ +Hex2EncodedUInt2, \ +Hex2EncodedUInt4, \ +Hex2EncodedUInt8, \ +Hex2EncodedFloat4, \ +Hex2EncodedFloat8, \ +IPv6AddressAndHexScopeId, \ +Hex2EncodedUtf8WithoutQuotes, \ +DateTimeInternal \ + = range(30) - def matplotInit(): - global matplotProc - global devNull +# Display modes. Keep that synchronized with DebuggerDisplay in watchutils.h +StopDisplay, \ +DisplayImageData, \ +DisplayUtf16String, \ +DisplayImageFile, \ +DisplayLatin1String, \ +DisplayUtf8String, \ +DisplayPlotData \ + = range(7) - if matplotProc is None: - devNull = open(os.devnull) - # FIXME: That might not be the one we want. - pythonExecutable = sys.executable - matplotProc = subprocess.Popen(args=[pythonExecutable, "-i"], - bufsize=0, stdin=subprocess.PIPE, stdout=devNull, stderr=devNull) - - matplotProc.stdin.write(b"import sys\n") - matplotProc.stdin.write(b"sys.ps1=''\n") - matplotProc.stdin.write(b"from matplotlib import pyplot\n") - matplotProc.stdin.write(b"import time\n") - matplotProc.stdin.write(b"pyplot.ion()\n") - matplotProc.stdin.flush() - - def matplotSend(iname, show, data): - global matplotFigure - global matplotCount - - matplotInit() - - def s(line): - matplotProc.stdin.write(line.encode("latin1")) - matplotProc.stdin.write(b"\n") - sys.stdout.flush() - matplotProc.stdin.flush() - - if show: - s("pyplot.ion()") - if not iname in matplotFigure: - matplotCount += 1 - matplotFigure[iname] = matplotCount - s("pyplot.figure(%s)" % matplotFigure[iname]) - s("pyplot.suptitle('%s')" % iname) - s("data = %s" % data) - s("pyplot.plot([i for i in range(len(data))], data, 'b.-')") - time.sleep(0.2) - s("pyplot.draw()") - matplotProc.stdin.flush() - else: - if iname in matplotFigure: - s("pyplot.figure(%s)" % matplotFigure[iname]) - s("pyplot.close()") - del matplotFigure[iname] - - matplotProc.stdin.flush() - - def matplotQuit(): - global matplotProc - if not matplotProc is None: - matplotProc.stdin.write(b"exit") - matplotProc.kill() - devNull.close() def arrayForms(): - global hasPlot - return [ArrayPlotFormat] if hasPlot else [] + return [ArrayPlotFormat] def mapForms(): return [CompactMapFormat] @@ -612,10 +577,7 @@ class DumperBase: self.putNumChild(0) self.putValue(mem, encodingType, elided=elided) - if displayFormat == Latin1StringFormat \ - or displayFormat == Utf8StringFormat: - self.putDisplay(StopDisplay) - elif displayFormat == SeparateLatin1StringFormat \ + if displayFormat == SeparateLatin1StringFormat \ or displayFormat == SeparateUtf8StringFormat: self.putField("editformat", displayType) elided, shown = self.computeLimit(bytelen, 100000) @@ -916,14 +878,14 @@ class DumperBase: def putCStyleArray(self, value): arrayType = value.type.unqualified() innerType = value[0].type + innerTypeName = str(innerType.unqualified()) ts = innerType.sizeof - #self.putAddress(value.address) + try: self.putValue("@0x%x" % self.addressOf(value), priority = -1) except: self.putEmptyValue() self.putType(arrayType) - self.putNumChild(1) try: p = self.addressOf(value) @@ -933,20 +895,20 @@ class DumperBase: displayFormat = self.currentItemFormat() n = int(arrayType.sizeof / ts) - if p and self.tryPutSimpleFormattedPointer(p, str(arrayType), displayFormat, arrayType.sizeof): - self.putNumChild(n) - pass - elif displayFormat is None: - innerTypeName = str(innerType.unqualified()) - blob = self.readMemory(self.addressOf(value), arrayType.sizeof) + if displayFormat != RawFormat: if innerTypeName == "char": # Use Latin1 as default for char []. + blob = self.readMemory(self.addressOf(value), arrayType.sizeof) self.putValue(blob, Hex2EncodedLatin1) elif innerTypeName == "wchar_t": + blob = self.readMemory(self.addressOf(value), arrayType.sizeof) if innerType.sizeof == 2: self.putValue(blob, Hex4EncodedLittleEndian) else: self.putValue(blob, Hex8EncodedLittleEndian) + elif p: + self.tryPutSimpleFormattedPointer(p, arrayType, innerTypeName, displayFormat, arrayType.sizeof) + self.putNumChild(n) if self.isExpanded(): try: @@ -958,17 +920,7 @@ class DumperBase: with Children(self, childType=innerType): self.putFields(value) - if hasPlot and self.isSimpleType(innerType): - show = displayFormat == ArrayPlotFormat - iname = self.currentIName - data = [] - if show: - base = self.createPointerValue(p, innerType) - data = [str(base[i]) for i in range(0, n)] - matplotSend(iname, show, data) - else: - #self.putValue(self.currentValue.value + " (not plottable)") - self.putField("plottable", "0") + self.putPlotDataHelper(p, n, innerType) def cleanAddress(self, addr): if addr is None: @@ -1038,29 +990,23 @@ class DumperBase: data = self.readMemory(base, shown) self.putValue(data, Hex2EncodedLatin1, elided=elided) - def putDisplay(self, editFormat, value = None, cmd = None): + def putDisplay(self, editFormat, value): self.put('editformat="%s",' % editFormat) - if cmd is None: - if not value is None: - self.put('editvalue="%s",' % value) - else: - self.put('editvalue="%s|%s",' % (cmd, value)) + self.put('editvalue="%s",' % value) # This is shared by pointer and array formatting. - def tryPutSimpleFormattedPointer(self, value, typeName, displayFormat, limit): - if displayFormat == AutomaticFormat and typeName == "char": + def tryPutSimpleFormattedPointer(self, value, typeName, innerTypeName, displayFormat, limit): + if displayFormat == AutomaticFormat and innerTypeName == "char": # Use Latin1 as default for char *. self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedLatin1, elided=elided) - self.putDisplay(StopDisplay) return True if displayFormat == Latin1StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedLatin1, elided=elided) - self.putDisplay(StopDisplay) return True if displayFormat == SeparateLatin1StringFormat: @@ -1074,7 +1020,6 @@ class DumperBase: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedUtf8, elided=elided) - self.putDisplay(StopDisplay) return True if displayFormat == SeparateUtf8StringFormat: @@ -1088,21 +1033,18 @@ class DumperBase: self.putType(typeName) (elided, data) = self.encodeCArray(value, 1, limit) self.putValue(data, Hex2EncodedLocal8Bit, elided=elided) - self.putDisplay(StopDisplay) return True if displayFormat == Utf16StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 2, limit) self.putValue(data, Hex4EncodedLittleEndian, elided=elided) - self.putDisplay(StopDisplay) return True if displayFormat == Ucs4StringFormat: self.putType(typeName) (elided, data) = self.encodeCArray(value, 4, limit) self.putValue(data, Hex8EncodedLittleEndian, elided=elided) - self.putDisplay(StopDisplay) return True return False @@ -1155,7 +1097,7 @@ class DumperBase: if displayFormat == SeparateLatin1StringFormat \ or displayFormat == SeparateUtf8StringFormat: limit = 1000000 - if self.tryPutSimpleFormattedPointer(value, typeName, displayFormat, limit): + if self.tryPutSimpleFormattedPointer(value, typeName, innerTypeName, displayFormat, limit): self.putNumChild(0) return @@ -1555,22 +1497,18 @@ class DumperBase: self.putArrayData(addr, n, self.lookupType(typeName)) self.putAddress(addr) - def putPlotData(self, base, n, typeobj): + def putPlotDataHelper(self, base, n, innerType): + if self.currentItemFormat() == ArrayPlotFormat and self.isSimpleType(innerType): + enc = self.simpleEncoding(innerType) + if enc: + self.putField("editencoding", enc) + self.putField("editvalue", self.readMemory(base, n * innerType.sizeof)) + self.putField("editformat", DisplayPlotData) + + def putPlotData(self, base, n, innerType): + self.putPlotDataHelper(base, n, innerType) if self.isExpanded(): - self.putArrayData(base, n, typeobj) - if hasPlot: - if self.isSimpleType(typeobj): - show = self.currentItemFormat() == ArrayPlotFormat - iname = self.currentIName - data = [] - if show: - base = self.createPointerValue(base, typeobj) - data = [str(base[i]) for i in range(0, toInteger(n))] - matplotSend(iname, show, data) - else: - #self.putValue(self.currentValue.value + " (not plottable)") - self.putValue(self.currentValue.value) - self.putField("plottable", "0") + self.putArrayData(base, n, innerType) def putSpecialArgv(self, value): """ @@ -1757,10 +1695,6 @@ class DumperBase: self.qqEditable = {} self.typeCache = {} - if hasPlot: # Hack for generic array type. [] is used as "type" name. - self.qqDumpers['[]'] = "" - self.qqFormats['[]'] = arrayForms() - for mod in self.dumpermodules: m = importlib.import_module(mod) dic = m.__dict__ @@ -1981,48 +1915,3 @@ class DumperBase: return items -# Some "Enums" - -# Encodings. Keep that synchronized with DebuggerEncoding in debuggerprotocol.h -Unencoded8Bit, \ -Base64Encoded8BitWithQuotes, \ -Base64Encoded16BitWithQuotes, \ -Base64Encoded32BitWithQuotes, \ -Base64Encoded16Bit, \ -Base64Encoded8Bit, \ -Hex2EncodedLatin1, \ -Hex4EncodedLittleEndian, \ -Hex8EncodedLittleEndian, \ -Hex2EncodedUtf8, \ -Hex8EncodedBigEndian, \ -Hex4EncodedBigEndian, \ -Hex4EncodedLittleEndianWithoutQuotes, \ -Hex2EncodedLocal8Bit, \ -JulianDate, \ -MillisecondsSinceMidnight, \ -JulianDateAndMillisecondsSinceMidnight, \ -Hex2EncodedInt1, \ -Hex2EncodedInt2, \ -Hex2EncodedInt4, \ -Hex2EncodedInt8, \ -Hex2EncodedUInt1, \ -Hex2EncodedUInt2, \ -Hex2EncodedUInt4, \ -Hex2EncodedUInt8, \ -Hex2EncodedFloat4, \ -Hex2EncodedFloat8, \ -IPv6AddressAndHexScopeId, \ -Hex2EncodedUtf8WithoutQuotes, \ -DateTimeInternal \ - = range(30) - -# Display modes. Keep that synchronized with DebuggerDisplay in watchutils.h -StopDisplay, \ -DisplayImageData, \ -DisplayUtf16String, \ -DisplayImageFile, \ -DisplayLatin1String, \ -DisplayUtf8String \ - = range(6) - - diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index e8f07d68f38..06ec7954479 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1615,8 +1615,6 @@ class Dumper(DumperBase): self.qmlBreakpoints.append(Resolver(self, args)) def exitGdb(self, _): - if hasPlot: - matplotQuit() gdb.execute("quit") def loadDumpers(self, args): diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 59a0829d9d5..8323314d346 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -62,14 +62,12 @@ def qdump__QByteArray(d, value): elided, p = d.encodeByteArrayHelper(d.extractPointer(value), d.displayStringLimit) displayFormat = d.currentItemFormat() if displayFormat == AutomaticFormat or displayFormat == Latin1StringFormat: - d.putDisplay(StopDisplay) d.putValue(p, Hex2EncodedLatin1, elided=elided) elif displayFormat == SeparateLatin1StringFormat: d.putValue(p, Hex2EncodedLatin1, elided=elided) d.putField("editformat", DisplayLatin1String) d.putField("editvalue", d.encodeByteArray(value, limit=100000)) elif displayFormat == Utf8StringFormat: - d.putDisplay(StopDisplay) d.putValue(p, Hex2EncodedUtf8, elided=elided) elif displayFormat == SeparateUtf8StringFormat: d.putValue(p, Hex2EncodedUtf8, elided=elided) @@ -546,8 +544,7 @@ def qdump__QFiniteStack(d, value): size = int(value["_size"]) d.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000) d.putItemCount(size) - if d.isExpanded(): - d.putPlotData(value["_array"], size, d.templateArgument(value.type, 0)) + d.putPlotData(value["_array"], size, d.templateArgument(value.type, 0)) def qdump__QFlags(d, value): @@ -847,9 +844,7 @@ def qdump__QImage(d, value): d.putType("void *") displayFormat = d.currentItemFormat() - if displayFormat == SimpleFormat: - d.putDisplay(StopDisplay) - elif displayFormat == SeparateFormat: + if displayFormat == SeparateFormat: # This is critical for performance. Writing to an external # file using the following is faster when using GDB. # file = tempfile.mkstemp(prefix="gdbpy_") @@ -1743,9 +1738,7 @@ def qdump__QString(d, value): data, size, alloc = d.stringData(value) d.putNumChild(size) displayFormat = d.currentItemFormat() - if displayFormat == SimpleFormat: - d.putDisplay(StopDisplay) - elif displayFormat == SeparateFormat: + if displayFormat == SeparateFormat: d.putField("editformat", DisplayUtf16String) d.putField("editvalue", d.encodeString(value, limit=100000)) if d.isExpanded(): @@ -1897,9 +1890,7 @@ def qdump__QUrl(d, value): d.putValue(url, Hex4EncodedLittleEndian) displayFormat = d.currentItemFormat() - if displayFormat == SimpleFormat: - d.putDisplay(StopDisplay) - elif displayFormat == SeparateFormat: + if displayFormat == SeparateFormat: d.putField("editformat", DisplayUtf16String) d.putField("editvalue", url) diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index 54a6cc34d71..eb34ac41594 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -711,15 +711,15 @@ def qdump__std__vector(d, value): d.checkPointer(alloc) d.putItemCount(size) - if d.isExpanded(): - if isBool: + if isBool: + if d.isExpanded(): with Children(d, size, maxNumChild=10000, childType=type): base = d.pointerValue(start) for i in d.childRange(): q = base + int(i / 8) d.putBoolItem(str(i), (int(d.extractPointer(q)) >> (i % 8)) & 1) - else: - d.putPlotData(start, size, type) + else: + d.putPlotData(start, size, type) def qdump__std__vector__QNX(d, value): innerType = d.templateArgument(value.type, 0) diff --git a/src/plugins/debugger/debuggerprotocol.h b/src/plugins/debugger/debuggerprotocol.h index 3214fdb76e0..7bccb4356ba 100644 --- a/src/plugins/debugger/debuggerprotocol.h +++ b/src/plugins/debugger/debuggerprotocol.h @@ -246,7 +246,8 @@ enum DebuggerDisplay { DisplayUtf16String = 2, DisplayImageFile = 3, DisplayLatin1String = 4, - DisplayUtf8String = 5 + DisplayUtf8String = 5, + DisplayPlotData = 6 }; // Decode string data as returned by the dumper helpers. QString decodeData(const QByteArray &baIn, int encoding); diff --git a/src/plugins/debugger/imageviewer.cpp b/src/plugins/debugger/imageviewer.cpp index 898ef7069a2..cc3a614124b 100644 --- a/src/plugins/debugger/imageviewer.cpp +++ b/src/plugins/debugger/imageviewer.cpp @@ -114,11 +114,15 @@ ImageViewer::ImageViewer(QWidget *parent) connect(m_imageWidget, &ImageWidget::clicked, this, &ImageViewer::clicked); } -void ImageViewer::setImage(const QImage &i) +void ImageViewer::setImage(const QImage &image) { - m_imageWidget->setImage(i); - m_info = tr("Size: %1x%2, %3 byte, format: %4, depth: %5") - .arg(i.width()).arg(i.height()).arg(i.byteCount()).arg(i.format()).arg(i.depth()); + m_imageWidget->setImage(image); + clicked(QString()); +} + +void ImageViewer::setInfo(const QString &info) +{ + m_info = info; clicked(QString()); } @@ -165,4 +169,77 @@ void ImageViewer::contextMenuEvent(QContextMenuEvent *ev) openImageViewer(image); } + +// +// +// + +PlotViewer::PlotViewer(QWidget *parent) + : QWidget(parent) +{ +} + +void PlotViewer::setData(const PlotViewer::Data &data) +{ + m_data = data; + update(); +} + +void PlotViewer::setInfo(const QString &description) +{ + m_info = description; + update(); +} + +void PlotViewer::paintEvent(QPaintEvent *) +{ + QPainter pain(this); + + const int n = int(m_data.size()); + const int w = width(); + const int h = height(); + const int b = 10; // Border width. + + pain.fillRect(rect(), Qt::white); + + double ymin = 0; + double ymax = 0; + for (int i = 0; i < n; ++i) { + const double v = m_data.at(i); + if (v < ymin) + ymin = v; + else if (v > ymax) + ymax = v; + } + + const double d = ymin == ymax ? (h / 2 - b) : (ymax - ymin); + const int k = 1; // Length of cross marker arms. + + for (int i = 0; i + 1 < n; ++i) { + // Lines between points. + const int x1 = b + i * (w - 2 * b) / (n - 1); + const int x2 = b + (i + 1) * (w - 2 * b) / (n - 1); + const int y1 = h - (b + int((m_data[i] - ymin) * (h - 2 * b) / d)); + const int y2 = h - (b + int((m_data[i + 1] - ymin) * (h - 2 * b) / d)); + pain.drawLine(x1, y1, x2, y2); + + if (i == 0) { + // Little cross marker on first point + pain.drawLine(x1 - k, y1 - k, x1 + k, y1 + k); + pain.drawLine(x1 + k, y1 - k, x1 - k, y1 + k); + } + // ... and all subsequent points. + pain.drawLine(x2 - k, y2 - k, x2 + k, y2 + k); + pain.drawLine(x2 + k, y2 - k, x2 - k, y2 + k); + } + + if (n) { + pain.drawText(10, 10, + QString::fromLatin1("%5 items. X: %1..%2, Y: %3...%4").arg(0).arg(n).arg(ymin).arg(ymax).arg(n)); + } else { + pain.drawText(10, 10, + QString::fromLatin1("Container is empty")); + } +} + #include "imageviewer.moc" diff --git a/src/plugins/debugger/imageviewer.h b/src/plugins/debugger/imageviewer.h index 668453daa59..5ddee6f022b 100644 --- a/src/plugins/debugger/imageviewer.h +++ b/src/plugins/debugger/imageviewer.h @@ -33,6 +33,8 @@ #include +#include + QT_BEGIN_NAMESPACE class QScrollArea; class QLabel; @@ -49,19 +51,36 @@ class ImageViewer : public QWidget public: explicit ImageViewer(QWidget *parent = 0); - void setImage(const QImage &); + void setImage(const QImage &image); + void setInfo(const QString &description); protected: void contextMenuEvent(QContextMenuEvent *); -private slots: +private: void clicked(const QString &); -private: QScrollArea *m_scrollArea; ImageWidget *m_imageWidget; QLabel *m_infoLabel; QString m_info; }; +class PlotViewer : public QWidget +{ + Q_OBJECT +public: + explicit PlotViewer(QWidget *parent = 0); + + typedef std::vector Data; + void setData(const Data &data); + void setInfo(const QString &description); + + void paintEvent(QPaintEvent *ev); + +private: + Data m_data; + QString m_info; +}; + #endif // IMAGEVIEWER_H diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp index 098051d9e9e..6d468352274 100644 --- a/src/plugins/debugger/watchdata.cpp +++ b/src/plugins/debugger/watchdata.cpp @@ -122,6 +122,7 @@ WatchData::WatchData() : id(0), state(InitialState), editformat(StopDisplay), + editencoding(Unencoded8Bit), address(0), origaddr(0), size(0), @@ -552,14 +553,12 @@ void parseChildrenData(const WatchData &data0, const GdbMi &item, GdbMi children = item["children"]; data.updateType(item["type"]); - GdbMi mi = item["editvalue"]; - if (mi.isValid()) - data.editvalue = mi.data(); - mi = item["editformat"]; - data.editformat = DebuggerDisplay(mi.toInt()); + data.editvalue = item["editvalue"].data(); + data.editformat = DebuggerDisplay(item["editformat"].toInt()); + data.editencoding = DebuggerEncoding(item["editencoding"].toInt()); - mi = item["valueelided"]; + GdbMi mi = item["valueelided"]; if (mi.isValid()) data.elided = mi.toInt(); @@ -658,6 +657,52 @@ void parseWatchData(const WatchData &data0, const GdbMi &input, parseChildrenData(data0, input, itemHandler, childHandler, arrayDecoder); } +template +void readNumericVectorHelper(std::vector *v, const QByteArray &ba) +{ + const T *p = (const T *) ba.data(); + std::copy(p, p + ba.size() / sizeof(T), std::back_insert_iterator >(*v)); +} + +void readNumericVector(std::vector *v, const QByteArray &rawData, DebuggerEncoding encoding) +{ + switch (encoding) { + case Hex2EncodedInt1: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedInt2: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedInt4: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedInt8: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedUInt1: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedUInt2: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedUInt4: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedUInt8: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedFloat4: + readNumericVectorHelper(v, rawData); + break; + case Hex2EncodedFloat8: + readNumericVectorHelper(v, rawData); + break; + default: + qDebug() << "ENCODING ERROR: " << encoding; + } + +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h index 5aa68af9652..58a61609fc7 100644 --- a/src/plugins/debugger/watchdata.h +++ b/src/plugins/debugger/watchdata.h @@ -37,6 +37,7 @@ #include #include +#include namespace Debugger { namespace Internal { @@ -113,6 +114,7 @@ public: QString value; // Displayed value QByteArray editvalue; // Displayed value DebuggerDisplay editformat; // Format of displayed value + DebuggerEncoding editencoding; // Encoding of displayed value QByteArray type; // Type for further processing QString displayedType; // Displayed type (optional) quint64 address; // Displayed address of the actual object @@ -134,6 +136,10 @@ void decodeArrayData(std::function itemHandler, const QByteArray &rawData, int encoding); +void readNumericVector(std::vector *, + const QByteArray &rawData, + DebuggerEncoding encoding); + void parseChildrenData(const WatchData &parent, const GdbMi &child, std::function itemHandler, std::function childHandler, diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 9ac7dbbedaa..cc27ae30c1d 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -53,11 +53,13 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -109,6 +111,52 @@ static void saveWatchers() setSessionValue("Watchers", WatchHandler::watchedExpressions()); } +static void loadFormats() +{ + QVariant value = sessionValue("DefaultFormats"); + QMapIterator it(value.toMap()); + while (it.hasNext()) { + it.next(); + if (!it.key().isEmpty()) + theTypeFormats.insert(it.key().toUtf8(), it.value().toInt()); + } + + value = sessionValue("IndividualFormats"); + it = QMapIterator(value.toMap()); + while (it.hasNext()) { + it.next(); + if (!it.key().isEmpty()) + theIndividualFormats.insert(it.key().toUtf8(), it.value().toInt()); + } +} + +static void saveFormats() +{ + QMap formats; + QHashIterator it(theTypeFormats); + while (it.hasNext()) { + it.next(); + const int format = it.value(); + if (format != AutomaticFormat) { + const QByteArray key = it.key().trimmed(); + if (!key.isEmpty()) + formats.insert(QString::fromLatin1(key), format); + } + } + setSessionValue("DefaultFormats", formats); + + formats.clear(); + it = QHashIterator(theIndividualFormats); + while (it.hasNext()) { + it.next(); + const int format = it.value(); + const QByteArray key = it.key().trimmed(); + if (!key.isEmpty()) + formats.insert(QString::fromLatin1(key), format); + } + setSessionValue("IndividualFormats", formats); +} + /////////////////////////////////////////////////////////////////////// // // SeparatedView @@ -126,17 +174,29 @@ public: setWindowTitle(WatchHandler::tr("Debugger - Qt Creator")); QVariant geometry = sessionValue("DebuggerSeparateWidgetGeometry"); - if (geometry.isValid()) - setGeometry(geometry.toRect()); + if (geometry.isValid()) { + QRect rc = geometry.toRect(); + if (rc.width() < 200) + rc.setWidth(200); + if (rc.height() < 200) + rc.setHeight(200); + setGeometry(rc); + } } - ~SeparatedView() + void saveGeometry() { setSessionValue("DebuggerSeparateWidgetGeometry", geometry()); } + ~SeparatedView() + { + saveGeometry(); + } + void removeObject(const QByteArray &key) { + saveGeometry(); if (QWidget *w = findWidget(key)) { removeTab(indexOf(w)); sanitize(); @@ -145,9 +205,11 @@ public: void closeTab(int index) { + saveGeometry(); if (QObject *o = widget(index)) { QByteArray iname = o->property(INameProperty).toByteArray(); theIndividualFormats.remove(iname); + saveFormats(); } removeTab(index); sanitize(); @@ -170,7 +232,7 @@ public: return 0; } - template T *prepareObject(const QByteArray &key, const QString &title) + template T *prepareObject(const QByteArray &key, const QString &tabName) { T *t = 0; if (QWidget *w = findWidget(key)) { @@ -181,7 +243,7 @@ public: if (!t) { t = new T; t->setProperty(KeyProperty, key); - addTab(t, title); + addTab(t, tabName); } setCurrentWidget(t); @@ -218,8 +280,9 @@ public: void insertItem(WatchItem *item); void reexpandItems(); - void showEditValue(const WatchData &data); - void setFormat(const QByteArray &type, int format); + void showEditValue(const WatchItem *item); + void setTypeFormat(const QByteArray &type, int format); + void setIndividualFormat(const QByteArray &iname, int format); QString removeNamespaces(QString str) const; @@ -884,16 +947,12 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role break; case LocalsTypeFormatRole: - setFormat(item->type, value.toInt()); + setTypeFormat(item->type, value.toInt()); m_engine->updateWatchItem(item); break; case LocalsIndividualFormatRole: { - const int format = value.toInt(); - if (format == AutomaticFormat) - theIndividualFormats.remove(item->iname); - else - theIndividualFormats[item->iname] = format; + setIndividualFormat(item->iname, value.toInt()); m_engine->updateWatchItem(item); break; } @@ -1010,7 +1069,7 @@ DisplayFormats WatchItem::typeFormatList() const formats << watchModel()->m_reportedTypeFormats.value(t); if (t.contains(QLatin1Char(']'))) - formats << watchModel()->m_reportedTypeFormats.value(QLatin1String("[]")); + formats.append(ArrayPlotFormat); // Fixed artificial string and pointer types. if (origaddr || isPointerType(type)) { @@ -1132,7 +1191,7 @@ void WatchModel::reinsertAllData() emit inameIsExpanded(parent->iname); emit itemIsExpanded(indexFromItem(parent)); } - showEditValue(data); + showEditValue(newItem); // FIXME: Needed? } } @@ -1192,7 +1251,7 @@ void WatchModel::insertItem(WatchItem *item) const int row = findInsertPosition(parent->children(), item); parent->insertChild(row, item); - item->walkTree([this](TreeItem *sub) { showEditValue(*static_cast(sub)); }); + item->walkTree([this](TreeItem *sub) { showEditValue(static_cast(sub)); }); } void WatchModel::reexpandItems() @@ -1326,20 +1385,20 @@ static void swapEndian(char *d, int nchar) } } -void WatchModel::showEditValue(const WatchData &data) +void WatchModel::showEditValue(const WatchItem *item) { - const QByteArray key = data.address ? data.hexAddress() : data.iname; - switch (data.editformat) { + const QByteArray key = item->address ? item->hexAddress() : item->iname; + switch (item->editformat) { case StopDisplay: - m_separatedView->removeObject(data.iname); + m_separatedView->removeObject(key); break; case DisplayImageData: case DisplayImageFile: { // QImage int width = 0, height = 0, nbytes = 0, format = 0; QByteArray ba; uchar *bits = 0; - if (data.editformat == DisplayImageData) { - ba = QByteArray::fromHex(data.editvalue); + if (item->editformat == DisplayImageData) { + ba = QByteArray::fromHex(item->editvalue); QTC_ASSERT(ba.size() > 16, return); const int *header = (int *)(ba.data()); if (!ba.at(0) && !ba.at(1)) // Check on 'width' for Python dumpers returning 4-byte swapped-data. @@ -1349,8 +1408,8 @@ void WatchModel::showEditValue(const WatchData &data) height = header[1]; nbytes = header[2]; format = header[3]; - } else if (data.editformat == DisplayImageFile) { - QTextStream ts(data.editvalue); + } else if (item->editformat == DisplayImageFile) { + QTextStream ts(item->editvalue); QString fileName; ts >> width >> height >> nbytes >> format >> fileName; QFile f(fileName); @@ -1365,33 +1424,45 @@ void WatchModel::showEditValue(const WatchData &data) QTC_ASSERT(0 < format && format < 32, return); QImage im(width, height, QImage::Format(format)); std::memcpy(im.bits(), bits, nbytes); - const QString title = data.address ? - tr("%1 Object at %2").arg(QLatin1String(data.type), - QLatin1String(data.hexAddress())) : - tr("%1 Object at Unknown Address").arg(QLatin1String(data.type)); - ImageViewer *v = m_separatedView->prepareObject(key, title); - v->setProperty(INameProperty, data.iname); + ImageViewer *v = m_separatedView->prepareObject(key, item->name); + v->setProperty(INameProperty, item->iname); + v->setInfo(item->address ? + tr("%1 Object at %2").arg(QLatin1String(item->type), + QLatin1String(item->hexAddress())) : + tr("%1 Object at Unknown Address").arg(QLatin1String(item->type)) + + QLatin1String(" ") + + ImageViewer::tr("Size: %1x%2, %3 byte, format: %4, depth: %5") + .arg(width).arg(height).arg(nbytes).arg(im.format()).arg(im.depth()) + ); v->setImage(im); break; } case DisplayUtf16String: case DisplayLatin1String: case DisplayUtf8String: { // String data. - QByteArray ba = QByteArray::fromHex(data.editvalue); + QByteArray ba = QByteArray::fromHex(item->editvalue); QString str; - if (data.editformat == DisplayUtf16String) + if (item->editformat == DisplayUtf16String) str = QString::fromUtf16((ushort *)ba.constData(), ba.size()/2); - else if (data.editformat == DisplayLatin1String) + else if (item->editformat == DisplayLatin1String) str = QString::fromLatin1(ba.constData(), ba.size()); - else if (data.editformat == DisplayUtf8String) + else if (item->editformat == DisplayUtf8String) str = QString::fromUtf8(ba.constData(), ba.size()); - QTextEdit *t = m_separatedView->prepareObject(key, data.name); - t->setProperty(INameProperty, data.iname); + QTextEdit *t = m_separatedView->prepareObject(key, item->name); + t->setProperty(INameProperty, item->iname); t->setText(str); break; } + case DisplayPlotData: { // Plots + std::vector data; + readNumericVector(&data, QByteArray::fromHex(item->editvalue), item->editencoding); + PlotViewer *v = m_separatedView->prepareObject(key, item->name); + v->setProperty(INameProperty, item->iname); + v->setData(data); + break; + } default: - QTC_ASSERT(false, qDebug() << "Display format: " << data.editformat); + QTC_ASSERT(false, qDebug() << "Display format: " << item->editformat); break; } } @@ -1439,52 +1510,6 @@ QStringList WatchHandler::watchedExpressions() return watcherNames; } -static void loadFormats() -{ - QVariant value = sessionValue("DefaultFormats"); - QMapIterator it(value.toMap()); - while (it.hasNext()) { - it.next(); - if (!it.key().isEmpty()) - theTypeFormats.insert(it.key().toUtf8(), it.value().toInt()); - } - - value = sessionValue("IndividualFormats"); - it = QMapIterator(value.toMap()); - while (it.hasNext()) { - it.next(); - if (!it.key().isEmpty()) - theIndividualFormats.insert(it.key().toUtf8(), it.value().toInt()); - } -} - -static void saveFormats() -{ - QMap formats; - QHashIterator it(theTypeFormats); - while (it.hasNext()) { - it.next(); - const int format = it.value(); - if (format != AutomaticFormat) { - const QByteArray key = it.key().trimmed(); - if (!key.isEmpty()) - formats.insert(QString::fromLatin1(key), format); - } - } - setSessionValue("DefaultFormats", formats); - - formats.clear(); - it = QHashIterator(theIndividualFormats); - while (it.hasNext()) { - it.next(); - const int format = it.value(); - const QByteArray key = it.key().trimmed(); - if (!key.isEmpty()) - formats.insert(QString::fromLatin1(key), format); - } - setSessionValue("IndividualFormats", formats); -} - void WatchHandler::saveSessionData() { saveWatchers(); @@ -1537,7 +1562,7 @@ const WatchItem *WatchHandler::findCppLocalVariable(const QString &name) const return 0; } -void WatchModel::setFormat(const QByteArray &type0, int format) +void WatchModel::setTypeFormat(const QByteArray &type0, int format) { const QByteArray type = stripForFormat(type0); if (format == AutomaticFormat) @@ -1548,6 +1573,15 @@ void WatchModel::setFormat(const QByteArray &type0, int format) reinsertAllData(); } +void WatchModel::setIndividualFormat(const QByteArray &iname, int format) +{ + if (format == AutomaticFormat) + theIndividualFormats.remove(iname); + else + theIndividualFormats[iname] = format; + saveFormats(); +} + int WatchHandler::format(const QByteArray &iname) const { int result = AutomaticFormat; From 8548343ef42cd3ac40bab9eb4a314787f716323d Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 2 Apr 2015 14:48:53 +0200 Subject: [PATCH 09/38] Test: Dumper: Fix Compilation and adjust cdb output of "BigInt" test. Change-Id: I8ecfd77cd72e155e291acdc96fcbfd49572c91e3 Reviewed-by: hjk --- tests/auto/debugger/tst_dumpers.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 4a514b588c6..845d1ba063b 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -5044,10 +5044,15 @@ void tst_Dumpers::dumper_data() "qint64 d = c;\n" "QString dummy;\n" "unused(&a, &b, &c, &d, &dummy);\n") - + Check("a", "-1143861252567568256", "@qint64") - + Check("b", "17302882821141983360", "@quint64") - + Check("c", "18446744073709551614", "@quint64") - + Check("d", "-2", "@qint64"); + + CoreProfile() + + Check("a", "-1143861252567568256", "@qint64") % NoCdbEngine + + Check("b", "17302882821141983360", "@quint64") % NoCdbEngine + + Check("c", "18446744073709551614", "@quint64") % NoCdbEngine + + Check("d", "-2", "@qint64") % NoCdbEngine + + Check("a", "-1143861252567568256", "int64") % CdbEngine + + Check("b", "17302882821141983360", "unsigned int64") % CdbEngine + + Check("c", "18446744073709551614", "unsigned int64") % CdbEngine + + Check("d", "-2", "int64") % CdbEngine; QTest::newRow("Hidden") << Data("#include \n", From 02b521a8ff5cf9102fbf468adc07fac5ba4f5d63 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Thu, 2 Apr 2015 13:07:16 +0200 Subject: [PATCH 10/38] Squish: Fix reading tooltips in tst_qml_editor Change-Id: Ie65752d2c8c87c3802c810b98ffe7b122549c762 Reviewed-by: Christian Stenger --- tests/system/shared/editor_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/shared/editor_utils.py b/tests/system/shared/editor_utils.py index 41c10040196..4ba01b058aa 100644 --- a/tests/system/shared/editor_utils.py +++ b/tests/system/shared/editor_utils.py @@ -153,7 +153,7 @@ def verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, e for ty in additionalKeyPresses: type(editor, ty) rect = editor.cursorRect(editor.textCursor()) - expectedToolTip = "{type='%s' visible='1'}" % expectedType + expectedToolTip = "{type='QTipLabel' visible='1'}" # wait for similar tooltips to disappear checkIfObjectExists(expectedToolTip, False, 1000, True) sendEvent("QMouseEvent", editor, QEvent.MouseMove, rect.x+rect.width/2, rect.y+rect.height/2, Qt.NoButton, 0) From 28c06b5b58230ad201fccf012bcb3c9690b92ff1 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 2 Apr 2015 13:19:40 +0200 Subject: [PATCH 11/38] Test: Dumper: Adjust QVector test to cdb output. Change-Id: I2da7f4b21251e1417efaf20813ce260ea286b1f2 Reviewed-by: Christian Stenger --- tests/auto/debugger/tst_dumpers.cpp | 30 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 845d1ba063b..3cbc36bddbc 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -3540,29 +3540,39 @@ void tst_Dumpers::dumper_data() + Check("v1.8999", "[8999]", "80982001", "int") + Check("v2", "<2 items>", "@QVector") - + Check("v2.0", "[0]", "", "Foo") + + Check("v2.0", "[0]", "", "Foo") % NoCdbEngine + + Check("v2.0", "[0]", "class Foo", "Foo") % CdbEngine + Check("v2.0.a", "1", "int") - + Check("v2.1", "[1]", "", "Foo") + + Check("v2.1", "[1]", "", "Foo") % NoCdbEngine + + Check("v2.1", "[1]", "class Foo", "Foo") % CdbEngine + Check("v2.1.a", "2", "int") - + Check("v3", "<2 items>", "FooVector") - + Check("v3.0", "[0]", "", "Foo") + + Check("v3", "<2 items>", "FooVector") % NoCdbEngine + + Check("v3", "<2 items>", "QVector") % CdbEngine + + Check("v3.0", "[0]", "", "Foo") % NoCdbEngine + + Check("v3.0", "[0]", "class Foo", "Foo") % CdbEngine + Check("v3.0.a", "1", "int") - + Check("v3.1", "[1]", "", "Foo") + + Check("v3.1", "[1]", "", "Foo") % NoCdbEngine + + Check("v3.1", "[1]", "class Foo", "Foo") % CdbEngine + Check("v3.1.a", "2", "int") + Check("v4", "<3 items>", "@QVector") - + CheckType("v4.0", "[0]", "Foo") + + CheckType("v4.0", "[0]", "Foo") % NoCdbEngine + + CheckType("v4.0", "[0]", "Foo *") % CdbEngine + Check("v4.0.a", "1", "int") + Check("v4.1", "[1]", "0x0", "Foo *") - + CheckType("v4.2", "[2]", "Foo") + + CheckType("v4.2", "[2]", "Foo") % NoCdbEngine + + CheckType("v4.2", "[2]", "Foo *") % CdbEngine + Check("v4.2.a", "5", "int") + Check("v5", "<2 items>", "@QVector") - + Check("v5.0", "[0]", "1", "bool") - + Check("v5.1", "[1]", "0", "bool") + + Check("v5.0", "[0]", "1", "bool") % NoCdbEngine + + Check("v5.1", "[1]", "0", "bool") % NoCdbEngine + + Check("v5.0", "[0]", "true", "bool") % CdbEngine + + Check("v5.1", "[1]", "false", "bool") % CdbEngine - + CheckType("pv", "@QVector<@QList>") + + CheckType("pv", "@QVector<@QList>") % NoCdbEngine + + CheckType("pv", "QVector > *") % CdbEngine + Check("pv.0", "[0]", "<1 items>", "@QList") + Check("pv.0.0", "[0]", "1", "int") + Check("pv.1", "[1]", "<2 items>", "@QList") From 4deadb5f8bf476018736c44806cc4fac5a189810 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 2 Apr 2015 15:55:37 +0200 Subject: [PATCH 12/38] Dumper: Test: Fix execution of dumper tests for LLDB Change-Id: Id4f437fe17d7989c15ad223c20605773411a1142 Reviewed-by: hjk --- share/qtcreator/debugger/lldbbridge.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 8007242e222..e8e6c29bb11 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -509,15 +509,15 @@ class Dumper(DumperBase): return int(value.GetLoadAddress()) def extractInt(self, address): - error = SBError() + error = lldb.SBError() return int(self.process.ReadUnsignedFromMemory(address, 4, error)) def extractInt64(self, address): - error = SBError() + error = lldb.SBError() return int(self.process.ReadUnsignedFromMemory(address, 8, error)) def extractByte(self, address): - error = SBError() + error = lldb.SBError() return int(self.process.ReadUnsignedFromMemory(address, 1, error) & 0xFF) def handleCommand(self, command): @@ -1130,13 +1130,13 @@ class Dumper(DumperBase): with SubItem(self, child): self.putItem(child) - def reportVariables(self, args = None): + def reportVariables(self, args = {}): with self.outputLock: sys.stdout.write("@\n") self.reportVariablesHelper(args) sys.stdout.write("@\n") - def reportVariablesHelper(self, args = None): + def reportVariablesHelper(self, args = {}): frame = self.currentFrame() if frame is None: return From e6f73164c3557b0b6b5c4d8be4fecc7472b5552d Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 2 Apr 2015 14:10:26 +0200 Subject: [PATCH 13/38] Debugger: Adjust QVariant2 dumper test Take new QPolygon{,F} dumpers into account, also make QUrlPrivate field accessible, Change-Id: I2b5c122895c3ee389ba939eaeffcd613fa206009 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/qttypes.py | 1 + tests/auto/debugger/tst_dumpers.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 8323314d346..031c72bf48f 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -1906,6 +1906,7 @@ def qdump__QUrl(d, value): d.putGenericItem("path", stringType, path, Hex4EncodedLittleEndian) d.putGenericItem("query", stringType, query, Hex4EncodedLittleEndian) d.putGenericItem("fragment", stringType, fragment, Hex4EncodedLittleEndian) + d.putFields(value) def qdumpHelper_QVariant_0(d, blob): # QVariant::Invalid diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 3cbc36bddbc..d13b7757ac8 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -3321,7 +3321,7 @@ void tst_Dumpers::dumper_data() + Check("var14", "(invalid)", "@QVariant (QDate)") + Check("var15", "(invalid)", "@QVariant (QTime)") + Check("var16", "(invalid)", "@QVariant (QDateTime)") - + Check4("var17.d", "", "@QUrlPrivate") + + Check("var17.d", "", "@QUrlPrivate") + Check5("var17", UnsubstitutedValue("\"http://foo@qt-project.org:10/have_fun\""), "@QVariant (QUrl)") + Check("var17.port", "10", "int") + Check("var18", "\"en_US\"", "@QVariant (QLocale)") @@ -3350,7 +3350,7 @@ void tst_Dumpers::dumper_data() + Check("var68", "", "@QVariant (QPalette)") + Check("var69", "", "@QVariant (QIcon)") + Check("var70", "(invalid)", "@QVariant (QImage)") - + Check("var71", "", "@QVariant (QPolygon)") + + Check("var71", "<0 items>", "@QVariant (QPolygon)") //+ Check("var72", "", "@QVariant (QRegion)") FIXME + Check("var73", "", "@QVariant (QBitmap)") + Check("var74", "", "@QVariant (QCursor)") @@ -3364,7 +3364,7 @@ void tst_Dumpers::dumper_data() + Check("var83", "", "@QVariant (QVector3D)") + Check("var84", "", "@QVariant (QVector4D)") + Check("var85", "", "@QVariant (QQuaternion)") - + Check("var86", "", "@QVariant (QPolygonF)"); + + Check("var86", "<0 items>", "@QVariant (QPolygonF)"); QTest::newRow("QVariant4") From 3417ffad83f4be1e55597883fb099674b8ff93d6 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 2 Apr 2015 14:23:10 +0200 Subject: [PATCH 14/38] Debugger: Make QHash dumper pass again Failures were due to version specific reordering. This is still checked in cases h1, h7, h8. Simplify maintanance by removing the check in the other cases. Change-Id: I481672e693f6370c75bc4739d6cca937b9f027ea Reviewed-by: Christian Stenger --- tests/auto/debugger/tst_dumpers.cpp | 55 +++++------------------------ 1 file changed, 9 insertions(+), 46 deletions(-) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index d13b7757ac8..2de739cf9ca 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1684,32 +1684,15 @@ void tst_Dumpers::dumper_data() "QHash h3;\n" "h3[\"22.0\"] = 22.0;\n" - "h3[\"123.0\"] = 22.0;\n" - "h3[\"111111ss111128.0\"] = 28.0;\n" - "h3[\"11124.0\"] = 22.0;\n" - "h3[\"1111125.0\"] = 22.0;\n" - "h3[\"11111126.0\"] = 22.0;\n" - "h3[\"111111127.0\"] = 27.0;\n" - "h3[\"111111111128.0\"] = 28.0;\n" - "h3[\"111111111111111111129.0\"] = 29.0;\n\n" "QHash h4;\n" "h4[\"22.0\"] = 22.0;\n" - "h4[\"123.0\"] = 22.0;\n" - "h4[\"111111ss111128.0\"] = 28.0;\n" - "h4[\"11124.0\"] = 22.0;\n" - "h4[\"1111125.0\"] = 22.0;\n" - "h4[\"11111126.0\"] = 22.0;\n" - "h4[\"111111127.0\"] = 27.0;\n" - "h4[\"111111111128.0\"] = 28.0;\n" - "h4[\"111111111111111111129.0\"] = 29.0;\n\n" "QHash h5;\n" "h5[22] = \"22.0\";\n\n" "QHash h6;\n" "h6[\"22.0\"] = Foo(22);\n" - "h6[\"33.0\"] = Foo(33);\n\n" "QObject ob;\n" "QHash > h7;\n" @@ -1749,45 +1732,25 @@ void tst_Dumpers::dumper_data() + Check("h2.0", "[0] 22", "22", "float") + Check("h2.1", "[1] 11", "11", "float") - + Check("h3", "<9 items>", "@QHash<@QString, int>") + + Check("h3", "<1 items>", "@QHash<@QString, int>") + Check("h3.0", "[0]", "", "@QHashNode<@QString, int>") - + Check("h3.0.key", "key", Value4("\"123.0\""), "@QString") - + Check("h3.0.key", "key", Value5("\"111111111128.0\""), "@QString") - + Check("h3.0.value", Value4("22"), "int") - + Check("h3.0.value", Value5("28"), "int") - + Check("h3.8", "[8]", "", "@QHashNode<@QString, int>") - + Check("h3.8.key", "key", Value4("\"11124.0\""), "@QString") - + Check("h3.8.key", "key", Value5("\"123.0\""), "@QString") - + Check("h3.8.value", "value", Value4("22"), "int") - + Check("h3.8.value", "value", Value5("22"), "int") + + Check("h3.0.key", "key", "\"22.0\"", "@QString") + + Check("h3.0.value", "22", "int") - + Check("h4", "<9 items>", "@QHash<@QByteArray, float>") + + Check("h4", "<1 items>", "@QHash<@QByteArray, float>") + Check("h4.0", "[0]", "", "@QHashNode<@QByteArray, float>") - + Check("h4.0.key", Value4("\"123.0\""), "@QByteArray") - + Check("h4.0.key", Value5("\"111111111128.0\""), "@QByteArray") - + Check("h4.0.value", Value4("22"), "float") - + Check("h4.0.value", Value5("28"), "float") - + Check("h4.8", "[8]", "", "@QHashNode<@QByteArray, float>") - + Check("h4.8.key", Value4("\"11124.0\""), "@QByteArray") - + Check("h4.8.key", Value5("\"123.0\""), "@QByteArray") - + Check("h4.8.value", Value4("22"), "float") - + Check("h4.8.value", Value5("22"), "float") + + Check("h4.0.key", "\"22.0\"", "@QByteArray") + + Check("h4.0.value", "22", "float") + Check("h5", "<1 items>", "@QHash") + Check("h5.0.key", "22", "int") + Check("h5.0.value", "\"22.0\"", "@QString") - + Check("h6", "<2 items>", "@QHash<@QString, Foo>") + + Check("h6", "<1 items>", "@QHash<@QString, Foo>") + Check("h6.0", "[0]", "", "@QHashNode<@QString, Foo>") - + Check("h6.0.key", Value4("\"22.0\""), "@QString") - + Check("h6.0.key", Value5("\"33.0\""), "@QString") + + Check("h6.0.key", "\"22.0\"", "@QString") + CheckType("h6.0.value", "Foo") - + Check("h6.0.value.a", Value4("22"), "int") - + Check("h6.0.value.a", Value5("33"), "int") - + Check("h6.1", "[1]", "", "@QHashNode<@QString, Foo>") - + Check("h6.1.key", Value4("\"33.0\""), "@QString") - + Check("h6.1.key", Value5("\"22.0\""), "@QString") - + CheckType("h6.1.value", "Foo") + + Check("h6.0.value.a", "22", "int") + CoreProfile() + Check("h7", "<3 items>", "@QHash<@QString, @QPointer<@QObject>>") From bfac365ebb2fb03e0d3b4ed261179f0353cf744a Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 2 Apr 2015 16:45:11 +0200 Subject: [PATCH 15/38] Debugger: Fix parameter passing to LLDB dumper tests Change-Id: Iae342ffe68385de877c7a1e9a7e61e7d4889f731 Reviewed-by: hjk --- share/qtcreator/debugger/lldbbridge.py | 9 +++++---- tests/auto/debugger/tst_dumpers.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index e8e6c29bb11..500c0477a8d 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -1765,12 +1765,13 @@ class Tester(Dumper): stoppedThread = self.firstStoppedThread() if stoppedThread is None: warn("NO STOPPED THREAD FOUND") - for i in xrange(0, self.process.GetNumThreads()): - thread = self.process.GetThreadAtIndex(i) - reason = thread.GetStopReason() - warn("THREAD: %s REASON: %s" % (thread, reason)) continue + #for i in xrange(0, self.process.GetNumThreads()): + # thread = self.process.GetThreadAtIndex(i) + # reason = thread.GetStopReason() + # warn("THREAD: %s REASON: %s" % (thread, reason)) + try: frame = stoppedThread.GetFrameAtIndex(0) break diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 2de739cf9ca..39e7c3bb8a3 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1274,7 +1274,7 @@ void tst_Dumpers::dumper() "sc sys.path.insert(1, '" + dumperDir + "')\n" "sc from lldbbridge import *\n" "sc print(dir())\n" - "sc Tester('" + t->buildPath.toLatin1() + "/doit', '" + expanded + "')\n" + "sc Tester('" + t->buildPath.toLatin1() + "/doit', [" + expandedq + "])\n" "quit\n"; fullLldb.write(cmds); From 27aad7dfca4ed4d782407d56c059210463d5efb9 Mon Sep 17 00:00:00 2001 From: Nikita Baryshnikov Date: Mon, 6 Apr 2015 15:40:07 +0300 Subject: [PATCH 16/38] DiffEditorManager fix typo in assert Change-Id: I8582fdb790f5541263eb17d1fa9418c3a48f88f6 Reviewed-by: Orgad Shaneh --- src/plugins/diffeditor/diffeditormanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/diffeditor/diffeditormanager.cpp b/src/plugins/diffeditor/diffeditormanager.cpp index 242b19bcd4f..5d3388d4a21 100644 --- a/src/plugins/diffeditor/diffeditormanager.cpp +++ b/src/plugins/diffeditor/diffeditormanager.cpp @@ -76,7 +76,7 @@ Core::IDocument *DiffEditorManager::findOrCreate(const QString &vcsId, const QSt QTC_ASSERT(diffEditor, return 0); document = qobject_cast(diffEditor->document()); - QTC_ASSERT(diffEditor, return 0); + QTC_ASSERT(document, return 0); document->setPreferredDisplayName(displayName); From f0d891758a4cb78458cd2afbae79644f779f57ed Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 2 Apr 2015 11:13:49 +0200 Subject: [PATCH 17/38] CppTools: Update project part structures consistently When the configuration (defines and includes dirs) did not change, we only updated the m_projectToProjectsInfo data structure, but not the others (m_projectFileToProjectPart, m_fileToProjectParts). Change-Id: I0ca235ea4bbe4556bd8b6d36897dedd6482f86a0 Reviewed-by: Christian Stenger --- src/plugins/cpptools/cppmodelmanager.cpp | 56 ++++++++++++------------ 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 6b4f8e24c0b..aad230149b7 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -748,47 +748,45 @@ QFuture CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn if (oldProjectInfo.isValid()) { ProjectInfoComparer comparer(oldProjectInfo, newProjectInfo); - if (!comparer.configurationOrFilesChanged()) { - // Some other attached data might have changed - d->m_projectToProjectsInfo.insert(project, newProjectInfo); - return QFuture(); - } + if (comparer.configurationOrFilesChanged()) { + d->m_dirty = true; - // If the project configuration changed, do a full reindexing - if (comparer.configurationChanged()) { - removeProjectInfoFilesAndIncludesFromSnapshot(oldProjectInfo); - filesToReindex.unite(newSourceFiles); + // If the project configuration changed, do a full reindexing + if (comparer.configurationChanged()) { + removeProjectInfoFilesAndIncludesFromSnapshot(oldProjectInfo); + filesToReindex.unite(newSourceFiles); - // The "configuration file" includes all defines and therefore should be updated - if (comparer.definesChanged()) { - QMutexLocker snapshotLocker(&d->m_snapshotMutex); - d->m_snapshot.remove(configurationFileName()); + // The "configuration file" includes all defines and therefore should be updated + if (comparer.definesChanged()) { + QMutexLocker snapshotLocker(&d->m_snapshotMutex); + d->m_snapshot.remove(configurationFileName()); + } + + // Otherwise check for added and modified files + } else { + const QSet addedFiles = comparer.addedFiles(); + filesToReindex.unite(addedFiles); + + const QSet modifiedFiles = comparer.timeStampModifiedFiles(snapshot()); + filesToReindex.unite(modifiedFiles); } - // Otherwise check for added and modified files - } else { - const QSet addedFiles = comparer.addedFiles(); - filesToReindex.unite(addedFiles); - - const QSet modifiedFiles = comparer.timeStampModifiedFiles(snapshot()); - filesToReindex.unite(modifiedFiles); - } - - // Announce and purge the removed files from the snapshot - const QSet removedFiles = comparer.removedFiles(); - if (!removedFiles.isEmpty()) { - filesRemoved = true; - emit aboutToRemoveFiles(removedFiles.toList()); - removeFilesFromSnapshot(removedFiles); + // Announce and purge the removed files from the snapshot + const QSet removedFiles = comparer.removedFiles(); + if (!removedFiles.isEmpty()) { + filesRemoved = true; + emit aboutToRemoveFiles(removedFiles.toList()); + removeFilesFromSnapshot(removedFiles); + } } // A new project was opened/created, do a full indexing } else { + d->m_dirty = true; filesToReindex.unite(newSourceFiles); } // Update Project/ProjectInfo and File/ProjectPart table - d->m_dirty = true; d->m_projectToProjectsInfo.insert(project, newProjectInfo); recalculateFileToProjectParts(); From c185a15c28ae85d1dc5057e59926bce7b2b7a1b8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 7 Apr 2015 10:55:58 +0200 Subject: [PATCH 18/38] QmlProfiler: Make message boxes always 300 pixels wide. Sometimes the text would not fit and constantly resizing them is ugly anyway. Change-Id: Id1136ae3b2d2f339ff6f4302b45794201221e6c4 Reviewed-by: Joerg Bornemann --- src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp b/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp index 9d4dc87c220..a6c8e47e322 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp @@ -200,7 +200,7 @@ void QmlProfilerStateWidget::showText(const QString &text, bool showProgress) } d->progressBar->setVisible(showProgress); d->text->setText(text); - resize(showProgress ? 300 : 200, 70); + resize(300, 70); reposition(); } From 96c78e622108ccc957a43d27d7884e250b4cbaa1 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 2 Apr 2015 15:19:55 +0200 Subject: [PATCH 19/38] Update qbs submodule. To HEAD of 1.4 branch. Change-Id: Ib37e757f5b90db01fdc6d77a21556f214e776aa0 Reviewed-by: Jake Petroules --- src/shared/qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/qbs b/src/shared/qbs index c96ef7654f6..0199fd7a839 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit c96ef7654f6ea8ebd5737261aada123b52981213 +Subproject commit 0199fd7a839e3c3899833092e4fa7b3f5ea89880 From a2c770f3240f92b69bc7878090e2ea40ee24f91d Mon Sep 17 00:00:00 2001 From: Raphael da Silva Couto Date: Tue, 7 Apr 2015 09:14:45 -0300 Subject: [PATCH 20/38] Android: Increase timeout running android.bat At some cases, android.bat on Windows running longer. Change-Id: I53ae90e4d7fea69b603cf8cca8c1f8ee5aa36a6a Task-number: QTCREATORBUG-14223 Reviewed-by: Daniel Teske --- src/plugins/android/androidconfigurations.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 833de15485c..1469afd7243 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -380,7 +380,7 @@ void AndroidConfig::updateAvailableSdkPlatforms() const QProcess proc; proc.setProcessEnvironment(androidToolEnvironment().toProcessEnvironment()); proc.start(androidToolPath().toString(), QStringList() << QLatin1String("list") << QLatin1String("target")); // list avaialbe AVDs - if (!proc.waitForFinished(5000)) { + if (!proc.waitForFinished(10000)) { proc.terminate(); return; } @@ -671,7 +671,7 @@ QVector AndroidConfig::androidVirtualDevicesImpl(const FileNa proc.setProcessEnvironment(environment.toProcessEnvironment()); proc.start(androidTool.toString(), QStringList() << QLatin1String("list") << QLatin1String("avd")); // list available AVDs - if (!proc.waitForFinished(5000)) { + if (!proc.waitForFinished(10000)) { proc.terminate(); return devices; } From 67e8d3689ee2b498e23f54caca6ba2ceaf6bfe24 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 2 Apr 2015 07:47:45 +0300 Subject: [PATCH 21/38] C++: Remove unimplemented function in LookupContext Should have been removed in fbb756cd. Change-Id: I86e0fd556ac031e6a88e9397a039d67ded5f7bd7 Reviewed-by: Nikolai Kosjar --- src/libs/cplusplus/LookupContext.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 7a75cf9c8f7..5858d80c954 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -133,7 +133,6 @@ private: Clone &cloner, Subst &subst, ClassOrNamespace *enclosingTemplateClassInstantiation); - bool isInstantiateNestedClassNeeded(const QList& symbols, const Subst &subst) const; ClassOrNamespace *findSpecialization(const TemplateNameId *templId, const TemplateNameIdTable &specializations); From d15e4ff2c9f31f5470c7c7dbc0ef46607e75fa6c Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 2 Apr 2015 15:03:59 +0200 Subject: [PATCH 22/38] Debugger: Replace block access to array data by plain loop. This makes the GccExtension dumper test pass with GDB Change-Id: Ia1319e878416bea8b162a1a9eef1271cb7bebc63 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 78f48db03d6..e8ff7ec5080 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -911,14 +911,9 @@ class DumperBase: self.putNumChild(n) if self.isExpanded(): - try: - # May fail on artificial items like xmm register data. - #if not self.tryPutArrayContents(p, n, innerType): - with Children(self, childType=innerType, addrBase=p, addrStep=ts): - self.putFields(value) - except: - with Children(self, childType=innerType): - self.putFields(value) + with Children(self): + for i in range(n): + self.putSubItem(i, value[i]) self.putPlotDataHelper(p, n, innerType) From 8c472f2074c58a48ce07a6b7e12a295aa3035bd1 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 8 Apr 2015 10:03:43 +0200 Subject: [PATCH 23/38] Doc: experimental Auto Test plugin Commercial only. Change-Id: Id2ee9a7765f226c32ec1595e32f4b53ee94d1207 Reviewed-by: Christian Stenger --- doc/config/qtcreator-project.qdocconf | 1 + .../qtcreator-autotests-sort-naturally.png | Bin 0 -> 702 bytes doc/images/qtcreator-autotests.png | Bin 0 -> 16602 bytes doc/images/qtcreator-closesidebar.png | Bin 785 -> 0 bytes doc/images/qtcreator-run-selected-tests.png | Bin 0 -> 526 bytes doc/src/analyze/cpu-usage-analyzer.qdoc | 2 +- doc/src/howto/creator-autotest.qdoc | 179 ++++++++++++++++++ doc/src/howto/creator-ui.qdoc | 33 +++- doc/src/overview/creator-advanced.qdoc | 2 +- .../overview/creator-commercial-overview.qdoc | 1 + doc/src/overview/creator-overview.qdoc | 8 +- doc/src/overview/creator-testing.qdoc | 7 +- .../projects/creator-projects-creating.qdoc | 5 + doc/src/qtcreator.qdoc | 7 +- 14 files changed, 235 insertions(+), 10 deletions(-) create mode 100644 doc/images/qtcreator-autotests-sort-naturally.png create mode 100644 doc/images/qtcreator-autotests.png delete mode 100644 doc/images/qtcreator-closesidebar.png create mode 100644 doc/images/qtcreator-run-selected-tests.png create mode 100644 doc/src/howto/creator-autotest.qdoc diff --git a/doc/config/qtcreator-project.qdocconf b/doc/config/qtcreator-project.qdocconf index 0cbfa5740f9..d4dc2f247c1 100644 --- a/doc/config/qtcreator-project.qdocconf +++ b/doc/config/qtcreator-project.qdocconf @@ -22,6 +22,7 @@ indexes += $QDOC_INDEX_DIR/qtwidgets/qtwidgets.index \ $QDOC_INDEX_DIR/qtlinguist/qtlinguist.index \ $QDOC_INDEX_DIR/qtscript/qtscript.index \ $QDOC_INDEX_DIR/qtsensors/qtsensors.index \ + $QDOC_INDEX_DIR/qttestlib/qttestlib.index \ $QDOC_INDEX_DIR/qtuitools/qtuitools.index \ $QDOC_INDEX_DIR/qtwebkit/qtwebkit.index \ $QDOC_INDEX_DIR/qtxml/qtxml.index diff --git a/doc/images/qtcreator-autotests-sort-naturally.png b/doc/images/qtcreator-autotests-sort-naturally.png new file mode 100644 index 0000000000000000000000000000000000000000..2f349047d469dabb831090bccdcea4256f148e2a GIT binary patch literal 702 zcmeAS@N?(olHy`uVBq!ia0y~yVBiN~4mJh`2J356y%-o6I14-?iy0XBj({-ZRBb+K z1_lQ95>H=O_WR7z{FW?lH!kP`3%N#=IF^=V zGe3_(m{U=ifq{VwB<`GFP+63jo>9WEhX0He0|NseShOfL5u{Y1Br`Xa!Sp*nCj$cm zCrBnZKdq!Zu_%=xw%|WVIX6hqC9^m=CowZOwTNN+fi3+E3=A9~;qb(wyv)3Gh6B>i z+F?!$&Mz%WPG$J|zxg#xnR9+_Zfaf$!?!cj_A@Xruz|FOWR~QlGOT!aNu7a#vD4GV zF+^kH+(`$$r5#0%)t@`3R_duSHRsGyZ<8qjRU-U?++S5zihO$hgg;p4QK-lHuagcx zOOaCISSvj{CH?-5!@Cr3yKvWj@caDxUd{bIH(!+P?*EgX$soA9=z+zn$iQRS$!EGR zuN7sOQdA&w)M))0j_li9g*NJDZ9yxKT)e2hs&1-^r&tf$hW^zXAK&cpTIv+A{_>5x zM?c%d^&eMh7Fb)FW!<%CYuWej-!u08cd(H7@b%A}^0R6Tfg*tgcSCGupZ|X`tgL@bCN)t z;(?~CGZnP2msW1x>Y9`mQ@{V1c1GR3`^8n2jxxtB!_xmTW^I*vTQ=Kw{h96eMEAz& zn}@8dIo0d8d~?L6YqN@W_87LEOxaY{x^wpQ|64uIlvK^OYb*Mvd+y&m@2@hS*^4_K W?U3IlUdF({z~JfX=d#Wzp$PyC`X^EV literal 0 HcmV?d00001 diff --git a/doc/images/qtcreator-autotests.png b/doc/images/qtcreator-autotests.png new file mode 100644 index 0000000000000000000000000000000000000000..ee16633a59d7b52823089fd45471e0a0f2310639 GIT binary patch literal 16602 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 literal 0 HcmV?d00001 diff --git a/doc/images/qtcreator-closesidebar.png b/doc/images/qtcreator-closesidebar.png deleted file mode 100644 index fd88604c36912b5dccda071ce9254aa9da153deb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 785 zcmeAS@N?(olHy`uVBq!ia0y~yU=RUe4mJh`hTcwDUIqpR&H|6fVg?4jBOuH;Rhv(m zfq{X&#M9T6{SJo+rzDq=dRqxt$TgzGv9u&3zldSwx-%XO3=BLat`Q|Jsl~}fnFS@8 z`FRY&oQlc}3=CW#ap(Mk%A(Blj1q=5{Aa8f7#R4#qD85RAf*Z=nYpP9rr-HF85kHi zK{CPlX(i=}MX3z21^+?Hxj}+1nZ?ODiJ7^nMGV^yZ0ToUVBi1=hbI>0W#*+b9FTt2 z4s%*?erZv1D#O?R&97m~obz*YQ}ap~zMYx2pMima4WuI@8wcRXDj zLo9l?PC0$*k%K_%{*sssmw>|0`c2|4yw0Nn>~t3;$DJ|D?&eKC{d7Xmv7H_Bcf_st*Igf`{pqL8)1sMCYma4^ zC~+`(EfqSNH1TWI*&MUSC04eD@w19{#z^!Z*I24C)r&*%gAM;>lbdoF=IwYM@Ljv zjM^!twQJT+oH((+zrUxer>d%|w7j^YwlJqNC+3c$$rN494q3gkqH?qORnIdh9cK9R z=g-%#U+>+%f9cYtQ>RYtKXP#M=FJNiEuKGr{@l59D=RBYN=oudGc$|Q(h5@2vy&!0 zPmFC$NX$!!OHL^4h;H8%8Ic%SKQ}a{E;Jx6r1W86KtMq5MsLql@3=*7_7N^FmCj+S z?M+QhjY3UaE*iO>FmzmM=y*j(Z@!YwG$qq>it_UEQWFG}7V?U9^D1v=Q`o?^{`-vW z3=9m%JzX3_IIhc{2;FwrK!Ewe$CNk6%4Gaz#@#-C=1k17zxhl3-naLuB!o5Q8nLfC zE%Yp^<%JPj$5w5ZB`Q`uUL6i0^}E)yhTObeuPy8-a7BKd{rpr{AMc|L2WEW!em!k} zX>rJ%z9o#B`gODZPtLiSl@RI`@T$n*&L^AoyMF|EHHK|pT=VT%uTyCDhtgXoH{JX5 zJK?%#&F;TjF2`<-@A+wK{m`x@(JH&XLm>H6%So5l2!yFloXbbkl e#;NzsuBlBEjx5nLZ)0F!VDNPHb6Mw<&;$UuuIQuy literal 0 HcmV?d00001 diff --git a/doc/src/analyze/cpu-usage-analyzer.qdoc b/doc/src/analyze/cpu-usage-analyzer.qdoc index 5db12465b50..1a2971b79de 100644 --- a/doc/src/analyze/cpu-usage-analyzer.qdoc +++ b/doc/src/analyze/cpu-usage-analyzer.qdoc @@ -26,7 +26,7 @@ \contentspage {Qt Creator Manual} \previouspage creator-clang-static-analyzer.html \page creator-cpu-usage-analyzer.html - \nextpage creator-advanced.html + \nextpage creator-autotest.html \title Analyzing CPU Usage diff --git a/doc/src/howto/creator-autotest.qdoc b/doc/src/howto/creator-autotest.qdoc new file mode 100644 index 00000000000..8500c1c1282 --- /dev/null +++ b/doc/src/howto/creator-autotest.qdoc @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +/*! + \contentspage {Qt Creator Manual} + \previouspage creator-cpu-usage-analyzer.html + \page creator-autotest.html + \nextpage creator-advanced.html + + \title Running Autotests + + \QC integrates the \l{Qt Test} framework for unit testing Qt based + applications and libraries (commercial only). You can use \QC to build and + run autotests for your projects. + + \image qtcreator-autotests.png + + To enable the experimental Auto Test plugin, select \uicontrol Help > + \uicontrol {About Plugins} > \uicontrol Utilities > \uicontrol {Auto Test}. + Restart \QC to be able to use the plugin. + + \section1 Creating Autotests + + You can use a wizard to create projects that contain autotests: + + \list 1 + \li Select \uicontrol File > \uicontrol {New File or Project} > + \uicontrol {Other Project} > \uicontrol {Auto Test} > + \uicontrol Choose to create a project with boilerplate code for an + autotest. + + \li In the \uicontrol {Project and Test Information} dialog, specify + settings for the project and autotest: + + \list 1 + + \li Select the \uicontrol {GUI Application} check box to create + a Qt application. + + \li In the \uicontrol {Test case name} field, enter a name for + the test case. + + \li Select the \uicontrol {Requires QApplication} check box to + add the include statement for QApplication to the main.cpp + file of the project. + + \li Select the \uicontrol {Generate initialization and cleanup + code} checkbox to add functions to your test that are + executed by the testing framework to initialize and clean + up the test. + + \li In the \uicontrol {Build auto tests} field, select + \uicontrol Always to always build the autotest when building + the project or \uicontrol {Debug Only} to only build it + during debug builds. + + \endlist + + \endlist + + \QC creates the autotest in the \c{tests\auto} directory in the project + directory. Edit the .cpp file to add private slots for each test + function in your test. For more information about creating autotests, see + \l{Creating a Test}. + + \section1 Building and Running Autotests + + To build and run autotests: + + \list 1 + + \li Open a project that contains autotests. + + \li In the \uicontrol {Test Results} output pane, select + \inlineimage qtcreator-run.png + (\uicontrol {Run All Tests}) to run all test or + \inlineimage qtcreator-run-selected-tests.png + (\uicontrol {Run Selected Tests}) to run the selected tests. + + You can select the tests to run in the \uicontrol Tests view in the + \uicontrol Projects pane. For more information, see + \l{Viewing Tests}. + + \note By default, \QC builds a project before deploying and running + it. + + \endlist + + If a test takes more than a minute to execute, the default timeout might + stop the test execution. To increase the timeout, select \uicontrol Tools > + \uicontrol Options > \uicontrol {Test Settings}. + + The code inside a benchmark test is measured, and possibly also repeated + several times in order to get an accurate measurement. This depends on the + measurement back-end that you can select in \uicontrol {Test Settings}: + walltime, CPU tick counter, event counter, Vallgrind Callgring, and Linux + Perf. For more information, see \l{Creating a Benchmark}. + + \section1 Viewing Test Output + + The test results are displayed in the \uicontrol {Test Results} output pane. + + \table + \header + \li Result + \li Description + \row + \li BENCH + \li Benchmark test. + \row + \li BFAIL + \li Blacklisted test case failed. Since Qt 5.4, you can + provide a BLACKLIST file for tests. It is mainly used internally + by the Qt CI system. + \row + \li BPASS + \li Blacklisted test case passed. + \row + \li DEBUG + \li Debug message. + \row + \li XFAIL + \li Test case is expected to fail, so it is marked by using the + QEXPECT_FAIL macro. If the test case passes instead, an + unexpected pass (XPASS) is written to the test log. + \row + \li FAIL + \li Test case failed. Double-click the line for more information. + \row + \li INTERNAL + \li Internal message. + \row + \li PASS + \li Test case passed. + \row + \li SKIP + \li Test case was skipped. + \row + \li XPASS + \li Test case passed even though it was expected to fail. + \row + \li WARN + \li Warning message. + \endtable + + To view only messages of a particular type, select + \inlineimage qtcreator-filter.png + (\uicontrol {Filter Test Results}), and then select the types of messages to + show. + + To hide internal messages and run configuration warnings, select + \uicontrol Tools > \uicontrol Options > \uicontrol {Test Settings}. +*/ diff --git a/doc/src/howto/creator-ui.qdoc b/doc/src/howto/creator-ui.qdoc index c85a65bc50c..01941b78215 100644 --- a/doc/src/howto/creator-ui.qdoc +++ b/doc/src/howto/creator-ui.qdoc @@ -132,6 +132,9 @@ \li \uicontrol Outline shows the symbol hierarchy of a C++ file and the type hierarchy of a QML file. + \li \uicontrol Tests lists autotests and Qt Quick tests in the project + (commercial only). + \li \uicontrol {Type Hierarchy} shows the base classes of a class. \li \uicontrol {Include Hierarchy} shows which files are included in the current file @@ -154,7 +157,7 @@ (\uicontrol {Split}). Select new content to view in the split view. \li To close a sidebar view, click - \inlineimage qtcreator-closesidebar.png + \inlineimage qtcreator-remove-split-button.png (\uicontrol {Close}). \endlist @@ -242,6 +245,29 @@ \endlist + \section2 Viewing Tests + + The \uicontrol Tests view shows the autotests and Qt Quick tests in the + current project (commercial only). Select the test cases to run. If a Qt + Quick test case does not have a name, it is marked \uicontrol Unnamed in the + list. Unnamed test cases are always executed when the application that + contains them is run, and therefore you cannot select or deselect them. + + To show or hide init and cleanup or data functions, select + \uicontrol {Filter Test Tree} > \uicontrol {Show Init and Cleanup Functions} + or \uicontrol {Show Data Functions}. Double-click a function in the list + to open its source code in the code editor. + + The test cases are listed in alphabetic order. To list them in the order in + which they are defined in the source code, select + \inlineimage qtcreator-autotests-sort-naturally.png + (\uicontrol {Sort Naturally}). + + To run tests, select \uicontrol {Run All Tests} or + \uicontrol {Run Selected Tests} in the context menu. + + To refresh the view, select \uicontrol {Rescan Tests} in the context menu. + \section2 Viewing Type Hierarchy To view the base classes of a class, right-click the class and select @@ -275,6 +301,8 @@ \li \uicontrol{General Messages} + \li \uicontrol{Test Results} (commercial only) + \endlist Output panes are available in all \l{Modes}{modes}. Click the name of an @@ -289,7 +317,8 @@ To open the \uicontrol{General Messages} and \l{Using Version Control Systems} {Version Control} panes, select \uicontrol {Window > Output Panes}. To display the \uicontrol {To-Do Entries} pane, - enable the Todo plugin. + enable the Todo plugin and to display the \l{Running Autotests} + {Test Results} pane, enable the Auto Tests plugin. \section2 Issues diff --git a/doc/src/overview/creator-advanced.qdoc b/doc/src/overview/creator-advanced.qdoc index 8a198eba7fd..d5364b50579 100644 --- a/doc/src/overview/creator-advanced.qdoc +++ b/doc/src/overview/creator-advanced.qdoc @@ -24,7 +24,7 @@ /*! \contentspage {Qt Creator Manual} - \previouspage creator-cpu-usage-analyzer.html + \previouspage creator-autotest.html \page creator-advanced.html \nextpage creator-os-supported-platforms.html diff --git a/doc/src/overview/creator-commercial-overview.qdoc b/doc/src/overview/creator-commercial-overview.qdoc index b4c393c4c05..3665d5c095a 100644 --- a/doc/src/overview/creator-commercial-overview.qdoc +++ b/doc/src/overview/creator-commercial-overview.qdoc @@ -32,6 +32,7 @@ \l{http://qt.io/licensing/}{Qt license}: \list + \li \l{Running Autotests} \li \l{Using Clang Static Analyzer}{Clang Static Analyzer} integration. \li Additional \l{Understanding the Data}{QML Profiler} event categories: diff --git a/doc/src/overview/creator-overview.qdoc b/doc/src/overview/creator-overview.qdoc index c1a9c8c2f7a..be8189706e8 100644 --- a/doc/src/overview/creator-overview.qdoc +++ b/doc/src/overview/creator-overview.qdoc @@ -92,7 +92,7 @@ different setups and target platforms. For more information, see \l{Building and Running}. - \li \b {\l{Debugging and Analyzing}} + \li \b {\l{Testing}} \QC is integrated to several external native debuggers: GNU Symbolic Debugger (GDB), Microsoft Console Debugger (CDB), and @@ -105,7 +105,11 @@ execution. In addition, the QML Profiler enables you to profile Qt Quick applications. - For more information, see \l{Debugging and Analyzing}. + \QC is integrated to the \l{Qt Test} framework for unit testing + Qt based applications and libraries. You can use \QC to build + and run autotests (commercial only). + + For more information, see \l{Testing}. \li \b {Publishing} \QC allows you to create installation packages for mobile diff --git a/doc/src/overview/creator-testing.qdoc b/doc/src/overview/creator-testing.qdoc index 059cbe2680f..40ac2388f32 100644 --- a/doc/src/overview/creator-testing.qdoc +++ b/doc/src/overview/creator-testing.qdoc @@ -28,7 +28,7 @@ \page creator-testing.html \nextpage creator-debugging.html - \title Debugging and Analyzing + \title Testing \image creator_testing.png @@ -51,6 +51,11 @@ installed as part of \QC. It enables you to profile your Qt Quick applications. + \li \l{Running Autotests} + + You can use an experimental Auto Test plugin to build and run + autotests using \QC (commercial only). + \endlist */ diff --git a/doc/src/projects/creator-projects-creating.qdoc b/doc/src/projects/creator-projects-creating.qdoc index e88869504be..3418bc1c790 100644 --- a/doc/src/projects/creator-projects-creating.qdoc +++ b/doc/src/projects/creator-projects-creating.qdoc @@ -159,6 +159,11 @@ Qt unit tests for features or classes + \li Qt Auto Test (commercial only) + + Projects with boilerplate code for an autotest. For more + information, see \l {Creating Autotests}. + \li Qt Custom Designer Widgets Custom \QD widget or widget collection diff --git a/doc/src/qtcreator.qdoc b/doc/src/qtcreator.qdoc index a5b4b632fdc..fc253e7ab08 100644 --- a/doc/src/qtcreator.qdoc +++ b/doc/src/qtcreator.qdoc @@ -87,10 +87,11 @@ \li \l{Deploying to Mobile Devices} \li \l{Connecting Mobile Devices} \endlist - \li \b {\l{Debugging and Analyzing}} + \li \b {\l{Testing}} \list \li \l{Debugging} \li \l{Analyzing Code} + \li \l{Running Autotests} \endlist \row \li \inlineimage creator_advanceduse.png @@ -245,7 +246,7 @@ \endlist \li \l{Customizing the Build Process} \endlist - \li \l{Debugging and Analyzing} + \li \l{Testing} \list \li \l{Debugging} \list @@ -270,7 +271,7 @@ \li \l{Using Clang Static Analyzer} \li \l{Analyzing CPU Usage} \endlist - + \li \l{Running Autotests} \endlist \li \l{Advanced Use} \list From db48c49af94b13bf33edf6e0bcad6fe77f988c28 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 8 Apr 2015 12:43:38 +0200 Subject: [PATCH 24/38] Doc: add a "commercial" icon to commercial-only topics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For purely commercial apps, this is done by using the template, but Qt Creator is mostly open source, so an image is used. Use a \commercial macro with a tooltip and link to the image. Change-Id: I5e3df953821551331afef2ec642b482b52ff909e Reviewed-by: Topi Reiniö --- doc/config/images/commercial.png | Bin 0 -> 334 bytes doc/config/macros.qdocconf | 1 + doc/config/qtcreator-project.qdocconf | 4 ++++ doc/src/analyze/cpu-usage-analyzer.qdoc | 2 ++ .../analyze/creator-clang-static-analyzer.qdoc | 2 ++ doc/src/howto/creator-autotest.qdoc | 2 ++ doc/src/overview/creator-commercial-overview.qdoc | 2 ++ doc/src/qtquick/qtquick-connection-editor.qdoc | 2 ++ doc/src/qtquick/qtquick-designer-extensions.qdoc | 2 ++ doc/src/qtquick/qtquick-pathview-editor.qdoc | 2 ++ 10 files changed, 19 insertions(+) create mode 100644 doc/config/images/commercial.png diff --git a/doc/config/images/commercial.png b/doc/config/images/commercial.png new file mode 100644 index 0000000000000000000000000000000000000000..852737d4bcb5c55e7e7b72066d26f5715a780073 GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0y~yU@&1|U~uGMW?*1g=~=#-fq|hbz$e5tW|heQ|Nl?^ z`TzghvDj5Xacf*Z|NsC0`SkeJMg^;cYgY;%{`vp!|G#VBe(QVu_Tt+Y|NlNedTmqN z?#v56|NsC0`Pa86M<3l-e(%QXmnUM6ANAS2cI~A#Wk;6(f4SuIlO;E9&%bzO{)}Uj z-rVVoT3a*wK-G;41vR@fV^_sDY;h^uVt8(!&a^cG^H&J$+Q#PXqvXcGz)vqV6Wn_@|Hg<#jhaTx@Z4TKxwT xr>*w#VNY9c&9dCm*Y;?=Z?U

\n\\endraw" macro.beginfloatleft.HTML = "
" macro.beginfloatright.HTML = "
" diff --git a/doc/config/qtcreator-project.qdocconf b/doc/config/qtcreator-project.qdocconf index d4dc2f247c1..598bd327358 100644 --- a/doc/config/qtcreator-project.qdocconf +++ b/doc/config/qtcreator-project.qdocconf @@ -8,6 +8,10 @@ imagedirs = $SRCDIR/images $SRCDIR/templates/images outputdir = $OUTDIR exampledirs = $SRCDIR/examples +HTML.extraimages = images/commercial.png +qhp.QtCreator.extraFiles = images/commercial.png + + indexes += $QDOC_INDEX_DIR/qtwidgets/qtwidgets.index \ $QDOC_INDEX_DIR/qtcore/qtcore.index \ $QDOC_INDEX_DIR/qtqml/qtqml.index \ diff --git a/doc/src/analyze/cpu-usage-analyzer.qdoc b/doc/src/analyze/cpu-usage-analyzer.qdoc index 1a2971b79de..e3eb74cdfdc 100644 --- a/doc/src/analyze/cpu-usage-analyzer.qdoc +++ b/doc/src/analyze/cpu-usage-analyzer.qdoc @@ -30,6 +30,8 @@ \title Analyzing CPU Usage + \commercial + \QC is integrated with the Linux Perf tool (commercial only) that can be used to analyze the CPU usage of an application on embedded devices and, to a limited extent, on Linux desktop platforms. The CPU Usage Analyzer uses diff --git a/doc/src/analyze/creator-clang-static-analyzer.qdoc b/doc/src/analyze/creator-clang-static-analyzer.qdoc index 3485be704fa..b4692213793 100644 --- a/doc/src/analyze/creator-clang-static-analyzer.qdoc +++ b/doc/src/analyze/creator-clang-static-analyzer.qdoc @@ -31,6 +31,8 @@ \title Using Clang Static Analyzer + \commercial + \QC integrates the \l{http://clang-analyzer.llvm.org} {Clang Static Analyzer} for finding problems in C, C++, and Objective-C programs (commercial only). diff --git a/doc/src/howto/creator-autotest.qdoc b/doc/src/howto/creator-autotest.qdoc index 8500c1c1282..a394dcc62f2 100644 --- a/doc/src/howto/creator-autotest.qdoc +++ b/doc/src/howto/creator-autotest.qdoc @@ -35,6 +35,8 @@ \title Running Autotests + \commercial + \QC integrates the \l{Qt Test} framework for unit testing Qt based applications and libraries (commercial only). You can use \QC to build and run autotests for your projects. diff --git a/doc/src/overview/creator-commercial-overview.qdoc b/doc/src/overview/creator-commercial-overview.qdoc index 3665d5c095a..f21189d373c 100644 --- a/doc/src/overview/creator-commercial-overview.qdoc +++ b/doc/src/overview/creator-commercial-overview.qdoc @@ -28,6 +28,8 @@ \title Qt Creator Commercial Features + \commercial + You can use the following \QC features if you have the appropriate \l{http://qt.io/licensing/}{Qt license}: diff --git a/doc/src/qtquick/qtquick-connection-editor.qdoc b/doc/src/qtquick/qtquick-connection-editor.qdoc index 6fb08767e2c..2d3aa49ccf6 100644 --- a/doc/src/qtquick/qtquick-connection-editor.qdoc +++ b/doc/src/qtquick/qtquick-connection-editor.qdoc @@ -35,6 +35,8 @@ \title Adding Connections + \commercial + You can use the \uicontrol {Connections} view (commercial only) to: \list diff --git a/doc/src/qtquick/qtquick-designer-extensions.qdoc b/doc/src/qtquick/qtquick-designer-extensions.qdoc index 0ff8231c7a5..127a1860425 100644 --- a/doc/src/qtquick/qtquick-designer-extensions.qdoc +++ b/doc/src/qtquick/qtquick-designer-extensions.qdoc @@ -35,6 +35,8 @@ \title Using Qt Quick Designer Extensions + \commercial + \image qmldesigner-extensions.png \QMLD contains commercial features that make developing Qt Quick diff --git a/doc/src/qtquick/qtquick-pathview-editor.qdoc b/doc/src/qtquick/qtquick-pathview-editor.qdoc index d65310f9adb..4e15cb0424a 100644 --- a/doc/src/qtquick/qtquick-pathview-editor.qdoc +++ b/doc/src/qtquick/qtquick-pathview-editor.qdoc @@ -35,6 +35,8 @@ \title Editing PathView Properties + \commercial + A \l{PathView} lays out data provided by data models on a \l{Path}. A graphical spline editor enables you to specify PathView paths, which From bcc4ab301f286a8e096dda277732c6749af31b1b Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 8 Apr 2015 17:01:01 +0200 Subject: [PATCH 25/38] ProjectExplorer: Fix FolderNode::addNewInformation(). We should use the actual display name of the node there, not some hardcoded value. Task-number: QTCREATORBUG-14240 Change-Id: Idf0fc4cdaab52d7f838d3d48d834a89b55ee593f Reviewed-by: Daniel Teske --- src/plugins/projectexplorer/projectnodes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 800ccfc9425..beea4f8ae75 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -367,7 +367,7 @@ bool FolderNode::renameFile(const QString &filePath, const QString &newFilePath) FolderNode::AddNewInformation FolderNode::addNewInformation(const QStringList &files, Node *context) const { Q_UNUSED(files); - return AddNewInformation(path().fileName(), context == this ? 120 : 100); + return AddNewInformation(displayName(), context == this ? 120 : 100); } /*! From e112647397bd24d85863853e9b65ec1e16ac1c9c Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 9 Apr 2015 15:17:02 +0200 Subject: [PATCH 26/38] Doc: fix capitalization of BAR Descriptor In the Issues output pane filter. Change-Id: I3283628f74dd48c2e95eeedad93ce28f1686c25f Reviewed-by: Leena Miettinen --- doc/src/howto/creator-ui.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/howto/creator-ui.qdoc b/doc/src/howto/creator-ui.qdoc index 01941b78215..b18ce343a0a 100644 --- a/doc/src/howto/creator-ui.qdoc +++ b/doc/src/howto/creator-ui.qdoc @@ -329,7 +329,7 @@ \li \uicontrol Analyzer - Errors encountered while running the \l{Analyzing Code}{Valgrind code analysis tools}. - \li \uicontrol {Bar Descriptor} - Errors and warnings encountered when using + \li \uicontrol {BAR Descriptor} - Errors and warnings encountered when using the BlackBerry 10 BAR descriptor editor to customize the appearance and behavior of an application. From 153a57ce80cf278b6dcc52477d5f3e51c399cf2f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 8 Apr 2015 18:05:20 +0200 Subject: [PATCH 27/38] Timeline: Test parenting of equal start times If you insert events with equal start times in a way that the model can not reorder them by their end times the parenting follows the indexes, not the end times. This has caused confusion multiple times and it's good to test it. Change-Id: I3e9ba212ff377dc2afa2a2893637bb55edebafea Reviewed-by: Kai Koehne --- .../timelinemodel/tst_timelinemodel.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp b/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp index c253503d9a6..7080d11bbaa 100644 --- a/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp +++ b/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp @@ -88,6 +88,7 @@ private slots: void insertStartEnd(); void rowCount(); void prevNext(); + void parentingOfEqualStarts(); }; DummyModel::DummyModel(int modelId) : @@ -443,6 +444,22 @@ void tst_TimelineModel::prevNext() QCOMPARE(dummy.prevItemByTypeId(-1, 10, 5), 4); } +void tst_TimelineModel::parentingOfEqualStarts() +{ + DummyModel dummy; + // Trick it so that it cannot reorder the events and has to parent them in the "wrong" way ... + QCOMPARE(dummy.insert(1, 10, 998), 0); + QCOMPARE(dummy.insertStart(1, 999), 1); + dummy.insertEnd(1, 20); + dummy.computeNesting(); + + // .. which is reflected in the resulting order. + QCOMPARE(dummy.selectionId(0), 998); + QCOMPARE(dummy.selectionId(1), 999); + QCOMPARE(dummy.firstIndex(10), 0); + QCOMPARE(dummy.lastIndex(2), 1); +} + QTEST_MAIN(tst_TimelineModel) #include "tst_timelinemodel.moc" From 7980538ef4038e1f983035be74d1dc8e5737ee57 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 9 Apr 2015 15:05:43 +0200 Subject: [PATCH 28/38] Doc: sidebar view context menus Update the screenshot, because the icons have changed. Change-Id: I55e46f8f01d293021914fd28c1e7f7d83d8bde11 Reviewed-by: Daniel Teske --- doc/images/qtcreator-sidebar.png | Bin 39861 -> 14946 bytes doc/src/howto/creator-ui.qdoc | 42 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/doc/images/qtcreator-sidebar.png b/doc/images/qtcreator-sidebar.png index 5a99a208a67760447c5fb0b98b80bfd1d53e7ae0..d44fe9e10ed1324df20c862257d0612bc7ae65e6 100644 GIT binary patch literal 14946 zcmeAS@N?(olHy`uVBq!ia0y~yV0g*E!1#!RnSp`9DpGnG0|PTdfKQ0)|Ns9#eE9JE z`SW-0-hKS^(bLm2B_+kr&o3$}>c`KYfq{Y9+1d4no$~VXii(QT($ZpMV~dN6+uPcb zlas%G{Zd#^5F8x*`puj2@`~So{&aPBhlYm6$HyN!bR;4o;@PMF0RaIC2?<*^Z{E0Z zS{Qv*|Uk>*6Nl8g%Wo7^WeyyymJioqg$IhL%UjP5|_3qa{|7XpbRb9R6 z|Nj?<7dCfnyz=A2wPKIzrOTK7{rT?a*XLhe@9N+6;OzVV@4x-nbm7(f1@r%WI(p~! z-Ff?OH`~U2eY0>ye%{qD|35sQwrT&B#M;?8Da;awfjc=Quy!iL;+Qaj^ zj&0lg@cgpZce>s@xq4~$oRCQ~QwqDA@)DM9KCxx`vInPf?!UZR)-bVo{g#(E=iEBD za!y0`-Yd@@U%Ptu`RlUfYm;X$s9fi2)M;SUVet9&<3*S6p1iqUv}bB|Wb5p_@EfO3 zh|XG^(Y)B$*!8wbob=*J12vS=B_<{D#bje zFUtM-=SS049=dpBhr)&(bC+$|e{gBbg!yZxlwaPPc;xKu{u!H&tqWYcXxEdg-4PlF zmtH*CGa>WNfuP*LAdOvzFRZSuj`NRna@e_S+M0PC4k;72_jWjXMimy%zkIm7DKdF! zmB)gP`8^w=v}KgSecQr9@@FS!0GsRqeGU7XC#UQ?2Jee&2oT;o<|8 zz&u>E3OqglY0Hu zO`CSht8V7jY4Ll`)*d;vVE@8t<#R&Z66+S%h#4l{$!Jw{*t}CFzL|l+T-MXYF{I+w zldBuMF9*o5f6(*wPMU3^sJbLGBS^}reb2qE0UG710<6_jco^Gz9Mz|;nYa1y!X{Zh z^``=XGJK-!M?Ww4f8g$miju;@!b|oC?!V5~JG*sd=#iuT>%Q-+z5a0D{yme{=AjgFOjY@78*D{NC=O5o3$)k_p%ND5tB#SX=~+pGTE}P zeD+tos1fT>*euB?&0}%n&G|Pf&xMw*p6T1N=6++4nsBV3QFrL%pZ`>jmd`uWWx(Ye zD6&0f&8zMk3hQ}zb~ERwWHe}tb=Q^tYD~(s%((TwzQ|gAvTP9pPyh5Zx8=^6Garg@ z8XucqQKWfP*kt_?G2hE?IAk`|2%nxFdU&dDpK+z^$^|^L8G}SvS$%xIbxvRmHwx!& zz3u++aB!fGNJ5NjHoMrIBjVMy75aJ_ZV5qwQQr2Ndsl8@KBRR)b){*-gLPMJy)H+s zTa!37<|udO^2qY9(T+=fE?ZihXk=x-$;Gl*ytb8D@}Fs-&Q6hrWoxhfaFN-4ezp2z z_x^Qv>#D!iRsXKovb*;CvCI7L<@VcZFA=&P*faIq;gG7!Lf5#qt-qh-rRrw*FfXfa z!PJttrv_Hx&bv}yA9mV&i}OX)TE^{{xphx-*=lal?d6zotb)yTCo_Yu@8@sDdmqQ% z+rNMJ|3?Ql9AE$b?w0{|W8CdDC zGfHC8qMuRB;deLH-gom+pME+u@%rb74_{aN#=kF|v51B3asK^Bn&FH~UIykD{eQvu zuk!O*Ir#(1d-nCu?mF9_ukc4`O8@eS8vNO-zARG;)Oa{^L#5-<5>*$aJ6RcXPd}65 zJ*FQt>z2Uk9hx~+lO9`4TF&R(uFT||7{#-6r%b~#9cw$&$Q6|pk8d5{>-_ukyUcu} zwoi-A=l55A+c=YJmTRW&+Rp}4?`<*Y4>D!HJh6YzTHUzNxo+08&t9vzJ~{RNRHK`> z%)y>Zo@CE8QHw#`1eVwp~~Oy1pA-}h6W zA3Pl>%d{(Ay+qU@_|K1{Y!)`R?^Y|ES=^za_JC7h<V*r02ZrhIALGh>nYis zrq9q~IbgG@>t%46Ps6kCOAl-+U%+r@Ie%Quy-um+CJgI%a(FTn6gWAOl9CSXmCWEy zJ6L1(`Czj+4-d!ub4d#rCmj5+^5LdKscYFAUD8Z;CC&O-^6X6G2hGEq4!OO**WB8= zmhpvA$ahT{o+YHGiR1Q zY%56JdHv9XH%px7w{7t+ovwej`De+^ncovWq^owkx4o*e`)O1}$+naC90YbhyRh8u z=Bt%zn~pkPTF%hvvT5_7nq4|?KVLnr|ID_ouvAuKU9{iYdspk;UYoc-_L%16hBwQc z)5ZV!))bY8i;C9%dhqu*d&$R@4~s$#XZRamHo71GcjfQ1aVhs~0;a_Mi)QuN>&;io zb-zaJh@aJ#lFXd53zu$eyYfME(W1%&&f@c*ojlQT%b|AG&0lrT{O8)A|CQ!cQxz}$ z=CZlM{CnYyKfgppCY)WFo!AJ{vh3l)@|(ABMX`T-xxF-D{;tD8?<*5tv2NThd#m8d zt##J1?{#=JziMhN*zM1M?d!hzKO^?MzrCySvx4fRHQjr?3#WAFR4R1n?pu-Nx9zNw zLVse%?=8#LeLr|+=KSYp=TvUx-~VjkyWqns7Tu{#*x)z4aoU6DIx-K`BW4}5JNm(l z$AG7l;lZ^xPLsI~Tl@>y-PxhhWwdC4URJ^t&DElnfg;>4g{s?3*2)H_rOAg$1b&K-{#kRcy3W}w|NPPV z_2%~X*(>iopL#Z=d_h~{tc>aAz< zqBhr5GACWFl1*7TCC@%&f_8)WhS_=5*8ka)o|=4gF<)yr{o~~c4vP6VS53)_mwg`> z+W&UJ=YubgS8t2bKJYWKwtW4g%2Qb{Z)H85XSe(1xkeK~&3I!G1<63(5T)JECO^9_ zTN3wht-1YTzJhcA;!X=6FJ1j-S5RFnb4+r~GRYrm`veyHek{;UeN|QJao5=4X~i4v zSx#qi)-o;sH)F~3s37I~?d-Rv956i=xc9r}cQ>6GR#ZS~^K$1Il9=k9gz zn19RGdDyqat?`>lCGQTl-7nv4oo_UmU9X3QW5I#n*R}MwzMEFI|5{q{mFUe6S}z&Z zINH~)b^BPu{~%WXTR7wO1k~14}iQ6G5QEg9sYx!UIyem@-`yxI2{L;d@3ry(}w?mc*pOrM_-DxyGgUMl` zo$UhqWxLcjuWoX@=%zk5ck{ZCka;_$L{7h1o>CTYS2#C>-FK1lx*4B13R;D#wFLC% z9hxEK+-c&-#>C=z>FKSPp0y<&&zJSd^~8R;*YQgBVX^xo^jdHJk#i_fixWs^(V?M*xkmPMt^3SoM~ zHGj*VoHMiL%_xs-)|y!-qi@Ra>{V2;DZh`em12tT>sz91fnTe3 zeN#4l`9)H0_bbQyljdZ~tlgz?`MYlU&bYms4NlCwwsq;>iJrx7i*C+rKB=}YfYrC3 zuWhyuw`%x`n$U)$)r_fM4Bp>3RT8Qddv&h+>PGDirF>cOOf!GAbG-5wcYU+!+Otis z-nhQYxo1DiY3VPQ21PE{6Y}z>>gD6V7ruA+b$z?&R34j|ul`lHuQ!vplc#)$$tGPU zUGmQLI*Iu!WbN8SOMdtjAF8l0S+?@Q_0?QH8Z(+i_y2p#Eb+(uhOhZ_?ga}D`)`r% zX5nNy+u|rT^^J{V77+Ma$AQwL8?zHr5N)eG;Iu)8xKh zVwBpghTeIpLX!55J@>*A>~C6rzcFo*Mc@5|i9+W^X3j`|7AumxRcTsa(6p;};(p!m z-n-~(=IXd;-n(tjW?g+Pe`Lvtq&0HF{kNt}n)&^ApmLI-ko3fmM}i-%zkho*VcF}J zZ;xhc`@OH9Kj+@p^7GIC^eubkko#@x%TTkLO|ka6J5Rqo`9AG{`)<4XGe=)p96i%q zs%h*H*VF#{^1HWF1QqR<^emv2m)F8X-!`}bB8ckSufUAA=htITts zc)$6asjvIIo5#LR?0WRW^R<0BuEn>)8YV@AM$8W`F@1k2`_VM6XIs8}68urI#v|%y z32WYEr?s<<-wXPf@8Vy5hd*?OuBiEp*O%{vpDpY2W__%zZkE6O?7rI4H;=_lXUD9M zEvpxL?tkWG!^Dq1t@|JREZ>$?`z$LV@SKDAi{+PYEp&gd_=GBJ)^|;pT|7Cg(?YGk z2>Vv~>Ke{BdOvUd&A(aq9tPhoXx?4-U`A?byS#Xf$F*zXB_R+0O*{CXBlAjyo%5{M zt3Rx?6rJ%}dcv-^Q8R*-KNh4v{hNFJ%9T00fI$%gO^I0dd<^WvgG5O_ga72wjGiweBf~|^&royP4jHawp5+?S@~DFXXRzR zZ!z{9_ktc;>UJ6A*+ktnJbHI-mEYprza`}tTy1VDZHwAbakVtnEtV^0#!jt6Gx9kV zSL(BP-m7Ka_DJ;xSADj-!G4{9V~rk1TaGc>8=il7e;vaTwzA3pY&k=||JyG5=5&4Z z!|P!wz1;s>r!2@}{mve}alwRr69cP%EMZ7amP*tXvzA>JGug9!p@v*a@{9`q_bVc1 z1}F&^eOFmCLH7M#r#&gAF4-(Oa*Fzj?93v3g+wB>t*XXx{3cSzl^=h@E9 zmaIKzdD_g9*>B2}_nK`f&~)Epnz*!O{`P{GIrpwb@H}aed&e=GQ~1l8-`~u(h%TG` z^0oNXHT@y3jcCg>kA4CRn#6WJd|Y6 z&;Nh3%0G{tAM0{hHzt;BF?1{R({lVfD{<@Og`P|9eEDYoZqKC4M;Dx)p?O~?bWZej z{@^Wp&R1PJ@#V!{o|pS-{n#^&CYG4a2%OZ^`RVjl_p;@kAJ0GBYQ2SH1RLZ*^heo!ncD*RLpzjo&oSB=N_Q&bu!aH##gVyjSwf>T`))R$snu zBkTF1h}G+T^{;Q5x8-QW!U-RZq*fn){H?;~G-sE{y_C4rSdjy#GoO|=GI@lH78``A zJdmnec>GuDEcSIO3auR<1;0;`__%TYpB%N1A0q-wz9{#Ia{Byw+Rg59SI%;R(P_R{ zo)WKxE`*)WU?^dyXY0O^|jz<$K?HuHxP44+{u)xY_uDPPMVGr7_ zT)Nl!*WhN9iJjQe_{-^;8}v6RD(L$4_kEbuv@0Uup}|By;lF21_+M9?T-IvV^=jSp zdyFr8D!q>==x=+_*1Mg{Oyb_7*B5`3eERq=*7=_-pO4f`xr>%ce{U-W?iA&lbmhX5 zq?ogZCvR1~Ict*0s{IbhQ!aS_V!P2WW&1-{Pp+QxHav`I+0dd^C7Ks!g~j-Yc=1yKDdZp1%3~omx}P=g0=W zl;k|t#iGEgVRS^m?pT}2+$r;q=uQ0Sy+px?%Q0m`a&Xv%B@^wp$8K=G$>O`qpx`!Z zuyDGWz_~*c{@>+tkXrDzNl=op|ILLre3j2@E-cx%jho4(ty4(S>esox7_r`zcUjiJKa87C+B;rgC}>|cM~1Pke%j91#qy8J>^0fDPn0@jo|vHJm2kH4)shQU(aS}@vL-LcW!dEs z;VE_X==HKhrzL&-XXa?Rf7Hr%Xm6cfA{w|@Ce&y0xifsb_Hh`lT>rMo|A26phyEV+ zAd$OEr+NK+8Rnzjy1J_SS(5kStA{p5?YgsV^E=D0tqP1H6DP48YciQDvNiTj$rE8u z&rcpbteIMx_M!HTz88ycnNKt^)$?2MO|4J#B2dY@78@im;xi4w={9rrs;k2_i5J)KW+ zi-JYz3*N>CXN3zsnG2dtr+RQ)@ocp+*%2vlC&zhCV4P5maiqklI?&?$kZ z{R(}PCAC&;O6TV5p1f_XZuz<+PjY7kT!~y25;XayNNrws=f0*DH@ekCx2{?D`cRFc zZ#h@$t;Dl&3sjGxWoC#YZ)n_f@*p(T$Ad~Tuqtp_wN%N9FOjXHzm?jZw^kAiw zh5Fv@%lxJI`1fqyxpv|*$0|+z)zTTs{2y%pC*QxMc6<59YtuHS7EDO;6i8t`9>u4! z;hDmY?T4h9?p!=#>Dw;GAtG@%x^c!N4*7G{+836qOw-m>b#kxdb)7Mj*^#GQ&~u7` zVCB-?K}Am=$krVw6q+J@X^P94CBmn+o$2J$n~=D1-DfV`=-Wr0D0q~y zykFa}_DtmVmG`+yK8fC0E;`+6?Y4FM9~=Mhb2=cneAAf@&CYJMStn1Pblg_CVXx@V z1A9fYvldqWKYS!|LM@k#sMnvV>z++KxShALWAXw&4b|JXZbkj{bi6*bu<%OrwVt)i z^WK!W?tLZ^epBUwk;(_2qtmntAI8Q=-`d%*+>Xc0;fQCzZ`lUBt%6zS(j+c5Oz>A_ zF7oGyWORJ=AXm8O-CBvSFALZg+sW1?Tv>jYzvoxUkH*0HeD(|p+uu3PVLNQm5UwJ> zvj3uI7uHJ@XQks%XT$0VRr*df3J$&}Wa!%AiS67!p0awAJaR&oG zaJ#b0UJ1N%^X$>*zO#;OI~I23={fnB`StNucmAKe{rI1GY+YDTaN^ff4(hkAoc9Q3 zRBC%3fB27pq0RrPWsBl|#!A~*{8@R1U+{48DgSd@zO=-oEvs5ItIuTiSq0WIlf@km zB~Lspa-8LD&ZE3k!Qse~>0P{*^JgyQA=|eu2Hqnb{wM_9?Vhb3XF% z^_O6reo0O2N=oY+j?UE08Q=E4Qn5NY|E2_6yh!uW2L`>}lhTjHEt1g9_+*v)#4BL; zlFFjY9+yoy8$1KfNl7#vUe{JS+xpmdA(f0%n^OJXIa^NRY1Z%feEUVCWTbH0&VqeU zX6fz8%THW(HjzzNLUbv|6y7B|+)TXf+g{cx{Mom(*723fEsof`TQVnqee=*b^234K zb}sz4BPJNmd0OG7Ag#)OhQpG*tm{nChh3d69s*`JQV(3(vu>uS#mTIrT^g^f_?P#w z?O*(C%H)T}SzBttgtiF3b$a;VvRe2vK0d+IO0o5yKOR24u)&4#WX?CY)%p@SVvniKge{bj7UE+UR^ZUWwx%d7aJsf^- z?yI>czJI%8UR}Gl;ia66Q_`FaeT6!Gf#olH*Y5TeJb3E#2fkIOEGrr~k~K8L&uDn{ zonEhft4C$!2FcSWpMUNPEu6CFO|eP-gk_8iR;tKKMZ9~IaMH3U>HI!-p8YR0{(f)X zvbSRMe4{t5&D+oDo~nHp^8Zi3^WzRT6^>q3eq__#DRO5~BfC=O1k=>*5544rF&22Ez;;}2tM8PpI^s&bJWa>ZwtIUPj53`qREiq6&T*m^R;e6N_~vSw93xw z-0JqWx4wRn^s?Rag=?1GQ?q$8DT+MYXCzigEU9R{8U5k$7on0U7Mr=E8y7vuvh?*n z$hwdtG}Lppb5f&brEj8Wn7G}Qtw-i)E6opfnmR9NnlH<(&g@lHr5X>Hy?^)iO#K1P z{{<)Z?BDv~Po{Ha&9B#!e(Dt$DLh`r)9T3xvg6Mi-6J|K-`SN#nxf z2YDyw?J}4fvZQm{y)6Yo2LrB%G@B@&by=Gs@nwnR6am(sN{h_*zAXQL`|YKv%5Ts9 zx3`yhb6WGz^ZnMAckh00_t|UwW>V&|dGo)%+Ptjf!=f4Y%TKy4df8hxedB^hp00j3 zuQnXL5&iwkwY{gm+da+dP^y_X?QGmrtvo*?XXZa|ma!i_KHF*%3vc9+hf|q9_ROBd zKEvoEW7R*C-1BuaOS)p7HEP2ZCJ&2Sj>boONCnF8k2w*5~88B8du@J>EZcziINeX|vFI#}6BQ_&pX~s=Vd( z>wTQYKApE~eV28p&3ot9{`y{tgmkmQj|ZXaJ{a?fO`8;;Y`jUc?CiJXf6>dne%q)K z{M4zbYr?XlUoKXptTMa3{CLi`>0PNCSbUU~tGJ&E?scfTdB*wWpDmMAtAC~WBwNSt z(?0)d<&7!-YqL(?e60U^j!55$WfRk?+ijBH9gV*I>t5HiwCgL)yq|BL#h6&{ul#@8 z=bd|Xb}zWs^*p8KW=P(){hxM(nVoG&`~7xLcK*LR!B^XjS1slHzio-*HBxXjh{9xU>gxVD^I*rauibFqozy*F19 zn^L^kXBNFyG}gZAvDuET@azlY)@>Ku7Eivo;LYa3xa3pfZ5O3-x9PJr8@8G)%lJ8A z^1)^Wqg1mk5ysN36Cw>ZFJikOR+_VQhSSl;*1I?Dgj4K}?2o&%_3G2+=;`zPrN6MR zvWoleUlV_>yxVkgKWEmy-PK%FepT(b3uEoc$1A?G z=ZTu9q<=lY^9%ycT}A=w zw?1i~+xhx$zR}(c=3ra7jEO7fZQeZZ^cr>n7rq6zSNq-i8Q>f4x&PK8; z+HAFa;kuj;<-vUXUrtOhZdln_P>doW|ljNRp?2zq)6YA9OJj$azvfY z^og)f&-(MJkD3dEKS`LY_Cu-4D~FDLJm`|~{nz|8eed>2nFdd}{_w!MdiAMMtEW6V z+bEEjsd8e$kMgj!K}|efi<4BH`c9pX+E*kItgg{w{Yve)o=1%L+TPIB%iTD?tSVci z>6zF!OW=bQ)9x!0dvBb|%D>0C$$6$t;!G9~y~#5zQ?4!!{LQv_hE(Wk@vE!Z6HB&M zX<4UUS)nIjuqQtt_2#0)_b(UOUomYvI+bPFrIkzO31)Ti-q6+zV@_0AwZgmgQT)%V z_jVrN5_+`o&!HO)x>|XYqs(S(S>)WlIbw>tw(M)2h?TjOp4!?RY(Wbqi8X#Yu|?HE zQ*!e0WAbyQt63&$RvR4ARZh_2a_(n@iQT539J7u-xBqu;Z*Km=D~GJ!?wy)% zRaJFb$nN``Z}Y0__TT@0r!D43+T4}aYwMa%i1!7Yh}rG-$z`F~OY@52e^nPEmaLt( zcca4HyyAzu`Ome?x$x@t#0mEw%=&#uNcgbXdWJhEJf4{EnDwL8`ng2itthkojzP)ce)Kl9IDJ=Q+IY5vkgk54go))^XUq_oB`^@X!eYO=o8T(IBq z&PLtqnNKFvH46$Vwx9c89o0Oc&u`{Ezc)OEiSp0mUY``xt56f&$*}b1R>9s^w-3k{ z9X)Jdx3m1v>}(Kylu-na*K z&1#<60jZyJx97_4SbfUi@3+VO^%vJ=@@8FM6PI5eF#CES-;0yev<2^Q+lTH5$lffF zdumHvt;-WFi%A+4Mn$d?ul-ivPgudW=4MeO)3ym;Kb*Q**ZkoCYhAMtquxm=fp_K= zFYb0+IDOx5{=KN5d8!loo_)G!d-Kk`)sin`wlic~K2o_M)e>+z((zkc_QW%S+dp$Z z6-+oQTEt#8^F&`w!&ifk|4ywq(EBE)^Ut^4580*nY+UqUK}^$vCq55 zVE;kq<<8+smoA*T?0%X3K;QefpXcwl<&v&yd>gl-I@okV^<&2+Yl}rcp5NsyCz$wM zx+lRkOOA{2zF)@u%{BrtDy=b`(VO+ozBAt;$;)C{btCpio-oH@Vc9=yzWM%ZY`&B| zeR*NiW%t>+OP1e@-Cod~!T#9Me+_&3d|m@#l|O8k3-ZD`(uyM-8FzdTtZNqhbXM?t zOWqXj1Kd2{rT6gH-BIV?mAg5&M8rmPi&nU>kkc>Tb=F6pN?H3J-|=v{{`C!39GCv4 zt=m}Yc&*4{&)$cfUl)A7sqlyGWBRm)-Ic|eKeQ~^cid07a*RpLW3$|?zPe_?*GdHs z>zV}>9sBB;$FL7ypH$RveYNS(Iw@obUct z!`;pI7sMWM{2)DNZA6LNG-Xz+p04Vg`mVdJ@0ZQ_w&3IaAAC*sAKWo~crX7#WXF^# z&yO{qJ~^#==f8|IpQK}UGVFH@*PF7Wq2%`35UrcLERR}ge%MS;eKkq9w`oa6N|a3;vEG+ z_Ks^54!BkE|9qxw@$!26dbN~!c1!HPK642?bwNF~@YKU|JbSz{Ubw`4_78BKw{QN} zNISPe#UT4@pKc2sW?r)-@X74{NbN`ZY2MZM{jIP3DP)z}`{>J-YQDV<`DVGR4!nMP zeyQ86T?Sp;?}IH@PdT0(;mLS@S;XxZfAjY2;5xkJdAY)+Iq$zMOMkE=e@^{InXj4C zI-8=~&U;HabSRY0_$7DD)4npWWZ|lRHWgmW{Oz_W*Z!Qk#@$Z-?$6kh#rLPy?8-g* zak`$EMH=9AXx=lo9vzPC?Nk4!{z|^8H8F9Qi?vbCvPTRB z?xzA7Uzp$D|Ml0tc?n-GDG95e7P&rsrOUKKD|^EGpW9b2S^a_YfZ2@6p)xPGU%qZ7 zG^I*w7tc=RR=K~go|iLhQDu97=3L9C)4cPiiKb7lpD``%)!vdXt(&*|A9}m`hQ-F+?t{-|JutavX{e!x+S&Wx9JcV_SqG?XU?!tm6IymvgcHRgsv`+*1xCQ=ZHkq z9=@C-wle?x2XUuU7k?i35zC>udDqhAv%an1{yFE`*EfGxE#+Ih^Uma=W6|I0eqPOA z|1exCuz2a$Yp$8RK@Ge4WWG&z3|@GB#$(G{O+u}4an3tk#kVgxlf}@g`R|}u!S+MB z6Ahe}Or3f5j?c>ASCd5!Usi2X(wtqiF8-az#S4Ggmi=Ilw?1~nbAPs}X~(Sdv(vu( zJk|Z$e`dVJCx=`2)_BisTW98q8Mzm+3eSp35Uux>>qQ_wW_5p@ z7xdvrPv4OvM=ok^-QTr%YEN!PnEK;hu4?C#k1KUQCV#xh<#W5z{rA@5>F4ET4>60q z?w)6xowcDaect|pWxb}U@A&JBb5``ez42h5HKGMIUx+>++pnYrxFd-7ah{KJnYjX;Tg^ zH$2>NF{bfpPwoa&tpMk?rvdx?=PnX$vpdO_Ie$UeoxQBLvXnv`z3%kxD-+Q)dd~JN zc4vQBOn&CVi*L#_qc)lx{_d(f@z=bV2}MlTlK5Ih_bG@k`B%Oj0!Lo&GD!&|O`dMyrxB7^vX8+MgMsMZ^YpmI^NaNh<{J%#p{N%3P zKle^ds!`{muFe~$crTr^$yBdpe}C!g751$zud1VLG?(v6msz|}%=gsF?4Ns6=d^VT zbStV(E{j?TuRnLse54kq*ka7Z{6W>R#3qjCAg`;J zqW!vm6%)NqK3}b)*%~>OvET{kkuNLaja=4Gl05h*wa54GNgjh$-}{3l&KAb0v@ZND zdL-jS%(O4P(?4JSe`|+PbmgzU+u7ahYU|Xd*6&c-wBpa2mv1{l1151Dm(S0*SK)q> zJDpu^^(H;pwflA?`Nmy~mwX>)=Evs~H__4ke!};ekJ)eTjJ=il*>7=!?K=6F(swJJ z?>%+Bv`a3#EU33MW$Jnxo}b~n*6i9K_nVl!(|26L%k{U}vQ}zqS&nmUQsW-C`SWjvS+Du_ z?8Vx5Kj$$#6<9yNdf6@ueOu?L^BC)mf6Yl-B+$0zu}F)-k+x3lI-Zi4Ux{U(zJ5yg zIyK*M$?##ukWznlIn5Vqj>%(=@bNyszagWP~ z&ZR$I;=K3mr$U!m*MAh;sMTl*T%XxGORA*C`&#PRlWs0nb&Fp0#!X(P!QHq2`>NhA zZ8tOIl8S#X@K?N{CAjRt5;n)R;+}y;m+XFDaII`&dN*yEm0Hyo&JuzB4aXT7Wj_ixyUEvo6WgI=k1@ohvPA`;0FK{sdaApL{9I;g)>CUHNs7{xe_N z+MmzIeOh$dKYowMrH6v#{{MGa)wn0-p#9fOgXRh`)5fAUb7@J)yRdb^2g8K-^Z&rOKNFoc`oprrLpUj!GZG!zlOGbkH~p* z>Spb&ABC-t7U%a*arpg4U&8lE-LnZiajG_pBJC&kK2=$0m%HM=eVr1&$M@|)_at7X zJ@Z)ftMkh0SlNJR!=L~7&TWogo>t!TE=PA!jO5WvIR%|pj&E_X>d%NPdnl>-{MWqL z63yKodP26QUw^ZSTl00@@uqI4sZV_jQVyNl$D45}anTEl>RCElrhJ%vBPOuZM8Y9` zdaQ<5`m#5lAIRjbJU3y+lPy6h0jH<9&CM-z<$rzX^VHaY4iVni1>-mOHibeii)S4)t>~Vj?w1rPTueh^( zmF=}n-SZ@5Vs7tzb>-ai{}$Dz8)L)o$7RQ=hw`tUnycE()VM3Teal+M)osn}hknm% zn>EYsb5EViiuGoznhnzfJFbM4T|BH{R}d-rQDRfw*~$NITrCVrQ~t_az2c*0#ub_wT;~FEUzYf`_twm{=16FBJ7fvw&wH8&U1gx=nXMD zF;DJ#`B9eWFVCD7N4D3SO*Y7kZk6zmZV2%$z0@$Rnd8dBH%VVloO>Q`m40fvpUf%+ z&!cCTuak5;bpDI^Z01?rDPchy@8yJ?SGc6NxauFjW~xWv&7;}2Jnfsf&B~uSxC&QP z*QWGKMoakYXgi_M61Dy0qU5L&nIrG{GXy+(o7rq0)aKX)wuwxQU9j-AO6qZTk(k&| z1$`pM`49fNYefa>pZy^I=YM(dC6+JOCL3iRP&Usm-Ty2abI#K>yXN-yfCjx z7Jrv4{hl>N;l&yO%bnr#$&|NRlf?GhcC~eRoCJyu9@9su#@VPs(a8 zFPLiT{rvK`<%Sp47HpPzV9U5sd7++da+`m1?Orhtsl8fRes-4v-XCxYjrnzKch@E3 zO+HgTTkVa!^x`(N^0NtMbup7JM}7X&ePNzSVB)g!Y>(D#C+EW*iFYc>nbpD`F1d7X zma;?D!#C9?l6$&;zYCow$KmbM5OeU}H~mv-dOR&p55LIuUv%6hGjPdLZL0b-$ZaK8AyVZ6%*XfA`>m}Vv z3kqj7EwC4w*_?9z$}GcuCzn>uJ3J?&wRr0elb9983)aqhefUbT$H|?Wc9^ufmtL~G z$kk!fI_p^dpRaGWeVh10#`1}BZq*h28wwJu1G!x@>pbyho8 z>YHm`-f>X>SpL72?4=%WFLq_|1*)dp+AFrH#O~y^ZP(4_-AXteo0)fER{O;3+2?Lt z;N2QFd5P@Yi}PhJsdp}JKi(F@ZlvL2r5>fYFG5ZE)5IgaptZTb8j;}yEK->>&iSi(6WKJAUv z5>8FQwF>4Pr)`IG1DtIu)RsBh9hz%+Z+@rTu7`Fzttvho z^RSRP7}IIBWZh!XOMYBZ-~V!7Kk0{qViGR`;xt>L7o#UVWE>&#af_)*;j;42S z-QxOKpj*ew`>vtWc9M~e%p=J~%RYRF(qCsbamh)!>tPmt?=5{xZ+*VmT)#*=^{CivbDcGn7hhGK}O52lEG-&;@SQ0Tip$mWWy6XO158L zZ|$SEe*(X)mX7XJ4%=001(vVB5p&!6LY1lJ-o2kc%)56uwD5)4*7H1z%L9rIzkaEG z=1{@9&_h#>PJA~rIJ)p%hD;)xskXOz`;42{s_Xli>;I?rH~snZhiTf~nB3MbXP#%i zy^~$f{q%77wW90U5=LA0hhfL!q7`3p{4UVj3>wu zyqm79%A30*I(;Q`_j2FESqiz2t~c(!{55aicjMi*3P&wg&6AsYo%0`S(5(DS!|p5F z(|>p`v0JWsDYEOM`n;pfCpf#-{q*2g=sg*mSlpzwXru6y>YzS_3(r_WGfSJi=JVWP zJh$xh=9f=co=!7y6WD$ABxjcU&(s3muA5WpqF?iA>Gj_g(R{!0%8h{df~F$xU29Bi z=DdHva@93leZ|q3REt}kSI$p9!1?OXli$2^o@YE`*;-=z)e_XaO`G_uY|A0#AU@_r zqSZ_WRws;ul%h5sKggN2CS{s%$Q;IL;j2?6I=(b3#qsVee6~R3rHx;}o|)a7=Pa0Y zZ_c`#XG_ZX&Odo4a;a^~;Tf`P8+0#Ku6j3DebuX=8A&y-a|^-_GFqORA|h#`bCO5$ zxIb(33VX$O-o}BJbT3Yj2l4@Zl2=`+D>jyJ7hvft99F8{Lo2bna>tzQUJd zwsMkbN#T<2naYN0o`NfX@BO3UvTBo?wukzPvpa;ZG~DIvlG!VCZRVM6R*z>&Jmy#; zIIEX?!_Gwlnu2S0_@zBB@ov#7XnHisFF;}AexAn>TnBlyqS9`j&Gb32-j4g%jG(qF zsapB##vZtbz6qHI^zD^q3DqZznvv0o#Z5t}-}YVq@-WV(eCeN=Z)FNx1Efv9 zsFxNsMae#U!lG*GrIA?i6r|QME=A|Fg<~hr1YdW~N{3Tx4rXi5nX^F1%1=psMgN88 zA^PUQs=vi2{+il0o$KdmrfEO735&eCygPXDyK`Un&wQ=v`^>#8sD7v0iH3`>Z~F!O zJNZG9SKu4_kAHi4O41x0?EieOyyVWj=GFJoOAU3apQ%1AvH5U-ZxLs9mB!M#ugqz; z-nf}B_kWwjl6d>tnX6BhdcPN5`?X#9+8R&qy(O8qf0>$uM0GT8`^&5KG}>on?TXb5 P3=9mOu6{1-oD!Mi<)dQ;-3$+emvcOQak0haATVL2e(hFlRea;YP+qM?7Vg^ z>bQjNiL(7X%1XxzE!HjgSSWMz`d;C>MNS;2HoaLET=QoEEa!N6&xaee`PR z)2n-5Ni3G?mWVCl?>eE)&2s+w0{>MW3(Pnz6OOAi*o!UKy*KH<;@`^){MViED~%2J zTrsgMvyp?Dk;l~IL_Eue$K^Sq<;x^q&r9N2t$67`*3~V_o^tOlib^Q{bdJ8dC5xry zVylioS(wnq58MIUPVKnKq1yU?|EIefc9i-*JNxSDo!-qC49|bGFfML8FaG*FQYm%yad zo99_S>{{m<_@qs4{fWz&U5T(O^gs>-8o@dX5_SWuMeH6 z4-1`^>U-Hh|C)eHph#%we)jIQN5c=S&YZPt-S*tq7Uyiv-`@6c*L&+#uXpu5-l4<2 zROH+RcLA1yDFzn4!bcu3eA&?|ao%fEOPIz*Zi%1D*U!c7KDEfApa$Vp*B zhqm6vfC9&h=UAl$rKOKPwZCxg+&L$gi-CeVF$MPvw+9y9FLy0uJbLZ`Pw*M`b7!8q z$K9K~XXbpKM8A)ZpY1C?xA*&;_mS_a4ewvS-o7^KOEzDs#OnQXn#;?|^rE(8{Q2>* z`1v{B>?4=%G)(GnuX=TQx_4{#=Yvk1z0a=1WS)2D#-`NMmzVqR-o1PGu3a*j4-d6oc=qzj z%HZ&|QLJB03^Fpz3nX5zjo6rUq(ksu%F1WYo-OsBK1&& z6MVTn{hr|eYhK+!8P9urdvkMhMV`%_yNaD(&Zhd?nVok`o@y=sZ1?cj*VmDPp4k;! zJ~B_rX7#?gE9l3cpT)n++WO_~>wbJ-EMi^ym{Vjyp%&Yuw71pY-rVdfe|N`{Sv*H7 zY+X#|@fq>^>;AsGYrX&ax>#f7pVp$xhN(G=T`rznez03aKQN55{a{yl^M<81D~*1C zdz*at$h1`p*1FXNXZKcrm$R#p zco{Huk!OV$EzOBz)#wv_&n>y@#* z)W|Pq^W)P~@3MCFFW=rqPx$rc=jLrb3p{dCxHCNNaES_*T`*8A_;{=G(UH!---2&4 z9g4*Ny>`Go-SnfZ6QSHfW0Z+#H<*turz7%m$vX&+^tc zc9ku^-}Em3QaK}0aFxaB6vxR@roS#OcK7OSQPNse@Z9Wur9$Z*ZgIUe@%#V%`1qK| zg|)&eLgu_rRR5$Bq2!!RxBmV8eSc4-@cPr6&X~-xsr>Ze;o&o@EDhwJN$+~X5v0Fg zFMi*g>$Td!%3OIV7pH3J`8=8UqDe@1R?Yoew^sS3E^R7!wK~H8ox6VAo(UdixwlmE zU*7&S%{z0dxoO1i^7r>PCbyd~s_t=U-j;rTo^1u!hlJ!qZPEGn_PlHo+M&a%BdLAl zjoLqx4YAyJb{4xkU$}hvaGwxAlSoVaOkvwyrBi2ry1hL=o4+(|(%Ku7?4L#-d^oY> z>(|%eu4Z{+&T}96e!sOfThcvaZS?kc@9yqa>t3q#>-O#2iHp{)^LxBM?X1+fd*Hv70k{Q0qwdqdQM zIoTXr{uhRS(mwR={(k;GpU3Cc$QEjCQ;1&mPGrZc{Xs%kduN;H+}Kd~_?Wu?yd87Y z=XuGke3A8%hLg?Kc(uoNI-eCkt2r-sPu(Z_tX`nU z@#p)bqn}glml)J8(5jGViA*>*b?y8p8#P{uBeCtihf1c(7x+BlJRKgiXV#-+E9d4d z&$kC%Fq@?Hr=TI}cB8#7cTd!peES2(k7@De2}rDXV&2Ab;8m$<2Yc#UZ&M{b=9RTw zTZ)&3>P9Mb@E%?8C;Z{7nieP{&rbl!JP<6r`gxj{u+Or|3Bfq&4R^R+qeHew}esg3&TP!4}T_>CCv)+>yH-w z%vlg4DCoL(+vy;IAI+?yf;=1?i#nzRgs||Knq+z^EM$4fdDbLKA$8KpDaC2eey`or z9XWY|%Pn`#_nRNxnQWYXPV(K&o4;*;SAM%Es$J9;{jL61shffS1gBC>jXNO@6Hc2x zGiBbt&$8a>W4l9L!JFUO}z)5}GhC2`Vcg=8}Gd=%! zSt9SNYncJ&D?&dnySuC8)vb-m%lTw)msc39`P=-~y2S9u&)0m*cQ6?pR@+$pJ?{ng zr{8(^pFR63cG{+#Ns(e&)G+s`h|0@#n`iEfWAd`k zkF7bfvAa`G|LnT#J687k@tf1Q`Chzu`*+C)hBZIh+(wcSHb5%}8&tX|2eKVzobH394|2Na;FYN#E<8i;|dnfkV zUoV$W_&mSn6X%jQKR-V&v`@+VpckQQ={e)U^tdWbHMO)yM>;QLoiI^Y@WXxQ{Mr-m zk~IEQD^4#6*|A#EIBmiW;pqq6fAD<>v9Uh9#b=&P<-b2aCj`!kiBX-BSm-^W@F4Rp zt^=D5HA^p59kt+pc!{gV>DJPoTJf^-|KYt1f$J+1f@kM-TkSI5;dgkkX7yaQPm*=- zd}PB~r?lU0dpFVAmyKiTjbpvi7nvMViVpAl^=h@}WVMA157UzG8>uMXJ6iR@?auX& zkB=`-ZOwHpby0D8c~INMc7E$t*A7PR(|&stzIAOBx_hJ9i{%v4w|T{f5*Ep7JYwD1 zwWWF=!y?0d{C8H}KKyXCf%43GZU=Fe%r!M?a7y7x+Sn?aptok)il4`I;%dK!DygyFl3@JkJ&AcuD6u@!WHIla7te zoT>6|{VMX}-E%*#t@`?^_5WkT3EO{!9SPg68P6P|F=fKM1uhZ=T77qHy0;(L_DMIa zy1S}PSACoP#YOGG7Gd%?1*LARt9*KGmb0*&gmD_rv96DW=M4nU9hk%#>^$%2?h}HM z`ET#+oSfUF+}L^4Vq-*|Sa)KqtHTiiLw6?mx{kjV5=o1`q(9-Cu&VHM79+X zFpg_=(p32UZdX~)?41wpu20|p|LdFS_WyRh7Qf5p_Vv}?1*cbReK^#-aApMt1u<_ulq5_H1n?3MJ4MlZzw9-tMd``sRP$yM3C)W&ZyvzfZaO@&1vyH=dP<#CsoR>UeJYXWHsFPLk6a z{|n6Sn%#ftYav&vq=xjK{6^1-840eBwyAIP%sQdY%z9KbPJM~hJk^4$OdA{pT52CJ z^w*g3cKM-bhRCD`)Ak0vW%+xE?WFF)1vb}84|~*Iy1qWCwQK4hX00Dnw@2sfS@v(P z);cDYz|_WjyiFZCoL@IFr$+3v+xNWqT>hQ?sil9~WIGF!m-YVsv0K0H_BN$w33GNZ zEiqTDdRXh(74(3s-1D69q`*@lE8Z-dHiy~c(Ps8f>`fgen)x5SIt{8*OwC&J4LaW( z@tx$X{?gU1$Ata;q}`8r1nfTC{L{6iu|#V6b8-rAdQOhcPnDcjF7+vb67t`r_cF_;^B(u=%kWN!}3&+du`FZl<#lt~GL47e++nxkGX$y`%{=PE*=|_(9 zj|&-A$fe9r`1EWBU%6~3Q?}8)qdf&S@0w3`Di=&By%AvkLHFXtivi~LvBPXU3N;#iy{ivc6z)0AJVR||eNTUGh};@+cc2fQn)B`2RxXPvS-cz@8}<P`GH$f#D?Atbw3QIJq)<= zrjT1zfn_7lA|WY<9ZpSZVXX`k=FV6gGP^LX@3^<4*QVYurse~jCqIACO5I`-J8|oW z56v7KDvrjzoYmQQN>5X!&86K`Y~h5*KUY=gFD!U{nYZEhvsOvzw>kC!dmB%teg4j! z5w>+|=w>c{f!YVNJFV|%tw$5B*NWoZxr*c`#R4 zyHI7#oB$4^eT=M{&l5|}ug`F~+04ZAkojNFRiR~vmlrf{I;wo_WMzedgA7|^uVN8{ ziRCuCt&s_hs z|DMIO+cPvLx{LoSR5?`2no@5i7QKUOXM6nJzb`kKg>x2smnnAlS7=^vhvA*_Q$|(C zbsHlp3R5)yTfMXp^-^D$Z?~h;gj+Gf=SSkD=+pCLH!V8{)3;V^R_;Xdbx4V-0ZWvQuZBa zJ2`7^zWHu1wsQ_uvu-nQ|G(Qbpl#`bg5Q^UkNeNLwb4FMjHN8^=8DkMX^+?zE||yl zvUa~()%?Xt3+BgL-d(u9%X3A*%1t3>ng6kC`toja{P*-JpXbpDr>EUL|5WZ~*wl1G z)hAlND|PbhQ@J0_FHrcn!?XAr_nM&9K|6O{)ta_G(h^?&c}46 zP3nJJ-2Ze=sjbyBP}6^>QVi6WDjqJ^c0Q_T}}&qidxq(IXrhf`zh*$mT|6+CctBJ4vF^YdSHkq!+#k`Pv@t2gR)?wPumv|=e%`P@Sr{A2dlNwRt z?{Kek#{>Ch)nxvektaO3HeU@oe&74Mw_W}zsoy80qy3Nlt_uBM-fbRi%&mDpP*Q;< z^{k&+cdD4PP-K*$2G>{aF6Nbfj{OetY?Y<0)q!_6{C=>peE%HFoJ;=lKC^CTAL0Hx z?fV<~n~Q(1sb6ciYmvXp@8x1;fA$ww>EDohxJyk#!%Kb3%fFBB|1CebibHRE{+HGj zHM-|3=ht1F^ebug!5;oqPl9(=H@mkqeTv}X3cvb1_D?;V@VemhbNoH+rx!h&^NMZt zC0=vh=<;{7cdJ#^U0Js?JNbHkw=mbMl^^7T7pKhlmwC?N*0NgnciEQ?oxk2L#qLO}FjaKP$ghhvnYbJL|e{_4S;4yUQ-$yZT$Gyi&T>H8FtM zw`t1c(}j07Da}i&)Ovk#?ylvo0k^Dbf0cMWXmyGd`c-&(VPoLAfLx!$u5A7Bl9HX} zVrLV#y}akPKD6+3aLmW6(p<|AzfkQ-i?%Dg5a#$=>c_kf48cqqk;}gL^Sx?mZMo4{ z>SoD2xjBS8S;;GCk1MOv&mhwa%XsweZB#kaE#1GM)unRdl)hMTGvDp6&n=d$zs~tF zS4P6>>&43CYCp*rtvHqy_@|Il>d=MwnemNlI@EI=MOVM#j4-<%ai{2) ztW9u3(poNsz!R6Zf9Tg)L%@-LAPpzwh^*)jgzQY~Q}9^pJKR7pJ0k z#UZ7wA4DWB&2MJonzGB-vgw@6m+s{+{MWuaJ>|GlRl}CXbHBb^6t1a>dpPdj-+Hz`w_b0JpMP_%$orsxwo>H{FT=X0^#@p9pLV$IXkHrsy5mb1 z@OV2u?98-k_rz}fqOV9i(5@o)T z|KUMRR@mww%>(foD{RCXk-F82A@T&H<9`Q}$O-&yy<_t)LE za{SuVV4$$eX<=DF`OXYDa^nOqgFX*Q*{=xITCrJuuHC2>)%?S>+U)}64s-NC(} zJyXqFZSxMHYUgE|`!{Kx*Xa2zy!e`IRH{b$a(@-B3j4+8Yo%&srrvx1weJH%`E)Ub zk_}4}M1^K$$t>f#lq=>o=~2}VS*NtW3x8Rb9IqHe&92!sxKKj z^EUqQS={g^(SGhEOI_j9iPD*gr=m^XwY_MWxa7LI?aodK4LbIncOrYDm)j^vkt-T&7)p^4RFAM}5JC$M5^^+muHfKY!}yk39d#Vzb|K zJ}_)iIHSCa%|^+z?TG1mrW1L_TlT-Zzu(^UN8VJ;w_S!Ve9dtw{K=XhDknJ{c~h|B zMlVn09G7o*CMCanEzTg{cK>Ntgv9bmbDxUlJr7>E=joS~&(snb-)QbTa?h`G@7>!k z79FwEzyCqXJMfs08D;ICye!c66>)h;bVsa1CPUp$5nO0zbBxat>M$w!mUMJDA zfFnDWUJP*VKKRhi(DBUNw7VQ^lKzKwaNR4_U-INg4Npj4{Uf12TFtv-dNuE)owZ&q zQ<3!V!pBfm`L_C7TZUr^JSMv(>dyXJ|LZ27>~8xX3E!{1-MuC2_R7@R z=R%w0JiK(@suZ|q-TAavlq=DDgRYTtkwA@S?Y*;M?rH08rfgGH{coE7_RIWhe)IR1 z-MX{lrQqxIGx7iL{@Rgh7gy(+CAyIN;n#hCzePv#x%kbodoN%6Meu4u(M2~#yDbW? z-(`5jbRryzQ@hF%iX@UxZdN(zuM?zkr?-vO|B&sneD;~g4!8497m$n%TV|TQ>zUCS z{|>8lxf}1uC-1kvS5e=z^4zyO3vwe%uURq$clX#VWY;wIPMs+p#=7;mUz7fv?LJ#K zPkv*Wb~ak3IVADfnVBmT7lCAGav|~Z+)nYy z+1o$uT%UDf%75ec&F6&UGe7S?yxaecy|^pDu!cQLIU~YG(72Iim0O2~{`oef?@s6%l%}_Fn1aUPh*# z)Mt)C#&PqK_A6$F$DBH7AAHTKb@hoK>J_%Lno`6L_!{qSR=B0vV%6gGrqe7oVp8=c zo5=?REe`a3UTaX!C%{!cJyCFjK;NRhDXGD~{%(HBw)vgI~y93D47AGxw_B zeR#$q-RiaeD!a>D<_84Gy>?q*X|nsA@uIVfX5M_@UarA8@AIJmg57_+3jZb|Zfv$<%k`sl7Tv(7hA@bP2%#~`18iPW3j!l|Chhp5&r-8 zm=TK zX{vtXkXgWaR&2HN=c9M}Qs#J^^Rk@#^ZTX6pLt|LD$ImaFL?aCU?K2cLG|t@eU7w9 zDgKbFMKeRq6?|Xb-mV|!y1n(1*PFNJa#l~vy?W6+!%FoV(+`QgLg(b{XI846PusTJ zkFe-3?W|LtD(-sJPeczzd~ zT?>5WSG`Fuj~Dve{rc8|1ua;m>&>m&_WH`+v(0yJ zZFwKJxo-30m(ROPmMhLKF#YMTGkag1)54xsr(L?IB$+aJy)-wT-XKbr3z9Wg9=W&5 z@Y*GTsRC1V7RmZP-aAWn%?+iCw+#HUC8pm_SS&U}$Hsx%eucD^;ps@mFS4B6+|3Ua zl}~kWt#e(e^>@4K>Jx^0tG_S%)-6WpK zr%2tnvpVkRg%5GX_p^TgT)i;4z5M60^3(IolGiOyV)|sLp}|qCc*)R)skkx!7=K{N zc{9Zs&x}QkiwX(~3|cpZtXuST5v%#JvlA!92kqF++kK-YF>vRvN8S3D{;j$pRJ}Pg z`Nh(cNyjtJ#hfrqzqaOG{M*MXB4b~*nXSBa!CU{m#+z49I^w=hkjZI1mG&$D`s(oh zl}s)6E9Nb9ZcjQsW9#lxYxW7&3(xcH^SyI5p!VL*#qVA+-gzwK{l;{zP__Kx1xMn_ zUmZIg{ATf_vaodz_M4Xe73Pf>kUP**vGloF>G>YXbjI%&ocR~dbewb8Ogu@km1n{U zkH__A_{?Uxz1?BR)9r5<>#lKUZ(HlER<80IQRzh?5v7i%wzjq!8~HytStlo^xBogA zb~p5Hz`EGA>s-CwL?#$sY4LMgGylRb-x&sp7Zx~XY{;l*{oL!X^h&XQ!bO2XP4<8= z{!Cwg_D2f6TU}RlFlMjdad7QU2PC4o=@A5bO z$}Ik6xwD>usuQo}sgK#@ZLT*j6)W5vf8M|BrqbsxZ+iaJ7JrNTVD>C^_U6C5q4HV( zCV{IHhh6s`UYYB6_uU4|CuYs8khYqi=0^LHA2-Uom6q#9S>`4_xyLe9EWC2fY(_Tg z^__Ruhp%`SytZ#+(b~|B^{Vr{{Jg!FMryoV5xm@A-frTgnNx$`*l=se?l_V3e9rqj zJ3s%r~q-K?Qbnh)NJP-Vf@2m*%bL%Eceb-1uo`U87C$vF0smN^eMML^>eB1$)pS&p>Gq6 zJF;2iRniaMT)^d#67bKnM($tFeINjuZ@@Kk}$qLd82^n|lfAIhg{ggl)_`wnRsznWBKv}(SgP7Tk^vY-z)SpJx>`LfNI za{G2+`OVEtv*Yh>5#r-NeYoL;*h@9eAKnUU{n@?37^Val3td{9ax~>P=b7$&)$}{e zcV;}qRZ@Is*nQm{YF8*ee#kUg-5^C+}>t+(-K!8F*=KRDYXyeFK9{dw0SSmdZK4&(F<$d4sP%Hl=}q z`RU!<8I}!?ANI*rJ`vP7bg-E{_~NNs9g*KeZVCG@Ec{>+yv%3eY~37wBlefy4EUNf zxi~82BoysV-?R{lKl+OI@wES3Ief;4I_m%ZOn;>8=5r=?TaKh&@wGLPn*_dJbCjGm z+i*?9MkN+*q2@_mZ$9VDy16V;(9)tr#=*mbLx@enZHig=q@FWHY79GL7swd*8L+vl zCW}c2n15kVKU5Uhm-4Y?VM0*P+IH^$^>6NS_rxBpWdE@H_3pX^g9lce3c}7J_W}TX#fB=K=Yri$Du7LFwxOBV!*t~h&mqOieQ*G46Whl!3p3wr;?4!W;kE3)*><5|TW^wmfbrk2 z-*!Dd7{NhH=#?6Yvr%X=X1+ntz159qUQ4rd)KA>Id1t~wrX*{3g(C{AGRCKuFLZrW=+gUesg}b^%^3^c zCoC#4R^XG*I+-8#iBo`mR;?Rfg5Yw2^*(8yn`Sw%L^Y=g3S~ru7}X}ZTODg=u@w^j z&7D{IqU*iR{J(RTKZ~tDE&cl1#ATkYHKG?Y=UKm>y?Ond-}(RlB^0}MJ0`xKt{a&n%tTz_;-Bomb%j$}@^rq_8{gn`yWxN~Gtz?<_{O*UTr>yeEEZD)fqY z9;B;s;N-(E-Ang>dp+Ojl)KgHxXABcXN%W9j{bi3_qF|Je*Q9_X7k6uCUQsQqq~*I zWjFu-w@my0%XjYKf67mW89&wd#xDP3Y4fsHk^i?|uP^>IvF?vDG;Y+_cwyndV_a=>Bzkd8($eN7yDy2l zbLdDVXomF6KgHC|HLLqjs^&Lg(W_2wJAKv5rzJB^o0D~5+vfwX{)9yQ^E-7x{_RI~ zV>Majjg=Xn%j>tUu$9(0y|!>oiqeDSLA65RJX+jqRy=)`>bm_$>2B7k3}H6kHrTFM z_`}EH*m=uO-ap^IUgU4T;oR-#+0SJP9G6_*`~Ow>{a@Rj7D=c6?@v9sqVQCJs+ECI zuijbi{>5Ssmq^NUu`K=c%FO9b$Cf!ugfuSCW!WLTVNnvhWmwJHV_VxluWK_ADcWb^ z#}~?@AyF-Oq3v}{sz(3j(!`yu()~|tC%@y_a7sDn-1GgG#ry63<6k#Vy_K-H`b`;= zw!+bx-nD|s!tv2e-t&!briKXpTwE5=TY163Xj7}izEd;Jr818;9XI!DWjHcv;zcD1&B-o?-!!u( zt`Nz#6jf?I)Wo5;@(Fv!jL8KXJQC-hK2wt1+LgG~y7pIznpRDqdq{p>>__f%IyG+h z`Pg-OHF(Y%Jg{4QV4}O6ir3YO>$UUw(@rk&itF@xCm7Y`=Gm`Wt<>(j^jy05zX#3ycK?1n&N+3Mr)6{4 z-dE~Jn-*<#yEOmUlt8_jA1OB$t={@F`1`S^QIqEH2u@HnO+Los{J?R>(~a!gVoHxX zB|3joJf3xujlr0K#cJKE)R#ky^1DlqHt8ydr)D0Ga(iy%m=N_6}l@_C3L1-&s^5ucJGxEDigx2YUXS@^2uYJQdciy9hh*F7teNI}_}Hb% z&3}nRgFX%2)`2B8qGb`Ka1zJ(zoHEnr-i8ds*<`cT^Bt^<3^_jg{`XRMnY zzh~XG%U4a;MeJSEv()*ZQoy6-GdAC;pR{1|4q4WSZHcd*`NrQ&ye!<#nIC>)>xvCK zoDCzk{rgz4!pN|(>Ex6fOWJqtZLoZC<-Z~8@@}>bOmpL67xcu3rkIuA%3Pkv@-DtP zFJZ^IDVYLa_k3rJXW-Pi)*5x{#nl%pAEp%excYmV=ozX!sj$DpelPh4=c*`=;PrZs zzcOrb?P2rUuBWv(`ugc8<-kh&ANFGVTV70?7ipamciBv1GV`5X^S?;VJiOZ9;^^my zlWLk3#~ZK4zLnZsUOMN)bDpg3OI4YY-t%u*r!ME0y!7Lp@p+rWi#WgiYPFmnQOYw$g zo2ds!T*@(p4?i_yQ+NE;ZPt6(wWiWHm~HRVbGb2f5uct&EI3}^-zvK4diS4}xpyia z_xf3Gn7<{Vu=|Xi@Be2NKbVUH9$QKGJZZ48=Z*{W;h1qpa>YrLrz=@c)$M(^>$OK| z>&MRwocEWmI4k()2IpPjZ|@{`yKh~+n`J}PB*9N?-O{Okh6^QZ&flom&MDu?RJ`ll znMLe-DtPwoEHDau;cUNk%~I!{72Gr1&iLN3sq9T`+Old%)@BgK2x%)P$S5jAKW->EsXE<3!ZYdS zrc?!?AWNR3UhO?gxjCw2p3h`w^e(lz^LOX$i1-Hou4UXG3_TFG4^g>U#IKSnkBmC-^YBpDPLw!G@D)+)%g9z zmJkcMJri$NDmpr@pEY&Qw5V&kT(bofbix*7?vYx4=t#AcXXT16&t!`}RrzY;GS73* zWX~Ru3_IO-sQBmByCD_7-)?_gVK{-Sz?1djzI!E?eTAx0K0Z1+jq{m~j_#k3quh+b z&vasw#SSle^pV3~VTJ77#JI^X?-pgw+3J28tLyw$UW1-fF`f$CHyZa9a+XQ&N#F67ZDvZU{(fmbfyW#zlARHM zM9X(7`o(XV8SH$*U-XFy7h~^jzr(q^tC#8=+Gzed`sI=HkN*YzoYLpAD=$%tXIf;I z{A+gO|J(O2ieJ0_TX?XZ^=I#N@AY>-yt=>cU)K3|40oHRt-JGOs(fwY6Dju0+Fr>S zcYUlpE3)3LtI&I#GDEt1<+`NP8y0sS++y=Q;NlXWXWqUC^OScy-EFAbU+~=4ZDFma zW!i?a;KWBWb>}jQy2QkMp%j zaKDmvYx4JFF)xKWPrm)}Gk{1A8_JkT%EjRx7N&CRac&=?U35NLYX~m*|mMg zjYUm8${BZk;@@BO_|$K!t0Afy!DbPAU!4~JA? z-{AW>RB4IvbB4fU%eN%iP3_#w-F-I0_t5nl%_p~XGjZqT9J#2x`}w?Tjduqp_!cj} z`TbtCeyRL}4_5^@Iaf#&1-$Zzaq?6@@-W#}WQFU_LcZLknT$_)=4AEy9*q@`mW-Iu zE1-PtYtHpH%_E0ex!>>qU$;TPq}wW@<>(^Q#&*jWVM6AgGzG#}9MQ=6KjBu>-5M(n zlhrTWtXjggWiwN6iCT(n<=UlpMJwXgg=L5GTNnfzo;;cCzf6ZU_iXhazsD;*&dfA! z-^X{)?P%G%J3F1)0ty=~fA!8vx+FYJajMU5g$-w#o#GBM-YvG;y3g&5%=|Cw4joh0 ztoY$_(x5|UX@k}qStni%r@%)kI?60Xx0WtDhabo;-7geZbi^ ziCvprN`IZ2VjuZz24izR>!cYT8qV_5`Ianu@!If7La)Xou`{j?OTCuG1|L%@nSJ_2 z@ciO)mS+?qPfysTv3$0Y>kTH^Yr-sQR`X{FXp2nf+R@mkt0u&-L~m;9Po7eaPa$GQ zuPK$jb@I`k9C&=G!9s<@@*5{8UsgXkS7=qse5Lk>ytPRI-7@nhcEnHq+v*cPbxXyR zo!tRy&3qxQ2@4%O4VULO_Uq3FbuO04vWLa}Pd}C3Ih){wnMQAaocsOY!iBD@`8jW1OPSZn+_ByG>g&nL->2Na zy1~>w^HIyk%+nmvi~2L zczM~JvO9sQ>n3P2uin1C{??UR{yX{e4<2N^leu5B-XKDH)pf1fp8bF8SA2U{9c}h? zU-Zc-D@8W!T6s3-WqtbPv}J1~MBI+Px-XxuYWFnf)$9A(uR~I`xOGedR_9AU+08Uf ztF*$1{g)DN*qnpE?&(g|43NmTVu>GNp7Cny(r-Ubmi3&XkJvn71!y3-VRmZ;M-MD1V z_Wsa{KkA8fJp2X!{5?x9UC}oSYgDg0tSsB&~)$QT6rlJDBuc z1&!8C5Uv)^^?GOXiDTWq&Fd$v+{%{e)28`{+wyfobHB`sc_(;wP3hfpXw`?W6Aq<1 z^1rM2`}Ml`qmQ1aAO2Eo^|>ec?^GY;qz}z zpCD&GXa;da*G-su*o&pg;y_}}X{AeI>uz7})6%$L z$u-4t+S|55+t7RKF6_uEeYNkmT>Trv=zSF@^wr;+@4FQ&aQVh!uDoOs-sK%xZSwDD z+Sl)!*k&+8cr`~oQ)_hoUQy=99d4csLef4ON)<*=c-BAVPE2)b;Y_d1z^<|v*rtdg1QS;ZGtKso$r+q&-ks&zepGV$~hiy;J z)tP88cb{)v$-eIG-EHgY3szL0xpnWK>E6HVbKX_IyX(9E#;&ab8x@nDf7CiWmBYB^ zq1HyFq?s$9-zh$C`}vIVz`cR zLnS5Ui@YX^`ga-3g)dnwI?yXvZQC8T*hW<7&hFli4+8!t!v7wHz%K`*%dUWk#l*@&?28QA$@jZIAu-*kE-+;A(`j z(*L-smrI=-o%=T|y)mOEV$b`1ziS@(EVDef-DhIO><>#=G<^h>nCHG^RD3uuM5_FtflnM)eA&%Z7KK;*H>A^)x2=D1$4;4L@#LJXN5YQG+2R@Q{Zs*E>tNCB$=dRkndF#7;=ls9dZ@;py$x>Z6nM+CAT4+)wm%Cz2 zvX=KW9mVC7d;f^AE>V7{#r3-@sI>K|xR;j(=bDQhOhrLIpZTODX7F~@?mB!$B+KW7 zzx`XAQz;n@s~*Mk_$+Gw|N5f4-0zFc{eKER*4tJ6um6+q(b-$R;>SkSe%<>Nn%@HW|`ec)-EWV4Uz)(KsrD+;7H zzV%CZGVk8I*Na@cXRXc<*qpQPu*Y(j7hzA7kMadusq3k zu^YFDfW^mc98Y)O4qJZcdR(>c6pehZMSE1O+LDY!Cu}&lP|)s0?1}J=1}nn6SvoHY zDXt6da}(2vSm5|GeQxQr=uH({7QR~W>xi)bl6kBhc|N}%v=(Y*Rz|}-~*gs7-y6nfpcIL?$ z_Rr$K>z@!g^ECL?+!Gt);{JC>^4t6qzhD3A=GXkWn<{ReykDJj?Yo@ym-+H>Uml%4 zd&49l?z@My<>Rc16$Tbj(;ihwCZ9U<*M9f2 zv*j~hnOy$Ay<9$^Z0hx!Kin4wI`^stHcxQjG?Vq&ESSK=gW$8X)KZ!SSEhi$8_2Rhu9T~TVF1=`hWk|`>p4!?(Z$nb2DB% z)B3}^tvlvazpK7iTzcNP`hEHP^!MR>5?&Fi6`$s4EbqBEVW*Lex(M?Ujr`7Hv%om=j89X)ULs?y{p(;a?&;m@*$Qfkr(H3aBQwWwj;{LKZpQT&4vVF4 z?N#GB;K}#visYWo1!BiuwQO4)v$s^B+<)EGWu^DZC9Hl-kaar~dv(LvH0J##W$m1c zx7(-OUi+`=eXJY*%{3K<=NBkM6)q9@b>UaVzIkEWboYfH=abMs^=wx5x{Y6&4^^~i z#7t1Me`{F1#jWbh0ms7|19Fs1kA0kedzr@vi_+${dV*C)&uMXVWNLj@-P0n z;k(A+-4tooyYFAe|F<&fmp1Ra?(y(v+n4z^d0>PrrV(x3nkwQT->=k2YK`GGAN8<30p19(~txEJ5`M^Wr%v)k)RM3QBB})0I+E zRTf-Oay(oV%Ca}Y^NU2D*y$I#3PFBp2D5i3%sf_G+tng`JfY=d`f*>$!q3*uu?y`3 z+WY1{d|bS3#oikyjJ<4pUM$*KH?7)I2ZoN^!q!yvp(a*6L($d+qgp56wNJ zM2iw~*PQy`Dlu97%z{RL@EkNRBfBxQ;k8=wj--<9k^ytJy3l3l{Czg?x%*MIG2Gp<2@8o{) zFe_JPHyXNKJHz$OxIjWb(<9g_K-H~(msnY9^_iYfM*|}j;YOVb3tRn6X2wldPvqW< zi1QbJYghB(_N7*hGqt~L_J26PnEmT-`QKu#Une%oS(m-Z+x_;LuG8L#>kHfEUae)} zYdylW>T=hoRQ|XP^S(`5v~YV(OR%a$S}IrKmziF?(?X04l}k_h?B-H$S9A7U@PE;? zfWP~WOw?GnW7eJtmQN>zzF3|fqbZf`7yCG}e_zQt;q|t^AG$xc{da5U{_3~&`+uC% zkDF;#hCZt% z8Cl9t3tVRTzCZozipT?E8@Aob(q>oNxTM$r^5wNU2`^(qE^n{;`)cc^|BsL7l>b?g z`~RVFwZ-D>B2Rz&88ZtX@Pr;TNZjyY%bu@$Zd%9LN4KT7N2D*gbWK6QMVS4qgosIe z>DAC3oF>8*4=WN4HT(}BerWvi0fYY^13A%G-2Giuhkwm7%bk^(yy}FE`^q{7E9=R- z%tBZ;{7VY>KmDA|w;6%A-|YSRVKx8l-|g-1Do=bq zJ~xB)>CvUE=}qSX;*xxn~%_I%{s&Aw&y7u+fKax>3aG2wJt$z z_cdI3b=i~RCTc&q({g&!PPN3m8EXv^MU~#@#}%#b3|v~!Y*9L`MQvWpn$23imoBZJ zZu#EHcZ2Aml|u7f1pT;ItHcH*=`WGg-MaX&A-6_Mpiw~dfJk+va`}TO9FIJc1 z&x;G!^v^DH`*YdFP)MX|!4bLTTh71^FinghY1DzIz~jyFtyXPW7~X|Lvws@pRIjaZ(~SCu0r6ms4Ul zmfZMc`s3VeuY(Jg_#T^75XvwyWr0rTxf}HkwTm?N?-MGTa!#bia8{4Y3=?mL6st>) zWt_EhYPP;(m^R-|tU<*pS$@a=e~Z80%ztf|eEZfk^II1+))wkS6&_?2f6=C!b}-~5 z|Eg^ZqC(`5?LBKe?fR|Bbq@Dm z3A^Xp7eCxocFrUELu;e+*=h#8J(6it(iYhlcqytCZ%bKen=fZFd+B+m4=3gB)qFmi z)}U?>#Ho>%-Lq%mltm_s#O_~F3=%Km%L{Wj9=k#1hRcP*m*Sk+wI&l7Y-i1sMD{0YPzi%`#FVU1vhL% zET090Y?-pDTv4NQjE+>IF#CP!G7&C8-1@Pp@1d3GVL-m(=G}f zG?XgYush-6)^&@1vOLm_eY#;Sr^>eVyWd%v90*8zc;dKk?e>DNOdk!T(#_VY$a|aX zR6f}*rWZSN>6}V~J1bwl7Y%o^c3xZ&Rl)AG@?62}cYD9b%~E5lt_ygy_PNyTIz{W0 z$Xvfk%(K{v8SA^7MO9D#%9&}bYeKz3F0pwA z1#?cW`d4eaz1X3!h*#Dj<;#paPbPW2u{C4;_WAi)<+z=@>VB;`vQM0|J$BKqtwJi6 z@ApKpEv@OS%@_3E?^5lr`b|FDv-i5io{e95A5JXD-l0GDX#S)vS}Ba5RlofT=d`SP z`^Z||Q}vtD1F_n<$Hf}DPDhJQ+qu#uz$EK_iISd{Tw3fTx%z(9h02y1!b&%iA5ZSf zy{Yi_@G7@ukq!%el#g}juV`F%Ys#behk6^=I&Sy66cH(8^^p*?$M0pFj>^c@#)jqh|h8hTjn0=);p1PFL`&y%k-<4n#AvQ6}QzH^&2OJ1Q`k$ z1(xdvDJW&lV3^vvYH}7&vx@Wm5C132Dsf&&7g-~RsQmosqa{5w;9{*_(t9XGS*2m0tQj6Jd=fA?Fn69OhoMu7p1 z?k6qYicV>AT>h)-Z2!bvGR!Skc(XMo@>p?L%I&F42wZma@HK|(kC!Va1~%Md=m3oo zuzazsfAq#o%s}qh0?YfCy;Juxo|&Vn7*DY$dZm~Qp7ChhRn%$@46KbEon=FzyBl`M}t;gdn|G&IG zKl;bTqyBpfA70M?^J3~s^LK~-)jLGpoBwjCoR;^j^_$W)G!=!u zSUpdj63c4-B1Ylq&EP1OD;&wk1-u0}^&ik`SMGiBHoxw(^fMt*rTe}oXP!CJy8D@% z&idU)?0##$zH@k4fa%|cS^Ki1udR#T|8R-n?f(0fyS4f5BnSMjtNlGi;!WU2yATeE zj~n|e9&xN{+WR9D*(|(8Cif4|G~*5vTU~y^k^P}Q1Ecs^iJ56XEHkW~$Uv&@>*{#VOlg1nhu;r!OGWqS^HO>eC#8$<>S0mv`uf>^DinKd;We`@Hz@H>;BNiN^cuE%#E!T2ESQJsJf>u$3j zG8A~=!N{mC<$lF8&R$4<&4MEr3LdPGlaEQtXH@=L#WCa2F$;ckCSe|pcOf7AM4uTq zt#gWN&~@PP5_`px5STede(}ok-t~;;3GF>c=YINn=gR7nnl^m%*C!UN+WkIH-g`yu zT>BTiuerV7+^^ZZmZIk?-XXorTsH{9>#n2Am;P34yg6 zHXd@_Jf|lrSdc|(qfd0%x^j_aWezUpIpVr^p6X4L4V4xB@53r}O`B6bc1{al9CM+< zjUNY^`TZ)tT&yg9KE)+*$Im9ug1g_s-=i#>7T61%{J&=V5#7oK_> zV!-Wk)JARLlcWf-hdi~<)_$D%sasuJ=AG zUinT6@=^V!7?@Q5!jZlA=Klk0-QEYC$qPtd=(y<}=kob=yA+o1VAfcXIgNALp2_`- z=f9b%)#NpChUKjfo+4g+hkUP1a8}YN+h`v2;*Lke6jwG8M8H1VRa;vsVhlPgDH~u;E)jw1Fe`n&5M*y>m&zdK=&UDwRq8%^c;5amKSG zZp=Du{egd?FIV=BuakTpZdx{Nsjn{Y+12(Df!m)hVEo2wQF~qXxnA7GTW+V@G6F?@ z8!nVE$bBOs-d=P{NyP9#Li(pVp-Y<`j%~djr(LX`EOB^_xaH(G$#*s6ZgEUx6!FoX ztYNQvO&vSZ$0p7fKYi?vc(?xK+NCZGcR~(G z?frSd`}_S`*UPU053~J$dvABlj^{HDZ({{JEKK@Ga}r{MfMb zaE`olTb}FF1}5KQA+5V}C)Kp>w&UA&HjqKWZU>{C)6%3*77uyOJ*|uH zs;E!6vSd<@ZvNbKle5Q?J}p&Z)$8T;+@rTLqwHFXpOb%`Z@`0d&(D?2Rgr(~zwL3} zU4zn-o1$E%*X;YbS4j0+jrfTT+rrW)X*!NspH#H>b{QskGzdrtScJH~_=GQq} zmM10ryrOh^`P#ki7KslRs=o|-K6kT>_cMKoqKyU?m27tSGk=(9(4!b zt<~E2e}~7Vh=**c-O7AjN5e}NzTKhXx!UR8#;G+Swi^ofBp-aC5$`u?$!67W*Sr+_ z3UBOuE3;ls-(iE?mSx={iSH*L$y;%<(^#yQM@cwx&b3lEpM`VRus1kJzVNB>_}~@sz*Pp_faJ#6S7HBts>4$!C>HpCq%Z=bL2R+!jCma--_?wY|=4d=h3E z6Jp=A^SrRHIxc&>{$Iz_#bv*fuQnv9bxN=}YldsQYfx~Q+tG8l#jC7u*1N?@Zl4;? zo#2JWbLu~hE++5zyt0kw?-M*|zwjrbSrjj8K%L!wp)vs=*zH9MME&CX! zG?%^J$R_d*cTdZ8)rOCPI)V!Xs*)~el(0P!V~p^Xypgm@k0&pGD$AP4t-SXuKl)$& z`>QVh{@r!ee{K0L#zphZ{&H_mw4cR_ih>6Rv?tng2CL?4Y?Y}#^;kq9FVPzg?Bl!t=kDptV!F8*88Knu+gGjocYf>F&(F^5 z?^HK2W4tDp)~G7Id8xs#9^-QxT8>PdG}ZV(<$)lU*E2RA-u!qTvvA)$;~GsK$73R! zyS};{dRY3>O62zY1u2oj7bEY!IwOH0Q-9NOmuq`wBt4z+Nvxjp(Ou2Mep8q9tjD^4I;z*Ux7n(0mw|Vi+ zW71?ltCcOsk|wQKZR37rmY$=QXL@++r?Wiqg`KslHhW*XDOCM#N-rC@Paptogwq z|N39S4SihC&MjHD(5p{F)IG#y{`UztD#CdWO>vix49L=EUn$LMS)i~@#Hy`Z?4Zwy z4`$8X+Yg1a1$!7WoZu<5JFKDY6TVZ~WcSvJ8EY2V9oL!{o1Jpd?yH_SW8%uqo8-$y zB)a{R4_`HSk-72aXS-?b6U&!ha4)}?xxD|{_N=skGkF19b#6Y7>`FOxFTkuTv1Rd> z8u31HrcmP*0#}x2{XKGx_t@*Adm&zP6g^|7tKG}%y4!Fi!91>q?FN%bYrK@$-s7P@_)*LI;sM$_YAO+!!@}@6>0#E9_jf%n`};2C~YVbGeNEsQwFMwS1p!CjYB^ z{>|jj&$H&X^X@B|AFFq(_>AK1+^^k_`Ro!-KRh}o;jGk~u=D*3j$Uf~(8WyuWlZzZgMSR|Q~u7B-9w2qWipYM@Wj^8gnt>|Ptax$c_6>mz+Nz#f8^t{*9evH#)bMrg zmEHp@t6$Df(~aC`5Y^yZpL%olxg$<@{h~CDW_#{hej zR)8GiHTG*u-mH(9qR^Vk?9;6|MQ63R?A9<*xyx-K5vx}%epL3axAWhHwW{AX?eSpI zo~A2pmy=N_6m@may%$Q0gftf@gs<4U`_J6|l%hSn*P0EMZD@77!}hvbErPXM>Vedn zCcEq(3q{<+0(s8#T2wkMJM`|=msaPmOgo>?t6t_aQ>eN1(^A3G8*G}I=_!>5jqmSK zaC{dx>zudtNz=}vn_KRv6ftwTJy~`2h}-naa!-?EzVDJ9FK=*UzW#l6V9M{~|E2?dVaVi2#eQuNZA}3X5OL_Df2-y|MOsV`?x><(glRukq9L4foy& zIIKP>tg4=*cV*p6W?|39gTh~*)r9SPD7NZH>-9vwiET;D*3a}cOmbA`K2etTd9q)E znRlXyip@b2WA}gtl_?o6UzMlKv}cntzp-j|jL?R(>t;3om)d`Qd;R&@P)7j7>qWojJ#_bfwIW>g{Eco_5#L{{H^C zb^0~4t6x@HRV|E>Mh_Y=Me8okgeJ6mDa_ifSh2$Nk$vK%vujT}6f0O~txUFkXw!Jnci%H#m;KMK>fWz>we@B9 zbTf0)wQJU|U!5NjdH+StNug?gzx5L9OkQ+|%n;x`z1d}JG9zz6+}gctulu$h+9b(& zZrWDc>&Fw`W+<)Ck(Zk{VPeJ#whe_d_%2${`+nBE>BNnh$FCLhairg2V^Wi}ulw`$ zdi?vI9nK9m!jC3x-P`3^QKU8{^vO%_AkNbZHykpYlbF(?_-umf-0x~rLXzZDym#N2 zuD9`hsF3wHmjoS8|79gNR^B*!P?=L`{-bg}f#$2y#e4tFHObgg851mTT3d604&1MZ!6#Odq;mxfs zal1LC@uBBAz4od2m)|#?dL#W%rT8(IC5>w*seW7W;_Z<+2RU9&d@ZUu;q>bd-^Ffr zF}>jHzTjNbsA3zCGx~Cx=Tw%jW;&jHu50^>MIE+jH-+X`Y0ps6 z$bb4iBF9t4)UGM~TX=z~w9cU?x{aR}9A{}fbjGe!=by^$h&_Vc8ull@EnY63tmXM) z!>2`?KFD_8m&=fxU$*i4V&PX_b#GS`K0YS*>1Lw!^czRxro@E#wa6a&koAFeN^zn_ z#hgR)PO(jtT4Ay=Kt{r`c#GsiU-_4J-#Qte&~~1ELaVK*DkD9_QzEk@m{hLdWHH_H1Gs&6)6}jgAvN7jj#n+8udxS1+c&aS0WvyfOq&#kOo#^69n$y8{XiEl}KKD7bb)`^3yf^^1SjXzpolTKjfs z>IS(D>o+-FKFnwBv%1_zVxEAum`VGFi-n7B(BK zl&L(gBNenGG4*uTm$M6NS3SFStzXj4CF=Q;i??gvPMm&iy4OXwt9#mWpT5{w+4WPX znnmJ?n5SEfj+e%@8FAegB_lXZX6QsB>F;epFLWM{~-S(35tZSt^p+%uGHC z^Fr%)B>Th_Ob4Z?|96}1Vz*blo$;_)KR9Xs^%>3E?!L1B_v!-kcCFZ?{mg#@8S*fbMu+rd$W}s=l=LyDs-q&-NdnffUhZ()PfAz}m6Px>urv%GH{QB4^ z!*cMTibs@Oy~-rZ+@3Y53Z2V%wuo=@neuA3Zr5Mmce?lOYjlKnEoNqZ|g9gd#!%C(S88XB2PY?Nq*h_3fXlvd?N>UcA=g`P{dU&$dJy z{yhJZ-($~RYMo4nb&~40Pr9on@7?x1O>F8ZPUSs%_PI~* zKYXvdLh#|`NAH!DJN?zV6xp6_J-od@*Hhr7S3;`i3yqE9i&w>N&FVgDuJ7mM{lRmW z=7*qi*0QPvmC})M{P%93n6Gh8(5Uy|v>bz1H@PSN_K1pdi%eYLwrpYYp3vV~$r|5v zWS{hiEn9f+0jG)U={teTA|LtB5Q#nH-ZHHzmN97WzSwNDkH*i9KR#c0g8hL@Sn9#Y z?=CT$#N6=~ESq4ut8V*dmNj*zria;i@6;IYzVW@>AnmwppLNllM{mpj9p1I?=uL?; zK@T|#xxYMJG3)w{i)O2uCOmp`p{?P;!g&yDHg>UOQO>Wdg1&T-5* z=`(v~81s%BM?}RQE1R%)+v)CpB5Zn?RdzeaZLPTZp?jl>PjJmJJJ0s}-uHd!ib}@4 z5sIDy!jJ46EJK&e-M?;T`OnqqnA!^Mm_1LvmD}&AeRYQQbhuy5>%GzUs@{Lwe((3I zDfjRHXfMB&WS(Hcv2`|=yKBlNJ_e-+8}~9?n))cn@jAyuX`lNpl?t|k>>JzHZ{ewH zVLp1+v1Y+ik;R|hHcZtkbZheX{lsSXLEVzXgiy^rGbXG^4B5+ZjWs^BaLv+n$)CLi zECYUeG+HkBS)d`q@qKq@4eyNXw_2WW+9J1p4d1`&$iB3{cDw)mIs3ix{qJ1cnn&}~ z_+xMo)GVSVs;Uni9L&Ii^@3n22BWA zruqGDd3;x|R#Hl{5?ir=aO%IxlUg_KXwMG*WmEs)kJ`%J{>uWwnfG0Nbn6&n?dpEn zt!FRR8-6--xBOP!j|q;o%&n?&Q(fjIrylR%=@F@ZzQjl768F)DRMxDBxemv?7kgO5 z#Z(9tuuT6m@9Tr3PKjZjZ%!0&R~jrXk^6l#yqlH9+IxPhznkUFjmLdEci-rp6aPZ& zi`aDS7mXs5z7;ZQ^hx^W9^ig=PT;f$TS~07{6vEFhsw=vmr?^0Qz+1`sD zTGuY~xZlXScrx3ER~^PWI%bQQ?PkiPZdtPbQJ40kZr4+rPOD74aa*wI>LkrG^OsNC zwfuJE=y8dv$o6=Em;5cZ&{vy?N!(P5$!q%bmJ&*7&U66&ci7 z`|8iVuaiusxyI}}Vz({NTlJf#)ov}3d3`gi6Ip)lx8U2@<~3k-Qs@e;#xgXvN9aoU}{kVHs*G2b&tE;v-IX}-7udX=t zKFPl9%Q^XVcQ0&Ty7lQSFc`YMbDOAU!DAF{}io_;>-F~woKvh>M=2Rswkk}BX=-+ zX6#x?20iVK#}yVFICB3j@57?zqhFHEYGqvBF6Pit(cn~Rdi;XNZt9tfc|UKa&o7OC z+R`N!8Ik)m(09sm zTSW=`C*@7<-1IhMkt4^1);#O4SAr$oRkUuLVlz&8G{0S@h=Zx;V;I|}ii}z6t%T=# zG}G}dRYH>e;;R--xSpD3XLshLj;Dw5%7gMtIJkFM{bYW=xnIj~QvcU)(fO6JG12+X z+y7L$Cdw6OPc&$<(Xy+)vX+@ezGJ%YZkOjKj~K+yH%^XOZSkymazhiNje+XtjtaHT zi8bprHhvde$Ku?%?SRp-GTSX8u}_^=I~jl2JEy<@(W za!-ljhDj=(2fQXVOjTjj_MF7BMujuNQ)t5^m6a1C4|m*J^4&wJRB-3#Hw*rp*mERw z$zf~p@&}XrKDjik;;);t?04$E;Gfk~elE58rkwWtbietgKRIvztJ%H%B)`34+Y75_ zrOEY^AAE6(@8si15?XZ8?XTL${QEbSPwTw>aMSmL3pV+mRAUO8nR%Ld#o_x)Y@S*5 zJpQBlwxy^}MXYVR*GWOcnk|9*JB^F}mpHJORh3)6@d)L9_Wq1~^zZpj4BT5ctLeR1 zBGx-`uKb;|pVO7izdk9vGjqOGmJM&V{gJs#UhR6wC>j4}o7Ic`s;RXTx74So$x7Vm z%ol3b_Inh~x^ma*6z7R+)=Oljem@Dv4K-fVBd{T}AtGwnb6>TaArWpAR%=`YGD z_Tk@3Hcy=$9>cM6ZMv{T{}*gbR4r~B8I|B~>VVc>Y)z}0tGTGVyfO>%u9sh2k$AGsr00=Tlwh;QKA)LF>2PSAP9B;wBs|U&FNKhi+HvVTq@8 zT2dPtuexM><+QqS(&Mn<0me9^`xo+`9B}`ad(FIS=ltvWU+)y3&-}CIh&#t~dxA)509bvrOGRMCwvOeZsca{I5 z?i#ia=Q=;lT-;~nCF|@xaZ8(~&I?`VIbTFCZoP2E^i8wSm*U)YQ~3@KyZu4q`0(aFG46x%A^bMqJYmOq=;R)LhY4H1EZqRTt)O zvQj<8oFwzRaKVw_FZ^F-TfAid82p=YG21!+SLGdfpAxq%I_2A&Qup!2fu~0tHJHr~ zZjpHMOD^I{^_GQB41TE%P0Z)@c3R@S?#f1Q8&Z_3w4W%;d*thw9GPQBQo`gZ@4Gk;`f z9C2E^SE`b?LF~zR6-gg(Kk2-SC>r79VaW{nair znkV~YHOq`M49;~aAB@!U!aqIV$}Vhk0FBM^0TH{7n9xSXYZ_-opz^`gtpunFWpahy{rF3l!(S`KK_UQ!zceH zOM~7`N4|NhuIKtIGH-JHobS#OF7*|x_toDYWKe2ez|gtx`?Uns-CL?{4sDZhIe+vT z`>}@g>zGR1zVw!z*;V<$$7PCcYKESGt+2w3jo-L@*n-0syY(71Pfo4T5w7akBGvjl z(5mCw!lkuq8lpe4hlI>n`=RB9gH%V+DW&{6@kyaw&;HweVqd5F^Zu2e0Smu`&G}!^ zQ7>LE;#IQx`xR4}j<`oR8{Sx~e^SEu?K*4yn`QHlGKXz?&42!I_s5^t1uhr$o7AOg zgy>zY;W}k%{$a__>#2F-0e)s7oUY0rrqy*#!?nFUHhZU zZ0a=m%TK_!f6ZI)ey8)) z<7b(U#kti~s-18@TD~$*JL~zL^)G&Xe0;oEJVTb@`{AE#uXruyIC*da8IMcyi1C1m9%qtfTj{4!-=6 z@r9ab>q48aLZcJfEjx_WDo2} zEWDKcC-R4N_fxj-+9A6P|M4}Ply6CHmi=*Jdna?UhfZIT&v%uD-rnKQxs30d1c)X- zy8gLcoV#H16LxD!Zj%LHmP^~`*fl<0Vz}|zY3~ZDkF$^S$hDvTZ0U6_z-;Qr0*8+& zf(h#{7MZQnl9%cG$ePmoVG=jf=10M`4BSGuB~$hGm9tN}a8&UDAH(Vzp|bT2_t$GJ+j8p7 zc7Lu~RO7bI+BEEWu+`f$r=RV8*>KLS_0AsNn-Lx9%M9k9QDdDhars~U?t@3mHN$dD z`!*HCl-r&2`?S%+mDS^Pyfp9OKj&l@oIUbX?@okR_zU$*p;32K-qx?Fb*awH6j{FL zafTto=i?KnzgWt0u6OT}!w0guSzj$UY;*9_cJ1_?yP_CuPj9k5A^k{T*@pgxc~d=( zX^19j|D2q9DkkCjtZlD^bv)NZ==vr}AMkk8IDKmS_Cy9&-+%J*!mExn)xI$n>OOzr zu!WE*QuZb7zdXs>D`Q{nS<~w;+SYn+W2pTXtRZGl^7~KRx8?Keta37& zU(Zhcz2=7Pfsjd}8|KSJw|WQYetI&cUNvXvolu8TQhrT za$G*m|77Zfs|PN+%j-r=dhd}vRY8!k>1G_`qfbJtN?DUUj9h;nOzrZ##Qe@tlP~0{ zuP>+Gl)tkj9oYgqu1&SzxHS2ab<**GAOpGd=BAC&>v(pqVQLb5#Ts|qRXkS2+Si4T z-J~<|(!Z*G?5TpUo$C~QjK2HL^5DC8ZuLZwLsgHNAI%R)OZ)M?{(t%Q$*Naho9&u( zOKIu#oVBxW6;`KxdUDgSHAOj=OYL_1A_Y4&W7bL&-+wB19-K^2yIDBTXtL)LgRidB z_%6SRZ#rouvP;nBj?<~mX_FK#`$`7Xbn(0uN_ceRZpmfe8f)f~_`biD^7VfT?UWas zo^V8bwS#AnQ?lpj%fc+FSEN2YxBqV`9@n0mBfuBssM5s8yqG7qEO=TeoAMq0y<0W+ zbCfzTh^@tb>@z#H_H=_-8I@uC-~j0nllBqD{KvKU9b4xzxtcaf;Bso%)HqN*u*1tk_OQ443 zJjpc?6_-2>Z?uLeI0?;lkNot`@~d5v`AWmbfq82*YP~Lfel2S^tzGty(Yh_^G9FAi z-e$j;k8a!{Yo40s%w;D~%O)I?v#PaeVM|hF$8yJmJLbgezf0g&-^g~5JLbrZ8*})N zPi}s8z$CuQw&?FPj@3Us8h8&qIRE6D*u=I~5uTUaHTxnm_AD&2xVR`RiI-6- zZfCNVx6-cb$_H0dPp|*6d;i=mN5$fI{>^K>^LEb#ugjB+&v$OH+u(O*(q+YIUDH}} ze@+UzE;gI>`RCs=g)@~-_i04GV4c*^dbIZH;eN$~bILybxNbW0X6c)~vw5waPrEIB z>$nlCPUa$;4M+T*=C*8F#B9H7vzWF+V4-6J?m}f9B9OBiCml`wNb* zIyIeTjlAur-P5Pld^yUge&_m~Pmd-oJ%477ZNY~LC%MJ!zI~Jbd|2cGyO+kK=kx3B zPGzaqAKB<)&T^(ErD18aKvc+7g@+5gGwL5$JW7v9+SHyT|8r*R*(a?%Ctn+c_A;q% zblsA}SeiORWCDZN8>X0xlN!F3PnNI9zPd`;&+?UV1@xqs=zU;J`#&Ejo0 z{%qd;ewzHsmS4BB*Oxk^FSypx!8IdL%V$Q*0tcJs6-*HoVQB&9jysyTDhdWRTbj&1 z;W>T1bfcDsXh7#@o<%E}b}#yqm@>H}d&k1Rm-dvsE%mqg>=*p`ox6PL;YF%nwZpG2 z__Wo;{OsKNlKFP!u|KY^ZR0uFA6}@vbcNq6Zq?)JvM2pc8nczo`gSNa;I#hv+#Y{N z#^|Y^mn2wK#0uTmsB0Ond3)oYhzK8_Iv$zzC85XMdrM3k*u0lJZCCY|%Kmle=>K20 zq-V>Q{#bIbTdY$+D~_-DSG;oY3%Xs#e?*4NbD5ukX3t4NMc;+>@^A#dK}m?VcaU_Ep>c zICMHYZ0(v=(OVa;TbKFmj`Fp&wJ#>+=h&7+ob;}6Dsr6EX0`Fgm3d5)1Nq+Bx*lSm z#5ko_?0dSrZMEti8KW;Rdidlyx|@BHPJgUmRnXN<-JQC|^o63()k#y+imh)vePuaw zUe!~k>=O$d?QK8)*jyqp$12x3Ir#J+R`=^y?o@yLd3dK$Zb!SX>&6V3vh#7-TosG_ z3^rzHo(Vdcc0~VKzvALKOBk1IoVowTGAk=S2CjKp3!a3xMtx`y*-&)%M!;v`Gx8I- z;(h-`_sx0CA8Ha`^=j%q^(_@wUz-09zxsb)(VhK&e!FiiT{~B-Yxx78YtCyX3;i{= zviBFdc39qi`Jq)FX*c7yrq*?cMuhcT*38QPKWkR>{<3p7^Y_$#h<|66bmPLg#d~H5 zdaW)E4fXt)b=vTAB;LR83UzynRa5^FUSc!9&UGcmF$?d3pDn)gXc7drjT% zcmCJ!xB0UvJbwPC1ed^QnrxrhGqIc zUp%UoxB2+lz2{bOzpj1#lbz@H{dh9p>&gk`J=!}pjrr%TK9gXm)-lUPa$(J@V}*uB zb0!{`78Fu3!(P8*>A$cA+ImxbgTAf!+xa2W$)T0$HGlE*`PIko#@oH)4&B{1cT>&N zOSf+QiY>Q%dapfhcI1iV&a}N7SGvh@MFvIkwwm;{CWbwepLjmwj_7S$mu$UN-f!Yu zw;J|+?)KW5o_N)!_28@UZvi@X%NG5V**($e-;Lu6jSC(%9A%2Ddf)umzW&IXx7&6X z{%c=u@x zsxA@ztWhs&#Cya;?sbXoCa={8d7m!t@e!?`SHfEFwDME`Pa{tmuHOQUfe9XJ(XIS{ zT;KoEC|#rAd0^JQFN?k3*S`3m%wL~;q$9rGV0GrhN2S`~xe=ka%YXH}wy*!e`TK3` znG?*irDvqh8|R+O@LjAGHP3y28^?}?W(VZ2F-N3Y)tm|DTR+osb zac5weXmr+T$u3Px$3H6;^0KO}6-ij?;v65=wZ!7un*M2X|J|Sb?dPG1{`|84-o2@0 zo-GwUTk5)}tN;H8+k%hHue#8v>O7@HR3%VoBQqE4vpwPGXGlM}x;g#5MRb|$=O2Yi zTe$i=_H5xv_^Gi#VCSqC&tltLJMJ#s+OlB79OX+cQ&iJrb37KT4N_suKD=w|>fcvw z!mmC*-!0C+BLB{XD?7HW+jf7=&h7JxoIFD&`lKHzZsqJcUS_|`$%1cDe2K-O)eqSe zGaCg9b{NELX|h#YtXg&QLoJWl+AYaXmixXgv+FvPJ^$FbhzxN~7TL)eFXord?3dre zUDSHsclN%grTbr$-#^^^ZrA$z|L0nK=#szt<%x0XvBk|r+ht!cEo!>QxL8fSSM%5W z|3BxyFyVRh^Z9)F)n?CopEsV2mi{?;{+}m@xb=D3Ir*FNTQ028+`5CMF zyoB~^nIF#2+xT>b<^kK6Qf17QADd_Xj{mvXI{vS7_I1wn-0?FX1(xQ16@Sy_HF?R# zHQN_W%<(YU`&O!q`R5zG zxAm#xtCT#0glmrv|-m0-Ou;$ zl&k%EzFNNRr!}|V<=m=x)bMrHwg$d6?5&CciY;4};`BEqv`Va$Q)j)*D*Ner zS5sW+)lk+atS=Wl+V#7mW#*k<3N8s|H9?oV968)nd_q_@q;&58d_cL|Ea%4~&*S@d zRehb8?Dn_p#RlX0;_SJre)bA-^G^KeacD)}*Aw-B9?QG4xryr^oU~#}xIp3(hwy{f z^qf{2c3OlTxR|4AKDleH{85W3?$T?#E=sOHcR)tS<<x zzDuFeu(0xFf%;oz{pKYKh6fj^H?nF>zgK$y%CWZd^KAaTQmwB``!?t1XR#3d_x)tP5+z5ic!s^{zL?Y2pGzRK%G?aCc6tRSs{He*xL^DIX0gMrC}R$f z(jXamNj7z-*oE7ToXQLqJY4kFr%{-#&&;F$?Yh0k#5;5^w+V&q zcXw8tjGC}&{qekjr2jwn)#h3Mzw@x!Oj|-eT5$2FRF}m5X+n#-lBQ2ddZh7GWiERe zpH0Op_x0^M8sa$zGgk1pNgAu)4wcqEy(Kbji^Gm=6Q#dTX3Q%N_0gE+^L%M7XBAJx z?p*6n`QL8;UYK6LzwD{j??pG*R#je`le{WQe#aB(=p<{=&gDmQFHN6){>azB#Xjpd z*oE*V?osG}vifBz&&KQ?7Qv%GY}8%WIq(bYn5O0Q%lP5l^82!NR-zeG*<~V^X8XKY zaNy=~p2dQj-#>G@-{tt^#@7@kL&oe62O6)>srYj}`nu`kT_&bm&&)0Vlh*uh-;3AI zn*C-+wES;cFPpc4i6^%1=hHn!UjnUtAAG-PJ0V3P+AQme2D=HDw76o$&rG(!D)n=p zcPOv!jqaIrYP$Nwdu2P@8WfTWw&*=_70oey5PaAvw$-b-D8PBz^;$dA@)tjas-L}m z6Ysxf*Pm18|KH|49dY>EQUh+S7ty<;R&43J`k?&5=_M*9Z;p6#O}a3*NGdsbsA+ytw}GmaVH)M1zv}qmRG4zMF%?GpMt663d$K=jZG{ z-I{OzZQZX9y-6yZ5&GxntrmH6V87L~+4+0^UYLEUOj_5gd{Kt_Bf*XN{@d0rWcEHW z$@gCK$+%4}?nTF1pH60fmz4HMp?hg-`m6&N4 zZ;!Nt|7rZ)Ubx7A2}4V>bl#4K&t~VBB}~4*rg}GXq-%HIqp)q;?-Y5T-1}8^)zr;O zE+Pjs`kh_`X6SEL`K}|O%`cm}<4eR#hvp>eYsp*s!F7(qn z722n~RlQ7=d9H8XxeT|g+!r=FL9vDstp}ey-!Oym3d2+BqVtCmK23e6o!z3LxJb=f z#pbs0Zr&xK54ATxuj^iC_3p(=Wj7m>`h&AlPhY=wHGjq0*Sqs-V~Z72U0E*e`#f)N z#ENBaBeY-55Ix6TckAxH9q&ZWWlYJ)d#w;{kj&d#Z2t2m4*nJ@Wl(i)WO#w{reX39}g@6Tc;zES=pFl&a49sP^!Mf=PaY3;ZwD z9;ixu_U5$wyrM6h$8D_&9=tYA`<9=vz~|c4YrKCGo~>Q(Ymqm9FV`N)7lJ|QJ8gjZEDdS_7YC3 zlTW8i<~@JXRXn!jm}L5bQx|I7*k%|px}Wm#jZj&>awE^pyK6TJZLo{@^}PFC?T3cP z{grE$-LIC{TNE8Ndv?U!I^#6IEvwJ%`z^AWGei94bPtJO%Xx+i6t-+|>Ll+o#;%pJ7{mDO1?*R{i})AHVc^1@`!A zX*DS2uaKK%)ycRc?5MZd*9jMGXE!qI7++ATFnW{Fb1=}1Ct|0IK^Ggd>YKC$?P5G9 z+E|>IEjX%s`h?s3vRj!S#rCM^os~Qn^J1IIUG_Dx+isVATB$Byf7~|P?d_HLOB=T3 zow!rEeeTDlAAi4#E!vab)AFxb{!hb2M$Kzn!CjV@56pa-sA{a{b78H_6YEUNj^lsc z=GRNRHXVDEU${0VRid@zoaOVH&$I6@5j@Lw#6VWy@#OylPpSekLPs*OvQpEQR;ictx+^S~&m58xJmv zH$FVA|t*y|B%vs!#lz>gh29(Bte=zV8WsQaBmY+=jlmd>tE50ta|H#)nw@hBAh zOr0LP?2_oSj;V8xHX6D#vV~YaNJvyU{_U6I2^$NMo40=?t$JVi{lqE8k1BW1<|(W{ zJFoZ!|GItec~v=WH7{P`<&KP-d;0#YCChK}&i&i{=gf<_@xPAOuXvSt@Z91v6<_u& zjq_RIWf!)T^Z(qy-x7B7r?iA6{5T@N+|4p^lFHTC)>Yi*YB0Aem8gW>!-!LJY2+{WO*`j&*>d>(wi}PW+`qGH)y2?Qg-KdRH(p-T@BIG7 zrFjjhj4Mxh9rI0_t`QctLuuEIWvnsV|NXiBKG34(3Fq;D^Fz1#pO63Wre`MeFa8;u zo-A&PeZ!g6r%f{N z@kv^La=S_bXKr+K<%D^WIiaf}LX^L5(^;Tq?92T7ebtp6^XqmznOn&{O(!lWHhT4u ze@AlNY7*D`i}#4fH7&WZA@bz(Cx(5edd=^>P@el+r0C=~7cR?lH~gHI@$XkSQ8npW z7TZx>Sr;pP&-_mt->@#?>hDx6E9iLiI4Lt?@3XFUxw-eZSA9NT`>pLK_jLWppuI(* z_m3TWHgmK8&722Ixc3F^(O+iL?e?~Vt?7-^+bt6{_SncyQP^UkfB#Kr-%Pt^r|L=E z*SM!JTa~8r{A-Gd%W1uT+Kk7)P$$aEJ96t$IdzsTsd;u0TYmiCWBv8O`Z=Z7n_6Qw z+wtJRtt)jOq0l zWy{OIZ)q0^ZT%%e?`A@_iz1gci!gnp|)SU!j`V$z14WevT(EGew)`{ zCaqA46tt~rQD$`x5qxv%b>^o&p~Zz9$>MXYZSQPs3H%(8H{rcRs)@7}PpV0W;ocn2 z84a${H!e7GZHrk_eW0P<=HU+SU!mszKi=gnaw~o|*Cyx267K!`B&WqlGZ|hKYiwn` z^I*jS)^?#s`GtG-SS?#L<@{sW1yx38Kb<;uLc>{6j9E`3_(jyagje@IZuE8ffA}wd zXzZV}pZ~qyzjbTwTOrR$UT;p?`$_!2b3g7!e*C{nY0NCFlT=Q!O&vZ7{{ z++Pu%lT;E^Jr7LEIQ}%avRqT0^#Bg$De9=kOz+ZEgTxxv! z({n?{hCJ)%0--{)^ry(IQFJo-$q~44YM^bV8h5xAPpjj{9uvN=Y@SLHLJtLfLx1I@ zMIKsXcTx4&lT5xVqP)|umd-Rg=i;NMC0X65lE9hJ)x$mI_9I1?iod z-i3?n-xM~jQn>Zf!BZhbQ9t7%qrcLk3ya^_n#5eu5N;55xq39jRB4Y}>_S_k|Nq|q zzqf8}-ji<2#V3v%Z2r1$`NTuKuhxZ_F}u9s^5H*uc+2M4KnXS5xGRghmb)kTR!2&+ z9++UMI=fco};3(bAu;he``2Od7Y==>Z;)1Mlm9a)R3 zCAX?Ea{oU1IqdeycN)Rp6mEN(8}uC6w|Cy(nd$RZ-V7*lEVDbUwW{>koJRGA;5Bo$ zzW8wM<8!<3mM(_hCMHdGE;+_iQ6JDTnYnLA{H1Oom%aTg6X%q_nYH)Zt?rr429Xbq zl-Z|wDKs%{UZM1}-TqHv$)2-eO&?fRCbGYDic(KlZZI`lUeEH2M*KHfiANc!!n3b? zyCgkU;E6Ka;kw=@Wcdl}bPwC=Hv;#j85GZ0q46q&&&iKX;rzU-k9Q_(9|`f1R?ax| zV#9$@CgpQ;3~!b_omMBXcrVkr1;5I3beH~OmnmQnms1pc{cQLBzwgf1eKY3v*Vyyr zlDFg9?}^%s+8WEAp5^sE-jZrPmri-lj9?fAc(U66CKlF0OSt>R;12SQ_YXGOa4n0c~(J-+Ev z&4+{RoAWkLTkI6sM(q zz}r8L<%xWeWbyc|asIr}M88v^i|_ByPvTFxoc=(geZ>!-$w94MX&3%osVwP?|Nray z1lZoZ;XhrC!bb^5((l|GA0`*if5{=dckylkc0hebsj zBo+i`%=@j%DXZzaEX;e3&-ROni~h{Ad%*T9ggrlnD{gw))=Q2KY}%`SWGc8gnN8s{ zp3TVSEM)pD?%x+U51q`1X^TQxlgS;;rYnJB44)_nvK(-p)OYgPKTotE17y!?OH$w2i4?jI(*KE7J)5y0~7!I}Hb?|UX3 z&i9U3sSrFv()6$Esr06gQV;mwpEqP}-rT_TP{{0xr$U47tRI!=oqKoqoS3}L z%q@tcG$~Q%j+TV>eBqUf^V^;kB)IB+pL1P)Q`eWtm7iF1nU+uDdex+%YyF1%n3qZC zddclk%xH40?Ms=+0m(THR}a@+-6^d8_Q%S*(&e|Grf+_JEkM`T zckM1^-|F|L_S%(xU8(*&P&A5h8_R{GFH~ndoqCX!naSdu^?RGbnhr)y+ZV1k-u^pf zc5`AV*CqD{9ja}@iZc0&6R*1+lAforHYZr@*RlxTPY2%IedRQb&*$k;`RX@@KPx=d zXG|{aV%f>5y@=nzsP*~Z?{im|->LidBJlg!=!nfpsiDq)+uD9j`<@oF_51SwFQ-iY z6*Bb(Z@i!qw2C4hh9^u5cxWOU0(H-`QDdg4#jLL;aPoCL+f+OjB{m92ei-Zkd6}G(XwumzW>8EuZhyL7I*iG`D%QGGJj3ukL-ko%{?A|n1qj*X4V>25LYvUrqYDsyCAs{b;H@^!u?*;WSH!fTL*( z&$q8X>=I;iQBq-#Mu=`tu#enyiQq}Q5B4ldi|{b&&dC!H>g9K0=hnV_Ug6iIMiure z63laN@QSKuUthob#kAXcGb^gI^+gPpKGaydrMvd1r*G-~|2FU6#Ql1@QoH+t-n+X~ zeG-La4o}g3!}{q-weh_9|LVfe%}`-{-IgA|<4^hdn4j(D@*5)yrh80cS#vwC_HWbqxXN1e{B{1nKTofpv;UgH>-qZHI?19Bjq!DVPHMjQ zyL+SZNr6tW%oK6Y?A9xroDU^139k}A-7jA2(54yuLQOqaRdvCwnQhHX8^Y43CFiA| zV_9?VRPXtHKf0&?FZd|A-0s5mU-v5I?QDy`O*-m5d;5(?zrWkZ{7Kh7qbs9zuJ5MM z?Ffw(;T%hBtmg4{?ytN0{ZnU&&=%MGg6SsiOGQJ{xH~Pw8Z)+Y+g9=(IQZ*hfBhSw zUe5(8TW0-RA?0*g>4SLsl%&(e-j7ALm|QQ7;W=}c^&M+?rsE&Un}zdNU7UJw%kNz_ zLSk)M`77OCOtkCbWB924aJ~XVw%p0%DO}dt<$JyzlfAsm-{NP>>+topdDr&vi|fAI zoD_Qck*c+BWYy=&bkRRIU#)&^=)K2-k1Hz3GU-Lw@2=TzZ62&lziH)LG1HY(#z$iM zftkm7%$=51&EF-kc%cF}=iHFKN1I<%Kko6^%l-D2knG#Jh2kHBE>_B_ehSge5GWU@ zHD${<(5-jmBUi#t=?SaNj$Loo3Ji0Rb(o&Y6giju(R{bqpUaQhXx_P?x%2tj@^#fO zuPXb={jZmvC9WHPar?rBZo595KYd&;(&*=&&EI6V1|O`r8PDrFxt<#-niE7*({5`ehb@qtGV|Ei5}eKRNi=qDX)j|p(5)}{iKjWwb|41`?MK(*DP2rd z(8kKIrtt9dLBl#0cKdfsH}`E0i9Py^t2$fg*V6Cy5wHUG#Izey^!Yjs>cn{A1nq_Qz$+aBIU zNplj9JT{fOmZ={0c<+sk*H@`{-kSbREShcQr@waDfBbn28m^vO;4#U+C_IQuvy4OM zJ?k|W9;;nDwk@BSJ!yrauuwaa75ihrjY;gi`;j5_Z Date: Fri, 10 Apr 2015 16:17:55 +0200 Subject: [PATCH 29/38] QbsProjectManager: Emit the fileListUpdated() signal... ... after adding and removing files. We need to do this for qbs because in contrast to other build system managers, we have optimized away the re-parse step. Change-Id: Iec217819621696081d6e8b87ef48be0be681372c Reviewed-by: Joerg Bornemann --- src/plugins/qbsprojectmanager/qbsproject.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 07da504eef4..853a378e63a 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -295,6 +295,7 @@ bool QbsProject::addFilesToProduct(QbsBaseProjectNode *node, const QStringList & QbsGroupNode::setupFiles(node, reRetrieveGroupData(productData, groupData), allPaths, QFileInfo(productFilePath).absolutePath(), true); m_rootProjectNode->update(); + emit fileListChanged(); } return notAdded->isEmpty(); } @@ -323,6 +324,7 @@ bool QbsProject::removeFilesFromProduct(QbsBaseProjectNode *node, const QStringL QbsGroupNode::setupFiles(node, reRetrieveGroupData(productData, groupData), allPaths, QFileInfo(productFilePath).absolutePath(), true); m_rootProjectNode->update(); + emit fileListChanged(); } return notRemoved->isEmpty(); } From 763c4267e03f91c5c3a8c3e1eddd6b4477789707 Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Wed, 8 Apr 2015 17:14:04 +0200 Subject: [PATCH 30/38] CMake: Tweak detecting of right project part Don't consider targets that end in _unittest or _automoc. Also don't read CMakeDirectoryInformation.cmake as that doesn't work with add_subdirectory. Change-Id: If06af60e1637e94cccd32d09fc26c6b87488671b Task-number: QTCREATORBUG-12183 Reviewed-by: Tobias Hunger --- .../cmakeprojectmanager/cmakeproject.cpp | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 08e287fe8e2..4ae5adf4801 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -1029,7 +1029,9 @@ void CMakeCbpParser::parseBuildTarget() while (!atEnd()) { readNext(); if (isEndElement()) { - if (!m_buildTarget.title.endsWith(QLatin1String("/fast"))) + if (!m_buildTarget.title.endsWith(QLatin1String("/fast")) + && !m_buildTarget.title.endsWith(QLatin1String("_automoc")) + && !m_buildTarget.title.endsWith(QLatin1String("_unittest"))) m_buildTargets.append(m_buildTarget); return; } else if (name() == QLatin1String("Compiler")) { @@ -1054,28 +1056,10 @@ void CMakeCbpParser::parseBuildTargetOption() m_buildTarget.targetType = TargetType(value.toInt()); } else if (attributes().hasAttribute(QLatin1String("working_dir"))) { m_buildTarget.workingDirectory = attributes().value(QLatin1String("working_dir")).toString(); - - QFile cmakeSourceInfoFile(m_buildTarget.workingDirectory - + QStringLiteral("/CMakeFiles/CMakeDirectoryInformation.cmake")); - if (cmakeSourceInfoFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream stream(&cmakeSourceInfoFile); - const QLatin1String searchSource("SET(CMAKE_RELATIVE_PATH_TOP_SOURCE \""); - while (!stream.atEnd()) { - const QString lineTopSource = stream.readLine().trimmed(); - if (lineTopSource.startsWith(searchSource)) { - m_buildTarget.sourceDirectory = lineTopSource.mid(searchSource.size()); - m_buildTarget.sourceDirectory.chop(2); // cut off ") - break; - } - } - } - - if (m_buildTarget.sourceDirectory.isEmpty()) { - QDir dir(m_buildDirectory); - const QString relative = dir.relativeFilePath(m_buildTarget.workingDirectory); - m_buildTarget.sourceDirectory - = FileName::fromString(m_sourceDirectory).appendPath(relative).toString(); - } + QDir dir(m_buildDirectory); + const QString relative = dir.relativeFilePath(m_buildTarget.workingDirectory); + m_buildTarget.sourceDirectory + = FileName::fromString(m_sourceDirectory).appendPath(relative).toString(); } while (!atEnd()) { readNext(); From f978f6a54b60c5ee1e9260e0bdb074c047992725 Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Thu, 9 Apr 2015 15:56:29 +0200 Subject: [PATCH 31/38] Custom Executable RunConfiguration: Esc should close dialog Change-Id: Ifaa4d87c73d2597a018d867f3c081113132e76ee Task-number: QTCREATORBUG-14202 Reviewed-by: Friedemann Kleint --- .../qtsupport/customexecutablerunconfiguration.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/plugins/qtsupport/customexecutablerunconfiguration.cpp b/src/plugins/qtsupport/customexecutablerunconfiguration.cpp index fcf62fc3c96..229751b5d93 100644 --- a/src/plugins/qtsupport/customexecutablerunconfiguration.cpp +++ b/src/plugins/qtsupport/customexecutablerunconfiguration.cpp @@ -115,6 +115,8 @@ public: void accept(); + bool event(QEvent *event); + private slots: void changed() { @@ -157,6 +159,18 @@ void CustomExecutableDialog::accept() QDialog::accept(); } +bool CustomExecutableDialog::event(QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) { + QKeyEvent *ke = static_cast(event); + if (ke->key() == Qt::Key_Escape && !ke->modifiers()) { + ke->accept(); + return true; + } + } + return QDialog::event(event); +} + // CustomExecutableRunConfiguration RunConfiguration::ConfigurationState CustomExecutableRunConfiguration::ensureConfigured(QString *errorMessage) From 8ed3973aadf55a79b25bc95cab1318ffb3342277 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 10 Apr 2015 17:29:38 +0200 Subject: [PATCH 32/38] Update qbs submodule. To HEAD of 1.4 branch. Change-Id: I989d723fcaf718d3502ee9047e9dd6048013244f Reviewed-by: Joerg Bornemann --- src/shared/qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/qbs b/src/shared/qbs index 0199fd7a839..7950b45a1ed 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 0199fd7a839e3c3899833092e4fa7b3f5ea89880 +Subproject commit 7950b45a1ed927dcc8bf0463dc3a48bb6a408aeb From 941356be764a5d8284d93d15f717b558a3179536 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 10 Apr 2015 14:20:11 +0200 Subject: [PATCH 33/38] Timeline: Don't delete the models from TimelineModelAggregator::clear() The aggregator doesn't own the models. They may live in separate plugins and should be cleared from the code where they are created. Change-Id: Icbde117561e530bd83fe752acd483e2c42692a1c Reviewed-by: Joerg Bornemann --- src/libs/timeline/timelinemodelaggregator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/timeline/timelinemodelaggregator.cpp b/src/libs/timeline/timelinemodelaggregator.cpp index cfd97871796..1311f60fb62 100644 --- a/src/libs/timeline/timelinemodelaggregator.cpp +++ b/src/libs/timeline/timelinemodelaggregator.cpp @@ -98,7 +98,6 @@ TimelineNotesModel *TimelineModelAggregator::notes() const void TimelineModelAggregator::clear() { - qDeleteAll(d->modelList); d->modelList.clear(); if (d->notesModel) d->notesModel->clear(); From 7da95de7b2af1e72341384fc4e934a750b996eef Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 10 Apr 2015 17:13:03 +0200 Subject: [PATCH 34/38] QbsProjectManager: Take the file type into account... ...when rebuilding the project tree. Consider this product: CppApplication { files: ["form.ui"] } Now change it to this: QtGuiApplication { files: ["form.ui"] } The qbs file tags will now include "ui", so the Qt Creator file type must change from "UnknownFileType" to "FormType". Therefore, we need to replace the respective file node in the tree. Change-Id: I6aa7e66d1af584e8ded2ffbb9b1215e8fc1135b8 Reviewed-by: Joerg Bornemann --- src/plugins/qbsprojectmanager/qbsnodes.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index f14d9956df4..8e1f783806b 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -519,10 +519,11 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root, const qbs::Gro // Handle files: if (c->isFile()) { + const ProjectExplorer::FileType newFileType = fileType(group, c->path()); ProjectExplorer::FileNode *fn = 0; foreach (ProjectExplorer::FileNode *f, root->fileNodes()) { // There can be one match only here! - if (f->path() != path) + if (f->path() != path || f->fileType() != newFileType) continue; fn = f; break; @@ -532,7 +533,7 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root, const qbs::Gro if (updateExisting) fn->emitNodeUpdated(); } else { - fn = new ProjectExplorer::FileNode(path, fileType(group, c->path()), false); + fn = new ProjectExplorer::FileNode(path, newFileType, false); filesToAdd.append(fn); } continue; From 1d23de641f5933553c636253a938eb17c308688d Mon Sep 17 00:00:00 2001 From: Nikita Baryshnikov Date: Thu, 9 Apr 2015 11:36:32 +0300 Subject: [PATCH 35/38] GitClient: fix diff when committing When a commit has several files, opening diff for the first file works, but trying to open another diff without closing the previous one doesn't refresh the diff editor. Change-Id: Ia973cb70f2355a89b70787dd97042ef9f751d9d6 Reviewed-by: Orgad Shaneh Reviewed-by: Nikita Baryshnikov --- src/plugins/diffeditor/diffeditorcontroller.cpp | 1 - src/plugins/git/gitclient.cpp | 16 ++++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/plugins/diffeditor/diffeditorcontroller.cpp b/src/plugins/diffeditor/diffeditorcontroller.cpp index 6380dee25b2..5f4cfef23e2 100644 --- a/src/plugins/diffeditor/diffeditorcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorcontroller.cpp @@ -48,7 +48,6 @@ DiffEditorController::DiffEditorController(Core::IDocument *document) : m_chunkIndex(-1) { QTC_ASSERT(m_document, return); - QTC_CHECK(!m_document->controller()); m_document->setController(this); } diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index ff068d46fd7..44d1837411e 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -792,19 +792,15 @@ void GitClient::requestReload(const QString &documentId, const QString &source, const QString &title, std::function factory) const { - DiffEditorController *controller = 0; IDocument *document = DiffEditorManager::findOrCreate(documentId, title); QTC_ASSERT(document, return); - controller = DiffEditorManager::controller(document); - if (!controller) { - controller = factory(document); - QTC_ASSERT(controller, return); + DiffEditorController *controller = factory(document); + QTC_ASSERT(controller, return); - connect(controller, &DiffEditorController::chunkActionsRequested, - this, &GitClient::slotChunkActionsRequested, Qt::DirectConnection); - connect(controller, &DiffEditorController::requestInformationForCommit, - this, &GitClient::branchesForCommit); - } + connect(controller, &DiffEditorController::chunkActionsRequested, + this, &GitClient::slotChunkActionsRequested, Qt::DirectConnection); + connect(controller, &DiffEditorController::requestInformationForCommit, + this, &GitClient::branchesForCommit); VcsBasePlugin::setSource(document, source); EditorManager::activateEditorForDocument(document); From 18a5d019c0b2c1e35b52b082d3458fb014b21d28 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 12 Apr 2015 11:16:15 +0300 Subject: [PATCH 36/38] Git: Fix suppression of git status command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed in 808f4492c56cd282305668a46b3627194097ce50. Change-Id: I8760ab9fa897d708423b21c34771d5275f87d1d7 Reviewed-by: André Hartmann --- src/plugins/git/gitclient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 44d1837411e..cd606a868eb 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -2184,8 +2184,8 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, St statusArgs << QLatin1String("--ignore-submodules=all"); statusArgs << QLatin1String("--porcelain") << QLatin1String("-b"); - const bool statusRc = fullySynchronousGit(workingDirectory, statusArgs, - &outputText, &errorText, false); + const bool statusRc = fullySynchronousGit(workingDirectory, statusArgs, &outputText, &errorText, + VcsBasePlugin::SuppressCommandLogging); if (output) *output = commandOutputFromLocal8Bit(outputText); From b9ea4843053d617db653dec7d3d73ef8310853d6 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 12 Apr 2015 15:49:12 +0300 Subject: [PATCH 37/38] TextEditor: Fix unused variable warning on release build Change-Id: Ia773f4cc69f9554caeb78c1380ddf69095684000 Reviewed-by: Christian Stenger Reviewed-by: David Schulz --- src/plugins/texteditor/snippets/snippet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/texteditor/snippets/snippet.cpp b/src/plugins/texteditor/snippets/snippet.cpp index c75f2fe5b97..082c1d38ca8 100644 --- a/src/plugins/texteditor/snippets/snippet.cpp +++ b/src/plugins/texteditor/snippets/snippet.cpp @@ -38,7 +38,6 @@ using namespace TextEditor; -const char NOMANGLER_ID[] = "TextEditor::NoMangler"; const char UCMANGLER_ID[] = "TextEditor::UppercaseMangler"; const char LCMANGLER_ID[] = "TextEditor::LowercaseMangler"; const char TCMANGLER_ID[] = "TextEditor::TitlecaseMangler"; @@ -276,6 +275,8 @@ Snippet::ParsedSnippet Snippet::parse(const QString &snippet) # include "../texteditorplugin.h" +const char NOMANGLER_ID[] = "TextEditor::NoMangler"; + void Internal::TextEditorPlugin::testSnippetParsing_data() { QTest::addColumn("input"); From 7b8d670bd83cd0312573f91b0f6e406614b15b1a Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 2 Apr 2015 10:25:46 +0200 Subject: [PATCH 38/38] Help: Fix that bookmarks were not restored We have to make sure that the help engine is properly set up before trying to read the bookmark data. Change-Id: Id57cce5f538472eeac17b39a3640bf2ed77fa56a Task-number: QTCREATORBUG-14106 Reviewed-by: Eike Ziller --- src/plugins/help/helpplugin.cpp | 2 ++ src/plugins/help/localhelpmanager.cpp | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index 5915c9f1022..2ad2dbcbe0c 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -30,6 +30,7 @@ #include "helpplugin.h" +#include "bookmarkmanager.h" #include "centralwidget.h" #include "docsettingspage.h" #include "filtersettingspage.h" @@ -668,6 +669,7 @@ void HelpPlugin::doSetupIfNeeded() resetFilter(); m_setupNeeded = false; OpenPagesManager::instance().setupInitialPages(); + LocalHelpManager::bookmarkManager().setupBookmarkModels(); } } diff --git a/src/plugins/help/localhelpmanager.cpp b/src/plugins/help/localhelpmanager.cpp index 3603d6fbb8d..96508149e75 100644 --- a/src/plugins/help/localhelpmanager.cpp +++ b/src/plugins/help/localhelpmanager.cpp @@ -140,10 +140,8 @@ BookmarkManager& LocalHelpManager::bookmarkManager() { if (!m_bookmarkManager) { QMutexLocker _(&m_bkmarkMutex); - if (!m_bookmarkManager) { + if (!m_bookmarkManager) m_bookmarkManager = new BookmarkManager; - m_bookmarkManager->setupBookmarkModels(); - } } return *m_bookmarkManager; }