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 diff --git a/doc/config/images/commercial.png b/doc/config/images/commercial.png new file mode 100644 index 00000000000..852737d4bcb Binary files /dev/null and b/doc/config/images/commercial.png differ diff --git a/doc/config/macros.qdocconf b/doc/config/macros.qdocconf index 38971f6e67b..0fc61558877 100644 --- a/doc/config/macros.qdocconf +++ b/doc/config/macros.qdocconf @@ -34,6 +34,7 @@ macro.begincomment = "\\c{/*}" macro.endcomment = "\\c{*/}" macro.uuml.HTML = "ü" macro.mdash.HTML = "—" +macro.commercial = "\\raw HTML\n

\n\\endraw" macro.beginfloatleft.HTML = "
" macro.beginfloatright.HTML = "
" diff --git a/doc/config/qtcreator-project.qdocconf b/doc/config/qtcreator-project.qdocconf index 0cbfa5740f9..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 \ @@ -22,6 +26,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 00000000000..2f349047d46 Binary files /dev/null and b/doc/images/qtcreator-autotests-sort-naturally.png differ diff --git a/doc/images/qtcreator-autotests.png b/doc/images/qtcreator-autotests.png new file mode 100644 index 00000000000..ee16633a59d Binary files /dev/null and b/doc/images/qtcreator-autotests.png differ diff --git a/doc/images/qtcreator-closesidebar.png b/doc/images/qtcreator-closesidebar.png deleted file mode 100644 index fd88604c369..00000000000 Binary files a/doc/images/qtcreator-closesidebar.png and /dev/null differ diff --git a/doc/images/qtcreator-run-selected-tests.png b/doc/images/qtcreator-run-selected-tests.png new file mode 100644 index 00000000000..60545bc56f9 Binary files /dev/null and b/doc/images/qtcreator-run-selected-tests.png differ diff --git a/doc/images/qtcreator-sidebar.png b/doc/images/qtcreator-sidebar.png index 5a99a208a67..d44fe9e10ed 100644 Binary files a/doc/images/qtcreator-sidebar.png and b/doc/images/qtcreator-sidebar.png differ diff --git a/doc/src/analyze/cpu-usage-analyzer.qdoc b/doc/src/analyze/cpu-usage-analyzer.qdoc index 5db12465b50..e3eb74cdfdc 100644 --- a/doc/src/analyze/cpu-usage-analyzer.qdoc +++ b/doc/src/analyze/cpu-usage-analyzer.qdoc @@ -26,10 +26,12 @@ \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 + \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 new file mode 100644 index 00000000000..a394dcc62f2 --- /dev/null +++ b/doc/src/howto/creator-autotest.qdoc @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** 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 + + \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. + + \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..284c1892eef 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 @@ -162,6 +165,9 @@ The additional options in each view are described in the following sections. + In some views, right-clicking opens a context menu that contains functions + for managing the objects listed in the view. + \section2 Viewing Project Files The sidebar displays projects in a project tree. The project tree contains @@ -208,6 +214,30 @@ the .pro file. This way they also become known to \QC, so that they are visible in the \uicontrol Projects view and are known to the locator and search. + The \uicontrol Projects view contains context menus for managing projects, + subprojects, folders, and files. The following functions are available for + managing projects and subprojects: + + \list + + \li Set a project as the active project. + + \li Execute the \uicontrol Build menu commands. + + \li Add subprojects, libraries, directories, and files. + + \li Remove subprojects. + + \li Search from the selected directory. + + \li Close projects. + + \endlist + + For managing files and directories, the same functions are available as in + the \uicontrol {File System} view. In addition, you can remove and rename + files. + \section2 Viewing the File System If you cannot see a file in the \uicontrol Projects view, switch to the @@ -218,6 +248,21 @@ To keep the position in the tree synchronized with the file opened in the editor, select \uicontrol {Synchronize with Editor}. + Use the context menu functions to: + + \list + + \li Open files with the default editor or some other editor. + + \li Show the file or directory in the file explorer. + + \li Open a terminal window in the selected directory or in the directory + that contains the file. + + \li Search from the selected directory. + + \endlist + \section2 Viewing the Class Hierarchy The \uicontrol {Class View} shows the class hierarchy of the currently @@ -242,6 +287,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 +343,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 +359,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 @@ -300,7 +371,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. 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..f21189d373c 100644 --- a/doc/src/overview/creator-commercial-overview.qdoc +++ b/doc/src/overview/creator-commercial-overview.qdoc @@ -28,10 +28,13 @@ \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}: \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 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 diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 584c35e1389..e8ff7ec5080 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,42 +895,27 @@ 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: - # 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]) - 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 +985,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 +1015,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 +1028,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 +1092,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 +1492,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 +1690,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 +1910,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/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 8007242e222..500c0477a8d 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 @@ -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/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index c075260a96a..031c72bf48f 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) @@ -548,27 +546,6 @@ def qdump__QFiniteStack(d, value): d.putItemCount(size) 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"] @@ -867,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_") @@ -1763,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(): @@ -1917,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) @@ -1935,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/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/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); 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. diff --git a/src/libs/timeline/qml/RangeDetails.qml b/src/libs/timeline/qml/RangeDetails.qml index a8903863666..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 @@ -201,6 +202,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 +322,7 @@ Item { MouseArea { anchors.fill: parent drag.target: parent + drag.minimumX: col.minimumWidth drag.axis: Drag.XAxis cursorShape: Qt.SizeHorCursor } 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(); 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; } diff --git a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp index 9bb260e2534..c75133b2180 100644 --- a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp +++ b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp @@ -224,7 +224,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")) { @@ -249,28 +251,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(); 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(); 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; 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/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); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 7483f61887f..7b3162786ff 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -781,19 +781,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); @@ -2137,8 +2133,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); 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; } 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); } /*! 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; 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(); } diff --git a/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp b/src/plugins/qmlprofiler/qmlprofilerstatewidget.cpp index 4fe735257ae..a6c8e47e322 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(300, 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; } 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(); 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) 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"); diff --git a/src/shared/qbs b/src/shared/qbs index c96ef7654f6..7950b45a1ed 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit c96ef7654f6ea8ebd5737261aada123b52981213 +Subproject commit 7950b45a1ed927dcc8bf0463dc3a48bb6a408aeb diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 4a514b588c6..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); @@ -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>>") @@ -3321,7 +3284,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 +3313,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 +3327,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") @@ -3540,29 +3503,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") @@ -5044,10 +5017,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", 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" 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)