summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@digia.com>2013-11-22 09:11:51 +0100
committerEike Ziller <eike.ziller@digia.com>2013-11-22 09:11:51 +0100
commit559e66cb353c510c2d624d60a6d28a37fa66dcb0 (patch)
treee8cf129eaafdd6167e62427f8aa5ec3a2321b7b5
parent759fd36a1eebb6af878b95484e9dc2ef91b90580 (diff)
parentcf3a9b019204e734324f9eedd128f2547e4a2e79 (diff)
downloadqt-creator-559e66cb353c510c2d624d60a6d28a37fa66dcb0.tar.gz
Merge remote-tracking branch 'origin/3.0'
-rwxr-xr-x[-rw-r--r--]doc/images/analyzer-issues.pngbin18296 -> 75473 bytes
-rw-r--r--doc/images/creator-qbs-project.pngbin35937 -> 30296 bytes
-rwxr-xr-x[-rw-r--r--]doc/images/qtcreator-analyze-menu.pngbin13988 -> 27136 bytes
-rwxr-xr-x[-rw-r--r--]doc/images/qtcreator-qml-performance-monitor.pngbin18422 -> 82849 bytes
-rwxr-xr-x[-rw-r--r--]doc/images/qtcreator-valgrind-callgrind.pngbin30989 -> 87032 bytes
-rwxr-xr-x[-rw-r--r--]doc/images/qtcreator-valgrind-memcheck-options.pngbin4070 -> 28803 bytes
-rw-r--r--doc/src/analyze/creator-valgrind-overview.qdoc4
-rw-r--r--doc/src/analyze/creator-valgrind.qdoc23
-rw-r--r--doc/src/debugger/creator-debugger.qdoc56
-rw-r--r--doc/src/projects/creator-projects-cmake.qdoc63
-rw-r--r--doc/src/projects/creator-projects-qbs.qdoc18
-rw-r--r--share/qtcreator/debugger/gdbbridge.py45
-rw-r--r--share/qtcreator/debugger/lldbbridge.py10
-rw-r--r--share/qtcreator/debugger/qttypes.py39
-rw-r--r--share/qtcreator/debugger/stdtypes.py21
-rw-r--r--share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppetmain.cpp6
-rw-r--r--share/qtcreator/templates/html5app/app.pro5
-rw-r--r--share/qtcreator/welcomescreen/widgets/SideBar.qml4
-rw-r--r--src/libs/languageutils/componentversion.cpp9
-rw-r--r--src/libs/languageutils/componentversion.h5
-rw-r--r--src/libs/languageutils/fakemetaobject.cpp138
-rw-r--r--src/libs/languageutils/fakemetaobject.h12
-rw-r--r--src/libs/qmljs/qmljs-lib.pri9
-rw-r--r--src/libs/qmljs/qmljs.qbs4
-rw-r--r--src/libs/qmljs/qmljsconstants.h18
-rw-r--r--src/libs/qmljs/qmljscontext.cpp11
-rw-r--r--src/libs/qmljs/qmljscontext.h8
-rw-r--r--src/libs/qmljs/qmljsdocument.cpp158
-rw-r--r--src/libs/qmljs/qmljsdocument.h23
-rw-r--r--src/libs/qmljs/qmljsimportdependencies.cpp931
-rw-r--r--src/libs/qmljs/qmljsimportdependencies.h235
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h2
-rw-r--r--src/libs/qmljs/qmljslink.cpp13
-rw-r--r--src/libs/qmljs/qmljslink.h2
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h9
-rw-r--r--src/libs/qmljs/qmljstypedescriptionreader.cpp1
-rw-r--r--src/libs/qmljs/qmljsviewercontext.cpp79
-rw-r--r--src/libs/qmljs/qmljsviewercontext.h63
-rw-r--r--src/plugins/android/androidconfigurations.cpp6
-rw-r--r--src/plugins/android/androidconfigurations.h2
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp2
-rw-r--r--src/plugins/android/androiddeployqtwidget.cpp2
-rw-r--r--src/plugins/android/androiddevicedialog.cpp2
-rw-r--r--src/plugins/android/androidsettingswidget.cpp4
-rw-r--r--src/plugins/android/createandroidmanifestwizard.cpp1
-rw-r--r--src/plugins/baremetal/baremetalruncontrolfactory.cpp2
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp4
-rw-r--r--src/plugins/coreplugin/core.qrc1
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp18
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.h2
-rw-r--r--src/plugins/coreplugin/fileiconprovider.cpp23
-rw-r--r--src/plugins/coreplugin/images/compile_error_taskbar.pngbin0 -> 618 bytes
-rw-r--r--src/plugins/coreplugin/progressmanager/progressmanager_win.cpp2
-rw-r--r--src/plugins/cppeditor/cppdoxygen_test.cpp149
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp4
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.h12
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy.cpp24
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy.h3
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy_test.cpp15
-rw-r--r--src/plugins/cppeditor/cppincludehierarchymodel.cpp27
-rw-r--r--src/plugins/cppeditor/cppincludehierarchymodel.h8
-rw-r--r--src/plugins/cpptools/cpptoolseditorsupport.cpp1
-rw-r--r--src/plugins/debugger/debuggerstartparameters.h2
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp7
-rw-r--r--src/plugins/debugger/lldb/lldbengine.cpp26
-rw-r--r--src/plugins/debugger/lldb/lldbengine.h1
-rw-r--r--src/plugins/debugger/threadshandler.cpp98
-rw-r--r--src/plugins/debugger/threadshandler.h10
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp12
-rw-r--r--src/plugins/git/gitclient.cpp2
-rw-r--r--src/plugins/ios/iosdebugsupport.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp3
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp3
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h2
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp27
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp74
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.h2
-rw-r--r--src/plugins/qmljseditor/qmljsfindreferences.cpp2
-rw-r--r--src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp2
-rw-r--r--src/plugins/qmljseditor/qmltaskmanager.cpp6
-rw-r--r--src/plugins/qmljseditor/qmltaskmanager.h2
-rw-r--r--src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp6
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp219
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.h22
-rw-r--r--src/plugins/qmljstools/qmljsplugindumper.cpp4
-rw-r--r--src/plugins/qmljstools/qmljstools_test.cpp2
-rw-r--r--src/plugins/qmljstools/qmljstoolsconstants.h1
-rw-r--r--src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp7
-rw-r--r--src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h1
-rw-r--r--src/plugins/qmlprofiler/qml/MainView.qml1
-rw-r--r--src/plugins/qmlprofiler/qml/SelectionRange.qml5
-rw-r--r--src/plugins/qmlprofiler/qml/TimeDisplay.qml11
-rw-r--r--src/plugins/qmlprofiler/qml/TimeMarks.qml15
-rw-r--r--src/plugins/qnx/blackberryconfiguration.cpp23
-rw-r--r--src/plugins/qnx/blackberryconfiguration.h2
-rw-r--r--src/plugins/qnx/blackberryinstallwizardpages.cpp12
-rw-r--r--src/plugins/qnx/blackberryndksettingswidget.cpp21
-rw-r--r--src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp5
-rw-r--r--src/plugins/qnx/cascadesimport/cascadesimportwizard.h1
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.cpp4
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.h3
105 files changed, 2534 insertions, 463 deletions
diff --git a/doc/images/analyzer-issues.png b/doc/images/analyzer-issues.png
index c60f86607c..7bcaeeecf6 100644..100755
--- a/doc/images/analyzer-issues.png
+++ b/doc/images/analyzer-issues.png
Binary files differ
diff --git a/doc/images/creator-qbs-project.png b/doc/images/creator-qbs-project.png
index ec4dcadae1..76466d4758 100644
--- a/doc/images/creator-qbs-project.png
+++ b/doc/images/creator-qbs-project.png
Binary files differ
diff --git a/doc/images/qtcreator-analyze-menu.png b/doc/images/qtcreator-analyze-menu.png
index 9a95504164..986ab48d91 100644..100755
--- a/doc/images/qtcreator-analyze-menu.png
+++ b/doc/images/qtcreator-analyze-menu.png
Binary files differ
diff --git a/doc/images/qtcreator-qml-performance-monitor.png b/doc/images/qtcreator-qml-performance-monitor.png
index 6cd007d8e5..28c2a143d4 100644..100755
--- a/doc/images/qtcreator-qml-performance-monitor.png
+++ b/doc/images/qtcreator-qml-performance-monitor.png
Binary files differ
diff --git a/doc/images/qtcreator-valgrind-callgrind.png b/doc/images/qtcreator-valgrind-callgrind.png
index 756c86e70d..e29d252027 100644..100755
--- a/doc/images/qtcreator-valgrind-callgrind.png
+++ b/doc/images/qtcreator-valgrind-callgrind.png
Binary files differ
diff --git a/doc/images/qtcreator-valgrind-memcheck-options.png b/doc/images/qtcreator-valgrind-memcheck-options.png
index baca54ecf6..a102b61367 100644..100755
--- a/doc/images/qtcreator-valgrind-memcheck-options.png
+++ b/doc/images/qtcreator-valgrind-memcheck-options.png
Binary files differ
diff --git a/doc/src/analyze/creator-valgrind-overview.qdoc b/doc/src/analyze/creator-valgrind-overview.qdoc
index 820b0cb9c7..7f69b554a1 100644
--- a/doc/src/analyze/creator-valgrind-overview.qdoc
+++ b/doc/src/analyze/creator-valgrind-overview.qdoc
@@ -36,8 +36,8 @@
to use them from \QC.
To run the Valgrind tools on a remote host over SSH, select \gui {Analyze
- > Valgrind Memory Analyzer (External)} or \gui {Valgrind Function Profiler
- (External)}.
+ > Valgrind Memory Analyzer (Remote)} or \gui {Valgrind Function Profiler
+ (Remote)}.
To stop the currently running analyzer, select \gui {Analyze
> Stop}.
diff --git a/doc/src/analyze/creator-valgrind.qdoc b/doc/src/analyze/creator-valgrind.qdoc
index 00e2edca20..7d00ae9792 100644
--- a/doc/src/analyze/creator-valgrind.qdoc
+++ b/doc/src/analyze/creator-valgrind.qdoc
@@ -97,6 +97,25 @@
uninitialized memory} check box is selected by default. You can deselect it
to make Memcheck run faster.
+ Memcheck searches for memory leaks when the client application finishes. To
+ view the amount of leaks that occurred, select \gui {Summary Only} in the
+ \gui {Check for leaks on finish} field. To also view details of each leak,
+ select \gui Full.
+
+ \section2 Showing Reachable and Indirectly Lost Blocks
+
+ \e Reachable blocks are blocks that are pointed at by a pointer or chain
+ of pointers and that might have been freed before the application exited.
+ \e {Indirectly lost} blocks are considered lost because all the blocks that
+ point to them are themselves lost. For example, all the children of a lost
+ root node are indirectly lost.
+
+ By default, Memcheck does not report reachable and indirectly lost blocks.
+ To have them reported, select the \gui {Show reachable and indirectly lost
+ blocks}.
+
+ \section2 Suppressing Errors
+
Memcheck detects numerous problems in the system libraries, such as the C
library, which come pre-installed with your OS. As you cannot easily fix
them, you want to suppress them. Valgrind reads a list of errors to suppress
@@ -252,8 +271,8 @@
\list 1
- \li Select \gui {Analyze > Valgrind Memory Analyzer (External)} or
- \gui {Valgrind Function Profiler (External)}.
+ \li Select \gui {Analyze > Valgrind Memory Analyzer (Remote)} or
+ \gui {Valgrind Function Profiler (Remote)}.
\image qtcreator-valgrind-remote-settings.png "Start Analyzer dialog"
diff --git a/doc/src/debugger/creator-debugger.qdoc b/doc/src/debugger/creator-debugger.qdoc
index e5b58c126c..ffe1a4d746 100644
--- a/doc/src/debugger/creator-debugger.qdoc
+++ b/doc/src/debugger/creator-debugger.qdoc
@@ -800,15 +800,13 @@
A snapshot contains the complete state of the debugged program
at a time, including the full memory contents.
- To create snapshots of a debugged program, select \gui Create in the
- context menu in the \gui Snapshot view.
+ To create snapshots of a debugged program, select \gui {Create Snapshot} in
+ the context menu in the \gui Snapshots view.
- Double-click on entries in the snapshot view to switch between
+ Double-click on entries in the \gui Snapshots view to switch between
snapshots. The debugger views are updated to reflect the
state of the program at time of taking the snapshot.
- By default, the \gui{Snapshots} view is hidden.
-
*/
@@ -901,7 +899,7 @@
\li There is no GDB to communicate with MSVC compiled applications on
Windows. So information can be displayed nicely only in a limited
- fashion by using a cdb extension DLL.
+ fashion by using a CDB extension DLL.
\endlist
@@ -986,13 +984,13 @@
]}"
\endcode
- The value of the \gui{iname} field is the internal name of the object,
+ The value of the \c iname field is the internal name of the object,
constituting a dot-separated list of identifiers, corresponding to the
position of the object's representation in the view. If it is not
present, is it generated by concatenating the parent object's iname,
a dot, and a sequential number.
- The value of the\gui{name} field is displayed in the \gui{name} column
+ The value of the \c name field is displayed in the \gui{Name} column
of the view. If it is not specified, a simple number in brackets
is used instead.
@@ -1003,44 +1001,44 @@
enums, known and unknown structs as well as some convenience functions to
handle common situations.
- The member functions of the \gui{Dumper} class are the following:
+ The member functions of the \c Dumper class are the following:
\list
- \li \gui{__init__(self)} - Initializes the output to an empty string and
+ \li \c{__init__(self)} - Initializes the output to an empty string and
empties the child stack. This should not be used in user code.
- \li \gui{put(self, value)} - Low level function to directly append to the
+ \li \c{put(self, value)} - Low level function to directly append to the
output string. That is also the fastest way to append output.
- \li \gui{putField(self, name, value)} - Appends a name='value' field.
+ \li \c{putField(self, name, value)} - Appends a \c{name='value'} field.
- \li \gui{childRange(self)} - Returns the range of children specified in
+ \li \c{childRange(self)} - Returns the range of children specified in
the current \c Children scope.
- \li \gui{putItemCount(self, count)} - Appends a field
+ \li \c{putItemCount(self, count)} - Appends a field
\c {value='<%d items'} to the output.
- \li \gui{putEllipsis(self)} - Appends fields
+ \li \c{putEllipsis(self)} - Appends fields
\c {'{name="<incomplete>",value="",type="",numchild="0"}'}. This is
automatically done by \c endChildren if the number of children to
print is smaller than the number of actual children.
- \li \gui{putName(self, name)} - Appends a \c {name=''} field.
+ \li \c{putName(self, name)} - Appends a \c {name=''} field.
- \li \gui{putType(self, type, priority=0)} - Appends a field \c {type=''}
+ \li \c{putType(self, type, priority=0)} - Appends a field \c {type=''}
unless the \a type coincides with the parent's default child type or
\c putType was already called for the current item with a higher
value of \c priority.
- \li \gui{putBetterType(self, type)} - Overrides the last recorded
+ \li \c{putBetterType(self, type)} - Overrides the last recorded
\c type.
- \li \gui{putNumChild(self, numchild)} - Appends a field \c {numchild=''}
+ \li \c{putNumChild(self, numchild)} - Appends a field \c {numchild=''}
unless the \c numchild coincides with the parent's default child
numchild value.
- \li \gui{putValue(self, value, encoding = None)} - Append a file \c {value=''},
+ \li \c{putValue(self, value, encoding = None)} - Append a file \c {value=''},
optionally followed by a field \c {valueencoding=''}. The \c value
needs to be convertible to a string entirely consisting of
alphanumerical values. The \c encoding parameter can be used to
@@ -1072,16 +1070,16 @@
double quotes are added.
\endlist
- \li \gui{putStringValue(self, value)} - Encodes a QString and calls
+ \li \c{putStringValue(self, value)} - Encodes a QString and calls
\c putValue with the correct \c encoding setting.
- \li \gui{putByteArrayValue(self, value)} - Encodes a QByteArray and calls
+ \li \c{putByteArrayValue(self, value)} - Encodes a QByteArray and calls
\c putValue with the correct \c encoding setting.
- \li \gui{isExpanded()} - Checks whether the current item
+ \li \c{isExpanded()} - Checks whether the current item
is expanded in the view.
- \li \gui{putIntItem(self, name, value)} - Equivalent to:
+ \li \c{putIntItem(self, name, value)} - Equivalent to:
\code
with SubItem(self, name):
self.putValue(value)
@@ -1090,7 +1088,7 @@
self.putNumChild(0)
\endcode
- \li \gui{putBoolItem(self, name, value)} - Equivalent to:
+ \li \c{putBoolItem(self, name, value)} - Equivalent to:
\code
with SubItem(self, name):
self.putValue(value)
@@ -1098,7 +1096,7 @@
self.putNumChild(0)
\endcode
- \li \gui{putCallItem(self, name, value, func, *args)} -
+ \li \c{putCallItem(self, name, value, func, *args)} -
Uses GDB to call the function \c func on the value specified by
\a {value} and output the resulting item. Use \c{putCallItem}
only if there is no other way to access the data.
@@ -1107,12 +1105,12 @@
and have the potential to change the state of the debugged
program.
- \li \gui{putItem(self, value)} - The "master function", handling
+ \li \c{putItem(self, value)} - The "master function", handling
basic types, references, pointers and enums directly, iterates
over base classes and class members of compound types and calls
\c qdump__* functions whenever appropriate.
- \li \gui{putSubItem(self, component, value)} - Equivalent to:
+ \li \c{putSubItem(self, component, value)} - Equivalent to:
\code
with SubItem(self, component):
self.putItem(value)
@@ -1135,7 +1133,7 @@
use \c Children and \c SubItem \e{Context Managers} to create the nested
items.
- The \c Children constructor \gui{__init__(self, dumper, numChild = 1,
+ The \c Children constructor \c{__init__(self, dumper, numChild = 1,
childType = None, childNumChild = None, maxNumChild = None, addrBase = None,
addrStep = None)} uses one mandatory argument and several
optional arguments. The mandatory argument refers to the current \c Dumper
diff --git a/doc/src/projects/creator-projects-cmake.qdoc b/doc/src/projects/creator-projects-cmake.qdoc
index 54638f942a..8443334240 100644
--- a/doc/src/projects/creator-projects-cmake.qdoc
+++ b/doc/src/projects/creator-projects-cmake.qdoc
@@ -110,6 +110,69 @@
For more information about known issues for the current version, see
\l{Known Issues}.
+ \section1 Deploying CMake Projects to Embedded Linux Devices
+
+ \QC cannot extract files to be installed from a CMake project, and
+ therefore, only executable targets are automatically added to deployment
+ files. You must specify all other files in the \c QtCreatorDeployment.txt
+ file that you create and place in the root directory of the CMake project.
+
+ Use the following syntax in the file:
+
+ \code
+ <deployment/prefix>
+ <relative/source/file1>:<relative/destination/dir1>
+ ...
+ <relative/source/filen>:<relative/destination/dirn>
+ \endcode
+
+ Where:
+
+ \list
+
+ \li \c{<deployment/prefix>} is the (absolute) path prefix to where files
+ are copied on the remote machine.
+
+ \li \c{<relative/source/file>} is the file path relative to the CMake
+ project root. No directories or wildcards are allowed in this
+ value.
+
+ \li \c{<relative/destination/dir>} is the destination directory path
+ relative to \c{deployment/prefix}.
+
+ \endlist
+
+ To automate the creation of \c QtCreatorDeployment.txt file:
+
+ \list 1
+
+ \li Define the following macros in the top level \c CMakeLists.txt file:
+
+ \code
+ file(WRITE "${CMAKE_SOURCE_DIR}/QtCreatorDeployment.txt" "<deployment/prefix>\n")
+
+ macro(add_deployment_file SRC DEST)
+ file(RELATIVE_PATH path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+ file(APPEND "${CMAKE_SOURCE_DIR}/QtCreatorDeployment.txt" "${path}/${SRC}:${DEST}\n")
+ endmacro()
+
+ macro(add_deployment_directory SRC DEST)
+ file(GLOB_RECURSE files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${SRC}/*")
+ foreach(filename ${files})
+ get_filename_component(path ${filename} PATH)
+ add_deployment_file("${filename}" "${DEST}/${path}")
+ endforeach(filename)
+ endmacro()
+ \endcode
+
+ \li Use \c {add_deployment_file(<file/name>)} to add files and
+ \c {add_deployment_directory(<folder/name>)} to add directories
+ (including subdirectories) to the \c QtCreatorDeployment.txt file.
+
+ \li Re-run \c cmake after you add or remove files using the macros.
+
+ \endlist
+
\section1 Adding External Libraries to CMake Projects
Through external libraries, \QC can support code completion and syntax
diff --git a/doc/src/projects/creator-projects-qbs.qdoc b/doc/src/projects/creator-projects-qbs.qdoc
index aacf512201..5a489ccdfa 100644
--- a/doc/src/projects/creator-projects-qbs.qdoc
+++ b/doc/src/projects/creator-projects-qbs.qdoc
@@ -31,7 +31,7 @@
To use Qbs to build a project, you must create a .qbs file for the project.
For more information, see the
- \l{http://doc-snapshot.qt-project.org/qbs/index.html}{Qbs Manual}.
+ \l{http://qt-project.org/doc/qbs/index.html}{Qbs Manual}.
\section1 Enabling the Qbs Plugin
@@ -58,18 +58,20 @@
\list 1
- \li Create a .qbs file for your project. For examples, see the
- \c {tests\manual} directory in the qbs repository.
-
- \li In \QC, select \gui File > \gui {Open File or Project}.
-
- \li Select the .qbs file for your project.
+ \li Select \gui File > \gui {New File or Project} > \gui {Plain C
+ Project (Qbs Build)} or \gui {Plain C++ Project (Qbs Build)} >
+ \gui Choose, and follow the instructions of the wizard to create a
+ Qbs project.
\image creator-qbs-project.png
+ \li Edit the .qbs file for you project. Usually, you must add the
+ \c Depends item for a Qt application. For examples, see the
+ \c {examples} directory in the qbs repository.
+
\li Click the
\inlineimage qtcreator-run.png
- (\gui Run) button to run the application.
+ (\gui Run) button to build, deploy, and run the application.
\endlist
diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py
index aa205c5f54..389f6f91de 100644
--- a/share/qtcreator/debugger/gdbbridge.py
+++ b/share/qtcreator/debugger/gdbbridge.py
@@ -420,7 +420,7 @@ class LocalItem:
#######################################################################
def bbedit(args):
- theDumper.bbedit(args.split(","))
+ theDumper.bbedit(args)
registerCommand("bbedit", bbedit)
@@ -706,7 +706,8 @@ class Dumper(DumperBase):
if type.find(":") >= 0:
type = "'" + type + "'"
# 'class' is needed, see http://sourceware.org/bugzilla/show_bug.cgi?id=11912
- exp = "((class %s*)%s)->%s(%s)" % (type, value.address, func, arg)
+ #exp = "((class %s*)%s)->%s(%s)" % (type, value.address, func, arg)
+ exp = "((%s*)%s)->%s(%s)" % (type, value.address, func, arg)
#warn("CALL: %s" % exp)
result = None
try:
@@ -903,6 +904,15 @@ class Dumper(DumperBase):
# Try _some_ fallback (good enough for the std::complex dumper)
return gdb.parse_and_eval("{%s}%s" % (referencedType, address))
+ def setValue(self, address, type, value):
+ cmd = "set {%s}%s=%s" % (type, address, value)
+ gdb.execute(cmd)
+
+ def setValues(self, address, type, values):
+ cmd = "set {%s[%s]}%s={%s}" \
+ % (type, len(values), address, ','.join(map(str, values)))
+ gdb.execute(cmd)
+
def selectedInferior(self):
try:
# gdb.Inferior is new in gdb 7.2
@@ -1630,6 +1640,10 @@ class Dumper(DumperBase):
return out
def threadnames(self, maximalStackDepth):
+ # FIXME: This needs a proper implementation for MinGW, and only there.
+ # Linux, Mac and QNX mirror the objectName()to the underlying threads,
+ # so we get the names already as part of the -thread-info output.
+ return '[]'
out = '['
oldthread = gdb.selected_thread()
if oldthread:
@@ -1676,22 +1690,25 @@ class Dumper(DumperBase):
return namespace
- def bbedit(self, type, expr, value):
- type = b16decode(type)
+ def bbedit(self, args):
+ (typeName, expr, data) = args.split(',')
+ typeName = b16decode(typeName)
ns = self.qtNamespace()
- if type.startswith(ns):
- type = type[len(ns):]
- type = type.replace("::", "__")
- pos = type.find('<')
+ if typeName.startswith(ns):
+ typeName = typeName[len(ns):]
+ typeName = typeName.replace("::", "__")
+ pos = typeName.find('<')
if pos != -1:
- type = type[0:pos]
+ typeName = typeName[0:pos]
expr = b16decode(expr)
- value = b16decode(value)
- #warn("EDIT: %s %s %s %s: " % (pos, type, expr, value))
- if self.qqEditable.has_key(type):
- self.qqEditable[type](expr, value)
+ data = b16decode(data)
+ if typeName in self.qqEditable:
+ #self.qqEditable[typeName](self, expr, data)
+ value = gdb.parse_and_eval(expr)
+ self.qqEditable[typeName](self, value, data)
else:
- gdb.execute("set (%s)=%s" % (expr, value))
+ cmd = "set variable (%s)=%s" % (expr, data)
+ gdb.execute(cmd)
def hasVTable(self, type):
fields = type.fields()
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py
index 235c56069b..07b8ead43c 100644
--- a/share/qtcreator/debugger/lldbbridge.py
+++ b/share/qtcreator/debugger/lldbbridge.py
@@ -618,7 +618,10 @@ class Dumper(DumperBase):
self.report('state="inferiorrunfailed"')
return
self.report('pid="%s"' % self.process.GetProcessID())
- self.report('state="enginerunandinferiorstopok"')
+ # even if it stops it seems that lldb assumes it is running and later detects that
+ # it did stop after all, so it is be better to mirror that and wait for the spontaneous
+ # stop
+ self.report('state="enginerunandinferiorrunok"')
elif len(self.remoteChannel_) > 0:
self.process = self.target.ConnectRemote(
self.debugger.GetListener(),
@@ -626,7 +629,10 @@ class Dumper(DumperBase):
if not error.Success():
self.report('state="inferiorrunfailed"')
return
- self.report('state="enginerunandinferiorstopok"')
+ # even if it stops it seems that lldb assumes it is running and later detects that
+ # it did stop after all, so it is be better to mirror that and wait for the spontaneous
+ # stop
+ self.report('state="enginerunandinferiorrunok"')
else:
launchInfo = lldb.SBLaunchInfo(self.processArgs_.split())
launchInfo.SetWorkingDirectory(os.getcwd())
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index f54757a4e8..cb54d39200 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -165,7 +165,7 @@ def qdump__QModelIndex(d, value):
v = val["d"]["data"]["ptr"]
d.putStringValue(d.makeValue(ns + 'QString', v))
except:
- d.putValue("(invalid)")
+ d.putValue("")
d.putNumChild(rowCount * columnCount)
if d.isExpanded():
@@ -1645,17 +1645,10 @@ def qdump__QStandardItem(d, value):
d.putPlainChildren(value)
-def qedit__QString(expr, value):
- cmd = "call (%s).resize(%d)" % (expr, len(value))
- gdb.execute(cmd)
- d = gdb.parse_and_eval(expr)["d"]["data"]
- cmd = "set {short[%d]}%s={" % (len(value), d.pointerValue(d))
- for i in range(len(value)):
- if i != 0:
- cmd += ','
- cmd += str(ord(value[i]))
- cmd += '}'
- gdb.execute(cmd)
+def qedit__QString(d, value, data):
+ d.call(value, "resize", str(len(data)))
+ (base, size, alloc) = d.stringData(value)
+ d.setValues(base, "short", [ord(c) for c in data])
def qform__QString():
return "Inline,Separate Window"
@@ -1981,15 +1974,19 @@ def qdump__QVariant(d, value):
return tdata.type
-def qedit__QVector(expr, value):
- values = value.split(',')
- ob = gdb.parse_and_eval(expr)
- cmd = "call (%s).resize(%d)" % (expr, len(values))
- gdb.execute(cmd)
- innerType = d.templateArgument(ob.type, 0)
- ptr = ob["p"]["array"].cast(d.voidPtrType())
- cmd = "set {%s[%d]}%s={%s}" % (innerType, len(values), d.pointerValue(ptr), value)
- gdb.execute(cmd)
+def qedit__QVector(d, value, data):
+ values = data.split(',')
+ size = len(values)
+ d.call(value, "resize", str(size))
+ innerType = d.templateArgument(value.type, 0)
+ try:
+ # Qt 5. Will fail on Qt 4 due to the missing 'offset' member.
+ offset = value["d"]["offset"]
+ base = d.pointerValue(value["d"].cast(d.charPtrType()) + offset)
+ except:
+ # Qt 4.
+ base = d.pointerValue(value["p"]["array"])
+ d.setValues(base, innerType, values)
def qform__QVector():
diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py
index 9f55089f50..8c1c129e2c 100644
--- a/share/qtcreator/debugger/stdtypes.py
+++ b/share/qtcreator/debugger/stdtypes.py
@@ -659,16 +659,16 @@ def qdump__std____debug__unordered_set(d, value):
qdump__std__unordered_set(d, value)
-def qedit__std__vector(expr, value):
- values = value.split(',')
+def qedit__std__vector(d, value, data):
+ import gdb
+ values = data.split(',')
n = len(values)
- ob = gdb.parse_and_eval(expr)
- innerType = d.templateArgument(ob.type, 0)
+ innerType = d.templateArgument(value.type, 0)
cmd = "set $d = (%s*)calloc(sizeof(%s)*%s,1)" % (innerType, innerType, n)
gdb.execute(cmd)
- cmd = "set {void*[3]}%s = {$d, $d+%s, $d+%s}" % (ob.address, n, n)
+ cmd = "set {void*[3]}%s = {$d, $d+%s, $d+%s}" % (value.address, n, n)
gdb.execute(cmd)
- cmd = "set (%s[%d])*$d={%s}" % (innerType, n, value)
+ cmd = "set (%s[%d])*$d={%s}" % (innerType, n, data)
gdb.execute(cmd)
def qdump__std__vector(d, value):
@@ -766,12 +766,11 @@ def qdump__std____1__vector(d, value):
def qdump__std____debug__vector(d, value):
qdump__std__vector(d, value)
-def qedit__std__string(expr, value):
- cmd = "print (%s).assign(\"%s\")" % (expr, value)
- gdb.execute(cmd)
+def qedit__std__string(d, value, data):
+ d.call(value, "assign", '"%s"' % data.replace('"', '\\"'))
-def qedit__string(expr, value):
- qedit__std__string(expr, value)
+def qedit__string(d, expr, value):
+ qedit__std__string(d, expr, value)
def qdump__string(d, value):
qdump__std__string(d, value)
diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppetmain.cpp b/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppetmain.cpp
index 4f712d0f86..13ce89e792 100644
--- a/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppetmain.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppetmain.cpp
@@ -35,6 +35,8 @@
#include <private/qsimulatorconnection_p.h>
#endif
+#include <iostream>
+
#include <qt4nodeinstanceclientproxy.h>
#ifdef ENABLE_QT_BREAKPAD
@@ -60,11 +62,11 @@ int main(int argc, char *argv[])
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setOrganizationDomain("qt-project.org");
QCoreApplication::setApplicationName("QmlPuppet");
- QCoreApplication::setApplicationVersion("1.1.0");
+ QCoreApplication::setApplicationVersion("2.0.0");
if (application.arguments().count() == 2 && application.arguments().at(1) == "--version") {
- qDebug() << QCoreApplication::applicationVersion();
+ std::cout << 2;
return 0;
}
diff --git a/share/qtcreator/templates/html5app/app.pro b/share/qtcreator/templates/html5app/app.pro
index 66cddd2618..42c6c9cdba 100644
--- a/share/qtcreator/templates/html5app/app.pro
+++ b/share/qtcreator/templates/html5app/app.pro
@@ -10,11 +10,6 @@ DEPLOYMENTFOLDERS = folder_01
# TOUCH_OPTIMIZED_NAVIGATION #
DEFINES += TOUCH_OPTIMIZED_NAVIGATION
-# If your application uses the Qt Mobility libraries, uncomment the following
-# lines and add the respective components to the MOBILITY variable.
-# CONFIG += mobility
-# MOBILITY +=
-
# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp
diff --git a/share/qtcreator/welcomescreen/widgets/SideBar.qml b/share/qtcreator/welcomescreen/widgets/SideBar.qml
index 5183c4b906..20ba652277 100644
--- a/share/qtcreator/welcomescreen/widgets/SideBar.qml
+++ b/share/qtcreator/welcomescreen/widgets/SideBar.qml
@@ -101,13 +101,13 @@ ColumnLayout {
width: parent.width
}
- Text {
+ NativeText {
text: qsTr("New to Qt?")
font.pixelSize: 18
font.bold: false
}
- Text {
+ NativeText {
text: qsTr("Learn how to develop your own applications and explore Qt Creator.")
font.pixelSize: 12
wrapMode: Text.WordWrap
diff --git a/src/libs/languageutils/componentversion.cpp b/src/libs/languageutils/componentversion.cpp
index b043802a00..99aff4a5b8 100644
--- a/src/libs/languageutils/componentversion.cpp
+++ b/src/libs/languageutils/componentversion.cpp
@@ -30,6 +30,7 @@
#include "componentversion.h"
#include <QString>
+#include <QCryptographicHash>
#include <limits>
@@ -77,7 +78,13 @@ bool ComponentVersion::isValid() const
QString ComponentVersion::toString() const
{
return QString::fromLatin1("%1.%2").arg(QString::number(_major),
- QString::number(_minor));
+ QString::number(_minor));
+}
+
+void ComponentVersion::addToHash(QCryptographicHash &hash) const
+{
+ hash.addData(reinterpret_cast<const char *>(&_major), sizeof(_major));
+ hash.addData(reinterpret_cast<const char *>(&_minor), sizeof(_minor));
}
namespace LanguageUtils {
diff --git a/src/libs/languageutils/componentversion.h b/src/libs/languageutils/componentversion.h
index d1c0bde541..7fe35e8792 100644
--- a/src/libs/languageutils/componentversion.h
+++ b/src/libs/languageutils/componentversion.h
@@ -32,6 +32,10 @@
#include "languageutils_global.h"
+QT_BEGIN_NAMESPACE
+class QCryptographicHash;
+QT_END_NAMESPACE
+
namespace LanguageUtils {
class LANGUAGEUTILS_EXPORT ComponentVersion
@@ -55,6 +59,7 @@ public:
bool isValid() const;
QString toString() const;
+ void addToHash(QCryptographicHash &hash) const;
};
bool LANGUAGEUTILS_EXPORT operator<(const ComponentVersion &lhs, const ComponentVersion &rhs);
diff --git a/src/libs/languageutils/fakemetaobject.cpp b/src/libs/languageutils/fakemetaobject.cpp
index a478b2171a..980b69d16f 100644
--- a/src/libs/languageutils/fakemetaobject.cpp
+++ b/src/libs/languageutils/fakemetaobject.cpp
@@ -28,6 +28,7 @@
****************************************************************************/
#include "fakemetaobject.h"
+#include <QCryptographicHash>
using namespace LanguageUtils;
@@ -62,6 +63,24 @@ QStringList FakeMetaEnum::keys() const
bool FakeMetaEnum::hasKey(const QString &key) const
{ return m_keys.contains(key); }
+void FakeMetaEnum::addToHash(QCryptographicHash &hash) const
+{
+ int len = m_name.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
+ len = m_keys.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const QString &key, m_keys) {
+ len = key.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
+ }
+ len = m_values.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (int value, m_values)
+ hash.addData(reinterpret_cast<const char *>(&value), sizeof(value));
+}
+
FakeMetaMethod::FakeMetaMethod(const QString &name, const QString &returnType)
: m_name(name)
, m_returnType(returnType)
@@ -109,6 +128,33 @@ int FakeMetaMethod::revision() const
void FakeMetaMethod::setRevision(int r)
{ m_revision = r; }
+void FakeMetaMethod::addToHash(QCryptographicHash &hash) const
+{
+ int len = m_name.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
+ hash.addData(reinterpret_cast<const char *>(&m_methodAccess), sizeof(m_methodAccess));
+ hash.addData(reinterpret_cast<const char *>(&m_methodTy), sizeof(m_methodTy));
+ hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
+ len = m_paramNames.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const QString &pName, m_paramNames) {
+ len = pName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(pName.constData()), len * sizeof(QChar));
+ }
+ len = m_paramTypes.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const QString &pType, m_paramTypes) {
+ len = pType.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(pType.constData()), len * sizeof(QChar));
+ }
+ len = m_returnType.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_returnType.constData()), len * sizeof(QChar));
+}
+
FakeMetaProperty::FakeMetaProperty(const QString &name, const QString &type, bool isList,
bool isWritable, bool isPointer, int revision)
@@ -138,6 +184,21 @@ bool FakeMetaProperty::isPointer() const
int FakeMetaProperty::revision() const
{ return m_revision; }
+void FakeMetaProperty::addToHash(QCryptographicHash &hash) const
+{
+ int len = m_propertyName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_propertyName.constData()), len * sizeof(QChar));
+ hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
+ int flags = (m_isList ? (1 << 0) : 0)
+ + (m_isPointer ? (1 << 1) : 0)
+ + (m_isWritable ? (1 << 2) : 0);
+ hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags));
+ len = m_type.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_type.constData()), len * sizeof(QChar));
+}
+
FakeMetaObject::FakeMetaObject()
{
@@ -226,8 +287,85 @@ QString FakeMetaObject::attachedTypeName() const
void FakeMetaObject::setAttachedTypeName(const QString &name)
{ m_attachedTypeName = name; }
+QByteArray FakeMetaObject::calculateFingerprint() const
+{
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ int len = m_className.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_className.constData()), len * sizeof(QChar));
+ len = m_attachedTypeName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_attachedTypeName.constData()), len * sizeof(QChar));
+ len = m_defaultPropertyName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_defaultPropertyName.constData()), len * sizeof(QChar));
+ len = m_enumNameToIndex.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ {
+ QStringList keys(m_enumNameToIndex.keys());
+ keys.sort();
+ foreach (const QString &key, keys) {
+ len = key.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
+ int value = m_enumNameToIndex.value(key);
+ hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
+ m_enums.at(value).addToHash(hash);
+ }
+ }
+ len = m_exports.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const Export &e, m_exports)
+ e.addToHash(hash); // normalize order?
+ len = m_exports.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const FakeMetaMethod &m, m_methods)
+ m.addToHash(hash); // normalize order?
+ {
+ QStringList keys(m_propNameToIdx.keys());
+ keys.sort();
+ foreach (const QString &key, keys) {
+ len = key.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
+ int value = m_propNameToIdx.value(key);
+ hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
+ m_props.at(value).addToHash(hash);
+ }
+ }
+ len = m_superName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(m_superName.constData()), len * sizeof(QChar));
+
+ QByteArray res = hash.result();
+ res.append('F');
+ return res;
+}
+
+void FakeMetaObject::updateFingerprint()
+{
+ m_fingerprint = calculateFingerprint();
+}
+
+QByteArray FakeMetaObject::fingerprint() const
+{
+ return m_fingerprint;
+}
+
FakeMetaObject::Export::Export()
: metaObjectRevision(0)
{}
bool FakeMetaObject::Export::isValid() const
{ return version.isValid() || !package.isEmpty() || !type.isEmpty(); }
+
+void FakeMetaObject::Export::addToHash(QCryptographicHash &hash) const
+{
+ int len = package.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(package.constData()), len * sizeof(QChar));
+ len = type.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(type.constData()), len * sizeof(QChar));
+ version.addToHash(hash);
+ hash.addData(reinterpret_cast<const char *>(&metaObjectRevision), sizeof(metaObjectRevision));
+}
diff --git a/src/libs/languageutils/fakemetaobject.h b/src/libs/languageutils/fakemetaobject.h
index c0a417a7e1..ed485d9f62 100644
--- a/src/libs/languageutils/fakemetaobject.h
+++ b/src/libs/languageutils/fakemetaobject.h
@@ -39,6 +39,10 @@
#include <QHash>
#include <QSharedPointer>
+QT_BEGIN_NAMESPACE
+class QCryptographicHash;
+QT_END_NAMESPACE
+
namespace LanguageUtils {
class LANGUAGEUTILS_EXPORT FakeMetaEnum {
@@ -60,6 +64,7 @@ public:
int keyCount() const;
QStringList keys() const;
bool hasKey(const QString &key) const;
+ void addToHash(QCryptographicHash &hash) const;
};
class LANGUAGEUTILS_EXPORT FakeMetaMethod {
@@ -96,6 +101,7 @@ public:
int revision() const;
void setRevision(int r);
+ void addToHash(QCryptographicHash &hash) const;
private:
QString m_name;
@@ -125,6 +131,7 @@ public:
bool isWritable() const;
bool isPointer() const;
int revision() const;
+ void addToHash(QCryptographicHash &hash) const;
};
class LANGUAGEUTILS_EXPORT FakeMetaObject {
@@ -144,6 +151,7 @@ public:
int metaObjectRevision;
bool isValid() const;
+ void addToHash(QCryptographicHash &hash) const;
};
private:
@@ -157,6 +165,7 @@ private:
QList<FakeMetaMethod> m_methods;
QString m_defaultPropertyName;
QString m_attachedTypeName;
+ QByteArray m_fingerprint;
public:
FakeMetaObject();
@@ -195,6 +204,9 @@ public:
QString attachedTypeName() const;
void setAttachedTypeName(const QString &name);
+ QByteArray calculateFingerprint() const;
+ void updateFingerprint();
+ QByteArray fingerprint() const;
};
} // namespace LanguageUtils
diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri
index d4e83127da..beb80b8fb8 100644
--- a/src/libs/qmljs/qmljs-lib.pri
+++ b/src/libs/qmljs/qmljs-lib.pri
@@ -39,7 +39,9 @@ HEADERS += \
$$PWD/qmljssimplereader.h \
$$PWD/persistenttrie.h \
$$PWD/qmljsqrcparser.h \
- $$PWD/qmljsconstants.h
+ $$PWD/qmljsconstants.h \
+ $$PWD/qmljsimportdependencies.h \
+ $$PWD/qmljsviewercontext.h
SOURCES += \
$$PWD/qmljsbind.cpp \
@@ -70,7 +72,10 @@ SOURCES += \
$$PWD/consoleitem.cpp \
$$PWD/qmljssimplereader.cpp \
$$PWD/persistenttrie.cpp \
- $$PWD/qmljsqrcparser.cpp
+ $$PWD/qmljsqrcparser.cpp \
+ $$PWD/qmljsimportdependencies.cpp \
+ $$PWD/qmljsviewercontext.cpp
+
RESOURCES += \
$$PWD/qmljs.qrc
diff --git a/src/libs/qmljs/qmljs.qbs b/src/libs/qmljs/qmljs.qbs
index c79197475f..94968cf313 100644
--- a/src/libs/qmljs/qmljs.qbs
+++ b/src/libs/qmljs/qmljs.qbs
@@ -35,6 +35,7 @@ QtcLibrary {
"qmljsevaluate.cpp", "qmljsevaluate.h",
"qmljsicons.cpp", "qmljsicons.h",
"qmljsicontextpane.h",
+ "qmljsimportdependencies.cpp", "qmljsimportdependencies.h",
"qmljsindenter.cpp", "qmljsindenter.h",
"qmljsinterpreter.cpp", "qmljsinterpreter.h",
"qmljslineinfo.cpp", "qmljslineinfo.h",
@@ -52,7 +53,8 @@ QtcLibrary {
"qmljsstaticanalysismessage.cpp", "qmljsstaticanalysismessage.h",
"qmljstypedescriptionreader.cpp", "qmljstypedescriptionreader.h",
"qmljsutils.cpp", "qmljsutils.h",
- "qmljsvalueowner.cpp", "qmljsvalueowner.h"
+ "qmljsvalueowner.cpp", "qmljsvalueowner.h",
+ "qmljsviewercontext.cpp", "qmljsviewercontext.h"
]
}
diff --git a/src/libs/qmljs/qmljsconstants.h b/src/libs/qmljs/qmljsconstants.h
index fcb117050f..6f0f4c7fad 100644
--- a/src/libs/qmljs/qmljsconstants.h
+++ b/src/libs/qmljs/qmljsconstants.h
@@ -35,14 +35,22 @@ namespace QmlJS {
namespace ImportType {
enum Enum {
Invalid,
- ImplicitDirectory,
Library,
- File,
Directory,
- QrcFile,
+ ImplicitDirectory,
+ File,
+ UnknownFile, // refers a file/directory that wasn't found (or to an url)
QrcDirectory,
- ImplicitQrcDirectory,
- UnknownFile // refers a file/directory that wasn't found
+ QrcFile
+};
+}
+
+namespace ImportKind {
+enum Enum {
+ Invalid,
+ Library,
+ Path,
+ QrcPath,
};
}
diff --git a/src/libs/qmljs/qmljscontext.cpp b/src/libs/qmljs/qmljscontext.cpp
index ff601e37a6..c04206c182 100644
--- a/src/libs/qmljs/qmljscontext.cpp
+++ b/src/libs/qmljs/qmljscontext.cpp
@@ -54,17 +54,20 @@ using namespace QmlJS::AST;
QmlJSTextEditorWidget::semanticInfo()::context.
*/
-ContextPtr Context::create(const QmlJS::Snapshot &snapshot, ValueOwner *valueOwner, const ImportsPerDocument &imports)
+ContextPtr Context::create(const QmlJS::Snapshot &snapshot, ValueOwner *valueOwner,
+ const ImportsPerDocument &imports, const ViewerContext &vContext)
{
- QSharedPointer<Context> result(new Context(snapshot, valueOwner, imports));
+ QSharedPointer<Context> result(new Context(snapshot, valueOwner, imports, vContext));
result->_ptr = result;
return result;
}
-Context::Context(const QmlJS::Snapshot &snapshot, ValueOwner *valueOwner, const ImportsPerDocument &imports)
+Context::Context(const QmlJS::Snapshot &snapshot, ValueOwner *valueOwner,
+ const ImportsPerDocument &imports, const ViewerContext &vContext)
: _snapshot(snapshot),
_valueOwner(valueOwner),
- _imports(imports)
+ _imports(imports),
+ _vContext(vContext)
{
}
diff --git a/src/libs/qmljs/qmljscontext.h b/src/libs/qmljs/qmljscontext.h
index 63466a2316..ad3d8ed118 100644
--- a/src/libs/qmljs/qmljscontext.h
+++ b/src/libs/qmljs/qmljscontext.h
@@ -32,6 +32,7 @@
#include "qmljs_global.h"
#include "qmljsvalueowner.h"
+#include "qmljsviewercontext.h"
#include <QSharedPointer>
@@ -50,7 +51,8 @@ public:
typedef QHash<const Document *, QSharedPointer<const Imports> > ImportsPerDocument;
// Context takes ownership of valueOwner
- static ContextPtr create(const Snapshot &snapshot, ValueOwner *valueOwner, const ImportsPerDocument &imports);
+ static ContextPtr create(const Snapshot &snapshot, ValueOwner *valueOwner,
+ const ImportsPerDocument &imports, const ViewerContext &vContext);
~Context();
ContextPtr ptr() const;
@@ -69,11 +71,13 @@ public:
private:
// Context takes ownership of valueOwner
- Context(const Snapshot &snapshot, ValueOwner *valueOwner, const ImportsPerDocument &imports);
+ Context(const Snapshot &snapshot, ValueOwner *valueOwner, const ImportsPerDocument &imports,
+ const ViewerContext &vContext);
Snapshot _snapshot;
QSharedPointer<ValueOwner> _valueOwner;
ImportsPerDocument _imports;
+ ViewerContext _vContext;
QWeakPointer<const Context> _ptr;
};
diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp
index fe169f795c..68fb5eadd5 100644
--- a/src/libs/qmljs/qmljsdocument.cpp
+++ b/src/libs/qmljs/qmljsdocument.cpp
@@ -30,11 +30,17 @@
#include "qmljsdocument.h"
#include "qmljsbind.h"
#include "qmljsconstants.h"
+#include "qmljsimportdependencies.h"
#include <qmljs/parser/qmljslexer_p.h>
#include <qmljs/parser/qmljsparser_p.h>
+#include <utils/qtcassert.h>
+
+#include <QCryptographicHash>
#include <QDir>
+#include <algorithm>
+
using namespace QmlJS;
using namespace QmlJS::AST;
@@ -204,6 +210,16 @@ void Document::setLanguage(Language::Enum l)
_language = l;
}
+QString Document::importId() const
+{
+ return _fileName;
+}
+
+QByteArray Document::fingerprint() const
+{
+ return _fingerprint;
+}
+
AST::UiProgram *Document::qmlProgram() const
{
return cast<UiProgram *>(_ast);
@@ -245,6 +261,9 @@ QString Document::source() const
void Document::setSource(const QString &source)
{
_source = source;
+ QCryptographicHash sha(QCryptographicHash::Sha1);
+ sha.addData(source.toUtf8());
+ _fingerprint = sha.result();
}
int Document::editorRevision() const
@@ -373,21 +392,88 @@ LibraryInfo::LibraryInfo(Status status)
: _status(status)
, _dumpStatus(NoTypeInfo)
{
+ updateFingerprint();
}
-LibraryInfo::LibraryInfo(const QmlDirParser &parser)
+LibraryInfo::LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerprint)
: _status(Found)
, _components(parser.components().values())
, _plugins(parser.plugins())
, _typeinfos(parser.typeInfos())
+ , _fingerprint(fingerprint)
, _dumpStatus(NoTypeInfo)
{
+ if (_fingerprint.isEmpty())
+ updateFingerprint();
}
LibraryInfo::~LibraryInfo()
{
}
+QByteArray LibraryInfo::calculateFingerprint() const
+{
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(reinterpret_cast<const char *>(&_status), sizeof(_status));
+ int len = _components.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const QmlDirParser::Component &component, _components) {
+ len = component.fileName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(component.fileName.constData()), len * sizeof(QChar));
+ hash.addData(reinterpret_cast<const char *>(&component.majorVersion), sizeof(component.majorVersion));
+ hash.addData(reinterpret_cast<const char *>(&component.minorVersion), sizeof(component.minorVersion));
+ len = component.typeName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(component.typeName.constData()), component.typeName.size() * sizeof(QChar));
+ int flags = (component.singleton ? (1 << 0) : 0) + (component.internal ? (1 << 1) : 0);
+ hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags));
+ }
+ len = _plugins.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const QmlDirParser::Plugin &plugin, _plugins) {
+ len = plugin.path.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(plugin.path.constData()), len * sizeof(QChar));
+ len = plugin.name.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(plugin.name.constData()), len * sizeof(QChar));
+ }
+ len = _typeinfos.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const QmlDirParser::TypeInfo &typeinfo, _typeinfos) {
+ len = typeinfo.fileName.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(typeinfo.fileName.constData()), len * sizeof(QChar));
+ }
+ len = _metaObjects.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ QList<QByteArray> metaFingerprints;
+ foreach (const LanguageUtils::FakeMetaObject::ConstPtr &metaObject, _metaObjects)
+ metaFingerprints.append(metaObject->fingerprint());
+ std::sort(metaFingerprints.begin(), metaFingerprints.end());
+ foreach (const QByteArray &fp, metaFingerprints)
+ hash.addData(fp);
+ hash.addData(reinterpret_cast<const char *>(&_dumpStatus), sizeof(_dumpStatus));
+ len = _dumpError.size(); // localization dependent (avoid?)
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(_dumpError.constData()), len * sizeof(QChar));
+
+ len = _moduleApis.size();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ foreach (const ModuleApiInfo &moduleInfo, _moduleApis)
+ moduleInfo.addToHash(hash); // make it order independent?
+
+ QByteArray res(hash.result());
+ res.append('L');
+ return res;
+}
+
+void LibraryInfo::updateFingerprint()
+{
+ _fingerprint = calculateFingerprint();
+}
+
Snapshot::Snapshot()
{
}
@@ -396,21 +482,67 @@ Snapshot::~Snapshot()
{
}
+Snapshot::Snapshot(const Snapshot &o)
+ : _documents(o._documents),
+ _documentsByPath(o._documentsByPath),
+ _libraries(o._libraries),
+ _dependencies(o._dependencies)
+{
+}
+
void Snapshot::insert(const Document::Ptr &document, bool allowInvalid)
{
if (document && (allowInvalid || document->qmlProgram() || document->jsProgram())) {
const QString fileName = document->fileName();
const QString path = document->path();
-
remove(fileName);
_documentsByPath[path].append(document);
_documents.insert(fileName, document);
+ CoreImport cImport;
+ cImport.importId = document->importId();
+ cImport.language = document->language();
+ cImport.possibleExports << Export(ImportKey(ImportType::File, fileName),
+ QString(), true);
+ cImport.fingerprint = document->fingerprint();
+ _dependencies.addCoreImport(cImport);
}
}
void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info)
{
+ QTC_CHECK(info.fingerprint() == info.calculateFingerprint());
_libraries.insert(QDir::cleanPath(path), info);
+ if (!info.wasFound()) return;
+ CoreImport cImport;
+ cImport.importId = path;
+ cImport.language = Language::Unknown;
+ QSet<ImportKey> packages;
+ foreach (const ModuleApiInfo &moduleInfo, info.moduleApis()) {
+ ImportKey iKey(ImportType::Library, moduleInfo.uri, moduleInfo.version.majorVersion(),
+ moduleInfo.version.minorVersion());
+ packages.insert(iKey);
+ }
+ foreach (const LanguageUtils::FakeMetaObject::ConstPtr &metaO, info.metaObjects()) {
+ foreach (const LanguageUtils::FakeMetaObject::Export &e, metaO->exports()) {
+ ImportKey iKey(ImportType::Library, e.package, e.version.majorVersion(),
+ e.version.minorVersion());
+ packages.insert(iKey);
+ }
+ }
+
+ QStringList splitPath = path.split(QLatin1Char('/'));
+ foreach (const ImportKey &importKey, packages) {
+ QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size()))
+ .join(QLatin1String("/"));
+ cImport.possibleExports << Export(importKey, requiredPath, true);
+ }
+ foreach (const QmlDirParser::Component &component, info.components()) {
+ foreach (const Export &e, cImport.possibleExports)
+ // renaming of type name not really represented here... fix?
+ _dependencies.addExport(component.fileName, e.exportName, e.pathRequired);
+ }
+ cImport.fingerprint = info.fingerprint();
+ _dependencies.addCoreImport(cImport);
}
void Snapshot::remove(const QString &fileName)
@@ -427,6 +559,16 @@ void Snapshot::remove(const QString &fileName)
}
}
+const QmlJS::ImportDependencies *Snapshot::importDependencies() const
+{
+ return &_dependencies;
+}
+
+QmlJS::ImportDependencies *Snapshot::importDependencies()
+{
+ return &_dependencies;
+}
+
Document::MutablePtr Snapshot::documentFromSource(
const QString &code, const QString &fileName,
Language::Enum language) const
@@ -454,3 +596,15 @@ LibraryInfo Snapshot::libraryInfo(const QString &path) const
{
return _libraries.value(QDir::cleanPath(path));
}
+
+
+void ModuleApiInfo::addToHash(QCryptographicHash &hash) const
+{
+ int len = uri.length();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(uri.constData()), len * sizeof(QChar));
+ version.addToHash(hash);
+ len = cppName.length();
+ hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
+ hash.addData(reinterpret_cast<const char *>(cppName.constData()), len * sizeof(QChar));
+}
diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h
index 5d22890880..59906c354e 100644
--- a/src/libs/qmljs/qmljsdocument.h
+++ b/src/libs/qmljs/qmljsdocument.h
@@ -39,11 +39,13 @@
#include "parser/qmljsengine_p.h"
#include "qmljs_global.h"
#include "qmljsconstants.h"
+#include "qmljsimportdependencies.h"
namespace QmlJS {
class Bind;
class Snapshot;
+class ImportDependencies;
class QMLJS_EXPORT Document
{
@@ -69,6 +71,8 @@ public:
Language::Enum language() const;
void setLanguage(Language::Enum l);
+ QString importId() const;
+ QByteArray fingerprint() const;
AST::UiProgram *qmlProgram() const;
AST::Program *jsProgram() const;
AST::ExpressionNode *expression() const;
@@ -111,6 +115,7 @@ private:
QString _componentName;
QString _source;
QWeakPointer<Document> _ptr;
+ QByteArray _fingerprint;
int _editorRevision;
Language::Enum _language;
bool _parsedCorrectly;
@@ -125,6 +130,8 @@ public:
QString uri;
LanguageUtils::ComponentVersion version;
QString cppName;
+
+ void addToHash(QCryptographicHash &hash) const;
};
class QMLJS_EXPORT LibraryInfo
@@ -152,15 +159,21 @@ private:
typedef QList<LanguageUtils::FakeMetaObject::ConstPtr> FakeMetaObjectList;
FakeMetaObjectList _metaObjects;
QList<ModuleApiInfo> _moduleApis;
+ QByteArray _fingerprint;
PluginTypeInfoStatus _dumpStatus;
QString _dumpError;
public:
explicit LibraryInfo(Status status = NotScanned);
- explicit LibraryInfo(const QmlDirParser &parser);
+ explicit LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerprint = QByteArray());
~LibraryInfo();
+ QByteArray calculateFingerprint() const;
+ void updateFingerprint();
+ QByteArray fingerprint() const
+ { return _fingerprint; }
+
QList<QmlDirParser::Component> components() const
{ return _components; }
@@ -188,6 +201,9 @@ public:
bool wasScanned() const
{ return _status != NotScanned; }
+ bool wasFound() const
+ { return _status != NotFound; }
+
PluginTypeInfoStatus pluginTypeInfoStatus() const
{ return _dumpStatus; }
@@ -204,9 +220,11 @@ class QMLJS_EXPORT Snapshot
QHash<QString, Document::Ptr> _documents;
QHash<QString, QList<Document::Ptr> > _documentsByPath;
QHash<QString, LibraryInfo> _libraries;
+ ImportDependencies _dependencies;
public:
Snapshot();
+ Snapshot(const Snapshot &o);
~Snapshot();
typedef _Base::iterator iterator;
@@ -219,6 +237,9 @@ public:
void insertLibraryInfo(const QString &path, const LibraryInfo &info);
void remove(const QString &fileName);
+ const ImportDependencies *importDependencies() const;
+ ImportDependencies *importDependencies();
+
Document::Ptr document(const QString &fileName) const;
QList<Document::Ptr> documentsInDirectory(const QString &path) const;
LibraryInfo libraryInfo(const QString &path) const;
diff --git a/src/libs/qmljs/qmljsimportdependencies.cpp b/src/libs/qmljs/qmljsimportdependencies.cpp
new file mode 100644
index 0000000000..dffcf8ee4b
--- /dev/null
+++ b/src/libs/qmljs/qmljsimportdependencies.cpp
@@ -0,0 +1,931 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmljsimportdependencies.h"
+#include "qmljsinterpreter.h"
+#include "qmljsqrcparser.h"
+
+#include <utils/qtcassert.h>
+#include <utils/function.h>
+
+#include <QCryptographicHash>
+
+#include <algorithm>
+
+namespace QmlJS {
+
+static bool debugImportDependencies = false;
+
+ImportKind::Enum toImportKind(ImportType::Enum type)
+{
+ switch (type) {
+ case ImportType::Invalid:
+ break;
+ case ImportType::Library:
+ return ImportKind::Library;
+ case ImportType::ImplicitDirectory:
+ case ImportType::File:
+ case ImportType::Directory:
+ case ImportType::UnknownFile:
+ return ImportKind::Path;
+ case ImportType::QrcFile:
+ case ImportType::QrcDirectory:
+ return ImportKind::QrcPath;
+ }
+ return ImportKind::Invalid;
+}
+
+ImportMatchStrength::ImportMatchStrength(QList<int> match)
+ : m_match(match)
+{ }
+
+int ImportMatchStrength::compareMatch(const ImportMatchStrength &o) const
+{
+ int len1 = m_match.size();
+ int len2 = o.m_match.size();
+ int len = ((len1 < len2) ? len1 : len2);
+ for (int i = 0; i < len; ++ i) {
+ int v1 = m_match.at(i);
+ int v2 = o.m_match.at(i);
+ if (v1 < v2)
+ return -1;
+ if (v2 > v1)
+ return 1;
+ }
+ if (len1 < len2)
+ return -1;
+ if (len1 > len2)
+ return 1;
+ return 0;
+}
+
+bool ImportMatchStrength::hasNoMatch()
+{
+ return m_match.isEmpty();
+}
+
+bool ImportMatchStrength::hasMatch()
+{
+ return !m_match.isEmpty();
+}
+
+bool operator ==(const ImportMatchStrength &m1, const ImportMatchStrength &m2)
+{
+ return m1.m_match == m2.m_match;
+}
+
+bool operator !=(const ImportMatchStrength &m1, const ImportMatchStrength &m2)
+{
+ return !(m1 == m2);
+}
+
+bool operator <(const ImportMatchStrength &m1, const ImportMatchStrength &m2)
+{
+ return m1.compareMatch(m2) < 0;
+}
+
+ImportKey::ImportKey()
+ : type(ImportType::Invalid),
+ majorVersion(LanguageUtils::ComponentVersion::NoVersion),
+ minorVersion(LanguageUtils::ComponentVersion::NoVersion)
+{ }
+
+ImportKey::ImportKey(const ImportInfo &info)
+ : type(info.type())
+ , majorVersion(info.version().majorVersion())
+ , minorVersion(info.version().minorVersion())
+{
+ splitPath = QFileInfo(info.path()).canonicalFilePath().split(QLatin1Char('/'),
+ QString::KeepEmptyParts);
+}
+
+ImportKey::ImportKey(ImportType::Enum type, const QString &path, int majorVersion, int minorVersion)
+ : type(type)
+ , majorVersion(majorVersion)
+ , minorVersion(minorVersion)
+{
+ switch (type) {
+ case ImportType::Library:
+ splitPath = path.split(QLatin1Char('.'));
+ break;
+ case ImportType::ImplicitDirectory:
+ case ImportType::Directory:
+ splitPath = path.split(QLatin1Char('/'));
+ if (splitPath.length() > 1 && splitPath.last().isEmpty())
+ splitPath.removeLast();
+ break;
+ case ImportType::File:
+ case ImportType::QrcFile:
+ splitPath = QrcParser::normalizedQrcFilePath(path).split(QLatin1Char('/'));
+ break;
+ case ImportType::QrcDirectory:
+ splitPath = QrcParser::normalizedQrcDirectoryPath(path).split(QLatin1Char('/'));
+ if (splitPath.length() > 1 && splitPath.last().isEmpty())
+ splitPath.removeLast();
+ break;
+ case ImportType::Invalid:
+ case ImportType::UnknownFile:
+ splitPath = path.split(QLatin1Char('/'));
+ break;
+ }
+}
+
+void ImportKey::addToHash(QCryptographicHash &hash) const
+{
+ hash.addData(reinterpret_cast<const char *>(&type), sizeof(type));
+ hash.addData(reinterpret_cast<const char *>(&majorVersion), sizeof(majorVersion));
+ hash.addData(reinterpret_cast<const char *>(&minorVersion), sizeof(minorVersion));
+ foreach (const QString &s, splitPath) {
+ hash.addData("/", 1);
+ hash.addData(reinterpret_cast<const char *>(s.constData()), sizeof(QChar) * s.size());
+ }
+ hash.addData("/", 1);
+}
+
+ImportKey ImportKey::flatKey() const {
+ switch (type) {
+ case ImportType::Invalid:
+ return *this;
+ case ImportType::ImplicitDirectory:
+ case ImportType::Library:
+ case ImportType::File:
+ case ImportType::Directory:
+ case ImportType::QrcFile:
+ case ImportType::QrcDirectory:
+ case ImportType::UnknownFile:
+ break;
+ }
+ QStringList flatPath = splitPath;
+ int i = 0;
+ while (i < flatPath.size()) {
+ if (flatPath.at(i).startsWith(QLatin1Char('+')))
+ flatPath.removeAt(i);
+ else
+ ++i;
+ }
+ if (flatPath.size() == splitPath.size())
+ return *this;
+ ImportKey res = *this;
+ res.splitPath = flatPath;
+ return res;
+}
+
+QString ImportKey::path() const
+{
+ QString res = splitPath.join(QString::fromLatin1("/"));
+ if (res.isEmpty() && !splitPath.isEmpty())
+ return QLatin1String("/");
+ return res;
+}
+
+ImportMatchStrength ImportKey::matchImport(const ImportKey &o, const ViewerContext &vContext) const
+{
+ if (majorVersion != o.majorVersion || minorVersion > o.minorVersion)
+ return ImportMatchStrength();
+ bool dirToFile = false;
+ switch (o.type) {
+ case ImportType::Invalid:
+ return ImportMatchStrength();
+ case ImportType::ImplicitDirectory:
+ case ImportType::Directory:
+ switch (type) {
+ case ImportType::File:
+ case ImportType::UnknownFile:
+ dirToFile = true;
+ break;
+ case ImportType::ImplicitDirectory:
+ case ImportType::Directory:
+ break;
+ default:
+ return ImportMatchStrength();
+ }
+ break;
+ case ImportType::Library:
+ if (type != ImportType::Library)
+ return ImportMatchStrength();
+ break;
+ case ImportType::QrcDirectory:
+ switch (type) {
+ case ImportType::QrcFile:
+ dirToFile = true;
+ break;
+ case ImportType::QrcDirectory:
+ break;
+ default:
+ return ImportMatchStrength();
+ }
+ break;
+ case ImportType::QrcFile:
+ if (type != ImportType::QrcFile)
+ return ImportMatchStrength();
+ case ImportType::UnknownFile:
+ case ImportType::File:
+ switch (type) {
+ case ImportType::UnknownFile:
+ case ImportType::File:
+ break;
+ default:
+ return ImportMatchStrength();
+ }
+ break;
+ }
+
+ QList<int> res;
+ int iPath1 = 0;
+ int lenPath1 = splitPath.size();
+ int iPath2 = 0;
+ int lenPath2 = o.splitPath.size();
+ if (dirToFile)
+ --lenPath1;
+ int iSelector = 0;
+ int nSelectors = vContext.selectors.size();
+ while (iPath1 < lenPath1) {
+ if (lenPath2 - iPath2 > lenPath1 - iPath1)
+ return ImportMatchStrength();
+ QString p1 = splitPath.at(iPath1);
+ if (iPath2 < lenPath2) {
+ QString p2 = splitPath.at(iPath2);
+ if (p1 == p2) {
+ ++iPath1;
+ ++iPath2;
+ continue;
+ }
+ }
+ if (!p1.startsWith(QLatin1Char('+')))
+ return QList<int>();
+ QStringRef selectorAtt(&p1, 1, p1.size()-1);
+ while (iSelector < nSelectors) {
+ if (selectorAtt == vContext.selectors.at(iSelector))
+ break;
+ ++iSelector;
+ }
+ if (iSelector == nSelectors)
+ return QList<int>();
+ res << (nSelectors - iSelector);
+ ++iSelector;
+ ++iPath1;
+ }
+ if (iPath2 != lenPath2)
+ return QList<int>();
+ if (res.isEmpty())
+ res << 0;
+ return ImportMatchStrength(res);
+}
+
+int ImportKey::compare(const ImportKey &other) const
+{
+ ImportKind::Enum k1 = toImportKind(type);
+ ImportKind::Enum k2 = toImportKind(other.type);
+ if (k1 < k2)
+ return -1;
+ if (k1 > k2)
+ return 1;
+ int len1 = splitPath.size();
+ int len2 = other.splitPath.size();
+ int len = ((len1 < len2) ? len1 : len2);
+ for (int i = 0; i < len; ++ i) {
+ QString v1 = splitPath.at(i);
+ QString v2 = other.splitPath.at(i);
+ if (v1 < v2)
+ return -1;
+ if (v2 > v1)
+ return 1;
+ }
+ if (len1 < len2)
+ return -1;
+ if (len1 > len2)
+ return 1;
+ if (majorVersion < other.majorVersion)
+ return -1;
+ if (majorVersion > other.majorVersion)
+ return 1;
+ if (minorVersion < other.minorVersion)
+ return -1;
+ if (minorVersion > other.minorVersion)
+ return 1;
+ if (type < other.type)
+ return -1;
+ if (type > other.type)
+ return 1;
+ return 0;
+}
+
+bool ImportKey::isDirectoryLike() const
+{
+ switch (type) {
+ case ImportType::Directory:
+ case ImportType::ImplicitDirectory:
+ case ImportType::QrcDirectory:
+ return true;
+ default:
+ return false;
+ }
+}
+
+ImportKey::DirCompareInfo ImportKey::compareDir(const ImportKey &superDir) const
+{
+ // assumes dir/+selectors/file (i.e. no directories inside selectors)
+ switch (superDir.type) {
+ case ImportType::UnknownFile:
+ case ImportType::File:
+ case ImportType::Directory:
+ case ImportType::ImplicitDirectory:
+ if (type != ImportType::File && type != ImportType::ImplicitDirectory
+ && type != ImportType::Directory && type != ImportType::UnknownFile)
+ return Incompatible;
+ break;
+ case ImportType::QrcDirectory:
+ case ImportType::QrcFile:
+ if (type != ImportType::QrcDirectory && type != ImportType::QrcFile)
+ return Incompatible;
+ break;
+ case ImportType::Invalid:
+ case ImportType::Library:
+ return Incompatible;
+ }
+ bool isDir1 = isDirectoryLike();
+ bool isDir2 = superDir.isDirectoryLike();
+ int len1 = splitPath.size();
+ int len2 = superDir.splitPath.size();
+ if (isDir1 && len1 > 0)
+ --len1;
+ if (isDir2 && len2 > 0)
+ --len2;
+
+ int i1 = 0;
+ int i2 = 0;
+ while (i1 < len1 && i2 < len2) {
+ QString p1 = splitPath.at(i1);
+ QString p2 = superDir.splitPath.at(i2);
+ if (p1 == p2) {
+ ++i1;
+ ++i2;
+ continue;
+ }
+ if (p1.startsWith(QLatin1Char('+'))) {
+ if (p2.startsWith(QLatin1Char('+')))
+ return SameDir;
+ return SecondInFirst;
+ }
+ if (p2.startsWith(QLatin1Char('+')))
+ return FirstInSecond;
+ return Different;
+ }
+ if (i1 < len1) {
+ if (splitPath.at(i1).startsWith(QLatin1Char('+')))
+ return SameDir;
+ return SecondInFirst;
+ }
+ if (i2 < len2) {
+ if (superDir.splitPath.at(i2).startsWith(QLatin1Char('+')))
+ return SameDir;
+ return SecondInFirst;
+ }
+ return SameDir;
+}
+
+QString ImportKey::toString() const
+{
+ QString res;
+ switch (type) {
+ case ImportType::UnknownFile:
+ case ImportType::File:
+ res = path();
+ break;
+ case ImportType::Directory:
+ case ImportType::ImplicitDirectory:
+ res = path() + QLatin1Char('/');
+ break;
+ case ImportType::QrcDirectory:
+ res = QLatin1String("qrc:") + path() + QLatin1Char('/');
+ break;
+ case ImportType::QrcFile:
+ res = QLatin1String("qrc:") + path() + QLatin1Char('/');
+ break;
+ case ImportType::Invalid:
+ res = path();
+ break;
+ case ImportType::Library:
+ res = splitPath.join(QLatin1String("."));
+ break;
+ }
+
+ if (majorVersion != LanguageUtils::ComponentVersion::NoVersion
+ || minorVersion != LanguageUtils::ComponentVersion::NoVersion)
+ return res + QLatin1Char(' ') + QString::number(majorVersion)
+ + QLatin1Char('.') + QString::number(minorVersion);
+
+ return res;
+}
+
+uint qHash(const ImportKey &info)
+{
+ uint res = ::qHash(info.type) ^
+ ::qHash(info.majorVersion) ^ ::qHash(info.minorVersion);
+ foreach (const QString &s, info.splitPath)
+ res = res ^ ::qHash(s);
+ return res;
+}
+
+bool operator==(const ImportKey &i1, const ImportKey &i2)
+{
+ return i1.type == i2.type
+ && i1.splitPath == i2.splitPath
+ && i1.majorVersion == i2.majorVersion
+ && i1.minorVersion == i2.minorVersion;
+}
+
+bool operator !=(const ImportKey &i1, const ImportKey &i2)
+{
+ return ! (i1 == i2);
+}
+
+bool operator <(const ImportKey &i1, const ImportKey &i2)
+{
+ return i1.compare(i2) < 0;
+}
+
+Export::Export()
+ : intrinsic(false)
+{ }
+
+Export::Export(ImportKey exportName, QString pathRequired, bool intrinsic)
+ : exportName(exportName), pathRequired(pathRequired), intrinsic(intrinsic)
+{ }
+
+bool Export::visibleInVContext(const ViewerContext &vContext) const
+{
+ return pathRequired.isEmpty() || vContext.paths.contains(pathRequired);
+}
+
+bool operator ==(const Export &i1, const Export &i2)
+{
+ return i1.exportName == i2.exportName
+ && i1.pathRequired == i2.pathRequired
+ && i1.intrinsic == i2.intrinsic;
+}
+
+bool operator !=(const Export &i1, const Export &i2)
+{
+ return !(i1 == i2);
+}
+
+CoreImport::CoreImport() : language(Language::Qml) { }
+
+CoreImport::CoreImport(const QString &importId, const QList<Export> &possibleExports,
+ Language::Enum language, const QByteArray &fingerprint)
+ : importId(importId), possibleExports(possibleExports), language(language),
+ fingerprint(fingerprint)
+{ }
+
+bool CoreImport::valid() {
+ return !fingerprint.isEmpty();
+}
+
+QByteArray DependencyInfo::calculateFingerprint(const ImportDependencies &deps)
+{
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ rootImport.addToHash(hash);
+ QStringList coreImports = allCoreImports.toList();
+ coreImports.sort();
+ foreach (const QString importId, coreImports) {
+ hash.addData(reinterpret_cast<const char*>(importId.constData()), importId.size() * sizeof(QChar));
+ QByteArray coreImportFingerprint = deps.coreImport(importId).fingerprint;
+ hash.addData(coreImportFingerprint);
+ }
+ hash.addData("/", 1);
+ QList<ImportKey> imports(allImports.toList());
+ std::sort(imports.begin(), imports.end());
+ foreach (const ImportKey &k, imports)
+ k.addToHash(hash);
+ return hash.result();
+}
+
+MatchedImport::MatchedImport()
+{ }
+
+MatchedImport::MatchedImport(ImportMatchStrength matchStrength, ImportKey importKey,
+ const QString &coreImportId)
+ : matchStrength(matchStrength), importKey(importKey), coreImportId(coreImportId)
+{ }
+
+int MatchedImport::compare(const MatchedImport &o) const {
+ int res = matchStrength.compareMatch(o.matchStrength);
+ if (res != 0)
+ return res;
+ res = importKey.compare(o.importKey);
+ if (res != 0)
+ return res;
+ if (coreImportId < o.coreImportId)
+ return -1;
+ if (coreImportId > o.coreImportId)
+ return 1;
+ return 0;
+}
+
+bool operator ==(const MatchedImport &m1, const MatchedImport &m2)
+{
+ return m1.compare(m2) == 0;
+}
+
+bool operator !=(const MatchedImport &m1, const MatchedImport &m2)
+{
+ return m1.compare(m2) != 0;
+}
+
+bool operator <(const MatchedImport &m1, const MatchedImport &m2)
+{
+ return m1.compare(m2) < 0;
+}
+
+ImportDependencies::ImportDependencies()
+{ }
+
+ImportDependencies::~ImportDependencies()
+{ }
+
+void ImportDependencies::filter(const ViewerContext &vContext)
+{
+ QMap<QString, CoreImport> newCoreImports;
+ QMap<ImportKey, QStringList> newImportCache;
+ QMapIterator<QString, CoreImport> j(m_coreImports);
+ bool hasChanges = false;
+ while (j.hasNext()) {
+ j.next();
+ const CoreImport &cImport = j.value();
+ if (vContext.languageIsCompatible(cImport.language)) {
+ QList<Export> newExports;
+ foreach (const Export &e, cImport.possibleExports) {
+ if (e.visibleInVContext(vContext)) {
+ newExports.append(e);
+ QStringList &candidateImports = newImportCache[e.exportName];
+ if (!candidateImports.contains(cImport.importId))
+ candidateImports.append(cImport.importId);
+ }
+ }
+ if (newExports.size() == cImport.possibleExports.size()) {
+ newCoreImports.insert(cImport.importId, cImport);
+ } else if (newExports.length() > 0) {
+ CoreImport newCImport = cImport;
+ newCImport.possibleExports = newExports;
+ newCoreImports.insert(newCImport.importId, newCImport);
+ hasChanges = true;
+ } else {
+ hasChanges = true;
+ }
+ } else {
+ hasChanges = true;
+ }
+ }
+ if (!hasChanges)
+ return;
+ m_coreImports = newCoreImports;
+ m_importCache = newImportCache;
+}
+
+CoreImport ImportDependencies::coreImport(const QString &importId) const
+{
+ return m_coreImports.value(importId);
+}
+
+void ImportDependencies::iterateOnCandidateImports(
+ const ImportKey &key, const ViewerContext &vContext,
+ Utils::function<bool (const ImportMatchStrength &,const Export &,const CoreImport &)>
+ const &iterF) const
+{
+ switch (key.type) {
+ case ImportType::Directory:
+ case ImportType::QrcDirectory:
+ case ImportType::ImplicitDirectory:
+ break;
+ default:
+ {
+ QStringList imp = m_importCache.value(key.flatKey());
+ foreach (const QString &cImportName, imp) {
+ CoreImport cImport = coreImport(cImportName);
+ if (vContext.languageIsCompatible(cImport.language)) {
+ foreach (const Export e, cImport.possibleExports) {
+ if (e.visibleInVContext(vContext)) {
+ ImportMatchStrength m = e.exportName.matchImport(key, vContext);
+ if (m.hasMatch()) {
+ if (!iterF(m, e, cImport))
+ return;
+ }
+ }
+ }
+ }
+ }
+ return;
+ }
+ }
+ QMap<ImportKey, QStringList>::const_iterator lb = m_importCache.lowerBound(key.flatKey());
+ QMap<ImportKey, QStringList>::const_iterator end = m_importCache.constEnd();
+ while (lb != end) {
+ ImportKey::DirCompareInfo c = key.compareDir(lb.key());
+ if (c == ImportKey::SameDir) {
+ foreach (const QString &cImportName, lb.value()) {
+ CoreImport cImport = coreImport(cImportName);
+ if (vContext.languageIsCompatible(cImport.language)) {
+ foreach (const Export e, cImport.possibleExports) {
+ if (e.visibleInVContext(vContext)) {
+ ImportMatchStrength m = e.exportName.matchImport(key, vContext);
+ if (m.hasMatch()) {
+ if (!iterF(m, e, cImport))
+ return;
+ }
+ }
+ }
+ }
+ }
+ } else if (c != ImportKey::SecondInFirst) {
+ break;
+ }
+ ++lb;
+ }
+}
+
+class CollectCandidateImports
+{
+public:
+ ImportDependencies::ImportElements &res;
+
+ CollectCandidateImports(ImportDependencies::ImportElements & res)
+ : res(res)
+ { }
+
+ bool operator ()(const ImportMatchStrength &m, const Export &e, const CoreImport &cI) const
+ {
+ ImportKey flatName = e.exportName.flatKey();
+ res[flatName].append(MatchedImport(m, e.exportName, cI.importId));
+ return true;
+ }
+};
+
+ImportDependencies::ImportElements ImportDependencies::candidateImports(
+ const ImportKey &key,
+ const ViewerContext &vContext) const
+{
+ ImportDependencies::ImportElements res;
+ CollectCandidateImports collector(res);
+ iterateOnCandidateImports(key, vContext, collector);
+ typedef QMap<ImportKey, QList<MatchedImport> >::iterator iter_t;
+ iter_t i = res.begin();
+ iter_t end = res.end();
+ while (i != end) {
+ std::sort(i.value().begin(), i.value().end());
+ ++i;
+ }
+ return res;
+}
+
+QList<DependencyInfo::ConstPtr> ImportDependencies::createDependencyInfos(
+ const ImportKey &mainDoc, const ViewerContext &vContext) const
+{
+ Q_UNUSED(mainDoc);
+ Q_UNUSED(vContext);
+ QList<DependencyInfo::ConstPtr> res;
+ QTC_CHECK(false);
+ return res;
+}
+
+void ImportDependencies::addCoreImport(const CoreImport &import)
+{
+ CoreImport newImport = import;
+ if (m_coreImports.contains(import.importId)) {
+ CoreImport oldVal = m_coreImports.value(import.importId);
+ foreach (const Export &e, oldVal.possibleExports) {
+ if (e.intrinsic)
+ removeImportCacheEntry(e.exportName, import.importId);
+ else
+ newImport.possibleExports.append(e);
+ }
+ }
+ foreach (const Export &e, import.possibleExports)
+ m_importCache[e.exportName].append(import.importId);
+ m_coreImports.insert(newImport.importId, newImport);
+ if (debugImportDependencies) {
+ QDebug dbg(qDebug());
+ dbg << "added import "<< newImport.importId << " for";
+ foreach (const Export &e, newImport.possibleExports)
+ dbg << " " << e.exportName.toString() << "(" << e.pathRequired << ")";
+ }
+}
+
+void ImportDependencies::removeCoreImport(const QString &importId)
+{
+ if (!m_coreImports.contains(importId)) {
+ qDebug() << "missing importId in removeCoreImport(" << importId << ")";
+ return;
+ }
+ CoreImport &cImport = m_coreImports[importId];
+ QList<Export> newExports;
+ foreach (const Export &e, cImport.possibleExports)
+ if (e.intrinsic)
+ removeImportCacheEntry(e.exportName, importId);
+ else
+ newExports.append(e);
+ if (newExports.size()>0)
+ cImport.possibleExports = newExports;
+ else
+ m_coreImports.remove(importId);
+
+ if (debugImportDependencies)
+ qDebug() << "removed import with id:"<< importId;
+}
+
+void ImportDependencies::removeImportCacheEntry(const ImportKey &importKey, const QString &importId)
+{
+ QStringList &cImp = m_importCache[importKey];
+ if (!cImp.removeOne(importId)) {
+ qDebug() << "missing possibleExport backpointer for " << importKey.toString() << " to "
+ << importId;
+ }
+ if (cImp.isEmpty())
+ m_importCache.remove(importKey);
+}
+
+void ImportDependencies::addExport(const QString &importId, const ImportKey &importKey,
+ const QString &requiredPath)
+{
+ if (!m_coreImports.contains(importId)) {
+ CoreImport newImport(importId);
+ newImport.language = Language::Unknown;
+ newImport.possibleExports.append(Export(importKey, requiredPath, false));
+ m_coreImports.insert(newImport.importId, newImport);
+ m_importCache[importKey].append(importId);
+ return;
+ }
+ CoreImport &importValue = m_coreImports[importId];
+ importValue.possibleExports.append(Export(importKey, requiredPath, false));
+ m_importCache[importKey].append(importId);
+ if (debugImportDependencies)
+ qDebug() << "added export "<< importKey.toString() << " for id " <<importId
+ << " (" << requiredPath << ")";
+}
+
+void ImportDependencies::removeExport(const QString &importId, const ImportKey &importKey,
+ const QString &requiredPath)
+{
+ if (!m_coreImports.contains(importId)) {
+ qDebug() << "non existing core import for removeExport(" << importId << ", "
+ << importKey.toString() << ")";
+ } else {
+ CoreImport &importValue = m_coreImports[importId];
+ if (!importValue.possibleExports.removeOne(Export(importKey, requiredPath, false))) {
+ qDebug() << "non existing export for removeExport(" << importId << ", "
+ << importKey.toString() << ")";
+ }
+ if (importValue.possibleExports.isEmpty() && importValue.fingerprint.isEmpty())
+ m_coreImports.remove(importId);
+ }
+ if (!m_importCache.contains(importKey)) {
+ qDebug() << "missing possibleExport for " << importKey.toString() << " when removing export of "
+ << importId;
+ } else {
+ removeImportCacheEntry(importKey, importId);
+ }
+ if (debugImportDependencies)
+ qDebug() << "removed export "<< importKey.toString() << " for id " << importId
+ << " (" << requiredPath << ")";
+}
+
+void ImportDependencies::iterateOnCoreImports(
+ const ViewerContext &vContext,
+ Utils::function<bool (const CoreImport &)> const &iterF) const
+{
+ QMapIterator<QString, CoreImport> i(m_coreImports);
+ while (i.hasNext()) {
+ i.next();
+ if (vContext.languageIsCompatible(i.value().language))
+ iterF(i.value()); // check also that at least one export is visible?
+ }
+}
+
+void ImportDependencies::iterateOnLibraryImports(
+ const ViewerContext &vContext,
+ Utils::function<bool (const ImportMatchStrength &,
+ const Export &,
+ const CoreImport &)> const &iterF) const
+{
+ typedef QMap<ImportKey, QStringList>::const_iterator iter_t;
+ ImportKey firstLib;
+ firstLib.type = ImportType::Library;
+ iter_t i = m_importCache.lowerBound(firstLib);
+ iter_t end = m_importCache.constEnd();
+ while (i != end && i.key().type == ImportType::Library) {
+ if (debugImportDependencies)
+ qDebug() << "libloop:" << i.key().toString() << i.value();
+ foreach (const QString &cImportName, i.value()) {
+ CoreImport cImport = coreImport(cImportName);
+ if (vContext.languageIsCompatible(cImport.language)) {
+ foreach (const Export &e, cImport.possibleExports) {
+ if (e.visibleInVContext(vContext) && e.exportName.type == ImportType::Library) {
+ ImportMatchStrength m = e.exportName.matchImport(i.key(), vContext);
+ if (m.hasMatch()) {
+ if (debugImportDependencies)
+ qDebug() << "import iterate:" << e.exportName.toString()
+ << " (" << e.pathRequired << "), id:" << cImport.importId;
+ if (!iterF(m, e, cImport))
+ return;
+ }
+ }
+ }
+ }
+ }
+ ++i;
+ }
+}
+
+void ImportDependencies::iterateOnSubImports(
+ const ImportKey &baseKey,
+ const ViewerContext &vContext,
+ Utils::function<bool (const ImportMatchStrength &,
+ const Export &,
+ const CoreImport &)> const &iterF) const
+{
+ typedef QMap<ImportKey, QStringList>::const_iterator iter_t;
+ iter_t i = m_importCache.lowerBound(baseKey);
+ iter_t end = m_importCache.constEnd();
+ while (i != end) {
+ ImportKey::DirCompareInfo c = baseKey.compareDir(i.key());
+ if (c != ImportKey::SameDir && c != ImportKey::SecondInFirst)
+ break;
+ foreach (const QString &cImportName, i.value()) {
+ CoreImport cImport = coreImport(cImportName);
+ if (vContext.languageIsCompatible(cImport.language)) {
+ foreach (const Export &e, cImport.possibleExports) {
+ if (e.visibleInVContext(vContext)) {
+ ImportMatchStrength m = e.exportName.matchImport(i.key(), vContext);
+ if (m.hasMatch()) {
+ if (!iterF(m, e, cImport))
+ return;
+ }
+ }
+ }
+ }
+ }
+ ++i;
+ }
+}
+
+class CollectImportKeys {
+public:
+ QSet<ImportKey> &imports;
+ CollectImportKeys(QSet<ImportKey> &imports)
+ : imports(imports)
+ { }
+ bool operator()(const ImportMatchStrength &m,
+ const Export &e,
+ const CoreImport &cI) const
+ {
+ Q_UNUSED(m);
+ Q_UNUSED(cI);
+ imports.insert(e.exportName.flatKey());
+ return true;
+ }
+};
+
+QSet<ImportKey> ImportDependencies::libraryImports(const ViewerContext &viewContext) const
+{
+ QSet<ImportKey> res;
+ CollectImportKeys importCollector(res);
+ iterateOnLibraryImports(viewContext, importCollector);
+ return res;
+}
+
+QSet<ImportKey> ImportDependencies::subdirImports(
+ const ImportKey &baseKey, const ViewerContext &viewContext) const
+{
+ QSet<ImportKey> res;
+ CollectImportKeys importCollector(res);
+ iterateOnSubImports(baseKey, viewContext, importCollector);
+ return res;
+}
+
+} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsimportdependencies.h b/src/libs/qmljs/qmljsimportdependencies.h
new file mode 100644
index 0000000000..fc84f0794f
--- /dev/null
+++ b/src/libs/qmljs/qmljsimportdependencies.h
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLJSIMPORTCACHE_H
+#define QMLJSIMPORTCACHE_H
+
+#include "qmljsviewercontext.h"
+
+#include <languageutils/componentversion.h>
+#include <utils/qtcoverride.h>
+#include <utils/function.h>
+
+#include <QObject>
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include <QMap>
+#include <QSet>
+#include <QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+class QCryptographicHash;
+QT_END_NAMESPACE
+
+namespace QmlJS {
+class ImportInfo;
+namespace Internal {
+class ImportDependenciesPrivate;
+}
+class ImportDependencies;
+
+// match strenght wrt to the selectors of a ViewerContext
+// this is valid only within a ViewerContext
+class QMLJS_EXPORT ImportMatchStrength
+{
+public:
+ explicit ImportMatchStrength() {}
+ ImportMatchStrength(QList<int> match);
+
+ int compareMatch(const ImportMatchStrength &o) const;
+
+ bool hasNoMatch();
+
+ bool hasMatch();
+private:
+ friend bool operator ==(const ImportMatchStrength &m1, const ImportMatchStrength &m2);
+ QList<int> m_match;
+};
+bool operator ==(const ImportMatchStrength &m1, const ImportMatchStrength &m2);
+bool operator !=(const ImportMatchStrength &m1, const ImportMatchStrength &m2);
+bool operator <(const ImportMatchStrength &m1, const ImportMatchStrength &m2);
+
+/*!
+ * \brief The ImportKey class represent an import (or export), and can be used as hash key
+ *
+ * This represent only what is to be imported, *not* how (i.e. no as clause)
+ *
+ * Order is defined so that files in the same directory are contiguous, and different
+ * ImportKind are separated.
+ * This is used to efficiently iterate just on library imports, or just on a directory
+ * while preserving space.
+ */
+class QMLJS_EXPORT ImportKey
+{
+public:
+ enum DirCompareInfo {
+ SameDir,
+ FirstInSecond,
+ SecondInFirst,
+ Different,
+ Incompatible
+ };
+
+ explicit ImportKey();
+ explicit ImportKey(const ImportInfo &info);
+ ImportKey(ImportType::Enum type, const QString &path,
+ int majorVersion = LanguageUtils::ComponentVersion::NoVersion,
+ int minorVersion = LanguageUtils::ComponentVersion::NoVersion);
+
+ ImportType::Enum type;
+ QStringList splitPath;
+ int majorVersion;
+ int minorVersion;
+
+ QString path() const;
+
+ void addToHash(QCryptographicHash &hash) const;
+ ImportKey flatKey() const;
+
+ // wrap QList in a special type?
+ ImportMatchStrength matchImport(const ImportKey &o, const ViewerContext &vContext) const;
+ int compare(const ImportKey &other) const;
+ bool isDirectoryLike() const;
+ DirCompareInfo compareDir(const ImportKey &other) const;
+ QString toString() const;
+};
+
+uint qHash(const ImportKey &info);
+bool operator ==(const ImportKey &i1, const ImportKey &i2);
+bool operator !=(const ImportKey &i1, const ImportKey &i2);
+bool operator <(const ImportKey &i1, const ImportKey &i2);
+
+class QMLJS_EXPORT Export
+{
+public:
+ Export();
+ Export(ImportKey exportName, QString pathRequired, bool intrinsic = false);
+ ImportKey exportName;
+ QString pathRequired;
+ bool intrinsic;
+ bool visibleInVContext(const ViewerContext &vContext) const;
+};
+bool operator ==(const Export &i1, const Export &i2);
+bool operator !=(const Export &i1, const Export &i2);
+
+class QMLJS_EXPORT CoreImport
+{
+public:
+ CoreImport();
+ CoreImport(const QString &importId, const QList<Export> &possibleExports = QList<Export>(),
+ Language::Enum language = Language::Qml, const QByteArray &fingerprint = QByteArray());
+ QString importId;
+ QList<Export> possibleExports;
+ Language::Enum language;
+ QByteArray fingerprint;
+ bool valid();
+};
+
+class QMLJS_EXPORT DependencyInfo
+{
+public:
+ typedef QSharedPointer<const DependencyInfo> ConstPtr;
+ typedef QSharedPointer<DependencyInfo> Ptr;
+
+ QByteArray calculateFingerprint(const ImportDependencies &deps);
+
+ ImportKey rootImport;
+ QSet<QString> allCoreImports;
+ QSet<ImportKey> allImports;
+ QByteArray fingerprint;
+};
+
+class QMLJS_EXPORT MatchedImport
+{
+public:
+ MatchedImport();
+ MatchedImport(ImportMatchStrength matchStrength, ImportKey importKey,
+ const QString &coreImportId);
+
+ ImportMatchStrength matchStrength;
+ ImportKey importKey;
+ QString coreImportId;
+ int compare(const MatchedImport &o) const;
+};
+bool operator ==(const MatchedImport &m1, const MatchedImport &m2);
+bool operator !=(const MatchedImport &m1, const MatchedImport &m2);
+bool operator <(const MatchedImport &m1, const MatchedImport &m2);
+
+class QMLJS_EXPORT ImportDependencies
+{
+public:
+ typedef QMap<ImportKey, QList<MatchedImport> > ImportElements;
+
+ explicit ImportDependencies();
+ ~ImportDependencies();
+
+ void filter(const ViewerContext &vContext);
+
+ CoreImport coreImport(const QString &importId) const;
+ void iterateOnCandidateImports(const ImportKey &key, const ViewerContext &vContext,
+ Utils::function<bool(const ImportMatchStrength &,
+ const Export &,
+ const CoreImport &)> const &iterF) const;
+ ImportElements candidateImports(const ImportKey &key, const ViewerContext &vContext) const;
+
+ QList<DependencyInfo::ConstPtr> createDependencyInfos(const ImportKey &mainDoc,
+ const ViewerContext &vContext) const;
+
+ void addCoreImport(const CoreImport &import);
+ void removeCoreImport(const QString &importId);
+
+ void addExport(const QString &importId, const ImportKey &importKey,
+ const QString &requiredPath);
+ void removeExport(const QString &importId, const ImportKey &importKey,
+ const QString &requiredPath);
+
+ void iterateOnCoreImports(const ViewerContext &vContext,
+ Utils::function<bool(const CoreImport &)> const &iterF) const;
+ void iterateOnLibraryImports(const ViewerContext &vContext,
+ Utils::function<bool(const ImportMatchStrength &,
+ const Export &,
+ const CoreImport &)> const &iterF) const;
+ void iterateOnSubImports(const ImportKey &baseKey, const ViewerContext &vContext,
+ Utils::function<bool(const ImportMatchStrength &,
+ const Export &,
+ const CoreImport &)> const &iterF) const;
+
+ QSet<ImportKey> libraryImports(const ViewerContext &viewContext) const;
+ QSet<ImportKey> subdirImports(const ImportKey &baseKey, const ViewerContext &viewContext) const;
+private:
+ void removeImportCacheEntry(const ImportKey &importKey, const QString &importId);
+
+ QMap<ImportKey, QStringList> m_importCache;
+ QMap<QString, CoreImport> m_coreImports;
+};
+
+} // namespace QmlJS
+
+#endif // QMLJSIMPORTCACHE_H
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index cf8d22a384..ef5577a90c 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -33,6 +33,7 @@
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljs_global.h>
#include <qmljs/qmljsconstants.h>
+#include <qmljs/qmljsimportdependencies.h>
#include <QFileInfoList>
#include <QList>
@@ -912,6 +913,7 @@ public:
// const!
ObjectValue *object;
ImportInfo info;
+ DependencyInfo::ConstPtr deps;
// uri imports: path to library, else empty
QString libraryPath;
// whether the import succeeded
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index 950d238f1b..01100454bc 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -34,7 +34,8 @@
#include "qmljsbind.h"
#include "qmljsutils.h"
#include "qmljsmodelmanagerinterface.h"
-#include <qmljs/qmljsqrcparser.h>
+#include "qmljsqrcparser.h"
+#include "qmljsconstants.h"
#include <QDir>
#include <QDebug>
@@ -83,6 +84,7 @@ public:
ValueOwner *valueOwner;
QStringList importPaths;
LibraryInfo builtins;
+ ViewerContext vContext;
QHash<ImportCacheKey, Import> importCache;
@@ -131,13 +133,14 @@ public:
\l{QmlJSEditor::SemanticInfo} of a \l{QmlJSEditor::QmlJSTextEditorWidget}.
*/
-Link::Link(const Snapshot &snapshot, const QStringList &importPaths, const LibraryInfo &builtins)
+Link::Link(const Snapshot &snapshot, const ViewerContext &vContext, const LibraryInfo &builtins)
: d(new LinkPrivate)
{
d->valueOwner = new ValueOwner;
d->snapshot = snapshot;
- d->importPaths = importPaths;
+ d->importPaths = vContext.paths;
d->builtins = builtins;
+ d->vContext = vContext;
d->diagnosticMessages = 0;
d->allDiagnosticMessages = 0;
@@ -173,14 +176,14 @@ Link::Link(const Snapshot &snapshot, const QStringList &importPaths, const Libra
ContextPtr Link::operator()(QHash<QString, QList<DiagnosticMessage> > *messages)
{
d->allDiagnosticMessages = messages;
- return Context::create(d->snapshot, d->valueOwner, d->linkImports());
+ return Context::create(d->snapshot, d->valueOwner, d->linkImports(), d->vContext);
}
ContextPtr Link::operator()(const Document::Ptr &doc, QList<DiagnosticMessage> *messages)
{
d->document = doc;
d->diagnosticMessages = messages;
- return Context::create(d->snapshot, d->valueOwner, d->linkImports());
+ return Context::create(d->snapshot, d->valueOwner, d->linkImports(), d->vContext);
}
Link::~Link()
diff --git a/src/libs/qmljs/qmljslink.h b/src/libs/qmljs/qmljslink.h
index 7d7875e421..dbb2904e0d 100644
--- a/src/libs/qmljs/qmljslink.h
+++ b/src/libs/qmljs/qmljslink.h
@@ -48,7 +48,7 @@ class QMLJS_EXPORT Link
Q_DECLARE_TR_FUNCTIONS(QmlJS::Link)
public:
- Link(const Snapshot &snapshot, const QStringList &importPaths, const LibraryInfo &builtins);
+ Link(const Snapshot &snapshot, const ViewerContext &vContext, const LibraryInfo &builtins);
// Link all documents in snapshot, collecting all diagnostic messages (if messages != 0)
ContextPtr operator()(QHash<QString, QList<DiagnosticMessage> > *messages = 0);
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index cdcaef362d..45a7c87991 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -33,7 +33,8 @@
#include "qmljs_global.h"
#include "qmljsdocument.h"
#include "qmljsbundle.h"
-
+#include "qmljsconstants.h"
+#include "qmljsviewercontext.h"
#include <utils/environment.h>
#include <QObject>
@@ -175,6 +176,12 @@ public:
virtual LibraryInfo builtins(const Document::Ptr &doc) const = 0;
+ virtual ViewerContext completeVContext(const ViewerContext &vCtx,
+ const Document::Ptr &doc = Document::Ptr(0)) const = 0;
+ virtual ViewerContext defaultVContext(bool autoComplete = true,
+ const Document::Ptr &doc = Document::Ptr(0)) const = 0;
+ virtual void setDefaultVContext(const ViewerContext &vContext) = 0;
+
// Blocks until all parsing threads are done. Used for testing.
virtual void joinAllThreads() = 0;
diff --git a/src/libs/qmljs/qmljstypedescriptionreader.cpp b/src/libs/qmljs/qmljstypedescriptionreader.cpp
index 6cfb5124dd..695ef5b5c9 100644
--- a/src/libs/qmljs/qmljstypedescriptionreader.cpp
+++ b/src/libs/qmljs/qmljstypedescriptionreader.cpp
@@ -223,6 +223,7 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
// ### add implicit export into the package of c++ types
fmo->addExport(fmo->className(), QmlJS::CppQmlTypes::cppPackage, ComponentVersion());
+ fmo->updateFingerprint();
_objects->insert(fmo->className(), fmo);
}
diff --git a/src/libs/qmljs/qmljsviewercontext.cpp b/src/libs/qmljs/qmljsviewercontext.cpp
new file mode 100644
index 0000000000..06f5dd1806
--- /dev/null
+++ b/src/libs/qmljs/qmljsviewercontext.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmljsviewercontext.h"
+
+namespace QmlJS {
+/*!
+ \class QmlJS::ViewerContext
+ \brief The ViewerContext class encapsulate selector and paths for a given viewer.
+
+ Using a a different viewer context can emulate (the pure qml part) of a device.
+ This allows checking how a given qml would be interpreted on another platform/viewer.
+
+ Screen information will also most likely need to be added here.
+*/
+ViewerContext::ViewerContext()
+ : language(Language::Qml), flags(AddAllPaths)
+{ }
+
+ViewerContext::ViewerContext(QStringList selectors, QStringList paths,
+ QmlJS::Language::Enum language,
+ QmlJS::ViewerContext::Flags flags)
+ : selectors(selectors), paths(paths), language(language),
+ flags(flags)
+{ }
+
+
+/*
+ which languages might be imported in this context
+ */
+bool ViewerContext::languageIsCompatible(Language::Enum l) const
+{
+ switch (language) {
+ case Language::JavaScript:
+ case Language::Json:
+ case Language::QmlProject:
+ case Language::QmlQbs:
+ case Language::QmlTypeInfo:
+ return language == l;
+ case Language::Qml:
+ return l == Language::Qml || l == Language::QmlQtQuick1 || l == Language::QmlQtQuick2
+ || Language::JavaScript;
+ case Language::QmlQtQuick1:
+ return l == Language::Qml || l == Language::QmlQtQuick1 || Language::JavaScript;
+ case Language::QmlQtQuick2:
+ return l == Language::Qml || l == Language::QmlQtQuick2 || Language::JavaScript;
+ case Language::Unknown: // ?
+ break;
+ }
+ return true;
+}
+
+} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsviewercontext.h b/src/libs/qmljs/qmljsviewercontext.h
new file mode 100644
index 0000000000..97620b5353
--- /dev/null
+++ b/src/libs/qmljs/qmljsviewercontext.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef VIEWERCONTEXT_H
+#define VIEWERCONTEXT_H
+
+#include "qmljs_global.h"
+#include "qmljsconstants.h"
+
+#include <QStringList>
+
+namespace QmlJS {
+
+class QMLJS_EXPORT ViewerContext
+{
+public:
+ enum Flags {
+ Complete,
+ AddAllPaths,
+ AddQtPath
+ };
+
+ ViewerContext();
+ ViewerContext(QStringList selectors, QStringList paths,
+ Language::Enum language = Language::Qml,
+ Flags flags = AddAllPaths);
+
+ bool languageIsCompatible(Language::Enum l) const;
+
+ QStringList selectors;
+ QStringList paths;
+ Language::Enum language;
+ Flags flags;
+};
+
+} // namespace QmlJS
+#endif // VIEWERCONTEXT_H
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index 5b4c95bf31..91e7b478a5 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -422,7 +422,7 @@ AndroidDeviceInfo AndroidConfigurations::showDeviceDialog(ProjectExplorer::Proje
return info;
}
- AndroidDeviceDialog dialog(apiLevel, abi);
+ AndroidDeviceDialog dialog(apiLevel, abi, Core::ICore::mainWindow());
if (dialog.exec() == QDialog::Accepted) {
AndroidDeviceInfo info = dialog.device();
if (dialog.saveDeviceSelection()) {
@@ -496,9 +496,9 @@ QVector<AndroidDeviceInfo> AndroidConfigurations::connectedDevices(QString *erro
return devices;
}
-QString AndroidConfigurations::createAVD(int minApiLevel, QString targetArch) const
+QString AndroidConfigurations::createAVD(QWidget *parent, int minApiLevel, QString targetArch) const
{
- QDialog d;
+ QDialog d(parent);
Ui::AddNewAVDDialog avdDialog;
avdDialog.setupUi(&d);
// NOTE: adb list targets does actually include information on which abis are supported per apilevel
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index 09c00d6b11..f69a830aed 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -102,7 +102,7 @@ public:
Utils::FileName zipalignPath() const;
Utils::FileName stripPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
Utils::FileName readelfPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const;
- QString createAVD(int minApiLevel = 0, QString targetArch = QString()) const;
+ QString createAVD(QWidget *parent, int minApiLevel = 0, QString targetArch = QString()) const;
QString createAVD(const QString &target, const QString &name, const QString &abi, int sdcardSize) const;
bool removeAVD(const QString &name) const;
QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0) const;
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index 53f1b148af..c4a5adc67a 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -388,7 +388,7 @@ bool AndroidDeployQtStep::fromMap(const QVariantMap &map)
m_deployAction = AndroidDeployQtAction(map.value(QLatin1String(DeployActionKey),
BundleLibrariesDeployment).toInt());
m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString());
- m_signPackage = map.value(SignPackageKey).toBool();
+ m_signPackage = false; // don't restore this
m_buildTargetSdk = map.value(BuildTargetSdkKey).toString();
m_verbose = map.value(VerboseOutputKey).toBool();
m_inputFile = map.value(InputFile).toString();
diff --git a/src/plugins/android/androiddeployqtwidget.cpp b/src/plugins/android/androiddeployqtwidget.cpp
index a1dee1ddba..7cc2e1561c 100644
--- a/src/plugins/android/androiddeployqtwidget.cpp
+++ b/src/plugins/android/androiddeployqtwidget.cpp
@@ -82,9 +82,11 @@ AndroidDeployQtWidget::AndroidDeployQtWidget(AndroidDeployQtStep *step)
}
// signing
+ m_ui->signPackageCheckBox->setChecked(m_step->signPackage());
m_ui->KeystoreLocationLineEdit->setText(m_step->keystorePath().toUserOutput());
m_ui->signingDebugWarningIcon->hide();
m_ui->signingDebugWarningLabel->hide();
+ signPackageCheckBoxToggled(m_step->signPackage());
m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput());
m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
diff --git a/src/plugins/android/androiddevicedialog.cpp b/src/plugins/android/androiddevicedialog.cpp
index 66f4c1ea98..6b3fb90bd5 100644
--- a/src/plugins/android/androiddevicedialog.cpp
+++ b/src/plugins/android/androiddevicedialog.cpp
@@ -446,7 +446,7 @@ void AndroidDeviceDialog::refreshDeviceList()
void AndroidDeviceDialog::createAvd()
{
- QString avd = AndroidConfigurations::instance().createAVD(m_apiLevel, m_abi);
+ QString avd = AndroidConfigurations::instance().createAVD(this, m_apiLevel, m_abi);
if (avd.isEmpty())
return;
refreshDeviceList();
diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp
index fc0a01c22a..4ab8228d0b 100644
--- a/src/plugins/android/androidsettingswidget.cpp
+++ b/src/plugins/android/androidsettingswidget.cpp
@@ -402,14 +402,16 @@ void AndroidSettingsWidget::browseOpenJDKLocation()
void AndroidSettingsWidget::addAVD()
{
- AndroidConfigurations::instance().createAVD();
+ AndroidConfigurations::instance().createAVD(this);
m_AVDModel.setAvdList(AndroidConfigurations::instance().androidVirtualDevices());
+ avdActivated(m_ui->AVDTableView->currentIndex());
}
void AndroidSettingsWidget::removeAVD()
{
AndroidConfigurations::instance().removeAVD(m_AVDModel.avdName(m_ui->AVDTableView->currentIndex()));
m_AVDModel.setAvdList(AndroidConfigurations::instance().androidVirtualDevices());
+ avdActivated(m_ui->AVDTableView->currentIndex());
}
void AndroidSettingsWidget::startAVD()
diff --git a/src/plugins/android/createandroidmanifestwizard.cpp b/src/plugins/android/createandroidmanifestwizard.cpp
index 84def92065..be51fb1c77 100644
--- a/src/plugins/android/createandroidmanifestwizard.cpp
+++ b/src/plugins/android/createandroidmanifestwizard.cpp
@@ -76,6 +76,7 @@ ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard, const
foreach (QmakeProFileNode *node, nodes)
m_comboBox->addItem(node->displayName(), QVariant::fromValue(static_cast<void *>(node))); // TODO something more?
+ nodeSelected(0);
connect(m_comboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(nodeSelected(int)));
diff --git a/src/plugins/baremetal/baremetalruncontrolfactory.cpp b/src/plugins/baremetal/baremetalruncontrolfactory.cpp
index 3ba17b73bf..50edf9a152 100644
--- a/src/plugins/baremetal/baremetalruncontrolfactory.cpp
+++ b/src/plugins/baremetal/baremetalruncontrolfactory.cpp
@@ -89,7 +89,7 @@ DebuggerStartParameters BareMetalRunControlFactory::startParameters(const BareMe
params.languages |= CppLanguage;
params.processArgs = runConfig->arguments();
params.startMode = AttachToRemoteServer;
- params.executable = Utils::HostOsInfo::withExecutableSuffix(runConfig->localExecutableFilePath());
+ params.executable = runConfig->localExecutableFilePath();
params.remoteSetupNeeded = false; //FIXME probably start debugserver with that, how?
params.displayName = runConfig->displayName();
if (const Project *project = target->project()) {
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index 4c08a10556..a08ec4e96d 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -1551,7 +1551,7 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName
QFile::rename(absPath + QLatin1String(".hijack"), absPath);
}
- if ((!response.error || response.stdOut.contains(QLatin1String("already checked out")))
+ if ((!response.error || response.stdErr.contains(QLatin1String("already checked out")))
&& !m_settings.disableIndexer) {
setStatus(absPath, FileStatus::CheckedOut);
}
@@ -1683,7 +1683,7 @@ bool ClearCasePlugin::ccFileOp(const QString &workingDir, const QString &title,
runCleartool(workingDir, args, m_settings.timeOutMS(),
ShowStdOutInLogWindow | FullySynchronously);
if (coResponse.error) {
- if (coResponse.stdOut.contains(QLatin1String("already checked out")))
+ if (coResponse.stdErr.contains(QLatin1String("already checked out")))
noCheckout = true;
else
return false;
diff --git a/src/plugins/coreplugin/core.qrc b/src/plugins/coreplugin/core.qrc
index d54182e37b..6fd7523c22 100644
--- a/src/plugins/coreplugin/core.qrc
+++ b/src/plugins/coreplugin/core.qrc
@@ -3,6 +3,7 @@
<file>images/clean_pane_small.png</file>
<file>images/clear.png</file>
<file>images/closebutton.png</file>
+ <file>images/compile_error_taskbar.png</file>
<file>images/dir.png</file>
<file>images/editcopy.png</file>
<file>images/editcut.png</file>
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index fb7620213f..253662a78f 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -114,8 +114,6 @@ using namespace Utils;
//===================EditorManager=====================
-EditorManagerPlaceHolder *EditorManagerPlaceHolder::m_current = 0;
-
EditorManagerPlaceHolder::EditorManagerPlaceHolder(Core::IMode *mode, QWidget *parent)
: QWidget(parent), m_mode(mode)
{
@@ -129,16 +127,17 @@ EditorManagerPlaceHolder::EditorManagerPlaceHolder(Core::IMode *mode, QWidget *p
EditorManagerPlaceHolder::~EditorManagerPlaceHolder()
{
- if (m_current == this) {
- EditorManager::instance()->setParent(0);
- EditorManager::instance()->hide();
+ // EditorManager will be deleted in ~MainWindow()
+ EditorManager *em = EditorManager::instance();
+ if (em && em->parent() == this) {
+ em->hide();
+ em->setParent(0);
}
}
void EditorManagerPlaceHolder::currentModeChanged(Core::IMode *mode)
{
if (m_mode == mode) {
- m_current = this;
QWidget *previousFocus = 0;
if (EditorManager::instance()->focusWidget() && EditorManager::instance()->focusWidget()->hasFocus())
previousFocus = EditorManager::instance()->focusWidget();
@@ -146,16 +145,9 @@ void EditorManagerPlaceHolder::currentModeChanged(Core::IMode *mode)
EditorManager::instance()->show();
if (previousFocus)
previousFocus->setFocus();
- } else if (m_current == this) {
- m_current = 0;
}
}
-EditorManagerPlaceHolder* EditorManagerPlaceHolder::current()
-{
- return m_current;
-}
-
// ---------------- EditorManager
namespace Core {
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 4b58092b41..9e554b4a46 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -79,12 +79,10 @@ class CORE_EXPORT EditorManagerPlaceHolder : public QWidget
public:
explicit EditorManagerPlaceHolder(Core::IMode *mode, QWidget *parent = 0);
~EditorManagerPlaceHolder();
- static EditorManagerPlaceHolder* current();
private slots:
void currentModeChanged(Core::IMode *);
private:
Core::IMode *m_mode;
- static EditorManagerPlaceHolder* m_current;
};
class CORE_EXPORT EditorManager : public QWidget
diff --git a/src/plugins/coreplugin/fileiconprovider.cpp b/src/plugins/coreplugin/fileiconprovider.cpp
index 6bba67ba06..4e56cd96b9 100644
--- a/src/plugins/coreplugin/fileiconprovider.cpp
+++ b/src/plugins/coreplugin/fileiconprovider.cpp
@@ -75,7 +75,7 @@ public:
: m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon))
{}
- QIcon icon(const QFileInfo &info) const;
+ QIcon icon(const QFileInfo &info);
using QFileIconProvider::icon;
void registerIconOverlayForSuffix(const QIcon &icon, const QString &suffix)
@@ -113,23 +113,26 @@ QFileIconProvider *iconProvider()
return instance();
}
-QIcon FileIconProviderImplementation::icon(const QFileInfo &fileInfo) const
+QIcon FileIconProviderImplementation::icon(const QFileInfo &fileInfo)
{
if (debug)
qDebug() << "FileIconProvider::icon" << fileInfo.absoluteFilePath();
// Check for cached overlay icons by file suffix.
- if (!m_cache.isEmpty() && !fileInfo.isDir()) {
- const QString suffix = fileInfo.suffix();
- if (!suffix.isEmpty() && m_cache.contains(suffix)) {
+ bool isDir = fileInfo.isDir();
+ QString suffix = !isDir ? fileInfo.suffix() : QString();
+ if (!m_cache.isEmpty() && !isDir && !suffix.isEmpty()) {
+ if (m_cache.contains(suffix))
return m_cache.value(suffix);
- }
}
// Get icon from OS.
+ QIcon icon;
if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost())
- return QFileIconProvider::icon(fileInfo);
-
- // File icons are unknown on linux systems.
- return fileInfo.isDir() ? QFileIconProvider::icon(fileInfo) : m_unknownFileIcon;
+ icon = QFileIconProvider::icon(fileInfo);
+ else // File icons are unknown on linux systems.
+ icon = isDir ? QFileIconProvider::icon(fileInfo) : m_unknownFileIcon;
+ if (!isDir && !suffix.isEmpty())
+ m_cache.insert(suffix, icon);
+ return icon;
}
/*!
diff --git a/src/plugins/coreplugin/images/compile_error_taskbar.png b/src/plugins/coreplugin/images/compile_error_taskbar.png
new file mode 100644
index 0000000000..71dd4ede42
--- /dev/null
+++ b/src/plugins/coreplugin/images/compile_error_taskbar.png
Binary files differ
diff --git a/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp b/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp
index 39ad2439de..1f04e55d47 100644
--- a/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp
+++ b/src/plugins/coreplugin/progressmanager/progressmanager_win.cpp
@@ -122,7 +122,7 @@ void Core::Internal::ProgressManagerPrivate::doSetApplicationLabel(const QString
if (text.isEmpty()) {
pITask->SetOverlayIcon(winId, NULL, NULL);
} else {
- QPixmap pix = QPixmap(QLatin1String(":/projectexplorer/images/compile_error.png"));
+ QPixmap pix = QPixmap(QLatin1String(":/core/images/compile_error_taskbar.png"));
QPainter p(&pix);
p.setPen(Qt::white);
QFont font = p.font();
diff --git a/src/plugins/cppeditor/cppdoxygen_test.cpp b/src/plugins/cppeditor/cppdoxygen_test.cpp
index 8feffc6579..ab8a947940 100644
--- a/src/plugins/cppeditor/cppdoxygen_test.cpp
+++ b/src/plugins/cppeditor/cppdoxygen_test.cpp
@@ -51,6 +51,9 @@ using namespace CPlusPlus;
using namespace CppEditor::Internal;
namespace {
+
+typedef QByteArray _;
+
/**
* Encapsulates the whole process of setting up an editor,
* pressing ENTER and checking the result.
@@ -140,205 +143,149 @@ void TestCase::run(const QByteArray &expected, int undoCount)
}
} // anonymous namespace
-void CppEditorPlugin::test_doxygen_comments_qt_style()
+void CppEditorPlugin::test_doxygen_comments_data()
{
- const QByteArray given =
+ QTest::addColumn<QByteArray>("given");
+ QTest::addColumn<QByteArray>("expected");
+
+ QTest::newRow("qt_style") << _(
"bool preventFolding;\n"
"/*!|\n"
"int a;\n"
- ;
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"/*!\n"
" * \\brief a\n"
" */\n"
"int a;\n"
- ;
+ );
- TestCase data(given);
- data.run(expected);
-}
-
-void CppEditorPlugin::test_doxygen_comments_qt_style_continuation()
-{
- const QByteArray given =
+ QTest::newRow("qt_style_continuation") << _(
"bool preventFolding;\n"
"/*!\n"
" * \\brief a|\n"
" */\n"
"int a;\n"
- ;
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"/*!\n"
" * \\brief a\n"
- " *\n"
+ " * \n"
" */\n"
"int a;\n"
- ;
+ );
- TestCase data(given);
- data.run(expected);
-}
-
-void CppEditorPlugin::test_doxygen_comments_java_style()
-{
- const QByteArray given =
+ QTest::newRow("java_style") << _(
"bool preventFolding;\n"
"/**|\n"
"int a;\n"
- ;
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"/**\n"
" * @brief a\n"
" */\n"
"int a;\n"
- ;
-
- TestCase data(given);
- data.run(expected);
-}
+ );
-void CppEditorPlugin::test_doxygen_comments_java_style_continuation()
-{
- const QByteArray given =
+ QTest::newRow("java_style_continuation") << _(
"bool preventFolding;\n"
"/**\n"
" * @brief a|\n"
" */\n"
"int a;\n"
- ;
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"/**\n"
" * @brief a\n"
- " *\n"
+ " * \n"
" */\n"
"int a;\n"
- ;
-
- TestCase data(given);
- data.run(expected);
-}
+ );
-void CppEditorPlugin::test_doxygen_comments_cpp_styleA()
-{
- const QByteArray given =
+ QTest::newRow("cpp_styleA") << _(
"bool preventFolding;\n"
"///|\n"
"int a;\n"
- ;
-
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"///\n"
"/// \\brief a\n"
"///\n"
"int a;\n"
- ;
- TestCase data(given);
- data.run(expected);
-}
+ );
-void CppEditorPlugin::test_doxygen_comments_cpp_styleB()
-{
- const QByteArray given =
+ QTest::newRow("cpp_styleB") << _(
"bool preventFolding;\n"
"//!|\n"
"int a;\n"
- ;
-
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"//!\n"
"//! \\brief a\n"
"//!\n"
"int a;\n"
- ;
- TestCase data(given);
- data.run(expected);
-}
+ );
-void CppEditorPlugin::test_doxygen_comments_cpp_styleA_continuation()
-{
- const QByteArray given =
+ QTest::newRow("cpp_styleA_continuation") << _(
"bool preventFolding;\n"
"///\n"
"/// \\brief a|\n"
"///\n"
"int a;\n"
- ;
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"///\n"
"/// \\brief a\n"
- "///\n"
+ "/// \n"
"///\n"
"int a;\n"
- ;
-
- TestCase data(given);
- data.run(expected);
-}
+ );
-/// test cpp style doxygen comment when inside a indented scope
-void CppEditorPlugin::test_doxygen_comments_cpp_styleA_indented()
-{
- const QByteArray given =
+ /// test cpp style doxygen comment when inside a indented scope
+ QTest::newRow("cpp_styleA_indented") << _(
" bool preventFolding;\n"
" ///|\n"
" int a;\n"
- ;
-
- const QByteArray expected =
+ ) << _(
" bool preventFolding;\n"
" ///\n"
" /// \\brief a\n"
" ///\n"
" int a;\n"
- ;
- TestCase data(given);
- data.run(expected);
-}
+ );
-/// test cpp style doxygen comment continuation when inside a indented scope
-void CppEditorPlugin::test_doxygen_comments_cpp_styleA_indented_continuation()
-{
- const QByteArray given =
+ /// test cpp style doxygen comment continuation when inside a indented scope
+ QTest::newRow("cpp_styleA_indented_continuation") << _(
" bool preventFolding;\n"
" ///\n"
" /// \\brief a|\n"
" ///\n"
" int a;\n"
- ;
- const QByteArray expected =
+ ) << _(
" bool preventFolding;\n"
" ///\n"
" /// \\brief a\n"
- " ///\n"
+ " /// \n"
" ///\n"
" int a;\n"
- ;
+ );
- TestCase data(given);
- data.run(expected);
-}
-
-void CppEditorPlugin::test_doxygen_comments_cpp_styleA_corner_case()
-{
- const QByteArray given =
+ QTest::newRow("cpp_styleA_corner_case") << _(
"bool preventFolding;\n"
"///\n"
"void d(); ///|\n"
- ;
- const QByteArray expected =
+ ) << _(
"bool preventFolding;\n"
"///\n"
"void d(); ///\n"
"\n"
- ;
+ );
+}
+void CppEditorPlugin::test_doxygen_comments()
+{
+ QFETCH(QByteArray, given);
+ QFETCH(QByteArray, expected);
TestCase data(given);
data.run(expected);
}
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 331c66946c..63d5bc2e5b 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -430,6 +430,7 @@ bool handleDoxygenCppStyleContinuation(QTextCursor &cursor,
const QString commentMarker = text.mid(offset, 3);
newLine.append(commentMarker);
+ newLine.append(QLatin1Char(' '));
cursor.insertText(newLine);
e->accept();
@@ -481,12 +482,13 @@ bool handleDoxygenContinuation(QTextCursor &cursor,
c.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, offset);
newLine.append(c.selectedText());
if (text.at(offset) == QLatin1Char('/')) {
- newLine.append(QLatin1String(" *"));
+ newLine.append(QLatin1String(" * "));
} else {
int start = offset;
while (offset < blockPos && text.at(offset) == QLatin1Char('*'))
++offset;
newLine.append(QString(offset - start, QLatin1Char('*')));
+ newLine.append(QLatin1Char(' '));
}
cursor.insertText(newLine);
e->accept();
diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h
index a05dc7bdd7..0989225538 100644
--- a/src/plugins/cppeditor/cppeditorplugin.h
+++ b/src/plugins/cppeditor/cppeditorplugin.h
@@ -116,16 +116,8 @@ private slots:
void test_FollowSymbolUnderCursor_virtualFunctionCall();
void test_FollowSymbolUnderCursor_virtualFunctionCall_multipleDocuments();
- void test_doxygen_comments_qt_style();
- void test_doxygen_comments_qt_style_continuation();
- void test_doxygen_comments_java_style();
- void test_doxygen_comments_java_style_continuation();
- void test_doxygen_comments_cpp_styleA();
- void test_doxygen_comments_cpp_styleB();
- void test_doxygen_comments_cpp_styleA_indented();
- void test_doxygen_comments_cpp_styleA_continuation();
- void test_doxygen_comments_cpp_styleA_indented_continuation();
- void test_doxygen_comments_cpp_styleA_corner_case();
+ void test_doxygen_comments_data();
+ void test_doxygen_comments();
void test_quickfix_CompleteSwitchCaseStatement_basic1();
void test_quickfix_CompleteSwitchCaseStatement_basic2();
diff --git a/src/plugins/cppeditor/cppincludehierarchy.cpp b/src/plugins/cppeditor/cppincludehierarchy.cpp
index 15a2429f82..3efde4c154 100644
--- a/src/plugins/cppeditor/cppincludehierarchy.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchy.cpp
@@ -36,6 +36,7 @@
#include "cppincludehierarchymodel.h"
#include "cppincludehierarchytreeview.h"
+#include <coreplugin/editormanager/editormanager.h>
#include <cplusplus/CppDocument.h>
#include <utils/annotateditemdelegate.h>
@@ -89,7 +90,8 @@ CppIncludeHierarchyWidget::CppIncludeHierarchyWidget() :
m_treeView(0),
m_model(0),
m_delegate(0),
- m_includeHierarchyInfoLabel(0)
+ m_includeHierarchyInfoLabel(0),
+ m_editor(0)
{
m_inspectedFile = new CppIncludeLabel(this);
m_inspectedFile->setMargin(5);
@@ -118,6 +120,9 @@ CppIncludeHierarchyWidget::CppIncludeHierarchyWidget() :
setLayout(layout);
connect(CppEditorPlugin::instance(), SIGNAL(includeHierarchyRequested()), SLOT(perform()));
+ connect(Core::EditorManager::instance(), SIGNAL(editorsClosed(QList<Core::IEditor *>)),
+ this, SLOT(editorsClosed(QList<Core::IEditor *>)));
+
}
CppIncludeHierarchyWidget::~CppIncludeHierarchyWidget()
@@ -128,15 +133,16 @@ void CppIncludeHierarchyWidget::perform()
{
showNoIncludeHierarchyLabel();
- CPPEditor *editor = qobject_cast<CPPEditor *>(Core::EditorManager::currentEditor());
- if (!editor)
+ m_editor = qobject_cast<CPPEditor *>(Core::EditorManager::currentEditor());
+ if (!m_editor)
return;
- CPPEditorWidget *widget = qobject_cast<CPPEditorWidget *>(editor->widget());
+
+ CPPEditorWidget *widget = qobject_cast<CPPEditorWidget *>(m_editor->widget());
if (!widget)
return;
m_model->clear();
- m_model->buildHierarchy(widget->editorDocument()->filePath());
+ m_model->buildHierarchy(m_editor, widget->editorDocument()->filePath());
if (m_model->isEmpty())
return;
@@ -162,6 +168,14 @@ void CppIncludeHierarchyWidget::onItemClicked(const QModelIndex &index)
Constants::CPPEDITOR_ID);
}
+void CppIncludeHierarchyWidget::editorsClosed(QList<Core::IEditor *> editors)
+{
+ foreach (Core::IEditor *editor, editors) {
+ if (m_editor == editor)
+ perform();
+ }
+}
+
void CppIncludeHierarchyWidget::showNoIncludeHierarchyLabel()
{
m_inspectedFile->hide();
diff --git a/src/plugins/cppeditor/cppincludehierarchy.h b/src/plugins/cppeditor/cppincludehierarchy.h
index fd8d31cbde..cb7720db5e 100644
--- a/src/plugins/cppeditor/cppincludehierarchy.h
+++ b/src/plugins/cppeditor/cppincludehierarchy.h
@@ -55,6 +55,7 @@ class FileName;
namespace CppEditor {
namespace Internal {
+class CPPEditor;
class CPPEditorWidget;
class CppInclude;
class CppIncludeLabel;
@@ -73,6 +74,7 @@ public slots:
private slots:
void onItemClicked(const QModelIndex &index);
+ void editorsClosed(QList<Core::IEditor *> editors);
private:
void showNoIncludeHierarchyLabel();
@@ -84,6 +86,7 @@ private:
Utils::AnnotatedItemDelegate *m_delegate;
CppIncludeLabel *m_inspectedFile;
QLabel *m_includeHierarchyInfoLabel;
+ CPPEditor *m_editor;
};
// @todo: Pretty much the same design as the OutlineWidgetStack. Maybe we can generalize the
diff --git a/src/plugins/cppeditor/cppincludehierarchy_test.cpp b/src/plugins/cppeditor/cppincludehierarchy_test.cpp
index e52273743c..7e641e7494 100644
--- a/src/plugins/cppeditor/cppincludehierarchy_test.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchy_test.cpp
@@ -30,6 +30,8 @@
#include "cppeditorplugin.h"
#include "cppincludehierarchymodel.h"
+#include <coreplugin/editormanager/editormanager.h>
+#include <cppeditor/cppeditor.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <utils/fileutils.h>
@@ -47,6 +49,7 @@ class TestCase
public:
TestCase(const QList<QByteArray> &sourceList)
: m_cmm(CppModelManagerInterface::instance())
+ , m_editor(0)
{
QStringList filePaths;
const int sourceListSize = sourceList.size();
@@ -82,22 +85,30 @@ public:
~TestCase()
{
+ // Close editor
+ if (m_editor)
+ Core::EditorManager::closeEditor(m_editor, false);
+
m_cmm->GC();
QVERIFY(m_cmm->snapshot().isEmpty());
}
- void run(int includesCount, int includedByCount) const
+ void run(int includesCount, int includedByCount)
{
const QString fileName = QDir::tempPath() + QLatin1String("/file1.h");
+ m_editor = qobject_cast<CPPEditor *>(Core::EditorManager::openEditor(fileName));
+ QVERIFY(m_editor);
+
CppIncludeHierarchyModel model(0);
- model.buildHierarchy(fileName);
+ model.buildHierarchy(m_editor, fileName);
QCOMPARE(model.rowCount(model.index(0, 0)), includesCount);
QCOMPARE(model.rowCount(model.index(1, 0)), includedByCount);
}
private:
CppModelManagerInterface *m_cmm;
+ CPPEditor *m_editor;
};
}
diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.cpp b/src/plugins/cppeditor/cppincludehierarchymodel.cpp
index 7709bed2d5..06fe941cd9 100644
--- a/src/plugins/cppeditor/cppincludehierarchymodel.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchymodel.cpp
@@ -35,10 +35,12 @@
#include <cplusplus/CppDocument.h>
#include <cppeditor/cppeditor.h>
#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/cpptoolseditorsupport.h>
#include <QSet>
using namespace CPlusPlus;
+using namespace CppTools;
namespace CppEditor {
namespace Internal {
@@ -48,7 +50,7 @@ CppIncludeHierarchyModel::CppIncludeHierarchyModel(QObject *parent)
, m_rootItem(new CppIncludeHierarchyItem(QString()))
, m_includesItem(new CppIncludeHierarchyItem(tr("Includes"), m_rootItem))
, m_includedByItem(new CppIncludeHierarchyItem(tr("Included by"), m_rootItem))
-
+ , m_editor(0)
{
m_rootItem->appendChild(m_includesItem);
m_rootItem->appendChild(m_includedByItem);
@@ -199,6 +201,15 @@ void CppIncludeHierarchyModel::clear()
endResetModel();
}
+void CppIncludeHierarchyModel::buildHierarchy(CPPEditor *editor, const QString &filePath)
+{
+ m_editor = editor;
+ beginResetModel();
+ buildHierarchyIncludes(filePath);
+ buildHierarchyIncludedBy(filePath);
+ endResetModel();
+}
+
bool CppIncludeHierarchyModel::hasChildren(const QModelIndex &parent) const
{
if (!parent.isValid())
@@ -210,14 +221,6 @@ bool CppIncludeHierarchyModel::hasChildren(const QModelIndex &parent) const
return parentItem->hasChildren();
}
-void CppIncludeHierarchyModel::buildHierarchy(const QString &filePath)
-{
- beginResetModel();
- buildHierarchyIncludes(filePath);
- buildHierarchyIncludedBy(filePath);
- endResetModel();
-}
-
bool CppIncludeHierarchyModel::isEmpty() const
{
return !m_includesItem->hasChildren() && !m_includedByItem->hasChildren();
@@ -233,7 +236,11 @@ void CppIncludeHierarchyModel::buildHierarchyIncludes_helper(const QString &file
CppIncludeHierarchyItem *parent,
QSet<QString> *cyclic, bool recursive)
{
- const Snapshot &snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
+ if (!m_editor)
+ return;
+
+ CppModelManagerInterface *cppMM = CppModelManagerInterface::instance();
+ const Snapshot &snapshot = cppMM->cppEditorSupport(m_editor)->snapshotUpdater()->snapshot();
Document::Ptr doc = snapshot.document(filePath);
if (!doc)
return;
diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.h b/src/plugins/cppeditor/cppincludehierarchymodel.h
index cc9cbef050..afb4c7ceb8 100644
--- a/src/plugins/cppeditor/cppincludehierarchymodel.h
+++ b/src/plugins/cppeditor/cppincludehierarchymodel.h
@@ -41,9 +41,14 @@ enum ItemRole {
} // Anonymous
+namespace Core {
+class IEditor;
+}
+
namespace CppEditor {
namespace Internal {
+class CPPEditor;
class CppIncludeHierarchyItem;
class CppIncludeHierarchyModel : public QAbstractItemModel
@@ -63,7 +68,7 @@ public:
bool hasChildren(const QModelIndex &parent) const;
void clear();
- void buildHierarchy(const QString &filePath);
+ void buildHierarchy(CPPEditor *editor, const QString &filePath);
bool isEmpty() const;
private:
@@ -77,6 +82,7 @@ private:
CppIncludeHierarchyItem *m_rootItem;
CppIncludeHierarchyItem *m_includesItem;
CppIncludeHierarchyItem *m_includedByItem;
+ CPPEditor *m_editor;
};
} // namespace Internal
diff --git a/src/plugins/cpptools/cpptoolseditorsupport.cpp b/src/plugins/cpptools/cpptoolseditorsupport.cpp
index 89e787d081..85c304cad6 100644
--- a/src/plugins/cpptools/cpptoolseditorsupport.cpp
+++ b/src/plugins/cpptools/cpptoolseditorsupport.cpp
@@ -169,6 +169,7 @@ CppEditorSupport::~CppEditorSupport()
m_highlighter.cancel();
m_futureSemanticInfo.cancel();
+ m_documentParser.waitForFinished();
m_highlighter.waitForFinished();
m_futureSemanticInfo.waitForFinished();
}
diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h
index 2b46a94b93..f928fd40e3 100644
--- a/src/plugins/debugger/debuggerstartparameters.h
+++ b/src/plugins/debugger/debuggerstartparameters.h
@@ -64,6 +64,7 @@ public:
attachPID(-1),
useTerminal(false),
breakOnMain(false),
+ continueAfterAttach(false),
multiProcess(false),
languages(AnyLanguage),
qmlServerAddress(QLatin1String("127.0.0.1")),
@@ -102,6 +103,7 @@ public:
qint64 attachPID;
bool useTerminal;
bool breakOnMain;
+ bool continueAfterAttach;
bool multiProcess;
DebuggerLanguages languages;
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index ae83e0801f..882dfaac9d 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -3603,6 +3603,7 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &)
void GdbEngine::reloadFullStack()
{
PENDING_DEBUG("RELOAD FULL STACK");
+ resetLocation();
postCommand("-stack-list-frames", Discardable, CB(handleStackListFrames),
QVariant::fromValue<StackCookie>(StackCookie(true, true)));
}
@@ -4307,10 +4308,8 @@ void GdbEngine::assignValueInDebugger(const WatchData *data,
+ value.toString().toUtf8().toHex();
postCommand(cmd, Discardable, CB(handleVarAssign));
} else {
- postCommand("-var-delete assign");
- postCommand("-var-create assign * " + expression.toLatin1());
- postCommand("-var-assign assign " +
- GdbMi::escapeCString(value.toString().toLatin1()),
+ postCommand("set variable (" + expression.toLatin1() + ")="
+ + GdbMi::escapeCString(value.toString().toLatin1()),
Discardable, CB(handleVarAssign));
}
}
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 7e740f0bd8..c2c7b69141 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -83,7 +83,7 @@ static QByteArray tooltipIName(const QString &exp)
///////////////////////////////////////////////////////////////////////
LldbEngine::LldbEngine(const DebuggerStartParameters &startParameters)
- : DebuggerEngine(startParameters)
+ : DebuggerEngine(startParameters), m_continueAtNextSpontaneousStop(false)
{
m_lastAgentId = 0;
m_lastToken = 0;
@@ -197,13 +197,19 @@ void LldbEngine::setupInferior()
cmd.arg("executable", QFileInfo(sp.executable).absoluteFilePath());
cmd.arg("startMode", sp.startMode); // directly relying on this is brittle wrt. insertions, so check it here
cmd.arg("processArgs", sp.processArgs);
- cmd.arg("attachPid", ((sp.startMode == AttachCrashedExternal || sp.startMode == AttachExternal)
- ? sp.attachPID : 0));
+
+ QTC_CHECK(!sp.attachPID || (sp.startMode == AttachCrashedExternal
+ || sp.startMode == AttachExternal));
+ cmd.arg("attachPid", sp.attachPID);
cmd.arg("sysRoot", sp.sysRoot);
cmd.arg("remoteChannel", ((sp.startMode == AttachToRemoteProcess
|| sp.startMode == AttachToRemoteServer)
? sp.remoteChannel : QString()));
cmd.arg("platform", sp.platform);
+ QTC_CHECK(!sp.continueAfterAttach || (sp.startMode == AttachToRemoteProcess
+ || sp.startMode == AttachExternal
+ || sp.startMode == AttachToRemoteServer));
+ m_continueAtNextSpontaneousStop = false;
runCommand(cmd);
updateLocals(); // update display options
}
@@ -1014,9 +1020,13 @@ void LldbEngine::refreshState(const GdbMi &reportedState)
notifyInferiorRunOk();
else if (newState == "inferiorrunfailed")
notifyInferiorRunFailed();
- else if (newState == "stopped")
+ else if (newState == "stopped") {
notifyInferiorSpontaneousStop();
- else if (newState == "inferiorstopok")
+ if (m_continueAtNextSpontaneousStop) {
+ m_continueAtNextSpontaneousStop = false;
+ continueInferior();
+ }
+ } else if (newState == "inferiorstopok")
notifyInferiorStopOk();
else if (newState == "inferiorstopfailed")
notifyInferiorStopFailed();
@@ -1028,9 +1038,11 @@ void LldbEngine::refreshState(const GdbMi &reportedState)
notifyEngineRunFailed();
else if (newState == "inferiorsetupok")
notifyInferiorSetupOk();
- else if (newState == "enginerunandinferiorrunok")
+ else if (newState == "enginerunandinferiorrunok") {
+ if (startParameters().continueAfterAttach)
+ m_continueAtNextSpontaneousStop = true;
notifyEngineRunAndInferiorRunOk();
- else if (newState == "enginerunandinferiorstopok")
+ } else if (newState == "enginerunandinferiorstopok")
notifyEngineRunAndInferiorStopOk();
else if (newState == "inferiorshutdownok")
notifyInferiorShutdownOk();
diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h
index 22d05cb293..dc4e174768 100644
--- a/src/plugins/debugger/lldb/lldbengine.h
+++ b/src/plugins/debugger/lldb/lldbengine.h
@@ -201,6 +201,7 @@ private:
// FIXME: Make generic.
int m_lastAgentId;
int m_lastToken;
+ int m_continueAtNextSpontaneousStop;
QMap<QPointer<DisassemblerAgent>, int> m_disassemblerAgents;
QMap<QPointer<MemoryAgent>, int> m_memoryAgents;
QHash<int, QPointer<QObject> > m_memoryAgentTokens;
diff --git a/src/plugins/debugger/threadshandler.cpp b/src/plugins/debugger/threadshandler.cpp
index 4996d34752..63b1e1375e 100644
--- a/src/plugins/debugger/threadshandler.cpp
+++ b/src/plugins/debugger/threadshandler.cpp
@@ -36,12 +36,11 @@
#include <utils/qtcassert.h>
#include <QDebug>
-#include <QSortFilterProxyModel>
namespace Debugger {
namespace Internal {
-void mergeThreadData(ThreadData &data, const ThreadData &other)
+static void mergeThreadData(ThreadData &data, const ThreadData &other)
{
if (!other.core.isEmpty())
data.core = other.core;
@@ -67,6 +66,40 @@ void mergeThreadData(ThreadData &data, const ThreadData &other)
data.lineNumber = other.lineNumber;
}
+static QVariant threadPart(const ThreadData &thread, int column)
+{
+ switch (column) {
+ case ThreadData::IdColumn:
+ return thread.id.raw();
+ case ThreadData::FunctionColumn:
+ return thread.function;
+ case ThreadData::FileColumn:
+ return thread.fileName.isEmpty() ? thread.module : thread.fileName;
+ case ThreadData::LineColumn:
+ return thread.lineNumber >= 0
+ ? QString::number(thread.lineNumber) : QString();
+ case ThreadData::AddressColumn:
+ return thread.address > 0
+ ? QLatin1String("0x") + QString::number(thread.address, 16)
+ : QString();
+ case ThreadData::CoreColumn:
+ return thread.core;
+ case ThreadData::StateColumn:
+ return thread.state;
+ case ThreadData::TargetIdColumn:
+ if (thread.targetId.startsWith(QLatin1String("Thread ")))
+ return thread.targetId.mid(7);
+ return thread.targetId;
+ case ThreadData::NameColumn:
+ return thread.name;
+ case ThreadData::DetailsColumn:
+ return thread.details;
+ case ThreadData::ComboNameColumn:
+ return QString::fromLatin1("#%1 %2").arg(thread.id.raw()).arg(thread.name);
+ }
+ return QVariant();
+}
+
////////////////////////////////////////////////////////////////////////
//
// ThreadsHandler
@@ -137,8 +170,6 @@ ThreadsHandler::ThreadsHandler()
{
m_resetLocationScheduled = false;
setObjectName(QLatin1String("ThreadsModel"));
- m_proxyModel = new QSortFilterProxyModel(this);
- m_proxyModel->setSourceModel(this);
}
int ThreadsHandler::currentThreadIndex() const
@@ -168,35 +199,7 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
switch (role) {
case Qt::DisplayRole:
- switch (index.column()) {
- case ThreadData::IdColumn:
- return thread.id.raw();
- case ThreadData::FunctionColumn:
- return thread.function;
- case ThreadData::FileColumn:
- return thread.fileName.isEmpty() ? thread.module : thread.fileName;
- case ThreadData::LineColumn:
- return thread.lineNumber >= 0
- ? QString::number(thread.lineNumber) : QString();
- case ThreadData::AddressColumn:
- return thread.address > 0
- ? QLatin1String("0x") + QString::number(thread.address, 16)
- : QString();
- case ThreadData::CoreColumn:
- return thread.core;
- case ThreadData::StateColumn:
- return thread.state;
- case ThreadData::TargetIdColumn:
- if (thread.targetId.startsWith(QLatin1String("Thread ")))
- return thread.targetId.mid(7);
- return thread.targetId;
- case ThreadData::NameColumn:
- return thread.name;
- case ThreadData::DetailsColumn:
- return thread.details;
- case ThreadData::ComboNameColumn:
- return QString::fromLatin1("#%1 %2").arg(thread.id.raw()).arg(thread.name);
- }
+ return threadPart(thread, index.column());
case Qt::ToolTipRole:
return threadToolTip(thread);
case Qt::DecorationRole:
@@ -250,6 +253,33 @@ Qt::ItemFlags ThreadsHandler::flags(const QModelIndex &index) const
return stopped ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
}
+struct Sorter
+{
+ Sorter(int column, Qt::SortOrder order)
+ : m_column(column), m_order(order)
+ {}
+
+ bool operator()(const ThreadData &t1, const ThreadData &t2) const
+ {
+ const QVariant v1 = threadPart(t1, m_column);
+ const QVariant v2 = threadPart(t2, m_column);
+ if (v1 == v2)
+ return false;
+ // FIXME: Use correct toXXX();
+ return (v1.toString() < v2.toString()) ^ (m_order == Qt::DescendingOrder);
+ }
+
+ int m_column;
+ Qt::SortOrder m_order;
+};
+
+void ThreadsHandler::sort(int column, Qt::SortOrder order)
+{
+ layoutAboutToBeChanged();
+ qSort(m_threads.begin(), m_threads.end(), Sorter(column, order));
+ layoutChanged();
+}
+
ThreadId ThreadsHandler::currentThread() const
{
return m_currentId;
@@ -490,7 +520,7 @@ void ThreadsHandler::resetLocation()
QAbstractItemModel *ThreadsHandler::model()
{
- return m_proxyModel;
+ return this;
}
} // namespace Internal
diff --git a/src/plugins/debugger/threadshandler.h b/src/plugins/debugger/threadshandler.h
index 1bf9ef6da9..30f458ee36 100644
--- a/src/plugins/debugger/threadshandler.h
+++ b/src/plugins/debugger/threadshandler.h
@@ -30,14 +30,10 @@
#ifndef THREADSHANDLER_H
#define THREADSHANDLER_H
-#include <QAbstractTableModel>
-#include <QIcon>
-
#include "threaddata.h"
-QT_BEGIN_NAMESPACE
-class QSortFilterProxyModel;
-QT_END_NAMESPACE
+#include <QAbstractTableModel>
+#include <QIcon>
////////////////////////////////////////////////////////////////////////
//
@@ -92,6 +88,7 @@ private:
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
+ void sort(int, Qt::SortOrder);
void updateThreadBox();
void threadDataChanged(ThreadId id);
@@ -101,7 +98,6 @@ private:
const QIcon m_emptyIcon;
bool m_resetLocationScheduled;
- QSortFilterProxyModel *m_proxyModel;
};
} // namespace Internal
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 5c3050f81d..388e60c7eb 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -784,6 +784,12 @@ static const QMap<QString, int> &vimKeyNames()
return k;
}
+bool isControlModifier(const Qt::KeyboardModifiers &mods)
+{
+ static const int ctrl = HostOsInfo::controlModifier();
+ return (mods & ctrl) == ctrl;
+}
+
Range::Range()
: beginPos(-1), endPos(-1), rangemode(RangeCharMode)
@@ -938,12 +944,12 @@ public:
bool is(int c) const
{
- return m_xkey == c && m_modifiers != HostOsInfo::controlModifier();
+ return m_xkey == c && !isControl();
}
bool isControl() const
{
- return m_modifiers == HostOsInfo::controlModifier();
+ return isControlModifier(m_modifiers);
}
bool isControl(int c) const
@@ -2215,7 +2221,7 @@ bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev)
}
// We are interested in overriding most Ctrl key combinations.
- if (mods == HostOsInfo::controlModifier()
+ if (isControlModifier(mods)
&& !config(ConfigPassControlKey).toBool()
&& ((key >= Key_A && key <= Key_Z && key != Key_K)
|| key == Key_BracketLeft || key == Key_BracketRight)) {
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index c37ff7c12e..1b3d521559 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -1443,7 +1443,7 @@ void GitClient::show(const QString &source, const QString &id,
GitDiffHandler *handler = new GitDiffHandler(diffEditor,
gitBinaryPath(),
- workingDirectory,
+ findRepositoryForDirectory(workingDirectory),
processEnvironment(),
settings()->intValue(GitSettings::timeoutKey));
handler->show(id);
diff --git a/src/plugins/ios/iosdebugsupport.cpp b/src/plugins/ios/iosdebugsupport.cpp
index 0d761320b9..32d69447af 100644
--- a/src/plugins/ios/iosdebugsupport.cpp
+++ b/src/plugins/ios/iosdebugsupport.cpp
@@ -84,6 +84,8 @@ RunControl *IosDebugSupport::createDebugRunControl(IosRunConfiguration *runConfi
}
params.displayName = runConfig->appName();
params.remoteSetupNeeded = true;
+ if (!params.breakOnMain)
+ params.continueAfterAttach = true;
Debugger::DebuggerRunConfigurationAspect *aspect
= runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>();
diff --git a/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp b/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp
index bb93d20043..169afe0cac 100644
--- a/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp
+++ b/src/plugins/qmakeprojectmanager/wizards/qtquickapp.cpp
@@ -249,9 +249,6 @@ void QtQuickApp::handleCurrentProFileTemplateLine(const QString &line,
if (!nextLine.startsWith(QLatin1String("QML_IMPORT_PATH =")))
return;
proFile << nextLine << endl;
- } else if (line.contains(QLatin1String("# HARMATTAN_BOOSTABLE"))) {
- QString nextLine = proFileTemplate.readLine(); // eats '# CONFIG += qdeclarative-boostable'
- proFile << nextLine << endl;
}
}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
index 9ed39b9f63..677d13bd81 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
@@ -119,6 +119,9 @@ void FormEditorItem::setHighlightBoundingRect(bool highlight)
void FormEditorItem::blurContent(bool blurContent)
{
+ if (!scene())
+ return;
+
if (m_blurContent != blurContent) {
m_blurContent = blurContent;
update();
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
index 8358c18608..1205aae5ae 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -510,7 +510,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
if ((valid || entry.forceImport())
&& (entry.requiredImport().isEmpty()
- || model->hasImport(entryToImport(entry), true, false) || entry.forceImport())) {
+ || model->hasImport(entryToImport(entry), true, true) || entry.forceImport())) {
QString itemSectionName = entry.category();
ItemLibrarySectionModel *sectionModel;
ItemLibraryItemModel *itemModel;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index ad7edd745c..99e92d88ea 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -367,13 +367,10 @@ void ItemLibraryWidget::startDragAndDrop(int itemLibId)
{
QMimeData *mimeData = m_itemLibraryModel->getMimeData(itemLibId);
QDrag *drag = new QDrag(this);
- const QImage image = qvariant_cast<QImage>(mimeData->imageData());
drag->setPixmap(m_itemLibraryModel->getIcon(itemLibId).pixmap(32, 32));
drag->setMimeData(mimeData);
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(m_itemsView->rootObject());
-
drag->exec();
}
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index 8e4334d87c..3d6e903d93 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -99,6 +99,8 @@ public:
QList<Import> possibleImports() const;
QList<Import> usedImports() const;
void changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importsToBeRemoved);
+ void setPossibleImports(const QList<Import> &possibleImports);
+ void setUsedImports(const QList<Import> &usedImports);
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false);
QString pathForImport(const Import &import);
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index 2405ef8412..bf845dcc81 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -75,6 +75,8 @@ static inline QStringList importPaths() {
static inline bool checkIfDerivedFromItem(const QString &fileName)
{
+ return true;
+
QmlJS::Snapshot snapshot;
@@ -101,7 +103,7 @@ static inline bool checkIfDerivedFromItem(const QString &fileName)
snapshot.insert(document);
- QmlJS::Link link(snapshot, modelManager->importPaths(), QmlJS::ModelManagerInterface::instance()->builtins(document));
+ QmlJS::Link link(snapshot, modelManager->defaultVContext(), QmlJS::ModelManagerInterface::instance()->builtins(document));
QList<QmlJS::DiagnosticMessage> diagnosticLinkMessages;
QmlJS::ContextPtr context = link(document, &diagnosticLinkMessages);
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index df895a4048..b2c2019bb7 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -1731,25 +1731,12 @@ QList<Import> Model::imports() const
QList<Import> Model::possibleImports() const
{
- QList<Import> possibleImportList;
-
- possibleImportList.append(Import::createLibraryImport("QtQuick.Controls", "1.0"));
- possibleImportList.append(Import::createLibraryImport("QtQuick.Layouts", "1.0"));
- possibleImportList.append(Import::createLibraryImport("QtQuick.Window", "2.0"));
-
- return possibleImportList;
+ return d->m_possibleImportList;
}
QList<Import> Model::usedImports() const
{
- QList<Import> usedImportList;
-
- usedImportList.append(Import::createLibraryImport("QtQuick", "1.0"));
- usedImportList.append(Import::createLibraryImport("QtQuick", "1.1"));
- usedImportList.append(Import::createLibraryImport("QtQuick", "2.0"));
- usedImportList.append(Import::createLibraryImport("QtQuick", "2.1"));
-
- return usedImportList;
+ return d->m_usedImportList;
}
void Model::changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importsToBeRemoved)
@@ -1757,6 +1744,16 @@ void Model::changeImports(const QList<Import> &importsToBeAdded, const QList<Imp
d->changeImports(importsToBeAdded, importsToBeRemoved);
}
+void Model::setPossibleImports(const QList<Import> &possibleImports)
+{
+ d->m_possibleImportList = possibleImports;
+}
+
+void Model::setUsedImports(const QList<Import> &usedImports)
+{
+ d->m_usedImportList = usedImports;
+}
+
static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion)
{
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index 7dcc150491..8b2653ed9c 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -236,6 +236,8 @@ private:
Model *m_q;
MetaInfo m_metaInfo;
QList<Import> m_imports;
+ QList<Import> m_possibleImportList;
+ QList<Import> m_usedImportList;
QList<QWeakPointer<AbstractView> > m_viewList;
QList<InternalNodePointer> m_selectedInternalNodeList;
QHash<QString,InternalNodePointer> m_idNodeHash;
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 20eec5c8e1..7b0b170d23 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -48,6 +48,7 @@
#include <qmljs/qmljsutils.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsqrcparser.h>
+#include <qmljs/qmljsinterpreter.h>
#include <utils/qtcassert.h>
@@ -306,10 +307,10 @@ class ReadingContext
{
public:
ReadingContext(const Snapshot &snapshot, const Document::Ptr &doc,
- const QStringList importPaths)
+ const ViewerContext &vContext)
: m_snapshot(snapshot)
, m_doc(doc)
- , m_link(snapshot, importPaths,
+ , m_link(snapshot, vContext,
QmlJS::ModelManagerInterface::instance()->builtins(doc))
, m_context(m_link(doc, &m_diagnosticLinkMessages))
, m_scopeChain(doc, m_context)
@@ -726,6 +727,67 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc,
differenceHandler.importAbsentInQMl(import);
}
+void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext)
+{
+ QList<Import> possibleImports;
+
+ QSet<ImportKey> possibleImportKeys = snapshot.importDependencies()->libraryImports(viewContext);
+
+ QHash<QString, ImportKey> filteredPossibleImportKeys;
+ foreach (const ImportKey &importKey, possibleImportKeys) {
+ if (!filteredPossibleImportKeys.contains(importKey.path())
+ || filteredPossibleImportKeys.value(importKey.path()).majorVersion < importKey.majorVersion
+ || (filteredPossibleImportKeys.value(importKey.path()).majorVersion == importKey.majorVersion
+ && filteredPossibleImportKeys.value(importKey.path()).minorVersion < importKey.minorVersion))
+ filteredPossibleImportKeys.insert(importKey.path(), importKey);
+ }
+
+ filteredPossibleImportKeys.remove(QLatin1String("<cpp>"));
+ filteredPossibleImportKeys.remove(QLatin1String("QML"));
+ filteredPossibleImportKeys.remove(QLatin1String("QtQml"));
+ filteredPossibleImportKeys.remove(QLatin1String("QtQuick/PrivateWidgets"));
+
+ QList<QmlJS::Import> allImports = m_scopeChain->context()->imports(m_document.data())->all();
+
+ foreach (const QmlJS::Import &import, allImports) {
+ filteredPossibleImportKeys.remove(import.info.path());
+ }
+
+ foreach (const ImportKey &importKey, filteredPossibleImportKeys) {
+ QString libraryName = importKey.splitPath.join(QLatin1Char('.'));
+ QString version = QString(QStringLiteral("%1.%2").arg(importKey.majorVersion).arg(importKey.minorVersion));
+ possibleImports.append(Import::createLibraryImport(libraryName, version));
+ }
+
+ if ( m_rewriterView->isAttached())
+ m_rewriterView->model()->setPossibleImports(possibleImports);
+}
+
+void TextToModelMerger::setupUsedImports()
+{
+ QList<QmlJS::Import> allImports = m_scopeChain->context()->imports(m_document.data())->all();
+
+ QList<Import> usedImports;
+
+ foreach (const QmlJS::Import &import, allImports) {
+ if (import.used) {
+ if (import.info.type() == ImportType::Library) {
+ usedImports.append(Import::createLibraryImport(import.info.name(), import.info.version().toString(), import.info.as()));
+ } else if (import.info.type() == ImportType::Directory || import.info.type() == ImportType::File) {
+ usedImports.append(Import::createFileImport(import.info.name(), import.info.version().toString(), import.info.as()));
+ }
+ }
+ }
+ // even if not explicitly used we probably want to keep QtQuick imports
+ usedImports.append(Import::createLibraryImport("QtQuick", "1.0"));
+ usedImports.append(Import::createLibraryImport("QtQuick", "1.1"));
+ usedImports.append(Import::createLibraryImport("QtQuick", "2.0"));
+ usedImports.append(Import::createLibraryImport("QtQuick", "2.1"));
+
+ if (m_rewriterView->isAttached())
+ m_rewriterView->model()->setUsedImports(usedImports);
+}
+
bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceHandler)
{
// qDebug() << "TextToModelMerger::load with data:" << data;
@@ -751,7 +813,11 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
return false;
}
snapshot.insert(doc);
- ReadingContext ctxt(snapshot, doc, importPaths);
+ QmlJS::ViewerContext vContext;
+ vContext.language = QmlJS::Language::Qml;
+ vContext.paths = importPaths;
+ vContext.flags = QmlJS::ViewerContext::Complete;
+ ReadingContext ctxt(snapshot, doc, vContext);
m_scopeChain = QSharedPointer<const ScopeChain>(
new ScopeChain(ctxt.scopeChain()));
m_document = doc;
@@ -764,6 +830,8 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
}
setupImports(doc, differenceHandler);
+ setupPossibleImports(snapshot, vContext);
+ setupUsedImports();
if (m_rewriterView->model()->imports().isEmpty()) {
const QmlJS::DiagnosticMessage diagnosticMessage(QmlJS::Severity::Error, AST::SourceLocation(0, 0, 0, 0), QCoreApplication::translate("QmlDesigner::TextToModelMerger", "No import statements found"));
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
index 8c98376db2..d82bf851fe 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
@@ -59,6 +59,8 @@ public:
bool isActive() const;
void setupImports(const QmlJS::Document::Ptr &doc, DifferenceHandler &differenceHandler);
+ void setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext);
+ void setupUsedImports();
bool load(const QString &data, DifferenceHandler &differenceHandler);
RewriterView *view() const
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp
index a8b7d70914..48a16d0de0 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.cpp
+++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp
@@ -831,7 +831,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
- Link link(snapshot, modelManager->importPaths(), modelManager->builtins(doc));
+ Link link(snapshot, modelManager->defaultVContext(), modelManager->builtins(doc));
ContextPtr context = link();
ScopeChain scopeChain(doc, context);
diff --git a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp
index 2e4a73b57e..30b3422cc5 100644
--- a/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp
+++ b/src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp
@@ -122,7 +122,7 @@ QmlJSTools::SemanticInfo SemanticInfoUpdater::makeNewSemanticInfo(const QmlJS::D
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
- Link link(semanticInfo.snapshot, modelManager->importPaths(), modelManager->builtins(doc));
+ Link link(semanticInfo.snapshot, modelManager->defaultVContext(), modelManager->builtins(doc));
semanticInfo.context = link(doc, &semanticInfo.semanticMessages);
ScopeChain *scopeChain = new ScopeChain(doc, semanticInfo.context);
diff --git a/src/plugins/qmljseditor/qmltaskmanager.cpp b/src/plugins/qmljseditor/qmltaskmanager.cpp
index 42f78bec19..40d19319aa 100644
--- a/src/plugins/qmljseditor/qmltaskmanager.cpp
+++ b/src/plugins/qmljseditor/qmltaskmanager.cpp
@@ -92,13 +92,13 @@ static QList<ProjectExplorer::Task> convertToTasks(const QList<StaticAnalysis::M
void QmlTaskManager::collectMessages(
QFutureInterface<FileErrorMessages> &future,
Snapshot snapshot, QList<ModelManagerInterface::ProjectInfo> projectInfos,
- QStringList importPaths, bool updateSemantic)
+ ViewerContext vContext, bool updateSemantic)
{
foreach (const ModelManagerInterface::ProjectInfo &info, projectInfos) {
QHash<QString, QList<DiagnosticMessage> > linkMessages;
ContextPtr context;
if (updateSemantic) {
- Link link(snapshot, importPaths, snapshot.libraryInfo(info.qtImportsPath));
+ Link link(snapshot, vContext, snapshot.libraryInfo(info.qtImportsPath));
context = link(&linkMessages);
}
@@ -161,7 +161,7 @@ void QmlTaskManager::updateMessagesNow(bool updateSemantic)
QFuture<FileErrorMessages> future =
QtConcurrent::run<FileErrorMessages>(
&collectMessages, modelManager->newestSnapshot(), modelManager->projectInfos(),
- modelManager->importPaths(), updateSemantic);
+ modelManager->defaultVContext(), updateSemantic);
m_messageCollector.setFuture(future);
}
diff --git a/src/plugins/qmljseditor/qmltaskmanager.h b/src/plugins/qmljseditor/qmltaskmanager.h
index 986a2e65f3..f7aaf0ab74 100644
--- a/src/plugins/qmljseditor/qmltaskmanager.h
+++ b/src/plugins/qmljseditor/qmltaskmanager.h
@@ -85,7 +85,7 @@ private:
static void collectMessages(QFutureInterface<FileErrorMessages> &future,
QmlJS::Snapshot snapshot,
QList<QmlJS::ModelManagerInterface::ProjectInfo> projectInfos,
- QStringList importPaths,
+ QmlJS::ViewerContext vContext,
bool updateSemantic);
private:
diff --git a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp
index 0d2bd263f5..13c88da73f 100644
--- a/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp
+++ b/src/plugins/qmljstools/qmljsfindexportedcpptypes.cpp
@@ -609,14 +609,12 @@ static LanguageUtils::FakeMetaObject::Ptr buildFakeMetaObject(
BaseClass *base = klass->baseClassAt(0);
if (!base->name())
return fmo;
-
const QString baseClassName = namePrinter.prettyName(base->name());
fmo->setSuperclassName(baseClassName);
Class *baseClass = lookupClass(baseClassName, klass, typeOf);
if (!baseClass)
return fmo;
-
buildFakeMetaObject(baseClass, fakeMetaObjects, typeOf);
}
@@ -735,8 +733,10 @@ void FindExportedCppTypes::operator()(const CPlusPlus::Document::Ptr &document)
// convert to list of FakeMetaObject::ConstPtr
m_exportedTypes.reserve(fakeMetaObjects.size());
- foreach (const LanguageUtils::FakeMetaObject::Ptr &fmo, fakeMetaObjects)
+ foreach (const LanguageUtils::FakeMetaObject::Ptr &fmo, fakeMetaObjects) {
+ fmo->updateFingerprint();
m_exportedTypes += fmo;
+ }
}
QList<LanguageUtils::FakeMetaObject::ConstPtr> FindExportedCppTypes::exportedTypes() const
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index 46beb6a345..61470f40c2 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -49,6 +49,7 @@
#include <qtsupport/qmldumptool.h>
#include <qtsupport/qtsupportconstants.h>
#include <utils/hostosinfo.h>
+#include <utils/function.h>
#include <extensionsystem/pluginmanager.h>
#include <QDir>
@@ -360,7 +361,7 @@ QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles,
QFuture<void> result = QtConcurrent::run(&ModelManager::parse,
workingCopy(), sourceFiles,
- this,
+ this, Language::Qml,
emitDocumentOnDiskChanged);
if (m_synchronizer.futures().size() > 10) {
@@ -386,7 +387,7 @@ void ModelManager::fileChangedOnDisk(const QString &path)
{
QtConcurrent::run(&ModelManager::parse,
workingCopy(), QStringList() << path,
- this, true);
+ this, Language::Unknown, true);
}
void ModelManager::removeFiles(const QStringList &files)
@@ -700,7 +701,8 @@ static bool findNewQmlLibraryInPath(const QString &path,
ModelManager *modelManager,
QStringList *importedFiles,
QSet<QString> *scannedPaths,
- QSet<QString> *newLibraries)
+ QSet<QString> *newLibraries,
+ bool ignoreMissing)
{
// if we know there is a library, done
const LibraryInfo &existingInfo = snapshot.libraryInfo(path);
@@ -715,8 +717,10 @@ static bool findNewQmlLibraryInPath(const QString &path,
const QDir dir(path);
QFile qmldirFile(dir.filePath(QLatin1String("qmldir")));
if (!qmldirFile.exists()) {
- LibraryInfo libraryInfo(LibraryInfo::NotFound);
- modelManager->updateLibraryInfo(path, libraryInfo);
+ if (!ignoreMissing) {
+ LibraryInfo libraryInfo(LibraryInfo::NotFound);
+ modelManager->updateLibraryInfo(path, libraryInfo);
+ }
return false;
}
@@ -765,18 +769,18 @@ static void findNewQmlLibrary(
QString::number(version.minorVersion()));
findNewQmlLibraryInPath(
libraryPath, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries);
+ importedFiles, scannedPaths, newLibraries, false);
libraryPath = QString::fromLatin1("%1.%2").arg(
path,
QString::number(version.majorVersion()));
findNewQmlLibraryInPath(
libraryPath, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries);
+ importedFiles, scannedPaths, newLibraries, false);
findNewQmlLibraryInPath(
path, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries);
+ importedFiles, scannedPaths, newLibraries, false);
}
static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snapshot,
@@ -785,7 +789,7 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap
{
// scan current dir
findNewQmlLibraryInPath(doc->path(), snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries);
+ importedFiles, scannedPaths, newLibraries, false);
// scan dir and lib imports
const QStringList importPaths = modelManager->importPaths();
@@ -793,7 +797,7 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap
if (import.type() == ImportType::Directory) {
const QString targetPath = import.path();
findNewQmlLibraryInPath(targetPath, snapshot, modelManager,
- importedFiles, scannedPaths, newLibraries);
+ importedFiles, scannedPaths, newLibraries, false);
}
if (import.type() == ImportType::Library) {
@@ -808,24 +812,18 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap
}
}
-void ModelManager::parse(QFutureInterface<void> &future,
- WorkingCopy workingCopy,
- QStringList files,
- ModelManager *modelManager,
- bool emitDocChangedOnDisk)
+void ModelManager::parseLoop(QSet<QString> &scannedPaths,
+ QSet<QString> &newLibraries,
+ WorkingCopy workingCopy,
+ QStringList files,
+ ModelManager *modelManager,
+ Language::Enum mainLanguage,
+ bool emitDocChangedOnDisk,
+ Utils::function<bool(qreal)> reportProgress)
{
- int progressRange = files.size();
- future.setProgressRange(0, progressRange);
-
- // paths we have scanned for files and added to the files list
- QSet<QString> scannedPaths;
- // libraries we've found while scanning imports
- QSet<QString> newLibraries;
-
for (int i = 0; i < files.size(); ++i) {
- if (future.isCanceled())
- break;
- future.setProgressValue(qreal(i) / files.size() * progressRange);
+ if (!reportProgress(qreal(i) / files.size()))
+ return;
const QString fileName = files.at(i);
@@ -835,7 +833,9 @@ void ModelManager::parse(QFutureInterface<void> &future,
modelManager->updateQrcFile(fileName);
continue;
}
-
+ if (language == Language::Qml
+ && (mainLanguage == Language::QmlQtQuick1 || Language::QmlQtQuick2))
+ language = mainLanguage;
QString contents;
int documentRevision = 0;
@@ -878,7 +878,116 @@ void ModelManager::parse(QFutureInterface<void> &future,
if (emitDocChangedOnDisk)
modelManager->emitDocumentChangedOnDisk(doc);
}
+}
+
+class FutureReporter
+{
+public:
+ FutureReporter(QFutureInterface<void> &future, int multiplier = 100, int base = 0)
+ :future(future), multiplier(multiplier), base(base)
+ { }
+ bool operator()(qreal val)
+ {
+ if (future.isCanceled())
+ return false;
+ future.setProgressValue(int(base + multiplier * val));
+ return true;
+ }
+private:
+ QFutureInterface<void> &future;
+ int multiplier;
+ int base;
+};
+
+void ModelManager::parse(QFutureInterface<void> &future,
+ WorkingCopy workingCopy,
+ QStringList files,
+ ModelManager *modelManager,
+ Language::Enum mainLanguage,
+ bool emitDocChangedOnDisk)
+{
+ FutureReporter reporter(future);
+ future.setProgressRange(0, 100);
+
+ // paths we have scanned for files and added to the files list
+ QSet<QString> scannedPaths;
+ // libraries we've found while scanning imports
+ QSet<QString> newLibraries;
+ parseLoop(scannedPaths, newLibraries, workingCopy, files, modelManager, mainLanguage,
+ emitDocChangedOnDisk, reporter);
+ future.setProgressValue(100);
+}
+
+struct ScanItem {
+ QString path;
+ int depth;
+ ScanItem(QString path = QString(), int depth = 0)
+ : path(path), depth(depth)
+ { }
+};
+
+void ModelManager::importScan(QFutureInterface<void> &future,
+ ModelManagerInterface::WorkingCopy workingCopy,
+ QStringList paths, ModelManager *modelManager,
+ Language::Enum language,
+ bool emitDocChangedOnDisk)
+{
+ // paths we have scanned for files and added to the files list
+ QSet<QString> scannedPaths = modelManager->m_scannedPaths;
+ // libraries we've found while scanning imports
+ QSet<QString> newLibraries;
+ QVector<ScanItem> pathsToScan;
+ pathsToScan.reserve(paths.size());
+ foreach (const QString &path, paths) {
+ QString cPath = QDir::cleanPath(path);
+ if (modelManager->m_scannedPaths.contains(cPath))
+ continue;
+ pathsToScan.append(ScanItem(cPath));
+ }
+ const int maxScanDepth = 5;
+ int progressRange = pathsToScan.size() * (1 << (2 + maxScanDepth));
+ int totalWork(progressRange), workDone(0);
+ future.setProgressRange(0, progressRange); // update max length while iterating?
+ const bool libOnly = true; // FIXME remove when tested more
+ while (!pathsToScan.isEmpty() && !future.isCanceled()) {
+ ScanItem toScan = pathsToScan.last();
+ pathsToScan.pop_back();
+ int pathBudget = (maxScanDepth + 2 - toScan.depth);
+ if (!scannedPaths.contains(toScan.path)) {
+ QStringList importedFiles;
+ const Snapshot snapshot = modelManager->snapshot();
+ if (!findNewQmlLibraryInPath(toScan.path, snapshot, modelManager, &importedFiles,
+ &scannedPaths, &newLibraries, true)
+ && !libOnly && snapshot.documentsInDirectory(toScan.path).isEmpty())
+ importedFiles += qmlFilesInDirectory(toScan.path);
+ workDone += 1;
+ future.setProgressValue(progressRange * workDone / totalWork);
+ if (!importedFiles.isEmpty()) {
+ FutureReporter reporter(future, progressRange * pathBudget / (4 * totalWork),
+ progressRange * workDone / totalWork);
+ parseLoop(scannedPaths, newLibraries, workingCopy, importedFiles, modelManager,
+ language, emitDocChangedOnDisk, reporter); // run in parallel??
+ importedFiles.clear();
+ }
+ workDone += pathBudget / 4 - 1;
+ future.setProgressValue(progressRange * workDone / totalWork);
+ } else {
+ workDone += pathBudget / 4;
+ }
+ // always descend tree, as we might have just scanned with a smaller depth
+ if (toScan.depth < maxScanDepth) {
+ QDir dir(toScan.path);
+ QStringList subDirs(dir.entryList(QDir::Dirs));
+ workDone += 1;
+ totalWork += pathBudget / 2 * subDirs.size() - pathBudget * 3 / 4 + 1;
+ foreach (const QString path, subDirs)
+ pathsToScan.append(ScanItem(dir.absoluteFilePath(path), toScan.depth + 1));
+ } else {
+ workDone += pathBudget *3 / 4;
+ }
+ future.setProgressValue(progressRange * workDone / totalWork);
+ }
future.setProgressValue(progressRange);
}
@@ -993,6 +1102,33 @@ void ModelManager::updateImportPaths()
findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
updateSourceFiles(importedFiles, true);
+
+ QStringList pathToScan;
+ foreach (QString importPath, allImportPaths)
+ if (!m_scannedPaths.contains(importPath))
+ pathToScan.append(importPath);
+
+ if (pathToScan.count() > 1) {
+ QFuture<void> result = QtConcurrent::run(&ModelManager::importScan,
+ workingCopy(), pathToScan,
+ this, Language::Qml,
+ true);
+
+ if (m_synchronizer.futures().size() > 10) {
+ QList<QFuture<void> > futures = m_synchronizer.futures();
+
+ m_synchronizer.clearFutures();
+
+ foreach (const QFuture<void> &future, futures) {
+ if (! (future.isFinished() || future.isCanceled()))
+ m_synchronizer.addFuture(future);
+ }
+ }
+
+ m_synchronizer.addFuture(result);
+
+ ProgressManager::addTask(result, tr("Qml import scan"), Constants::TASK_IMPORT_SCAN);
+ }
}
void ModelManager::loadPluginTypes(const QString &libraryPath, const QString &importPath,
@@ -1121,6 +1257,35 @@ LibraryInfo ModelManager::builtins(const Document::Ptr &doc) const
return _validSnapshot.libraryInfo(info.qtImportsPath);
}
+ViewerContext ModelManager::completeVContext(const ViewerContext &vCtx,
+ const Document::Ptr &doc) const
+{
+ Q_UNUSED(doc);
+ ViewerContext res = vCtx;
+ switch (res.flags) {
+ case ViewerContext::Complete:
+ break;
+ case ViewerContext::AddQtPath:
+ case ViewerContext::AddAllPaths:
+ res.paths << importPaths();
+ }
+ res.flags = ViewerContext::Complete;
+ return res;
+}
+
+ViewerContext ModelManager::defaultVContext(bool autoComplete, const Document::Ptr &doc) const
+{
+ if (autoComplete)
+ return completeVContext(m_vContext, doc);
+ else
+ return m_vContext;
+}
+
+void ModelManager::setDefaultVContext(const ViewerContext &vContext)
+{
+ m_vContext = vContext;
+}
+
void ModelManager::joinAllThreads()
{
foreach (QFuture<void> future, m_synchronizer.futures())
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h
index 04cb3d5d4e..6d30d536e2 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.h
+++ b/src/plugins/qmljstools/qmljsmodelmanager.h
@@ -34,6 +34,7 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsqrcparser.h>
+#include <qmljs/qmljsconstants.h>
#include <cplusplus/CppDocument.h>
#include <utils/qtcoverride.h>
@@ -115,6 +116,14 @@ public:
QmlJS::LibraryInfo builtins(const QmlJS::Document::Ptr &doc) const QTC_OVERRIDE;
+ QmlJS::ViewerContext completeVContext(
+ const QmlJS::ViewerContext &vCtx,
+ const QmlJS::Document::Ptr &doc = QmlJS::Document::Ptr(0)) const QTC_OVERRIDE;
+ QmlJS::ViewerContext defaultVContext(
+ bool autoComplete = true,
+ const QmlJS::Document::Ptr &doc = QmlJS::Document::Ptr(0)) const QTC_OVERRIDE;
+ void setDefaultVContext(const QmlJS::ViewerContext &vContext) QTC_OVERRIDE;
+
void joinAllThreads() QTC_OVERRIDE;
public slots:
@@ -127,11 +136,22 @@ protected:
QFuture<void> refreshSourceFiles(const QStringList &sourceFiles,
bool emitDocumentOnDiskChanged);
+ static void parseLoop(QSet<QString> &scannedPaths, QSet<QString> &newLibraries,
+ WorkingCopy workingCopy, QStringList files, ModelManager *modelManager,
+ QmlJS::Language::Enum mainLanguage, bool emitDocChangedOnDisk,
+ Utils::function<bool (qreal)> reportProgress);
static void parse(QFutureInterface<void> &future,
WorkingCopy workingCopy,
QStringList files,
ModelManager *modelManager,
+ QmlJS::Language::Enum mainLanguage,
bool emitDocChangedOnDisk);
+ static void importScan(QFutureInterface<void> &future,
+ WorkingCopy workingCopy,
+ QStringList paths,
+ ModelManager *modelManager,
+ QmlJS::Language::Enum mainLanguage,
+ bool emitDocChangedOnDisk);
void loadQmlTypeDescriptions();
void loadQmlTypeDescriptions(const QString &path);
@@ -158,6 +178,8 @@ private:
QStringList m_defaultImportPaths;
QmlJS::QmlLanguageBundles m_activeBundles;
QmlJS::QmlLanguageBundles m_extendedBundles;
+ QmlJS::ViewerContext m_vContext;
+ QSet<QString> m_scannedPaths;
QTimer *m_updateCppQmlTypesTimer;
QTimer *m_asyncResetTimer;
diff --git a/src/plugins/qmljstools/qmljsplugindumper.cpp b/src/plugins/qmljstools/qmljsplugindumper.cpp
index bb8a4a8835..d0fb8a7b46 100644
--- a/src/plugins/qmljstools/qmljsplugindumper.cpp
+++ b/src/plugins/qmljstools/qmljsplugindumper.cpp
@@ -339,6 +339,7 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
if (!warning.isEmpty())
printParseWarnings(libraryPath, warning);
}
+ libraryInfo.updateFingerprint();
m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
}
@@ -361,6 +362,7 @@ void PluginDumper::qmlPluginTypeDumpError(QProcess::ProcessError)
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages));
+ libraryInfo.updateFingerprint();
m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
}
}
@@ -418,6 +420,7 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
if (!warnings.isEmpty())
printParseWarnings(libraryPath, warnings.join(QLatin1String("\n")));
+ libraryInfo.updateFingerprint();
m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
}
@@ -456,6 +459,7 @@ void PluginDumper::dump(const Plugin &plugin)
}
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, errorMessage);
+ libraryInfo.updateFingerprint();
m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
return;
}
diff --git a/src/plugins/qmljstools/qmljstools_test.cpp b/src/plugins/qmljstools/qmljstools_test.cpp
index e4336b0146..010da935dc 100644
--- a/src/plugins/qmljstools/qmljstools_test.cpp
+++ b/src/plugins/qmljstools/qmljstools_test.cpp
@@ -53,7 +53,7 @@ void QmlJSTools::Internal::QmlJSToolsPlugin::test_basic()
Document::Ptr doc = snapshot.document(welcomescreenRootPath);
QVERIFY(doc && doc->isQmlDocument());
- ContextPtr context = Link(snapshot, QStringList(), LibraryInfo())();
+ ContextPtr context = Link(snapshot, ViewerContext(), LibraryInfo())();
QVERIFY(context);
const CppComponentValue *rectangleValue = context->valueOwner()->cppQmlTypes().objectByQualifiedName(
diff --git a/src/plugins/qmljstools/qmljstoolsconstants.h b/src/plugins/qmljstools/qmljstoolsconstants.h
index 4662204fe0..2a0d7644f1 100644
--- a/src/plugins/qmljstools/qmljstoolsconstants.h
+++ b/src/plugins/qmljstools/qmljstoolsconstants.h
@@ -43,6 +43,7 @@ const char JS_MIMETYPE[] = "application/javascript";
const char JSON_MIMETYPE[] = "application/json";
const char TASK_INDEX[] = "QmlJSEditor.TaskIndex";
+const char TASK_IMPORT_SCAN[] = "QmlJSEditor.TaskImportScan";
const char QML_JS_CODE_STYLE_SETTINGS_ID[] = "A.Code Style";
const char QML_JS_CODE_STYLE_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("QmlJSTools", "Code Style");
diff --git a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp
index 9107e53d48..3503807896 100644
--- a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp
+++ b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp
@@ -92,6 +92,13 @@ void QmlProfilerCanvas::componentComplete()
QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0);
}
QQuickItem::componentComplete();
+ requestRedraw();
+}
+
+void QmlProfilerCanvas::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+ requestRedraw();
}
}
diff --git a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h
index b320601396..4a360d012c 100644
--- a/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h
+++ b/src/plugins/qmlprofiler/canvas/qmlprofilercanvas.h
@@ -61,6 +61,7 @@ private slots:
protected:
virtual void paint(QPainter *);
virtual void componentComplete();
+ virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
private:
Context2D *m_context2d;
diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml
index f067422819..9b2864c19b 100644
--- a/src/plugins/qmlprofiler/qml/MainView.qml
+++ b/src/plugins/qmlprofiler/qml/MainView.qml
@@ -330,6 +330,7 @@ Rectangle {
contentWidth: 0
height: labels.height + labelsTail.height
flickableDirection: Flickable.HorizontalFlick
+ boundsBehavior: Flickable.StopAtBounds
onContentXChanged: view.updateZoomControl()
clip:true
diff --git a/src/plugins/qmlprofiler/qml/SelectionRange.qml b/src/plugins/qmlprofiler/qml/SelectionRange.qml
index 86fdb2a7c6..e3930c7d16 100644
--- a/src/plugins/qmlprofiler/qml/SelectionRange.qml
+++ b/src/plugins/qmlprofiler/qml/SelectionRange.qml
@@ -69,6 +69,11 @@ RangeMover {
}
function setPos(pos) {
+ if (pos < 0)
+ pos = 0;
+ else if (pos > width)
+ pos = width;
+
switch (creationState) {
case 1: {
setLeft(pos);
diff --git a/src/plugins/qmlprofiler/qml/TimeDisplay.qml b/src/plugins/qmlprofiler/qml/TimeDisplay.qml
index 81bc47d337..5a6a63b9e4 100644
--- a/src/plugins/qmlprofiler/qml/TimeDisplay.qml
+++ b/src/plugins/qmlprofiler/qml/TimeDisplay.qml
@@ -38,17 +38,6 @@ Canvas2D {
property real endTime : 0
property real timePerPixel: 0
-
- Component.onCompleted: {
- requestRedraw();
- }
- onWidthChanged: {
- requestRedraw();
- }
- onHeightChanged: {
- requestRedraw();
- }
-
Connections {
target: zoomControl
onRangeChanged: {
diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml
index ee06d501d8..6d48cbb014 100644
--- a/src/plugins/qmlprofiler/qml/TimeMarks.qml
+++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml
@@ -38,21 +38,6 @@ Canvas2D {
property real endTime
property real timePerPixel
- Component.onCompleted: {
- requestRedraw();
- }
-
- onWidthChanged: {
- requestRedraw();
- }
- onHeightChanged: {
- requestRedraw();
- }
-
- onYChanged: {
- requestRedraw();
- }
-
Connections {
target: labels
onHeightChanged: { requestRedraw(); }
diff --git a/src/plugins/qnx/blackberryconfiguration.cpp b/src/plugins/qnx/blackberryconfiguration.cpp
index 397c82ab94..9125b07a62 100644
--- a/src/plugins/qnx/blackberryconfiguration.cpp
+++ b/src/plugins/qnx/blackberryconfiguration.cpp
@@ -73,27 +73,27 @@ BlackBerryConfiguration::BlackBerryConfiguration(const FileName &ndkEnvFile, boo
m_qnxEnv = QnxUtils::qnxEnvironmentFromNdkFile(m_ndkEnvFile.toString());
QString ndkTarget;
- QString qnxHost;
foreach (const Utils::EnvironmentItem &item, m_qnxEnv) {
if (item.name == QLatin1String("QNX_TARGET"))
ndkTarget = item.value;
else if (item.name == QLatin1String("QNX_HOST"))
- qnxHost = item.value;
+ m_qnxHost = item.value;
}
- QString sep = QString::fromLatin1("%1qnx6").arg(QDir::separator());
- m_targetName = ndkTarget.split(sep).first().split(QDir::separator()).last();
+ // The QNX_TARGET value is using Unix-like separator on all platforms.
+ QString sep = QString::fromLatin1("/qnx6");
+ m_targetName = ndkTarget.split(sep).first().split(QLatin1Char('/')).last();
if (QDir(ndkTarget).exists())
m_sysRoot = FileName::fromString(ndkTarget);
- FileName qmake4Path = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/qmake")));
- FileName qmake5Path = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/qt5/qmake")));
- FileName gccPath = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/qcc")));
- FileName deviceGdbPath = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/ntoarm-gdb")));
- FileName simulatorGdbPath = QnxUtils::executableWithExtension(FileName::fromString(qnxHost + QLatin1String("/usr/bin/ntox86-gdb")));
+ FileName qmake4Path = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/qmake")));
+ FileName qmake5Path = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/qt5/qmake")));
+ FileName gccPath = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/qcc")));
+ FileName deviceGdbPath = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/ntoarm-gdb")));
+ FileName simulatorGdbPath = QnxUtils::executableWithExtension(FileName::fromString(m_qnxHost + QLatin1String("/usr/bin/ntox86-gdb")));
if (qmake4Path.toFileInfo().exists())
m_qmake4BinaryFile = qmake4Path;
@@ -126,6 +126,11 @@ QString BlackBerryConfiguration::targetName() const
return m_targetName;
}
+QString BlackBerryConfiguration::qnxHost() const
+{
+ return m_qnxHost;
+}
+
bool BlackBerryConfiguration::isAutoDetected() const
{
return m_isAutoDetected;
diff --git a/src/plugins/qnx/blackberryconfiguration.h b/src/plugins/qnx/blackberryconfiguration.h
index 51473a5b0a..1b31d186b3 100644
--- a/src/plugins/qnx/blackberryconfiguration.h
+++ b/src/plugins/qnx/blackberryconfiguration.h
@@ -66,6 +66,7 @@ public:
QString ndkPath() const;
QString displayName() const;
QString targetName() const;
+ QString qnxHost() const;
bool isAutoDetected() const;
bool isActive() const;
bool isValid() const;
@@ -81,6 +82,7 @@ public:
private:
QString m_displayName;
QString m_targetName;
+ QString m_qnxHost;
bool m_isAutoDetected;
Utils::FileName m_ndkEnvFile;
Utils::FileName m_qmake4BinaryFile;
diff --git a/src/plugins/qnx/blackberryinstallwizardpages.cpp b/src/plugins/qnx/blackberryinstallwizardpages.cpp
index b854475ff5..b2bd3f5dc0 100644
--- a/src/plugins/qnx/blackberryinstallwizardpages.cpp
+++ b/src/plugins/qnx/blackberryinstallwizardpages.cpp
@@ -64,10 +64,13 @@ NdkPathChooser::NdkPathChooser(Mode mode, QWidget *parent)
: Utils::PathChooser(parent)
, m_mode(mode)
{
- if (m_mode == NdkPathChooser::InstallMode)
+ if (m_mode == NdkPathChooser::InstallMode) {
setExpectedKind(Utils::PathChooser::Directory);
- else
+ } else {
setExpectedKind(Utils::PathChooser::File);
+ setPromptDialogFilter(Utils::HostOsInfo::isWindowsHost() ? QLatin1String("*.bat") :
+ QLatin1String("*.sh"));
+ }
}
bool NdkPathChooser::validatePath(const QString &path, QString *errorMessage)
@@ -80,7 +83,10 @@ bool NdkPathChooser::validatePath(const QString &path, QString *errorMessage)
return !(QnxUtils::sdkInstallerPath(path).isEmpty());
QFileInfo fi(path);
- return (fi.suffix() == QLatin1String("sh") || fi.suffix() == QLatin1String("bat"));
+ if (Utils::HostOsInfo::isWindowsHost())
+ return fi.suffix() == QLatin1String("bat");
+
+ return fi.suffix() == QLatin1String("sh");
}
//------------------------------------------------------------------
diff --git a/src/plugins/qnx/blackberryndksettingswidget.cpp b/src/plugins/qnx/blackberryndksettingswidget.cpp
index 9ca62b4aa6..a1982539e7 100644
--- a/src/plugins/qnx/blackberryndksettingswidget.cpp
+++ b/src/plugins/qnx/blackberryndksettingswidget.cpp
@@ -144,15 +144,18 @@ void BlackBerryNDKSettingsWidget::updateInfoTable(QTreeWidgetItem* currentItem)
if (!config)
return;
- foreach (const NdkInstallInformation &ndkInfo, QnxUtils::installedNdks())
- {
- if (ndkInfo.name == config->displayName()) {
- m_ui->baseNameLabel->setText(ndkInfo.name);
- m_ui->ndkPathLabel->setText(ndkInfo.path);
- m_ui->versionLabel->setText(ndkInfo.version);
- m_ui->hostLabel->setText(ndkInfo.host);
- m_ui->targetLabel->setText(ndkInfo.target);
- break;
+ m_ui->baseNameLabel->setText(config->displayName());
+ m_ui->ndkPathLabel->setText(QDir::toNativeSeparators(config->ndkPath()));
+ m_ui->hostLabel->setText(QDir::toNativeSeparators(config->qnxHost()));
+ m_ui->targetLabel->setText(QDir::toNativeSeparators(config->sysRoot().toString()));
+ m_ui->versionLabel->clear();
+ // TODO: Add a versionNumber attribute for the BlackBerryConfiguration class
+ if (config->isAutoDetected()) {
+ foreach (const NdkInstallInformation &ndkInfo, QnxUtils::installedNdks()) {
+ if (ndkInfo.name == config->displayName()) {
+ m_ui->versionLabel->setText(ndkInfo.version);
+ break;
+ }
}
}
diff --git a/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp b/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp
index 3291e0c762..d21fa5af86 100644
--- a/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp
+++ b/src/plugins/qnx/cascadesimport/cascadesimportwizard.cpp
@@ -129,11 +129,6 @@ CascadesImportWizard::~CascadesImportWizard()
{
}
-Core::FeatureSet CascadesImportWizard::requiredFeatures() const
-{
- return Core::FeatureSet(Constants::QNX_BB_FEATURE);
-}
-
Core::BaseFileWizard::ExtensionList CascadesImportWizard::selectExtensions()
{
return Core::BaseFileWizard::ExtensionList();
diff --git a/src/plugins/qnx/cascadesimport/cascadesimportwizard.h b/src/plugins/qnx/cascadesimport/cascadesimportwizard.h
index 599be858e6..9a60db994e 100644
--- a/src/plugins/qnx/cascadesimport/cascadesimportwizard.h
+++ b/src/plugins/qnx/cascadesimport/cascadesimportwizard.h
@@ -68,7 +68,6 @@ public:
CascadesImportWizard(QObject *parent = 0);
virtual ~CascadesImportWizard();
- Core::FeatureSet requiredFeatures() const;
protected:
ExtensionList selectExtensions();
QWizard* createWizardDialog(QWidget *parent,
diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp
index 19211acdbb..a894b2f092 100644
--- a/src/plugins/texteditor/generichighlighter/highlighter.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp
@@ -75,7 +75,8 @@ Highlighter::Highlighter(QTextDocument *parent) :
<< TextEditor::C_TEXT // TODO : add style for error (eg. red underline)
<< TextEditor::C_FUNCTION
<< TextEditor::C_TEXT
- << TextEditor::C_TEXT;
+ << TextEditor::C_TEXT
+ << TextEditor::C_LOCAL;
}
setTextFormatCategories(categories);
@@ -113,6 +114,7 @@ KateFormatMap::KateFormatMap()
m_ids.insert(QLatin1String("dsFunction"), Highlighter::Function);
m_ids.insert(QLatin1String("dsRegionMarker"), Highlighter::RegionMarker);
m_ids.insert(QLatin1String("dsOthers"), Highlighter::Others);
+ m_ids.insert(QLatin1String("dsIdentifier"), Highlighter::Identifier);
}
Q_GLOBAL_STATIC(KateFormatMap, kateFormatMap)
diff --git a/src/plugins/texteditor/generichighlighter/highlighter.h b/src/plugins/texteditor/generichighlighter/highlighter.h
index 968a48a6c1..ef0498036a 100644
--- a/src/plugins/texteditor/generichighlighter/highlighter.h
+++ b/src/plugins/texteditor/generichighlighter/highlighter.h
@@ -83,7 +83,8 @@ public:
Error,
Function,
RegionMarker,
- Others
+ Others,
+ Identifier
};
void setTabSettings(const TabSettings &ts);