summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--README.md4
-rw-r--r--dist/clangformat/.clang-format115
-rw-r--r--dist/clangformat/README.md157
-rw-r--r--doc/src/android/deploying-android.qdoc16
-rw-r--r--doc/src/editors/creator-beautifier.qdoc8
-rw-r--r--doc/src/editors/creator-clang-codemodel.qdoc4
-rw-r--r--doc/src/editors/creator-modeling.qdoc18
-rw-r--r--doc/src/howto/creator-autotest.qdoc12
-rw-r--r--qbs/modules/libclang/functions.js8
-rw-r--r--qbs/modules/qtc/qtc.js6
-rw-r--r--qbs/modules/qtc/qtc.qbs6
-rw-r--r--qtcreator.pri8
-rwxr-xr-xscripts/deployqt.py2
-rw-r--r--share/qtcreator/debugger/dumper.py17
-rw-r--r--share/qtcreator/debugger/gdbbridge.py16
-rw-r--r--share/qtcreator/debugger/lldbbridge.py20
-rw-r--r--share/qtcreator/debugger/misctypes.py31
-rw-r--r--share/qtcreator/debugger/qttypes.py2
-rw-r--r--share/qtcreator/modeleditor/standard.def188
-rw-r--r--share/qtcreator/qml-type-descriptions/builtins.qmltypes1
-rw-r--r--share/qtcreator/qml-type-descriptions/qbs.qmltypes11
-rw-r--r--share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp1
-rw-r--r--share/qtcreator/qml/qmlpuppet/container/instancecontainer.h10
-rw-r--r--share/qtcreator/qml/qmlpuppet/container/sharedmemory_unix.cpp6
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp18
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h9
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri5
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp3
-rw-r--r--share/qtcreator/templates/wizards/autotest/wizard.json13
-rw-r--r--share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/CMakeLists.txt13
-rw-r--r--share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/app.pro25
-rw-r--r--share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp13
-rw-r--r--share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.qml.tpl30
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/MainForm.ui.qml.tpl29
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/file.qbs)0
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/icon.png (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/3dapplication.png)bin671 -> 671 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/icon@2x.png (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/3dapplication@2x.png)bin1193 -> 1193 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/main.qml.tpl67
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/plaincanvas3d/glcode.js (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/plaincanvas3d/glcode.js)0
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/qml.qrc (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/qml.qrc)0
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/threejs/3rdparty/three.js (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/threejs/3rdparty/three.js)0
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/threejs/glcode.js (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/threejs/glcode.js)0
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/wizard.json (renamed from share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/wizard.json)90
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/empty/icon.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-empty.png)bin376 -> 376 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/empty/icon@2x.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-empty@2x.png)bin689 -> 689 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/empty/main.qml.tpl46
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/empty/qml.qrc5
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json)103
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp7
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/main.qml.tpl77
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/qml.qrc9
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/qtquickcontrols2.conf23
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/icon.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-scroll.png)bin573 -> 573 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/icon@2x.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-scroll@2x.png)bin1095 -> 1095 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/main.qml.tpl59
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/qml.qrc6
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json252
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/HomeForm.ui.qml.tpl14
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page1Form.ui.qml.tpl14
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page2Form.ui.qml.tpl14
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/icon.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-stack.png)bin480 -> 480 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/icon@2x.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-stack@2x.png)bin851 -> 851 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/main.qml.tpl99
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/qml.qrc9
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json281
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page1Form.ui.qml.tpl18
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page2Form.ui.qml.tpl18
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/icon.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-swipe.png)bin561 -> 561 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/icon@2x.png (renamed from share/qtcreator/templates/wizards/projects/qtquickapplication/icon-swipe@2x.png)bin1079 -> 1079 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/main.qml.tpl (renamed from share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.qml.tpl)32
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/qml.qrc (renamed from share/qtcreator/templates/wizards/projects/qtquickcontrols2application/qml.qrc)6
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json277
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/CMakeLists.txt13
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1.qml.tpl7
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1Form.ui.qml.tpl24
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/app.pro28
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/file.qbs38
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp18
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/qtquickcontrols2.conf15
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json170
-rw-r--r--share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json70
-rw-r--r--share/qtcreator/themes/flat-dark.creatortheme2
-rw-r--r--src/app/app.pro5
-rw-r--r--src/app/app_version.h.in4
-rw-r--r--src/app/main.cpp36
-rw-r--r--src/libs/3rdparty/cplusplus/Symbols.cpp16
-rw-r--r--src/libs/clangbackendipc/clangbackendipc_dependencies.pri3
-rw-r--r--src/libs/clangbackendipc/projectpartsdonotexistmessage.h77
-rw-r--r--src/libs/clangbackendipc/stringcache.h179
-rw-r--r--src/libs/clangbackendipc/translationunitdoesnotexistmessage.cpp55
-rw-r--r--src/libs/clangsupport/cancelmessage.cpp (renamed from src/libs/clangbackendipc/cancelmessage.cpp)0
-rw-r--r--src/libs/clangsupport/cancelmessage.h (renamed from src/libs/clangbackendipc/cancelmessage.h)2
-rw-r--r--src/libs/clangsupport/clangcodemodelclientinterface.cpp (renamed from src/libs/clangbackendipc/clangcodemodelclientinterface.cpp)9
-rw-r--r--src/libs/clangsupport/clangcodemodelclientinterface.h (renamed from src/libs/clangbackendipc/clangcodemodelclientinterface.h)7
-rw-r--r--src/libs/clangsupport/clangcodemodelclientmessages.h (renamed from src/libs/clangbackendipc/clangcodemodelclientmessages.h)3
-rw-r--r--src/libs/clangsupport/clangcodemodelclientproxy.cpp (renamed from src/libs/clangbackendipc/clangcodemodelclientproxy.cpp)11
-rw-r--r--src/libs/clangsupport/clangcodemodelclientproxy.h (renamed from src/libs/clangbackendipc/clangcodemodelclientproxy.h)5
-rw-r--r--src/libs/clangsupport/clangcodemodelconnectionclient.cpp (renamed from src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp)0
-rw-r--r--src/libs/clangsupport/clangcodemodelconnectionclient.h (renamed from src/libs/clangbackendipc/clangcodemodelconnectionclient.h)0
-rw-r--r--src/libs/clangsupport/clangcodemodelserverinterface.cpp (renamed from src/libs/clangbackendipc/clangcodemodelserverinterface.cpp)3
-rw-r--r--src/libs/clangsupport/clangcodemodelserverinterface.h (renamed from src/libs/clangbackendipc/clangcodemodelserverinterface.h)3
-rw-r--r--src/libs/clangsupport/clangcodemodelservermessages.h (renamed from src/libs/clangbackendipc/clangcodemodelservermessages.h)1
-rw-r--r--src/libs/clangsupport/clangcodemodelserverproxy.cpp (renamed from src/libs/clangbackendipc/clangcodemodelserverproxy.cpp)5
-rw-r--r--src/libs/clangsupport/clangcodemodelserverproxy.h (renamed from src/libs/clangbackendipc/clangcodemodelserverproxy.h)1
-rw-r--r--src/libs/clangsupport/clangrefactoringclientmessages.h (renamed from src/libs/clangbackendipc/clangrefactoringclientmessages.h)0
-rw-r--r--src/libs/clangsupport/clangrefactoringmessages.h (renamed from src/libs/clangbackendipc/clangrefactoringmessages.h)0
-rw-r--r--src/libs/clangsupport/clangrefactoringservermessages.h (renamed from src/libs/clangbackendipc/clangrefactoringservermessages.h)2
-rw-r--r--src/libs/clangsupport/clangsupport-lib.pri (renamed from src/libs/clangbackendipc/clangbackendipc-lib.pri)26
-rw-r--r--src/libs/clangsupport/clangsupport.pro (renamed from src/libs/clangbackendipc/clangbackendipc.pro)2
-rw-r--r--src/libs/clangsupport/clangsupport.qbs (renamed from src/libs/clangbackendipc/clangbackendipc.qbs)4
-rw-r--r--src/libs/clangsupport/clangsupport_dependencies.pri3
-rw-r--r--src/libs/clangsupport/clangsupport_global.h (renamed from src/libs/clangbackendipc/clangbackendipc_global.h)12
-rw-r--r--src/libs/clangsupport/clangsupportdebugutils.cpp (renamed from src/libs/clangbackendipc/clangbackendipcdebugutils.cpp)4
-rw-r--r--src/libs/clangsupport/clangsupportdebugutils.h (renamed from src/libs/clangbackendipc/clangbackendipcdebugutils.h)2
-rw-r--r--src/libs/clangsupport/cmbalivemessage.cpp (renamed from src/libs/clangbackendipc/cmbalivemessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbalivemessage.h (renamed from src/libs/clangbackendipc/cmbalivemessage.h)2
-rw-r--r--src/libs/clangsupport/cmbcodecompletedmessage.cpp (renamed from src/libs/clangbackendipc/cmbcodecompletedmessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbcodecompletedmessage.h (renamed from src/libs/clangbackendipc/cmbcodecompletedmessage.h)0
-rw-r--r--src/libs/clangsupport/cmbcompletecodemessage.cpp (renamed from src/libs/clangbackendipc/cmbcompletecodemessage.cpp)6
-rw-r--r--src/libs/clangsupport/cmbcompletecodemessage.h (renamed from src/libs/clangbackendipc/cmbcompletecodemessage.h)30
-rw-r--r--src/libs/clangsupport/cmbechomessage.cpp (renamed from src/libs/clangbackendipc/cmbechomessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbechomessage.h (renamed from src/libs/clangbackendipc/cmbechomessage.h)2
-rw-r--r--src/libs/clangsupport/cmbendmessage.cpp (renamed from src/libs/clangbackendipc/cmbendmessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbendmessage.h (renamed from src/libs/clangbackendipc/cmbendmessage.h)2
-rw-r--r--src/libs/clangsupport/cmbregisterprojectsforeditormessage.cpp (renamed from src/libs/clangbackendipc/cmbregisterprojectsforeditormessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbregisterprojectsforeditormessage.h (renamed from src/libs/clangbackendipc/cmbregisterprojectsforeditormessage.h)0
-rw-r--r--src/libs/clangsupport/cmbregistertranslationunitsforeditormessage.cpp (renamed from src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbregistertranslationunitsforeditormessage.h (renamed from src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.h)0
-rw-r--r--src/libs/clangsupport/cmbunregisterprojectsforeditormessage.cpp (renamed from src/libs/clangbackendipc/cmbunregisterprojectsforeditormessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbunregisterprojectsforeditormessage.h (renamed from src/libs/clangbackendipc/cmbunregisterprojectsforeditormessage.h)2
-rw-r--r--src/libs/clangsupport/cmbunregistertranslationunitsforeditormessage.cpp (renamed from src/libs/clangbackendipc/cmbunregistertranslationunitsforeditormessage.cpp)0
-rw-r--r--src/libs/clangsupport/cmbunregistertranslationunitsforeditormessage.h (renamed from src/libs/clangbackendipc/cmbunregistertranslationunitsforeditormessage.h)2
-rw-r--r--src/libs/clangsupport/codecompletion.cpp (renamed from src/libs/clangbackendipc/codecompletion.cpp)0
-rw-r--r--src/libs/clangsupport/codecompletion.h (renamed from src/libs/clangbackendipc/codecompletion.h)2
-rw-r--r--src/libs/clangsupport/codecompletionchunk.cpp (renamed from src/libs/clangbackendipc/codecompletionchunk.cpp)0
-rw-r--r--src/libs/clangsupport/codecompletionchunk.h (renamed from src/libs/clangbackendipc/codecompletionchunk.h)2
-rw-r--r--src/libs/clangsupport/connectionclient.cpp (renamed from src/libs/clangbackendipc/connectionclient.cpp)2
-rw-r--r--src/libs/clangsupport/connectionclient.h (renamed from src/libs/clangbackendipc/connectionclient.h)0
-rw-r--r--src/libs/clangsupport/connectionserver.cpp (renamed from src/libs/clangbackendipc/connectionserver.cpp)0
-rw-r--r--src/libs/clangsupport/connectionserver.h (renamed from src/libs/clangbackendipc/connectionserver.h)2
-rw-r--r--src/libs/clangsupport/diagnosticcontainer.cpp (renamed from src/libs/clangbackendipc/diagnosticcontainer.cpp)0
-rw-r--r--src/libs/clangsupport/diagnosticcontainer.h (renamed from src/libs/clangbackendipc/diagnosticcontainer.h)0
-rw-r--r--src/libs/clangsupport/documentannotationschangedmessage.cpp (renamed from src/libs/clangbackendipc/documentannotationschangedmessage.cpp)0
-rw-r--r--src/libs/clangsupport/documentannotationschangedmessage.h (renamed from src/libs/clangbackendipc/documentannotationschangedmessage.h)2
-rw-r--r--src/libs/clangsupport/dynamicastmatcherdiagnosticcontainer.cpp (renamed from src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontainer.cpp)0
-rw-r--r--src/libs/clangsupport/dynamicastmatcherdiagnosticcontainer.h (renamed from src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontainer.h)0
-rw-r--r--src/libs/clangsupport/dynamicastmatcherdiagnosticcontextcontainer.cpp (renamed from src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.cpp)0
-rw-r--r--src/libs/clangsupport/dynamicastmatcherdiagnosticcontextcontainer.h (renamed from src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h)0
-rw-r--r--src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.cpp (renamed from src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp)0
-rw-r--r--src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.h (renamed from src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h)0
-rw-r--r--src/libs/clangsupport/dynamicmatcherdiagnostics.h (renamed from src/libs/clangbackendipc/dynamicmatcherdiagnostics.h)0
-rw-r--r--src/libs/clangsupport/filecontainer.cpp (renamed from src/libs/clangbackendipc/filecontainer.cpp)2
-rw-r--r--src/libs/clangsupport/filecontainer.h (renamed from src/libs/clangbackendipc/filecontainer.h)2
-rw-r--r--src/libs/clangsupport/filecontainerv2.cpp (renamed from src/libs/clangbackendipc/filecontainerv2.cpp)0
-rw-r--r--src/libs/clangsupport/filecontainerv2.h (renamed from src/libs/clangbackendipc/filecontainerv2.h)2
-rw-r--r--src/libs/clangsupport/filepath.cpp (renamed from src/libs/clangbackendipc/filepath.cpp)0
-rw-r--r--src/libs/clangsupport/filepath.h (renamed from src/libs/clangbackendipc/filepath.h)2
-rw-r--r--src/libs/clangsupport/fixitcontainer.cpp (renamed from src/libs/clangbackendipc/fixitcontainer.cpp)0
-rw-r--r--src/libs/clangsupport/fixitcontainer.h (renamed from src/libs/clangbackendipc/fixitcontainer.h)0
-rw-r--r--src/libs/clangsupport/followsymbolmessage.cpp (renamed from src/libs/clangbackendipc/projectpartsdonotexistmessage.cpp)24
-rw-r--r--src/libs/clangsupport/followsymbolmessage.h (renamed from src/libs/clangbackendipc/translationunitdoesnotexistmessage.h)54
-rw-r--r--src/libs/clangsupport/highlightingmarkcontainer.cpp (renamed from src/libs/clangbackendipc/highlightingmarkcontainer.cpp)6
-rw-r--r--src/libs/clangsupport/highlightingmarkcontainer.h (renamed from src/libs/clangbackendipc/highlightingmarkcontainer.h)34
-rw-r--r--src/libs/clangsupport/ipcclientinterface.cpp (renamed from src/libs/clangbackendipc/ipcclientinterface.cpp)0
-rw-r--r--src/libs/clangsupport/ipcclientinterface.h (renamed from src/libs/clangbackendipc/ipcclientinterface.h)0
-rw-r--r--src/libs/clangsupport/ipcclientprovider.h (renamed from src/libs/clangbackendipc/ipcserverinterface.h)14
-rw-r--r--src/libs/clangsupport/ipcinterface.cpp (renamed from src/libs/clangbackendipc/ipcinterface.cpp)0
-rw-r--r--src/libs/clangsupport/ipcinterface.h (renamed from src/libs/clangbackendipc/ipcinterface.h)2
-rw-r--r--src/libs/clangsupport/ipcserverinterface.cpp (renamed from src/libs/clangbackendipc/ipcserverinterface.cpp)0
-rw-r--r--src/libs/clangsupport/ipcserverinterface.h36
-rw-r--r--src/libs/clangsupport/lineprefixer.cpp (renamed from src/libs/clangbackendipc/lineprefixer.cpp)0
-rw-r--r--src/libs/clangsupport/lineprefixer.h (renamed from src/libs/clangbackendipc/lineprefixer.h)2
-rw-r--r--src/libs/clangsupport/messageenvelop.cpp (renamed from src/libs/clangbackendipc/messageenvelop.cpp)6
-rw-r--r--src/libs/clangsupport/messageenvelop.h (renamed from src/libs/clangbackendipc/messageenvelop.h)2
-rw-r--r--src/libs/clangsupport/pchmanagerclientinterface.cpp (renamed from src/libs/clangbackendipc/pchmanagerclientinterface.cpp)0
-rw-r--r--src/libs/clangsupport/pchmanagerclientinterface.h (renamed from src/libs/clangbackendipc/pchmanagerclientinterface.h)0
-rw-r--r--src/libs/clangsupport/pchmanagerclientproxy.cpp (renamed from src/libs/clangbackendipc/pchmanagerclientproxy.cpp)0
-rw-r--r--src/libs/clangsupport/pchmanagerclientproxy.h (renamed from src/libs/clangbackendipc/pchmanagerclientproxy.h)2
-rw-r--r--src/libs/clangsupport/pchmanagerserverinterface.cpp (renamed from src/libs/clangbackendipc/pchmanagerserverinterface.cpp)0
-rw-r--r--src/libs/clangsupport/pchmanagerserverinterface.h46
-rw-r--r--src/libs/clangsupport/pchmanagerserverproxy.cpp (renamed from src/libs/clangbackendipc/pchmanagerserverproxy.cpp)0
-rw-r--r--src/libs/clangsupport/pchmanagerserverproxy.h (renamed from src/libs/clangbackendipc/pchmanagerserverproxy.h)2
-rw-r--r--src/libs/clangsupport/precompiledheadersupdatedmessage.cpp (renamed from src/libs/clangbackendipc/precompiledheadersupdatedmessage.cpp)0
-rw-r--r--src/libs/clangsupport/precompiledheadersupdatedmessage.h (renamed from src/libs/clangbackendipc/precompiledheadersupdatedmessage.h)0
-rw-r--r--src/libs/clangsupport/projectmanagementserverinterface.h (renamed from src/libs/clangbackendipc/pchmanagerserverinterface.h)11
-rw-r--r--src/libs/clangsupport/projectpartcontainer.cpp (renamed from src/libs/clangbackendipc/projectpartcontainer.cpp)2
-rw-r--r--src/libs/clangsupport/projectpartcontainer.h (renamed from src/libs/clangbackendipc/projectpartcontainer.h)2
-rw-r--r--src/libs/clangsupport/projectpartcontainerv2.cpp (renamed from src/libs/clangbackendipc/projectpartcontainerv2.cpp)0
-rw-r--r--src/libs/clangsupport/projectpartcontainerv2.h (renamed from src/libs/clangbackendipc/projectpartcontainerv2.h)2
-rw-r--r--src/libs/clangsupport/projectpartpch.cpp (renamed from src/libs/clangbackendipc/projectpartpch.cpp)0
-rw-r--r--src/libs/clangsupport/projectpartpch.h (renamed from src/libs/clangbackendipc/projectpartpch.h)2
-rw-r--r--src/libs/clangsupport/readmessageblock.cpp (renamed from src/libs/clangbackendipc/readmessageblock.cpp)0
-rw-r--r--src/libs/clangsupport/readmessageblock.h (renamed from src/libs/clangbackendipc/readmessageblock.h)0
-rw-r--r--src/libs/clangsupport/refactoringclientinterface.cpp (renamed from src/libs/clangbackendipc/refactoringclientinterface.cpp)0
-rw-r--r--src/libs/clangsupport/refactoringclientinterface.h (renamed from src/libs/clangbackendipc/refactoringclientinterface.h)0
-rw-r--r--src/libs/clangsupport/refactoringclientproxy.cpp (renamed from src/libs/clangbackendipc/refactoringclientproxy.cpp)0
-rw-r--r--src/libs/clangsupport/refactoringclientproxy.h (renamed from src/libs/clangbackendipc/refactoringclientproxy.h)2
-rw-r--r--src/libs/clangsupport/refactoringdatabaseinitializer.h93
-rw-r--r--src/libs/clangsupport/refactoringserverinterface.cpp (renamed from src/libs/clangbackendipc/refactoringserverinterface.cpp)6
-rw-r--r--src/libs/clangsupport/refactoringserverinterface.h (renamed from src/libs/clangbackendipc/refactoringserverinterface.h)7
-rw-r--r--src/libs/clangsupport/refactoringserverproxy.cpp (renamed from src/libs/clangbackendipc/refactoringserverproxy.cpp)10
-rw-r--r--src/libs/clangsupport/refactoringserverproxy.h (renamed from src/libs/clangbackendipc/refactoringserverproxy.h)4
-rw-r--r--src/libs/clangsupport/referencesmessage.cpp (renamed from src/libs/clangbackendipc/referencesmessage.cpp)0
-rw-r--r--src/libs/clangsupport/referencesmessage.h (renamed from src/libs/clangbackendipc/referencesmessage.h)0
-rw-r--r--src/libs/clangsupport/registerunsavedfilesforeditormessage.cpp (renamed from src/libs/clangbackendipc/registerunsavedfilesforeditormessage.cpp)0
-rw-r--r--src/libs/clangsupport/registerunsavedfilesforeditormessage.h (renamed from src/libs/clangbackendipc/registerunsavedfilesforeditormessage.h)0
-rw-r--r--src/libs/clangsupport/removepchprojectpartsmessage.cpp (renamed from src/libs/clangbackendipc/removepchprojectpartsmessage.cpp)0
-rw-r--r--src/libs/clangsupport/removepchprojectpartsmessage.h (renamed from src/libs/clangbackendipc/removepchprojectpartsmessage.h)0
-rw-r--r--src/libs/clangsupport/requestdocumentannotations.cpp (renamed from src/libs/clangbackendipc/requestdocumentannotations.cpp)0
-rw-r--r--src/libs/clangsupport/requestdocumentannotations.h (renamed from src/libs/clangbackendipc/requestdocumentannotations.h)0
-rw-r--r--src/libs/clangsupport/requestfollowsymbolmessage.cpp64
-rw-r--r--src/libs/clangsupport/requestfollowsymbolmessage.h121
-rw-r--r--src/libs/clangsupport/requestreferencesmessage.cpp (renamed from src/libs/clangbackendipc/requestreferencesmessage.cpp)0
-rw-r--r--src/libs/clangsupport/requestreferencesmessage.h (renamed from src/libs/clangbackendipc/requestreferencesmessage.h)2
-rw-r--r--src/libs/clangsupport/requestsourcelocationforrenamingmessage.cpp (renamed from src/libs/clangbackendipc/requestsourcelocationforrenamingmessage.cpp)0
-rw-r--r--src/libs/clangsupport/requestsourcelocationforrenamingmessage.h (renamed from src/libs/clangbackendipc/requestsourcelocationforrenamingmessage.h)2
-rw-r--r--src/libs/clangsupport/requestsourcerangesanddiagnosticsforquerymessage.cpp (renamed from src/libs/clangbackendipc/requestsourcerangesanddiagnosticsforquerymessage.cpp)0
-rw-r--r--src/libs/clangsupport/requestsourcerangesanddiagnosticsforquerymessage.h (renamed from src/libs/clangbackendipc/requestsourcerangesanddiagnosticsforquerymessage.h)0
-rw-r--r--src/libs/clangsupport/requestsourcerangesforquerymessage.cpp (renamed from src/libs/clangbackendipc/requestsourcerangesforquerymessage.cpp)0
-rw-r--r--src/libs/clangsupport/requestsourcerangesforquerymessage.h (renamed from src/libs/clangbackendipc/requestsourcerangesforquerymessage.h)0
-rw-r--r--src/libs/clangsupport/sourcefilepathcontainerbase.cpp (renamed from src/libs/clangbackendipc/sourcefilepathcontainerbase.cpp)0
-rw-r--r--src/libs/clangsupport/sourcefilepathcontainerbase.h (renamed from src/libs/clangbackendipc/sourcefilepathcontainerbase.h)0
-rw-r--r--src/libs/clangsupport/sourcelocationcontainer.cpp (renamed from src/libs/clangbackendipc/sourcelocationcontainer.cpp)0
-rw-r--r--src/libs/clangsupport/sourcelocationcontainer.h (renamed from src/libs/clangbackendipc/sourcelocationcontainer.h)2
-rw-r--r--src/libs/clangsupport/sourcelocationcontainerv2.cpp (renamed from src/libs/clangbackendipc/sourcelocationcontainerv2.cpp)0
-rw-r--r--src/libs/clangsupport/sourcelocationcontainerv2.h (renamed from src/libs/clangbackendipc/sourcelocationcontainerv2.h)2
-rw-r--r--src/libs/clangsupport/sourcelocationscontainer.cpp (renamed from src/libs/clangbackendipc/sourcelocationscontainer.cpp)0
-rw-r--r--src/libs/clangsupport/sourcelocationscontainer.h (renamed from src/libs/clangbackendipc/sourcelocationscontainer.h)0
-rw-r--r--src/libs/clangsupport/sourcelocationsforrenamingmessage.cpp (renamed from src/libs/clangbackendipc/sourcelocationsforrenamingmessage.cpp)0
-rw-r--r--src/libs/clangsupport/sourcelocationsforrenamingmessage.h (renamed from src/libs/clangbackendipc/sourcelocationsforrenamingmessage.h)0
-rw-r--r--src/libs/clangsupport/sourcerangecontainer.cpp (renamed from src/libs/clangbackendipc/sourcerangecontainer.cpp)0
-rw-r--r--src/libs/clangsupport/sourcerangecontainer.h (renamed from src/libs/clangbackendipc/sourcerangecontainer.h)0
-rw-r--r--src/libs/clangsupport/sourcerangecontainerv2.cpp (renamed from src/libs/clangbackendipc/sourcerangecontainerv2.cpp)0
-rw-r--r--src/libs/clangsupport/sourcerangecontainerv2.h (renamed from src/libs/clangbackendipc/sourcerangecontainerv2.h)0
-rw-r--r--src/libs/clangsupport/sourcerangesanddiagnosticsforquerymessage.cpp (renamed from src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.cpp)0
-rw-r--r--src/libs/clangsupport/sourcerangesanddiagnosticsforquerymessage.h (renamed from src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.h)0
-rw-r--r--src/libs/clangsupport/sourcerangescontainer.cpp (renamed from src/libs/clangbackendipc/sourcerangescontainer.cpp)0
-rw-r--r--src/libs/clangsupport/sourcerangescontainer.h (renamed from src/libs/clangbackendipc/sourcerangescontainer.h)0
-rw-r--r--src/libs/clangsupport/sourcerangesforquerymessage.cpp (renamed from src/libs/clangbackendipc/sourcerangesforquerymessage.cpp)0
-rw-r--r--src/libs/clangsupport/sourcerangesforquerymessage.h (renamed from src/libs/clangbackendipc/sourcerangesforquerymessage.h)0
-rw-r--r--src/libs/clangsupport/sourcerangewithtextcontainer.cpp (renamed from src/libs/clangbackendipc/sourcerangewithtextcontainer.cpp)0
-rw-r--r--src/libs/clangsupport/sourcerangewithtextcontainer.h (renamed from src/libs/clangbackendipc/sourcerangewithtextcontainer.h)0
-rw-r--r--src/libs/clangsupport/stringcache.h237
-rw-r--r--src/libs/clangsupport/stringcachealgorithms.h72
-rw-r--r--src/libs/clangsupport/stringcachefwd.h51
-rw-r--r--src/libs/clangsupport/unregisterunsavedfilesforeditormessage.cpp (renamed from src/libs/clangbackendipc/unregisterunsavedfilesforeditormessage.cpp)0
-rw-r--r--src/libs/clangsupport/unregisterunsavedfilesforeditormessage.h (renamed from src/libs/clangbackendipc/unregisterunsavedfilesforeditormessage.h)0
-rw-r--r--src/libs/clangsupport/updatepchprojectpartsmessage.cpp (renamed from src/libs/clangbackendipc/updatepchprojectpartsmessage.cpp)0
-rw-r--r--src/libs/clangsupport/updatepchprojectpartsmessage.h (renamed from src/libs/clangbackendipc/updatepchprojectpartsmessage.h)0
-rw-r--r--src/libs/clangsupport/updatetranslationunitsforeditormessage.cpp (renamed from src/libs/clangbackendipc/updatetranslationunitsforeditormessage.cpp)0
-rw-r--r--src/libs/clangsupport/updatetranslationunitsforeditormessage.h (renamed from src/libs/clangbackendipc/updatetranslationunitsforeditormessage.h)0
-rw-r--r--src/libs/clangsupport/updatevisibletranslationunitsmessage.cpp (renamed from src/libs/clangbackendipc/updatevisibletranslationunitsmessage.cpp)0
-rw-r--r--src/libs/clangsupport/updatevisibletranslationunitsmessage.h (renamed from src/libs/clangbackendipc/updatevisibletranslationunitsmessage.h)2
-rw-r--r--src/libs/clangsupport/writemessageblock.cpp (renamed from src/libs/clangbackendipc/writemessageblock.cpp)0
-rw-r--r--src/libs/clangsupport/writemessageblock.h (renamed from src/libs/clangbackendipc/writemessageblock.h)0
-rw-r--r--src/libs/extensionsystem/pluginerroroverview.ui2
-rw-r--r--src/libs/extensionsystem/pluginmanager.cpp15
-rw-r--r--src/libs/extensionsystem/pluginview.cpp3
-rw-r--r--src/libs/extensionsystem/pluginview.h7
-rw-r--r--src/libs/flamegraph/flamegraph.h3
-rw-r--r--src/libs/libs.pro2
-rw-r--r--src/libs/libs.qbs2
-rw-r--r--src/libs/modelinglib/modelinglib.qbs12
-rw-r--r--src/libs/modelinglib/qmt/config/configcontroller.cpp9
-rw-r--r--src/libs/modelinglib/qmt/config/configcontroller.h4
-rw-r--r--src/libs/modelinglib/qmt/config/sourcepos.cpp3
-rw-r--r--src/libs/modelinglib/qmt/config/sourcepos.h6
-rw-r--r--src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp707
-rw-r--r--src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h36
-rw-r--r--src/libs/modelinglib/qmt/config/stringtextsource.cpp12
-rw-r--r--src/libs/modelinglib/qmt/config/stringtextsource.h8
-rw-r--r--src/libs/modelinglib/qmt/config/textscanner.cpp8
-rw-r--r--src/libs/modelinglib/qmt/config/textscanner.h2
-rw-r--r--src/libs/modelinglib/qmt/config/token.cpp4
-rw-r--r--src/libs/modelinglib/qmt/config/token.h1
-rw-r--r--src/libs/modelinglib/qmt/controller/namecontroller.cpp10
-rw-r--r--src/libs/modelinglib/qmt/controller/namecontroller.h2
-rw-r--r--src/libs/modelinglib/qmt/controller/undocommand.cpp4
-rw-r--r--src/libs/modelinglib/qmt/controller/undocommand.h4
-rw-r--r--src/libs/modelinglib/qmt/controller/undocontroller.cpp3
-rw-r--r--src/libs/modelinglib/qmt/controller/undocontroller.h6
-rw-r--r--src/libs/modelinglib/qmt/diagram/dannotation.cpp4
-rw-r--r--src/libs/modelinglib/qmt/diagram/dannotation.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram/dassociation.cpp2
-rw-r--r--src/libs/modelinglib/qmt/diagram/dassociation.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram/dclass.cpp2
-rw-r--r--src/libs/modelinglib/qmt/diagram/dclass.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram/dcomponent.cpp2
-rw-r--r--src/libs/modelinglib/qmt/diagram/dcomponent.h2
-rw-r--r--src/libs/modelinglib/qmt/diagram/dconnection.cpp103
-rw-r--r--src/libs/modelinglib/qmt/diagram/dconnection.h78
-rw-r--r--src/libs/modelinglib/qmt/diagram/dconstvisitor.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram/ddependency.cpp1
-rw-r--r--src/libs/modelinglib/qmt/diagram/ddependency.h2
-rw-r--r--src/libs/modelinglib/qmt/diagram/ditem.cpp2
-rw-r--r--src/libs/modelinglib/qmt/diagram/ditem.h2
-rw-r--r--src/libs/modelinglib/qmt/diagram/dobject.cpp8
-rw-r--r--src/libs/modelinglib/qmt/diagram/dobject.h14
-rw-r--r--src/libs/modelinglib/qmt/diagram/dswimlane.cpp (renamed from src/libs/sqlite/columndefinition.cpp)61
-rw-r--r--src/libs/modelinglib/qmt/diagram/dswimlane.h58
-rw-r--r--src/libs/modelinglib/qmt/diagram/dvisitor.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp33
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h8
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dfactory.cpp14
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dfactory.h3
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp39
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp76
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h6
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp42
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.h9
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp22
-rw-r--r--src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/capabilities/intersectionable.h2
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/diagramgraphicsscene.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h1
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp134
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h26
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp83
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h16
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp19
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h14
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/associationitem.cpp6
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/associationitem.h12
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp21
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h16
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp271
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/classitem.h31
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp54
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h21
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.cpp170
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.h64
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp8
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h8
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp50
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h17
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp331
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h40
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp47
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h17
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp83
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h16
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp2
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp250
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h87
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/latchcontroller.cpp9
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/latchcontroller.h16
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp16
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/alignlineitem.h8
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.cpp156
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.h22
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.cpp6
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.h2
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.cpp10
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.h6
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.cpp22
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.h6
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.cpp13
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.h15
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.cpp2
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.h2
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.cpp2
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h1
-rw-r--r--src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.cpp15
-rw-r--r--src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.h12
-rw-r--r--src/libs/modelinglib/qmt/diagram_ui/sceneinspector.cpp7
-rw-r--r--src/libs/modelinglib/qmt/diagram_ui/sceneinspector.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.cpp7
-rw-r--r--src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.h4
-rw-r--r--src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp24
-rw-r--r--src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h2
-rw-r--r--src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.cpp7
-rw-r--r--src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.h4
-rw-r--r--src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp9
-rw-r--r--src/libs/modelinglib/qmt/document_controller/documentcontroller.h26
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/contextmenuaction.h4
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp2
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/geometryutilities.h2
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/handle.h10
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/handles.h28
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/qcompressedfile.cpp16
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/qcompressedfile.h6
-rw-r--r--src/libs/modelinglib/qmt/infrastructure/qmtassert.h4
-rw-r--r--src/libs/modelinglib/qmt/model/massociation.cpp2
-rw-r--r--src/libs/modelinglib/qmt/model/massociation.h4
-rw-r--r--src/libs/modelinglib/qmt/model/mclassmember.cpp32
-rw-r--r--src/libs/modelinglib/qmt/model/mclassmember.h8
-rw-r--r--src/libs/modelinglib/qmt/model/mconnection.cpp114
-rw-r--r--src/libs/modelinglib/qmt/model/mconnection.h85
-rw-r--r--src/libs/modelinglib/qmt/model/mconstvisitor.h2
-rw-r--r--src/libs/modelinglib/qmt/model/mdependency.cpp2
-rw-r--r--src/libs/modelinglib/qmt/model/mdependency.h2
-rw-r--r--src/libs/modelinglib/qmt/model/mdiagram.cpp10
-rw-r--r--src/libs/modelinglib/qmt/model/melement.h6
-rw-r--r--src/libs/modelinglib/qmt/model/mitem.cpp3
-rw-r--r--src/libs/modelinglib/qmt/model/mitem.h4
-rw-r--r--src/libs/modelinglib/qmt/model/mobject.cpp44
-rw-r--r--src/libs/modelinglib/qmt/model/msourceexpansion.cpp4
-rw-r--r--src/libs/modelinglib/qmt/model/msourceexpansion.h2
-rw-r--r--src/libs/modelinglib/qmt/model/mvisitor.h2
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.cpp6
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.h1
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mclonevisitor.cpp29
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mclonevisitor.h6
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp26
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.h3
-rw-r--r--src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp165
-rw-r--r--src/libs/modelinglib/qmt/model_controller/modelcontroller.h8
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mvoidvisitor.cpp11
-rw-r--r--src/libs/modelinglib/qmt/model_controller/mvoidvisitor.h2
-rw-r--r--src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h4
-rw-r--r--src/libs/modelinglib/qmt/model_ui/stereotypescontroller.cpp2
-rw-r--r--src/libs/modelinglib/qmt/model_ui/stereotypescontroller.h2
-rw-r--r--src/libs/modelinglib/qmt/model_ui/treemodel.cpp117
-rw-r--r--src/libs/modelinglib/qmt/model_ui/treemodel.h2
-rw-r--r--src/libs/modelinglib/qmt/model_ui/treemodelmanager.cpp8
-rw-r--r--src/libs/modelinglib/qmt/model_ui/treemodelmanager.h6
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.cpp130
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.h2
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp36
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h6
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/palettebox.cpp13
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/palettebox.h4
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.cpp38
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.h16
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp383
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h102
-rw-r--r--src/libs/modelinglib/qmt/project/project.h2
-rw-r--r--src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp3
-rw-r--r--src/libs/modelinglib/qmt/project_controller/projectcontroller.h4
-rw-r--r--src/libs/modelinglib/qmt/qmt.pri16
-rw-r--r--src/libs/modelinglib/qmt/resources/48x48/swimlane.pngbin0 -> 191 bytes
-rw-r--r--src/libs/modelinglib/qmt/resources/resources.qrc1
-rw-r--r--src/libs/modelinglib/qmt/serializer/diagramserializer.cpp142
-rw-r--r--src/libs/modelinglib/qmt/serializer/infrastructureserializer.h10
-rw-r--r--src/libs/modelinglib/qmt/serializer/modelserializer.cpp106
-rw-r--r--src/libs/modelinglib/qmt/serializer/projectserializer.cpp18
-rw-r--r--src/libs/modelinglib/qmt/stereotype/customrelation.cpp139
-rw-r--r--src/libs/modelinglib/qmt/stereotype/customrelation.h166
-rw-r--r--src/libs/modelinglib/qmt/stereotype/iconshape.cpp22
-rw-r--r--src/libs/modelinglib/qmt/stereotype/iconshape.h2
-rw-r--r--src/libs/modelinglib/qmt/stereotype/shape.h2
-rw-r--r--src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp56
-rw-r--r--src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h4
-rw-r--r--src/libs/modelinglib/qmt/stereotype/shapes.cpp44
-rw-r--r--src/libs/modelinglib/qmt/stereotype/shapes.h70
-rw-r--r--src/libs/modelinglib/qmt/stereotype/shapevalue.h6
-rw-r--r--src/libs/modelinglib/qmt/stereotype/shapevisitor.h6
-rw-r--r--src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp28
-rw-r--r--src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h8
-rw-r--r--src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp15
-rw-r--r--src/libs/modelinglib/qmt/stereotype/stereotypeicon.h17
-rw-r--r--src/libs/modelinglib/qmt/stereotype/toolbar.cpp11
-rw-r--r--src/libs/modelinglib/qmt/stereotype/toolbar.h13
-rw-r--r--src/libs/modelinglib/qmt/style/defaultstyleengine.cpp55
-rw-r--r--src/libs/modelinglib/qmt/style/defaultstyleengine.h5
-rw-r--r--src/libs/modelinglib/qmt/style/objectvisuals.cpp4
-rw-r--r--src/libs/modelinglib/qmt/style/objectvisuals.h8
-rw-r--r--src/libs/modelinglib/qmt/style/stylecontroller.cpp11
-rw-r--r--src/libs/modelinglib/qmt/style/stylecontroller.h5
-rw-r--r--src/libs/modelinglib/qmt/style/styledobject.h2
-rw-r--r--src/libs/modelinglib/qmt/style/styledrelation.h6
-rw-r--r--src/libs/modelinglib/qmt/style/styleengine.h6
-rw-r--r--src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp17
-rw-r--r--src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h8
-rw-r--r--src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp198
-rw-r--r--src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h39
-rw-r--r--src/libs/modelinglib/qmt/tasks/finddiagramvisitor.cpp2
-rw-r--r--src/libs/modelinglib/qmt/tasks/finddiagramvisitor.h2
-rw-r--r--src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.cpp2
-rw-r--r--src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.h2
-rw-r--r--src/libs/modelinglib/qstringparser/qstringparser.h4
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/attribute.h18
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/baseclass.h4
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/qxmlinarchive.h48
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/qxmloutarchive.h5
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/reference.h18
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/serialize_basic.h8
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/serialize_container.h50
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/serialize_pointer.h6
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/tag.h2
-rw-r--r--src/libs/modelinglib/qtserialization/inc/qark/typeregistry.h12
-rw-r--r--src/libs/qmldebug/baseenginedebugclient.cpp28
-rw-r--r--src/libs/qmldebug/baseenginedebugclient.h6
-rw-r--r--src/libs/qmldebug/basetoolsclient.h2
-rw-r--r--src/libs/qmldebug/declarativeenginedebugclient.cpp8
-rw-r--r--src/libs/qmldebug/declarativeenginedebugclient.h9
-rw-r--r--src/libs/qmldebug/declarativetoolsclient.h15
-rw-r--r--src/libs/qmldebug/qdebugmessageclient.h5
-rw-r--r--src/libs/qmldebug/qmldebugclient.cpp20
-rw-r--r--src/libs/qmldebug/qmldebugclient.h4
-rw-r--r--src/libs/qmldebug/qmldebugcommandlinearguments.h18
-rw-r--r--src/libs/qmldebug/qmlenginecontrolclient.h3
-rw-r--r--src/libs/qmldebug/qmltoolsclient.cpp8
-rw-r--r--src/libs/qmldebug/qmltoolsclient.h15
-rw-r--r--src/libs/qmldebug/qpacketprotocol.h3
-rw-r--r--src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp9
-rw-r--r--src/libs/qmleditorwidgets/easingpane/easingpane.qrc2
-rw-r--r--src/libs/qmleditorwidgets/easingpane/playicon.pngbin100 -> 0 bytes
-rw-r--r--src/libs/qmleditorwidgets/easingpane/stopicon.pngbin78 -> 0 bytes
-rw-r--r--src/libs/qmleditorwidgets/images/hole.pngbin116 -> 0 bytes
-rw-r--r--src/libs/qmleditorwidgets/images/lock.pngbin525 -> 0 bytes
-rw-r--r--src/libs/qmleditorwidgets/resources.qrc2
-rw-r--r--src/libs/qmljs/parser/qmljslexer.cpp1
-rw-r--r--src/libs/qmljs/parser/qmljsparser.cpp1
-rw-r--r--src/libs/qmljs/qmljscheck.cpp24
-rw-r--r--src/libs/qmljs/qmljscodeformatter.cpp3
-rw-r--r--src/libs/qmljs/qmljsdescribevalue.h2
-rw-r--r--src/libs/qmljs/qmljsfindexportedcpptypes.cpp4
-rw-r--r--src/libs/qmljs/qmljsreformatter.cpp24
-rw-r--r--src/libs/qmljs/qmljsreformatter.h1
-rw-r--r--src/libs/qmljs/qmljsscopeastpath.h2
-rw-r--r--src/libs/qmljs/qmljsstaticanalysismessage.cpp2
-rw-r--r--src/libs/qmljs/qmljsstaticanalysismessage.h2
-rw-r--r--src/libs/qmljs/qmljstypedescriptionreader.h4
-rw-r--r--src/libs/qt-breakpad/poster/__init__.py32
-rw-r--r--src/libs/qt-breakpad/poster/encode.py433
-rw-r--r--src/libs/qt-breakpad/poster/streaminghttp.py216
-rw-r--r--src/libs/qt-breakpad/qtbreakpad.pri64
-rw-r--r--src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.cpp222
-rw-r--r--src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.h56
-rwxr-xr-xsrc/libs/qt-breakpad/qtbreakpadsymbols271
-rw-r--r--src/libs/qt-breakpad/qtbreakpadsymbols.bat1
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler.pri21
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/detaildialog.cpp55
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/detaildialog.h48
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp178
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/dumpsender.h (renamed from src/libs/sqlite/sqlitedatabaseconnection.h)36
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/main.cpp73
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/mainwidget.cpp155
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/mainwidget.h (renamed from src/libs/sqlite/sqlitedatabaseconnectionproxy.h)53
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/mainwidget.ui143
-rw-r--r--src/libs/qt-breakpad/qtcrashhandler/qtcrashhandler.pro6
-rw-r--r--src/libs/qt-breakpad/testapp/main.cpp43
-rw-r--r--src/libs/qt-breakpad/testapp/testapp.pro14
-rw-r--r--src/libs/sqlite/columndefinition.h52
-rw-r--r--src/libs/sqlite/createtablesqlstatementbuilder.cpp113
-rw-r--r--src/libs/sqlite/createtablesqlstatementbuilder.h33
-rw-r--r--src/libs/sqlite/sqlite-lib.pri17
-rw-r--r--src/libs/sqlite/sqlitecolumn.cpp54
-rw-r--r--src/libs/sqlite/sqlitecolumn.h94
-rw-r--r--src/libs/sqlite/sqlitedatabase.cpp108
-rw-r--r--src/libs/sqlite/sqlitedatabase.h84
-rw-r--r--src/libs/sqlite/sqlitedatabasebackend.cpp274
-rw-r--r--src/libs/sqlite/sqlitedatabasebackend.h100
-rw-r--r--src/libs/sqlite/sqlitedatabaseconnection.cpp97
-rw-r--r--src/libs/sqlite/sqlitedatabaseconnectionproxy.cpp92
-rw-r--r--src/libs/sqlite/sqliteexception.cpp17
-rw-r--r--src/libs/sqlite/sqliteexception.h226
-rw-r--r--src/libs/sqlite/sqliteglobal.cpp8
-rw-r--r--src/libs/sqlite/sqliteglobal.h44
-rw-r--r--src/libs/sqlite/sqliteindex.h82
-rw-r--r--src/libs/sqlite/sqlitereadstatement.cpp13
-rw-r--r--src/libs/sqlite/sqlitereadstatement.h25
-rw-r--r--src/libs/sqlite/sqlitereadwritestatement.cpp8
-rw-r--r--src/libs/sqlite/sqlitereadwritestatement.h32
-rw-r--r--src/libs/sqlite/sqlitestatement.cpp606
-rw-r--r--src/libs/sqlite/sqlitestatement.h368
-rw-r--r--src/libs/sqlite/sqlitetable.cpp86
-rw-r--r--src/libs/sqlite/sqlitetable.h143
-rw-r--r--src/libs/sqlite/sqlitetransaction.cpp29
-rw-r--r--src/libs/sqlite/sqlitetransaction.h66
-rw-r--r--src/libs/sqlite/sqliteworkerthread.cpp59
-rw-r--r--src/libs/sqlite/sqliteworkerthread.h49
-rw-r--r--src/libs/sqlite/sqlitewritestatement.cpp13
-rw-r--r--src/libs/sqlite/sqlitewritestatement.h22
-rw-r--r--src/libs/sqlite/sqlstatementbuilder.cpp168
-rw-r--r--src/libs/sqlite/sqlstatementbuilder.h59
-rw-r--r--src/libs/sqlite/sqlstatementbuilderexception.cpp11
-rw-r--r--src/libs/sqlite/sqlstatementbuilderexception.h8
-rw-r--r--src/libs/sqlite/tablewriteworker.cpp65
-rw-r--r--src/libs/sqlite/tablewriteworkerproxy.cpp62
-rw-r--r--src/libs/ssh/images/dir.png (renamed from src/libs/utils/images/dir.png)bin862 -> 862 bytes
-rw-r--r--src/libs/ssh/images/help.png (renamed from src/libs/utils/images/help.png)bin430 -> 430 bytes
-rw-r--r--src/libs/ssh/images/unknownfile.png (renamed from src/libs/utils/images/unknownfile.png)bin345 -> 345 bytes
-rw-r--r--src/libs/ssh/sftpfilesystemmodel.cpp6
-rw-r--r--src/libs/ssh/ssh.pro2
-rw-r--r--src/libs/ssh/ssh.qbs1
-rw-r--r--src/libs/ssh/ssh.qrc7
-rw-r--r--src/libs/ssh/sshagent.cpp2
-rw-r--r--src/libs/ssh/sshagent_p.h2
-rw-r--r--src/libs/ssh/sshexception_p.h11
-rw-r--r--src/libs/timeline/qml/MainView.qml3
-rw-r--r--src/libs/timeline/qml/lock_closed@2x.pngbin190 -> 0 bytes
-rw-r--r--src/libs/timeline/qml/lock_open@2x.pngbin177 -> 0 bytes
-rw-r--r--src/libs/timeline/timelineabstractrenderer.h2
-rw-r--r--src/libs/timeline/timelinemodelaggregator.h1
-rw-r--r--src/libs/timeline/timelinerenderer.h2
-rw-r--r--src/libs/utils/basetreeview.cpp2
-rw-r--r--src/libs/utils/benchmarker.cpp67
-rw-r--r--src/libs/utils/benchmarker.h53
-rw-r--r--src/libs/utils/camelhumpmatcher.cpp146
-rw-r--r--src/libs/utils/camelhumpmatcher.h58
-rw-r--r--src/libs/utils/environment.cpp84
-rw-r--r--src/libs/utils/fancylineedit.cpp25
-rw-r--r--src/libs/utils/fancylineedit.h9
-rw-r--r--src/libs/utils/fileutils.cpp3
-rw-r--r--src/libs/utils/highlightingitemdelegate.cpp43
-rw-r--r--src/libs/utils/images/empty16.pngbin0 -> 75 bytes
-rw-r--r--src/libs/utils/images/magnifier.pngbin178 -> 201 bytes
-rw-r--r--src/libs/utils/images/magnifier@2x.pngbin338 -> 360 bytes
-rw-r--r--src/libs/utils/optional.h2
-rw-r--r--src/libs/utils/pathchooser.cpp38
-rw-r--r--src/libs/utils/pathchooser.h4
-rw-r--r--src/libs/utils/persistentsettings.h1
-rw-r--r--src/libs/utils/progressindicator.cpp134
-rw-r--r--src/libs/utils/progressindicator.h70
-rw-r--r--src/libs/utils/reloadpromptutils.cpp10
-rw-r--r--src/libs/utils/shellcommand.cpp17
-rw-r--r--src/libs/utils/shellcommand.h2
-rw-r--r--src/libs/utils/smallstring.h381
-rw-r--r--src/libs/utils/smallstringfwd.h6
-rw-r--r--src/libs/utils/smallstringio.h58
-rw-r--r--src/libs/utils/smallstringiterator.h2
-rw-r--r--src/libs/utils/smallstringlayout.h6
-rw-r--r--src/libs/utils/smallstringliteral.h11
-rw-r--r--src/libs/utils/smallstringvector.h28
-rw-r--r--src/libs/utils/smallstringview.h123
-rw-r--r--src/libs/utils/stylehelper.cpp11
-rw-r--r--src/libs/utils/textutils.cpp (renamed from src/plugins/texteditor/convenience.cpp)19
-rw-r--r--src/libs/utils/textutils.h (renamed from src/plugins/texteditor/convenience.h)30
-rw-r--r--src/libs/utils/theme/theme.cpp2
-rw-r--r--src/libs/utils/tooltip/tooltip.cpp7
-rw-r--r--src/libs/utils/treemodel.cpp22
-rw-r--r--src/libs/utils/treemodel.h3
-rw-r--r--src/libs/utils/utils-lib.pri13
-rw-r--r--src/libs/utils/utils.qbs6
-rw-r--r--src/libs/utils/utils.qrc4
-rw-r--r--src/libs/utils/utilsicons.cpp1
-rw-r--r--src/libs/utils/utilsicons.h1
-rw-r--r--src/plugins/android/android.qbs1
-rw-r--r--src/plugins/android/androidanalyzesupport.cpp2
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp59
-rw-r--r--src/plugins/android/androidbuildapkstep.h8
-rw-r--r--src/plugins/android/androidbuildapkwidget.cpp48
-rw-r--r--src/plugins/android/androidbuildapkwidget.h3
-rw-r--r--src/plugins/android/androidbuildapkwidget.ui97
-rw-r--r--src/plugins/android/androidconfigurations.cpp71
-rw-r--r--src/plugins/android/androidconfigurations.h15
-rw-r--r--src/plugins/android/androiddebugsupport.cpp52
-rw-r--r--src/plugins/android/androiddeployqtstep.cpp12
-rw-r--r--src/plugins/android/androiddevicedialog.cpp15
-rw-r--r--src/plugins/android/androiddevicedialog.h2
-rw-r--r--src/plugins/android/androidmanager.cpp27
-rw-r--r--src/plugins/android/androidmanager.h1
-rw-r--r--src/plugins/android/androidpotentialkit.cpp7
-rw-r--r--src/plugins/android/androidqtsupport.cpp6
-rw-r--r--src/plugins/android/androidrunconfiguration.cpp9
-rw-r--r--src/plugins/android/androidrunconfiguration.h11
-rw-r--r--src/plugins/android/androidrunconfigurationwidget.cpp4
-rw-r--r--src/plugins/android/androidrunner.cpp31
-rw-r--r--src/plugins/android/androidrunner.h9
-rw-r--r--src/plugins/android/androidsdkmanager.cpp9
-rw-r--r--src/plugins/android/androidsettingswidget.cpp232
-rw-r--r--src/plugins/android/androidsettingswidget.h13
-rw-r--r--src/plugins/android/androidsettingswidget.ui462
-rw-r--r--src/plugins/android/androidtoolchain.cpp2
-rw-r--r--src/plugins/android/images/androiddevice.pngbin211 -> 216 bytes
-rw-r--r--src/plugins/android/images/androiddevice@2x.pngbin255 -> 259 bytes
-rw-r--r--src/plugins/autotest/autotest.qrc1
-rw-r--r--src/plugins/autotest/autotestconstants.h12
-rw-r--r--src/plugins/autotest/autotesticons.h4
-rw-r--r--src/plugins/autotest/autotestplugin.cpp6
-rw-r--r--src/plugins/autotest/gtest/gtestconfiguration.cpp42
-rw-r--r--src/plugins/autotest/gtest/gtestconfiguration.h2
-rw-r--r--src/plugins/autotest/gtest/gtestoutputreader.cpp87
-rw-r--r--src/plugins/autotest/gtest/gtestoutputreader.h8
-rw-r--r--src/plugins/autotest/gtest/gtestresult.cpp66
-rw-r--r--src/plugins/autotest/gtest/gtestresult.h12
-rw-r--r--src/plugins/autotest/gtest/gtesttreeitem.cpp12
-rw-r--r--src/plugins/autotest/images/benchmark.pngbin374 -> 202 bytes
-rw-r--r--src/plugins/autotest/images/benchmark@2x.pngbin0 -> 366 bytes
-rw-r--r--src/plugins/autotest/images/text.pngbin148 -> 152 bytes
-rw-r--r--src/plugins/autotest/images/text@2x.pngbin274 -> 212 bytes
-rw-r--r--src/plugins/autotest/images/visual.pngbin213 -> 123 bytes
-rw-r--r--src/plugins/autotest/images/visual@2x.pngbin297 -> 134 bytes
-rw-r--r--src/plugins/autotest/qtest/qttest_utils.cpp58
-rw-r--r--src/plugins/autotest/qtest/qttest_utils.h1
-rw-r--r--src/plugins/autotest/qtest/qttestconfiguration.cpp12
-rw-r--r--src/plugins/autotest/qtest/qttestconfiguration.h2
-rw-r--r--src/plugins/autotest/qtest/qttestoutputreader.cpp16
-rw-r--r--src/plugins/autotest/qtest/qttestparser.cpp7
-rw-r--r--src/plugins/autotest/qtest/qttesttreeitem.cpp2
-rw-r--r--src/plugins/autotest/quick/quicktestconfiguration.cpp11
-rw-r--r--src/plugins/autotest/quick/quicktestconfiguration.h2
-rw-r--r--src/plugins/autotest/quick/quicktestframework.cpp2
-rw-r--r--src/plugins/autotest/quick/quicktestparser.cpp25
-rw-r--r--src/plugins/autotest/quick/quicktesttreeitem.cpp2
-rw-r--r--src/plugins/autotest/testcodeparser.cpp2
-rw-r--r--src/plugins/autotest/testconfiguration.cpp129
-rw-r--r--src/plugins/autotest/testconfiguration.h39
-rw-r--r--src/plugins/autotest/testnavigationwidget.cpp32
-rw-r--r--src/plugins/autotest/testnavigationwidget.h2
-rw-r--r--src/plugins/autotest/testoutputreader.cpp6
-rw-r--r--src/plugins/autotest/testoutputreader.h4
-rw-r--r--src/plugins/autotest/testresult.cpp5
-rw-r--r--src/plugins/autotest/testresult.h3
-rw-r--r--src/plugins/autotest/testresultspane.cpp47
-rw-r--r--src/plugins/autotest/testresultspane.h5
-rw-r--r--src/plugins/autotest/testrunconfiguration.h3
-rw-r--r--src/plugins/autotest/testrunner.cpp247
-rw-r--r--src/plugins/autotest/testrunner.h38
-rw-r--r--src/plugins/autotest/testsettings.cpp3
-rw-r--r--src/plugins/autotest/testsettings.h1
-rw-r--r--src/plugins/autotest/testsettingspage.cpp2
-rw-r--r--src/plugins/autotest/testsettingspage.ui11
-rw-r--r--src/plugins/autotest/testtreeitem.cpp31
-rw-r--r--src/plugins/autotest/testtreeitem.h5
-rw-r--r--src/plugins/autotoolsprojectmanager/autogenstep.cpp14
-rw-r--r--src/plugins/autotoolsprojectmanager/autoreconfstep.cpp10
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsopenprojectwizard.cpp2
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsproject.cpp5
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsproject.h1
-rw-r--r--src/plugins/autotoolsprojectmanager/configurestep.cpp18
-rw-r--r--src/plugins/autotoolsprojectmanager/makefileparser.cpp10
-rw-r--r--src/plugins/autotoolsprojectmanager/makefileparser.h9
-rw-r--r--src/plugins/autotoolsprojectmanager/makefileparserthread.cpp6
-rw-r--r--src/plugins/autotoolsprojectmanager/makefileparserthread.h11
-rw-r--r--src/plugins/autotoolsprojectmanager/makestep.cpp27
-rw-r--r--src/plugins/baremetal/baremetalcustomrunconfiguration.cpp14
-rw-r--r--src/plugins/baremetal/baremetalcustomrunconfiguration.h8
-rw-r--r--src/plugins/baremetal/baremetaldebugsupport.cpp36
-rw-r--r--src/plugins/baremetal/baremetalrunconfiguration.cpp51
-rw-r--r--src/plugins/baremetal/baremetalrunconfiguration.h13
-rw-r--r--src/plugins/baremetal/baremetalrunconfigurationfactory.cpp9
-rw-r--r--src/plugins/baremetal/baremetalrunconfigurationwidget.cpp35
-rw-r--r--src/plugins/baremetal/baremetalrunconfigurationwidget.h3
-rw-r--r--src/plugins/baremetal/images/baremetaldevice.pngbin184 -> 185 bytes
-rw-r--r--src/plugins/baremetal/images/baremetaldevice@2x.pngbin277 -> 280 bytes
-rw-r--r--src/plugins/bazaar/bazaarplugin.cpp6
-rw-r--r--src/plugins/beautifier/beautifierplugin.cpp16
-rw-r--r--src/plugins/beautifier/beautifierplugin.h2
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.cpp63
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.h4
-rw-r--r--src/plugins/beautifier/clangformat/clangformatconstants.h3
-rw-r--r--src/plugins/beautifier/clangformat/clangformatoptionspage.cpp2
-rw-r--r--src/plugins/beautifier/clangformat/clangformatoptionspage.ui36
-rw-r--r--src/plugins/beautifier/clangformat/clangformatsettings.cpp12
-rw-r--r--src/plugins/beautifier/clangformat/clangformatsettings.h3
-rw-r--r--src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp23
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalmodel.h2
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.cpp581
-rw-r--r--src/plugins/clangcodemodel/clangbackendcommunicator.h (renamed from src/plugins/clangcodemodel/clangbackendipcintegration.h)118
-rw-r--r--src/plugins/clangcodemodel/clangbackendipcintegration.cpp866
-rw-r--r--src/plugins/clangcodemodel/clangbackendlogging.cpp (renamed from src/libs/sqlite/createtablecommand.cpp)12
-rw-r--r--src/plugins/clangcodemodel/clangbackendlogging.h35
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.cpp287
-rw-r--r--src/plugins/clangcodemodel/clangbackendreceiver.h96
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.cpp141
-rw-r--r--src/plugins/clangcodemodel/clangbackendsender.h62
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.pro12
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.qbs14
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel_dependencies.pri2
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistinterface.cpp8
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistinterface.h8
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp47
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprocessor.h9
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprovider.cpp6
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprovider.h6
-rw-r--r--src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h2
-rw-r--r--src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp32
-rw-r--r--src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h8
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticfilter.h2
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticmanager.cpp4
-rw-r--r--src/plugins/clangcodemodel/clangdiagnosticmanager.h2
-rw-r--r--src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h2
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp97
-rw-r--r--src/plugins/clangcodemodel/clangeditordocumentprocessor.h10
-rw-r--r--src/plugins/clangcodemodel/clangfixitoperation.h2
-rw-r--r--src/plugins/clangcodemodel/clangfixitoperationsextractor.h2
-rw-r--r--src/plugins/clangcodemodel/clangfollowsymbol.cpp144
-rw-r--r--src/plugins/clangcodemodel/clangfollowsymbol.h (renamed from src/libs/sqlite/createtablecommand.h)26
-rw-r--r--src/plugins/clangcodemodel/clangfunctionhintmodel.cpp9
-rw-r--r--src/plugins/clangcodemodel/clangfunctionhintmodel.h1
-rw-r--r--src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp9
-rw-r--r--src/plugins/clangcodemodel/clanghighlightingmarksreporter.h2
-rw-r--r--src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h2
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.cpp62
-rw-r--r--src/plugins/clangcodemodel/clangmodelmanagersupport.h9
-rw-r--r--src/plugins/clangcodemodel/clangtextmark.h4
-rw-r--r--src/plugins/clangcodemodel/clangutils.cpp43
-rw-r--r--src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp369
-rw-r--r--src/plugins/clangcodemodel/test/clangcodecompletion_test.h2
-rw-r--r--src/plugins/clangpchmanager/clangpchmanager-source.pri6
-rw-r--r--src/plugins/clangpchmanager/clangpchmanager_dependencies.pri2
-rw-r--r--src/plugins/clangpchmanager/clangpchmanagerplugin.cpp2
-rw-r--r--src/plugins/clangpchmanager/pchmanagerclient.cpp2
-rw-r--r--src/plugins/clangpchmanager/pchmanagerprojectupdater.cpp47
-rw-r--r--src/plugins/clangpchmanager/pchmanagerprojectupdater.h44
-rw-r--r--src/plugins/clangpchmanager/projectupdater.cpp41
-rw-r--r--src/plugins/clangpchmanager/projectupdater.h12
-rw-r--r--src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp39
-rw-r--r--src/plugins/clangpchmanager/qtcreatorprojectupdater.h56
-rw-r--r--src/plugins/clangrefactoring/clangqueryhoverhandler.cpp4
-rw-r--r--src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp27
-rw-r--r--src/plugins/clangrefactoring/clangrefactoring-source.pri6
-rw-r--r--src/plugins/clangrefactoring/clangrefactoring.pro8
-rw-r--r--src/plugins/clangrefactoring/clangrefactoring_dependencies.pri5
-rw-r--r--src/plugins/clangrefactoring/clangrefactoringplugin.cpp7
-rw-r--r--src/plugins/clangrefactoring/qtcreatorsearch.cpp11
-rw-r--r--src/plugins/clangrefactoring/qtcreatorsearch.h5
-rw-r--r--src/plugins/clangrefactoring/querysqlitestatementfactory.h54
-rw-r--r--src/plugins/clangrefactoring/refactoringclient.cpp2
-rw-r--r--src/plugins/clangrefactoring/refactoringengine.cpp29
-rw-r--r--src/plugins/clangrefactoring/refactoringengine.h5
-rw-r--r--src/plugins/clangrefactoring/refactoringprojectupdater.cpp37
-rw-r--r--src/plugins/clangrefactoring/refactoringprojectupdater.h41
-rw-r--r--src/plugins/clangrefactoring/sourcelocations.h65
-rw-r--r--src/plugins/clangrefactoring/symbolquery.cpp30
-rw-r--r--src/plugins/clangrefactoring/symbolquery.h110
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp15
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp2
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp318
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h14
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp166
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h17
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp2
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp14
-rw-r--r--src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h2
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp20
-rw-r--r--src/plugins/clearcase/clearcaseplugin.h3
-rw-r--r--src/plugins/cmakeprojectmanager/builddirmanager.cpp32
-rw-r--r--src/plugins/cmakeprojectmanager/builddirmanager.h4
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp38
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h6
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp132
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h5
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.cpp79
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.h4
-rw-r--r--src/plugins/cmakeprojectmanager/cmakecbpparser.cpp18
-rw-r--r--src/plugins/cmakeprojectmanager/cmakecbpparser.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeeditor.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakekitinformation.cpp6
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp187
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.h35
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp3
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp10
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp4
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectplugin.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp105
-rw-r--r--src/plugins/cmakeprojectmanager/cmakerunconfiguration.h22
-rw-r--r--src/plugins/cmakeprojectmanager/cmakesettingspage.cpp36
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.cpp17
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.h3
-rw-r--r--src/plugins/cmakeprojectmanager/configmodel.cpp550
-rw-r--r--src/plugins/cmakeprojectmanager/configmodel.h51
-rw-r--r--src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp128
-rw-r--r--src/plugins/cmakeprojectmanager/configmodelitemdelegate.h20
-rw-r--r--src/plugins/cmakeprojectmanager/servermodereader.cpp138
-rw-r--r--src/plugins/cmakeprojectmanager/servermodereader.h29
-rw-r--r--src/plugins/cmakeprojectmanager/tealeafreader.cpp7
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager.h1
-rw-r--r--src/plugins/coreplugin/actionmanager/actionmanager_p.h6
-rw-r--r--src/plugins/coreplugin/actionmanager/commandmappings.h1
-rw-r--r--src/plugins/coreplugin/actionmanager/commandsfile.cpp7
-rw-r--r--src/plugins/coreplugin/basefilewizardfactory.h2
-rw-r--r--src/plugins/coreplugin/coreconstants.h3
-rw-r--r--src/plugins/coreplugin/corejsextensions.cpp2
-rw-r--r--src/plugins/coreplugin/coreplugin.cpp22
-rw-r--r--src/plugins/coreplugin/coreplugin.h1
-rw-r--r--src/plugins/coreplugin/dialogs/newdialog.h1
-rw-r--r--src/plugins/coreplugin/dialogs/openwithdialog.h1
-rw-r--r--src/plugins/coreplugin/dialogs/saveitemsdialog.h6
-rw-r--r--src/plugins/coreplugin/dialogs/shortcutsettings.h2
-rw-r--r--src/plugins/coreplugin/documentmanager.cpp243
-rw-r--r--src/plugins/coreplugin/documentmanager.h63
-rw-r--r--src/plugins/coreplugin/editormanager/documentmodel.cpp9
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp25
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.h12
-rw-r--r--src/plugins/coreplugin/editormanager/editorview.h4
-rw-r--r--src/plugins/coreplugin/editormanager/openeditorswindow.h2
-rw-r--r--src/plugins/coreplugin/externaltool.cpp5
-rw-r--r--src/plugins/coreplugin/externaltoolmanager.cpp2
-rw-r--r--src/plugins/coreplugin/fancyactionbar.cpp8
-rw-r--r--src/plugins/coreplugin/fancytabwidget.cpp17
-rw-r--r--src/plugins/coreplugin/fancytabwidget.h3
-rw-r--r--src/plugins/coreplugin/fileiconprovider.cpp13
-rw-r--r--src/plugins/coreplugin/fileiconprovider.h2
-rw-r--r--src/plugins/coreplugin/find/findplugin.cpp5
-rw-r--r--src/plugins/coreplugin/find/findtoolbar.cpp8
-rw-r--r--src/plugins/coreplugin/find/searchresultwindow.h2
-rw-r--r--src/plugins/coreplugin/generalsettings.cpp2
-rw-r--r--src/plugins/coreplugin/icore.cpp5
-rw-r--r--src/plugins/coreplugin/icore.h2
-rw-r--r--src/plugins/coreplugin/images/mode_Design.pngbin1779 -> 1565 bytes
-rw-r--r--src/plugins/coreplugin/images/mode_Design@2x.pngbin6227 -> 5116 bytes
-rw-r--r--src/plugins/coreplugin/images/mode_Edit.pngbin426 -> 389 bytes
-rw-r--r--src/plugins/coreplugin/images/mode_Edit@2x.pngbin3157 -> 1081 bytes
-rw-r--r--src/plugins/coreplugin/images/mode_design_mask.pngbin223 -> 218 bytes
-rw-r--r--src/plugins/coreplugin/images/mode_design_mask@2x.pngbin369 -> 362 bytes
-rw-r--r--src/plugins/coreplugin/images/mode_edit_mask.pngbin109 -> 110 bytes
-rw-r--r--src/plugins/coreplugin/images/mode_edit_mask@2x.pngbin118 -> 117 bytes
-rw-r--r--src/plugins/coreplugin/iversioncontrol.cpp6
-rw-r--r--src/plugins/coreplugin/iwizardfactory.cpp9
-rw-r--r--src/plugins/coreplugin/jsexpander.cpp2
-rw-r--r--src/plugins/coreplugin/locator/basefilefilter.cpp29
-rw-r--r--src/plugins/coreplugin/locator/ilocatorfilter.cpp27
-rw-r--r--src/plugins/coreplugin/locator/ilocatorfilter.h15
-rw-r--r--src/plugins/coreplugin/locator/locatorsettingspage.h1
-rw-r--r--src/plugins/coreplugin/locator/locatorwidget.cpp9
-rw-r--r--src/plugins/coreplugin/locator/locatorwidget.h3
-rw-r--r--src/plugins/coreplugin/locator/opendocumentsfilter.cpp18
-rw-r--r--src/plugins/coreplugin/mainwindow.cpp12
-rw-r--r--src/plugins/coreplugin/mainwindow.h3
-rw-r--r--src/plugins/coreplugin/messagemanager.cpp28
-rw-r--r--src/plugins/coreplugin/messagemanager.h4
-rw-r--r--src/plugins/coreplugin/mimetypemagicdialog.ui2
-rw-r--r--src/plugins/coreplugin/mimetypesettings.cpp3
-rw-r--r--src/plugins/coreplugin/navigationwidget.h1
-rw-r--r--src/plugins/coreplugin/outputpanemanager.h2
-rw-r--r--src/plugins/coreplugin/outputwindow.cpp2
-rw-r--r--src/plugins/coreplugin/patchtool.cpp6
-rw-r--r--src/plugins/coreplugin/rightpane.h1
-rw-r--r--src/plugins/coreplugin/shellcommand.cpp21
-rw-r--r--src/plugins/coreplugin/sidebarwidget.h2
-rw-r--r--src/plugins/coreplugin/systemsettings.cpp6
-rw-r--r--src/plugins/coreplugin/systemsettings.ui13
-rw-r--r--src/plugins/coreplugin/themechooser.cpp2
-rw-r--r--src/plugins/coreplugin/variablechooser.cpp8
-rw-r--r--src/plugins/coreplugin/vcsmanager.cpp103
-rw-r--r--src/plugins/coreplugin/vcsmanager.h17
-rw-r--r--src/plugins/coreplugin/versiondialog.cpp2
-rw-r--r--src/plugins/coreplugin/windowsupport.cpp3
-rw-r--r--src/plugins/cpaster/cpasterplugin.h2
-rw-r--r--src/plugins/cppeditor/cppautocompleter.cpp1
-rw-r--r--src/plugins/cppeditor/cppcodemodelinspectordialog.cpp39
-rw-r--r--src/plugins/cppeditor/cppdoxygen_test.cpp2
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp992
-rw-r--r--src/plugins/cppeditor/cppeditor.h114
-rw-r--r--src/plugins/cppeditor/cppeditor.pro8
-rw-r--r--src/plugins/cppeditor/cppeditor.qbs8
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp2
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.h5
-rw-r--r--src/plugins/cppeditor/cppeditortestcase.cpp1
-rw-r--r--src/plugins/cppeditor/cppeditortestcase.h2
-rw-r--r--src/plugins/cppeditor/cppeditorwidget.cpp1085
-rw-r--r--src/plugins/cppeditor/cppeditorwidget.h151
-rw-r--r--src/plugins/cppeditor/cppelementevaluator.h1
-rw-r--r--src/plugins/cppeditor/cppfunctiondecldeflink.cpp2
-rw-r--r--src/plugins/cppeditor/cpphighlighter.h1
-rw-r--r--src/plugins/cppeditor/cpphoverhandler.cpp6
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy.cpp3
-rw-r--r--src/plugins/cppeditor/cppincludehierarchy_test.cpp2
-rw-r--r--src/plugins/cppeditor/cppoutline.h1
-rw-r--r--src/plugins/cppeditor/cppparsecontext.cpp2
-rw-r--r--src/plugins/cppeditor/cpppreprocessordialog.cpp1
-rw-r--r--src/plugins/cppeditor/cppquickfix_test.cpp2
-rw-r--r--src/plugins/cppeditor/cppquickfixassistant.cpp3
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp50
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.cpp1
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.h4
-rw-r--r--src/plugins/cppeditor/cppuseselections_test.cpp1
-rw-r--r--src/plugins/cppeditor/cppuseselectionsupdater.cpp42
-rw-r--r--src/plugins/cppeditor/cppuseselectionsupdater.h7
-rw-r--r--src/plugins/cppeditor/fileandtokenactions_test.cpp1
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp145
-rw-r--r--src/plugins/cpptools/baseeditordocumentprocessor.h2
-rw-r--r--src/plugins/cpptools/builtincursorinfo.cpp6
-rw-r--r--src/plugins/cpptools/builtineditordocumentparser.cpp5
-rw-r--r--src/plugins/cpptools/builtineditordocumentprocessor.cpp4
-rw-r--r--src/plugins/cpptools/builtineditordocumentprocessor.h2
-rw-r--r--src/plugins/cpptools/clangcompileroptionsbuilder.cpp117
-rw-r--r--src/plugins/cpptools/clangcompileroptionsbuilder.h27
-rw-r--r--src/plugins/cpptools/clangdiagnosticconfigswidget.cpp87
-rw-r--r--src/plugins/cpptools/clangdiagnosticconfigswidget.h3
-rw-r--r--src/plugins/cpptools/clangdiagnosticconfigswidget.ui54
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.cpp115
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.h14
-rw-r--r--src/plugins/cpptools/cppcanonicalsymbol.cpp5
-rw-r--r--src/plugins/cpptools/cppcodemodelinspectordumper.cpp24
-rw-r--r--src/plugins/cpptools/cppcodemodelinspectordumper.h1
-rw-r--r--src/plugins/cpptools/cppcodemodelsettingspage.ui4
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp5
-rw-r--r--src/plugins/cpptools/cppcompletionassist.cpp12
-rw-r--r--src/plugins/cpptools/cppcurrentdocumentfilter.cpp31
-rw-r--r--src/plugins/cpptools/cppeditorwidgetinterface.h54
-rw-r--r--src/plugins/cpptools/cppfindreferences.cpp37
-rw-r--r--src/plugins/cpptools/cppfindreferences.h1
-rw-r--r--src/plugins/cpptools/cppfollowsymbolundercursor.cpp (renamed from src/plugins/cppeditor/cppfollowsymbolundercursor.cpp)83
-rw-r--r--src/plugins/cpptools/cppfollowsymbolundercursor.h (renamed from src/plugins/cppeditor/cppfollowsymbolundercursor.h)37
-rw-r--r--src/plugins/cpptools/cpplocatorfilter.cpp51
-rw-r--r--src/plugins/cpptools/cpplocatorfilter_test.cpp13
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp67
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h8
-rw-r--r--src/plugins/cpptools/cppmodelmanager_test.cpp18
-rw-r--r--src/plugins/cpptools/cppmodelmanagersupport.h2
-rw-r--r--src/plugins/cpptools/cppmodelmanagersupportinternal.cpp13
-rw-r--r--src/plugins/cpptools/cppmodelmanagersupportinternal.h8
-rw-r--r--src/plugins/cpptools/cppprojectinfogenerator.cpp5
-rw-r--r--src/plugins/cpptools/cpprawprojectpart.cpp9
-rw-r--r--src/plugins/cpptools/cpprawprojectpart.h6
-rw-r--r--src/plugins/cpptools/cpprefactoringengine.cpp55
-rw-r--r--src/plugins/cpptools/cpprefactoringengine.h43
-rw-r--r--src/plugins/cpptools/cppselectionchanger.cpp4
-rw-r--r--src/plugins/cpptools/cppsourceprocessor.cpp21
-rw-r--r--src/plugins/cpptools/cppsymbolinfo.h44
-rw-r--r--src/plugins/cpptools/cpptools.pro16
-rw-r--r--src/plugins/cpptools/cpptools.qbs13
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp28
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.cpp4
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.h5
-rw-r--r--src/plugins/cpptools/cpptoolsunittestfiles.pri4
-rw-r--r--src/plugins/cpptools/cppvirtualfunctionassistprovider.cpp (renamed from src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp)24
-rw-r--r--src/plugins/cpptools/cppvirtualfunctionassistprovider.h (renamed from src/plugins/cppeditor/cppvirtualfunctionassistprovider.h)10
-rw-r--r--src/plugins/cpptools/cppvirtualfunctionproposalitem.cpp (renamed from src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp)6
-rw-r--r--src/plugins/cpptools/cppvirtualfunctionproposalitem.h (renamed from src/plugins/cppeditor/cppvirtualfunctionproposalitem.h)8
-rw-r--r--src/plugins/cpptools/cursorineditor.h54
-rw-r--r--src/plugins/cpptools/doxygengenerator.cpp9
-rw-r--r--src/plugins/cpptools/followsymbolinterface.h53
-rw-r--r--src/plugins/cpptools/projectinfo.cpp11
-rw-r--r--src/plugins/cpptools/projectinfo.h2
-rw-r--r--src/plugins/cpptools/projectpart.cpp15
-rw-r--r--src/plugins/cpptools/projectpart.h12
-rw-r--r--src/plugins/cpptools/refactoringengineinterface.h23
-rw-r--r--src/plugins/cpptools/wrappablelineedit.cpp59
-rw-r--r--src/plugins/cpptools/wrappablelineedit.h44
-rw-r--r--src/plugins/cvs/cvsplugin.cpp5
-rw-r--r--src/plugins/cvs/cvssettings.cpp2
-rw-r--r--src/plugins/debugger/breakhandler.cpp2
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp48
-rw-r--r--src/plugins/debugger/cdb/cdbengine.h2
-rw-r--r--src/plugins/debugger/cdb/cdboptionspagewidget.ui2
-rw-r--r--src/plugins/debugger/commonoptionspage.cpp17
-rw-r--r--src/plugins/debugger/debugger.pro1
-rw-r--r--src/plugins/debugger/debugger.qbs7
-rw-r--r--src/plugins/debugger/debuggerconstants.h1
-rw-r--r--src/plugins/debugger/debuggerdialogs.cpp80
-rw-r--r--src/plugins/debugger/debuggerdialogs.h4
-rw-r--r--src/plugins/debugger/debuggerengine.cpp138
-rw-r--r--src/plugins/debugger/debuggerengine.h131
-rw-r--r--src/plugins/debugger/debuggerkitinformation.cpp8
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp391
-rw-r--r--src/plugins/debugger/debuggerruncontrol.cpp859
-rw-r--r--src/plugins/debugger/debuggerruncontrol.h89
-rw-r--r--src/plugins/debugger/debuggersourcepathmappingwidget.cpp2
-rw-r--r--src/plugins/debugger/debuggerstartparameters.h112
-rw-r--r--src/plugins/debugger/disassembleragent.cpp1
-rw-r--r--src/plugins/debugger/gdb/attachgdbadapter.cpp125
-rw-r--r--src/plugins/debugger/gdb/coregdbadapter.cpp321
-rw-r--r--src/plugins/debugger/gdb/coregdbadapter.h78
-rw-r--r--src/plugins/debugger/gdb/gdb.pri10
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp1032
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h253
-rw-r--r--src/plugins/debugger/gdb/gdboptionspage.cpp10
-rw-r--r--src/plugins/debugger/gdb/gdbplainengine.cpp148
-rw-r--r--src/plugins/debugger/gdb/gdbplainengine.h57
-rw-r--r--src/plugins/debugger/gdb/remotegdbserveradapter.cpp459
-rw-r--r--src/plugins/debugger/gdb/remotegdbserveradapter.h68
-rw-r--r--src/plugins/debugger/gdb/startgdbserverdialog.cpp19
-rw-r--r--src/plugins/debugger/gdb/termgdbadapter.cpp208
-rw-r--r--src/plugins/debugger/images/debugger_continue.pngbin2812 -> 2601 bytes
-rw-r--r--src/plugins/debugger/images/debugger_continue@2x.pngbin2271 -> 2222 bytes
-rw-r--r--src/plugins/debugger/images/debugger_continue_1_mask.pngbin97 -> 97 bytes
-rw-r--r--src/plugins/debugger/images/debugger_continue_1_mask@2x.pngbin99 -> 101 bytes
-rw-r--r--src/plugins/debugger/images/debugger_continue_2_mask.pngbin147 -> 157 bytes
-rw-r--r--src/plugins/debugger/images/debugger_continue_2_mask@2x.pngbin192 -> 202 bytes
-rw-r--r--src/plugins/debugger/images/debugger_interrupt.pngbin1231 -> 1193 bytes
-rw-r--r--src/plugins/debugger/images/debugger_interrupt@2x.pngbin1442 -> 1402 bytes
-rw-r--r--src/plugins/debugger/images/debugger_interrupt_mask.pngbin98 -> 100 bytes
-rw-r--r--src/plugins/debugger/images/debugger_interrupt_mask@2x.pngbin101 -> 105 bytes
-rw-r--r--src/plugins/debugger/images/mode_debug.pngbin2061 -> 1756 bytes
-rw-r--r--src/plugins/debugger/images/mode_debug@2x.pngbin6535 -> 5524 bytes
-rw-r--r--src/plugins/debugger/images/mode_debug_mask.pngbin285 -> 282 bytes
-rw-r--r--src/plugins/debugger/images/mode_debug_mask@2x.pngbin547 -> 531 bytes
-rw-r--r--src/plugins/debugger/lldb/lldbengine.cpp105
-rw-r--r--src/plugins/debugger/lldb/lldbengine.h8
-rw-r--r--src/plugins/debugger/loadcoredialog.cpp6
-rw-r--r--src/plugins/debugger/logwindow.cpp10
-rw-r--r--src/plugins/debugger/memoryagent.cpp1
-rw-r--r--src/plugins/debugger/moduleshandler.cpp2
-rw-r--r--src/plugins/debugger/pdb/pdbengine.cpp1
-rw-r--r--src/plugins/debugger/qml/qmlcppengine.cpp43
-rw-r--r--src/plugins/debugger/qml/qmlcppengine.h10
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp168
-rw-r--r--src/plugins/debugger/qml/qmlengine.h8
-rw-r--r--src/plugins/debugger/registerhandler.cpp6
-rw-r--r--src/plugins/debugger/stackhandler.cpp2
-rw-r--r--src/plugins/debugger/terminal.cpp70
-rw-r--r--src/plugins/debugger/terminal.h31
-rw-r--r--src/plugins/debugger/watchhandler.cpp19
-rw-r--r--src/plugins/designer/formeditorplugin.cpp2
-rw-r--r--src/plugins/diffeditor/diffeditor.h1
-rw-r--r--src/plugins/diffeditor/diffeditorwidgetcontroller.cpp2
-rw-r--r--src/plugins/diffeditor/differ.cpp2
-rw-r--r--src/plugins/diffeditor/diffview.h1
-rw-r--r--src/plugins/diffeditor/sidebysidediffeditorwidget.h1
-rw-r--r--src/plugins/diffeditor/unifieddiffeditorwidget.h5
-rw-r--r--src/plugins/fakevim/fakevimoptions.ui4
-rw-r--r--src/plugins/genericprojectmanager/genericmakestep.cpp27
-rw-r--r--src/plugins/genericprojectmanager/genericmakestep.h2
-rw-r--r--src/plugins/genericprojectmanager/genericproject.cpp7
-rw-r--r--src/plugins/genericprojectmanager/genericprojectmanager.qbs1
-rw-r--r--src/plugins/genericprojectmanager/genericprojectwizard.cpp4
-rw-r--r--src/plugins/git/branchdialog.h1
-rw-r--r--src/plugins/git/changeselectiondialog.h4
-rw-r--r--src/plugins/git/gerrit/gerritdialog.cpp2
-rw-r--r--src/plugins/git/gerrit/gerritmodel.h4
-rw-r--r--src/plugins/git/gerrit/gerritplugin.cpp2
-rw-r--r--src/plugins/git/gerrit/gerritplugin.h4
-rw-r--r--src/plugins/git/gitclient.cpp27
-rw-r--r--src/plugins/git/gitclient.h5
-rw-r--r--src/plugins/git/giteditor.h4
-rw-r--r--src/plugins/git/gitplugin.cpp7
-rw-r--r--src/plugins/git/gitplugin.h3
-rw-r--r--src/plugins/git/gitsubmiteditor.h1
-rw-r--r--src/plugins/git/mergetool.h2
-rw-r--r--src/plugins/git/remotemodel.cpp3
-rw-r--r--src/plugins/git/remotemodel.h2
-rw-r--r--src/plugins/git/settingspage.h4
-rw-r--r--src/plugins/git/stashdialog.h1
-rw-r--r--src/plugins/help/centralwidget.h2
-rw-r--r--src/plugins/help/generalsettingspage.h1
-rw-r--r--src/plugins/help/helpplugin.h7
-rw-r--r--src/plugins/help/helpwidget.h1
-rw-r--r--src/plugins/help/images/mode_help.pngbin1445 -> 1328 bytes
-rw-r--r--src/plugins/help/images/mode_help@2x.pngbin5215 -> 4348 bytes
-rw-r--r--src/plugins/help/images/mode_help_mask.pngbin316 -> 312 bytes
-rw-r--r--src/plugins/help/images/mode_help_mask@2x.pngbin629 -> 614 bytes
-rw-r--r--src/plugins/help/searchwidget.h1
-rw-r--r--src/plugins/imageviewer/imageviewerplugin.cpp16
-rw-r--r--src/plugins/ios/images/iosdevice.pngbin196 -> 196 bytes
-rw-r--r--src/plugins/ios/images/iosdevice@2x.pngbin349 -> 351 bytes
-rw-r--r--src/plugins/ios/iosbuildstep.cpp18
-rw-r--r--src/plugins/ios/iosbuildstep.h5
-rw-r--r--src/plugins/ios/iosdsymbuildstep.cpp10
-rw-r--r--src/plugins/ios/iosrunconfiguration.cpp95
-rw-r--r--src/plugins/ios/iosrunconfiguration.h19
-rw-r--r--src/plugins/ios/iosrunfactories.cpp7
-rw-r--r--src/plugins/ios/iosrunner.cpp34
-rw-r--r--src/plugins/ios/iossettingswidget.cpp2
-rw-r--r--src/plugins/macros/imacrohandler.cpp36
-rw-r--r--src/plugins/macros/imacrohandler.h6
-rw-r--r--src/plugins/macros/macroevent.h1
-rw-r--r--src/plugins/macros/macrolocatorfilter.h1
-rw-r--r--src/plugins/macros/macromanager.cpp12
-rw-r--r--src/plugins/macros/macromanager.h4
-rw-r--r--src/plugins/macros/macrooptionswidget.h1
-rw-r--r--src/plugins/macros/macrosplugin.cpp4
-rw-r--r--src/plugins/macros/macrosplugin.h3
-rw-r--r--src/plugins/macros/texteditormacrohandler.cpp5
-rw-r--r--src/plugins/macros/texteditormacrohandler.h2
-rw-r--r--src/plugins/mercurial/mercurialclient.h1
-rw-r--r--src/plugins/mercurial/mercurialplugin.cpp12
-rw-r--r--src/plugins/mercurial/mercurialplugin.h7
-rw-r--r--src/plugins/modeleditor/actionhandler.cpp40
-rw-r--r--src/plugins/modeleditor/actionhandler.h2
-rw-r--r--src/plugins/modeleditor/classviewcontroller.cpp2
-rw-r--r--src/plugins/modeleditor/classviewcontroller.h2
-rw-r--r--src/plugins/modeleditor/componentviewcontroller.cpp22
-rw-r--r--src/plugins/modeleditor/componentviewcontroller.h2
-rw-r--r--src/plugins/modeleditor/diagramsviewmanager.h2
-rw-r--r--src/plugins/modeleditor/dragtool.h2
-rw-r--r--src/plugins/modeleditor/editordiagramview.cpp4
-rw-r--r--src/plugins/modeleditor/editordiagramview.h2
-rw-r--r--src/plugins/modeleditor/elementtasks.cpp16
-rw-r--r--src/plugins/modeleditor/elementtasks.h2
-rw-r--r--src/plugins/modeleditor/extdocumentcontroller.cpp4
-rw-r--r--src/plugins/modeleditor/extdocumentcontroller.h2
-rw-r--r--src/plugins/modeleditor/extpropertiesmview.cpp4
-rw-r--r--src/plugins/modeleditor/extpropertiesmview.h6
-rw-r--r--src/plugins/modeleditor/jsextension.h2
-rw-r--r--src/plugins/modeleditor/modeldocument.cpp2
-rw-r--r--src/plugins/modeleditor/modeldocument.h2
-rw-r--r--src/plugins/modeleditor/modeleditor.cpp131
-rw-r--r--src/plugins/modeleditor/modeleditor.h2
-rw-r--r--src/plugins/modeleditor/modeleditor_plugin.cpp10
-rw-r--r--src/plugins/modeleditor/modeleditorfactory.cpp4
-rw-r--r--src/plugins/modeleditor/modeleditorfactory.h2
-rw-r--r--src/plugins/modeleditor/modelindexer.cpp40
-rw-r--r--src/plugins/modeleditor/modelindexer.h2
-rw-r--r--src/plugins/modeleditor/modelsmanager.cpp22
-rw-r--r--src/plugins/modeleditor/modelsmanager.h2
-rw-r--r--src/plugins/modeleditor/openelementvisitor.cpp16
-rw-r--r--src/plugins/modeleditor/openelementvisitor.h35
-rw-r--r--src/plugins/modeleditor/pxnodecontroller.cpp36
-rw-r--r--src/plugins/modeleditor/pxnodecontroller.h2
-rw-r--r--src/plugins/modeleditor/pxnodeutilities.cpp18
-rw-r--r--src/plugins/modeleditor/pxnodeutilities.h2
-rw-r--r--src/plugins/modeleditor/settingscontroller.h2
-rw-r--r--src/plugins/modeleditor/uicontroller.h2
-rw-r--r--src/plugins/nim/project/nimcompilerbuildstep.cpp4
-rw-r--r--src/plugins/nim/project/nimproject.cpp3
-rw-r--r--src/plugins/nim/project/nimprojectnode.cpp2
-rw-r--r--src/plugins/nim/project/nimprojectnode.h2
-rw-r--r--src/plugins/nim/project/nimrunconfiguration.cpp8
-rw-r--r--src/plugins/nim/project/nimrunconfiguration.h4
-rw-r--r--src/plugins/nim/project/nimrunconfigurationfactory.cpp8
-rw-r--r--src/plugins/nim/project/nimrunconfigurationwidget.cpp10
-rw-r--r--src/plugins/nim/project/nimrunconfigurationwidget.h4
-rw-r--r--src/plugins/nim/project/nimtoolchain.cpp4
-rw-r--r--src/plugins/nim/project/nimtoolchain.h2
-rw-r--r--src/plugins/perforce/perforceplugin.cpp9
-rw-r--r--src/plugins/perforce/perforceplugin.h1
-rw-r--r--src/plugins/projectexplorer/abi.cpp354
-rw-r--r--src/plugins/projectexplorer/abi.h6
-rw-r--r--src/plugins/projectexplorer/abstractmsvctoolchain.cpp9
-rw-r--r--src/plugins/projectexplorer/abstractmsvctoolchain.h9
-rw-r--r--src/plugins/projectexplorer/appoutputpane.cpp8
-rw-r--r--src/plugins/projectexplorer/baseprojectwizarddialog.cpp3
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp16
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.h3
-rw-r--r--src/plugins/projectexplorer/buildconfigurationmodel.cpp184
-rw-r--r--src/plugins/projectexplorer/buildconfigurationmodel.h58
-rw-r--r--src/plugins/projectexplorer/buildenvironmentwidget.cpp2
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.cpp4
-rw-r--r--src/plugins/projectexplorer/buildstep.cpp15
-rw-r--r--src/plugins/projectexplorer/buildstep.h6
-rw-r--r--src/plugins/projectexplorer/buildsteplist.cpp16
-rw-r--r--src/plugins/projectexplorer/buildsteplist.h3
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.cpp13
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.h2
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.cpp38
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.h10
-rw-r--r--src/plugins/projectexplorer/customtoolchain.cpp63
-rw-r--r--src/plugins/projectexplorer/customtoolchain.h8
-rw-r--r--src/plugins/projectexplorer/dependenciespanel.cpp10
-rw-r--r--src/plugins/projectexplorer/deployconfiguration.cpp16
-rw-r--r--src/plugins/projectexplorer/deployconfiguration.h3
-rw-r--r--src/plugins/projectexplorer/deployconfigurationmodel.cpp184
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp2
-rw-r--r--src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp11
-rw-r--r--src/plugins/projectexplorer/extracompiler.cpp4
-rw-r--r--src/plugins/projectexplorer/foldernavigationwidget.cpp410
-rw-r--r--src/plugins/projectexplorer/foldernavigationwidget.h87
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp224
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.h28
-rw-r--r--src/plugins/projectexplorer/gcctoolchainfactories.h2
-rw-r--r--src/plugins/projectexplorer/images/build.pngbin1239 -> 925 bytes
-rw-r--r--src/plugins/projectexplorer/images/build@2x.pngbin2803 -> 2305 bytes
-rw-r--r--src/plugins/projectexplorer/images/build_hammerhandle_mask.pngbin165 -> 173 bytes
-rw-r--r--src/plugins/projectexplorer/images/build_hammerhandle_mask@2x.pngbin240 -> 258 bytes
-rw-r--r--src/plugins/projectexplorer/images/build_hammerhead_mask.pngbin183 -> 183 bytes
-rw-r--r--src/plugins/projectexplorer/images/build_hammerhead_mask@2x.pngbin228 -> 246 bytes
-rw-r--r--src/plugins/projectexplorer/images/build_small.pngbin475 -> 0 bytes
-rw-r--r--src/plugins/projectexplorer/images/buildhammerhandle.pngbin0 -> 153 bytes
-rw-r--r--src/plugins/projectexplorer/images/buildhammerhandle@2x.pngbin0 -> 184 bytes
-rw-r--r--src/plugins/projectexplorer/images/buildhammerhead.pngbin0 -> 143 bytes
-rw-r--r--src/plugins/projectexplorer/images/buildhammerhead@2x.pngbin0 -> 186 bytes
-rw-r--r--src/plugins/projectexplorer/images/debugger_beetle_mask.pngbin198 -> 207 bytes
-rw-r--r--src/plugins/projectexplorer/images/debugger_beetle_mask@2x.pngbin357 -> 375 bytes
-rw-r--r--src/plugins/projectexplorer/images/debugger_start.pngbin2094 -> 1677 bytes
-rw-r--r--src/plugins/projectexplorer/images/debugger_start@2x.pngbin5121 -> 5095 bytes
-rw-r--r--src/plugins/projectexplorer/images/desktopdevice.pngbin181 -> 187 bytes
-rw-r--r--src/plugins/projectexplorer/images/desktopdevice@2x.pngbin227 -> 233 bytes
-rw-r--r--src/plugins/projectexplorer/images/devicestatusindicator.pngbin158 -> 157 bytes
-rw-r--r--src/plugins/projectexplorer/images/devicestatusindicator@2x.pngbin265 -> 269 bytes
-rw-r--r--src/plugins/projectexplorer/images/mode_project.pngbin1658 -> 870 bytes
-rw-r--r--src/plugins/projectexplorer/images/mode_project@2x.pngbin4227 -> 3256 bytes
-rw-r--r--src/plugins/projectexplorer/images/mode_project_mask.pngbin239 -> 235 bytes
-rw-r--r--src/plugins/projectexplorer/images/mode_project_mask@2x.pngbin410 -> 399 bytes
-rw-r--r--src/plugins/projectexplorer/images/rebuildhammerhandles.pngbin189 -> 168 bytes
-rw-r--r--src/plugins/projectexplorer/images/rebuildhammerhandles@2x.pngbin267 -> 240 bytes
-rw-r--r--src/plugins/projectexplorer/images/rebuildhammerheads.pngbin180 -> 143 bytes
-rw-r--r--src/plugins/projectexplorer/images/rebuildhammerheads@2x.pngbin169 -> 178 bytes
-rw-r--r--src/plugins/projectexplorer/images/run.pngbin1719 -> 1152 bytes
-rw-r--r--src/plugins/projectexplorer/images/run@2x.pngbin3058 -> 2832 bytes
-rw-r--r--src/plugins/projectexplorer/images/run_mask.pngbin177 -> 179 bytes
-rw-r--r--src/plugins/projectexplorer/images/run_mask@2x.pngbin273 -> 291 bytes
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp52
-rw-r--r--src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp3
-rw-r--r--src/plugins/projectexplorer/kit.cpp2
-rw-r--r--src/plugins/projectexplorer/kitinformation.cpp25
-rw-r--r--src/plugins/projectexplorer/localenvironmentaspect.cpp4
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp296
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.h27
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp41
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.h4
-rw-r--r--src/plugins/projectexplorer/project.cpp101
-rw-r--r--src/plugins/projectexplorer/project.h53
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.cpp42
-rw-r--r--src/plugins/projectexplorer/projectconfiguration.h33
-rw-r--r--src/plugins/projectexplorer/projectconfigurationmodel.cpp218
-rw-r--r--src/plugins/projectexplorer/projectconfigurationmodel.h (renamed from src/plugins/projectexplorer/runconfigurationmodel.h)44
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp267
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pro16
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs7
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qrc5
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h1
-rw-r--r--src/plugins/projectexplorer/projectexplorericons.cpp8
-rw-r--r--src/plugins/projectexplorer/projectexplorersettings.h6
-rw-r--r--src/plugins/projectexplorer/projectexplorersettingspage.cpp9
-rw-r--r--src/plugins/projectexplorer/projectexplorersettingspage.ui56
-rw-r--r--src/plugins/projectexplorer/projectexplorerunittestfiles.pri12
-rw-r--r--src/plugins/projectexplorer/projectmacro.cpp226
-rw-r--r--src/plugins/projectexplorer/projectmacro.h102
-rw-r--r--src/plugins/projectexplorer/projectmodels.cpp48
-rw-r--r--src/plugins/projectexplorer/projectmodels.h6
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp22
-rw-r--r--src/plugins/projectexplorer/projectnodes.h27
-rw-r--r--src/plugins/projectexplorer/projecttree.cpp58
-rw-r--r--src/plugins/projectexplorer/projecttree.h13
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp95
-rw-r--r--src/plugins/projectexplorer/runconfiguration.cpp180
-rw-r--r--src/plugins/projectexplorer/runconfiguration.h36
-rw-r--r--src/plugins/projectexplorer/runconfigurationmodel.cpp186
-rw-r--r--src/plugins/projectexplorer/runnables.cpp6
-rw-r--r--src/plugins/projectexplorer/runnables.h1
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.cpp40
-rw-r--r--src/plugins/projectexplorer/runsettingspropertiespage.h4
-rw-r--r--src/plugins/projectexplorer/session.cpp40
-rw-r--r--src/plugins/projectexplorer/session.h2
-rw-r--r--src/plugins/projectexplorer/sessiondialog.ui3
-rw-r--r--src/plugins/projectexplorer/settingsaccessor.cpp18
-rw-r--r--src/plugins/projectexplorer/subscription.cpp117
-rw-r--r--src/plugins/projectexplorer/subscription.h (renamed from src/plugins/projectexplorer/deployconfigurationmodel.h)52
-rw-r--r--src/plugins/projectexplorer/target.cpp101
-rw-r--r--src/plugins/projectexplorer/target.h61
-rw-r--r--src/plugins/projectexplorer/targetsettingspanel.cpp16
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp2
-rw-r--r--src/plugins/projectexplorer/task.cpp11
-rw-r--r--src/plugins/projectexplorer/toolchain.h5
-rw-r--r--src/plugins/projectexplorer/toolchainmanager.cpp2
-rw-r--r--src/plugins/pythoneditor/pythoneditorplugin.cpp78
-rw-r--r--src/plugins/pythoneditor/pythonhighlighter.cpp36
-rw-r--r--src/plugins/pythoneditor/pythonhighlighter.h3
-rw-r--r--src/plugins/pythoneditor/pythonindenter.cpp29
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp6
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildconfiguration.h4
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.cpp13
-rw-r--r--src/plugins/qbsprojectmanager/qbsinstallstep.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.cpp54
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.h6
-rw-r--r--src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp3
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp47
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.h7
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectimporter.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.qbs1
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp20
-rw-r--r--src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp117
-rw-r--r--src/plugins/qbsprojectmanager/qbsrunconfiguration.h32
-rw-r--r--src/plugins/qmakeandroidsupport/androidpackageinstallationstep.cpp12
-rw-r--r--src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp62
-rw-r--r--src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp80
-rw-r--r--src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h19
-rw-r--r--src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp19
-rw-r--r--src/plugins/qmakeprojectmanager/addlibrarywizard.h1
-rw-r--r--src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.h1
-rw-r--r--src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp99
-rw-r--r--src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h17
-rw-r--r--src/plugins/qmakeprojectmanager/externaleditors.h1
-rw-r--r--src/plugins/qmakeprojectmanager/makefileparse.h4
-rw-r--r--src/plugins/qmakeprojectmanager/makestep.cpp54
-rw-r--r--src/plugins/qmakeprojectmanager/makestep.h1
-rw-r--r--src/plugins/qmakeprojectmanager/profileeditor.cpp60
-rw-r--r--src/plugins/qmakeprojectmanager/profilehoverhandler.h1
-rw-r--r--src/plugins/qmakeprojectmanager/qmakekitinformation.cpp5
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.cpp8
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.h2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp17
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp8
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp38
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.h5
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp11
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h1
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs1
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp14
-rw-r--r--src/plugins/qmakeprojectmanager/qmakestep.cpp53
-rw-r--r--src/plugins/qmakeprojectmanager/qmakestep.h1
-rw-r--r--src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp10
-rw-r--r--src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/componentcore_constants.h4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/findimplementation.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp9
-rw-r--r--src/plugins/qmldesigner/components/componentcore/selectioncontext.h4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorindicatorgraphicsitem.h4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp1
-rw-r--r--src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp36
-rw-r--r--src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h8
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigator.qrc1
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h2
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp29
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.h3
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp26
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.h1
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp69
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorwidget.h1
-rw-r--r--src/plugins/qmldesigner/components/navigator/warning.pngbin287 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.pngbin898 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.pngbin898 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.pngbin898 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.pngbin390 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button_normal.pngbin379 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.pngbin1328 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/frame.pngbin4826 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/images/gradient.pngbin533 -> 0 bytes
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc12
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp2
-rw-r--r--src/plugins/qmldesigner/components/resources/resources.qrc1
-rw-r--r--src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml10
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorview.cpp4
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp6
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorwidget.h4
-rw-r--r--src/plugins/qmldesigner/designercore/designercore-lib.pri8
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/astobjecttextextractor.h2
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.h2
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/moveobjectbeforeobjectvisitor.h4
-rw-r--r--src/plugins/qmldesigner/designercore/filemanager/objectlengthcalculator.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractview.h7
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlobjectnode.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlstate.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmltimelinekeyframes.h65
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h62
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp10
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h16
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp26
-rw-r--r--src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp7
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp31
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode_p.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h3
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnode.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp45
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltimelinekeyframes.cpp147
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp167
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriteaction.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/textmodifier.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/rewritertransaction.h2
-rw-r--r--src/plugins/qmldesigner/designersettings.cpp2
-rw-r--r--src/plugins/qmldesigner/designersettings.h1
-rw-r--r--src/plugins/qmldesigner/openuiqmlfiledialog.cpp2
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp16
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.qbs6
-rw-r--r--src/plugins/qmldesigner/settingspage.cpp5
-rw-r--r--src/plugins/qmldesigner/settingspage.ui4
-rw-r--r--src/plugins/qmldesigner/shortcutmanager.cpp2
-rw-r--r--src/plugins/qmljseditor/qmljseditorplugin.cpp7
-rw-r--r--src/plugins/qmljseditor/qmljsfindreferences.cpp15
-rw-r--r--src/plugins/qmljseditor/qmljsfindreferences.h1
-rw-r--r--src/plugins/qmljseditor/qmljssemantichighlighter.h1
-rw-r--r--src/plugins/qmljstools/qmljsfunctionfilter.cpp34
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp3
-rw-r--r--src/plugins/qmlprofiler/flamegraphmodel.h5
-rw-r--r--src/plugins/qmlprofiler/flamegraphview.cpp7
-rw-r--r--src/plugins/qmlprofiler/flamegraphview.h1
-rw-r--r--src/plugins/qmlprofiler/inputeventsmodel.cpp2
-rw-r--r--src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml8
-rw-r--r--src/plugins/qmlprofiler/qmlprofiler.qbs4
-rw-r--r--src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp1
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp13
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerclientmanager.h7
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerconfigwidget.h3
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerconfigwidget.ui2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp58
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h16
-rw-r--r--src/plugins/qmlprofiler/qmlprofilereventsview.h7
-rw-r--r--src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp29
-rw-r--r--src/plugins/qmlprofiler/qmlprofilermodelmanager.h23
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerplugin.cpp4
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp27
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatemanager.h13
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatewidget.h3
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsview.h21
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertextmark.cpp22
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertextmark.h10
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertimelinemodel.h7
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.cpp23
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertool.h8
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertraceclient.cpp15
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertraceclient.h7
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertracefile.cpp11
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertraceview.cpp4
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertraceview.h1
-rw-r--r--src/plugins/qmlprofiler/qmltypedevent.cpp8
-rw-r--r--src/plugins/qmlprofiler/tests/Test.qml7
-rw-r--r--src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp18
-rw-r--r--src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp13
-rw-r--r--src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp3
-rw-r--r--src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp8
-rw-r--r--src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp83
-rw-r--r--src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp215
-rw-r--r--src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.h (renamed from src/plugins/debugger/gdb/attachgdbadapter.h)34
-rw-r--r--src/plugins/qmlprofiler/tests/tests.pri5
-rw-r--r--src/plugins/qmlprofiler/tests/tests.qrc6
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp5
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectnodes.cpp18
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectnodes.h2
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp95
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h24
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp6
-rw-r--r--src/plugins/qnx/images/qnx-target.pngbin2810 -> 0 bytes
-rw-r--r--src/plugins/qnx/images/qnxdevice.pngbin0 -> 428 bytes
-rw-r--r--src/plugins/qnx/images/qnxdevice@2x.pngbin0 -> 899 bytes
-rw-r--r--src/plugins/qnx/images/qnxdevicesmall.pngbin0 -> 247 bytes
-rw-r--r--src/plugins/qnx/images/qnxdevicesmall@2x.pngbin0 -> 445 bytes
-rw-r--r--src/plugins/qnx/qnx.pro4
-rw-r--r--src/plugins/qnx/qnx.qbs4
-rw-r--r--src/plugins/qnx/qnx.qrc5
-rw-r--r--src/plugins/qnx/qnxattachdebugdialog.cpp66
-rw-r--r--src/plugins/qnx/qnxattachdebugdialog.h51
-rw-r--r--src/plugins/qnx/qnxattachdebugsupport.cpp171
-rw-r--r--src/plugins/qnx/qnxattachdebugsupport.h81
-rw-r--r--src/plugins/qnx/qnxconfiguration.cpp1
-rw-r--r--src/plugins/qnx/qnxconstants.h2
-rw-r--r--src/plugins/qnx/qnxdebugsupport.cpp211
-rw-r--r--src/plugins/qnx/qnxdebugsupport.h16
-rw-r--r--src/plugins/qnx/qnxdevice.cpp35
-rw-r--r--src/plugins/qnx/qnxdevicefactory.cpp9
-rw-r--r--src/plugins/qnx/qnxplugin.cpp11
-rw-r--r--src/plugins/qnx/qnxrunconfiguration.cpp13
-rw-r--r--src/plugins/qnx/qnxrunconfiguration.h9
-rw-r--r--src/plugins/qnx/qnxrunconfigurationfactory.cpp7
-rw-r--r--src/plugins/qnx/qnxutils.cpp21
-rw-r--r--src/plugins/qnx/qnxutils.h1
-rw-r--r--src/plugins/qtsupport/gettingstartedwelcomepage.cpp2
-rw-r--r--src/plugins/qtsupport/qtkitinformation.cpp6
-rw-r--r--src/plugins/qtsupport/qtoptionspage.cpp4
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxrunsupport.cpp99
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxrunsupport.h54
-rw-r--r--src/plugins/remotelinux/remotelinux.pro2
-rw-r--r--src/plugins/remotelinux/remotelinux.qbs2
-rw-r--r--src/plugins/remotelinux/remotelinuxanalyzesupport.cpp74
-rw-r--r--src/plugins/remotelinux/remotelinuxanalyzesupport.h31
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp36
-rw-r--r--src/plugins/remotelinux/remotelinuxcustomrunconfiguration.h10
-rw-r--r--src/plugins/remotelinux/remotelinuxdebugsupport.cpp64
-rw-r--r--src/plugins/remotelinux/remotelinuxdebugsupport.h10
-rw-r--r--src/plugins/remotelinux/remotelinuxplugin.cpp1
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfiguration.cpp69
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfiguration.h18
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp16
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp34
-rw-r--r--src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h3
-rw-r--r--src/plugins/resourceeditor/qrceditor/resourcefile.cpp4
-rw-r--r--src/plugins/resourceeditor/qrceditor/resourceview.h3
-rw-r--r--src/plugins/resourceeditor/resourceeditorplugin.cpp26
-rw-r--r--src/plugins/resourceeditor/resourceeditorplugin.h2
-rw-r--r--src/plugins/resourceeditor/resourcenode.cpp10
-rw-r--r--src/plugins/resourceeditor/resourcenode.h6
-rw-r--r--src/plugins/scxmleditor/common/stateproperties.cpp2
-rw-r--r--src/plugins/scxmleditor/outputpane/warningmodel.cpp11
-rw-r--r--src/plugins/scxmleditor/plugin_interface/connectableitem.cpp4
-rw-r--r--src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp2
-rw-r--r--src/plugins/scxmleditor/plugin_interface/scattributeitemmodel.cpp3
-rw-r--r--src/plugins/scxmleditor/plugin_interface/transitionitem.cpp2
-rw-r--r--src/plugins/subversion/settingspage.h4
-rw-r--r--src/plugins/subversion/subversionclient.h5
-rw-r--r--src/plugins/subversion/subversioncontrol.cpp1
-rw-r--r--src/plugins/subversion/subversionplugin.cpp5
-rw-r--r--src/plugins/subversion/subversionsettings.cpp4
-rw-r--r--src/plugins/texteditor/basefilefind.cpp12
-rw-r--r--src/plugins/texteditor/basefilefind.h6
-rw-r--r--src/plugins/texteditor/behaviorsettingspage.cpp10
-rw-r--r--src/plugins/texteditor/behaviorsettingswidget.ui4
-rw-r--r--src/plugins/texteditor/codeassist/assistinterface.cpp4
-rw-r--r--src/plugins/texteditor/codeassist/assistproposalitem.h1
-rw-r--r--src/plugins/texteditor/codeassist/assistproposaliteminterface.h2
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.cpp29
-rw-r--r--src/plugins/texteditor/codeassist/codeassistant.h4
-rw-r--r--src/plugins/texteditor/codeassist/functionhintproposal.cpp9
-rw-r--r--src/plugins/texteditor/codeassist/functionhintproposal.h1
-rw-r--r--src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp85
-rw-r--r--src/plugins/texteditor/codeassist/functionhintproposalwidget.h3
-rw-r--r--src/plugins/texteditor/codeassist/genericproposal.cpp5
-rw-r--r--src/plugins/texteditor/codeassist/genericproposal.h1
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalmodel.cpp72
-rw-r--r--src/plugins/texteditor/codeassist/genericproposalmodel.h5
-rw-r--r--src/plugins/texteditor/codeassist/iassistprocessor.h1
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposal.cpp10
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposal.h4
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposalmodel.h1
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposalwidget.cpp10
-rw-r--r--src/plugins/texteditor/codeassist/iassistproposalwidget.h6
-rw-r--r--src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.cpp7
-rw-r--r--src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.h3
-rw-r--r--src/plugins/texteditor/codeassist/runner.cpp4
-rw-r--r--src/plugins/texteditor/codeassist/runner.h10
-rw-r--r--src/plugins/texteditor/codestyleselectorwidget.h8
-rw-r--r--src/plugins/texteditor/findinfiles.h2
-rw-r--r--src/plugins/texteditor/fontsettingspage.cpp2
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp3
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.cpp5
-rw-r--r--src/plugins/texteditor/generichighlighter/manager.h1
-rw-r--r--src/plugins/texteditor/generichighlighter/specificrules.h13
-rw-r--r--src/plugins/texteditor/helpitem.h2
-rw-r--r--src/plugins/texteditor/icodestylepreferencesfactory.h1
-rw-r--r--src/plugins/texteditor/linenumberfilter.h2
-rw-r--r--src/plugins/texteditor/outlinefactory.cpp6
-rw-r--r--src/plugins/texteditor/semantichighlighter.h4
-rw-r--r--src/plugins/texteditor/textdocument.cpp4
-rw-r--r--src/plugins/texteditor/texteditor.cpp81
-rw-r--r--src/plugins/texteditor/texteditor.h4
-rw-r--r--src/plugins/texteditor/texteditor.pro2
-rw-r--r--src/plugins/texteditor/texteditor.qbs2
-rw-r--r--src/plugins/texteditor/texteditor_p.h2
-rw-r--r--src/plugins/texteditor/texteditor_test.cpp8
-rw-r--r--src/plugins/texteditor/texteditoractionhandler.cpp166
-rw-r--r--src/plugins/texteditor/texteditorconstants.h1
-rw-r--r--src/plugins/texteditor/texteditorsettings.h1
-rw-r--r--src/plugins/texteditor/textmark.cpp2
-rw-r--r--src/plugins/texteditor/textmark.h5
-rw-r--r--src/plugins/todo/todoitemsprovider.cpp2
-rw-r--r--src/plugins/todo/todoplugin.cpp2
-rw-r--r--src/plugins/updateinfo/settingspage.cpp2
-rw-r--r--src/plugins/updateinfo/settingspage.ui2
-rw-r--r--src/plugins/valgrind/callgrindvisualisation.h1
-rw-r--r--src/plugins/valgrind/memcheckengine.cpp186
-rw-r--r--src/plugins/valgrind/memcheckengine.h69
-rw-r--r--src/plugins/valgrind/memchecktool.cpp252
-rw-r--r--src/plugins/valgrind/valgrind.pro2
-rw-r--r--src/plugins/valgrind/valgrind.qbs2
-rw-r--r--src/plugins/valgrind/valgrindengine.cpp2
-rw-r--r--src/plugins/valgrind/xmlprotocol/error.h1
-rw-r--r--src/plugins/vcsbase/basevcseditorfactory.cpp4
-rw-r--r--src/plugins/vcsbase/commonsettingspage.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseclientsettings.cpp8
-rw-r--r--src/plugins/vcsbase/vcsbaseeditor.cpp2
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.cpp15
-rw-r--r--src/plugins/vcsbase/vcsbaseplugin.h18
-rw-r--r--src/plugins/vcsbase/vcsprojectcache.cpp4
-rw-r--r--src/plugins/welcome/images/mode_edit_mask.pngbin189 -> 0 bytes
-rw-r--r--src/plugins/welcome/images/mode_welcome.pngbin1243 -> 1100 bytes
-rw-r--r--src/plugins/welcome/images/mode_welcome@2x.pngbin2282 -> 2271 bytes
-rw-r--r--src/plugins/welcome/images/mode_welcome_mask.pngbin100 -> 101 bytes
-rw-r--r--src/plugins/welcome/images/mode_welcome_mask@2x.pngbin106 -> 107 bytes
-rw-r--r--src/plugins/welcome/welcome.qbs1
-rw-r--r--src/plugins/welcome/welcome.qrc1
-rw-r--r--src/plugins/welcome/welcomeplugin.cpp7
-rw-r--r--src/plugins/winrt/images/winrtdevice.pngbin163 -> 164 bytes
-rw-r--r--src/plugins/winrt/images/winrtdevice@2x.pngbin235 -> 239 bytes
-rw-r--r--src/plugins/winrt/winrt.qbs1
-rw-r--r--src/plugins/winrt/winrtdebugsupport.cpp39
-rw-r--r--src/plugins/winrt/winrtdebugsupport.h2
-rw-r--r--src/plugins/winrt/winrtrunconfiguration.cpp14
-rw-r--r--src/plugins/winrt/winrtrunconfiguration.h8
-rw-r--r--src/plugins/winrt/winrtrunfactories.cpp6
-rw-r--r--src/plugins/winrt/winrtrunnerhelper.cpp3
-rw-r--r--src/shared/clang/clang_installation.pri9
-rw-r--r--src/shared/help/bookmarkmanager.cpp6
-rw-r--r--src/tools/clangbackend/clangbackend.pro4
-rw-r--r--src/tools/clangbackend/clangbackend.qbs6
-rw-r--r--src/tools/clangbackend/ipcsource/clangiasyncjob.cpp107
-rw-r--r--src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp78
-rw-r--r--src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp94
-rw-r--r--src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp117
-rw-r--r--src/tools/clangbackend/source/clangasyncjob.h (renamed from src/tools/clangbackend/ipcsource/clangasyncjob.h)4
-rw-r--r--src/tools/clangbackend/source/clangbackend_global.h (renamed from src/tools/clangbackend/ipcsource/clangbackend_global.h)0
-rw-r--r--src/tools/clangbackend/source/clangbackendclangipc-source.pri (renamed from src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri)9
-rw-r--r--src/tools/clangbackend/source/clangclock.h (renamed from src/tools/clangbackend/ipcsource/clangclock.h)0
-rw-r--r--src/tools/clangbackend/source/clangcodecompleteresults.cpp (renamed from src/tools/clangbackend/ipcsource/clangcodecompleteresults.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangcodecompleteresults.h (renamed from src/tools/clangbackend/ipcsource/clangcodecompleteresults.h)0
-rw-r--r--src/tools/clangbackend/source/clangcodemodelserver.cpp (renamed from src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp)45
-rw-r--r--src/tools/clangbackend/source/clangcodemodelserver.h (renamed from src/tools/clangbackend/ipcsource/clangcodemodelserver.h)8
-rw-r--r--src/tools/clangbackend/source/clangcompletecodejob.cpp (renamed from src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp)60
-rw-r--r--src/tools/clangbackend/source/clangcompletecodejob.h (renamed from src/tools/clangbackend/ipcsource/clangcompletecodejob.h)10
-rw-r--r--src/tools/clangbackend/source/clangcreateinitialdocumentpreamblejob.cpp (renamed from src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp)34
-rw-r--r--src/tools/clangbackend/source/clangcreateinitialdocumentpreamblejob.h (renamed from src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.h)9
-rw-r--r--src/tools/clangbackend/source/clangdocument.cpp (renamed from src/tools/clangbackend/ipcsource/clangdocument.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangdocument.h (renamed from src/tools/clangbackend/ipcsource/clangdocument.h)0
-rw-r--r--src/tools/clangbackend/source/clangdocumentjob.h (renamed from src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h)37
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessor.cpp (renamed from src/tools/clangbackend/ipcsource/clangdocumentprocessor.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessor.h (renamed from src/tools/clangbackend/ipcsource/clangdocumentprocessor.h)0
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessors.cpp (renamed from src/tools/clangbackend/ipcsource/clangdocumentprocessors.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangdocumentprocessors.h (renamed from src/tools/clangbackend/ipcsource/clangdocumentprocessors.h)0
-rw-r--r--src/tools/clangbackend/source/clangdocuments.cpp (renamed from src/tools/clangbackend/ipcsource/clangdocuments.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangdocuments.h (renamed from src/tools/clangbackend/ipcsource/clangdocuments.h)0
-rw-r--r--src/tools/clangbackend/source/clangdocumentsuspenderresumer.cpp (renamed from src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.cpp)2
-rw-r--r--src/tools/clangbackend/source/clangdocumentsuspenderresumer.h (renamed from src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.h)0
-rw-r--r--src/tools/clangbackend/source/clangexceptions.cpp (renamed from src/tools/clangbackend/ipcsource/clangexceptions.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangexceptions.h (renamed from src/tools/clangbackend/ipcsource/clangexceptions.h)0
-rw-r--r--src/tools/clangbackend/source/clangfilepath.cpp (renamed from src/tools/clangbackend/ipcsource/clangfilepath.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangfilepath.h (renamed from src/tools/clangbackend/ipcsource/clangfilepath.h)0
-rw-r--r--src/tools/clangbackend/source/clangfilesystemwatcher.cpp (renamed from src/tools/clangbackend/ipcsource/clangfilesystemwatcher.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangfilesystemwatcher.h (renamed from src/tools/clangbackend/ipcsource/clangfilesystemwatcher.h)0
-rw-r--r--src/tools/clangbackend/source/clangfollowsymbol.cpp337
-rw-r--r--src/tools/clangbackend/source/clangfollowsymbol.h52
-rw-r--r--src/tools/clangbackend/source/clangfollowsymboljob.cpp73
-rw-r--r--src/tools/clangbackend/source/clangfollowsymboljob.h (renamed from src/tools/clangbackend/ipcsource/clangrequestreferencesjob.h)15
-rw-r--r--src/tools/clangbackend/source/clangiasyncjob.cpp71
-rw-r--r--src/tools/clangbackend/source/clangiasyncjob.h (renamed from src/tools/clangbackend/ipcsource/clangiasyncjob.h)2
-rw-r--r--src/tools/clangbackend/source/clangjobcontext.cpp (renamed from src/tools/clangbackend/ipcsource/clangjobcontext.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangjobcontext.h (renamed from src/tools/clangbackend/ipcsource/clangjobcontext.h)0
-rw-r--r--src/tools/clangbackend/source/clangjobqueue.cpp (renamed from src/tools/clangbackend/ipcsource/clangjobqueue.cpp)20
-rw-r--r--src/tools/clangbackend/source/clangjobqueue.h (renamed from src/tools/clangbackend/ipcsource/clangjobqueue.h)0
-rw-r--r--src/tools/clangbackend/source/clangjobrequest.cpp (renamed from src/tools/clangbackend/ipcsource/clangjobrequest.cpp)159
-rw-r--r--src/tools/clangbackend/source/clangjobrequest.h (renamed from src/tools/clangbackend/ipcsource/clangjobrequest.h)27
-rw-r--r--src/tools/clangbackend/source/clangjobs.cpp (renamed from src/tools/clangbackend/ipcsource/clangjobs.cpp)37
-rw-r--r--src/tools/clangbackend/source/clangjobs.h (renamed from src/tools/clangbackend/ipcsource/clangjobs.h)3
-rw-r--r--src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp59
-rw-r--r--src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h42
-rw-r--r--src/tools/clangbackend/source/clangreferencescollector.cpp (renamed from src/tools/clangbackend/ipcsource/clangreferencescollector.cpp)2
-rw-r--r--src/tools/clangbackend/source/clangreferencescollector.h (renamed from src/tools/clangbackend/ipcsource/clangreferencescollector.h)2
-rw-r--r--src/tools/clangbackend/source/clangreparsesupportivetranslationunitjob.cpp (renamed from src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp)46
-rw-r--r--src/tools/clangbackend/source/clangreparsesupportivetranslationunitjob.h (renamed from src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.h)9
-rw-r--r--src/tools/clangbackend/source/clangrequestdocumentannotationsjob.cpp71
-rw-r--r--src/tools/clangbackend/source/clangrequestdocumentannotationsjob.h (renamed from src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h)18
-rw-r--r--src/tools/clangbackend/source/clangrequestreferencesjob.cpp (renamed from src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp)40
-rw-r--r--src/tools/clangbackend/source/clangrequestreferencesjob.h (renamed from src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.h)12
-rw-r--r--src/tools/clangbackend/source/clangresumedocumentjob.cpp (renamed from src/tools/clangbackend/ipcsource/clangresumedocumentjob.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangresumedocumentjob.h (renamed from src/tools/clangbackend/ipcsource/clangresumedocumentjob.h)0
-rw-r--r--src/tools/clangbackend/source/clangstring.h (renamed from src/tools/clangbackend/ipcsource/clangstring.h)0
-rw-r--r--src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.cpp (renamed from src/tools/clangbackend/ipcsource/clangsupportivetranslationunitinitializer.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.h (renamed from src/tools/clangbackend/ipcsource/clangsupportivetranslationunitinitializer.h)0
-rw-r--r--src/tools/clangbackend/source/clangsuspenddocumentjob.cpp (renamed from src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp)30
-rw-r--r--src/tools/clangbackend/source/clangsuspenddocumentjob.h39
-rw-r--r--src/tools/clangbackend/source/clangtranslationunit.cpp (renamed from src/tools/clangbackend/ipcsource/clangtranslationunit.cpp)20
-rw-r--r--src/tools/clangbackend/source/clangtranslationunit.h (renamed from src/tools/clangbackend/ipcsource/clangtranslationunit.h)14
-rw-r--r--src/tools/clangbackend/source/clangtranslationunits.cpp (renamed from src/tools/clangbackend/ipcsource/clangtranslationunits.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangtranslationunits.h (renamed from src/tools/clangbackend/ipcsource/clangtranslationunits.h)0
-rw-r--r--src/tools/clangbackend/source/clangtranslationunitupdater.cpp (renamed from src/tools/clangbackend/ipcsource/clangtranslationunitupdater.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangtranslationunitupdater.h (renamed from src/tools/clangbackend/ipcsource/clangtranslationunitupdater.h)0
-rw-r--r--src/tools/clangbackend/source/clangtype.cpp (renamed from src/tools/clangbackend/ipcsource/clangtype.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangtype.h (renamed from src/tools/clangbackend/ipcsource/clangtype.h)0
-rw-r--r--src/tools/clangbackend/source/clangunsavedfilesshallowarguments.cpp (renamed from src/tools/clangbackend/ipcsource/clangunsavedfilesshallowarguments.cpp)0
-rw-r--r--src/tools/clangbackend/source/clangunsavedfilesshallowarguments.h (renamed from src/tools/clangbackend/ipcsource/clangunsavedfilesshallowarguments.h)0
-rw-r--r--src/tools/clangbackend/source/clangupdatedocumentannotationsjob.cpp90
-rw-r--r--src/tools/clangbackend/source/clangupdatedocumentannotationsjob.h (renamed from src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h)22
-rw-r--r--src/tools/clangbackend/source/codecompleter.cpp (renamed from src/tools/clangbackend/ipcsource/codecompleter.cpp)71
-rw-r--r--src/tools/clangbackend/source/codecompleter.h (renamed from src/tools/clangbackend/ipcsource/codecompleter.h)8
-rw-r--r--src/tools/clangbackend/source/codecompletionchunkconverter.cpp (renamed from src/tools/clangbackend/ipcsource/codecompletionchunkconverter.cpp)0
-rw-r--r--src/tools/clangbackend/source/codecompletionchunkconverter.h (renamed from src/tools/clangbackend/ipcsource/codecompletionchunkconverter.h)0
-rw-r--r--src/tools/clangbackend/source/codecompletionsextractor.cpp (renamed from src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp)6
-rw-r--r--src/tools/clangbackend/source/codecompletionsextractor.h (renamed from src/tools/clangbackend/ipcsource/codecompletionsextractor.h)2
-rw-r--r--src/tools/clangbackend/source/commandlinearguments.cpp (renamed from src/tools/clangbackend/ipcsource/commandlinearguments.cpp)0
-rw-r--r--src/tools/clangbackend/source/commandlinearguments.h (renamed from src/tools/clangbackend/ipcsource/commandlinearguments.h)0
-rw-r--r--src/tools/clangbackend/source/cursor.cpp (renamed from src/tools/clangbackend/ipcsource/cursor.cpp)5
-rw-r--r--src/tools/clangbackend/source/cursor.h (renamed from src/tools/clangbackend/ipcsource/cursor.h)1
-rw-r--r--src/tools/clangbackend/source/diagnostic.cpp (renamed from src/tools/clangbackend/ipcsource/diagnostic.cpp)0
-rw-r--r--src/tools/clangbackend/source/diagnostic.h (renamed from src/tools/clangbackend/ipcsource/diagnostic.h)2
-rw-r--r--src/tools/clangbackend/source/diagnosticset.cpp (renamed from src/tools/clangbackend/ipcsource/diagnosticset.cpp)0
-rw-r--r--src/tools/clangbackend/source/diagnosticset.h (renamed from src/tools/clangbackend/ipcsource/diagnosticset.h)0
-rw-r--r--src/tools/clangbackend/source/diagnosticsetiterator.h (renamed from src/tools/clangbackend/ipcsource/diagnosticsetiterator.h)0
-rw-r--r--src/tools/clangbackend/source/fixit.cpp (renamed from src/tools/clangbackend/ipcsource/fixit.cpp)0
-rw-r--r--src/tools/clangbackend/source/fixit.h (renamed from src/tools/clangbackend/ipcsource/fixit.h)0
-rw-r--r--src/tools/clangbackend/source/highlightingmark.cpp (renamed from src/tools/clangbackend/ipcsource/highlightingmark.cpp)8
-rw-r--r--src/tools/clangbackend/source/highlightingmark.h (renamed from src/tools/clangbackend/ipcsource/highlightingmark.h)4
-rw-r--r--src/tools/clangbackend/source/highlightingmarks.cpp (renamed from src/tools/clangbackend/ipcsource/highlightingmarks.cpp)9
-rw-r--r--src/tools/clangbackend/source/highlightingmarks.h (renamed from src/tools/clangbackend/ipcsource/highlightingmarks.h)0
-rw-r--r--src/tools/clangbackend/source/highlightingmarksiterator.h (renamed from src/tools/clangbackend/ipcsource/highlightingmarksiterator.h)0
-rw-r--r--src/tools/clangbackend/source/projectpart.cpp (renamed from src/tools/clangbackend/ipcsource/projectpart.cpp)0
-rw-r--r--src/tools/clangbackend/source/projectpart.h (renamed from src/tools/clangbackend/ipcsource/projectpart.h)0
-rw-r--r--src/tools/clangbackend/source/projects.cpp (renamed from src/tools/clangbackend/ipcsource/projects.cpp)0
-rw-r--r--src/tools/clangbackend/source/projects.h (renamed from src/tools/clangbackend/ipcsource/projects.h)0
-rw-r--r--src/tools/clangbackend/source/skippedsourceranges.cpp (renamed from src/tools/clangbackend/ipcsource/skippedsourceranges.cpp)0
-rw-r--r--src/tools/clangbackend/source/skippedsourceranges.h (renamed from src/tools/clangbackend/ipcsource/skippedsourceranges.h)0
-rw-r--r--src/tools/clangbackend/source/sourcelocation.cpp (renamed from src/tools/clangbackend/ipcsource/sourcelocation.cpp)0
-rw-r--r--src/tools/clangbackend/source/sourcelocation.h (renamed from src/tools/clangbackend/ipcsource/sourcelocation.h)0
-rw-r--r--src/tools/clangbackend/source/sourcerange.cpp (renamed from src/tools/clangbackend/ipcsource/sourcerange.cpp)0
-rw-r--r--src/tools/clangbackend/source/sourcerange.h (renamed from src/tools/clangbackend/ipcsource/sourcerange.h)0
-rw-r--r--src/tools/clangbackend/source/unsavedfile.cpp (renamed from src/tools/clangbackend/ipcsource/unsavedfile.cpp)0
-rw-r--r--src/tools/clangbackend/source/unsavedfile.h (renamed from src/tools/clangbackend/ipcsource/unsavedfile.h)0
-rw-r--r--src/tools/clangbackend/source/unsavedfiles.cpp (renamed from src/tools/clangbackend/ipcsource/unsavedfiles.cpp)0
-rw-r--r--src/tools/clangbackend/source/unsavedfiles.h (renamed from src/tools/clangbackend/ipcsource/unsavedfiles.h)0
-rw-r--r--src/tools/clangbackend/source/utf8positionfromlinecolumn.cpp (renamed from src/tools/clangbackend/ipcsource/utf8positionfromlinecolumn.cpp)0
-rw-r--r--src/tools/clangbackend/source/utf8positionfromlinecolumn.h (renamed from src/tools/clangbackend/ipcsource/utf8positionfromlinecolumn.h)0
-rw-r--r--src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro2
-rw-r--r--src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp4
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpathwatcher.h46
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectincludesaction.h16
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h20
-rw-r--r--src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h16
-rw-r--r--src/tools/clangpchmanagerbackend/source/idpaths.h4
-rw-r--r--src/tools/clangpchmanagerbackend/source/includecollector.cpp4
-rw-r--r--src/tools/clangpchmanagerbackend/source/includecollector.h8
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreator.cpp32
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreator.h12
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchgenerator.h4
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp2
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchmanagerserver.h10
-rw-r--r--src/tools/clangrefactoringbackend/clangrefactoringbackend.pro2
-rw-r--r--src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp13
-rw-r--r--src/tools/clangrefactoringbackend/source/clangquery.cpp2
-rw-r--r--src/tools/clangrefactoringbackend/source/clangquery.h4
-rw-r--r--src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp12
-rw-r--r--src/tools/clangrefactoringbackend/source/clangquerygatherer.h6
-rw-r--r--src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri28
-rw-r--r--src/tools/clangrefactoringbackend/source/clangtool.cpp26
-rw-r--r--src/tools/clangrefactoringbackend/source/clangtool.h15
-rw-r--r--src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp35
-rw-r--r--src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h38
-rw-r--r--src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp39
-rw-r--r--src/tools/clangrefactoringbackend/source/collectsymbolsaction.h73
-rw-r--r--src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h158
-rw-r--r--src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h74
-rw-r--r--src/tools/clangrefactoringbackend/source/findcursorusr.h38
-rw-r--r--src/tools/clangrefactoringbackend/source/findusrforcursoraction.cpp63
-rw-r--r--src/tools/clangrefactoringbackend/source/findusrforcursoraction.h32
-rw-r--r--src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h14
-rw-r--r--src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h4
-rw-r--r--src/tools/clangrefactoringbackend/source/refactoringserver.cpp34
-rw-r--r--src/tools/clangrefactoringbackend/source/refactoringserver.h13
-rw-r--r--src/tools/clangrefactoringbackend/source/sourcelocationentry.cpp42
-rw-r--r--src/tools/clangrefactoringbackend/source/sourcelocationentry.h92
-rw-r--r--src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp4
-rw-r--r--src/tools/clangrefactoringbackend/source/sourcerangeextractor.h6
-rw-r--r--src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h142
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolentry.cpp41
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolentry.h62
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolfinder.h16
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexer.cpp50
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexer.h50
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexing.cpp30
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexing.h87
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexinginterface.h40
-rw-r--r--src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp16
-rw-r--r--src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h24
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolscollector.cpp63
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolscollector.h57
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h54
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorage.cpp30
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorage.h158
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorageinterface.h40
-rw-r--r--src/tools/icons/qtcreatoricons.svg1164
-rw-r--r--src/tools/qml2puppet/qml2puppet/qml2puppet.pro3
-rw-r--r--src/tools/qtcrashhandler/qtcrashhandler.pro7
-rw-r--r--src/tools/sdktool/addcmakeoperation.cpp2
-rw-r--r--src/tools/sdktool/adddebuggeroperation.cpp2
-rw-r--r--src/tools/sdktool/adddeviceoperation.cpp2
-rw-r--r--src/tools/sdktool/addkeysoperation.cpp2
-rw-r--r--src/tools/sdktool/addkitoperation.cpp2
-rw-r--r--src/tools/sdktool/addqtoperation.cpp2
-rw-r--r--src/tools/sdktool/addtoolchainoperation.cpp2
-rw-r--r--src/tools/sdktool/findkeyoperation.cpp2
-rw-r--r--src/tools/sdktool/findvalueoperation.cpp2
-rw-r--r--src/tools/sdktool/getoperation.cpp2
-rw-r--r--src/tools/sdktool/main.cpp6
-rw-r--r--src/tools/sdktool/rmcmakeoperation.cpp2
-rw-r--r--src/tools/sdktool/rmdebuggeroperation.cpp2
-rw-r--r--src/tools/sdktool/rmdeviceoperation.cpp2
-rw-r--r--src/tools/sdktool/rmkeysoperation.cpp2
-rw-r--r--src/tools/sdktool/rmkitoperation.cpp2
-rw-r--r--src/tools/sdktool/rmqtoperation.cpp2
-rw-r--r--src/tools/sdktool/rmtoolchainoperation.cpp2
-rw-r--r--src/tools/tools.pro3
-rw-r--r--tests/auto/debugger/tst_dumpers.cpp116
-rw-r--r--tests/auto/environment/tst_environment.cpp149
-rw-r--r--tests/auto/utils/camelhumpmatcher/camelhumpmatcher.pro6
-rw-r--r--tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs8
-rw-r--r--tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp145
-rw-r--r--tests/auto/utils/stringutils/tst_stringutils.cpp12
-rw-r--r--tests/auto/utils/utils.pro1
-rw-r--r--tests/cpplocators/testdata_basic/file1.cpp4
-rw-r--r--tests/manual/clang-format-for-qtc/clang-format-for-qtc.pro4
-rw-r--r--tests/manual/clang-format-for-qtc/test.cpp690
-rw-r--r--tests/manual/debugger/simple/simple_test_app.cpp6
-rw-r--r--tests/system/objects.map4
-rw-r--r--tests/system/shared/project.py8
-rw-r--r--tests/system/suite_SCOM/tst_SCOM02/test.py2
-rw-r--r--tests/system/suite_debugger/tst_simple_analyze/test.py6
-rw-r--r--tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv11
-rw-r--r--tests/system/suite_debugger/tst_simple_debug/test.py6
-rw-r--r--tests/system/suite_editors/tst_delete_externally/test.py8
-rw-r--r--tests/system/suite_editors/tst_edit_externally/test.py4
-rw-r--r--tests/system/suite_general/tst_create_proj_wizard/test.py17
-rw-r--r--tests/system/suite_qtquick/tst_qtquick_creation/test.py12
-rw-r--r--tests/system/suite_qtquick/tst_qtquick_creation3/test.py24
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.cpp9
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.h7
-rw-r--r--tests/unit/echoserver/echoserver.pro4
-rw-r--r--tests/unit/echoserver/echoserverprocessmain.cpp4
-rw-r--r--tests/unit/mockup/projectexplorer/toolchain.h3
-rw-r--r--tests/unit/unittest/activationsequencecontextprocessor-test.cpp8
-rw-r--r--tests/unit/unittest/clang_dependency.pri2
-rw-r--r--tests/unit/unittest/clangasyncjob-base.cpp7
-rw-r--r--tests/unit/unittest/clangcodemodelserver-test.cpp46
-rw-r--r--tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp23
-rw-r--r--tests/unit/unittest/clangfollowsymbol-test.cpp385
-rw-r--r--tests/unit/unittest/clangjobqueue-test.cpp5
-rw-r--r--tests/unit/unittest/clangpathwatcher-test.cpp31
-rw-r--r--tests/unit/unittest/clangquery-test.cpp4
-rw-r--r--tests/unit/unittest/clangquerygatherer-test.cpp2
-rw-r--r--tests/unit/unittest/clangqueryprojectfindfilter-test.cpp2
-rw-r--r--tests/unit/unittest/clangreferencescollector-test.cpp2
-rw-r--r--tests/unit/unittest/clientserverinprocess-test.cpp24
-rw-r--r--tests/unit/unittest/codecompleter-test.cpp33
-rw-r--r--tests/unit/unittest/createtablesqlstatementbuilder-test.cpp109
-rw-r--r--tests/unit/unittest/creator_dependency.pri6
-rw-r--r--tests/unit/unittest/data/complete_smartpointer.cpp58
-rw-r--r--tests/unit/unittest/data/followsymbol_header.h (renamed from src/libs/sqlite/tablewriteworker.h)39
-rw-r--r--tests/unit/unittest/data/followsymbol_main.cpp (renamed from src/libs/sqlite/tablewriteworkerproxy.h)67
-rw-r--r--tests/unit/unittest/data/symbolindexing_main1.cpp36
-rw-r--r--tests/unit/unittest/data/symbolscollector_simple.cpp15
-rw-r--r--tests/unit/unittest/data/symbolscollector_unsaved.cpp1
-rw-r--r--tests/unit/unittest/diagnosticset-test.cpp2
-rw-r--r--tests/unit/unittest/dummyclangipcclient.h3
-rw-r--r--tests/unit/unittest/google-using-declarations.h47
-rw-r--r--tests/unit/unittest/googletest.h4
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp34
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h12
-rw-r--r--tests/unit/unittest/highlightingmarks-test.cpp38
-rw-r--r--tests/unit/unittest/includecollector-test.cpp2
-rw-r--r--tests/unit/unittest/mockclangcodemodelclient.h10
-rw-r--r--tests/unit/unittest/mockclangcodemodelserver.h2
-rw-r--r--tests/unit/unittest/mockmutex.h37
-rw-r--r--tests/unit/unittest/mockrefactoringserver.h16
-rw-r--r--tests/unit/unittest/mocksqlitedatabase.h54
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.cpp56
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.h107
-rw-r--r--tests/unit/unittest/mocksqlitewritestatement.h59
-rw-r--r--tests/unit/unittest/mocksymbolindexing.h45
-rw-r--r--tests/unit/unittest/mocksymbolscollector.h50
-rw-r--r--tests/unit/unittest/mocksymbolstorage.h38
-rw-r--r--tests/unit/unittest/pchcreator-test.cpp14
-rw-r--r--tests/unit/unittest/pchmanagerclient-test.cpp7
-rw-r--r--tests/unit/unittest/pchmanagerserver-test.cpp2
-rw-r--r--tests/unit/unittest/projectupdater-test.cpp23
-rw-r--r--tests/unit/unittest/querysqlitestatementfactory-test.cpp (renamed from src/plugins/debugger/gdb/termgdbadapter.h)65
-rw-r--r--tests/unit/unittest/readandwritemessageblock-test.cpp8
-rw-r--r--tests/unit/unittest/refactoringclient-test.cpp4
-rw-r--r--tests/unit/unittest/refactoringclientserverinprocess-test.cpp30
-rw-r--r--tests/unit/unittest/refactoringcompilationdatabase-test.cpp6
-rw-r--r--tests/unit/unittest/refactoringdatabaseinitializer-test.cpp92
-rw-r--r--tests/unit/unittest/refactoringengine-test.cpp16
-rw-r--r--tests/unit/unittest/refactoringserver-test.cpp25
-rw-r--r--tests/unit/unittest/smallstring-test.cpp453
-rw-r--r--tests/unit/unittest/sourcerangeextractor-test.cpp4
-rw-r--r--tests/unit/unittest/sqlitecolumn-test.cpp39
-rw-r--r--tests/unit/unittest/sqlitedatabase-test.cpp74
-rw-r--r--tests/unit/unittest/sqlitedatabasebackend-test.cpp66
-rw-r--r--tests/unit/unittest/sqliteindex-test.cpp66
-rw-r--r--tests/unit/unittest/sqlitestatement-test.cpp601
-rw-r--r--tests/unit/unittest/sqlitetable-test.cpp94
-rw-r--r--tests/unit/unittest/sqliteteststatement.h54
-rw-r--r--tests/unit/unittest/sqlitetransaction-test.cpp115
-rw-r--r--tests/unit/unittest/sqlstatementbuilder-test.cpp119
-rw-r--r--tests/unit/unittest/storagesqlitestatementfactory-test.cpp163
-rw-r--r--tests/unit/unittest/stringcache-test.cpp197
-rw-r--r--tests/unit/unittest/symbolindexer-test.cpp163
-rw-r--r--tests/unit/unittest/symbolindexing-test.cpp112
-rw-r--r--tests/unit/unittest/symbolquery-test.cpp93
-rw-r--r--tests/unit/unittest/symbolscollector-test.cpp179
-rw-r--r--tests/unit/unittest/symbolstorage-test.cpp205
-rw-r--r--tests/unit/unittest/unittest-matchers.h78
-rw-r--r--tests/unit/unittest/unittest.pro21
-rw-r--r--tests/unit/unittest/unittests-main.cpp2
1940 files changed, 37906 insertions, 21894 deletions
diff --git a/.gitignore b/.gitignore
index c9d7aca99c..cdee18b344 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,7 @@
.DS_Store
/.qmake.cache
/.qmake.stash
+/.clang-format
Makefile*
Thumbs.db
core
@@ -51,6 +52,7 @@ wrapper.sh
/src/app/Info.plist
/src/plugins/**/*.json
/src/plugins/coreplugin/ide_version.h
+/src/libs/qt-breakpad/bin
app_version.h
phony.c
diff --git a/README.md b/README.md
index 87bc9e34fb..dbaa481626 100644
--- a/README.md
+++ b/README.md
@@ -242,14 +242,14 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
1. Clone LLVM and switch to a suitable branch
- git clone http://llvm.org/git/llvm.git
+ git clone https://git.llvm.org/git/llvm.git/
cd llvm
git checkout release_39
2. Clone Clang into llvm/tools/clang and switch to a suitable branch
cd tools
- git clone http://llvm.org/git/clang.git
+ git clone https://git.llvm.org/git/clang.git/
cd clang
git checkout release_39
diff --git a/dist/clangformat/.clang-format b/dist/clangformat/.clang-format
new file mode 100644
index 0000000000..25df05eb26
--- /dev/null
+++ b/dist/clangformat/.clang-format
@@ -0,0 +1,115 @@
+# .clang-format for Qt Creator
+#
+# This is for clang-format >= 5.0.
+#
+# The configuration below follows the Qt Creator Coding Rules [1] as closely as
+# possible. For documentation of the options, see [2].
+#
+# Use ../../tests/manual/clang-format-for-qtc/test.cpp for documenting problems
+# or testing changes.
+#
+# [1] https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html
+# [2] https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+#
+---
+Language: Cpp
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: DontAlign
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: true
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+BreakBeforeBinaryOperators: All
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit: 100
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - forever # avoids { wrapped to next line
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeCategories:
+ - Regex: '^<Q.*'
+ Priority: 200
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+# Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between.
+MacroBlockBegin: ""
+MacroBlockEnd: ""
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 4
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 150
+PenaltyBreakBeforeFirstCallParameter: 300
+PenaltyBreakComment: 500
+PenaltyBreakFirstLessLess: 400
+PenaltyBreakString: 600
+PenaltyExcessCharacter: 50
+PenaltyReturnTypeOnItsOwnLine: 300
+PointerAlignment: Right
+ReflowComments: false
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: true
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
diff --git a/dist/clangformat/README.md b/dist/clangformat/README.md
new file mode 100644
index 0000000000..05fd065c01
--- /dev/null
+++ b/dist/clangformat/README.md
@@ -0,0 +1,157 @@
+# .clang-format for Qt Creator
+
+Alongside this file you find an EXPERIMENTAL .clang-format configuration file
+for the Qt Creator code base.
+
+The current configuration is useful, but not fully in accordance with the
+coding rules. There is also other undesired formatting. Running clang-format
+blindly will not only improve formatting here and there, but will also
+normalize/worsen code that is already considered ideally formatted. See section
+"Coding rules violated by clang-format" below for more information.
+
+If needed, clang-format can be instructed to not format code ranges. Do not
+overuse this.
+
+ // clang-format off
+ void unformatted_code ;
+ // clang-format on
+
+For more information about clang-format, see
+
+ <https://clang.llvm.org/docs/ClangFormat.html>
+
+## Prerequisites
+
+ * clang-format >= 5.0
+
+## Set up Qt Creator for use with clang-format
+
+### Install the configuration file
+
+For a given source file to format, clang-format it will read the configuration
+from .clang-format in the closest parent directory for the file to format.
+
+Hence symlink/copy .clang-format from this directory to e.g. Qt Creator's top
+level directory:
+
+For Linux/macOS:
+
+ $ cd $QTC_SOURCE
+ $ ln -s dist/clangformat/.clang-format
+
+For Windows:
+
+ $ cd $QTC_SOURCE
+ $ copy dist\clangformat\.clang-format # Do not forget to keep this updated
+
+### Configure Qt Creator
+
+ 1. Enable the Beautifier plugin and restart to load it.
+
+ 2. Configure the plugin:
+ In Menu: Tools > Options > Beautifier > Tab: Clang Format
+ * Select a valid clang-format executable
+ * Use predefined style: File
+ * Fallback style: None
+
+ 3. Set shortcuts for convenience:
+ In Menu: Tools > Options > Environment > Keyboard
+ * ClangFormat / FormatFile - e.g. Alt+C, F
+ * ClangFormat / FormatAtCursor - e.g. Alt+C, C
+ * ClangFormat / DisableFormattingSelectedText - e.g. Alt+C, D
+
+Due to several issues outlined below the FormatFile action might be of limited
+use.
+
+## Coding rules enforced by clang-format
+
+This is a copy-pasted list of coding rules from
+<https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html> that can be
+enforced with the current configuration:
+
+* Formatting
+ * Whitespace
+ * Use four spaces for indentation, no tabs.
+ * Always use only one blank line (to group statements together)
+ * Pointers and References: For pointers or references, always use a single
+ space before an asterisk (*) or an ampersand (&), but never after.
+ * Operator Names and Parentheses: Do not use spaces between operator names
+ and parentheses.
+ * Function Names and Parentheses: Do not use spaces between function names
+ and parentheses.
+ * Keywords: Always use a single space after a keyword, and before a curly
+ brace.
+ * Braces
+ * As a base rule, place the left curly brace on the same line as the start
+ of the statement.
+ * Exception: Function implementations and class declarations always have
+ the left brace in the beginning of a line
+ * Line Breaks
+ * Keep lines shorter than 100 characters
+ * Insert line breaks if necessary.
+ * Commas go at the end of a broken line.
+ * Operators start at the beginning of the new line.
+ * Namespaces:
+ * Put the left curly brace on the same line as the namespace keyword.
+ * Do not indent declarations or definitions inside.
+ * Optional, but recommended if the namespaces spans more than a few lines:
+ Add a comment after the right curly brace repeating the namespace.
+* Patterns and Practices
+ * C++11 and C++14 Features / Lambdas:
+ * Optionally, place the lambda completely on one line if it fits.
+ * Place a closing parenthesis and semicolon of an enclosing function call
+ on the same line as the closing brace of the lambda.
+
+## Coding rules violated by clang-format
+
+* Formatting / Namespaces
+ * As an exception, if there is only a single class declaration inside the
+ namespace, all can go on a single line. Currently this ends up on several
+ lines, which is noisy.
+* Patterns and Practices / C++11 and C++14 Features / Lambdas
+ * If you are using a lambda in an 'if' statement, start the lambda on a new
+ line.
+
+### Other undesired formattings
+
+For a more complete list of observations and problems, see the "// NOTE: "
+comments in ../../tests/manual/clang-format-for-qtc/test.cpp.
+
+#### Manually aligned complex expressions in e.g. if-conditions are collapsed
+
+We want:
+
+ if (someFancyAndLongerExpression1
+ || someFancyAndLongerExpression2
+ || someFancyAndLongerExpression3) {
+ return value;
+ }
+
+Current:
+
+ if (someFancyAndLongerExpression1 || someFancyAndLongerExpression2
+ || someFancyAndLongerExpression3) {
+ return value;
+ }
+
+#### connect() calls do not follow the standard two-line pattern
+
+In general, for middle-sized and longer connect() calls we want to follow this
+two-line pattern.
+
+ connect(sender, &SomeFancySender::signal,
+ receiver, &SomeFancyReceiver::slot);
+
+Current:
+
+ connect(sender,
+ &SomeFancySender::signal,
+ receiver,
+ &SomeFancySender::slot);
+
+#### QTC_ASSERT and excess space after return keyword
+
+For QTC_ASSERT in combination with the return keyword, an excess space is added:
+
+ QTC_ASSERT(headItem, return );
+
diff --git a/doc/src/android/deploying-android.qdoc b/doc/src/android/deploying-android.qdoc
index cf9018ce31..0074867b77 100644
--- a/doc/src/android/deploying-android.qdoc
+++ b/doc/src/android/deploying-android.qdoc
@@ -82,22 +82,6 @@
To use Ministro to install the Qt libraries, select the
\uicontrol {Use Ministro service to install Qt} option.
- \section1 Deploying Qt Libraries for Debugging
-
- To test your application on a device that is physically connected to the
- development host (or on an emulator), you can copy the Qt libraries into a
- temporary directory on your device and run the application against them.
-
- An APK built in this way is not distributable, since it relies on the device
- containing the Qt libraries in the correct location. However, as the Qt
- libraries are only copied into the device once, this method provides a fast
- turn-around time, and is therefore convenient for testing the application
- during development.
-
- Select the \uicontrol {Deploy local Qt libraries to temporary directory} option to
- deploy Qt libraries to the \c{/data/local/tmp/qt} folder on the device and
- to run the application against them.
-
\section1 Packaging Applications
Because bundling applications as APK packages is not
diff --git a/doc/src/editors/creator-beautifier.qdoc b/doc/src/editors/creator-beautifier.qdoc
index c47f9fb512..52662b53c9 100644
--- a/doc/src/editors/creator-beautifier.qdoc
+++ b/doc/src/editors/creator-beautifier.qdoc
@@ -174,7 +174,13 @@
\endlist
In addition to the \uicontrol {Format Current File} command, ClangFormat
- and Uncrustify provide the \uicontrol {Format Selected Text} command. If you
+ and Uncrustify provide additional commands.
+ ClangFormat provides the \uicontrol {Format at Cursor} command. If you
+ select it when no text is selected, the syntactic entity under the cursor
+ is formatted. The \uicontrol {Disable Formatting for Selected Text} command
+ wraps selected lines within \c {// clang-format off} and
+ \c {// clang-format on}.
+ Uncrustify provides the \uicontrol {Format Selected Text} command. If you
select it when no text is selected, the whole file is formatted by default.
To disable this behavior, deselect the
\uicontrol {Format entire file if no text was selected} check box.
diff --git a/doc/src/editors/creator-clang-codemodel.qdoc b/doc/src/editors/creator-clang-codemodel.qdoc
index 24cf8be38d..4b29842e96 100644
--- a/doc/src/editors/creator-clang-codemodel.qdoc
+++ b/doc/src/editors/creator-clang-codemodel.qdoc
@@ -133,8 +133,8 @@
language files if you develop mainly using C, select the
\uicontrol {Interpret ambiguous headers as C headers} check box.
- \li To process pre-compiled headers, deselect the
- \uicontrol {Ignore pre-compiled headers} check box.
+ \li To process precompiled headers, deselect the
+ \uicontrol {Ignore precompiled headers} check box.
\li To avoid out-of-memory crashes caused by indexing huge source files
that are typically auto-generated by scripts or code, the size of
diff --git a/doc/src/editors/creator-modeling.qdoc b/doc/src/editors/creator-modeling.qdoc
index 2c09149a12..0de481668e 100644
--- a/doc/src/editors/creator-modeling.qdoc
+++ b/doc/src/editors/creator-modeling.qdoc
@@ -71,10 +71,16 @@
\endlist
You can group elements by surrounding them with a boundary. When you move
- the boundary, all elements within it are moved together. Similarly, classes
- that you lay on packages are moved with the packages. You can move
- individual elements and modify their properties (5) by selecting them. You
- can also use \e multiselection to group elements temporarily.
+ the boundary, all elements within it are moved together. Similary drag
+ a swimlane to the diagram. When you move the swimlane all elements right
+ to the swimlane (for vertical swimlanes) or below it (for horizontal swimlanes)
+ will be moved together. A vertical swimlane is created when you drop the
+ swimlane icon on the top border of the diagram and a horizontal swimlane
+ is created when you drop the icon near the left border.
+
+ Classes or other objects that you lay on packages are moved with the packages.
+ You can move individual elements and modify their properties (5) by selecting
+ them. You can also use \e multiselection to group elements temporarily.
Drag the mouse over elements to select them and apply actions such as
changing their \e stereotype or color. A stereotype is a classifier for
@@ -399,7 +405,9 @@
For more information about the available options, see \e standard.def
in the \e share/qtcreator/modeleditor directory in the \QC installation
- directory.
+ directory. It describes also how to define custom relation types
+ and templates for existing types (such as a composition relation that
+ can be drawn between classes).
You can add your own definition file and save it with the file extension
\e .def to add custom colors and icons for stereotypes, elements, or tool
diff --git a/doc/src/howto/creator-autotest.qdoc b/doc/src/howto/creator-autotest.qdoc
index 2bd3ad5cf7..ac54307b65 100644
--- a/doc/src/howto/creator-autotest.qdoc
+++ b/doc/src/howto/creator-autotest.qdoc
@@ -201,7 +201,7 @@
If a test takes more than a minute to execute, the default timeout might
stop the test execution. To increase the timeout, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Test Settings} > \uicontrol General.
+ \uicontrol Options > \uicontrol {Testing} > \uicontrol General.
\section2 Selecting Tests to Run
@@ -220,7 +220,7 @@
You can add filters to specify the directories within the current project
to scan for tests. Select \uicontrol Tools > \uicontrol Options >
- \uicontrol {Test Settings} > \uicontrol General > \uicontrol Add, and
+ \uicontrol {Testing} > \uicontrol General > \uicontrol Add, and
specify paths to the directories to scan for tests. Wildcards are not
supported in the filter expressions.
@@ -242,7 +242,7 @@
several times in order to get an accurate measurement. This depends on the
measurement back-end that you can select in the
\uicontrol {Benchmark Metrics} group in \uicontrol Tools >
- \uicontrol Options > \uicontrol {Test Settings} > \uicontrol {Qt Test}:
+ \uicontrol Options > \uicontrol {Testing} > \uicontrol {Qt Test}:
walltime, CPU tick counter, event counter, Valgrind Callgrind, and Linux
Perf. For more information, see \l{Creating a Benchmark}.
@@ -260,7 +260,7 @@
\section2 Specifying Settings for Running Google Tests
To specify settings for running Google tests, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Test Settings} > \uicontrol {Google Test}.
+ \uicontrol Options > \uicontrol {Testing} > \uicontrol {Google Test}.
\image qtcreator-autotests-options-google.png
@@ -286,7 +286,7 @@
can be parsed, which might lead to information loss. The lost information
might be retrievable when viewing the results as plain text.
To view the results of Qt tests as plain text, select \uicontrol Tools >
- \uicontrol Options > \uicontrol {Test Settings} > \uicontrol {Qt Test}, and
+ \uicontrol Options > \uicontrol {Testing} > \uicontrol {Qt Test}, and
then deselect the \uicontrol {Use XML output} check box. Then select the
\inlineimage text.png
(\uicontrol {Switch Between Visual and Text Display}) button in the
@@ -356,7 +356,7 @@
By default, test result output is limited to 100,000 characters. The output
pane is automatically scrolled down when new results are added. To display
full results, select \uicontrol Tools > \uicontrol Options >
- \uicontrol {Test Settings} > \uicontrol General, and then deselect the
+ \uicontrol {Testing} > \uicontrol General, and then deselect the
\uicontrol {Limit result output} check box. To disable automatic scrolling,
deselect the \uicontrol {Automatically scroll results} check box.
diff --git a/qbs/modules/libclang/functions.js b/qbs/modules/libclang/functions.js
index 5ad07af8fa..17d1bc4f9a 100644
--- a/qbs/modules/libclang/functions.js
+++ b/qbs/modules/libclang/functions.js
@@ -1,8 +1,8 @@
-var Environment = loadExtension("qbs.Environment")
-var File = loadExtension("qbs.File")
-var FileInfo = loadExtension("qbs.FileInfo")
+var Environment = require("qbs.Environment")
+var File = require("qbs.File")
+var FileInfo = require("qbs.FileInfo")
var MinimumLLVMVersion = "3.9.0"
-var Process = loadExtension("qbs.Process")
+var Process = require("qbs.Process")
function readOutput(executable, args)
{
diff --git a/qbs/modules/qtc/qtc.js b/qbs/modules/qtc/qtc.js
index 7183592b7b..375841af4e 100644
--- a/qbs/modules/qtc/qtc.js
+++ b/qbs/modules/qtc/qtc.js
@@ -1,6 +1,6 @@
-var File = loadExtension("qbs.File");
-var FileInfo = loadExtension("qbs.FileInfo");
-var TextFile = loadExtension("qbs.TextFile");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var TextFile = require("qbs.TextFile");
function getExportBlock(productFile)
{
diff --git a/qbs/modules/qtc/qtc.qbs b/qbs/modules/qtc/qtc.qbs
index 9b8c3c68bb..86effdd3b3 100644
--- a/qbs/modules/qtc/qtc.qbs
+++ b/qbs/modules/qtc/qtc.qbs
@@ -4,16 +4,16 @@ import qbs.FileInfo
import "qtc.js" as HelperFunctions
Module {
- property string qtcreator_display_version: '4.4.1'
+ property string qtcreator_display_version: '4.5.0-beta1'
property string ide_version_major: '4'
property string ide_version_minor: '4'
- property string ide_version_release: '1'
+ property string ide_version_release: '82'
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.'
+ ide_version_release
property string ide_compat_version_major: '4'
property string ide_compat_version_minor: '4'
- property string ide_compat_version_release: '0'
+ property string ide_compat_version_release: '82'
property string qtcreator_compat_version: ide_compat_version_major + '.'
+ ide_compat_version_minor + '.' + ide_compat_version_release
diff --git a/qtcreator.pri b/qtcreator.pri
index a1dd1fe807..4dddddce4a 100644
--- a/qtcreator.pri
+++ b/qtcreator.pri
@@ -1,12 +1,12 @@
!isEmpty(QTCREATOR_PRI_INCLUDED):error("qtcreator.pri already included")
QTCREATOR_PRI_INCLUDED = 1
-QTCREATOR_VERSION = 4.4.1
-QTCREATOR_COMPAT_VERSION = 4.4.0
+QTCREATOR_VERSION = 4.4.82
+QTCREATOR_COMPAT_VERSION = 4.4.82
VERSION = $$QTCREATOR_VERSION
-QTCREATOR_DISPLAY_VERSION = 4.4.1
+QTCREATOR_DISPLAY_VERSION = 4.5.0-beta1
QTCREATOR_COPYRIGHT_YEAR = 2017
-BINARY_ARTIFACTS_BRANCH = 4.4
+BINARY_ARTIFACTS_BRANCH = master
CONFIG += c++14
diff --git a/scripts/deployqt.py b/scripts/deployqt.py
index 8e7fa8ba47..5559587f99 100755
--- a/scripts/deployqt.py
+++ b/scripts/deployqt.py
@@ -223,8 +223,6 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
os.path.join(install_dir, 'bin')))
deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang.exe'),
clangbindirtarget))
- deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang-cl.exe'),
- clangbindirtarget))
resourcetarget = os.path.join(clanglibdirtarget, 'clang')
else:
libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*'))
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index 6966a50cf5..7ec7c02fb0 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -2714,6 +2714,8 @@ class DumperBase:
if typeobj.code == TypeCodePointer:
self.putFormattedPointer(value)
+ if value.summary and self.useFancy:
+ self.putValue(self.hexencode(value.summary), 'utf8:1:0')
return
self.putAddress(value.address())
@@ -2741,7 +2743,7 @@ class DumperBase:
#warn('BITFIELD VALUE: %s %d %s' % (value.name, value.lvalue, typeName))
self.putNumChild(0)
if typeobj.ltarget and typeobj.ltarget.code == TypeCodeEnum:
- self.putValue(typeobj.ltarget.typeData().enumDisplay(value.lvalue, value.laddress))
+ self.putValue(typeobj.ltarget.typeData().enumHexDisplay(value.lvalue, value.laddress))
else:
self.putValue(value.lvalue)
self.putType(typeName)
@@ -2797,6 +2799,12 @@ class DumperBase:
#warn('INAMES: %s ' % self.expandedINames)
#warn('EXPANDED: %s ' % (self.currentIName in self.expandedINames))
self.putType(typeName)
+
+ if value.summary is not None and self.useFancy:
+ self.putValue(self.hexencode(value.summary), 'utf8:1:0')
+ self.putNumChild(0)
+ return
+
self.putNumChild(1)
self.putEmptyValue()
#warn('STRUCT GUTS: %s ADDRESS: 0x%x ' % (value.name, value.address()))
@@ -2858,6 +2866,7 @@ class DumperBase:
self.laddress = None # Own address.
self.lIsInScope = True
self.ldisplay = None
+ self.summary = None # Always hexencoded UTF-8.
self.lbitpos = None
self.lbitsize = None
self.targetValue = None # For references.
@@ -2873,6 +2882,7 @@ class DumperBase:
val.laddress = self.laddress
val.lIsInScope = self.lIsInScope
val.ldisplay = self.ldisplay
+ val.summary = self.summary
val.lbitpos = self.lbitpos
val.lbitsize = self.lbitsize
val.targetValue = self.targetValue
@@ -2898,9 +2908,11 @@ class DumperBase:
% (self.name, self.type.name, self.lbitsize, self.lbitpos,
self.dumper.hexencode(self.ldata), addr)
- def display(self):
+ def display(self, useHex = 1):
if self.type.code == TypeCodeEnum:
intval = self.integer()
+ if useHex:
+ return self.type.typeData().enumHexDisplay(intval, self.laddress)
return self.type.typeData().enumDisplay(intval, self.laddress)
simple = self.value()
if simple is not None:
@@ -3188,6 +3200,7 @@ class DumperBase:
return self.detypedef().dereference()
val = self.dumper.Value(self.dumper)
if self.type.code == TypeCodeReference:
+ val.summary = self.summary
if self.nativeValue is None:
val.laddress = self.pointer()
if val.laddress is None and self.laddress is not None:
diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py
index 16a11929db..17a833a9f5 100644
--- a/share/qtcreator/debugger/gdbbridge.py
+++ b/share/qtcreator/debugger/gdbbridge.py
@@ -354,7 +354,9 @@ class Dumper(DumperBase):
}[code]
if tdata.code == TypeCodeEnum:
tdata.enumDisplay = lambda intval, addr : \
- self.nativeTypeEnumDisplay(nativeType, intval)
+ self.nativeTypeEnumDisplay(nativeType, intval, 0)
+ tdata.enumHexDisplay = lambda intval, addr : \
+ self.nativeTypeEnumDisplay(nativeType, intval, 1)
if tdata.code == TypeCodeStruct:
tdata.lalignment = lambda : \
self.nativeStructAlignment(nativeType)
@@ -385,13 +387,17 @@ class Dumper(DumperBase):
targs2 = self.listTemplateParametersManually(str(nativeType))
return targs if len(targs) >= len(targs2) else targs2
- def nativeTypeEnumDisplay(self, nativeType, intval):
+ def nativeTypeEnumDisplay(self, nativeType, intval, useHex):
+ if useHex:
+ format = lambda text, intval: '%s (0x%04x)' % (text, intval)
+ else:
+ format = lambda text, intval: '%s (%d)' % (text, intval)
try:
enumerators = []
for field in nativeType.fields():
# If we found an exact match, return it immediately
if field.enumval == intval:
- return '%s (%d)' % (field.name, intval)
+ return format(field.name, intval)
enumerators.append((field.name, field.enumval))
# No match was found, try to return as flags
@@ -407,9 +413,11 @@ class Dumper(DumperBase):
if not found or v != 0:
# Leftover value
flags.append('unknown:%d' % v)
- return "(%s) (%d)" % (" | ".join(flags), intval)
+ return format(" | ".join(flags), intval)
except:
pass
+ if useHex:
+ return '0x%04x' % intval;
return '%d' % intval
def nativeTypeId(self, nativeType):
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py
index 968572bb4d..181b7ac657 100644
--- a/share/qtcreator/debugger/lldbbridge.py
+++ b/share/qtcreator/debugger/lldbbridge.py
@@ -125,10 +125,27 @@ class Dumper(DumperBase):
def fromNativeValue(self, nativeValue):
self.check(isinstance(nativeValue, lldb.SBValue))
- nativeValue.SetPreferSyntheticValue(False)
nativeType = nativeValue.GetType()
+ typeName = nativeType.GetName()
code = nativeType.GetTypeClass()
+ # Display the result of GetSummary() for Core Foundation string
+ # and string-like types.
+ summary = None
+ if self.useFancy:
+ if (typeName.startswith('CF')
+ or typeName.startswith('__CF')
+ or typeName.startswith('NS')
+ or typeName.startswith('__NSCF')):
+ if code == lldb.eTypeClassPointer:
+ summary = nativeValue.Dereference().GetSummary()
+ elif code == lldb.eTypeClassReference:
+ summary = nativeValue.Dereference().GetSummary()
+ else:
+ summary = nativeValue.GetSummary()
+
+ nativeValue.SetPreferSyntheticValue(False)
+
if code == lldb.eTypeClassReference:
nativeTargetType = nativeType.GetDereferencedType()
if not nativeTargetType.IsPointerType():
@@ -196,6 +213,7 @@ class Dumper(DumperBase):
#elif code == lldb.eTypeClassVector:
# val.type.ltarget = self.fromNativeType(nativeType.GetVectorElementType())
+ val.summary = summary
val.lIsInScope = nativeValue.IsInScope()
val.name = nativeValue.GetName()
return val
diff --git a/share/qtcreator/debugger/misctypes.py b/share/qtcreator/debugger/misctypes.py
index 30c5985e5e..0b7662660b 100644
--- a/share/qtcreator/debugger/misctypes.py
+++ b/share/qtcreator/debugger/misctypes.py
@@ -381,3 +381,34 @@ def qdump__QtcDumperTest_BufArray(d, value):
for i in d.childRange():
d.putSubItem(i, (buffer + (i * objsize)).dereference().cast(valueType))
+def qdump__QtcDumperTest_List__NodeX(d, value):
+ typename = value.type.unqualified().name
+ pos0 = typename.find('<')
+ pos1 = typename.find('>')
+ tName = typename[pos0+1:pos1]
+ d.putBetterType('QtcDumperTest_List<' + tName + '>::Node')
+ d.putNumChild(1)
+ if d.isExpanded():
+ obj_type = d.lookupType(tName)
+ with Children(d):
+ d.putSubItem("this", value.cast(obj_type))
+ d.putFields(value)
+ #d.putPlainChildren(value)
+
+def qdump__QtcDumperTest_List(d, value):
+ innerType = value.type[0]
+ d.putNumChild(1)
+ p = value['root']
+ if d.isExpanded():
+ with Children(d):
+ d.putSubItem("[p]", p)
+ d.putSubItem("[root]", value["root"].cast(innerType))
+ d.putFields(value)
+ #d.putPlainChildren(value)
+
+def qdump__QtcDumperTest_String(d, value):
+ with Children(d):
+ first = d.hexdecode(d.putSubItem('first', value['first']).value)
+ second = d.hexdecode(d.putSubItem('second', value['second']).value)
+ third = d.hexdecode(d.putSubItem('third', value['third']).value)[:-1]
+ d.putValue(first + ', ' + second + ', ' + third)
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index 287ddfd199..221d28361d 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -645,7 +645,7 @@ def qdump__QFlags(d, value):
i = value.split('{int}')[0]
enumType = value.type[0]
if d.isGdb:
- d.putValue(i.cast('enum ' + enumType.name).display())
+ d.putValue(i.cast('enum ' + enumType.name).display(useHex = 1))
else:
d.putValue(i.cast(enumType.name).display())
d.putNumChild(0)
diff --git a/share/qtcreator/modeleditor/standard.def b/share/qtcreator/modeleditor/standard.def
index 010ce382f5..662bee8e48 100644
--- a/share/qtcreator/modeleditor/standard.def
+++ b/share/qtcreator/modeleditor/standard.def
@@ -2,6 +2,9 @@
//
// Language syntax and commands:
//
+//
+// An Icon defines an icon of an element selected by stereotype.
+//
// Icon {
// id: <id>
// title: <a UI title. Defaults to the id of the icon.>
@@ -29,6 +32,8 @@
// RoundedRect { x: <x>; y: <y>; width: <width>; height: <height>; radius: <radius> }
// Circle { x: <center_x>; y: <center_y>; radius: <radius> }
// Ellipse { x: <center_x>; y: <center_y>; radiusX: <radius_x>; radiusY: <radius_y> }
+// Diamond { x: <center_x>; y: <center_y>; width: <width>; height: <height; filled: <yes or no or true or false> }
+// Triangle { x: <center_x>; y: <center_y>; width: <width>; height: <height; filled: <yes or no or true or false> }
// Arc { x: <center_x>; y: <center_y>; radiusX: <radius_x>; radiusY: <radius_y>; start: <start_angle>; span: <span_angle> }
// MoveTo { x: <x>; y: <y> }
// LineTo { x: <x>; y: <y> }
@@ -38,12 +43,94 @@
// }
// }
//
+//
+// A Relation defines a new relation between to items:
+//
+// Relation {
+// id: <id>
+// title: <a UI title. Defaults to the id of the icon.>
+// elements: <A list of elements that may be the start or end element of the relation. Can be one of
+// class, component, package, diagram, item or any id of an Icon definition. Must be given.>
+// stereotype: <Stereotype as a string. Defaults to nothing.>
+// name: <Name of the relation. Defaults to nothing.>
+// direction: <One of AtoB, BtoA or Bi. Defaults to nothing.>
+// pattern: <The pattern used for the relation shaft.
+// One of solid, dash, dot, dashdot, dashdotdot. Defaults to solid>
+// color: <The color of the relation. One of A or B (uses the color of the respective end element) or
+// any valid color (#rrggbb or a color name). Defaults to A.>
+// End {
+// end: <One of A or B. Defines the settings of the relations end.>
+// elements: <Overrides the elements property of parent.>
+// role: <The role of the end. A string that defaults to nothing.>
+// cardinality: <An integer or a string defining the cardinality of the end. Defaults to nothing.>
+// navigable: <If the end is navigable. One of Yes, No, True, False. Defaults to nothing.>
+// head: <Predefined shapes. One of none, arrow, triangle, filledtriangle, diamond, filleddiamond.
+// Defaults to none.>
+// }
+// }
+//
+//
+// A Dependency defines settings of a dependency specialization:
+//
+// Dependency {
+// id: <id>
+// title: <a UI title. Defaults to the id of the icon.>
+// elements: <A list of elements that provides this specialization in its menu. Can be one of
+// class, component, package, diagram, item or any id of an Icon definition. Must be given.>
+// stereotype: <Stereotype as a string. Defaults to nothing.>
+// name: <Name of the relation. Defaults to nothing.>
+// direction: <One of AtoB, BtoA or Bi. Defaults to nothing.>
+// }
+//
+//
+// An Inheritance defines settings of an inheritance specialization:
+//
+// Inheritance {
+// id: <id>
+// title: <a UI title. Defaults to the id of the icon.>
+// elements: <A list of elements that provides this specialization in its menu. Can be one of
+// class or any id of an Icon definition for classes. Defaults to class.>
+// stereotype: <Stereotype as a string. Defaults to nothing.>
+// name: <Name of the relation. Defaults to nothing.>
+// }
+//
+//
+// An Association defines settings of an association specialization:
+//
+// Association {
+// id: <id>
+// title: <a UI title. Defaults to the id of the icon.>
+// elements: <A list of elements that provides this specialization in its menu. Can be one of
+// class or any id of an Icon definition for classes. Defaults to class.>
+// stereotype: <Stereotype as a string. Defaults to nothing.>
+// name: <Name of the relation. Defaults to nothing.>
+// End {
+// end: <One of A or B. Defines the settings of the relations end.>
+// role: <The role of the end. A string that defaults to nothing.>
+// cardinality: <An integer or a string defining the cardinality of the end. Defaults to nothing.>
+// navigable: <If the end is navigable. One of Yes, No, True, False. Defaults to nothing.>
+// relationship: <One of Association, Aggregation, Composition. Defaults to Association.>
+// }
+// }
+//
+//
+// A toolbar of icons. If no toolbar is defined the standard toolbar is shown.
+//
// Toolbar {
// id: <id>
// title: <a Ui title. Defaults to the id of the toolbar>
+// element: <List of elements the toolbar is assigned to. Each element can be one of package, component,
+// class, item or any Icon definition. Default to nothing which defines an object toolbar for
+// diagrams.>
// priority: <priority number which decides about the position of toolbar in toolbox. Defaults to 0>
// Tools {
-// Tool { title: <Ui title>; element: <element type>; stereotype: <stereotype, defaults to nothing> }
+// Tool {
+// title: <Ui title>;
+// element: <element type; one of package, class, component, item, annotation, boundary or swimlane
+// for object toolbars. One of dependency, inheritance or association for element toolbars.
+// Must be given>;
+// stereotype: <stereotype, defaults to nothing>
+// }
// Separator
// }
// }
@@ -104,6 +191,54 @@ Icon {
}
}
+Association {
+ id: Aggregation
+ title: "Aggregation"
+ End {
+ end: A
+ cardinality: "*"
+ navigable: yes
+ relationship: aggregation
+ }
+}
+
+Association {
+ id: Composition
+ title: "Composition"
+ End {
+ end: A
+ cardinality: "1"
+ navigable: yes
+ relationship: composition
+ }
+}
+
+// ********************
+// ** Class Toolbars **
+// ********************
+
+Toolbar {
+ id: ClassToolbar
+ element: class
+ Tools {
+ Tool { element: dependency }
+ Tool { element: inheritance }
+ Tool { element: association }
+ Tool { element: Aggregation }
+ Tool { element: Composition }
+ }
+}
+
+Toolbar {
+ id: InterfaceToolbar
+ element: Interface
+ Tools {
+ Tool { element: dependency }
+ Tool { element: inheritance }
+ }
+}
+
+
// ****************
// ** Components **
// ****************
@@ -178,6 +313,29 @@ Icon {
}
}
+Relation {
+ id: Communication
+ elements: UseCase, Actor
+ pattern: solid
+ color: A
+ End {
+ end: A
+ }
+ End {
+ end: B
+ }
+}
+
+Toolbar {
+ id: UseCaseToolbar
+ element: UseCase, Actor
+ Tools {
+ Tool { element: Communication }
+ Tool { element: dependency }
+ }
+}
+
+
// ****************
// ** Activities **
// ****************
@@ -276,6 +434,30 @@ Icon {
}
}
+Relation {
+ id: Controlflow
+ pattern: solid
+ color: A
+ End {
+ end: A
+ elements: Start, Activity, Condition, HorizontalBar, VerticalBar
+ }
+ End {
+ end: B
+ elements: Activity, Condition, HorizontalBar, VerticalBar, Termination
+ head: arrow
+ }
+}
+
+Toolbar {
+ id: ActivityToolbar
+ element: Start, Activity, Condition, HorizontalBar, VerticalBar
+ Tools {
+ Tool { element: Controlflow }
+ Tool { element: dependency }
+ }
+}
+
// **************
// ** Toolbars **
// **************
@@ -292,6 +474,7 @@ Toolbar {
Separator
Tool { title: "Annotation"; element: annotation }
Tool { title: "Boundary"; element: boundary }
+ Tool { title: "Swimlane"; element: swimlane }
}
}
@@ -304,6 +487,7 @@ Toolbar {
Separator
Tool { title: "Annotation"; element: annotation }
Tool { title: "Boundary"; element: boundary }
+ Tool { title: "Swimlane"; element: swimlane }
}
}
@@ -316,6 +500,7 @@ Toolbar {
Separator
Tool { title: "Annotation"; element: annotation }
Tool { title: "Boundary"; element: boundary }
+ Tool { title: "Swimlane"; element: swimlane }
}
}
@@ -331,5 +516,6 @@ Toolbar {
Separator
Tool { title: "Annotation"; element: annotation }
Tool { title: "Boundary"; element: boundary }
+ Tool { title: "Swimlane"; element: swimlane }
}
}
diff --git a/share/qtcreator/qml-type-descriptions/builtins.qmltypes b/share/qtcreator/qml-type-descriptions/builtins.qmltypes
index f99c636889..811ad87c1e 100644
--- a/share/qtcreator/qml-type-descriptions/builtins.qmltypes
+++ b/share/qtcreator/qml-type-descriptions/builtins.qmltypes
@@ -417,6 +417,7 @@ Module {
Property { name: "amplitude"; type: "qreal" }
Property { name: "overshoot"; type: "qreal" }
Property { name: "period"; type: "qreal" }
+ Property { name: "bezierCurve"; type: "QVariantList" }
}
Component {
name: "QDeclarativeFlickable"
diff --git a/share/qtcreator/qml-type-descriptions/qbs.qmltypes b/share/qtcreator/qml-type-descriptions/qbs.qmltypes
index 20d36bf532..718baa6a04 100644
--- a/share/qtcreator/qml-type-descriptions/qbs.qmltypes
+++ b/share/qtcreator/qml-type-descriptions/qbs.qmltypes
@@ -20,7 +20,7 @@ Module {
prototype: "QQuickItem"
Property { name: "condition"; type: "bool" }
Property { name: "limitToSubProject"; type: "bool" }
- Property { name: "multiplexConfigurationId"; type: "string" }
+ Property { name: "multiplexConfigurationIds"; type: "string"; isList: true }
Property { name: "name"; type: "string" }
Property { name: "productTypes"; type: "string"; isList: true }
Property { name: "profiles"; type: "string"; isList: true }
@@ -49,6 +49,7 @@ Module {
Property { name: "condition"; type: "bool" }
Property { name: "fileTags"; type: "string"; isList: true }
Property { name: "patterns"; type: "string"; isList: true }
+ Property { name: "priority"; type: "int" }
}
Component {
name: "Group"
@@ -119,6 +120,14 @@ Module {
Property { name: "version"; type: "string" }
}
Component {
+ name: "Profile"
+ exports: [ "qbs/Profile 1.0" ]
+ prototype: "QQuickItem"
+ Property { name: "baseProfile"; type: "string" }
+ Property { name: "condition"; type: "bool" }
+ Property { name: "name"; type: "string" }
+ }
+ Component {
name: "Project"
exports: [ "qbs/Project 1.0" ]
prototype: "QQuickItem"
diff --git a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp
index b77b1d23ae..bb9ec18161 100644
--- a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp
+++ b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp
@@ -41,7 +41,6 @@ static TypeName properDelemitingOfType(const TypeName &typeName)
}
InstanceContainer::InstanceContainer()
- : m_instanceId(-1), m_majorNumber(-1), m_minorNumber(-1)
{
}
diff --git a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h
index f8b4d84680..6dc86bf93c 100644
--- a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h
+++ b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h
@@ -67,14 +67,14 @@ public:
NodeMetaType metaType() const;
private:
- qint32 m_instanceId;
+ qint32 m_instanceId = -1;
TypeName m_type;
- qint32 m_majorNumber;
- qint32 m_minorNumber;
+ qint32 m_majorNumber = -1;
+ qint32 m_minorNumber = -1;
QString m_componentPath;
QString m_nodeSource;
- qint32 m_nodeSourceType;
- qint32 m_metaType;
+ qint32 m_nodeSourceType = 0;
+ qint32 m_metaType = 0;
};
QDebug operator <<(QDebug debug, const InstanceContainer &command);
diff --git a/share/qtcreator/qml/qmlpuppet/container/sharedmemory_unix.cpp b/share/qtcreator/qml/qmlpuppet/container/sharedmemory_unix.cpp
index 53e7c7533a..9cd0e2a953 100644
--- a/share/qtcreator/qml/qmlpuppet/container/sharedmemory_unix.cpp
+++ b/share/qtcreator/qml/qmlpuppet/container/sharedmemory_unix.cpp
@@ -388,7 +388,8 @@ bool SharedMemory::createInternal(QSharedMemory::AccessMode mode, int size)
}
struct stat statBuffer;
- fstat(m_fileHandle, &statBuffer);
+ if (fstat(m_fileHandle, &statBuffer) == -1)
+ return false;
int fileSize = statBuffer.st_size;
if (fileSize < size) {
@@ -457,7 +458,8 @@ bool SharedMemory::attachInternal(QSharedMemory::AccessMode mode)
}
struct stat statBuffer;
- fstat(m_fileHandle, &statBuffer);
+ if (fstat(m_fileHandle, &statBuffer) == -1)
+ return false;
int size = statBuffer.st_size;
int protection = mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_WRITE;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
index 875c80d378..fb1bad0603 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
@@ -157,7 +157,7 @@ void sortFilterImports(const QStringList &imports, QStringList *workingImports,
namespace QmlDesigner {
-static NodeInstanceServer *nodeInstanceServerInstance = 0;
+static NodeInstanceServer *nodeInstanceServerInstance = nullptr;
static void notifyPropertyChangeCallBackFunction(QObject *object, const PropertyName &propertyName)
{
@@ -170,11 +170,7 @@ static void (*notifyPropertyChangeCallBackPointer)(QObject *, const PropertyName
NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
NodeInstanceServerInterface(),
m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)),
- m_nodeInstanceClient(nodeInstanceClient),
- m_timer(0),
- m_renderTimerInterval(16),
- m_slowRenderTimer(false),
- m_slowRenderTimerInterval(200)
+ m_nodeInstanceClient(nodeInstanceClient)
{
qmlRegisterType<DummyContextObject>("QmlDesigner", 1, 0, "DummyContextObject");
@@ -184,10 +180,6 @@ NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstance
Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack();
}
-NodeInstanceServer::~NodeInstanceServer()
-{
-}
-
QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<InstanceContainer> &containerVector)
{
Q_ASSERT(declarativeView() || quickView());
@@ -247,7 +239,7 @@ ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const
bool NodeInstanceServer::hasInstanceForObject(QObject *object) const
{
- if (object == 0)
+ if (object == nullptr)
return false;
return m_objectInstanceHash.contains(object) && m_objectInstanceHash.value(object).isValid();
@@ -671,7 +663,7 @@ QQmlContext *NodeInstanceServer::context() const
if (engine())
return rootContext();
- return 0;
+ return nullptr;
}
QQmlContext *NodeInstanceServer::rootContext() const
@@ -979,7 +971,7 @@ void NodeInstanceServer::setInstanceAuxiliaryData(const PropertyValueContainer &
}
}
if (auxiliaryContainer.name().endsWith("@NodeInstance")) {
- PropertyName propertyName = auxiliaryContainer.name().left(auxiliaryContainer.name().count() - 12);
+ PropertyName propertyName = auxiliaryContainer.name().left(auxiliaryContainer.name().count() - 13);
if (!auxiliaryContainer.value().isNull()) {
setInstancePropertyVariant(PropertyValueContainer(auxiliaryContainer.instanceId(),
propertyName,
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
index c7a0e58b32..c777c0a7a1 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
@@ -71,7 +71,6 @@ public:
typedef QPair<QString, QPointer<QObject> > DummyPair;
explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient);
- ~NodeInstanceServer();
void createInstances(const CreateInstancesCommand &command);
void changeFileUrl(const ChangeFileUrlCommand &command);
@@ -214,10 +213,10 @@ private:
QPointer<Internal::ChildrenChangeEventFilter> m_childrenChangeEventFilter;
QUrl m_fileUrl;
NodeInstanceClientInterface *m_nodeInstanceClient;
- int m_timer;
- int m_renderTimerInterval;
- bool m_slowRenderTimer;
- int m_slowRenderTimerInterval;
+ int m_timer = 0;
+ int m_renderTimerInterval = 16;
+ bool m_slowRenderTimer = false;
+ int m_slowRenderTimerInterval = 200;
QVector<InstancePropertyPair> m_changedPropertyList;
QByteArray m_importCode;
QPointer<QObject> m_dummyContextObject;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri
index 5a10394f18..39599385a8 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri
@@ -13,11 +13,6 @@ include (../interfaces/interfaces.pri)
include (../types/types.pri)
include (../qmlprivategate/qmlprivategate.pri)
-QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
-!isEmpty(QT_BREAKPAD_ROOT_PATH) {
- include($$QT_BREAKPAD_ROOT_PATH/qtbreakpad.pri)
-}
-
SOURCES += $$PWD/qml2puppetmain.cpp
RESOURCES += $$PWD/../qmlpuppet.qrc
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp
index 0d29b554e6..22460eaf6b 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp
@@ -111,7 +111,8 @@ int internalMain(QGuiApplication *application)
#ifdef ENABLE_QT_BREAKPAD
- QtSystemExceptionHandler systemExceptionHandler;
+ const QString libexecPath = QCoreApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH;
+ QtSystemExceptionHandler systemExceptionHandler(libexecPath);
#endif
new QmlDesigner::Qt5NodeInstanceClientProxy(application);
diff --git a/share/qtcreator/templates/wizards/autotest/wizard.json b/share/qtcreator/templates/wizards/autotest/wizard.json
index 9e57f2ea56..d7d2d75f14 100644
--- a/share/qtcreator/templates/wizards/autotest/wizard.json
+++ b/share/qtcreator/templates/wizards/autotest/wizard.json
@@ -157,17 +157,18 @@
[
{
"trKey": "qmake",
- "value": "qmake"
- },
- {
- "trKey": "Qbs",
- "value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ "value": "qmake",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
"condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "Qbs",
+ "value": "qbs",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
}
]
}
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/CMakeLists.txt
deleted file mode 100644
index 1e36df0c28..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-
-project(%{ProjectName} LANGUAGES CXX)
-
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-
-find_package(Qt5 COMPONENTS Core Quick REQUIRED)
-
-add_executable(${PROJECT_NAME} "%{MainCppFileName}" "qml.qrc")
-
-target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick)
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/app.pro b/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/app.pro
deleted file mode 100644
index 07633b1e61..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/app.pro
+++ /dev/null
@@ -1,25 +0,0 @@
-QT += quick
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any feature of Qt which as been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if you use deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += %{MainCppFileName}
-
-RESOURCES += qml.qrc
-
-# Additional import path used to resolve QML modules in Qt Creator's code model
-QML_IMPORT_PATH =
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp
deleted file mode 100644
index 9579699af1..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-%{Cpp:LicenseTemplate}\
-%{JS: QtSupport.qtIncludes([], ["QtGui/QGuiApplication", "QtQml/QQmlApplicationEngine"])}
-int main(int argc, char *argv[])
-{
- QGuiApplication app(argc, argv);
-
- QQmlApplicationEngine engine;
- engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
- if (engine.rootObjects().isEmpty())
- return -1;
-
- return app.exec();
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.qml.tpl b/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.qml.tpl
deleted file mode 100644
index 47241e6ebd..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/main.qml.tpl
+++ /dev/null
@@ -1,30 +0,0 @@
-import QtQuick 2.4
-import QtCanvas3D 1.1
-import QtQuick.Window 2.2
-
-import "glcode.js" as GLCode
-
-Window {
- title: qsTr("%{ProjectName}")
- width: 1280
- height: 768
- visible: true
-
- Canvas3D {
- id: canvas3d
- anchors.fill: parent
- focus: true
-
- onInitializeGL: {
- GLCode.initializeGL(canvas3d);
- }
-
- onPaintGL: {
- GLCode.paintGL(canvas3d);
- }
-
- onResizeGL: {
- GLCode.resizeGL(canvas3d);
- }
- }
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/MainForm.ui.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/MainForm.ui.qml.tpl
deleted file mode 100644
index a41e66157c..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/MainForm.ui.qml.tpl
+++ /dev/null
@@ -1,29 +0,0 @@
-import QtQuick %{QtQuickVersion}
-
-Rectangle {
- property alias mouseArea: mouseArea
- property alias textEdit: textEdit
-
- width: 360
- height: 360
-
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- }
-
- TextEdit {
- id: textEdit
- text: qsTr("Enter some text...")
- verticalAlignment: Text.AlignVCenter
- anchors.top: parent.top
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: 20
- Rectangle {
- anchors.fill: parent
- anchors.margins: -10
- color: "transparent"
- border.width: 1
- }
- }
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/file.qbs b/share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs
index 679e14eaa7..679e14eaa7 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/file.qbs
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/app.qbs
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/3dapplication.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/icon.png
index 4cda40554b..4cda40554b 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/3dapplication.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/icon.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/3dapplication@2x.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/icon@2x.png
index 148cc540e7..148cc540e7 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/3dapplication@2x.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/icon@2x.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/main.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/main.qml.tpl
new file mode 100644
index 0000000000..4e8466a8b3
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/main.qml.tpl
@@ -0,0 +1,67 @@
+import QtQuick 2.4
+import QtCanvas3D 1.1
+import QtQuick.Window 2.2
+@if %{UseVirtualKeyboard}
+import %{QtQuickVirtualKeyboardImport}
+@endif
+
+import "glcode.js" as GLCode
+
+Window {
+@if %{UseVirtualKeyboard}
+ id: window
+@endif
+ title: qsTr("%{ProjectName}")
+ width: 640
+ height: 360
+ visible: true
+
+ Canvas3D {
+ id: canvas3d
+ anchors.fill: parent
+ focus: true
+
+ onInitializeGL: {
+ GLCode.initializeGL(canvas3d);
+ }
+
+ onPaintGL: {
+ GLCode.paintGL(canvas3d);
+ }
+
+ onResizeGL: {
+ GLCode.resizeGL(canvas3d);
+ }
+ }
+@if %{UseVirtualKeyboard}
+
+ InputPanel {
+ id: inputPanel
+ z: 99
+ x: 0
+ y: window.height
+ width: window.width
+
+ states: State {
+ name: "visible"
+ when: inputPanel.active
+ PropertyChanges {
+ target: inputPanel
+ y: window.height - inputPanel.height
+ }
+ }
+ transitions: Transition {
+ from: ""
+ to: "visible"
+ reversible: true
+ ParallelAnimation {
+ NumberAnimation {
+ properties: "y"
+ duration: 250
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+@endif
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/plaincanvas3d/glcode.js b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/plaincanvas3d/glcode.js
index 154e85b809..154e85b809 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/plaincanvas3d/glcode.js
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/plaincanvas3d/glcode.js
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/qml.qrc b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/qml.qrc
index 22314afd30..22314afd30 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/qml.qrc
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/qml.qrc
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/threejs/3rdparty/three.js b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/threejs/3rdparty/three.js
index fd129e04bb..fd129e04bb 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/threejs/3rdparty/three.js
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/threejs/3rdparty/three.js
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/threejs/glcode.js b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/threejs/glcode.js
index a5f14f4055..a5f14f4055 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/threejs/glcode.js
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/threejs/glcode.js
diff --git a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/wizard.json
index 652842a67e..13a05271cb 100644
--- a/share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/wizard.json
@@ -1,13 +1,13 @@
{
"version": 1,
"supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ],
- "id": "W.QtCanvas3dApplication",
+ "id": "W.QtQuickApplicationCanvas3D",
"category": "F.Application",
- "trDescription": "Creates a Qt Canvas 3D QML project. Optionally including three.js.",
- "trDisplayName": "Qt Canvas 3D Application",
+ "trDescription": "Creates a Qt Canvas 3D QML project, optionally including three.js.",
+ "trDisplayName": "Qt Quick Application - Canvas 3D",
"trDisplayCategory": "Application",
- "icon": "3dapplication.png",
- "featuresRequired": [ "QtSupport.Wizards.FeatureQtCanvas3d1.1" ],
+ "icon": "icon.png",
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.7" ],
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
"options":
@@ -17,8 +17,13 @@
{ "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.qtQuickVersion}" },
- { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.qtQuickWindowVersion}" }
+ { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
+ { "key": "QtQuick3DVersion", "value": "%{JS: %{QtVersion}.QtQuick3DVersion}" },
+ { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.QtQuickWindowVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
],
"pages":
@@ -71,6 +76,48 @@
"data":
[
{
+ "name": "QtVersion",
+ "trDisplayName": "Minimal required Qt version:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Qt 5.9",
+ "value":
+ "{
+ 'QtQuickVersion': '2.9',
+ 'QtQuick3DVersion': '1.1',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ },
+ {
+ "trKey": "Qt 5.8",
+ "value":
+ "{
+ 'QtQuickVersion': '2.8',
+ 'QtQuick3DVersion': '1.1',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ },
+ {
+ "trKey": "Qt 5.7",
+ "value":
+ "{
+ 'QtQuickVersion': '2.7',
+ 'QtQuick3DVersion': '1.1',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ }
+ ]
+ }
+ },
+ {
"name": "ThreeJs",
"trDisplayName": "Create a three.js based application.",
"type": "CheckBox",
@@ -78,6 +125,15 @@
{
"checked": false
}
+ },
+ {
+ "name": "UseVirtualKeyboard",
+ "trDisplayName": "Use Qt Virtual Keyboard.",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ }
}
]
},
@@ -86,7 +142,10 @@
"trShortTitle": "Kits",
"typeId": "Kits",
"enabled": "%{JS: ! %{IsSubproject}}",
- "data": { "projectFilePath": "%{ProjectFile}" }
+ "data": {
+ "projectFilePath": "%{ProjectFile}",
+ "requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
+ }
},
{
"trDisplayName": "Project Management",
@@ -101,24 +160,25 @@
"data":
[
{
- "source": "app.pro",
+ "source": "../app.pro",
"target": "%{ProFile}",
"openAsProject": true,
"condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
},
{
- "source": "CMakeLists.txt",
+ "source": "../CMakeLists.txt",
+ "target": "CMakeLists.txt",
"openAsProject": true,
"condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
},
{
- "source": "file.qbs",
+ "source": "../app.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
"condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
},
{
- "source": "main.cpp",
+ "source": "../main.cpp",
"target": "%{MainCppFileName}"
},
{
@@ -129,18 +189,18 @@
{
"source": "threejs/3rdparty/three.js",
"condition": "%{ThreeJs}",
- "target": "%{ProjectDirectory}/three.js",
+ "target": "three.js",
"isBinary": true
},
{
"source": "%{JS: (%{ThreeJs} ? 'threejs' : 'plaincanvas3d') + '/glcode.js'}",
- "target": "%{ProjectDirectory}/glcode.js"
+ "target": "glcode.js"
},
{
"source": "qml.qrc"
},
{
- "source": "../git.ignore",
+ "source": "../../git.ignore",
"target": ".gitignore",
"condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-empty.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/icon.png
index d9747274a9..d9747274a9 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-empty.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/icon.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-empty@2x.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/icon@2x.png
index 7d79b412e3..7d79b412e3 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-empty@2x.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/icon@2x.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/main.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/main.qml.tpl
new file mode 100644
index 0000000000..6d8fab6a21
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/main.qml.tpl
@@ -0,0 +1,46 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Window %{QtQuickWindowVersion}
+@if %{UseVirtualKeyboard}
+import %{QtQuickVirtualKeyboardImport}
+@endif
+
+Window {
+@if %{UseVirtualKeyboard}
+ id: window
+@endif
+ visible: true
+ width: 640
+ height: 480
+ title: qsTr("Hello World")
+@if %{UseVirtualKeyboard}
+
+ InputPanel {
+ id: inputPanel
+ z: 99
+ x: 0
+ y: window.height
+ width: window.width
+
+ states: State {
+ name: "visible"
+ when: inputPanel.active
+ PropertyChanges {
+ target: inputPanel
+ y: window.height - inputPanel.height
+ }
+ }
+ transitions: Transition {
+ from: ""
+ to: "visible"
+ reversible: true
+ ParallelAnimation {
+ NumberAnimation {
+ properties: "y"
+ duration: 250
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+@endif
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/qml.qrc b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/qml.qrc
new file mode 100644
index 0000000000..5f6483ac33
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
index 5f8be50699..1cd0b7d820 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/empty/wizard.json
@@ -1,13 +1,13 @@
{
"version": 1,
"supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ],
- "id": "U.QtQuickApplication",
+ "id": "U.QtQuickApplicationEmpty",
"category": "F.Application",
- "trDescription": "Creates a deployable Qt Quick 2 application.",
- "trDisplayName": "Qt Quick Application",
+ "trDescription": "Creates a Qt Quick application that contains an empty window.",
+ "trDisplayName": "Qt Quick Application - Empty",
"trDisplayCategory": "Application",
- "icon": "icon-empty.png",
- "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.3" ],
+ "icon": "icon.png",
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.6" ],
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
"options":
@@ -17,14 +17,12 @@
{ "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.qtQuickVersion}" },
- { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.qtQuickWindowVersion}" },
- { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.qtQuickVirtualKeyboardImport}" },
- { "key": "QtQuickVirtualKeyboardWhenVisible", "value": "%{JS: %{QtVersion}.qtQuickVirtualKeyboardWhenVisible}" },
+ { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
+ { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.QtQuickWindowVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
{ "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
- { "key": "UiSupport", "value": "%{JS: '%{QtQuickVersion}' !== '2.3' }" },
- { "key": "IsUiFileInUse", "value": "%{JS: %{UiSupport} && %{QmlUiSplit} }" },
- { "key": "UseVirtualKeyboard", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" }
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
],
"pages":
@@ -82,80 +80,55 @@
"type": "ComboBox",
"data":
{
- "index": 2,
+ "index": 0,
"items":
[
{
- "trKey": "Qt 5.8",
- "value":
- "{
- 'qtQuickVersion': '2.8',
- 'qtQuickWindowVersion': '2.2',
- 'qtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1',
- 'qtQuickVirtualKeyboardWhenVisible': 'inputPanel.active'
- }"
- },
- {
- "trKey": "Qt 5.7",
+ "trKey": "Qt 5.9",
"value":
"{
- 'qtQuickVersion': '2.7',
- 'qtQuickWindowVersion': '2.2',
- 'qtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1',
- 'qtQuickVirtualKeyboardWhenVisible': 'inputPanel.active'
+ 'QtQuickVersion': '2.9',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
}"
},
{
- "trKey": "Qt 5.6",
- "value":
- "{
- 'qtQuickVersion': '2.6',
- 'qtQuickWindowVersion': '2.2',
- 'qtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 2.0',
- 'qtQuickVirtualKeyboardWhenVisible': 'inputPanel.active'
- }"
- },
- {
- "trKey": "Qt 5.5",
+ "trKey": "Qt 5.8",
"value":
"{
- 'qtQuickVersion': '2.5',
- 'qtQuickWindowVersion': '2.2',
- 'qtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 1.3',
- 'qtQuickVirtualKeyboardWhenVisible': 'Qt.inputMethod.visible'
+ 'QtQuickVersion': '2.8',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
}"
},
{
- "trKey": "Qt 5.4",
+ "trKey": "Qt 5.7",
"value":
"{
- 'qtQuickVersion': '2.4',
- 'qtQuickWindowVersion': '2.2',
- 'qtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 1.0',
- 'qtQuickVirtualKeyboardWhenVisible': 'Qt.inputMethod.visible'
+ 'QtQuickVersion': '2.7',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
}"
},
{
- "trKey": "Qt 5.3",
+ "trKey": "Qt 5.6",
"value":
"{
- 'qtQuickVersion': '2.3',
- 'qtQuickWindowVersion': '2.2',
- 'qtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 1.0',
- 'qtQuickVirtualKeyboardWhenVisible': 'Qt.inputMethod.visible'
+ 'QtQuickVersion': '2.6',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 2.0'
}"
}
]
}
},
{
- "name": "QmlUiSplit",
- "trDisplayName": "With ui.qml file",
+ "name": "UseVirtualKeyboard",
+ "trDisplayName": "Use Qt Virtual Keyboard.",
"type": "CheckBox",
- "visible": "%{UiSupport}",
"data":
{
- "checked": true
+ "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
}
}
]
@@ -183,24 +156,25 @@
"data":
[
{
- "source": "app.pro",
+ "source": "../app.pro",
"target": "%{ProFile}",
"openAsProject": true,
"condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
},
{
- "source": "CMakeLists.txt",
+ "source": "../CMakeLists.txt",
+ "target": "CMakeLists.txt",
"openAsProject": true,
"condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
},
{
- "source": "file.qbs",
+ "source": "../app.qbs",
"target": "%{QbsFile}",
"openAsProject": true,
"condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
},
{
- "source": "main.cpp",
+ "source": "../main.cpp",
"target": "%{MainCppFileName}"
},
{
@@ -209,15 +183,10 @@
"openInEditor": true
},
{
- "source": "MainForm.ui.qml.tpl",
- "target": "MainForm.ui.qml",
- "condition": "%{IsUiFileInUse}"
- },
- {
"source": "qml.qrc"
},
{
- "source": "../git.ignore",
+ "source": "../../git.ignore",
"target": ".gitignore",
"condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp
index 31af279601..3b6ab97c69 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp
@@ -2,10 +2,17 @@
%{JS: QtSupport.qtIncludes([], ["QtGui/QGuiApplication", "QtQml/QQmlApplicationEngine"])}
int main(int argc, char *argv[])
{
+@if %{SetQPAPhysicalSize}
+ qputenv("QT_QPA_EGLFS_PHYSICAL_WIDTH", QByteArray("213"));
+ qputenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT", QByteArray("120"));
+
+@endif
@if %{UseVirtualKeyboard}
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
@endif
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.qml.tpl
deleted file mode 100644
index bf7b08db71..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.qml.tpl
+++ /dev/null
@@ -1,77 +0,0 @@
-import QtQuick %{QtQuickVersion}
-import QtQuick.Window %{QtQuickWindowVersion}
-@if %{UseVirtualKeyboard}
-import %{QtQuickVirtualKeyboardImport}
-@endif
-
-Window {
- visible: true
- width: 640
- height: 480
- title: qsTr("Hello World")
-@if %{UseVirtualKeyboard}
- id: root
-@endif
-
-@if %{IsUiFileInUse}
- MainForm {
- anchors.fill: parent
- mouseArea.onClicked: {
- console.log(qsTr('Clicked on background. Text: "' + textEdit.text + '"'))
- }
- }
-@else
- MouseArea {
- anchors.fill: parent
- onClicked: {
- console.log(qsTr('Clicked on background. Text: "' + textEdit.text + '"'))
- }
- }
-
- TextEdit {
- id: textEdit
- text: qsTr("Enter some text...")
- verticalAlignment: Text.AlignVCenter
- anchors.top: parent.top
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: 20
- Rectangle {
- anchors.fill: parent
- anchors.margins: -10
- color: "transparent"
- border.width: 1
- }
- }
-@endif
-@if %{UseVirtualKeyboard}
-
- InputPanel {
- id: inputPanel
- z: 99
- x: 0
- y: root.height
- width: root.width
-
- states: State {
- name: "visible"
- when: %{QtQuickVirtualKeyboardWhenVisible}
- PropertyChanges {
- target: inputPanel
- y: root.height - inputPanel.height
- }
- }
- transitions: Transition {
- from: ""
- to: "visible"
- reversible: true
- ParallelAnimation {
- NumberAnimation {
- properties: "y"
- duration: 250
- easing.type: Easing.InOutQuad
- }
- }
- }
- }
-@endif
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/qml.qrc b/share/qtcreator/templates/wizards/projects/qtquickapplication/qml.qrc
deleted file mode 100644
index 7f48101612..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/qml.qrc
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE RCC>
-<RCC version="1.0">
- <qresource prefix="/">
- <file>main.qml</file>
-@if %{IsUiFileInUse}
- <file>MainForm.ui.qml</file>
-@endif
- </qresource>
-</RCC>
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/qtquickcontrols2.conf b/share/qtcreator/templates/wizards/projects/qtquickapplication/qtquickcontrols2.conf
new file mode 100644
index 0000000000..9c7633fb0a
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/qtquickcontrols2.conf
@@ -0,0 +1,23 @@
+; This file can be edited to change the style of the application
+; Read "Qt Quick Controls 2 Configuration File" for details:
+; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
+
+[Controls]
+Style=%{QtQuickControlsStyle}
+@if '%{QtQuickControlsStyle}' == 'Universal'
+
+[Universal]
+Theme=%{QtQuickControlsStyleTheme}
+;Accent=Steel
+;Foreground=Brown
+;Background=Steel
+@endif
+@if '%{QtQuickControlsStyle}' == 'Material'
+
+[Material]
+Theme=%{QtQuickControlsStyleTheme}
+;Accent=BlueGrey
+;Primary=BlueGray
+;Foreground=Brown
+;Background=Grey
+@endif
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-scroll.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/icon.png
index 7d0267a603..7d0267a603 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-scroll.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/icon.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-scroll@2x.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/icon@2x.png
index 27004e6468..27004e6468 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-scroll@2x.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/icon@2x.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/main.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/main.qml.tpl
new file mode 100644
index 0000000000..da4fdc8c2c
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/main.qml.tpl
@@ -0,0 +1,59 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
+@if %{UseVirtualKeyboard}
+import %{QtQuickVirtualKeyboardImport}
+@endif
+
+ApplicationWindow {
+@if %{UseVirtualKeyboard}
+ id: window
+@endif
+ visible: true
+ width: 640
+ height: 480
+ title: qsTr("Scroll")
+
+ ScrollView {
+ anchors.fill: parent
+
+ ListView {
+ width: parent.width
+ model: 20
+ delegate: ItemDelegate {
+ text: "Item " + (index + 1)
+ width: parent.width
+ }
+ }
+ }
+@if %{UseVirtualKeyboard}
+
+ InputPanel {
+ id: inputPanel
+ z: 99
+ x: 0
+ y: window.height
+ width: window.width
+
+ states: State {
+ name: "visible"
+ when: inputPanel.active
+ PropertyChanges {
+ target: inputPanel
+ y: window.height - inputPanel.height
+ }
+ }
+ transitions: Transition {
+ from: ""
+ to: "visible"
+ reversible: true
+ ParallelAnimation {
+ NumberAnimation {
+ properties: "y"
+ duration: 250
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+@endif
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/qml.qrc b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/qml.qrc
new file mode 100644
index 0000000000..af1cc9bc02
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/qml.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>qtquickcontrols2.conf</file>
+ </qresource>
+</RCC>
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json
new file mode 100644
index 0000000000..b915b2ff04
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/wizard.json
@@ -0,0 +1,252 @@
+{
+ "version": 1,
+ "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ],
+ "id": "V.QtQuickApplicationScroll",
+ "category": "F.Application",
+ "trDescription": "Creates a Qt Quick Controls application with a ScrollView.",
+ "trDisplayName": "Qt Quick Application - Scroll",
+ "trDisplayCategory": "Application",
+ "icon": "icon.png",
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.9" ],
+ "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+
+ "options":
+ [
+ { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
+ { "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
+ { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
+ { "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.QtQuickControlsVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickControlsStyle", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyle}" },
+ { "key": "QtQuickControlsStyleTheme", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyleTheme}" },
+ { "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
+ ],
+
+ "pages":
+ [
+ {
+ "trDisplayName": "Project Location",
+ "trShortTitle": "Location",
+ "typeId": "Project"
+ },
+ {
+ "trDisplayName": "Define Build System",
+ "trShortTitle": "Build System",
+ "typeId": "Fields",
+ "enabled": "%{JS: ! %{IsSubproject}}",
+ "data":
+ [
+ {
+ "name": "BuildSystem",
+ "trDisplayName": "Build system:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "qmake",
+ "value": "qmake",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "CMake",
+ "value": "cmake",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "Qbs",
+ "value": "qbs",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Define Project Details",
+ "trShortTitle": "Details",
+ "typeId": "Fields",
+ "data":
+ [
+ {
+ "name": "QtVersion",
+ "trDisplayName": "Minimal required Qt version:",
+ "type": "ComboBox",
+ "visible": false,
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Qt 5.9",
+ "value":
+ "{
+ 'QtQuickVersion': '2.9',
+ 'QtQuickControlsVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ControlsStyle",
+ "trDisplayName": "Qt Quick Controls Style:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Default",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Default',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ },
+ {
+ "trKey": "Material Light",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Material',
+ 'QtQuickControlsStyleTheme': 'Light'
+ }"
+ },
+ {
+ "trKey": "Material Dark",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Material',
+ 'QtQuickControlsStyleTheme': 'Dark'
+ }"
+ },
+ {
+ "trKey": "Universal Light",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'Light'
+ }"
+ },
+ {
+ "trKey": "Universal Dark",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'Dark'
+ }"
+ },
+ {
+ "trKey": "Universal System",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'System'
+ }"
+ },
+ {
+ "trKey": "Fusion (Qt 5.10+)",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Fusion',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ },
+ {
+ "trKey": "Imagine (Qt 5.10+)",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Imagine',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ }
+ ]
+ }
+ },
+ {
+ "name": "UseVirtualKeyboard",
+ "trDisplayName": "Use Qt Virtual Keyboard.",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Kit Selection",
+ "trShortTitle": "Kits",
+ "typeId": "Kits",
+ "enabled": "%{JS: ! %{IsSubproject}}",
+ "data": {
+ "projectFilePath": "%{ProjectFile}",
+ "requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
+ }
+ },
+ {
+ "trDisplayName": "Project Management",
+ "trShortTitle": "Summary",
+ "typeId": "Summary"
+ }
+ ],
+ "generators":
+ [
+ {
+ "typeId": "File",
+ "data":
+ [
+ {
+ "source": "../app.pro",
+ "target": "%{ProFile}",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ },
+ {
+ "source": "../CMakeLists.txt",
+ "target": "CMakeLists.txt",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ },
+ {
+ "source": "../app.qbs",
+ "target": "%{QbsFile}",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ },
+ {
+ "source": "../main.cpp",
+ "target": "%{MainCppFileName}"
+ },
+ {
+ "source": "main.qml.tpl",
+ "target": "main.qml",
+ "openInEditor": true
+ },
+ {
+ "source": "../qtquickcontrols2.conf",
+ "target": "qtquickcontrols2.conf"
+ },
+ {
+ "source": "qml.qrc"
+ },
+ {
+ "source": "../../git.ignore",
+ "target": ".gitignore",
+ "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ }
+ ]
+ }
+ ]
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/HomeForm.ui.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/HomeForm.ui.qml.tpl
new file mode 100644
index 0000000000..dc133ab09e
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/HomeForm.ui.qml.tpl
@@ -0,0 +1,14 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
+
+Page {
+ width: 600
+ height: 400
+
+ title: qsTr("Home")
+
+ Label {
+ text: qsTr("You are on the home page.")
+ anchors.centerIn: parent
+ }
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page1Form.ui.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page1Form.ui.qml.tpl
new file mode 100644
index 0000000000..562060a16d
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page1Form.ui.qml.tpl
@@ -0,0 +1,14 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
+
+Page {
+ width: 600
+ height: 400
+
+ title: qsTr("Page 1")
+
+ Label {
+ text: qsTr("You are on Page 1.")
+ anchors.centerIn: parent
+ }
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page2Form.ui.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page2Form.ui.qml.tpl
new file mode 100644
index 0000000000..3a22d7ff04
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/Page2Form.ui.qml.tpl
@@ -0,0 +1,14 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
+
+Page {
+ width: 600
+ height: 400
+
+ title: qsTr("Page 2")
+
+ Label {
+ text: qsTr("You are on Page 2.")
+ anchors.centerIn: parent
+ }
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-stack.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/icon.png
index d7ab9f9e81..d7ab9f9e81 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-stack.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/icon.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-stack@2x.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/icon@2x.png
index 87adc78f55..87adc78f55 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-stack@2x.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/icon@2x.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/main.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/main.qml.tpl
new file mode 100644
index 0000000000..b6505572c3
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/main.qml.tpl
@@ -0,0 +1,99 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
+@if %{UseVirtualKeyboard}
+import %{QtQuickVirtualKeyboardImport}
+@endif
+
+ApplicationWindow {
+ id: window
+ visible: true
+ width: 640
+ height: 480
+ title: qsTr("Stack")
+
+ header: ToolBar {
+ contentHeight: toolButton.implicitHeight
+
+ ToolButton {
+ id: toolButton
+ text: stackView.depth > 1 ? "\\u25C0" : "\\u2630"
+ font.pixelSize: Qt.application.font.pixelSize * 1.6
+ onClicked: {
+ if (stackView.depth > 1) {
+ stackView.pop()
+ } else {
+ drawer.open()
+ }
+ }
+ }
+
+ Label {
+ text: stackView.currentItem.title
+ anchors.centerIn: parent
+ }
+ }
+
+ Drawer {
+ id: drawer
+ width: window.width * 0.66
+ height: window.height
+
+ Column {
+ anchors.fill: parent
+
+ ItemDelegate {
+ text: qsTr("Page 1")
+ width: parent.width
+ onClicked: {
+ stackView.push("Page1Form.ui.qml")
+ drawer.close()
+ }
+ }
+ ItemDelegate {
+ text: qsTr("Page 2")
+ width: parent.width
+ onClicked: {
+ stackView.push("Page2Form.ui.qml")
+ drawer.close()
+ }
+ }
+ }
+ }
+
+ StackView {
+ id: stackView
+ initialItem: "HomeForm.ui.qml"
+ anchors.fill: parent
+ }
+@if %{UseVirtualKeyboard}
+
+ InputPanel {
+ id: inputPanel
+ z: 99
+ x: 0
+ y: window.height
+ width: window.width
+
+ states: State {
+ name: "visible"
+ when: inputPanel.active
+ PropertyChanges {
+ target: inputPanel
+ y: window.height - inputPanel.height
+ }
+ }
+ transitions: Transition {
+ from: ""
+ to: "visible"
+ reversible: true
+ ParallelAnimation {
+ NumberAnimation {
+ properties: "y"
+ duration: 250
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+@endif
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/qml.qrc b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/qml.qrc
new file mode 100644
index 0000000000..7725989667
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/qml.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>HomeForm.ui.qml</file>
+ <file>Page1Form.ui.qml</file>
+ <file>Page2Form.ui.qml</file>
+ <file>qtquickcontrols2.conf</file>
+ </qresource>
+</RCC>
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
new file mode 100644
index 0000000000..1430fce281
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
@@ -0,0 +1,281 @@
+{
+ "version": 1,
+ "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ],
+ "id": "V.QtQuickApplicationStack",
+ "category": "F.Application",
+ "trDescription": "Creates a Qt Quick Controls application with a StackView to display content, and a Drawer and ToolBar for navigation.",
+ "trDisplayName": "Qt Quick Application - Stack",
+ "trDisplayCategory": "Application",
+ "icon": "icon.png",
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.7" ],
+ "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+
+ "options":
+ [
+ { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
+ { "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
+ { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
+ { "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.QtQuickControlsVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickControlsStyle", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyle}" },
+ { "key": "QtQuickControlsStyleTheme", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyleTheme}" },
+ { "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
+ ],
+
+ "pages":
+ [
+ {
+ "trDisplayName": "Project Location",
+ "trShortTitle": "Location",
+ "typeId": "Project"
+ },
+ {
+ "trDisplayName": "Define Build System",
+ "trShortTitle": "Build System",
+ "typeId": "Fields",
+ "enabled": "%{JS: ! %{IsSubproject}}",
+ "data":
+ [
+ {
+ "name": "BuildSystem",
+ "trDisplayName": "Build system:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "qmake",
+ "value": "qmake",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "CMake",
+ "value": "cmake",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "Qbs",
+ "value": "qbs",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Define Project Details",
+ "trShortTitle": "Details",
+ "typeId": "Fields",
+ "data":
+ [
+ {
+ "name": "QtVersion",
+ "trDisplayName": "Minimal required Qt version:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Qt 5.9",
+ "value":
+ "{
+ 'QtQuickVersion': '2.9',
+ 'QtQuickControlsVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ },
+ {
+ "trKey": "Qt 5.8",
+ "value":
+ "{
+ 'QtQuickVersion': '2.8',
+ 'QtQuickControlsVersion': '2.1',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ },
+ {
+ "trKey": "Qt 5.7",
+ "value":
+ "{
+ 'QtQuickVersion': '2.7',
+ 'QtQuickControlsVersion': '2.0',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ControlsStyle",
+ "trDisplayName": "Qt Quick Controls Style:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Default",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Default',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ },
+ {
+ "trKey": "Material Light",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Material',
+ 'QtQuickControlsStyleTheme': 'Light'
+ }"
+ },
+ {
+ "trKey": "Material Dark",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Material',
+ 'QtQuickControlsStyleTheme': 'Dark'
+ }"
+ },
+ {
+ "trKey": "Universal Light",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'Light'
+ }"
+ },
+ {
+ "trKey": "Universal Dark",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'Dark'
+ }"
+ },
+ {
+ "trKey": "Universal System",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'System'
+ }"
+ },
+ {
+ "trKey": "Fusion (Qt 5.10+)",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Fusion',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ },
+ {
+ "trKey": "Imagine (Qt 5.10+)",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Imagine',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ }
+ ]
+ }
+ },
+ {
+ "name": "UseVirtualKeyboard",
+ "trDisplayName": "Use Qt Virtual Keyboard.",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Kit Selection",
+ "trShortTitle": "Kits",
+ "typeId": "Kits",
+ "enabled": "%{JS: ! %{IsSubproject}}",
+ "data": {
+ "projectFilePath": "%{ProjectFile}",
+ "requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
+ }
+ },
+ {
+ "trDisplayName": "Project Management",
+ "trShortTitle": "Summary",
+ "typeId": "Summary"
+ }
+ ],
+ "generators":
+ [
+ {
+ "typeId": "File",
+ "data":
+ [
+ {
+ "source": "../app.pro",
+ "target": "%{ProFile}",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ },
+ {
+ "source": "../CMakeLists.txt",
+ "target": "CMakeLists.txt",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ },
+ {
+ "source": "../app.qbs",
+ "target": "%{QbsFile}",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ },
+ {
+ "source": "../main.cpp",
+ "target": "%{MainCppFileName}"
+ },
+ {
+ "source": "main.qml.tpl",
+ "target": "main.qml",
+ "openInEditor": true
+ },
+ {
+ "source": "HomeForm.ui.qml.tpl",
+ "target": "HomeForm.ui.qml"
+ },
+ {
+ "source": "Page1Form.ui.qml.tpl",
+ "target": "Page1Form.ui.qml"
+ },
+ {
+ "source": "Page2Form.ui.qml.tpl",
+ "target": "Page2Form.ui.qml"
+ },
+ {
+ "source": "../qtquickcontrols2.conf",
+ "target": "qtquickcontrols2.conf"
+ },
+ {
+ "source": "qml.qrc"
+ },
+ {
+ "source": "../../git.ignore",
+ "target": ".gitignore",
+ "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ }
+ ]
+ }
+ ]
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page1Form.ui.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page1Form.ui.qml.tpl
new file mode 100644
index 0000000000..bc932b93ef
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page1Form.ui.qml.tpl
@@ -0,0 +1,18 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
+
+Page {
+ width: 600
+ height: 400
+
+ header: Label {
+ text: qsTr("Page 1")
+ font.pixelSize: Qt.application.font.pixelSize * 2
+ padding: 10
+ }
+
+ Label {
+ text: qsTr("You are on Page 1.")
+ anchors.centerIn: parent
+ }
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page2Form.ui.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page2Form.ui.qml.tpl
new file mode 100644
index 0000000000..b4a68b3054
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/Page2Form.ui.qml.tpl
@@ -0,0 +1,18 @@
+import QtQuick %{QtQuickVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
+
+Page {
+ width: 600
+ height: 400
+
+ header: Label {
+ text: qsTr("Page 2")
+ font.pixelSize: Qt.application.font.pixelSize * 2
+ padding: 10
+ }
+
+ Label {
+ text: qsTr("You are on Page 2.")
+ anchors.centerIn: parent
+ }
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-swipe.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/icon.png
index 17d2daae1d..17d2daae1d 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-swipe.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/icon.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-swipe@2x.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/icon@2x.png
index dd2adfbd95..dd2adfbd95 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/icon-swipe@2x.png
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/icon@2x.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/main.qml.tpl
index 8c55ad596a..bf0da44833 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.qml.tpl
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/main.qml.tpl
@@ -1,43 +1,39 @@
import QtQuick %{QtQuickVersion}
-import QtQuick.Controls %{QtQuickControls2Version}
-import QtQuick.Layouts %{QtQuickLayoutsVersion}
+import QtQuick.Controls %{QtQuickControlsVersion}
@if %{UseVirtualKeyboard}
-import QtQuick.VirtualKeyboard %{QtQuickVirtualKeyboardVersion}
+import %{QtQuickVirtualKeyboardImport}
@endif
ApplicationWindow {
+@if %{UseVirtualKeyboard}
+ id: window
+@endif
visible: true
width: 640
height: 480
- title: qsTr("Hello World")
-@if %{UseVirtualKeyboard}
- id: root
-@endif
+ title: qsTr("Tabs")
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
- Page1 {
+ Page1Form {
}
- Page {
- Label {
- text: qsTr("Second page")
- anchors.centerIn: parent
- }
+ Page2Form {
}
}
footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
+
TabButton {
- text: qsTr("First")
+ text: qsTr("Page 1")
}
TabButton {
- text: qsTr("Second")
+ text: qsTr("Page 2")
}
}
@if %{UseVirtualKeyboard}
@@ -46,15 +42,15 @@ ApplicationWindow {
id: inputPanel
z: 99
x: 0
- y: root.height
- width: root.width
+ y: window.height
+ width: window.width
states: State {
name: "visible"
when: inputPanel.active
PropertyChanges {
target: inputPanel
- y: root.height - inputPanel.height
+ y: window.height - inputPanel.height
}
}
transitions: Transition {
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/qml.qrc b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/qml.qrc
index 419888c66b..61176f1348 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/qml.qrc
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/qml.qrc
@@ -1,9 +1,9 @@
-<!DOCTYPE RCC>
-<RCC version="1.0">
+<RCC>
<qresource prefix="/">
<file>main.qml</file>
- <file>Page1.qml</file>
<file>Page1Form.ui.qml</file>
+ <file>Page2Form.ui.qml</file>
+ <file>main.qml</file>
<file>qtquickcontrols2.conf</file>
</qresource>
</RCC>
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json
new file mode 100644
index 0000000000..9d4287314c
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/wizard.json
@@ -0,0 +1,277 @@
+{
+ "version": 1,
+ "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ],
+ "id": "V.QtQuickApplicationSwipe",
+ "category": "F.Application",
+ "trDescription": "Creates a Qt Quick Controls application with a with a StackView to display content, and a Drawer and ToolBar for navigation.",
+ "trDisplayName": "Qt Quick Application - Swipe",
+ "trDisplayCategory": "Application",
+ "icon": "icon.png",
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.7" ],
+ "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
+
+ "options":
+ [
+ { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
+ { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
+ { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
+ { "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
+ { "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
+ { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
+ { "key": "QtQuickControlsVersion", "value": "%{JS: %{QtVersion}.QtQuickControlsVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickControlsStyle", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyle}" },
+ { "key": "QtQuickControlsStyleTheme", "value": "%{JS: %{ControlsStyle}.QtQuickControlsStyleTheme}" },
+ { "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" },
+ { "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }
+ ],
+
+ "pages":
+ [
+ {
+ "trDisplayName": "Project Location",
+ "trShortTitle": "Location",
+ "typeId": "Project"
+ },
+ {
+ "trDisplayName": "Define Build System",
+ "trShortTitle": "Build System",
+ "typeId": "Fields",
+ "enabled": "%{JS: ! %{IsSubproject}}",
+ "data":
+ [
+ {
+ "name": "BuildSystem",
+ "trDisplayName": "Build system:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "qmake",
+ "value": "qmake",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "CMake",
+ "value": "cmake",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
+ },
+ {
+ "trKey": "Qbs",
+ "value": "qbs",
+ "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Define Project Details",
+ "trShortTitle": "Details",
+ "typeId": "Fields",
+ "data":
+ [
+ {
+ "name": "QtVersion",
+ "trDisplayName": "Minimal required Qt version:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Qt 5.9",
+ "value":
+ "{
+ 'QtQuickVersion': '2.9',
+ 'QtQuickControlsVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ },
+ {
+ "trKey": "Qt 5.8",
+ "value":
+ "{
+ 'QtQuickVersion': '2.8',
+ 'QtQuickControlsVersion': '2.1',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ },
+ {
+ "trKey": "Qt 5.7",
+ "value":
+ "{
+ 'QtQuickVersion': '2.7',
+ 'QtQuickControlsVersion': '2.0',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
+ }"
+ }
+ ]
+ }
+ },
+ {
+ "name": "ControlsStyle",
+ "trDisplayName": "Qt Quick Controls Style:",
+ "type": "ComboBox",
+ "data":
+ {
+ "index": 0,
+ "items":
+ [
+ {
+ "trKey": "Default",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Default',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ },
+ {
+ "trKey": "Material Light",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Material',
+ 'QtQuickControlsStyleTheme': 'Light'
+ }"
+ },
+ {
+ "trKey": "Material Dark",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Material',
+ 'QtQuickControlsStyleTheme': 'Dark'
+ }"
+ },
+ {
+ "trKey": "Universal Light",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'Light'
+ }"
+ },
+ {
+ "trKey": "Universal Dark",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'Dark'
+ }"
+ },
+ {
+ "trKey": "Universal System",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Universal',
+ 'QtQuickControlsStyleTheme': 'System'
+ }"
+ },
+ {
+ "trKey": "Fusion (Qt 5.10+)",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Fusion',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ },
+ {
+ "trKey": "Imagine (Qt 5.10+)",
+ "value":
+ "{
+ 'QtQuickControlsStyle': 'Imagine',
+ 'QtQuickControlsStyleTheme': ''
+ }"
+ }
+ ]
+ }
+ },
+ {
+ "name": "UseVirtualKeyboard",
+ "trDisplayName": "Use Qt Virtual Keyboard.",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
+ }
+ }
+ ]
+ },
+ {
+ "trDisplayName": "Kit Selection",
+ "trShortTitle": "Kits",
+ "typeId": "Kits",
+ "enabled": "%{JS: ! %{IsSubproject}}",
+ "data": {
+ "projectFilePath": "%{ProjectFile}",
+ "requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ]
+ }
+ },
+ {
+ "trDisplayName": "Project Management",
+ "trShortTitle": "Summary",
+ "typeId": "Summary"
+ }
+ ],
+ "generators":
+ [
+ {
+ "typeId": "File",
+ "data":
+ [
+ {
+ "source": "../app.pro",
+ "target": "%{ProFile}",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
+ },
+ {
+ "source": "../CMakeLists.txt",
+ "target": "CMakeLists.txt",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
+ },
+ {
+ "source": "../app.qbs",
+ "target": "%{QbsFile}",
+ "openAsProject": true,
+ "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
+ },
+ {
+ "source": "../main.cpp",
+ "target": "%{MainCppFileName}"
+ },
+ {
+ "source": "main.qml.tpl",
+ "target": "main.qml",
+ "openInEditor": true
+ },
+ {
+ "source": "Page1Form.ui.qml.tpl",
+ "target": "Page1Form.ui.qml"
+ },
+ {
+ "source": "Page2Form.ui.qml.tpl",
+ "target": "Page2Form.ui.qml"
+ },
+ {
+ "source": "../qtquickcontrols2.conf",
+ "target": "qtquickcontrols2.conf"
+ },
+ {
+ "source": "qml.qrc"
+ },
+ {
+ "source": "../../git.ignore",
+ "target": ".gitignore",
+ "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
+ }
+ ]
+ }
+ ]
+}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/CMakeLists.txt b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/CMakeLists.txt
deleted file mode 100644
index 1e36df0c28..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-
-project(%{ProjectName} LANGUAGES CXX)
-
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-
-find_package(Qt5 COMPONENTS Core Quick REQUIRED)
-
-add_executable(${PROJECT_NAME} "%{MainCppFileName}" "qml.qrc")
-
-target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick)
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1.qml.tpl
deleted file mode 100644
index 71c6c62362..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1.qml.tpl
+++ /dev/null
@@ -1,7 +0,0 @@
-import QtQuick %{QtQuickVersion}
-
-Page1Form {
- button1.onClicked: {
- console.log("Button Pressed. Entered text: " + textField1.text);
- }
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1Form.ui.qml.tpl b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1Form.ui.qml.tpl
deleted file mode 100644
index f2fcc8cff3..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/Page1Form.ui.qml.tpl
+++ /dev/null
@@ -1,24 +0,0 @@
-import QtQuick %{QtQuickVersion}
-import QtQuick.Controls %{QtQuickControls2Version}
-import QtQuick.Layouts %{QtQuickLayoutsVersion}
-
-Item {
- property alias textField1: textField1
- property alias button1: button1
-
- RowLayout {
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.topMargin: 20
- anchors.top: parent.top
-
- TextField {
- id: textField1
- placeholderText: qsTr("Text Field")
- }
-
- Button {
- id: button1
- text: qsTr("Press Me")
- }
- }
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/app.pro b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/app.pro
deleted file mode 100644
index 6ee001160a..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/app.pro
+++ /dev/null
@@ -1,28 +0,0 @@
-QT += quick
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any feature of Qt which as been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if you use deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += %{MainCppFileName}
-
-RESOURCES += qml.qrc
-
-# Additional import path used to resolve QML modules in Qt Creator's code model
-QML_IMPORT_PATH =
-
-# Additional import path used to resolve QML modules just for Qt Quick Designer
-QML_DESIGNER_IMPORT_PATH =
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/file.qbs b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/file.qbs
deleted file mode 100644
index 679e14eaa7..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/file.qbs
+++ /dev/null
@@ -1,38 +0,0 @@
-import qbs
-
-Project {
- minimumQbsVersion: "1.7.1"
-
- CppApplication {
- Depends { name: "Qt.core" }
- Depends { name: "Qt.quick" }
-
- // Additional import path used to resolve QML modules in Qt Creator's code model
- property pathList qmlImportPaths: []
-
- cpp.cxxLanguageVersion: "c++11"
-
- cpp.defines: [
- // The following define makes your compiler emit warnings if you use
- // any feature of Qt which as been marked deprecated (the exact warnings
- // depend on your compiler). Please consult the documentation of the
- // deprecated API in order to know how to port your code away from it.
- "QT_DEPRECATED_WARNINGS",
-
- // You can also make your code fail to compile if you use deprecated APIs.
- // In order to do so, uncomment the following line.
- // You can also select to disable deprecated APIs only up to a certain version of Qt.
- //"QT_DISABLE_DEPRECATED_BEFORE=0x060000" // disables all the APIs deprecated before Qt 6.0.0
- ]
-
- files: [
- "%{MainCppFileName}",
- "qml.qrc",
- ]
-
- Group { // Properties for the produced executable
- fileTagsFilter: product.type
- qbs.install: true
- }
- }
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp
deleted file mode 100644
index cabbb206e3..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/main.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-%{Cpp:LicenseTemplate}\
-%{JS: QtSupport.qtIncludes([], ["QtGui/QGuiApplication", "QtQml/QQmlApplicationEngine"])}
-int main(int argc, char *argv[])
-{
-@if %{UseVirtualKeyboard}
- qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
-
-@endif
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- QGuiApplication app(argc, argv);
-
- QQmlApplicationEngine engine;
- engine.load(QUrl(QLatin1String("qrc:/main.qml")));
- if (engine.rootObjects().isEmpty())
- return -1;
-
- return app.exec();
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/qtquickcontrols2.conf b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/qtquickcontrols2.conf
deleted file mode 100644
index 0b853e0ea9..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/qtquickcontrols2.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-; This file can be edited to change the style of the application
-; See Styling Qt Quick Controls 2 in the documentation for details:
-; http://doc.qt.io/qt-5/qtquickcontrols2-styles.html
-
-[Controls]
-Style=%{ControlsStyle}
-
-[Universal]
-Theme=Light
-;Accent=Steel
-
-[Material]
-Theme=Light
-;Accent=BlueGrey
-;Primary=BlueGray
diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json
deleted file mode 100644
index 6b694b4a49..0000000000
--- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json
+++ /dev/null
@@ -1,170 +0,0 @@
-{
- "version": 1,
- "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ],
- "id": "V.QtQuickControls2Application",
- "category": "F.Application",
- "trDescription": "Creates a deployable Qt Quick 2 application using Qt Quick Controls 2.<br/><br/><b>Note:</b> Qt Quick Controls 2 are available with Qt 5.7 and later.",
- "trDisplayName": "Qt Quick Controls 2 Application",
- "trDisplayCategory": "Application",
- "icon": "../qtquickapplication/icon-swipe.png",
- "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.2" ],
- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",
-
- "options":
- [
- { "key": "ProjectFile", "value": "%{JS: '%{BuildSystem}' === 'qmake' ? '%{ProFile}' : ('%{BuildSystem}' === 'cmake' ? '%{CMakeFile}' : '%{QbsFile}')}" },
- { "key": "ProFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
- { "key": "QbsFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" },
- { "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
- { "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
- { "key": "QtQuickVersion", "value": "2.7" },
- { "key": "QtQuickControls2Version", "value": "2.0" },
- { "key": "QtQuickDialogsVersion", "value": "1.0" },
- { "key": "QtQuickLayoutsVersion", "value": "1.3" },
- { "key": "QtQuickVirtualKeyboardVersion", "value": "2.1" },
- { "key": "UseVirtualKeyboard", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" }
- ],
-
- "pages":
- [
- {
- "trDisplayName": "Project Location",
- "trShortTitle": "Location",
- "typeId": "Project"
- },
- {
- "trDisplayName": "Define Build System",
- "trShortTitle": "Build System",
- "typeId": "Fields",
- "enabled": "%{JS: ! %{IsSubproject}}",
- "data":
- [
- {
- "name": "BuildSystem",
- "trDisplayName": "Build system:",
- "type": "ComboBox",
- "data":
- {
- "index": 0,
- "items":
- [
- {
- "trKey": "qmake",
- "value": "qmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}"
- },
- {
- "trKey": "CMake",
- "value": "cmake",
- "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
- },
- {
- "trKey": "Qbs",
- "value": "qbs",
- "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
- }
- ]
- }
- }
- ]
- },
- {
- "trDisplayName": "Define Project Details",
- "trShortTitle": "Details",
- "typeId": "Fields",
- "data":
- [
- {
- "name": "ControlsStyle",
- "trDisplayName": "Qt Quick Controls 2 Style:",
- "type": "ComboBox",
- "data":
- {
- "index": 0,
- "items":
- [
- {
- "trKey": "Default",
- "value": "Default"
- },
- {
- "trKey": "Material",
- "value": "Material"
- },
- {
- "trKey": "Universal",
- "value": "Universal"
- }
- ]
- }
- }
- ]
- },
- {
- "trDisplayName": "Kit Selection",
- "trShortTitle": "Kits",
- "typeId": "Kits",
- "enabled": "%{JS: ! %{IsSubproject}}",
- "data": { "projectFilePath": "%{ProjectFile}" }
- },
- {
- "trDisplayName": "Project Management",
- "trShortTitle": "Summary",
- "typeId": "Summary"
- }
- ],
- "generators":
- [
- {
- "typeId": "File",
- "data":
- [
- {
- "source": "app.pro",
- "target": "%{ProFile}",
- "openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qmake'}"
- },
- {
- "source": "CMakeLists.txt",
- "openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'cmake'}"
- },
- {
- "source": "file.qbs",
- "target": "%{QbsFile}",
- "openAsProject": true,
- "condition": "%{JS: '%{BuildSystem}' === 'qbs'}"
- },
- {
- "source": "main.cpp",
- "target": "%{MainCppFileName}"
- },
- {
- "source": "main.qml.tpl",
- "target": "main.qml",
- "openInEditor": true
- },
- {
- "source": "Page1.qml.tpl",
- "target": "Page1.qml"
- },
- {
- "source": "Page1Form.ui.qml.tpl",
- "target": "Page1Form.ui.qml"
- },
- {
- "source": "qml.qrc"
- },
- {
- "source": "qtquickcontrols2.conf"
- },
- {
- "source": "../git.ignore",
- "target": ".gitignore",
- "condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
- }
- ]
- }
- ]
-}
diff --git a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
index 259ebdc2bf..ea3b5a136d 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json
@@ -8,17 +8,17 @@
"trDisplayCategory": "Other Project",
"icon": "qtquickuiprototype.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
- "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.1.3", "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],
+ "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],
"options":
[
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qmlproject')}" },
{ "key": "MainQmlFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qml')}" },
- { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.qtQuickVersion}" },
- { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.qtQuickWindowVersion}" },
- { "key": "UiSupport", "value": "%{JS: '%{QtQuickVersion}' !== '2.3' }" },
- { "key": "IsUiFileInUse", "value": "%{JS: %{UiSupport} && %{QmlUiSplit} }" },
- { "key": "UseVirtualKeyboard", "value": "false" }
+ { "key": "QtQuickVersion", "value": "%{JS: %{QtVersion}.QtQuickVersion}" },
+ { "key": "QtQuickWindowVersion", "value": "%{JS: %{QtVersion}.QtQuickWindowVersion}" },
+ { "key": "QtQuickVirtualKeyboardImport", "value": "%{JS: %{QtVersion}.QtQuickVirtualKeyboardImport}" },
+ { "key": "QtQuickFeature", "value": "QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}" },
+ { "key": "UseVirtualKeyboardByDefault", "value": "%{JS: [ %{Plugins} ].indexOf('Boot2Qt') >= 0 || [ %{Plugins} ].indexOf('Boot2QtQdb') >= 0}" }
],
"pages":
@@ -43,64 +43,51 @@
"items":
[
{
- "trKey": "Qt 5.8",
- "value":
- "{
- 'qtQuickVersion': '2.8',
- 'qtQuickWindowVersion': '2.2'
- }"
- },
- {
- "trKey": "Qt 5.7",
- "value":
- "{
- 'qtQuickVersion': '2.7',
- 'qtQuickWindowVersion': '2.2'
- }"
- },
- {
- "trKey": "Qt 5.6",
+ "trKey": "Qt 5.9",
"value":
"{
- 'qtQuickVersion': '2.6',
- 'qtQuickWindowVersion': '2.2'
+ 'QtQuickVersion': '2.9',
+ 'QtQuickWindowVersion': '2.3',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
}"
},
{
- "trKey": "Qt 5.5",
+ "trKey": "Qt 5.8",
"value":
"{
- 'qtQuickVersion': '2.5',
- 'qtQuickWindowVersion': '2.2'
+ 'QtQuickVersion': '2.8',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
}"
},
{
- "trKey": "Qt 5.4",
+ "trKey": "Qt 5.7",
"value":
"{
- 'qtQuickVersion': '2.4',
- 'qtQuickWindowVersion': '2.2'
+ 'QtQuickVersion': '2.7',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.VirtualKeyboard 2.1'
}"
},
{
- "trKey": "Qt 5.3",
+ "trKey": "Qt 5.6",
"value":
"{
- 'qtQuickVersion': '2.3',
- 'qtQuickWindowVersion': '2.2'
+ 'QtQuickVersion': '2.6',
+ 'QtQuickWindowVersion': '2.2',
+ 'QtQuickVirtualKeyboardImport': 'QtQuick.Enterprise.VirtualKeyboard 2.0'
}"
}
]
}
},
{
- "name": "QmlUiSplit",
- "trDisplayName": "With ui.qml file",
+ "name": "UseVirtualKeyboard",
+ "trDisplayName": "Use Qt Virtual Keyboard.",
"type": "CheckBox",
- "visible": "%{UiSupport}",
"data":
{
- "checked": false
+ "checked": "%{JS: %{UseVirtualKeyboardByDefault}}"
}
}
]
@@ -123,16 +110,11 @@
"openAsProject": true
},
{
- "source": "../qtquickapplication/main.qml.tpl",
+ "source": "../qtquickapplication/empty/main.qml.tpl",
"target": "%{ProjectDirectory}/%{MainQmlFileName}",
"openInEditor": true
},
{
- "source": "../qtquickapplication/MainForm.ui.qml.tpl",
- "target": "%{ProjectDirectory}/MainForm.ui.qml",
- "condition": "%{IsUiFileInUse}"
- },
- {
"source": "../git.ignore",
"target": "%{ProjectDirectory}/.gitignore",
"condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme
index c854bbf2ba..66f8c230a6 100644
--- a/share/qtcreator/themes/flat-dark.creatortheme
+++ b/share/qtcreator/themes/flat-dark.creatortheme
@@ -206,7 +206,7 @@ PaletteWindowText=text
PaletteBase=normalBackground
PaletteAlternateBase=alternateBackground
PaletteButton=shadowBackground
-PaletteBrightText=ffff0000
+PaletteBrightText=ffff3333
PaletteText=text
PaletteButtonText=text
PaletteToolTipBase=selectedBackground
diff --git a/src/app/app.pro b/src/app/app.pro
index da162cce81..37a999fd8d 100644
--- a/src/app/app.pro
+++ b/src/app/app.pro
@@ -12,13 +12,10 @@ HEADERS += ../tools/qtcreatorcrashhandler/crashhandlersetup.h
SOURCES += main.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.cpp
include(../rpath.pri)
+include(../libs/qt-breakpad/qtbreakpad.pri)
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils)
-QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
-!isEmpty(QT_BREAKPAD_ROOT_PATH) {
- include($$QT_BREAKPAD_ROOT_PATH/qtbreakpad.pri)
-}
win32 {
# We need the version in two separate formats for the .rc file
# RC_VERSION=4,3,82,0 (quadruple)
diff --git a/src/app/app_version.h.in b/src/app/app_version.h.in
index 97fd0735a4..2c31ce0e16 100644
--- a/src/app/app_version.h.in
+++ b/src/app/app_version.h.in
@@ -31,6 +31,10 @@ namespace Constants {
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+const char IDE_DISPLAY_NAME[] = \"Qt Creator\";
+const char IDE_ID[] = \"qtcreator\";
+const char IDE_CASED_ID[] = \"QtCreator\";
+
#define IDE_VERSION $${QTCREATOR_VERSION}
#define IDE_VERSION_STR STRINGIFY(IDE_VERSION)
#define IDE_VERSION_DISPLAY_DEF $${QTCREATOR_DISPLAY_VERSION}
diff --git a/src/app/main.cpp b/src/app/main.cpp
index c1ae3245fb..7235796e3f 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -66,7 +66,6 @@ using namespace ExtensionSystem;
enum { OptionIndent = 4, DescriptionIndent = 34 };
-const char appNameC[] = "Qt Creator";
const char corePluginNameC[] = "Core";
const char fixedOptionsC[] =
" [OPTION]... [FILE]...\n"
@@ -110,7 +109,7 @@ static inline QString toHtml(const QString &t)
static void displayHelpText(const QString &t)
{
if (Utils::HostOsInfo::isWindowsHost())
- QMessageBox::information(0, QLatin1String(appNameC), toHtml(t));
+ QMessageBox::information(0, QLatin1String(Core::Constants::IDE_DISPLAY_NAME), toHtml(t));
else
qWarning("%s", qPrintable(t));
}
@@ -118,7 +117,7 @@ static void displayHelpText(const QString &t)
static void displayError(const QString &t)
{
if (Utils::HostOsInfo::isWindowsHost())
- QMessageBox::critical(0, QLatin1String(appNameC), t);
+ QMessageBox::critical(0, QLatin1String(Core::Constants::IDE_DISPLAY_NAME), t);
else
qCritical("%s", qPrintable(t));
}
@@ -127,7 +126,7 @@ static void printVersion(const PluginSpec *coreplugin)
{
QString version;
QTextStream str(&version);
- str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
+ str << '\n' << Core::Constants::IDE_DISPLAY_NAME << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
PluginManager::formatPluginVersions(str);
str << '\n' << coreplugin->copyright() << '\n';
displayHelpText(version);
@@ -211,7 +210,9 @@ static inline QStringList getPluginPaths()
pluginPath += QLatin1Char('/')
+ QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)
+ QLatin1Char('/');
- pluginPath += QLatin1String(Utils::HostOsInfo::isMacHost() ? "Qt Creator" : "qtcreator");
+ pluginPath += QLatin1String(Utils::HostOsInfo::isMacHost() ?
+ Core::Constants::IDE_DISPLAY_NAME :
+ Core::Constants::IDE_ID);
pluginPath += QLatin1String("/plugins/");
pluginPath += QLatin1String(Core::Constants::IDE_VERSION_LONG);
rc.push_back(pluginPath);
@@ -228,7 +229,7 @@ static void setupInstallSettings()
QCoreApplication::applicationDirPath() + '/' + RELATIVE_DATA_PATH);
QSettings installSettings(QSettings::IniFormat, QSettings::UserScope,
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
- QLatin1String("QtCreator"));
+ QLatin1String(Core::Constants::IDE_CASED_ID));
if (installSettings.contains(kInstallSettingsKey)) {
QString installSettingsPath = installSettings.value(kInstallSettingsKey).toString();
if (QDir::isRelativePath(installSettingsPath))
@@ -241,7 +242,7 @@ static QSettings *createUserSettings()
{
return new QSettings(QSettings::IniFormat, QSettings::UserScope,
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
- QLatin1String("QtCreator"));
+ QLatin1String(Core::Constants::IDE_CASED_ID));
}
static inline QSettings *userSettings()
@@ -276,9 +277,9 @@ static inline QSettings *userSettings()
|| lowerFile.startsWith(QLatin1String("qtversion.xml"))
|| lowerFile.startsWith(QLatin1String("devices.xml"))
|| lowerFile.startsWith(QLatin1String("debuggers.xml"))
- || lowerFile.startsWith(QLatin1String("qtcreator.")))
+ || lowerFile.startsWith(QLatin1String(Core::Constants::IDE_ID) + "."))
QFile::copy(srcDir.absoluteFilePath(file), destDir.absoluteFilePath(file));
- if (file == QLatin1String("qtcreator"))
+ if (file == QLatin1String(Core::Constants::IDE_ID))
copyRecursively(srcDir.absoluteFilePath(file), destDir.absoluteFilePath(file));
}
@@ -300,7 +301,7 @@ int main(int argc, char **argv)
if (Utils::HostOsInfo::isLinuxHost())
QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
- Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/QtCreator-XXXXXX");
+ Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
setHighDpiEnvironmentVariable();
@@ -316,7 +317,7 @@ int main(int argc, char **argv)
#endif
SharedTools::QtSingleApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
- SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);
+ SharedTools::QtSingleApplication app((QLatin1String(Core::Constants::IDE_DISPLAY_NAME)), argc, argv);
loadFonts();
@@ -329,13 +330,14 @@ int main(int argc, char **argv)
const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));
- // Display a backtrace once a serious signal is delivered (Linux only).
const QString libexecPath = QCoreApplication::applicationDirPath()
+ '/' + RELATIVE_LIBEXEC_PATH;
- CrashHandlerSetup setupCrashHandler(appNameC, CrashHandlerSetup::EnableRestart, libexecPath);
-
#ifdef ENABLE_QT_BREAKPAD
- QtSystemExceptionHandler systemExceptionHandler;
+ QtSystemExceptionHandler systemExceptionHandler(libexecPath);
+#else
+ // Display a backtrace once a serious signal is delivered (Linux only).
+ CrashHandlerSetup setupCrashHandler(Core::Constants::IDE_DISPLAY_NAME,
+ CrashHandlerSetup::EnableRestart, libexecPath);
#endif
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
@@ -384,7 +386,7 @@ int main(int argc, char **argv)
QSettings *globalSettings = new QSettings(QSettings::IniFormat, QSettings::SystemScope,
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
- QLatin1String("QtCreator"));
+ QLatin1String(Core::Constants::IDE_CASED_ID));
PluginManager pluginManager;
PluginManager::setPluginIID(QLatin1String("org.qt-project.Qt.QtCreatorPlugin"));
PluginManager::setGlobalSettings(globalSettings);
@@ -401,7 +403,7 @@ int main(int argc, char **argv)
+ '/' + RELATIVE_DATA_PATH + "/translations";
foreach (QString locale, uiLanguages) {
locale = QLocale(locale).name();
- if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
+ if (translator.load(QString::fromLatin1(Core::Constants::IDE_ID) + "_" + locale, creatorTrPath)) {
const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
const QString &qtTrFile = QLatin1String("qt_") + locale;
// Binary installer puts Qt tr files into creatorTrPath
diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp
index fe0148b23b..4952469fba 100644
--- a/src/libs/3rdparty/cplusplus/Symbols.cpp
+++ b/src/libs/3rdparty/cplusplus/Symbols.cpp
@@ -341,8 +341,22 @@ bool Function::isSignatureEqualTo(const Function *other, Matcher *matcher) const
for (unsigned i = 0; i < argc; ++i) {
Symbol *l = argumentAt(i);
Symbol *r = other->argumentAt(i);
- if (! l->type().match(r->type(), matcher))
+ if (! l->type().match(r->type(), matcher)) {
+ if (!l->type()->isReferenceType() && !l->type()->isPointerType()
+ && !l->type()->isPointerToMemberType()
+ && !r->type()->isReferenceType() && !r->type()->isPointerType()
+ && !r->type()->isPointerToMemberType()) {
+ FullySpecifiedType lType = l->type();
+ FullySpecifiedType rType = r->type();
+ lType.setConst(false);
+ lType.setVolatile(false);
+ rType.setConst(false);
+ rType.setVolatile(false);
+ if (lType.match(rType))
+ continue;
+ }
return false;
+ }
}
return true;
}
diff --git a/src/libs/clangbackendipc/clangbackendipc_dependencies.pri b/src/libs/clangbackendipc/clangbackendipc_dependencies.pri
deleted file mode 100644
index 3b52d130c3..0000000000
--- a/src/libs/clangbackendipc/clangbackendipc_dependencies.pri
+++ /dev/null
@@ -1,3 +0,0 @@
-QTC_LIB_NAME = Clangbackendipc
-QTC_LIB_DEPENDS += sqlite utils
-INCLUDEPATH *= $$IDE_SOURCE_TREE/src/libs/clangbackendipc
diff --git a/src/libs/clangbackendipc/projectpartsdonotexistmessage.h b/src/libs/clangbackendipc/projectpartsdonotexistmessage.h
deleted file mode 100644
index 65a8132dc5..0000000000
--- a/src/libs/clangbackendipc/projectpartsdonotexistmessage.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangbackendipc_global.h"
-
-#include <utf8stringvector.h>
-
-#include <QDataStream>
-
-namespace ClangBackEnd {
-
-class ProjectPartsDoNotExistMessage
-{
-public:
- ProjectPartsDoNotExistMessage() = default;
- ProjectPartsDoNotExistMessage(const Utf8StringVector &projectPartIds)
- : m_projectPartIds(projectPartIds)
- {
- }
-
- const Utf8StringVector &projectPartIds() const
- {
- return m_projectPartIds;
- }
-
- friend QDataStream &operator<<(QDataStream &out, const ProjectPartsDoNotExistMessage &message)
- {
- out << message.m_projectPartIds;
-
- return out;
- }
-
- friend QDataStream &operator>>(QDataStream &in, ProjectPartsDoNotExistMessage &message)
- {
- in >> message.m_projectPartIds;
-
- return in;
- }
-
- friend bool operator==(const ProjectPartsDoNotExistMessage &first, const ProjectPartsDoNotExistMessage &second)
- {
- return first.m_projectPartIds == second.m_projectPartIds;
- }
-
-private:
- Utf8StringVector m_projectPartIds;
-};
-
-CMBIPC_EXPORT QDebug operator<<(QDebug debug, const ProjectPartsDoNotExistMessage &message);
-std::ostream &operator<<(std::ostream &os, const ProjectPartsDoNotExistMessage &message);
-
-DECLARE_MESSAGE(ProjectPartsDoNotExistMessage)
-} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/stringcache.h b/src/libs/clangbackendipc/stringcache.h
deleted file mode 100644
index 7b4230b577..0000000000
--- a/src/libs/clangbackendipc/stringcache.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <utils/smallstringview.h>
-
-#include <algorithm>
-#include <mutex>
-#include <vector>
-
-namespace ClangBackEnd {
-
-class NonLockingMutex
-{
-public:
- constexpr NonLockingMutex() noexcept {}
- NonLockingMutex(const NonLockingMutex&) = delete;
- NonLockingMutex& operator=(const NonLockingMutex&) = delete;
- void lock() {}
- void unlock() {}
-};
-
-template <typename StringType,
- typename Mutex = NonLockingMutex>
-class StringCache
-{
- class StringCacheEntry
- {
- public:
- StringCacheEntry(StringType &&string, uint id)
- : string(std::move(string)),
- id(id)
- {}
-
- friend bool operator<(const StringCacheEntry &entry, Utils::SmallStringView stringView)
- {
- return entry.string < stringView;
- }
-
- friend bool operator<(Utils::SmallStringView stringView, const StringCacheEntry &entry)
- {
- return stringView < entry.string;
- }
-
- StringType string;
- uint id;
- };
-
- using StringCacheEntries = std::vector<StringCacheEntry>;
- using const_iterator = typename StringCacheEntries::const_iterator;
-
- class Found
- {
- public:
- typename StringCacheEntries::const_iterator iterator;
- bool wasFound;
- };
-
-
-public:
- StringCache()
- {
- m_strings.reserve(1024);
- m_indices.reserve(1024);
- }
-
- uint stringId(Utils::SmallStringView stringView)
- {
- std::lock_guard<Mutex> lock(m_mutex);
-
- Found found = find(stringView);
-
- if (!found.wasFound)
- return insertString(found.iterator, stringView);
-
- return found.iterator->id;
- }
-
- std::vector<uint> stringIds(const std::vector<StringType> &strings)
- {
- std::lock_guard<Mutex> lock(m_mutex);
-
- std::vector<uint> ids;
- ids.reserve(strings.size());
-
- std::transform(strings.begin(),
- strings.end(),
- std::back_inserter(ids),
- [&] (const StringType &string) { return stringId(string); });
-
- return ids;
- }
-
- const StringType &string(uint id) const
- {
- std::lock_guard<Mutex> lock(m_mutex);
-
- return m_strings.at(m_indices.at(id)).string;
- }
-
- std::vector<StringType> strings(const std::vector<uint> &ids) const
- {
- std::lock_guard<Mutex> lock(m_mutex);
-
- std::vector<StringType> strings;
- strings.reserve(ids.size());
-
- std::transform(ids.begin(),
- ids.end(),
- std::back_inserter(strings),
- [&] (uint id) { return m_strings.at(m_indices.at(id)).string; });
-
- return strings;
- }
-
-private:
- Found find(Utils::SmallStringView stringView)
- {
- auto range = std::equal_range(m_strings.cbegin(), m_strings.cend(), stringView);
-
- return {range.first, range.first != range.second};
- }
-
- void incrementLargerOrEqualIndicesByOne(uint newIndex)
- {
- std::transform(m_indices.begin(),
- m_indices.end(),
- m_indices.begin(),
- [&] (uint index) {
- return index >= newIndex ? ++index : index;
- });
- }
-
- uint insertString(const_iterator beforeIterator,
- Utils::SmallStringView stringView)
- {
- auto id = uint(m_strings.size());
-
- auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id);
-
- auto newIndex = uint(std::distance(m_strings.begin(), inserted));
-
- incrementLargerOrEqualIndicesByOne(newIndex);
-
- m_indices.push_back(newIndex);
-
- return id;
- }
-
-private:
- StringCacheEntries m_strings;
- std::vector<uint> m_indices;
- mutable Mutex m_mutex;
-};
-
-} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/translationunitdoesnotexistmessage.cpp b/src/libs/clangbackendipc/translationunitdoesnotexistmessage.cpp
deleted file mode 100644
index 28f54325bb..0000000000
--- a/src/libs/clangbackendipc/translationunitdoesnotexistmessage.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "translationunitdoesnotexistmessage.h"
-
-#include <QDebug>
-
-#include <ostream>
-
-namespace ClangBackEnd {
-
-QDebug operator<<(QDebug debug, const TranslationUnitDoesNotExistMessage &message)
-{
- debug.nospace() << "TranslationUnitDoesNotExistMessage(";
-
- debug.nospace() << message.fileContainer();
-
- debug.nospace() << ")";
-
- return debug;
-}
-
-std::ostream &operator<<(std::ostream &os, const TranslationUnitDoesNotExistMessage &message)
-{
- os << "("
- << message.fileContainer()
- << ")";
-
- return os;
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/libs/clangbackendipc/cancelmessage.cpp b/src/libs/clangsupport/cancelmessage.cpp
index ca5adf0ab4..ca5adf0ab4 100644
--- a/src/libs/clangbackendipc/cancelmessage.cpp
+++ b/src/libs/clangsupport/cancelmessage.cpp
diff --git a/src/libs/clangbackendipc/cancelmessage.h b/src/libs/clangsupport/cancelmessage.h
index c8924faec6..151799c3ab 100644
--- a/src/libs/clangbackendipc/cancelmessage.h
+++ b/src/libs/clangsupport/cancelmessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
namespace ClangBackEnd {
diff --git a/src/libs/clangbackendipc/clangcodemodelclientinterface.cpp b/src/libs/clangsupport/clangcodemodelclientinterface.cpp
index 6fa2b25d47..0de9f39044 100644
--- a/src/libs/clangbackendipc/clangcodemodelclientinterface.cpp
+++ b/src/libs/clangsupport/clangcodemodelclientinterface.cpp
@@ -44,18 +44,15 @@ void ClangCodeModelClientInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::CodeCompletedMessage:
codeCompleted(messageEnvelop.message<CodeCompletedMessage>());
break;
- case MessageType::TranslationUnitDoesNotExistMessage:
- translationUnitDoesNotExist(messageEnvelop.message<TranslationUnitDoesNotExistMessage>());
- break;
- case MessageType::ProjectPartsDoNotExistMessage:
- projectPartsDoNotExist(messageEnvelop.message<ProjectPartsDoNotExistMessage>());
- break;
case MessageType::DocumentAnnotationsChangedMessage:
documentAnnotationsChanged(messageEnvelop.message<DocumentAnnotationsChangedMessage>());
break;
case MessageType::ReferencesMessage:
references(messageEnvelop.message<ReferencesMessage>());
break;
+ case MessageType::FollowSymbolMessage:
+ followSymbol(messageEnvelop.message<FollowSymbolMessage>());
+ break;
default:
qWarning() << "Unknown ClangCodeModelClientMessage";
}
diff --git a/src/libs/clangbackendipc/clangcodemodelclientinterface.h b/src/libs/clangsupport/clangcodemodelclientinterface.h
index d526b98228..3577abb154 100644
--- a/src/libs/clangbackendipc/clangcodemodelclientinterface.h
+++ b/src/libs/clangsupport/clangcodemodelclientinterface.h
@@ -35,14 +35,14 @@ class CodeCompletedMessage;
class CompleteCodeMessage;
class DocumentAnnotationsChangedMessage;
class EchoMessage;
-class ProjectPartsDoNotExistMessage;
class ReferencesMessage;
+class FollowSymbolMessage;
class RegisterProjectPartsForEditorMessage;
class RegisterTranslationUnitForEditorMessage;
class RegisterUnsavedFilesForEditorMessage;
class RequestDocumentAnnotationsMessage;
class RequestReferencesMessage;
-class TranslationUnitDoesNotExistMessage;
+class RequestFollowSymbolMessage;
class UnregisterProjectPartsForEditorMessage;
class UnregisterTranslationUnitsForEditorMessage;
class UnregisterUnsavedFilesForEditorMessage;
@@ -57,10 +57,9 @@ public:
virtual void alive() = 0;
virtual void echo(const EchoMessage &message) = 0;
virtual void codeCompleted(const CodeCompletedMessage &message) = 0;
- virtual void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) = 0;
- virtual void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) = 0;
virtual void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) = 0;
virtual void references(const ReferencesMessage &message) = 0;
+ virtual void followSymbol(const FollowSymbolMessage &message) = 0;
};
} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/clangcodemodelclientmessages.h b/src/libs/clangsupport/clangcodemodelclientmessages.h
index 9f75d6a9ff..5b5c9b42ed 100644
--- a/src/libs/clangbackendipc/clangcodemodelclientmessages.h
+++ b/src/libs/clangsupport/clangcodemodelclientmessages.h
@@ -29,6 +29,5 @@
#include "cmbcodecompletedmessage.h"
#include "cmbechomessage.h"
#include "documentannotationschangedmessage.h"
-#include "projectpartsdonotexistmessage.h"
#include "referencesmessage.h"
-#include "translationunitdoesnotexistmessage.h"
+#include "followsymbolmessage.h"
diff --git a/src/libs/clangbackendipc/clangcodemodelclientproxy.cpp b/src/libs/clangsupport/clangcodemodelclientproxy.cpp
index f9786092bb..6a285c2366 100644
--- a/src/libs/clangbackendipc/clangcodemodelclientproxy.cpp
+++ b/src/libs/clangsupport/clangcodemodelclientproxy.cpp
@@ -80,22 +80,17 @@ void ClangCodeModelClientProxy::codeCompleted(const CodeCompletedMessage &messag
m_writeMessageBlock.write(message);
}
-void ClangCodeModelClientProxy::translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message)
-{
- m_writeMessageBlock.write(message);
-}
-
-void ClangCodeModelClientProxy::projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message)
+void ClangCodeModelClientProxy::documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message)
{
m_writeMessageBlock.write(message);
}
-void ClangCodeModelClientProxy::documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message)
+void ClangCodeModelClientProxy::references(const ReferencesMessage &message)
{
m_writeMessageBlock.write(message);
}
-void ClangCodeModelClientProxy::references(const ReferencesMessage &message)
+void ClangCodeModelClientProxy::followSymbol(const FollowSymbolMessage &message)
{
m_writeMessageBlock.write(message);
}
diff --git a/src/libs/clangbackendipc/clangcodemodelclientproxy.h b/src/libs/clangsupport/clangcodemodelclientproxy.h
index 689f968476..91cf900eb4 100644
--- a/src/libs/clangbackendipc/clangcodemodelclientproxy.h
+++ b/src/libs/clangsupport/clangcodemodelclientproxy.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "clangcodemodelclientinterface.h"
#include "readmessageblock.h"
#include "writemessageblock.h"
@@ -54,10 +54,9 @@ public:
void alive() override;
void echo(const EchoMessage &message) override;
void codeCompleted(const CodeCompletedMessage &message) override;
- void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) override;
- void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) override;
void documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message) override;
void references(const ReferencesMessage &message) override;
+ void followSymbol(const FollowSymbolMessage &message) override;
void readMessages();
diff --git a/src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp b/src/libs/clangsupport/clangcodemodelconnectionclient.cpp
index 254f650f22..254f650f22 100644
--- a/src/libs/clangbackendipc/clangcodemodelconnectionclient.cpp
+++ b/src/libs/clangsupport/clangcodemodelconnectionclient.cpp
diff --git a/src/libs/clangbackendipc/clangcodemodelconnectionclient.h b/src/libs/clangsupport/clangcodemodelconnectionclient.h
index 4069d654bd..4069d654bd 100644
--- a/src/libs/clangbackendipc/clangcodemodelconnectionclient.h
+++ b/src/libs/clangsupport/clangcodemodelconnectionclient.h
diff --git a/src/libs/clangbackendipc/clangcodemodelserverinterface.cpp b/src/libs/clangsupport/clangcodemodelserverinterface.cpp
index 67090e2c54..bdaa802a47 100644
--- a/src/libs/clangbackendipc/clangcodemodelserverinterface.cpp
+++ b/src/libs/clangsupport/clangcodemodelserverinterface.cpp
@@ -68,6 +68,9 @@ void ClangCodeModelServerInterface::dispatch(const MessageEnvelop &messageEnvelo
case MessageType::RequestReferencesMessage:
requestReferences(messageEnvelop.message<RequestReferencesMessage>());
break;
+ case MessageType::RequestFollowSymbolMessage:
+ requestFollowSymbol(messageEnvelop.message<RequestFollowSymbolMessage>());
+ break;
case MessageType::UpdateVisibleTranslationUnitsMessage:
updateVisibleTranslationUnits(messageEnvelop.message<UpdateVisibleTranslationUnitsMessage>());
break;
diff --git a/src/libs/clangbackendipc/clangcodemodelserverinterface.h b/src/libs/clangsupport/clangcodemodelserverinterface.h
index e25b9ef66b..e5b2956edd 100644
--- a/src/libs/clangbackendipc/clangcodemodelserverinterface.h
+++ b/src/libs/clangsupport/clangcodemodelserverinterface.h
@@ -33,7 +33,7 @@ namespace ClangBackEnd {
class ClangCodeModelClientInterface;
-class CMBIPC_EXPORT ClangCodeModelServerInterface : public IpcServerInterface<ClangCodeModelClientInterface>
+class CMBIPC_EXPORT ClangCodeModelServerInterface : public IpcServerInterface
{
public:
void dispatch(const MessageEnvelop &messageEnvelop) override;
@@ -49,6 +49,7 @@ public:
virtual void completeCode(const CompleteCodeMessage &message) = 0;
virtual void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) = 0;
virtual void requestReferences(const RequestReferencesMessage &message) = 0;
+ virtual void requestFollowSymbol(const RequestFollowSymbolMessage &message) = 0;
virtual void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0;
};
diff --git a/src/libs/clangbackendipc/clangcodemodelservermessages.h b/src/libs/clangsupport/clangcodemodelservermessages.h
index 8d8cb037b7..b1ba7a0701 100644
--- a/src/libs/clangbackendipc/clangcodemodelservermessages.h
+++ b/src/libs/clangsupport/clangcodemodelservermessages.h
@@ -35,6 +35,7 @@
#include "registerunsavedfilesforeditormessage.h"
#include "requestdocumentannotations.h"
#include "requestreferencesmessage.h"
+#include "requestfollowsymbolmessage.h"
#include "unregisterunsavedfilesforeditormessage.h"
#include "updatetranslationunitsforeditormessage.h"
#include "updatevisibletranslationunitsmessage.h"
diff --git a/src/libs/clangbackendipc/clangcodemodelserverproxy.cpp b/src/libs/clangsupport/clangcodemodelserverproxy.cpp
index 9b6a214160..a5b6411e75 100644
--- a/src/libs/clangbackendipc/clangcodemodelserverproxy.cpp
+++ b/src/libs/clangsupport/clangcodemodelserverproxy.cpp
@@ -110,6 +110,11 @@ void ClangCodeModelServerProxy::requestReferences(const RequestReferencesMessage
m_writeMessageBlock.write(message);
}
+void ClangCodeModelServerProxy::requestFollowSymbol(const RequestFollowSymbolMessage &message)
+{
+ m_writeMessageBlock.write(message);
+}
+
void ClangCodeModelServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
m_writeMessageBlock.write(message);
diff --git a/src/libs/clangbackendipc/clangcodemodelserverproxy.h b/src/libs/clangsupport/clangcodemodelserverproxy.h
index a854225ffc..c43c9cd01d 100644
--- a/src/libs/clangbackendipc/clangcodemodelserverproxy.h
+++ b/src/libs/clangsupport/clangcodemodelserverproxy.h
@@ -60,6 +60,7 @@ public:
void completeCode(const CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
+ void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
void readMessages();
diff --git a/src/libs/clangbackendipc/clangrefactoringclientmessages.h b/src/libs/clangsupport/clangrefactoringclientmessages.h
index 7b90453540..7b90453540 100644
--- a/src/libs/clangbackendipc/clangrefactoringclientmessages.h
+++ b/src/libs/clangsupport/clangrefactoringclientmessages.h
diff --git a/src/libs/clangbackendipc/clangrefactoringmessages.h b/src/libs/clangsupport/clangrefactoringmessages.h
index 7f6f0de69e..7f6f0de69e 100644
--- a/src/libs/clangbackendipc/clangrefactoringmessages.h
+++ b/src/libs/clangsupport/clangrefactoringmessages.h
diff --git a/src/libs/clangbackendipc/clangrefactoringservermessages.h b/src/libs/clangsupport/clangrefactoringservermessages.h
index 797b3d58ef..2be6f0d54d 100644
--- a/src/libs/clangbackendipc/clangrefactoringservermessages.h
+++ b/src/libs/clangsupport/clangrefactoringservermessages.h
@@ -30,3 +30,5 @@
#include "requestsourcelocationforrenamingmessage.h"
#include "requestsourcerangesanddiagnosticsforquerymessage.h"
#include "requestsourcerangesforquerymessage.h"
+#include "updatepchprojectpartsmessage.h"
+#include "removepchprojectpartsmessage.h"
diff --git a/src/libs/clangbackendipc/clangbackendipc-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri
index 3f3758772d..25b48dfc07 100644
--- a/src/libs/clangbackendipc/clangbackendipc-lib.pri
+++ b/src/libs/clangsupport/clangsupport-lib.pri
@@ -1,7 +1,7 @@
shared {
- DEFINES += CLANGBACKENDIPC_BUILD_LIB
+ DEFINES += CLANGSUPPORT_BUILD_LIB
} else {
- DEFINES += CLANGBACKENDIPC_BUILD_STATIC_LIB
+ DEFINES += CLANGSUPPORT_BUILD_STATIC_LIB
}
QT += network
@@ -10,7 +10,7 @@ INCLUDEPATH += $$PWD
SOURCES += \
$$PWD/cancelmessage.cpp \
- $$PWD/clangbackendipcdebugutils.cpp \
+ $$PWD/clangsupportdebugutils.cpp \
$$PWD/clangcodemodelclientinterface.cpp \
$$PWD/clangcodemodelclientproxy.cpp \
$$PWD/clangcodemodelconnectionclient.cpp \
@@ -38,6 +38,7 @@ SOURCES += \
$$PWD/filecontainerv2.cpp \
$$PWD/filepath.cpp \
$$PWD/fixitcontainer.cpp \
+ $$PWD/followsymbolmessage.cpp \
$$PWD/highlightingmarkcontainer.cpp \
$$PWD/ipcclientinterface.cpp \
$$PWD/ipcinterface.cpp \
@@ -52,7 +53,6 @@ SOURCES += \
$$PWD/projectpartcontainer.cpp \
$$PWD/projectpartcontainerv2.cpp \
$$PWD/projectpartpch.cpp \
- $$PWD/projectpartsdonotexistmessage.cpp \
$$PWD/readmessageblock.cpp \
$$PWD/refactoringclientinterface.cpp \
$$PWD/refactoringclientproxy.cpp \
@@ -62,6 +62,7 @@ SOURCES += \
$$PWD/registerunsavedfilesforeditormessage.cpp \
$$PWD/removepchprojectpartsmessage.cpp \
$$PWD/requestdocumentannotations.cpp \
+ $$PWD/requestfollowsymbolmessage.cpp \
$$PWD/requestreferencesmessage.cpp \
$$PWD/requestsourcelocationforrenamingmessage.cpp \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \
@@ -77,17 +78,16 @@ SOURCES += \
$$PWD/sourcerangescontainer.cpp \
$$PWD/sourcerangesforquerymessage.cpp \
$$PWD/sourcerangewithtextcontainer.cpp \
- $$PWD/translationunitdoesnotexistmessage.cpp \
$$PWD/unregisterunsavedfilesforeditormessage.cpp \
$$PWD/updatepchprojectpartsmessage.cpp \
$$PWD/updatetranslationunitsforeditormessage.cpp \
$$PWD/updatevisibletranslationunitsmessage.cpp \
- $$PWD/writemessageblock.cpp \
+ $$PWD/writemessageblock.cpp
HEADERS += \
$$PWD/cancelmessage.h \
- $$PWD/clangbackendipcdebugutils.h \
- $$PWD/clangbackendipc_global.h \
+ $$PWD/clangsupportdebugutils.h \
+ $$PWD/clangsupport_global.h \
$$PWD/clangcodemodelclientinterface.h \
$$PWD/clangcodemodelclientmessages.h \
$$PWD/clangcodemodelclientproxy.h \
@@ -121,6 +121,7 @@ HEADERS += \
$$PWD/filecontainerv2.h \
$$PWD/filepath.h \
$$PWD/fixitcontainer.h \
+ $$PWD/followsymbolmessage.h \
$$PWD/highlightingmarkcontainer.h \
$$PWD/ipcclientinterface.h \
$$PWD/ipcinterface.h \
@@ -135,7 +136,6 @@ HEADERS += \
$$PWD/projectpartcontainer.h \
$$PWD/projectpartcontainerv2.h \
$$PWD/projectpartpch.h \
- $$PWD/projectpartsdonotexistmessage.h \
$$PWD/readmessageblock.h \
$$PWD/refactoringclientinterface.h \
$$PWD/refactoringclientproxy.h \
@@ -145,6 +145,7 @@ HEADERS += \
$$PWD/registerunsavedfilesforeditormessage.h \
$$PWD/removepchprojectpartsmessage.h \
$$PWD/requestdocumentannotations.h \
+ $$PWD/requestfollowsymbolmessage.h \
$$PWD/requestreferencesmessage.h \
$$PWD/requestsourcelocationforrenamingmessage.h \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \
@@ -161,11 +162,16 @@ HEADERS += \
$$PWD/sourcerangesforquerymessage.h \
$$PWD/sourcerangewithtextcontainer.h \
$$PWD/stringcache.h \
- $$PWD/translationunitdoesnotexistmessage.h \
$$PWD/unregisterunsavedfilesforeditormessage.h \
$$PWD/updatepchprojectpartsmessage.h \
$$PWD/updatetranslationunitsforeditormessage.h \
$$PWD/updatevisibletranslationunitsmessage.h \
$$PWD/writemessageblock.h \
+ $$PWD/ipcclientprovider.h \
+ $$PWD/requestsourcerangesforquerymessage.h \
+ $$PWD/stringcachefwd.h \
+ $$PWD/stringcachealgorithms.h \
+ $$PWD/projectmanagementserverinterface.h \
+ $$PWD/refactoringdatabaseinitializer.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
diff --git a/src/libs/clangbackendipc/clangbackendipc.pro b/src/libs/clangsupport/clangsupport.pro
index e5997d0688..fa614e74ff 100644
--- a/src/libs/clangbackendipc/clangbackendipc.pro
+++ b/src/libs/clangsupport/clangsupport.pro
@@ -1,2 +1,2 @@
include(../../qtcreatorlibrary.pri)
-include(clangbackendipc-lib.pri)
+include(clangsupport-lib.pri)
diff --git a/src/libs/clangbackendipc/clangbackendipc.qbs b/src/libs/clangsupport/clangsupport.qbs
index afa80a5e2b..6b76f784af 100644
--- a/src/libs/clangbackendipc/clangbackendipc.qbs
+++ b/src/libs/clangsupport/clangsupport.qbs
@@ -1,14 +1,14 @@
import qbs 1.0
QtcLibrary {
- name: "ClangBackEndIpc"
+ name: "ClangSupport"
targetName: "Clangbackendipc"
Depends { name: "Qt.network" }
Depends { name: "Sqlite" }
Depends { name: "Utils" }
- cpp.defines: base.concat("CLANGBACKENDIPC_BUILD_LIB")
+ cpp.defines: base.concat("CLANGSUPPORT_BUILD_LIB")
cpp.includePaths: base.concat(".")
Group {
diff --git a/src/libs/clangsupport/clangsupport_dependencies.pri b/src/libs/clangsupport/clangsupport_dependencies.pri
new file mode 100644
index 0000000000..74afbf09a8
--- /dev/null
+++ b/src/libs/clangsupport/clangsupport_dependencies.pri
@@ -0,0 +1,3 @@
+QTC_LIB_NAME = Clangsupport
+QTC_LIB_DEPENDS += sqlite utils
+INCLUDEPATH *= $$IDE_SOURCE_TREE/src/libs/clangsupport
diff --git a/src/libs/clangbackendipc/clangbackendipc_global.h b/src/libs/clangsupport/clangsupport_global.h
index e48a05e7d9..f69b11b7d2 100644
--- a/src/libs/clangbackendipc/clangbackendipc_global.h
+++ b/src/libs/clangsupport/clangsupport_global.h
@@ -35,9 +35,9 @@
#include <gtest/gtest.h>
#endif
-#if defined(CLANGBACKENDIPC_BUILD_LIB)
+#if defined(CLANGSUPPORT_BUILD_LIB)
# define CMBIPC_EXPORT Q_DECL_EXPORT
-#elif defined(CLANGBACKENDIPC_BUILD_STATIC_LIB)
+#elif defined(CLANGSUPPORT_BUILD_STATIC_LIB)
# define CMBIPC_EXPORT
#else
# define CMBIPC_EXPORT Q_DECL_IMPORT
@@ -116,14 +116,14 @@ enum class MessageType : quint8 {
RequestReferencesMessage,
ReferencesMessage,
+ RequestFollowSymbolMessage,
+ FollowSymbolMessage,
+
UpdateVisibleTranslationUnitsMessage,
CompleteCodeMessage,
CodeCompletedMessage,
- TranslationUnitDoesNotExistMessage,
- ProjectPartsDoNotExistMessage,
-
SourceLocationsForRenamingMessage,
RequestSourceLocationsForRenamingMessage,
@@ -154,7 +154,7 @@ struct MessageTrait<Message> \
using MixinHighlightingTypes = Utils::SizedArray<HighlightingType, 6>;
struct HighlightingTypes {
- HighlightingType mainHighlightingType;
+ HighlightingType mainHighlightingType = HighlightingType::Invalid;
MixinHighlightingTypes mixinHighlightingTypes;
};
diff --git a/src/libs/clangbackendipc/clangbackendipcdebugutils.cpp b/src/libs/clangsupport/clangsupportdebugutils.cpp
index 8c0f83e10b..c62ad0bbc1 100644
--- a/src/libs/clangbackendipc/clangbackendipcdebugutils.cpp
+++ b/src/libs/clangsupport/clangsupportdebugutils.cpp
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "clangbackendipcdebugutils.h"
+#include "clangsupportdebugutils.h"
#include "filecontainer.h"
@@ -43,7 +43,7 @@ class DebugInspectionDir : public QTemporaryDir
{
public:
DebugInspectionDir()
- : QTemporaryDir(QDir::tempPath() + QLatin1String("/qtc-clangbackendipc-XXXXXX"))
+ : QTemporaryDir(QDir::tempPath() + QLatin1String("/qtc-clangsupport-XXXXXX"))
{
setAutoRemove(false); // Keep around for later inspection.
}
diff --git a/src/libs/clangbackendipc/clangbackendipcdebugutils.h b/src/libs/clangsupport/clangsupportdebugutils.h
index 7f766c45d5..52352bb315 100644
--- a/src/libs/clangbackendipc/clangbackendipcdebugutils.h
+++ b/src/libs/clangsupport/clangsupportdebugutils.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QElapsedTimer>
diff --git a/src/libs/clangbackendipc/cmbalivemessage.cpp b/src/libs/clangsupport/cmbalivemessage.cpp
index d0ec78d632..d0ec78d632 100644
--- a/src/libs/clangbackendipc/cmbalivemessage.cpp
+++ b/src/libs/clangsupport/cmbalivemessage.cpp
diff --git a/src/libs/clangbackendipc/cmbalivemessage.h b/src/libs/clangsupport/cmbalivemessage.h
index 435423a2f0..6093b4b86b 100644
--- a/src/libs/clangbackendipc/cmbalivemessage.h
+++ b/src/libs/clangsupport/cmbalivemessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QDataStream>
diff --git a/src/libs/clangbackendipc/cmbcodecompletedmessage.cpp b/src/libs/clangsupport/cmbcodecompletedmessage.cpp
index e5667fd04e..e5667fd04e 100644
--- a/src/libs/clangbackendipc/cmbcodecompletedmessage.cpp
+++ b/src/libs/clangsupport/cmbcodecompletedmessage.cpp
diff --git a/src/libs/clangbackendipc/cmbcodecompletedmessage.h b/src/libs/clangsupport/cmbcodecompletedmessage.h
index 1bcac526ca..1bcac526ca 100644
--- a/src/libs/clangbackendipc/cmbcodecompletedmessage.h
+++ b/src/libs/clangsupport/cmbcodecompletedmessage.h
diff --git a/src/libs/clangbackendipc/cmbcompletecodemessage.cpp b/src/libs/clangsupport/cmbcompletecodemessage.cpp
index 3bc968e76d..561391b3d5 100644
--- a/src/libs/clangbackendipc/cmbcompletecodemessage.cpp
+++ b/src/libs/clangsupport/cmbcompletecodemessage.cpp
@@ -42,6 +42,8 @@ QDebug operator<<(QDebug debug, const CompleteCodeMessage &message)
debug.nospace() << message.m_column << ", ";
debug.nospace() << message.m_projectPartId << ", ";
debug.nospace() << message.m_ticketNumber;
+ debug.nospace() << message.m_funcNameStartLine << ", ";
+ debug.nospace() << message.m_funcNameStartColumn << ", ";
debug.nospace() << ")";
@@ -55,7 +57,9 @@ std::ostream &operator<<(std::ostream &os, const CompleteCodeMessage &message)
<< message.m_line << ", "
<< message.m_column << ", "
<< message.m_projectPartId.constData() << ", "
- << message.m_ticketNumber
+ << message.m_ticketNumber << ", "
+ << message.m_funcNameStartLine << ", "
+ << message.m_funcNameStartColumn
<< ")";
diff --git a/src/libs/clangbackendipc/cmbcompletecodemessage.h b/src/libs/clangsupport/cmbcompletecodemessage.h
index 1c37a6538b..423d711d45 100644
--- a/src/libs/clangbackendipc/cmbcompletecodemessage.h
+++ b/src/libs/clangsupport/cmbcompletecodemessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utf8string.h>
@@ -41,12 +41,16 @@ public:
CompleteCodeMessage(const Utf8String &filePath,
quint32 line,
quint32 column,
- const Utf8String &projectPartId)
+ const Utf8String &projectPartId,
+ qint32 funcNameStartLine = -1,
+ qint32 funcNameStartColumn = -1)
: m_filePath(filePath),
m_projectPartId(projectPartId),
m_ticketNumber(++ticketCounter),
m_line(line),
- m_column(column)
+ m_column(column),
+ m_funcNameStartLine(funcNameStartLine),
+ m_funcNameStartColumn(funcNameStartColumn)
{
}
@@ -75,6 +79,16 @@ public:
return m_ticketNumber;
}
+ qint32 funcNameStartLine() const
+ {
+ return m_funcNameStartLine;
+ }
+
+ qint32 funcNameStartColumn() const
+ {
+ return m_funcNameStartColumn;
+ }
+
friend QDataStream &operator<<(QDataStream &out, const CompleteCodeMessage &message)
{
out << message.m_filePath;
@@ -82,6 +96,8 @@ public:
out << message.m_ticketNumber;
out << message.m_line;
out << message.m_column;
+ out << message.m_funcNameStartLine;
+ out << message.m_funcNameStartColumn;
return out;
}
@@ -93,6 +109,8 @@ public:
in >> message.m_ticketNumber;
in >> message.m_line;
in >> message.m_column;
+ in >> message.m_funcNameStartLine;
+ in >> message.m_funcNameStartColumn;
return in;
}
@@ -103,7 +121,9 @@ public:
&& first.m_filePath == second.m_filePath
&& first.m_projectPartId == second.m_projectPartId
&& first.m_line == second.m_line
- && first.m_column == second.m_column;
+ && first.m_column == second.m_column
+ && first.m_funcNameStartLine == second.m_funcNameStartLine
+ && first.m_funcNameStartColumn == second.m_funcNameStartColumn;
}
friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const CompleteCodeMessage &message);
@@ -116,6 +136,8 @@ private:
quint64 m_ticketNumber = 0;
quint32 m_line = 0;
quint32 m_column = 0;
+ qint32 m_funcNameStartLine = -1;
+ qint32 m_funcNameStartColumn = -1;
};
DECLARE_MESSAGE(CompleteCodeMessage);
diff --git a/src/libs/clangbackendipc/cmbechomessage.cpp b/src/libs/clangsupport/cmbechomessage.cpp
index 734eb0d103..734eb0d103 100644
--- a/src/libs/clangbackendipc/cmbechomessage.cpp
+++ b/src/libs/clangsupport/cmbechomessage.cpp
diff --git a/src/libs/clangbackendipc/cmbechomessage.h b/src/libs/clangsupport/cmbechomessage.h
index 098d75f240..7e75a35e3a 100644
--- a/src/libs/clangbackendipc/cmbechomessage.h
+++ b/src/libs/clangsupport/cmbechomessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "messageenvelop.h"
diff --git a/src/libs/clangbackendipc/cmbendmessage.cpp b/src/libs/clangsupport/cmbendmessage.cpp
index d4535f45fa..d4535f45fa 100644
--- a/src/libs/clangbackendipc/cmbendmessage.cpp
+++ b/src/libs/clangsupport/cmbendmessage.cpp
diff --git a/src/libs/clangbackendipc/cmbendmessage.h b/src/libs/clangsupport/cmbendmessage.h
index 684e5b7a7d..40db9ef51f 100644
--- a/src/libs/clangbackendipc/cmbendmessage.h
+++ b/src/libs/clangsupport/cmbendmessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QDataStream>
diff --git a/src/libs/clangbackendipc/cmbregisterprojectsforeditormessage.cpp b/src/libs/clangsupport/cmbregisterprojectsforeditormessage.cpp
index c18cf08980..c18cf08980 100644
--- a/src/libs/clangbackendipc/cmbregisterprojectsforeditormessage.cpp
+++ b/src/libs/clangsupport/cmbregisterprojectsforeditormessage.cpp
diff --git a/src/libs/clangbackendipc/cmbregisterprojectsforeditormessage.h b/src/libs/clangsupport/cmbregisterprojectsforeditormessage.h
index 10880735f7..10880735f7 100644
--- a/src/libs/clangbackendipc/cmbregisterprojectsforeditormessage.h
+++ b/src/libs/clangsupport/cmbregisterprojectsforeditormessage.h
diff --git a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.cpp b/src/libs/clangsupport/cmbregistertranslationunitsforeditormessage.cpp
index 3b3d3e5e28..3b3d3e5e28 100644
--- a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.cpp
+++ b/src/libs/clangsupport/cmbregistertranslationunitsforeditormessage.cpp
diff --git a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.h b/src/libs/clangsupport/cmbregistertranslationunitsforeditormessage.h
index 85afdf63f9..85afdf63f9 100644
--- a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.h
+++ b/src/libs/clangsupport/cmbregistertranslationunitsforeditormessage.h
diff --git a/src/libs/clangbackendipc/cmbunregisterprojectsforeditormessage.cpp b/src/libs/clangsupport/cmbunregisterprojectsforeditormessage.cpp
index e509926970..e509926970 100644
--- a/src/libs/clangbackendipc/cmbunregisterprojectsforeditormessage.cpp
+++ b/src/libs/clangsupport/cmbunregisterprojectsforeditormessage.cpp
diff --git a/src/libs/clangbackendipc/cmbunregisterprojectsforeditormessage.h b/src/libs/clangsupport/cmbunregisterprojectsforeditormessage.h
index 355e85217d..8f1e02f2fe 100644
--- a/src/libs/clangbackendipc/cmbunregisterprojectsforeditormessage.h
+++ b/src/libs/clangsupport/cmbunregisterprojectsforeditormessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utf8stringvector.h>
diff --git a/src/libs/clangbackendipc/cmbunregistertranslationunitsforeditormessage.cpp b/src/libs/clangsupport/cmbunregistertranslationunitsforeditormessage.cpp
index c547b94b2f..c547b94b2f 100644
--- a/src/libs/clangbackendipc/cmbunregistertranslationunitsforeditormessage.cpp
+++ b/src/libs/clangsupport/cmbunregistertranslationunitsforeditormessage.cpp
diff --git a/src/libs/clangbackendipc/cmbunregistertranslationunitsforeditormessage.h b/src/libs/clangsupport/cmbunregistertranslationunitsforeditormessage.h
index ea9df17d28..aa6bf47edd 100644
--- a/src/libs/clangbackendipc/cmbunregistertranslationunitsforeditormessage.h
+++ b/src/libs/clangsupport/cmbunregistertranslationunitsforeditormessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "filecontainer.h"
diff --git a/src/libs/clangbackendipc/codecompletion.cpp b/src/libs/clangsupport/codecompletion.cpp
index 07b2daac0f..07b2daac0f 100644
--- a/src/libs/clangbackendipc/codecompletion.cpp
+++ b/src/libs/clangsupport/codecompletion.cpp
diff --git a/src/libs/clangbackendipc/codecompletion.h b/src/libs/clangsupport/codecompletion.h
index bd63115da0..78303c1c33 100644
--- a/src/libs/clangbackendipc/codecompletion.h
+++ b/src/libs/clangsupport/codecompletion.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "codecompletionchunk.h"
#include <utf8string.h>
diff --git a/src/libs/clangbackendipc/codecompletionchunk.cpp b/src/libs/clangsupport/codecompletionchunk.cpp
index 60a0fee2c4..60a0fee2c4 100644
--- a/src/libs/clangbackendipc/codecompletionchunk.cpp
+++ b/src/libs/clangsupport/codecompletionchunk.cpp
diff --git a/src/libs/clangbackendipc/codecompletionchunk.h b/src/libs/clangsupport/codecompletionchunk.h
index 8ba1032c8e..57d351afde 100644
--- a/src/libs/clangbackendipc/codecompletionchunk.h
+++ b/src/libs/clangsupport/codecompletionchunk.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utf8string.h>
diff --git a/src/libs/clangbackendipc/connectionclient.cpp b/src/libs/clangsupport/connectionclient.cpp
index c0a0fa5de5..e53fac1810 100644
--- a/src/libs/clangbackendipc/connectionclient.cpp
+++ b/src/libs/clangsupport/connectionclient.cpp
@@ -25,7 +25,7 @@
#include "connectionclient.h"
-#include "clangbackendipcdebugutils.h"
+#include "clangsupportdebugutils.h"
#include <QCoreApplication>
#include <QMetaMethod>
diff --git a/src/libs/clangbackendipc/connectionclient.h b/src/libs/clangsupport/connectionclient.h
index d8c6692b56..d8c6692b56 100644
--- a/src/libs/clangbackendipc/connectionclient.h
+++ b/src/libs/clangsupport/connectionclient.h
diff --git a/src/libs/clangbackendipc/connectionserver.cpp b/src/libs/clangsupport/connectionserver.cpp
index 6828041de8..6828041de8 100644
--- a/src/libs/clangbackendipc/connectionserver.cpp
+++ b/src/libs/clangsupport/connectionserver.cpp
diff --git a/src/libs/clangbackendipc/connectionserver.h b/src/libs/clangsupport/connectionserver.h
index 021ffac0f9..268c3776a4 100644
--- a/src/libs/clangbackendipc/connectionserver.h
+++ b/src/libs/clangsupport/connectionserver.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QCoreApplication>
#include <QLocalServer>
diff --git a/src/libs/clangbackendipc/diagnosticcontainer.cpp b/src/libs/clangsupport/diagnosticcontainer.cpp
index b73114d6d0..b73114d6d0 100644
--- a/src/libs/clangbackendipc/diagnosticcontainer.cpp
+++ b/src/libs/clangsupport/diagnosticcontainer.cpp
diff --git a/src/libs/clangbackendipc/diagnosticcontainer.h b/src/libs/clangsupport/diagnosticcontainer.h
index 56f45abee3..56f45abee3 100644
--- a/src/libs/clangbackendipc/diagnosticcontainer.h
+++ b/src/libs/clangsupport/diagnosticcontainer.h
diff --git a/src/libs/clangbackendipc/documentannotationschangedmessage.cpp b/src/libs/clangsupport/documentannotationschangedmessage.cpp
index a9fef59e4a..a9fef59e4a 100644
--- a/src/libs/clangbackendipc/documentannotationschangedmessage.cpp
+++ b/src/libs/clangsupport/documentannotationschangedmessage.cpp
diff --git a/src/libs/clangbackendipc/documentannotationschangedmessage.h b/src/libs/clangsupport/documentannotationschangedmessage.h
index 75b9350cd3..63fbdcd902 100644
--- a/src/libs/clangbackendipc/documentannotationschangedmessage.h
+++ b/src/libs/clangsupport/documentannotationschangedmessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "diagnosticcontainer.h"
#include "filecontainer.h"
#include "highlightingmarkcontainer.h"
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontainer.cpp b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontainer.cpp
index a7e367609a..a7e367609a 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontainer.cpp
+++ b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontainer.cpp
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontainer.h b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontainer.h
index 09149ea35d..09149ea35d 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontainer.h
+++ b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontainer.h
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.cpp b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontextcontainer.cpp
index 37ce066706..37ce066706 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.cpp
+++ b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontextcontainer.cpp
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontextcontainer.h
index c220aa2377..c220aa2377 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h
+++ b/src/libs/clangsupport/dynamicastmatcherdiagnosticcontextcontainer.h
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp b/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.cpp
index e17ecd4da9..e17ecd4da9 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp
+++ b/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.cpp
diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h b/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.h
index 07a21af605..07a21af605 100644
--- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h
+++ b/src/libs/clangsupport/dynamicastmatcherdiagnosticmessagecontainer.h
diff --git a/src/libs/clangbackendipc/dynamicmatcherdiagnostics.h b/src/libs/clangsupport/dynamicmatcherdiagnostics.h
index 52bcbcb8e5..52bcbcb8e5 100644
--- a/src/libs/clangbackendipc/dynamicmatcherdiagnostics.h
+++ b/src/libs/clangsupport/dynamicmatcherdiagnostics.h
diff --git a/src/libs/clangbackendipc/filecontainer.cpp b/src/libs/clangsupport/filecontainer.cpp
index 9de0b550a3..c3f484dbdf 100644
--- a/src/libs/clangbackendipc/filecontainer.cpp
+++ b/src/libs/clangsupport/filecontainer.cpp
@@ -25,7 +25,7 @@
#include "filecontainer.h"
-#include "clangbackendipcdebugutils.h"
+#include "clangsupportdebugutils.h"
#include <QDebug>
diff --git a/src/libs/clangbackendipc/filecontainer.h b/src/libs/clangsupport/filecontainer.h
index 5677939694..0a45c491d2 100644
--- a/src/libs/clangbackendipc/filecontainer.h
+++ b/src/libs/clangsupport/filecontainer.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utf8string.h>
#include <utf8stringvector.h>
diff --git a/src/libs/clangbackendipc/filecontainerv2.cpp b/src/libs/clangsupport/filecontainerv2.cpp
index 57b460d842..57b460d842 100644
--- a/src/libs/clangbackendipc/filecontainerv2.cpp
+++ b/src/libs/clangsupport/filecontainerv2.cpp
diff --git a/src/libs/clangbackendipc/filecontainerv2.h b/src/libs/clangsupport/filecontainerv2.h
index 365bb5283d..7832a43c39 100644
--- a/src/libs/clangbackendipc/filecontainerv2.h
+++ b/src/libs/clangsupport/filecontainerv2.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "filepath.h"
#include <vector>
diff --git a/src/libs/clangbackendipc/filepath.cpp b/src/libs/clangsupport/filepath.cpp
index 0dbb1b4e26..0dbb1b4e26 100644
--- a/src/libs/clangbackendipc/filepath.cpp
+++ b/src/libs/clangsupport/filepath.cpp
diff --git a/src/libs/clangbackendipc/filepath.h b/src/libs/clangsupport/filepath.h
index a29ecf941f..c57da408bc 100644
--- a/src/libs/clangbackendipc/filepath.h
+++ b/src/libs/clangsupport/filepath.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utils/smallstringio.h>
diff --git a/src/libs/clangbackendipc/fixitcontainer.cpp b/src/libs/clangsupport/fixitcontainer.cpp
index 05cea43ffc..05cea43ffc 100644
--- a/src/libs/clangbackendipc/fixitcontainer.cpp
+++ b/src/libs/clangsupport/fixitcontainer.cpp
diff --git a/src/libs/clangbackendipc/fixitcontainer.h b/src/libs/clangsupport/fixitcontainer.h
index eac27da02f..eac27da02f 100644
--- a/src/libs/clangbackendipc/fixitcontainer.h
+++ b/src/libs/clangsupport/fixitcontainer.h
diff --git a/src/libs/clangbackendipc/projectpartsdonotexistmessage.cpp b/src/libs/clangsupport/followsymbolmessage.cpp
index 18fc44e0ab..cafd22aa4b 100644
--- a/src/libs/clangbackendipc/projectpartsdonotexistmessage.cpp
+++ b/src/libs/clangsupport/followsymbolmessage.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "projectpartsdonotexistmessage.h"
+#include "followsymbolmessage.h"
#include <QDebug>
@@ -31,25 +31,27 @@
namespace ClangBackEnd {
-QDebug operator<<(QDebug debug, const ProjectPartsDoNotExistMessage &message)
+QDebug operator<<(QDebug debug, const FollowSymbolMessage &message)
{
- debug.nospace() << "ProjectPartDoesNotExistMessage(";
-
- debug.nospace() << message.projectPartIds();
+ debug.nospace() << "FollowSymbolMessage("
+ << message.m_fileContainer
+ << ", " << message.m_ticketNumber
+ << ", " << message.m_sourceRange;
debug.nospace() << ")";
return debug;
}
-std::ostream &operator<<(std::ostream &os, const ProjectPartsDoNotExistMessage &message)
+std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message)
{
- os << "("
- << message.projectPartIds()
- << ")";
+ os << "("
+ << message.m_fileContainer << ", "
+ << message.m_ticketNumber << ", "
+ << message.m_sourceRange << ", "
+ << ")";
return os;
}
} // namespace ClangBackEnd
-
diff --git a/src/libs/clangbackendipc/translationunitdoesnotexistmessage.h b/src/libs/clangsupport/followsymbolmessage.h
index 67c6601fae..3893a6e49c 100644
--- a/src/libs/clangbackendipc/translationunitdoesnotexistmessage.h
+++ b/src/libs/clangsupport/followsymbolmessage.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -26,63 +26,71 @@
#pragma once
#include "filecontainer.h"
+#include "sourcerangecontainer.h"
+
+#include <QDataStream>
+#include <QVector>
namespace ClangBackEnd {
-class TranslationUnitDoesNotExistMessage
+class FollowSymbolMessage
{
public:
- TranslationUnitDoesNotExistMessage() = default;
- TranslationUnitDoesNotExistMessage(const FileContainer &fileContainer)
+ FollowSymbolMessage() = default;
+ FollowSymbolMessage(const FileContainer &fileContainer,
+ const SourceRangeContainer &range,
+ quint64 ticketNumber)
: m_fileContainer(fileContainer)
+ , m_sourceRange(range)
+ , m_ticketNumber(ticketNumber)
{
}
-
- TranslationUnitDoesNotExistMessage(const Utf8String &filePath, const Utf8String &projectPartId)
- : m_fileContainer(filePath, projectPartId)
- {
- }
-
const FileContainer &fileContainer() const
{
return m_fileContainer;
}
- const Utf8String &filePath() const
+ const SourceRangeContainer &sourceRange() const
{
- return m_fileContainer.filePath();
+ return m_sourceRange;
}
- const Utf8String &projectPartId() const
+ quint64 ticketNumber() const
{
- return m_fileContainer.projectPartId();
+ return m_ticketNumber;
}
- friend QDataStream &operator<<(QDataStream &out, const TranslationUnitDoesNotExistMessage &message)
+ friend QDataStream &operator<<(QDataStream &out, const FollowSymbolMessage &message)
{
out << message.m_fileContainer;
-
+ out << message.m_sourceRange;
+ out << message.m_ticketNumber;
return out;
}
- friend QDataStream &operator>>(QDataStream &in, TranslationUnitDoesNotExistMessage &message)
+ friend QDataStream &operator>>(QDataStream &in, FollowSymbolMessage &message)
{
in >> message.m_fileContainer;
-
+ in >> message.m_sourceRange;
+ in >> message.m_ticketNumber;
return in;
}
- friend bool operator==(const TranslationUnitDoesNotExistMessage &first, const TranslationUnitDoesNotExistMessage &second)
+ friend bool operator==(const FollowSymbolMessage &first, const FollowSymbolMessage &second)
{
- return first.m_fileContainer == second.m_fileContainer;
+ return first.m_ticketNumber == second.m_ticketNumber
+ && first.m_fileContainer == second.m_fileContainer
+ && first.m_sourceRange == second.m_sourceRange;
}
+ friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message);
+ friend std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message);
private:
FileContainer m_fileContainer;
+ SourceRangeContainer m_sourceRange;
+ quint64 m_ticketNumber = 0;
};
-CMBIPC_EXPORT QDebug operator<<(QDebug debug, const TranslationUnitDoesNotExistMessage &message);
-std::ostream &operator<<(std::ostream &os, const TranslationUnitDoesNotExistMessage &message);
+DECLARE_MESSAGE(FollowSymbolMessage);
-DECLARE_MESSAGE(TranslationUnitDoesNotExistMessage)
} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/highlightingmarkcontainer.cpp b/src/libs/clangsupport/highlightingmarkcontainer.cpp
index ab679c8d89..ec460a14a6 100644
--- a/src/libs/clangbackendipc/highlightingmarkcontainer.cpp
+++ b/src/libs/clangsupport/highlightingmarkcontainer.cpp
@@ -65,6 +65,8 @@ QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container)
<< container.column() << ", "
<< container.length() << ", "
<< highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", "
+ << container.isIdentifier() << ", "
+ << container.isIncludeDirectivePath()
<< ")";
return debug;
@@ -94,7 +96,9 @@ std::ostream &operator<<(std::ostream &os, const HighlightingMarkContainer &cont
<< container.line() << ", "
<< container.column() << ", "
<< container.length() << ", "
- << container.types()
+ << container.types() << ", "
+ << container.isIdentifier() << ", "
+ << container.isIncludeDirectivePath()
<< ")";
return os;
diff --git a/src/libs/clangbackendipc/highlightingmarkcontainer.h b/src/libs/clangsupport/highlightingmarkcontainer.h
index 56e998f26c..8b6e585e50 100644
--- a/src/libs/clangbackendipc/highlightingmarkcontainer.h
+++ b/src/libs/clangsupport/highlightingmarkcontainer.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QDataStream>
@@ -44,11 +44,14 @@ class HighlightingMarkContainer
{
public:
HighlightingMarkContainer() = default;
- HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types)
+ HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types,
+ bool isIdentifier = false, bool isIncludeDirectivePath = false)
: line_(line),
column_(column),
length_(length),
- types_(types)
+ types_(types),
+ isIdentifier_(isIdentifier),
+ isIncludeDirectivePath_(isIncludeDirectivePath)
{
}
@@ -80,12 +83,29 @@ public:
return types_;
}
+ bool isInvalid() const
+ {
+ return line_ == 0 && column_ == 0 && length_ == 0;
+ }
+
+ bool isIdentifier() const
+ {
+ return isIdentifier_;
+ }
+
+ bool isIncludeDirectivePath() const
+ {
+ return isIncludeDirectivePath_;
+ }
+
friend QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container)
{
out << container.line_;
out << container.column_;
out << container.length_;
out << container.types_;
+ out << container.isIdentifier_;
+ out << container.isIncludeDirectivePath_;
return out;
}
@@ -96,6 +116,8 @@ public:
in >> container.column_;
in >> container.length_;
in >> container.types_;
+ in >> container.isIdentifier_;
+ in >> container.isIncludeDirectivePath_;
return in;
}
@@ -105,7 +127,9 @@ public:
return first.line_ == second.line_
&& first.column_ == second.column_
&& first.length_ == second.length_
- && first.types_ == second.types_;
+ && first.types_ == second.types_
+ && first.isIdentifier_ == second.isIdentifier_
+ && first.isIncludeDirectivePath_ == second.isIncludeDirectivePath_;
}
private:
@@ -113,6 +137,8 @@ private:
uint column_ = 0;
uint length_ = 0;
HighlightingTypes types_;
+ bool isIdentifier_ = false;
+ bool isIncludeDirectivePath_ = false;
};
inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType)
diff --git a/src/libs/clangbackendipc/ipcclientinterface.cpp b/src/libs/clangsupport/ipcclientinterface.cpp
index 76f5d81eea..76f5d81eea 100644
--- a/src/libs/clangbackendipc/ipcclientinterface.cpp
+++ b/src/libs/clangsupport/ipcclientinterface.cpp
diff --git a/src/libs/clangbackendipc/ipcclientinterface.h b/src/libs/clangsupport/ipcclientinterface.h
index 080de8a207..080de8a207 100644
--- a/src/libs/clangbackendipc/ipcclientinterface.h
+++ b/src/libs/clangsupport/ipcclientinterface.h
diff --git a/src/libs/clangbackendipc/ipcserverinterface.h b/src/libs/clangsupport/ipcclientprovider.h
index 87caf34c88..a4bcb7705c 100644
--- a/src/libs/clangbackendipc/ipcserverinterface.h
+++ b/src/libs/clangsupport/ipcclientprovider.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -25,15 +25,13 @@
#pragma once
-#include "ipcinterface.h"
-
namespace ClangBackEnd {
-template <typename ClientInterface>
-class IpcServerInterface : public IpcInterface
+template <typename ClientType>
+class IpcClientProvider
{
public:
- void setClient(ClientInterface *client)
+ void setClient(ClientType *client)
{
client_ = client;
}
@@ -43,13 +41,13 @@ public:
client_ = nullptr;
}
- ClientInterface *client()
+ ClientType *client()
{
return client_;
}
private:
- ClientInterface *client_;
+ ClientType *client_;
};
} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/ipcinterface.cpp b/src/libs/clangsupport/ipcinterface.cpp
index dc579a49f9..dc579a49f9 100644
--- a/src/libs/clangbackendipc/ipcinterface.cpp
+++ b/src/libs/clangsupport/ipcinterface.cpp
diff --git a/src/libs/clangbackendipc/ipcinterface.h b/src/libs/clangsupport/ipcinterface.h
index f58a7e2a5c..25ebeb650f 100644
--- a/src/libs/clangbackendipc/ipcinterface.h
+++ b/src/libs/clangsupport/ipcinterface.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QtGlobal>
diff --git a/src/libs/clangbackendipc/ipcserverinterface.cpp b/src/libs/clangsupport/ipcserverinterface.cpp
index fbc92de52e..fbc92de52e 100644
--- a/src/libs/clangbackendipc/ipcserverinterface.cpp
+++ b/src/libs/clangsupport/ipcserverinterface.cpp
diff --git a/src/libs/clangsupport/ipcserverinterface.h b/src/libs/clangsupport/ipcserverinterface.h
new file mode 100644
index 0000000000..d78176ece0
--- /dev/null
+++ b/src/libs/clangsupport/ipcserverinterface.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "ipcinterface.h"
+
+namespace ClangBackEnd {
+
+class IpcServerInterface : public IpcInterface
+{
+};
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/lineprefixer.cpp b/src/libs/clangsupport/lineprefixer.cpp
index b11f98e7a7..b11f98e7a7 100644
--- a/src/libs/clangbackendipc/lineprefixer.cpp
+++ b/src/libs/clangsupport/lineprefixer.cpp
diff --git a/src/libs/clangbackendipc/lineprefixer.h b/src/libs/clangsupport/lineprefixer.h
index 4e2972319c..de87e4b10d 100644
--- a/src/libs/clangbackendipc/lineprefixer.h
+++ b/src/libs/clangsupport/lineprefixer.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QString>
#include <QTextStream>
diff --git a/src/libs/clangbackendipc/messageenvelop.cpp b/src/libs/clangsupport/messageenvelop.cpp
index 489806a986..58139c4c8f 100644
--- a/src/libs/clangbackendipc/messageenvelop.cpp
+++ b/src/libs/clangsupport/messageenvelop.cpp
@@ -83,12 +83,6 @@ QDebug operator<<(QDebug debug, const MessageEnvelop &messageEnvelop)
case MessageType::ReferencesMessage:
qDebug() << messageEnvelop.message<ReferencesMessage>();
break;
- case MessageType::TranslationUnitDoesNotExistMessage:
- qDebug() << messageEnvelop.message<TranslationUnitDoesNotExistMessage>();
- break;
- case MessageType::ProjectPartsDoNotExistMessage:
- qDebug() << messageEnvelop.message<ProjectPartsDoNotExistMessage>();
- break;
case MessageType::DocumentAnnotationsChangedMessage:
qDebug() << messageEnvelop.message<DocumentAnnotationsChangedMessage>();
break;
diff --git a/src/libs/clangbackendipc/messageenvelop.h b/src/libs/clangsupport/messageenvelop.h
index 592fdcd7f9..b2dd657620 100644
--- a/src/libs/clangbackendipc/messageenvelop.h
+++ b/src/libs/clangsupport/messageenvelop.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QByteArray>
#include <QDataStream>
diff --git a/src/libs/clangbackendipc/pchmanagerclientinterface.cpp b/src/libs/clangsupport/pchmanagerclientinterface.cpp
index b7e40f3f5d..b7e40f3f5d 100644
--- a/src/libs/clangbackendipc/pchmanagerclientinterface.cpp
+++ b/src/libs/clangsupport/pchmanagerclientinterface.cpp
diff --git a/src/libs/clangbackendipc/pchmanagerclientinterface.h b/src/libs/clangsupport/pchmanagerclientinterface.h
index 771951641a..771951641a 100644
--- a/src/libs/clangbackendipc/pchmanagerclientinterface.h
+++ b/src/libs/clangsupport/pchmanagerclientinterface.h
diff --git a/src/libs/clangbackendipc/pchmanagerclientproxy.cpp b/src/libs/clangsupport/pchmanagerclientproxy.cpp
index ad583113bb..ad583113bb 100644
--- a/src/libs/clangbackendipc/pchmanagerclientproxy.cpp
+++ b/src/libs/clangsupport/pchmanagerclientproxy.cpp
diff --git a/src/libs/clangbackendipc/pchmanagerclientproxy.h b/src/libs/clangsupport/pchmanagerclientproxy.h
index 210e5b0125..71361881e9 100644
--- a/src/libs/clangbackendipc/pchmanagerclientproxy.h
+++ b/src/libs/clangsupport/pchmanagerclientproxy.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "pchmanagerclientinterface.h"
#include "readmessageblock.h"
#include "writemessageblock.h"
diff --git a/src/libs/clangbackendipc/pchmanagerserverinterface.cpp b/src/libs/clangsupport/pchmanagerserverinterface.cpp
index 1a6d9d4a25..1a6d9d4a25 100644
--- a/src/libs/clangbackendipc/pchmanagerserverinterface.cpp
+++ b/src/libs/clangsupport/pchmanagerserverinterface.cpp
diff --git a/src/libs/clangsupport/pchmanagerserverinterface.h b/src/libs/clangsupport/pchmanagerserverinterface.h
new file mode 100644
index 0000000000..6af04c91fe
--- /dev/null
+++ b/src/libs/clangsupport/pchmanagerserverinterface.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "projectmanagementserverinterface.h"
+
+#include <memory>
+
+namespace ClangBackEnd {
+
+class PchManagerClientInterface;
+class RemovePchProjectPartsMessage;
+class UpdatePchProjectPartsMessage;
+
+class CMBIPC_EXPORT PchManagerServerInterface : public ProjectManagementServerInterface
+{
+public:
+ void dispatch(const MessageEnvelop &messageEnvelop) override;
+
+ virtual void end() = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/pchmanagerserverproxy.cpp b/src/libs/clangsupport/pchmanagerserverproxy.cpp
index d513fddc87..d513fddc87 100644
--- a/src/libs/clangbackendipc/pchmanagerserverproxy.cpp
+++ b/src/libs/clangsupport/pchmanagerserverproxy.cpp
diff --git a/src/libs/clangbackendipc/pchmanagerserverproxy.h b/src/libs/clangsupport/pchmanagerserverproxy.h
index 0b4e593bc1..6b7c212934 100644
--- a/src/libs/clangbackendipc/pchmanagerserverproxy.h
+++ b/src/libs/clangsupport/pchmanagerserverproxy.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "pchmanagerserverinterface.h"
#include "readmessageblock.h"
#include "writemessageblock.h"
diff --git a/src/libs/clangbackendipc/precompiledheadersupdatedmessage.cpp b/src/libs/clangsupport/precompiledheadersupdatedmessage.cpp
index 38c56be38b..38c56be38b 100644
--- a/src/libs/clangbackendipc/precompiledheadersupdatedmessage.cpp
+++ b/src/libs/clangsupport/precompiledheadersupdatedmessage.cpp
diff --git a/src/libs/clangbackendipc/precompiledheadersupdatedmessage.h b/src/libs/clangsupport/precompiledheadersupdatedmessage.h
index e4fdcda011..e4fdcda011 100644
--- a/src/libs/clangbackendipc/precompiledheadersupdatedmessage.h
+++ b/src/libs/clangsupport/precompiledheadersupdatedmessage.h
diff --git a/src/libs/clangbackendipc/pchmanagerserverinterface.h b/src/libs/clangsupport/projectmanagementserverinterface.h
index a4a8ed683d..5704db417c 100644
--- a/src/libs/clangbackendipc/pchmanagerserverinterface.h
+++ b/src/libs/clangsupport/projectmanagementserverinterface.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -27,21 +27,14 @@
#include "ipcserverinterface.h"
-#include <memory>
-
namespace ClangBackEnd {
-class PchManagerClientInterface;
class RemovePchProjectPartsMessage;
class UpdatePchProjectPartsMessage;
-
-class CMBIPC_EXPORT PchManagerServerInterface : public IpcServerInterface<PchManagerClientInterface>
+class CMBIPC_EXPORT ProjectManagementServerInterface : public IpcInterface
{
public:
- void dispatch(const MessageEnvelop &messageEnvelop) override;
-
- virtual void end() = 0;
virtual void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) = 0;
virtual void removePchProjectParts(RemovePchProjectPartsMessage &&message) = 0;
};
diff --git a/src/libs/clangbackendipc/projectpartcontainer.cpp b/src/libs/clangsupport/projectpartcontainer.cpp
index f39ba741c3..9fc1e8d905 100644
--- a/src/libs/clangbackendipc/projectpartcontainer.cpp
+++ b/src/libs/clangsupport/projectpartcontainer.cpp
@@ -25,7 +25,7 @@
#include "projectpartcontainer.h"
-#include "clangbackendipcdebugutils.h"
+#include "clangsupportdebugutils.h"
#include <QDebug>
diff --git a/src/libs/clangbackendipc/projectpartcontainer.h b/src/libs/clangsupport/projectpartcontainer.h
index 6d5fb147f1..9c735632a5 100644
--- a/src/libs/clangbackendipc/projectpartcontainer.h
+++ b/src/libs/clangsupport/projectpartcontainer.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utf8stringvector.h>
diff --git a/src/libs/clangbackendipc/projectpartcontainerv2.cpp b/src/libs/clangsupport/projectpartcontainerv2.cpp
index 89b489ee5b..89b489ee5b 100644
--- a/src/libs/clangbackendipc/projectpartcontainerv2.cpp
+++ b/src/libs/clangsupport/projectpartcontainerv2.cpp
diff --git a/src/libs/clangbackendipc/projectpartcontainerv2.h b/src/libs/clangsupport/projectpartcontainerv2.h
index a0ad06f3ca..be2102fad3 100644
--- a/src/libs/clangbackendipc/projectpartcontainerv2.h
+++ b/src/libs/clangsupport/projectpartcontainerv2.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utils/smallstringio.h>
diff --git a/src/libs/clangbackendipc/projectpartpch.cpp b/src/libs/clangsupport/projectpartpch.cpp
index 0df291b3df..0df291b3df 100644
--- a/src/libs/clangbackendipc/projectpartpch.cpp
+++ b/src/libs/clangsupport/projectpartpch.cpp
diff --git a/src/libs/clangbackendipc/projectpartpch.h b/src/libs/clangsupport/projectpartpch.h
index 6798f0eafb..5ddbca57a0 100644
--- a/src/libs/clangbackendipc/projectpartpch.h
+++ b/src/libs/clangsupport/projectpartpch.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utils/smallstringio.h>
diff --git a/src/libs/clangbackendipc/readmessageblock.cpp b/src/libs/clangsupport/readmessageblock.cpp
index e566093074..e566093074 100644
--- a/src/libs/clangbackendipc/readmessageblock.cpp
+++ b/src/libs/clangsupport/readmessageblock.cpp
diff --git a/src/libs/clangbackendipc/readmessageblock.h b/src/libs/clangsupport/readmessageblock.h
index 54c06b9fe6..54c06b9fe6 100644
--- a/src/libs/clangbackendipc/readmessageblock.h
+++ b/src/libs/clangsupport/readmessageblock.h
diff --git a/src/libs/clangbackendipc/refactoringclientinterface.cpp b/src/libs/clangsupport/refactoringclientinterface.cpp
index fc69cd0cd5..fc69cd0cd5 100644
--- a/src/libs/clangbackendipc/refactoringclientinterface.cpp
+++ b/src/libs/clangsupport/refactoringclientinterface.cpp
diff --git a/src/libs/clangbackendipc/refactoringclientinterface.h b/src/libs/clangsupport/refactoringclientinterface.h
index 8f10986929..8f10986929 100644
--- a/src/libs/clangbackendipc/refactoringclientinterface.h
+++ b/src/libs/clangsupport/refactoringclientinterface.h
diff --git a/src/libs/clangbackendipc/refactoringclientproxy.cpp b/src/libs/clangsupport/refactoringclientproxy.cpp
index 576489aa25..576489aa25 100644
--- a/src/libs/clangbackendipc/refactoringclientproxy.cpp
+++ b/src/libs/clangsupport/refactoringclientproxy.cpp
diff --git a/src/libs/clangbackendipc/refactoringclientproxy.h b/src/libs/clangsupport/refactoringclientproxy.h
index 2f7c3af980..482fde8b1f 100644
--- a/src/libs/clangbackendipc/refactoringclientproxy.h
+++ b/src/libs/clangsupport/refactoringclientproxy.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "refactoringclientinterface.h"
#include "readmessageblock.h"
#include "writemessageblock.h"
diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h
new file mode 100644
index 0000000000..29f41d621e
--- /dev/null
+++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <createtablesqlstatementbuilder.h>
+
+#include <sqlitetransaction.h>
+#include <sqlitetable.h>
+
+namespace ClangBackEnd {
+
+template<typename DatabaseType>
+class RefactoringDatabaseInitializer
+{
+public:
+ RefactoringDatabaseInitializer(DatabaseType &database)
+ : database(database)
+ {
+ Sqlite::ImmediateTransaction<DatabaseType> transaction{database};
+
+ createSymbolsTable();
+ createLocationsTable();
+ createSourcesTable();
+
+ transaction.commit();
+ }
+
+ void createSymbolsTable()
+ {
+ Sqlite::Table table;
+ table.setUseIfNotExists(true);
+ table.setName("symbols");
+ table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
+ const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
+ table.addColumn("symbolName", Sqlite::ColumnType::Text);
+ table.addIndex({usrColumn});
+
+ table.initialize(database);
+ }
+
+ void createLocationsTable()
+ {
+ Sqlite::Table table;
+ table.setUseIfNotExists(true);
+ table.setName("locations");
+ table.addColumn("symbolId", Sqlite::ColumnType::Integer);
+ table.addColumn("line", Sqlite::ColumnType::Integer);
+ table.addColumn("column", Sqlite::ColumnType::Integer);
+ const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
+ table.addIndex({sourceIdColumn});
+
+ table.initialize(database);
+ }
+
+ void createSourcesTable()
+ {
+ Sqlite::Table table;
+ table.setUseIfNotExists(true);
+ table.setName("sources");
+ table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
+ table.addColumn("sourcePath", Sqlite::ColumnType::Text);
+
+ table.initialize(database);
+ }
+
+public:
+ DatabaseType &database;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/refactoringserverinterface.cpp b/src/libs/clangsupport/refactoringserverinterface.cpp
index d6b0f6815b..52ab7834b0 100644
--- a/src/libs/clangbackendipc/refactoringserverinterface.cpp
+++ b/src/libs/clangsupport/refactoringserverinterface.cpp
@@ -47,6 +47,12 @@ void RefactoringServerInterface::dispatch(const MessageEnvelop &messageEnvelop)
case MessageType::RequestSourceRangesForQueryMessage:
requestSourceRangesForQueryMessage(messageEnvelop.message<RequestSourceRangesForQueryMessage>());
break;
+ case MessageType::UpdatePchProjectPartsMessage:
+ updatePchProjectParts(messageEnvelop.message<UpdatePchProjectPartsMessage>());
+ break;
+ case MessageType::RemovePchProjectPartsMessage:
+ removePchProjectParts(messageEnvelop.message<RemovePchProjectPartsMessage>());
+ break;
case MessageType::CancelMessage:
cancel();
break;
diff --git a/src/libs/clangbackendipc/refactoringserverinterface.h b/src/libs/clangsupport/refactoringserverinterface.h
index c4a8ec6195..a4a3b1e6f4 100644
--- a/src/libs/clangbackendipc/refactoringserverinterface.h
+++ b/src/libs/clangsupport/refactoringserverinterface.h
@@ -25,7 +25,7 @@
#pragma once
-#include "ipcserverinterface.h"
+#include "projectmanagementserverinterface.h"
#include <memory>
@@ -36,8 +36,11 @@ class RequestSourceLocationsForRenamingMessage;
class RequestSourceRangesAndDiagnosticsForQueryMessage;
class RequestSourceRangesForQueryMessage;
class CancelMessage;
+class UpdatePchProjectPartsMessage;
+class RemovePchProjectPartsMessage;
+
+class CMBIPC_EXPORT RefactoringServerInterface : public ProjectManagementServerInterface
-class CMBIPC_EXPORT RefactoringServerInterface : public IpcServerInterface<RefactoringClientInterface>
{
public:
void dispatch(const MessageEnvelop &messageEnvelop) override;
diff --git a/src/libs/clangbackendipc/refactoringserverproxy.cpp b/src/libs/clangsupport/refactoringserverproxy.cpp
index 0cf4473f07..cc6741b118 100644
--- a/src/libs/clangbackendipc/refactoringserverproxy.cpp
+++ b/src/libs/clangsupport/refactoringserverproxy.cpp
@@ -62,6 +62,16 @@ void RefactoringServerProxy::requestSourceRangesForQueryMessage(RequestSourceRan
writeMessageBlock.write(message);
}
+void RefactoringServerProxy::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
+{
+ writeMessageBlock.write(message);
+}
+
+void RefactoringServerProxy::removePchProjectParts(RemovePchProjectPartsMessage &&message)
+{
+ writeMessageBlock.write(message);
+}
+
void RefactoringServerProxy::cancel()
{
writeMessageBlock.write(CancelMessage());
diff --git a/src/libs/clangbackendipc/refactoringserverproxy.h b/src/libs/clangsupport/refactoringserverproxy.h
index 73d165a9a0..611155b511 100644
--- a/src/libs/clangbackendipc/refactoringserverproxy.h
+++ b/src/libs/clangsupport/refactoringserverproxy.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "refactoringserverinterface.h"
#include "readmessageblock.h"
#include "writemessageblock.h"
@@ -53,6 +53,8 @@ public:
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override;
void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override;
+ void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
+ void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
void cancel() override;
void readMessages();
diff --git a/src/libs/clangbackendipc/referencesmessage.cpp b/src/libs/clangsupport/referencesmessage.cpp
index 8b994a7d7c..8b994a7d7c 100644
--- a/src/libs/clangbackendipc/referencesmessage.cpp
+++ b/src/libs/clangsupport/referencesmessage.cpp
diff --git a/src/libs/clangbackendipc/referencesmessage.h b/src/libs/clangsupport/referencesmessage.h
index 5d0b4d292a..5d0b4d292a 100644
--- a/src/libs/clangbackendipc/referencesmessage.h
+++ b/src/libs/clangsupport/referencesmessage.h
diff --git a/src/libs/clangbackendipc/registerunsavedfilesforeditormessage.cpp b/src/libs/clangsupport/registerunsavedfilesforeditormessage.cpp
index 2881382ce8..2881382ce8 100644
--- a/src/libs/clangbackendipc/registerunsavedfilesforeditormessage.cpp
+++ b/src/libs/clangsupport/registerunsavedfilesforeditormessage.cpp
diff --git a/src/libs/clangbackendipc/registerunsavedfilesforeditormessage.h b/src/libs/clangsupport/registerunsavedfilesforeditormessage.h
index 973fe9294f..973fe9294f 100644
--- a/src/libs/clangbackendipc/registerunsavedfilesforeditormessage.h
+++ b/src/libs/clangsupport/registerunsavedfilesforeditormessage.h
diff --git a/src/libs/clangbackendipc/removepchprojectpartsmessage.cpp b/src/libs/clangsupport/removepchprojectpartsmessage.cpp
index 24c657336a..24c657336a 100644
--- a/src/libs/clangbackendipc/removepchprojectpartsmessage.cpp
+++ b/src/libs/clangsupport/removepchprojectpartsmessage.cpp
diff --git a/src/libs/clangbackendipc/removepchprojectpartsmessage.h b/src/libs/clangsupport/removepchprojectpartsmessage.h
index c6ae105dd0..c6ae105dd0 100644
--- a/src/libs/clangbackendipc/removepchprojectpartsmessage.h
+++ b/src/libs/clangsupport/removepchprojectpartsmessage.h
diff --git a/src/libs/clangbackendipc/requestdocumentannotations.cpp b/src/libs/clangsupport/requestdocumentannotations.cpp
index 6d3400ccc3..6d3400ccc3 100644
--- a/src/libs/clangbackendipc/requestdocumentannotations.cpp
+++ b/src/libs/clangsupport/requestdocumentannotations.cpp
diff --git a/src/libs/clangbackendipc/requestdocumentannotations.h b/src/libs/clangsupport/requestdocumentannotations.h
index e8facfef33..e8facfef33 100644
--- a/src/libs/clangbackendipc/requestdocumentannotations.h
+++ b/src/libs/clangsupport/requestdocumentannotations.h
diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.cpp b/src/libs/clangsupport/requestfollowsymbolmessage.cpp
new file mode 100644
index 0000000000..dcb0b5cd2e
--- /dev/null
+++ b/src/libs/clangsupport/requestfollowsymbolmessage.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "requestfollowsymbolmessage.h"
+
+#include <QDebug>
+
+#include <ostream>
+
+namespace ClangBackEnd {
+
+quint64 RequestFollowSymbolMessage::ticketCounter = 0;
+
+QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message)
+{
+ debug.nospace() << "RequestFollowSymbolMessage(";
+
+ debug.nospace() << message.m_fileContainer << ", ";
+ debug.nospace() << message.m_dependentFiles << ", ";
+ debug.nospace() << message.m_ticketNumber << ", ";
+ debug.nospace() << message.m_line << ", ";
+ debug.nospace() << message.m_column << ", ";
+
+ debug.nospace() << ")";
+
+ return debug;
+}
+
+std::ostream &operator<<(std::ostream &os, const RequestFollowSymbolMessage &message)
+{
+ os << "("
+ << message.m_fileContainer << ", "
+ << message.m_dependentFiles << ", "
+ << message.m_ticketNumber << ", "
+ << message.m_line << ", "
+ << message.m_column << ", "
+ << ")";
+
+ return os;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/requestfollowsymbolmessage.h b/src/libs/clangsupport/requestfollowsymbolmessage.h
new file mode 100644
index 0000000000..1305abfba8
--- /dev/null
+++ b/src/libs/clangsupport/requestfollowsymbolmessage.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangsupport_global.h"
+
+#include "filecontainer.h"
+
+#include <QDataStream>
+
+namespace ClangBackEnd {
+
+class RequestFollowSymbolMessage
+{
+public:
+ RequestFollowSymbolMessage() = default;
+ RequestFollowSymbolMessage(const FileContainer &fileContainer,
+ const QVector<Utf8String> &dependentFiles,
+ quint32 line,
+ quint32 column)
+ : m_fileContainer(fileContainer)
+ , m_ticketNumber(++ticketCounter)
+ , m_line(line)
+ , m_column(column)
+ , m_dependentFiles(dependentFiles)
+ {
+ }
+
+ const FileContainer &fileContainer() const
+ {
+ return m_fileContainer;
+ }
+
+ const QVector<Utf8String> &dependentFiles() const
+ {
+ return m_dependentFiles;
+ }
+
+ quint32 line() const
+ {
+ return m_line;
+ }
+
+ quint32 column() const
+ {
+ return m_column;
+ }
+
+ quint64 ticketNumber() const
+ {
+ return m_ticketNumber;
+ }
+
+ friend QDataStream &operator<<(QDataStream &out, const RequestFollowSymbolMessage &message)
+ {
+ out << message.m_fileContainer;
+ out << message.m_dependentFiles;
+ out << message.m_ticketNumber;
+ out << message.m_line;
+ out << message.m_column;
+
+ return out;
+ }
+
+ friend QDataStream &operator>>(QDataStream &in, RequestFollowSymbolMessage &message)
+ {
+ in >> message.m_fileContainer;
+ in >> message.m_dependentFiles;
+ in >> message.m_ticketNumber;
+ in >> message.m_line;
+ in >> message.m_column;
+
+ return in;
+ }
+
+ friend bool operator==(const RequestFollowSymbolMessage &first,
+ const RequestFollowSymbolMessage &second)
+ {
+ return first.m_ticketNumber == second.m_ticketNumber
+ && first.m_line == second.m_line
+ && first.m_column == second.m_column
+ && first.m_fileContainer == second.m_fileContainer
+ && first.m_dependentFiles == second.m_dependentFiles;
+ }
+
+ friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message);
+ friend std::ostream &operator<<(std::ostream &os, const RequestFollowSymbolMessage &message);
+private:
+ FileContainer m_fileContainer;
+ quint64 m_ticketNumber = 0;
+ quint32 m_line = 0;
+ quint32 m_column = 0;
+ QVector<Utf8String> m_dependentFiles;
+ static CMBIPC_EXPORT quint64 ticketCounter;
+};
+
+DECLARE_MESSAGE(RequestFollowSymbolMessage);
+} // namespace ClangBackEnd
diff --git a/src/libs/clangbackendipc/requestreferencesmessage.cpp b/src/libs/clangsupport/requestreferencesmessage.cpp
index 0527db59d6..0527db59d6 100644
--- a/src/libs/clangbackendipc/requestreferencesmessage.cpp
+++ b/src/libs/clangsupport/requestreferencesmessage.cpp
diff --git a/src/libs/clangbackendipc/requestreferencesmessage.h b/src/libs/clangsupport/requestreferencesmessage.h
index 8d76c1c5af..8757799d20 100644
--- a/src/libs/clangbackendipc/requestreferencesmessage.h
+++ b/src/libs/clangsupport/requestreferencesmessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "filecontainer.h"
diff --git a/src/libs/clangbackendipc/requestsourcelocationforrenamingmessage.cpp b/src/libs/clangsupport/requestsourcelocationforrenamingmessage.cpp
index 6d5d8a24a1..6d5d8a24a1 100644
--- a/src/libs/clangbackendipc/requestsourcelocationforrenamingmessage.cpp
+++ b/src/libs/clangsupport/requestsourcelocationforrenamingmessage.cpp
diff --git a/src/libs/clangbackendipc/requestsourcelocationforrenamingmessage.h b/src/libs/clangsupport/requestsourcelocationforrenamingmessage.h
index 8b1f46798c..271202cda3 100644
--- a/src/libs/clangbackendipc/requestsourcelocationforrenamingmessage.h
+++ b/src/libs/clangsupport/requestsourcelocationforrenamingmessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "filepath.h"
#include <utils/smallstringvector.h>
diff --git a/src/libs/clangbackendipc/requestsourcerangesanddiagnosticsforquerymessage.cpp b/src/libs/clangsupport/requestsourcerangesanddiagnosticsforquerymessage.cpp
index 878f11f0de..878f11f0de 100644
--- a/src/libs/clangbackendipc/requestsourcerangesanddiagnosticsforquerymessage.cpp
+++ b/src/libs/clangsupport/requestsourcerangesanddiagnosticsforquerymessage.cpp
diff --git a/src/libs/clangbackendipc/requestsourcerangesanddiagnosticsforquerymessage.h b/src/libs/clangsupport/requestsourcerangesanddiagnosticsforquerymessage.h
index afac9e9b6b..afac9e9b6b 100644
--- a/src/libs/clangbackendipc/requestsourcerangesanddiagnosticsforquerymessage.h
+++ b/src/libs/clangsupport/requestsourcerangesanddiagnosticsforquerymessage.h
diff --git a/src/libs/clangbackendipc/requestsourcerangesforquerymessage.cpp b/src/libs/clangsupport/requestsourcerangesforquerymessage.cpp
index ab5b8d8468..ab5b8d8468 100644
--- a/src/libs/clangbackendipc/requestsourcerangesforquerymessage.cpp
+++ b/src/libs/clangsupport/requestsourcerangesforquerymessage.cpp
diff --git a/src/libs/clangbackendipc/requestsourcerangesforquerymessage.h b/src/libs/clangsupport/requestsourcerangesforquerymessage.h
index 1dc3ca6ac5..1dc3ca6ac5 100644
--- a/src/libs/clangbackendipc/requestsourcerangesforquerymessage.h
+++ b/src/libs/clangsupport/requestsourcerangesforquerymessage.h
diff --git a/src/libs/clangbackendipc/sourcefilepathcontainerbase.cpp b/src/libs/clangsupport/sourcefilepathcontainerbase.cpp
index 66d44d8827..66d44d8827 100644
--- a/src/libs/clangbackendipc/sourcefilepathcontainerbase.cpp
+++ b/src/libs/clangsupport/sourcefilepathcontainerbase.cpp
diff --git a/src/libs/clangbackendipc/sourcefilepathcontainerbase.h b/src/libs/clangsupport/sourcefilepathcontainerbase.h
index ebf717f15e..ebf717f15e 100644
--- a/src/libs/clangbackendipc/sourcefilepathcontainerbase.h
+++ b/src/libs/clangsupport/sourcefilepathcontainerbase.h
diff --git a/src/libs/clangbackendipc/sourcelocationcontainer.cpp b/src/libs/clangsupport/sourcelocationcontainer.cpp
index f4c9648f56..f4c9648f56 100644
--- a/src/libs/clangbackendipc/sourcelocationcontainer.cpp
+++ b/src/libs/clangsupport/sourcelocationcontainer.cpp
diff --git a/src/libs/clangbackendipc/sourcelocationcontainer.h b/src/libs/clangsupport/sourcelocationcontainer.h
index 6514b48469..80971e8ee8 100644
--- a/src/libs/clangbackendipc/sourcelocationcontainer.h
+++ b/src/libs/clangsupport/sourcelocationcontainer.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utf8string.h>
diff --git a/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp b/src/libs/clangsupport/sourcelocationcontainerv2.cpp
index 3206daf2b5..3206daf2b5 100644
--- a/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp
+++ b/src/libs/clangsupport/sourcelocationcontainerv2.cpp
diff --git a/src/libs/clangbackendipc/sourcelocationcontainerv2.h b/src/libs/clangsupport/sourcelocationcontainerv2.h
index db54c7c028..def1c389fa 100644
--- a/src/libs/clangbackendipc/sourcelocationcontainerv2.h
+++ b/src/libs/clangsupport/sourcelocationcontainerv2.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <QDataStream>
diff --git a/src/libs/clangbackendipc/sourcelocationscontainer.cpp b/src/libs/clangsupport/sourcelocationscontainer.cpp
index c5775e6a76..c5775e6a76 100644
--- a/src/libs/clangbackendipc/sourcelocationscontainer.cpp
+++ b/src/libs/clangsupport/sourcelocationscontainer.cpp
diff --git a/src/libs/clangbackendipc/sourcelocationscontainer.h b/src/libs/clangsupport/sourcelocationscontainer.h
index 731ad16906..731ad16906 100644
--- a/src/libs/clangbackendipc/sourcelocationscontainer.h
+++ b/src/libs/clangsupport/sourcelocationscontainer.h
diff --git a/src/libs/clangbackendipc/sourcelocationsforrenamingmessage.cpp b/src/libs/clangsupport/sourcelocationsforrenamingmessage.cpp
index 0ce0b8f7a8..0ce0b8f7a8 100644
--- a/src/libs/clangbackendipc/sourcelocationsforrenamingmessage.cpp
+++ b/src/libs/clangsupport/sourcelocationsforrenamingmessage.cpp
diff --git a/src/libs/clangbackendipc/sourcelocationsforrenamingmessage.h b/src/libs/clangsupport/sourcelocationsforrenamingmessage.h
index 5362ed2e46..5362ed2e46 100644
--- a/src/libs/clangbackendipc/sourcelocationsforrenamingmessage.h
+++ b/src/libs/clangsupport/sourcelocationsforrenamingmessage.h
diff --git a/src/libs/clangbackendipc/sourcerangecontainer.cpp b/src/libs/clangsupport/sourcerangecontainer.cpp
index a2db7545eb..a2db7545eb 100644
--- a/src/libs/clangbackendipc/sourcerangecontainer.cpp
+++ b/src/libs/clangsupport/sourcerangecontainer.cpp
diff --git a/src/libs/clangbackendipc/sourcerangecontainer.h b/src/libs/clangsupport/sourcerangecontainer.h
index ff871cf8ed..ff871cf8ed 100644
--- a/src/libs/clangbackendipc/sourcerangecontainer.h
+++ b/src/libs/clangsupport/sourcerangecontainer.h
diff --git a/src/libs/clangbackendipc/sourcerangecontainerv2.cpp b/src/libs/clangsupport/sourcerangecontainerv2.cpp
index 47907beb8d..47907beb8d 100644
--- a/src/libs/clangbackendipc/sourcerangecontainerv2.cpp
+++ b/src/libs/clangsupport/sourcerangecontainerv2.cpp
diff --git a/src/libs/clangbackendipc/sourcerangecontainerv2.h b/src/libs/clangsupport/sourcerangecontainerv2.h
index a5dba3ddf1..a5dba3ddf1 100644
--- a/src/libs/clangbackendipc/sourcerangecontainerv2.h
+++ b/src/libs/clangsupport/sourcerangecontainerv2.h
diff --git a/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.cpp b/src/libs/clangsupport/sourcerangesanddiagnosticsforquerymessage.cpp
index f4ac78ea43..f4ac78ea43 100644
--- a/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.cpp
+++ b/src/libs/clangsupport/sourcerangesanddiagnosticsforquerymessage.cpp
diff --git a/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.h b/src/libs/clangsupport/sourcerangesanddiagnosticsforquerymessage.h
index f91db432f6..f91db432f6 100644
--- a/src/libs/clangbackendipc/sourcerangesanddiagnosticsforquerymessage.h
+++ b/src/libs/clangsupport/sourcerangesanddiagnosticsforquerymessage.h
diff --git a/src/libs/clangbackendipc/sourcerangescontainer.cpp b/src/libs/clangsupport/sourcerangescontainer.cpp
index ff833be874..ff833be874 100644
--- a/src/libs/clangbackendipc/sourcerangescontainer.cpp
+++ b/src/libs/clangsupport/sourcerangescontainer.cpp
diff --git a/src/libs/clangbackendipc/sourcerangescontainer.h b/src/libs/clangsupport/sourcerangescontainer.h
index 6968830a6d..6968830a6d 100644
--- a/src/libs/clangbackendipc/sourcerangescontainer.h
+++ b/src/libs/clangsupport/sourcerangescontainer.h
diff --git a/src/libs/clangbackendipc/sourcerangesforquerymessage.cpp b/src/libs/clangsupport/sourcerangesforquerymessage.cpp
index e9227b3a66..e9227b3a66 100644
--- a/src/libs/clangbackendipc/sourcerangesforquerymessage.cpp
+++ b/src/libs/clangsupport/sourcerangesforquerymessage.cpp
diff --git a/src/libs/clangbackendipc/sourcerangesforquerymessage.h b/src/libs/clangsupport/sourcerangesforquerymessage.h
index 7aa410e1ae..7aa410e1ae 100644
--- a/src/libs/clangbackendipc/sourcerangesforquerymessage.h
+++ b/src/libs/clangsupport/sourcerangesforquerymessage.h
diff --git a/src/libs/clangbackendipc/sourcerangewithtextcontainer.cpp b/src/libs/clangsupport/sourcerangewithtextcontainer.cpp
index 82f410c896..82f410c896 100644
--- a/src/libs/clangbackendipc/sourcerangewithtextcontainer.cpp
+++ b/src/libs/clangsupport/sourcerangewithtextcontainer.cpp
diff --git a/src/libs/clangbackendipc/sourcerangewithtextcontainer.h b/src/libs/clangsupport/sourcerangewithtextcontainer.h
index 4edb231550..4edb231550 100644
--- a/src/libs/clangbackendipc/sourcerangewithtextcontainer.h
+++ b/src/libs/clangsupport/sourcerangewithtextcontainer.h
diff --git a/src/libs/clangsupport/stringcache.h b/src/libs/clangsupport/stringcache.h
new file mode 100644
index 0000000000..6d5f4e986b
--- /dev/null
+++ b/src/libs/clangsupport/stringcache.h
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "stringcachealgorithms.h"
+#include "stringcachefwd.h"
+
+#include <utils/smallstringview.h>
+#include <utils/smallstringfwd.h>
+
+#include <algorithm>
+#include <mutex>
+#include <vector>
+
+namespace ClangBackEnd {
+
+class StringCacheException : public std::exception
+{
+ const char *what() const noexcept override
+ {
+ return "StringCache entries are in invalid state.";
+ }
+};
+
+class NonLockingMutex
+{
+public:
+ constexpr NonLockingMutex() noexcept {}
+ NonLockingMutex(const NonLockingMutex&) = delete;
+ NonLockingMutex& operator=(const NonLockingMutex&) = delete;
+ void lock() {}
+ void unlock() {}
+};
+
+template <typename StringType, typename IndexType>
+class StringCacheEntry
+{
+public:
+ StringCacheEntry(StringType &&string, IndexType id)
+ : string(std::move(string)),
+ id(id)
+ {}
+
+ operator Utils::SmallStringView() const
+ {
+ return {string.data(), string.size()};
+ }
+
+ StringType string;
+ uint id;
+};
+
+template <typename StringType, typename IndexType>
+using StringCacheEntries = std::vector<StringCacheEntry<StringType, IndexType>>;
+
+using FileCacheCacheEntry = StringCacheEntry<Utils::PathString, FilePathIndex>;
+using FileCacheCacheEntries = std::vector<FileCacheCacheEntry>;
+
+template <typename StringType,
+ typename IndexType,
+ typename Mutex,
+ typename Compare,
+ Compare compare = Utils::compare>
+class StringCache
+{
+ using CacheEntry = StringCacheEntry<StringType, IndexType>;
+ using CacheEnties = StringCacheEntries<StringType, IndexType>;
+ using const_iterator = typename CacheEnties::const_iterator;
+ using Found = ClangBackEnd::Found<const_iterator>;
+public:
+ StringCache()
+ {
+ m_strings.reserve(1024);
+ m_indices.reserve(1024);
+ }
+
+ void populate(CacheEnties &&entries)
+ {
+ uncheckedPopulate(std::move(entries));
+
+ checkEntries();
+ }
+
+ void uncheckedPopulate(CacheEnties &&entries)
+ {
+ std::sort(entries.begin(),
+ entries.end(),
+ [] (Utils::SmallStringView first, Utils::SmallStringView second) {
+ return compare(first, second) < 0;
+ });
+
+ m_strings = std::move(entries);
+ m_indices.resize(m_strings.size());
+
+ auto begin = m_strings.cbegin();
+ for (auto current = begin; current != m_strings.end(); ++current)
+ m_indices.at(current->id) = std::distance(begin, current);
+ }
+
+
+ IndexType stringId(Utils::SmallStringView stringView)
+ {
+ std::lock_guard<Mutex> lock(m_mutex);
+
+ return ungardedStringId(stringView);
+ }
+
+ template <typename Container>
+ std::vector<IndexType> stringIds(const Container &strings)
+ {
+ std::lock_guard<Mutex> lock(m_mutex);
+
+ std::vector<IndexType> ids;
+ ids.reserve(strings.size());
+
+ std::transform(strings.begin(),
+ strings.end(),
+ std::back_inserter(ids),
+ [&] (const auto &string) { return this->ungardedStringId(string); });
+
+ return ids;
+ }
+
+ std::vector<IndexType> stringIds(std::initializer_list<StringType> strings)
+ {
+ return stringIds<std::initializer_list<StringType>>(strings);
+ }
+
+ Utils::SmallStringView string(IndexType id) const
+ {
+ std::lock_guard<Mutex> lock(m_mutex);
+
+ return m_strings.at(m_indices.at(id)).string;
+ }
+
+ std::vector<StringType> strings(const std::vector<IndexType> &ids) const
+ {
+ std::lock_guard<Mutex> lock(m_mutex);
+
+ std::vector<StringType> strings;
+ strings.reserve(ids.size());
+
+ std::transform(ids.begin(),
+ ids.end(),
+ std::back_inserter(strings),
+ [&] (IndexType id) { return m_strings.at(m_indices.at(id)).string; });
+
+ return strings;
+ }
+
+ bool isEmpty() const
+ {
+ return m_strings.empty() && m_indices.empty();
+ }
+
+private:
+ IndexType ungardedStringId(Utils::SmallStringView stringView)
+ {
+ Found found = find(stringView);
+
+ if (!found.wasFound)
+ return insertString(found.iterator, stringView);
+
+ return found.iterator->id;
+ }
+
+ Found find(Utils::SmallStringView stringView)
+ {
+ return findInSorted(m_strings.cbegin(), m_strings.cend(), stringView, compare);
+ }
+
+ void incrementLargerOrEqualIndicesByOne(IndexType newIndex)
+ {
+ std::transform(m_indices.begin(),
+ m_indices.end(),
+ m_indices.begin(),
+ [&] (IndexType index) {
+ return index >= newIndex ? ++index : index;
+ });
+ }
+
+ IndexType insertString(const_iterator beforeIterator,
+ Utils::SmallStringView stringView)
+ {
+ auto id = IndexType(m_indices.size());
+
+ auto inserted = m_strings.emplace(beforeIterator, StringType(stringView), id);
+
+ auto newIndex = IndexType(std::distance(m_strings.begin(), inserted));
+
+ incrementLargerOrEqualIndicesByOne(newIndex);
+
+ m_indices.push_back(newIndex);
+
+ return id;
+ }
+
+ void checkEntries()
+ {
+ for (const auto &entry : m_strings) {
+ if (entry.string != string(entry.id) || entry.id != stringId(entry.string))
+ throw StringCacheException();
+ }
+ }
+
+private:
+ CacheEnties m_strings;
+ std::vector<IndexType> m_indices;
+ mutable Mutex m_mutex;
+};
+
+using FilePathIndices = std::vector<FilePathIndex>;
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/stringcachealgorithms.h b/src/libs/clangsupport/stringcachealgorithms.h
new file mode 100644
index 0000000000..573a692b72
--- /dev/null
+++ b/src/libs/clangsupport/stringcachealgorithms.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/smallstringio.h>
+
+#include <iterator>
+
+#include <QDebug>
+
+namespace ClangBackEnd {
+
+template <typename Iterator>
+class Found
+{
+public:
+ Iterator iterator;
+ bool wasFound;
+};
+
+template<typename ForwardIterator,
+ typename Type,
+ typename Compare>
+Found<ForwardIterator> findInSorted(ForwardIterator first, ForwardIterator last, const Type& value, Compare compare)
+{
+ ForwardIterator current;
+ using DifferenceType = typename std::iterator_traits<ForwardIterator>::difference_type;
+ DifferenceType count{std::distance(first, last)};
+ DifferenceType step;
+
+ while (count > 0) {
+ current = first;
+ step = count / 2;
+ std::advance(current, step);
+ auto comparison = compare(*current, value);
+ if (comparison < 0) {
+ first = ++current;
+ count -= step + 1;
+ } else if (comparison > 0) {
+ count = step;
+ } else {
+ return {current, true};
+ }
+ }
+
+ return {first, false};
+}
+
+} // namespace ClangBackEnd
diff --git a/src/libs/clangsupport/stringcachefwd.h b/src/libs/clangsupport/stringcachefwd.h
new file mode 100644
index 0000000000..66448411e1
--- /dev/null
+++ b/src/libs/clangsupport/stringcachefwd.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/smallstringfwd.h>
+
+namespace ClangBackEnd {
+
+using FilePathIndex = long long int;
+
+class NonLockingMutex;
+
+template <typename StringType,
+ typename IndexType,
+ typename Mutex,
+ typename Compare,
+ Compare compare>
+class StringCache;
+
+template <typename Mutex = NonLockingMutex>
+using FilePathCache = StringCache<Utils::PathString,
+ FilePathIndex,
+ Mutex,
+ decltype(&Utils::reverseCompare),
+ Utils::reverseCompare>;
+
+} // namespace ClangBackEnd
+
diff --git a/src/libs/clangbackendipc/unregisterunsavedfilesforeditormessage.cpp b/src/libs/clangsupport/unregisterunsavedfilesforeditormessage.cpp
index 7cd1403909..7cd1403909 100644
--- a/src/libs/clangbackendipc/unregisterunsavedfilesforeditormessage.cpp
+++ b/src/libs/clangsupport/unregisterunsavedfilesforeditormessage.cpp
diff --git a/src/libs/clangbackendipc/unregisterunsavedfilesforeditormessage.h b/src/libs/clangsupport/unregisterunsavedfilesforeditormessage.h
index cc43e18872..cc43e18872 100644
--- a/src/libs/clangbackendipc/unregisterunsavedfilesforeditormessage.h
+++ b/src/libs/clangsupport/unregisterunsavedfilesforeditormessage.h
diff --git a/src/libs/clangbackendipc/updatepchprojectpartsmessage.cpp b/src/libs/clangsupport/updatepchprojectpartsmessage.cpp
index f86ef12aac..f86ef12aac 100644
--- a/src/libs/clangbackendipc/updatepchprojectpartsmessage.cpp
+++ b/src/libs/clangsupport/updatepchprojectpartsmessage.cpp
diff --git a/src/libs/clangbackendipc/updatepchprojectpartsmessage.h b/src/libs/clangsupport/updatepchprojectpartsmessage.h
index 67301faf44..67301faf44 100644
--- a/src/libs/clangbackendipc/updatepchprojectpartsmessage.h
+++ b/src/libs/clangsupport/updatepchprojectpartsmessage.h
diff --git a/src/libs/clangbackendipc/updatetranslationunitsforeditormessage.cpp b/src/libs/clangsupport/updatetranslationunitsforeditormessage.cpp
index 0dc0d861a7..0dc0d861a7 100644
--- a/src/libs/clangbackendipc/updatetranslationunitsforeditormessage.cpp
+++ b/src/libs/clangsupport/updatetranslationunitsforeditormessage.cpp
diff --git a/src/libs/clangbackendipc/updatetranslationunitsforeditormessage.h b/src/libs/clangsupport/updatetranslationunitsforeditormessage.h
index 3838ea89ae..3838ea89ae 100644
--- a/src/libs/clangbackendipc/updatetranslationunitsforeditormessage.h
+++ b/src/libs/clangsupport/updatetranslationunitsforeditormessage.h
diff --git a/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.cpp b/src/libs/clangsupport/updatevisibletranslationunitsmessage.cpp
index 00f154f4c8..00f154f4c8 100644
--- a/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.cpp
+++ b/src/libs/clangsupport/updatevisibletranslationunitsmessage.cpp
diff --git a/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.h b/src/libs/clangsupport/updatevisibletranslationunitsmessage.h
index 033d3a98a1..cdd57fe2f1 100644
--- a/src/libs/clangbackendipc/updatevisibletranslationunitsmessage.h
+++ b/src/libs/clangsupport/updatevisibletranslationunitsmessage.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include <utf8stringvector.h>
diff --git a/src/libs/clangbackendipc/writemessageblock.cpp b/src/libs/clangsupport/writemessageblock.cpp
index f891f83c29..f891f83c29 100644
--- a/src/libs/clangbackendipc/writemessageblock.cpp
+++ b/src/libs/clangsupport/writemessageblock.cpp
diff --git a/src/libs/clangbackendipc/writemessageblock.h b/src/libs/clangsupport/writemessageblock.h
index edf1d74a1c..edf1d74a1c 100644
--- a/src/libs/clangbackendipc/writemessageblock.h
+++ b/src/libs/clangsupport/writemessageblock.h
diff --git a/src/libs/extensionsystem/pluginerroroverview.ui b/src/libs/extensionsystem/pluginerroroverview.ui
index 768b2f6573..e87cb34c63 100644
--- a/src/libs/extensionsystem/pluginerroroverview.ui
+++ b/src/libs/extensionsystem/pluginerroroverview.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>Qt Creator - Plugin loader messages</string>
+ <string>Plugin loader messages</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp
index 5bd975ceac..fd554be585 100644
--- a/src/libs/extensionsystem/pluginmanager.cpp
+++ b/src/libs/extensionsystem/pluginmanager.cpp
@@ -47,6 +47,7 @@
#include <QSysInfo>
#include <utils/algorithm.h>
+#include <utils/benchmarker.h>
#include <utils/executeondestruction.h>
#include <utils/hostosinfo.h>
#include <utils/mimetypes/mimedatabase.h>
@@ -1322,11 +1323,11 @@ bool PluginManagerPrivate::loadQueue(PluginSpec *spec, QList<PluginSpec *> &queu
spec->d->errorString += QLatin1Char('\n');
int index = circularityCheckQueue.indexOf(spec);
for (int i = index; i < circularityCheckQueue.size(); ++i) {
- spec->d->errorString.append(PluginManager::tr("%1(%2) depends on")
+ spec->d->errorString.append(PluginManager::tr("%1 (%2) depends on")
.arg(circularityCheckQueue.at(i)->name()).arg(circularityCheckQueue.at(i)->version()));
spec->d->errorString += QLatin1Char('\n');
}
- spec->d->errorString.append(PluginManager::tr("%1(%2)").arg(spec->name()).arg(spec->version()));
+ spec->d->errorString.append(PluginManager::tr("%1 (%2)").arg(spec->name()).arg(spec->version()));
return false;
}
circularityCheckQueue.append(spec);
@@ -1348,7 +1349,7 @@ bool PluginManagerPrivate::loadQueue(PluginSpec *spec, QList<PluginSpec *> &queu
if (!loadQueue(depSpec, queue, circularityCheckQueue)) {
spec->d->hasError = true;
spec->d->errorString =
- PluginManager::tr("Cannot load plugin because dependency failed to load: %1(%2)\nReason: %3")
+ PluginManager::tr("Cannot load plugin because dependency failed to load: %1 (%2)\nReason: %3")
.arg(depSpec->name()).arg(depSpec->version()).arg(depSpec->errorString());
return false;
}
@@ -1559,6 +1560,13 @@ void PluginManagerPrivate::profilingReport(const char *what, const PluginSpec *s
qDebug("%-22s %-22s %8dms (%8dms)", what, qPrintable(spec->name()), absoluteElapsedMS, elapsedMS);
else
qDebug("%-45s %8dms (%8dms)", what, absoluteElapsedMS, elapsedMS);
+ if (what && *what == '<') {
+ QString tc;
+ if (spec)
+ tc = spec->name() + '_';
+ tc += QString::fromUtf8(QByteArray(what + 1));
+ Utils::Benchmarker::report("loadPlugins", tc, elapsedMS);
+ }
}
}
@@ -1579,6 +1587,7 @@ void PluginManagerPrivate::profilingSummary() const
qDebug("%-22s %8dms ( %5.2f%% )", qPrintable(it.value()->name()),
it.key(), 100.0 * it.key() / total);
qDebug("Total: %8dms", total);
+ Utils::Benchmarker::report("loadPlugins", "Total", total);
}
}
diff --git a/src/libs/extensionsystem/pluginview.cpp b/src/libs/extensionsystem/pluginview.cpp
index 042e666c6a..96052579ee 100644
--- a/src/libs/extensionsystem/pluginview.cpp
+++ b/src/libs/extensionsystem/pluginview.cpp
@@ -33,7 +33,6 @@
#include <utils/utilsicons.h>
#include <utils/itemviews.h>
#include <utils/qtcassert.h>
-#include <utils/treemodel.h>
#include <QDebug>
#include <QDir>
@@ -42,7 +41,6 @@
#include <QItemSelectionModel>
#include <QMessageBox>
#include <QSet>
-#include <QSortFilterProxyModel>
/*!
\class ExtensionSystem::PluginView
@@ -86,7 +84,6 @@ static const int HiddenByDefaultRole = Qt::UserRole + 2;
static const QIcon &icon(IconIndex icon)
{
- using namespace Utils;
switch (icon) {
case OkIcon: {
static const QIcon ok = Utils::Icons::OK.icon();
diff --git a/src/libs/extensionsystem/pluginview.h b/src/libs/extensionsystem/pluginview.h
index 44ca2e2b12..33c48ba0b9 100644
--- a/src/libs/extensionsystem/pluginview.h
+++ b/src/libs/extensionsystem/pluginview.h
@@ -30,18 +30,11 @@
#include <utils/treemodel.h>
#include <QWidget>
-#include <QSet>
-#include <QHash>
-
-QT_BEGIN_NAMESPACE
-class QSortFilterProxyModel;
-QT_END_NAMESPACE
namespace Utils { class TreeView; }
namespace ExtensionSystem {
-class PluginManager;
class PluginSpec;
namespace Internal {
diff --git a/src/libs/flamegraph/flamegraph.h b/src/libs/flamegraph/flamegraph.h
index 5fe7f88ca0..9a25a6bb10 100644
--- a/src/libs/flamegraph/flamegraph.h
+++ b/src/libs/flamegraph/flamegraph.h
@@ -85,10 +85,9 @@ signals:
void depthChanged(int depth);
void maximumDepthChanged();
-private slots:
+private:
void rebuild();
-private:
QQmlComponent *m_delegate = nullptr;
QAbstractItemModel *m_model = nullptr;
int m_sizeRole = 0;
diff --git a/src/libs/libs.pro b/src/libs/libs.pro
index 178a7a4cb8..669dc0183a 100644
--- a/src/libs/libs.pro
+++ b/src/libs/libs.pro
@@ -15,7 +15,7 @@ SUBDIRS = \
glsl \
ssh \
sqlite \
- clangbackendipc
+ clangsupport
qtHaveModule(quick) {
SUBDIRS += \
diff --git a/src/libs/libs.qbs b/src/libs/libs.qbs
index 29eb744c1a..4eedda662c 100644
--- a/src/libs/libs.qbs
+++ b/src/libs/libs.qbs
@@ -4,7 +4,7 @@ Project {
name: "Libs"
references: [
"aggregation/aggregation.qbs",
- "clangbackendipc/clangbackendipc.qbs",
+ "clangsupport/clangsupport.qbs",
"cplusplus/cplusplus.qbs",
"extensionsystem/extensionsystem.qbs",
"flamegraph/flamegraph.qbs",
diff --git a/src/libs/modelinglib/modelinglib.qbs b/src/libs/modelinglib/modelinglib.qbs
index ab79fcc112..b9ee382bbd 100644
--- a/src/libs/modelinglib/modelinglib.qbs
+++ b/src/libs/modelinglib/modelinglib.qbs
@@ -55,6 +55,8 @@ QtcLibrary {
"diagram/dclass.h",
"diagram/dcomponent.cpp",
"diagram/dcomponent.h",
+ "diagram/dconnection.cpp",
+ "diagram/dconnection.h",
"diagram/dconstvisitor.h",
"diagram/ddependency.cpp",
"diagram/ddependency.h",
@@ -72,6 +74,8 @@ QtcLibrary {
"diagram/dpackage.h",
"diagram/drelation.cpp",
"diagram/drelation.h",
+ "diagram/dswimlane.cpp",
+ "diagram/dswimlane.h",
"diagram/dvisitor.h",
"diagram_controller/dclonevisitor.cpp",
"diagram_controller/dclonevisitor.h",
@@ -114,6 +118,8 @@ QtcLibrary {
"diagram_scene/items/classitem.h",
"diagram_scene/items/componentitem.cpp",
"diagram_scene/items/componentitem.h",
+ "diagram_scene/items/connectionitem.cpp",
+ "diagram_scene/items/connectionitem.h",
"diagram_scene/items/diagramitem.cpp",
"diagram_scene/items/diagramitem.h",
"diagram_scene/items/itemitem.cpp",
@@ -126,6 +132,8 @@ QtcLibrary {
"diagram_scene/items/relationitem.h",
"diagram_scene/items/stereotypedisplayvisitor.cpp",
"diagram_scene/items/stereotypedisplayvisitor.h",
+ "diagram_scene/items/swimlaneitem.cpp",
+ "diagram_scene/items/swimlaneitem.h",
"diagram_scene/latchcontroller.cpp",
"diagram_scene/latchcontroller.h",
"diagram_scene/parts/alignbuttonsitem.cpp",
@@ -188,6 +196,8 @@ QtcLibrary {
"model/mclassmember.h",
"model/mcomponent.cpp",
"model/mcomponent.h",
+ "model/mconnection.cpp",
+ "model/mconnection.h",
"model/mconstvisitor.h",
"model/mdependency.cpp",
"model/mdependency.h",
@@ -252,6 +262,8 @@ QtcLibrary {
"serializer/modelserializer.h",
"serializer/projectserializer.cpp",
"serializer/projectserializer.h",
+ "stereotype/customrelation.cpp",
+ "stereotype/customrelation.h",
"stereotype/iconshape.cpp",
"stereotype/iconshape.h",
"stereotype/shape.h",
diff --git a/src/libs/modelinglib/qmt/config/configcontroller.cpp b/src/libs/modelinglib/qmt/config/configcontroller.cpp
index cb31845e2c..c7b9a78355 100644
--- a/src/libs/modelinglib/qmt/config/configcontroller.cpp
+++ b/src/libs/modelinglib/qmt/config/configcontroller.cpp
@@ -42,7 +42,7 @@ namespace qmt {
class ConfigController::ConfigControllerPrivate
{
public:
- StereotypeController *m_stereotypeController = 0;
+ StereotypeController *m_stereotypeController = nullptr;
};
ConfigController::ConfigController(QObject *parent)
@@ -71,6 +71,8 @@ void ConfigController::readStereotypeDefinitions(const QString &path)
StereotypeDefinitionParser parser;
connect(&parser, &StereotypeDefinitionParser::iconParsed,
this, &ConfigController::onStereotypeIconParsed);
+ connect(&parser, &StereotypeDefinitionParser::relationParsed,
+ this, &ConfigController::onRelationParsed);
connect(&parser, &StereotypeDefinitionParser::toolbarParsed,
this, &ConfigController::onToolbarParsed);
@@ -116,6 +118,11 @@ void ConfigController::onStereotypeIconParsed(const StereotypeIcon &stereotypeIc
d->m_stereotypeController->addStereotypeIcon(stereotypeIcon);
}
+void ConfigController::onRelationParsed(const CustomRelation &customRelation)
+{
+ d->m_stereotypeController->addCustomRelation(customRelation);
+}
+
void ConfigController::onToolbarParsed(const Toolbar &toolbar)
{
d->m_stereotypeController->addToolbar(toolbar);
diff --git a/src/libs/modelinglib/qmt/config/configcontroller.h b/src/libs/modelinglib/qmt/config/configcontroller.h
index 34135bb4af..c14202b8c1 100644
--- a/src/libs/modelinglib/qmt/config/configcontroller.h
+++ b/src/libs/modelinglib/qmt/config/configcontroller.h
@@ -30,6 +30,7 @@
namespace qmt {
+class CustomRelation;
class StereotypeController;
class StereotypeIcon;
class Toolbar;
@@ -40,7 +41,7 @@ class QMT_EXPORT ConfigController : public QObject
class ConfigControllerPrivate;
public:
- explicit ConfigController(QObject *parent = 0);
+ explicit ConfigController(QObject *parent = nullptr);
~ConfigController() override;
void setStereotypeController(StereotypeController *stereotypeController);
@@ -49,6 +50,7 @@ public:
private:
void onStereotypeIconParsed(const StereotypeIcon &stereotypeIcon);
+ void onRelationParsed(const CustomRelation &customRelation);
void onToolbarParsed(const Toolbar &toolbar);
ConfigControllerPrivate *d;
diff --git a/src/libs/modelinglib/qmt/config/sourcepos.cpp b/src/libs/modelinglib/qmt/config/sourcepos.cpp
index eeab8c890d..e58b2b32d7 100644
--- a/src/libs/modelinglib/qmt/config/sourcepos.cpp
+++ b/src/libs/modelinglib/qmt/config/sourcepos.cpp
@@ -28,9 +28,6 @@
namespace qmt {
SourcePos::SourcePos()
- : m_sourceId(-1),
- m_lineNumber(-1),
- m_columnNumber(-1)
{
}
diff --git a/src/libs/modelinglib/qmt/config/sourcepos.h b/src/libs/modelinglib/qmt/config/sourcepos.h
index 2d86eca92d..cb9b3423c5 100644
--- a/src/libs/modelinglib/qmt/config/sourcepos.h
+++ b/src/libs/modelinglib/qmt/config/sourcepos.h
@@ -42,9 +42,9 @@ public:
int columnNumber() const { return m_columnNumber; }
private:
- int m_sourceId;
- int m_lineNumber;
- int m_columnNumber;
+ int m_sourceId = -1;
+ int m_lineNumber = -1;
+ int m_columnNumber = -1;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp
index e9ea4e90c5..8c28e63838 100644
--- a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp
+++ b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp
@@ -30,12 +30,13 @@
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/stereotype/stereotypeicon.h"
#include "qmt/stereotype/shapevalue.h"
+#include "qmt/stereotype/customrelation.h"
#include "qmt/stereotype/toolbar.h"
#include <QHash>
#include <QSet>
#include <QPair>
-#include <QDebug>
+#include <QVariant>
namespace qmt {
@@ -89,6 +90,40 @@ static const int KEYWORD_TOOL = 73;
static const int KEYWORD_ELEMENT = 74;
static const int KEYWORD_SEPARATOR = 75;
+// Relation Definition
+static const int KEYWORD_RELATION = 100;
+static const int KEYWORD_DEPENDENCY = 101;
+static const int KEYWORD_INHERITANCE = 102;
+static const int KEYWORD_ASSOCIATION = 103;
+static const int KEYWORD_NAME = 104;
+static const int KEYWORD_DIRECTION = 105;
+static const int KEYWORD_ATOB = 106;
+static const int KEYWORD_BTOA = 107;
+static const int KEYWORD_BI = 108;
+static const int KEYWORD_END = 109;
+static const int KEYWORD_A = 110;
+static const int KEYWORD_B = 111;
+static const int KEYWORD_ROLE = 112;
+static const int KEYWORD_CARDINALITY = 113;
+static const int KEYWORD_NAVIGABLE = 114;
+static const int KEYWORD_RELATIONSHIP = 115;
+static const int KEYWORD_AGGREGATION = 116;
+static const int KEYWORD_COMPOSITION = 117;
+static const int KEYWORD_SHAFT = 118;
+static const int KEYWORD_HEAD = 119;
+
+// Relation Shapes
+static const int KEYWORD_DIAMOND = 130;
+static const int KEYWORD_TRIANGLE = 131;
+static const int KEYWORD_FILLED = 132;
+static const int KEYWORD_PATTERN = 133;
+static const int KEYWORD_SOLID = 134;
+static const int KEYWORD_DOT = 135;
+static const int KEYWORD_DASH = 136;
+static const int KEYWORD_DASHDOT = 137;
+static const int KEYWORD_DASHDOTDOT = 138;
+static const int KEYWORD_COLOR = 139;
+
// Operatoren
static const int OPERATOR_SEMICOLON = 1;
static const int OPERATOR_BRACE_OPEN = 2;
@@ -117,25 +152,68 @@ StereotypeDefinitionParserError::~StereotypeDefinitionParserError()
class StereotypeDefinitionParser::StereotypeDefinitionParserPrivate
{
public:
- TextScanner *m_scanner = 0;
+ TextScanner *m_scanner = nullptr;
};
class StereotypeDefinitionParser::IconCommandParameter
{
public:
+ enum Type {
+ ShapeValue,
+ Boolean
+ };
+
IconCommandParameter() = default;
IconCommandParameter(int keyword, ShapeValueF::Unit unit, ShapeValueF::Origin origin = ShapeValueF::OriginSmart)
: m_keyword(keyword),
+ m_type(ShapeValue),
m_unit(unit),
m_origin(origin)
{
}
+ IconCommandParameter(int keyword, Type type)
+ : m_keyword(keyword),
+ m_type(type)
+ {
+ }
+
+ operator ShapeValueF() const { return m_shapeValue; }
+
+ Type type() const { return m_type; }
+ ShapeValueF::Unit unit() const { return m_unit; }
+ ShapeValueF::Origin origin() const { return m_origin; }
+ ShapeValueF shapeValue() const { return m_shapeValue; }
+ void setShapeValue(const ShapeValueF &shapeValue) { m_shapeValue = shapeValue; }
+ bool boolean() const { return m_boolean; }
+ void setBoolean(bool boolean) { m_boolean = boolean; }
+
+private:
int m_keyword = -1;
- ShapeValueF::Unit m_unit;
- ShapeValueF::Origin m_origin;
+ Type m_type = ShapeValue;
+ ShapeValueF::Unit m_unit = ShapeValueF::UnitAbsolute;
+ ShapeValueF::Origin m_origin = ShapeValueF::OriginSmart;
+ ShapeValueF m_shapeValue;
+ bool m_boolean = false;
+};
+
+class StereotypeDefinitionParser::Value
+{
+public:
+ Value(StereotypeDefinitionParser::Type type, QVariant value)
+ : m_type(type),
+ m_value(value)
+ {
+ }
+
+ StereotypeDefinitionParser::Type type() const { return m_type; }
+ QVariant value() const { return m_value; }
+
+private:
+ StereotypeDefinitionParser::Type m_type = StereotypeDefinitionParser::Void;
+ QVariant m_value;
};
StereotypeDefinitionParser::StereotypeDefinitionParser(QObject *parent)
@@ -154,58 +232,88 @@ void StereotypeDefinitionParser::parse(ITextSource *source)
TextScanner textScanner;
textScanner.setKeywords(
QList<QPair<QString, int> >()
- << qMakePair(QString(QStringLiteral("icon")), KEYWORD_ICON)
- << qMakePair(QString(QStringLiteral("id")), KEYWORD_ID)
- << qMakePair(QString(QStringLiteral("title")), KEYWORD_TITLE)
- << qMakePair(QString(QStringLiteral("elements")), KEYWORD_ELEMENTS)
- << qMakePair(QString(QStringLiteral("stereotype")), KEYWORD_STEREOTYPE)
- << qMakePair(QString(QStringLiteral("width")), KEYWORD_WIDTH)
- << qMakePair(QString(QStringLiteral("height")), KEYWORD_HEIGHT)
- << qMakePair(QString(QStringLiteral("minwidth")), KEYWORD_MINWIDTH)
- << qMakePair(QString(QStringLiteral("minheight")), KEYWORD_MINHEIGHT)
- << qMakePair(QString(QStringLiteral("locksize")), KEYWORD_LOCK_SIZE)
- << qMakePair(QString(QStringLiteral("display")), KEYWORD_DISPLAY)
- << qMakePair(QString(QStringLiteral("textalignment")), KEYWORD_TEXTALIGN)
- << qMakePair(QString(QStringLiteral("basecolor")), KEYWORD_BASECOLOR)
- << qMakePair(QString(QStringLiteral("shape")), KEYWORD_SHAPE)
- << qMakePair(QString(QStringLiteral("circle")), KEYWORD_CIRCLE)
- << qMakePair(QString(QStringLiteral("ellipse")), KEYWORD_ELLIPSE)
- << qMakePair(QString(QStringLiteral("line")), KEYWORD_LINE)
- << qMakePair(QString(QStringLiteral("rect")), KEYWORD_RECT)
- << qMakePair(QString(QStringLiteral("roundedrect")), KEYWORD_ROUNDEDRECT)
- << qMakePair(QString(QStringLiteral("arc")), KEYWORD_ARC)
- << qMakePair(QString(QStringLiteral("moveto")), KEYWORD_MOVETO)
- << qMakePair(QString(QStringLiteral("lineto")), KEYWORD_LINETO)
- << qMakePair(QString(QStringLiteral("arcmoveto")), KEYWORD_ARCMOVETO)
- << qMakePair(QString(QStringLiteral("arcto")), KEYWORD_ARCTO)
- << qMakePair(QString(QStringLiteral("close")), KEYWORD_CLOSE)
- << qMakePair(QString(QStringLiteral("x")), KEYWORD_X)
- << qMakePair(QString(QStringLiteral("y")), KEYWORD_Y)
- << qMakePair(QString(QStringLiteral("x0")), KEYWORD_X0)
- << qMakePair(QString(QStringLiteral("y0")), KEYWORD_Y0)
- << qMakePair(QString(QStringLiteral("x1")), KEYWORD_X1)
- << qMakePair(QString(QStringLiteral("y1")), KEYWORD_Y1)
- << qMakePair(QString(QStringLiteral("radius")), KEYWORD_RADIUS)
- << qMakePair(QString(QStringLiteral("radiusx")), KEYWORD_RADIUS_X)
- << qMakePair(QString(QStringLiteral("radiusy")), KEYWORD_RADIUS_Y)
- << qMakePair(QString(QStringLiteral("start")), KEYWORD_START)
- << qMakePair(QString(QStringLiteral("span")), KEYWORD_SPAN)
- << qMakePair(QString(QStringLiteral("toolbar")), KEYWORD_TOOLBAR)
- << qMakePair(QString(QStringLiteral("priority")), KEYWORD_PRIORITY)
- << qMakePair(QString(QStringLiteral("tools")), KEYWORD_TOOLS)
- << qMakePair(QString(QStringLiteral("tool")), KEYWORD_TOOL)
- << qMakePair(QString(QStringLiteral("element")), KEYWORD_ELEMENT)
- << qMakePair(QString(QStringLiteral("separator")), KEYWORD_SEPARATOR)
+ << qMakePair(QString("icon"), KEYWORD_ICON)
+ << qMakePair(QString("id"), KEYWORD_ID)
+ << qMakePair(QString("title"), KEYWORD_TITLE)
+ << qMakePair(QString("elements"), KEYWORD_ELEMENTS)
+ << qMakePair(QString("stereotype"), KEYWORD_STEREOTYPE)
+ << qMakePair(QString("width"), KEYWORD_WIDTH)
+ << qMakePair(QString("height"), KEYWORD_HEIGHT)
+ << qMakePair(QString("minwidth"), KEYWORD_MINWIDTH)
+ << qMakePair(QString("minheight"), KEYWORD_MINHEIGHT)
+ << qMakePair(QString("locksize"), KEYWORD_LOCK_SIZE)
+ << qMakePair(QString("display"), KEYWORD_DISPLAY)
+ << qMakePair(QString("textalignment"), KEYWORD_TEXTALIGN)
+ << qMakePair(QString("basecolor"), KEYWORD_BASECOLOR)
+ << qMakePair(QString("shape"), KEYWORD_SHAPE)
+ << qMakePair(QString("circle"), KEYWORD_CIRCLE)
+ << qMakePair(QString("ellipse"), KEYWORD_ELLIPSE)
+ << qMakePair(QString("line"), KEYWORD_LINE)
+ << qMakePair(QString("rect"), KEYWORD_RECT)
+ << qMakePair(QString("roundedrect"), KEYWORD_ROUNDEDRECT)
+ << qMakePair(QString("arc"), KEYWORD_ARC)
+ << qMakePair(QString("moveto"), KEYWORD_MOVETO)
+ << qMakePair(QString("lineto"), KEYWORD_LINETO)
+ << qMakePair(QString("arcmoveto"), KEYWORD_ARCMOVETO)
+ << qMakePair(QString("arcto"), KEYWORD_ARCTO)
+ << qMakePair(QString("close"), KEYWORD_CLOSE)
+ << qMakePair(QString("x"), KEYWORD_X)
+ << qMakePair(QString("y"), KEYWORD_Y)
+ << qMakePair(QString("x0"), KEYWORD_X0)
+ << qMakePair(QString("y0"), KEYWORD_Y0)
+ << qMakePair(QString("x1"), KEYWORD_X1)
+ << qMakePair(QString("y1"), KEYWORD_Y1)
+ << qMakePair(QString("radius"), KEYWORD_RADIUS)
+ << qMakePair(QString("radiusx"), KEYWORD_RADIUS_X)
+ << qMakePair(QString("radiusy"), KEYWORD_RADIUS_Y)
+ << qMakePair(QString("start"), KEYWORD_START)
+ << qMakePair(QString("span"), KEYWORD_SPAN)
+ << qMakePair(QString("toolbar"), KEYWORD_TOOLBAR)
+ << qMakePair(QString("priority"), KEYWORD_PRIORITY)
+ << qMakePair(QString("tools"), KEYWORD_TOOLS)
+ << qMakePair(QString("tool"), KEYWORD_TOOL)
+ << qMakePair(QString("element"), KEYWORD_ELEMENT)
+ << qMakePair(QString("separator"), KEYWORD_SEPARATOR)
+ << qMakePair(QString("relation"), KEYWORD_RELATION)
+ << qMakePair(QString("dependency"), KEYWORD_DEPENDENCY)
+ << qMakePair(QString("inheritance"), KEYWORD_INHERITANCE)
+ << qMakePair(QString("association"), KEYWORD_ASSOCIATION)
+ << qMakePair(QString("name"), KEYWORD_NAME)
+ << qMakePair(QString("direction"), KEYWORD_DIRECTION)
+ << qMakePair(QString("atob"), KEYWORD_ATOB)
+ << qMakePair(QString("btoa"), KEYWORD_BTOA)
+ << qMakePair(QString("bi"), KEYWORD_BI)
+ << qMakePair(QString("end"), KEYWORD_END)
+ << qMakePair(QString("a"), KEYWORD_A)
+ << qMakePair(QString("b"), KEYWORD_B)
+ << qMakePair(QString("role"), KEYWORD_ROLE)
+ << qMakePair(QString("cardinality"), KEYWORD_CARDINALITY)
+ << qMakePair(QString("navigable"), KEYWORD_NAVIGABLE)
+ << qMakePair(QString("relationship"), KEYWORD_RELATIONSHIP)
+ << qMakePair(QString("aggregation"), KEYWORD_AGGREGATION)
+ << qMakePair(QString("composition"), KEYWORD_COMPOSITION)
+ << qMakePair(QString("shaft"), KEYWORD_SHAFT)
+ << qMakePair(QString("head"), KEYWORD_HEAD)
+ << qMakePair(QString("diamond"), KEYWORD_DIAMOND)
+ << qMakePair(QString("triangle"), KEYWORD_TRIANGLE)
+ << qMakePair(QString("filled"), KEYWORD_FILLED)
+ << qMakePair(QString("pattern"), KEYWORD_PATTERN)
+ << qMakePair(QString("solid"), KEYWORD_SOLID)
+ << qMakePair(QString("dot"), KEYWORD_DOT)
+ << qMakePair(QString("dash"), KEYWORD_DASH)
+ << qMakePair(QString("dashdot"), KEYWORD_DASHDOT)
+ << qMakePair(QString("dashdotdot"), KEYWORD_DASHDOTDOT)
+ << qMakePair(QString("color"), KEYWORD_COLOR)
);
textScanner.setOperators(
QList<QPair<QString, int> >()
- << qMakePair(QString(QStringLiteral(";")), OPERATOR_SEMICOLON)
- << qMakePair(QString(QStringLiteral("{")), OPERATOR_BRACE_OPEN)
- << qMakePair(QString(QStringLiteral("}")), OPERATOR_BRACE_CLOSE)
- << qMakePair(QString(QStringLiteral(":")), OPERATOR_COLON)
- << qMakePair(QString(QStringLiteral(",")), OPERATOR_COMMA)
- << qMakePair(QString(QStringLiteral(".")), OPERATOR_PERIOD)
- << qMakePair(QString(QStringLiteral("-")), OPERATOR_MINUS)
+ << qMakePair(QString(";"), OPERATOR_SEMICOLON)
+ << qMakePair(QString("{"), OPERATOR_BRACE_OPEN)
+ << qMakePair(QString("}"), OPERATOR_BRACE_CLOSE)
+ << qMakePair(QString(":"), OPERATOR_COLON)
+ << qMakePair(QString(","), OPERATOR_COMMA)
+ << qMakePair(QString("."), OPERATOR_PERIOD)
+ << qMakePair(QString("-"), OPERATOR_MINUS)
);
textScanner.setSource(source);
@@ -213,10 +321,10 @@ void StereotypeDefinitionParser::parse(ITextSource *source)
try {
parseFile();
} catch (...) {
- d->m_scanner = 0;
+ d->m_scanner = nullptr;
throw;
}
- d->m_scanner = 0;
+ d->m_scanner = nullptr;
}
void StereotypeDefinitionParser::parseFile()
@@ -229,8 +337,16 @@ void StereotypeDefinitionParser::parseFile()
parseIcon();
else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_TOOLBAR)
parseToolbar();
+ else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_RELATION)
+ parseRelation(CustomRelation::Element::Relation);
+ else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_DEPENDENCY)
+ parseRelation(CustomRelation::Element::Dependency);
+ else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_INHERITANCE)
+ parseRelation(CustomRelation::Element::Inheritance);
+ else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_ASSOCIATION)
+ parseRelation(CustomRelation::Element::Association);
else
- throw StereotypeDefinitionParserError(QStringLiteral("Expected 'Icon' or 'Toolbar'."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected 'Icon', 'Toolbar', 'Relation', 'Dependency', 'Inheritance' or 'Association'.", token.sourcePos());
}
}
@@ -251,19 +367,15 @@ void StereotypeDefinitionParser::parseIcon()
break;
case KEYWORD_ELEMENTS:
{
- QList<QString> identifiers = parseIdentifierListProperty();
- foreach (const QString &identifier, identifiers) {
- static QHash<QString, StereotypeIcon::Element> elementNames = QHash<QString, StereotypeIcon::Element>()
- << qMakePair(QString(QStringLiteral("package")), StereotypeIcon::ElementPackage)
- << qMakePair(QString(QStringLiteral("component")), StereotypeIcon::ElementComponent)
- << qMakePair(QString(QStringLiteral("class")), StereotypeIcon::ElementClass)
- << qMakePair(QString(QStringLiteral("diagram")), StereotypeIcon::ElementDiagram)
- << qMakePair(QString(QStringLiteral("item")), StereotypeIcon::ElementItem);
- QString elementName = identifier.toLower();
- if (!elementNames.contains(elementName))
- throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(identifier), token.sourcePos());
- elements.insert(elementNames.value(elementName));
- }
+ const static QHash<QString, StereotypeIcon::Element> elementNames = QHash<QString, StereotypeIcon::Element>()
+ << qMakePair(QString("package"), StereotypeIcon::ElementPackage)
+ << qMakePair(QString("component"), StereotypeIcon::ElementComponent)
+ << qMakePair(QString("class"), StereotypeIcon::ElementClass)
+ << qMakePair(QString("diagram"), StereotypeIcon::ElementDiagram)
+ << qMakePair(QString("item"), StereotypeIcon::ElementItem);
+ parseEnums<StereotypeIcon::Element>(
+ parseIdentifierListProperty(), elementNames, token.sourcePos(),
+ [&](StereotypeIcon::Element element) { elements.insert(element); });
break;
}
case KEYWORD_STEREOTYPE:
@@ -283,61 +395,46 @@ void StereotypeDefinitionParser::parseIcon()
break;
case KEYWORD_LOCK_SIZE:
{
- QString lockValue = parseIdentifierProperty();
- QString lockName = lockValue.toLower();
- static QHash<QString, StereotypeIcon::SizeLock> lockNames = QHash<QString, StereotypeIcon::SizeLock>()
- << qMakePair(QString(QStringLiteral("none")), StereotypeIcon::LockNone)
- << qMakePair(QString(QStringLiteral("width")), StereotypeIcon::LockWidth)
- << qMakePair(QString(QStringLiteral("height")), StereotypeIcon::LockHeight)
- << qMakePair(QString(QStringLiteral("size")), StereotypeIcon::LockSize)
- << qMakePair(QString(QStringLiteral("ratio")), StereotypeIcon::LockRatio);
- if (lockNames.contains(lockName)) {
- StereotypeIcon::SizeLock sizeLock = lockNames.value(lockName);
- stereotypeIcon.setSizeLock(sizeLock);
- } else {
- throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for size lock.")).arg(lockValue), token.sourcePos());
- }
+ const static QHash<QString, StereotypeIcon::SizeLock> lockNames = QHash<QString, StereotypeIcon::SizeLock>()
+ << qMakePair(QString("none"), StereotypeIcon::LockNone)
+ << qMakePair(QString("width"), StereotypeIcon::LockWidth)
+ << qMakePair(QString("height"), StereotypeIcon::LockHeight)
+ << qMakePair(QString("size"), StereotypeIcon::LockSize)
+ << qMakePair(QString("ratio"), StereotypeIcon::LockRatio);
+ parseEnum<StereotypeIcon::SizeLock>(
+ parseIdentifierProperty(), lockNames, token.sourcePos(),
+ [&](StereotypeIcon::SizeLock lock) { stereotypeIcon.setSizeLock(lock); });
break;
}
case KEYWORD_DISPLAY:
{
- QString displayValue = parseIdentifierProperty();
- QString displayName = displayValue.toLower();
- static QHash<QString, StereotypeIcon::Display> displayNames = QHash<QString, StereotypeIcon::Display>()
- << qMakePair(QString(QStringLiteral("none")), StereotypeIcon::DisplayNone)
- << qMakePair(QString(QStringLiteral("label")), StereotypeIcon::DisplayLabel)
- << qMakePair(QString(QStringLiteral("decoration")), StereotypeIcon::DisplayDecoration)
- << qMakePair(QString(QStringLiteral("icon")), StereotypeIcon::DisplayIcon)
- << qMakePair(QString(QStringLiteral("smart")), StereotypeIcon::DisplaySmart);
- if (displayNames.contains(displayName)) {
- StereotypeIcon::Display display = displayNames.value(displayName);
- stereotypeIcon.setDisplay(display);
- } else {
- throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for stereotype display.")).arg(displayValue), token.sourcePos());
- }
+ const static QHash<QString, StereotypeIcon::Display> displayNames = QHash<QString, StereotypeIcon::Display>()
+ << qMakePair(QString("none"), StereotypeIcon::DisplayNone)
+ << qMakePair(QString("label"), StereotypeIcon::DisplayLabel)
+ << qMakePair(QString("decoration"), StereotypeIcon::DisplayDecoration)
+ << qMakePair(QString("icon"), StereotypeIcon::DisplayIcon)
+ << qMakePair(QString("smart"), StereotypeIcon::DisplaySmart);
+ parseEnum<StereotypeIcon::Display>(
+ parseIdentifierProperty(), displayNames, token.sourcePos(),
+ [&](StereotypeIcon::Display display) { stereotypeIcon.setDisplay(display); });
break;
}
case KEYWORD_TEXTALIGN:
{
- QString alignValue = parseIdentifierProperty();
- QString alignName = alignValue.toLower();
- static QHash<QString, StereotypeIcon::TextAlignment> alignNames = QHash<QString, StereotypeIcon::TextAlignment>()
- << qMakePair(QString(QStringLiteral("below")), StereotypeIcon::TextalignBelow)
- << qMakePair(QString(QStringLiteral("center")), StereotypeIcon::TextalignCenter)
- << qMakePair(QString(QStringLiteral("none")), StereotypeIcon::TextalignNone);
- if (alignNames.contains(alignName)) {
- StereotypeIcon::TextAlignment textAlignment = alignNames.value(alignName);
- stereotypeIcon.setTextAlignment(textAlignment);
- } else {
- throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for text alignment.")).arg(alignValue), token.sourcePos());
- }
+ const static QHash<QString, StereotypeIcon::TextAlignment> alignNames = QHash<QString, StereotypeIcon::TextAlignment>()
+ << qMakePair(QString("below"), StereotypeIcon::TextalignBelow)
+ << qMakePair(QString("center"), StereotypeIcon::TextalignCenter)
+ << qMakePair(QString("none"), StereotypeIcon::TextalignNone);
+ parseEnum<StereotypeIcon::TextAlignment>(
+ parseIdentifierProperty(), alignNames, token.sourcePos(),
+ [&](StereotypeIcon::TextAlignment align) { stereotypeIcon.setTextAlignment(align); });
break;
}
case KEYWORD_BASECOLOR:
stereotypeIcon.setBaseColor(parseColorProperty());
break;
case KEYWORD_SHAPE:
- parseIconShape(&stereotypeIcon);
+ stereotypeIcon.setIconShape(parseIconShape());
break;
default:
throwUnknownPropertyError(token);
@@ -348,7 +445,7 @@ void StereotypeDefinitionParser::parseIcon()
stereotypeIcon.setElements(elements);
stereotypeIcon.setStereotypes(stereotypes);
if (stereotypeIcon.id().isEmpty())
- throw StereotypeDefinitionParserError(QStringLiteral("Missing id in Icon definition."), d->m_scanner->sourcePos());
+ throw StereotypeDefinitionParserError("Missing id in Icon definition.", d->m_scanner->sourcePos());
emit iconParsed(stereotypeIcon);
}
@@ -367,10 +464,15 @@ QPair<int, StereotypeDefinitionParser::IconCommandParameter> StereotypeDefinitio
return qMakePair(keyword, IconCommandParameter(keyword, ShapeValueF::UnitAbsolute));
}
-void StereotypeDefinitionParser::parseIconShape(StereotypeIcon *stereotypeIcon)
+QPair<int, StereotypeDefinitionParser::IconCommandParameter> StereotypeDefinitionParser::BOOLEAN(int keyword)
+{
+ return qMakePair(keyword, IconCommandParameter(keyword, IconCommandParameter::Boolean));
+}
+
+IconShape StereotypeDefinitionParser::parseIconShape()
{
IconShape iconShape;
- QHash<int, ShapeValueF> values;
+ QHash<int, IconCommandParameter> values;
typedef QHash<int, IconCommandParameter> Parameters;
expectBlockBegin();
Token token;
@@ -458,26 +560,50 @@ void StereotypeDefinitionParser::parseIconShape(StereotypeIcon *stereotypeIcon)
iconShape.closePath();
skipOptionalEmptyBlock();
break;
+ case KEYWORD_DIAMOND:
+ values = parseIconShapeProperties(
+ Parameters() << SCALED(KEYWORD_X) << SCALED(KEYWORD_Y)
+ << SCALED(KEYWORD_WIDTH) << SCALED(KEYWORD_HEIGHT)
+ << BOOLEAN(KEYWORD_FILLED));
+ iconShape.addDiamond(ShapePointF(values.value(KEYWORD_X), values.value(KEYWORD_Y)),
+ ShapeSizeF(values.value(KEYWORD_WIDTH), values.value(KEYWORD_HEIGHT)),
+ values.value(KEYWORD_FILLED).boolean());
+ break;
+ case KEYWORD_TRIANGLE:
+ values = parseIconShapeProperties(
+ Parameters() << SCALED(KEYWORD_X) << SCALED(KEYWORD_Y)
+ << SCALED(KEYWORD_WIDTH) << SCALED(KEYWORD_HEIGHT)
+ << BOOLEAN(KEYWORD_FILLED));
+ iconShape.addTriangle(ShapePointF(values.value(KEYWORD_X), values.value(KEYWORD_Y)),
+ ShapeSizeF(values.value(KEYWORD_WIDTH), values.value(KEYWORD_HEIGHT)),
+ values.value(KEYWORD_FILLED).boolean());
+ break;
default:
throwUnknownPropertyError(token);
}
if (!expectPropertySeparatorOrBlockEnd())
break;
}
- stereotypeIcon->setIconShape(iconShape);
+ return iconShape;
}
-QHash<int, ShapeValueF> StereotypeDefinitionParser::parseIconShapeProperties(const QHash<int, IconCommandParameter> &parameters)
+QHash<int, StereotypeDefinitionParser::IconCommandParameter> StereotypeDefinitionParser::parseIconShapeProperties(const QHash<int, IconCommandParameter> &parameters)
{
expectBlockBegin();
- QHash<int, ShapeValueF> values;
+ QHash<int, IconCommandParameter> values;
Token token;
while (readProperty(&token)) {
if (parameters.contains(token.subtype())) {
- IconCommandParameter parameter = parameters.value(token.subtype());
if (values.contains(token.subtype()))
- throw StereotypeDefinitionParserError(QStringLiteral("Property givent twice."), token.sourcePos());
- values.insert(token.subtype(), ShapeValueF(parseFloatProperty(), parameter.m_unit, parameter.m_origin));
+ throw StereotypeDefinitionParserError("Property given twice.", token.sourcePos());
+ IconCommandParameter parameter = parameters.value(token.subtype());
+ if (parameter.type() == IconCommandParameter::ShapeValue)
+ parameter.setShapeValue(ShapeValueF(parseFloatProperty(), parameter.unit(), parameter.origin()));
+ else if (parameter.type() == IconCommandParameter::Boolean)
+ parameter.setBoolean(parseBoolProperty());
+ else
+ throw StereotypeDefinitionParserError("Unexpected type of property.", token.sourcePos());
+ values.insert(token.subtype(), parameter);
} else {
throwUnknownPropertyError(token);
}
@@ -485,12 +611,198 @@ QHash<int, ShapeValueF> StereotypeDefinitionParser::parseIconShapeProperties(con
break;
}
if (values.count() < parameters.count())
- throw StereotypeDefinitionParserError(QStringLiteral("Missing some properties."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Missing some properties.", token.sourcePos());
else if (values.count() > parameters.count())
- throw StereotypeDefinitionParserError(QStringLiteral("Too many properties given."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Too many properties given.", token.sourcePos());
return values;
}
+void StereotypeDefinitionParser::parseRelation(CustomRelation::Element element)
+{
+ CustomRelation relation;
+ relation.setElement(element);
+ QSet<QString> stereotypes;
+ expectBlockBegin();
+ Token token;
+ while (readProperty(&token)) {
+ switch (token.subtype()) {
+ case KEYWORD_ID:
+ relation.setId(parseIdentifierProperty());
+ break;
+ case KEYWORD_TITLE:
+ relation.setTitle(parseStringProperty());
+ break;
+ case KEYWORD_ELEMENTS:
+ relation.setEndItems(parseIdentifierListProperty());
+ break;
+ case KEYWORD_STEREOTYPE:
+ stereotypes.insert(parseStringProperty());
+ break;
+ case KEYWORD_NAME:
+ relation.setName(parseStringProperty());
+ break;
+ case KEYWORD_DIRECTION:
+ {
+ const static QHash<QString, CustomRelation::Direction> directionNames = QHash<QString, CustomRelation::Direction>()
+ << qMakePair(QString("atob"), CustomRelation::Direction::AtoB)
+ << qMakePair(QString("btoa"), CustomRelation::Direction::BToA)
+ << qMakePair(QString("bi"), CustomRelation::Direction::Bi);
+ if (element != CustomRelation::Element::Dependency)
+ throwUnknownPropertyError(token);
+ parseEnum<CustomRelation::Direction>(
+ parseIdentifierProperty(), directionNames, token.sourcePos(),
+ [&](CustomRelation::Direction direction) { relation.setDirection(direction); });
+ break;
+ }
+ case KEYWORD_PATTERN:
+ {
+ const static QHash<QString, CustomRelation::ShaftPattern> patternNames = QHash<QString, CustomRelation::ShaftPattern>()
+ << qMakePair(QString("solid"), CustomRelation::ShaftPattern::Solid)
+ << qMakePair(QString("dash"), CustomRelation::ShaftPattern::Dash)
+ << qMakePair(QString("dot"), CustomRelation::ShaftPattern::Dot)
+ << qMakePair(QString("dashdot"), CustomRelation::ShaftPattern::DashDot)
+ << qMakePair(QString("dashdotdot"), CustomRelation::ShaftPattern::DashDotDot);
+ if (element != CustomRelation::Element::Relation)
+ throwUnknownPropertyError(token);
+ parseEnum<CustomRelation::ShaftPattern>(
+ parseIdentifierProperty(), patternNames, token.sourcePos(),
+ [&](CustomRelation::ShaftPattern pattern) { relation.setShaftPattern(pattern); });
+ break;
+ }
+ case KEYWORD_COLOR:
+ {
+ if (element != CustomRelation::Element::Relation)
+ throwUnknownPropertyError(token);
+ Value expression = parseProperty();
+ if (expression.type() == Color) {
+ relation.setColorType(CustomRelation::ColorType::Custom);
+ relation.setColor(expression.value().value<QColor>());
+ } else if (expression.type() == Identifier) {
+ QString colorValue = expression.value().toString();
+ QString colorName = colorValue.toLower();
+ if (colorName == "a") {
+ relation.setColorType(CustomRelation::ColorType::EndA);
+ } else if (colorName == "b") {
+ relation.setColorType(CustomRelation::ColorType::EndB);
+ } else if (QColor::isValidColor(colorName)) {
+ relation.setColorType(CustomRelation::ColorType::Custom);
+ relation.setColor(QColor(colorName));
+ } else {
+ throw StereotypeDefinitionParserError(QString("Unexpected value \"%1\" for color.").arg(colorValue), token.sourcePos());
+ }
+ } else {
+ throw StereotypeDefinitionParserError("Unexpected value for color.", token.sourcePos());
+ }
+ break;
+ }
+ case KEYWORD_END:
+ parseRelationEnd(&relation);
+ break;
+ default:
+ throwUnknownPropertyError(token);
+ }
+ if (!expectPropertySeparatorOrBlockEnd())
+ break;
+ }
+ relation.setStereotypes(stereotypes);
+ if (relation.id().isEmpty())
+ throw StereotypeDefinitionParserError("Missing id in Relation definition.", d->m_scanner->sourcePos());
+ emit relationParsed(relation);
+}
+
+void StereotypeDefinitionParser::parseRelationEnd(CustomRelation *relation)
+{
+ CustomRelation::End relationEnd;
+ bool isEndB = false;
+ expectBlockBegin();
+ Token token;
+ while (readProperty(&token)) {
+ switch (token.subtype()) {
+ case KEYWORD_END:
+ {
+ QString endValue = parseIdentifierProperty();
+ QString endName = endValue.toLower();
+ if (endName == "a")
+ isEndB = false;
+ else if (endName == "b")
+ isEndB = true;
+ else
+ throw StereotypeDefinitionParserError(QString("Unexpected value \"%1\" for end.").arg(endValue), token.sourcePos());
+ break;
+ }
+ case KEYWORD_ELEMENTS:
+ if (relation->element() != CustomRelation::Element::Relation)
+ throwUnknownPropertyError(token);
+ relationEnd.setEndItems(parseIdentifierListProperty());
+ break;
+ case KEYWORD_ROLE:
+ if (relation->element() != CustomRelation::Element::Relation && relation->element() != CustomRelation::Element::Association)
+ throwUnknownPropertyError(token);
+ relationEnd.setRole(parseStringProperty());
+ break;
+ case KEYWORD_CARDINALITY:
+ {
+ if (relation->element() != CustomRelation::Element::Relation && relation->element() != CustomRelation::Element::Association)
+ throwUnknownPropertyError(token);
+ Value expression = parseProperty();
+ if (expression.type() == Int || expression.type() == String)
+ relationEnd.setCardinality(expression.value().toString());
+ else
+ throw StereotypeDefinitionParserError("Wrong type for cardinality.", token.sourcePos());
+ break;
+ }
+ case KEYWORD_NAVIGABLE:
+ if (relation->element() != CustomRelation::Element::Relation && relation->element() != CustomRelation::Element::Association)
+ throwUnknownPropertyError(token);
+ relationEnd.setNavigable(parseBoolProperty());
+ break;
+ case KEYWORD_RELATIONSHIP:
+ {
+ if (relation->element() != CustomRelation::Element::Association)
+ throwUnknownPropertyError(token);
+ const static QHash<QString, CustomRelation::Relationship> relationshipNames = QHash<QString, CustomRelation::Relationship>()
+ << qMakePair(QString("association"), CustomRelation::Relationship::Association)
+ << qMakePair(QString("aggregation"), CustomRelation::Relationship::Aggregation)
+ << qMakePair(QString("composition"), CustomRelation::Relationship::Composition);
+ parseEnum<CustomRelation::Relationship>(
+ parseIdentifierProperty(), relationshipNames, token.sourcePos(),
+ [&](CustomRelation::Relationship relationship) { relationEnd.setRelationship(relationship); });
+ break;
+ }
+ case KEYWORD_HEAD:
+ {
+ if (relation->element() != CustomRelation::Element::Relation)
+ throwUnknownPropertyError(token);
+ const static QHash<QString, CustomRelation::Head> headNames = QHash<QString, CustomRelation::Head>()
+ << qMakePair(QString("none"), CustomRelation::Head::None)
+ << qMakePair(QString("arrow"), CustomRelation::Head::Arrow)
+ << qMakePair(QString("triangle"), CustomRelation::Head::Triangle)
+ << qMakePair(QString("filledtriangle"), CustomRelation::Head::FilledTriangle)
+ << qMakePair(QString("diamond"), CustomRelation::Head::Diamond)
+ << qMakePair(QString("filleddiamond"), CustomRelation::Head::FilledDiamond);
+ parseEnum<CustomRelation::Head>(
+ parseIdentifierProperty(), headNames, token.sourcePos(),
+ [&](CustomRelation::Head head) { relationEnd.setHead(head); });
+ break;
+ }
+ case KEYWORD_SHAPE:
+ if (relation->element() != CustomRelation::Element::Relation)
+ throwUnknownPropertyError(token);
+ relationEnd.setHead(CustomRelation::Head::Shape);
+ relationEnd.setShape(parseIconShape());
+ break;
+ default:
+ throwUnknownPropertyError(token);
+ }
+ if (!expectPropertySeparatorOrBlockEnd())
+ break;
+ }
+ if (isEndB)
+ relation->setEndB(relationEnd);
+ else
+ relation->setEndA(relationEnd);
+}
+
void StereotypeDefinitionParser::parseToolbar()
{
Toolbar toolbar;
@@ -507,6 +819,10 @@ void StereotypeDefinitionParser::parseToolbar()
case KEYWORD_PRIORITY:
toolbar.setPriority(parseIntProperty());
break;
+ case KEYWORD_ELEMENT:
+ toolbar.setElementTypes(parseIdentifierListProperty());
+ toolbar.setToolbarType(toolbar.elementTypes().isEmpty() ? Toolbar::ObjectToolbar : Toolbar::RelationToolbar);
+ break;
case KEYWORD_TOOLS:
parseToolbarTools(&toolbar);
break;
@@ -517,7 +833,7 @@ void StereotypeDefinitionParser::parseToolbar()
break;
}
if (toolbar.id().isEmpty())
- throw StereotypeDefinitionParserError(QStringLiteral("Missing id in Toolbar definition."), d->m_scanner->sourcePos());
+ throw StereotypeDefinitionParserError("Missing id in Toolbar definition.", d->m_scanner->sourcePos());
emit toolbarParsed(toolbar);
}
@@ -532,7 +848,7 @@ void StereotypeDefinitionParser::parseToolbarTools(Toolbar *toolbar)
{
Toolbar::Tool tool;
tool.m_toolType = Toolbar::TooltypeTool;
- parseToolbarTool(&tool);
+ parseToolbarTool(toolbar, &tool);
tools.append(tool);
break;
}
@@ -549,7 +865,7 @@ void StereotypeDefinitionParser::parseToolbarTools(Toolbar *toolbar)
toolbar->setTools(tools);
}
-void StereotypeDefinitionParser::parseToolbarTool(Toolbar::Tool *tool)
+void StereotypeDefinitionParser::parseToolbarTool(const Toolbar *toolbar, Toolbar::Tool *tool)
{
expectBlockBegin();
Token token;
@@ -561,17 +877,30 @@ void StereotypeDefinitionParser::parseToolbarTool(Toolbar::Tool *tool)
case KEYWORD_ELEMENT:
{
QString element = parseIdentifierProperty();
- static QSet<QString> elementNames = QSet<QString>()
- << QStringLiteral("package")
- << QStringLiteral("component")
- << QStringLiteral("class")
- << QStringLiteral("item")
- << QStringLiteral("annotation")
- << QStringLiteral("boundary");
- QString elementName = element.toLower();
- if (!elementNames.contains(elementName))
- throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(element), token.sourcePos());
- tool->m_elementType = elementName;
+ if (toolbar->toolbarType() == Toolbar::ObjectToolbar) {
+ static QSet<QString> elementNames = QSet<QString>()
+ << "package"
+ << "component"
+ << "class"
+ << "item"
+ << "annotation"
+ << "boundary"
+ << "swimlane";
+ QString elementName = element.toLower();
+ if (!elementNames.contains(elementName))
+ throw StereotypeDefinitionParserError(QString("Unexpected value \"%1\" for element.").arg(element), token.sourcePos());
+ tool->m_elementType = elementName;
+ } else {
+ static QSet<QString> relationNames = QSet<QString>()
+ << "dependency"
+ << "inheritance"
+ << "association";
+ QString relationName = element.toLower();
+ if (relationNames.contains(relationName))
+ tool->m_elementType = relationName;
+ else
+ tool->m_elementType = element;
+ }
break;
}
case KEYWORD_STEREOTYPE:
@@ -585,6 +914,28 @@ void StereotypeDefinitionParser::parseToolbarTool(Toolbar::Tool *tool)
}
}
+template<typename T>
+void StereotypeDefinitionParser::parseEnums(const QList<QString> &identifiers,
+ const QHash<QString, T> &identifierNames,
+ const SourcePos &sourcePos,
+ std::function<void (T)> setter)
+{
+ for (const QString &identifier : identifiers)
+ parseEnum(identifier, identifierNames, sourcePos, setter);
+}
+
+template<typename T>
+void StereotypeDefinitionParser::parseEnum(const QString &identifier,
+ const QHash<QString, T> &identifierNames,
+ const SourcePos &sourcePos,
+ std::function<void (T)> setter)
+{
+ const QString name = identifier.toLower();
+ if (!identifierNames.contains(name))
+ throw StereotypeDefinitionParserError(QString("Unexpected value \"%1\".").arg(identifier), sourcePos);
+ setter(identifierNames.value(name));
+}
+
QString StereotypeDefinitionParser::parseStringProperty()
{
expectColon();
@@ -616,7 +967,7 @@ QList<QString> StereotypeDefinitionParser::parseIdentifierListProperty()
for (;;) {
Token token = d->m_scanner->read();
if (token.type() != Token::TokenIdentifier && token.type() != Token::TokenKeyword) {
- throw StereotypeDefinitionParserError(QStringLiteral("Expected identifier."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected identifier.", token.sourcePos());
}
identifiers.append(token.text());
token = d->m_scanner->read();
@@ -640,11 +991,17 @@ QColor StereotypeDefinitionParser::parseColorProperty()
return parseColorExpression();
}
+StereotypeDefinitionParser::Value StereotypeDefinitionParser::parseProperty()
+{
+ expectColon();
+ return parseExpression();
+}
+
QString StereotypeDefinitionParser::parseStringExpression()
{
Token token = d->m_scanner->read();
if (token.type() != Token::TokenString)
- throw StereotypeDefinitionParserError(QStringLiteral("Expected string constant."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected string constant.", token.sourcePos());
return token.text();
}
@@ -665,7 +1022,7 @@ qreal StereotypeDefinitionParser::parseFloatExpression()
QMT_CHECK(ok);
return value;
} else {
- throw StereotypeDefinitionParserError(QStringLiteral("Expected number constant."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected number constant.", token.sourcePos());
}
}
}
@@ -683,7 +1040,7 @@ int StereotypeDefinitionParser::parseIntExpression()
QMT_CHECK(ok);
return value;
} else {
- throw StereotypeDefinitionParserError(QStringLiteral("Expected integer constant."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected integer constant.", token.sourcePos());
}
}
}
@@ -692,7 +1049,7 @@ QString StereotypeDefinitionParser::parseIdentifierExpression()
{
Token token = d->m_scanner->read();
if (token.type() != Token::TokenIdentifier && token.type() != Token::TokenKeyword)
- throw StereotypeDefinitionParserError(QStringLiteral("Expected identifier."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected identifier.", token.sourcePos());
return token.text();
}
@@ -701,12 +1058,12 @@ bool StereotypeDefinitionParser::parseBoolExpression()
Token token = d->m_scanner->read();
if (token.type() == Token::TokenIdentifier) {
QString value = token.text().toLower();
- if (value == QStringLiteral("yes") || value == QStringLiteral("true"))
+ if (value == "yes" || value == "true")
return true;
- else if (value == QStringLiteral("no") || value == QStringLiteral("false"))
+ else if (value == "no" || value == "false")
return false;
}
- throw StereotypeDefinitionParserError(QStringLiteral("Expected 'yes', 'no', 'true' or 'false'."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected 'yes', 'no', 'true' or 'false'.", token.sourcePos());
}
QColor StereotypeDefinitionParser::parseColorExpression()
@@ -720,13 +1077,57 @@ QColor StereotypeDefinitionParser::parseColorExpression()
return color;
}
}
- throw StereotypeDefinitionParserError(QStringLiteral("Expected color name."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected color name.", token.sourcePos());
+}
+
+StereotypeDefinitionParser::Value StereotypeDefinitionParser::parseExpression()
+{
+ Token token = d->m_scanner->read();
+ if (token.type() == Token::TokenString) {
+ return Value(String, QVariant(token.text()));
+ } else if (token.type() == Token::TokenOperator && token.subtype() == OPERATOR_MINUS) {
+ Value v = parseExpression();
+ if (v.type() == Int)
+ return Value(Int, QVariant(-v.value().toInt()));
+ else if (v.type() == Float)
+ return Value(Float, QVariant(-v.value().toDouble()));
+ else
+ throw StereotypeDefinitionParserError("Illegal number expression.", token.sourcePos());
+ } else if (token.type() == Token::TokenInteger) {
+ bool ok = false;
+ int value = token.text().toInt(&ok);
+ QMT_CHECK(ok);
+ return Value(Int, QVariant(value));
+ } else if (token.type() == Token::TokenFloat) {
+ bool ok = false;
+ qreal value = token.text().toDouble(&ok);
+ QMT_CHECK(ok);
+ return Value(Float, QVariant(value));
+ } else if (token.type() == Token::TokenColor) {
+ QString value = token.text().toLower();
+ QColor color;
+ if (QColor::isValidColor(value)) {
+ color.setNamedColor(value);
+ return Value(Color, QVariant(color));
+ } else {
+ throw StereotypeDefinitionParserError("Invalid color.", token.sourcePos());
+ }
+ } else if (token.type() == Token::TokenIdentifier || token.type() == Token::TokenKeyword) {
+ QString value = token.text().toLower();
+ if (value == "yes" || value == "true")
+ return Value(Boolean, QVariant(true));
+ else if (value == "no" || value == "false")
+ return Value(Boolean, QVariant(false));
+ else
+ return Value(Identifier, QVariant(token.text()));
+ }
+ throw StereotypeDefinitionParserError("Syntax error in expression.", token.sourcePos());
}
void StereotypeDefinitionParser::expectBlockBegin()
{
skipEOLTokens();
- expectOperator(OPERATOR_BRACE_OPEN, QStringLiteral("{"));
+ expectOperator(OPERATOR_BRACE_OPEN, "{");
}
bool StereotypeDefinitionParser::readProperty(Token *token)
@@ -739,13 +1140,13 @@ bool StereotypeDefinitionParser::readProperty(Token *token)
else if (token->type() == Token::TokenIdentifier)
throwUnknownPropertyError(*token);
else
- throw StereotypeDefinitionParserError(QStringLiteral("Syntax error."), token->sourcePos());
+ throw StereotypeDefinitionParserError("Syntax error.", token->sourcePos());
return false; // will never be reached but avoids compiler warning
}
void StereotypeDefinitionParser::throwUnknownPropertyError(const Token &token)
{
- throw StereotypeDefinitionParserError(QString(QStringLiteral("Unknown property '%1'.")).arg(token.text()), token.sourcePos());
+ throw StereotypeDefinitionParserError(QString("Unknown property '%1'.").arg(token.text()), token.sourcePos());
}
bool StereotypeDefinitionParser::expectPropertySeparatorOrBlockEnd()
@@ -764,7 +1165,7 @@ bool StereotypeDefinitionParser::expectPropertySeparatorOrBlockEnd()
else
d->m_scanner->unread(token);
if (!ok)
- throw StereotypeDefinitionParserError(QStringLiteral("Expected ';', '}' or end-of-line."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected ';', '}' or end-of-line.", token.sourcePos());
return true;
}
@@ -782,7 +1183,7 @@ void StereotypeDefinitionParser::skipOptionalEmptyBlock()
if (isOperator(token, OPERATOR_BRACE_OPEN)) {
token = readNextToken();
if (!isOperator(token, OPERATOR_BRACE_CLOSE))
- throw StereotypeDefinitionParserError(QStringLiteral("Expected '}' in empty block."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected '}' in empty block.", token.sourcePos());
} else {
d->m_scanner->unread(token);
d->m_scanner->unread(eolToken);
@@ -790,7 +1191,7 @@ void StereotypeDefinitionParser::skipOptionalEmptyBlock()
} else if (isOperator(token, OPERATOR_BRACE_OPEN)) {
token = readNextToken();
if (!isOperator(token, OPERATOR_BRACE_CLOSE))
- throw StereotypeDefinitionParserError(QStringLiteral("Expected '}' in empty block."), token.sourcePos());
+ throw StereotypeDefinitionParserError("Expected '}' in empty block.", token.sourcePos());
} else {
d->m_scanner->unread(token);
}
@@ -799,7 +1200,7 @@ void StereotypeDefinitionParser::skipOptionalEmptyBlock()
qreal StereotypeDefinitionParser::expectAbsoluteValue(const ShapeValueF &value, const SourcePos &sourcePos)
{
if (value.unit() != ShapeValueF::UnitAbsolute || value.origin() != ShapeValueF::OriginSmart)
- throw StereotypeDefinitionParserError(QStringLiteral("Expected absolute value"), sourcePos);
+ throw StereotypeDefinitionParserError("Expected absolute value", sourcePos);
return value.value();
}
@@ -812,12 +1213,12 @@ void StereotypeDefinitionParser::expectOperator(int op, const QString &opName)
{
Token token = d->m_scanner->read();
if (!isOperator(token, op))
- throw StereotypeDefinitionParserError(QString(QStringLiteral("Expected '%1'.")).arg(opName), token.sourcePos());
+ throw StereotypeDefinitionParserError(QString("Expected '%1'.").arg(opName), token.sourcePos());
}
void StereotypeDefinitionParser::expectColon()
{
- expectOperator(OPERATOR_COLON, QStringLiteral(":"));
+ expectOperator(OPERATOR_COLON, ":");
}
void StereotypeDefinitionParser::skipEOLTokens()
diff --git a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h
index 390ab4424e..2a25e70b09 100644
--- a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h
+++ b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h
@@ -27,12 +27,14 @@
#include <QObject>
#include "qmt/infrastructure/exceptions.h"
+#include "qmt/stereotype/customrelation.h"
#include "qmt/stereotype/toolbar.h"
#include "sourcepos.h"
#include <QPair>
#include <QHash>
+#include <functional>
namespace qmt {
@@ -59,13 +61,25 @@ class QMT_EXPORT StereotypeDefinitionParser : public QObject
Q_OBJECT
class StereotypeDefinitionParserPrivate;
class IconCommandParameter;
+ class Value;
+
+ enum Type {
+ Void,
+ Identifier,
+ String,
+ Int,
+ Float,
+ Boolean,
+ Color
+ };
public:
- explicit StereotypeDefinitionParser(QObject *parent = 0);
+ explicit StereotypeDefinitionParser(QObject *parent = nullptr);
~StereotypeDefinitionParser() override;
signals:
void iconParsed(const StereotypeIcon &stereotypeIcon);
+ void relationParsed(const CustomRelation &relation);
void toolbarParsed(const Toolbar &toolbar);
public:
@@ -78,12 +92,24 @@ private:
static QPair<int, IconCommandParameter> SCALED(int keyword);
static QPair<int, IconCommandParameter> FIX(int keyword);
static QPair<int, IconCommandParameter> ABSOLUTE(int keyword);
- void parseIconShape(StereotypeIcon *stereotypeIcon);
- QHash<int, ShapeValueF> parseIconShapeProperties(const QHash<int, IconCommandParameter> &parameters);
+ static QPair<int, IconCommandParameter> BOOLEAN(int keyword);
+ IconShape parseIconShape();
+ QHash<int, IconCommandParameter> parseIconShapeProperties(const QHash<int, IconCommandParameter> &parameters);
+
+ void parseRelation(CustomRelation::Element element);
+ void parseRelationEnd(CustomRelation *relation);
void parseToolbar();
void parseToolbarTools(Toolbar *toolbar);
- void parseToolbarTool(Toolbar::Tool *tool);
+ void parseToolbarTool(const Toolbar *toolbar, Toolbar::Tool *tool);
+
+ template<typename T>
+ void parseEnums(const QList<QString> &identifiers, const QHash<QString, T> &identifierNames,
+ const SourcePos &sourcePos, std::function<void(T)> setter);
+
+ template<typename T>
+ void parseEnum(const QString &identifier, const QHash<QString, T> &identifierNames,
+ const SourcePos &sourcePos, std::function<void(T)> setter);
QString parseStringProperty();
int parseIntProperty();
@@ -92,6 +118,7 @@ private:
QList<QString> parseIdentifierListProperty();
bool parseBoolProperty();
QColor parseColorProperty();
+ Value parseProperty();
QString parseStringExpression();
qreal parseFloatExpression();
@@ -99,6 +126,7 @@ private:
QString parseIdentifierExpression();
bool parseBoolExpression();
QColor parseColorExpression();
+ Value parseExpression();
void expectBlockBegin();
bool readProperty(Token *token);
diff --git a/src/libs/modelinglib/qmt/config/stringtextsource.cpp b/src/libs/modelinglib/qmt/config/stringtextsource.cpp
index d62575ffa6..bf7a6b9219 100644
--- a/src/libs/modelinglib/qmt/config/stringtextsource.cpp
+++ b/src/libs/modelinglib/qmt/config/stringtextsource.cpp
@@ -31,10 +31,6 @@
namespace qmt {
StringTextSource::StringTextSource()
- : m_sourceId(-1),
- m_index(-1),
- m_lineNumber(-1),
- m_columnNumber(-1)
{
}
@@ -57,10 +53,10 @@ void StringTextSource::setSourceId(int sourceId)
SourceChar StringTextSource::readNextChar()
{
- QMT_CHECK(m_sourceId >= 0);
- QMT_CHECK(m_index >= 0);
- QMT_CHECK(m_lineNumber >= 0);
- QMT_CHECK(m_columnNumber >= 0);
+ QMT_ASSERT(m_sourceId >= 0, return SourceChar());
+ QMT_ASSERT(m_index >= 0, return SourceChar());
+ QMT_ASSERT(m_lineNumber >= 0, return SourceChar());
+ QMT_ASSERT(m_columnNumber >= 0, return SourceChar());
if (m_index >= m_text.length())
return SourceChar(QChar(), SourcePos(m_sourceId, m_lineNumber, m_columnNumber));
diff --git a/src/libs/modelinglib/qmt/config/stringtextsource.h b/src/libs/modelinglib/qmt/config/stringtextsource.h
index 01301ca6cd..5cfcc32a5d 100644
--- a/src/libs/modelinglib/qmt/config/stringtextsource.h
+++ b/src/libs/modelinglib/qmt/config/stringtextsource.h
@@ -46,10 +46,10 @@ public:
private:
QString m_text;
- int m_sourceId;
- int m_index;
- int m_lineNumber;
- int m_columnNumber;
+ int m_sourceId = -1;
+ int m_index = -1;
+ int m_lineNumber = -1;
+ int m_columnNumber = -1;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/config/textscanner.cpp b/src/libs/modelinglib/qmt/config/textscanner.cpp
index 80c13c80d0..32e3d937c1 100644
--- a/src/libs/modelinglib/qmt/config/textscanner.cpp
+++ b/src/libs/modelinglib/qmt/config/textscanner.cpp
@@ -57,7 +57,7 @@ public:
int m_maxOperatorLength = 0;
QSet<QChar> m_operatorFirstCharsSet;
QSet<QChar> m_operatorCharsSet;
- ITextSource *m_source = 0;
+ ITextSource *m_source = nullptr;
QStack<SourceChar> m_unreadSourceChars;
SourcePos m_lastSourcePos;
QStack<Token> m_unreadTokens;
@@ -129,7 +129,7 @@ Token TextScanner::read()
else if (d->m_operatorFirstCharsSet.contains(sourceChar.ch))
return scanOperator(sourceChar);
else
- throw TextScannerError(QStringLiteral("Unexpected character."), sourceChar.pos);
+ throw TextScannerError("Unexpected character.", sourceChar.pos);
}
void TextScanner::unread(const Token &token)
@@ -201,9 +201,9 @@ Token TextScanner::scanString(const SourceChar &delimiterChar)
else if (sourceChar.ch == QLatin1Char('\''))
text += QLatin1Char('\'');
else
- throw TextScannerError(QStringLiteral("Unexpected character after '\\' in string constant."), sourceChar.pos);
+ throw TextScannerError("Unexpected character after '\\' in string constant.", sourceChar.pos);
} else if (sourceChar.ch == QChar::LineFeed || sourceChar.ch == QChar::CarriageReturn) {
- throw TextScannerError(QStringLiteral("Unexpected end of line in string constant."), sourceChar.pos);
+ throw TextScannerError("Unexpected end of line in string constant.", sourceChar.pos);
} else {
text += sourceChar.ch;
}
diff --git a/src/libs/modelinglib/qmt/config/textscanner.h b/src/libs/modelinglib/qmt/config/textscanner.h
index de682a65c4..941a3a5b3e 100644
--- a/src/libs/modelinglib/qmt/config/textscanner.h
+++ b/src/libs/modelinglib/qmt/config/textscanner.h
@@ -55,7 +55,7 @@ class QMT_EXPORT TextScanner : public QObject
class TextScannerPrivate;
public:
- explicit TextScanner(QObject *parent = 0);
+ explicit TextScanner(QObject *parent = nullptr);
~TextScanner() override;
void setKeywords(const QList<QPair<QString, int> > &keywords);
diff --git a/src/libs/modelinglib/qmt/config/token.cpp b/src/libs/modelinglib/qmt/config/token.cpp
index 9ef1ee2bd8..8c740f95be 100644
--- a/src/libs/modelinglib/qmt/config/token.cpp
+++ b/src/libs/modelinglib/qmt/config/token.cpp
@@ -46,10 +46,6 @@ Token::Token(Token::Type type, int subtype, const QString &text, const SourcePos
{
}
-Token::~Token()
-{
-}
-
void Token::setType(Token::Type type)
{
m_type = type;
diff --git a/src/libs/modelinglib/qmt/config/token.h b/src/libs/modelinglib/qmt/config/token.h
index 8672c0ea1d..dd9888795c 100644
--- a/src/libs/modelinglib/qmt/config/token.h
+++ b/src/libs/modelinglib/qmt/config/token.h
@@ -50,7 +50,6 @@ public:
Token();
Token(Type type, const QString &text, const SourcePos &sourcePos);
Token(Type type, int subtype, const QString &text, const SourcePos &sourcePos);
- ~Token();
Type type() const { return m_type; }
void setType(Type type);
diff --git a/src/libs/modelinglib/qmt/controller/namecontroller.cpp b/src/libs/modelinglib/qmt/controller/namecontroller.cpp
index 2285fb3971..c2c23c772a 100644
--- a/src/libs/modelinglib/qmt/controller/namecontroller.cpp
+++ b/src/libs/modelinglib/qmt/controller/namecontroller.cpp
@@ -135,11 +135,11 @@ QStringList NameController::buildElementsPath(const QString &filePath, bool igno
{
QList<QString> relativeElements;
- QStringList splitted = filePath.split(QStringLiteral("/"));
- QStringList::const_iterator splittedEnd = splitted.end();
- if (ignoreLastFilePathPart || splitted.last().isEmpty())
- splittedEnd = --splittedEnd;
- for (auto it = splitted.cbegin(); it != splittedEnd; ++it) {
+ QStringList split = filePath.split("/");
+ QStringList::const_iterator splitEnd = split.end();
+ if (ignoreLastFilePathPart || split.last().isEmpty())
+ splitEnd = --splitEnd;
+ for (auto it = split.cbegin(); it != splitEnd; ++it) {
QString packageName = qmt::NameController::convertFileNameToElementName(*it);
relativeElements.append(packageName);
}
diff --git a/src/libs/modelinglib/qmt/controller/namecontroller.h b/src/libs/modelinglib/qmt/controller/namecontroller.h
index ec77165695..50ed023d20 100644
--- a/src/libs/modelinglib/qmt/controller/namecontroller.h
+++ b/src/libs/modelinglib/qmt/controller/namecontroller.h
@@ -38,7 +38,7 @@ class QMT_EXPORT NameController : public QObject
Q_OBJECT
private:
- explicit NameController(QObject *parent = 0);
+ explicit NameController(QObject *parent = nullptr);
~NameController() override;
public:
diff --git a/src/libs/modelinglib/qmt/controller/undocommand.cpp b/src/libs/modelinglib/qmt/controller/undocommand.cpp
index eea123a942..40348d3f86 100644
--- a/src/libs/modelinglib/qmt/controller/undocommand.cpp
+++ b/src/libs/modelinglib/qmt/controller/undocommand.cpp
@@ -30,9 +30,7 @@
namespace qmt {
UndoCommand::UndoCommand(const QString &text)
- : QUndoCommand(text),
- m_canRedo(false),
- m_doNotMerge(false)
+ : QUndoCommand(text)
{
}
diff --git a/src/libs/modelinglib/qmt/controller/undocommand.h b/src/libs/modelinglib/qmt/controller/undocommand.h
index 52cd00b707..aa96cd7430 100644
--- a/src/libs/modelinglib/qmt/controller/undocommand.h
+++ b/src/libs/modelinglib/qmt/controller/undocommand.h
@@ -47,8 +47,8 @@ public:
void redo() override;
private:
- bool m_canRedo;
- bool m_doNotMerge;
+ bool m_canRedo = false;
+ bool m_doNotMerge = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/controller/undocontroller.cpp b/src/libs/modelinglib/qmt/controller/undocontroller.cpp
index 85475d55cc..a994029141 100644
--- a/src/libs/modelinglib/qmt/controller/undocontroller.cpp
+++ b/src/libs/modelinglib/qmt/controller/undocontroller.cpp
@@ -33,8 +33,7 @@ namespace qmt {
UndoController::UndoController(QObject *parent) :
QObject(parent),
- m_undoStack(new QUndoStack(this)),
- m_doNotMerge(false)
+ m_undoStack(new QUndoStack(this))
{
}
diff --git a/src/libs/modelinglib/qmt/controller/undocontroller.h b/src/libs/modelinglib/qmt/controller/undocontroller.h
index 7a3e162d1b..8179493a55 100644
--- a/src/libs/modelinglib/qmt/controller/undocontroller.h
+++ b/src/libs/modelinglib/qmt/controller/undocontroller.h
@@ -41,7 +41,7 @@ class QMT_EXPORT UndoController : public QObject
Q_OBJECT
public:
- explicit UndoController(QObject *parent = 0);
+ explicit UndoController(QObject *parent = nullptr);
~UndoController() override;
QUndoStack *undoStack() const { return m_undoStack; }
@@ -54,8 +54,8 @@ public:
void doNotMerge();
private:
- QUndoStack *m_undoStack;
- bool m_doNotMerge;
+ QUndoStack *m_undoStack = nullptr;
+ bool m_doNotMerge = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dannotation.cpp b/src/libs/modelinglib/qmt/diagram/dannotation.cpp
index cae6d96eb2..2a7787c7b5 100644
--- a/src/libs/modelinglib/qmt/diagram/dannotation.cpp
+++ b/src/libs/modelinglib/qmt/diagram/dannotation.cpp
@@ -31,9 +31,7 @@
namespace qmt {
DAnnotation::DAnnotation()
- : DElement(),
- m_visualRole(RoleNormal),
- m_isAutoSized(true)
+ : DElement()
{
}
diff --git a/src/libs/modelinglib/qmt/diagram/dannotation.h b/src/libs/modelinglib/qmt/diagram/dannotation.h
index fe1e57d37d..f0080820e5 100644
--- a/src/libs/modelinglib/qmt/diagram/dannotation.h
+++ b/src/libs/modelinglib/qmt/diagram/dannotation.h
@@ -69,8 +69,8 @@ private:
QString m_text;
QPointF m_pos;
QRectF m_rect;
- VisualRole m_visualRole;
- bool m_isAutoSized;
+ VisualRole m_visualRole = RoleNormal;
+ bool m_isAutoSized = true;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dassociation.cpp b/src/libs/modelinglib/qmt/diagram/dassociation.cpp
index 1c62bd388f..f1c2ea9b52 100644
--- a/src/libs/modelinglib/qmt/diagram/dassociation.cpp
+++ b/src/libs/modelinglib/qmt/diagram/dassociation.cpp
@@ -31,8 +31,6 @@
namespace qmt {
DAssociationEnd::DAssociationEnd()
- : m_kind(MAssociationEnd::Association),
- m_isNavigable(false)
{
}
diff --git a/src/libs/modelinglib/qmt/diagram/dassociation.h b/src/libs/modelinglib/qmt/diagram/dassociation.h
index 1da72c36b5..7c914272e5 100644
--- a/src/libs/modelinglib/qmt/diagram/dassociation.h
+++ b/src/libs/modelinglib/qmt/diagram/dassociation.h
@@ -49,8 +49,8 @@ public:
private:
QString m_name;
QString m_cardinality;
- MAssociationEnd::Kind m_kind;
- bool m_isNavigable;
+ MAssociationEnd::Kind m_kind = MAssociationEnd::Association;
+ bool m_isNavigable = false;
};
diff --git a/src/libs/modelinglib/qmt/diagram/dclass.cpp b/src/libs/modelinglib/qmt/diagram/dclass.cpp
index 56337a998e..92103439c5 100644
--- a/src/libs/modelinglib/qmt/diagram/dclass.cpp
+++ b/src/libs/modelinglib/qmt/diagram/dclass.cpp
@@ -31,8 +31,6 @@
namespace qmt {
DClass::DClass()
- : m_templateDisplay(TemplateSmart),
- m_showAllMembers(false)
{
}
diff --git a/src/libs/modelinglib/qmt/diagram/dclass.h b/src/libs/modelinglib/qmt/diagram/dclass.h
index c86d8b335c..159c79a940 100644
--- a/src/libs/modelinglib/qmt/diagram/dclass.h
+++ b/src/libs/modelinglib/qmt/diagram/dclass.h
@@ -65,8 +65,8 @@ private:
QList<QString> m_templateParameters;
QList<MClassMember> m_members;
QSet<Uid> m_visibleMembers;
- TemplateDisplay m_templateDisplay;
- bool m_showAllMembers;
+ TemplateDisplay m_templateDisplay = TemplateSmart;
+ bool m_showAllMembers = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dcomponent.cpp b/src/libs/modelinglib/qmt/diagram/dcomponent.cpp
index 4bee3ad9b9..4fe05aa8a6 100644
--- a/src/libs/modelinglib/qmt/diagram/dcomponent.cpp
+++ b/src/libs/modelinglib/qmt/diagram/dcomponent.cpp
@@ -31,8 +31,6 @@
namespace qmt {
DComponent::DComponent()
- : DObject(),
- m_isPlainShape(false)
{
}
diff --git a/src/libs/modelinglib/qmt/diagram/dcomponent.h b/src/libs/modelinglib/qmt/diagram/dcomponent.h
index 03ef43ecdb..c3602a1015 100644
--- a/src/libs/modelinglib/qmt/diagram/dcomponent.h
+++ b/src/libs/modelinglib/qmt/diagram/dcomponent.h
@@ -42,7 +42,7 @@ public:
void accept(DConstVisitor *visitor) const override;
private:
- bool m_isPlainShape;
+ bool m_isPlainShape = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dconnection.cpp b/src/libs/modelinglib/qmt/diagram/dconnection.cpp
new file mode 100644
index 0000000000..a5611795fc
--- /dev/null
+++ b/src/libs/modelinglib/qmt/diagram/dconnection.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "dconnection.h"
+
+#include "dvisitor.h"
+#include "dconstvisitor.h"
+
+namespace qmt {
+
+DConnectionEnd::DConnectionEnd()
+{
+}
+
+DConnectionEnd::~DConnectionEnd()
+{
+}
+
+void DConnectionEnd::setName(const QString &name)
+{
+ m_name = name;
+}
+
+void DConnectionEnd::setCardinatlity(const QString &cardinality)
+{
+ m_cardinality = cardinality;
+}
+
+void DConnectionEnd::setNavigable(bool navigable)
+{
+ m_isNavigable = navigable;
+}
+
+bool operator==(const DConnectionEnd &lhs, const DConnectionEnd &rhs)
+{
+ if (&lhs == &rhs)
+ return true;
+ return lhs.name() == rhs.name()
+ && lhs.cardinality() == rhs.cardinality()
+ && lhs.isNavigable() == rhs.isNavigable();
+}
+
+bool operator!=(const DConnectionEnd &lhs, const DConnectionEnd &rhs)
+{
+ return !operator==(lhs, rhs);
+}
+
+DConnection::DConnection()
+{
+}
+
+DConnection::~DConnection()
+{
+}
+
+void DConnection::setCustomRelationId(const QString &customRelationId)
+{
+ m_customRelationId = customRelationId;
+}
+
+void DConnection::setEndA(const DConnectionEnd &endA)
+{
+ m_endA = endA;
+}
+
+void DConnection::setEndB(const DConnectionEnd &endB)
+{
+ m_endB = endB;
+}
+
+void DConnection::accept(DVisitor *visitor)
+{
+ visitor->visitDConnection(this);
+}
+
+void DConnection::accept(DConstVisitor *visitor) const
+{
+ visitor->visitDConnection(this);
+}
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dconnection.h b/src/libs/modelinglib/qmt/diagram/dconnection.h
new file mode 100644
index 0000000000..4100142eef
--- /dev/null
+++ b/src/libs/modelinglib/qmt/diagram/dconnection.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "drelation.h"
+
+#include "qmt/model/mconnection.h"
+
+namespace qmt {
+
+class QMT_EXPORT DConnectionEnd
+{
+public:
+ DConnectionEnd();
+ ~DConnectionEnd();
+
+ QString name() const { return m_name; }
+ void setName(const QString &name);
+ QString cardinality() const { return m_cardinality; }
+ void setCardinatlity(const QString &cardinality);
+ bool isNavigable() const { return m_isNavigable; }
+ void setNavigable(bool navigable);
+
+private:
+ QString m_name;
+ QString m_cardinality;
+ bool m_isNavigable = false;
+};
+
+bool operator==(const DConnectionEnd &lhs, const DConnectionEnd &rhs);
+bool operator!=(const DConnectionEnd &lhs, const DConnectionEnd &rhs);
+
+class QMT_EXPORT DConnection : public DRelation
+{
+public:
+ DConnection();
+ ~DConnection() override;
+
+ QString customRelationId() const { return m_customRelationId; }
+ void setCustomRelationId(const QString &customRelationId);
+ DConnectionEnd endA() const { return m_endA; }
+ void setEndA(const DConnectionEnd &endA);
+ DConnectionEnd endB() const { return m_endB; }
+ void setEndB(const DConnectionEnd &endB);
+
+ void accept(DVisitor *visitor) override;
+ void accept(DConstVisitor *visitor) const override;
+
+private:
+ QString m_customRelationId;
+ DConnectionEnd m_endA;
+ DConnectionEnd m_endB;
+};
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dconstvisitor.h b/src/libs/modelinglib/qmt/diagram/dconstvisitor.h
index 23bdb91d58..a8f6032aa5 100644
--- a/src/libs/modelinglib/qmt/diagram/dconstvisitor.h
+++ b/src/libs/modelinglib/qmt/diagram/dconstvisitor.h
@@ -38,8 +38,10 @@ class DRelation;
class DInheritance;
class DDependency;
class DAssociation;
+class DConnection;
class DAnnotation;
class DBoundary;
+class DSwimlane;
class DConstVisitor
{
@@ -57,8 +59,10 @@ public:
virtual void visitDInheritance(const DInheritance *inheritance) = 0;
virtual void visitDDependency(const DDependency *dependency) = 0;
virtual void visitDAssociation(const DAssociation *association) = 0;
+ virtual void visitDConnection(const DConnection *connection) = 0;
virtual void visitDAnnotation(const DAnnotation *annotation) = 0;
virtual void visitDBoundary(const DBoundary *boundary) = 0;
+ virtual void visitDSwimlane(const DSwimlane *swimlane) = 0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/ddependency.cpp b/src/libs/modelinglib/qmt/diagram/ddependency.cpp
index 8706ebc4ff..1a0e5136c9 100644
--- a/src/libs/modelinglib/qmt/diagram/ddependency.cpp
+++ b/src/libs/modelinglib/qmt/diagram/ddependency.cpp
@@ -31,7 +31,6 @@
namespace qmt {
DDependency::DDependency()
- : m_direction(MDependency::AToB)
{
}
diff --git a/src/libs/modelinglib/qmt/diagram/ddependency.h b/src/libs/modelinglib/qmt/diagram/ddependency.h
index 7c3c712452..6542379a0b 100644
--- a/src/libs/modelinglib/qmt/diagram/ddependency.h
+++ b/src/libs/modelinglib/qmt/diagram/ddependency.h
@@ -50,7 +50,7 @@ public:
void accept(DConstVisitor *visitor) const override;
private:
- MDependency::Direction m_direction;
+ MDependency::Direction m_direction = MDependency::AToB;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/ditem.cpp b/src/libs/modelinglib/qmt/diagram/ditem.cpp
index d9a33dc602..3c7241575f 100644
--- a/src/libs/modelinglib/qmt/diagram/ditem.cpp
+++ b/src/libs/modelinglib/qmt/diagram/ditem.cpp
@@ -31,8 +31,6 @@
namespace qmt {
DItem::DItem()
- : DObject(),
- m_isShapeEditable(true)
{
}
diff --git a/src/libs/modelinglib/qmt/diagram/ditem.h b/src/libs/modelinglib/qmt/diagram/ditem.h
index 7782e9497d..e6c184bf33 100644
--- a/src/libs/modelinglib/qmt/diagram/ditem.h
+++ b/src/libs/modelinglib/qmt/diagram/ditem.h
@@ -48,7 +48,7 @@ public:
private:
QString m_variety;
QString m_shape;
- bool m_isShapeEditable;
+ bool m_isShapeEditable = true;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dobject.cpp b/src/libs/modelinglib/qmt/diagram/dobject.cpp
index 4405b16554..4111ba929e 100644
--- a/src/libs/modelinglib/qmt/diagram/dobject.cpp
+++ b/src/libs/modelinglib/qmt/diagram/dobject.cpp
@@ -31,14 +31,6 @@
namespace qmt {
DObject::DObject()
- : DElement(),
- m_modelUid(Uid::invalidUid()),
- m_depth(0),
- m_visualPrimaryRole(PrimaryRoleNormal),
- m_visualSecondaryRole(SecondaryRoleNone),
- m_stereotypeDisplay(StereotypeSmart),
- m_isAutoSized(true),
- m_isVisualEmphasized(false)
{
}
diff --git a/src/libs/modelinglib/qmt/diagram/dobject.h b/src/libs/modelinglib/qmt/diagram/dobject.h
index 6e5f85358a..17d22488ab 100644
--- a/src/libs/modelinglib/qmt/diagram/dobject.h
+++ b/src/libs/modelinglib/qmt/diagram/dobject.h
@@ -104,18 +104,18 @@ public:
void accept(DConstVisitor *visitor) const override;
private:
- Uid m_modelUid;
+ Uid m_modelUid = Uid::invalidUid();
QList<QString> m_stereotypes;
QString m_context;
QString m_name;
QPointF m_pos;
QRectF m_rect;
- int m_depth;
- VisualPrimaryRole m_visualPrimaryRole;
- VisualSecondaryRole m_visualSecondaryRole;
- StereotypeDisplay m_stereotypeDisplay;
- bool m_isAutoSized;
- bool m_isVisualEmphasized;
+ int m_depth = 0;
+ VisualPrimaryRole m_visualPrimaryRole = PrimaryRoleNormal;
+ VisualSecondaryRole m_visualSecondaryRole = SecondaryRoleNone;
+ StereotypeDisplay m_stereotypeDisplay = StereotypeSmart;
+ bool m_isAutoSized = true;
+ bool m_isVisualEmphasized = false;
};
} // namespace qmt
diff --git a/src/libs/sqlite/columndefinition.cpp b/src/libs/modelinglib/qmt/diagram/dswimlane.cpp
index 2d2d83844c..41d29a32b8 100644
--- a/src/libs/sqlite/columndefinition.cpp
+++ b/src/libs/modelinglib/qmt/diagram/dswimlane.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Jochen Becher
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,51 +23,64 @@
**
****************************************************************************/
-#include "columndefinition.h"
+#include "dswimlane.h"
-namespace Internal {
+#include "dvisitor.h"
+#include "dconstvisitor.h"
-void ColumnDefinition::setName(const Utf8String &name)
+namespace qmt {
+
+DSwimlane::DSwimlane()
+ : DElement()
{
- name_ = name;
}
-const Utf8String &ColumnDefinition::name() const
+DSwimlane::DSwimlane(const DSwimlane &rhs)
+ : DElement(rhs),
+ m_text(rhs.m_text),
+ m_horizontal(rhs.m_horizontal),
+ m_pos(rhs.m_pos)
{
- return name_;
}
-void ColumnDefinition::setType(ColumnType type)
+DSwimlane::~DSwimlane()
{
- type_ = type;
}
-ColumnType ColumnDefinition::type() const
+DSwimlane &DSwimlane::operator=(const DSwimlane &rhs)
{
- return type_;
+ if (this != &rhs) {
+ DElement::operator=(rhs);
+ m_text = rhs.m_text;
+ m_horizontal = rhs.m_horizontal;
+ m_pos = rhs.m_pos;
+ }
+ return *this;
}
-Utf8String ColumnDefinition::typeString() const
+void DSwimlane::setText(const QString &text)
{
- switch (type_) {
- case ColumnType::None: return Utf8String();
- case ColumnType::Numeric: return Utf8StringLiteral("NUMERIC");
- case ColumnType::Integer: return Utf8StringLiteral("INTEGER");
- case ColumnType::Real: return Utf8StringLiteral("REAL");
- case ColumnType::Text: return Utf8StringLiteral("TEXT");
- }
+ m_text = text;
+}
- Q_UNREACHABLE();
+void DSwimlane::setHorizontal(bool horizontal)
+{
+ m_horizontal = horizontal;
}
-void ColumnDefinition::setIsPrimaryKey(bool isPrimaryKey)
+void DSwimlane::setPos(qreal pos)
{
- isPrimaryKey_ = isPrimaryKey;
+ m_pos = pos;
}
-bool ColumnDefinition::isPrimaryKey() const
+void DSwimlane::accept(DVisitor *visitor)
{
- return isPrimaryKey_;
+ visitor->visitDSwimlane(this);
}
+void DSwimlane::accept(DConstVisitor *visitor) const
+{
+ visitor->visitDSwimlane(this);
}
+
+} // namespoace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dswimlane.h b/src/libs/modelinglib/qmt/diagram/dswimlane.h
new file mode 100644
index 0000000000..c1b8796063
--- /dev/null
+++ b/src/libs/modelinglib/qmt/diagram/dswimlane.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "delement.h"
+
+namespace qmt {
+
+class QMT_EXPORT DSwimlane : public DElement
+{
+public:
+ DSwimlane();
+ DSwimlane(const DSwimlane &rhs);
+ ~DSwimlane();
+
+ DSwimlane &operator=(const DSwimlane &rhs);
+
+ Uid modelUid() const override { return Uid::invalidUid(); }
+ QString text() const { return m_text; }
+ void setText(const QString &text);
+ bool isHorizontal() const { return m_horizontal; }
+ void setHorizontal(bool horizontal);
+ qreal pos() const { return m_pos; }
+ void setPos(qreal pos);
+
+ void accept(DVisitor *visitor) override;
+ void accept(DConstVisitor *visitor) const override;
+
+private:
+ QString m_text;
+ bool m_horizontal = false; // false: vertical, true: horizontal
+ qreal m_pos = 0.0;
+};
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram/dvisitor.h b/src/libs/modelinglib/qmt/diagram/dvisitor.h
index bb9e7873ee..01adf15b70 100644
--- a/src/libs/modelinglib/qmt/diagram/dvisitor.h
+++ b/src/libs/modelinglib/qmt/diagram/dvisitor.h
@@ -38,8 +38,10 @@ class DRelation;
class DInheritance;
class DDependency;
class DAssociation;
+class DConnection;
class DAnnotation;
class DBoundary;
+class DSwimlane;
class DVisitor
{
@@ -57,8 +59,10 @@ public:
virtual void visitDInheritance(DInheritance *inheritance) = 0;
virtual void visitDDependency(DDependency *dependency) = 0;
virtual void visitDAssociation(DAssociation *association) = 0;
+ virtual void visitDConnection(DConnection *connection) = 0;
virtual void visitDAnnotation(DAnnotation *annotation) = 0;
virtual void visitDBoundary(DBoundary *boundary) = 0;
+ virtual void visitDSwimlane(DSwimlane *swimlane) = 0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp
index c9e2067c8b..d882c81eef 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp
+++ b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp
@@ -36,14 +36,15 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
+#include "qmt/diagram/dswimlane.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
DCloneVisitor::DCloneVisitor()
- : m_cloned(0)
{
}
@@ -122,6 +123,13 @@ void DCloneVisitor::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
+void DCloneVisitor::visitDConnection(const DConnection *connection)
+{
+ if (!m_cloned)
+ m_cloned = new DConnection(*connection);
+ visitDRelation(connection);
+}
+
void DCloneVisitor::visitDAnnotation(const DAnnotation *annotation)
{
if (!m_cloned)
@@ -136,8 +144,15 @@ void DCloneVisitor::visitDBoundary(const DBoundary *boundary)
visitDElement(boundary);
}
+void DCloneVisitor::visitDSwimlane(const DSwimlane *swimlane)
+{
+ if (!m_cloned)
+ m_cloned = new DSwimlane(*swimlane);
+ visitDElement(swimlane);
+}
+
+
DCloneDeepVisitor::DCloneDeepVisitor()
- : m_cloned(0)
{
}
@@ -215,6 +230,13 @@ void DCloneDeepVisitor::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
+void DCloneDeepVisitor::visitDConnection(const DConnection *connection)
+{
+ if (!m_cloned)
+ m_cloned = new DConnection(*connection);
+ visitDRelation(connection);
+}
+
void DCloneDeepVisitor::visitDAnnotation(const DAnnotation *annotation)
{
if (!m_cloned)
@@ -229,4 +251,11 @@ void DCloneDeepVisitor::visitDBoundary(const DBoundary *boundary)
visitDElement(boundary);
}
+void DCloneDeepVisitor::visitDSwimlane(const DSwimlane *swimlane)
+{
+ if (!m_cloned)
+ m_cloned = new DSwimlane(*swimlane);
+ visitDElement(swimlane);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h
index c69534b542..82877bef58 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h
+++ b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h
@@ -48,11 +48,13 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
+ void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
+ void visitDSwimlane(const DSwimlane *swimlane) override;
private:
- DElement *m_cloned;
+ DElement *m_cloned = nullptr;
};
class QMT_EXPORT DCloneDeepVisitor : public DConstVisitor
@@ -73,11 +75,13 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
+ void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
+ void visitDSwimlane(const DSwimlane *swimlane) override;
private:
- DElement *m_cloned;
+ DElement *m_cloned = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dfactory.cpp b/src/libs/modelinglib/qmt/diagram_controller/dfactory.cpp
index 02745bf71a..e87fb8ce5e 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dfactory.cpp
+++ b/src/libs/modelinglib/qmt/diagram_controller/dfactory.cpp
@@ -36,6 +36,7 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/model/melement.h"
#include "qmt/model/mobject.h"
@@ -53,7 +54,6 @@
namespace qmt {
DFactory::DFactory()
- : m_product(0)
{
}
@@ -66,7 +66,7 @@ void DFactory::visitMElement(const MElement *element)
void DFactory::visitMObject(const MObject *object)
{
auto diagramObject = dynamic_cast<DObject *>(m_product);
- QMT_CHECK(diagramObject);
+ QMT_ASSERT(diagramObject, return);
diagramObject->setModelUid(object->uid());
visitMElement(object);
}
@@ -120,7 +120,7 @@ void DFactory::visitMItem(const MItem *item)
void DFactory::visitMRelation(const MRelation *relation)
{
auto diagramRelation = dynamic_cast<DRelation *>(m_product);
- QMT_CHECK(diagramRelation);
+ QMT_ASSERT(diagramRelation, return);
diagramRelation->setModelUid(relation->uid());
visitMElement(relation);
}
@@ -149,4 +149,12 @@ void DFactory::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
+void DFactory::visitMConnection(const MConnection *connection)
+{
+ QMT_CHECK(!m_product);
+ auto diagramConnection = new DConnection();
+ m_product = diagramConnection;
+ visitMRelation(connection);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dfactory.h b/src/libs/modelinglib/qmt/diagram_controller/dfactory.h
index 5d5e48ded8..c55879c73e 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dfactory.h
+++ b/src/libs/modelinglib/qmt/diagram_controller/dfactory.h
@@ -51,9 +51,10 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
+ void visitMConnection(const MConnection *connection) override;
private:
- DElement *m_product;
+ DElement *m_product = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp
index 16902bc0d4..20531bb85c 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp
+++ b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp
@@ -36,8 +36,10 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
+#include "qmt/diagram/dswimlane.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
@@ -59,7 +61,7 @@ void DFlatAssignmentVisitor::visitDObject(const DObject *object)
{
visitDElement(object);
auto target = dynamic_cast<DObject *>(m_target);
- QMT_CHECK(target);
+ QMT_ASSERT(target, return);
target->setStereotypes(object->stereotypes());
target->setName(object->name());
target->setPos(object->pos());
@@ -81,7 +83,7 @@ void DFlatAssignmentVisitor::visitDClass(const DClass *klass)
{
visitDObject(klass);
auto target = dynamic_cast<DClass *>(m_target);
- QMT_CHECK(target);
+ QMT_ASSERT(target, return);
target->setUmlNamespace(klass->umlNamespace());
target->setTemplateParameters(klass->templateParameters());
target->setTemplateDisplay(klass->templateDisplay());
@@ -94,7 +96,7 @@ void DFlatAssignmentVisitor::visitDComponent(const DComponent *component)
{
visitDObject(component);
auto target = dynamic_cast<DComponent *>(m_target);
- QMT_CHECK(target);
+ QMT_ASSERT(target, return);
target->setPlainShape(component->isPlainShape());
}
@@ -107,7 +109,7 @@ void DFlatAssignmentVisitor::visitDItem(const DItem *item)
{
visitDObject(item);
auto target = dynamic_cast<DItem *>(m_target);
- QMT_CHECK(target);
+ QMT_ASSERT(target, return);
target->setVariety(target->variety());
target->setShapeEditable(target->isShapeEditable());
target->setShape(target->shape());
@@ -117,7 +119,7 @@ void DFlatAssignmentVisitor::visitDRelation(const DRelation *relation)
{
visitDElement(relation);
auto target = dynamic_cast<DRelation *>(m_target);
- QMT_CHECK(target);
+ QMT_ASSERT(target, return);
target->setStereotypes(relation->stereotypes());
target->setIntermediatePoints(relation->intermediatePoints());
}
@@ -131,7 +133,7 @@ void DFlatAssignmentVisitor::visitDDependency(const DDependency *dependency)
{
visitDRelation(dependency);
auto target = dynamic_cast<DDependency *>(m_target);
- QMT_CHECK(target);
+ QMT_ASSERT(target, return);
target->setDirection(dependency->direction());
}
@@ -139,15 +141,27 @@ void DFlatAssignmentVisitor::visitDAssociation(const DAssociation *association)
{
visitDRelation(association);
auto target = dynamic_cast<DAssociation *>(m_target);
- QMT_CHECK(target);
+ QMT_ASSERT(target, return);
target->setEndA(association->endA());
target->setEndB(association->endB());
+ // TODO assign assoziation class?
+}
+
+void DFlatAssignmentVisitor::visitDConnection(const DConnection *connection)
+{
+ visitDRelation(connection);
+ auto target = dynamic_cast<DConnection *>(m_target);
+ QMT_ASSERT(target, return);
+ target->setCustomRelationId(connection->customRelationId());
+ target->setEndA(connection->endA());
+ target->setEndB(connection->endB());
}
void DFlatAssignmentVisitor::visitDAnnotation(const DAnnotation *annotation)
{
visitDElement(annotation);
auto target = dynamic_cast<DAnnotation *>(m_target);
+ QMT_ASSERT(target, return);
target->setText(annotation->text());
target->setPos(annotation->pos());
target->setRect(annotation->rect());
@@ -159,9 +173,20 @@ void DFlatAssignmentVisitor::visitDBoundary(const DBoundary *boundary)
{
visitDElement(boundary);
auto target = dynamic_cast<DBoundary *>(m_target);
+ QMT_ASSERT(target, return);
target->setText(boundary->text());
target->setPos(boundary->pos());
target->setRect(boundary->rect());
}
+void DFlatAssignmentVisitor::visitDSwimlane(const DSwimlane *swimlane)
+{
+ visitDElement(swimlane);
+ auto target = dynamic_cast<DSwimlane *>(m_target);
+ QMT_ASSERT(target, return);
+ target->setText(swimlane->text());
+ target->setHorizontal(swimlane->isHorizontal());
+ target->setPos(swimlane->pos());
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h
index 8c2537ab05..0109c3b753 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h
+++ b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h
@@ -46,11 +46,13 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
+ void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
+ void visitDSwimlane(const DSwimlane *swimlane) override;
private:
- DElement *m_target;
+ DElement *m_target = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp
index d2111cbac5..a794de55a7 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp
+++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp
@@ -55,7 +55,7 @@ class DiagramController::Clone
public:
Uid m_elementKey;
int m_indexOfElement = -1;
- DElement *m_clonedElement = 0;
+ DElement *m_clonedElement = nullptr;
};
class DiagramController::DiagramUndoCommand : public UndoCommand
@@ -84,7 +84,7 @@ protected:
}
private:
- DiagramController *m_diagramController = 0;
+ DiagramController *m_diagramController = nullptr;
Uid m_diagramKey;
};
@@ -151,7 +151,7 @@ private:
MDiagram *diagram = this->diagram();
foreach (DElement *clonedElement, m_clonedElements) {
DElement *activeElement = diagramController->findElement(clonedElement->uid(), diagram);
- QMT_CHECK(activeElement);
+ QMT_ASSERT(activeElement, return);
int row = diagram->diagramElements().indexOf(activeElement);
emit diagramController->beginUpdateElement(row, diagram);
// clone active element
@@ -198,9 +198,9 @@ protected:
Clone &clone = m_clonedElements[i];
QMT_CHECK(!clone.m_clonedElement);
DElement *activeElement = diagramController->findElement(clone.m_elementKey, diagram);
- QMT_CHECK(activeElement);
+ QMT_ASSERT(activeElement, return);
clone.m_indexOfElement = diagram->diagramElements().indexOf(activeElement);
- QMT_CHECK(clone.m_indexOfElement >= 0);
+ QMT_ASSERT(clone.m_indexOfElement >= 0, return);
emit diagramController->beginRemoveElement(clone.m_indexOfElement, diagram);
DCloneDeepVisitor cloneVisitor;
activeElement->accept(&cloneVisitor);
@@ -221,11 +221,11 @@ protected:
bool inserted = false;
for (int i = m_clonedElements.count() - 1; i >= 0; --i) {
Clone &clone = m_clonedElements[i];
- QMT_CHECK(clone.m_clonedElement);
+ QMT_ASSERT(clone.m_clonedElement, return);
QMT_CHECK(clone.m_clonedElement->uid() == clone.m_elementKey);
emit diagramController->beginInsertElement(clone.m_indexOfElement, diagram);
diagram->insertDiagramElement(clone.m_indexOfElement, clone.m_clonedElement);
- clone.m_clonedElement = 0;
+ clone.m_clonedElement = nullptr;
emit diagramController->endInsertElement(clone.m_indexOfElement, diagram);
inserted = true;
}
@@ -287,7 +287,7 @@ public:
DCloneDeepVisitor visitor;
element->accept(&visitor);
clone.m_clonedElement = visitor.cloned();
- QMT_CHECK(clone.m_clonedElement);
+ QMT_ASSERT(clone.m_clonedElement, return);
m_clonedElements.append(clone);
}
@@ -321,13 +321,11 @@ public:
}
private:
- QList<MDiagram *> *m_allDiagrams = 0;
+ QList<MDiagram *> *m_allDiagrams = nullptr;
};
DiagramController::DiagramController(QObject *parent)
- : QObject(parent),
- m_modelController(nullptr),
- m_undoController(nullptr)
+ : QObject(parent)
{
}
@@ -338,8 +336,8 @@ DiagramController::~DiagramController()
void DiagramController::setModelController(ModelController *modelController)
{
if (m_modelController) {
- disconnect(m_modelController, 0, this, 0);
- m_modelController = 0;
+ disconnect(m_modelController, nullptr, this, nullptr);
+ m_modelController = nullptr;
}
if (modelController) {
m_modelController = modelController;
@@ -424,7 +422,7 @@ void DiagramController::removeElement(DElement *element, MDiagram *diagram)
DElement *DiagramController::findElement(const Uid &key, const MDiagram *diagram) const
{
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return nullptr);
return diagram->findDiagramElement(key);
}
@@ -432,7 +430,7 @@ DElement *DiagramController::findElement(const Uid &key, const MDiagram *diagram
bool DiagramController::hasDelegate(const MElement *modelElement, const MDiagram *diagram) const
{
// PERFORM smarter implementation after map is introduced
- return findDelegate(modelElement, diagram) != 0;
+ return findDelegate(modelElement, diagram) != nullptr;
}
DElement *DiagramController::findDelegate(const MElement *modelElement, const MDiagram *diagram) const
@@ -442,7 +440,7 @@ DElement *DiagramController::findDelegate(const MElement *modelElement, const MD
if (diagramElement->modelUid().isValid() && diagramElement->modelUid() == modelElement->uid())
return diagramElement;
}
- return 0;
+ return nullptr;
}
void DiagramController::startUpdateElement(DElement *element, MDiagram *diagram, UpdateAction updateAction)
@@ -476,7 +474,7 @@ DContainer DiagramController::cutElements(const DSelection &diagramSelection, MD
DContainer DiagramController::copyElements(const DSelection &diagramSelection, const MDiagram *diagram)
{
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return DContainer());
DReferences simplifiedSelection = simplify(diagramSelection, diagram);
DContainer copiedElements;
@@ -491,7 +489,7 @@ DContainer DiagramController::copyElements(const DSelection &diagramSelection, c
void DiagramController::pasteElements(const DContainer &diagramContainer, MDiagram *diagram)
{
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return);
// clone all elements and renew their keys
QHash<Uid, Uid> renewedKeys;
@@ -593,7 +591,7 @@ void DiagramController::onBeginUpdateObject(int row, const MObject *parent)
void DiagramController::onEndUpdateObject(int row, const MObject *parent)
{
MObject *modelObject = m_modelController->object(row, parent);
- QMT_CHECK(modelObject);
+ QMT_ASSERT(modelObject, return);
auto modelPackage = dynamic_cast<MPackage *>(modelObject);
foreach (MDiagram *diagram, m_allDiagrams) {
DObject *object = findDelegate<DObject>(modelObject, diagram);
@@ -622,7 +620,7 @@ void DiagramController::onBeginInsertObject(int row, const MObject *owner)
void DiagramController::onEndInsertObject(int row, const MObject *owner)
{
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
MObject *modelObject = m_modelController->object(row, owner);
if (auto modelDiagram = dynamic_cast<MDiagram *>(modelObject)) {
@@ -634,7 +632,7 @@ void DiagramController::onEndInsertObject(int row, const MObject *owner)
void DiagramController::onBeginRemoveObject(int row, const MObject *parent)
{
- QMT_CHECK(parent);
+ QMT_ASSERT(parent, return);
MObject *modelObject = m_modelController->object(row, parent);
removeObjects(modelObject);
@@ -658,7 +656,7 @@ void DiagramController::onEndMoveObject(int row, const MObject *owner)
// if diagram was moved update all elements because of changed context
MObject *modelObject = m_modelController->object(row, owner);
- QMT_CHECK(modelObject);
+ QMT_ASSERT(modelObject, return);
auto modelDiagram = dynamic_cast<MDiagram *>(modelObject);
if (modelDiagram) {
emit beginResetDiagram(modelDiagram);
@@ -691,7 +689,7 @@ void DiagramController::onEndUpdateRelation(int row, const MObject *owner)
void DiagramController::onBeginRemoveRelation(int row, const MObject *owner)
{
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
MRelation *modelRelation = owner->relations().at(row);
removeRelations(modelRelation);
@@ -719,7 +717,7 @@ void DiagramController::onEndMoveRelation(int row, const MObject *owner)
void DiagramController::deleteElements(const DSelection &diagramSelection, MDiagram *diagram,
const QString &commandLabel)
{
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return);
DReferences simplifiedSelection = simplify(diagramSelection, diagram);
if (simplifiedSelection.elements().isEmpty())
@@ -757,7 +755,7 @@ DElement *DiagramController::findElementOnAnyDiagram(const Uid &uid)
if (element)
return element;
}
- return 0;
+ return nullptr;
}
void DiagramController::removeObjects(MObject *modelObject)
@@ -818,7 +816,7 @@ void DiagramController::removeRelations(DElement *element, MDiagram *diagram)
void DiagramController::renewElementKey(DElement *element, QHash<Uid, Uid> *renewedKeys)
{
- QMT_CHECK(renewedKeys);
+ QMT_ASSERT(renewedKeys, return);
if (element) {
DElement *existingElementOnDiagram = findElementOnAnyDiagram(element->uid());
@@ -850,7 +848,7 @@ void DiagramController::updateElementFromModel(DElement *element, const MDiagram
DUpdateVisitor visitor(element, diagram);
MElement *melement = m_modelController->findElement(element->modelUid());
- QMT_CHECK(melement);
+ QMT_ASSERT(melement, return);
if (emitUpdateSignal) {
visitor.setCheckNeedsUpdate(true);
@@ -890,7 +888,7 @@ DReferences DiagramController::simplify(const DSelection &diagramSelection, cons
MElement *DiagramController::delegatedElement(const DElement *element) const
{
if (!element->modelUid().isValid())
- return 0;
+ return nullptr;
return m_modelController->findElement(element->modelUid());
}
@@ -925,7 +923,7 @@ void DiagramController::verifyDiagramsIntegrity()
FindDiagramsVisitor visitor(&allDiagrams);
m_modelController->rootPackage()->accept(&visitor);
}
- QMT_CHECK(allDiagrams == m_allDiagrams);
+ QMT_ASSERT(allDiagrams == m_allDiagrams, return);
foreach (const MDiagram *diagram, allDiagrams)
verifyDiagramIntegrity(diagram);
}
@@ -936,27 +934,27 @@ void DiagramController::verifyDiagramIntegrity(const MDiagram *diagram)
QHash<Uid, const DElement *> delementsMap;
foreach (const DElement *delement, diagram->diagramElements()) {
delementsMap.insert(delement->uid(), delement);
- if (dynamic_cast<const DObject *>(delement) != 0 || dynamic_cast<const DRelation *>(delement) != 0) {
- QMT_CHECK(delement->modelUid().isValid());
- QMT_CHECK(m_modelController->findElement(delement->modelUid()) != 0);
- if (!delement->modelUid().isValid() || m_modelController->findElement(delement->modelUid()) == 0) {
+ if (dynamic_cast<const DObject *>(delement) || dynamic_cast<const DRelation *>(delement)) {
+ QMT_ASSERT(delement->modelUid().isValid(), return);
+ QMT_ASSERT(m_modelController->findElement(delement->modelUid()), return);
+ if (!delement->modelUid().isValid() || !m_modelController->findElement(delement->modelUid())) {
if (const DObject *dobject = dynamic_cast<const DObject *>(delement))
qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": object" << dobject->name() << dobject->uid().toString() << "has invalid reference to model element.";
else if (const DRelation *drelation = dynamic_cast<const DRelation *>(delement))
qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": relation" << drelation->uid().toString() << "has invalid refeference to model element.";
}
} else {
- QMT_CHECK(!delement->modelUid().isValid());
+ QMT_ASSERT(!delement->modelUid().isValid(), return);
}
}
foreach (const DElement *delement, diagram->diagramElements()) {
if (const DRelation *drelation = dynamic_cast<const DRelation *>(delement)) {
- QMT_CHECK(drelation->endAUid().isValid());
- QMT_CHECK(delementsMap.contains(drelation->endAUid()));
+ QMT_ASSERT(drelation->endAUid().isValid(), return);
+ QMT_ASSERT(delementsMap.contains(drelation->endAUid()), return);
if (!drelation->endAUid().isValid() || !delementsMap.contains(drelation->endAUid()))
qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": relation" << drelation->uid().toString() << "has invalid end A.";
- QMT_CHECK(drelation->endBUid().isValid());
- QMT_CHECK(delementsMap.contains(drelation->endBUid()));
+ QMT_ASSERT(drelation->endBUid().isValid(), return);
+ QMT_ASSERT(delementsMap.contains(drelation->endBUid()), return);
if (!drelation->endBUid().isValid() || !delementsMap.contains(drelation->endBUid()))
qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": relation" << drelation->uid().toString() << "has invalid end B.";
}
diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h
index 1f688198a4..aa09636e5e 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h
+++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h
@@ -65,7 +65,7 @@ private:
class FindDiagramsVisitor;
public:
- explicit DiagramController(QObject *parent = 0);
+ explicit DiagramController(QObject *parent = nullptr);
~DiagramController() override;
signals:
@@ -167,8 +167,8 @@ private:
void verifyDiagramsIntegrity();
void verifyDiagramIntegrity(const MDiagram *diagram);
- ModelController *m_modelController;
- UndoController *m_undoController;
+ ModelController *m_modelController = nullptr;
+ UndoController *m_undoController = nullptr;
QList<MDiagram *> m_allDiagrams;
};
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp
index 3454de2602..4b99d5e69a 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp
+++ b/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp
@@ -32,6 +32,7 @@
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/model/melement.h"
#include "qmt/model/mobject.h"
@@ -72,7 +73,7 @@ void DUpdateVisitor::visitMElement(const MElement *element)
void DUpdateVisitor::visitMObject(const MObject *object)
{
auto dobject = dynamic_cast<DObject *>(m_target);
- QMT_CHECK(dobject);
+ QMT_ASSERT(dobject, return);
if (isUpdating(object->stereotypes() != dobject->stereotypes()))
dobject->setStereotypes(object->stereotypes());
const MObject *objectOwner = object->owner();
@@ -107,7 +108,7 @@ void DUpdateVisitor::visitMPackage(const MPackage *package)
void DUpdateVisitor::visitMClass(const MClass *klass)
{
auto dclass = dynamic_cast<DClass *>(m_target);
- QMT_CHECK(dclass);
+ QMT_ASSERT(dclass, return);
if (isUpdating(klass->umlNamespace() != dclass->umlNamespace()))
dclass->setUmlNamespace(klass->umlNamespace());
if (isUpdating(klass->templateParameters() != dclass->templateParameters()))
@@ -135,7 +136,7 @@ void DUpdateVisitor::visitMCanvasDiagram(const MCanvasDiagram *diagram)
void DUpdateVisitor::visitMItem(const MItem *item)
{
auto ditem = dynamic_cast<DItem *>(m_target);
- QMT_CHECK(ditem);
+ QMT_ASSERT(ditem, return);
if (isUpdating(item->isShapeEditable() != ditem->isShapeEditable()))
ditem->setShapeEditable(item->isShapeEditable());
if (isUpdating(item->variety() != ditem->variety()))
@@ -146,7 +147,7 @@ void DUpdateVisitor::visitMItem(const MItem *item)
void DUpdateVisitor::visitMRelation(const MRelation *relation)
{
auto drelation = dynamic_cast<DRelation *>(m_target);
- QMT_CHECK(drelation);
+ QMT_ASSERT(drelation, return);
if (isUpdating(relation->stereotypes() != drelation->stereotypes()))
drelation->setStereotypes(relation->stereotypes());
if (isUpdating(relation->name() != drelation->name()))
@@ -154,8 +155,8 @@ void DUpdateVisitor::visitMRelation(const MRelation *relation)
// TODO improve performance of MDiagram::findDiagramElement
DObject *endAObject = dynamic_cast<DObject *>(m_diagram->findDiagramElement(drelation->endAUid()));
if (!endAObject || relation->endAUid() != endAObject->modelUid()) {
- isUpdating(true);
- endAObject = 0;
+ (void) isUpdating(true);
+ endAObject = nullptr;
// TODO use DiagramController::findDelegate (and improve performance of that method)
foreach (DElement *diagramElement, m_diagram->diagramElements()) {
if (diagramElement->modelUid().isValid() && diagramElement->modelUid() == relation->endAUid()) {
@@ -170,8 +171,8 @@ void DUpdateVisitor::visitMRelation(const MRelation *relation)
}
DObject *endBObject = dynamic_cast<DObject *>(m_diagram->findDiagramElement(drelation->endBUid()));
if (!endBObject || relation->endBUid() != endBObject->modelUid()) {
- isUpdating(true);
- endBObject = 0;
+ (void) isUpdating(true);
+ endBObject = nullptr;
// TODO use DiagramController::findDelegate
foreach (DElement *diagramElement, m_diagram->diagramElements()) {
if (diagramElement->modelUid().isValid() && diagramElement->modelUid() == relation->endBUid()) {
@@ -190,7 +191,7 @@ void DUpdateVisitor::visitMRelation(const MRelation *relation)
void DUpdateVisitor::visitMDependency(const MDependency *dependency)
{
auto ddependency = dynamic_cast<DDependency *>(m_target);
- QMT_CHECK(ddependency);
+ QMT_ASSERT(ddependency, return);
if (isUpdating(dependency->direction() != ddependency->direction()))
ddependency->setDirection(dependency->direction());
visitMRelation(dependency);
@@ -204,7 +205,7 @@ void DUpdateVisitor::visitMInheritance(const MInheritance *inheritance)
void DUpdateVisitor::visitMAssociation(const MAssociation *association)
{
auto dassociation = dynamic_cast<DAssociation *>(m_target);
- QMT_CHECK(dassociation);
+ QMT_ASSERT(dassociation, return);
DAssociationEnd endA;
endA.setName(association->endA().name());
endA.setCardinatlity(association->endA().cardinality());
@@ -222,6 +223,27 @@ void DUpdateVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
+void DUpdateVisitor::visitMConnection(const MConnection *connection)
+{
+ auto dconnection = dynamic_cast<DConnection *>(m_target);
+ QMT_ASSERT(dconnection, return);
+ if (isUpdating(connection->customRelationId() != dconnection->customRelationId()))
+ dconnection->setCustomRelationId(connection->customRelationId());
+ DConnectionEnd endA;
+ endA.setName(connection->endA().name());
+ endA.setCardinatlity(connection->endA().cardinality());
+ endA.setNavigable(connection->endA().isNavigable());
+ if (isUpdating(endA != dconnection->endA()))
+ dconnection->setEndA(endA);
+ DConnectionEnd endB;
+ endB.setName(connection->endB().name());
+ endB.setCardinatlity(connection->endB().cardinality());
+ endB.setNavigable(connection->endB().isNavigable());
+ if (isUpdating(endB != dconnection->endB()))
+ dconnection->setEndB(endB);
+ visitMRelation(connection);
+}
+
bool DUpdateVisitor::isUpdating(bool valueChanged)
{
if (m_checkNeedsUpdate) {
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.h b/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.h
index e88e9eed4b..f435a39705 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.h
+++ b/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.h
@@ -52,14 +52,15 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
+ void visitMConnection(const MConnection *connection) override;
private:
bool isUpdating(bool valueChanged);
- DElement *m_target;
- const MDiagram *m_diagram;
- bool m_checkNeedsUpdate;
- bool m_isUpdateNeeded;
+ DElement *m_target = nullptr;
+ const MDiagram *m_diagram = nullptr;
+ bool m_checkNeedsUpdate = false;
+ bool m_isUpdateNeeded = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp
index 09b7c92d50..56fdfe2cb4 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp
+++ b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp
@@ -36,8 +36,10 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
+#include "qmt/diagram/dswimlane.h"
namespace qmt {
@@ -100,6 +102,11 @@ void DVoidVisitor::visitDAssociation(DAssociation *association)
visitDRelation(association);
}
+void DVoidVisitor::visitDConnection(DConnection *connection)
+{
+ visitDRelation(connection);
+}
+
void DVoidVisitor::visitDAnnotation(DAnnotation *annotation)
{
visitDElement(annotation);
@@ -110,6 +117,11 @@ void DVoidVisitor::visitDBoundary(DBoundary *boundary)
visitDElement(boundary);
}
+void DVoidVisitor::visitDSwimlane(DSwimlane *swimlane)
+{
+ visitDElement(swimlane);
+}
+
DConstVoidVisitor::DConstVoidVisitor()
{
}
@@ -169,6 +181,11 @@ void DConstVoidVisitor::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
+void DConstVoidVisitor::visitDConnection(const DConnection *connection)
+{
+ visitDRelation(connection);
+}
+
void DConstVoidVisitor::visitDAnnotation(const DAnnotation *annotation)
{
visitDElement(annotation);
@@ -179,4 +196,9 @@ void DConstVoidVisitor::visitDBoundary(const DBoundary *boundary)
visitDElement(boundary);
}
+void DConstVoidVisitor::visitDSwimlane(const DSwimlane *swimlane)
+{
+ visitDElement(swimlane);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h
index 4519c1a943..7050b7adbf 100644
--- a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h
+++ b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h
@@ -47,8 +47,10 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
+ void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;
+ void visitDSwimlane(DSwimlane *swimlane) override;
};
class QMT_EXPORT DConstVoidVisitor : public DConstVisitor
@@ -67,8 +69,10 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
+ void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
+ void visitDSwimlane(const DSwimlane *swimlane) override;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/capabilities/intersectionable.h b/src/libs/modelinglib/qmt/diagram_scene/capabilities/intersectionable.h
index bb7b0ec81c..eb1371ea98 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/capabilities/intersectionable.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/capabilities/intersectionable.h
@@ -40,7 +40,7 @@ public:
virtual ~IIntersectionable() { }
virtual bool intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint,
- QLineF *intersectionLine = 0) const = 0;
+ QLineF *intersectionLine = nullptr) const = 0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h b/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h
index 5afcf64efd..8da587bc56 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h
@@ -25,6 +25,8 @@
#pragma once
+#include <QRectF>
+
namespace qmt {
class ISelectable
@@ -36,6 +38,8 @@ public:
virtual void setSecondarySelected(bool secondarySelected) = 0;
virtual bool isFocusSelected() const = 0;
virtual void setFocusSelected(bool focusSelected) = 0;
+ virtual QRectF getSecondarySelectionBoundary() = 0;
+ virtual void setBoundarySelected(const QRectF &boundary, bool secondary) = 0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramgraphicsscene.h b/src/libs/modelinglib/qmt/diagram_scene/diagramgraphicsscene.h
index 3be43fa397..d9fc21f441 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/diagramgraphicsscene.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/diagramgraphicsscene.h
@@ -37,7 +37,7 @@ class QMT_EXPORT DiagramGraphicsScene : public QGraphicsScene
Q_OBJECT
public:
- explicit DiagramGraphicsScene(DiagramSceneModel *diagramSceneModel, QObject *parent = 0);
+ explicit DiagramGraphicsScene(DiagramSceneModel *diagramSceneModel, QObject *parent = nullptr);
~DiagramGraphicsScene() override;
signals:
@@ -64,7 +64,7 @@ protected:
void inputMethodEvent(QInputMethodEvent *event) override;
private:
- DiagramSceneModel *m_diagramSceneModel;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h b/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h
index 6f7d0a89e2..c91e62725b 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h
@@ -27,6 +27,7 @@
namespace qmt {
+const int SWIMLANE_ITEMS_ZVALUE = -1100;
const int BOUNDARY_ITEMS_ZVALUE = -1000;
// all model objects have z-values from -500 to 500 depending on their depth in the model tree
const int RELATION_ITEMS_ZVALUE = 1000;
diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp
index 9d40cf3a8e..b1ca87b008 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp
@@ -38,6 +38,8 @@
#include "qmt/diagram/drelation.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram_controller/dselection.h"
+#include "qmt/diagram_scene/items/objectitem.h"
+#include "qmt/diagram_scene/items/swimlaneitem.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/mobject.h"
#include "qmt/model/mpackage.h"
@@ -47,6 +49,8 @@
#include "qmt/tasks/diagramscenecontroller.h"
#include "qmt/tasks/ielementtasks.h"
+#include "utils/asconst.h"
+
#include <QSet>
#include <QGraphicsItem>
#include <QGraphicsSceneMouseEvent>
@@ -68,7 +72,7 @@ namespace qmt {
class DiagramSceneModel::OriginItem : public QGraphicsItem
{
public:
- explicit OriginItem(QGraphicsItem *parent = 0)
+ explicit OriginItem(QGraphicsItem *parent = nullptr)
: QGraphicsItem(parent)
{
}
@@ -92,16 +96,9 @@ public:
DiagramSceneModel::DiagramSceneModel(QObject *parent)
: QObject(parent),
- m_diagramController(0),
- m_diagramSceneController(0),
- m_styleController(0),
- m_stereotypeController(0),
- m_diagram(0),
m_graphicsScene(new DiagramGraphicsScene(this)),
m_latchController(new LatchController(this)),
- m_busyState(NotBusy),
- m_originItem(new OriginItem()),
- m_focusItem(0)
+ m_originItem(new OriginItem())
{
m_latchController->setDiagramSceneModel(this);
connect(m_graphicsScene, &QGraphicsScene::selectionChanged,
@@ -111,7 +108,6 @@ DiagramSceneModel::DiagramSceneModel(QObject *parent)
m_graphicsScene->addItem(m_originItem);
m_latchController->addToGraphicsScene(m_graphicsScene);
-
}
DiagramSceneModel::~DiagramSceneModel()
@@ -120,7 +116,7 @@ DiagramSceneModel::~DiagramSceneModel()
m_latchController->removeFromGraphicsScene(m_graphicsScene);
disconnect();
if (m_diagramController)
- disconnect(m_diagramController, 0, this, 0);
+ disconnect(m_diagramController, nullptr, this, nullptr);
m_graphicsScene->deleteLater();
}
@@ -129,8 +125,8 @@ void DiagramSceneModel::setDiagramController(DiagramController *diagramControlle
if (m_diagramController == diagramController)
return;
if (m_diagramController) {
- disconnect(m_diagramController, 0, this, 0);
- m_diagramController = 0;
+ disconnect(m_diagramController, nullptr, this, nullptr);
+ m_diagramController = nullptr;
}
m_diagramController = diagramController;
if (diagramController) {
@@ -197,7 +193,7 @@ bool DiagramSceneModel::hasMultiObjectsSelection() const
foreach (QGraphicsItem *item, m_graphicsScene->selectedItems()) {
DElement *element = m_itemToElementMap.value(item);
QMT_CHECK(element);
- if (dynamic_cast<DObject *>(element) != 0) {
+ if (dynamic_cast<DObject *>(element)) {
++count;
if (count > 1)
return true;
@@ -211,7 +207,7 @@ DSelection DiagramSceneModel::selectedElements() const
DSelection selection;
foreach (QGraphicsItem *item, m_graphicsScene->selectedItems()) {
DElement *element = m_itemToElementMap.value(item);
- QMT_CHECK(element);
+ QMT_ASSERT(element, return selection);
selection.append(element->uid(), m_diagram->uid());
}
return selection;
@@ -225,21 +221,29 @@ DElement *DiagramSceneModel::findTopmostElement(const QPointF &scenePos) const
if (m_graphicsItems.contains(item))
return m_itemToElementMap.value(item);
}
- return 0;
+ return nullptr;
}
DObject *DiagramSceneModel::findTopmostObject(const QPointF &scenePos) const
{
+ ObjectItem *item = findTopmostObjectItem(scenePos);
+ if (!item)
+ return nullptr;
+ return item->object();
+}
+
+ObjectItem *DiagramSceneModel::findTopmostObjectItem(const QPointF &scenePos) const
+{
// fetch affected items from scene in correct drawing order to find topmost element
- QList<QGraphicsItem *> items = m_graphicsScene->items(scenePos);
- foreach (QGraphicsItem *item, items) {
+ const QList<QGraphicsItem *> items = m_graphicsScene->items(scenePos);
+ for (QGraphicsItem *item : Utils::asConst(items)) {
if (m_graphicsItems.contains(item)) {
DObject *object = dynamic_cast<DObject *>(m_itemToElementMap.value(item));
if (object)
- return object;
+ return dynamic_cast<ObjectItem *>(item);
}
}
- return 0;
+ return nullptr;
}
QGraphicsItem *DiagramSceneModel::graphicsItem(DElement *element) const
@@ -264,8 +268,8 @@ DElement *DiagramSceneModel::element(QGraphicsItem *item) const
bool DiagramSceneModel::isElementEditable(const DElement *element) const
{
- auto editable = dynamic_cast<IEditable *>(m_elementToItemMap.value(element));
- return editable != 0 && editable->isEditable();
+ auto editable = dynamic_cast<IEditable *>(m_elementToItemMap.value(element));
+ return editable && editable->isEditable();
}
void DiagramSceneModel::selectAllElements()
@@ -288,7 +292,7 @@ void DiagramSceneModel::selectElement(DElement *element)
void DiagramSceneModel::editElement(DElement *element)
{
auto editable = dynamic_cast<IEditable *>(m_elementToItemMap.value(element));
- if (editable != 0 && editable->isEditable())
+ if (editable && editable->isEditable())
editable->edit();
}
@@ -569,8 +573,6 @@ QList<QGraphicsItem *> DiagramSceneModel::collectCollidingObjectItems(const QGra
}
}
break;
- default:
- QMT_CHECK(false);
}
return collidingItems;
}
@@ -633,7 +635,7 @@ void DiagramSceneModel::mouseReleaseEventReparenting(QGraphicsSceneMouseEvent *e
{
if (event->modifiers() & Qt::AltModifier) {
ModelController *modelController = diagramController()->modelController();
- MPackage *newOwner = 0;
+ MPackage *newOwner = nullptr;
QSet<QGraphicsItem *> selectedItemSet = m_graphicsScene->selectedItems().toSet();
QList<QGraphicsItem *> itemsUnderMouse = m_graphicsScene->items(event->scenePos());
foreach (QGraphicsItem *item, itemsUnderMouse) {
@@ -649,7 +651,7 @@ void DiagramSceneModel::mouseReleaseEventReparenting(QGraphicsSceneMouseEvent *e
if (newOwner) {
foreach (QGraphicsItem *item, m_graphicsScene->selectedItems()) {
DElement *element = m_itemToElementMap.value(item);
- QMT_CHECK(element);
+ QMT_ASSERT(element, return);
if (element->modelUid().isValid()) {
MObject *modelObject = modelController->findObject(element->modelUid());
if (modelObject) {
@@ -698,6 +700,7 @@ void DiagramSceneModel::onEndResetDiagram(const MDiagram *diagram)
// update graphics items again so every item gets a correct list of colliding items
foreach (DElement *element, diagram->diagramElements())
updateGraphicsItem(m_elementToItemMap.value(element), element);
+ recalcSceneRectSize();
}
m_busyState = NotBusy;
}
@@ -717,6 +720,7 @@ void DiagramSceneModel::onEndUpdateElement(int row, const MDiagram *diagram)
if (diagram == m_diagram) {
QGraphicsItem *item = m_graphicsItems.at(row);
updateGraphicsItem(item, diagram->diagramElements().at(row));
+ recalcSceneRectSize();
}
m_busyState = NotBusy;
}
@@ -732,7 +736,7 @@ void DiagramSceneModel::onBeginInsertElement(int row, const MDiagram *diagram)
void DiagramSceneModel::onEndInsertElement(int row, const MDiagram *diagram)
{
QMT_CHECK(m_busyState == InsertElement);
- QGraphicsItem *item = 0;
+ QGraphicsItem *item = nullptr;
if (diagram == m_diagram) {
DElement *element = diagram->diagramElements().at(row);
item = createGraphicsItem(element);
@@ -740,6 +744,7 @@ void DiagramSceneModel::onEndInsertElement(int row, const MDiagram *diagram)
updateGraphicsItem(item, element);
m_graphicsScene->invalidate();
updateGraphicsItem(item, element);
+ recalcSceneRectSize();
}
m_busyState = NotBusy;
}
@@ -750,6 +755,7 @@ void DiagramSceneModel::onBeginRemoveElement(int row, const MDiagram *diagram)
if (diagram == m_diagram) {
QGraphicsItem *item = m_graphicsItems.takeAt(row);
deleteGraphicsItem(item, diagram->diagramElements().at(row));
+ recalcSceneRectSize();
}
m_busyState = RemoveElement;
}
@@ -791,7 +797,7 @@ void DiagramSceneModel::onSelectionChanged()
// select all contained objects secondarily
foreach (QGraphicsItem *selectedItem, m_selectedItems) {
foreach (QGraphicsItem *item, collectCollidingObjectItems(selectedItem, CollidingInnerItems)) {
- if (!item->isSelected() && dynamic_cast<ISelectable *>(item) != 0
+ if (!item->isSelected() && dynamic_cast<ISelectable *>(item)
&& item->collidesWithItem(selectedItem, Qt::ContainsItemBoundingRect)
&& isInFrontOf(item, selectedItem)) {
QMT_CHECK(!m_selectedItems.contains(item));
@@ -800,20 +806,41 @@ void DiagramSceneModel::onSelectionChanged()
}
}
+ // select more items secondarily
+ for (QGraphicsItem *selectedItem : Utils::asConst(m_selectedItems)) {
+ if (auto selectable = dynamic_cast<ISelectable *>(selectedItem)) {
+ QRectF boundary = selectable->getSecondarySelectionBoundary();
+ if (!boundary.isEmpty()) {
+ for (QGraphicsItem *item : Utils::asConst(m_graphicsItems)) {
+ if (auto secondarySelectable = dynamic_cast<ISelectable *>(item)) {
+ if (!item->isSelected() && !secondarySelectable->isSecondarySelected()) {
+ secondarySelectable->setBoundarySelected(boundary, true);
+ QMT_CHECK(!m_selectedItems.contains(item));
+ QMT_CHECK(!m_secondarySelectedItems.contains(item));
+ if (secondarySelectable->isSecondarySelected())
+ newSecondarySelectedItems.insert(item);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
// select all relations where both ends are primary or secondary selected
foreach (DElement *element, m_diagram->diagramElements()) {
auto relation = dynamic_cast<DRelation *>(element);
if (relation) {
QGraphicsItem *relationItem = m_elementToItemMap.value(relation);
- QMT_CHECK(relationItem);
+ QMT_ASSERT(relationItem, return);
DObject *endAObject = m_diagramController->findElement<DObject>(relation->endAUid(), m_diagram);
- QMT_CHECK(endAObject);
+ QMT_ASSERT(endAObject, return);
QGraphicsItem *endAItem = m_elementToItemMap.value(endAObject);
- QMT_CHECK(endAItem);
+ QMT_ASSERT(endAItem, return);
DObject *endBObject = m_diagramController->findElement<DObject>(relation->endBUid(), m_diagram);
- QMT_CHECK(endBObject);
+ QMT_ASSERT(endBObject, return);
QGraphicsItem *endBItem = m_elementToItemMap.value(endBObject);
- QMT_CHECK(endBItem);
+ QMT_ASSERT(endBItem, return);
if (relationItem && !relationItem->isSelected()
&& (m_selectedItems.contains(endAItem) || newSecondarySelectedItems.contains(endAItem))
&& (m_selectedItems.contains(endBItem) || newSecondarySelectedItems.contains(endBItem))) {
@@ -826,7 +853,7 @@ void DiagramSceneModel::onSelectionChanged()
foreach (QGraphicsItem *item, m_secondarySelectedItems) {
if (!newSecondarySelectedItems.contains(item)) {
auto selectable = dynamic_cast<ISelectable *>(item);
- QMT_CHECK(selectable);
+ QMT_ASSERT(selectable, return);
selectable->setSecondarySelected(false);
selectionChanged = true;
}
@@ -834,7 +861,7 @@ void DiagramSceneModel::onSelectionChanged()
foreach (QGraphicsItem *item, newSecondarySelectedItems) {
if (!m_secondarySelectedItems.contains(item)) {
auto selectable = dynamic_cast<ISelectable *>(item);
- QMT_CHECK(selectable);
+ QMT_ASSERT(selectable, return);
selectable->setSecondarySelected(true);
selectionChanged = true;
}
@@ -856,7 +883,7 @@ void DiagramSceneModel::clearGraphicsScene()
m_elementToItemMap.clear();
m_selectedItems.clear();
m_secondarySelectedItems.clear();
- m_focusItem = 0;
+ m_focusItem = nullptr;
// save extra items from being deleted
removeExtraSceneItems();
m_graphicsScene->clear();
@@ -875,9 +902,20 @@ void DiagramSceneModel::addExtraSceneItems()
m_latchController->addToGraphicsScene(m_graphicsScene);
}
+void DiagramSceneModel::recalcSceneRectSize()
+{
+ QRectF sceneRect = m_originItem->mapRectToScene(m_originItem->boundingRect());
+ for (QGraphicsItem *item : Utils::asConst(m_graphicsItems)) {
+ // TODO use an interface to update sceneRect by item
+ if (!dynamic_cast<SwimlaneItem *>(item))
+ sceneRect |= item->mapRectToScene(item->boundingRect());
+ }
+ emit sceneRectChanged(sceneRect);
+}
+
QGraphicsItem *DiagramSceneModel::createGraphicsItem(DElement *element)
{
- QMT_CHECK(element);
+ QMT_ASSERT(element, return nullptr);
QMT_CHECK(!m_elementToItemMap.contains(element));
CreationVisitor visitor(this);
@@ -891,8 +929,8 @@ QGraphicsItem *DiagramSceneModel::createGraphicsItem(DElement *element)
void DiagramSceneModel::updateGraphicsItem(QGraphicsItem *item, DElement *element)
{
- QMT_CHECK(item);
- QMT_CHECK(element);
+ QMT_ASSERT(item, return);
+ QMT_ASSERT(element, return);
UpdateVisitor visitor(item, this);
element->accept(&visitor);
@@ -915,8 +953,8 @@ void DiagramSceneModel::deleteGraphicsItem(QGraphicsItem *item, DElement *elemen
void DiagramSceneModel::updateFocusItem(const QSet<QGraphicsItem *> &selectedItems)
{
QGraphicsItem *mouseGrabberItem = m_graphicsScene->mouseGrabberItem();
- QGraphicsItem *focusItem = 0;
- ISelectable *selectable = 0;
+ QGraphicsItem *focusItem = nullptr;
+ ISelectable *selectable = nullptr;
if (mouseGrabberItem && selectedItems.contains(mouseGrabberItem)) {
selectable = dynamic_cast<ISelectable *>(mouseGrabberItem);
@@ -939,17 +977,17 @@ void DiagramSceneModel::unsetFocusItem()
oldSelectable->setFocusSelected(false);
else
QMT_CHECK(false);
- m_focusItem = 0;
+ m_focusItem = nullptr;
}
}
bool DiagramSceneModel::isInFrontOf(const QGraphicsItem *frontItem, const QGraphicsItem *backItem)
{
- QMT_CHECK(frontItem);
- QMT_CHECK(backItem);
+ QMT_ASSERT(frontItem, return false);
+ QMT_ASSERT(backItem, return false);
// shortcut for usual case of root items
- if (frontItem->parentItem() == 0 && backItem->parentItem() == 0) {
+ if (!frontItem->parentItem() && !backItem->parentItem()) {
foreach (const QGraphicsItem *item, m_graphicsScene->items()) {
if (item == frontItem)
return true;
@@ -963,7 +1001,7 @@ bool DiagramSceneModel::isInFrontOf(const QGraphicsItem *frontItem, const QGraph
// collect all anchestors of front item
QList<const QGraphicsItem *> frontStack;
const QGraphicsItem *iterator = frontItem;
- while (iterator != 0) {
+ while (iterator) {
frontStack.append(iterator);
iterator = iterator->parentItem();
}
@@ -971,7 +1009,7 @@ bool DiagramSceneModel::isInFrontOf(const QGraphicsItem *frontItem, const QGraph
// collect all anchestors of back item
QList<const QGraphicsItem *> backStack;
iterator = backItem;
- while (iterator != 0) {
+ while (iterator) {
backStack.append(iterator);
iterator = iterator->parentItem();
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h
index 1b616710cf..04cbf6b418 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h
@@ -54,6 +54,7 @@ class DSelection;
class MDiagram;
class DElement;
class DObject;
+class ObjectItem;
class QMT_EXPORT DiagramSceneModel : public QObject
{
@@ -73,12 +74,13 @@ public:
CollidingOuterItems
};
- explicit DiagramSceneModel(QObject *parent = 0);
+ explicit DiagramSceneModel(QObject *parent = nullptr);
~DiagramSceneModel() override;
signals:
void diagramSceneActivated(const MDiagram *diagram);
void selectionHasChanged(const MDiagram *diagram);
+ void sceneRectChanged(const QRectF &sceneRect);
public:
DiagramController *diagramController() const { return m_diagramController; }
@@ -98,6 +100,7 @@ public:
DSelection selectedElements() const;
DElement *findTopmostElement(const QPointF &scenePos) const;
DObject *findTopmostObject(const QPointF &scenePos) const;
+ ObjectItem *findTopmostObjectItem(const QPointF &scenePos) const;
QList<QGraphicsItem *> graphicsItems() const { return m_graphicsItems; }
QGraphicsItem *graphicsItem(DElement *element) const;
@@ -150,6 +153,7 @@ private:
void clearGraphicsScene();
void removeExtraSceneItems();
void addExtraSceneItems();
+ void recalcSceneRectSize();
QGraphicsItem *createGraphicsItem(DElement *element);
void updateGraphicsItem(QGraphicsItem *item, DElement *element);
void deleteGraphicsItem(QGraphicsItem *item, DElement *element);
@@ -165,21 +169,21 @@ private:
RemoveElement
};
- DiagramController *m_diagramController;
- DiagramSceneController *m_diagramSceneController;
- StyleController *m_styleController;
- StereotypeController *m_stereotypeController;
- MDiagram *m_diagram;
- DiagramGraphicsScene *m_graphicsScene;
- LatchController *m_latchController;
+ DiagramController *m_diagramController = nullptr;
+ DiagramSceneController *m_diagramSceneController = nullptr;
+ StyleController *m_styleController = nullptr;
+ StereotypeController *m_stereotypeController = nullptr;
+ MDiagram *m_diagram = nullptr;
+ DiagramGraphicsScene *m_graphicsScene = nullptr;
+ LatchController *m_latchController = nullptr;
QList<QGraphicsItem *> m_graphicsItems;
QHash<const QGraphicsItem *, DElement *> m_itemToElementMap;
QHash<const DElement *, QGraphicsItem *> m_elementToItemMap;
QSet<QGraphicsItem *> m_selectedItems;
QSet<QGraphicsItem *> m_secondarySelectedItems;
- Busy m_busyState;
- OriginItem *m_originItem;
- QGraphicsItem *m_focusItem;
+ Busy m_busyState = NotBusy;
+ OriginItem *m_originItem = nullptr;
+ QGraphicsItem *m_focusItem = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp
index 370b901d6b..2a0a557190 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp
@@ -32,8 +32,10 @@
#include "items/itemitem.h"
#include "items/relationitem.h"
#include "items/associationitem.h"
+#include "items/connectionitem.h"
#include "items/annotationitem.h"
#include "items/boundaryitem.h"
+#include "items/swimlaneitem.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
@@ -46,15 +48,16 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
+#include "qmt/diagram/dswimlane.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
DiagramSceneModel::CreationVisitor::CreationVisitor(DiagramSceneModel *diagramSceneModel)
- : m_diagramSceneModel(diagramSceneModel),
- m_graphicsItem(nullptr)
+ : m_diagramSceneModel(diagramSceneModel)
{
}
@@ -122,6 +125,12 @@ void DiagramSceneModel::CreationVisitor::visitDAssociation(DAssociation *associa
m_graphicsItem = new AssociationItem(association, m_diagramSceneModel);
}
+void DiagramSceneModel::CreationVisitor::visitDConnection(DConnection *connection)
+{
+ QMT_CHECK(!m_graphicsItem);
+ m_graphicsItem = new ConnectionItem(connection, m_diagramSceneModel);
+}
+
void DiagramSceneModel::CreationVisitor::visitDAnnotation(DAnnotation *annotation)
{
QMT_CHECK(!m_graphicsItem);
@@ -134,6 +143,12 @@ void DiagramSceneModel::CreationVisitor::visitDBoundary(DBoundary *boundary)
m_graphicsItem = new BoundaryItem(boundary, m_diagramSceneModel);
}
+void DiagramSceneModel::CreationVisitor::visitDSwimlane(DSwimlane *swimlane)
+{
+ QMT_CHECK(!m_graphicsItem);
+ m_graphicsItem = new SwimlaneItem(swimlane, m_diagramSceneModel);
+}
+
DiagramSceneModel::UpdateVisitor::UpdateVisitor(QGraphicsItem *item, DiagramSceneModel *diagramSceneModel,
DElement *relatedElement)
: m_graphicsItem(item),
@@ -150,12 +165,12 @@ void DiagramSceneModel::UpdateVisitor::visitDElement(DElement *element)
void DiagramSceneModel::UpdateVisitor::visitDObject(DObject *object)
{
- if (m_relatedElement == 0) {
+ if (!m_relatedElement) {
// update all related relations
foreach (QGraphicsItem *item, m_diagramSceneModel->m_graphicsItems) {
DElement *element = m_diagramSceneModel->m_itemToElementMap.value(item);
QMT_CHECK(element);
- if (dynamic_cast<DRelation *>(element) != 0) {
+ if (dynamic_cast<DRelation *>(element)) {
UpdateVisitor visitor(item, m_diagramSceneModel, object);
element->accept(&visitor);
}
@@ -165,11 +180,11 @@ void DiagramSceneModel::UpdateVisitor::visitDObject(DObject *object)
void DiagramSceneModel::UpdateVisitor::visitDPackage(DPackage *package)
{
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
- if (m_relatedElement == 0) {
+ if (!m_relatedElement) {
PackageItem *packageItem = qgraphicsitem_cast<PackageItem *>(m_graphicsItem);
- QMT_CHECK(packageItem);
+ QMT_ASSERT(packageItem, return);
QMT_CHECK(packageItem->object() == package);
packageItem->update();
}
@@ -179,11 +194,11 @@ void DiagramSceneModel::UpdateVisitor::visitDPackage(DPackage *package)
void DiagramSceneModel::UpdateVisitor::visitDClass(DClass *klass)
{
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
- if (m_relatedElement == 0) {
+ if (!m_relatedElement) {
ClassItem *classItem = qgraphicsitem_cast<ClassItem *>(m_graphicsItem);
- QMT_CHECK(classItem);
+ QMT_ASSERT(classItem, return);
QMT_CHECK(classItem->object() == klass);
classItem->update();
}
@@ -193,11 +208,11 @@ void DiagramSceneModel::UpdateVisitor::visitDClass(DClass *klass)
void DiagramSceneModel::UpdateVisitor::visitDComponent(DComponent *component)
{
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
- if (m_relatedElement == 0) {
+ if (!m_relatedElement) {
ComponentItem *componentItem = qgraphicsitem_cast<ComponentItem *>(m_graphicsItem);
- QMT_CHECK(componentItem);
+ QMT_ASSERT(componentItem, return);
QMT_CHECK(componentItem->object() == component);
componentItem->update();
}
@@ -207,11 +222,11 @@ void DiagramSceneModel::UpdateVisitor::visitDComponent(DComponent *component)
void DiagramSceneModel::UpdateVisitor::visitDDiagram(DDiagram *diagram)
{
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
- if (m_relatedElement == 0) {
+ if (!m_relatedElement) {
DiagramItem *documentItem = qgraphicsitem_cast<DiagramItem *>(m_graphicsItem);
- QMT_CHECK(documentItem);
+ QMT_ASSERT(documentItem, return);
QMT_CHECK(documentItem->object() == diagram);
documentItem->update();
}
@@ -221,11 +236,11 @@ void DiagramSceneModel::UpdateVisitor::visitDDiagram(DDiagram *diagram)
void DiagramSceneModel::UpdateVisitor::visitDItem(DItem *item)
{
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
- if (m_relatedElement == 0) {
+ if (!m_relatedElement) {
ItemItem *itemItem = qgraphicsitem_cast<ItemItem *>(m_graphicsItem);
- QMT_CHECK(itemItem);
+ QMT_ASSERT(itemItem, return);
QMT_CHECK(itemItem->object() == item);
itemItem->update();
}
@@ -235,13 +250,13 @@ void DiagramSceneModel::UpdateVisitor::visitDItem(DItem *item)
void DiagramSceneModel::UpdateVisitor::visitDRelation(DRelation *relation)
{
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
- if (m_relatedElement == 0
+ if (!m_relatedElement
|| m_relatedElement->uid() == relation->endAUid()
|| m_relatedElement->uid() == relation->endBUid()) {
RelationItem *relationItem = qgraphicsitem_cast<RelationItem *>(m_graphicsItem);
- QMT_CHECK(relationItem);
+ QMT_ASSERT(relationItem, return);
QMT_CHECK(relationItem->relation() == relation);
relationItem->update();
}
@@ -262,13 +277,18 @@ void DiagramSceneModel::UpdateVisitor::visitDAssociation(DAssociation *associati
visitDRelation(association);
}
+void DiagramSceneModel::UpdateVisitor::visitDConnection(DConnection *connection)
+{
+ visitDRelation(connection);
+}
+
void DiagramSceneModel::UpdateVisitor::visitDAnnotation(DAnnotation *annotation)
{
Q_UNUSED(annotation); // avoid warning in release mode
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
AnnotationItem *annotationItem = qgraphicsitem_cast<AnnotationItem *>(m_graphicsItem);
- QMT_CHECK(annotationItem);
+ QMT_ASSERT(annotationItem, return);
QMT_CHECK(annotationItem->annotation() == annotation);
annotationItem->update();
}
@@ -276,12 +296,23 @@ void DiagramSceneModel::UpdateVisitor::visitDAnnotation(DAnnotation *annotation)
void DiagramSceneModel::UpdateVisitor::visitDBoundary(DBoundary *boundary)
{
Q_UNUSED(boundary); // avoid warning in release mode
- QMT_CHECK(m_graphicsItem);
+ QMT_ASSERT(m_graphicsItem, return);
BoundaryItem *boundaryItem = qgraphicsitem_cast<BoundaryItem *>(m_graphicsItem);
- QMT_CHECK(boundaryItem);
+ QMT_ASSERT(boundaryItem, return);
QMT_CHECK(boundaryItem->boundary() == boundary);
boundaryItem->update();
}
+void DiagramSceneModel::UpdateVisitor::visitDSwimlane(DSwimlane *swimlane)
+{
+ Q_UNUSED(swimlane); // avoid warning in release mode
+ QMT_ASSERT(m_graphicsItem, return);
+
+ SwimlaneItem *swimlaneItem = qgraphicsitem_cast<SwimlaneItem *>(m_graphicsItem);
+ QMT_ASSERT(swimlaneItem, return);
+ QMT_CHECK(swimlaneItem->swimlane() == swimlane);
+ swimlaneItem->update();
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h
index 138f087481..a2bbefc9f0 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h
@@ -49,19 +49,21 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
+ void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;
+ void visitDSwimlane(DSwimlane *swimlane) override;
private:
- DiagramSceneModel *m_diagramSceneModel;
- QGraphicsItem *m_graphicsItem;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
+ QGraphicsItem *m_graphicsItem = nullptr;
};
class QMT_EXPORT DiagramSceneModel::UpdateVisitor : public DVisitor
{
public:
UpdateVisitor(QGraphicsItem *item, DiagramSceneModel *diagramSceneModel,
- DElement *relatedElement = 0);
+ DElement *relatedElement = nullptr);
void visitDElement(DElement *element) override;
void visitDObject(DObject *object) override;
@@ -74,13 +76,15 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
+ void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;
+ void visitDSwimlane(DSwimlane *swimlane) override;
private:
- QGraphicsItem *m_graphicsItem;
- DiagramSceneModel *m_diagramSceneModel;
- DElement *m_relatedElement;
+ QGraphicsItem *m_graphicsItem = nullptr;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
+ DElement *m_relatedElement = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp
index 2f21e00042..d9da017d58 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp
@@ -60,7 +60,7 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
- QMT_CHECK(option);
+ QMT_ASSERT(option, return);
QStyleOptionGraphicsItem option2(*option);
option2.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
@@ -213,6 +213,21 @@ void AnnotationItem::setFocusSelected(bool focusSelected)
}
}
+QRectF AnnotationItem::getSecondarySelectionBoundary()
+{
+ return QRectF();
+}
+
+void AnnotationItem::setBoundarySelected(const QRectF &boundary, bool secondary)
+{
+ if (boundary.contains(mapRectToScene(boundingRect()))) {
+ if (secondary)
+ setSecondarySelected(true);
+ else
+ setSelected(true);
+ }
+}
+
bool AnnotationItem::isEditable() const
{
return true;
@@ -260,7 +275,7 @@ void AnnotationItem::updateSelectionMarker()
if (m_selectionMarker->scene())
m_selectionMarker->scene()->removeItem(m_selectionMarker);
delete m_selectionMarker;
- m_selectionMarker = 0;
+ m_selectionMarker = nullptr;
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h
index 29e16224ec..d7bce8d8dc 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h
@@ -50,7 +50,7 @@ class AnnotationItem :
public:
AnnotationItem(DAnnotation *annotation, DiagramSceneModel *diagramSceneModel,
- QGraphicsItem *parent = 0);
+ QGraphicsItem *parent = nullptr);
~AnnotationItem() override;
DAnnotation *annotation() const { return m_annotation; }
@@ -77,6 +77,8 @@ public:
void setSecondarySelected(bool secondarySelected) override;
bool isFocusSelected() const override;
void setFocusSelected(bool focusSelected) override;
+ QRectF getSecondarySelectionBoundary() override;
+ void setBoundarySelected(const QRectF &boundary, bool secondary) override;
bool isEditable() const override;
void edit() override;
@@ -98,13 +100,13 @@ private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
- DAnnotation *m_annotation = 0;
- DiagramSceneModel *m_diagramSceneModel = 0;
+ DAnnotation *m_annotation = nullptr;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
bool m_isSecondarySelected = false;
bool m_isFocusSelected = false;
- RectangularSelectionItem *m_selectionMarker = 0;
- QGraphicsRectItem *m_noTextItem = 0;
- AnnotationTextItem *m_textItem = 0;
+ RectangularSelectionItem *m_selectionMarker = nullptr;
+ QGraphicsRectItem *m_noTextItem = nullptr;
+ AnnotationTextItem *m_textItem = nullptr;
bool m_isUpdating = false;
bool m_isChanged = false;
};
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.cpp
index 0211700ab2..1aee12d465 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.cpp
@@ -60,7 +60,7 @@ void AssociationItem::update(const Style *style)
updateEndLabels(m_association->endA(), m_association->endB(), &m_endAName, &m_endACardinality, style);
updateEndLabels(m_association->endB(), m_association->endA(), &m_endBName, &m_endBCardinality, style);
- QMT_CHECK(m_arrow);
+ QMT_ASSERT(m_arrow, return);
QGraphicsItem *endAItem = m_diagramSceneModel->graphicsItem(m_association->endAUid());
if (!endAItem)
return;
@@ -86,7 +86,7 @@ void AssociationItem::updateEndLabels(const DAssociationEnd &end, const DAssocia
} else if (*endName) {
(*endName)->scene()->removeItem(*endName);
delete *endName;
- *endName = 0;
+ *endName = nullptr;
}
if (!otherEnd.cardinality().isEmpty()) {
@@ -98,7 +98,7 @@ void AssociationItem::updateEndLabels(const DAssociationEnd &end, const DAssocia
} else if (*endCardinality) {
(*endCardinality)->scene()->removeItem(*endCardinality);
delete *endCardinality;
- *endCardinality = 0;
+ *endCardinality = nullptr;
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.h
index ad076eee59..ea11df42e3 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/associationitem.h
@@ -40,7 +40,7 @@ class AssociationItem : public RelationItem
{
public:
AssociationItem(DAssociation *association, DiagramSceneModel *diagramSceneModel,
- QGraphicsItem *parent = 0);
+ QGraphicsItem *parent = nullptr);
~AssociationItem() override;
protected:
@@ -54,11 +54,11 @@ private:
QGraphicsItem *endCardinality,
QGraphicsItem *endItem, double headLength);
- DAssociation *m_association = 0;
- QGraphicsSimpleTextItem *m_endAName = 0;
- QGraphicsSimpleTextItem *m_endACardinality = 0;
- QGraphicsSimpleTextItem *m_endBName = 0;
- QGraphicsSimpleTextItem *m_endBCardinality = 0;
+ DAssociation *m_association = nullptr;
+ QGraphicsSimpleTextItem *m_endAName = nullptr;
+ QGraphicsSimpleTextItem *m_endACardinality = nullptr;
+ QGraphicsSimpleTextItem *m_endBName = nullptr;
+ QGraphicsSimpleTextItem *m_endBCardinality = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp
index 6cd673969d..cedfc5816c 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp
@@ -62,7 +62,7 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
- QMT_CHECK(option);
+ QMT_ASSERT(option, return);
QStyleOptionGraphicsItem option2(*option);
option2.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
@@ -126,7 +126,7 @@ void BoundaryItem::update()
} else if (m_noTextItem) {
m_noTextItem->scene()->removeItem(m_noTextItem);
delete m_noTextItem;
- m_noTextItem = 0;
+ m_noTextItem = nullptr;
}
// item shown if annotation has no text and is not selected
@@ -264,6 +264,21 @@ void BoundaryItem::setFocusSelected(bool focusSelected)
}
}
+QRectF BoundaryItem::getSecondarySelectionBoundary()
+{
+ return QRectF();
+}
+
+void BoundaryItem::setBoundarySelected(const QRectF &boundary, bool secondary)
+{
+ if (boundary.contains(mapRectToScene(boundingRect()))) {
+ if (secondary)
+ setSecondarySelected(true);
+ else
+ setSelected(true);
+ }
+}
+
bool BoundaryItem::isEditable() const
{
return true;
@@ -308,7 +323,7 @@ void BoundaryItem::updateSelectionMarker()
if (m_selectionMarker->scene())
m_selectionMarker->scene()->removeItem(m_selectionMarker);
delete m_selectionMarker;
- m_selectionMarker = 0;
+ m_selectionMarker = nullptr;
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h
index b6b3380beb..d2105c08bf 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h
@@ -50,7 +50,7 @@ class BoundaryItem :
public:
BoundaryItem(DBoundary *boundary, DiagramSceneModel *diagramSceneModel,
- QGraphicsItem *parent = 0);
+ QGraphicsItem *parent = nullptr);
~BoundaryItem() override;
DBoundary *boundary() const { return m_boundary; }
@@ -76,6 +76,8 @@ public:
void setSecondarySelected(bool secondarySelected) override;
bool isFocusSelected() const override;
void setFocusSelected(bool focusSelected) override;
+ QRectF getSecondarySelectionBoundary() override;
+ void setBoundarySelected(const QRectF &boundary, bool secondary) override;
bool isEditable() const override;
void edit() override;
@@ -96,14 +98,14 @@ private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
- DBoundary *m_boundary = 0;
- DiagramSceneModel *m_diagramSceneModel = 0;
+ DBoundary *m_boundary = nullptr;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
bool m_isSecondarySelected = false;
bool m_isFocusSelected = false;
- RectangularSelectionItem *m_selectionMarker = 0;
- QGraphicsRectItem *m_borderItem = 0;
- QGraphicsRectItem *m_noTextItem = 0;
- BoundaryTextItem *m_textItem = 0;
+ RectangularSelectionItem *m_selectionMarker = nullptr;
+ QGraphicsRectItem *m_borderItem = nullptr;
+ QGraphicsRectItem *m_noTextItem = nullptr;
+ BoundaryTextItem *m_textItem = nullptr;
bool m_isUpdating = false;
bool m_isChanged = false;
};
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp
index a1c76b2617..fe459338a1 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp
@@ -40,6 +40,7 @@
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/model/mclass.h"
#include "qmt/model/mclassmember.h"
+#include "qmt/model/massociation.h"
#include "qmt/model_controller/modelcontroller.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/stereotype/stereotypeicon.h"
@@ -59,15 +60,20 @@
#include <algorithm>
+#include <qmt/stereotype/customrelation.h>
+
namespace qmt {
+static const char ASSOCIATION[] = "association";
+static const char INHERITANCE[] = "inheritance";
+
static const qreal MINIMUM_AUTO_WIDTH = 80.0;
static const qreal MINIMUM_AUTO_HEIGHT = 60.0;
static const qreal BODY_VERT_BORDER = 4.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
ClassItem::ClassItem(DClass *klass, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
- : ObjectItem(klass, diagramSceneModel, parent)
+ : ObjectItem("class", klass, diagramSceneModel, parent)
{
}
@@ -82,7 +88,7 @@ void ClassItem::update()
updateStereotypeIconDisplay();
auto diagramClass = dynamic_cast<DClass *>(object());
- QMT_CHECK(diagramClass);
+ QMT_ASSERT(diagramClass, return);
const Style *style = adaptedStyle(stereotypeIconId());
@@ -105,7 +111,7 @@ void ClassItem::update()
} else if (m_customIcon) {
m_customIcon->scene()->removeItem(m_customIcon);
delete m_customIcon;
- m_customIcon = 0;
+ m_customIcon = nullptr;
}
// shape
@@ -118,7 +124,7 @@ void ClassItem::update()
} else if (m_shape){
m_shape->scene()->removeItem(m_shape);
delete m_shape;
- m_shape = 0;
+ m_shape = nullptr;
}
// stereotypes
@@ -134,7 +140,7 @@ void ClassItem::update()
} else if (m_namespace) {
m_namespace->scene()->removeItem(m_namespace);
delete m_namespace;
- m_namespace = 0;
+ m_namespace = nullptr;
}
// class name
@@ -150,7 +156,7 @@ void ClassItem::update()
} else if (m_contextLabel) {
m_contextLabel->scene()->removeItem(m_contextLabel);
delete m_contextLabel;
- m_contextLabel = 0;
+ m_contextLabel = nullptr;
}
// attributes separator
@@ -162,7 +168,7 @@ void ClassItem::update()
} else if (m_attributesSeparator) {
m_attributesSeparator->scene()->removeItem(m_attributesSeparator);
delete m_attributesSeparator;
- m_attributesSeparator = 0;
+ m_attributesSeparator = nullptr;
}
// attributes
@@ -176,7 +182,7 @@ void ClassItem::update()
} else if (m_attributes) {
m_attributes->scene()->removeItem(m_attributes);
delete m_attributes;
- m_attributes = 0;
+ m_attributes = nullptr;
}
// methods separator
@@ -188,7 +194,7 @@ void ClassItem::update()
} else if (m_methodsSeparator) {
m_methodsSeparator->scene()->removeItem(m_methodsSeparator);
delete m_methodsSeparator;
- m_methodsSeparator = 0;
+ m_methodsSeparator = nullptr;
}
// methods
@@ -202,7 +208,7 @@ void ClassItem::update()
} else if (m_methods) {
m_methods->scene()->removeItem(m_methods);
delete m_methods;
- m_methods = 0;
+ m_methods = nullptr;
}
// template parameters
@@ -223,27 +229,11 @@ void ClassItem::update()
} else if (m_templateParameterBox) {
m_templateParameterBox->scene()->removeItem(m_templateParameterBox);
delete m_templateParameterBox;
- m_templateParameterBox = 0;
+ m_templateParameterBox = nullptr;
}
updateSelectionMarker(m_customIcon);
-
- // relation starters
- if (isFocusSelected()) {
- if (!m_relationStarter) {
- m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
- scene()->addItem(m_relationStarter);
- m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
- m_relationStarter->addArrow(QLatin1String("inheritance"), ArrowItem::ShaftSolid, ArrowItem::HeadTriangle);
- m_relationStarter->addArrow(QLatin1String("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
- m_relationStarter->addArrow(QLatin1String("association"), ArrowItem::ShaftSolid, ArrowItem::HeadFilledTriangle);
- }
- } else if (m_relationStarter) {
- scene()->removeItem(m_relationStarter);
- delete m_relationStarter;
- m_relationStarter = 0;
- }
-
+ updateRelationStarter();
updateAlignmentButtons();
updateGeometry();
}
@@ -263,42 +253,90 @@ QSizeF ClassItem::minimumSize() const
return calcMinimumGeometry();
}
-QPointF ClassItem::relationStartPos() const
+void ClassItem::relationDrawn(const QString &id, ObjectItem *targetItem, const QList<QPointF> &intermediatePoints)
{
- return pos();
-}
-
-void ClassItem::relationDrawn(const QString &id, const QPointF &toScenePos, const QList<QPointF> &intermediatePoints)
-{
- DElement *targetElement = diagramSceneModel()->findTopmostElement(toScenePos);
- if (targetElement) {
- if (id == QLatin1String("inheritance")) {
- auto baseClass = dynamic_cast<DClass *>(targetElement);
- if (baseClass) {
- auto derivedClass = dynamic_cast<DClass *>(object());
- QMT_CHECK(derivedClass);
- diagramSceneModel()->diagramSceneController()->createInheritance(derivedClass, baseClass, intermediatePoints, diagramSceneModel()->diagram());
+ DiagramSceneController *diagramSceneController = diagramSceneModel()->diagramSceneController();
+ if (id == INHERITANCE) {
+ auto baseClass = dynamic_cast<DClass *>(targetItem->object());
+ if (baseClass) {
+ auto derivedClass = dynamic_cast<DClass *>(object());
+ QMT_ASSERT(derivedClass, return);
+ diagramSceneController->createInheritance(derivedClass, baseClass, intermediatePoints, diagramSceneModel()->diagram());
+ }
+ return;
+ } else if (id == ASSOCIATION) {
+ auto associatedClass = dynamic_cast<DClass *>(targetItem->object());
+ if (associatedClass) {
+ auto derivedClass = dynamic_cast<DClass *>(object());
+ QMT_ASSERT(derivedClass, return);
+ diagramSceneController->createAssociation(derivedClass, associatedClass, intermediatePoints, diagramSceneModel()->diagram());
+ }
+ return;
+ } else {
+ StereotypeController *stereotypeController = diagramSceneModel()->stereotypeController();
+ CustomRelation customRelation = stereotypeController->findCustomRelation(id);
+ if (!customRelation.isNull()) {
+ switch (customRelation.element()) {
+ case CustomRelation::Element::Inheritance:
+ {
+ auto baseClass = dynamic_cast<DClass *>(targetItem->object());
+ if (baseClass) {
+ auto derivedClass = dynamic_cast<DClass *>(object());
+ QMT_ASSERT(derivedClass, return);
+ diagramSceneController->createInheritance(derivedClass, baseClass, intermediatePoints, diagramSceneModel()->diagram());
+ }
+ return;
}
- } else if (id == QLatin1String("dependency")) {
- auto dependantObject = dynamic_cast<DObject *>(targetElement);
- if (dependantObject)
- diagramSceneModel()->diagramSceneController()->createDependency(object(), dependantObject, intermediatePoints, diagramSceneModel()->diagram());
- } else if (id == QLatin1String("association")) {
- auto assoziatedClass = dynamic_cast<DClass *>(targetElement);
- if (assoziatedClass) {
- auto derivedClass = dynamic_cast<DClass *>(object());
- QMT_CHECK(derivedClass);
- diagramSceneModel()->diagramSceneController()->createAssociation(derivedClass, assoziatedClass, intermediatePoints, diagramSceneModel()->diagram());
+ case CustomRelation::Element::Association:
+ {
+ auto assoziatedClass = dynamic_cast<DClass *>(targetItem->object());
+ if (assoziatedClass) {
+ auto derivedClass = dynamic_cast<DClass *>(object());
+ QMT_ASSERT(derivedClass, return);
+ diagramSceneController->createAssociation(
+ derivedClass, assoziatedClass, intermediatePoints, diagramSceneModel()->diagram(),
+ [=] (MAssociation *mAssociation, DAssociation *dAssociation) {
+ if (mAssociation && dAssociation) {
+ static const QHash<CustomRelation::Relationship, MAssociationEnd::Kind> relationship2KindMap = {
+ { CustomRelation::Relationship::Association, MAssociationEnd::Association },
+ { CustomRelation::Relationship::Aggregation, MAssociationEnd::Aggregation },
+ { CustomRelation::Relationship::Composition, MAssociationEnd::Composition } };
+ diagramSceneController->modelController()->startUpdateRelation(mAssociation);
+ mAssociation->setStereotypes(customRelation.stereotypes().toList());
+ mAssociation->setName(customRelation.name());
+ MAssociationEnd endA;
+ endA.setCardinality(customRelation.endA().cardinality());
+ endA.setKind(relationship2KindMap.value(customRelation.endA().relationship()));
+ endA.setName(customRelation.endA().role());
+ endA.setNavigable(customRelation.endA().navigable());
+ mAssociation->setEndA(endA);
+ MAssociationEnd endB;
+ endB.setCardinality(customRelation.endB().cardinality());
+ endB.setKind(relationship2KindMap.value(customRelation.endB().relationship()));
+ endB.setName(customRelation.endB().role());
+ endB.setNavigable(customRelation.endB().navigable());
+ mAssociation->setEndB(endB);
+ diagramSceneController->modelController()->finishUpdateRelation(mAssociation, false);
+ }
+ });
+ }
+ return;
+ }
+ case CustomRelation::Element::Dependency:
+ case CustomRelation::Element::Relation:
+ // fall thru
+ break;
}
}
}
+ ObjectItem::relationDrawn(id, targetItem, intermediatePoints);
}
bool ClassItem::extendContextMenu(QMenu *menu)
{
bool extended = false;
if (diagramSceneModel()->diagramSceneController()->elementTasks()->hasClassDefinition(object(), diagramSceneModel()->diagram())) {
- menu->addAction(new ContextMenuAction(tr("Show Definition"), QStringLiteral("showDefinition"), menu));
+ menu->addAction(new ContextMenuAction(tr("Show Definition"), "showDefinition", menu));
extended = true;
}
return extended;
@@ -306,7 +344,7 @@ bool ClassItem::extendContextMenu(QMenu *menu)
bool ClassItem::handleSelectedContextMenuAction(const QString &id)
{
- if (id == QStringLiteral("showDefinition")) {
+ if (id == "showDefinition") {
diagramSceneModel()->diagramSceneController()->elementTasks()->openClassDefinition(object(), diagramSceneModel()->diagram());
return true;
}
@@ -316,7 +354,7 @@ bool ClassItem::handleSelectedContextMenuAction(const QString &id)
QString ClassItem::buildDisplayName() const
{
auto diagramClass = dynamic_cast<DClass *>(object());
- QMT_CHECK(diagramClass);
+ QMT_ASSERT(diagramClass, return QString());
QString name;
if (templateDisplay() == DClass::TemplateName && !diagramClass->templateParameters().isEmpty()) {
@@ -342,9 +380,9 @@ void ClassItem::setFromDisplayName(const QString &displayName)
QString name;
QStringList templateParameters;
// NOTE namespace is ignored because it has its own edit field
- if (NameController::parseClassName(displayName, 0, &name, &templateParameters)) {
+ if (NameController::parseClassName(displayName, nullptr, &name, &templateParameters)) {
auto diagramClass = dynamic_cast<DClass *>(object());
- QMT_CHECK(diagramClass);
+ QMT_ASSERT(diagramClass, return);
ModelController *modelController = diagramSceneModel()->diagramSceneController()->modelController();
MClass *mklass = modelController->findObject<MClass>(diagramClass->modelUid());
if (mklass && (name != mklass->name() || templateParameters != mklass->templateParameters())) {
@@ -359,10 +397,70 @@ void ClassItem::setFromDisplayName(const QString &displayName)
}
}
+void ClassItem::addRelationStarterTool(const QString &id)
+{
+ if (id == INHERITANCE)
+ relationStarter()->addArrow(INHERITANCE, ArrowItem::ShaftSolid,
+ ArrowItem::HeadNone, ArrowItem::HeadTriangle,
+ tr("Inheritance"));
+ else if (id == ASSOCIATION)
+ relationStarter()->addArrow(ASSOCIATION, ArrowItem::ShaftSolid,
+ ArrowItem::HeadNone, ArrowItem::HeadFilledTriangle,
+ tr("Association"));
+ else
+ ObjectItem::addRelationStarterTool(id);
+}
+
+void ClassItem::addRelationStarterTool(const CustomRelation &customRelation)
+{
+ ArrowItem::Shaft shaft = ArrowItem::ShaftSolid;
+ ArrowItem::Head headStart = ArrowItem::HeadNone;
+ ArrowItem::Head headEnd = ArrowItem::HeadNone;
+ switch (customRelation.element()) {
+ case CustomRelation::Element::Inheritance:
+ shaft = ArrowItem::ShaftSolid;
+ headEnd = ArrowItem::HeadTriangle;
+ break;
+ case CustomRelation::Element::Association:
+ switch (customRelation.endA().relationship()) {
+ case CustomRelation::Relationship::Association:
+ if (customRelation.endA().navigable() && customRelation.endB().navigable()) {
+ headStart = ArrowItem::HeadNone;
+ headEnd = ArrowItem::HeadNone;
+ } else if (customRelation.endA().navigable()) {
+ headStart = ArrowItem::HeadFilledTriangle;
+ } else {
+ headEnd = ArrowItem::HeadFilledTriangle;
+ }
+ break;
+ case CustomRelation::Relationship::Aggregation:
+ headStart = ArrowItem::HeadDiamond;
+ break;
+ case CustomRelation::Relationship::Composition:
+ headStart = ArrowItem::HeadFilledDiamond;
+ break;
+ }
+ break;
+ case CustomRelation::Element::Dependency:
+ case CustomRelation::Element::Relation:
+ ObjectItem::addRelationStarterTool(customRelation);
+ return;
+ }
+ relationStarter()->addArrow(customRelation.id(), shaft, headStart, headEnd,
+ customRelation.title());
+}
+
+void ClassItem::addStandardRelationStarterTools()
+{
+ ObjectItem::addStandardRelationStarterTools();
+ addRelationStarterTool(INHERITANCE);
+ addRelationStarterTool(ASSOCIATION);
+}
+
DClass::TemplateDisplay ClassItem::templateDisplay() const
{
auto diagramClass = dynamic_cast<DClass *>(object());
- QMT_CHECK(diagramClass);
+ QMT_ASSERT(diagramClass, return DClass::TemplateSmart);
DClass::TemplateDisplay templateDisplay = diagramClass->templateDisplay();
if (templateDisplay == DClass::TemplateSmart) {
@@ -535,10 +633,7 @@ void ClassItem::updateGeometry()
}
updateSelectionMarkerGeometry(rect);
-
- if (m_relationStarter)
- m_relationStarter->setPos(mapToScene(QPointF(right + 8.0, top)));
-
+ updateRelationStarterGeometry(rect);
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
@@ -555,17 +650,17 @@ void ClassItem::updateMembers(const Style *style)
QString attributesGroup;
QString methodsGroup;
- MClassMember::Visibility *currentVisibility = 0;
- QString *currentGroup = 0;
- QString *text = 0;
+ MClassMember::Visibility *currentVisibility = nullptr;
+ QString *currentGroup = nullptr;
+ QString *text = nullptr;
auto dclass = dynamic_cast<DClass *>(object());
- QMT_CHECK(dclass);
+ QMT_ASSERT(dclass, return);
foreach (const MClassMember &member, dclass->members()) {
switch (member.memberType()) {
case MClassMember::MemberUndefined:
- QMT_CHECK(false);
+ QMT_ASSERT(false, return);
break;
case MClassMember::MemberAttribute:
currentVisibility = &attributesVisibility;
@@ -580,19 +675,19 @@ void ClassItem::updateMembers(const Style *style)
}
if (text && !text->isEmpty())
- *text += QStringLiteral("<br/>");
+ *text += "<br/>";
bool addNewline = false;
bool addSpace = false;
if (currentVisibility)
*currentVisibility = member.visibility();
if (currentGroup && member.group() != *currentGroup) {
- *text += QString(QStringLiteral("[%1]")).arg(member.group());
+ *text += QString("[%1]").arg(member.group());
addNewline = true;
*currentGroup = member.group();
}
if (addNewline)
- *text += QStringLiteral("<br/>");
+ *text += "<br/>";
bool haveSignal = false;
bool haveSlot = false;
@@ -602,34 +697,34 @@ void ClassItem::updateMembers(const Style *style)
case MClassMember::VisibilityUndefined:
break;
case MClassMember::VisibilityPublic:
- vis = QStringLiteral("+");
+ vis = "+";
addSpace = true;
break;
case MClassMember::VisibilityProtected:
- vis = QStringLiteral("#");
+ vis = "#";
addSpace = true;
break;
case MClassMember::VisibilityPrivate:
- vis = QStringLiteral("-");
+ vis = "-";
addSpace = true;
break;
case MClassMember::VisibilitySignals:
- vis = QStringLiteral("&gt;");
+ vis = "&gt;";
haveSignal = true;
addSpace = true;
break;
case MClassMember::VisibilityPrivateSlots:
- vis = QStringLiteral("-$");
+ vis = "-$";
haveSlot = true;
addSpace = true;
break;
case MClassMember::VisibilityProtectedSlots:
- vis = QStringLiteral("#$");
+ vis = "#$";
haveSlot = true;
addSpace = true;
break;
case MClassMember::VisibilityPublicSlots:
- vis = QStringLiteral("+$");
+ vis = "+$";
haveSlot = true;
addSpace = true;
break;
@@ -638,34 +733,34 @@ void ClassItem::updateMembers(const Style *style)
}
if (member.properties() & MClassMember::PropertyQsignal && !haveSignal) {
- *text += QStringLiteral("&gt;");
+ *text += "&gt;";
addSpace = true;
}
if (member.properties() & MClassMember::PropertyQslot && !haveSlot) {
- *text += QStringLiteral("$");
+ *text += "$";
addSpace = true;
}
if (addSpace)
- *text += QStringLiteral(" ");
+ *text += " ";
if (member.properties() & MClassMember::PropertyQinvokable)
- *text += QStringLiteral("invokable ");
+ *text += "invokable ";
if (!member.stereotypes().isEmpty()) {
*text += StereotypesItem::format(member.stereotypes());
- *text += QStringLiteral(" ");
+ *text += " ";
}
if (member.properties() & MClassMember::PropertyStatic)
- *text += QStringLiteral("static ");
+ *text += "static ";
if (member.properties() & MClassMember::PropertyVirtual)
- *text += QStringLiteral("virtual ");
+ *text += "virtual ";
*text += member.declaration().toHtmlEscaped();
if (member.properties() & MClassMember::PropertyConst)
- *text += QStringLiteral(" const");
+ *text += " const";
if (member.properties() & MClassMember::PropertyOverride)
- *text += QStringLiteral(" override");
+ *text += " override";
if (member.properties() & MClassMember::PropertyFinal)
- *text += QStringLiteral(" final");
+ *text += " final";
if (member.properties() & MClassMember::PropertyAbstract)
- *text += QStringLiteral(" = 0");
+ *text += " = 0";
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h
index eb80e3e865..9fa9dc40bd 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h
@@ -27,7 +27,6 @@
#include "objectitem.h"
-#include "qmt/diagram_scene/capabilities/relationable.h"
#include "qmt/diagram/dclass.h"
QT_BEGIN_NAMESPACE
@@ -43,15 +42,14 @@ class DiagramSceneModel;
class CustomIconItem;
class ContextLabelItem;
class TemplateParameterBox;
-class RelationStarter;
class Style;
-class ClassItem : public ObjectItem, public IRelationable
+class ClassItem : public ObjectItem
{
Q_DECLARE_TR_FUNCTIONS(qmt::ClassItem)
public:
- ClassItem(DClass *klass, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = 0);
+ ClassItem(DClass *klass, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = nullptr);
~ClassItem() override;
void update() override;
@@ -61,8 +59,7 @@ public:
QSizeF minimumSize() const override;
- QPointF relationStartPos() const override;
- void relationDrawn(const QString &id, const QPointF &toScenePos,
+ void relationDrawn(const QString &id, ObjectItem *targetElement,
const QList<QPointF> &intermediatePoints) override;
protected:
@@ -70,6 +67,9 @@ protected:
bool handleSelectedContextMenuAction(const QString &id) override;
QString buildDisplayName() const override;
void setFromDisplayName(const QString &displayName) override;
+ void addRelationStarterTool(const QString &id) override;
+ void addRelationStarterTool(const CustomRelation &customRelation) override;
+ void addStandardRelationStarterTools() override;
private:
DClass::TemplateDisplay templateDisplay() const;
@@ -77,18 +77,17 @@ private:
void updateGeometry();
void updateMembers(const Style *style);
- CustomIconItem *m_customIcon = 0;
- QGraphicsRectItem *m_shape = 0;
- QGraphicsSimpleTextItem *m_namespace = 0;
- ContextLabelItem *m_contextLabel = 0;
- QGraphicsLineItem *m_attributesSeparator = 0;
+ CustomIconItem *m_customIcon = nullptr;
+ QGraphicsRectItem *m_shape = nullptr;
+ QGraphicsSimpleTextItem *m_namespace = nullptr;
+ ContextLabelItem *m_contextLabel = nullptr;
+ QGraphicsLineItem *m_attributesSeparator = nullptr;
QString m_attributesText;
- QGraphicsTextItem *m_attributes = 0;
- QGraphicsLineItem *m_methodsSeparator = 0;
+ QGraphicsTextItem *m_attributes = nullptr;
+ QGraphicsLineItem *m_methodsSeparator = nullptr;
QString m_methodsText;
- QGraphicsTextItem *m_methods = 0;
- TemplateParameterBox *m_templateParameterBox = 0;
- RelationStarter *m_relationStarter = 0;
+ QGraphicsTextItem *m_methods = nullptr;
+ TemplateParameterBox *m_templateParameterBox = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp
index af4818f283..98aa69c5c3 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp
@@ -32,7 +32,6 @@
#include "qmt/diagram_scene/parts/contextlabelitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/editabletextitem.h"
-#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
@@ -61,7 +60,7 @@ static const qreal BODY_VERT_BORDER = 4.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
ComponentItem::ComponentItem(DComponent *component, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
- : ObjectItem(component, diagramSceneModel, parent)
+ : ObjectItem("component", component, diagramSceneModel, parent)
{
}
@@ -88,7 +87,7 @@ void ComponentItem::update()
} else if (m_customIcon) {
m_customIcon->scene()->removeItem(m_customIcon);
delete m_customIcon;
- m_customIcon = 0;
+ m_customIcon = nullptr;
}
// shape
@@ -118,19 +117,19 @@ void ComponentItem::update()
if (m_shape) {
m_shape->scene()->removeItem(m_shape);
delete m_shape;
- m_shape = 0;
+ m_shape = nullptr;
}
}
if (deleteRects) {
if (m_lowerRect) {
m_lowerRect->scene()->removeItem(m_lowerRect);
delete m_lowerRect;
- m_lowerRect = 0;
+ m_lowerRect = nullptr;
}
if (m_upperRect) {
m_upperRect->scene()->removeItem(m_upperRect);
delete m_upperRect;
- m_upperRect = 0;
+ m_upperRect = nullptr;
}
}
@@ -150,26 +149,11 @@ void ComponentItem::update()
} else if (m_contextLabel) {
m_contextLabel->scene()->removeItem(m_contextLabel);
delete m_contextLabel;
- m_contextLabel = 0;
+ m_contextLabel = nullptr;
}
updateSelectionMarker(m_customIcon);
-
- // relation starters
- if (isFocusSelected()) {
- if (!m_relationStarter && scene()) {
- m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
- scene()->addItem(m_relationStarter);
- m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
- m_relationStarter->addArrow(QStringLiteral("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
- }
- } else if (m_relationStarter) {
- if (m_relationStarter->scene())
- m_relationStarter->scene()->removeItem(m_relationStarter);
- delete m_relationStarter;
- m_relationStarter = 0;
- }
-
+ updateRelationStarter();
updateAlignmentButtons();
updateGeometry();
}
@@ -217,27 +201,10 @@ QList<ILatchable::Latch> ComponentItem::verticalLatches(ILatchable::Action actio
return ObjectItem::verticalLatches(action, grabbedItem);
}
-QPointF ComponentItem::relationStartPos() const
-{
- return pos();
-}
-
-void ComponentItem::relationDrawn(const QString &id, const QPointF &toScenePos, const QList<QPointF> &intermediatePoints)
-{
- DElement *targetElement = diagramSceneModel()->findTopmostElement(toScenePos);
- if (targetElement) {
- if (id == QStringLiteral("dependency")) {
- auto dependantObject = dynamic_cast<DObject *>(targetElement);
- if (dependantObject)
- diagramSceneModel()->diagramSceneController()->createDependency(object(), dependantObject, intermediatePoints, diagramSceneModel()->diagram());
- }
- }
-}
-
bool ComponentItem::hasPlainShape() const
{
auto diagramComponent = dynamic_cast<DComponent *>(object());
- QMT_CHECK(diagramComponent);
+ QMT_ASSERT(diagramComponent, return false);
return diagramComponent->isPlainShape();
}
@@ -361,10 +328,7 @@ void ComponentItem::updateGeometry()
}
updateSelectionMarkerGeometry(rect);
-
- if (m_relationStarter)
- m_relationStarter->setPos(mapToScene(QPointF(right + 8.0, top)));
-
+ updateRelationStarterGeometry(rect);
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h
index 1b524247f3..83e01062ea 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h
@@ -27,8 +27,6 @@
#include "objectitem.h"
-#include "qmt/diagram_scene/capabilities/relationable.h"
-
QT_BEGIN_NAMESPACE
class QGraphicsRectItem;
class QGraphicsSimpleTextItem;
@@ -43,11 +41,11 @@ class CustomIconItem;
class ContextLabelItem;
class RelationStarter;
-class ComponentItem : public ObjectItem, public IRelationable
+class ComponentItem : public ObjectItem
{
public:
ComponentItem(DComponent *component, DiagramSceneModel *diagramSceneModel,
- QGraphicsItem *parent = 0);
+ QGraphicsItem *parent = nullptr);
~ComponentItem() override;
void update() override;
@@ -60,21 +58,16 @@ public:
QList<Latch> horizontalLatches(Action action, bool grabbedItem) const override;
QList<Latch> verticalLatches(Action action, bool grabbedItem) const override;
- QPointF relationStartPos() const override;
- void relationDrawn(const QString &id, const QPointF &toScenePos, const
- QList<QPointF> &intermediatePoints) override;
-
private:
bool hasPlainShape() const;
QSizeF calcMinimumGeometry() const;
void updateGeometry();
- CustomIconItem *m_customIcon = 0;
- QGraphicsRectItem *m_shape = 0;
- QGraphicsRectItem *m_upperRect = 0;
- QGraphicsRectItem *m_lowerRect = 0;
- ContextLabelItem *m_contextLabel = 0;
- RelationStarter *m_relationStarter = 0;
+ CustomIconItem *m_customIcon = nullptr;
+ QGraphicsRectItem *m_shape = nullptr;
+ QGraphicsRectItem *m_upperRect = nullptr;
+ QGraphicsRectItem *m_lowerRect = nullptr;
+ ContextLabelItem *m_contextLabel = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.cpp
new file mode 100644
index 0000000000..d8e3a37df5
--- /dev/null
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "connectionitem.h"
+
+#include "qmt/diagram_controller/diagramcontroller.h"
+#include "qmt/diagram/dconnection.h"
+#include "qmt/diagram_scene/capabilities/intersectionable.h"
+#include "qmt/diagram_scene/diagramscenemodel.h"
+#include "qmt/diagram_scene/parts/arrowitem.h"
+#include "qmt/infrastructure/geometryutilities.h"
+#include "qmt/infrastructure/qmtassert.h"
+#include "qmt/style/style.h"
+
+#include <QGraphicsScene>
+#include <QFont>
+#include <QPen>
+#include <QBrush>
+#include <QVector2D>
+#include <QPair>
+
+namespace qmt {
+
+ConnectionItem::ConnectionItem(DConnection *connection, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
+ : RelationItem(connection, diagramSceneModel, parent),
+ m_connection(connection)
+{
+}
+
+ConnectionItem::~ConnectionItem()
+{
+}
+
+void ConnectionItem::update(const Style *style)
+{
+ RelationItem::update(style);
+
+ updateEndLabels(m_connection->endA(), m_connection->endB(), &m_endAName, &m_endACardinality, style);
+ updateEndLabels(m_connection->endB(), m_connection->endA(), &m_endBName, &m_endBCardinality, style);
+
+ QMT_CHECK(m_arrow);
+ QGraphicsItem *endAItem = m_diagramSceneModel->graphicsItem(m_connection->endAUid());
+ if (!endAItem)
+ return;
+ placeEndLabels(m_arrow->firstLineSegment(), m_endAName, m_endACardinality, endAItem, m_arrow->startHeadLength());
+ QGraphicsItem *endBItem = m_diagramSceneModel->graphicsItem(m_connection->endBUid());
+ if (!endBItem)
+ return;
+ placeEndLabels(m_arrow->lastLineSegment(), m_endBName, m_endBCardinality, endBItem, m_arrow->endHeadLength());
+}
+
+void ConnectionItem::updateEndLabels(const DConnectionEnd &end, const DConnectionEnd &otherEnd,
+ QGraphicsSimpleTextItem **endName, QGraphicsSimpleTextItem **endCardinality,
+ const Style *style)
+{
+ Q_UNUSED(end);
+
+ if (!otherEnd.name().isEmpty()) {
+ if (!*endName)
+ *endName = new QGraphicsSimpleTextItem(this);
+ (*endName)->setFont(style->smallFont());
+ (*endName)->setBrush(style->textBrush());
+ (*endName)->setText(otherEnd.name());
+ } else if (*endName) {
+ (*endName)->scene()->removeItem(*endName);
+ delete *endName;
+ *endName = nullptr;
+ }
+
+ if (!otherEnd.cardinality().isEmpty()) {
+ if (!*endCardinality)
+ *endCardinality = new QGraphicsSimpleTextItem(this);
+ (*endCardinality)->setFont(style->smallFont());
+ (*endCardinality)->setBrush(style->textBrush());
+ (*endCardinality)->setText(otherEnd.cardinality());
+ } else if (*endCardinality) {
+ (*endCardinality)->scene()->removeItem(*endCardinality);
+ delete *endCardinality;
+ *endCardinality = nullptr;
+ }
+}
+
+void ConnectionItem::placeEndLabels(const QLineF &lineSegment, QGraphicsItem *endName, QGraphicsItem *endCardinality,
+ QGraphicsItem *endItem, double headLength)
+{
+ const double HEAD_OFFSET = headLength + 6.0;
+ const double SIDE_OFFSET = 4.0;
+ QPointF headOffset = QPointF(HEAD_OFFSET, 0);
+ QPointF sideOffset = QPointF(0.0, SIDE_OFFSET);
+
+ double angle = GeometryUtilities::calcAngle(lineSegment);
+ if (angle >= -5 && angle <= 5) {
+ if (endName)
+ endName->setPos(lineSegment.p1() + headOffset + sideOffset);
+ if (endCardinality)
+ endCardinality->setPos(lineSegment.p1() + headOffset - sideOffset
+ - endCardinality->boundingRect().bottomLeft());
+ } else if (angle <= -175 || angle >= 175) {
+ if (endName)
+ endName->setPos(lineSegment.p1() - headOffset + sideOffset - endName->boundingRect().topRight());
+ if (endCardinality)
+ endCardinality->setPos(lineSegment.p1() - headOffset
+ - sideOffset - endCardinality->boundingRect().bottomRight());
+ } else {
+ QRectF rect;
+ if (endCardinality)
+ rect = endCardinality->boundingRect();
+ if (endName)
+ rect = rect.united(endName->boundingRect().translated(rect.bottomLeft()));
+
+ QPointF rectPlacement;
+ GeometryUtilities::Side alignedSide = GeometryUtilities::SideUnspecified;
+
+ if (auto objectItem = dynamic_cast<IIntersectionable *>(endItem)) {
+ QPointF intersectionPoint;
+ QLineF intersectionLine;
+
+ if (objectItem->intersectShapeWithLine(GeometryUtilities::stretch(lineSegment.translated(pos()), 2.0, 0.0),
+ &intersectionPoint, &intersectionLine)) {
+ if (!GeometryUtilities::placeRectAtLine(rect, lineSegment, HEAD_OFFSET, SIDE_OFFSET,
+ intersectionLine, &rectPlacement, &alignedSide)) {
+ rectPlacement = intersectionPoint;
+ }
+ } else {
+ rectPlacement = lineSegment.p1();
+ }
+ } else {
+ rectPlacement = endItem->pos();
+ }
+
+ if (endCardinality) {
+ if (alignedSide == GeometryUtilities::SideRight)
+ endCardinality->setPos(rectPlacement
+ + QPointF(rect.width() - endCardinality->boundingRect().width(), 0.0));
+ else
+ endCardinality->setPos(rectPlacement);
+ rectPlacement += endCardinality->boundingRect().bottomLeft();
+ }
+ if (endName) {
+ if (alignedSide == GeometryUtilities::SideRight)
+ endName->setPos(rectPlacement + QPointF(rect.width() - endName->boundingRect().width(), 0.0));
+ else
+ endName->setPos(rectPlacement);
+ }
+ }
+}
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.h
new file mode 100644
index 0000000000..6f47306741
--- /dev/null
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/connectionitem.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "relationitem.h"
+
+QT_BEGIN_NAMESPACE
+class QGraphicsSimpleTextItem;
+QT_END_NAMESPACE
+
+namespace qmt {
+
+class DConnection;
+class DConnectionEnd;
+
+class ConnectionItem : public RelationItem
+{
+public:
+ ConnectionItem(DConnection *connection, DiagramSceneModel *diagramSceneModel,
+ QGraphicsItem *parent = nullptr);
+ ~ConnectionItem() override;
+
+protected:
+ void update(const Style *style) override;
+
+private:
+ void updateEndLabels(const DConnectionEnd &end, const DConnectionEnd &otherEnd,
+ QGraphicsSimpleTextItem **endName,
+ QGraphicsSimpleTextItem **endCardinality, const Style *style);
+ void placeEndLabels(const QLineF &lineSegment, QGraphicsItem *endName,
+ QGraphicsItem *endCardinality,
+ QGraphicsItem *endItem, double headLength);
+
+ DConnection *m_connection = nullptr;
+ QGraphicsSimpleTextItem *m_endAName = nullptr;
+ QGraphicsSimpleTextItem *m_endACardinality = nullptr;
+ QGraphicsSimpleTextItem *m_endBName = nullptr;
+ QGraphicsSimpleTextItem *m_endBCardinality = nullptr;
+};
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp
index 01feb195a1..c466328407 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp
@@ -54,7 +54,7 @@ static const qreal BODY_HORIZ_BORDER = 4.0;
static const qreal BODY_VERT_BORDER = 4.0;
DiagramItem::DiagramItem(DDiagram *diagram, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
- : ObjectItem(diagram, diagramSceneModel, parent)
+ : ObjectItem("diagram", diagram, diagramSceneModel, parent)
{
}
@@ -81,7 +81,7 @@ void DiagramItem::update()
} else if (m_customIcon) {
m_customIcon->scene()->removeItem(m_customIcon);
delete m_customIcon;
- m_customIcon = 0;
+ m_customIcon = nullptr;
}
// shape
@@ -100,12 +100,12 @@ void DiagramItem::update()
if (m_fold) {
m_fold->scene()->removeItem(m_fold);
delete m_fold;
- m_fold = 0;
+ m_fold = nullptr;
}
if (m_body) {
m_body->scene()->removeItem(m_body);
delete m_body;
- m_body = 0;
+ m_body = nullptr;
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h
index 33919920a6..d20ba34bee 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h
@@ -37,7 +37,7 @@ class DiagramItem : public ObjectItem
{
public:
explicit DiagramItem(DDiagram *diagram, DiagramSceneModel *diagramSceneModel,
- QGraphicsItem *parent = 0);
+ QGraphicsItem *parent = nullptr);
~DiagramItem() override;
void update() override;
@@ -51,9 +51,9 @@ private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
- CustomIconItem *m_customIcon = 0;
- QGraphicsPolygonItem *m_body = 0;
- QGraphicsPolygonItem *m_fold = 0;
+ CustomIconItem *m_customIcon = nullptr;
+ QGraphicsPolygonItem *m_body = nullptr;
+ QGraphicsPolygonItem *m_fold = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp
index 5eea90c443..dba8f7822f 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp
@@ -32,7 +32,6 @@
#include "qmt/diagram_scene/parts/contextlabelitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/editabletextitem.h"
-#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
@@ -56,7 +55,7 @@ static const qreal BODY_VERT_BORDER = 4.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
ItemItem::ItemItem(DItem *item, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
- : ObjectItem(item, diagramSceneModel, parent)
+ : ObjectItem("item", item, diagramSceneModel, parent)
{
}
@@ -71,7 +70,7 @@ void ItemItem::update()
auto diagramItem = dynamic_cast<DItem *>(object());
Q_UNUSED(diagramItem); // avoid warning about unsed variable
- QMT_CHECK(diagramItem);
+ QMT_ASSERT(diagramItem, return);
const Style *style = adaptedStyle(shapeIconId());
@@ -86,7 +85,7 @@ void ItemItem::update()
} else if (m_customIcon) {
m_customIcon->scene()->removeItem(m_customIcon);
delete m_customIcon;
- m_customIcon = 0;
+ m_customIcon = nullptr;
}
// shape
@@ -100,7 +99,7 @@ void ItemItem::update()
if (m_shape) {
m_shape->scene()->removeItem(m_shape);
delete m_shape;
- m_shape = 0;
+ m_shape = nullptr;
}
}
@@ -120,26 +119,11 @@ void ItemItem::update()
} else if (m_contextLabel) {
m_contextLabel->scene()->removeItem(m_contextLabel);
delete m_contextLabel;
- m_contextLabel = 0;
+ m_contextLabel = nullptr;
}
updateSelectionMarker(m_customIcon);
-
- // relation starters
- if (isFocusSelected()) {
- if (!m_relationStarter && scene()) {
- m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
- scene()->addItem(m_relationStarter);
- m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
- m_relationStarter->addArrow(QStringLiteral("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
- }
- } else if (m_relationStarter) {
- if (m_relationStarter->scene())
- m_relationStarter->scene()->removeItem(m_relationStarter);
- delete m_relationStarter;
- m_relationStarter = 0;
- }
-
+ updateRelationStarter();
updateAlignmentButtons();
updateGeometry();
}
@@ -175,23 +159,6 @@ QList<ILatchable::Latch> ItemItem::verticalLatches(ILatchable::Action action, bo
return ObjectItem::verticalLatches(action, grabbedItem);
}
-QPointF ItemItem::relationStartPos() const
-{
- return pos();
-}
-
-void ItemItem::relationDrawn(const QString &id, const QPointF &toScenePos, const QList<QPointF> &intermediatePoints)
-{
- DElement *targetElement = diagramSceneModel()->findTopmostElement(toScenePos);
- if (targetElement) {
- if (id == QStringLiteral("dependency")) {
- auto dependantObject = dynamic_cast<DObject *>(targetElement);
- if (dependantObject)
- diagramSceneModel()->diagramSceneController()->createDependency(object(), dependantObject, intermediatePoints, diagramSceneModel()->diagram());
- }
- }
-}
-
QSizeF ItemItem::calcMinimumGeometry() const
{
double width = 0.0;
@@ -294,10 +261,7 @@ void ItemItem::updateGeometry()
}
updateSelectionMarkerGeometry(rect);
-
- if (m_relationStarter)
- m_relationStarter->setPos(mapToScene(QPointF(right + 8.0, top)));
-
+ updateRelationStarterGeometry(rect);
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h
index 49a3c2fc58..3030071a0d 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h
@@ -27,8 +27,6 @@
#include "objectitem.h"
-#include "qmt/diagram_scene/capabilities/relationable.h"
-
QT_BEGIN_NAMESPACE
class QGraphicsRectItem;
class QGraphicsSimpleTextItem;
@@ -43,10 +41,10 @@ class CustomIconItem;
class ContextLabelItem;
class RelationStarter;
-class ItemItem : public ObjectItem, public IRelationable
+class ItemItem : public ObjectItem
{
public:
- ItemItem(DItem *item, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = 0);
+ ItemItem(DItem *item, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = nullptr);
~ItemItem() override;
void update() override;
@@ -59,18 +57,13 @@ public:
QList<Latch> horizontalLatches(Action action, bool grabbedItem) const override;
QList<Latch> verticalLatches(Action action, bool grabbedItem) const override;
- QPointF relationStartPos() const override;
- void relationDrawn(const QString &id, const QPointF &toScenePos,
- const QList<QPointF> &intermediatePoints) override;
-
private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
- CustomIconItem *m_customIcon = 0;
- QGraphicsRectItem *m_shape = 0;
- ContextLabelItem *m_contextLabel = 0;
- RelationStarter *m_relationStarter = 0;
+ CustomIconItem *m_customIcon = nullptr;
+ QGraphicsRectItem *m_shape = nullptr;
+ ContextLabelItem *m_contextLabel = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
index 8c73b3c91f..104d374ee8 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
@@ -34,6 +34,7 @@
#include "qmt/diagram_scene/parts/alignbuttonsitem.h"
#include "qmt/diagram_scene/parts/editabletextitem.h"
#include "qmt/diagram_scene/parts/rectangularselectionitem.h"
+#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/contextmenuaction.h"
@@ -41,7 +42,9 @@
#include "qmt/model/mdiagram.h"
#include "qmt/model/mobject.h"
#include "qmt/model_controller/modelcontroller.h"
+#include "qmt/stereotype/customrelation.h"
#include "qmt/stereotype/stereotypecontroller.h"
+#include "qmt/stereotype/toolbar.h"
#include "qmt/style/style.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/styledobject.h"
@@ -57,8 +60,12 @@
namespace qmt {
-ObjectItem::ObjectItem(DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
+static const char DEPENDENCY[] = "dependency";
+
+
+ObjectItem::ObjectItem(const QString &elementType, DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
: QGraphicsItem(parent),
+ m_elementType(elementType),
m_object(object),
m_diagramSceneModel(diagramSceneModel)
{
@@ -201,8 +208,25 @@ void ObjectItem::setFocusSelected(bool focusSelected)
}
}
+QRectF ObjectItem::getSecondarySelectionBoundary()
+{
+ return QRectF();
+}
+
+void ObjectItem::setBoundarySelected(const QRectF &boundary, bool secondary)
+{
+ if (boundary.contains(mapRectToScene(boundingRect()))) {
+ if (secondary)
+ setSecondarySelected(true);
+ else
+ setSelected(true);
+ }
+}
+
ILatchable::Action ObjectItem::horizontalLatchAction() const
{
+ if (!m_selectionMarker)
+ return Move;
switch (m_selectionMarker->activeHandle()) {
case RectangularSelectionItem::HandleTopLeft:
case RectangularSelectionItem::HandleLeft:
@@ -225,6 +249,8 @@ ILatchable::Action ObjectItem::horizontalLatchAction() const
ILatchable::Action ObjectItem::verticalLatchAction() const
{
+ if (!m_selectionMarker)
+ return Move;
switch (m_selectionMarker->activeHandle()) {
case RectangularSelectionItem::HandleTopLeft:
case RectangularSelectionItem::HandleTop:
@@ -253,18 +279,18 @@ QList<ILatchable::Latch> ObjectItem::horizontalLatches(ILatchable::Action action
QList<ILatchable::Latch> result;
switch (action) {
case ILatchable::Move:
- result << ILatchable::Latch(ILatchable::Left, rect.left(), rect.top(), rect.bottom(), QStringLiteral("left"))
- << ILatchable::Latch(ILatchable::Hcenter, rect.center().x(), rect.top(), rect.bottom(), QStringLiteral("center"))
- << ILatchable::Latch(ILatchable::Right, rect.right(), rect.top(), rect.bottom(), QStringLiteral("right"));
+ result << ILatchable::Latch(ILatchable::Left, rect.left(), rect.top(), rect.bottom(), "left")
+ << ILatchable::Latch(ILatchable::Hcenter, rect.center().x(), rect.top(), rect.bottom(), "center")
+ << ILatchable::Latch(ILatchable::Right, rect.right(), rect.top(), rect.bottom(), "right");
break;
case ILatchable::ResizeLeft:
- result << ILatchable::Latch(ILatchable::Left, rect.left(), rect.top(), rect.bottom(), QStringLiteral("left"));
+ result << ILatchable::Latch(ILatchable::Left, rect.left(), rect.top(), rect.bottom(), "left");
break;
case ILatchable::ResizeTop:
QMT_CHECK(false);
break;
case ILatchable::ResizeRight:
- result << ILatchable::Latch(ILatchable::Right, rect.right(), rect.top(), rect.bottom(), QStringLiteral("right"));
+ result << ILatchable::Latch(ILatchable::Right, rect.right(), rect.top(), rect.bottom(), "right");
break;
case ILatchable::ResizeBottom:
QMT_CHECK(false);
@@ -281,26 +307,91 @@ QList<ILatchable::Latch> ObjectItem::verticalLatches(ILatchable::Action action,
QList<ILatchable::Latch> result;
switch (action) {
case ILatchable::Move:
- result << ILatchable::Latch(ILatchable::Top, rect.top(), rect.left(), rect.right(), QStringLiteral("top"))
- << ILatchable::Latch(ILatchable::Vcenter, rect.center().y(), rect.left(), rect.right(), QStringLiteral("center"))
- << ILatchable::Latch(ILatchable::Bottom, rect.bottom(), rect.left(), rect.right(), QStringLiteral("bottom"));
+ result << ILatchable::Latch(ILatchable::Top, rect.top(), rect.left(), rect.right(), "top")
+ << ILatchable::Latch(ILatchable::Vcenter, rect.center().y(), rect.left(), rect.right(), "center")
+ << ILatchable::Latch(ILatchable::Bottom, rect.bottom(), rect.left(), rect.right(), "bottom");
break;
case ILatchable::ResizeLeft:
QMT_CHECK(false);
break;
case ILatchable::ResizeTop:
- result << ILatchable::Latch(ILatchable::Top, rect.top(), rect.left(), rect.right(), QStringLiteral("top"));
+ result << ILatchable::Latch(ILatchable::Top, rect.top(), rect.left(), rect.right(), "top");
break;
case ILatchable::ResizeRight:
QMT_CHECK(false);
break;
case ILatchable::ResizeBottom:
- result << ILatchable::Latch(ILatchable::Bottom, rect.bottom(), rect.left(), rect.right(), QStringLiteral("bottom"));
+ result << ILatchable::Latch(ILatchable::Bottom, rect.bottom(), rect.left(), rect.right(), "bottom");
break;
}
return result;
}
+QPointF ObjectItem::relationStartPos() const
+{
+ return pos();
+}
+
+void ObjectItem::relationDrawn(const QString &id, const QPointF &toScenePos, const QList<QPointF> &intermediatePoints)
+{
+ ObjectItem *targetItem = diagramSceneModel()->findTopmostObjectItem(toScenePos);
+ if (targetItem)
+ relationDrawn(id, targetItem, intermediatePoints);
+}
+
+void ObjectItem::relationDrawn(const QString &id, ObjectItem *targetItem, const QList<QPointF> &intermediatePoints)
+{
+ DiagramSceneController *diagramSceneController = diagramSceneModel()->diagramSceneController();
+ if (id == DEPENDENCY) {
+ DObject *dependantObject = targetItem->object();
+ if (dependantObject)
+ diagramSceneController->createDependency(object(), dependantObject, intermediatePoints,
+ diagramSceneModel()->diagram());
+ } else {
+ StereotypeController *stereotypeController = diagramSceneModel()->stereotypeController();
+ CustomRelation customRelation = stereotypeController->findCustomRelation(id);
+ if (!customRelation.isNull()) {
+ switch (customRelation.element()) {
+ case CustomRelation::Element::Dependency:
+ {
+ DObject *dependantObject = targetItem->object();
+ if (dependantObject)
+ diagramSceneController->createDependency(object(), dependantObject, intermediatePoints,
+ diagramSceneModel()->diagram());
+ break;
+ }
+ case CustomRelation::Element::Relation:
+ {
+ DObject *relatedObject = targetItem->object();
+ if (relatedObject) {
+ // check if element is allowed as target
+ QList<QString> endItems = customRelation.endB().endItems();
+ if (endItems.isEmpty())
+ endItems = customRelation.endItems();
+ QString elementType;
+ if (!targetItem->stereotypeIconId().isEmpty())
+ elementType = targetItem->stereotypeIconId();
+ else if (!targetItem->shapeIconId().isEmpty())
+ elementType = targetItem->shapeIconId();
+ else
+ elementType = targetItem->elementType();
+ if (!endItems.contains(elementType)) {
+ return;
+ }
+ // create relation
+ diagramSceneController->createConnection(id, object(), relatedObject, intermediatePoints,
+ diagramSceneModel()->diagram());
+ }
+ break;
+ }
+ default:
+ // ignore other elements
+ break;
+ }
+ }
+ }
+}
+
void ObjectItem::align(IAlignable::AlignType alignType, const QString &identifier)
{
Q_UNUSED(identifier); // avoid warning in release mode
@@ -309,49 +400,49 @@ void ObjectItem::align(IAlignable::AlignType alignType, const QString &identifie
// but this implementation does not. So assert the names.
switch (alignType) {
case IAlignable::AlignLeft:
- QMT_CHECK(identifier == QStringLiteral("left"));
+ QMT_CHECK(identifier == "left");
m_diagramSceneModel->diagramSceneController()->alignLeft(m_object, m_diagramSceneModel->selectedElements(),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignRight:
- QMT_CHECK(identifier == QStringLiteral("right"));
+ QMT_CHECK(identifier == "right");
m_diagramSceneModel->diagramSceneController()->alignRight(m_object, m_diagramSceneModel->selectedElements(),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignTop:
- QMT_CHECK(identifier == QStringLiteral("top"));
+ QMT_CHECK(identifier == "top");
m_diagramSceneModel->diagramSceneController()->alignTop(m_object, m_diagramSceneModel->selectedElements(),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignBottom:
- QMT_CHECK(identifier == QStringLiteral("bottom"));
+ QMT_CHECK(identifier == "bottom");
m_diagramSceneModel->diagramSceneController()->alignBottom(m_object, m_diagramSceneModel->selectedElements(),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignHcenter:
- QMT_CHECK(identifier == QStringLiteral("center"));
+ QMT_CHECK(identifier == "center");
m_diagramSceneModel->diagramSceneController()->alignHCenter(m_object, m_diagramSceneModel->selectedElements(),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignVcenter:
- QMT_CHECK(identifier == QStringLiteral("center"));
+ QMT_CHECK(identifier == "center");
m_diagramSceneModel->diagramSceneController()->alignVCenter(m_object, m_diagramSceneModel->selectedElements(),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignWidth:
- QMT_CHECK(identifier == QStringLiteral("width"));
+ QMT_CHECK(identifier == "width");
m_diagramSceneModel->diagramSceneController()->alignWidth(m_object, m_diagramSceneModel->selectedElements(),
minimumSize(m_diagramSceneModel->selectedItems()),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignHeight:
- QMT_CHECK(identifier == QStringLiteral("height"));
+ QMT_CHECK(identifier == "height");
m_diagramSceneModel->diagramSceneController()->alignHeight(m_object, m_diagramSceneModel->selectedElements(),
minimumSize(m_diagramSceneModel->selectedItems()),
m_diagramSceneModel->diagram());
break;
case IAlignable::AlignSize:
- QMT_CHECK(identifier == QStringLiteral("size"));
+ QMT_CHECK(identifier == "size");
m_diagramSceneModel->diagramSceneController()->alignSize(m_object, m_diagramSceneModel->selectedElements(),
minimumSize(m_diagramSceneModel->selectedItems()),
m_diagramSceneModel->diagram());
@@ -400,7 +491,7 @@ void ObjectItem::updateStereotypes(const QString &stereotypeIconId, StereotypeIc
} else if (m_stereotypeIcon) {
m_stereotypeIcon->scene()->removeItem(m_stereotypeIcon);
delete m_stereotypeIcon;
- m_stereotypeIcon = 0;
+ m_stereotypeIcon = nullptr;
}
if (stereotypeDisplay != StereotypeIcon::DisplayNone && !stereotypes.isEmpty()) {
if (!m_stereotypes)
@@ -411,7 +502,7 @@ void ObjectItem::updateStereotypes(const QString &stereotypeIconId, StereotypeIc
} else if (m_stereotypes) {
m_stereotypes->scene()->removeItem(m_stereotypes);
delete m_stereotypes;
- m_stereotypes = 0;
+ m_stereotypes = nullptr;
}
}
@@ -559,7 +650,7 @@ void ObjectItem::updateSelectionMarker(ResizeFlags resizeFlags)
if (m_selectionMarker->scene())
m_selectionMarker->scene()->removeItem(m_selectionMarker);
delete m_selectionMarker;
- m_selectionMarker = 0;
+ m_selectionMarker = nullptr;
}
}
@@ -569,6 +660,118 @@ void ObjectItem::updateSelectionMarkerGeometry(const QRectF &objectRect)
m_selectionMarker->setRect(objectRect);
}
+void ObjectItem::updateRelationStarter()
+{
+ if (isFocusSelected()) {
+ if (!m_relationStarter) {
+ m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
+ scene()->addItem(m_relationStarter);
+ m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
+ QString elementType;
+ if (!m_stereotypeIconId.isEmpty())
+ elementType = m_stereotypeIconId;
+ else if (!m_shapeIconId.isEmpty())
+ elementType = m_shapeIconId;
+ else
+ elementType = m_elementType;
+ StereotypeController *stereotypeController = diagramSceneModel()->stereotypeController();
+ QList<Toolbar> toolbars = stereotypeController->findToolbars(elementType);
+ if (!toolbars.isEmpty()) {
+ foreach (const Toolbar &toolbar, toolbars) {
+ foreach (const Toolbar::Tool &tool, toolbar.tools()) {
+ CustomRelation customRelation =
+ stereotypeController->findCustomRelation(tool.m_elementType);
+ if (!customRelation.isNull())
+ addRelationStarterTool(customRelation);
+ else
+ addRelationStarterTool(tool.m_elementType);
+ }
+ }
+ } else {
+ addStandardRelationStarterTools();
+ }
+ }
+ } else if (m_relationStarter) {
+ scene()->removeItem(m_relationStarter);
+ delete m_relationStarter;
+ m_relationStarter = nullptr;
+ }
+
+}
+
+void ObjectItem::addRelationStarterTool(const QString &id)
+{
+ if (id == DEPENDENCY)
+ m_relationStarter->addArrow(DEPENDENCY, ArrowItem::ShaftDashed,
+ ArrowItem::HeadNone, ArrowItem::HeadOpen,
+ tr("Dependency"));
+}
+
+void ObjectItem::addRelationStarterTool(const CustomRelation &customRelation)
+{
+ ArrowItem::Shaft shaft = ArrowItem::ShaftSolid;
+ ArrowItem::Head headStart = ArrowItem::HeadNone;
+ ArrowItem::Head headEnd = ArrowItem::HeadNone;
+ switch (customRelation.element()) {
+ case CustomRelation::Element::Dependency:
+ shaft = ArrowItem::ShaftDashed;
+ switch (customRelation.direction()) {
+ case CustomRelation::Direction::AtoB:
+ headEnd = ArrowItem::HeadOpen;
+ break;
+ case CustomRelation::Direction::BToA:
+ headStart = ArrowItem::HeadOpen;
+ break;
+ case CustomRelation::Direction::Bi:
+ headStart = ArrowItem::HeadOpen;
+ headEnd = ArrowItem::HeadOpen;
+ break;
+ }
+ break;
+ case CustomRelation::Element::Relation:
+ {
+ // TODO support custom shapes
+ static const QHash<CustomRelation::ShaftPattern, ArrowItem::Shaft> shaft2shaft = {
+ { CustomRelation::ShaftPattern::Solid, ArrowItem::ShaftSolid },
+ { CustomRelation::ShaftPattern::Dash, ArrowItem::ShaftDashed },
+ { CustomRelation::ShaftPattern::Dot, ArrowItem::ShaftDot },
+ { CustomRelation::ShaftPattern::DashDot, ArrowItem::ShaftDashDot },
+ { CustomRelation::ShaftPattern::DashDotDot, ArrowItem::ShaftDashDotDot },
+ };
+ static const QHash<CustomRelation::Head, ArrowItem::Head> head2head = {
+ { CustomRelation::Head::None, ArrowItem::HeadNone },
+ { CustomRelation::Head::Shape, ArrowItem::HeadNone },
+ { CustomRelation::Head::Arrow, ArrowItem::HeadOpen },
+ { CustomRelation::Head::Triangle, ArrowItem::HeadTriangle },
+ { CustomRelation::Head::FilledTriangle, ArrowItem::HeadFilledTriangle },
+ { CustomRelation::Head::Diamond, ArrowItem::HeadDiamond },
+ { CustomRelation::Head::FilledDiamond, ArrowItem::HeadFilledDiamond },
+ };
+ shaft = shaft2shaft.value(customRelation.shaftPattern());
+ headStart = head2head.value(customRelation.endA().head());
+ headEnd = head2head.value(customRelation.endB().head());
+ // TODO use color?
+ break;
+ }
+ default:
+ return;
+ }
+ m_relationStarter->addArrow(customRelation.id(), shaft, headStart, headEnd,
+ customRelation.title());
+
+}
+
+void ObjectItem::addStandardRelationStarterTools()
+{
+ addRelationStarterTool(DEPENDENCY);
+}
+
+void ObjectItem::updateRelationStarterGeometry(const QRectF &objectRect)
+{
+ if (m_relationStarter)
+ m_relationStarter->setPos(mapToScene(QPointF(objectRect.right() + 8.0, objectRect.top())));
+}
+
void ObjectItem::updateAlignmentButtons()
{
if (isFocusSelected() && m_diagramSceneModel->hasMultiObjectsSelection()) {
@@ -588,13 +791,13 @@ void ObjectItem::updateAlignmentButtons()
if (m_horizontalAlignButtons->scene())
m_horizontalAlignButtons->scene()->removeItem(m_horizontalAlignButtons);
delete m_horizontalAlignButtons;
- m_horizontalAlignButtons = 0;
+ m_horizontalAlignButtons = nullptr;
}
if (m_verticalAlignButtons) {
if (m_verticalAlignButtons->scene())
m_verticalAlignButtons->scene()->removeItem(m_verticalAlignButtons);
delete m_verticalAlignButtons;
- m_verticalAlignButtons = 0;
+ m_verticalAlignButtons = nullptr;
}
}
}
@@ -674,7 +877,7 @@ bool ObjectItem::showContext() const
// TODO Because of this algorithm adding, moving, removing of one item need to update() all colliding items as well
QMT_CHECK(object()->modelUid().isValid());
MObject *mobject = m_diagramSceneModel->diagramController()->modelController()->findObject(object()->modelUid());
- QMT_CHECK(mobject);
+ QMT_ASSERT(mobject, return false);
MObject *owner = mobject->owner();
if (owner) {
foreach (QGraphicsItem *item, m_diagramSceneModel->collectCollidingObjectItems(this, DiagramSceneModel::CollidingOuterItems)) {
@@ -740,10 +943,10 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
bool addSeparator = false;
if (element_tasks->hasDiagram(m_object, m_diagramSceneModel->diagram())) {
- menu.addAction(new ContextMenuAction(tr("Open Diagram"), QStringLiteral("openDiagram"), &menu));
+ menu.addAction(new ContextMenuAction(tr("Open Diagram"), "openDiagram", &menu));
addSeparator = true;
} else if (element_tasks->mayCreateDiagram(m_object, m_diagramSceneModel->diagram())) {
- menu.addAction(new ContextMenuAction(tr("Create Diagram"), QStringLiteral("createDiagram"), &menu));
+ menu.addAction(new ContextMenuAction(tr("Create Diagram"), "createDiagram", &menu));
addSeparator = true;
}
if (extendContextMenu(&menu))
@@ -752,70 +955,70 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
addSeparator = true;
if (addSeparator)
menu.addSeparator();
- menu.addAction(new ContextMenuAction(tr("Remove"), QStringLiteral("remove"),
+ menu.addAction(new ContextMenuAction(tr("Remove"), "remove",
QKeySequence(QKeySequence::Delete), &menu));
- menu.addAction(new ContextMenuAction(tr("Delete"), QStringLiteral("delete"),
+ menu.addAction(new ContextMenuAction(tr("Delete"), "delete",
QKeySequence(Qt::CTRL + Qt::Key_D), &menu));
- //menu.addAction(new ContextMenuAction(tr("Select in Model Tree"), QStringLiteral("selectInModelTree"), &menu));
+ //menu.addAction(new ContextMenuAction(tr("Select in Model Tree"), "selectInModelTree", &menu));
QMenu alignMenu;
alignMenu.setTitle(tr("Align Objects"));
- alignMenu.addAction(new ContextMenuAction(tr("Align Left"), QStringLiteral("alignLeft"), &alignMenu));
- alignMenu.addAction(new ContextMenuAction(tr("Center Vertically"), QStringLiteral("centerVertically"),
+ alignMenu.addAction(new ContextMenuAction(tr("Align Left"), "alignLeft", &alignMenu));
+ alignMenu.addAction(new ContextMenuAction(tr("Center Vertically"), "centerVertically",
&alignMenu));
- alignMenu.addAction(new ContextMenuAction(tr("Align Right"), QStringLiteral("alignRight"), &alignMenu));
+ alignMenu.addAction(new ContextMenuAction(tr("Align Right"), "alignRight", &alignMenu));
alignMenu.addSeparator();
- alignMenu.addAction(new ContextMenuAction(tr("Align Top"), QStringLiteral("alignTop"), &alignMenu));
- alignMenu.addAction(new ContextMenuAction(tr("Center Horizontally"), QStringLiteral("centerHorizontally"),
+ alignMenu.addAction(new ContextMenuAction(tr("Align Top"), "alignTop", &alignMenu));
+ alignMenu.addAction(new ContextMenuAction(tr("Center Horizontally"), "centerHorizontally",
&alignMenu));
- alignMenu.addAction(new ContextMenuAction(tr("Align Bottom"), QStringLiteral("alignBottom"), &alignMenu));
+ alignMenu.addAction(new ContextMenuAction(tr("Align Bottom"), "alignBottom", &alignMenu));
alignMenu.addSeparator();
- alignMenu.addAction(new ContextMenuAction(tr("Same Width"), QStringLiteral("sameWidth"), &alignMenu));
- alignMenu.addAction(new ContextMenuAction(tr("Same Height"), QStringLiteral("sameHeight"), &alignMenu));
- alignMenu.addAction(new ContextMenuAction(tr("Same Size"), QStringLiteral("sameSize"), &alignMenu));
+ alignMenu.addAction(new ContextMenuAction(tr("Same Width"), "sameWidth", &alignMenu));
+ alignMenu.addAction(new ContextMenuAction(tr("Same Height"), "sameHeight", &alignMenu));
+ alignMenu.addAction(new ContextMenuAction(tr("Same Size"), "sameSize", &alignMenu));
alignMenu.setEnabled(m_diagramSceneModel->hasMultiObjectsSelection());
menu.addMenu(&alignMenu);
QAction *selectedAction = menu.exec(event->screenPos());
if (selectedAction) {
auto action = dynamic_cast<ContextMenuAction *>(selectedAction);
- QMT_CHECK(action);
+ QMT_ASSERT(action, return);
bool handled = handleSelectedContextMenuAction(action->id());
handled |= element_tasks->handleContextMenuAction(object(), diagramSceneModel()->diagram(), action->id());
if (!handled) {
- if (action->id() == QStringLiteral("openDiagram")) {
+ if (action->id() == "openDiagram") {
m_diagramSceneModel->diagramSceneController()->elementTasks()->openDiagram(m_object, m_diagramSceneModel->diagram());
- } else if (action->id() == QStringLiteral("createDiagram")) {
+ } else if (action->id() == "createDiagram") {
m_diagramSceneModel->diagramSceneController()->elementTasks()->createAndOpenDiagram(m_object, m_diagramSceneModel->diagram());
- } else if (action->id() == QStringLiteral("remove")) {
+ } else if (action->id() == "remove") {
DSelection selection = m_diagramSceneModel->selectedElements();
if (selection.isEmpty())
selection.append(m_object->uid(), m_diagramSceneModel->diagram()->uid());
m_diagramSceneModel->diagramController()->deleteElements(selection, m_diagramSceneModel->diagram());
- } else if (action->id() == QStringLiteral("delete")) {
+ } else if (action->id() == "delete") {
DSelection selection = m_diagramSceneModel->selectedElements();
if (selection.isEmpty())
selection.append(m_object->uid(), m_diagramSceneModel->diagram()->uid());
m_diagramSceneModel->diagramSceneController()->deleteFromDiagram(selection, m_diagramSceneModel->diagram());
- } else if (action->id() == QStringLiteral("selectInModelTree")) {
+ } else if (action->id() == "selectInModelTree") {
// TODO implement
- } else if (action->id() == QStringLiteral("alignLeft")) {
- align(IAlignable::AlignLeft, QStringLiteral("left"));
- } else if (action->id() == QStringLiteral("centerVertically")) {
- align(IAlignable::AlignVcenter, QStringLiteral("center"));
- } else if (action->id() == QStringLiteral("alignRight")) {
- align(IAlignable::AlignRight, QStringLiteral("right"));
- } else if (action->id() == QStringLiteral("alignTop")) {
- align(IAlignable::AlignTop, QStringLiteral("top"));
- } else if (action->id() == QStringLiteral("centerHorizontally")) {
- align(IAlignable::AlignHcenter, QStringLiteral("center"));
- } else if (action->id() == QStringLiteral("alignBottom")) {
- align(IAlignable::AlignBottom, QStringLiteral("bottom"));
- } else if (action->id() == QStringLiteral("sameWidth")) {
- align(IAlignable::AlignWidth, QStringLiteral("width"));
- } else if (action->id() == QStringLiteral("sameHeight")) {
- align(IAlignable::AlignHeight, QStringLiteral("height"));
- } else if (action->id() == QStringLiteral("sameSize")) {
- align(IAlignable::AlignSize, QStringLiteral("size"));
+ } else if (action->id() == "alignLeft") {
+ align(IAlignable::AlignLeft, "left");
+ } else if (action->id() == "centerVertically") {
+ align(IAlignable::AlignVcenter, "center");
+ } else if (action->id() == "alignRight") {
+ align(IAlignable::AlignRight, "right");
+ } else if (action->id() == "alignTop") {
+ align(IAlignable::AlignTop, "top");
+ } else if (action->id() == "centerHorizontally") {
+ align(IAlignable::AlignHcenter, "center");
+ } else if (action->id() == "alignBottom") {
+ align(IAlignable::AlignBottom, "bottom");
+ } else if (action->id() == "sameWidth") {
+ align(IAlignable::AlignWidth, "width");
+ } else if (action->id() == "sameHeight") {
+ align(IAlignable::AlignHeight, "height");
+ } else if (action->id() == "sameSize") {
+ align(IAlignable::AlignSize, "size");
}
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h
index 5595c86667..89bf89ea57 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h
@@ -32,6 +32,7 @@
#include "qmt/diagram_scene/capabilities/moveable.h"
#include "qmt/diagram_scene/capabilities/selectable.h"
#include "qmt/diagram_scene/capabilities/latchable.h"
+#include "qmt/diagram_scene/capabilities/relationable.h"
#include "qmt/diagram_scene/capabilities/alignable.h"
#include "qmt/diagram_scene/capabilities/editable.h"
@@ -45,12 +46,15 @@ QT_END_NAMESPACE
namespace qmt {
+class DElement;
class DObject;
class DiagramSceneModel;
class StereotypesItem;
class CustomIconItem;
+class CustomRelation;
class EditableTextItem;
class RectangularSelectionItem;
+class RelationStarter;
class AlignButtonsItem;
class Style;
@@ -66,6 +70,7 @@ class ObjectItem :
public IMoveable,
public ISelectable,
public ILatchable,
+ public IRelationable,
public IAlignable,
public IEditable
{
@@ -81,9 +86,10 @@ protected:
};
public:
- ObjectItem(DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = 0);
+ ObjectItem(const QString &elementType, DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = nullptr);
~ObjectItem() override;
+ QString elementType() const { return m_elementType; }
DObject *object() const { return m_object; }
DiagramSceneModel *diagramSceneModel() const { return m_diagramSceneModel; }
@@ -107,12 +113,20 @@ public:
void setSecondarySelected(bool secondarySelected) override;
bool isFocusSelected() const override;
void setFocusSelected(bool focusSelected) override;
+ QRectF getSecondarySelectionBoundary() override;
+ void setBoundarySelected(const QRectF &boundary, bool secondary) override;
Action horizontalLatchAction() const override;
Action verticalLatchAction() const override;
QList<Latch> horizontalLatches(Action action, bool grabbedItem) const override;
QList<Latch> verticalLatches(Action action, bool grabbedItem) const override;
+ QPointF relationStartPos() const override;
+ void relationDrawn(const QString &id, const QPointF &toScenePos,
+ const QList<QPointF> &intermediatePoints) override;
+ virtual void relationDrawn(const QString &id, ObjectItem *targetElement,
+ const QList<QPointF> &intermediatePoints);
+
void align(AlignType alignType, const QString &identifier) override;
bool isEditable() const override;
@@ -139,6 +153,12 @@ protected:
void updateSelectionMarker(CustomIconItem *customIconItem);
void updateSelectionMarker(ResizeFlags resizeFlags);
void updateSelectionMarkerGeometry(const QRectF &objectRect);
+ void updateRelationStarter();
+ RelationStarter *relationStarter() const { return m_relationStarter; }
+ virtual void addRelationStarterTool(const QString &id);
+ virtual void addRelationStarterTool(const CustomRelation &customRelation);
+ virtual void addStandardRelationStarterTools();
+ void updateRelationStarterGeometry(const QRectF &objectRect);
void updateAlignmentButtons();
void updateAlignmentButtonsGeometry(const QRectF &objectRect);
@@ -158,19 +178,21 @@ protected:
private:
QSizeF minimumSize(const QSet<QGraphicsItem *> &items) const;
- DObject *m_object = 0;
- DiagramSceneModel *m_diagramSceneModel = 0;
+ QString m_elementType;
+ DObject *m_object = nullptr;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
bool m_isSecondarySelected = false;
bool m_isFocusSelected = false;
QString m_stereotypeIconId;
QString m_shapeIconId;
StereotypeIcon::Display m_stereotypeIconDisplay = StereotypeIcon::DisplayLabel;
- StereotypesItem *m_stereotypes = 0;
- CustomIconItem *m_stereotypeIcon = 0;
- EditableTextItem *m_nameItem = 0;
- RectangularSelectionItem *m_selectionMarker = 0;
- AlignButtonsItem *m_horizontalAlignButtons = 0;
- AlignButtonsItem *m_verticalAlignButtons = 0;
+ StereotypesItem *m_stereotypes = nullptr;
+ CustomIconItem *m_stereotypeIcon = nullptr;
+ EditableTextItem *m_nameItem = nullptr;
+ RectangularSelectionItem *m_selectionMarker = nullptr;
+ RelationStarter *m_relationStarter = nullptr;
+ AlignButtonsItem *m_horizontalAlignButtons = nullptr;
+ AlignButtonsItem *m_verticalAlignButtons = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp
index 783a284fa3..97ff26f00a 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp
@@ -32,7 +32,6 @@
#include "qmt/diagram_scene/parts/contextlabelitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/editabletextitem.h"
-#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/stereotype/stereotypecontroller.h"
@@ -72,7 +71,7 @@ public:
};
PackageItem::PackageItem(DPackage *package, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
- : ObjectItem(package, diagramSceneModel, parent)
+ : ObjectItem("package", package, diagramSceneModel, parent)
{
}
@@ -99,7 +98,7 @@ void PackageItem::update()
} else if (m_customIcon) {
m_customIcon->scene()->removeItem(m_customIcon);
delete m_customIcon;
- m_customIcon = 0;
+ m_customIcon = nullptr;
}
// shape
@@ -112,7 +111,7 @@ void PackageItem::update()
} else if (m_shape) {
m_shape->scene()->removeItem(m_shape);
delete m_shape;
- m_shape = 0;
+ m_shape = nullptr;
}
// stereotypes
@@ -131,25 +130,11 @@ void PackageItem::update()
} else if (m_contextLabel) {
m_contextLabel->scene()->removeItem(m_contextLabel);
delete m_contextLabel;
- m_contextLabel = 0;
+ m_contextLabel = nullptr;
}
updateSelectionMarker(m_customIcon);
-
- // relation starters
- if (isFocusSelected()) {
- if (!m_relationStarter) {
- m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
- scene()->addItem(m_relationStarter);
- m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
- m_relationStarter->addArrow(QStringLiteral("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
- }
- } else if (m_relationStarter) {
- scene()->removeItem(m_relationStarter);
- delete m_relationStarter;
- m_relationStarter = 0;
- }
-
+ updateRelationStarter();
updateAlignmentButtons();
updateGeometry();
}
@@ -190,23 +175,6 @@ QList<ILatchable::Latch> PackageItem::verticalLatches(ILatchable::Action action,
return ObjectItem::verticalLatches(action, grabbedItem);
}
-QPointF PackageItem::relationStartPos() const
-{
- return pos();
-}
-
-void PackageItem::relationDrawn(const QString &id, const QPointF &toScenePos, const QList<QPointF> &intermediatePoints)
-{
- DElement *targetElement = diagramSceneModel()->findTopmostElement(toScenePos);
- if (targetElement) {
- if (id == QStringLiteral("dependency")) {
- auto dependantObject = dynamic_cast<DObject *>(targetElement);
- if (dependantObject)
- diagramSceneModel()->diagramSceneController()->createDependency(object(), dependantObject, intermediatePoints, diagramSceneModel()->diagram());
- }
- }
-}
-
PackageItem::ShapeGeometry PackageItem::calcMinimumGeometry() const
{
double width = 0.0;
@@ -343,10 +311,7 @@ void PackageItem::updateGeometry()
}
updateSelectionMarkerGeometry(rect);
-
- if (m_relationStarter)
- m_relationStarter->setPos(mapToScene(QPointF(right + 8.0, top)));
-
+ updateRelationStarterGeometry(rect);
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h
index c08add8368..323447dda5 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h
@@ -27,8 +27,6 @@
#include "objectitem.h"
-#include "qmt/diagram_scene/capabilities/relationable.h"
-
QT_BEGIN_NAMESPACE
class QGraphicsPolygonItem;
class QGraphicsSimpleTextItem;
@@ -42,12 +40,12 @@ class CustomIconItem;
class ContextLabelItem;
class RelationStarter;
-class PackageItem : public ObjectItem, public IRelationable
+class PackageItem : public ObjectItem
{
class ShapeGeometry;
public:
- PackageItem(DPackage *package, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = 0);
+ PackageItem(DPackage *package, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = nullptr);
~PackageItem() override;
void update() override;
@@ -60,18 +58,13 @@ public:
QList<Latch> horizontalLatches(Action action, bool grabbedItem) const override;
QList<Latch> verticalLatches(Action action, bool grabbedItem) const override;
- QPointF relationStartPos() const override;
- void relationDrawn(const QString &id, const QPointF &toScenePos,
- const QList<QPointF> &intermediatePoints) override;
-
private:
ShapeGeometry calcMinimumGeometry() const;
void updateGeometry();
- CustomIconItem *m_customIcon = 0;
- QGraphicsPolygonItem *m_shape = 0;
- ContextLabelItem *m_contextLabel = 0;
- RelationStarter *m_relationStarter = 0;
+ CustomIconItem *m_customIcon = nullptr;
+ QGraphicsPolygonItem *m_shape = nullptr;
+ ContextLabelItem *m_contextLabel = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp
index 338c57595b..6904bc2a04 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp
@@ -28,6 +28,7 @@
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram_controller/dvoidvisitor.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/dobject.h"
@@ -41,6 +42,8 @@
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
+#include "qmt/stereotype/customrelation.h"
+#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/styledrelation.h"
#include "qmt/style/style.h"
@@ -67,11 +70,11 @@ public:
void visitDInheritance(const DInheritance *inheritance)
{
DObject *baseObject = m_diagramSceneModel->diagramController()->findElement<DObject>(inheritance->base(), m_diagramSceneModel->diagram());
- QMT_CHECK(baseObject);
+ QMT_ASSERT(baseObject, return);
bool baseIsInterface = false;
bool lollipopDisplay = false;
if (baseObject) {
- baseIsInterface = baseObject->stereotypes().contains(QStringLiteral("interface"));
+ baseIsInterface = baseObject->stereotypes().contains("interface");
if (baseIsInterface) {
StereotypeDisplayVisitor stereotypeDisplayVisitor;
stereotypeDisplayVisitor.setModelController(m_diagramSceneModel->diagramSceneController()->modelController());
@@ -83,7 +86,7 @@ public:
if (lollipopDisplay) {
m_arrow->setShaft(ArrowItem::ShaftSolid);
m_arrow->setEndHead(ArrowItem::HeadNone);
- } else if (baseIsInterface || inheritance->stereotypes().contains(QStringLiteral("realize"))) {
+ } else if (baseIsInterface || inheritance->stereotypes().contains("realize")) {
m_arrow->setShaft(ArrowItem::ShaftDashed);
m_arrow->setEndHead(ArrowItem::HeadTriangle);
} else {
@@ -99,7 +102,7 @@ public:
{
ArrowItem::Head endAHead = ArrowItem::HeadNone;
ArrowItem::Head endBHead = ArrowItem::HeadNone;
- bool isRealization = dependency->stereotypes().contains(QStringLiteral("realize"));
+ bool isRealization = dependency->stereotypes().contains("realize");
switch (dependency->direction()) {
case MDependency::AToB:
endBHead = isRealization ? ArrowItem::HeadTriangle : ArrowItem::HeadOpen;
@@ -166,9 +169,49 @@ public:
m_arrow->setPoints(m_points);
}
+ void visitDConnection(const DConnection *connection)
+ {
+
+ ArrowItem::Shaft shaft = ArrowItem::ShaftSolid;
+ ArrowItem::Head endAHead = ArrowItem::HeadNone;
+ ArrowItem::Head endBHead = ArrowItem::HeadNone;
+
+ CustomRelation customRelation = m_diagramSceneModel->stereotypeController()->findCustomRelation(connection->customRelationId());
+ if (!customRelation.isNull()) {
+ // TODO support custom shapes
+ static const QHash<CustomRelation::ShaftPattern, ArrowItem::Shaft> shaft2shaft = {
+ { CustomRelation::ShaftPattern::Solid, ArrowItem::ShaftSolid },
+ { CustomRelation::ShaftPattern::Dash, ArrowItem::ShaftDashed },
+ { CustomRelation::ShaftPattern::Dot, ArrowItem::ShaftDot },
+ { CustomRelation::ShaftPattern::DashDot, ArrowItem::ShaftDashDot },
+ { CustomRelation::ShaftPattern::DashDotDot, ArrowItem::ShaftDashDotDot },
+ };
+ static const QHash<CustomRelation::Head, ArrowItem::Head> head2head = {
+ { CustomRelation::Head::None, ArrowItem::HeadNone },
+ { CustomRelation::Head::Shape, ArrowItem::HeadNone },
+ { CustomRelation::Head::Arrow, ArrowItem::HeadOpen },
+ { CustomRelation::Head::Triangle, ArrowItem::HeadTriangle },
+ { CustomRelation::Head::FilledTriangle, ArrowItem::HeadFilledTriangle },
+ { CustomRelation::Head::Diamond, ArrowItem::HeadDiamond },
+ { CustomRelation::Head::FilledDiamond, ArrowItem::HeadFilledDiamond },
+ };
+ shaft = shaft2shaft.value(customRelation.shaftPattern());
+ endAHead = head2head.value(customRelation.endA().head());
+ endBHead = head2head.value(customRelation.endB().head());
+ // TODO color
+ }
+
+ m_arrow->setShaft(shaft);
+ m_arrow->setArrowSize(12.0);
+ m_arrow->setDiamondSize(12.0);
+ m_arrow->setStartHead(endAHead);
+ m_arrow->setEndHead(endBHead);
+ m_arrow->setPoints(m_points);
+ }
+
private:
- DiagramSceneModel *m_diagramSceneModel = 0;
- ArrowItem *m_arrow = 0;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
+ ArrowItem *m_arrow = nullptr;
QList<QPointF> m_points;
};
@@ -273,6 +316,18 @@ void RelationItem::setFocusSelected(bool focusSelected)
}
}
+QRectF RelationItem::getSecondarySelectionBoundary()
+{
+ return QRectF();
+}
+
+void RelationItem::setBoundarySelected(const QRectF &boundary, bool secondary)
+{
+ // TODO make individual intermediate points selectable
+ Q_UNUSED(boundary)
+ Q_UNUSED(secondary)
+}
+
QPointF RelationItem::grabHandle(int index)
{
if (index == 0) {
@@ -289,7 +344,7 @@ QPointF RelationItem::grabHandle(int index)
} else {
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
--index;
- QMT_CHECK(index >= 0 && index < intermediatePoints.size());
+ QMT_ASSERT(index >= 0 && index < intermediatePoints.size(), return QPointF());
return intermediatePoints.at(index).pos();
}
}
@@ -337,7 +392,7 @@ void RelationItem::setHandlePos(int index, const QPointF &pos)
} else {
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
--index;
- QMT_CHECK(index >= 0 && index < intermediatePoints.size());
+ QMT_ASSERT(index >= 0 && index < intermediatePoints.size(), return);
intermediatePoints[index].setPos(pos);
m_diagramSceneModel->diagramController()->startUpdateElement(m_relation, m_diagramSceneModel->diagram(), DiagramController::UpdateMinor);
@@ -361,7 +416,7 @@ void RelationItem::dropHandle(int index, double rasterWidth, double rasterHeight
} else {
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
--index;
- QMT_CHECK(index >= 0 && index < intermediatePoints.size());
+ QMT_ASSERT(index >= 0 && index < intermediatePoints.size(), return);
QPointF pos = intermediatePoints.at(index).pos();
double x = qRound(pos.x() / rasterWidth) * rasterWidth;
@@ -424,7 +479,7 @@ void RelationItem::update(const Style *style)
} else if (m_name) {
m_name->scene()->removeItem(m_name);
delete m_name;
- m_name = 0;
+ m_name = nullptr;
}
if (!m_relation->stereotypes().isEmpty()) {
@@ -437,7 +492,7 @@ void RelationItem::update(const Style *style)
} else if (m_stereotypes) {
m_stereotypes->scene()->removeItem(m_stereotypes);
delete m_stereotypes;
- m_stereotypes = 0;
+ m_stereotypes = nullptr;
}
if (isSelected() || isSecondarySelected()) {
@@ -449,7 +504,7 @@ void RelationItem::update(const Style *style)
if (m_selectionHandles->scene())
m_selectionHandles->scene()->removeItem(m_selectionHandles);
delete m_selectionHandles;
- m_selectionHandles = 0;
+ m_selectionHandles = nullptr;
}
setZValue((isSelected() || isSecondarySelected()) ? RELATION_ITEMS_ZVALUE_SELECTED : RELATION_ITEMS_ZVALUE);
@@ -486,7 +541,7 @@ QPointF RelationItem::calcEndPoint(const Uid &end, const Uid &otherEnd, int near
// otherEndPos will not be used
} else {
DObject *endOtherObject = m_diagramSceneModel->diagramController()->findElement<DObject>(otherEnd, m_diagramSceneModel->diagram());
- QMT_CHECK(endOtherObject);
+ QMT_ASSERT(endOtherObject, return QPointF());
if (endOtherObject)
otherEndPos = endOtherObject->pos();
}
@@ -502,7 +557,7 @@ QPointF RelationItem::calcEndPoint(const Uid &end, const QPointF &otherEndPos, i
QPointF endPos;
if (endObjectItem) {
DObject *endObject = m_diagramSceneModel->diagramController()->findElement<DObject>(end, m_diagramSceneModel->diagram());
- QMT_CHECK(endObject);
+ QMT_ASSERT(endObject, return QPointF());
bool preferAxis = false;
QPointF otherPos;
if (nearestIntermediatePointIndex >= 0 && nearestIntermediatePointIndex < m_relation->intermediatePoints().size()) {
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h
index 983d480fbc..4705b9c5e1 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h
@@ -54,7 +54,7 @@ class RelationItem :
public:
RelationItem(DRelation *relation, DiagramSceneModel *diagramSceneModel,
- QGraphicsItem *parent = 0);
+ QGraphicsItem *parent = nullptr);
~RelationItem() override;
DRelation *relation() const { return m_relation; }
@@ -70,6 +70,8 @@ public:
void setSecondarySelected(bool secondarySelected) override;
bool isFocusSelected() const override;
void setFocusSelected(bool focusSelected) override;
+ QRectF getSecondarySelectionBoundary() override;
+ void setBoundarySelected(const QRectF &boundary, bool secondary) override;
QPointF grabHandle(int index) override;
void insertHandle(int beforeIndex, const QPointF &pos, double rasterWidth, double rasterHeight) override;
@@ -92,16 +94,16 @@ private:
QPointF calcEndPoint(const Uid &end, const QPointF &otherEndPos,
int nearestIntermediatePointIndex);
- DRelation *m_relation = 0;
+ DRelation *m_relation = nullptr;
protected:
- DiagramSceneModel *m_diagramSceneModel = 0;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
bool m_isSecondarySelected = false;
bool m_isFocusSelected = false;
- ArrowItem *m_arrow = 0;
- QGraphicsSimpleTextItem *m_name = 0;
- StereotypesItem *m_stereotypes = 0;
- PathSelectionItem *m_selectionHandles = 0;
+ ArrowItem *m_arrow = nullptr;
+ QGraphicsSimpleTextItem *m_name = nullptr;
+ StereotypesItem *m_stereotypes = nullptr;
+ PathSelectionItem *m_selectionHandles = nullptr;
static bool m_grabbedEndA;
static bool m_grabbedEndB;
static QPointF m_grabbedEndPos;
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp
index b5130477ad..dae666a3eb 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp
@@ -121,7 +121,7 @@ void StereotypeDisplayVisitor::visitDClass(const DClass *klass)
m_stereotypeIconElement = StereotypeIcon::ElementClass;
MClass *modelKlass = m_modelController->findObject<MClass>(klass->modelUid());
bool hasMembers = false;
- if (!modelKlass->members().isEmpty() && klass->showAllMembers())
+ if (modelKlass && !modelKlass->members().isEmpty() && klass->showAllMembers())
hasMembers = true;
m_stereotypeSmartDisplay = hasMembers ? DObject::StereotypeDecoration : DObject::StereotypeIcon;
visitDObject(klass);
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.h b/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.h
index cac65534d2..feb83c0752 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.h
@@ -56,8 +56,8 @@ public:
void visitDItem(const DItem *item) override;
private:
- ModelController *m_modelController = 0;
- StereotypeController *m_stereotypeController = 0;
+ ModelController *m_modelController = nullptr;
+ StereotypeController *m_stereotypeController = nullptr;
DObject::StereotypeDisplay m_stereotypeDisplay = DObject::StereotypeNone;
QString m_stereotypeIconId;
QString m_shapeIconId;
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp
new file mode 100644
index 0000000000..ee8b791f6a
--- /dev/null
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "swimlaneitem.h"
+
+#include "qmt/diagram_controller/diagramcontroller.h"
+#include "qmt/diagram/dswimlane.h"
+#include "qmt/diagram_scene/diagramsceneconstants.h"
+#include "qmt/diagram_scene/diagramscenemodel.h"
+#include "qmt/infrastructure/qmtassert.h"
+#include "qmt/style/stylecontroller.h"
+#include "qmt/style/style.h"
+
+#include <QBrush>
+#include <QGraphicsLineItem>
+#include <QGraphicsScene>
+#include <QGraphicsSceneMouseEvent>
+#include <QPen>
+
+namespace qmt {
+
+static const qreal SWIMLANE_LENGTH = 100000;
+static const qreal SWIMLANE_WIDTH = 16;
+static const qreal SWIMLANE_MARKER_WIDTH = 8;
+
+SwimlaneItem::SwimlaneItem(DSwimlane *swimlane, DiagramSceneModel *diagramSceneModel,
+ QGraphicsItem *parent)
+ : QGraphicsItem (parent),
+ m_swimlane(swimlane),
+ m_diagramSceneModel(diagramSceneModel)
+{
+ setFlags(QGraphicsItem::ItemIsSelectable);
+}
+
+SwimlaneItem::~SwimlaneItem()
+{
+}
+
+QRectF SwimlaneItem::boundingRect() const
+{
+ if (m_swimlane->isHorizontal())
+ return QRectF(-SWIMLANE_LENGTH/2, -SWIMLANE_WIDTH/2, SWIMLANE_LENGTH, SWIMLANE_WIDTH);
+ else
+ return QRectF(-SWIMLANE_WIDTH/2, -SWIMLANE_LENGTH/2, SWIMLANE_WIDTH, SWIMLANE_LENGTH);
+}
+
+void SwimlaneItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+}
+
+void SwimlaneItem::update()
+{
+ QMT_CHECK(!m_isUpdating);
+ m_isUpdating = true;
+
+ prepareGeometryChange();
+
+ const Style *style = adaptedStyle();
+ Q_UNUSED(style);
+
+ // swimline line
+ if (!m_lineItem)
+ m_lineItem = new QGraphicsLineItem(this);
+ m_lineItem->setPen(QPen(QBrush(Qt::black), 1, Qt::DashLine));
+
+ updateSelectionMarker();
+ updateGeometry();
+ setZValue(SWIMLANE_ITEMS_ZVALUE);
+
+ m_isUpdating = false;
+}
+
+void SwimlaneItem::moveDelta(const QPointF &delta)
+{
+ m_diagramSceneModel->diagramController()->startUpdateElement(m_swimlane, m_diagramSceneModel->diagram(),
+ DiagramController::UpdateGeometry);
+ if (m_swimlane->isHorizontal())
+ m_swimlane->setPos(m_swimlane->pos() + delta.y());
+ else
+ m_swimlane->setPos(m_swimlane->pos() + delta.x());
+ m_diagramSceneModel->diagramController()->finishUpdateElement(m_swimlane, m_diagramSceneModel->diagram(), false);
+}
+
+void SwimlaneItem::alignItemPositionToRaster(double rasterWidth, double rasterHeight)
+{
+ if (m_swimlane->isHorizontal()) {
+ qreal yDelta = qRound(m_swimlane->pos() / rasterHeight) * rasterHeight - m_swimlane->pos();
+ moveDelta(QPointF(0, yDelta));
+ } else {
+ qreal xDelta = qRound(m_swimlane->pos() / rasterWidth) * rasterWidth - m_swimlane->pos();
+ moveDelta(QPointF(xDelta, 0));
+ }
+}
+
+bool SwimlaneItem::isSecondarySelected() const
+{
+ return m_secondarySelected;
+}
+
+void SwimlaneItem::setSecondarySelected(bool secondarySelected)
+{
+ if (m_secondarySelected != secondarySelected) {
+ m_secondarySelected = secondarySelected;
+ update();
+ }
+}
+
+bool SwimlaneItem::isFocusSelected() const
+{
+ return false;
+}
+
+void SwimlaneItem::setFocusSelected(bool focusSelected)
+{
+ Q_UNUSED(focusSelected);
+}
+
+QRectF SwimlaneItem::getSecondarySelectionBoundary()
+{
+ QRectF boundary;
+ if (m_swimlane->isHorizontal())
+ boundary = QRectF(-SWIMLANE_LENGTH/2, pos().y(), SWIMLANE_LENGTH, SWIMLANE_LENGTH);
+ else
+ boundary = QRectF(pos().x(), -SWIMLANE_LENGTH/2, SWIMLANE_LENGTH, SWIMLANE_LENGTH);
+ return boundary;
+}
+
+void SwimlaneItem::setBoundarySelected(const QRectF &boundary, bool secondary)
+{
+ qreal pos = m_swimlane->pos();
+ bool c;
+
+ if (m_swimlane->isHorizontal())
+ c = pos >= boundary.top() && pos <= boundary.bottom() && boundary.top() > -SWIMLANE_LENGTH/2;
+ else
+ c = pos >= boundary.left() && pos <= boundary.right() && boundary.left() > -SWIMLANE_LENGTH/2;
+ if (c) {
+ if (secondary)
+ setSecondarySelected(true);
+ else
+ setSelected(true);
+ }
+}
+
+void SwimlaneItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) {
+ bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0;
+ m_diagramSceneModel->selectItem(this, multiSelect);
+ }
+}
+
+void SwimlaneItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->buttons() & Qt::LeftButton) {
+ QPointF delta = event->scenePos() - event->lastScenePos();
+ if (m_swimlane->isHorizontal())
+ delta.setX(0.0);
+ else
+ delta.setY(0.0);
+ m_diagramSceneModel->moveSelectedItems(this, delta);
+ }
+}
+
+void SwimlaneItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ if (event->scenePos() != event->buttonDownScenePos(Qt::LeftButton))
+ m_diagramSceneModel->alignSelectedItemsPositionOnRaster();
+ }
+}
+
+void SwimlaneItem::updateSelectionMarker()
+{
+ if (isSelected() || m_secondarySelected) {
+ if (!m_selectionMarker)
+ m_selectionMarker = new QGraphicsRectItem(this);
+ m_selectionMarker->setBrush(isSelected() ? Qt::lightGray : Qt::transparent);
+ m_selectionMarker->setPen(isSelected() ? Qt::NoPen : QPen(Qt::lightGray));
+ m_selectionMarker->setZValue(-1);
+ } else if (m_selectionMarker) {
+ if (m_selectionMarker->scene())
+ m_selectionMarker->scene()->removeItem(m_selectionMarker);
+ delete m_selectionMarker;
+ m_selectionMarker = nullptr;
+ }
+}
+
+const Style *SwimlaneItem::adaptedStyle()
+{
+ return m_diagramSceneModel->styleController()->adaptSwimlaneStyle(m_swimlane);
+}
+
+QSizeF SwimlaneItem::calcMinimumGeometry() const
+{
+ if (m_swimlane->isHorizontal())
+ return QSizeF(SWIMLANE_LENGTH, SWIMLANE_WIDTH);
+ else
+ return QSizeF(SWIMLANE_WIDTH, SWIMLANE_LENGTH);
+}
+
+void SwimlaneItem::updateGeometry()
+{
+ prepareGeometryChange();
+
+ QSizeF geometry = calcMinimumGeometry();
+ qreal width = geometry.width();
+ qreal height = geometry.height();
+
+ if (m_swimlane->isHorizontal()) {
+ setPos(0, m_swimlane->pos());
+ if (m_lineItem)
+ m_lineItem->setLine(-width / 2, 0, width / 2, 0);
+ if (m_selectionMarker)
+ m_selectionMarker->setRect(-width / 2, -SWIMLANE_MARKER_WIDTH / 2, width, SWIMLANE_MARKER_WIDTH);
+ } else {
+ setPos(m_swimlane->pos(), 0);
+ if (m_lineItem)
+ m_lineItem->setLine(0, -height / 2, 0, height / 2);
+ if (m_selectionMarker)
+ m_selectionMarker->setRect(-SWIMLANE_MARKER_WIDTH / 2, -height / 2, SWIMLANE_MARKER_WIDTH, height);
+ }
+}
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h
new file mode 100644
index 0000000000..bae23feaf1
--- /dev/null
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QGraphicsItem>
+
+#include "qmt/diagram_scene/capabilities/moveable.h"
+#include "qmt/diagram_scene/capabilities/selectable.h"
+
+namespace qmt {
+
+class DSwimlane;
+class DiagramSceneModel;
+class Style;
+
+class SwimlaneItem :
+ public QGraphicsItem,
+ public IMoveable,
+ public ISelectable
+{
+public:
+ SwimlaneItem(DSwimlane *swimlane, DiagramSceneModel *diagramSceneModel,
+ QGraphicsItem *parent = nullptr);
+ ~SwimlaneItem() override;
+
+ DSwimlane *swimlane() const { return m_swimlane; }
+ DiagramSceneModel *diagramSceneModel() const { return m_diagramSceneModel; }
+
+ QRectF boundingRect() const override;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
+
+ virtual void update();
+
+ void moveDelta(const QPointF &delta) override;
+ void alignItemPositionToRaster(double rasterWidth, double rasterHeight) override;
+
+ bool isSecondarySelected() const override;
+ void setSecondarySelected(bool secondarySelected) override;
+ bool isFocusSelected() const override;
+ void setFocusSelected(bool focusSelected) override;
+ QRectF getSecondarySelectionBoundary() override;
+ void setBoundarySelected(const QRectF &boundary, bool secondary) override;
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
+
+ void updateSelectionMarker();
+ const Style *adaptedStyle();
+
+private:
+ QSizeF calcMinimumGeometry() const;
+ void updateGeometry();
+
+ DSwimlane *m_swimlane = nullptr;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
+ QGraphicsLineItem *m_lineItem = nullptr;
+ QGraphicsRectItem *m_selectionMarker = nullptr;
+ bool m_isUpdating = false;
+ bool m_secondarySelected = false;
+};
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.cpp b/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.cpp
index f9b7643e9f..6ac9ab9120 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.cpp
@@ -41,13 +41,8 @@ namespace qmt {
LatchController::LatchController(QObject *parent)
: QObject(parent),
- m_diagramSceneModel(nullptr),
m_horizontalAlignLine(new AlignLineItem(AlignLineItem::Horizontal, 0)),
- m_verticalAlignLine(new AlignLineItem(AlignLineItem::Vertical, 0)),
- m_foundHorizontalLatch(false),
- m_horizontalDist(0.0),
- m_foundVerticalLatch(false),
- m_verticalDist(0.0)
+ m_verticalAlignLine(new AlignLineItem(AlignLineItem::Vertical, 0))
{
m_horizontalAlignLine->setZValue(LATCH_LINES_ZVALUE);
m_horizontalAlignLine->setVisible(false);
@@ -73,7 +68,7 @@ void LatchController::setDiagramSceneModel(DiagramSceneModel *diagramSceneModel)
void LatchController::addToGraphicsScene(QGraphicsScene *graphicsScene)
{
- QMT_CHECK(graphicsScene);
+ QMT_ASSERT(graphicsScene, return);
graphicsScene->addItem(m_horizontalAlignLine);
graphicsScene->addItem(m_verticalAlignLine);
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.h b/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.h
index fc91764d2f..18c977114f 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/latchcontroller.h
@@ -47,7 +47,7 @@ class QMT_EXPORT LatchController : public QObject
Q_OBJECT
public:
- explicit LatchController(QObject *parent = 0);
+ explicit LatchController(QObject *parent = nullptr);
~LatchController() override;
void setDiagramSceneModel(DiagramSceneModel *diagramSceneModel);
@@ -67,15 +67,15 @@ private:
void applyLatches();
private:
- DiagramSceneModel *m_diagramSceneModel;
- AlignLineItem *m_horizontalAlignLine;
- AlignLineItem *m_verticalAlignLine;
- bool m_foundHorizontalLatch;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
+ AlignLineItem *m_horizontalAlignLine = nullptr;
+ AlignLineItem *m_verticalAlignLine = nullptr;
+ bool m_foundHorizontalLatch = false;
ILatchable::Latch m_horizontalLatch;
- qreal m_horizontalDist;
- bool m_foundVerticalLatch;
+ qreal m_horizontalDist = 0.0;
+ bool m_foundVerticalLatch = false;
ILatchable::Latch m_verticalLatch;
- qreal m_verticalDist;
+ qreal m_verticalDist = 0.0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp
index f8482e992c..4848d91c75 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp
@@ -85,8 +85,8 @@ public:
private:
IAlignable::AlignType m_alignType = IAlignable::AlignLeft;
QString m_identifier;
- IAlignable *m_alignable = 0;
- QGraphicsPixmapItem *m_pixmapItem = 0;
+ IAlignable *m_alignable = nullptr;
+ QGraphicsPixmapItem *m_pixmapItem = nullptr;
};
AlignButtonsItem::AlignButtonsItem(IAlignable *alignable, QGraphicsItem *parent)
@@ -124,42 +124,42 @@ void AlignButtonsItem::addButton(IAlignable::AlignType alignType, const QString
switch (alignType) {
case IAlignable::AlignLeft:
{
- static const QPixmap alignLeftPixmap = QPixmap(QStringLiteral(":/modelinglib/25x25/align-left.png")).scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ static const QPixmap alignLeftPixmap = QPixmap(":/modelinglib/25x25/align-left.png").scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
item->setPixmap(alignLeftPixmap);
item->setPos(pos - InnerBorder - 3.0, 0); // subtract additional shift of image within pixmap
break;
}
case IAlignable::AlignRight:
{
- static const QPixmap alignRightPixmap = QPixmap(QStringLiteral(":/modelinglib/25x25/align-right.png")).scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ static const QPixmap alignRightPixmap = QPixmap(":/modelinglib/25x25/align-right.png").scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
item->setPixmap(alignRightPixmap);
item->setPos(pos - item->boundingRect().width() + InnerBorder + 3.0, 0);
break;
}
case IAlignable::AlignTop:
{
- static const QPixmap alignTopPixmap = QPixmap(QStringLiteral(":/modelinglib/25x25/align-top.png")).scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ static const QPixmap alignTopPixmap = QPixmap(":/modelinglib/25x25/align-top.png").scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
item->setPixmap(alignTopPixmap);
item->setPos(0, pos - InnerBorder - 3.0);
break;
}
case IAlignable::AlignBottom:
{
- static const QPixmap alignBottomPixmap = QPixmap(QStringLiteral(":/modelinglib/25x25/align-bottom.png")).scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ static const QPixmap alignBottomPixmap = QPixmap(":/modelinglib/25x25/align-bottom.png").scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
item->setPixmap(alignBottomPixmap);
item->setPos(0, pos - item->boundingRect().height() + InnerBorder + 3.0);
break;
}
case IAlignable::AlignHcenter:
{
- static const QPixmap alignHorizontalPixmap = QPixmap(QStringLiteral(":/modelinglib/25x25/align-horizontal.png")).scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ static const QPixmap alignHorizontalPixmap = QPixmap(":/modelinglib/25x25/align-horizontal.png").scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
item->setPixmap(alignHorizontalPixmap);
item->setPos(pos - item->boundingRect().center().x(), 0);
break;
}
case IAlignable::AlignVcenter:
{
- static const QPixmap alignVerticalPixmap = QPixmap(QStringLiteral(":/modelinglib/25x25/align-vertical.png")).scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ static const QPixmap alignVerticalPixmap = QPixmap(":/modelinglib/25x25/align-vertical.png").scaled(NormalPixmapWidth, NormalPixmapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
item->setPixmap(alignVerticalPixmap);
item->setPos(0, pos - item->boundingRect().center().y());
break;
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.h
index 96a48f3d8a..d17906b299 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.h
@@ -48,7 +48,7 @@ public:
VerticalDistanceToObejct = HorizontalDistanceToObject
};
- explicit AlignButtonsItem(IAlignable *alignable, QGraphicsItem *parent = 0);
+ explicit AlignButtonsItem(IAlignable *alignable, QGraphicsItem *parent = nullptr);
~AlignButtonsItem() override;
QRectF boundingRect() const override;
@@ -58,7 +58,7 @@ public:
void addButton(IAlignable::AlignType alignType, const QString &identifier, qreal pos);
private:
- IAlignable *m_alignable = 0;
+ IAlignable *m_alignable = nullptr;
QList<AlignButtonItem *> m_alignItems;
};
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/alignlineitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/alignlineitem.h
index a630efc2b7..1244cb5894 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/alignlineitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/alignlineitem.h
@@ -37,7 +37,7 @@ public:
Vertical
};
- explicit AlignLineItem(Direction direction, QGraphicsItem *parent = 0);
+ explicit AlignLineItem(Direction direction, QGraphicsItem *parent = nullptr);
~AlignLineItem() override;
void setLine(qreal pos);
@@ -45,11 +45,11 @@ public:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
- QWidget *widget = 0) override;
+ QWidget *widget = nullptr) override;
Direction m_direction = Horizontal;
- QGraphicsLineItem *m_alignLine = 0;
- QGraphicsLineItem *m_highlightLine = 0;
+ QGraphicsLineItem *m_alignLine = nullptr;
+ QGraphicsLineItem *m_highlightLine = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.cpp
index 7de0bf0d98..93a4a10f19 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.cpp
@@ -38,6 +38,8 @@
#include <QPainter>
#include <QPen>
+//#define DEBUG_PAINT_SHAPE
+
namespace qmt {
class ArrowItem::GraphicsHeadItem : public QGraphicsItem
@@ -110,6 +112,7 @@ public:
double length = 0.0;
switch (m_head) {
case ArrowItem::HeadNone:
+ case ArrowItem::HeadCustom:
break;
case ArrowItem::HeadOpen:
case ArrowItem::HeadTriangle:
@@ -146,6 +149,7 @@ public:
bool hasDiamond = false;
switch (m_head) {
case ArrowItem::HeadNone:
+ case ArrowItem::HeadCustom:
break;
case ArrowItem::HeadOpen:
case ArrowItem::HeadTriangle:
@@ -188,7 +192,7 @@ public:
} else if (m_arrowItem) {
m_arrowItem->scene()->removeItem(m_arrowItem);
delete m_arrowItem;
- m_arrowItem = 0;
+ m_arrowItem = nullptr;
}
if (hasDiamond) {
@@ -213,7 +217,7 @@ public:
} else if (m_diamondItem) {
m_diamondItem->scene()->removeItem(m_diamondItem);
delete m_diamondItem;
- m_diamondItem = 0;
+ m_diamondItem = nullptr;
}
}
@@ -221,8 +225,8 @@ private:
ArrowItem::Head m_head = ArrowItem::HeadNone;
double m_arrowSize = 10.0;
double m_diamondSize = 15.0;
- QGraphicsPathItem *m_arrowItem = 0;
- QGraphicsPathItem *m_diamondItem = 0;
+ QGraphicsPathItem *m_arrowItem = nullptr;
+ QGraphicsPathItem *m_diamondItem = nullptr;
};
class ArrowItem::GraphicsShaftItem : public QGraphicsPathItem
@@ -236,7 +240,6 @@ public:
ArrowItem::ArrowItem(QGraphicsItem *parent)
: QGraphicsItem(parent),
- m_shaft(ShaftSolid),
m_shaftItem(new GraphicsShaftItem(this))
{
}
@@ -248,9 +251,7 @@ ArrowItem::ArrowItem(const ArrowItem &rhs, QGraphicsItem *parent)
m_arrowSize(rhs.m_arrowSize),
m_diamondSize(rhs.m_diamondSize),
m_startHead(rhs.m_startHead),
- m_startHeadItem(nullptr),
- m_endHead(rhs.m_endHead),
- m_endHeadItem(nullptr)
+ m_endHead(rhs.m_endHead)
{
}
@@ -278,14 +279,36 @@ void ArrowItem::setDiamondSize(double diamondSize)
void ArrowItem::setStartHead(ArrowItem::Head head)
{
- if (m_startHead != head)
- m_startHead = head;
+ m_startHead = head;
+}
+
+void ArrowItem::setStartHead(QGraphicsItem *startHeadItem)
+{
+ deleteHead(&m_startHeadItem);
+ if (!startHeadItem) {
+ m_startHead = HeadNone;
+ } else {
+ QTC_ASSERT(startHeadItem->parentItem() == this, return);
+ m_startHead = HeadCustom;
+ m_startHeadItem = startHeadItem;
+ }
}
void ArrowItem::setEndHead(ArrowItem::Head head)
{
- if (m_endHead != head)
- m_endHead = head;
+ m_endHead = head;
+}
+
+void ArrowItem::setEndHead(QGraphicsItem *endHeadItem)
+{
+ deleteHead(&m_endHeadItem);
+ if (!endHeadItem) {
+ m_endHead = HeadNone;
+ } else {
+ QTC_ASSERT(endHeadItem->parentItem() == this, return);
+ m_endHead = HeadCustom;
+ m_endHeadItem = endHeadItem;
+ }
}
void ArrowItem::setPoints(const QList<QPointF> &points)
@@ -346,27 +369,27 @@ QPointF ArrowItem::calcPointAtPercent(double percentage) const
QLineF ArrowItem::firstLineSegment() const
{
- QTC_ASSERT(m_points.size() > 1, return QLineF());
+ QMT_ASSERT(m_points.size() > 1, return QLineF());
return QLineF(m_points.at(0), m_points.at(1));
}
QLineF ArrowItem::lastLineSegment() const
{
- QTC_ASSERT(m_points.size() > 1, return QLineF());
+ QMT_ASSERT(m_points.size() > 1, return QLineF());
return QLineF(m_points.at(m_points.size() - 1), m_points.at(m_points.size() - 2));
}
double ArrowItem::startHeadLength() const
{
if (m_startHeadItem)
- return m_startHeadItem->calcHeadLength();
+ return calcHeadLength(m_startHeadItem);
return 0.0;
}
double ArrowItem::endHeadLength() const
{
if (m_endHeadItem)
- return m_endHeadItem->calcHeadLength();
+ return calcHeadLength(m_endHeadItem);
return 0.0;
}
@@ -380,52 +403,89 @@ void ArrowItem::update(const Style *style)
void ArrowItem::updateShaft(const Style *style)
{
- QTC_ASSERT(m_shaftItem, return);
+ QMT_ASSERT(m_shaftItem, return);
QPen pen(style->linePen());
- if (m_shaft == ShaftDashed)
- pen.setDashPattern(QVector<qreal>() << (4.0 / pen.widthF()) << (4.0 / pen.widthF()));
+ switch (m_shaft) {
+ case ShaftSolid:
+ break;
+ case ShaftDashed:
+ pen.setDashPattern(QVector<qreal>()
+ << (4.0 / pen.widthF()) << (4.0 / pen.widthF()));
+ break;
+ case ShaftDot:
+ pen.setDashPattern(QVector<qreal>()
+ << (2.0 / pen.widthF()) << (2.0 / pen.widthF()));
+ break;
+ case ShaftDashDot:
+ pen.setDashPattern(QVector<qreal>()
+ << (4.0 / pen.widthF()) << (2.0 / pen.widthF())
+ << (2.0 / pen.widthF()) << (2.0 / pen.widthF()));
+ break;
+ case ShaftDashDotDot:
+ pen.setDashPattern(QVector<qreal>()
+ << (4.0 / pen.widthF()) << (2.0 / pen.widthF())
+ << (2.0 / pen.widthF()) << (2.0 / pen.widthF())
+ << (2.0 / pen.widthF()) << (2.0 / pen.widthF()));
+ break;
+ }
m_shaftItem->setPen(pen);
}
-void ArrowItem::updateHead(GraphicsHeadItem **headItem, Head head, const Style *style)
+void ArrowItem::deleteHead(QGraphicsItem **headItem)
+{
+ if (*headItem) {
+ if ((*headItem)->scene())
+ (*headItem)->scene()->removeItem(*headItem);
+ delete *headItem;
+ *headItem = nullptr;
+ }
+}
+
+void ArrowItem::updateHead(QGraphicsItem **headItem, Head head, const Style *style)
{
if (head == HeadNone) {
- if (*headItem) {
- if ((*headItem)->scene())
- (*headItem)->scene()->removeItem(*headItem);
- delete *headItem;
- *headItem = 0;
+ deleteHead(headItem);
+ } else if (head == HeadCustom) {
+ // nothing to do
+ } else {
+ QTC_ASSERT(headItem, return);
+ QTC_ASSERT(!*headItem || dynamic_cast<GraphicsHeadItem *>(*headItem), return);
+ GraphicsHeadItem *item;
+ if (!*headItem) {
+ item = new GraphicsHeadItem(this);
+ *headItem = item;
+ } else {
+ item = dynamic_cast<GraphicsHeadItem *>(*headItem);
+ if (!item)
+ return;
}
- return;
+ item->setArrowSize(m_arrowSize);
+ item->setDiamondSize(m_diamondSize);
+ item->setHead(head);
+ item->update(style);
}
- if (!*headItem)
- *headItem = new GraphicsHeadItem(this);
- (*headItem)->setArrowSize(m_arrowSize);
- (*headItem)->setDiamondSize(m_diamondSize);
- (*headItem)->setHead(head);
- (*headItem)->update(style);
}
-void ArrowItem::updateHeadGeometry(GraphicsHeadItem **headItem, const QPointF &pos, const QPointF &otherPos)
+void ArrowItem::updateHeadGeometry(QGraphicsItem *headItem, const QPointF &pos, const QPointF &otherPos)
{
- if (!*headItem)
+ if (!headItem)
return;
- (*headItem)->setPos(pos);
+ headItem->setPos(pos);
QVector2D directionVector(pos - otherPos);
directionVector.normalize();
double angle = qAcos(directionVector.x()) * 180.0 / 3.1415926535;
if (directionVector.y() > 0.0)
angle = -angle;
- (*headItem)->setRotation(-angle);
+ headItem->setRotation(-angle);
}
void ArrowItem::updateGeometry()
{
- QTC_ASSERT(m_points.size() > 1, return);
- QTC_ASSERT(m_shaftItem, return);
+ QMT_ASSERT(m_points.size() > 1, return);
+ QMT_ASSERT(m_shaftItem, return);
prepareGeometryChange();
@@ -434,8 +494,8 @@ void ArrowItem::updateGeometry()
if (m_startHeadItem) {
QVector2D startDirectionVector(m_points.at(1) - m_points.at(0));
startDirectionVector.normalize();
- startDirectionVector *= m_startHeadItem->calcHeadLength();
- path.moveTo(m_points.at(0) + startDirectionVector.toPointF());
+ startDirectionVector *= calcHeadLength(m_startHeadItem);
+ path.moveTo(m_points[0] + startDirectionVector.toPointF());
} else {
path.moveTo(m_points.at(0));
}
@@ -446,16 +506,24 @@ void ArrowItem::updateGeometry()
if (m_endHeadItem) {
QVector2D endDirectionVector(m_points.at(m_points.size() - 1) - m_points.at(m_points.size() - 2));
endDirectionVector.normalize();
- endDirectionVector *= m_endHeadItem->calcHeadLength();
- path.lineTo(m_points.at(m_points.size() - 1) - endDirectionVector.toPointF());
+ endDirectionVector *= calcHeadLength(m_endHeadItem);
+ path.lineTo(m_points[m_points.size() - 1] - endDirectionVector.toPointF());
} else {
path.lineTo(m_points.at(m_points.size() - 1));
}
m_shaftItem->setPath(path);
- updateHeadGeometry(&m_startHeadItem, m_points.at(0), m_points.at(1));
- updateHeadGeometry(&m_endHeadItem, m_points.at(m_points.size() - 1), m_points.at(m_points.size() - 2));
+ updateHeadGeometry(m_startHeadItem, m_points.at(0), m_points.at(1));
+ updateHeadGeometry(m_endHeadItem, m_points.at(m_points.size() - 1), m_points.at(m_points.size() - 2));
+}
+
+double ArrowItem::calcHeadLength(QGraphicsItem *headItem) const
+{
+ // TODO use an interface
+ if (GraphicsHeadItem *item = dynamic_cast<GraphicsHeadItem *>(headItem))
+ return item->calcHeadLength();
+ return 100.0;
}
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.h
index 0f4af541fc..6f93a0d710 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/arrowitem.h
@@ -43,11 +43,15 @@ class ArrowItem : public QGraphicsItem
public:
enum Shaft {
ShaftSolid,
- ShaftDashed
+ ShaftDashed,
+ ShaftDot,
+ ShaftDashDot,
+ ShaftDashDotDot
};
enum Head {
HeadNone,
+ HeadCustom,
HeadOpen,
HeadTriangle,
HeadFilledTriangle,
@@ -57,15 +61,17 @@ public:
HeadFilledDiamondFilledTriangle
};
- explicit ArrowItem(QGraphicsItem *parent = 0);
- explicit ArrowItem(const ArrowItem &rhs, QGraphicsItem *parent = 0);
+ explicit ArrowItem(QGraphicsItem *parent = nullptr);
+ explicit ArrowItem(const ArrowItem &rhs, QGraphicsItem *parent = nullptr);
~ArrowItem() override;
void setShaft(Shaft shaft);
void setArrowSize(double arrowSize);
void setDiamondSize(double diamondSize);
void setStartHead(Head head);
+ void setStartHead(QGraphicsItem *startHeadItem);
void setEndHead(Head head);
+ void setEndHead(QGraphicsItem *endHeadItem);
void setPoints(const QList<QPointF> &points);
QRectF boundingRect() const override;
@@ -82,19 +88,21 @@ public:
private:
void updateShaft(const Style *style);
- void updateHead(GraphicsHeadItem **headItem, Head head, const Style *style);
- void updateHeadGeometry(GraphicsHeadItem **headItem, const QPointF &pos,
+ void deleteHead(QGraphicsItem **headItem);
+ void updateHead(QGraphicsItem **headItem, Head head, const Style *style);
+ void updateHeadGeometry(QGraphicsItem *headItem, const QPointF &pos,
const QPointF &otherPos);
void updateGeometry();
+ double calcHeadLength(QGraphicsItem *headItem) const;
Shaft m_shaft = ShaftSolid;
GraphicsShaftItem *m_shaftItem = nullptr;
double m_arrowSize = 10.0;
double m_diamondSize = 15.0;
Head m_startHead = HeadNone;
- GraphicsHeadItem *m_startHeadItem = nullptr;
+ QGraphicsItem *m_startHeadItem = nullptr;
Head m_endHead = HeadNone;
- GraphicsHeadItem *m_endHeadItem = nullptr;
+ QGraphicsItem *m_endHeadItem = nullptr;
QList<QPointF> m_points;
};
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.cpp
index 4eec6da076..afda90db4f 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.cpp
@@ -69,16 +69,16 @@ double ContextLabelItem::height() const
void ContextLabelItem::update()
{
- setText(QString(QStringLiteral("(from %1)")).arg(m_context));
+ setText(QString("(from %1)").arg(m_context));
if (m_maxWidth > 0.0) {
double contextWidth = boundingRect().width();
if (contextWidth > m_maxWidth) {
- setText(QString(QStringLiteral("(%1)")).arg(m_context));
+ setText(QString("(%1)").arg(m_context));
contextWidth = boundingRect().width();
}
if (contextWidth > m_maxWidth) {
QFontMetricsF metrics(font());
- setText(metrics.elidedText(QString(QStringLiteral("(%1)")).arg(m_context), Qt::ElideMiddle, m_maxWidth));
+ setText(metrics.elidedText(QString("(%1)").arg(m_context), Qt::ElideMiddle, m_maxWidth));
}
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.h
index 3bbce88073..62cac6619c 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/contextlabelitem.h
@@ -32,7 +32,7 @@ namespace qmt {
class ContextLabelItem : public QGraphicsSimpleTextItem
{
public:
- explicit ContextLabelItem(QGraphicsItem *parent = 0);
+ explicit ContextLabelItem(QGraphicsItem *parent = nullptr);
~ContextLabelItem() override;
void setMaxWidth(double maxWidth);
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h
index a1280f45e6..93e083b962 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h
@@ -40,7 +40,7 @@ class DiagramSceneModel;
class CustomIconItem : public QGraphicsItem
{
public:
- explicit CustomIconItem(DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = 0);
+ explicit CustomIconItem(DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = nullptr);
~CustomIconItem() override;
void setStereotypeIconId(const QString &stereotypeIconId);
@@ -56,7 +56,7 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
private:
- DiagramSceneModel *m_diagramSceneModel = 0;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
QString m_stereotypeIconId;
StereotypeIcon m_stereotypeIcon;
QSizeF m_baseSize;
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.cpp
index 3af578ceaf..78fa4fff80 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.cpp
@@ -130,7 +130,7 @@ private:
}
}
- PathSelectionItem *m_owner = 0;
+ PathSelectionItem *m_owner = nullptr;
int m_pointIndex = -1;
QSizeF m_pointSize;
Selection m_selection = NotSelected;
@@ -207,10 +207,10 @@ QList<QPointF> PathSelectionItem::points() const
void PathSelectionItem::setPoints(const QList<QPointF> &points)
{
- QMT_CHECK(points.size() >= 2);
+ QMT_ASSERT(points.size() >= 2, return);
prepareGeometryChange();
- GraphicsHandleItem *focusEndBItem = 0;
+ GraphicsHandleItem *focusEndBItem = nullptr;
if (!m_handles.isEmpty() && m_focusHandleItem == m_handles.last()) {
focusEndBItem = m_focusHandleItem;
m_handles.removeLast();
@@ -222,7 +222,7 @@ void PathSelectionItem::setPoints(const QList<QPointF> &points)
handle = focusEndBItem;
handle->setPointIndex(pointIndex);
m_handles.insert(pointIndex, handle);
- focusEndBItem = 0;
+ focusEndBItem = nullptr;
} else if (pointIndex >= m_handles.size()) {
handle = new GraphicsHandleItem(pointIndex, this);
handle->setPointSize(m_pointSize);
@@ -297,7 +297,7 @@ void PathSelectionItem::moveHandle(int pointIndex, const QPointF &deltaMove, Han
m_windable->setHandlePos(pointIndex, newPos);
if (handleStatus == Release) {
m_windable->dropHandle(pointIndex, RASTER_WIDTH, RASTER_HEIGHT);
- m_focusHandleItem = 0;
+ m_focusHandleItem = nullptr;
}
break;
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.h
index b38688e2a0..3b8e1685fe 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/pathselectionitem.h
@@ -49,7 +49,7 @@ class PathSelectionItem : public QGraphicsItem
};
public:
- explicit PathSelectionItem(IWindable *windable, QGraphicsItem *parent = 0);
+ explicit PathSelectionItem(IWindable *windable, QGraphicsItem *parent = nullptr);
~PathSelectionItem() override;
QRectF boundingRect() const override;
@@ -72,11 +72,11 @@ private:
HandleQualifier handleQualifier);
void keyPressed(int pointIndex, QKeyEvent *event, const QPointF &pos);
- IWindable *m_windable = 0;
+ IWindable *m_windable = nullptr;
QSizeF m_pointSize;
bool m_isSecondarySelected = false;
QList<GraphicsHandleItem *> m_handles;
- GraphicsHandleItem *m_focusHandleItem = 0;
+ GraphicsHandleItem *m_focusHandleItem = nullptr;
QPointF m_originalHandlePos;
};
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.cpp
index ba65d97d51..64936fb773 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.cpp
@@ -86,7 +86,7 @@ protected:
}
private:
- RectangularSelectionItem *m_owner = 0;
+ RectangularSelectionItem *m_owner = nullptr;
RectangularSelectionItem::Handle m_handle = RectangularSelectionItem::HandleNone;
bool m_isSecondarySelected = false;
QPointF m_startPos;
@@ -157,7 +157,7 @@ void RectangularSelectionItem::setSecondarySelected(bool secondarySelected)
void RectangularSelectionItem::update()
{
- QMT_CHECK(HandleFirst == 0 && HandleLast == 7);
+ QMT_ASSERT(HandleFirst == 0 && HandleLast == 7, return);
prepareGeometryChange();
for (int i = 0; i <= 7; ++i) {
@@ -191,7 +191,7 @@ void RectangularSelectionItem::update()
visible = m_freedom == FreedomAny || m_freedom == FreedomKeepRatio;
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
m_points[i]->setSecondarySelected(m_isSecondarySelected);
@@ -220,7 +220,7 @@ void RectangularSelectionItem::update()
if (m_borderItem->scene())
m_borderItem->scene()->removeItem(m_borderItem);
delete m_borderItem;
- m_borderItem = 0;
+ m_borderItem = nullptr;
}
}
@@ -269,7 +269,7 @@ void RectangularSelectionItem::moveHandle(Handle handle, const QPointF &deltaMov
moveable = m_freedom == FreedomAny || m_freedom == FreedomKeepRatio;
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
if (!moveable)
@@ -328,7 +328,7 @@ void RectangularSelectionItem::moveHandle(Handle handle, const QPointF &deltaMov
bottomRightDelta = -(v * deltaLength);
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
} else {
@@ -360,7 +360,7 @@ void RectangularSelectionItem::moveHandle(Handle handle, const QPointF &deltaMov
bottomRightDelta = deltaMove;
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
}
@@ -386,7 +386,7 @@ void RectangularSelectionItem::moveHandle(Handle handle, const QPointF &deltaMov
bottomRightDelta.setX(bottomRightDelta.x() + sizeDelta.width());
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
@@ -408,7 +408,7 @@ void RectangularSelectionItem::moveHandle(Handle handle, const QPointF &deltaMov
bottomRightDelta.setY(bottomRightDelta.y() + sizeDelta.height());
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
@@ -433,7 +433,7 @@ void RectangularSelectionItem::moveHandle(Handle handle, const QPointF &deltaMov
// nothing
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
switch (handle) {
@@ -452,7 +452,7 @@ void RectangularSelectionItem::moveHandle(Handle handle, const QPointF &deltaMov
// nothing
break;
case HandleNone:
- QMT_CHECK(false);
+ Q_UNREACHABLE();
break;
}
m_itemResizer->alignItemSizeToRaster(horiz, vert, 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT);
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.h
index bb82cc4460..5c5d9fcbf0 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/rectangularselectionitem.h
@@ -75,7 +75,7 @@ public:
FreedomKeepRatio
};
- explicit RectangularSelectionItem(IResizable *itemResizer, QGraphicsItem *parent = 0);
+ explicit RectangularSelectionItem(IResizable *itemResizer, QGraphicsItem *parent = nullptr);
~RectangularSelectionItem() override;
QRectF boundingRect() const override;
@@ -99,14 +99,14 @@ private:
void moveHandle(Handle handle, const QPointF &deltaMove, HandleStatus handleStatus,
HandleQualifier handleQualifier);
- IResizable *m_itemResizer = 0;
+ IResizable *m_itemResizer = nullptr;
QRectF m_rect;
QSizeF m_pointSize;
QVector<GraphicsHandleItem *> m_points;
QPointF m_originalResizePos;
QRectF m_originalResizeRect;
bool m_showBorder = false;
- QGraphicsRectItem *m_borderItem = 0;
+ QGraphicsRectItem *m_borderItem = nullptr;
Freedom m_freedom = FreedomAny;
bool m_isSecondarySelected = false;
Handle m_activeHandle = HandleNone;
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.cpp
index 5c2ce279e6..705f673ac5 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.cpp
@@ -70,16 +70,18 @@ void RelationStarter::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
}
void RelationStarter::addArrow(const QString &id, ArrowItem::Shaft shaft,
- ArrowItem::Head endHead, ArrowItem::Head startHead)
+ ArrowItem::Head startHead, ArrowItem::Head endHead,
+ const QString &toolTip)
{
QMT_CHECK(!id.isEmpty());
prepareGeometryChange();
auto arrow = new ArrowItem(this);
arrow->setArrowSize(10.0);
- arrow->setDiamondSize(15.0);
+ arrow->setDiamondSize(8.0);
arrow->setShaft(shaft);
arrow->setStartHead(startHead);
arrow->setEndHead(endHead);
+ arrow->setToolTip(toolTip.isEmpty() ? id : toolTip);
arrow->setPoints(QList<QPointF>() << QPointF(0.0, 10.0) << QPointF(15.0, 0.0));
arrow->setPos(6.0, m_arrows.size() * 20.0 + 8.0);
arrow->update(m_diagramSceneModel->styleController()->relationStarterStyle());
@@ -99,6 +101,9 @@ void RelationStarter::mousePressEvent(QGraphicsSceneMouseEvent *event)
m_currentPreviewArrowId = m_arrowIds.value(item);
QMT_CHECK(!m_currentPreviewArrowId.isEmpty());
m_currentPreviewArrow = new ArrowItem(*item);
+ // TODO use constants for sizes (in relationitem.h also)
+ m_currentPreviewArrow->setArrowSize(12.0);
+ m_currentPreviewArrow->setDiamondSize(12.0);
m_currentPreviewArrow->setPoints(QList<QPointF>() << m_owner->relationStartPos() << mapToScene(event->pos()));
m_currentPreviewArrow->update(m_diagramSceneModel->styleController()->relationStarterStyle());
m_currentPreviewArrow->setZValue(PREVIEW_RELATION_ZVALUE);
@@ -123,7 +128,7 @@ void RelationStarter::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
m_currentPreviewArrowIntermediatePoints);
m_currentPreviewArrow->scene()->removeItem(m_currentPreviewArrow);
delete m_currentPreviewArrow;
- m_currentPreviewArrow = 0;
+ m_currentPreviewArrow = nullptr;
m_currentPreviewArrowIntermediatePoints.clear();
}
}
@@ -152,7 +157,7 @@ void RelationStarter::focusOutEvent(QFocusEvent *event)
if (m_currentPreviewArrow) {
m_currentPreviewArrow->scene()->removeItem(m_currentPreviewArrow);
delete m_currentPreviewArrow;
- m_currentPreviewArrow = 0;
+ m_currentPreviewArrow = nullptr;
m_currentPreviewArrowIntermediatePoints.clear();
}
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.h b/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.h
index cbf69e9244..a25d03c7bf 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/relationstarter.h
@@ -40,15 +40,16 @@ class RelationStarter : public QGraphicsRectItem
{
public:
RelationStarter(IRelationable *owner, DiagramSceneModel *diagramSceneModel,
- QGraphicsItem *parent = 0);
+ QGraphicsItem *parent = nullptr);
~RelationStarter() override;
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
- QWidget *widget = 0) override;
+ QWidget *widget = nullptr) override;
- void addArrow(const QString &id, ArrowItem::Shaft shaft, ArrowItem::Head endHead,
- ArrowItem::Head startHead = ArrowItem::HeadNone);
+ void addArrow(const QString &id, ArrowItem::Shaft shaft, ArrowItem::Head startHead,
+ ArrowItem::Head endHead,
+ const QString &toolTip = QString());
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
@@ -60,11 +61,11 @@ protected:
private:
void updateCurrentPreviewArrow(const QPointF &headPoint);
- IRelationable *m_owner = 0;
- DiagramSceneModel *m_diagramSceneModel = 0;
+ IRelationable *m_owner = nullptr;
+ DiagramSceneModel *m_diagramSceneModel = nullptr;
QList<ArrowItem *> m_arrows;
QHash<ArrowItem *, QString> m_arrowIds;
- ArrowItem *m_currentPreviewArrow = 0;
+ ArrowItem *m_currentPreviewArrow = nullptr;
QString m_currentPreviewArrowId;
QList<QPointF> m_currentPreviewArrowIntermediatePoints;
};
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.cpp
index 2c6075590a..0269bb1e07 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.cpp
@@ -49,7 +49,7 @@ QString StereotypesItem::format(const QList<QString> &stereotypes)
bool first = true;
foreach (const QString &stereotype, stereotypes) {
if (!first)
- text += QStringLiteral(", ");
+ text += ", ";
text += stereotype;
first = false;
}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.h
index bfb5808261..b07d59a3dd 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/stereotypesitem.h
@@ -33,7 +33,7 @@ namespace qmt {
class StereotypesItem : public QGraphicsSimpleTextItem
{
public:
- explicit StereotypesItem(QGraphicsItem *parent = 0);
+ explicit StereotypesItem(QGraphicsItem *parent = nullptr);
~StereotypesItem() override;
void setStereotypes(const QList<QString> &stereotypes);
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.cpp
index 51c386c16b..8da88ea401 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.cpp
@@ -82,7 +82,7 @@ void TemplateParameterBox::updateText()
if (m_breakLines)
templateText += QLatin1Char('\n');
else
- templateText += QStringLiteral(", ");
+ templateText += ", ";
}
templateText += parameter;
first = false;
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.h b/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.h
index 63349f8ab8..b93eb3e1e7 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/templateparameterbox.h
@@ -32,7 +32,7 @@ namespace qmt {
class TemplateParameterBox : public QGraphicsRectItem
{
public:
- explicit TemplateParameterBox(QGraphicsItem *parent = 0);
+ explicit TemplateParameterBox(QGraphicsItem *parent = nullptr);
~TemplateParameterBox() override;
void setFont(const QFont &font);
@@ -46,7 +46,7 @@ private:
QList<QString> m_templateParameters;
bool m_breakLines = false;
- QGraphicsSimpleTextItem *m_parametersText = 0;
+ QGraphicsSimpleTextItem *m_parametersText = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h b/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h
index 5926f07ba1..f1f56bfe74 100644
--- a/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h
+++ b/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h
@@ -38,5 +38,6 @@ static const char ELEMENT_TYPE_CLASS[] = "class";
static const char ELEMENT_TYPE_ITEM[] = "item";
static const char ELEMENT_TYPE_ANNOTATION[] = "annotation";
static const char ELEMENT_TYPE_BOUNDARY[] = "boundary";
+static const char ELEMENT_TYPE_SWIMLANE[] = "swimlane";
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.cpp b/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.cpp
index 9803a37785..0b5097fe63 100644
--- a/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.cpp
+++ b/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.cpp
@@ -64,12 +64,7 @@ DiagramsManager::ManagedDiagram::~ManagedDiagram()
}
DiagramsManager::DiagramsManager(QObject *parent)
- : QObject(parent),
- m_diagramsView(0),
- m_diagramController(0),
- m_diagramSceneController(0),
- m_styleController(0),
- m_stereotypeController(0)
+ : QObject(parent)
{
}
@@ -81,7 +76,7 @@ DiagramsManager::~DiagramsManager()
void DiagramsManager::setModel(TreeModel *model)
{
if (m_model)
- connect(m_model, 0, this, 0);
+ connect(m_model, nullptr, this, nullptr);
m_model = model;
if (model) {
connect(model, &QAbstractItemModel::dataChanged,
@@ -97,7 +92,7 @@ void DiagramsManager::setDiagramsView(DiagramsViewInterface *diagramsView)
void DiagramsManager::setDiagramController(DiagramController *diagramController)
{
if (m_diagramController)
- connect(m_diagramController, 0, this, 0);
+ connect(m_diagramController, nullptr, this, nullptr);
m_diagramController = diagramController;
if (diagramController) {
connect(diagramController, &DiagramController::diagramAboutToBeRemoved,
@@ -142,13 +137,13 @@ DiagramSceneModel *DiagramsManager::bindDiagramSceneModel(MDiagram *diagram)
DiagramSceneModel *DiagramsManager::diagramSceneModel(const MDiagram *diagram) const
{
const ManagedDiagram *managedDiagram = m_diagramUidToManagedDiagramMap.value(diagram->uid());
- QMT_CHECK(managedDiagram);
+ QMT_ASSERT(managedDiagram, return nullptr);
return managedDiagram->diagramSceneModel();
}
void DiagramsManager::unbindDiagramSceneModel(const MDiagram *diagram)
{
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return);
ManagedDiagram *managedDiagram = m_diagramUidToManagedDiagramMap.take(diagram->uid());
QMT_CHECK(managedDiagram);
delete managedDiagram;
diff --git a/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.h b/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.h
index f9af7636a0..226c2389a5 100644
--- a/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.h
+++ b/src/libs/modelinglib/qmt/diagram_ui/diagramsmanager.h
@@ -56,7 +56,7 @@ class QMT_EXPORT DiagramsManager : public QObject
class ManagedDiagram;
public:
- explicit DiagramsManager(QObject *parent = 0);
+ explicit DiagramsManager(QObject *parent = nullptr);
~DiagramsManager() override;
signals:
@@ -84,11 +84,11 @@ private:
void onDataChanged(const QModelIndex &topleft, const QModelIndex &bottomright);
QPointer<TreeModel> m_model;
- DiagramsViewInterface *m_diagramsView;
- DiagramController *m_diagramController;
- DiagramSceneController *m_diagramSceneController;
- StyleController *m_styleController;
- StereotypeController *m_stereotypeController;
+ DiagramsViewInterface *m_diagramsView = nullptr;
+ DiagramController *m_diagramController = nullptr;
+ DiagramSceneController *m_diagramSceneController = nullptr;
+ StyleController *m_styleController = nullptr;
+ StereotypeController *m_stereotypeController = nullptr;
QHash<Uid, ManagedDiagram *> m_diagramUidToManagedDiagramMap;
};
diff --git a/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.cpp b/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.cpp
index 283506cb2a..3e3a144f1c 100644
--- a/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.cpp
+++ b/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.cpp
@@ -38,8 +38,7 @@
namespace qmt {
SceneInspector::SceneInspector(QObject *parent)
- : QObject(parent),
- m_diagramsManager(nullptr)
+ : QObject(parent)
{
}
@@ -86,7 +85,7 @@ IMoveable *SceneInspector::moveable(const DElement *element, const MDiagram *dia
}
}
QMT_CHECK(false);
- return 0;
+ return nullptr;
}
IResizable *SceneInspector::resizable(const DElement *element, const MDiagram *diagram) const
@@ -102,7 +101,7 @@ IResizable *SceneInspector::resizable(const DElement *element, const MDiagram *d
}
}
QMT_CHECK(false);
- return 0;
+ return nullptr;
}
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.h b/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.h
index 9cd964a6d9..dcc5bed532 100644
--- a/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.h
+++ b/src/libs/modelinglib/qmt/diagram_ui/sceneinspector.h
@@ -36,7 +36,7 @@ class DiagramsManager;
class QMT_EXPORT SceneInspector : public QObject, public ISceneInspector
{
public:
- explicit SceneInspector(QObject *parent = 0);
+ explicit SceneInspector(QObject *parent = nullptr);
~SceneInspector() override;
void setDiagramsManager(DiagramsManager *diagramsManager);
@@ -47,7 +47,7 @@ public:
IResizable *resizable(const DElement *element, const MDiagram *diagram) const override;
private:
- DiagramsManager *m_diagramsManager;
+ DiagramsManager *m_diagramsManager = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.cpp b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.cpp
index f878944159..e0bce45f09 100644
--- a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.cpp
+++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.cpp
@@ -37,8 +37,7 @@
namespace qmt {
DiagramsView::DiagramsView(QWidget *parent)
- : QTabWidget(parent),
- m_diagramsManager(nullptr)
+ : QTabWidget(parent)
{
setTabsClosable(true);
setMovable(true);
@@ -58,7 +57,7 @@ void DiagramsView::setDiagramsManager(DiagramsManager *diagramsManager)
void DiagramsView::openDiagram(MDiagram *diagram)
{
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return);
DiagramView *diagramView = m_diagramViews.value(diagram->uid());
if (!diagramView) {
DiagramSceneModel *diagramSceneModel = m_diagramsManager->bindDiagramSceneModel(diagram);
@@ -128,7 +127,7 @@ MDiagram *DiagramsView::diagram(int tabIndex) const
MDiagram *DiagramsView::diagram(DiagramView *diagramView) const
{
if (!diagramView || diagramView->diagramSceneModel())
- return 0;
+ return nullptr;
return diagramView->diagramSceneModel()->diagram();
}
diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.h b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.h
index 6913957b66..ec8cc026a4 100644
--- a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.h
+++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramsview.h
@@ -46,7 +46,7 @@ class QMT_EXPORT DiagramsView : public QTabWidget, public DiagramsViewInterface
Q_OBJECT
public:
- explicit DiagramsView(QWidget *parent = 0);
+ explicit DiagramsView(QWidget *parent = nullptr);
~DiagramsView() override;
signals:
@@ -69,7 +69,7 @@ private:
MDiagram *diagram(int tabIndex) const;
MDiagram *diagram(DiagramView * diagramView) const;
- DiagramsManager *m_diagramsManager;
+ DiagramsManager *m_diagramsManager = nullptr;
QHash<Uid, DiagramView *> m_diagramViews;
};
diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp
index 16f361a1ea..25ac120ee7 100644
--- a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp
+++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp
@@ -60,10 +60,13 @@ DiagramSceneModel *DiagramView::diagramSceneModel() const
void DiagramView::setDiagramSceneModel(DiagramSceneModel *diagramSceneModel)
{
- setScene(0);
+ setScene(nullptr);
m_diagramSceneModel = diagramSceneModel;
- if (diagramSceneModel)
+ if (diagramSceneModel) {
setScene(m_diagramSceneModel->graphicsScene());
+ connect(m_diagramSceneModel, &DiagramSceneModel::sceneRectChanged,
+ this, &DiagramView::onSceneRectChanged, Qt::QueuedConnection);
+ }
}
void DiagramView::dragEnterEvent(QDragEnterEvent *event)
@@ -110,14 +113,17 @@ void DiagramView::dragMoveEvent(QDragMoveEvent *event)
void DiagramView::dropEvent(QDropEvent *event)
{
event->setDropAction(Qt::MoveAction);
+ DiagramSceneController *diagramSceneController = m_diagramSceneModel->diagramSceneController();
if (event->mimeData()->hasFormat(QLatin1String(MIME_TYPE_MODEL_ELEMENTS))) {
QDataStream dataStream(event->mimeData()->data(QLatin1String(MIME_TYPE_MODEL_ELEMENTS)));
while (dataStream.status() == QDataStream::Ok) {
QString key;
dataStream >> key;
if (!key.isEmpty()) {
- if (m_diagramSceneModel->diagramSceneController()->isAddingAllowed(Uid(key), m_diagramSceneModel->diagram()))
- m_diagramSceneModel->diagramSceneController()->addExistingModelElement(Uid(key), mapToScene(event->pos()), m_diagramSceneModel->diagram());
+ if (diagramSceneController->isAddingAllowed(Uid(key), m_diagramSceneModel->diagram())) {
+ diagramSceneController->addExistingModelElement(Uid(key), mapToScene(event->pos()),
+ m_diagramSceneModel->diagram());
+ }
}
}
event->accept();
@@ -130,7 +136,9 @@ void DiagramView::dropEvent(QDropEvent *event)
dataStream >> newElementId >> name >> stereotype;
if (!newElementId.isEmpty()) {
QPointF pos = mapToScene(event->pos());
- m_diagramSceneModel->diagramSceneController()->dropNewElement(newElementId, name, stereotype, m_diagramSceneModel->findTopmostElement(pos), pos, m_diagramSceneModel->diagram());
+ diagramSceneController->dropNewElement(
+ newElementId, name, stereotype, m_diagramSceneModel->findTopmostElement(pos),
+ pos, m_diagramSceneModel->diagram(), event->pos(), size());
}
}
event->accept();
@@ -139,4 +147,10 @@ void DiagramView::dropEvent(QDropEvent *event)
}
}
+void DiagramView::onSceneRectChanged(const QRectF &sceneRect)
+{
+ // TODO add some adjustment to all 4 sides?
+ setSceneRect(sceneRect);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h
index 3ddc1951b1..c4a01b76d3 100644
--- a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h
+++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h
@@ -51,6 +51,8 @@ protected:
void dropEvent(QDropEvent *event) override;
private:
+ void onSceneRectChanged(const QRectF &sceneRect);
+
QPointer<DiagramSceneModel> m_diagramSceneModel;
};
diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.cpp b/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.cpp
index c459463bb0..7592bc57db 100644
--- a/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.cpp
+++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.cpp
@@ -37,8 +37,7 @@
namespace qmt {
StackedDiagramsView::StackedDiagramsView(QWidget *parent)
- : QStackedWidget(parent),
- m_diagramsManager(nullptr)
+ : QStackedWidget(parent)
{
connect(this, &QStackedWidget::currentChanged, this, &StackedDiagramsView::onCurrentChanged);
}
@@ -54,7 +53,7 @@ void StackedDiagramsView::setDiagramsManager(DiagramsManager *diagramsManager)
void StackedDiagramsView::openDiagram(MDiagram *diagram)
{
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return);
DiagramView *diagramView = m_diagramViews.value(diagram->uid());
if (!diagramView) {
DiagramSceneModel *diagramSceneModel = m_diagramsManager->bindDiagramSceneModel(diagram);
@@ -117,7 +116,7 @@ MDiagram *StackedDiagramsView::diagram(int tabIndex) const
MDiagram *StackedDiagramsView::diagram(DiagramView *diagramView) const
{
if (!diagramView || !diagramView->diagramSceneModel())
- return 0;
+ return nullptr;
return diagramView->diagramSceneModel()->diagram();
}
diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.h b/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.h
index d4b9eb1b3f..36822ea245 100644
--- a/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.h
+++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/stackeddiagramsview.h
@@ -45,7 +45,7 @@ class QMT_EXPORT StackedDiagramsView : public QStackedWidget, public DiagramsVie
Q_OBJECT
public:
- explicit StackedDiagramsView(QWidget *parent = 0);
+ explicit StackedDiagramsView(QWidget *parent = nullptr);
~StackedDiagramsView() override;
signals:
@@ -67,7 +67,7 @@ private:
MDiagram *diagram(int tabIndex) const;
MDiagram *diagram(DiagramView * diagramView) const;
- DiagramsManager *m_diagramsManager;
+ DiagramsManager *m_diagramsManager = nullptr;
QHash<Uid, DiagramView *> m_diagramViews;
};
diff --git a/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp b/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp
index f6271ff14d..009e16d2d1 100644
--- a/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp
+++ b/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp
@@ -91,6 +91,7 @@ DocumentController::DocumentController(QObject *parent) :
// diagram scene controller
m_diagramSceneController->setModelController(m_modelController);
m_diagramSceneController->setDiagramController(m_diagramController);
+ m_diagramSceneController->setStereotypeController(m_stereotypeController);
// config controller
m_configController->setStereotypeController(m_stereotypeController);
@@ -272,8 +273,8 @@ MDiagram *DocumentController::findOrCreateRootDiagram()
void DocumentController::createNewProject(const QString &fileName)
{
m_diagramsManager->removeAllDiagrams();
- m_treeModel->setModelController(0);
- m_modelController->setRootPackage(0);
+ m_treeModel->setModelController(nullptr);
+ m_modelController->setRootPackage(nullptr);
m_undoController->reset();
m_projectController->newProject(fileName);
@@ -285,8 +286,8 @@ void DocumentController::createNewProject(const QString &fileName)
void DocumentController::loadProject(const QString &fileName)
{
m_diagramsManager->removeAllDiagrams();
- m_treeModel->setModelController(0);
- m_modelController->setRootPackage(0);
+ m_treeModel->setModelController(nullptr);
+ m_modelController->setRootPackage(nullptr);
m_undoController->reset();
m_projectController->newProject(fileName);
diff --git a/src/libs/modelinglib/qmt/document_controller/documentcontroller.h b/src/libs/modelinglib/qmt/document_controller/documentcontroller.h
index d9a253773f..6b4eea9676 100644
--- a/src/libs/modelinglib/qmt/document_controller/documentcontroller.h
+++ b/src/libs/modelinglib/qmt/document_controller/documentcontroller.h
@@ -56,7 +56,7 @@ class QMT_EXPORT DocumentController : public QObject
{
Q_OBJECT
public:
- explicit DocumentController(QObject *parent = 0);
+ explicit DocumentController(QObject *parent = nullptr);
~DocumentController() override;
signals:
@@ -106,18 +106,18 @@ public:
void loadProject(const QString &fileName);
private:
- ProjectController *m_projectController;
- UndoController *m_undoController;
- ModelController *m_modelController;
- DiagramController *m_diagramController;
- DiagramSceneController *m_diagramSceneController;
- StyleController *m_styleController;
- StereotypeController *m_stereotypeController;
- ConfigController *m_configController;
- TreeModel *m_treeModel;
- SortedTreeModel *m_sortedTreeModel;
- DiagramsManager *m_diagramsManager;
- SceneInspector *m_sceneInspector;
+ ProjectController *m_projectController = nullptr;
+ UndoController *m_undoController = nullptr;
+ ModelController *m_modelController = nullptr;
+ DiagramController *m_diagramController = nullptr;
+ DiagramSceneController *m_diagramSceneController = nullptr;
+ StyleController *m_styleController = nullptr;
+ StereotypeController *m_stereotypeController = nullptr;
+ ConfigController *m_configController = nullptr;
+ TreeModel *m_treeModel = nullptr;
+ SortedTreeModel *m_sortedTreeModel = nullptr;
+ DiagramsManager *m_diagramsManager = nullptr;
+ SceneInspector *m_sceneInspector = nullptr;
QScopedPointer<MContainer> m_modelClipboard;
QScopedPointer<DContainer> m_diagramClipboard;
};
diff --git a/src/libs/modelinglib/qmt/infrastructure/contextmenuaction.h b/src/libs/modelinglib/qmt/infrastructure/contextmenuaction.h
index 2f1402d4d3..eeab0d6f9c 100644
--- a/src/libs/modelinglib/qmt/infrastructure/contextmenuaction.h
+++ b/src/libs/modelinglib/qmt/infrastructure/contextmenuaction.h
@@ -33,9 +33,9 @@ namespace qmt {
class QMT_EXPORT ContextMenuAction : public QAction
{
public:
- ContextMenuAction(const QString &label, const QString &id, QObject *parent = 0);
+ ContextMenuAction(const QString &label, const QString &id, QObject *parent = nullptr);
ContextMenuAction(const QString &label, const QString &id, const QKeySequence &shortcut,
- QObject *parent = 0);
+ QObject *parent = nullptr);
~ContextMenuAction() override;
QString id() const { return m_id; }
diff --git a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp
index c3b1d47ce9..90c9d38499 100644
--- a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp
+++ b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp
@@ -86,7 +86,7 @@ public:
bool GeometryUtilities::placeRectAtLine(const QRectF &rect, const QLineF &line, double lineOffset, double distance,
const QLineF &intersectionLine, QPointF *placement, Side *horizontalAlignedSide)
{
- QMT_CHECK(placement);
+ QMT_ASSERT(placement, return false);
QList<Candidate> candidates;
candidates << Candidate(QVector2D(rect.topRight() - rect.topLeft()), QPointF(0.0, 0.0), SideTop)
diff --git a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h
index c0062aa297..f0b4f697b0 100644
--- a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h
+++ b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h
@@ -52,7 +52,7 @@ public:
static QLineF stretch(const QLineF &line, double p1Extension, double p2Extension);
static bool intersect(const QPolygonF &polygon, const QLineF &line,
- QPointF *intersectionPoint, QLineF *intersectionLine = 0);
+ QPointF *intersectionPoint, QLineF *intersectionLine = nullptr);
static bool placeRectAtLine(const QRectF &rect, const QLineF &line, double lineOffset,
double distance, const QLineF &intersectionLine, QPointF *placement,
Side *horizontalAlignedSide);
diff --git a/src/libs/modelinglib/qmt/infrastructure/handle.h b/src/libs/modelinglib/qmt/infrastructure/handle.h
index 261f8c7460..0c28c3f228 100644
--- a/src/libs/modelinglib/qmt/infrastructure/handle.h
+++ b/src/libs/modelinglib/qmt/infrastructure/handle.h
@@ -42,13 +42,13 @@ public:
Handle(const Handle<U> &rhs) : m_uid(rhs.uid()), m_target(rhs.target()) { }
bool isNull() const { return !m_uid.isValid(); }
- bool hasTarget() const { return m_target != 0; }
+ bool hasTarget() const { return m_target != nullptr; }
Uid uid() const { return m_uid; }
T *target() const { return m_target; }
void setUid(const Uid &uid)
{
- QMT_CHECK(m_target != 0 ? (m_target->uid() == uid) : true);
+ QMT_CHECK(m_target ? (m_target->uid() == uid) : true);
m_uid = uid;
}
@@ -61,14 +61,14 @@ public:
void clear()
{
m_uid = Uid();
- m_target = 0;
+ m_target = nullptr;
}
- void clearTarget() { m_target = 0; }
+ void clearTarget() { m_target = nullptr; }
private:
Uid m_uid;
- T *m_target = 0;
+ T *m_target = nullptr;
};
template<class T>
diff --git a/src/libs/modelinglib/qmt/infrastructure/handles.h b/src/libs/modelinglib/qmt/infrastructure/handles.h
index d0e4c83ea5..4b1d0e1c93 100644
--- a/src/libs/modelinglib/qmt/infrastructure/handles.h
+++ b/src/libs/modelinglib/qmt/infrastructure/handles.h
@@ -86,7 +86,7 @@ public:
bool contains(const T *t) const
{
- QMT_CHECK(t);
+ QMT_ASSERT(t, return false);
return contains(t->uid());
}
@@ -96,18 +96,18 @@ public:
if (handle.uid() == uid)
return handle.target();
}
- return 0;
+ return nullptr;
}
T *at(int index) const
{
- QMT_CHECK(index >= 0 && index < m_handleList.size());
+ QMT_ASSERT(index >= 0 && index < m_handleList.size(), return nullptr);
return m_handleList.at(index).target();
}
T *at(int index)
{
- QMT_CHECK(index >= 0 && index < m_handleList.size());
+ QMT_ASSERT(index >= 0 && index < m_handleList.size(), return nullptr);
return m_handleList.at(index);
}
@@ -124,7 +124,7 @@ public:
int indexOf(const T *t) const
{
- QMT_CHECK(t);
+ QMT_ASSERT(t, return -1);
return indexOf(t->uid());
}
@@ -164,27 +164,27 @@ public:
void add(T *t)
{
- QMT_CHECK(t);
+ QMT_ASSERT(t, return);
m_handleList.append(Handle<T>(t));
}
void insert(int beforeIndex, const Uid &uid)
{
- QMT_CHECK(beforeIndex >= 0 && beforeIndex <= m_handleList.size());
- QMT_CHECK(uid.isValid());
+ QMT_ASSERT(beforeIndex >= 0 && beforeIndex <= m_handleList.size(), return);
+ QMT_ASSERT(uid.isValid(), return);
m_handleList.insert(beforeIndex, Handle<T>(uid));
}
void insert(int beforeIndex, T *t)
{
- QMT_CHECK(beforeIndex >= 0 && beforeIndex <= m_handleList.size());
- QMT_CHECK(t);
+ QMT_ASSERT(beforeIndex >= 0 && beforeIndex <= m_handleList.size(), return);
+ QMT_ASSERT(t, return);
m_handleList.insert(beforeIndex, Handle<T>(t));
}
void remove(int index)
{
- QMT_CHECK(index >= 0 && index < size());
+ QMT_ASSERT(index >= 0 && index < size(), return);
if (m_takesOwnership) {
T *t = m_handleList.at(index).target();
m_handleList.removeAt(index);
@@ -201,13 +201,13 @@ public:
void remove(T *t)
{
- QMT_CHECK(t);
+ QMT_ASSERT(t, return);
remove(indexOf(t));
}
T * take(int index)
{
- QMT_CHECK(index >= 0 && index < size());
+ QMT_ASSERT(index >= 0 && index < size(), return nullptr);
T *t = m_handleList.at(index).target();
m_handleList.removeAt(index);
return t;
@@ -220,7 +220,7 @@ public:
T *take(T *t)
{
- QMT_CHECK(t);
+ QMT_ASSERT(t, return nullptr);
return take(indexOf(t));
}
diff --git a/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.cpp b/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.cpp
index 32ab6dc3ee..7853ad2341 100644
--- a/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.cpp
+++ b/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.cpp
@@ -60,9 +60,9 @@ void QCompressedDevice::close()
qint64 QCompressedDevice::readData(char *data, qint64 maxlen)
{
- QMT_CHECK(m_targetDevice);
- QMT_CHECK(m_targetDevice->isOpen());
- QMT_CHECK(m_targetDevice->openMode() == QIODevice::ReadOnly);
+ QMT_ASSERT(m_targetDevice, return 0);
+ QMT_ASSERT(m_targetDevice->isOpen(), return 0);
+ QMT_ASSERT(m_targetDevice->openMode() == QIODevice::ReadOnly, return 0);
if (m_bytesInBuffer == 0) {
QByteArray compressedBuffer;
@@ -86,9 +86,9 @@ qint64 QCompressedDevice::readData(char *data, qint64 maxlen)
qint64 QCompressedDevice::writeData(const char *data, qint64 len)
{
- QMT_CHECK(m_targetDevice);
- QMT_CHECK(m_targetDevice->isOpen());
- QMT_CHECK(m_targetDevice->openMode() == QIODevice::WriteOnly);
+ QMT_ASSERT(m_targetDevice, return 0);
+ QMT_ASSERT(m_targetDevice->isOpen(), return 0);
+ QMT_ASSERT(m_targetDevice->openMode() == QIODevice::WriteOnly, return 0);
m_buffer.append(data, len);
if (m_buffer.size() > 1024*1024) {
@@ -106,8 +106,8 @@ qint64 QCompressedDevice::writeData(const char *data, qint64 len)
qint64 QCompressedDevice::flush()
{
if (openMode() == QIODevice::WriteOnly && m_buffer.size() > 0) {
- QMT_CHECK(m_targetDevice->isOpen());
- QMT_CHECK(m_targetDevice->openMode() == QIODevice::WriteOnly);
+ QMT_ASSERT(m_targetDevice->isOpen(), return 0);
+ QMT_ASSERT(m_targetDevice->openMode() == QIODevice::WriteOnly, return 0);
QByteArray compressedBuffer = qCompress(m_buffer);
int compressedLen = static_cast<int>(compressedBuffer.size());
if (m_targetDevice->write(reinterpret_cast<const char *>(&compressedLen), sizeof(int)) != sizeof(int))
diff --git a/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.h b/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.h
index dad4f9a596..efe31b102d 100644
--- a/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.h
+++ b/src/libs/modelinglib/qmt/infrastructure/qcompressedfile.h
@@ -35,8 +35,8 @@ class QCompressedDevice : public QIODevice
Q_OBJECT
public:
- explicit QCompressedDevice(QObject *parent = 0);
- explicit QCompressedDevice(QIODevice *targetDevice, QObject *parent = 0);
+ explicit QCompressedDevice(QObject *parent = nullptr);
+ explicit QCompressedDevice(QIODevice *targetDevice, QObject *parent = nullptr);
~QCompressedDevice() override;
QIODevice *targetDevice() const { return m_targetDevice; }
@@ -52,7 +52,7 @@ public:
qint64 flush();
private:
- QIODevice *m_targetDevice = 0;
+ QIODevice *m_targetDevice = nullptr;
QByteArray m_buffer;
qint64 m_bytesInBuffer = 0;
qint64 m_indexInBuffer = 0;
diff --git a/src/libs/modelinglib/qmt/infrastructure/qmtassert.h b/src/libs/modelinglib/qmt/infrastructure/qmtassert.h
index c87076be25..3417671fcf 100644
--- a/src/libs/modelinglib/qmt/infrastructure/qmtassert.h
+++ b/src/libs/modelinglib/qmt/infrastructure/qmtassert.h
@@ -27,7 +27,7 @@
#include "utils/qtcassert.h"
-// TODO extend with parameter action
#define QMT_CHECK(condition) QTC_CHECK(condition)
+#define QMT_ASSERT(condition, action) QTC_ASSERT(condition, action)
// TODO implement logging of where and what
-#define QMT_CHECK_X(condition, where, what) QTC_CHECK(condition)
+#define QMT_CHECK_X(condition, where, what) QMT_CHECK(condition)
diff --git a/src/libs/modelinglib/qmt/model/massociation.cpp b/src/libs/modelinglib/qmt/model/massociation.cpp
index 5bd833df52..79b88226d9 100644
--- a/src/libs/modelinglib/qmt/model/massociation.cpp
+++ b/src/libs/modelinglib/qmt/model/massociation.cpp
@@ -31,8 +31,6 @@
namespace qmt {
MAssociationEnd::MAssociationEnd()
- : m_kind(Association),
- m_isNavigable(false)
{
}
diff --git a/src/libs/modelinglib/qmt/model/massociation.h b/src/libs/modelinglib/qmt/model/massociation.h
index 82f6bdf0c6..cec083f4fc 100644
--- a/src/libs/modelinglib/qmt/model/massociation.h
+++ b/src/libs/modelinglib/qmt/model/massociation.h
@@ -61,8 +61,8 @@ public:
private:
QString m_name;
QString m_cardinality;
- Kind m_kind;
- bool m_isNavigable;
+ Kind m_kind = Association;
+ bool m_isNavigable = false;
};
bool operator==(const MAssociationEnd &lhs, const MAssociationEnd &rhs);
diff --git a/src/libs/modelinglib/qmt/model/mclassmember.cpp b/src/libs/modelinglib/qmt/model/mclassmember.cpp
index 49bea877b7..a5a5be28bb 100644
--- a/src/libs/modelinglib/qmt/model/mclassmember.cpp
+++ b/src/libs/modelinglib/qmt/model/mclassmember.cpp
@@ -28,40 +28,10 @@
namespace qmt {
MClassMember::MClassMember(MemberType memberType)
- : m_visibility(VisibilityUndefined),
- m_memberType(memberType)
+ : m_memberType(memberType)
{
}
-MClassMember::MClassMember(const MClassMember &rhs)
- : m_uid(rhs.m_uid),
- m_stereotypes(rhs.m_stereotypes),
- m_group(rhs.m_group),
- m_declaration(rhs.m_declaration),
- m_visibility(rhs.m_visibility),
- m_memberType(rhs.m_memberType),
- m_properties(rhs.m_properties)
-{
-}
-
-MClassMember::~MClassMember()
-{
-}
-
-MClassMember &MClassMember::operator=(const MClassMember &rhs)
-{
- if (this != &rhs) {
- m_uid = rhs.m_uid;
- m_stereotypes = rhs.m_stereotypes;
- m_group = rhs.m_group;
- m_declaration = rhs.m_declaration;
- m_visibility = rhs.m_visibility;
- m_memberType = rhs.m_memberType;
- m_properties = rhs.m_properties;
- }
- return *this;
-}
-
void MClassMember::setUid(const Uid &uid)
{
m_uid = uid;
diff --git a/src/libs/modelinglib/qmt/model/mclassmember.h b/src/libs/modelinglib/qmt/model/mclassmember.h
index 99acb8d2ae..9b530b0e33 100644
--- a/src/libs/modelinglib/qmt/model/mclassmember.h
+++ b/src/libs/modelinglib/qmt/model/mclassmember.h
@@ -69,10 +69,6 @@ public:
Q_DECLARE_FLAGS(Properties, Property)
explicit MClassMember(MemberType memberType = MemberUndefined);
- MClassMember(const MClassMember &rhs);
- ~MClassMember();
-
- MClassMember &operator=(const MClassMember &rhs);
Uid uid() const { return m_uid; }
void setUid(const Uid &uid);
@@ -95,8 +91,8 @@ private:
QList<QString> m_stereotypes;
QString m_group;
QString m_declaration;
- Visibility m_visibility;
- MemberType m_memberType;
+ Visibility m_visibility = VisibilityUndefined;
+ MemberType m_memberType = MemberUndefined;
Properties m_properties;
};
diff --git a/src/libs/modelinglib/qmt/model/mconnection.cpp b/src/libs/modelinglib/qmt/model/mconnection.cpp
new file mode 100644
index 0000000000..2d8ab6c2c3
--- /dev/null
+++ b/src/libs/modelinglib/qmt/model/mconnection.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mconnection.h"
+
+#include "mvisitor.h"
+#include "mconstvisitor.h"
+
+namespace qmt {
+
+MConnectionEnd::MConnectionEnd()
+{
+}
+
+MConnectionEnd::MConnectionEnd(const MConnectionEnd &rhs)
+ : m_name(rhs.name()),
+ m_cardinality(rhs.m_cardinality),
+ m_isNavigable(rhs.m_isNavigable)
+{
+}
+
+MConnectionEnd::~MConnectionEnd()
+{
+}
+
+MConnectionEnd &MConnectionEnd::operator=(const MConnectionEnd &rhs)
+{
+ if (this != &rhs) {
+ m_name = rhs.m_name;
+ m_cardinality = rhs.m_cardinality;
+ m_isNavigable = rhs.m_isNavigable;
+ }
+ return *this;
+}
+
+void MConnectionEnd::setName(const QString &name)
+{
+ m_name = name;
+}
+
+void MConnectionEnd::setCardinality(const QString &cardinality)
+{
+ m_cardinality = cardinality;
+}
+
+void MConnectionEnd::setNavigable(bool navigable)
+{
+ m_isNavigable = navigable;
+}
+
+bool operator==(const MConnectionEnd &lhs, const MConnectionEnd &rhs)
+{
+ return lhs.name() == rhs.name()
+ && lhs.cardinality() == rhs.cardinality()
+ && lhs.isNavigable() == rhs.isNavigable();
+}
+
+MConnection::MConnection()
+ : MRelation()
+{
+}
+
+MConnection::~MConnection()
+{
+}
+
+void MConnection::setCustomRelationId(const QString &customRelationId)
+{
+ m_customRelationId = customRelationId;
+}
+
+void MConnection::setEndA(const MConnectionEnd &end)
+{
+ m_endA = end;
+}
+
+void MConnection::setEndB(const MConnectionEnd &end)
+{
+ m_endB = end;
+}
+
+void MConnection::accept(MVisitor *visitor)
+{
+ visitor->visitMConnection(this);
+}
+
+void MConnection::accept(MConstVisitor *visitor) const
+{
+ visitor->visitMConnection(this);
+}
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model/mconnection.h b/src/libs/modelinglib/qmt/model/mconnection.h
new file mode 100644
index 0000000000..2fe10fcbc5
--- /dev/null
+++ b/src/libs/modelinglib/qmt/model/mconnection.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "mrelation.h"
+#include "qmt/infrastructure/handle.h"
+
+#include <QString>
+
+namespace qmt {
+
+class QMT_EXPORT MConnectionEnd
+{
+public:
+ MConnectionEnd();
+ MConnectionEnd(const MConnectionEnd &rhs);
+ ~MConnectionEnd();
+
+ MConnectionEnd &operator=(const MConnectionEnd &rhs);
+
+ QString name() const { return m_name; }
+ void setName(const QString &name);
+ QString cardinality() const { return m_cardinality; }
+ void setCardinality(const QString &cardinality);
+ bool isNavigable() const { return m_isNavigable; }
+ void setNavigable(bool navigable);
+
+private:
+ QString m_name;
+ QString m_cardinality;
+ bool m_isNavigable = false;
+};
+
+bool operator==(const MConnectionEnd &lhs, const MConnectionEnd &rhs);
+inline bool operator!=(const MConnectionEnd &lhs, const MConnectionEnd &rhs)
+{
+ return !(lhs == rhs);
+}
+
+class QMT_EXPORT MConnection : public MRelation
+{
+public:
+ MConnection();
+ ~MConnection() override;
+
+ QString customRelationId() const { return m_customRelationId; }
+ void setCustomRelationId(const QString &customRelationId);
+ MConnectionEnd endA() const { return m_endA; }
+ void setEndA(const MConnectionEnd &end);
+ MConnectionEnd endB() const { return m_endB; }
+ void setEndB(const MConnectionEnd &end);
+
+ void accept(MVisitor *visitor) override;
+ void accept(MConstVisitor *visitor) const override;
+
+private:
+ QString m_customRelationId;
+ MConnectionEnd m_endA;
+ MConnectionEnd m_endB;
+};
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model/mconstvisitor.h b/src/libs/modelinglib/qmt/model/mconstvisitor.h
index fcfa9665fc..5ef7182726 100644
--- a/src/libs/modelinglib/qmt/model/mconstvisitor.h
+++ b/src/libs/modelinglib/qmt/model/mconstvisitor.h
@@ -41,6 +41,7 @@ class MRelation;
class MDependency;
class MInheritance;
class MAssociation;
+class MConnection;
class MConstVisitor
{
@@ -59,6 +60,7 @@ public:
virtual void visitMDependency(const MDependency *dependency) = 0;
virtual void visitMInheritance(const MInheritance *inheritance) = 0;
virtual void visitMAssociation(const MAssociation *association) = 0;
+ virtual void visitMConnection(const MConnection *connection) = 0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model/mdependency.cpp b/src/libs/modelinglib/qmt/model/mdependency.cpp
index d0b4bf0cb5..72567be748 100644
--- a/src/libs/modelinglib/qmt/model/mdependency.cpp
+++ b/src/libs/modelinglib/qmt/model/mdependency.cpp
@@ -31,8 +31,6 @@
namespace qmt {
MDependency::MDependency()
- : MRelation(),
- m_direction(AToB)
{
}
diff --git a/src/libs/modelinglib/qmt/model/mdependency.h b/src/libs/modelinglib/qmt/model/mdependency.h
index f2754c4f9c..1d5d31aa5b 100644
--- a/src/libs/modelinglib/qmt/model/mdependency.h
+++ b/src/libs/modelinglib/qmt/model/mdependency.h
@@ -57,7 +57,7 @@ public:
void accept(MConstVisitor *visitor) const override;
private:
- Direction m_direction;
+ Direction m_direction = AToB;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model/mdiagram.cpp b/src/libs/modelinglib/qmt/model/mdiagram.cpp
index 2220609598..7f9d7e8789 100644
--- a/src/libs/modelinglib/qmt/model/mdiagram.cpp
+++ b/src/libs/modelinglib/qmt/model/mdiagram.cpp
@@ -71,7 +71,7 @@ DElement *MDiagram::findDiagramElement(const Uid &key) const
if (element->uid() == key)
return element;
}
- return 0;
+ return nullptr;
}
void MDiagram::setDiagramElements(const QList<DElement *> &elements)
@@ -81,21 +81,21 @@ void MDiagram::setDiagramElements(const QList<DElement *> &elements)
void MDiagram::addDiagramElement(DElement *element)
{
- QMT_CHECK(element);
+ QMT_ASSERT(element, return);
m_elements.append(element);
}
void MDiagram::insertDiagramElement(int beforeElement, DElement *element)
{
- QMT_CHECK(beforeElement >= 0 && beforeElement <= m_elements.size());
+ QMT_ASSERT(beforeElement >= 0 && beforeElement <= m_elements.size(), return);
m_elements.insert(beforeElement, element);
}
void MDiagram::removeDiagramElement(int index)
{
- QMT_CHECK(index >= 0 && index < m_elements.size());
+ QMT_ASSERT(index >= 0 && index < m_elements.size(), return);
delete m_elements.at(index);
m_elements.removeAt(index);
@@ -103,7 +103,7 @@ void MDiagram::removeDiagramElement(int index)
void MDiagram::removeDiagramElement(DElement *element)
{
- QMT_CHECK(element);
+ QMT_ASSERT(element, return);
removeDiagramElement(m_elements.indexOf(element));
}
diff --git a/src/libs/modelinglib/qmt/model/melement.h b/src/libs/modelinglib/qmt/model/melement.h
index b83b5bd980..7707399fbb 100644
--- a/src/libs/modelinglib/qmt/model/melement.h
+++ b/src/libs/modelinglib/qmt/model/melement.h
@@ -81,10 +81,10 @@ public:
private:
Uid m_uid;
- MObject *m_owner = 0;
- MExpansion *m_expansion = 0;
+ MObject *m_owner = nullptr;
+ MExpansion *m_expansion = nullptr;
QList<QString> m_stereotypes;
- Flags m_flags = 0;
+ Flags m_flags;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MElement::Flags)
diff --git a/src/libs/modelinglib/qmt/model/mitem.cpp b/src/libs/modelinglib/qmt/model/mitem.cpp
index 3eb766fa3b..ada6be5fc0 100644
--- a/src/libs/modelinglib/qmt/model/mitem.cpp
+++ b/src/libs/modelinglib/qmt/model/mitem.cpp
@@ -31,9 +31,6 @@
namespace qmt {
MItem::MItem()
- : MObject(),
- m_isVarietyEditable(true),
- m_isShapeEditable(false)
{
}
diff --git a/src/libs/modelinglib/qmt/model/mitem.h b/src/libs/modelinglib/qmt/model/mitem.h
index ebedea5efe..e60efde215 100644
--- a/src/libs/modelinglib/qmt/model/mitem.h
+++ b/src/libs/modelinglib/qmt/model/mitem.h
@@ -47,8 +47,8 @@ public:
private:
QString m_variety;
- bool m_isVarietyEditable;
- bool m_isShapeEditable;
+ bool m_isVarietyEditable = true;
+ bool m_isShapeEditable = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model/mobject.cpp b/src/libs/modelinglib/qmt/model/mobject.cpp
index 583335e96e..1d5f7dc96c 100644
--- a/src/libs/modelinglib/qmt/model/mobject.cpp
+++ b/src/libs/modelinglib/qmt/model/mobject.cpp
@@ -82,8 +82,8 @@ void MObject::addChild(const Uid &uid)
void MObject::addChild(MObject *child)
{
- QMT_CHECK(child);
- QMT_CHECK(child->owner() == 0);
+ QMT_ASSERT(child, return);
+ QMT_ASSERT(!child->owner(), return);
m_children.add(child);
child->setOwner(this);
}
@@ -95,43 +95,43 @@ void MObject::insertChild(int beforeIndex, const Uid &uid)
void MObject::insertChild(int beforeIndex, MObject *child)
{
- QMT_CHECK(child);
- QMT_CHECK(child->owner() == 0);
+ QMT_ASSERT(child, return);
+ QMT_ASSERT(!child->owner(), return);
m_children.insert(beforeIndex, child);
child->setOwner(this);
}
void MObject::removeChild(const Uid &uid)
{
- QMT_CHECK(m_children.contains(uid));
+ QMT_ASSERT(m_children.contains(uid), return);
MObject *child = m_children.find(uid);
if (child)
- child->setOwner(0);
+ child->setOwner(nullptr);
m_children.remove(uid);
}
void MObject::removeChild(MObject *child)
{
- QMT_CHECK(child);
- QMT_CHECK(m_children.contains(child));
- child->setOwner(0);
+ QMT_ASSERT(child, return);
+ QMT_ASSERT(m_children.contains(child), return);
+ child->setOwner(nullptr);
m_children.remove(child);
}
void MObject::decontrolChild(const Uid &uid)
{
- QMT_CHECK(m_children.contains(uid));
+ QMT_ASSERT(m_children.contains(uid), return);
MObject *child = m_children.find(uid);
if (child)
- child->setOwner(0);
+ child->setOwner(nullptr);
m_children.take(uid);
}
void MObject::decontrolChild(MObject *child)
{
- QMT_CHECK(child);
- QMT_CHECK(m_children.contains(child));
- child->setOwner(0);
+ QMT_ASSERT(child, return);
+ QMT_ASSERT(m_children.contains(child), return);
+ child->setOwner(nullptr);
m_children.take(child);
}
@@ -151,31 +151,31 @@ void MObject::addRelation(const Uid &uid)
void MObject::addRelation(MRelation *relation)
{
- QMT_CHECK(relation);
- QMT_CHECK(relation->owner() == 0);
+ QMT_ASSERT(relation, return);
+ QMT_ASSERT(!relation->owner(), return);
relation->setOwner(this);
m_relations.add(relation);
}
void MObject::insertRelation(int beforeIndex, MRelation *relation)
{
- QMT_CHECK(relation);
- QMT_CHECK(relation->owner() == 0);
+ QMT_ASSERT(relation, return);
+ QMT_ASSERT(!relation->owner(), return);
relation->setOwner(this);
m_relations.insert(beforeIndex, relation);
}
void MObject::removeRelation(MRelation *relation)
{
- QMT_CHECK(relation);
- relation->setOwner(0);
+ QMT_ASSERT(relation, return);
+ relation->setOwner(nullptr);
m_relations.remove(relation);
}
void MObject::decontrolRelation(MRelation *relation)
{
- QMT_CHECK(relation);
- relation->setOwner(0);
+ QMT_ASSERT(relation, return);
+ relation->setOwner(nullptr);
m_relations.take(relation);
}
diff --git a/src/libs/modelinglib/qmt/model/msourceexpansion.cpp b/src/libs/modelinglib/qmt/model/msourceexpansion.cpp
index 9a21d635e7..1d02c2811a 100644
--- a/src/libs/modelinglib/qmt/model/msourceexpansion.cpp
+++ b/src/libs/modelinglib/qmt/model/msourceexpansion.cpp
@@ -30,8 +30,6 @@
namespace qmt {
MSourceExpansion::MSourceExpansion()
- : MExpansion(),
- m_isTransient(false)
{
}
@@ -58,7 +56,7 @@ MSourceExpansion &MSourceExpansion::operator=(const MSourceExpansion &rhs)
MSourceExpansion *MSourceExpansion::clone(const MElement &rhs) const
{
auto rightExpansion = dynamic_cast<MSourceExpansion *>(rhs.expansion());
- QMT_CHECK(rightExpansion);
+ QMT_ASSERT(rightExpansion, return nullptr);
auto expansion = new MSourceExpansion(*rightExpansion);
return expansion;
}
diff --git a/src/libs/modelinglib/qmt/model/msourceexpansion.h b/src/libs/modelinglib/qmt/model/msourceexpansion.h
index eb7c1bc3a5..a631f1ab5f 100644
--- a/src/libs/modelinglib/qmt/model/msourceexpansion.h
+++ b/src/libs/modelinglib/qmt/model/msourceexpansion.h
@@ -47,7 +47,7 @@ public:
private:
QString m_sourceId;
- bool m_isTransient;
+ bool m_isTransient = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model/mvisitor.h b/src/libs/modelinglib/qmt/model/mvisitor.h
index bce52be8d0..23390a47e3 100644
--- a/src/libs/modelinglib/qmt/model/mvisitor.h
+++ b/src/libs/modelinglib/qmt/model/mvisitor.h
@@ -41,6 +41,7 @@ class MRelation;
class MDependency;
class MInheritance;
class MAssociation;
+class MConnection;
class MVisitor
{
@@ -59,6 +60,7 @@ public:
virtual void visitMDependency(MDependency *dependency) = 0;
virtual void visitMInheritance(MInheritance *inheritance) = 0;
virtual void visitMAssociation(MAssociation *association) = 0;
+ virtual void visitMConnection(MConnection *connection) = 0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.cpp b/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.cpp
index b9edd7ff30..aed3f795f0 100644
--- a/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.cpp
+++ b/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.cpp
@@ -34,6 +34,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
#include "qmt/model/massociation.h"
+#include "qmt/model/mconnection.h"
namespace qmt {
@@ -102,4 +103,9 @@ void MChildrenVisitor::visitMAssociation(MAssociation *association)
visitMRelation(association);
}
+void MChildrenVisitor::visitMConnection(MConnection *connection)
+{
+ visitMRelation(connection);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.h b/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.h
index 406febde8e..b36fc2104f 100644
--- a/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.h
+++ b/src/libs/modelinglib/qmt/model_controller/mchildrenvisitor.h
@@ -45,6 +45,7 @@ public:
void visitMDependency(MDependency *dependency) override;
void visitMInheritance(MInheritance *inheritance) override;
void visitMAssociation(MAssociation *association) override;
+ void visitMConnection(MConnection *connection) override;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/mclonevisitor.cpp b/src/libs/modelinglib/qmt/model_controller/mclonevisitor.cpp
index 19dd6ab8e5..7231346b55 100644
--- a/src/libs/modelinglib/qmt/model_controller/mclonevisitor.cpp
+++ b/src/libs/modelinglib/qmt/model_controller/mclonevisitor.cpp
@@ -35,6 +35,7 @@
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
+#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
@@ -44,7 +45,6 @@
namespace qmt {
MCloneVisitor::MCloneVisitor()
- : m_cloned(0)
{
}
@@ -85,7 +85,7 @@ void MCloneVisitor::visitMDiagram(const MDiagram *diagram)
{
QMT_CHECK(m_cloned);
auto cloned = dynamic_cast<MDiagram *>(m_cloned);
- QMT_CHECK(cloned);
+ QMT_ASSERT(cloned, return);
foreach (const DElement *element, diagram->diagramElements()) {
DCloneDeepVisitor visitor;
element->accept(&visitor);
@@ -136,8 +136,14 @@ void MCloneVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
+void MCloneVisitor::visitMConnection(const MConnection *connection)
+{
+ if (!m_cloned)
+ m_cloned = new MConnection(*connection);
+ visitMRelation(connection);
+}
+
MCloneDeepVisitor::MCloneDeepVisitor()
- : m_cloned(0)
{
}
@@ -152,13 +158,13 @@ void MCloneDeepVisitor::visitMObject(const MObject *object)
QMT_CHECK(m_cloned);
visitMElement(object);
auto cloned = dynamic_cast<MObject *>(m_cloned);
- QMT_CHECK(cloned);
+ QMT_ASSERT(cloned, return);
foreach (const Handle<MObject> &handle, object->children()) {
if (handle.hasTarget()) {
MCloneDeepVisitor visitor;
handle.target()->accept(&visitor);
auto clonedChild = dynamic_cast<MObject *>(visitor.cloned());
- QMT_CHECK(clonedChild);
+ QMT_ASSERT(clonedChild, return);
cloned->addChild(clonedChild);
} else {
cloned->addChild(handle.uid());
@@ -169,7 +175,7 @@ void MCloneDeepVisitor::visitMObject(const MObject *object)
MCloneDeepVisitor visitor;
handle.target()->accept(&visitor);
auto clonedRelation = dynamic_cast<MRelation *>(visitor.cloned());
- QMT_CHECK(clonedRelation);
+ QMT_ASSERT(clonedRelation, return);
cloned->addRelation(clonedRelation);
} else {
cloned->addRelation(handle.uid());
@@ -202,7 +208,7 @@ void MCloneDeepVisitor::visitMDiagram(const MDiagram *diagram)
{
QMT_CHECK(m_cloned);
auto cloned = dynamic_cast<MDiagram *>(m_cloned);
- QMT_CHECK(cloned);
+ QMT_ASSERT(cloned, return);
foreach (const DElement *element, diagram->diagramElements()) {
DCloneDeepVisitor visitor;
element->accept(&visitor);
@@ -231,7 +237,7 @@ void MCloneDeepVisitor::visitMRelation(const MRelation *relation)
QMT_CHECK(m_cloned);
visitMElement(relation);
auto cloned = dynamic_cast<MRelation *>(m_cloned);
- QMT_CHECK(cloned);
+ QMT_ASSERT(cloned, return);
cloned->setEndAUid(relation->endAUid());
cloned->setEndBUid(relation->endBUid());
}
@@ -257,4 +263,11 @@ void MCloneDeepVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
+void MCloneDeepVisitor::visitMConnection(const MConnection *connection)
+{
+ if (!m_cloned)
+ m_cloned = new MConnection(*connection);
+ visitMRelation(connection);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/mclonevisitor.h b/src/libs/modelinglib/qmt/model_controller/mclonevisitor.h
index 4d97acdd4f..2f833bc53e 100644
--- a/src/libs/modelinglib/qmt/model_controller/mclonevisitor.h
+++ b/src/libs/modelinglib/qmt/model_controller/mclonevisitor.h
@@ -51,9 +51,10 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
+ void visitMConnection(const MConnection *connection) override;
private:
- MElement *m_cloned;
+ MElement *m_cloned = nullptr;
};
class QMT_EXPORT MCloneDeepVisitor : public MConstVisitor
@@ -75,9 +76,10 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
+ void visitMConnection(const MConnection *connection) override;
private:
- MElement *m_cloned;
+ MElement *m_cloned = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp b/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp
index 424dca860d..8f47337e51 100644
--- a/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp
+++ b/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp
@@ -34,6 +34,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
#include "qmt/model/massociation.h"
+#include "qmt/model/mconnection.h"
namespace qmt {
@@ -54,7 +55,7 @@ void MFlatAssignmentVisitor::visitMObject(const MObject *object)
{
visitMElement(object);
auto targetObject = dynamic_cast<MObject *>(m_target);
- QMT_CHECK(targetObject);
+ QMT_ASSERT(targetObject, return);
targetObject->setName(object->name());
}
@@ -67,7 +68,7 @@ void MFlatAssignmentVisitor::visitMClass(const MClass *klass)
{
visitMObject(klass);
auto targetClass = dynamic_cast<MClass *>(m_target);
- QMT_CHECK(targetClass);
+ QMT_ASSERT(targetClass, return);
targetClass->setUmlNamespace(klass->umlNamespace());
targetClass->setTemplateParameters(klass->templateParameters());
targetClass->setMembers(klass->members());
@@ -82,7 +83,7 @@ void MFlatAssignmentVisitor::visitMDiagram(const MDiagram *diagram)
{
visitMObject(diagram);
auto targetDiagram = dynamic_cast<MDiagram *>(m_target);
- QMT_CHECK(targetDiagram);
+ QMT_ASSERT(targetDiagram, return);
targetDiagram->setToolbarId(diagram->toolbarId());
}
@@ -95,7 +96,7 @@ void MFlatAssignmentVisitor::visitMItem(const MItem *item)
{
visitMObject(item);
auto targetItem = dynamic_cast<MItem *>(m_target);
- QMT_CHECK(targetItem);
+ QMT_ASSERT(targetItem, return);
targetItem->setVarietyEditable(item->isVarietyEditable());
targetItem->setVariety(item->variety());
targetItem->setShapeEditable(item->isShapeEditable());
@@ -105,7 +106,7 @@ void MFlatAssignmentVisitor::visitMRelation(const MRelation *relation)
{
visitMElement(relation);
auto targetRelation = dynamic_cast<MRelation *>(m_target);
- QMT_CHECK(targetRelation);
+ QMT_ASSERT(targetRelation, return);
targetRelation->setName(relation->name());
targetRelation->setEndAUid(relation->endAUid());
targetRelation->setEndBUid(relation->endBUid());
@@ -115,7 +116,7 @@ void MFlatAssignmentVisitor::visitMDependency(const MDependency *dependency)
{
visitMRelation(dependency);
auto targetDependency = dynamic_cast<MDependency *>(m_target);
- QMT_CHECK(targetDependency);
+ QMT_ASSERT(targetDependency, return);
targetDependency->setDirection(dependency->direction());
}
@@ -128,9 +129,20 @@ void MFlatAssignmentVisitor::visitMAssociation(const MAssociation *association)
{
visitMRelation(association);
auto targetAssociation = dynamic_cast<MAssociation *>(m_target);
- QMT_CHECK(targetAssociation);
+ QMT_ASSERT(targetAssociation, return);
targetAssociation->setEndA(association->endA());
targetAssociation->setEndB(association->endB());
+ // TODO assign association class UID?
+}
+
+void MFlatAssignmentVisitor::visitMConnection(const MConnection *connection)
+{
+ visitMRelation(connection);
+ auto targetConnection = dynamic_cast<MConnection *>(m_target);
+ QMT_ASSERT(targetConnection, return);
+ targetConnection->setCustomRelationId(connection->customRelationId());
+ targetConnection->setEndA(connection->endA());
+ targetConnection->setEndB(connection->endB());
}
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.h b/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.h
index 49d696fd92..6794ac68dc 100644
--- a/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.h
+++ b/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.h
@@ -49,9 +49,10 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
+ void visitMConnection(const MConnection *connection) override;
private:
- MElement *m_target;
+ MElement *m_target = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp b/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp
index 9257e149b3..fc3072da27 100644
--- a/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp
+++ b/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp
@@ -49,7 +49,7 @@ public:
Uid m_elementKey;
Uid m_ownerKey;
int m_indexOfElement = -1;
- MElement *m_clonedElement = 0;
+ MElement *m_clonedElement = nullptr;
};
class ModelController::UpdateObjectCommand : public UndoCommand
@@ -99,7 +99,7 @@ private:
void assign()
{
MObject *object = m_modelController->findObject<MObject>(m_object->uid());
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
int row = 0;
MObject *parent = object->owner();
if (!parent) {
@@ -121,8 +121,8 @@ private:
m_modelController->verifyModelIntegrity();
}
- ModelController *m_modelController = 0;
- MObject *m_object = 0;
+ ModelController *m_modelController = nullptr;
+ MObject *m_object = nullptr;
};
class ModelController::UpdateRelationCommand :
@@ -173,9 +173,9 @@ private:
void assign()
{
MRelation *relation = m_modelController->findRelation<MRelation>(m_relation->uid());
- QMT_CHECK(relation);
+ QMT_ASSERT(relation, return);
MObject *owner = relation->owner();
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
int row = owner->relations().indexOf(relation);
emit m_modelController->beginUpdateRelation(row, owner);
MCloneVisitor cloneVisitor;
@@ -191,8 +191,8 @@ private:
m_modelController->verifyModelIntegrity();
}
- ModelController *m_modelController = 0;
- MRelation *m_relation = 0;
+ ModelController *m_modelController = nullptr;
+ MRelation *m_relation = nullptr;
};
class ModelController::AddElementsCommand : public UndoCommand
@@ -226,10 +226,10 @@ public:
bool inserted = false;
for (int i = m_clonedElements.count() - 1; i >= 0; --i) {
Clone &clone = m_clonedElements[i];
- QMT_CHECK(clone.m_clonedElement);
+ QMT_ASSERT(clone.m_clonedElement, return);
QMT_CHECK(clone.m_clonedElement->uid() == clone.m_elementKey);
MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
QMT_CHECK(clone.m_indexOfElement >= 0);
switch (clone.m_elementType) {
case TypeObject:
@@ -239,7 +239,7 @@ public:
QMT_CHECK(object);
m_modelController->mapObject(object);
owner->insertChild(clone.m_indexOfElement, object);
- clone.m_clonedElement = 0;
+ clone.m_clonedElement = nullptr;
emit m_modelController->endInsertObject(clone.m_indexOfElement, owner);
inserted = true;
break;
@@ -251,7 +251,7 @@ public:
QMT_CHECK(relation);
m_modelController->mapRelation(relation);
owner->insertRelation(clone.m_indexOfElement, relation);
- clone.m_clonedElement = 0;
+ clone.m_clonedElement = nullptr;
emit m_modelController->endInsertRelation(clone.m_indexOfElement, owner);
inserted = true;
break;
@@ -275,12 +275,12 @@ public:
Clone &clone = m_clonedElements[i];
QMT_CHECK(!clone.m_clonedElement);
MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
switch (clone.m_elementType) {
case TypeObject:
{
MObject *object = m_modelController->findObject<MObject>(clone.m_elementKey);
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
clone.m_indexOfElement = owner->children().indexOf(object);
QMT_CHECK(clone.m_indexOfElement >= 0);
emit m_modelController->beginRemoveObject(clone.m_indexOfElement, owner);
@@ -296,7 +296,7 @@ public:
case TypeRelation:
{
MRelation *relation = m_modelController->findRelation<MRelation>(clone.m_elementKey);
- QMT_CHECK(relation);
+ QMT_ASSERT(relation, return);
clone.m_indexOfElement = owner->relations().indexOf(relation);
QMT_CHECK(clone.m_indexOfElement >= 0);
emit m_modelController->beginRemoveRelation(clone.m_indexOfElement, owner);
@@ -321,7 +321,7 @@ public:
}
private:
- ModelController *m_modelController = 0;
+ ModelController *m_modelController = nullptr;
QList<ModelController::Clone> m_clonedElements;
};
@@ -360,7 +360,7 @@ public:
MCloneDeepVisitor visitor;
element->accept(&visitor);
clone.m_clonedElement = visitor.cloned();
- QMT_CHECK(clone.m_clonedElement);
+ QMT_ASSERT(clone.m_clonedElement, return);
m_clonedElements.append(clone);
}
@@ -372,12 +372,12 @@ public:
Clone &clone = m_clonedElements[i];
QMT_CHECK(!clone.m_clonedElement);
MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
switch (clone.m_elementType) {
case TypeObject:
{
MObject *object = m_modelController->findObject<MObject>(clone.m_elementKey);
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
clone.m_indexOfElement = owner->children().indexOf(object);
QMT_CHECK(clone.m_indexOfElement >= 0);
emit m_modelController->beginRemoveObject(clone.m_indexOfElement, owner);
@@ -393,7 +393,7 @@ public:
case TypeRelation:
{
MRelation *relation = m_modelController->findRelation<MRelation>(clone.m_elementKey);
- QMT_CHECK(relation);
+ QMT_ASSERT(relation, return);
clone.m_indexOfElement = owner->relations().indexOf(relation);
QMT_CHECK(clone.m_indexOfElement >= 0);
emit m_modelController->beginRemoveRelation(clone.m_indexOfElement, owner);
@@ -423,9 +423,9 @@ public:
bool inserted = false;
for (int i = m_clonedElements.count() - 1; i >= 0; --i) {
Clone &clone = m_clonedElements[i];
- QMT_CHECK(clone.m_clonedElement);
+ QMT_ASSERT(clone.m_clonedElement, return);
MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
QMT_CHECK(clone.m_indexOfElement >= 0);
switch (clone.m_elementType) {
case TypeObject:
@@ -435,7 +435,7 @@ public:
QMT_CHECK(object);
m_modelController->mapObject(object);
owner->insertChild(clone.m_indexOfElement, object);
- clone.m_clonedElement = 0;
+ clone.m_clonedElement = nullptr;
emit m_modelController->endInsertObject(clone.m_indexOfElement, owner);
inserted = true;
break;
@@ -447,7 +447,7 @@ public:
QMT_CHECK(relation);
m_modelController->mapRelation(relation);
owner->insertRelation(clone.m_indexOfElement, relation);
- clone.m_clonedElement = 0;
+ clone.m_clonedElement = nullptr;
emit m_modelController->endInsertRelation(clone.m_indexOfElement, owner);
inserted = true;
break;
@@ -464,7 +464,7 @@ public:
}
private:
- ModelController *m_modelController = 0;
+ ModelController *m_modelController = nullptr;
QList<ModelController::Clone> m_clonedElements;
};
@@ -502,12 +502,13 @@ private:
void swap()
{
MObject *object = m_modelController->findObject(m_objectKey);
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
MObject *formerOwner = object->owner();
int formerRow = formerOwner->children().indexOf(object);
+ MObject *newOwner = m_modelController->findObject(m_ownerKey);
+ QMT_ASSERT(newOwner, return);
emit m_modelController->beginMoveObject(formerRow, formerOwner);
formerOwner->decontrolChild(object);
- MObject *newOwner = m_modelController->findObject(m_ownerKey);
newOwner->insertChild(m_indexOfElement, object);
int newRow = m_indexOfElement;
m_ownerKey = formerOwner->uid();
@@ -517,7 +518,7 @@ private:
m_modelController->verifyModelIntegrity();
}
- ModelController *m_modelController = 0;
+ ModelController *m_modelController = nullptr;
Uid m_objectKey;
Uid m_ownerKey;
int m_indexOfElement = -1;
@@ -557,12 +558,13 @@ private:
void swap()
{
MRelation *relation = m_modelController->findRelation(m_relationKey);
- QMT_CHECK(relation);
+ QMT_ASSERT(relation, return);
MObject *formerOwner = relation->owner();
int formerRow = formerOwner->relations().indexOf(relation);
+ MObject *newOwner = m_modelController->findObject(m_ownerKey);
+ QMT_ASSERT(newOwner, return);
emit m_modelController->beginMoveRelation(formerRow, formerOwner);
formerOwner->decontrolRelation(relation);
- MObject *newOwner = m_modelController->findObject(m_ownerKey);
newOwner->insertRelation(m_indexOfElement, relation);
int newRow = m_indexOfElement;
m_ownerKey = formerOwner->uid();
@@ -572,17 +574,14 @@ private:
m_modelController->verifyModelIntegrity();
}
- ModelController *m_modelController = 0;
+ ModelController *m_modelController = nullptr;
Uid m_relationKey;
Uid m_ownerKey;
int m_indexOfElement = -1;
};
ModelController::ModelController(QObject *parent)
- : QObject(parent),
- m_rootPackage(0),
- m_undoController(0),
- m_isResettingModel(false)
+ : QObject(parent)
{
}
@@ -607,7 +606,7 @@ void ModelController::setUndoController(UndoController *undoController)
Uid ModelController::ownerKey(const MElement *element) const
{
- QMT_CHECK(element);
+ QMT_ASSERT(element, return Uid());
MObject *owner = element->owner();
if (!owner)
return Uid();
@@ -620,7 +619,7 @@ MElement *ModelController::findElement(const Uid &key)
return object;
else if (MRelation *relation = findRelation(key))
return relation;
- return 0;
+ return nullptr;
}
void ModelController::startResetModel()
@@ -647,7 +646,7 @@ MObject *ModelController::object(int row, const MObject *owner) const
QMT_CHECK(row == 0);
return m_rootPackage;
}
- QMT_CHECK(row >= 0 && row < owner->children().size());
+ QMT_ASSERT(row >= 0 && row < owner->children().size(), return nullptr);
return owner->children().at(row);
}
@@ -658,8 +657,8 @@ MObject *ModelController::findObject(const Uid &key) const
void ModelController::addObject(MPackage *parentPackage, MObject *object)
{
- QMT_CHECK(parentPackage);
- QMT_CHECK(object);
+ QMT_ASSERT(parentPackage, return);
+ QMT_ASSERT(object, return);
int row = parentPackage->children().size();
if (!m_isResettingModel)
emit beginInsertObject(row, parentPackage);
@@ -679,12 +678,12 @@ void ModelController::addObject(MPackage *parentPackage, MObject *object)
void ModelController::removeObject(MObject *object)
{
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
if (m_undoController)
m_undoController->beginMergeSequence(tr("Delete Object"));
removeRelatedRelations(object);
// remove object
- QMT_CHECK(object->owner());
+ QMT_ASSERT(object->owner(), return);
int row = object->owner()->children().indexOf(object);
MObject *owner = object->owner();
if (!m_isResettingModel)
@@ -707,7 +706,7 @@ void ModelController::removeObject(MObject *object)
void ModelController::startUpdateObject(MObject *object)
{
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
int row = 0;
MObject *parent = object->owner();
if (!parent) {
@@ -725,7 +724,7 @@ void ModelController::startUpdateObject(MObject *object)
void ModelController::finishUpdateObject(MObject *object, bool cancelled)
{
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
int row = 0;
MObject *parent = object->owner();
@@ -752,9 +751,9 @@ void ModelController::finishUpdateObject(MObject *object, bool cancelled)
void ModelController::moveObject(MPackage *newOwner, MObject *object)
{
- QMT_CHECK(newOwner);
- QMT_CHECK(object);
- QMT_CHECK(object != m_rootPackage);
+ QMT_ASSERT(newOwner, return);
+ QMT_ASSERT(object, return);
+ QMT_ASSERT(object != m_rootPackage, return);
// verify that newOwner is not a child of object
MObject *newOwnerObject = newOwner;
@@ -766,7 +765,7 @@ void ModelController::moveObject(MPackage *newOwner, MObject *object)
if (newOwner != object->owner()) {
int formerRow = 0;
MObject *formerOwner = object->owner();
- QMT_CHECK(formerOwner);
+ QMT_ASSERT(formerOwner, return);
formerRow = formerOwner->children().indexOf(object);
if (!m_isResettingModel)
emit beginMoveObject(formerRow, formerOwner);
@@ -792,10 +791,10 @@ MRelation *ModelController::findRelation(const Uid &key) const
void ModelController::addRelation(MObject *owner, MRelation *relation)
{
- QMT_CHECK(owner);
- QMT_CHECK(relation);
- QMT_CHECK(findObject(relation->endAUid()));
- QMT_CHECK(findObject(relation->endBUid()));
+ QMT_ASSERT(owner, return);
+ QMT_ASSERT(relation, return);
+ QMT_ASSERT(findObject(relation->endAUid()), return);
+ QMT_ASSERT(findObject(relation->endBUid()), return);
int row = owner->relations().size();
if (!m_isResettingModel)
@@ -816,9 +815,9 @@ void ModelController::addRelation(MObject *owner, MRelation *relation)
void ModelController::removeRelation(MRelation *relation)
{
- QMT_CHECK(relation);
+ QMT_ASSERT(relation, return);
MObject *owner = relation->owner();
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
int row = owner->relations().indexOf(relation);
if (!m_isResettingModel)
emit beginRemoveRelation(row, owner);
@@ -838,9 +837,9 @@ void ModelController::removeRelation(MRelation *relation)
void ModelController::startUpdateRelation(MRelation *relation)
{
- QMT_CHECK(relation);
+ QMT_ASSERT(relation, return);
MObject *owner = relation->owner();
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
if (!m_isResettingModel)
emit beginUpdateRelation(owner->relations().indexOf(relation), owner);
if (m_undoController)
@@ -849,11 +848,11 @@ void ModelController::startUpdateRelation(MRelation *relation)
void ModelController::finishUpdateRelation(MRelation *relation, bool cancelled)
{
- QMT_CHECK(relation);
- QMT_CHECK(findObject(relation->endAUid()));
- QMT_CHECK(findObject(relation->endBUid()));
+ QMT_ASSERT(relation, return);
+ QMT_ASSERT(findObject(relation->endAUid()), return);
+ QMT_ASSERT(findObject(relation->endBUid()), return);
MObject *owner = relation->owner();
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
if (!m_isResettingModel) {
emit endUpdateRelation(owner->relations().indexOf(relation), owner);
if (!cancelled)
@@ -864,13 +863,13 @@ void ModelController::finishUpdateRelation(MRelation *relation, bool cancelled)
void ModelController::moveRelation(MObject *newOwner, MRelation *relation)
{
- QMT_CHECK(newOwner);
- QMT_CHECK(relation);
+ QMT_ASSERT(newOwner, return);
+ QMT_ASSERT(relation, return);
if (newOwner != relation->owner()) {
int formerRow = 0;
MObject *formerOwner = relation->owner();
- QMT_CHECK(formerOwner);
+ QMT_ASSERT(formerOwner, return);
formerRow = formerOwner->relations().indexOf(relation);
if (!m_isResettingModel)
emit beginMoveRelation(formerRow, formerOwner);
@@ -891,7 +890,7 @@ void ModelController::moveRelation(MObject *newOwner, MRelation *relation)
QList<MRelation *> ModelController::findRelationsOfObject(const MObject *object) const
{
- QMT_CHECK(object);
+ QMT_ASSERT(object, return QList<MRelation *>());
return m_objectRelationsMap.values(object->uid());
}
@@ -1140,7 +1139,7 @@ MReferences ModelController::simplify(const MSelection &modelSelection)
MReferences references;
foreach (const MSelection::Index &index, modelSelection.indices()) {
MElement *element = findElement(index.elementKey());
- QMT_CHECK(element);
+ QMT_ASSERT(element, return MReferences());
// if any (grand-)parent of element is in modelSelection then ignore element
bool ignore = false;
MObject *owner = element->owner();
@@ -1166,28 +1165,28 @@ void ModelController::verifyModelIntegrity() const
{
static const bool debugModelIntegrity = false;
if (debugModelIntegrity) {
- QMT_CHECK(m_rootPackage);
+ QMT_ASSERT(m_rootPackage, return);
QHash<Uid, const MObject *> objectsMap;
QHash<Uid, const MRelation *> relationsMap;
QMultiHash<Uid, MRelation *> objectRelationsMap;
verifyModelIntegrity(m_rootPackage, &objectsMap, &relationsMap, &objectRelationsMap);
- QMT_CHECK(objectsMap.size() == m_objectsMap.size());
+ QMT_ASSERT(objectsMap.size() == m_objectsMap.size(), return);
foreach (const MObject *object, m_objectsMap) {
- QMT_CHECK(object);
- QMT_CHECK(m_objectsMap.contains(object->uid()));
- QMT_CHECK(objectsMap.contains(object->uid()));
+ QMT_ASSERT(object, return);
+ QMT_ASSERT(m_objectsMap.contains(object->uid()), return);
+ QMT_ASSERT(objectsMap.contains(object->uid()), return);
}
- QMT_CHECK(relationsMap.size() == m_relationsMap.size());
+ QMT_ASSERT(relationsMap.size() == m_relationsMap.size(), return);
foreach (const MRelation *relation, m_relationsMap) {
- QMT_CHECK(relation);
- QMT_CHECK(m_relationsMap.contains(relation->uid()));
- QMT_CHECK(relationsMap.contains(relation->uid()));
+ QMT_ASSERT(relation, return);
+ QMT_ASSERT(m_relationsMap.contains(relation->uid()), return);
+ QMT_ASSERT(relationsMap.contains(relation->uid()), return);
}
- QMT_CHECK(objectRelationsMap.size() == m_objectRelationsMap.size());
+ QMT_ASSERT(objectRelationsMap.size() == m_objectRelationsMap.size(), return);
for (auto it = m_objectRelationsMap.cbegin(); it != m_objectRelationsMap.cend(); ++it) {
- QMT_CHECK(objectRelationsMap.contains(it.key(), it.value()));
+ QMT_ASSERT(objectRelationsMap.contains(it.key(), it.value()), return);
}
}
}
@@ -1196,19 +1195,19 @@ void ModelController::verifyModelIntegrity(const MObject *object, QHash<Uid, con
QHash<Uid, const MRelation *> *relationsMap,
QMultiHash<Uid, MRelation *> *objectRelationsMap) const
{
- QMT_CHECK(object);
- QMT_CHECK(!objectsMap->contains(object->uid()));
+ QMT_ASSERT(object, return);
+ QMT_ASSERT(!objectsMap->contains(object->uid()), return);
objectsMap->insert(object->uid(), object);
foreach (const Handle<MRelation> &handle, object->relations()) {
MRelation *relation = handle.target();
if (relation) {
- QMT_CHECK(!relationsMap->contains(relation->uid()));
+ QMT_ASSERT(!relationsMap->contains(relation->uid()), return);
relationsMap->insert(relation->uid(), relation);
- QMT_CHECK(findObject(relation->endAUid()));
- QMT_CHECK(findObject(relation->endBUid()));
- QMT_CHECK(!objectRelationsMap->contains(relation->endAUid(), relation));
+ QMT_ASSERT(findObject(relation->endAUid()), return);
+ QMT_ASSERT(findObject(relation->endBUid()), return);
+ QMT_ASSERT(!objectRelationsMap->contains(relation->endAUid(), relation), return);
objectRelationsMap->insert(relation->endAUid(), relation);
- QMT_CHECK(!objectRelationsMap->contains(relation->endBUid(), relation));
+ QMT_ASSERT(!objectRelationsMap->contains(relation->endBUid(), relation), return);
objectRelationsMap->insert(relation->endBUid(), relation);
}
}
diff --git a/src/libs/modelinglib/qmt/model_controller/modelcontroller.h b/src/libs/modelinglib/qmt/model_controller/modelcontroller.h
index ccc53078a5..345d5c0ce9 100644
--- a/src/libs/modelinglib/qmt/model_controller/modelcontroller.h
+++ b/src/libs/modelinglib/qmt/model_controller/modelcontroller.h
@@ -61,7 +61,7 @@ class QMT_EXPORT ModelController : public QObject
class MoveRelationCommand;
public:
- explicit ModelController(QObject *parent = 0);
+ explicit ModelController(QObject *parent = nullptr);
~ModelController() override;
signals:
@@ -151,12 +151,12 @@ private:
QHash<Uid, const MRelation *> *relationsMap,
QMultiHash<Uid, MRelation *> *objectRelationsMap) const;
- MPackage *m_rootPackage;
- UndoController *m_undoController;
+ MPackage *m_rootPackage = nullptr;
+ UndoController *m_undoController = nullptr;
QHash<Uid, MObject *> m_objectsMap;
QHash<Uid, MRelation *> m_relationsMap;
QMultiHash<Uid, MRelation *> m_objectRelationsMap;
- bool m_isResettingModel;
+ bool m_isResettingModel = false;
QString m_oldPackageName;
};
diff --git a/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.cpp b/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.cpp
index 67e93cf693..4e475ce3dd 100644
--- a/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.cpp
+++ b/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.cpp
@@ -35,6 +35,7 @@
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
+#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
@@ -102,6 +103,11 @@ void MVoidVisitor::visitMAssociation(MAssociation *association)
visitMRelation(association);
}
+void MVoidVisitor::visitMConnection(MConnection *connection)
+{
+ visitMRelation(connection);
+}
+
void MVoidConstVisitor::visitMElement(const MElement *element)
{
Q_UNUSED(element);
@@ -162,4 +168,9 @@ void MVoidConstVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
+void MVoidConstVisitor::visitMConnection(const MConnection *connection)
+{
+ visitMRelation(connection);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.h b/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.h
index 34404adbb2..ff65a861ca 100644
--- a/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.h
+++ b/src/libs/modelinglib/qmt/model_controller/mvoidvisitor.h
@@ -46,6 +46,7 @@ public:
void visitMDependency(MDependency *dependency) override;
void visitMInheritance(MInheritance *inheritance) override;
void visitMAssociation(MAssociation *association) override;
+ void visitMConnection(MConnection *connection) override;
};
class QMT_EXPORT MVoidConstVisitor : public MConstVisitor
@@ -63,6 +64,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
+ void visitMConnection(const MConnection *connection) override;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h b/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h
index fed3721768..afc3ec0ebf 100644
--- a/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h
+++ b/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h
@@ -39,7 +39,7 @@ class QMT_EXPORT SortedTreeModel : public QSortFilterProxyModel
Q_OBJECT
public:
- explicit SortedTreeModel(QObject *parent = 0);
+ explicit SortedTreeModel(QObject *parent = nullptr);
~SortedTreeModel() override;
TreeModel *treeModel() const { return m_treeModel; }
@@ -55,7 +55,7 @@ private:
void startDelayedSortTimer();
- TreeModel *m_treeModel;
+ TreeModel *m_treeModel = nullptr;
QTimer m_delayedSortTimer;
};
diff --git a/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.cpp b/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.cpp
index 738b0250b5..7f1493dcbc 100644
--- a/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.cpp
+++ b/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.cpp
@@ -51,7 +51,7 @@ QString StereotypesController::toString(const QList<QString> &stereotypes)
bool first = true;
foreach (const QString &stereotype, stereotypes) {
if (!first)
- s += QStringLiteral(", ");
+ s += ", ";
s += stereotype;
first = false;
}
diff --git a/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.h b/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.h
index e7034640df..5395adb6cd 100644
--- a/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.h
+++ b/src/libs/modelinglib/qmt/model_ui/stereotypescontroller.h
@@ -38,7 +38,7 @@ class QMT_EXPORT StereotypesController : public QObject
Q_OBJECT
public:
- explicit StereotypesController(QObject *parent = 0);
+ explicit StereotypesController(QObject *parent = nullptr);
signals:
void parseError(const QString &stereotypes);
diff --git a/src/libs/modelinglib/qmt/model_ui/treemodel.cpp b/src/libs/modelinglib/qmt/model_ui/treemodel.cpp
index cce2ee1720..bd0bf56bc1 100644
--- a/src/libs/modelinglib/qmt/model_ui/treemodel.cpp
+++ b/src/libs/modelinglib/qmt/model_ui/treemodel.cpp
@@ -36,6 +36,7 @@
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
+#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
@@ -86,7 +87,7 @@ public:
void visitMObject(const MObject *object)
{
Q_UNUSED(object);
- QMT_CHECK(m_item);
+ QMT_ASSERT(m_item, return);
m_item->setEditable(false);
}
@@ -94,7 +95,7 @@ public:
{
QMT_CHECK(!m_item);
- static QIcon icon(QStringLiteral(":/modelinglib/48x48/package.png"));
+ static QIcon icon(":/modelinglib/48x48/package.png");
m_item = new ModelItem(icon, m_treeModel->createObjectLabel(package));
m_item->setData(TreeModel::Package, TreeModel::RoleItemType);
visitMObject(package);
@@ -105,7 +106,7 @@ public:
QMT_CHECK(!m_item);
QIcon icon = m_treeModel->createIcon(StereotypeIcon::ElementClass, StyleEngine::TypeClass, klass->stereotypes(),
- QStringLiteral(":/modelinglib/48x48/class.png"));
+ ":/modelinglib/48x48/class.png");
m_item = new ModelItem(icon, m_treeModel->createObjectLabel(klass));
m_item->setData(TreeModel::Element, TreeModel::RoleItemType);
m_item->setStereotypes(klass->stereotypes());
@@ -118,7 +119,7 @@ public:
QIcon icon = m_treeModel->createIcon(StereotypeIcon::ElementComponent, StyleEngine::TypeComponent,
component->stereotypes(),
- QStringLiteral(":/modelinglib/48x48/component.png"));
+ ":/modelinglib/48x48/component.png");
m_item = new ModelItem(icon, m_treeModel->createObjectLabel(component));
m_item->setData(TreeModel::Element, TreeModel::RoleItemType);
m_item->setStereotypes(component->stereotypes());
@@ -135,7 +136,7 @@ public:
{
QMT_CHECK(!m_item);
- static QIcon icon(QStringLiteral(":/modelinglib/48x48/canvas-diagram.png"));
+ static QIcon icon(":/modelinglib/48x48/canvas-diagram.png");
m_item = new ModelItem(icon, m_treeModel->createObjectLabel(diagram));
visitMDiagram(diagram);
}
@@ -146,7 +147,7 @@ public:
QList<QString> stereotypes = item->stereotypes() << item->variety();
QIcon icon = m_treeModel->createIcon(StereotypeIcon::ElementItem, StyleEngine::TypeItem, stereotypes,
- QStringLiteral(":/modelinglib/48x48/item.png"));
+ ":/modelinglib/48x48/item.png");
m_item = new ModelItem(icon, m_treeModel->createObjectLabel(item));
m_item->setData(TreeModel::Element, TreeModel::RoleItemType);
m_item->setStereotypes(stereotypes);
@@ -156,7 +157,7 @@ public:
void visitMRelation(const MRelation *relation)
{
Q_UNUSED(relation);
- QMT_CHECK(m_item);
+ QMT_ASSERT(m_item, return);
m_item->setEditable(false);
m_item->setData(TreeModel::Relation, TreeModel::RoleItemType);
}
@@ -165,7 +166,7 @@ public:
{
QMT_CHECK(!m_item);
- static QIcon icon(QStringLiteral(":/modelinglib/48x48/dependency.png"));
+ static QIcon icon(":/modelinglib/48x48/dependency.png");
m_item = new ModelItem(icon, m_treeModel->createRelationLabel(dependency));
visitMRelation(dependency);
}
@@ -174,7 +175,7 @@ public:
{
QMT_CHECK(!m_item);
- static QIcon icon(QStringLiteral(":/modelinglib/48x48/inheritance.png"));
+ static QIcon icon(":/modelinglib/48x48/inheritance.png");
m_item = new ModelItem(icon, m_treeModel->createRelationLabel(inheritance));
visitMRelation(inheritance);
}
@@ -183,14 +184,23 @@ public:
{
QMT_CHECK(!m_item);
- static QIcon icon(QStringLiteral(":/modelinglib/48x48/association.png"));
+ static QIcon icon(":/modelinglib/48x48/association.png");
m_item = new ModelItem(icon, m_treeModel->createRelationLabel(association));
visitMRelation(association);
}
+ void visitMConnection(const MConnection *connection)
+ {
+ QMT_CHECK(!m_item);
+
+ static QIcon icon(":modelinglib/48x48/connection.ong");
+ m_item = new ModelItem(icon, m_treeModel->createRelationLabel(connection));
+ visitMRelation(connection);
+ }
+
private:
- TreeModel *m_treeModel = 0;
- TreeModel::ModelItem *m_item = 0;
+ TreeModel *m_treeModel = nullptr;
+ TreeModel::ModelItem *m_item = nullptr;
};
class TreeModel::ItemUpdater : public MConstVisitor
@@ -224,7 +234,7 @@ public:
{
if (klass->stereotypes() != m_item->stereotypes()) {
QIcon icon = m_treeModel->createIcon(StereotypeIcon::ElementClass, StyleEngine::TypeClass,
- klass->stereotypes(), QStringLiteral(":/modelinglib/48x48/class.png"));
+ klass->stereotypes(), ":/modelinglib/48x48/class.png");
m_item->setIcon(icon);
m_item->setStereotypes(klass->stereotypes());
}
@@ -236,7 +246,7 @@ public:
if (component->stereotypes() != m_item->stereotypes()) {
QIcon icon = m_treeModel->createIcon(StereotypeIcon::ElementComponent, StyleEngine::TypeComponent,
component->stereotypes(),
- QStringLiteral(":/modelinglib/48x48/component.png"));
+ ":/modelinglib/48x48/component.png");
m_item->setIcon(icon);
m_item->setStereotypes(component->stereotypes());
}
@@ -258,7 +268,7 @@ public:
QList<QString> stereotypes = item->stereotypes() << item->variety();
if (stereotypes != m_item->stereotypes()) {
QIcon icon = m_treeModel->createIcon(StereotypeIcon::ElementItem, StyleEngine::TypeItem, stereotypes,
- QStringLiteral(":/modelinglib/48x48/item.png"));
+ ":/modelinglib/48x48/item.png");
m_item->setIcon(icon);
m_item->setStereotypes(stereotypes);
}
@@ -285,12 +295,17 @@ public:
visitMRelation(association);
}
+ void visitMConnection(const MConnection *connection)
+ {
+ visitMRelation(connection);
+ }
+
private:
void updateObjectLabel(const MObject *object);
void updateRelationLabel(const MRelation *relation);
- TreeModel *m_treeModel = 0;
- TreeModel::ModelItem *m_item = 0;
+ TreeModel *m_treeModel = nullptr;
+ TreeModel::ModelItem *m_item = nullptr;
};
void TreeModel::ItemUpdater::updateObjectLabel(const MObject *object)
@@ -324,7 +339,7 @@ void TreeModel::setModelController(ModelController *modelController)
{
if (m_modelController != modelController) {
if (m_modelController)
- disconnect(m_modelController, 0, this, 0);
+ disconnect(m_modelController, nullptr, this, nullptr);
m_modelController = modelController;
if (m_modelController) {
connect(m_modelController, &ModelController::beginResetModel,
@@ -386,18 +401,18 @@ MElement *TreeModel::element(const QModelIndex &index) const
{
QMT_CHECK(index.isValid());
- MElement *element = 0;
+ MElement *element = nullptr;
QStandardItem *item = itemFromIndex(index);
if (item) {
if (item->parent()) {
auto parentModelItem = dynamic_cast<ModelItem *>(item->parent());
- QMT_CHECK(parentModelItem);
+ QMT_ASSERT(parentModelItem, return nullptr);
const MObject *parentObject = m_itemToObjectMap.value(parentModelItem);
- QMT_CHECK(parentObject);
+ QMT_ASSERT(parentObject, return nullptr);
if (parentObject) {
if (index.row() >= 0 && index.row() < parentObject->children().size()) {
element = parentObject->children().at(index.row());
- QMT_CHECK(element);
+ QMT_ASSERT(element, return nullptr);
} else if (index.row() >= parentObject->children().size()
&& index.row() < parentObject->children().size() + parentObject->relations().size()) {
element = parentObject->relations().at(index.row() - parentObject->children().size());
@@ -510,7 +525,7 @@ void TreeModel::onEndUpdateObject(int row, const MObject *parent)
auto object = dynamic_cast<MObject *>(element);
if (object) {
auto item = dynamic_cast<ModelItem *>(itemFromIndex(elementIndex));
- QMT_CHECK(item);
+ QMT_ASSERT(item, return);
ItemUpdater visitor(this, item);
element->accept(&visitor);
}
@@ -531,7 +546,7 @@ void TreeModel::onEndInsertObject(int row, const MObject *parent)
{
QMT_CHECK(m_busyState == InsertElement);
ModelItem *parentItem =m_objectToItemMap.value(parent);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
MObject *object = parent->children().at(row);
ModelItem *item = createItem(object);
parentItem->insertRow(row, item);
@@ -542,13 +557,13 @@ void TreeModel::onEndInsertObject(int row, const MObject *parent)
void TreeModel::onBeginRemoveObject(int row, const MObject *parent)
{
QMT_CHECK(m_busyState == NotBusy);
+ QMT_ASSERT(parent, return);
m_busyState = RemoveElement;
- QMT_CHECK(parent);
MObject *object = parent->children().at(row);
if (object)
removeObjectFromItemMap(object);
ModelItem *parentItem = m_objectToItemMap.value(parent);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
parentItem->removeRow(row);
}
@@ -563,13 +578,13 @@ void TreeModel::onEndRemoveObject(int row, const MObject *parent)
void TreeModel::onBeginMoveObject(int formerRow, const MObject *formerOwner)
{
QMT_CHECK(m_busyState == NotBusy);
+ QMT_ASSERT(formerOwner, return);
m_busyState = MoveElement;
- QMT_CHECK(formerOwner);
MObject *object = formerOwner->children().at(formerRow);
if (object)
removeObjectFromItemMap(object);
ModelItem *parentItem = m_objectToItemMap.value(formerOwner);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
parentItem->removeRow(formerRow);
}
@@ -577,7 +592,7 @@ void TreeModel::onEndMoveObject(int row, const MObject *owner)
{
QMT_CHECK(m_busyState == MoveElement);
ModelItem *parentItem =m_objectToItemMap.value(owner);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
MObject *object = owner->children().at(row);
ModelItem *item = createItem(object);
parentItem->insertRow(row, item);
@@ -595,12 +610,12 @@ void TreeModel::onBeginUpdateRelation(int row, const MObject *parent)
void TreeModel::onEndUpdateRelation(int row, const MObject *parent)
{
- QMT_CHECK(parent);
+ QMT_ASSERT(parent, return);
QMT_CHECK(m_busyState == UpdateRelation);
QMT_CHECK(m_objectToItemMap.contains(parent));
ModelItem *parentItem = m_objectToItemMap.value(parent);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
QModelIndex parentIndex = indexFromItem(parentItem);
// reflect updated relation in standard item
@@ -611,7 +626,7 @@ void TreeModel::onEndUpdateRelation(int row, const MObject *parent)
auto relation = dynamic_cast<MRelation *>(element);
if (relation) {
auto item = dynamic_cast<ModelItem *>(itemFromIndex(elementIndex));
- QMT_CHECK(item);
+ QMT_ASSERT(item, return);
ItemUpdater visitor(this, item);
element->accept(&visitor);
}
@@ -630,10 +645,10 @@ void TreeModel::onBeginInsertRelation(int row, const MObject *parent)
void TreeModel::onEndInsertRelation(int row, const MObject *parent)
{
- QMT_CHECK(parent);
+ QMT_ASSERT(parent, return);
QMT_CHECK(m_busyState == InsertRelation);
ModelItem *parentItem =m_objectToItemMap.value(parent);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
MRelation *relation = parent->relations().at(row);
ModelItem *item = createItem(relation);
parentItem->insertRow(parent->children().size() + row, item);
@@ -642,12 +657,12 @@ void TreeModel::onEndInsertRelation(int row, const MObject *parent)
void TreeModel::onBeginRemoveRelation(int row, const MObject *parent)
{
- QMT_CHECK(parent);
+ QMT_ASSERT(parent, return);
QMT_CHECK(m_busyState == NotBusy);
m_busyState = RemoveRelation;
QMT_CHECK(parent->relations().at(row));
ModelItem *parentItem = m_objectToItemMap.value(parent);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
parentItem->removeRow(parent->children().size() + row);
}
@@ -662,20 +677,20 @@ void TreeModel::onEndRemoveRelation(int row, const MObject *parent)
void TreeModel::onBeginMoveRelation(int formerRow, const MObject *formerOwner)
{
QMT_CHECK(m_busyState == NotBusy);
+ QMT_ASSERT(formerOwner, return);
m_busyState = MoveElement;
- QMT_CHECK(formerOwner);
QMT_CHECK(formerOwner->relations().at(formerRow));
ModelItem *parentItem = m_objectToItemMap.value(formerOwner);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
parentItem->removeRow(formerOwner->children().size() + formerRow);
}
void TreeModel::onEndMoveRelation(int row, const MObject *owner)
{
- QMT_CHECK(owner);
+ QMT_ASSERT(owner, return);
QMT_CHECK(m_busyState == MoveElement);
ModelItem *parentItem =m_objectToItemMap.value(owner);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
MRelation *relation = owner->relations().at(row);
ModelItem *item = createItem(relation);
parentItem->insertRow(owner->children().size() + row, item);
@@ -688,10 +703,10 @@ void TreeModel::onRelationEndChanged(MRelation *relation, MObject *endObject)
QMT_CHECK(m_busyState == NotBusy);
MObject *parent = relation->owner();
- QMT_CHECK(parent);
+ QMT_ASSERT(parent, return);
QMT_CHECK(m_objectToItemMap.contains(parent));
ModelItem *parentItem = m_objectToItemMap.value(parent);
- QMT_CHECK(parentItem);
+ QMT_ASSERT(parentItem, return);
QModelIndex parentIndex = indexFromItem(parentItem);
int row = parent->children().size() + relation->owner()->relations().indexOf(relation);
@@ -699,7 +714,7 @@ void TreeModel::onRelationEndChanged(MRelation *relation, MObject *endObject)
QMT_CHECK(elementIndex.isValid());
auto item = dynamic_cast<ModelItem *>(itemFromIndex(elementIndex));
- QMT_CHECK(item);
+ QMT_ASSERT(item, return);
QString label = createRelationLabel(relation);
if (item->text() != label)
@@ -721,7 +736,7 @@ void TreeModel::onModelDataChanged(const QModelIndex &topleft, const QModelIndex
void TreeModel::clear()
{
QStandardItemModel::clear();
- m_rootItem = 0;
+ m_rootItem = nullptr;
m_objectToItemMap.clear();
m_itemToObjectMap.clear();
}
@@ -758,10 +773,10 @@ void TreeModel::createChildren(const MObject *parentObject, ModelItem *parentIte
void TreeModel::removeObjectFromItemMap(const MObject *object)
{
- QMT_CHECK(object);
+ QMT_ASSERT(object, return);
QMT_CHECK(m_objectToItemMap.contains(object));
ModelItem *item = m_objectToItemMap.value(object);
- QMT_CHECK(item);
+ QMT_ASSERT(item, return);
QMT_CHECK(m_itemToObjectMap.contains(item));
m_itemToObjectMap.remove(item);
m_objectToItemMap.remove(object);
@@ -773,19 +788,19 @@ void TreeModel::removeObjectFromItemMap(const MObject *object)
QString TreeModel::createObjectLabel(const MObject *object)
{
- QMT_CHECK(object);
+ QMT_ASSERT(object, return QString());
if (object->name().isEmpty()) {
if (auto item = dynamic_cast<const MItem *>(object)) {
if (!item->variety().isEmpty())
- return QString(QStringLiteral("[%1]")).arg(item->variety());
+ return QString("[%1]").arg(item->variety());
}
return tr("[unnamed]");
}
if (auto klass = dynamic_cast<const MClass *>(object)) {
if (!klass->umlNamespace().isEmpty())
- return QString(QStringLiteral("%1 [%2]")).arg(klass->name()).arg(klass->umlNamespace());
+ return QString("%1 [%2]").arg(klass->name()).arg(klass->umlNamespace());
}
return object->name();
}
@@ -795,11 +810,11 @@ QString TreeModel::createRelationLabel(const MRelation *relation)
QString name;
if (!relation->name().isEmpty()) {
name += relation->name();
- name += QStringLiteral(": ");
+ name += ": ";
}
if (MObject *endA = m_modelController->findObject(relation->endAUid()))
name += createObjectLabel(endA);
- name += QStringLiteral(" - ");
+ name += " - ";
if (MObject *endB = m_modelController->findObject(relation->endBUid()))
name += createObjectLabel(endB);
return name;
diff --git a/src/libs/modelinglib/qmt/model_ui/treemodel.h b/src/libs/modelinglib/qmt/model_ui/treemodel.h
index f3d8e16779..7e9bb0a4fc 100644
--- a/src/libs/modelinglib/qmt/model_ui/treemodel.h
+++ b/src/libs/modelinglib/qmt/model_ui/treemodel.h
@@ -68,7 +68,7 @@ public:
RoleItemType = Qt::UserRole + 1
};
- explicit TreeModel(QObject *parent = 0);
+ explicit TreeModel(QObject *parent = nullptr);
~TreeModel() override;
ModelController *modelController() const { return m_modelController; }
diff --git a/src/libs/modelinglib/qmt/model_ui/treemodelmanager.cpp b/src/libs/modelinglib/qmt/model_ui/treemodelmanager.cpp
index a90fd546fd..5a2711b14c 100644
--- a/src/libs/modelinglib/qmt/model_ui/treemodelmanager.cpp
+++ b/src/libs/modelinglib/qmt/model_ui/treemodelmanager.cpp
@@ -38,9 +38,7 @@
namespace qmt {
TreeModelManager::TreeModelManager(QObject *parent) :
- QObject(parent),
- m_treeModel(nullptr),
- m_modelTreeView(nullptr)
+ QObject(parent)
{
}
@@ -70,7 +68,7 @@ bool TreeModelManager::isRootPackageSelected() const
MObject *TreeModelManager::selectedObject() const
{
- MObject *object = 0;
+ MObject *object = nullptr;
if (m_modelTreeView->currentSourceModelIndex().isValid()) {
MElement *element = m_treeModel->element(m_modelTreeView->currentSourceModelIndex());
if (element)
@@ -84,7 +82,7 @@ MPackage *TreeModelManager::selectedPackage() const
if (m_modelTreeView->currentSourceModelIndex().isValid())
{
MElement *element = m_treeModel->element(m_modelTreeView->currentSourceModelIndex());
- QMT_CHECK(element);
+ QMT_ASSERT(element, return nullptr);
if (auto package = dynamic_cast<MPackage *>(element)) {
return package;
} else if (auto object = dynamic_cast<MObject *>(element)) {
diff --git a/src/libs/modelinglib/qmt/model_ui/treemodelmanager.h b/src/libs/modelinglib/qmt/model_ui/treemodelmanager.h
index dfb604cd98..ea5156c117 100644
--- a/src/libs/modelinglib/qmt/model_ui/treemodelmanager.h
+++ b/src/libs/modelinglib/qmt/model_ui/treemodelmanager.h
@@ -41,7 +41,7 @@ class QMT_EXPORT TreeModelManager : public QObject
Q_OBJECT
public:
- explicit TreeModelManager(QObject *parent = 0);
+ explicit TreeModelManager(QObject *parent = nullptr);
~TreeModelManager() override;
TreeModel *treeModel() const { return m_treeModel; }
@@ -55,8 +55,8 @@ public:
MSelection selectedObjects() const;
private:
- TreeModel *m_treeModel;
- ModelTreeViewInterface *m_modelTreeView;
+ TreeModel *m_treeModel = nullptr;
+ ModelTreeViewInterface *m_modelTreeView = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.cpp
index bc9b770f56..68b63e3ac9 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.cpp
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.cpp
@@ -94,10 +94,10 @@ QString ClassMembersEdit::Cursor::readWord()
} else {
if (c == QLatin1Char('<') && m_pos < m_text.length() && m_text.at(m_pos) == QLatin1Char('<')) {
++m_pos;
- word = QStringLiteral("<<");
+ word = "<<";
} else if (c == QLatin1Char('>') && m_pos < m_text.length() && m_text.at(m_pos) == QLatin1Char('>')) {
++m_pos;
- word = QStringLiteral(">>");
+ word = ">>";
} else {
word = c;
}
@@ -123,7 +123,7 @@ QString ClassMembersEdit::Cursor::readUntil(const QString &delimiter)
{
QString s;
while (m_isValid) {
- if (m_pos >= m_text.length() || m_text.at(m_pos) == QStringLiteral("\n")) {
+ if (m_pos >= m_text.length() || m_text.at(m_pos) == '\n') {
m_isValid = false;
return s;
}
@@ -154,7 +154,7 @@ void ClassMembersEdit::Cursor::skipUntilOrNewline(const QString &delimiter)
while (m_isValid) {
if (m_pos >= m_text.length())
return;
- if (m_text.at(m_pos) == QStringLiteral("\n"))
+ if (m_text.at(m_pos) == '\n')
return;
if (m_pos + delimiter.length() <= m_text.length()
&& QString::compare(m_text.mid(m_pos, delimiter.length()), delimiter, Qt::CaseInsensitive) == 0) {
@@ -183,10 +183,10 @@ QString ClassMembersEdit::Cursor::readWordFromRight()
} else {
if (c == QLatin1Char('<') && m_pos >= 0 && m_text.at(m_pos) == QLatin1Char('<')) {
--m_pos;
- word = QStringLiteral("<<");
+ word = "<<";
} else if (c == QLatin1Char('>') && m_pos >= 0 && m_text.at(m_pos) == QLatin1Char('>')) {
--m_pos;
- word = QStringLiteral(">>");
+ word = ">>";
} else {
word = c;
}
@@ -218,13 +218,13 @@ bool ClassMembersEdit::Cursor::searchOutsideOfBracketsFromRight(const QString &s
int brackets = 0;
for (;;) {
const QString word = readWordFromRight();
- if (!m_isValid || word == QStringLiteral("\n"))
+ if (!m_isValid || word == "\n")
break;
if (brackets == 0 && word == s)
return true;
- else if (word == QStringLiteral("(") || word == QStringLiteral("[") || word == QStringLiteral("{"))
+ else if (word == "(" || word == "[" || word == "{")
++brackets;
- else if (word == QStringLiteral(")") || word == QStringLiteral("]") || word == QStringLiteral("}"))
+ else if (word == ")" || word == "]" || word == "}")
--brackets;
}
m_isValid = true;
@@ -238,12 +238,12 @@ QString ClassMembersEdit::Cursor::extractSubstr(int start, int stop)
if (m_isValid && start >= 0 && start < m_text.length() && stop >= start && stop < m_text.length())
return m_text.mid(start, stop - start + 1);
m_isValid = false;
- return QStringLiteral("");
+ return QString();
}
void ClassMembersEdit::Cursor::skipWhitespaces()
{
- while (m_isValid && m_pos < m_text.length() && m_text.at(m_pos).isSpace() && m_text.at(m_pos) != QStringLiteral("\n"))
+ while (m_isValid && m_pos < m_text.length() && m_text.at(m_pos).isSpace() && m_text.at(m_pos) != '\n')
++m_pos;
if (m_pos >= m_text.length())
m_isValid = false;
@@ -251,7 +251,7 @@ void ClassMembersEdit::Cursor::skipWhitespaces()
void ClassMembersEdit::Cursor::skipWhitespacesFromRight()
{
- while (m_isValid && m_pos >= 0 && m_text.at(m_pos).isSpace() && m_text.at(m_pos) != QStringLiteral("\n"))
+ while (m_isValid && m_pos >= 0 && m_text.at(m_pos).isSpace() && m_text.at(m_pos) != '\n')
--m_pos;
if (m_pos < 0)
m_isValid = false;
@@ -378,29 +378,29 @@ QString ClassMembersEdit::build(const QList<MClassMember> &members)
case MClassMember::VisibilityUndefined:
break;
case MClassMember::VisibilityPublic:
- vis = QStringLiteral("public:");
+ vis = "public:";
break;
case MClassMember::VisibilityProtected:
- vis = QStringLiteral("protected:");
+ vis = "protected:";
break;
case MClassMember::VisibilityPrivate:
- vis = QStringLiteral("private:");
+ vis = "private:";
break;
case MClassMember::VisibilitySignals:
- vis = QStringLiteral("signals:");
+ vis = "signals:";
break;
case MClassMember::VisibilityPrivateSlots:
- vis = QStringLiteral("private slots:");
+ vis = "private slots:";
break;
case MClassMember::VisibilityProtectedSlots:
- vis = QStringLiteral("protected slots:");
+ vis = "protected slots:";
break;
case MClassMember::VisibilityPublicSlots:
- vis = QStringLiteral("public slots:");
+ vis = "public slots:";
break;
}
if (!text.isEmpty())
- text += QStringLiteral("\n");
+ text += "\n";
text += vis;
addNewline = true;
addSpace = true;
@@ -409,42 +409,42 @@ QString ClassMembersEdit::build(const QList<MClassMember> &members)
}
if (member.group() != currentGroup) {
if (addSpace)
- text += QStringLiteral(" ");
+ text += " ";
else if (!text.isEmpty())
- text += QStringLiteral("\n");
- text += QString(QStringLiteral("[%1]")).arg(member.group());
+ text += "\n";
+ text += QString("[%1]").arg(member.group());
addNewline = true;
currentGroup = member.group();
}
if (addNewline)
- text += QStringLiteral("\n");
+ text += "\n";
if (!member.stereotypes().isEmpty()) {
StereotypesController ctrl;
- text += QString(QStringLiteral("<<%1>> ")).arg(ctrl.toString(member.stereotypes()));
+ text += QString("<<%1>> ").arg(ctrl.toString(member.stereotypes()));
}
if (member.properties() & MClassMember::PropertyQsignal)
- text += QStringLiteral("signal ");
+ text += "signal ";
if (member.properties() & MClassMember::PropertyQslot)
- text += QStringLiteral("slot ");
+ text += "slot ";
if (member.properties() & MClassMember::PropertyQinvokable)
- text += QStringLiteral("invokable ");
+ text += "invokable ";
if (member.properties() & MClassMember::PropertyStatic)
- text += QStringLiteral("static ");
+ text += "static ";
if (member.properties() & MClassMember::PropertyVirtual)
- text += QStringLiteral("virtual ");
+ text += "virtual ";
if (member.properties() & MClassMember::PropertyConstexpr)
- text += QStringLiteral("constexpr ");
+ text += "constexpr ";
text += member.declaration();
if (member.properties() & MClassMember::PropertyConst)
- text += QStringLiteral(" const");
+ text += " const";
if (member.properties() & MClassMember::PropertyOverride)
- text += QStringLiteral(" override");
+ text += " override";
if (member.properties() & MClassMember::PropertyFinal)
- text += QStringLiteral(" final");
+ text += " final";
if (member.properties() & MClassMember::PropertyAbstract)
- text += QStringLiteral(" = 0");
- text += QStringLiteral(";\n");
+ text += " = 0";
+ text += ";\n";
}
return text;
@@ -452,7 +452,7 @@ QString ClassMembersEdit::build(const QList<MClassMember> &members)
QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
{
- QMT_CHECK(ok);
+ QMT_ASSERT(ok, return QList<MClassMember>());
*ok = true;
QList<MClassMember> members;
@@ -468,19 +468,19 @@ QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
member = MClassMember();
QString word = cursor.readWord().toLower();
for (;;) {
- if (word == QStringLiteral("public")) {
+ if (word == "public") {
currentVisibility = MClassMember::VisibilityPublic;
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("protected")) {
+ } else if (word == "protected") {
currentVisibility = MClassMember::VisibilityProtected;
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("private")) {
+ } else if (word == "private") {
currentVisibility = MClassMember::VisibilityPrivate;
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("signals")) {
+ } else if (word == "signals") {
currentVisibility = MClassMember::VisibilitySignals;
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("slots")) {
+ } else if (word == "slots") {
switch (currentVisibility) {
case MClassMember::VisibilityPrivate:
currentVisibility = MClassMember::VisibilityPrivateSlots;
@@ -496,34 +496,34 @@ QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
break;
}
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("[")) {
- currentGroup = cursor.readUntil(QStringLiteral("]"));
+ } else if (word == "[") {
+ currentGroup = cursor.readUntil("]");
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("<<")) {
- QString stereotypes = cursor.readUntil(QStringLiteral(">>"));
+ } else if (word == "<<") {
+ QString stereotypes = cursor.readUntil(">>");
StereotypesController ctrl;
member.setStereotypes(ctrl.fromString(stereotypes));
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("static")) {
+ } else if (word == "static") {
member.setProperties(member.properties() | MClassMember::PropertyStatic);
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("virtual")) {
+ } else if (word == "virtual") {
member.setProperties(member.properties() | MClassMember::PropertyVirtual);
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("constexpr") || word == QStringLiteral("q_decl_constexpr")
- || word == QStringLiteral("q_decl_relaxed_constexpr")) {
+ } else if (word == "constexpr" || word == "q_decl_constexpr"
+ || word == "q_decl_relaxed_constexpr") {
member.setProperties(member.properties() | MClassMember::PropertyConstexpr);
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("signal") || word == QStringLiteral("q_signal")) {
+ } else if (word == "signal" || word == "q_signal") {
member.setProperties(member.properties() | MClassMember::PropertyQsignal);
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("slot") || word == QStringLiteral("q_slot")) {
+ } else if (word == "slot" || word == "q_slot") {
member.setProperties(member.properties() | MClassMember::PropertyQslot);
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral("invokable") || word == QStringLiteral("q_invokable")) {
+ } else if (word == "invokable" || word == "q_invokable") {
member.setProperties(member.properties() | MClassMember::PropertyQinvokable);
word = cursor.readWord().toLower();
- } else if (word == QStringLiteral(":")) {
+ } else if (word == ":") {
word = cursor.readWord().toLower();
} else {
cursor.unreadWord();
@@ -532,32 +532,32 @@ QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
}
member.setVisibility(currentVisibility);
member.setGroup(currentGroup);
- if (word != QStringLiteral("\n")) {
+ if (word != "\n") {
int declarationStart = cursor.position();
- cursor.skipUntilOrNewline(QStringLiteral(";"));
+ cursor.skipUntilOrNewline(";");
int nextLinePosition = cursor.position();
cursor.setPosition(nextLinePosition - 1);
word = cursor.readWordFromRight().toLower();
- if (word != QStringLiteral(";"))
+ if (word != ";")
cursor.unreadWord();
int endPosition = cursor.position();
QString expr;
- if (cursor.searchOutsideOfBracketsFromRight(QStringLiteral("=")))
+ if (cursor.searchOutsideOfBracketsFromRight("="))
expr = cursor.extractSubstr(cursor.position() + 2, endPosition).trimmed();
word = cursor.readWordFromRight().toLower();
for (;;) {
// TODO ignore throw(), noexpect(*),
- if (word == QStringLiteral("final") || word == QStringLiteral("q_decl_final")) {
+ if (word == "final" || word == "q_decl_final") {
member.setProperties(member.properties() | MClassMember::PropertyFinal);
word = cursor.readWordFromRight().toLower();
- } else if (word == QStringLiteral("override") || word == QStringLiteral("q_decl_override")) {
+ } else if (word == "override" || word == "q_decl_override") {
member.setProperties(member.properties() | MClassMember::PropertyOverride);
word = cursor.readWordFromRight().toLower();
- } else if (word == QStringLiteral("const")) {
+ } else if (word == "const") {
member.setProperties(member.properties() | MClassMember::PropertyConst);
word = cursor.readWordFromRight().toLower();
- } else if (word == QStringLiteral("noexpect")) {
+ } else if (word == "noexpect") {
// just ignore it
word = cursor.readWordFromRight().toLower();
} else {
@@ -572,9 +572,9 @@ QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
if (!declaration.isEmpty()) {
member.setDeclaration(declaration);
// TODO recognize function pointer
- if (declaration.endsWith(QStringLiteral(")"))) {
+ if (declaration.endsWith(")")) {
member.setMemberType(MClassMember::MemberMethod);
- if (expr == QStringLiteral("0"))
+ if (expr == "0")
member.setProperties(member.properties() | MClassMember::PropertyAbstract);
} else {
member.setMemberType(MClassMember::MemberAttribute);
@@ -584,7 +584,7 @@ QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
cursor.setPosition(nextLinePosition);
if (cursor.atEnd())
return members;
- cursor.skip(QStringLiteral("\n"));
+ cursor.skip("\n");
} else {
word = cursor.readWord().toLower();
}
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.h b/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.h
index ca23702742..f20acd9601 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.h
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/classmembersedit.h
@@ -39,7 +39,7 @@ class QMT_EXPORT ClassMembersEdit : public QPlainTextEdit
class ClassMembersEditPrivate;
public:
- explicit ClassMembersEdit(QWidget *parent = 0);
+ explicit ClassMembersEdit(QWidget *parent = nullptr);
~ClassMembersEdit() override;
signals:
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp
index f392a59e60..37e74adeac 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp
@@ -48,9 +48,7 @@
namespace qmt {
ModelTreeView::ModelTreeView(QWidget *parent)
- : QTreeView(parent),
- m_sortedTreeModel(nullptr),
- m_elementTasks(nullptr)
+ : QTreeView(parent)
{
setHeaderHidden(true);
setSortingEnabled(false);
@@ -113,7 +111,7 @@ void ModelTreeView::startDrag(Qt::DropActions supportedActions)
Q_UNUSED(supportedActions);
TreeModel *treeModel = m_sortedTreeModel->treeModel();
- QMT_CHECK(treeModel);
+ QMT_ASSERT(treeModel, return);
QByteArray dragData;
QDataStream dataStream(&dragData, QIODevice::WriteOnly);
@@ -140,10 +138,10 @@ void ModelTreeView::startDrag(Qt::DropActions supportedActions)
}
auto mimeData = new QMimeData;
- mimeData->setData(QStringLiteral("text/model-elements"), dragData);
+ mimeData->setData("text/model-elements", dragData);
if (dragIcon.isNull())
- dragIcon = QIcon(QStringLiteral(":/modelinglib/48x48/generic.png"));
+ dragIcon = QIcon(":/modelinglib/48x48/generic.png");
QPixmap pixmap(48, 48);
pixmap = dragIcon.pixmap(48, 48);
@@ -170,7 +168,7 @@ void ModelTreeView::dragMoveEvent(QDragMoveEvent *event)
QModelIndex dropSourceModelIndex = m_sortedTreeModel->mapToSource(dropIndex);
if (dropSourceModelIndex.isValid()) {
TreeModel *treeModel = m_sortedTreeModel->treeModel();
- QMT_CHECK(treeModel);
+ QMT_ASSERT(treeModel, return);
MElement *modelElement = treeModel->element(dropSourceModelIndex);
if (dynamic_cast<MObject*>(modelElement))
accept = true;
@@ -197,15 +195,15 @@ void ModelTreeView::dropEvent(QDropEvent *event)
{
bool accept = false;
event->setDropAction(Qt::MoveAction);
- if (event->mimeData()->hasFormat(QStringLiteral("text/model-elements"))) {
+ if (event->mimeData()->hasFormat("text/model-elements")) {
QModelIndex dropIndex = indexAt(event->pos());
QModelIndex dropSourceModelIndex = m_sortedTreeModel->mapToSource(dropIndex);
if (dropSourceModelIndex.isValid()) {
TreeModel *treeModel = m_sortedTreeModel->treeModel();
- QMT_CHECK(treeModel);
+ QMT_ASSERT(treeModel, return);
MElement *targetModelElement = treeModel->element(dropSourceModelIndex);
if (auto targetModelObject = dynamic_cast<MObject *>(targetModelElement)) {
- QDataStream dataStream(event->mimeData()->data(QStringLiteral("text/model-elements")));
+ QDataStream dataStream(event->mimeData()->data("text/model-elements"));
while (dataStream.status() == QDataStream::Ok) {
QString key;
dataStream >> key;
@@ -245,35 +243,35 @@ void ModelTreeView::contextMenuEvent(QContextMenuEvent *event)
QModelIndex sourceModelIndex = m_sortedTreeModel->mapToSource(index);
if (sourceModelIndex.isValid()) {
TreeModel *treeModel = m_sortedTreeModel->treeModel();
- QMT_CHECK(treeModel);
+ QMT_ASSERT(treeModel, return);
MElement *melement = treeModel->element(sourceModelIndex);
- QMT_CHECK(melement);
+ QMT_ASSERT(melement, return);
QMenu menu;
bool addSeparator = false;
if (m_elementTasks->hasClassDefinition(melement)) {
- menu.addAction(new ContextMenuAction(tr("Show Definition"), QStringLiteral("showDefinition"), &menu));
+ menu.addAction(new ContextMenuAction(tr("Show Definition"), "showDefinition", &menu));
addSeparator = true;
}
if (m_elementTasks->hasDiagram(melement)) {
- menu.addAction(new ContextMenuAction(tr("Open Diagram"), QStringLiteral("openDiagram"), &menu));
+ menu.addAction(new ContextMenuAction(tr("Open Diagram"), "openDiagram", &menu));
addSeparator = true;
}
if (melement->owner()) {
if (addSeparator)
menu.addSeparator();
- menu.addAction(new ContextMenuAction(tr("Delete"), QStringLiteral("delete"),
+ menu.addAction(new ContextMenuAction(tr("Delete"), "delete",
QKeySequence(Qt::CTRL + Qt::Key_D), &menu));
}
QAction *selectedAction = menu.exec(event->globalPos());
if (selectedAction) {
auto action = dynamic_cast<ContextMenuAction *>(selectedAction);
- QMT_CHECK(action);
- if (action->id() == QStringLiteral("showDefinition")) {
+ QMT_ASSERT(action, return);
+ if (action->id() == "showDefinition") {
m_elementTasks->openClassDefinition(melement);
- } else if (action->id() == QStringLiteral("openDiagram")) {
+ } else if (action->id() == "openDiagram") {
m_elementTasks->openDiagram(melement);
- } else if (action->id() == QStringLiteral("delete")) {
+ } else if (action->id() == "delete") {
MSelection selection;
selection.append(melement->uid(), melement->owner()->uid());
m_sortedTreeModel->treeModel()->modelController()->deleteElements(selection);
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h
index bb910bd635..724097a365 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h
@@ -41,7 +41,7 @@ class QMT_EXPORT ModelTreeView : public QTreeView, public ModelTreeViewInterface
Q_OBJECT
public:
- explicit ModelTreeView(QWidget *parent = 0);
+ explicit ModelTreeView(QWidget *parent = nullptr);
~ModelTreeView() override;
signals:
@@ -67,8 +67,8 @@ protected:
void contextMenuEvent(QContextMenuEvent *event) override;
private:
- SortedTreeModel *m_sortedTreeModel;
- IElementTasks *m_elementTasks;
+ SortedTreeModel *m_sortedTreeModel = nullptr;
+ IElementTasks *m_elementTasks = nullptr;
QModelIndex m_autoDelayIndex;
QTime m_autoDelayStartTime;
};
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.cpp
index 8e48202009..2f5f8d8487 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.cpp
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.cpp
@@ -35,8 +35,7 @@ namespace qmt {
PaletteBox::PaletteBox(QWidget *parent)
: QWidget(parent),
m_brushes(6),
- m_pens(6),
- m_currentIndex(-1)
+ m_pens(6)
{
setFocusPolicy(Qt::StrongFocus);
}
@@ -47,13 +46,13 @@ PaletteBox::~PaletteBox()
QBrush PaletteBox::brush(int index) const
{
- QMT_CHECK(index >= 0 && index <= m_brushes.size());
+ QMT_ASSERT(index >= 0 && index <= m_brushes.size(), return QBrush());
return m_brushes.at(index);
}
void PaletteBox::setBrush(int index, const QBrush &brush)
{
- QMT_CHECK(index >= 0 && index <= m_brushes.size());
+ QMT_ASSERT(index >= 0 && index <= m_brushes.size(), return);
if (m_brushes[index] != brush) {
m_brushes[index] = brush;
update();
@@ -62,13 +61,13 @@ void PaletteBox::setBrush(int index, const QBrush &brush)
QPen PaletteBox::linePen(int index) const
{
- QMT_CHECK(index >= 0 && index <= m_pens.size());
+ QMT_ASSERT(index >= 0 && index <= m_pens.size(), return QPen());
return m_pens.at(index);
}
void PaletteBox::setLinePen(int index, const QPen &pen)
{
- QMT_CHECK(index >= 0 && index <= m_pens.size());
+ QMT_ASSERT(index >= 0 && index <= m_pens.size(), return);
if (m_pens[index] != pen) {
m_pens[index] = pen;
update();
@@ -125,7 +124,7 @@ void PaletteBox::mousePressEvent(QMouseEvent *event)
qreal w = static_cast<qreal>(width()) / static_cast<qreal>(m_brushes.size());
int i = static_cast<int>((event->x() / w));
- QMT_CHECK(i >= 0 && i < m_brushes.size());
+ QMT_ASSERT(i >= 0 && i < m_brushes.size(), return);
setCurrentIndex(i);
if (m_currentIndex >= 0 && m_currentIndex < m_brushes.size())
emit activated(m_currentIndex);
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.h b/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.h
index 501b7ea758..76499c9019 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.h
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/palettebox.h
@@ -38,7 +38,7 @@ class QMT_EXPORT PaletteBox : public QWidget
Q_OBJECT
public:
- explicit PaletteBox(QWidget *parent = 0);
+ explicit PaletteBox(QWidget *parent = nullptr);
~PaletteBox() override;
signals:
@@ -62,7 +62,7 @@ protected:
private:
QVector<QBrush> m_brushes;
QVector<QPen> m_pens;
- int m_currentIndex;
+ int m_currentIndex = -1;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.cpp
index 0c59fe20c1..350803d168 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.cpp
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.cpp
@@ -39,13 +39,7 @@ namespace qmt {
PropertiesView::PropertiesView(QObject *parent)
: QObject(parent),
- m_modelController(0),
- m_diagramController(0),
- m_stereotypeController(0),
- m_styleController(0),
- m_viewFactory([=](PropertiesView *propertiesView) { return new MView(propertiesView); }),
- m_selectedDiagram(0),
- m_widget(0)
+ m_viewFactory([=](PropertiesView *propertiesView) { return new MView(propertiesView); })
{
}
@@ -57,7 +51,7 @@ void PropertiesView::setModelController(ModelController *modelController)
{
if (m_modelController != modelController) {
if (m_modelController)
- disconnect(m_modelController, 0, this, 0);
+ disconnect(m_modelController, nullptr, this, nullptr);
m_modelController = modelController;
if (m_modelController) {
connect(m_modelController, &ModelController::beginResetModel,
@@ -109,8 +103,8 @@ void PropertiesView::setDiagramController(DiagramController *diagramController)
{
if (m_diagramController != diagramController) {
if (m_diagramController) {
- disconnect(m_diagramController, 0, this, 0);
- m_diagramController = 0;
+ disconnect(m_diagramController, nullptr, this, nullptr);
+ m_diagramController = nullptr;
}
m_diagramController = diagramController;
if (diagramController) {
@@ -162,7 +156,7 @@ void PropertiesView::setSelectedModelElements(const QList<MElement *> &modelElem
if (m_selectedModelElements != modelElements) {
m_selectedModelElements = modelElements;
m_selectedDiagramElements.clear();
- m_selectedDiagram = 0;
+ m_selectedDiagram = nullptr;
m_mview.reset(m_viewFactory(this));
m_mview->update(m_selectedModelElements);
m_widget = m_mview->topLevelWidget();
@@ -172,7 +166,7 @@ void PropertiesView::setSelectedModelElements(const QList<MElement *> &modelElem
void PropertiesView::setSelectedDiagramElements(const QList<DElement *> &diagramElements, MDiagram *diagram)
{
QMT_CHECK(diagramElements.size() > 0);
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagram, return);
if (m_selectedDiagramElements != diagramElements || m_selectedDiagram != diagram) {
m_selectedDiagramElements = diagramElements;
@@ -188,9 +182,9 @@ void PropertiesView::clearSelection()
{
m_selectedModelElements.clear();
m_selectedDiagramElements.clear();
- m_selectedDiagram = 0;
+ m_selectedDiagram = nullptr;
m_mview.reset();
- m_widget = 0;
+ m_widget = nullptr;
}
QWidget *PropertiesView::widget() const
@@ -386,7 +380,7 @@ void PropertiesView::onEndRemoveElement(int row, const MDiagram *diagram)
void PropertiesView::beginUpdate(MElement *modelElement)
{
- QMT_CHECK(modelElement);
+ QMT_ASSERT(modelElement, return);
if (auto object = dynamic_cast<MObject *>(modelElement)) {
m_modelController->startUpdateObject(object);
@@ -399,7 +393,7 @@ void PropertiesView::beginUpdate(MElement *modelElement)
void PropertiesView::endUpdate(MElement *modelElement, bool cancelled)
{
- QMT_CHECK(modelElement);
+ QMT_ASSERT(modelElement, return);
if (auto object = dynamic_cast<MObject *>(modelElement)) {
m_modelController->finishUpdateObject(object, cancelled);
@@ -412,18 +406,18 @@ void PropertiesView::endUpdate(MElement *modelElement, bool cancelled)
void PropertiesView::beginUpdate(DElement *diagramElement)
{
- QMT_CHECK(diagramElement);
- QMT_CHECK(m_selectedDiagram != 0);
- QMT_CHECK(m_diagramController->findElement(diagramElement->uid(), m_selectedDiagram) == diagramElement);
+ QMT_ASSERT(diagramElement, return);
+ QMT_ASSERT(m_selectedDiagram, return);
+ QMT_ASSERT(m_diagramController->findElement(diagramElement->uid(), m_selectedDiagram) == diagramElement, return);
m_diagramController->startUpdateElement(diagramElement, m_selectedDiagram, DiagramController::UpdateMinor);
}
void PropertiesView::endUpdate(DElement *diagramElement, bool cancelled)
{
- QMT_CHECK(diagramElement);
- QMT_CHECK(m_selectedDiagram != 0);
- QMT_CHECK(m_diagramController->findElement(diagramElement->uid(), m_selectedDiagram) == diagramElement);
+ QMT_ASSERT(diagramElement, return);
+ QMT_ASSERT(m_selectedDiagram, return);
+ QMT_ASSERT(m_diagramController->findElement(diagramElement->uid(), m_selectedDiagram) == diagramElement, return);
m_diagramController->finishUpdateElement(diagramElement, m_selectedDiagram, cancelled);
}
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.h b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.h
index 39c1f817a1..78273ed01b 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.h
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesview.h
@@ -55,7 +55,7 @@ class QMT_EXPORT PropertiesView : public QObject
public:
class MView;
- explicit PropertiesView(QObject *parent = 0);
+ explicit PropertiesView(QObject *parent = nullptr);
~PropertiesView() override;
ModelController *modelController() const { return m_modelController; }
@@ -116,16 +116,16 @@ private:
void beginUpdate(DElement *diagramElement);
void endUpdate(DElement *diagramElement, bool cancelled);
- ModelController *m_modelController;
- DiagramController *m_diagramController;
- StereotypeController *m_stereotypeController;
- StyleController *m_styleController;
- std::function<MView *(PropertiesView *)> m_viewFactory;
+ ModelController *m_modelController = nullptr;
+ DiagramController *m_diagramController = nullptr;
+ StereotypeController *m_stereotypeController = nullptr;
+ StyleController *m_styleController = nullptr;
+ std::function<MView *(PropertiesView *)> m_viewFactory = nullptr;
QList<MElement *> m_selectedModelElements;
QList<DElement *> m_selectedDiagramElements;
- MDiagram *m_selectedDiagram;
+ MDiagram *m_selectedDiagram = nullptr;
QScopedPointer<MView> m_mview;
- QWidget *m_widget;
+ QWidget *m_widget = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp
index 62ceaad1a3..d0a87dfaa9 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp
@@ -43,6 +43,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
#include "qmt/model/massociation.h"
+#include "qmt/model/mconnection.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
@@ -55,12 +56,15 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
+#include "qmt/diagram/dswimlane.h"
// TODO move into better place
#include "qmt/diagram_scene/items/stereotypedisplayvisitor.h"
#include "qmt/stereotype/stereotypecontroller.h"
+#include "qmt/stereotype/customrelation.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/style.h"
#include "qmt/style/objectvisuals.h"
@@ -102,7 +106,7 @@ static MDependency::Direction translateIndexToDirection(int index)
static const MDependency::Direction map[] = {
MDependency::AToB, MDependency::BToA, MDependency::Bidirectional
};
- QMT_CHECK(isValidDirectionIndex(index));
+ QMT_ASSERT(isValidDirectionIndex(index), return MDependency::AToB);
return map[index];
}
@@ -129,7 +133,7 @@ static MAssociationEnd::Kind translateIndexToAssociationKind(int index)
static const MAssociationEnd::Kind map[] = {
MAssociationEnd::Association, MAssociationEnd::Aggregation, MAssociationEnd::Composition
};
- QMT_CHECK(isValidAssociationKindIndex(index));
+ QMT_ASSERT(isValidAssociationKindIndex(index), return MAssociationEnd::Association);
return map[index];
}
@@ -164,7 +168,7 @@ static DObject::VisualPrimaryRole translateIndexToVisualPrimaryRole(int index)
DObject::PrimaryRoleCustom1, DObject::PrimaryRoleCustom2, DObject::PrimaryRoleCustom3,
DObject::PrimaryRoleCustom4, DObject::PrimaryRoleCustom5
};
- QMT_CHECK(index >= 0 && index <= 5);
+ QMT_ASSERT(index >= 0 && index <= 5, return DObject::PrimaryRoleNormal);
return map[index];
}
@@ -192,7 +196,7 @@ static DObject::VisualSecondaryRole translateIndexToVisualSecondaryRole(int inde
DObject::SecondaryRoleLighter, DObject::SecondaryRoleDarker,
DObject::SecondaryRoleSoften, DObject::SecondaryRoleOutline
};
- QMT_CHECK(index >= 0 && index <= 4);
+ QMT_ASSERT(index >= 0 && index <= 4, return DObject::SecondaryRoleNone);
return map[index];
}
@@ -222,7 +226,7 @@ static DObject::StereotypeDisplay translateIndexToStereotypeDisplay(int index)
DObject::StereotypeDecoration,
DObject::StereotypeIcon
};
- QMT_CHECK(index >= 0 && index <= 4);
+ QMT_ASSERT(index >= 0 && index <= 4, return DObject::StereotypeSmart);
return map[index];
}
@@ -246,7 +250,7 @@ static DClass::TemplateDisplay translateIndexToTemplateDisplay(int index)
DClass::TemplateBox,
DClass::TemplateName
};
- QMT_CHECK(index >= 0 && index <= 2);
+ QMT_ASSERT(index >= 0 && index <= 2, return DClass::TemplateSmart);
return map[index];
}
@@ -275,56 +279,13 @@ static DAnnotation::VisualRole translateIndexToAnnotationVisualRole(int index)
DAnnotation::RoleNormal, DAnnotation::RoleTitle, DAnnotation::RoleSubtitle,
DAnnotation::RoleEmphasized, DAnnotation::RoleSoften, DAnnotation::RoleFootnote
};
- QMT_CHECK(index >= 0 && index <= 5);
+ QMT_ASSERT(index >= 0 && index <= 5, return DAnnotation::RoleNormal);
return map[index];
}
PropertiesView::MView::MView(PropertiesView *propertiesView)
: m_propertiesView(propertiesView),
- m_diagram(0),
- m_stereotypesController(new StereotypesController(this)),
- m_topWidget(0),
- m_topLayout(0),
- m_stereotypeElement(StereotypeIcon::ElementAny),
- m_classNameLabel(0),
- m_stereotypeComboBox(0),
- m_reverseEngineeredLabel(0),
- m_elementNameLineEdit(0),
- m_childrenLabel(0),
- m_relationsLabel(0),
- m_namespaceLineEdit(0),
- m_templateParametersLineEdit(0),
- m_classMembersStatusLabel(0),
- m_classMembersParseButton(0),
- m_classMembersEdit(0),
- m_diagramsLabel(0),
- m_itemVarietyEdit(0),
- m_endALabel(0),
- m_endBLabel(0),
- m_directionSelector(0),
- m_endAEndName(0),
- m_endACardinality(0),
- m_endANavigable(0),
- m_endAKind(0),
- m_endBEndName(0),
- m_endBCardinality(0),
- m_endBNavigable(0),
- m_endBKind(0),
- m_separatorLine(0),
- m_styleElementType(StyleEngine::TypeOther),
- m_posRectLabel(0),
- m_autoSizedCheckbox(0),
- m_visualPrimaryRoleSelector(0),
- m_visualSecondaryRoleSelector(0),
- m_visualEmphasizedCheckbox(0),
- m_stereotypeDisplaySelector(0),
- m_depthLabel(0),
- m_templateDisplaySelector(0),
- m_showAllMembersCheckbox(0),
- m_plainShapeCheckbox(0),
- m_itemShapeEdit(0),
- m_annotationAutoWidthCheckbox(0),
- m_annotationVisualRoleSelector(0)
+ m_stereotypesController(new StereotypesController(this))
{
}
@@ -334,18 +295,18 @@ PropertiesView::MView::~MView()
void PropertiesView::MView::update(QList<MElement *> &modelElements)
{
- QMT_CHECK(modelElements.size() > 0);
+ QMT_ASSERT(modelElements.size() > 0, return);
m_modelElements = modelElements;
m_diagramElements.clear();
- m_diagram = 0;
+ m_diagram = nullptr;
modelElements.at(0)->accept(this);
}
void PropertiesView::MView::update(QList<DElement *> &diagramElements, MDiagram *diagram)
{
- QMT_CHECK(diagramElements.size() > 0);
- QMT_CHECK(diagram);
+ QMT_ASSERT(diagramElements.size() > 0, return);
+ QMT_ASSERT(diagram, return);
m_diagramElements = diagramElements;
m_diagram = diagram;
@@ -361,7 +322,7 @@ void PropertiesView::MView::update(QList<DElement *> &diagramElements, MDiagram
}
if (!appendedMelement) {
// ensure that indices within m_diagramElements match indices into m_modelElements
- m_modelElements.append(0);
+ m_modelElements.append(nullptr);
}
}
diagramElements.at(0)->accept(this);
@@ -380,7 +341,7 @@ void PropertiesView::MView::visitMElement(const MElement *element)
Q_UNUSED(element);
prepare();
- if (m_stereotypeComboBox == 0) {
+ if (!m_stereotypeComboBox) {
m_stereotypeComboBox = new QComboBox(m_topWidget);
m_stereotypeComboBox->setEditable(true);
m_stereotypeComboBox->setInsertPolicy(QComboBox::NoInsert);
@@ -404,7 +365,7 @@ void PropertiesView::MView::visitMElement(const MElement *element)
}
}
#ifdef SHOW_DEBUG_PROPERTIES
- if (m_reverseEngineeredLabel == 0) {
+ if (!m_reverseEngineeredLabel) {
m_reverseEngineeredLabel = new QLabel(m_topWidget);
addRow(tr("Reverse engineered:"), m_reverseEngineeredLabel, "reverse engineered");
}
@@ -418,7 +379,7 @@ void PropertiesView::MView::visitMObject(const MObject *object)
visitMElement(object);
QList<MObject *> selection = filter<MObject>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
- if (m_elementNameLineEdit == 0) {
+ if (!m_elementNameLineEdit) {
m_elementNameLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Name:"), m_elementNameLineEdit, "name");
connect(m_elementNameLineEdit, &QLineEdit::textChanged,
@@ -434,12 +395,12 @@ void PropertiesView::MView::visitMObject(const MObject *object)
m_elementNameLineEdit->setEnabled(isSingleSelection);
#ifdef SHOW_DEBUG_PROPERTIES
- if (m_childrenLabel == 0) {
+ if (!m_childrenLabel) {
m_childrenLabel = new QLabel(m_topWidget);
addRow(tr("Children:"), m_childrenLabel, "children");
}
m_childrenLabel->setText(QString::number(object->children().size()));
- if (m_relationsLabel == 0) {
+ if (!m_relationsLabel) {
m_relationsLabel = new QLabel(m_topWidget);
addRow(tr("Relations:"), m_relationsLabel, "relations");
}
@@ -462,7 +423,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
visitMObject(klass);
QList<MClass *> selection = filter<MClass>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
- if (m_namespaceLineEdit == 0) {
+ if (!m_namespaceLineEdit) {
m_namespaceLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Namespace:"), m_namespaceLineEdit, "namespace");
connect(m_namespaceLineEdit, &QLineEdit::textEdited,
@@ -479,7 +440,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
m_namespaceLineEdit->setEnabled(false);
}
}
- if (m_templateParametersLineEdit == 0) {
+ if (!m_templateParametersLineEdit) {
m_templateParametersLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Template:"), m_templateParametersLineEdit, "template");
connect(m_templateParametersLineEdit, &QLineEdit::textChanged,
@@ -496,7 +457,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
}
if (m_templateParametersLineEdit->isEnabled() != isSingleSelection)
m_templateParametersLineEdit->setEnabled(isSingleSelection);
- if (m_classMembersStatusLabel == 0) {
+ if (!m_classMembersStatusLabel) {
QMT_CHECK(!m_classMembersParseButton);
m_classMembersStatusLabel = new QLabel(m_topWidget);
m_classMembersParseButton = new QPushButton(tr("Clean Up"), m_topWidget);
@@ -505,13 +466,13 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
layout->addWidget(m_classMembersParseButton);
layout->setStretch(0, 1);
layout->setStretch(1, 0);
- addRow(QStringLiteral(""), layout, "members status");
+ addRow("", layout, "members status");
connect(m_classMembersParseButton, &QAbstractButton::clicked,
this, &PropertiesView::MView::onParseClassMembers);
}
if (m_classMembersParseButton->isEnabled() != isSingleSelection)
m_classMembersParseButton->setEnabled(isSingleSelection);
- if (m_classMembersEdit == 0) {
+ if (!m_classMembersEdit) {
m_classMembersEdit = new ClassMembersEdit(m_topWidget);
m_classMembersEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
addRow(tr("Members:"), m_classMembersEdit, "members");
@@ -541,7 +502,7 @@ void PropertiesView::MView::visitMDiagram(const MDiagram *diagram)
setTitle<MDiagram>(m_modelElements, tr("Diagram"), tr("Diagrams"));
visitMObject(diagram);
#ifdef SHOW_DEBUG_PROPERTIES
- if (m_diagramsLabel == 0) {
+ if (!m_diagramsLabel) {
m_diagramsLabel = new QLabel(m_topWidget);
addRow(tr("Elements:"), m_diagramsLabel, "elements");
}
@@ -562,7 +523,7 @@ void PropertiesView::MView::visitMItem(const MItem *item)
QList<MItem *> selection = filter<MItem>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
if (item->isVarietyEditable()) {
- if (m_itemVarietyEdit == 0) {
+ if (!m_itemVarietyEdit) {
m_itemVarietyEdit = new QLineEdit(m_topWidget);
addRow(tr("Variety:"), m_itemVarietyEdit, "variety");
connect(m_itemVarietyEdit, &QLineEdit::textChanged,
@@ -584,7 +545,7 @@ void PropertiesView::MView::visitMRelation(const MRelation *relation)
visitMElement(relation);
QList<MRelation *> selection = filter<MRelation>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
- if (m_elementNameLineEdit == 0) {
+ if (!m_elementNameLineEdit) {
m_elementNameLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Name:"), m_elementNameLineEdit, "name");
connect(m_elementNameLineEdit, &QLineEdit::textChanged,
@@ -599,10 +560,10 @@ void PropertiesView::MView::visitMRelation(const MRelation *relation)
if (m_elementNameLineEdit->isEnabled() != isSingleSelection)
m_elementNameLineEdit->setEnabled(isSingleSelection);
MObject *endAObject = m_propertiesView->modelController()->findObject(relation->endAUid());
- QMT_CHECK(endAObject);
+ QMT_ASSERT(endAObject, return);
setEndAName(tr("End A: %1").arg(endAObject->name()));
MObject *endBObject = m_propertiesView->modelController()->findObject(relation->endBUid());
- QMT_CHECK(endBObject);
+ QMT_ASSERT(endBObject, return);
setEndBName(tr("End B: %1").arg(endBObject->name()));
}
@@ -612,7 +573,7 @@ void PropertiesView::MView::visitMDependency(const MDependency *dependency)
visitMRelation(dependency);
QList<MDependency *> selection = filter<MDependency>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
- if (m_directionSelector == 0) {
+ if (!m_directionSelector) {
m_directionSelector = new QComboBox(m_topWidget);
m_directionSelector->addItems(QStringList({ "->", "<-", "<->" }));
addRow(tr("Direction:"), m_directionSelector, "direction");
@@ -636,9 +597,10 @@ void PropertiesView::MView::visitMInheritance(const MInheritance *inheritance)
{
setTitle<MInheritance>(m_modelElements, tr("Inheritance"), tr("Inheritances"));
MObject *derivedClass = m_propertiesView->modelController()->findObject(inheritance->derived());
- QMT_CHECK(derivedClass);
+ QMT_ASSERT(derivedClass, return);
setEndAName(tr("Derived class: %1").arg(derivedClass->name()));
MObject *baseClass = m_propertiesView->modelController()->findObject(inheritance->base());
+ QMT_ASSERT(baseClass, return);
setEndBName(tr("Base class: %1").arg(baseClass->name()));
visitMRelation(inheritance);
}
@@ -649,11 +611,11 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
visitMRelation(association);
QList<MAssociation *> selection = filter<MAssociation>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
- if (m_endALabel == 0) {
- m_endALabel = new QLabel(QStringLiteral("<b>") + m_endAName + QStringLiteral("</b>"));
+ if (!m_endALabel) {
+ m_endALabel = new QLabel("<b>" + m_endAName + "</b>");
addRow(m_endALabel, "end a");
}
- if (m_endAEndName == 0) {
+ if (!m_endAEndName) {
m_endAEndName = new QLineEdit(m_topWidget);
addRow(tr("Role:"), m_endAEndName, "role a");
connect(m_endAEndName, &QLineEdit::textChanged,
@@ -667,7 +629,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endAEndName->isEnabled() != isSingleSelection)
m_endAEndName->setEnabled(isSingleSelection);
- if (m_endACardinality == 0) {
+ if (!m_endACardinality) {
m_endACardinality = new QLineEdit(m_topWidget);
addRow(tr("Cardinality:"), m_endACardinality, "cardinality a");
connect(m_endACardinality, &QLineEdit::textChanged,
@@ -681,7 +643,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endACardinality->isEnabled() != isSingleSelection)
m_endACardinality->setEnabled(isSingleSelection);
- if (m_endANavigable == 0) {
+ if (!m_endANavigable) {
m_endANavigable = new QCheckBox(tr("Navigable"), m_topWidget);
addRow(QString(), m_endANavigable, "navigable a");
connect(m_endANavigable, &QAbstractButton::clicked,
@@ -695,7 +657,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endANavigable->isEnabled() != isSingleSelection)
m_endANavigable->setEnabled(isSingleSelection);
- if (m_endAKind == 0) {
+ if (!m_endAKind) {
m_endAKind = new QComboBox(m_topWidget);
m_endAKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") });
addRow(tr("Relationship:"), m_endAKind, "relationship a");
@@ -714,11 +676,11 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
if (m_endAKind->isEnabled() != isSingleSelection)
m_endAKind->setEnabled(isSingleSelection);
- if (m_endBLabel == 0) {
- m_endBLabel = new QLabel(QStringLiteral("<b>") + m_endBName + QStringLiteral("</b>"));
+ if (!m_endBLabel) {
+ m_endBLabel = new QLabel("<b>" + m_endBName + "</b>");
addRow(m_endBLabel, "end b");
}
- if (m_endBEndName == 0) {
+ if (!m_endBEndName) {
m_endBEndName = new QLineEdit(m_topWidget);
addRow(tr("Role:"), m_endBEndName, "role b");
connect(m_endBEndName, &QLineEdit::textChanged,
@@ -732,7 +694,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endBEndName->isEnabled() != isSingleSelection)
m_endBEndName->setEnabled(isSingleSelection);
- if (m_endBCardinality == 0) {
+ if (!m_endBCardinality) {
m_endBCardinality = new QLineEdit(m_topWidget);
addRow(tr("Cardinality:"), m_endBCardinality, "cardinality b");
connect(m_endBCardinality, &QLineEdit::textChanged,
@@ -746,7 +708,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endBCardinality->isEnabled() != isSingleSelection)
m_endBCardinality->setEnabled(isSingleSelection);
- if (m_endBNavigable == 0) {
+ if (!m_endBNavigable) {
m_endBNavigable = new QCheckBox(tr("Navigable"), m_topWidget);
addRow(QString(), m_endBNavigable, "navigable b");
connect(m_endBNavigable, &QAbstractButton::clicked,
@@ -760,7 +722,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endBNavigable->isEnabled() != isSingleSelection)
m_endBNavigable->setEnabled(isSingleSelection);
- if (m_endBKind == 0) {
+ if (!m_endBKind) {
m_endBKind = new QComboBox(m_topWidget);
m_endBKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") });
addRow(tr("Relationship:"), m_endBKind, "relationship b");
@@ -780,6 +742,107 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
m_endBKind->setEnabled(isSingleSelection);
}
+void PropertiesView::MView::visitMConnection(const MConnection *connection)
+{
+ setTitle<MConnection>(connection, m_modelElements, tr("Connection"), tr("Connections"));
+ visitMRelation(connection);
+ QList<MConnection *> selection = filter<MConnection>(m_modelElements);
+ const bool isSingleSelection = selection.size() == 1;
+ if (!m_endALabel) {
+ m_endALabel = new QLabel("<b>" + m_endAName + "</b>");
+ addRow(m_endALabel, "end a");
+ }
+ if (!m_endAEndName) {
+ m_endAEndName = new QLineEdit(m_topWidget);
+ addRow(tr("Role:"), m_endAEndName, "role a");
+ connect(m_endAEndName, &QLineEdit::textChanged,
+ this, &PropertiesView::MView::onConnectionEndANameChanged);
+ }
+ if (isSingleSelection) {
+ if (connection->endA().name() != m_endAEndName->text() && !m_endAEndName->hasFocus())
+ m_endAEndName->setText(connection->endA().name());
+ } else {
+ m_endAEndName->clear();
+ }
+ if (m_endAEndName->isEnabled() != isSingleSelection)
+ m_endAEndName->setEnabled(isSingleSelection);
+ if (!m_endACardinality) {
+ m_endACardinality = new QLineEdit(m_topWidget);
+ addRow(tr("Cardinality:"), m_endACardinality, "cardinality a");
+ connect(m_endACardinality, &QLineEdit::textChanged,
+ this, &PropertiesView::MView::onConnectionEndACardinalityChanged);
+ }
+ if (isSingleSelection) {
+ if (connection->endA().cardinality() != m_endACardinality->text() && !m_endACardinality->hasFocus())
+ m_endACardinality->setText(connection->endA().cardinality());
+ } else {
+ m_endACardinality->clear();
+ }
+ if (m_endACardinality->isEnabled() != isSingleSelection)
+ m_endACardinality->setEnabled(isSingleSelection);
+ if (!m_endANavigable) {
+ m_endANavigable = new QCheckBox(tr("Navigable"), m_topWidget);
+ addRow(QString(), m_endANavigable, "navigable a");
+ connect(m_endANavigable, &QAbstractButton::clicked,
+ this, &PropertiesView::MView::onConnectionEndANavigableChanged);
+ }
+ if (isSingleSelection) {
+ if (connection->endA().isNavigable() != m_endANavigable->isChecked())
+ m_endANavigable->setChecked(connection->endA().isNavigable());
+ } else {
+ m_endANavigable->setChecked(false);
+ }
+ if (m_endANavigable->isEnabled() != isSingleSelection)
+ m_endANavigable->setEnabled(isSingleSelection);
+
+ if (!m_endBLabel) {
+ m_endBLabel = new QLabel("<b>" + m_endBName + "</b>");
+ addRow(m_endBLabel, "end b");
+ }
+ if (!m_endBEndName) {
+ m_endBEndName = new QLineEdit(m_topWidget);
+ addRow(tr("Role:"), m_endBEndName, "role b");
+ connect(m_endBEndName, &QLineEdit::textChanged,
+ this, &PropertiesView::MView::onConnectionEndBNameChanged);
+ }
+ if (isSingleSelection) {
+ if (connection->endB().name() != m_endBEndName->text() && !m_endBEndName->hasFocus())
+ m_endBEndName->setText(connection->endB().name());
+ } else {
+ m_endBEndName->clear();
+ }
+ if (m_endBEndName->isEnabled() != isSingleSelection)
+ m_endBEndName->setEnabled(isSingleSelection);
+ if (!m_endBCardinality) {
+ m_endBCardinality = new QLineEdit(m_topWidget);
+ addRow(tr("Cardinality:"), m_endBCardinality, "cardinality b");
+ connect(m_endBCardinality, &QLineEdit::textChanged,
+ this, &PropertiesView::MView::onConnectionEndBCardinalityChanged);
+ }
+ if (isSingleSelection) {
+ if (connection->endB().cardinality() != m_endBCardinality->text() && !m_endBCardinality->hasFocus())
+ m_endBCardinality->setText(connection->endB().cardinality());
+ } else {
+ m_endBCardinality->clear();
+ }
+ if (m_endBCardinality->isEnabled() != isSingleSelection)
+ m_endBCardinality->setEnabled(isSingleSelection);
+ if (!m_endBNavigable) {
+ m_endBNavigable = new QCheckBox(tr("Navigable"), m_topWidget);
+ addRow(QString(), m_endBNavigable, "navigable b");
+ connect(m_endBNavigable, &QAbstractButton::clicked,
+ this, &PropertiesView::MView::onConnectionEndBNavigableChanged);
+ }
+ if (isSingleSelection) {
+ if (connection->endB().isNavigable() != m_endBNavigable->isChecked())
+ m_endBNavigable->setChecked(connection->endB().isNavigable());
+ } else {
+ m_endBNavigable->setChecked(false);
+ }
+ if (m_endBNavigable->isEnabled() != isSingleSelection)
+ m_endBNavigable->setEnabled(isSingleSelection);
+}
+
void PropertiesView::MView::visitDElement(const DElement *element)
{
Q_UNUSED(element);
@@ -788,7 +851,7 @@ void PropertiesView::MView::visitDElement(const DElement *element)
m_propertiesTitle.clear();
m_modelElements.at(0)->accept(this);
#ifdef SHOW_DEBUG_PROPERTIES
- if (m_separatorLine == 0) {
+ if (!m_separatorLine) {
m_separatorLine = new QFrame(m_topWidget);
m_separatorLine->setFrameShape(QFrame::StyledPanel);
m_separatorLine->setLineWidth(2);
@@ -805,11 +868,11 @@ void PropertiesView::MView::visitDObject(const DObject *object)
{
visitDElement(object);
#ifdef SHOW_DEBUG_PROPERTIES
- if (m_posRectLabel == 0) {
+ if (!m_posRectLabel) {
m_posRectLabel = new QLabel(m_topWidget);
addRow(tr("Position and size:"), m_posRectLabel, "position and size");
}
- m_posRectLabel->setText(QString(QStringLiteral("(%1,%2):(%3,%4)-(%5,%6)"))
+ m_posRectLabel->setText(QString("(%1,%2):(%3,%4)-(%5,%6)")
.arg(object->pos().x())
.arg(object->pos().y())
.arg(object->rect().left())
@@ -817,7 +880,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
.arg(object->rect().right())
.arg(object->rect().bottom()));
#endif
- if (m_autoSizedCheckbox == 0) {
+ if (!m_autoSizedCheckbox) {
m_autoSizedCheckbox = new QCheckBox(tr("Auto sized"), m_topWidget);
addRow(QString(), m_autoSizedCheckbox, "auto size");
connect(m_autoSizedCheckbox, &QAbstractButton::clicked,
@@ -830,7 +893,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_autoSizedCheckbox->setChecked(false);
}
- if (m_visualPrimaryRoleSelector == 0) {
+ if (!m_visualPrimaryRoleSelector) {
m_visualPrimaryRoleSelector = new PaletteBox(m_topWidget);
setPrimaryRolePalette(m_styleElementType, DObject::PrimaryRoleCustom1, QColor());
setPrimaryRolePalette(m_styleElementType, DObject::PrimaryRoleCustom2, QColor());
@@ -859,7 +922,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_visualPrimaryRoleSelector->setCurrentIndex(-1);
}
- if (m_visualSecondaryRoleSelector == 0) {
+ if (!m_visualSecondaryRoleSelector) {
m_visualSecondaryRoleSelector = new QComboBox(m_topWidget);
m_visualSecondaryRoleSelector->addItems({ tr("Normal"), tr("Lighter"), tr("Darker"),
tr("Soften"), tr("Outline") });
@@ -874,7 +937,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_visualSecondaryRoleSelector->setCurrentIndex(-1);
}
- if (m_visualEmphasizedCheckbox == 0) {
+ if (!m_visualEmphasizedCheckbox) {
m_visualEmphasizedCheckbox = new QCheckBox(tr("Emphasized"), m_topWidget);
addRow(QString(), m_visualEmphasizedCheckbox, "emphasized");
connect(m_visualEmphasizedCheckbox, &QAbstractButton::clicked,
@@ -887,7 +950,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_visualEmphasizedCheckbox->setChecked(false);
}
- if (m_stereotypeDisplaySelector == 0) {
+ if (!m_stereotypeDisplaySelector) {
m_stereotypeDisplaySelector = new QComboBox(m_topWidget);
m_stereotypeDisplaySelector->addItems({ tr("Smart"), tr("None"), tr("Label"),
tr("Decoration"), tr("Icon") });
@@ -903,7 +966,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
m_stereotypeDisplaySelector->setCurrentIndex(-1);
}
#ifdef SHOW_DEBUG_PROPERTIES
- if (m_depthLabel == 0) {
+ if (!m_depthLabel) {
m_depthLabel = new QLabel(m_topWidget);
addRow(tr("Depth:"), m_depthLabel, "depth");
}
@@ -925,7 +988,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
setStereotypeIconElement(StereotypeIcon::ElementClass);
setStyleElementType(StyleEngine::TypeClass);
visitDObject(klass);
- if (m_templateDisplaySelector == 0) {
+ if (!m_templateDisplaySelector) {
m_templateDisplaySelector = new QComboBox(m_topWidget);
m_templateDisplaySelector->addItems({ tr("Smart"), tr("Box"), tr("Angle Brackets") });
addRow(tr("Template display:"), m_templateDisplaySelector, "template display");
@@ -939,7 +1002,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
else
m_templateDisplaySelector->setCurrentIndex(-1);
}
- if (m_showAllMembersCheckbox == 0) {
+ if (!m_showAllMembersCheckbox) {
m_showAllMembersCheckbox = new QCheckBox(tr("Show members"), m_topWidget);
addRow(QString(), m_showAllMembersCheckbox, "show members");
connect(m_showAllMembersCheckbox, &QAbstractButton::clicked,
@@ -960,7 +1023,7 @@ void PropertiesView::MView::visitDComponent(const DComponent *component)
setStereotypeIconElement(StereotypeIcon::ElementComponent);
setStyleElementType(StyleEngine::TypeComponent);
visitDObject(component);
- if (m_plainShapeCheckbox == 0) {
+ if (!m_plainShapeCheckbox) {
m_plainShapeCheckbox = new QCheckBox(tr("Plain shape"), m_topWidget);
addRow(QString(), m_plainShapeCheckbox, "plain shape");
connect(m_plainShapeCheckbox, &QAbstractButton::clicked,
@@ -991,7 +1054,7 @@ void PropertiesView::MView::visitDItem(const DItem *item)
QList<DItem *> selection = filter<DItem>(m_diagramElements);
bool isSingleSelection = selection.size() == 1;
if (item->isShapeEditable()) {
- if (m_itemShapeEdit == 0) {
+ if (!m_itemShapeEdit) {
m_itemShapeEdit = new QLineEdit(m_topWidget);
addRow(tr("Shape:"), m_itemShapeEdit, "shape");
connect(m_itemShapeEdit, &QLineEdit::textChanged,
@@ -1031,11 +1094,17 @@ void PropertiesView::MView::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
+void PropertiesView::MView::visitDConnection(const DConnection *connection)
+{
+ setTitle<DConnection>(m_diagramElements, tr("Connection"), tr("Connections"));
+ visitDRelation(connection);
+}
+
void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
{
setTitle<DAnnotation>(m_diagramElements, tr("Annotation"), tr("Annotations"));
visitDElement(annotation);
- if (m_annotationAutoWidthCheckbox == 0) {
+ if (!m_annotationAutoWidthCheckbox) {
m_annotationAutoWidthCheckbox = new QCheckBox(tr("Auto width"), m_topWidget);
addRow(QString(), m_annotationAutoWidthCheckbox, "auto width");
connect(m_annotationAutoWidthCheckbox, &QAbstractButton::clicked,
@@ -1048,7 +1117,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
else
m_annotationAutoWidthCheckbox->setChecked(false);
}
- if (m_annotationVisualRoleSelector == 0) {
+ if (!m_annotationVisualRoleSelector) {
m_annotationVisualRoleSelector = new QComboBox(m_topWidget);
m_annotationVisualRoleSelector->addItems(QStringList({ tr("Normal"), tr("Title"),
tr("Subtitle"), tr("Emphasized"),
@@ -1072,6 +1141,12 @@ void PropertiesView::MView::visitDBoundary(const DBoundary *boundary)
visitDElement(boundary);
}
+void PropertiesView::MView::visitDSwimlane(const DSwimlane *swimlane)
+{
+ setTitle<DSwimlane>(m_diagramElements, tr("Swimlane"), tr("Swimlanes"));
+ visitDElement(swimlane);
+}
+
void PropertiesView::MView::onStereotypesChanged(const QString &stereotypes)
{
QList<QString> set = m_stereotypesController->fromString(stereotypes);
@@ -1206,6 +1281,48 @@ void PropertiesView::MView::onAssociationEndBKindChanged(int kindIndex)
&MAssociationEnd::kind, &MAssociationEnd::setKind);
}
+void PropertiesView::MView::onConnectionEndANameChanged(const QString &name)
+{
+ assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
+ m_modelElements, SelectionSingle, name, &MConnection::endA, &MConnection::setEndA,
+ &MConnectionEnd::name, &MConnectionEnd::setName);
+}
+
+void PropertiesView::MView::onConnectionEndACardinalityChanged(const QString &cardinality)
+{
+ assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
+ m_modelElements, SelectionSingle, cardinality, &MConnection::endA, &MConnection::setEndA,
+ &MConnectionEnd::cardinality, &MConnectionEnd::setCardinality);
+}
+
+void PropertiesView::MView::onConnectionEndANavigableChanged(bool navigable)
+{
+ assignEmbeddedModelElement<MConnection, MConnectionEnd, bool>(
+ m_modelElements, SelectionSingle, navigable, &MConnection::endA, &MConnection::setEndA,
+ &MConnectionEnd::isNavigable, &MConnectionEnd::setNavigable);
+}
+
+void PropertiesView::MView::onConnectionEndBNameChanged(const QString &name)
+{
+ assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
+ m_modelElements, SelectionSingle, name, &MConnection::endB, &MConnection::setEndB,
+ &MConnectionEnd::name, &MConnectionEnd::setName);
+}
+
+void PropertiesView::MView::onConnectionEndBCardinalityChanged(const QString &cardinality)
+{
+ assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
+ m_modelElements, SelectionSingle, cardinality, &MConnection::endB, &MConnection::setEndB,
+ &MConnectionEnd::cardinality, &MConnectionEnd::setCardinality);
+}
+
+void PropertiesView::MView::onConnectionEndBNavigableChanged(bool navigable)
+{
+ assignEmbeddedModelElement<MConnection, MConnectionEnd, bool>(
+ m_modelElements, SelectionSingle, navigable, &MConnection::endB, &MConnection::setEndB,
+ &MConnectionEnd::isNavigable, &MConnectionEnd::setNavigable);
+}
+
void PropertiesView::MView::onAutoSizedChanged(bool autoSized)
{
assignModelElement<DObject, bool>(m_diagramElements, SelectionMulti, autoSized,
@@ -1283,17 +1400,17 @@ void PropertiesView::MView::onAnnotationVisualRoleChanged(int visualRoleIndex)
void PropertiesView::MView::prepare()
{
QMT_CHECK(!m_propertiesTitle.isEmpty());
- if (m_topWidget == 0) {
+ if (!m_topWidget) {
m_topWidget = new QWidget();
m_topLayout = new QFormLayout(m_topWidget);
m_topWidget->setLayout(m_topLayout);
}
- if (m_classNameLabel == 0) {
+ if (!m_classNameLabel) {
m_classNameLabel = new QLabel();
m_topLayout->addRow(m_classNameLabel);
m_rowToId.append("title");
}
- QString title(QStringLiteral("<b>") + m_propertiesTitle + QStringLiteral("</b>"));
+ QString title("<b>" + m_propertiesTitle + "</b>");
if (m_classNameLabel->text() != title)
m_classNameLabel->setText(title);
}
@@ -1371,26 +1488,54 @@ template<typename T, typename V>
void PropertiesView::MView::setTitle(const MItem *item, const QList<V *> &elements,
const QString &singularTitle, const QString &pluralTitle)
{
- if (m_propertiesTitle.isEmpty()) {
- QList<T *> filtered = filter<T>(elements);
- if (filtered.size() == elements.size()) {
- if (elements.size() == 1) {
- if (item && !item->isVarietyEditable()) {
- QString stereotypeIconId = m_propertiesView->stereotypeController()
+ if (!m_propertiesTitle.isEmpty())
+ return;
+ QList<T *> filtered = filter<T>(elements);
+ if (filtered.size() == elements.size()) {
+ if (elements.size() == 1) {
+ if (item && !item->isVarietyEditable()) {
+ QString stereotypeIconId = m_propertiesView->stereotypeController()
->findStereotypeIconId(StereotypeIcon::ElementItem, QStringList(item->variety()));
- if (!stereotypeIconId.isEmpty()) {
- StereotypeIcon stereotypeIcon = m_propertiesView->stereotypeController()->findStereotypeIcon(stereotypeIconId);
- m_propertiesTitle = stereotypeIcon.title();
- }
+ if (!stereotypeIconId.isEmpty()) {
+ StereotypeIcon stereotypeIcon = m_propertiesView->stereotypeController()->findStereotypeIcon(stereotypeIconId);
+ m_propertiesTitle = stereotypeIcon.title();
+ }
+ }
+ if (m_propertiesTitle.isEmpty())
+ m_propertiesTitle = singularTitle;
+ } else {
+ m_propertiesTitle = pluralTitle;
+ }
+ } else {
+ m_propertiesTitle = QCoreApplication::translate("qmt::PropertiesView::MView", "Multi-Selection");
+ }
+}
+
+template<typename T, typename V>
+void PropertiesView::MView::setTitle(const MConnection *connection, const QList<V *> &elements,
+ const QString &singularTitle, const QString &pluralTitle)
+{
+ if (!m_propertiesTitle.isEmpty())
+ return;
+ QList<T *> filtered = filter<T>(elements);
+ if (filtered.size() == elements.size()) {
+ if (elements.size() == 1) {
+ if (connection) {
+ CustomRelation customRelation = m_propertiesView->stereotypeController()
+ ->findCustomRelation(connection->customRelationId());
+ if (!customRelation.isNull()) {
+ m_propertiesTitle = customRelation.title();
+ if (m_propertiesTitle.isEmpty())
+ m_propertiesTitle = connection->customRelationId();
}
- if (m_propertiesTitle.isEmpty())
- m_propertiesTitle = singularTitle;
- } else {
- m_propertiesTitle = pluralTitle;
}
+ if (m_propertiesTitle.isEmpty())
+ m_propertiesTitle = singularTitle;
} else {
- m_propertiesTitle = QCoreApplication::translate("qmt::PropertiesView::MView", "Multi-Selection");
+ m_propertiesTitle = pluralTitle;
}
+ } else {
+ m_propertiesTitle = QCoreApplication::translate("qmt::PropertiesView::MView", "Multi-Selection");
}
}
@@ -1444,7 +1589,7 @@ QString PropertiesView::MView::formatTemplateParameters(const QList<QString> &te
bool first = true;
foreach (const QString &parameter, templateParametersList) {
if (!first)
- templateParamters += QStringLiteral(", ");
+ templateParamters += ", ";
templateParamters += parameter;
first = false;
}
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h
index 36418cbd9c..1c3f091f35 100644
--- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h
@@ -78,6 +78,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
+ void visitMConnection(const MConnection *connection) override;
void visitDElement(const DElement *element) override;
void visitDObject(const DObject *object) override;
@@ -90,8 +91,10 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
+ void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
+ void visitDSwimlane(const DSwimlane *swimlane) override;
void update(QList<MElement *> &modelElements);
void update(QList<DElement *> &diagramElements, MDiagram *diagram);
@@ -116,6 +119,12 @@ protected:
void onAssociationEndBCardinalityChanged(const QString &cardinality);
void onAssociationEndBNavigableChanged(bool navigable);
void onAssociationEndBKindChanged(int kindIndex);
+ void onConnectionEndANameChanged(const QString &name);
+ void onConnectionEndACardinalityChanged(const QString &cardinality);
+ void onConnectionEndANavigableChanged(bool navigable);
+ void onConnectionEndBNameChanged(const QString &name);
+ void onConnectionEndBCardinalityChanged(const QString &cardinality);
+ void onConnectionEndBNavigableChanged(bool navigable);
void onAutoSizedChanged(bool autoSized);
void onVisualPrimaryRoleChanged(int visualRoleIndex);
void onVisualSecondaryRoleChanged(int visualRoleIndex);
@@ -141,6 +150,9 @@ protected:
template<typename T, typename V>
void setTitle(const MItem *item, const QList<V *> &elements,
const QString &singularTitle, const QString &pluralTitle);
+ template<typename T, typename V>
+ void setTitle(const MConnection *connection, const QList<V *> &elements,
+ const QString &singularTitle, const QString &pluralTitle);
void setStereotypeIconElement(StereotypeIcon::Element stereotypeElement);
void setStyleElementType(StyleEngine::ElementType elementType);
void setPrimaryRolePalette(StyleEngine::ElementType elementType,
@@ -178,72 +190,72 @@ protected:
void (T::*setter)(const E &),
V (E::*vGetter)() const, void (E::*vSetter)(V));
- PropertiesView *m_propertiesView;
+ PropertiesView *m_propertiesView = nullptr;
QList<MElement *> m_modelElements;
QList<DElement *> m_diagramElements;
- MDiagram *m_diagram;
- StereotypesController *m_stereotypesController;
- QWidget *m_topWidget;
- QFormLayout *m_topLayout;
+ MDiagram *m_diagram = nullptr;
+ StereotypesController *m_stereotypesController = nullptr;
+ QWidget *m_topWidget = nullptr;
+ QFormLayout *m_topLayout = nullptr;
QList<const char *> m_rowToId;
QString m_propertiesTitle;
// MElement
- StereotypeIcon::Element m_stereotypeElement;
- QLabel *m_classNameLabel;
- QComboBox *m_stereotypeComboBox;
- QLabel *m_reverseEngineeredLabel;
+ StereotypeIcon::Element m_stereotypeElement = StereotypeIcon::ElementAny;
+ QLabel *m_classNameLabel = nullptr;
+ QComboBox *m_stereotypeComboBox = nullptr;
+ QLabel *m_reverseEngineeredLabel = nullptr;
// MObject
- QLineEdit *m_elementNameLineEdit;
- QLabel *m_childrenLabel;
- QLabel *m_relationsLabel;
+ QLineEdit *m_elementNameLineEdit = nullptr;
+ QLabel *m_childrenLabel = nullptr;
+ QLabel *m_relationsLabel = nullptr;
// MClass
- QLineEdit *m_namespaceLineEdit;
- QLineEdit *m_templateParametersLineEdit;
- QLabel *m_classMembersStatusLabel;
- QPushButton *m_classMembersParseButton;
- ClassMembersEdit *m_classMembersEdit;
+ QLineEdit *m_namespaceLineEdit = nullptr;
+ QLineEdit *m_templateParametersLineEdit = nullptr;
+ QLabel *m_classMembersStatusLabel = nullptr;
+ QPushButton *m_classMembersParseButton = nullptr;
+ ClassMembersEdit *m_classMembersEdit = nullptr;
// MDiagram
- QLabel *m_diagramsLabel;
+ QLabel *m_diagramsLabel = nullptr;
// MItem
- QLineEdit *m_itemVarietyEdit;
+ QLineEdit *m_itemVarietyEdit = nullptr;
// MRelation
QString m_endAName;
- QLabel *m_endALabel;
+ QLabel *m_endALabel = nullptr;
QString m_endBName;
- QLabel *m_endBLabel;
+ QLabel *m_endBLabel = nullptr;
// MDependency
- QComboBox *m_directionSelector;
+ QComboBox *m_directionSelector = nullptr;
// MAssociation
- QLineEdit *m_endAEndName;
- QLineEdit *m_endACardinality;
- QCheckBox *m_endANavigable;
- QComboBox *m_endAKind;
- QLineEdit *m_endBEndName;
- QLineEdit *m_endBCardinality;
- QCheckBox *m_endBNavigable;
- QComboBox *m_endBKind;
+ QLineEdit *m_endAEndName = nullptr;
+ QLineEdit *m_endACardinality = nullptr;
+ QCheckBox *m_endANavigable = nullptr;
+ QComboBox *m_endAKind = nullptr;
+ QLineEdit *m_endBEndName = nullptr;
+ QLineEdit *m_endBCardinality = nullptr;
+ QCheckBox *m_endBNavigable = nullptr;
+ QComboBox *m_endBKind = nullptr;
// DElement
- QFrame *m_separatorLine;
+ QFrame *m_separatorLine = nullptr;
// DObject
- StyleEngine::ElementType m_styleElementType;
- QLabel *m_posRectLabel;
- QCheckBox *m_autoSizedCheckbox;
- PaletteBox *m_visualPrimaryRoleSelector;
- QComboBox *m_visualSecondaryRoleSelector;
- QCheckBox *m_visualEmphasizedCheckbox;
- QComboBox *m_stereotypeDisplaySelector;
- QLabel *m_depthLabel;
+ StyleEngine::ElementType m_styleElementType = StyleEngine::TypeOther;
+ QLabel *m_posRectLabel = nullptr;
+ QCheckBox *m_autoSizedCheckbox = nullptr;
+ PaletteBox *m_visualPrimaryRoleSelector = nullptr;
+ QComboBox *m_visualSecondaryRoleSelector = nullptr;
+ QCheckBox *m_visualEmphasizedCheckbox = nullptr;
+ QComboBox *m_stereotypeDisplaySelector = nullptr;
+ QLabel *m_depthLabel = nullptr;
// DClass
- QComboBox *m_templateDisplaySelector;
- QCheckBox *m_showAllMembersCheckbox;
+ QComboBox *m_templateDisplaySelector = nullptr;
+ QCheckBox *m_showAllMembersCheckbox = nullptr;
// DComponent
- QCheckBox *m_plainShapeCheckbox;
+ QCheckBox *m_plainShapeCheckbox = nullptr;
// DItem
- QLineEdit *m_itemShapeEdit;
+ QLineEdit *m_itemShapeEdit = nullptr;
// DAnnotation
- QCheckBox *m_annotationAutoWidthCheckbox;
- QComboBox *m_annotationVisualRoleSelector;
+ QCheckBox *m_annotationAutoWidthCheckbox = nullptr;
+ QComboBox *m_annotationVisualRoleSelector = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/project/project.h b/src/libs/modelinglib/qmt/project/project.h
index b135769d87..d803789b87 100644
--- a/src/libs/modelinglib/qmt/project/project.h
+++ b/src/libs/modelinglib/qmt/project/project.h
@@ -52,7 +52,7 @@ public:
private:
Uid m_uid;
QString m_fileName;
- MPackage *m_rootPackage;
+ MPackage *m_rootPackage = nullptr;
QString m_configPath;
};
diff --git a/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp b/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp
index 9698a2f601..5feb0ebd56 100644
--- a/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp
+++ b/src/libs/modelinglib/qmt/project_controller/projectcontroller.cpp
@@ -43,8 +43,7 @@ ProjectIsModifiedException::ProjectIsModifiedException()
}
ProjectController::ProjectController(QObject *parent)
- : QObject(parent),
- m_isModified(false)
+ : QObject(parent)
{
}
diff --git a/src/libs/modelinglib/qmt/project_controller/projectcontroller.h b/src/libs/modelinglib/qmt/project_controller/projectcontroller.h
index 73daf2a2ac..6b57522e20 100644
--- a/src/libs/modelinglib/qmt/project_controller/projectcontroller.h
+++ b/src/libs/modelinglib/qmt/project_controller/projectcontroller.h
@@ -52,7 +52,7 @@ class QMT_EXPORT ProjectController : public QObject
Q_OBJECT
public:
- explicit ProjectController(QObject *parent = 0);
+ explicit ProjectController(QObject *parent = nullptr);
~ProjectController() override;
signals:
@@ -73,7 +73,7 @@ public:
private:
QScopedPointer<Project> m_project;
- bool m_isModified;
+ bool m_isModified = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/qmt.pri b/src/libs/modelinglib/qmt/qmt.pri
index d6f5e76a52..14f38f6991 100644
--- a/src/libs/modelinglib/qmt/qmt.pri
+++ b/src/libs/modelinglib/qmt/qmt.pri
@@ -27,6 +27,7 @@ HEADERS += \
$$PWD/diagram/dboundary.h \
$$PWD/diagram/dclass.h \
$$PWD/diagram/dcomponent.h \
+ $$PWD/diagram/dconnection.h \
$$PWD/diagram/dconstvisitor.h \
$$PWD/diagram/ddependency.h \
$$PWD/diagram/ddiagram.h \
@@ -55,6 +56,7 @@ HEADERS += \
$$PWD/diagram_scene/items/boundaryitem.h \
$$PWD/diagram_scene/items/classitem.h \
$$PWD/diagram_scene/items/componentitem.h \
+ $$PWD/diagram_scene/items/connectionitem.h \
$$PWD/diagram_scene/items/diagramitem.h \
$$PWD/diagram_scene/items/itemitem.h \
$$PWD/diagram_scene/items/objectitem.h \
@@ -103,6 +105,7 @@ HEADERS += \
$$PWD/model/mclass.h \
$$PWD/model/mclassmember.h \
$$PWD/model/mcomponent.h \
+ $$PWD/model/mconnection.h \
$$PWD/model/mconstvisitor.h \
$$PWD/model/mdependency.h \
$$PWD/model/mdiagram.h \
@@ -130,6 +133,7 @@ HEADERS += \
$$PWD/serializer/infrastructureserializer.h \
$$PWD/serializer/modelserializer.h \
$$PWD/serializer/projectserializer.h \
+ $$PWD/stereotype/customrelation.h \
$$PWD/stereotype/iconshape.h \
$$PWD/stereotype/shape.h \
$$PWD/stereotype/shapepaintvisitor.h \
@@ -155,7 +159,9 @@ HEADERS += \
$$PWD/tasks/ielementtasks.h \
$$PWD/tasks/isceneinspector.h \
$$PWD/tasks/voidelementtasks.h \
- $$PWD/infrastructure/qmtassert.h
+ $$PWD/infrastructure/qmtassert.h \
+ $$PWD/diagram_scene/items/swimlaneitem.h \
+ $$PWD/diagram/dswimlane.h
SOURCES += \
$$PWD/config/configcontroller.cpp \
@@ -179,6 +185,7 @@ SOURCES += \
$$PWD/diagram/dboundary.cpp \
$$PWD/diagram/dclass.cpp \
$$PWD/diagram/dcomponent.cpp \
+ $$PWD/diagram/dconnection.cpp \
$$PWD/diagram/ddependency.cpp \
$$PWD/diagram/ddiagram.cpp \
$$PWD/diagram/delement.cpp \
@@ -195,6 +202,7 @@ SOURCES += \
$$PWD/diagram_scene/items/boundaryitem.cpp \
$$PWD/diagram_scene/items/classitem.cpp \
$$PWD/diagram_scene/items/componentitem.cpp \
+ $$PWD/diagram_scene/items/connectionitem.cpp \
$$PWD/diagram_scene/items/diagramitem.cpp \
$$PWD/diagram_scene/items/itemitem.cpp \
$$PWD/diagram_scene/items/objectitem.cpp \
@@ -234,6 +242,7 @@ SOURCES += \
$$PWD/model/mclass.cpp \
$$PWD/model/mclassmember.cpp \
$$PWD/model/mcomponent.cpp \
+ $$PWD/model/mconnection.cpp \
$$PWD/model/mdependency.cpp \
$$PWD/model/mdiagram.cpp \
$$PWD/model/melement.cpp \
@@ -258,6 +267,7 @@ SOURCES += \
$$PWD/serializer/infrastructureserializer.cpp \
$$PWD/serializer/modelserializer.cpp \
$$PWD/serializer/projectserializer.cpp \
+ $$PWD/stereotype/customrelation.cpp \
$$PWD/stereotype/iconshape.cpp \
$$PWD/stereotype/shapepaintvisitor.cpp \
$$PWD/stereotype/shapes.cpp \
@@ -277,7 +287,9 @@ SOURCES += \
$$PWD/tasks/diagramscenecontroller.cpp \
$$PWD/tasks/finddiagramvisitor.cpp \
$$PWD/tasks/findrootdiagramvisitor.cpp \
- $$PWD/tasks/voidelementtasks.cpp
+ $$PWD/tasks/voidelementtasks.cpp \
+ $$PWD/diagram_scene/items/swimlaneitem.cpp \
+ $$PWD/diagram/dswimlane.cpp
RESOURCES += \
$$PWD/resources/resources.qrc
diff --git a/src/libs/modelinglib/qmt/resources/48x48/swimlane.png b/src/libs/modelinglib/qmt/resources/48x48/swimlane.png
new file mode 100644
index 0000000000..ae2b89fb24
--- /dev/null
+++ b/src/libs/modelinglib/qmt/resources/48x48/swimlane.png
Binary files differ
diff --git a/src/libs/modelinglib/qmt/resources/resources.qrc b/src/libs/modelinglib/qmt/resources/resources.qrc
index 896e41c050..f6ff6af119 100644
--- a/src/libs/modelinglib/qmt/resources/resources.qrc
+++ b/src/libs/modelinglib/qmt/resources/resources.qrc
@@ -21,5 +21,6 @@
<file>48x48/inheritance.png</file>
<file>48x48/item.png</file>
<file>48x48/package.png</file>
+ <file>48x48/swimlane.png</file>
</qresource>
</RCC>
diff --git a/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp b/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp
index c58eaca70e..d00a5f9407 100644
--- a/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp
+++ b/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp
@@ -41,9 +41,11 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
+#include "qmt/diagram/dswimlane.h"
#include "qark/qxmloutarchive.h"
#include "qark/qxmlinarchive.h"
@@ -62,7 +64,7 @@ template<class Archive>
inline void Access<Archive, DElement>::serialize(Archive &archive, DElement &element)
{
archive || tag(element)
- || attr(QStringLiteral("uid"), element, &DElement::uid, &DElement::setUid)
+ || attr("uid", element, &DElement::uid, &DElement::setUid)
|| end;
}
@@ -112,17 +114,17 @@ inline void Access<Archive, DObject>::serialize(Archive &archive, DObject &objec
{
archive || tag(object)
|| base<DElement>(object)
- || attr(QStringLiteral("object"), object, &DObject::modelUid, &DObject::setModelUid)
- || attr(QStringLiteral("stereotypes"), object, &DObject::stereotypes, &DObject::setStereotypes)
- || attr(QStringLiteral("context"), object, &DObject::context, &DObject::setContext)
- || attr(QStringLiteral("name"), object, &DObject::name, &DObject::setName)
- || attr(QStringLiteral("pos"), object, &DObject::pos, &DObject::setPos)
- || attr(QStringLiteral("rect"), object, &DObject::rect, &DObject::setRect)
- || attr(QStringLiteral("auto-sized"), object, &DObject::isAutoSized, &DObject::setAutoSized)
- || attr(QStringLiteral("visual-role"), object, &visualRole, &setVisualRole)
- || attr(QStringLiteral("visual-role2"), object, &DObject::visualSecondaryRole, &DObject::setVisualSecondaryRole)
- || attr(QStringLiteral("visual-emphasized"), object, &DObject::isVisualEmphasized, &DObject::setVisualEmphasized)
- || attr(QStringLiteral("stereotype-display"), object, &DObject::stereotypeDisplay, &DObject::setStereotypeDisplay)
+ || attr("object", object, &DObject::modelUid, &DObject::setModelUid)
+ || attr("stereotypes", object, &DObject::stereotypes, &DObject::setStereotypes)
+ || attr("context", object, &DObject::context, &DObject::setContext)
+ || attr("name", object, &DObject::name, &DObject::setName)
+ || attr("pos", object, &DObject::pos, &DObject::setPos)
+ || attr("rect", object, &DObject::rect, &DObject::setRect)
+ || attr("auto-sized", object, &DObject::isAutoSized, &DObject::setAutoSized)
+ || attr("visual-role", object, &visualRole, &setVisualRole)
+ || attr("visual-role2", object, &DObject::visualSecondaryRole, &DObject::setVisualSecondaryRole)
+ || attr("visual-emphasized", object, &DObject::isVisualEmphasized, &DObject::setVisualEmphasized)
+ || attr("stereotype-display", object, &DObject::stereotypeDisplay, &DObject::setStereotypeDisplay)
// depth is not persistent
|| end;
}
@@ -158,11 +160,11 @@ inline void Access<Archive, DClass>::serialize(Archive &archive, DClass &klass)
{
archive || tag(klass)
|| base<DObject>(klass)
- || attr(QStringLiteral("namespace"), klass, &DClass::umlNamespace, &DClass::setUmlNamespace)
- || attr(QStringLiteral("template"), klass, &DClass::templateParameters, &DClass::setTemplateParameters)
- || attr(QStringLiteral("template-display"), klass, &DClass::templateDisplay, &DClass::setTemplateDisplay)
- || attr(QStringLiteral("show-all-members"), klass, &DClass::showAllMembers, &DClass::setShowAllMembers)
- || attr(QStringLiteral("visible-members"), klass, &DClass::visibleMembers, &DClass::setVisibleMembers)
+ || attr("namespace", klass, &DClass::umlNamespace, &DClass::setUmlNamespace)
+ || attr("template", klass, &DClass::templateParameters, &DClass::setTemplateParameters)
+ || attr("template-display", klass, &DClass::templateDisplay, &DClass::setTemplateDisplay)
+ || attr("show-all-members", klass, &DClass::showAllMembers, &DClass::setShowAllMembers)
+ || attr("visible-members", klass, &DClass::visibleMembers, &DClass::setVisibleMembers)
|| end;
}
@@ -180,7 +182,7 @@ inline void Access<Archive, DComponent>::serialize(Archive &archive, DComponent
{
archive || tag(component)
|| base<DObject>(component)
- || attr(QStringLiteral("plain-shape"), component, &DComponent::isPlainShape, &DComponent::setPlainShape)
+ || attr("plain-shape", component, &DComponent::isPlainShape, &DComponent::setPlainShape)
|| end;
}
@@ -215,9 +217,9 @@ inline void Access<Archive, DItem>::serialize(Archive &archive, DItem &item)
{
archive || tag(item)
|| base<DObject>(item)
- || attr(QStringLiteral("variety"), item, &DItem::variety, &DItem::setVariety)
- || attr(QStringLiteral("shape-editable"), item, &DItem::isShapeEditable, &DItem::setShapeEditable)
- || attr(QStringLiteral("shape"), item, &DItem::shape, &DItem::setShape)
+ || attr("variety", item, &DItem::variety, &DItem::setVariety)
+ || attr("shape-editable", item, &DItem::isShapeEditable, &DItem::setShapeEditable)
+ || attr("shape", item, &DItem::shape, &DItem::setShape)
|| end;
}
@@ -234,12 +236,12 @@ inline void Access<Archive, DRelation>::serialize(Archive &archive, DRelation &r
{
archive || tag(relation)
|| base<DElement>(relation)
- || attr(QStringLiteral("object"), relation, &DRelation::modelUid, &DRelation::setModelUid)
- || attr(QStringLiteral("stereotypes"), relation, &DRelation::stereotypes, &DRelation::setStereotypes)
- || attr(QStringLiteral("a"), relation, &DRelation::endAUid, &DRelation::setEndAUid)
- || attr(QStringLiteral("b"), relation, &DRelation::endBUid, &DRelation::setEndBUid)
- || attr(QStringLiteral("name"), relation, &DRelation::name, &DRelation::setName)
- || attr(QStringLiteral("points"), relation, &DRelation::intermediatePoints, &DRelation::setIntermediatePoints)
+ || attr("object", relation, &DRelation::modelUid, &DRelation::setModelUid)
+ || attr("stereotypes", relation, &DRelation::stereotypes, &DRelation::setStereotypes)
+ || attr("a", relation, &DRelation::endAUid, &DRelation::setEndAUid)
+ || attr("b", relation, &DRelation::endBUid, &DRelation::setEndBUid)
+ || attr("name", relation, &DRelation::name, &DRelation::setName)
+ || attr("points", relation, &DRelation::intermediatePoints, &DRelation::setIntermediatePoints)
|| end;
}
@@ -254,7 +256,7 @@ template<class Archive>
inline void Access<Archive, DRelation::IntermediatePoint>::serialize(Archive &archive, DRelation::IntermediatePoint &point)
{
archive || tag(point)
- || attr(QStringLiteral("pos"), point, &DRelation::IntermediatePoint::pos, &DRelation::IntermediatePoint::setPos)
+ || attr("pos", point, &DRelation::IntermediatePoint::pos, &DRelation::IntermediatePoint::setPos)
|| end;
}
@@ -289,7 +291,7 @@ inline void Access<Archive, DDependency>::serialize(Archive &archive, DDependenc
{
archive || tag(dependency)
|| base<DRelation>(dependency)
- || attr(QStringLiteral("direction"), dependency, &DDependency::direction, &DDependency::setDirection)
+ || attr("direction", dependency, &DDependency::direction, &DDependency::setDirection)
|| end;
}
@@ -304,10 +306,10 @@ template<class Archive>
inline void Access<Archive, DAssociationEnd>::serialize(Archive &archive, DAssociationEnd &associationEnd)
{
archive || tag(associationEnd)
- || attr(QStringLiteral("name"), associationEnd, &DAssociationEnd::name, &DAssociationEnd::setName)
- || attr(QStringLiteral("cradinality"), associationEnd, &DAssociationEnd::cardinality, &DAssociationEnd::setCardinatlity)
- || attr(QStringLiteral("navigable"), associationEnd, &DAssociationEnd::isNavigable, &DAssociationEnd::setNavigable)
- || attr(QStringLiteral("kind"), associationEnd, &DAssociationEnd::kind, &DAssociationEnd::setKind)
+ || attr("name", associationEnd, &DAssociationEnd::name, &DAssociationEnd::setName)
+ || attr("cradinality", associationEnd, &DAssociationEnd::cardinality, &DAssociationEnd::setCardinatlity)
+ || attr("navigable", associationEnd, &DAssociationEnd::isNavigable, &DAssociationEnd::setNavigable)
+ || attr("kind", associationEnd, &DAssociationEnd::kind, &DAssociationEnd::setKind)
|| end;
}
@@ -321,14 +323,47 @@ inline void Access<Archive, DAssociation>::serialize(Archive &archive, DAssociat
{
archive || tag(association)
|| base<DRelation>(association)
- || attr(QStringLiteral("class"), association, &DAssociation::assoicationClassUid, &DAssociation::setAssociationClassUid)
- || attr(QStringLiteral("a"), association, &DAssociation::endA, &DAssociation::setEndA)
- || attr(QStringLiteral("b"), association, &DAssociation::endB, &DAssociation::setEndB)
+ || attr("class", association, &DAssociation::assoicationClassUid, &DAssociation::setAssociationClassUid)
+ || attr("a", association, &DAssociation::endA, &DAssociation::setEndA)
+ || attr("b", association, &DAssociation::endB, &DAssociation::setEndB)
|| end;
}
QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DAssociation)
+// DConnection
+
+QARK_REGISTER_TYPE_NAME(DConnectionEnd, "DConnectionEnd")
+QARK_ACCESS_SERIALIZE(DConnectionEnd)
+
+template<class Archive>
+inline void Access<Archive, DConnectionEnd>::serialize(Archive &archive, DConnectionEnd &connectionEnd)
+{
+ archive || tag(connectionEnd)
+ || attr("name", connectionEnd, &DConnectionEnd::name, &DConnectionEnd::setName)
+ || attr("cradinality", connectionEnd, &DConnectionEnd::cardinality, &DConnectionEnd::setCardinatlity)
+ || attr("navigable", connectionEnd, &DConnectionEnd::isNavigable, &DConnectionEnd::setNavigable)
+ || end;
+}
+
+QARK_REGISTER_TYPE_NAME(DConnection, "DConnection")
+QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, DConnection, DElement)
+QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, DConnection, DRelation)
+QARK_ACCESS_SERIALIZE(DConnection)
+
+template<class Archive>
+inline void Access<Archive, DConnection>::serialize(Archive &archive, DConnection &connection)
+{
+ archive || tag(connection)
+ || base<DRelation>(connection)
+ || attr("custom-relation", connection, &DConnection::customRelationId, &DConnection::setCustomRelationId)
+ || attr("a", connection, &DConnection::endA, &DConnection::setEndA)
+ || attr("b", connection, &DConnection::endB, &DConnection::setEndB)
+ || end;
+}
+
+QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DConnection)
+
// DAnnotation
QARK_REGISTER_TYPE_NAME(DAnnotation, "DAnnotation")
@@ -340,11 +375,11 @@ inline void Access<Archive, DAnnotation>::serialize(Archive &archive, DAnnotatio
{
archive || tag(annotation)
|| base<DElement>(annotation)
- || attr(QStringLiteral("text"), annotation, &DAnnotation::text, &DAnnotation::setText)
- || attr(QStringLiteral("pos"), annotation, &DAnnotation::pos, &DAnnotation::setPos)
- || attr(QStringLiteral("rect"), annotation, &DAnnotation::rect, &DAnnotation::setRect)
- || attr(QStringLiteral("auto-sized"), annotation, &DAnnotation::isAutoSized, &DAnnotation::setAutoSized)
- || attr(QStringLiteral("visual-role"), annotation, &DAnnotation::visualRole, &DAnnotation::setVisualRole)
+ || attr("text", annotation, &DAnnotation::text, &DAnnotation::setText)
+ || attr("pos", annotation, &DAnnotation::pos, &DAnnotation::setPos)
+ || attr("rect", annotation, &DAnnotation::rect, &DAnnotation::setRect)
+ || attr("auto-sized", annotation, &DAnnotation::isAutoSized, &DAnnotation::setAutoSized)
+ || attr("visual-role", annotation, &DAnnotation::visualRole, &DAnnotation::setVisualRole)
|| end;
}
@@ -361,12 +396,31 @@ inline void Access<Archive, DBoundary>::serialize(Archive &archive, DBoundary &b
{
archive || tag(boundary)
|| base<DElement>(boundary)
- || attr(QStringLiteral("text"), boundary, &DBoundary::text, &DBoundary::setText)
- || attr(QStringLiteral("pos"), boundary, &DBoundary::pos, &DBoundary::setPos)
- || attr(QStringLiteral("rect"), boundary, &DBoundary::rect, &DBoundary::setRect)
+ || attr("text", boundary, &DBoundary::text, &DBoundary::setText)
+ || attr("pos", boundary, &DBoundary::pos, &DBoundary::setPos)
+ || attr("rect", boundary, &DBoundary::rect, &DBoundary::setRect)
|| end;
}
QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DBoundary)
+// DSwimlane
+
+QARK_REGISTER_TYPE_NAME(DSwimlane, "DSwimlane")
+QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, DSwimlane, DElement)
+QARK_ACCESS_SERIALIZE(DSwimlane)
+
+template<class Archive>
+inline void Access<Archive, DSwimlane>::serialize(Archive &archive, DSwimlane &swimlane)
+{
+ archive || tag(swimlane)
+ || base<DElement>(swimlane)
+ || attr("text", swimlane, &DSwimlane::text, &DSwimlane::setText)
+ || attr("horizontal", swimlane, &DSwimlane::isHorizontal, &DSwimlane::setHorizontal)
+ || attr("pos", swimlane, &DSwimlane::pos, &DSwimlane::setPos)
+ || end;
+}
+
+QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DSwimlane)
+
} // namespace qark
diff --git a/src/libs/modelinglib/qmt/serializer/infrastructureserializer.h b/src/libs/modelinglib/qmt/serializer/infrastructureserializer.h
index 1814fb6a9d..29a0cc69ad 100644
--- a/src/libs/modelinglib/qmt/serializer/infrastructureserializer.h
+++ b/src/libs/modelinglib/qmt/serializer/infrastructureserializer.h
@@ -57,9 +57,9 @@ inline void load(Archive &archive, qmt::Uid &uid)
template<class Archive, class T>
inline void serialize(Archive &archive, qmt::Handle<T> &handle)
{
- archive || tag(QStringLiteral("handle"), handle)
- || attr(QStringLiteral("uid"), handle, &qmt::Handle<T>::uid, &qmt::Handle<T>::setUid)
- || attr(QStringLiteral("target"), handle, &qmt::Handle<T>::target, &qmt::Handle<T>::setTarget)
+ archive || tag("handle", handle)
+ || attr("uid", handle, &qmt::Handle<T>::uid, &qmt::Handle<T>::setUid)
+ || attr("target", handle, &qmt::Handle<T>::target, &qmt::Handle<T>::setTarget)
|| end;
}
@@ -68,8 +68,8 @@ inline void serialize(Archive &archive, qmt::Handle<T> &handle)
template<class Archive, class T>
inline void serialize(Archive &archive, qmt::Handles<T> &handles)
{
- archive || tag(QStringLiteral("handles"), handles)
- || attr(QStringLiteral("handles"), handles, &qmt::Handles<T>::get, &qmt::Handles<T>::set)
+ archive || tag("handles", handles)
+ || attr("handles", handles, &qmt::Handles<T>::get, &qmt::Handles<T>::set)
|| end;
}
diff --git a/src/libs/modelinglib/qmt/serializer/modelserializer.cpp b/src/libs/modelinglib/qmt/serializer/modelserializer.cpp
index e141c050e9..66a96472de 100644
--- a/src/libs/modelinglib/qmt/serializer/modelserializer.cpp
+++ b/src/libs/modelinglib/qmt/serializer/modelserializer.cpp
@@ -41,6 +41,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/massociation.h"
#include "qmt/model/minheritance.h"
+#include "qmt/model/mconnection.h"
#include "qmt/diagram/delement.h"
@@ -79,8 +80,8 @@ inline void Access<Archive, MSourceExpansion>::serialize(Archive &archive, MSour
{
archive || tag(sourceExpansion)
|| base<MExpansion>(sourceExpansion)
- || attr(QStringLiteral("source"), sourceExpansion, &MSourceExpansion::sourceId, &MSourceExpansion::setSourceId)
- || attr(QStringLiteral("transient"), sourceExpansion, &MSourceExpansion::isTransient, &MSourceExpansion::setTransient)
+ || attr("source", sourceExpansion, &MSourceExpansion::sourceId, &MSourceExpansion::setSourceId)
+ || attr("transient", sourceExpansion, &MSourceExpansion::isTransient, &MSourceExpansion::setTransient)
|| end;
}
@@ -95,10 +96,10 @@ template<class Archive>
inline void Access<Archive, MElement>::serialize(Archive &archive, MElement &element)
{
archive || tag(element)
- || attr(QStringLiteral("uid"), element, &MElement::uid, &MElement::setUid)
- || attr(QStringLiteral("flags"), element, &MElement::flags, &MElement::setFlags)
- || attr(QStringLiteral("expansion"), element, &MElement::expansion, &MElement::setExpansion)
- || attr(QStringLiteral("stereotypes"), element, &MElement::stereotypes, &MElement::setStereotypes)
+ || attr("uid", element, &MElement::uid, &MElement::setUid)
+ || attr("flags", element, &MElement::flags, &MElement::setFlags)
+ || attr("expansion", element, &MElement::expansion, &MElement::setExpansion)
+ || attr("stereotypes", element, &MElement::stereotypes, &MElement::setStereotypes)
|| end;
}
@@ -115,9 +116,9 @@ inline void Access<Archive, MObject>::serialize(Archive &archive, MObject &objec
{
archive || tag(object)
|| base<MElement>(object)
- || attr(QStringLiteral("name"), object, &MObject::name, &MObject::setName)
- || attr(QStringLiteral("children"), object, &MObject::children, &MObject::setChildren)
- || attr(QStringLiteral("relations"), object, &MObject::relations, &MObject::setRelations)
+ || attr("name", object, &MObject::name, &MObject::setName)
+ || attr("children", object, &MObject::children, &MObject::setChildren)
+ || attr("relations", object, &MObject::relations, &MObject::setRelations)
|| end;
}
@@ -152,9 +153,9 @@ inline void Access<Archive, MClass>::serialize(Archive &archive, MClass &klass)
{
archive || tag(klass)
|| base<MObject>(klass)
- || attr(QStringLiteral("namespace"), klass, &MClass::umlNamespace, &MClass::setUmlNamespace)
- || attr(QStringLiteral("template"), klass, &MClass::templateParameters, &MClass::setTemplateParameters)
- || attr(QStringLiteral("members"), klass, &MClass::members, &MClass::setMembers)
+ || attr("namespace", klass, &MClass::umlNamespace, &MClass::setUmlNamespace)
+ || attr("template", klass, &MClass::templateParameters, &MClass::setTemplateParameters)
+ || attr("members", klass, &MClass::members, &MClass::setMembers)
|| end;
}
@@ -169,13 +170,13 @@ template<class Archive>
inline void Access<Archive, MClassMember>::serialize(Archive &archive, MClassMember &member)
{
archive || tag(member)
- || attr(QStringLiteral("uid"), member, &MClassMember::uid, &MClassMember::setUid)
- || attr(QStringLiteral("stereotypes"), member, &MClassMember::stereotypes, &MClassMember::setStereotypes)
- || attr(QStringLiteral("group"), member, &MClassMember::group, &MClassMember::setGroup)
- || attr(QStringLiteral("visibility"), member, &MClassMember::visibility, &MClassMember::setVisibility)
- || attr(QStringLiteral("type"), member, &MClassMember::memberType, &MClassMember::setMemberType)
- || attr(QStringLiteral("properties"), member, &MClassMember::properties, &MClassMember::setProperties)
- || attr(QStringLiteral("declaration"), member, &MClassMember::declaration, &MClassMember::setDeclaration)
+ || attr("uid", member, &MClassMember::uid, &MClassMember::setUid)
+ || attr("stereotypes", member, &MClassMember::stereotypes, &MClassMember::setStereotypes)
+ || attr("group", member, &MClassMember::group, &MClassMember::setGroup)
+ || attr("visibility", member, &MClassMember::visibility, &MClassMember::setVisibility)
+ || attr("type", member, &MClassMember::memberType, &MClassMember::setMemberType)
+ || attr("properties", member, &MClassMember::properties, &MClassMember::setProperties)
+ || attr("declaration", member, &MClassMember::declaration, &MClassMember::setDeclaration)
|| end;
}
@@ -210,9 +211,9 @@ inline void Access<Archive, MDiagram>::serialize(Archive &archive, MDiagram &dia
{
archive || tag(diagram)
|| base<MObject>(diagram)
- || attr(QStringLiteral("elements"), diagram, &MDiagram::diagramElements, &MDiagram::setDiagramElements)
- || attr(QStringLiteral("last-modified"), diagram, &MDiagram::lastModified, &MDiagram::setLastModified)
- || attr(QStringLiteral("toolbarid"), diagram, &MDiagram::toolbarId, &MDiagram::setToolbarId)
+ || attr("elements", diagram, &MDiagram::diagramElements, &MDiagram::setDiagramElements)
+ || attr("last-modified", diagram, &MDiagram::lastModified, &MDiagram::setLastModified)
+ || attr("toolbarid", diagram, &MDiagram::toolbarId, &MDiagram::setToolbarId)
|| end;
}
@@ -248,9 +249,9 @@ inline void Access<Archive, MItem>::serialize(Archive &archive, MItem &item)
{
archive || tag(item)
|| base<MObject>(item)
- || attr(QStringLiteral("variety-editable"), item, &MItem::isVarietyEditable, &MItem::setVarietyEditable)
- || attr(QStringLiteral("variety"), item, &MItem::variety, &MItem::setVariety)
- || attr(QStringLiteral("shape-editable"), item, &MItem::isShapeEditable, &MItem::setShapeEditable)
+ || attr("variety-editable", item, &MItem::isVarietyEditable, &MItem::setVarietyEditable)
+ || attr("variety", item, &MItem::variety, &MItem::setVariety)
+ || attr("shape-editable", item, &MItem::isShapeEditable, &MItem::setShapeEditable)
|| end;
}
@@ -267,9 +268,9 @@ inline void Access<Archive, MRelation>::serialize(Archive &archive, MRelation &r
{
archive || tag(relation)
|| base<MElement>(relation)
- || attr(QStringLiteral("name"), relation, &MRelation::name, &MRelation::setName)
- || attr(QStringLiteral("a"), relation, &MRelation::endAUid, &MRelation::setEndAUid)
- || attr(QStringLiteral("b"), relation, &MRelation::endBUid, &MRelation::setEndBUid)
+ || attr("name", relation, &MRelation::name, &MRelation::setName)
+ || attr("a", relation, &MRelation::endAUid, &MRelation::setEndAUid)
+ || attr("b", relation, &MRelation::endBUid, &MRelation::setEndBUid)
|| end;
}
@@ -304,7 +305,7 @@ inline void Access<Archive, MDependency>::serialize(Archive &archive, MDependenc
{
archive || tag(dependency)
|| base<MRelation>(dependency)
- || attr(QStringLiteral("direction"), dependency, &MDependency::direction, &MDependency::setDirection)
+ || attr("direction", dependency, &MDependency::direction, &MDependency::setDirection)
|| end;
}
@@ -319,10 +320,10 @@ template<class Archive>
inline void Access<Archive, MAssociationEnd>::serialize(Archive &archive, MAssociationEnd &associationEnd)
{
archive || tag(associationEnd)
- || attr(QStringLiteral("name"), associationEnd, &MAssociationEnd::name, &MAssociationEnd::setName)
- || attr(QStringLiteral("cardinality"), associationEnd, &MAssociationEnd::cardinality, &MAssociationEnd::setCardinality)
- || attr(QStringLiteral("navigable"), associationEnd, &MAssociationEnd::isNavigable, &MAssociationEnd::setNavigable)
- || attr(QStringLiteral("kind"), associationEnd, &MAssociationEnd::kind, &MAssociationEnd::setKind)
+ || attr("name", associationEnd, &MAssociationEnd::name, &MAssociationEnd::setName)
+ || attr("cardinality", associationEnd, &MAssociationEnd::cardinality, &MAssociationEnd::setCardinality)
+ || attr("navigable", associationEnd, &MAssociationEnd::isNavigable, &MAssociationEnd::setNavigable)
+ || attr("kind", associationEnd, &MAssociationEnd::kind, &MAssociationEnd::setKind)
|| end;
}
@@ -336,12 +337,45 @@ inline void Access<Archive, MAssociation>::serialize(Archive &archive, MAssociat
{
archive || tag(association)
|| base<MRelation>(association)
- || attr(QStringLiteral("class"), association, &MAssociation::assoicationClassUid, &MAssociation::setAssociationClassUid)
- || attr(QStringLiteral("a"), association, &MAssociation::endA, &MAssociation::setEndA)
- || attr(QStringLiteral("b"), association, &MAssociation::endB, &MAssociation::setEndB)
+ || attr("class", association, &MAssociation::assoicationClassUid, &MAssociation::setAssociationClassUid)
+ || attr("a", association, &MAssociation::endA, &MAssociation::setEndA)
+ || attr("b", association, &MAssociation::endB, &MAssociation::setEndB)
|| end;
}
QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, MAssociation)
+// MConnection
+
+QARK_REGISTER_TYPE_NAME(MConnectionEnd, "MConnectionEnd")
+QARK_ACCESS_SERIALIZE(MConnectionEnd)
+
+template<class Archive>
+inline void Access<Archive, MConnectionEnd>::serialize(Archive &archive, MConnectionEnd &connectionEnd)
+{
+ archive || tag(connectionEnd)
+ || attr("name", connectionEnd, &MConnectionEnd::name, &MConnectionEnd::setName)
+ || attr("cardinality", connectionEnd, &MConnectionEnd::cardinality, &MConnectionEnd::setCardinality)
+ || attr("navigable", connectionEnd, &MConnectionEnd::isNavigable, &MConnectionEnd::setNavigable)
+ || end;
+}
+
+QARK_REGISTER_TYPE_NAME(MConnection, "MConnection")
+QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, MConnection, MElement)
+QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, MConnection, MRelation)
+QARK_ACCESS_SERIALIZE(MConnection)
+
+template<class Archive>
+inline void Access<Archive, MConnection>::serialize(Archive &archive, MConnection &connection)
+{
+ archive || tag(connection)
+ || base<MRelation>(connection)
+ || attr("custom-relation", connection, &MConnection::customRelationId, &MConnection::setCustomRelationId)
+ || attr("a", connection, &MConnection::endA, &MConnection::setEndA)
+ || attr("b", connection, &MConnection::endB, &MConnection::setEndB)
+ || end;
+}
+
+QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, MConnection)
+
} // namespace qark
diff --git a/src/libs/modelinglib/qmt/serializer/projectserializer.cpp b/src/libs/modelinglib/qmt/serializer/projectserializer.cpp
index 13338ed175..d1ddc8de73 100644
--- a/src/libs/modelinglib/qmt/serializer/projectserializer.cpp
+++ b/src/libs/modelinglib/qmt/serializer/projectserializer.cpp
@@ -51,10 +51,10 @@ QARK_REGISTER_TYPE_NAME(Project, "Project")
template<class Archive>
void serialize(Archive &archive, Project &project)
{
- archive || qark::tag(QStringLiteral("project"), project)
- || qark::attr(QStringLiteral("uid"), project, &Project::uid, &Project::setUid)
- || qark::attr(QStringLiteral("root-package"), project, &Project::rootPackage, &Project::setRootPackage)
- || qark::attr(QStringLiteral("config-path"), project, &Project::configPath, &Project::setConfigPath)
+ archive || qark::tag("project", project)
+ || qark::attr("uid", project, &Project::uid, &Project::setUid)
+ || qark::attr("root-package", project, &Project::rootPackage, &Project::setRootPackage)
+ || qark::attr("config-path", project, &Project::configPath, &Project::setConfigPath)
|| qark::end;
}
@@ -72,7 +72,7 @@ ProjectSerializer::~ProjectSerializer()
void ProjectSerializer::save(const QString &fileName, const Project *project)
{
- QMT_CHECK(project);
+ QMT_ASSERT(project, return);
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly))
@@ -108,7 +108,7 @@ QByteArray ProjectSerializer::save(const Project *project)
void ProjectSerializer::load(const QString &fileName, Project *project)
{
- QMT_CHECK(project);
+ QMT_ASSERT(project, return);
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly))
@@ -133,9 +133,9 @@ void ProjectSerializer::load(const QString &fileName, Project *project)
archive >> qark::end;
archive.endDocument();
} catch (const qark::QXmlInArchive::FileFormatException &) {
- throw FileIOException(QStringLiteral("illegal file format"), fileName);
+ throw FileIOException("illegal file format", fileName);
} catch (...) {
- throw FileIOException(QStringLiteral("serialization error"), fileName);
+ throw FileIOException("serialization error", fileName);
}
#ifdef USE_COMPRESSED_FILES
@@ -157,7 +157,7 @@ void ProjectSerializer::write(QXmlStreamWriter *writer, const Project *project)
archive << qark::end;
archive.endDocument();
} catch (...) {
- throw IOException(QStringLiteral("serialization error"));
+ throw IOException("serialization error");
}
}
diff --git a/src/libs/modelinglib/qmt/stereotype/customrelation.cpp b/src/libs/modelinglib/qmt/stereotype/customrelation.cpp
new file mode 100644
index 0000000000..b51abbe367
--- /dev/null
+++ b/src/libs/modelinglib/qmt/stereotype/customrelation.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "customrelation.h"
+
+namespace qmt {
+
+void CustomRelation::End::setEndItems(const QList<QString> &endItems)
+{
+ m_endItems = endItems;
+}
+
+void CustomRelation::End::setRole(const QString &role)
+{
+ m_role = role;
+}
+
+void CustomRelation::End::setCardinality(const QString &cardinality)
+{
+ m_cardinality = cardinality;
+}
+
+void CustomRelation::End::setNavigable(bool navigable)
+{
+ m_navigable = navigable;
+}
+
+void CustomRelation::End::setRelationship(CustomRelation::Relationship relationship)
+{
+ m_relationship = relationship;
+}
+
+void CustomRelation::End::setHead(CustomRelation::Head head)
+{
+ m_head = head;
+}
+
+void CustomRelation::End::setShape(const IconShape &shape)
+{
+ m_shape = shape;
+}
+
+
+CustomRelation::CustomRelation()
+{
+}
+
+CustomRelation::~CustomRelation()
+{
+}
+
+bool CustomRelation::isNull() const
+{
+ return m_id.isEmpty();
+}
+
+void CustomRelation::setElement(CustomRelation::Element element)
+{
+ m_element = element;
+}
+
+void CustomRelation::setId(const QString &id)
+{
+ m_id = id;
+}
+
+void CustomRelation::setTitle(const QString &title)
+{
+ m_title = title;
+}
+
+void CustomRelation::setEndItems(const QList<QString> &endItems)
+{
+ m_endItems = endItems;
+}
+
+void CustomRelation::setStereotypes(const QSet<QString> &stereotypes)
+{
+ m_stereotypes = stereotypes;
+}
+
+void CustomRelation::setName(const QString &name)
+{
+ m_name = name;
+}
+
+void CustomRelation::setDirection(CustomRelation::Direction direction)
+{
+ m_direction = direction;
+}
+
+void CustomRelation::setEndA(const CustomRelation::End &end)
+{
+ m_endA = end;
+}
+
+void CustomRelation::setEndB(const CustomRelation::End &end)
+{
+ m_endB = end;
+}
+
+void CustomRelation::setShaftPattern(CustomRelation::ShaftPattern shaftPattern)
+{
+ m_shaftPattern = shaftPattern;
+}
+
+void CustomRelation::setColorType(CustomRelation::ColorType colorType)
+{
+ m_colorType = colorType;
+}
+
+void CustomRelation::setColor(const QColor &color)
+{
+ m_color = color;
+}
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/stereotype/customrelation.h b/src/libs/modelinglib/qmt/stereotype/customrelation.h
new file mode 100644
index 0000000000..0b72be20fd
--- /dev/null
+++ b/src/libs/modelinglib/qmt/stereotype/customrelation.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Jochen Becher
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "iconshape.h"
+
+#include <QString>
+#include <QList>
+#include <QSet>
+#include <QColor>
+
+namespace qmt {
+
+class QMT_EXPORT CustomRelation
+{
+public:
+ enum class Element {
+ Relation,
+ Dependency,
+ Inheritance,
+ Association
+ };
+
+ enum class Direction {
+ AtoB,
+ BToA,
+ Bi
+ };
+
+ enum class Relationship {
+ Association,
+ Aggregation,
+ Composition
+ };
+
+ enum class ShaftPattern {
+ Solid,
+ Dash,
+ Dot,
+ DashDot,
+ DashDotDot
+ };
+
+ enum class Head {
+ None,
+ Shape,
+ Arrow,
+ Triangle,
+ FilledTriangle,
+ Diamond,
+ FilledDiamond
+ };
+
+ enum class ColorType {
+ EndA,
+ EndB,
+ Custom
+ };
+
+ class End {
+ public:
+ QList<QString> endItems() const { return m_endItems; }
+ void setEndItems(const QList<QString> &endItems);
+ QString role() const { return m_role; }
+ void setRole(const QString &role);
+ QString cardinality() const { return m_cardinality; }
+ void setCardinality(const QString &cardinality);
+ bool navigable() const { return m_navigable; }
+ void setNavigable(bool navigable);
+ Relationship relationship() const { return m_relationship; }
+ void setRelationship(Relationship relationship);
+ Head head() const { return m_head; }
+ void setHead(Head head);
+ IconShape shape() const { return m_shape; }
+ void setShape(const IconShape &shape);
+
+ private:
+ QList<QString> m_endItems;
+ QString m_role;
+ QString m_cardinality;
+ bool m_navigable = false;
+ Relationship m_relationship = Relationship::Association;
+ Head m_head = Head::None;
+ IconShape m_shape;
+ };
+
+ CustomRelation();
+ ~CustomRelation();
+
+ bool isNull() const;
+ Element element() const { return m_element; }
+ void setElement(Element element);
+ QString id() const { return m_id; }
+ void setId(const QString &id);
+ QString title() const { return m_title; }
+ void setTitle(const QString &title);
+ QList<QString> endItems() const { return m_endItems; }
+ void setEndItems(const QList<QString> &endItems);
+ QSet<QString> stereotypes() const { return m_stereotypes; }
+ void setStereotypes(const QSet<QString> &stereotypes);
+ QString name() const { return m_name; }
+ void setName(const QString &name);
+ Direction direction() const { return m_direction; }
+ void setDirection(Direction direction);
+ End endA() const { return m_endA; }
+ void setEndA(const End &end);
+ End endB() const { return m_endB; }
+ void setEndB(const End &end);
+ ShaftPattern shaftPattern() const { return m_shaftPattern; }
+ void setShaftPattern(ShaftPattern shaftPattern);
+ ColorType colorType() const { return m_colorType; }
+ void setColorType(ColorType colorType);
+ QColor color() const { return m_color; }
+ void setColor(const QColor &color);
+
+private:
+ Element m_element = Element::Relation;
+ QString m_id;
+ QString m_title;
+ QList<QString> m_endItems;
+ QSet<QString> m_stereotypes;
+ QString m_name;
+ Direction m_direction = Direction::AtoB;
+ End m_endA;
+ End m_endB;
+ ShaftPattern m_shaftPattern = ShaftPattern::Solid;
+ ColorType m_colorType = ColorType::EndA;
+ QColor m_color;
+};
+
+inline uint qHash(CustomRelation::Relationship relationship) {
+ return ::qHash(static_cast<int>(relationship));
+}
+
+inline uint qHash(CustomRelation::ShaftPattern pattern) {
+ return ::qHash(static_cast<int>(pattern));
+}
+
+inline uint qHash(CustomRelation::Head head) {
+ return ::qHash(static_cast<int>(head));
+}
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp
index d9a4be058b..f138684b64 100644
--- a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp
+++ b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp
@@ -34,11 +34,11 @@
#include <QPainter>
template<class T>
-QList<T *> CloneAll(const QList<T *> &rhs)
+QList<T *> cloneAll(const QList<T *> &rhs)
{
QList<T *> result;
foreach (T *t, rhs)
- result.append(t != 0 ? t->Clone() : 0);
+ result.append(t ? t->clone() : nullptr);
return result;
}
@@ -50,7 +50,7 @@ public:
IconShapePrivate() = default;
IconShapePrivate(const IconShapePrivate &rhs)
- : m_shapes(CloneAll(rhs.m_shapes))
+ : m_shapes(cloneAll(rhs.m_shapes))
{
}
@@ -63,7 +63,7 @@ public:
{
if (this != &rhs) {
qDeleteAll(m_shapes);
- m_shapes = CloneAll(rhs.m_shapes);
+ m_shapes = cloneAll(rhs.m_shapes);
}
return *this;
}
@@ -75,10 +75,10 @@ public:
PathShape *IconShape::IconShapePrivate::activePath()
{
- PathShape *pathShape = 0;
+ PathShape *pathShape = nullptr;
if (m_shapes.count() > 0)
pathShape = dynamic_cast<PathShape *>(m_shapes.last());
- if (pathShape == 0) {
+ if (!pathShape) {
pathShape = new PathShape();
m_shapes.append(pathShape);
}
@@ -132,6 +132,16 @@ void IconShape::addEllipse(const ShapePointF &center, const ShapeSizeF &radius)
d->m_shapes.append(new EllipseShape(center, radius));
}
+void IconShape::addDiamond(const ShapePointF &center, const ShapeSizeF &size, bool filled)
+{
+ d->m_shapes.append(new DiamondShape(center, size, filled));
+}
+
+void IconShape::addTriangle(const ShapePointF &center, const ShapeSizeF &size, bool filled)
+{
+ d->m_shapes.append(new TriangleShape(center, size, filled));
+}
+
void IconShape::addArc(const ShapePointF &center, const ShapeSizeF &radius, qreal startAngle, qreal spanAngle)
{
d->m_shapes.append(new ArcShape(center, radius, startAngle, spanAngle));
diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.h b/src/libs/modelinglib/qmt/stereotype/iconshape.h
index 0efea797ff..215dc8adec 100644
--- a/src/libs/modelinglib/qmt/stereotype/iconshape.h
+++ b/src/libs/modelinglib/qmt/stereotype/iconshape.h
@@ -54,6 +54,8 @@ public:
void addRoundedRect(const ShapePointF &pos, const ShapeSizeF &size, const ShapeValueF &radius);
void addCircle(const ShapePointF &center, const ShapeValueF &radius);
void addEllipse(const ShapePointF &center, const ShapeSizeF &radius);
+ void addDiamond(const ShapePointF &center, const ShapeSizeF &size, bool filled);
+ void addTriangle(const ShapePointF &center, const ShapeSizeF &size, bool filled);
void addArc(const ShapePointF &center, const ShapeSizeF &radius,
qreal startAngle, qreal spanAngle);
diff --git a/src/libs/modelinglib/qmt/stereotype/shape.h b/src/libs/modelinglib/qmt/stereotype/shape.h
index 467266b961..9bf56bd5b2 100644
--- a/src/libs/modelinglib/qmt/stereotype/shape.h
+++ b/src/libs/modelinglib/qmt/stereotype/shape.h
@@ -35,7 +35,7 @@ class IShape
public:
virtual ~IShape() { }
- virtual IShape *Clone() const = 0;
+ virtual IShape *clone() const = 0;
virtual void accept(ShapeVisitor *visitor) = 0;
virtual void accept(ShapeConstVisitor *visitor) const = 0;
};
diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp
index 552852c1e0..880835287a 100644
--- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp
+++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp
@@ -75,6 +75,37 @@ void ShapePaintVisitor::visitEllipse(const EllipseShape *shapeEllipse)
radius.width(), radius.height());
}
+void ShapePaintVisitor::visitDiamond(const DiamondShape *shapeDiamond)
+{
+ m_painter->save();
+ m_painter->setRenderHint(QPainter::Antialiasing, true);
+ QPainterPath path;
+ QPointF center = shapeDiamond->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ QSizeF size = shapeDiamond->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ path.moveTo(center + QPointF(0.0, size.height() / 2.0));
+ path.lineTo(center + QPointF(-size.width() / 2.0, 0.0));
+ path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
+ path.lineTo(center + QPointF(size.width() / 2.0, 0.0));
+ path.closeSubpath();
+ m_painter->drawPath(path);
+ m_painter->restore();
+}
+
+void ShapePaintVisitor::visitTriangle(const TriangleShape *shapeTriangle)
+{
+ m_painter->save();
+ m_painter->setRenderHint(QPainter::Antialiasing, true);
+ QPainterPath path;
+ QPointF center = shapeTriangle->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ QSizeF size = shapeTriangle->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ path.moveTo(center + QPointF(size.width() / 2.0, size.height() / 2.0));
+ path.lineTo(center + QPointF(-size.width() / 2.0, size.height() / 2.0));
+ path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
+ path.closeSubpath();
+ m_painter->drawPath(path);
+ m_painter->restore();
+}
+
void ShapePaintVisitor::visitArc(const ArcShape *shapeArc)
{
QSizeF radius = shapeArc->radius().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
@@ -160,6 +191,31 @@ void ShapeSizeVisitor::visitEllipse(const EllipseShape *shapeEllipse)
m_boundingRect |= QRectF(shapeEllipse->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size) - QPointF(radius.width(), radius.height()), radius * 2.0);
}
+void ShapeSizeVisitor::visitDiamond(const DiamondShape *shapeDiamond)
+{
+ QPainterPath path;
+ QPointF center = shapeDiamond->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ QSizeF size = shapeDiamond->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ path.moveTo(center + QPointF(0.0, size.height() / 2.0));
+ path.lineTo(center + QPointF(-size.width() / 2.0, 0.0));
+ path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
+ path.lineTo(center + QPointF(size.width() / 2.0, 0.0));
+ path.closeSubpath();
+ m_boundingRect |= path.boundingRect();
+}
+
+void ShapeSizeVisitor::visitTriangle(const TriangleShape *shapeTriangle)
+{
+ QPainterPath path;
+ QPointF center = shapeTriangle->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ QSizeF size = shapeTriangle->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
+ path.moveTo(center + QPointF(size.width() / 2.0, size.height() / 2.0));
+ path.lineTo(center + QPointF(-size.width() / 2.0, size.height() / 2.0));
+ path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
+ path.closeSubpath();
+ m_boundingRect |= path.boundingRect();
+}
+
void ShapeSizeVisitor::visitArc(const ArcShape *shapeArc)
{
// TODO this is the max bound rect; not the minimal one
diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h
index 67a90ee6ac..92e340e3e9 100644
--- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h
+++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h
@@ -45,6 +45,8 @@ public:
void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) override;
void visitCircle(const CircleShape *shapeCircle) override;
void visitEllipse(const EllipseShape *shapeEllipse) override;
+ void visitDiamond(const DiamondShape *shapeDiamond) override;
+ void visitTriangle(const TriangleShape *shapeTriangle) override;
void visitArc(const ArcShape *shapeArc) override;
void visitPath(const PathShape *shapePath) override;
@@ -69,6 +71,8 @@ public:
void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) override;
void visitCircle(const CircleShape *shapeCircle) override;
void visitEllipse(const EllipseShape *shapeEllipse) override;
+ void visitDiamond(const DiamondShape *shapeDiamond) override;
+ void visitTriangle(const TriangleShape *shapeTriangle) override;
void visitArc(const ArcShape *shapeArc) override;
void visitPath(const PathShape *shapePath) override;
diff --git a/src/libs/modelinglib/qmt/stereotype/shapes.cpp b/src/libs/modelinglib/qmt/stereotype/shapes.cpp
index 05f6e61e5a..0ee04f9bb0 100644
--- a/src/libs/modelinglib/qmt/stereotype/shapes.cpp
+++ b/src/libs/modelinglib/qmt/stereotype/shapes.cpp
@@ -27,7 +27,7 @@
namespace qmt {
-IShape *LineShape::Clone() const
+IShape *LineShape::clone() const
{
return new LineShape(*this);
}
@@ -42,7 +42,7 @@ void LineShape::accept(ShapeConstVisitor *visitor) const
visitor->visitLine(this);
}
-IShape *RectShape::Clone() const
+IShape *RectShape::clone() const
{
return new RectShape(*this);
}
@@ -57,7 +57,7 @@ void RectShape::accept(ShapeConstVisitor *visitor) const
visitor->visitRect(this);
}
-IShape *RoundedRectShape::Clone() const
+IShape *RoundedRectShape::clone() const
{
return new RoundedRectShape(*this);
}
@@ -72,7 +72,7 @@ void RoundedRectShape::accept(ShapeConstVisitor *visitor) const
visitor->visitRoundedRect(this);
}
-IShape *CircleShape::Clone() const
+IShape *CircleShape::clone() const
{
return new CircleShape(*this);
}
@@ -87,7 +87,7 @@ void CircleShape::accept(ShapeConstVisitor *visitor) const
visitor->visitCircle(this);
}
-IShape *EllipseShape::Clone() const
+IShape *EllipseShape::clone() const
{
return new EllipseShape(*this);
}
@@ -102,7 +102,37 @@ void EllipseShape::accept(ShapeConstVisitor *visitor) const
visitor->visitEllipse(this);
}
-IShape *ArcShape::Clone() const
+IShape *DiamondShape::clone() const
+{
+ return new DiamondShape(*this);
+}
+
+void DiamondShape::accept(ShapeVisitor *visitor)
+{
+ visitor->visitDiamond(this);
+}
+
+void DiamondShape::accept(ShapeConstVisitor *visitor) const
+{
+ visitor->visitDiamond(this);
+}
+
+IShape *TriangleShape::clone() const
+{
+ return new TriangleShape(*this);
+}
+
+void TriangleShape::accept(ShapeVisitor *visitor)
+{
+ visitor->visitTriangle(this);
+}
+
+void TriangleShape::accept(ShapeConstVisitor *visitor) const
+{
+ visitor->visitTriangle(this);
+}
+
+IShape *ArcShape::clone() const
{
return new ArcShape(*this);
}
@@ -125,7 +155,7 @@ PathShape::~PathShape()
{
}
-IShape *PathShape::Clone() const
+IShape *PathShape::clone() const
{
return new PathShape(*this);
}
diff --git a/src/libs/modelinglib/qmt/stereotype/shapes.h b/src/libs/modelinglib/qmt/stereotype/shapes.h
index 88f4c6e392..145fcb4bb6 100644
--- a/src/libs/modelinglib/qmt/stereotype/shapes.h
+++ b/src/libs/modelinglib/qmt/stereotype/shapes.h
@@ -49,7 +49,7 @@ public:
ShapePointF pos1() const { return m_pos1; }
ShapePointF pos2() const { return m_pos2; }
- IShape *Clone() const override;
+ IShape *clone() const override;
void accept(ShapeVisitor *visitor) override;
void accept(ShapeConstVisitor *visitor) const override;
@@ -72,7 +72,7 @@ public:
ShapePointF pos() const { return m_pos; }
ShapeSizeF size() const { return m_size; }
- IShape *Clone() const override;
+ IShape *clone() const override;
void accept(ShapeVisitor *visitor) override;
void accept(ShapeConstVisitor *visitor) const override;
@@ -97,7 +97,7 @@ public:
ShapeSizeF size() const { return m_size; }
ShapeValueF radius() const { return m_radius; }
- IShape *Clone() const override;
+ IShape *clone() const override;
void accept(ShapeVisitor *visitor) override;
void accept(ShapeConstVisitor *visitor) const override;
@@ -121,7 +121,7 @@ public:
ShapePointF center() const { return m_center; }
ShapeValueF radius() const { return m_radius; }
- IShape *Clone() const override;
+ IShape *clone() const override;
void accept(ShapeVisitor *visitor) override;
void accept(ShapeConstVisitor *visitor) const override;
@@ -144,7 +144,7 @@ public:
ShapePointF center() const { return m_center; }
ShapeSizeF radius() const { return m_radius; }
- IShape *Clone() const override;
+ IShape *clone() const override;
void accept(ShapeVisitor *visitor) override;
void accept(ShapeConstVisitor *visitor) const override;
@@ -153,6 +153,58 @@ private:
ShapeSizeF m_radius;
};
+class QMT_EXPORT DiamondShape : public IShape
+{
+public:
+ DiamondShape() = default;
+
+ DiamondShape(const ShapePointF &center, const ShapeSizeF &size, bool filled)
+ : m_center(center),
+ m_size(size),
+ m_filled(filled)
+ {
+ }
+
+ ShapePointF center() const { return m_center; }
+ ShapeSizeF size() const { return m_size; }
+ bool filled() const { return m_filled; }
+
+ IShape *clone() const override;
+ void accept(ShapeVisitor *visitor) override;
+ void accept(ShapeConstVisitor *visitor) const override;
+
+private:
+ ShapePointF m_center;
+ ShapeSizeF m_size;
+ bool m_filled = false;
+};
+
+class QMT_EXPORT TriangleShape : public IShape
+{
+public:
+ TriangleShape() = default;
+
+ TriangleShape(const ShapePointF &center, const ShapeSizeF &size, bool filled)
+ : m_center(center),
+ m_size(size),
+ m_filled(filled)
+ {
+ }
+
+ ShapePointF center() const { return m_center; }
+ ShapeSizeF size() const { return m_size; }
+ bool filled() const { return m_filled; }
+
+ IShape *clone() const override;
+ void accept(ShapeVisitor *visitor) override;
+ void accept(ShapeConstVisitor *visitor) const override;
+
+private:
+ ShapePointF m_center;
+ ShapeSizeF m_size;
+ bool m_filled = false;
+};
+
class QMT_EXPORT ArcShape : public IShape
{
public:
@@ -171,15 +223,15 @@ public:
qreal startAngle() const { return m_startAngle; }
qreal spanAngle() const { return m_spanAngle; }
- IShape *Clone() const override;
+ IShape *clone() const override;
void accept(ShapeVisitor *visitor) override;
void accept(ShapeConstVisitor *visitor) const override;
private:
ShapePointF m_center;
ShapeSizeF m_radius;
- qreal m_startAngle;
- qreal m_spanAngle;
+ qreal m_startAngle = 0.0;
+ qreal m_spanAngle = 0.0;
};
class QMT_EXPORT PathShape : public IShape
@@ -214,7 +266,7 @@ public:
QList<Element> elements() const { return m_elements; }
- IShape *Clone() const override;
+ IShape *clone() const override;
void accept(ShapeVisitor *visitor) override;
void accept(ShapeConstVisitor *visitor) const override;
diff --git a/src/libs/modelinglib/qmt/stereotype/shapevalue.h b/src/libs/modelinglib/qmt/stereotype/shapevalue.h
index 4b2f09a1dc..8e184b147d 100644
--- a/src/libs/modelinglib/qmt/stereotype/shapevalue.h
+++ b/src/libs/modelinglib/qmt/stereotype/shapevalue.h
@@ -80,9 +80,9 @@ public:
qreal actualSize) const;
private:
- qreal m_value;
- Unit m_unit;
- Origin m_origin;
+ qreal m_value = 0.0;
+ Unit m_unit = UnitRelative;
+ Origin m_origin = OriginSmart;
};
class QMT_EXPORT ShapePointF
diff --git a/src/libs/modelinglib/qmt/stereotype/shapevisitor.h b/src/libs/modelinglib/qmt/stereotype/shapevisitor.h
index 6adbba12ba..83f12ec5b8 100644
--- a/src/libs/modelinglib/qmt/stereotype/shapevisitor.h
+++ b/src/libs/modelinglib/qmt/stereotype/shapevisitor.h
@@ -32,6 +32,8 @@ class RectShape;
class RoundedRectShape;
class CircleShape;
class EllipseShape;
+class DiamondShape;
+class TriangleShape;
class ArcShape;
class PathShape;
@@ -45,6 +47,8 @@ public:
virtual void visitRoundedRect(RoundedRectShape *shapeRoundedRect) = 0;
virtual void visitCircle(CircleShape *shapeCircle) = 0;
virtual void visitEllipse(EllipseShape *shapeEllipse) = 0;
+ virtual void visitDiamond(DiamondShape *shapeDiamond) = 0;
+ virtual void visitTriangle(TriangleShape *shapeDiamond) = 0;
virtual void visitArc(ArcShape *shapeArc) = 0;
virtual void visitPath(PathShape *shapePath) = 0;
};
@@ -59,6 +63,8 @@ public:
virtual void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) = 0;
virtual void visitCircle(const CircleShape *shapeCircle) = 0;
virtual void visitEllipse(const EllipseShape *shapeEllipse) = 0;
+ virtual void visitDiamond(const DiamondShape *shapeDiamond) = 0;
+ virtual void visitTriangle(const TriangleShape *shapeDiamond) = 0;
virtual void visitArc(const ArcShape *shapeArc) = 0;
virtual void visitPath(const PathShape *shapePath) = 0;
};
diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp
index 8c7bbdbc26..5e5e4b73fd 100644
--- a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp
+++ b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp
@@ -25,12 +25,14 @@
#include "stereotypecontroller.h"
+#include "customrelation.h"
#include "stereotypeicon.h"
#include "shapepaintvisitor.h"
#include "toolbar.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/style/style.h"
+#include "utils/algorithm.h"
#include <QHash>
#include <QPainter>
@@ -46,7 +48,9 @@ class StereotypeController::StereotypeControllerPrivate
public:
QHash<QPair<StereotypeIcon::Element, QString>, QString> m_stereotypeToIconIdMap;
QHash<QString, StereotypeIcon> m_iconIdToStereotypeIconsMap;
+ QHash<QString, CustomRelation> m_relationIdToCustomRelationMap;
QList<Toolbar> m_toolbars;
+ QList<Toolbar> m_elementToolbars;
};
StereotypeController::StereotypeController(QObject *parent) :
@@ -70,6 +74,13 @@ QList<Toolbar> StereotypeController::toolbars() const
return d->m_toolbars;
}
+QList<Toolbar> StereotypeController::findToolbars(const QString &elementType) const
+{
+ return Utils::filtered(d->m_elementToolbars, [&elementType](const Toolbar &tb) {
+ return tb.elementTypes().contains(elementType);
+ });
+}
+
QList<QString> StereotypeController::knownStereotypes(StereotypeIcon::Element stereotypeElement) const
{
QSet<QString> stereotypes;
@@ -105,12 +116,17 @@ QList<QString> StereotypeController::filterStereotypesByIconId(const QString &st
return filteredStereotypes;
}
-StereotypeIcon StereotypeController::findStereotypeIcon(const QString &stereotypeIconId)
+StereotypeIcon StereotypeController::findStereotypeIcon(const QString &stereotypeIconId) const
{
QMT_CHECK(d->m_iconIdToStereotypeIconsMap.contains(stereotypeIconId));
return d->m_iconIdToStereotypeIconsMap.value(stereotypeIconId);
}
+CustomRelation StereotypeController::findCustomRelation(const QString &customRelationId) const
+{
+ return d->m_relationIdToCustomRelationMap.value(customRelationId);
+}
+
QIcon StereotypeController::createIcon(StereotypeIcon::Element element, const QList<QString> &stereotypes,
const QString &defaultIconPath, const Style *style, const QSize &size,
const QMarginsF &margins)
@@ -180,9 +196,17 @@ void StereotypeController::addStereotypeIcon(const StereotypeIcon &stereotypeIco
d->m_iconIdToStereotypeIconsMap.insert(stereotypeIcon.id(), stereotypeIcon);
}
+void StereotypeController::addCustomRelation(const CustomRelation &customRelation)
+{
+ d->m_relationIdToCustomRelationMap.insert(customRelation.id(), customRelation);
+}
+
void StereotypeController::addToolbar(const Toolbar &toolbar)
{
- d->m_toolbars.append(toolbar);
+ if (toolbar.elementTypes().isEmpty())
+ d->m_toolbars.append(toolbar);
+ else
+ d->m_elementToolbars.append(toolbar);
}
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h
index 990c2ae8b4..a010352e36 100644
--- a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h
+++ b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h
@@ -33,6 +33,7 @@
namespace qmt {
+class CustomRelation;
class Toolbar;
class Style;
@@ -42,23 +43,26 @@ class QMT_EXPORT StereotypeController : public QObject
class StereotypeControllerPrivate;
public:
- explicit StereotypeController(QObject *parent = 0);
+ explicit StereotypeController(QObject *parent = nullptr);
~StereotypeController() override;
QList<StereotypeIcon> stereotypeIcons() const;
QList<Toolbar> toolbars() const;
+ QList<Toolbar> findToolbars(const QString &elementType) const;
QList<QString> knownStereotypes(StereotypeIcon::Element stereotypeElement) const;
QString findStereotypeIconId(StereotypeIcon::Element element,
const QList<QString> &stereotypes) const;
QList<QString> filterStereotypesByIconId(const QString &stereotypeIconId,
const QList<QString> &stereotypes) const;
- StereotypeIcon findStereotypeIcon(const QString &stereotypeIconId);
+ StereotypeIcon findStereotypeIcon(const QString &stereotypeIconId) const;
+ CustomRelation findCustomRelation(const QString &customRelationId) const;
QIcon createIcon(StereotypeIcon::Element element, const QList<QString> &stereotypes,
const QString &defaultIconPath, const Style *style,
const QSize &size, const QMarginsF &margins);
void addStereotypeIcon(const StereotypeIcon &stereotypeIcon);
+ void addCustomRelation(const CustomRelation &customRelation);
void addToolbar(const Toolbar &toolbar);
private:
diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp
index 885eeade53..d3cc9d606b 100644
--- a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp
+++ b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp
@@ -27,21 +27,6 @@
namespace qmt {
-StereotypeIcon::StereotypeIcon()
- : m_width(100.0),
- m_height(100.0),
- m_minWidth(-1),
- m_minHeight(-1),
- m_sizeLock(LockNone),
- m_display(DisplaySmart),
- m_textAlignment(TextalignBelow)
-{
-}
-
-StereotypeIcon::~StereotypeIcon()
-{
-}
-
void StereotypeIcon::setId(const QString &id)
{
m_id = id;
diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h
index 354bd6f9ce..acdeb3f07e 100644
--- a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h
+++ b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h
@@ -67,9 +67,6 @@ public:
TextalignNone
};
- StereotypeIcon();
- ~StereotypeIcon();
-
QString id() const { return m_id; }
void setId(const QString &id);
QString title() const;
@@ -104,13 +101,13 @@ private:
QString m_title;
QSet<Element> m_elements;
QSet<QString> m_stereotypes;
- qreal m_width;
- qreal m_height;
- qreal m_minWidth;
- qreal m_minHeight;
- SizeLock m_sizeLock;
- Display m_display;
- TextAlignment m_textAlignment;
+ qreal m_width = 100.0;
+ qreal m_height = 100.0;
+ qreal m_minWidth = -1;
+ qreal m_minHeight = -1;
+ SizeLock m_sizeLock = LockNone;
+ Display m_display = DisplaySmart;
+ TextAlignment m_textAlignment = TextalignBelow;
QColor m_baseColor;
IconShape m_iconShape;
};
diff --git a/src/libs/modelinglib/qmt/stereotype/toolbar.cpp b/src/libs/modelinglib/qmt/stereotype/toolbar.cpp
index 9106d74360..95ae78a594 100644
--- a/src/libs/modelinglib/qmt/stereotype/toolbar.cpp
+++ b/src/libs/modelinglib/qmt/stereotype/toolbar.cpp
@@ -28,7 +28,6 @@
namespace qmt {
Toolbar::Toolbar()
- : m_priority(-1)
{
}
@@ -36,6 +35,11 @@ Toolbar::~Toolbar()
{
}
+void Toolbar::setToolbarType(Toolbar::ToolbarType toolbarType)
+{
+ m_toolbarType = toolbarType;
+}
+
void Toolbar::setId(const QString &id)
{
m_id = id;
@@ -46,6 +50,11 @@ void Toolbar::setPriority(int priority)
m_priority = priority;
}
+void Toolbar::setElementTypes(const QStringList &elementTypes)
+{
+ m_elementTypes = elementTypes;
+}
+
void Toolbar::setTools(const QList<Toolbar::Tool> &tools)
{
m_tools = tools;
diff --git a/src/libs/modelinglib/qmt/stereotype/toolbar.h b/src/libs/modelinglib/qmt/stereotype/toolbar.h
index b7422f408d..ab3974ec2e 100644
--- a/src/libs/modelinglib/qmt/stereotype/toolbar.h
+++ b/src/libs/modelinglib/qmt/stereotype/toolbar.h
@@ -35,6 +35,11 @@ namespace qmt {
class QMT_EXPORT Toolbar
{
public:
+ enum ToolbarType {
+ ObjectToolbar,
+ RelationToolbar
+ };
+
enum ToolType {
TooltypeTool,
TooltypeSeparator
@@ -65,16 +70,22 @@ public:
Toolbar();
~Toolbar();
+ ToolbarType toolbarType() const { return m_toolbarType; }
+ void setToolbarType(ToolbarType toolbarType);
QString id() const { return m_id; }
void setId(const QString &id);
int priority() const { return m_priority; }
void setPriority(int priority);
+ QStringList elementTypes() const { return m_elementTypes; }
+ void setElementTypes(const QStringList &elementTypes);
QList<Tool> tools() const { return m_tools; }
void setTools(const QList<Tool> &tools);
private:
+ ToolbarType m_toolbarType = ObjectToolbar;
QString m_id;
- int m_priority;
+ int m_priority = -1;
+ QStringList m_elementTypes;
QList<Tool> m_tools;
};
diff --git a/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp b/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp
index e6438e96c9..7f69962c67 100644
--- a/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp
+++ b/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp
@@ -40,7 +40,6 @@
#include <utils/algorithm.h>
#include <QSet>
-#include <QDebug>
namespace {
@@ -158,6 +157,26 @@ bool operator==(const BoundaryStyleKey &lhs, const BoundaryStyleKey &rhs)
return true;
}
+// TODO remove class if no attributes needed even with future extensions
+class SwimlaneStyleKey
+{
+};
+
+uint qHash(const SwimlaneStyleKey &styleKey)
+{
+ Q_UNUSED(styleKey);
+
+ return 1;
+}
+
+bool operator==(const SwimlaneStyleKey &lhs, const SwimlaneStyleKey &rhs)
+{
+ Q_UNUSED(lhs);
+ Q_UNUSED(rhs);
+
+ return true;
+}
+
DefaultStyleEngine::DefaultStyleEngine()
{
}
@@ -190,6 +209,8 @@ const Style *DefaultStyleEngine::applyStyle(const Style *baseStyle, StyleEngine:
parameters);
case TypeOther:
break;
+ case TypeSwimlane:
+ return applySwimlaneStyle(baseStyle, parameters);
}
return baseStyle;
}
@@ -371,6 +392,13 @@ const Style *DefaultStyleEngine::applyBoundaryStyle(const Style *baseStyle, cons
return applyBoundaryStyle(baseStyle, parameters);
}
+const Style *DefaultStyleEngine::applySwimlaneStyle(const Style *baseStyle, const DSwimlane *swimlane, const StyleEngine::Parameters *parameters)
+{
+ Q_UNUSED(swimlane);
+
+ return applySwimlaneStyle(baseStyle, parameters);
+}
+
const Style *DefaultStyleEngine::applyAnnotationStyle(const Style *baseStyle, DAnnotation::VisualRole visualRole,
const StyleEngine::Parameters *parameters)
{
@@ -429,6 +457,22 @@ const Style *DefaultStyleEngine::applyBoundaryStyle(const Style *baseStyle, cons
return derivedStyle;
}
+const Style *DefaultStyleEngine::applySwimlaneStyle(const Style *baseStyle, const StyleEngine::Parameters *parameters)
+{
+ Q_UNUSED(parameters);
+
+ SwimlaneStyleKey key;
+ const Style *derivedStyle = m_swimlaneStyleMap.value(key);
+ if (!derivedStyle) {
+ auto style = new Style(baseStyle->type());
+ style->setNormalFont(baseStyle->normalFont());
+ style->setTextBrush(baseStyle->textBrush());
+ m_swimlaneStyleMap.insert(key, style);
+ derivedStyle = style;
+ }
+ return derivedStyle;
+}
+
DefaultStyleEngine::ElementType DefaultStyleEngine::objectType(const DObject *object)
{
ElementType elementType;
@@ -459,7 +503,6 @@ bool DefaultStyleEngine::areStackingRoles(DObject::VisualPrimaryRole rhsPrimaryR
case DObject::SecondaryRoleLighter:
case DObject::SecondaryRoleDarker:
return lhsPrimaryRole == rhsPrimaryRole;
- break;
case DObject::SecondaryRoleSoften:
case DObject::SecondaryRoleOutline:
return false;
@@ -495,7 +538,11 @@ QColor DefaultStyleEngine::baseColor(ElementType elementType, ObjectVisuals obje
case TypeItem:
baseColor = QColor("#B995C6");
break;
- default:
+ case TypeRelation:
+ case TypeAnnotation:
+ case TypeBoundary:
+ case TypeSwimlane:
+ case TypeOther:
baseColor = QColor("#BF7D65");
break;
}
@@ -510,7 +557,7 @@ QColor DefaultStyleEngine::baseColor(ElementType elementType, ObjectVisuals obje
};
int index = static_cast<int>(objectVisuals.visualPrimaryRole()) - static_cast<int>(DObject::PrimaryRoleCustom1);
- QMT_CHECK(index >= 0 && index <= 4);
+ QMT_ASSERT(index >= 0 && index <= 4, return baseColor);
baseColor = customColors[index];
}
diff --git a/src/libs/modelinglib/qmt/style/defaultstyleengine.h b/src/libs/modelinglib/qmt/style/defaultstyleengine.h
index 792b9247a0..6f73b72b3f 100644
--- a/src/libs/modelinglib/qmt/style/defaultstyleengine.h
+++ b/src/libs/modelinglib/qmt/style/defaultstyleengine.h
@@ -42,6 +42,7 @@ class ObjectStyleKey;
class RelationStyleKey;
class AnnotationStyleKey;
class BoundaryStyleKey;
+class SwimlaneStyleKey;
class QMT_EXPORT DefaultStyleEngine : public StyleEngine
{
@@ -64,11 +65,14 @@ public:
const Parameters *parameters) override;
const Style *applyBoundaryStyle(const Style *baseStyle, const DBoundary *boundary,
const Parameters *parameters) override;
+ const Style *applySwimlaneStyle(const Style *baseStyle, const DSwimlane *swimlane,
+ const Parameters *parameters) override;
private:
const Style *applyAnnotationStyle(const Style *baseStyle, DAnnotation::VisualRole visualRole,
const Parameters *parameters);
const Style *applyBoundaryStyle(const Style *baseStyle, const Parameters *parameters);
+ const Style *applySwimlaneStyle(const Style *baseStyle, const Parameters *parameters);
ElementType objectType(const DObject *object);
@@ -87,6 +91,7 @@ private:
QHash<RelationStyleKey, const Style *> m_relationStyleMap;
QHash<AnnotationStyleKey, const Style *> m_annotationStyleMap;
QHash<BoundaryStyleKey, const Style *> m_boundaryStyleMap;
+ QHash<SwimlaneStyleKey, const Style *> m_swimlaneStyleMap;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/style/objectvisuals.cpp b/src/libs/modelinglib/qmt/style/objectvisuals.cpp
index e9c73267f8..a4bdadc26e 100644
--- a/src/libs/modelinglib/qmt/style/objectvisuals.cpp
+++ b/src/libs/modelinglib/qmt/style/objectvisuals.cpp
@@ -30,10 +30,6 @@
namespace qmt {
ObjectVisuals::ObjectVisuals()
- : m_visualPrimaryRole(DObject::PrimaryRoleNormal),
- m_visualSecondaryRole(DObject::SecondaryRoleNone),
- m_isEmphasized(false),
- m_depth(0)
{
}
diff --git a/src/libs/modelinglib/qmt/style/objectvisuals.h b/src/libs/modelinglib/qmt/style/objectvisuals.h
index 715252befc..0d708fe0a5 100644
--- a/src/libs/modelinglib/qmt/style/objectvisuals.h
+++ b/src/libs/modelinglib/qmt/style/objectvisuals.h
@@ -52,11 +52,11 @@ public:
void setDepth(int depth);
private:
- DObject::VisualPrimaryRole m_visualPrimaryRole;
- DObject::VisualSecondaryRole m_visualSecondaryRole;
- bool m_isEmphasized;
+ DObject::VisualPrimaryRole m_visualPrimaryRole = DObject::PrimaryRoleNormal;
+ DObject::VisualSecondaryRole m_visualSecondaryRole = DObject::SecondaryRoleNone;
+ bool m_isEmphasized = false;
QColor m_baseColor;
- int m_depth;
+ int m_depth = 0;
};
bool operator==(const ObjectVisuals &lhs, const ObjectVisuals &rhs);
diff --git a/src/libs/modelinglib/qmt/style/stylecontroller.cpp b/src/libs/modelinglib/qmt/style/stylecontroller.cpp
index 89a6fd243c..947fef9445 100644
--- a/src/libs/modelinglib/qmt/style/stylecontroller.cpp
+++ b/src/libs/modelinglib/qmt/style/stylecontroller.cpp
@@ -47,15 +47,14 @@ public:
}
private:
- StyleController *m_styleController = 0;
+ StyleController *m_styleController = nullptr;
};
StyleController::StyleController(QObject *parent)
: QObject(parent),
m_defaultStyle(new DefaultStyle),
m_relationStarterStyle(new RelationStarterStyle),
- m_defaultStyleEngine(new DefaultStyleEngine),
- m_suppressGradients(false)
+ m_defaultStyleEngine(new DefaultStyleEngine)
{
}
@@ -104,6 +103,12 @@ const Style *StyleController::adaptBoundaryStyle(const DBoundary *boundary)
return m_defaultStyleEngine->applyBoundaryStyle(m_defaultStyle.data(), boundary, &parameters);
}
+const Style *StyleController::adaptSwimlaneStyle(const DSwimlane *swimlane)
+{
+ Parameters parameters(this);
+ return m_defaultStyleEngine->applySwimlaneStyle(m_defaultStyle.data(), swimlane, &parameters);
+}
+
const Style *StyleController::relationStarterStyle()
{
return m_relationStarterStyle.data();
diff --git a/src/libs/modelinglib/qmt/style/stylecontroller.h b/src/libs/modelinglib/qmt/style/stylecontroller.h
index 344409e941..5a36da6e36 100644
--- a/src/libs/modelinglib/qmt/style/stylecontroller.h
+++ b/src/libs/modelinglib/qmt/style/stylecontroller.h
@@ -47,7 +47,7 @@ class QMT_EXPORT StyleController : public QObject
class Parameters;
public:
- explicit StyleController(QObject *parent = 0);
+ explicit StyleController(QObject *parent = nullptr);
~StyleController() override;
bool suppressGradients() const { return m_suppressGradients; }
@@ -60,13 +60,14 @@ public:
const Style *adaptRelationStyle(const StyledRelation &relation);
const Style *adaptAnnotationStyle(const DAnnotation *annotation);
const Style *adaptBoundaryStyle(const DBoundary *boundary);
+ const Style *adaptSwimlaneStyle(const DSwimlane *swimlane);
const Style *relationStarterStyle();
private:
QScopedPointer<Style> m_defaultStyle;
QScopedPointer<Style> m_relationStarterStyle;
QScopedPointer<StyleEngine> m_defaultStyleEngine;
- bool m_suppressGradients;
+ bool m_suppressGradients = false;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/style/styledobject.h b/src/libs/modelinglib/qmt/style/styledobject.h
index 26687065b7..ea6855234e 100644
--- a/src/libs/modelinglib/qmt/style/styledobject.h
+++ b/src/libs/modelinglib/qmt/style/styledobject.h
@@ -45,7 +45,7 @@ public:
QList<const DObject *> collidingObjects() const { return m_collidingObjects; }
private:
- const DObject *m_object;
+ const DObject *m_object = nullptr;
ObjectVisuals m_objectVisuals;
QList<const DObject *> m_collidingObjects;
};
diff --git a/src/libs/modelinglib/qmt/style/styledrelation.h b/src/libs/modelinglib/qmt/style/styledrelation.h
index 6811f3e3da..42fd5b883a 100644
--- a/src/libs/modelinglib/qmt/style/styledrelation.h
+++ b/src/libs/modelinglib/qmt/style/styledrelation.h
@@ -43,9 +43,9 @@ public:
const DObject *endB() const { return m_endB; }
private:
- const DRelation *m_relation;
- const DObject *m_endA;
- const DObject *m_endB;
+ const DRelation *m_relation = nullptr;
+ const DObject *m_endA = nullptr;
+ const DObject *m_endB = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/style/styleengine.h b/src/libs/modelinglib/qmt/style/styleengine.h
index 2da52b429a..1b2828ceb2 100644
--- a/src/libs/modelinglib/qmt/style/styleengine.h
+++ b/src/libs/modelinglib/qmt/style/styleengine.h
@@ -40,6 +40,7 @@ class StyledRelation;
class DAnnotation;
class DBoundary;
+class DSwimlane;
class QMT_EXPORT StyleEngine
{
@@ -52,7 +53,8 @@ public:
TypeItem,
TypeRelation,
TypeAnnotation,
- TypeBoundary
+ TypeBoundary,
+ TypeSwimlane
};
class Parameters
@@ -77,6 +79,8 @@ public:
const Parameters *) = 0;
virtual const Style *applyBoundaryStyle(const Style *baseStyle, const DBoundary *,
const Parameters *) = 0;
+ virtual const Style *applySwimlaneStyle(const Style *baseStyle, const DSwimlane *,
+ const Parameters *) = 0;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp
index 5a6fa6c381..e896f08462 100644
--- a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp
+++ b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp
@@ -31,6 +31,7 @@
#include "qmt/diagram/dboundary.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/dcomponent.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram/ditem.h"
@@ -39,6 +40,7 @@
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/dpackage.h"
#include "qmt/diagram/drelation.h"
+#include "qmt/diagram/dswimlane.h"
#include "qmt/diagram_scene/capabilities/moveable.h"
#include "qmt/diagram_scene/capabilities/resizable.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
@@ -47,9 +49,6 @@
namespace qmt {
AlignOnRasterVisitor::AlignOnRasterVisitor()
- : m_diagramController(0),
- m_sceneInspector(0),
- m_diagram(0)
{
}
@@ -135,6 +134,11 @@ void AlignOnRasterVisitor::visitDAssociation(DAssociation *association)
visitDRelation(association);
}
+void AlignOnRasterVisitor::visitDConnection(DConnection *connection)
+{
+ visitDRelation(connection);
+}
+
void AlignOnRasterVisitor::visitDAnnotation(DAnnotation *annotation)
{
IMoveable *moveable = m_sceneInspector->moveable(annotation, m_diagram);
@@ -153,4 +157,11 @@ void AlignOnRasterVisitor::visitDBoundary(DBoundary *boundary)
moveable->alignItemPositionToRaster(RASTER_WIDTH, RASTER_HEIGHT);
}
+void AlignOnRasterVisitor::visitDSwimlane(DSwimlane *swimlane)
+{
+ IMoveable *moveable = m_sceneInspector->moveable(swimlane, m_diagram);
+ if (moveable)
+ moveable->alignItemPositionToRaster(RASTER_WIDTH, RASTER_HEIGHT);
+}
+
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h
index 994cab48c3..195f1a5c51 100644
--- a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h
+++ b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h
@@ -55,13 +55,15 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
+ void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;
+ void visitDSwimlane(DSwimlane *swimlane) override;
private:
- DiagramController *m_diagramController;
- ISceneInspector *m_sceneInspector;
- MDiagram *m_diagram;
+ DiagramController *m_diagramController = nullptr;
+ ISceneInspector *m_sceneInspector = nullptr;
+ MDiagram *m_diagram = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
index d7619d7786..3ae964bbcf 100644
--- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
+++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
@@ -31,11 +31,14 @@
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram_controller/dselection.h"
#include "qmt/diagram/dannotation.h"
+#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/diagram/dclass.h"
-#include "qmt/diagram/dpackage.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/ditem.h"
+#include "qmt/diagram/dpackage.h"
#include "qmt/diagram/drelation.h"
+#include "qmt/diagram/dswimlane.h"
#include "qmt/diagram_ui/diagram_mime_types.h"
#include "qmt/model_controller/modelcontroller.h"
#include "qmt/model_controller/mselection.h"
@@ -44,6 +47,7 @@
#include "qmt/model/mcanvasdiagram.h"
#include "qmt/model/mclass.h"
#include "qmt/model/mcomponent.h"
+#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/minheritance.h"
@@ -51,6 +55,8 @@
#include "qmt/model/mobject.h"
#include "qmt/model/mpackage.h"
#include "qmt/model/msourceexpansion.h"
+#include "qmt/stereotype/customrelation.h"
+#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/tasks/alignonrastervisitor.h"
#include "qmt/tasks/isceneinspector.h"
#include "qmt/tasks/voidelementtasks.h"
@@ -70,8 +76,11 @@ static VoidElementTasks dummyElementTasks;
class DiagramSceneController::AcceptRelationVisitor : public MVoidConstVisitor
{
public:
- AcceptRelationVisitor(const MRelation *relation)
- : m_relation(relation)
+ AcceptRelationVisitor(StereotypeController *stereotypeController, const MRelation *relation,
+ RelationEnd relationEnd)
+ : m_stereotypeController(stereotypeController),
+ m_relation(relation),
+ m_relationEnd(relationEnd)
{
}
@@ -80,28 +89,49 @@ public:
void visitMObject(const MObject *object) override
{
Q_UNUSED(object);
- m_accepted = dynamic_cast<const MDependency *>(m_relation) != 0;
+ if (auto connection = dynamic_cast<const MConnection *>(m_relation)) {
+ CustomRelation customRelation = m_stereotypeController->findCustomRelation(connection->customRelationId());
+ if (!customRelation.isNull()) {
+ QMT_ASSERT(customRelation.element() == CustomRelation::Element::Relation, return);
+ CustomRelation::End customEnd = m_relationEnd == EndA ? customRelation.endA() : customRelation.endB();
+ QStringList endItems = customEnd.endItems();
+ if (endItems.isEmpty())
+ endItems = customRelation.endItems();
+ QString stereotypeIconId = m_stereotypeController->findStereotypeIconId(StereotypeIcon::ElementItem, object->stereotypes());
+ if (stereotypeIconId.isEmpty() && !m_variety.isEmpty())
+ stereotypeIconId = m_stereotypeController->findStereotypeIconId(StereotypeIcon::ElementItem, QStringList(m_variety));
+ m_accepted = endItems.contains(stereotypeIconId);
+ }
+ }
+ if (!m_accepted)
+ m_accepted = dynamic_cast<const MDependency *>(m_relation) != nullptr;
}
void visitMClass(const MClass *klass) override
{
- Q_UNUSED(klass);
- m_accepted = dynamic_cast<const MDependency *>(m_relation) != 0
- || dynamic_cast<const MInheritance *>(m_relation) != 0
- || dynamic_cast<const MAssociation *>(m_relation) != 0;
+ m_accepted = dynamic_cast<const MInheritance *>(m_relation) != nullptr
+ || dynamic_cast<const MAssociation *>(m_relation) != nullptr;
+ if (!m_accepted)
+ visitMObject(klass);
+ }
+
+ void visitMItem(const MItem *item) override
+ {
+ m_variety = item->variety();
+ visitMObject(item);
}
private:
- const MRelation *m_relation = 0;
+ StereotypeController *m_stereotypeController = nullptr;
+ const MRelation *m_relation = nullptr;
+ RelationEnd m_relationEnd = EndA;
+ QString m_variety;
bool m_accepted = false;
};
DiagramSceneController::DiagramSceneController(QObject *parent)
: QObject(parent),
- m_modelController(0),
- m_diagramController(0),
- m_elementTasks(&dummyElementTasks),
- m_sceneInspector(0)
+ m_elementTasks(&dummyElementTasks)
{
}
@@ -114,8 +144,8 @@ void DiagramSceneController::setModelController(ModelController *modelController
if (m_modelController == modelController)
return;
if (m_modelController) {
- disconnect(m_modelController, 0, this, 0);
- m_modelController = 0;
+ disconnect(m_modelController, nullptr, this, nullptr);
+ m_modelController = nullptr;
}
if (modelController)
m_modelController = modelController;
@@ -126,13 +156,18 @@ void DiagramSceneController::setDiagramController(DiagramController *diagramCont
if (m_diagramController == diagramController)
return;
if (m_diagramController) {
- disconnect(m_diagramController, 0, this, 0);
- m_diagramController = 0;
+ disconnect(m_diagramController, nullptr, this, nullptr);
+ m_diagramController = nullptr;
}
if (diagramController)
m_diagramController = diagramController;
}
+void DiagramSceneController::setStereotypeController(StereotypeController *stereotypeController)
+{
+ m_stereotypeController = stereotypeController;
+}
+
void DiagramSceneController::setElementTasks(IElementTasks *elementTasks)
{
m_elementTasks = elementTasks;
@@ -150,10 +185,10 @@ void DiagramSceneController::deleteFromDiagram(const DSelection &dselection, MDi
DSelection remainingDselection;
foreach (const DSelection::Index &index, dselection.indices()) {
DElement *delement = m_diagramController->findElement(index.elementKey(), diagram);
- QMT_CHECK(delement);
+ QMT_ASSERT(delement, return);
if (delement->modelUid().isValid()) {
MElement *melement = m_modelController->findElement(delement->modelUid());
- QMT_CHECK(melement);
+ QMT_ASSERT(melement, return);
if (melement->owner())
mselection.append(melement->uid(), melement->owner()->uid());
} else {
@@ -173,9 +208,9 @@ void DiagramSceneController::createDependency(DObject *endAObject, DObject *endB
m_diagramController->undoController()->beginMergeSequence(tr("Create Dependency"));
MObject *endAModelObject = m_modelController->findObject<MObject>(endAObject->modelUid());
- QMT_CHECK(endAModelObject);
+ QMT_ASSERT(endAModelObject, return);
MObject *endBModelObject = m_modelController->findObject<MObject>(endBObject->modelUid());
- QMT_CHECK(endBModelObject);
+ QMT_ASSERT(endBModelObject, return);
if (endAModelObject == endBModelObject)
return;
@@ -200,9 +235,9 @@ void DiagramSceneController::createInheritance(DClass *derivedClass, DClass *bas
m_diagramController->undoController()->beginMergeSequence(tr("Create Inheritance"));
MClass *derivedModelClass = m_modelController->findObject<MClass>(derivedClass->modelUid());
- QMT_CHECK(derivedModelClass);
+ QMT_ASSERT(derivedModelClass, return);
MClass *baseModelClass = m_modelController->findObject<MClass>(baseClass->modelUid());
- QMT_CHECK(baseModelClass);
+ QMT_ASSERT(baseModelClass, return);
if (derivedModelClass == baseModelClass)
return;
@@ -221,14 +256,15 @@ void DiagramSceneController::createInheritance(DClass *derivedClass, DClass *bas
}
void DiagramSceneController::createAssociation(DClass *endAClass, DClass *endBClass,
- const QList<QPointF> &intermediatePoints, MDiagram *diagram)
+ const QList<QPointF> &intermediatePoints, MDiagram *diagram,
+ std::function<void (MAssociation*, DAssociation*)> custom)
{
m_diagramController->undoController()->beginMergeSequence(tr("Create Association"));
MClass *endAModelObject = m_modelController->findObject<MClass>(endAClass->modelUid());
- QMT_CHECK(endAModelObject);
+ QMT_ASSERT(endAModelObject, return);
MClass *endBModelObject = m_modelController->findObject<MClass>(endBClass->modelUid());
- QMT_CHECK(endBModelObject);
+ QMT_ASSERT(endBModelObject, return);
// TODO allow self assignment with just one intermediate point and a nice round arrow
if (endAModelObject == endBModelObject && intermediatePoints.count() < 2)
@@ -243,6 +279,49 @@ void DiagramSceneController::createAssociation(DClass *endAClass, DClass *endBCl
m_modelController->addRelation(endAModelObject, modelAssociation);
DRelation *relation = addRelation(modelAssociation, intermediatePoints, diagram);
+ DAssociation *diagramAssociation = dynamic_cast<DAssociation *>(relation);
+ QMT_CHECK(diagramAssociation);
+
+ if (custom)
+ custom(modelAssociation, diagramAssociation);
+
+ m_diagramController->undoController()->endMergeSequence();
+
+ if (relation)
+ emit newElementCreated(relation, diagram);
+}
+
+void DiagramSceneController::createConnection(const QString &customRelationId,
+ DObject *endAObject, DObject *endBObject,
+ const QList<QPointF> &intermediatePoints, MDiagram *diagram,
+ std::function<void (MConnection *, DConnection *)> custom)
+{
+ m_diagramController->undoController()->beginMergeSequence(tr("Create Connection"));
+
+ MObject *endAModelObject = m_modelController->findObject<MObject>(endAObject->modelUid());
+ QMT_CHECK(endAModelObject);
+ MObject *endBModelObject = m_modelController->findObject<MObject>(endBObject->modelUid());
+ QMT_CHECK(endBModelObject);
+
+ // TODO allow self assignment with just one intermediate point and a nice round arrow
+ if (endAModelObject == endBModelObject && intermediatePoints.count() < 2)
+ return;
+
+ auto modelConnection = new MConnection();
+ modelConnection->setCustomRelationId(customRelationId);
+ modelConnection->setEndAUid(endAModelObject->uid());
+ MConnectionEnd endA = modelConnection->endA();
+ endA.setNavigable(true);
+ modelConnection->setEndA(endA);
+ modelConnection->setEndBUid(endBModelObject->uid());
+ m_modelController->addRelation(endAModelObject, modelConnection);
+
+ DRelation *relation = addRelation(modelConnection, intermediatePoints, diagram);
+ DConnection *diagramConnection = dynamic_cast<DConnection *>(relation);
+ QMT_CHECK(diagramConnection);
+
+ if (custom)
+ custom(modelConnection, diagramConnection);
m_diagramController->undoController()->endMergeSequence();
@@ -252,29 +331,29 @@ void DiagramSceneController::createAssociation(DClass *endAClass, DClass *endBCl
bool DiagramSceneController::relocateRelationEndA(DRelation *relation, DObject *targetObject)
{
- return relocateRelationEnd(relation, targetObject, &MRelation::endAUid, &MRelation::setEndAUid);
+ return relocateRelationEnd(relation, targetObject, EndA, &MRelation::endAUid, &MRelation::setEndAUid);
}
bool DiagramSceneController::relocateRelationEndB(DRelation *relation, DObject *targetObject)
{
- return relocateRelationEnd(relation, targetObject, &MRelation::endBUid, &MRelation::setEndBUid);
+ return relocateRelationEnd(relation, targetObject, EndB, &MRelation::endBUid, &MRelation::setEndBUid);
}
bool DiagramSceneController::isAddingAllowed(const Uid &modelElementKey, MDiagram *diagram)
{
MElement *modelElement = m_modelController->findElement(modelElementKey);
- QMT_CHECK(modelElement);
+ QMT_ASSERT(modelElement, return false);
if (m_diagramController->hasDelegate(modelElement, diagram))
return false;
if (auto modelRelation = dynamic_cast<MRelation *>(modelElement)) {
MObject *endAModelObject = m_modelController->findObject(modelRelation->endAUid());
- QMT_CHECK(endAModelObject);
+ QMT_ASSERT(endAModelObject, return false);
DObject *endADiagramObject = m_diagramController->findDelegate<DObject>(endAModelObject, diagram);
if (!endADiagramObject)
return false;
MObject *endBModelObject = m_modelController->findObject(modelRelation->endBUid());
- QMT_CHECK(endBModelObject);
+ QMT_ASSERT(endBModelObject, return false);
DObject *endBDiagramObject = m_diagramController->findDelegate<DObject>(endBModelObject, diagram);
if (!endBDiagramObject)
return false;
@@ -290,11 +369,11 @@ void DiagramSceneController::addExistingModelElement(const Uid &modelElementKey,
}
void DiagramSceneController::dropNewElement(const QString &newElementId, const QString &name, const QString &stereotype,
- DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram)
+ DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram,
+ const QPoint &viewPos, const QSize &viewSize)
{
if (newElementId == QLatin1String(ELEMENT_TYPE_ANNOTATION)) {
auto annotation = new DAnnotation();
- annotation->setText(QStringLiteral(""));
annotation->setPos(pos - QPointF(10.0, 10.0));
m_diagramController->addElement(annotation, diagram);
alignOnRaster(annotation, diagram);
@@ -305,9 +384,19 @@ void DiagramSceneController::dropNewElement(const QString &newElementId, const Q
m_diagramController->addElement(boundary, diagram);
alignOnRaster(boundary, diagram);
emit newElementCreated(boundary, diagram);
+ } else if (newElementId == QLatin1String(ELEMENT_TYPE_SWIMLANE)) {
+ auto swimlane = new DSwimlane();
+ qreal x = static_cast<qreal>(viewPos.x()) / viewSize.width();
+ qreal y = static_cast<qreal>(viewPos.y()) / viewSize.height();
+ bool horizontal = (y > x && (1-y) > x) || (y <= x && (1-y) <= x);
+ swimlane->setHorizontal(horizontal);
+ swimlane->setPos(horizontal ? pos.y() : pos.x());
+ m_diagramController->addElement(swimlane, diagram);
+ alignOnRaster(swimlane, diagram);
+ emit newElementCreated(swimlane, diagram);
} else {
MPackage *parentPackage = findSuitableParentPackage(topMostElementAtPos, diagram);
- MObject *newObject = 0;
+ MObject *newObject = nullptr;
QString newName;
if (newElementId == QLatin1String(ELEMENT_TYPE_PACKAGE)) {
auto package = new MPackage();
@@ -358,7 +447,7 @@ void DiagramSceneController::dropNewModelElement(MObject *modelObject, MPackage
MPackage *DiagramSceneController::findSuitableParentPackage(DElement *topmostDiagramElement, MDiagram *diagram)
{
- MPackage *parentPackage = 0;
+ MPackage *parentPackage = nullptr;
if (auto diagramPackage = dynamic_cast<DPackage *>(topmostDiagramElement)) {
parentPackage = m_modelController->findObject<MPackage>(diagramPackage->modelUid());
} else if (auto diagramObject = dynamic_cast<DObject *>(topmostDiagramElement)) {
@@ -366,9 +455,9 @@ MPackage *DiagramSceneController::findSuitableParentPackage(DElement *topmostDia
if (modelObject)
parentPackage = dynamic_cast<MPackage *>(modelObject->owner());
}
- if (parentPackage == 0 && diagram != 0)
+ if (!parentPackage && diagram)
parentPackage = dynamic_cast<MPackage *>(diagram->owner());
- if (parentPackage == 0)
+ if (!parentPackage)
parentPackage = m_modelController->rootPackage();
return parentPackage;
}
@@ -384,7 +473,7 @@ MDiagram *DiagramSceneController::findDiagramBySearchId(MPackage *package, const
}
}
}
- return 0;
+ return nullptr;
}
namespace {
@@ -582,7 +671,7 @@ void DiagramSceneController::alignOnRaster(DElement *element, MDiagram *diagram)
DElement *DiagramSceneController::addModelElement(const Uid &modelElementKey, const QPointF &pos, MDiagram *diagram)
{
- DElement *element = 0;
+ DElement *element = nullptr;
if (MObject *modelObject = m_modelController->findObject(modelElementKey)) {
element = addObject(modelObject, pos, diagram);
} else if (MRelation *modelRelation = m_modelController->findRelation(modelElementKey)) {
@@ -595,17 +684,17 @@ DElement *DiagramSceneController::addModelElement(const Uid &modelElementKey, co
DObject *DiagramSceneController::addObject(MObject *modelObject, const QPointF &pos, MDiagram *diagram)
{
- QMT_CHECK(modelObject);
+ QMT_ASSERT(modelObject, return nullptr);
if (m_diagramController->hasDelegate(modelObject, diagram))
- return 0;
+ return nullptr;
m_diagramController->undoController()->beginMergeSequence(tr("Add Element"));
DFactory factory;
modelObject->accept(&factory);
auto diagramObject = dynamic_cast<DObject *>(factory.product());
- QMT_CHECK(diagramObject);
+ QMT_ASSERT(diagramObject, return nullptr);
diagramObject->setPos(pos);
m_diagramController->addElement(diagramObject, diagram);
alignOnRaster(diagramObject, diagram);
@@ -657,26 +746,26 @@ DObject *DiagramSceneController::addObject(MObject *modelObject, const QPointF &
DRelation *DiagramSceneController::addRelation(MRelation *modelRelation, const QList<QPointF> &intermediatePoints,
MDiagram *diagram)
{
- QMT_CHECK(modelRelation);
+ QMT_ASSERT(modelRelation, return nullptr);
if (m_diagramController->hasDelegate(modelRelation, diagram))
- return 0;
+ return nullptr;
DFactory factory;
modelRelation->accept(&factory);
auto diagramRelation = dynamic_cast<DRelation *>(factory.product());
- QMT_CHECK(diagramRelation);
+ QMT_ASSERT(diagramRelation, return nullptr);
MObject *endAModelObject = m_modelController->findObject(modelRelation->endAUid());
- QMT_CHECK(endAModelObject);
+ QMT_ASSERT(endAModelObject, return nullptr);
DObject *endADiagramObject = m_diagramController->findDelegate<DObject>(endAModelObject, diagram);
- QMT_CHECK(endADiagramObject);
+ QMT_ASSERT(endADiagramObject, return nullptr);
diagramRelation->setEndAUid(endADiagramObject->uid());
MObject *endBModelObject = m_modelController->findObject(modelRelation->endBUid());
- QMT_CHECK(endBModelObject);
+ QMT_ASSERT(endBModelObject, return nullptr);
DObject *endBDiagramObject = m_diagramController->findDelegate<DObject>(endBModelObject, diagram);
- QMT_CHECK(endBDiagramObject);
+ QMT_ASSERT(endBDiagramObject, return nullptr);
diagramRelation->setEndBUid(endBDiagramObject->uid());
QList<DRelation::IntermediatePoint> relationPoints;
@@ -709,20 +798,21 @@ DRelation *DiagramSceneController::addRelation(MRelation *modelRelation, const Q
}
bool DiagramSceneController::relocateRelationEnd(DRelation *relation, DObject *targetObject,
+ RelationEnd relationEnd,
Uid (MRelation::*endUid)() const,
void (MRelation::*setEndUid)(const Uid &))
{
- QMT_CHECK(relation);
+ QMT_ASSERT(relation, return false);
if (targetObject && targetObject->uid() != relation->endAUid()) {
MRelation *modelRelation = m_modelController->findRelation(relation->modelUid());
- QMT_CHECK(modelRelation);
+ QMT_ASSERT(modelRelation, return false);
MObject *targetMObject = m_modelController->findObject(targetObject->modelUid());
- QMT_CHECK(targetMObject);
- AcceptRelationVisitor visitor(modelRelation);
+ QMT_ASSERT(targetMObject, return false);
+ AcceptRelationVisitor visitor(m_stereotypeController, modelRelation, relationEnd);
targetMObject->accept(&visitor);
if (visitor.isAccepted()) {
MObject *currentTargetMObject = m_modelController->findObject((modelRelation->*endUid)());
- QMT_CHECK(currentTargetMObject);
+ QMT_ASSERT(currentTargetMObject, return false);
m_modelController->undoController()->beginMergeSequence(tr("Relocate Relation"));
// move relation into new target if it was a child of the old target
if (currentTargetMObject == modelRelation->owner())
diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
index 967e02f51c..d0483a0301 100644
--- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
+++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
@@ -28,6 +28,8 @@
#include <QObject>
#include "qmt/infrastructure/qmt_global.h"
+#include <functional>
+
QT_BEGIN_NAMESPACE
class QPointF;
QT_END_NAMESPACE
@@ -37,14 +39,19 @@ namespace qmt {
class Uid;
class ModelController;
class DiagramController;
+class StereotypeController;
class MObject;
class MPackage;
class MDiagram;
class MRelation;
+class MAssociation;
+class MConnection;
class DElement;
class DObject;
class DClass;
class DRelation;
+class DAssociation;
+class DConnection;
class DSelection;
class IElementTasks;
class ISceneInspector;
@@ -55,8 +62,13 @@ class QMT_EXPORT DiagramSceneController : public QObject
class AcceptRelationVisitor;
+ enum RelationEnd {
+ EndA,
+ EndB
+ };
+
public:
- explicit DiagramSceneController(QObject *parent = 0);
+ explicit DiagramSceneController(QObject *parent = nullptr);
~DiagramSceneController() override;
signals:
@@ -68,6 +80,8 @@ public:
void setModelController(ModelController *modelController);
DiagramController *diagramController() const { return m_diagramController; }
void setDiagramController(DiagramController *diagramController);
+ StereotypeController *stereotypeController() const { return m_stereotypeController; }
+ void setStereotypeController(StereotypeController *stereotypeController);
IElementTasks *elementTasks() const { return m_elementTasks; }
void setElementTasks(IElementTasks *elementTasks);
ISceneInspector *sceneInspector() const { return m_sceneInspector; }
@@ -80,14 +94,18 @@ public:
void createInheritance(DClass *derivedClass, DClass *baseClass,
const QList<QPointF> &intermediatePoints, MDiagram *diagram);
void createAssociation(DClass *endAClass, DClass *endBClass,
- const QList<QPointF> &intermediatePoints, MDiagram *diagram);
+ const QList<QPointF> &intermediatePoints, MDiagram *diagram,
+ std::function<void (MAssociation*, DAssociation*)> custom = nullptr);
+ void createConnection(const QString &customRelationId, DObject *endAObject, DObject *endBObject,
+ const QList<QPointF> &intermediatePoints, MDiagram *diagram,
+ std::function<void (MConnection*, DConnection*)> custom = nullptr);
bool relocateRelationEndA(DRelation *relation, DObject *targetObject);
bool relocateRelationEndB(DRelation *relation, DObject *targetObject);
bool isAddingAllowed(const Uid &modelElementKey, MDiagram *diagram);
void addExistingModelElement(const Uid &modelElementKey, const QPointF &pos, MDiagram *diagram);
void dropNewElement(const QString &newElementId, const QString &name, const QString &stereotype,
- DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram);
+ DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram, const QPoint &viewPos, const QSize &viewSize);
void dropNewModelElement(MObject *modelObject, MPackage *parentPackage, const QPointF &pos,
MDiagram *diagram);
@@ -122,13 +140,14 @@ private:
DObject *addObject(MObject *modelObject, const QPointF &pos, MDiagram *diagram);
DRelation *addRelation(MRelation *modelRelation, const QList<QPointF> &intermediatePoints,
MDiagram *diagram);
- bool relocateRelationEnd(DRelation *relation, DObject *targetObject, Uid (MRelation::*endUid)() const,
- void (MRelation::*setEndUid)(const Uid &));
-
- ModelController *m_modelController;
- DiagramController *m_diagramController;
- IElementTasks *m_elementTasks;
- ISceneInspector *m_sceneInspector;
+ bool relocateRelationEnd(DRelation *relation, DObject *targetObject, RelationEnd relationEnd,
+ Uid (MRelation::*endUid)() const, void (MRelation::*setEndUid)(const Uid &));
+
+ ModelController *m_modelController = nullptr;
+ DiagramController *m_diagramController = nullptr;
+ StereotypeController *m_stereotypeController = nullptr;
+ IElementTasks *m_elementTasks = nullptr;
+ ISceneInspector *m_sceneInspector = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.cpp b/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.cpp
index 8bbb88f60f..a4bbd79528 100644
--- a/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.cpp
+++ b/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.cpp
@@ -31,8 +31,6 @@
namespace qmt {
FindDiagramVisitor::FindDiagramVisitor()
- : MVoidConstVisitor(),
- m_diagram(nullptr)
{
}
diff --git a/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.h b/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.h
index bd664629f1..6be8e188d9 100644
--- a/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.h
+++ b/src/libs/modelinglib/qmt/tasks/finddiagramvisitor.h
@@ -41,7 +41,7 @@ public:
void visitMDiagram(const MDiagram *diagram) override;
private:
- const MDiagram *m_diagram;
+ const MDiagram *m_diagram = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.cpp b/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.cpp
index cf73774f32..6fad5d6d34 100644
--- a/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.cpp
+++ b/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.cpp
@@ -30,8 +30,6 @@
namespace qmt {
FindRootDiagramVisitor::FindRootDiagramVisitor()
- : MVoidVisitor(),
- m_diagram(nullptr)
{
}
diff --git a/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.h b/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.h
index a520ef6e34..c06315a0cd 100644
--- a/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.h
+++ b/src/libs/modelinglib/qmt/tasks/findrootdiagramvisitor.h
@@ -42,7 +42,7 @@ public:
void visitMObject(MObject *object) override;
private:
- MDiagram *m_diagram;
+ MDiagram *m_diagram = nullptr;
};
} // namespace qmt
diff --git a/src/libs/modelinglib/qstringparser/qstringparser.h b/src/libs/modelinglib/qstringparser/qstringparser.h
index 8735e9b60b..76b5a9fa7c 100644
--- a/src/libs/modelinglib/qstringparser/qstringparser.h
+++ b/src/libs/modelinglib/qstringparser/qstringparser.h
@@ -62,7 +62,7 @@ private:
void (U::*setter() const)(V) { return m_setter; }
private:
U &m_object;
- void (U::*m_setter)(V) = 0;
+ void (U::*m_setter)(V) = nullptr;
};
public:
@@ -92,7 +92,7 @@ private:
template<typename V>
bool visit(RefNode<V> *node, int *index)
{
- V v = 0;
+ V v = nullptr;
if (!scan(&v, index))
return false;
node->ref() = v;
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/attribute.h b/src/libs/modelinglib/qtserialization/inc/qark/attribute.h
index 7070964d6f..4e90427e0d 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/attribute.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/attribute.h
@@ -54,7 +54,7 @@ public:
private:
QString m_qualifiedName;
- T *m_value = 0;
+ T *m_value = nullptr;
Parameters m_parameters;
};
@@ -110,7 +110,7 @@ public:
private:
QString m_qualifiedName;
const U &m_u;
- T (U::*m_getter)() const = 0;
+ T (U::*m_getter)() const = nullptr;
Parameters m_parameters;
};
@@ -155,7 +155,7 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- void (U::*m_setter)(T) = 0;
+ void (U::*m_setter)(T) = nullptr;
Parameters m_parameters;
};
@@ -205,8 +205,8 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- T (U::*m_getter)() const = 0;
- void (U::*m_setter)(V) = 0;
+ T (U::*m_getter)() const = nullptr;
+ void (U::*m_setter)(V) = nullptr;
Parameters m_parameters;
};
@@ -253,7 +253,7 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- T (*m_getFunc)(const U &) = 0;
+ T (*m_getFunc)(const U &) = nullptr;
Parameters m_parameters;
};
@@ -298,7 +298,7 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- void (*m_setFunc)(U &, T) = 0;
+ void (*m_setFunc)(U &, T) = nullptr;
Parameters m_parameters;
};
@@ -347,8 +347,8 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- T (*m_getFunc)(const U &) = 0;
- void (*m_setFunc)(U &, V) = 0;
+ T (*m_getFunc)(const U &) = nullptr;
+ void (*m_setFunc)(U &, V) = nullptr;
Parameters m_parameters;
};
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/baseclass.h b/src/libs/modelinglib/qtserialization/inc/qark/baseclass.h
index 4fae0f2e7a..d4252eaf48 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/baseclass.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/baseclass.h
@@ -87,13 +87,13 @@ Base<BASE, DERIVED> base(const QString &qualifiedName, DERIVED *&obj, const Para
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(DERIVED &obj)
{
- return Base<BASE, DERIVED>(QString(QStringLiteral("base-%1")).arg(typeUid<BASE>()), obj);
+ return Base<BASE, DERIVED>(QString("base-%1").arg(typeUid<BASE>()), obj);
}
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(DERIVED &obj, const Parameters &parameters)
{
- return Base<BASE, DERIVED>(QString(QStringLiteral("base-%1")).arg(typeUid<BASE>()),
+ return Base<BASE, DERIVED>(QString("base-%1").arg(typeUid<BASE>()),
obj, parameters);
}
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/qxmlinarchive.h b/src/libs/modelinglib/qtserialization/inc/qark/qxmlinarchive.h
index b11a4db04b..a32f823919 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/qxmlinarchive.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/qxmlinarchive.h
@@ -296,9 +296,7 @@ private:
public:
explicit QXmlInArchive(QXmlStreamReader &stream)
- : m_stream(stream),
- m_endTagWasRead(false),
- m_currentRefNode(0)
+ : m_stream(stream)
{
}
@@ -491,7 +489,7 @@ public:
{
public:
explicit ReferenceTag(ReferenceKind k = Nullpointer,
- const QString &string = QLatin1String(""))
+ const QString &string = QString())
: kind(k),
typeName(string)
{
@@ -587,7 +585,7 @@ private:
template<class T>
void visit(ObjectNode<T> *node, const XmlTag &tag)
{
- if (tag.m_id.isValid() && node->object().object() != 0)
+ if (tag.m_id.isValid() && node->object().object() != nullptr)
m_loadingRefMap.addObject(tag.m_id, node->object().object());
readChildren(node);
}
@@ -704,9 +702,9 @@ private:
m_currentRefNode = node;
T value = T();
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
*node->reference().value() = value;
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -719,9 +717,9 @@ private:
m_currentRefNode = node;
T value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().object().*(node->reference().setter()))(value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -734,9 +732,9 @@ private:
m_currentRefNode = node;
T value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().object().*(node->reference().setter()))(value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -749,9 +747,9 @@ private:
m_currentRefNode = node;
V value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().object().*(node->reference().setter()))(value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -764,9 +762,9 @@ private:
m_currentRefNode = node;
V value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().object().*(node->reference().setter()))(value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -779,9 +777,9 @@ private:
m_currentRefNode = node;
T value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().setterFunc())(node->reference().object(), value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -794,9 +792,9 @@ private:
m_currentRefNode = node;
T value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().setterFunc())(node->reference().object(), value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -809,9 +807,9 @@ private:
m_currentRefNode = node;
V value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().setterFunc())(node->reference().object(), value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -824,9 +822,9 @@ private:
m_currentRefNode = node;
V value;
load(*this, value, node->reference().parameters());
- if (m_currentRefNode != 0) { // ref node was not consumed by forward reference
+ if (m_currentRefNode) { // ref node was not consumed by forward reference
(node->reference().setterFunc())(node->reference().object(), value);
- m_currentRefNode = 0;
+ m_currentRefNode = nullptr;
}
XmlTag xmlTag = readTag();
if (!xmlTag.m_isEndTag || xmlTag.m_tagName != node->reference().qualifiedName())
@@ -837,10 +835,10 @@ private:
inline void skipUntilEndOfTag(const XmlTag &xmlTag);
QXmlStreamReader &m_stream;
- bool m_endTagWasRead;
+ bool m_endTagWasRead = false;
QStack<Node *> m_nodeStack;
impl::LoadingRefMap m_loadingRefMap;
- Node *m_currentRefNode;
+ Node *m_currentRefNode = nullptr;
};
QXmlInArchive::XmlTag QXmlInArchive::readTag()
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/qxmloutarchive.h b/src/libs/modelinglib/qtserialization/inc/qark/qxmloutarchive.h
index 91525173cb..8c51d0a2c4 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/qxmloutarchive.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/qxmloutarchive.h
@@ -52,8 +52,7 @@ public:
static const bool outArchive = true;
QXmlOutArchive(QXmlStreamWriter &stream)
- : m_stream(stream),
- m_isNextPointerAReference(false)
+ : m_stream(stream)
{
}
@@ -322,7 +321,7 @@ public:
private:
QXmlStreamWriter &m_stream;
impl::SavingRefMap m_savingRefMap;
- bool m_isNextPointerAReference;
+ bool m_isNextPointerAReference = false;
};
} // namespace qark
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/reference.h b/src/libs/modelinglib/qtserialization/inc/qark/reference.h
index c00c6b6664..0c5c9ba378 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/reference.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/reference.h
@@ -54,7 +54,7 @@ public:
private:
QString m_qualifiedName;
- T *m_value = 0;
+ T *m_value = nullptr;
Parameters m_parameters;
};
@@ -110,7 +110,7 @@ public:
private:
QString m_qualifiedName;
const U &m_u;
- T (U::*m_getter)() const = 0;
+ T (U::*m_getter)() const = nullptr;
Parameters m_parameters;
};
@@ -155,7 +155,7 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- void (U::*m_setter)(T) = 0;
+ void (U::*m_setter)(T) = nullptr;
Parameters m_parameters;
};
@@ -217,8 +217,8 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- T (U::*m_getter)() const = 0;
- void (U::*m_setter)(V) = 0;
+ T (U::*m_getter)() const = nullptr;
+ void (U::*m_setter)(V) = nullptr;
Parameters m_parameters;
};
@@ -279,7 +279,7 @@ public:
private:
QString m_qualifiedName;
const U &m_u;
- T (*m_getFunc)(const U &) = 0;
+ T (*m_getFunc)(const U &) = nullptr;
Parameters m_parameters;
};
@@ -324,7 +324,7 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- void (*m_setFunc)(U &, T) = 0;
+ void (*m_setFunc)(U &, T) = nullptr;
Parameters m_parameters;
};
@@ -386,8 +386,8 @@ public:
private:
QString m_qualifiedName;
U &m_u;
- T (*m_getFunc)(const U &) = 0;
- void (*m_setFunc)(U &, V) = 0;
+ T (*m_getFunc)(const U &) = nullptr;
+ void (*m_setFunc)(U &, V) = nullptr;
Parameters m_parameters;
};
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/serialize_basic.h b/src/libs/modelinglib/qtserialization/inc/qark/serialize_basic.h
index 695c53031d..1997d6630d 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/serialize_basic.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/serialize_basic.h
@@ -73,7 +73,7 @@ QARK_BASIC_SAVELOAD(QString)
template<class Archive>
inline void save(Archive &archive, const QPointF &point, const Parameters &)
{
- archive.write(QString(QStringLiteral("x:%1;y:%2")).arg(point.x()).arg(point.y()));
+ archive.write(QString("x:%1;y:%2").arg(point.x()).arg(point.y()));
}
template<class Archive>
@@ -81,7 +81,7 @@ inline void load(Archive &archive, QPointF &point, const Parameters &)
{
QString s;
archive.read(&s);
- if (QStringParser(s).parse(QStringLiteral("x:%1;y:%2"))
+ if (QStringParser(s).parse("x:%1;y:%2")
.arg(point, &QPointF::setX).arg(point, &QPointF::setY).failed()) {
throw typename Archive::FileFormatException();
}
@@ -92,7 +92,7 @@ inline void load(Archive &archive, QPointF &point, const Parameters &)
template<class Archive>
inline void save(Archive &archive, const QRectF &rect, const Parameters &)
{
- archive.write(QString(QStringLiteral("x:%1;y:%2;w:%3;h:%4"))
+ archive.write(QString("x:%1;y:%2;w:%3;h:%4")
.arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height()));
}
@@ -101,7 +101,7 @@ inline void load(Archive &archive, QRectF &point, const Parameters &)
{
QString s;
archive.read(&s);
- if (QStringParser(s).parse(QStringLiteral("x:%1;y:%2;w:%3;h:%4"))
+ if (QStringParser(s).parse("x:%1;y:%2;w:%3;h:%4")
.arg(point, &QRectF::setX).arg(point, &QRectF::setY)
.arg(point, &QRectF::setWidth).arg(point, &QRectF::setHeight).failed()) {
throw typename Archive::FileFormatException();
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/serialize_container.h b/src/libs/modelinglib/qtserialization/inc/qark/serialize_container.h
index a9d8e2a922..723194a64e 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/serialize_container.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/serialize_container.h
@@ -41,7 +41,7 @@ inline void save(Archive &archive, const QList<T> &list, const Parameters &)
{
archive << tag("qlist");
foreach (const T &t, list)
- archive << attr(QStringLiteral("item"), t);
+ archive << attr("item", t);
archive << end;
}
@@ -51,10 +51,10 @@ inline void save(Archive &archive, const QList<T *> &list, const Parameters &par
archive << tag("qlist");
if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
foreach (const T *t, list)
- archive << ref(QStringLiteral("item"), t);
+ archive << ref("item", t);
} else {
foreach (const T *t, list)
- archive << attr(QStringLiteral("item"), t);
+ archive << attr("item", t);
}
archive << end;
}
@@ -62,21 +62,21 @@ inline void save(Archive &archive, const QList<T *> &list, const Parameters &par
template<class Archive, class T>
inline void load(Archive &archive, QList<T> &list, const Parameters &)
{
- archive >> tag(QStringLiteral("qlist"));
- archive >> attr<QList<T>, const T &>(QStringLiteral("item"), list, &QList<T>::append);
+ archive >> tag("qlist");
+ archive >> attr<QList<T>, const T &>("item", list, &QList<T>::append);
archive >> end;
}
template<class Archive, class T>
inline void load(Archive &archive, QList<T *> &list, const Parameters &parameters)
{
- archive >> tag(QStringLiteral("qlist"));
+ archive >> tag("qlist");
if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
// why does the following line not compile but the line below selects the correct function?
//archive >> ref<QList<T *>, T * const &>("item", list, &QList<T *>::append);
- archive >> ref(QStringLiteral("item"), list, &QList<T *>::append);
+ archive >> ref("item", list, &QList<T *>::append);
} else {
- archive >> attr<QList<T *>, T * const &>(QStringLiteral("item"), list, &QList<T *>::append);
+ archive >> attr<QList<T *>, T * const &>("item", list, &QList<T *>::append);
}
archive >> end;
}
@@ -88,7 +88,7 @@ inline void save(Archive &archive, const QSet<T> &set, const Parameters &)
{
archive << tag("qset");
foreach (const T &t, set)
- archive << attr(QStringLiteral("item"), t);
+ archive << attr("item", t);
archive << end;
}
@@ -98,10 +98,10 @@ inline void save(Archive &archive, const QSet<T *> &set, const Parameters &param
archive << tag("qset");
if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
foreach (const T *t, set)
- archive << ref(QStringLiteral("item"), t);
+ archive << ref("item", t);
} else {
foreach (const T *t, set)
- archive << attr(QStringLiteral("item"), t);
+ archive << attr("item", t);
}
archive << end;
}
@@ -118,19 +118,19 @@ void insertIntoSet(QSet<T> &set, const T &t) {
template<class Archive, class T>
inline void load(Archive &archive, QSet<T> &set, const Parameters &)
{
- archive >> tag(QStringLiteral("qset"));
- archive >> attr<QSet<T>, const T &>(QStringLiteral("item"), set, &impl::insertIntoSet<T>);
+ archive >> tag("qset");
+ archive >> attr<QSet<T>, const T &>("item", set, &impl::insertIntoSet<T>);
archive >> end;
}
template<class Archive, class T>
inline void load(Archive &archive, QSet<T *> &set, const Parameters &parameters)
{
- archive >> tag(QStringLiteral("qset"));
+ archive >> tag("qset");
if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS))
- archive >> ref(QStringLiteral("item"), set, &impl::insertIntoSet<T *>);
+ archive >> ref("item", set, &impl::insertIntoSet<T *>);
else
- archive >> attr<QSet<T *>, T * const &>(QStringLiteral("item"), set,
+ archive >> attr<QSet<T *>, T * const &>("item", set,
&impl::insertIntoSet<T *>);
archive >> end;
}
@@ -155,25 +155,25 @@ public:
template<class Archive, class KEY, class VALUE>
inline void save(Archive &archive, const impl::KeyValuePair<KEY, VALUE> &pair, const Parameters &)
{
- archive << tag(QStringLiteral("pair"))
- << attr(QStringLiteral("key"), pair.m_key)
- << attr(QStringLiteral("value"), pair.m_value)
+ archive << tag("pair")
+ << attr("key", pair.m_key)
+ << attr("value", pair.m_value)
<< end;
}
template<class Archive, class KEY, class VALUE>
inline void load(Archive &archive, impl::KeyValuePair<KEY, VALUE> &pair, const Parameters &)
{
- archive >> tag(QStringLiteral("pair"))
- >> attr(QStringLiteral("key"), pair.m_key)
- >> attr(QStringLiteral("value"), pair.m_value)
+ archive >> tag("pair")
+ >> attr("key", pair.m_key)
+ >> attr("value", pair.m_value)
>> end;
}
template<class Archive, class KEY, class VALUE>
inline void save(Archive &archive, const QHash<KEY, VALUE> &hash, const Parameters &)
{
- archive << tag(QStringLiteral("qhash"));
+ archive << tag("qhash");
for (auto it = hash.begin(); it != hash.end(); ++it) {
impl::KeyValuePair<KEY, VALUE> pair(it.key(), it.value());
archive << attr("item", pair);
@@ -194,8 +194,8 @@ inline void keyValuePairInsert(QHash<KEY, VALUE> &hash, const KeyValuePair<KEY,
template<class Archive, class KEY, class VALUE>
inline void load(Archive &archive, QHash<KEY, VALUE> &hash, const Parameters &)
{
- archive >> tag(QStringLiteral("qhash"));
- archive >> attr(QStringLiteral("item"), hash, &impl::keyValuePairInsert<KEY, VALUE>);
+ archive >> tag("qhash");
+ archive >> attr("item", hash, &impl::keyValuePairInsert<KEY, VALUE>);
archive >> end;
}
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/serialize_pointer.h b/src/libs/modelinglib/qtserialization/inc/qark/serialize_pointer.h
index 876609643d..246f1eca84 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/serialize_pointer.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/serialize_pointer.h
@@ -45,7 +45,7 @@ inline void save(Archive &archive, T *p, const Parameters &)
} else {
archive.beginInstance(typeUid(*p));
typename registry::TypeRegistry<Archive, T>::TypeInfo typeData = typeInfo<Archive, T>(*p);
- if (typeData.m_saveFunc == 0)
+ if (!typeData.m_saveFunc)
throw UnregisteredType();
else
typeData.m_saveFunc(archive, p);
@@ -64,7 +64,7 @@ void load(Archive &archive, T *&p, const Parameters &)
typename Archive::ReferenceTag refTag = archive.readReferenceTag();
switch (refTag.kind) {
case Archive::Nullpointer:
- p = 0;
+ p = nullptr;
break;
case Archive::Pointer:
archive.read(p);
@@ -74,7 +74,7 @@ void load(Archive &archive, T *&p, const Parameters &)
registry::loadNonVirtualPointer<Archive,T>(archive, p);
} else {
typename registry::TypeRegistry<Archive, T>::TypeInfo typeData = typeInfo<Archive, T>(refTag.typeName);
- if (typeData.m_loadFunc == 0)
+ if (!typeData.m_loadFunc)
throw UnregisteredType();
else
typeData.m_loadFunc(archive, p);
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/tag.h b/src/libs/modelinglib/qtserialization/inc/qark/tag.h
index 24f81e5d92..9216e0cf66 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/tag.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/tag.h
@@ -73,7 +73,7 @@ public:
T *object() const { return m_object; }
private:
- T *m_object = 0;
+ T *m_object = nullptr;
};
inline Tag tag(const QString &qualifiedName)
diff --git a/src/libs/modelinglib/qtserialization/inc/qark/typeregistry.h b/src/libs/modelinglib/qtserialization/inc/qark/typeregistry.h
index aa0750cfdb..c92ac8f376 100644
--- a/src/libs/modelinglib/qtserialization/inc/qark/typeregistry.h
+++ b/src/libs/modelinglib/qtserialization/inc/qark/typeregistry.h
@@ -59,8 +59,8 @@ public:
static MapType &uidToNameMap() { return *typeidUidToNameMap; }
#if !defined(QT_NO_DEBUG)
- static bool hasNameToUidMap() { return typeidNameToUidMap != 0; }
- static bool hasUidToNameMap() { return typeidUidToNameMap != 0; }
+ static bool hasNameToUidMap() { return typeidNameToUidMap != nullptr; }
+ static bool hasUidToNameMap() { return typeidUidToNameMap != nullptr; }
#endif
protected:
@@ -119,8 +119,6 @@ public:
typedef Archive &(*LoadFuncType)(Archive &, BASE * &p);
explicit TypeInfo()
- : m_saveFunc(0),
- m_loadFunc(0)
{
}
@@ -135,8 +133,8 @@ public:
return m_saveFunc == rhs.m_saveFunc && m_loadFunc == rhs.m_loadFunc;
}
- SaveFuncType m_saveFunc;
- LoadFuncType m_loadFunc;
+ SaveFuncType m_saveFunc = nullptr;
+ LoadFuncType m_loadFunc = nullptr;
};
typedef QHash<QString, TypeInfo> MapType;
@@ -144,7 +142,7 @@ public:
static MapType &map() { return *m_map; }
#if !defined(QT_NO_DEBUG)
- static bool hasMap() { return m_map != 0; }
+ static bool hasMap() { return m_map != nullptr; }
#endif
protected:
diff --git a/src/libs/qmldebug/baseenginedebugclient.cpp b/src/libs/qmldebug/baseenginedebugclient.cpp
index f3e5271e32..df014e43a0 100644
--- a/src/libs/qmldebug/baseenginedebugclient.cpp
+++ b/src/libs/qmldebug/baseenginedebugclient.cpp
@@ -178,7 +178,7 @@ void BaseEngineDebugClient::stateChanged(State state)
void BaseEngineDebugClient::messageReceived(const QByteArray &data)
{
- QPacket ds(connection()->currentDataStreamVersion(), data);
+ QPacket ds(dataStreamVersion(), data);
int queryId;
QByteArray type;
ds >> type >> queryId;
@@ -251,7 +251,7 @@ quint32 BaseEngineDebugClient::addWatch(const PropertyReference &property)
quint32 id = 0;
if (state() == Enabled) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("WATCH_PROPERTY") << id << property.m_objectDebugId
<< property.m_name.toUtf8();
sendMessage(ds.data());
@@ -272,7 +272,7 @@ quint32 BaseEngineDebugClient::addWatch(const ObjectReference &object,
quint32 id = 0;
if (state() == Enabled) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.m_debugId << expr;
sendMessage(ds.data());
}
@@ -284,7 +284,7 @@ quint32 BaseEngineDebugClient::addWatch(int objectDebugId)
quint32 id = 0;
if (state() == Enabled) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("WATCH_OBJECT") << id << objectDebugId;
sendMessage(ds.data());
}
@@ -300,7 +300,7 @@ quint32 BaseEngineDebugClient::addWatch(const FileReference &/*file*/)
void BaseEngineDebugClient::removeWatch(quint32 id)
{
if (state() == Enabled) {
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("NO_WATCH") << id;
sendMessage(ds.data());
}
@@ -311,7 +311,7 @@ quint32 BaseEngineDebugClient::queryAvailableEngines()
quint32 id = 0;
if (state() == Enabled) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("LIST_ENGINES") << id;
sendMessage(ds.data());
}
@@ -323,7 +323,7 @@ quint32 BaseEngineDebugClient::queryRootContexts(const EngineReference &engine)
quint32 id = 0;
if (state() == Enabled && engine.m_debugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("LIST_OBJECTS") << id << engine.m_debugId;
sendMessage(ds.data());
}
@@ -335,7 +335,7 @@ quint32 BaseEngineDebugClient::queryObject(int objectId)
quint32 id = 0;
if (state() == Enabled && objectId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("FETCH_OBJECT") << id << objectId << false <<
true;
sendMessage(ds.data());
@@ -348,7 +348,7 @@ quint32 BaseEngineDebugClient::queryObjectRecursive(int objectId)
quint32 id = 0;
if (state() == Enabled && objectId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("FETCH_OBJECT") << id << objectId << true <<
true;
sendMessage(ds.data());
@@ -363,7 +363,7 @@ quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId,
quint32 id = 0;
if (state() == Enabled && objectDebugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
<< engineId;
sendMessage(ds.data());
@@ -381,7 +381,7 @@ quint32 BaseEngineDebugClient::setBindingForObject(
quint32 id = 0;
if (state() == Enabled && objectDebugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName
<< bindingExpression << isLiteralValue << source << line;
sendMessage(ds.data());
@@ -396,7 +396,7 @@ quint32 BaseEngineDebugClient::resetBindingForObject(
quint32 id = 0;
if (state() == Enabled && objectDebugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName;
sendMessage(ds.data());
}
@@ -410,7 +410,7 @@ quint32 BaseEngineDebugClient::setMethodBody(
quint32 id = 0;
if (state() == Enabled && objectDebugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId
<< methodName << methodBody;
sendMessage(ds.data());
@@ -424,7 +424,7 @@ quint32 BaseEngineDebugClient::queryObjectsForLocation(
quint32 id = 0;
if (state() == Enabled) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id <<
fileName << lineNumber << columnNumber << false <<
true;
diff --git a/src/libs/qmldebug/baseenginedebugclient.h b/src/libs/qmldebug/baseenginedebugclient.h
index b74397cf9d..1f3f2f3dfe 100644
--- a/src/libs/qmldebug/baseenginedebugclient.h
+++ b/src/libs/qmldebug/baseenginedebugclient.h
@@ -72,6 +72,9 @@ public:
virtual quint32 queryObjectsForLocation(const QString &fileName, int lineNumber,
int columnNumber);
+ virtual void stateChanged(State status) override;
+ virtual void messageReceived(const QByteArray &) override;
+
signals:
void newState(QmlDebug::QmlDebugClient::State status);
void newObject(int engineId, int objectId, int parentId);
@@ -80,9 +83,6 @@ signals:
void result(quint32 queryId, const QVariant &result, const QByteArray &type);
protected:
- virtual void stateChanged(State status);
- virtual void messageReceived(const QByteArray &);
-
quint32 getId() { return m_nextId++; }
void decode(QDataStream &d, ContextReference &context);
diff --git a/src/libs/qmldebug/basetoolsclient.h b/src/libs/qmldebug/basetoolsclient.h
index d84e02066e..cb8d86cb19 100644
--- a/src/libs/qmldebug/basetoolsclient.h
+++ b/src/libs/qmldebug/basetoolsclient.h
@@ -59,7 +59,7 @@ signals:
void logActivity(QString client, QString message);
protected:
- void stateChanged(State status);
+ void stateChanged(State status) override;
void recurseObjectIdList(const ObjectReference &ref,
QList<int> &debugIds, QList<QString> &objectIds);
diff --git a/src/libs/qmldebug/declarativeenginedebugclient.cpp b/src/libs/qmldebug/declarativeenginedebugclient.cpp
index e014aa44fa..21a13a960d 100644
--- a/src/libs/qmldebug/declarativeenginedebugclient.cpp
+++ b/src/libs/qmldebug/declarativeenginedebugclient.cpp
@@ -46,7 +46,7 @@ quint32 DeclarativeEngineDebugClient::setBindingForObject(
quint32 id = 0;
if (state() == Enabled && objectDebugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("SET_BINDING") << objectDebugId << propertyName
<< bindingExpression << isLiteralValue << source << line;
sendMessage(ds.data());
@@ -61,7 +61,7 @@ quint32 DeclarativeEngineDebugClient::resetBindingForObject(
quint32 id = 0;
if (state() == Enabled && objectDebugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName;
sendMessage(ds.data());
}
@@ -75,7 +75,7 @@ quint32 DeclarativeEngineDebugClient::setMethodBody(
quint32 id = 0;
if (state() == Enabled && objectDebugId != -1) {
id = getId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray("SET_METHOD_BODY") << objectDebugId
<< methodName << methodBody;
sendMessage(ds.data());
@@ -85,7 +85,7 @@ quint32 DeclarativeEngineDebugClient::setMethodBody(
void DeclarativeEngineDebugClient::messageReceived(const QByteArray &data)
{
- QPacket ds(connection()->currentDataStreamVersion(), data);
+ QPacket ds(dataStreamVersion(), data);
QByteArray type;
ds >> type;
diff --git a/src/libs/qmldebug/declarativeenginedebugclient.h b/src/libs/qmldebug/declarativeenginedebugclient.h
index 793347e9c7..ccd087726f 100644
--- a/src/libs/qmldebug/declarativeenginedebugclient.h
+++ b/src/libs/qmldebug/declarativeenginedebugclient.h
@@ -40,13 +40,12 @@ public:
quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
const QVariant &bindingExpression,
bool isLiteralValue,
- QString source, int line);
- quint32 resetBindingForObject(int objectDebugId, const QString &propertyName);
+ QString source, int line) override;
+ quint32 resetBindingForObject(int objectDebugId, const QString &propertyName) override;
quint32 setMethodBody(int objectDebugId, const QString &methodName,
- const QString &methodBody);
+ const QString &methodBody) override;
-protected:
- void messageReceived(const QByteArray &data);
+ void messageReceived(const QByteArray &data) override;
};
} // namespace QmlDebug
diff --git a/src/libs/qmldebug/declarativetoolsclient.h b/src/libs/qmldebug/declarativetoolsclient.h
index 83698b4037..a6031e87c3 100644
--- a/src/libs/qmldebug/declarativetoolsclient.h
+++ b/src/libs/qmldebug/declarativetoolsclient.h
@@ -35,17 +35,16 @@ class QMLDEBUG_EXPORT DeclarativeToolsClient : public BaseToolsClient
public:
DeclarativeToolsClient(QmlDebugConnection *client);
- void setDesignModeBehavior(bool inDesignMode);
- void changeToSelectTool();
- void changeToSelectMarqueeTool();
- void changeToZoomTool();
- void showAppOnTop(bool showOnTop);
+ void setDesignModeBehavior(bool inDesignMode) override;
+ void changeToSelectTool() override;
+ void changeToSelectMarqueeTool() override;
+ void changeToZoomTool() override;
+ void showAppOnTop(bool showOnTop) override;
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
- void setObjectIdList(const QList<ObjectReference> &objectRoots);
+ void setObjectIdList(const QList<ObjectReference> &objectRoots) override;
-protected:
- void messageReceived(const QByteArray &);
+ void messageReceived(const QByteArray &) override;
private:
void log(LogDirection direction,
diff --git a/src/libs/qmldebug/qdebugmessageclient.h b/src/libs/qmldebug/qdebugmessageclient.h
index 0c6d5995c1..6862cfd69d 100644
--- a/src/libs/qmldebug/qdebugmessageclient.h
+++ b/src/libs/qmldebug/qdebugmessageclient.h
@@ -46,9 +46,8 @@ class QMLDEBUG_EXPORT QDebugMessageClient : public QmlDebugClient
public:
explicit QDebugMessageClient(QmlDebugConnection *client);
-protected:
- virtual void stateChanged(State state);
- virtual void messageReceived(const QByteArray &);
+ virtual void stateChanged(State state) override;
+ virtual void messageReceived(const QByteArray &) override;
signals:
void newState(QmlDebug::QmlDebugClient::State);
diff --git a/src/libs/qmldebug/qmldebugclient.cpp b/src/libs/qmldebug/qmldebugclient.cpp
index 597281ab25..ffa21a458c 100644
--- a/src/libs/qmldebug/qmldebugclient.cpp
+++ b/src/libs/qmldebug/qmldebugclient.cpp
@@ -33,9 +33,12 @@
#include <qlocalserver.h>
#include <qlocalsocket.h>
+#include <QPointer>
+
namespace QmlDebug {
const int protocolVersion = 1;
+const int minimumDataStreamVersion = QDataStream::Qt_4_7;
const QString serverId = QLatin1String("QDeclarativeDebugServer");
const QString clientId = QLatin1String("QDeclarativeDebugClient");
@@ -46,7 +49,7 @@ public:
QmlDebugClientPrivate();
QString name;
- QmlDebugConnection *connection;
+ QPointer<QmlDebugConnection> connection;
};
class QmlDebugConnectionPrivate
@@ -84,7 +87,7 @@ static QString socketErrorToString(QAbstractSocket::SocketError error)
QmlDebugConnectionPrivate::QmlDebugConnectionPrivate() :
protocol(0), server(0), device(0), gotHello(false),
- currentDataStreamVersion(QDataStream::Qt_4_7),
+ currentDataStreamVersion(minimumDataStreamVersion),
maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion)
{
}
@@ -263,11 +266,7 @@ QmlDebugConnection::QmlDebugConnection(QObject *parent)
QmlDebugConnection::~QmlDebugConnection()
{
- Q_D(QmlDebugConnection);
socketDisconnected();
- QHash<QString, QmlDebugClient*>::iterator iter = d->plugins.begin();
- for (; iter != d->plugins.end(); ++iter)
- iter.value()->d_func()->connection = 0;
}
bool QmlDebugConnection::isConnected() const
@@ -398,7 +397,7 @@ void QmlDebugConnection::newConnection()
connect(socket, &QLocalSocket::disconnected, this, &QmlDebugConnection::socketDisconnected);
connect(socket, static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>
- (&QLocalSocket::error), this, [this, d](QLocalSocket::LocalSocketError error) {
+ (&QLocalSocket::error), this, [this](QLocalSocket::LocalSocketError error) {
emit logError(socketErrorToString(static_cast<QAbstractSocket::SocketError>(error)));
socketDisconnected();
});
@@ -435,7 +434,6 @@ QAbstractSocket::SocketState QmlDebugConnection::socketState() const
}
QmlDebugClientPrivate::QmlDebugClientPrivate()
- : connection(0)
{
}
@@ -496,6 +494,12 @@ QmlDebugConnection *QmlDebugClient::connection() const
return d->connection;
}
+int QmlDebugClient::dataStreamVersion() const
+{
+ Q_D(const QmlDebugClient);
+ return (d->connection ? d->connection->currentDataStreamVersion() : minimumDataStreamVersion);
+}
+
void QmlDebugClient::sendMessage(const QByteArray &message)
{
Q_D(QmlDebugClient);
diff --git a/src/libs/qmldebug/qmldebugclient.h b/src/libs/qmldebug/qmldebugclient.h
index 2e485ecc1a..b39ec5f3db 100644
--- a/src/libs/qmldebug/qmldebugclient.h
+++ b/src/libs/qmldebug/qmldebugclient.h
@@ -95,15 +95,13 @@ public:
float serviceVersion() const;
State state() const;
QmlDebugConnection *connection() const;
+ int dataStreamVersion() const;
virtual void sendMessage(const QByteArray &);
-
-protected:
virtual void stateChanged(State);
virtual void messageReceived(const QByteArray &);
private:
- friend class QmlDebugConnection;
QScopedPointer<QmlDebugClientPrivate> d_ptr;
};
diff --git a/src/libs/qmldebug/qmldebugcommandlinearguments.h b/src/libs/qmldebug/qmldebugcommandlinearguments.h
index 407f991114..dfcb40927b 100644
--- a/src/libs/qmldebug/qmldebugcommandlinearguments.h
+++ b/src/libs/qmldebug/qmldebugcommandlinearguments.h
@@ -66,12 +66,9 @@ static inline QString qmlDebugCommandLineArguments(QmlDebugServicesPreset servic
}
static inline QString qmlDebugTcpArguments(QmlDebugServicesPreset services,
- Utils::Port port = Utils::Port(),
- bool block = true)
+ Utils::Port port, bool block = true)
{
- return qmlDebugCommandLineArguments(services, port.isValid() ?
- QString::fromLatin1("port:%1").arg(port.number()) :
- QStringLiteral("port:%qml_port%"), block);
+ return qmlDebugCommandLineArguments(services, QString("port:%1").arg(port.number()), block);
}
static inline QString qmlDebugNativeArguments(QmlDebugServicesPreset services, bool block = true)
@@ -85,15 +82,4 @@ static inline QString qmlDebugLocalArguments(QmlDebugServicesPreset services, co
return qmlDebugCommandLineArguments(services, QLatin1String("file:") + socket, block);
}
-static inline QString qmlDebugArguments(QmlDebugServicesPreset services, const QUrl &serverUrl,
- bool block = true)
-{
- if (serverUrl.scheme() == "socket")
- return qmlDebugCommandLineArguments(services, "file:" + serverUrl.path(), block);
- else
- return qmlDebugCommandLineArguments(services, serverUrl.port() != -1 ?
- QString("port:%1").arg(serverUrl.port()) :
- "port:%qml_port%", block);
-}
-
} // namespace QmlDebug
diff --git a/src/libs/qmldebug/qmlenginecontrolclient.h b/src/libs/qmldebug/qmlenginecontrolclient.h
index c5da7a7130..c947fd72f0 100644
--- a/src/libs/qmldebug/qmlenginecontrolclient.h
+++ b/src/libs/qmldebug/qmlenginecontrolclient.h
@@ -52,6 +52,8 @@ public:
void blockEngine(int engineId);
void releaseEngine(int engineId);
+ void messageReceived(const QByteArray &) override;
+
signals:
void engineAboutToBeAdded(int engineId, const QString &name);
void engineAdded(int engineId, const QString &name);
@@ -59,7 +61,6 @@ signals:
void engineRemoved(int engineId, const QString &name);
protected:
- void messageReceived(const QByteArray &);
void sendCommand(CommandType command, int engineId);
struct EngineState {
diff --git a/src/libs/qmldebug/qmltoolsclient.cpp b/src/libs/qmldebug/qmltoolsclient.cpp
index 7ce05ef71a..e882f0733b 100644
--- a/src/libs/qmldebug/qmltoolsclient.cpp
+++ b/src/libs/qmldebug/qmltoolsclient.cpp
@@ -55,7 +55,7 @@ QmlToolsClient::QmlToolsClient(QmlDebugConnection *client)
void QmlToolsClient::messageReceived(const QByteArray &message)
{
- QPacket ds(connection()->currentDataStreamVersion(), message);
+ QPacket ds(dataStreamVersion(), message);
QByteArray type;
int requestId;
@@ -98,7 +98,7 @@ void QmlToolsClient::setObjectIdList(const QList<ObjectReference> &objectRoots)
foreach (const ObjectReference &object, objectRoots)
debugIds << object.debugId();
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray(REQUEST) << m_requestId++ << QByteArray(SELECT) << debugIds;
sendMessage(ds.data());
}
@@ -108,7 +108,7 @@ void QmlToolsClient::setDesignModeBehavior(bool inDesignMode)
if (!m_connection || !m_connection->isConnected())
return;
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray(REQUEST) << m_requestId++;
if (inDesignMode)
ds << QByteArray(ENABLE);
@@ -140,7 +140,7 @@ void QmlToolsClient::showAppOnTop(bool showOnTop)
if (!m_connection || !m_connection->isConnected())
return;
- QPacket ds(connection()->currentDataStreamVersion());
+ QPacket ds(dataStreamVersion());
ds << QByteArray(REQUEST) << m_requestId++
<< QByteArray(SHOW_APP_ON_TOP) << showOnTop;
diff --git a/src/libs/qmldebug/qmltoolsclient.h b/src/libs/qmldebug/qmltoolsclient.h
index 51dc6730af..0a3aba6bd4 100644
--- a/src/libs/qmldebug/qmltoolsclient.h
+++ b/src/libs/qmldebug/qmltoolsclient.h
@@ -35,17 +35,16 @@ class QMLDEBUG_EXPORT QmlToolsClient : public BaseToolsClient
public:
explicit QmlToolsClient(QmlDebugConnection *client);
- void setDesignModeBehavior(bool inDesignMode);
- void changeToSelectTool();
- void changeToSelectMarqueeTool();
- void changeToZoomTool();
- void showAppOnTop(bool showOnTop);
+ void setDesignModeBehavior(bool inDesignMode) override;
+ void changeToSelectTool() override;
+ void changeToSelectMarqueeTool() override;
+ void changeToZoomTool() override;
+ void showAppOnTop(bool showOnTop) override;
// ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
- void setObjectIdList(const QList<ObjectReference> &objectRoots);
+ void setObjectIdList(const QList<ObjectReference> &objectRoots) override;
-protected:
- void messageReceived(const QByteArray &);
+ void messageReceived(const QByteArray &) override;
private:
void log(LogDirection direction,
diff --git a/src/libs/qmldebug/qpacketprotocol.h b/src/libs/qmldebug/qpacketprotocol.h
index 33d1ecdbf6..308fd7ba58 100644
--- a/src/libs/qmldebug/qpacketprotocol.h
+++ b/src/libs/qmldebug/qpacketprotocol.h
@@ -50,7 +50,7 @@ public:
QByteArray read();
bool waitForReadyRead(int msecs = 3000);
-Q_SIGNALS:
+signals:
void readyRead();
void invalidPacket();
@@ -66,7 +66,6 @@ public:
QByteArray data() const;
private:
- void init(QIODevice::OpenMode mode);
QBuffer buf;
};
diff --git a/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp b/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp
index 86b83ef85a..3a7c929d30 100644
--- a/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp
+++ b/src/libs/qmleditorwidgets/easingpane/easingcontextpane.cpp
@@ -26,6 +26,7 @@
#include "easingcontextpane.h"
#include "ui_easingcontextpane.h"
#include <qmljs/qmljspropertyreader.h>
+#include <utils/utilsicons.h>
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
@@ -124,9 +125,7 @@ EasingContextPane::EasingContextPane(QWidget *parent) :
m_easingGraph->raise();
setLinear();
- ui->playButton->setIcon(QIcon(QLatin1String(":/playicon.png")));
-
-
+ ui->playButton->setIcon(Utils::Icons::RUN_SMALL.icon());
setGraphDisplayMode(GraphMode);
@@ -228,14 +227,14 @@ void EasingContextPane::startAnimation()
m_simulation->stop();
} else {
m_simulation->animate(ui->durationSpinBox->value(), m_easingGraph->easingCurve());
- ui->playButton->setIcon(QIcon(QLatin1String(":/stopicon.png")));
+ ui->playButton->setIcon(Utils::Icons::STOP_SMALL.icon());
}
}
void EasingContextPane::switchToGraph()
{
- ui->playButton->setIcon(QIcon(QLatin1String(":/playicon.png")));
+ ui->playButton->setIcon(Utils::Icons::RUN_SMALL.icon());
setGraphDisplayMode(GraphMode);
}
diff --git a/src/libs/qmleditorwidgets/easingpane/easingpane.qrc b/src/libs/qmleditorwidgets/easingpane/easingpane.qrc
index f6e6953680..f90ab25d14 100644
--- a/src/libs/qmleditorwidgets/easingpane/easingpane.qrc
+++ b/src/libs/qmleditorwidgets/easingpane/easingpane.qrc
@@ -1,7 +1,5 @@
<RCC>
<qresource prefix="/">
<file>qt_logo.png</file>
- <file>playicon.png</file>
- <file>stopicon.png</file>
</qresource>
</RCC>
diff --git a/src/libs/qmleditorwidgets/easingpane/playicon.png b/src/libs/qmleditorwidgets/easingpane/playicon.png
deleted file mode 100644
index ba4f36b5bf..0000000000
--- a/src/libs/qmleditorwidgets/easingpane/playicon.png
+++ /dev/null
Binary files differ
diff --git a/src/libs/qmleditorwidgets/easingpane/stopicon.png b/src/libs/qmleditorwidgets/easingpane/stopicon.png
deleted file mode 100644
index 74eb2ead32..0000000000
--- a/src/libs/qmleditorwidgets/easingpane/stopicon.png
+++ /dev/null
Binary files differ
diff --git a/src/libs/qmleditorwidgets/images/hole.png b/src/libs/qmleditorwidgets/images/hole.png
deleted file mode 100644
index b75cca1ea3..0000000000
--- a/src/libs/qmleditorwidgets/images/hole.png
+++ /dev/null
Binary files differ
diff --git a/src/libs/qmleditorwidgets/images/lock.png b/src/libs/qmleditorwidgets/images/lock.png
deleted file mode 100644
index 8f1b546c8d..0000000000
--- a/src/libs/qmleditorwidgets/images/lock.png
+++ /dev/null
Binary files differ
diff --git a/src/libs/qmleditorwidgets/resources.qrc b/src/libs/qmleditorwidgets/resources.qrc
index 5c7164c7b8..5ac0786481 100644
--- a/src/libs/qmleditorwidgets/resources.qrc
+++ b/src/libs/qmleditorwidgets/resources.qrc
@@ -4,8 +4,6 @@
<file>images/checkbox_indicator@2x.png</file>
<file>images/tr.png</file>
<file>images/tr@2x.png</file>
- <file>images/lock.png</file>
- <file>images/hole.png</file>
<file>images/scrollbar-borderimage-horizontal.png</file>
<file>images/scrollbar-borderimage-vertical.png</file>
<file>images/aspectlockset.png</file>
diff --git a/src/libs/qmljs/parser/qmljslexer.cpp b/src/libs/qmljs/parser/qmljslexer.cpp
index 8ab06dc7ec..d24920e24d 100644
--- a/src/libs/qmljs/parser/qmljslexer.cpp
+++ b/src/libs/qmljs/parser/qmljslexer.cpp
@@ -72,6 +72,7 @@ static inline QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4)
Lexer::Lexer(Engine *engine)
: _engine(engine)
, _codePtr(0)
+ , _endPtr(0)
, _lastLinePtr(0)
, _tokenLinePtr(0)
, _tokenStartPtr(0)
diff --git a/src/libs/qmljs/parser/qmljsparser.cpp b/src/libs/qmljs/parser/qmljsparser.cpp
index 87cc41b00c..1bba51e410 100644
--- a/src/libs/qmljs/parser/qmljsparser.cpp
+++ b/src/libs/qmljs/parser/qmljsparser.cpp
@@ -78,6 +78,7 @@ Parser::Parser(Engine *engine):
location_stack(0),
string_stack(0),
program(0),
+ yylval(0),
first_token(0),
last_token(0)
{
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 69fdcef601..6bc596eacd 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -324,7 +324,7 @@ protected:
class MarkUnreachableCode : protected ReachesEndCheck
{
QList<Message> _messages;
- bool _emittedWarning;
+ bool _emittedWarning = false;
public:
QList<Message> operator()(Node *ast)
@@ -1709,6 +1709,7 @@ bool Check::visit(TypeOfExpression *ast)
/// ### Maybe put this into the context as a helper function.
const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
{
+
if (!_importsOk)
return 0;
@@ -1716,6 +1717,17 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
if (scopeObjects.isEmpty())
return 0;
+ const auto getAttachedTypes = [this, &scopeObjects](const QString &propertyName) {
+ bool isAttachedProperty = false;
+ if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
+ isAttachedProperty = true;
+ if (const ObjectValue *qmlTypes = _scopeChain.qmlTypes())
+ scopeObjects += qmlTypes;
+ }
+ return isAttachedProperty;
+ };
+
+
if (! id)
return 0; // ### error?
@@ -1728,12 +1740,7 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
return 0; // ### should probably be a special value
// attached properties
- bool isAttachedProperty = false;
- if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
- isAttachedProperty = true;
- if (const ObjectValue *qmlTypes = _scopeChain.qmlTypes())
- scopeObjects += qmlTypes;
- }
+ bool isAttachedProperty = getAttachedTypes(propertyName);
if (scopeObjects.isEmpty())
return 0;
@@ -1775,6 +1782,9 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
idPart = idPart->next;
propertyName = idPart->name.toString();
+ isAttachedProperty = getAttachedTypes(propertyName);
+ if (isAttachedProperty)
+ return 0;
value = objectValue->lookupMember(propertyName, _context);
if (! value) {
diff --git a/src/libs/qmljs/qmljscodeformatter.cpp b/src/libs/qmljs/qmljscodeformatter.cpp
index d4e3bfb084..5d974d735b 100644
--- a/src/libs/qmljs/qmljscodeformatter.cpp
+++ b/src/libs/qmljs/qmljscodeformatter.cpp
@@ -41,7 +41,8 @@ CodeFormatter::BlockData::BlockData()
}
CodeFormatter::CodeFormatter()
- : m_indentDepth(0)
+ : m_tokenIndex(0)
+ , m_indentDepth(0)
, m_tabSize(4)
{
}
diff --git a/src/libs/qmljs/qmljsdescribevalue.h b/src/libs/qmljs/qmljsdescribevalue.h
index 3c27c320e5..3c5d23bcbd 100644
--- a/src/libs/qmljs/qmljsdescribevalue.h
+++ b/src/libs/qmljs/qmljsdescribevalue.h
@@ -65,7 +65,7 @@ private:
int m_depth;
int m_indent;
int m_indentIncrement;
- bool m_emptyContext;
+ bool m_emptyContext = false;
ContextPtr m_context;
QSet<const Value *> m_visited;
QString m_description;
diff --git a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
index 7c45339d90..84ada6a0d6 100644
--- a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
+++ b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
@@ -252,7 +252,7 @@ protected:
_doc->fileName(),
line, column,
QmlJS::FindExportedCppTypes::tr(
- "The type will only be available in Qt Creator's QML editors when the type name is a string literal"));
+ "The type will only be available in the QML editors when the type name is a string literal"));
return false;
}
@@ -314,7 +314,7 @@ protected:
QmlJS::FindExportedCppTypes::tr(
"The module URI cannot be determined by static analysis. The type will be available\n"
"globally in the QML editor. You can add a \"// @uri My.Module.Uri\" annotation to let\n"
- "Qt Creator know about a likely URI."));
+ "the QML editor know about a likely URI."));
}
// version arguments must be integer literals
diff --git a/src/libs/qmljs/qmljsreformatter.cpp b/src/libs/qmljs/qmljsreformatter.cpp
index 6c4befa0f8..c78f52f5b8 100644
--- a/src/libs/qmljs/qmljsreformatter.cpp
+++ b/src/libs/qmljs/qmljsreformatter.cpp
@@ -90,11 +90,11 @@ class Rewriter : protected Visitor
QList<Split> _possibleSplits;
QTextDocument _resultDocument;
SimpleFormatter _formatter;
- int _indent;
- int _nextComment;
- int _lastNewlineOffset;
- bool _hadEmptyLine;
- int _binaryExpDepth;
+ int _indent = 0;
+ int _nextComment = 0;
+ int _lastNewlineOffset = -1;
+ bool _hadEmptyLine = false;
+ int _binaryExpDepth = 0;
public:
Rewriter(Document::Ptr doc)
@@ -102,6 +102,9 @@ public:
{
}
+ void setIndentSize(int size) { _formatter.setIndentSize(size); }
+ void setTabSize(int size) { _formatter.setTabSize(size); }
+
QString operator()(Node *node)
{
Q_ASSERT(node == _doc->ast()); // comment handling fails otherwise
@@ -1099,7 +1102,8 @@ protected:
out("case ", ast->caseToken);
accept(ast->expression);
out(ast->colonToken);
- lnAcceptIndented(ast->statements);
+ if (ast->statements)
+ lnAcceptIndented(ast->statements);
return false;
}
@@ -1309,3 +1313,11 @@ QString QmlJS::reformat(const Document::Ptr &doc)
Rewriter rewriter(doc);
return rewriter(doc->ast());
}
+
+QString QmlJS::reformat(const Document::Ptr &doc, int indentSize, int tabSize)
+{
+ Rewriter rewriter(doc);
+ rewriter.setIndentSize(indentSize);
+ rewriter.setTabSize(tabSize);
+ return rewriter(doc->ast());
+}
diff --git a/src/libs/qmljs/qmljsreformatter.h b/src/libs/qmljs/qmljsreformatter.h
index 18d5c6fd85..7465a1a17f 100644
--- a/src/libs/qmljs/qmljsreformatter.h
+++ b/src/libs/qmljs/qmljsreformatter.h
@@ -31,4 +31,5 @@
namespace QmlJS {
QMLJS_EXPORT QString reformat(const Document::Ptr &doc);
+QMLJS_EXPORT QString reformat(const Document::Ptr &doc, int indentSize, int tabSize);
}
diff --git a/src/libs/qmljs/qmljsscopeastpath.h b/src/libs/qmljs/qmljsscopeastpath.h
index f06db11c5c..44b4eacf7c 100644
--- a/src/libs/qmljs/qmljsscopeastpath.h
+++ b/src/libs/qmljs/qmljsscopeastpath.h
@@ -56,7 +56,7 @@ private:
QList<AST::Node *> _result;
Document::Ptr _doc;
- quint32 _offset;
+ quint32 _offset = 0;
};
} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsstaticanalysismessage.cpp b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
index 34929ab3b6..389cbdf348 100644
--- a/src/libs/qmljs/qmljsstaticanalysismessage.cpp
+++ b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
@@ -254,7 +254,7 @@ QList<Type> Message::allMessageTypes()
}
Message::Message()
- : type(UnknownType), severity(Hint)
+ : type(UnknownType)
{}
Message::Message(Type type,
diff --git a/src/libs/qmljs/qmljsstaticanalysismessage.h b/src/libs/qmljs/qmljsstaticanalysismessage.h
index 4d07614c8d..109a85a027 100644
--- a/src/libs/qmljs/qmljsstaticanalysismessage.h
+++ b/src/libs/qmljs/qmljsstaticanalysismessage.h
@@ -160,7 +160,7 @@ public:
AST::SourceLocation location;
QString message;
Type type;
- Severity::Enum severity;
+ Severity::Enum severity = Severity::Enum::Hint;
static const PrototypeMessageData prototypeForMessageType(Type type);
};
diff --git a/src/libs/qmljs/qmljstypedescriptionreader.h b/src/libs/qmljs/qmljstypedescriptionreader.h
index 900ec38304..69eec45b17 100644
--- a/src/libs/qmljs/qmljstypedescriptionreader.h
+++ b/src/libs/qmljs/qmljstypedescriptionreader.h
@@ -91,8 +91,8 @@ private:
QString _errorMessage;
QString _warningMessage;
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects;
- QList<ModuleApiInfo> *_moduleApis;
- QStringList *_dependencies;
+ QList<ModuleApiInfo> *_moduleApis = nullptr;
+ QStringList *_dependencies = nullptr;
};
} // namespace QmlJS
diff --git a/src/libs/qt-breakpad/poster/__init__.py b/src/libs/qt-breakpad/poster/__init__.py
new file mode 100644
index 0000000000..e963d70b96
--- /dev/null
+++ b/src/libs/qt-breakpad/poster/__init__.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2010 Chris AtLee
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+"""poster module
+
+Support for streaming HTTP uploads, and multipart/form-data encoding
+
+```poster.version``` is a 3-tuple of integers representing the version number.
+New releases of poster will always have a version number that compares greater
+than an older version of poster.
+New in version 0.6."""
+
+import poster.streaminghttp
+import poster.encode
+
+version = (0, 8, 0) # Thanks JP!
diff --git a/src/libs/qt-breakpad/poster/encode.py b/src/libs/qt-breakpad/poster/encode.py
new file mode 100644
index 0000000000..fbc4e76452
--- /dev/null
+++ b/src/libs/qt-breakpad/poster/encode.py
@@ -0,0 +1,433 @@
+# Copyright (c) 2010 Chris AtLee
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+"""multipart/form-data encoding module
+
+This module provides functions that faciliate encoding name/value pairs
+as multipart/form-data suitable for a HTTP POST or PUT request.
+
+multipart/form-data is the standard way to upload files over HTTP"""
+
+__all__ = ['gen_boundary', 'encode_and_quote', 'MultipartParam',
+ 'encode_string', 'encode_file_header', 'get_body_size', 'get_headers',
+ 'multipart_encode']
+
+try:
+ import uuid
+ def gen_boundary():
+ """Returns a random string to use as the boundary for a message"""
+ return uuid.uuid4().hex
+except ImportError:
+ import random, sha
+ def gen_boundary():
+ """Returns a random string to use as the boundary for a message"""
+ bits = random.getrandbits(160)
+ return sha.new(str(bits)).hexdigest()
+
+import urllib, re, os, mimetypes
+try:
+ from email.header import Header
+except ImportError:
+ # Python 2.4
+ from email.Header import Header
+
+def encode_and_quote(data):
+ """If ``data`` is unicode, return urllib.quote_plus(data.encode("utf-8"))
+ otherwise return urllib.quote_plus(data)"""
+ if data is None:
+ return None
+
+ if isinstance(data, unicode):
+ data = data.encode("utf-8")
+ return urllib.quote_plus(data)
+
+def _strify(s):
+ """If s is a unicode string, encode it to UTF-8 and return the results,
+ otherwise return str(s), or None if s is None"""
+ if s is None:
+ return None
+ if isinstance(s, unicode):
+ return s.encode("utf-8")
+ return str(s)
+
+class MultipartParam(object):
+ """Represents a single parameter in a multipart/form-data request
+
+ ``name`` is the name of this parameter.
+
+ If ``value`` is set, it must be a string or unicode object to use as the
+ data for this parameter.
+
+ If ``filename`` is set, it is what to say that this parameter's filename
+ is. Note that this does not have to be the actual filename any local file.
+
+ If ``filetype`` is set, it is used as the Content-Type for this parameter.
+ If unset it defaults to "text/plain; charset=utf8"
+
+ If ``filesize`` is set, it specifies the length of the file ``fileobj``
+
+ If ``fileobj`` is set, it must be a file-like object that supports
+ .read().
+
+ Both ``value`` and ``fileobj`` must not be set, doing so will
+ raise a ValueError assertion.
+
+ If ``fileobj`` is set, and ``filesize`` is not specified, then
+ the file's size will be determined first by stat'ing ``fileobj``'s
+ file descriptor, and if that fails, by seeking to the end of the file,
+ recording the current position as the size, and then by seeking back to the
+ beginning of the file.
+
+ ``cb`` is a callable which will be called from iter_encode with (self,
+ current, total), representing the current parameter, current amount
+ transferred, and the total size.
+ """
+ def __init__(self, name, value=None, filename=None, filetype=None,
+ filesize=None, fileobj=None, cb=None):
+ self.name = Header(name).encode()
+ self.value = _strify(value)
+ if filename is None:
+ self.filename = None
+ else:
+ if isinstance(filename, unicode):
+ # Encode with XML entities
+ self.filename = filename.encode("ascii", "xmlcharrefreplace")
+ else:
+ self.filename = str(filename)
+ self.filename = self.filename.encode("string_escape").\
+ replace('"', '\\"')
+ self.filetype = _strify(filetype)
+
+ self.filesize = filesize
+ self.fileobj = fileobj
+ self.cb = cb
+
+ if self.value is not None and self.fileobj is not None:
+ raise ValueError("Only one of value or fileobj may be specified")
+
+ if fileobj is not None and filesize is None:
+ # Try and determine the file size
+ try:
+ self.filesize = os.fstat(fileobj.fileno()).st_size
+ except (OSError, AttributeError):
+ try:
+ fileobj.seek(0, 2)
+ self.filesize = fileobj.tell()
+ fileobj.seek(0)
+ except:
+ raise ValueError("Could not determine filesize")
+
+ def __cmp__(self, other):
+ attrs = ['name', 'value', 'filename', 'filetype', 'filesize', 'fileobj']
+ myattrs = [getattr(self, a) for a in attrs]
+ oattrs = [getattr(other, a) for a in attrs]
+ return cmp(myattrs, oattrs)
+
+ def reset(self):
+ if self.fileobj is not None:
+ self.fileobj.seek(0)
+ elif self.value is None:
+ raise ValueError("Don't know how to reset this parameter")
+
+ @classmethod
+ def from_file(cls, paramname, filename):
+ """Returns a new MultipartParam object constructed from the local
+ file at ``filename``.
+
+ ``filesize`` is determined by os.path.getsize(``filename``)
+
+ ``filetype`` is determined by mimetypes.guess_type(``filename``)[0]
+
+ ``filename`` is set to os.path.basename(``filename``)
+ """
+
+ return cls(paramname, filename=os.path.basename(filename),
+ filetype=mimetypes.guess_type(filename)[0],
+ filesize=os.path.getsize(filename),
+ fileobj=open(filename, "rb"))
+
+ @classmethod
+ def from_params(cls, params):
+ """Returns a list of MultipartParam objects from a sequence of
+ name, value pairs, MultipartParam instances,
+ or from a mapping of names to values
+
+ The values may be strings or file objects, or MultipartParam objects.
+ MultipartParam object names must match the given names in the
+ name,value pairs or mapping, if applicable."""
+ if hasattr(params, 'items'):
+ params = params.items()
+
+ retval = []
+ for item in params:
+ if isinstance(item, cls):
+ retval.append(item)
+ continue
+ name, value = item
+ if isinstance(value, cls):
+ assert value.name == name
+ retval.append(value)
+ continue
+ if hasattr(value, 'read'):
+ # Looks like a file object
+ filename = getattr(value, 'name', None)
+ if filename is not None:
+ filetype = mimetypes.guess_type(filename)[0]
+ else:
+ filetype = None
+
+ retval.append(cls(name=name, filename=filename,
+ filetype=filetype, fileobj=value))
+ else:
+ retval.append(cls(name, value))
+ return retval
+
+ def encode_hdr(self, boundary):
+ """Returns the header of the encoding of this parameter"""
+ boundary = encode_and_quote(boundary)
+
+ headers = ["--%s" % boundary]
+
+ if self.filename:
+ disposition = 'form-data; name="%s"; filename="%s"' % (self.name,
+ self.filename)
+ else:
+ disposition = 'form-data; name="%s"' % self.name
+
+ headers.append("Content-Disposition: %s" % disposition)
+
+ if self.filetype:
+ filetype = self.filetype
+ else:
+ filetype = "text/plain; charset=utf-8"
+
+ headers.append("Content-Type: %s" % filetype)
+
+ headers.append("")
+ headers.append("")
+
+ return "\r\n".join(headers)
+
+ def encode(self, boundary):
+ """Returns the string encoding of this parameter"""
+ if self.value is None:
+ value = self.fileobj.read()
+ else:
+ value = self.value
+
+ if re.search("^--%s$" % re.escape(boundary), value, re.M):
+ raise ValueError("boundary found in encoded string")
+
+ return "%s%s\r\n" % (self.encode_hdr(boundary), value)
+
+ def iter_encode(self, boundary, blocksize=4096):
+ """Yields the encoding of this parameter
+ If self.fileobj is set, then blocks of ``blocksize`` bytes are read and
+ yielded."""
+ total = self.get_size(boundary)
+ current = 0
+ if self.value is not None:
+ block = self.encode(boundary)
+ current += len(block)
+ yield block
+ if self.cb:
+ self.cb(self, current, total)
+ else:
+ block = self.encode_hdr(boundary)
+ current += len(block)
+ yield block
+ if self.cb:
+ self.cb(self, current, total)
+ last_block = ""
+ encoded_boundary = "--%s" % encode_and_quote(boundary)
+ boundary_exp = re.compile("^%s$" % re.escape(encoded_boundary),
+ re.M)
+ while True:
+ block = self.fileobj.read(blocksize)
+ if not block:
+ current += 2
+ yield "\r\n"
+ if self.cb:
+ self.cb(self, current, total)
+ break
+ last_block += block
+ if boundary_exp.search(last_block):
+ raise ValueError("boundary found in file data")
+ last_block = last_block[-len(encoded_boundary)-2:]
+ current += len(block)
+ yield block
+ if self.cb:
+ self.cb(self, current, total)
+
+ def get_size(self, boundary):
+ """Returns the size in bytes that this param will be when encoded
+ with the given boundary."""
+ if self.filesize is not None:
+ valuesize = self.filesize
+ else:
+ valuesize = len(self.value)
+
+ return len(self.encode_hdr(boundary)) + 2 + valuesize
+
+def encode_string(boundary, name, value):
+ """Returns ``name`` and ``value`` encoded as a multipart/form-data
+ variable. ``boundary`` is the boundary string used throughout
+ a single request to separate variables."""
+
+ return MultipartParam(name, value).encode(boundary)
+
+def encode_file_header(boundary, paramname, filesize, filename=None,
+ filetype=None):
+ """Returns the leading data for a multipart/form-data field that contains
+ file data.
+
+ ``boundary`` is the boundary string used throughout a single request to
+ separate variables.
+
+ ``paramname`` is the name of the variable in this request.
+
+ ``filesize`` is the size of the file data.
+
+ ``filename`` if specified is the filename to give to this field. This
+ field is only useful to the server for determining the original filename.
+
+ ``filetype`` if specified is the MIME type of this file.
+
+ The actual file data should be sent after this header has been sent.
+ """
+
+ return MultipartParam(paramname, filesize=filesize, filename=filename,
+ filetype=filetype).encode_hdr(boundary)
+
+def get_body_size(params, boundary):
+ """Returns the number of bytes that the multipart/form-data encoding
+ of ``params`` will be."""
+ size = sum(p.get_size(boundary) for p in MultipartParam.from_params(params))
+ return size + len(boundary) + 6
+
+def get_headers(params, boundary):
+ """Returns a dictionary with Content-Type and Content-Length headers
+ for the multipart/form-data encoding of ``params``."""
+ headers = {}
+ boundary = urllib.quote_plus(boundary)
+ headers['Content-Type'] = "multipart/form-data; boundary=%s" % boundary
+ headers['Content-Length'] = str(get_body_size(params, boundary))
+ return headers
+
+class multipart_yielder:
+ def __init__(self, params, boundary, cb):
+ self.params = params
+ self.boundary = boundary
+ self.cb = cb
+
+ self.i = 0
+ self.p = None
+ self.param_iter = None
+ self.current = 0
+ self.total = get_body_size(params, boundary)
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ """generator function to yield multipart/form-data representation
+ of parameters"""
+ if self.param_iter is not None:
+ try:
+ block = self.param_iter.next()
+ self.current += len(block)
+ if self.cb:
+ self.cb(self.p, self.current, self.total)
+ return block
+ except StopIteration:
+ self.p = None
+ self.param_iter = None
+
+ if self.i is None:
+ raise StopIteration
+ elif self.i >= len(self.params):
+ self.param_iter = None
+ self.p = None
+ self.i = None
+ block = "--%s--\r\n" % self.boundary
+ self.current += len(block)
+ if self.cb:
+ self.cb(self.p, self.current, self.total)
+ return block
+
+ self.p = self.params[self.i]
+ self.param_iter = self.p.iter_encode(self.boundary)
+ self.i += 1
+ return self.next()
+
+ def reset(self):
+ self.i = 0
+ self.current = 0
+ for param in self.params:
+ param.reset()
+
+def multipart_encode(params, boundary=None, cb=None):
+ """Encode ``params`` as multipart/form-data.
+
+ ``params`` should be a sequence of (name, value) pairs or MultipartParam
+ objects, or a mapping of names to values.
+ Values are either strings parameter values, or file-like objects to use as
+ the parameter value. The file-like objects must support .read() and either
+ .fileno() or both .seek() and .tell().
+
+ If ``boundary`` is set, then it as used as the MIME boundary. Otherwise
+ a randomly generated boundary will be used. In either case, if the
+ boundary string appears in the parameter values a ValueError will be
+ raised.
+
+ If ``cb`` is set, it should be a callback which will get called as blocks
+ of data are encoded. It will be called with (param, current, total),
+ indicating the current parameter being encoded, the current amount encoded,
+ and the total amount to encode.
+
+ Returns a tuple of `datagen`, `headers`, where `datagen` is a
+ generator that will yield blocks of data that make up the encoded
+ parameters, and `headers` is a dictionary with the assoicated
+ Content-Type and Content-Length headers.
+
+ Examples:
+
+ >>> datagen, headers = multipart_encode( [("key", "value1"), ("key", "value2")] )
+ >>> s = "".join(datagen)
+ >>> assert "value2" in s and "value1" in s
+
+ >>> p = MultipartParam("key", "value2")
+ >>> datagen, headers = multipart_encode( [("key", "value1"), p] )
+ >>> s = "".join(datagen)
+ >>> assert "value2" in s and "value1" in s
+
+ >>> datagen, headers = multipart_encode( {"key": "value1"} )
+ >>> s = "".join(datagen)
+ >>> assert "value2" not in s and "value1" in s
+
+ """
+ if boundary is None:
+ boundary = gen_boundary()
+ else:
+ boundary = urllib.quote_plus(boundary)
+
+ headers = get_headers(params, boundary)
+ params = MultipartParam.from_params(params)
+
+ return multipart_yielder(params, boundary, cb), headers
diff --git a/src/libs/qt-breakpad/poster/streaminghttp.py b/src/libs/qt-breakpad/poster/streaminghttp.py
new file mode 100644
index 0000000000..eb3b4661d3
--- /dev/null
+++ b/src/libs/qt-breakpad/poster/streaminghttp.py
@@ -0,0 +1,216 @@
+# Copyright (c) 2010 Chris AtLee
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+"""Streaming HTTP uploads module.
+
+This module extends the standard httplib and urllib2 objects so that
+iterable objects can be used in the body of HTTP requests.
+
+In most cases all one should have to do is call :func:`register_openers()`
+to register the new streaming http handlers which will take priority over
+the default handlers, and then you can use iterable objects in the body
+of HTTP requests.
+
+**N.B.** You must specify a Content-Length header if using an iterable object
+since there is no way to determine in advance the total size that will be
+yielded, and there is no way to reset an interator.
+
+Example usage:
+
+>>> from StringIO import StringIO
+>>> import urllib2, poster.streaminghttp
+
+>>> opener = poster.streaminghttp.register_openers()
+
+>>> s = "Test file data"
+>>> f = StringIO(s)
+
+>>> req = urllib2.Request("http://localhost:5000", f,
+... {'Content-Length': str(len(s))})
+"""
+
+import httplib, urllib2, socket
+from httplib import NotConnected
+
+__all__ = ['StreamingHTTPConnection', 'StreamingHTTPRedirectHandler',
+ 'StreamingHTTPHandler', 'register_openers']
+
+if hasattr(httplib, 'HTTPS'):
+ __all__.extend(['StreamingHTTPSHandler', 'StreamingHTTPSConnection'])
+
+class _StreamingHTTPMixin:
+ """Mixin class for HTTP and HTTPS connections that implements a streaming
+ send method."""
+ def send(self, value):
+ """Send ``value`` to the server.
+
+ ``value`` can be a string object, a file-like object that supports
+ a .read() method, or an iterable object that supports a .next()
+ method.
+ """
+ # Based on python 2.6's httplib.HTTPConnection.send()
+ if self.sock is None:
+ if self.auto_open:
+ self.connect()
+ else:
+ raise NotConnected()
+
+ # send the data to the server. if we get a broken pipe, then close
+ # the socket. we want to reconnect when somebody tries to send again.
+ #
+ # NOTE: we DO propagate the error, though, because we cannot simply
+ # ignore the error... the caller will know if they can retry.
+ if self.debuglevel > 0:
+ print "send:", repr(value)
+ try:
+ blocksize = 8192
+ if hasattr(value, 'read') :
+ if hasattr(value, 'seek'):
+ value.seek(0)
+ if self.debuglevel > 0:
+ print "sendIng a read()able"
+ data = value.read(blocksize)
+ while data:
+ self.sock.sendall(data)
+ data = value.read(blocksize)
+ elif hasattr(value, 'next'):
+ if hasattr(value, 'reset'):
+ value.reset()
+ if self.debuglevel > 0:
+ print "sendIng an iterable"
+ for data in value:
+ self.sock.sendall(data)
+ else:
+ self.sock.sendall(value)
+ except socket.error, v:
+ if v[0] == 32: # Broken pipe
+ self.close()
+ raise
+
+class StreamingHTTPConnection(_StreamingHTTPMixin, httplib.HTTPConnection):
+ """Subclass of `httplib.HTTPConnection` that overrides the `send()` method
+ to support iterable body objects"""
+
+class StreamingHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
+ """Subclass of `urllib2.HTTPRedirectHandler` that overrides the
+ `redirect_request` method to properly handle redirected POST requests
+
+ This class is required because python 2.5's HTTPRedirectHandler does
+ not remove the Content-Type or Content-Length headers when requesting
+ the new resource, but the body of the original request is not preserved.
+ """
+
+ handler_order = urllib2.HTTPRedirectHandler.handler_order - 1
+
+ # From python2.6 urllib2's HTTPRedirectHandler
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
+ """Return a Request or None in response to a redirect.
+
+ This is called by the http_error_30x methods when a
+ redirection response is received. If a redirection should
+ take place, return a new Request to allow http_error_30x to
+ perform the redirect. Otherwise, raise HTTPError if no-one
+ else should try to handle this url. Return None if you can't
+ but another Handler might.
+ """
+ m = req.get_method()
+ if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
+ or code in (301, 302, 303) and m == "POST"):
+ # Strictly (according to RFC 2616), 301 or 302 in response
+ # to a POST MUST NOT cause a redirection without confirmation
+ # from the user (of urllib2, in this case). In practice,
+ # essentially all clients do redirect in this case, so we
+ # do the same.
+ # be conciliant with URIs containing a space
+ newurl = newurl.replace(' ', '%20')
+ newheaders = dict((k, v) for k, v in req.headers.items()
+ if k.lower() not in (
+ "content-length", "content-type")
+ )
+ return urllib2.Request(newurl,
+ headers=newheaders,
+ origin_req_host=req.get_origin_req_host(),
+ unverifiable=True)
+ else:
+ raise urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp)
+
+class StreamingHTTPHandler(urllib2.HTTPHandler):
+ """Subclass of `urllib2.HTTPHandler` that uses
+ StreamingHTTPConnection as its http connection class."""
+
+ handler_order = urllib2.HTTPHandler.handler_order - 1
+
+ def http_open(self, req):
+ """Open a StreamingHTTPConnection for the given request"""
+ return self.do_open(StreamingHTTPConnection, req)
+
+ def http_request(self, req):
+ """Handle a HTTP request. Make sure that Content-Length is specified
+ if we're using an interable value"""
+ # Make sure that if we're using an iterable object as the request
+ # body, that we've also specified Content-Length
+ if req.has_data():
+ data = req.get_data()
+ if hasattr(data, 'read') or hasattr(data, 'next'):
+ if not req.has_header('Content-length'):
+ raise ValueError(
+ "No Content-Length specified for iterable body")
+ return urllib2.HTTPHandler.do_request_(self, req)
+
+if hasattr(httplib, 'HTTPS'):
+ class StreamingHTTPSConnection(_StreamingHTTPMixin,
+ httplib.HTTPSConnection):
+ """Subclass of `httplib.HTTSConnection` that overrides the `send()`
+ method to support iterable body objects"""
+
+ class StreamingHTTPSHandler(urllib2.HTTPSHandler):
+ """Subclass of `urllib2.HTTPSHandler` that uses
+ StreamingHTTPSConnection as its http connection class."""
+
+ handler_order = urllib2.HTTPSHandler.handler_order - 1
+
+ def https_open(self, req):
+ return self.do_open(StreamingHTTPSConnection, req)
+
+ def https_request(self, req):
+ # Make sure that if we're using an iterable object as the request
+ # body, that we've also specified Content-Length
+ if req.has_data():
+ data = req.get_data()
+ if hasattr(data, 'read') or hasattr(data, 'next'):
+ if not req.has_header('Content-length'):
+ raise ValueError(
+ "No Content-Length specified for iterable body")
+ return urllib2.HTTPSHandler.do_request_(self, req)
+
+
+def register_openers():
+ """Register the streaming http handlers in the global urllib2 default
+ opener object.
+
+ Returns the created OpenerDirector object."""
+ handlers = [StreamingHTTPHandler, StreamingHTTPRedirectHandler]
+ if hasattr(httplib, "HTTPS"):
+ handlers.append(StreamingHTTPSHandler)
+
+ opener = urllib2.build_opener(*handlers)
+
+ urllib2.install_opener(opener)
+
+ return opener
diff --git a/src/libs/qt-breakpad/qtbreakpad.pri b/src/libs/qt-breakpad/qtbreakpad.pri
new file mode 100644
index 0000000000..4eada575c1
--- /dev/null
+++ b/src/libs/qt-breakpad/qtbreakpad.pri
@@ -0,0 +1,64 @@
+isEmpty(BREAKPAD_SOURCE_DIR): return()
+
+HEADERS += $$PWD/qtbreakpad/qtsystemexceptionhandler.h
+SOURCES += $$PWD/qtbreakpad/qtsystemexceptionhandler.cpp
+
+DEFINES += ENABLE_QT_BREAKPAD
+
+win32:BREAKPAD_SOURCE_DIR ~= s,\\,/,
+
+INCLUDEPATH += \
+ $$BREAKPAD_SOURCE_DIR/src \
+ $$PWD/qtbreakpad
+
+SOURCES += \
+ $$BREAKPAD_SOURCE_DIR/src/common/string_conversion.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/convert_UTF.c \
+ $$BREAKPAD_SOURCE_DIR/src/common/md5.cc
+
+linux:SOURCES += \
+ $$BREAKPAD_SOURCE_DIR/src/client/minidump_file_writer.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/log/log.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/handler/exception_handler.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/handler/minidump_descriptor.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/linux/guid_creator.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/dump_writer_common/thread_info.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/dump_writer_common/ucontext_reader.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/minidump_writer/linux_dumper.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/minidump_writer/minidump_writer.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/microdump_writer/microdump_writer.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/linux/file_id.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/linux/elfutils.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/linux/linux_libc_support.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/linux/memory_mapped_file.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/linux/safe_readlink.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/linux/crash_generation/crash_generation_client.cc
+
+win32:SOURCES += \
+ $$BREAKPAD_SOURCE_DIR/src/common/windows/guid_string.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/windows/handler/exception_handler.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/windows/crash_generation/minidump_generator.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/windows/crash_generation/client_info.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/windows/crash_generation/crash_generation_client.cc
+
+macos {
+ SOURCES += \
+ $$BREAKPAD_SOURCE_DIR/src/client/minidump_file_writer.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/mac/crash_generation/crash_generation_client.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/mac/handler/exception_handler.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/mac/handler/minidump_generator.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/mac/handler/breakpad_nlist_64.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/mac/handler/dynamic_images.cc \
+ $$BREAKPAD_SOURCE_DIR/src/client/mac/handler/protected_memory_allocator.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/bootstrap_compat.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/file_id.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/macho_id.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/macho_reader.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/macho_utilities.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/macho_walker.cc \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/string_utilities.cc
+ OBJECTIVE_SOURCES += \
+ $$BREAKPAD_SOURCE_DIR/src/common/mac/MachIPC.mm
+ LIBS += -framework Foundation
+}
diff --git a/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.cpp b/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.cpp
new file mode 100644
index 0000000000..d439ba112d
--- /dev/null
+++ b/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qtsystemexceptionhandler.h"
+
+#include <utils/fileutils.h>
+#include <utils/hostosinfo.h>
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QDir>
+#include <QProcess>
+
+#if defined(Q_OS_LINUX)
+# include "client/linux/handler/exception_handler.h"
+#elif defined(Q_OS_WIN)
+# include "client/windows/handler/exception_handler.h"
+#elif defined(Q_OS_MACOS)
+# include "client/mac/handler/exception_handler.h"
+#endif
+
+#if defined(Q_OS_LINUX)
+static bool exceptionHandlerCallback(const google_breakpad::MinidumpDescriptor& descriptor,
+ void* /*context*/,
+ bool succeeded)
+{
+ if (!succeeded)
+ return succeeded;
+
+ const QStringList argumentList = {
+ QString::fromLocal8Bit(descriptor.path()),
+ QString::number(QtSystemExceptionHandler::startTime().toTime_t()),
+ QCoreApplication::applicationName(),
+ QCoreApplication::applicationVersion(),
+ QtSystemExceptionHandler::plugins(),
+ QtSystemExceptionHandler::buildVersion(),
+ QCoreApplication::applicationFilePath()
+ };
+
+ return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList);
+}
+#elif defined(Q_OS_MACOS)
+static bool exceptionHandlerCallback(const char *dump_dir,
+ const char *minidump_id,
+ void *context,
+ bool succeeded)
+{
+ Q_UNUSED(context);
+
+ if (!succeeded)
+ return succeeded;
+
+ const QString path = QString::fromLocal8Bit(dump_dir) + '/'
+ + QString::fromLocal8Bit(minidump_id) + ".dmp";
+ const QStringList argumentList = {
+ path,
+ QString::number(QtSystemExceptionHandler::startTime().toTime_t()),
+ QCoreApplication::applicationName(),
+ QCoreApplication::applicationVersion(),
+ QtSystemExceptionHandler::plugins(),
+ QtSystemExceptionHandler::buildVersion(),
+ QCoreApplication::applicationFilePath()
+ };
+
+ return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList);
+}
+#elif defined(Q_OS_WIN)
+static bool exceptionHandlerCallback(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ bool succeeded)
+{
+ Q_UNUSED(assertion);
+ Q_UNUSED(exinfo);
+ Q_UNUSED(context);
+
+ if (!succeeded)
+ return succeeded;
+
+ const QString path = QString::fromWCharArray(dump_path, int(wcslen(dump_path))) + '/'
+ + QString::fromWCharArray(minidump_id, int(wcslen(minidump_id))) + ".dmp";
+ const QStringList argumentList = {
+ path,
+ QString::number(QtSystemExceptionHandler::startTime().toTime_t()),
+ QCoreApplication::applicationName(),
+ QCoreApplication::applicationVersion(),
+ QtSystemExceptionHandler::plugins(),
+ QtSystemExceptionHandler::buildVersion(),
+ QCoreApplication::applicationFilePath()
+ };
+
+ return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList);
+}
+#endif
+
+static QDateTime s_startTime;
+static QString s_plugins;
+static QString s_buildVersion;
+static QString s_crashHandlerPath;
+
+#if defined(Q_OS_LINUX)
+QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath)
+ : exceptionHandler(new google_breakpad::ExceptionHandler(
+ google_breakpad::MinidumpDescriptor(QDir::tempPath().toStdString()),
+ NULL,
+ exceptionHandlerCallback,
+ NULL,
+ true,
+ -1))
+{
+ init(libexecPath);
+}
+#elif defined(Q_OS_MACOS)
+QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath)
+ : exceptionHandler(new google_breakpad::ExceptionHandler(
+ QDir::tempPath().toStdString(),
+ NULL,
+ exceptionHandlerCallback,
+ NULL,
+ true,
+ NULL))
+{
+ init(libexecPath);
+}
+#elif defined(Q_OS_WIN)
+QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath)
+ : exceptionHandler(new google_breakpad::ExceptionHandler(
+ QDir::tempPath().toStdWString(),
+ NULL,
+ exceptionHandlerCallback,
+ NULL,
+ google_breakpad::ExceptionHandler::HANDLER_ALL))
+{
+ init(libexecPath);
+}
+#else
+QtSystemExceptionHandler::QtSystemExceptionHandler(const QString & /*libexecPath*/)
+ : exceptionHandler(0)
+{
+
+}
+#endif
+
+void QtSystemExceptionHandler::init(const QString &libexecPath)
+{
+ s_startTime = QDateTime::currentDateTime();
+ s_crashHandlerPath = libexecPath + Utils::HostOsInfo::withExecutableSuffix("/qtcrashhandler");
+}
+
+QtSystemExceptionHandler::~QtSystemExceptionHandler()
+{
+#ifdef ENABLE_QT_BREAKPAD
+ delete exceptionHandler;
+#endif
+}
+
+void QtSystemExceptionHandler::setPlugins(const QStringList &pluginNameList)
+{
+ s_plugins = QString("{%1}").arg(pluginNameList.join(","));
+}
+
+void QtSystemExceptionHandler::setBuildVersion(const QString &version)
+{
+ s_buildVersion = version;
+}
+
+QString QtSystemExceptionHandler::buildVersion()
+{
+ return s_buildVersion;
+}
+
+QString QtSystemExceptionHandler::plugins()
+{
+ return s_plugins;
+}
+
+void QtSystemExceptionHandler::setCrashHandlerPath(const QString &crashHandlerPath)
+{
+ s_crashHandlerPath = crashHandlerPath;
+}
+
+QString QtSystemExceptionHandler::crashHandlerPath()
+{
+ return s_crashHandlerPath;
+}
+
+void QtSystemExceptionHandler::crash()
+{
+ int *a = (int*)0x42;
+
+ fprintf(stdout, "Going to crash...\n");
+ fprintf(stdout, "A = %d", *a);
+}
+
+QDateTime QtSystemExceptionHandler::startTime()
+{
+ return s_startTime;
+}
diff --git a/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.h b/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.h
new file mode 100644
index 0000000000..2cc3067d77
--- /dev/null
+++ b/src/libs/qt-breakpad/qtbreakpad/qtsystemexceptionhandler.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QDateTime>
+
+namespace google_breakpad {
+ class ExceptionHandler;
+}
+
+class QtSystemExceptionHandler
+{
+public:
+ QtSystemExceptionHandler(const QString &libexecPath);
+ ~QtSystemExceptionHandler();
+
+ static void crash();
+ static void setPlugins(const QStringList &pluginNameList);
+ static void setBuildVersion(const QString &version);
+ static void setCrashHandlerPath(const QString &crashHandlerPath);
+
+ static QString plugins();
+ static QString buildVersion();
+ static QString crashHandlerPath();
+
+ static QDateTime startTime();
+
+protected:
+ void init(const QString &libexecPath);
+
+private:
+ google_breakpad::ExceptionHandler *exceptionHandler = nullptr;
+};
diff --git a/src/libs/qt-breakpad/qtbreakpadsymbols b/src/libs/qt-breakpad/qtbreakpadsymbols
new file mode 100755
index 0000000000..3b7c5af8ff
--- /dev/null
+++ b/src/libs/qt-breakpad/qtbreakpadsymbols
@@ -0,0 +1,271 @@
+#!/usr/bin/python
+
+import sys
+import os
+import os.path
+import subprocess
+import shlex
+import shutil
+import base64
+
+from poster.encode import multipart_encode
+from poster.encode import MultipartParam
+from poster.streaminghttp import register_openers
+import urllib2
+
+from optparse import OptionParser
+
+register_openers()
+
+breakpadSourceDir = os.environ['BREAKPAD_SOURCE_DIR']
+breakpadUploadUrl = os.environ['BREAKPAD_UPLOAD_URL']
+breakpadUserName = os.environ['BREAKPAD_USER_NAME']
+breakpadUserPassword = os.environ['BREAKPAD_USER_PASSWORD']
+
+if sys.platform == 'win32':
+ nullfilename = 'nul:'
+else:
+ nullfilename = '/dev/null'
+nullfile = open(nullfilename, 'r+b')
+
+
+def stdoutFromProcess(process):
+ (stdout, stderr) = process.communicate()
+ if stderr:
+ print stderr
+ raise SystemError()
+ sys.exit(1)
+ return stdout
+
+def toolPath():
+ if sys.platform == 'linux2':
+ dumpsymsPath = os.path.join(breakpadSourceDir, 'src/tools/linux/dump_syms/dump_syms')
+ elif sys.platform == 'darwin':
+ dumpsymsPath = os.path.join(breakpadSourceDir, 'src/tools/mac/dump_syms/build/Release/dump_syms')
+ elif sys.platform == 'win32':
+ dumpsymsPath = os.path.join(breakpadSourceDir,'src\\tools\\windows\\binaries\\dump_syms.exe')
+ else:
+ sys.exit(1)
+ return dumpsymsPath
+
+gitRootDirectoryCache = {}
+
+def gitRootDirectory(path):
+ directory = os.path.dirname(path)
+ if directory in gitRootDirectoryCache:
+ return gitRootDirectoryCache[directory]
+ directoryList = directory.split(os.sep)
+ while len(directoryList) > 0:
+ gitDirectory = os.sep.join(directoryList + ['.git'])
+ if os.path.exists(gitDirectory):
+ gitDirectory = os.sep.join(directoryList)
+ gitRootDirectoryCache[directory] = gitDirectory
+ return gitDirectory
+ directoryList.pop()
+
+ return None
+
+
+gitCommitShaCache = {}
+
+
+def gitCommitSha(gitRootPath):
+ if gitRootPath in gitCommitShaCache:
+ return gitCommitShaCache[gitRootPath]
+ gitProcess = subprocess.Popen(shlex.split('git rev-parse HEAD'),
+ stdout=subprocess.PIPE,
+ stderr=nullfile, cwd=gitRootPath)
+ commitSha = stdoutFromProcess(gitProcess).strip('\n')
+ gitCommitShaCache[gitRootPath] = commitSha
+ return commitSha
+
+
+gitRemoteRepositoryCache = {}
+
+
+def gitRemoteRepository(gitRootPath):
+ if gitRootPath in gitRemoteRepositoryCache:
+ return gitRemoteRepositoryCache[gitRootPath]
+ gitProcess = \
+ subprocess.Popen(shlex.split('git config remote.origin.url'),
+ stdout=subprocess.PIPE, stderr=nullfile,
+ cwd=gitRootPath)
+ repository = stdoutFromProcess(gitProcess).strip('\n')
+ gitRemoteRepositoryCache[gitRootPath] = repository
+ return repository
+
+
+gitFilePathCache = {}
+
+
+def populateFilePathCache(gitRootPath):
+ if gitRootPath not in gitFilePathCache:
+ gitProcess = \
+ subprocess.Popen(shlex.split('git ls-files --full-name'),
+ stdout=subprocess.PIPE, stderr=nullfile,
+ cwd=gitRootPath)
+ fileNameList = stdoutFromProcess(gitProcess).split('\n')
+ filePathCache = {}
+ for fileName in fileNameList:
+ baseFileName = os.path.basename(fileName)
+ filePathCache[baseFileName] = fileName
+ gitFilePathCache[gitRootPath] = filePathCache
+
+
+def gitFilePath(path, gitRootPath):
+ if not gitRootPath:
+ return path
+
+ populateFilePathCache(gitRootPath)
+
+ baseFileName = os.path.basename(path)
+ filePathCache = gitFilePathCache[gitRootPath]
+ if baseFileName in filePathCache:
+ return filePathCache[baseFileName]
+ else:
+ return os.path.relpath(path, gitRootPath)
+
+
+def isInRepository(path):
+ gitRootPath = gitRootDirectory(path)
+ if not gitRootPath:
+ return False
+
+ populateFilePathCache(gitRootPath)
+ baseFileName = os.path.basename(path)
+ if baseFileName in gitFilePathCache[gitRootPath]:
+ return True
+ else:
+ return False
+
+
+def sendSymbolsToServer(
+ breakpadUploadUrl,
+ symbolText,
+ codeFile,
+ debugFile,
+ debugIdentifier,
+ operatingSystem,
+ cpu,
+ ):
+ (data, headers) = multipart_encode({
+ 'symbol_file': MultipartParam('symbol_file', value=symbolText,
+ filename='symbol_file'),
+ 'code_file': codeFile,
+ 'debug_file': debugFile,
+ 'debug_identifier': debugIdentifier,
+ 'os': operatingSystem,
+ 'cpu': cpu,
+ })
+ request = urllib2.Request(breakpadUploadUrl, data, headers)
+ auth = base64.encodestring('%s:%s' % (breakpadUserName,
+ breakpadUserPassword))[:-1] # This is just standard un/pw encoding
+ request.add_header('Authorization', 'Basic %s' % auth) # Add Auth header to request
+ result = urllib2.urlopen(request).read()
+
+
+def generateSymbolFilesAndSend(binaryPath, projectPath):
+ dumpsymsPath = toolPath()
+
+ originalBinaryPath = binaryPath
+
+ if sys.platform == 'darwin':
+ dsymutilProcess = \
+ subprocess.Popen(shlex.split('/usr/bin/dsymutil "'
+ + binaryPath + '"'), stdout=nullfile,
+ stderr=nullfile)
+ dsymutilProcess.wait()
+ binaryPath += os.path.join('.dSYM/Contents/Resources/DWARF/',
+ os.path.basename(binaryPath))
+
+ binaryPath = os.path.normpath(binaryPath)
+
+ dumpsymsProcess = subprocess.Popen(shlex.split('"' + dumpsymsPath
+ + '" "' + binaryPath + '"'), stdout=subprocess.PIPE,
+ stderr=nullfile, cwd=projectPath)
+ symbolList = stdoutFromProcess(dumpsymsProcess).split('\n')
+
+ outputTextList = []
+ codeFile = os.path.basename(binaryPath)
+ debugFile = ''
+ debugIdentifier = ''
+ operatingSystem = ''
+ cpu = ''
+ moduleNotParsed = True
+ for line in symbolList:
+ line = line.strip('\n').strip('\r')
+ if line[:4] == 'FILE':
+ (marker, idnumber, filepath) = line.split(' ', 2)
+ filepath = os.path.normpath(os.path.join(projectPath,
+ filepath))
+
+ if isInRepository(filepath):
+ gitRootPath = gitRootDirectory(filepath)
+ commitSha = gitCommitSha(gitRootPath)
+ repository = \
+ gitRemoteRepository(gitRootPath).replace(':', '/')
+ relativeFilePath = gitFilePath(filepath,
+ gitRootPath).replace('\\', '/')
+ outputTextList.append('FILE ' + idnumber + ' git:'
+ + repository + ':' + relativeFilePath + ':'
+ + commitSha)
+ else:
+ outputTextList.append(line)
+ elif moduleNotParsed and line[:6] == 'MODULE':
+ (operatingSystem, cpu, debugIdentifier, debugFile) = \
+ line[7:].split(' ', 3)
+ moduleNotParsed = False
+ elif line:
+ outputTextList.append(line)
+
+ if moduleNotParsed:
+ print 'Module not parsed'
+ sys.exit(1)
+
+ sendSymbolsToServer(
+ breakpadUploadUrl,
+ '\n'.join(outputTextList),
+ codeFile,
+ debugFile,
+ debugIdentifier,
+ operatingSystem,
+ cpu,
+ )
+
+ if sys.platform == 'darwin':
+ shutil.rmtree(originalBinaryPath + '.dSYM')
+
+
+def testForBreakpad():
+ try:
+ dumpsymsPath = toolPath()
+ if not dumpsymsPath:
+ sys.exit(1)
+ subprocess.Popen([dumpsymsPath], stdout=nullfile,
+ stderr=nullfile)
+ except (OSError, KeyError):
+ print 'No dumpsyms can be executed. Maybe BREAKPAD_SOURCE_DIR is wrong.'
+ sys.exit(1)
+ sys.exit(0)
+
+
+def main():
+ usage = 'usage: %prog [options] binary projectpath'
+ parser = OptionParser(usage=usage)
+ parser.add_option('-v', '--verbose', action='store_true',
+ dest='verbose')
+ parser.add_option('-e', '--breakpad-exists', action='store_true',
+ dest='testForBreakpad')
+
+ (options, args) = parser.parse_args()
+
+ if options.testForBreakpad == True:
+ testForBreakpad()
+ if len(args) > 1:
+ generateSymbolFilesAndSend(args[0], args[1])
+ else:
+ parser.print_help()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/libs/qt-breakpad/qtbreakpadsymbols.bat b/src/libs/qt-breakpad/qtbreakpadsymbols.bat
new file mode 100644
index 0000000000..aad26594d6
--- /dev/null
+++ b/src/libs/qt-breakpad/qtbreakpadsymbols.bat
@@ -0,0 +1 @@
+@python qtbreakpadsymbols %*
diff --git a/src/libs/qt-breakpad/qtcrashhandler.pri b/src/libs/qt-breakpad/qtcrashhandler.pri
new file mode 100644
index 0000000000..c452c09bd8
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler.pri
@@ -0,0 +1,21 @@
+isEmpty(BREAKPAD_SOURCE_DIR): return()
+
+QT += network
+
+INCLUDEPATH += \
+ $$BREAKPAD_SOURCE_DIR/src \
+ $$PWD/qtcrashhandler
+
+SOURCES += \
+ $$PWD/qtcrashhandler/main.cpp \
+ $$PWD/qtcrashhandler/mainwidget.cpp \
+ $$PWD/qtcrashhandler/detaildialog.cpp \
+ $$PWD/qtcrashhandler/dumpsender.cpp
+
+HEADERS += \
+ $$PWD/qtcrashhandler/mainwidget.h \
+ $$PWD/qtcrashhandler/detaildialog.h \
+ $$PWD/qtcrashhandler/dumpsender.h
+
+FORMS += \
+ $$PWD/qtcrashhandler/mainwidget.ui
diff --git a/src/libs/qt-breakpad/qtcrashhandler/detaildialog.cpp b/src/libs/qt-breakpad/qtcrashhandler/detaildialog.cpp
new file mode 100644
index 0000000000..21c7e87c89
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler/detaildialog.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "detaildialog.h"
+
+#include <QDialogButtonBox>
+#include <QTextBrowser>
+#include <QVBoxLayout>
+
+DetailDialog::DetailDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ resize(640, 480);
+ QVBoxLayout *verticalLayout = new QVBoxLayout(this);
+ textBrowser = new QTextBrowser(this);
+ verticalLayout->addWidget(textBrowser);
+ buttonBox = new QDialogButtonBox(this);
+ buttonBox->setOrientation(Qt::Horizontal);
+ buttonBox->setStandardButtons(QDialogButtonBox::Close);
+
+ verticalLayout->addWidget(buttonBox);
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+}
+
+DetailDialog::~DetailDialog()
+{
+}
+
+void DetailDialog::setText(const QString &text)
+{
+ textBrowser->setPlainText(text);
+}
diff --git a/src/libs/qt-breakpad/qtcrashhandler/detaildialog.h b/src/libs/qt-breakpad/qtcrashhandler/detaildialog.h
new file mode 100644
index 0000000000..9db319a4e8
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler/detaildialog.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+class QTextBrowser;
+class QDialogButtonBox;
+QT_END_NAMESPACE
+
+class DetailDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit DetailDialog(QWidget *parent = nullptr);
+ ~DetailDialog();
+
+ void setText(const QString &text);
+
+private:
+ QTextBrowser *textBrowser = nullptr;
+ QDialogButtonBox *buttonBox = nullptr;
+};
diff --git a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp
new file mode 100644
index 0000000000..5b0d1ac3d5
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "dumpsender.h"
+
+#include <QCoreApplication>
+#include <QDateTime>
+#include <QDebug>
+#include <QFile>
+#include <QFileInfo>
+#include <QHttpMultiPart>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QPair>
+#include <QProcess>
+#include <QStringList>
+#include <QTemporaryFile>
+#include <QUrl>
+
+static const QByteArray boundary = "12345cfdfzfsdfsdfassssaaadsd24324jxccxzzzzz98xzcz";
+
+DumpSender::DumpSender(QObject *parent) :
+ QObject(parent),
+ m_httpMultiPart(QHttpMultiPart::FormDataType)
+{
+ const QString dumpPath = QCoreApplication::arguments().at(1);
+ const QByteArray startupTime = QCoreApplication::arguments().at(2).toLocal8Bit();
+ const QByteArray applicationName = QCoreApplication::arguments().at(3).toLocal8Bit();
+ QByteArray applicationVersion = QCoreApplication::arguments().at(4).toLocal8Bit();
+ const QByteArray plugins = QCoreApplication::arguments().at(5).toLocal8Bit();
+ // QByteArray ideRevision = QCoreApplication::arguments().at(6).toLocal8Bit();
+ m_applicationFilePath = QCoreApplication::arguments().at(7);
+
+ if (applicationVersion.isEmpty())
+ applicationVersion = "1.0.0";
+
+ QFile dumpFile(dumpPath, this);
+ const bool isOpen = dumpFile.open(QIODevice::ReadOnly);
+ Q_ASSERT(isOpen);
+ Q_UNUSED(isOpen);
+
+ const QList<QPair<QByteArray, QByteArray> > pairList = {
+ { "StartupTime", startupTime },
+ { "Vendor", "Qt Project" },
+ { "InstallTime", "0" },
+ { "Add-ons", plugins },
+ { "BuildID", "" },
+ { "SecondsSinceLastCrash", "0" },
+ { "ProductName", applicationName },
+ { "URL", "" },
+ { "Theme", "" },
+ { "Version", applicationVersion },
+ { "CrashTime", QByteArray::number(QDateTime::currentDateTime().toTime_t()) },
+ { "Throttleable", "0" }
+ };
+
+ m_formData.append("--" + boundary + "\r\n");
+ for (const auto &pair : pairList) {
+ m_formData.append("Content-Disposition: form-data; name=\"" + pair.first + "\"\r\n\r\n");
+ m_formData.append(pair.second + "\r\n");
+ m_formData.append("--" + boundary + "\r\n");
+ }
+
+
+ QByteArray dumpArray = dumpFile.readAll();
+ m_formData.append("Content-Type: application/octet-stream\r\n");
+ m_formData.append("Content-Disposition: form-data; name=\"upload_file_minidump\"; filename=\""
+ + QFileInfo(dumpPath).baseName().toUtf8() + "\r\n");
+ m_formData.append("Content-Transfer-Encoding: binary\r\n\r\n");
+ m_formData.append(dumpArray);
+
+ m_formData.append("--" + boundary + "--\r\n");
+
+ for (const auto &pair : pairList) {
+ QHttpPart httpPart;
+ httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"" + pair.first + "\"");
+ httpPart.setBody(pair.second);
+ m_httpMultiPart.append(httpPart);
+ }
+
+ QHttpPart dumpPart;
+ dumpPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
+ dumpPart.setHeader(QNetworkRequest::ContentDispositionHeader,
+ "form-data; name=\"upload_file_minidump\"; filename=\""
+ + QFileInfo(dumpPath).baseName().toUtf8() + "\"");
+ dumpPart.setRawHeader("Content-Transfer-Encoding:", "binary");
+ dumpPart.setBody(dumpArray);
+ m_httpMultiPart.append(dumpPart);
+}
+
+void DumpSender::sendDumpAndQuit()
+{
+ QNetworkAccessManager *manager = new QNetworkAccessManager(this);
+
+ QNetworkRequest request(QUrl("http://crashes.qt.io/submit"));
+
+ request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary);
+
+ QList<QPair<QByteArray, QByteArray>> pairList;
+
+ if (!m_emailAddress.isEmpty())
+ pairList.append({ "Email", m_emailAddress.toLocal8Bit() });
+
+ if (!m_commentText.isEmpty())
+ pairList.append({ "Comments", m_commentText.toLocal8Bit() });
+
+ for (const auto &pair : pairList) {
+ m_formData.append("Content-Disposition: form-data; name=\"" + pair.first + "\"\r\n\r\n");
+ m_formData.append(pair.second + "\r\n");
+ m_formData.append("--" + boundary + "\r\n");
+ }
+
+ for (const auto &pair : pairList) {
+ QHttpPart httpPart;
+ httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"" + pair.first + "\"");
+ httpPart.setBody(pair.second);
+ m_httpMultiPart.append(httpPart);
+ }
+
+ QNetworkReply *reply = manager->post(request, &m_httpMultiPart);
+
+ m_httpMultiPart.setParent(reply);
+
+ connect(reply, &QNetworkReply::uploadProgress, this, &DumpSender::uploadProgress);
+ connect(reply, &QNetworkReply::finished, QCoreApplication::instance(), &QCoreApplication::quit);
+ connect(reply,
+ static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
+ QCoreApplication::instance(), &QCoreApplication::quit);
+}
+
+void DumpSender::restartCrashedApplicationAndSendDump()
+{
+ QProcess::startDetached(m_applicationFilePath);
+ sendDumpAndQuit();
+}
+
+void DumpSender::restartCrashedApplication()
+{
+ QProcess::startDetached(m_applicationFilePath);
+ QCoreApplication::quit();
+}
+
+void DumpSender::setEmailAddress(const QString &email)
+{
+ m_emailAddress = email;
+}
+
+void DumpSender::setCommentText(const QString &comment)
+{
+ m_commentText = comment;
+}
+
+int DumpSender::dumperSize() const
+{
+ return m_formData.size();
+}
diff --git a/src/libs/sqlite/sqlitedatabaseconnection.h b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.h
index bbf813ffe6..4a57a5e99d 100644
--- a/src/libs/sqlite/sqlitedatabaseconnection.h
+++ b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -25,33 +25,31 @@
#pragma once
-#include "sqlitedatabasebackend.h"
-
+#include <QHttpMultiPart>
#include <QObject>
-struct sqlite3;
-
-class SQLITE_EXPORT SqliteDatabaseConnection final : public QObject
+class DumpSender : public QObject
{
Q_OBJECT
-public:
- explicit SqliteDatabaseConnection(QObject *parent = 0);
- ~SqliteDatabaseConnection();
- static sqlite3 *currentSqliteDatabase();
+public:
+ explicit DumpSender(QObject *parent = nullptr);
-public slots:
- void setDatabaseFilePath(const QString &databaseName);
- void setJournalMode(JournalMode journalMode);
- void close();
+ int dumperSize() const;
-protected:
- void prioritizeThreadDown();
+ void sendDumpAndQuit();
+ void restartCrashedApplication();
+ void restartCrashedApplicationAndSendDump();
+ void setEmailAddress(const QString &email);
+ void setCommentText(const QString &comment);
signals:
- void databaseConnectionIsOpened();
- void databaseConnectionIsClosed();
+ void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
private:
- SqliteDatabaseBackend databaseBackend;
+ QHttpMultiPart m_httpMultiPart;
+ QByteArray m_formData;
+ QString m_applicationFilePath;
+ QString m_emailAddress;
+ QString m_commentText;
};
diff --git a/src/libs/qt-breakpad/qtcrashhandler/main.cpp b/src/libs/qt-breakpad/qtcrashhandler/main.cpp
new file mode 100644
index 0000000000..7a307381cc
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler/main.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mainwidget.h"
+#include "dumpsender.h"
+
+#include <QApplication>
+#include <QFileInfo>
+#include <QHostInfo>
+#include <QNetworkProxyFactory>
+
+int main(int argc, char *argv[])
+{
+ QApplication application(argc, argv);
+
+ if (application.arguments().count() <= 1)
+ return 0;
+
+ const QString dumpPath = QApplication::arguments().at(1);
+ if (!QFileInfo(dumpPath).exists())
+ return 0;
+
+ QNetworkProxyFactory::setUseSystemConfiguration(true);
+
+ QHostInfo hostInfo = QHostInfo::fromName("crashes.qt.io");
+
+// if (hostInfo.error() != QHostInfo::NoError)
+// return 0;
+
+ DumpSender dumpSender;
+
+ MainWidget mainWindow;
+
+ mainWindow.setProgressbarMaximum(dumpSender.dumperSize());
+
+ QObject::connect(&mainWindow, &MainWidget::restartCrashedApplication,
+ &dumpSender, &DumpSender::restartCrashedApplication);
+ QObject::connect(&mainWindow, &MainWidget::restartCrashedApplicationAndSendDump,
+ &dumpSender, &DumpSender::restartCrashedApplicationAndSendDump);
+ QObject::connect(&mainWindow, &MainWidget::sendDump,
+ &dumpSender, &DumpSender::sendDumpAndQuit);
+ QObject::connect(&mainWindow, &MainWidget::commentChanged,
+ &dumpSender, &DumpSender::setCommentText);
+ QObject::connect(&mainWindow, &MainWidget::emailAdressChanged,
+ &dumpSender, &DumpSender::setEmailAddress);
+ QObject::connect(&dumpSender, &DumpSender::uploadProgress,
+ &mainWindow, &MainWidget::updateProgressBar);
+
+ mainWindow.show();
+ return application.exec();
+}
diff --git a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.cpp b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.cpp
new file mode 100644
index 0000000000..0fc4f2e1d4
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mainwidget.h"
+#include "ui_mainwidget.h"
+
+#include <QApplication>
+#include <QDateTime>
+#include <QFile>
+#include <QFileInfo>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QPair>
+#include <QStringList>
+#include <QTemporaryFile>
+#include <QUrl>
+
+MainWidget::MainWidget(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWidget)
+{
+ ui->setupUi(this);
+
+ connect(ui->restartButton, &QAbstractButton::clicked, this, &MainWidget::restartApplication);
+ connect(ui->quitButton, &QAbstractButton::clicked, this, &MainWidget::quitApplication);
+ connect(ui->detailButton, &QAbstractButton::clicked, this, &MainWidget::showDetails);
+ connect(ui->commentTextEdit, &QTextEdit::textChanged, this, &MainWidget::commentIsProvided);
+ connect(ui->emailLineEdit, &QLineEdit::textEdited, this, &MainWidget::emailAdressChanged);
+}
+
+MainWidget::~MainWidget()
+{
+ delete ui;
+}
+
+void MainWidget::setProgressbarMaximum(int maximum)
+{
+ ui->progressBar->setMaximum(maximum);
+}
+
+void MainWidget::changeEvent(QEvent *e)
+{
+ QWidget::changeEvent(e);
+ if (e->type() == QEvent::LanguageChange)
+ ui->retranslateUi(this);
+}
+
+void MainWidget::updateProgressBar(qint64 progressCount, qint64 fullCount)
+{
+ ui->progressBar->setValue(static_cast<int>(progressCount));
+ ui->progressBar->setMaximum(static_cast<int>(fullCount));
+}
+
+void MainWidget::showError(QNetworkReply::NetworkError error)
+{
+ QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
+ if (error != QNetworkReply::NoError && reply) {
+ ui->commentTextEdit->setReadOnly(true);
+ ui->commentTextEdit->setPlainText(reply->errorString());
+ }
+}
+
+void MainWidget::restartApplication()
+{
+ if (ui->sendDumpCheckBox->isChecked())
+ emit restartCrashedApplicationAndSendDump();
+ else
+ emit restartCrashedApplication();
+}
+
+void MainWidget::quitApplication()
+{
+ ui->quitButton->setEnabled(false);
+ if (ui->sendDumpCheckBox->isChecked())
+ emit sendDump();
+ else
+ QCoreApplication::quit();
+}
+
+void MainWidget::commentIsProvided()
+{
+ m_commentIsProvided = true;
+ emit commentChanged(ui->commentTextEdit->toPlainText());
+}
+
+void MainWidget::showDetails()
+{
+ if (m_detailDialog.isNull()) {
+ m_detailDialog = new DetailDialog(this);
+
+ QString detailText;
+
+ detailText.append(tr("We specifically send the following information:\n\n"));
+
+ QString dumpPath = QApplication::arguments().at(1);
+ QString startupTime = QApplication::arguments().at(2);
+ QString applicationName = QApplication::arguments().at(3);
+ QString applicationVersion = QApplication::arguments().at(4);
+ QString plugins = QApplication::arguments().at(5);
+ QString ideRevision = QApplication::arguments().at(6);
+
+ detailText.append(QString("StartupTime: %1\n").arg(startupTime));
+ detailText.append(QString("Vendor: %1\n").arg("Qt Project"));
+ detailText.append(QString("InstallTime: %1\n").arg("0"));
+ detailText.append(QString("Add-ons: %1\n").arg(plugins));
+ detailText.append(QString("BuildID: %1\n").arg("0"));
+ detailText.append(QString("SecondsSinceLastCrash: %1\n").arg("0"));
+ detailText.append(QString("ProductName: %1\n").arg(applicationName));
+ detailText.append(QString("URL: %1\n").arg(""));
+ detailText.append(QString("Theme: %1\n").arg(""));
+ detailText.append(QString("Version: %1\n").arg(applicationVersion));
+ detailText.append(QString("CrashTime: %1\n").arg(QString::number(QDateTime::currentDateTime().toTime_t())));
+
+ if (!ui->emailLineEdit->text().isEmpty())
+ detailText.append(tr("Email: %1\n").arg(ui->emailLineEdit->text()));
+
+ if (m_commentIsProvided)
+ detailText.append(tr("Comments: %1\n").arg(ui->commentTextEdit->toPlainText()));
+
+ detailText.append(
+ tr("In addition, we send a Microsoft Minidump file, which contains information "
+ "about this computer, such as the operating system and CPU, and most "
+ "importantly, it contains the stacktrace, which is an internal structure that "
+ "shows where the program crashed. This information will help us to identify "
+ "the cause of the crash and to fix it."));
+
+ m_detailDialog.data()->setText(detailText);
+ }
+ if (m_detailDialog->isVisible())
+ m_detailDialog->showNormal();
+ else
+ m_detailDialog->show();
+}
diff --git a/src/libs/sqlite/sqlitedatabaseconnectionproxy.h b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.h
index ddc25f18b9..4e3b9880c1 100644
--- a/src/libs/sqlite/sqlitedatabaseconnectionproxy.h
+++ b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -25,39 +25,46 @@
#pragma once
-#include <sqliteglobal.h>
+#include "detaildialog.h"
-#include <QObject>
+#include <QByteArray>
+#include <QNetworkReply>
#include <QPointer>
+#include <QWidget>
-struct sqlite3;
-class SqliteWorkerThread;
+namespace Ui { class MainWidget; }
-class SQLITE_EXPORT SqliteDatabaseConnectionProxy final : public QObject
+class MainWidget : public QWidget
{
Q_OBJECT
-public:
- explicit SqliteDatabaseConnectionProxy(const QString &threadName);
- ~SqliteDatabaseConnectionProxy();
-
- QThread *connectionThread() const;
- bool isOpen() const;
+public:
+ explicit MainWidget(QWidget *parent = nullptr);
+ ~MainWidget();
- static void registerTypes();
+ void setProgressbarMaximum(int maximum);
+ void updateProgressBar(qint64 progressCount, qint64 fullCount);
signals:
- void setDatabaseFilePath(const QString &databaseFilePath);
- void setJournalMode(JournalMode journal);
- void connectionIsOpened();
- void connectionIsClosed();
- void close();
+ void restartCrashedApplication();
+ void sendDump();
+ void restartCrashedApplicationAndSendDump();
+ void emailAdressChanged(const QString &email);
+ void commentChanged(const QString &comment);
-private slots:
- void handleDatabaseConnectionIsOpened();
- void handleDatabaseConnectionIsClosed();
+protected:
+ void changeEvent(QEvent *e);
private:
- QPointer<SqliteWorkerThread> databaseConnectionThread;
- bool databaseConnectionIsOpen;
+ void restartApplication();
+ void quitApplication();
+ void showError(QNetworkReply::NetworkError error);
+ void showDetails();
+ void commentIsProvided();
+
+private:
+ Ui::MainWidget *ui;
+
+ QPointer<DetailDialog> m_detailDialog;
+ bool m_commentIsProvided = false;
};
diff --git a/src/libs/qt-breakpad/qtcrashhandler/mainwidget.ui b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.ui
new file mode 100644
index 0000000000..f509a70569
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler/mainwidget.ui
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWidget</class>
+ <widget class="QWidget" name="MainWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>422</width>
+ <height>510</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Crash Handler</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="font">
+ <font>
+ <pointsize>20</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Qt Creator has crashed</string>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>You can send us a crash report in order to help us diagnose and fix the problem.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Email:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="emailLineEdit">
+ <property name="placeholderText">
+ <string>Enter here your email (optional)</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="sendDumpCheckBox">
+ <property name="text">
+ <string>Tell The Qt Company about this crash so they can fix it</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="detailButton">
+ <property name="text">
+ <string>Details</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="commentTextEdit">
+ <property name="overwriteMode">
+ <bool>true</bool>
+ </property>
+ <property name="placeholderText">
+ <string>Please describe what you did before it crashed (comments are publicly visible)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Your crash report will be submitted before you quit or restart.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="value">
+ <number>0</number>
+ </property>
+ <property name="format">
+ <string>%v/%m Bytes</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="restartButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Restart</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="quitButton">
+ <property name="text">
+ <string>Quit</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/libs/qt-breakpad/qtcrashhandler/qtcrashhandler.pro b/src/libs/qt-breakpad/qtcrashhandler/qtcrashhandler.pro
new file mode 100644
index 0000000000..f4bca4e322
--- /dev/null
+++ b/src/libs/qt-breakpad/qtcrashhandler/qtcrashhandler.pro
@@ -0,0 +1,6 @@
+TARGET = qtcrashhandler
+QT += network
+TEMPLATE = app
+
+include(../qtcrashhandler.pri)
+DESTDIR = ../bin
diff --git a/src/libs/qt-breakpad/testapp/main.cpp b/src/libs/qt-breakpad/testapp/main.cpp
new file mode 100644
index 0000000000..1f21f86e4b
--- /dev/null
+++ b/src/libs/qt-breakpad/testapp/main.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include <qtsystemexceptionhandler.h>
+
+#include <QCoreApplication>
+#include <QTimer>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+
+ a.setApplicationName("testapp");
+ a.setApplicationVersion("1.0.0");
+
+ QtSystemExceptionHandler exceptionHandler;
+
+ QTimer::singleShot(100, [] { QtSystemExceptionHandler::crash(); });
+
+ return a.exec();
+}
diff --git a/src/libs/qt-breakpad/testapp/testapp.pro b/src/libs/qt-breakpad/testapp/testapp.pro
new file mode 100644
index 0000000000..407ad1e2ea
--- /dev/null
+++ b/src/libs/qt-breakpad/testapp/testapp.pro
@@ -0,0 +1,14 @@
+QT -= gui
+
+include(../qtbreakpad.pri)
+
+unix:TARGET = testapp.bin
+win32:TARGET = testapp
+
+## install_name_tool -change libQtBreakpad.1.dylib @executable_path/../lib/qtbreakpad/libQtBreakpad.dylib
+
+DESTDIR = ../bin
+
+CONFIG += console release c++11
+
+SOURCES += main.cpp
diff --git a/src/libs/sqlite/columndefinition.h b/src/libs/sqlite/columndefinition.h
deleted file mode 100644
index 91f64cb24c..0000000000
--- a/src/libs/sqlite/columndefinition.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "sqliteglobal.h"
-#include "utf8string.h"
-
-namespace Internal {
-
-class ColumnDefinition
-{
-public:
- void setName(const Utf8String &name);
- const Utf8String &name() const;
-
- void setType(ColumnType type);
- ColumnType type() const;
- Utf8String typeString() const;
-
- void setIsPrimaryKey(bool isPrimaryKey);
- bool isPrimaryKey() const;
-
-private:
- Utf8String name_;
- ColumnType type_;
- bool isPrimaryKey_ = false;
-};
-
-}
diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.cpp b/src/libs/sqlite/createtablesqlstatementbuilder.cpp
index 71ca071997..9a64d8e488 100644
--- a/src/libs/sqlite/createtablesqlstatementbuilder.cpp
+++ b/src/libs/sqlite/createtablesqlstatementbuilder.cpp
@@ -25,102 +25,129 @@
#include "createtablesqlstatementbuilder.h"
-#include "utf8stringvector.h"
-
-namespace Internal {
+namespace Sqlite {
CreateTableSqlStatementBuilder::CreateTableSqlStatementBuilder()
- : sqlStatementBuilder(Utf8StringLiteral("CREATE TABLE IF NOT EXISTS $table($columnDefinitions)$withoutRowId")),
- useWithoutRowId(false)
+ : m_sqlStatementBuilder("CREATE $temporaryTABLE $ifNotExits$table($columnDefinitions)$withoutRowId")
{
}
-void CreateTableSqlStatementBuilder::setTable(const Utf8String &tableName)
+void CreateTableSqlStatementBuilder::setTableName(Utils::SmallString &&tableName)
{
- sqlStatementBuilder.clear();
+ m_sqlStatementBuilder.clear();
- this->tableName = tableName;
+ this->m_tableName = std::move(tableName);
}
-void CreateTableSqlStatementBuilder::addColumnDefinition(const Utf8String &columnName,
- ColumnType columnType,
- bool isPrimaryKey)
+void CreateTableSqlStatementBuilder::addColumn(Utils::SmallString &&columnName,
+ ColumnType columnType,
+ Contraint constraint)
{
- sqlStatementBuilder.clear();
-
- ColumnDefinition columnDefinition;
- columnDefinition.setName(columnName);
- columnDefinition.setType(columnType);
- columnDefinition.setIsPrimaryKey(isPrimaryKey);
+ m_sqlStatementBuilder.clear();
- columnDefinitions.append(columnDefinition);
+ m_columns.emplace_back(std::move(columnName), columnType, constraint);
}
-void CreateTableSqlStatementBuilder::setColumnDefinitions(const QVector<ColumnDefinition> &columnDefinitions)
+void CreateTableSqlStatementBuilder::setColumns(const SqliteColumns &columns)
{
- sqlStatementBuilder.clear();
+ m_sqlStatementBuilder.clear();
- this->columnDefinitions = columnDefinitions;
+ m_columns = std::move(columns);
}
void CreateTableSqlStatementBuilder::setUseWithoutRowId(bool useWithoutRowId)
{
- this->useWithoutRowId = useWithoutRowId;
+ m_useWithoutRowId = useWithoutRowId;
+}
+
+void CreateTableSqlStatementBuilder::setUseIfNotExists(bool useIfNotExists)
+{
+ m_useIfNotExits = useIfNotExists;
+}
+
+void CreateTableSqlStatementBuilder::setUseTemporaryTable(bool useTemporaryTable)
+{
+ m_useTemporaryTable = useTemporaryTable;
}
void CreateTableSqlStatementBuilder::clear()
{
- sqlStatementBuilder.clear();
- columnDefinitions.clear();
- tableName.clear();
- useWithoutRowId = false;
+ m_sqlStatementBuilder.clear();
+ m_columns.clear();
+ m_tableName.clear();
+ m_useWithoutRowId = false;
}
void CreateTableSqlStatementBuilder::clearColumns()
{
- sqlStatementBuilder.clear();
- columnDefinitions.clear();
+ m_sqlStatementBuilder.clear();
+ m_columns.clear();
}
-Utf8String CreateTableSqlStatementBuilder::sqlStatement() const
+Utils::SmallStringView CreateTableSqlStatementBuilder::sqlStatement() const
{
- if (!sqlStatementBuilder.isBuild())
+ if (!m_sqlStatementBuilder.isBuild())
bindAll();
- return sqlStatementBuilder.sqlStatement();
+ return m_sqlStatementBuilder.sqlStatement();
}
bool CreateTableSqlStatementBuilder::isValid() const
{
- return tableName.hasContent() && !columnDefinitions.isEmpty();
+ return m_tableName.hasContent() && !m_columns.empty();
}
void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
{
- Utf8StringVector columnDefinitionStrings;
+ Utils::SmallStringVector columnDefinitionStrings;
- foreach (const ColumnDefinition &columnDefinition, columnDefinitions) {
- Utf8String columnDefinitionString = columnDefinition.name() + Utf8StringLiteral(" ") + columnDefinition.typeString();
+ for (const Column &columns : m_columns) {
+ Utils::SmallString columnDefinitionString = {columns.name(), " ", columns.typeString()};
- if (columnDefinition.isPrimaryKey())
- columnDefinitionString.append(Utf8StringLiteral(" PRIMARY KEY"));
+ switch (columns.constraint()) {
+ case Contraint::PrimaryKey: columnDefinitionString.append(" PRIMARY KEY"); break;
+ case Contraint::Unique: columnDefinitionString.append(" UNIQUE"); break;
+ case Contraint::NoConstraint: break;
+ }
- columnDefinitionStrings.append(columnDefinitionString);
+ columnDefinitionStrings.push_back(columnDefinitionString);
}
- sqlStatementBuilder.bind(Utf8StringLiteral("$columnDefinitions"), columnDefinitionStrings);
+ m_sqlStatementBuilder.bind("$columnDefinitions", columnDefinitionStrings);
}
void CreateTableSqlStatementBuilder::bindAll() const
{
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), tableName);
+ m_sqlStatementBuilder.bind("$table", m_tableName.clone());
+ bindTemporary();
+ bindIfNotExists();
bindColumnDefinitions();
+ bindWithoutRowId();
+}
- if (useWithoutRowId)
- sqlStatementBuilder.bind(Utf8StringLiteral("$withoutRowId"), Utf8StringLiteral(" WITHOUT ROWID"));
+void CreateTableSqlStatementBuilder::bindWithoutRowId() const
+{
+ if (m_useWithoutRowId)
+ m_sqlStatementBuilder.bind("$withoutRowId", " WITHOUT ROWID");
+ else
+ m_sqlStatementBuilder.bindEmptyText("$withoutRowId");
+}
+
+void CreateTableSqlStatementBuilder::bindIfNotExists() const
+{
+ if (m_useIfNotExits)
+ m_sqlStatementBuilder.bind("$ifNotExits", "IF NOT EXISTS ");
else
- sqlStatementBuilder.bindEmptyText(Utf8StringLiteral("$withoutRowId"));
+ m_sqlStatementBuilder.bindEmptyText("$ifNotExits");
}
+void CreateTableSqlStatementBuilder::bindTemporary() const
+{
+ if (m_useTemporaryTable)
+ m_sqlStatementBuilder.bind("$temporary", "TEMPORARY ");
+ else
+ m_sqlStatementBuilder.bindEmptyText("$temporary");
}
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.h b/src/libs/sqlite/createtablesqlstatementbuilder.h
index 3445d4946f..00c9ebd45a 100644
--- a/src/libs/sqlite/createtablesqlstatementbuilder.h
+++ b/src/libs/sqlite/createtablesqlstatementbuilder.h
@@ -25,39 +25,46 @@
#pragma once
-#include "columndefinition.h"
+#include "sqlitecolumn.h"
#include "sqlstatementbuilder.h"
-#include <QVector>
-
-namespace Internal {
+namespace Sqlite {
class SQLITE_EXPORT CreateTableSqlStatementBuilder
{
public:
CreateTableSqlStatementBuilder();
- void setTable(const Utf8String &tableName);
- void addColumnDefinition(const Utf8String &columnName, ColumnType columnType, bool isPrimaryKey = false);
- void setColumnDefinitions(const QVector<ColumnDefinition> & columnDefinitions);
+ void setTableName(Utils::SmallString &&tableName);
+ void addColumn(Utils::SmallString &&columnName,
+ ColumnType columnType,
+ Contraint constraint = Contraint::NoConstraint);
+ void setColumns(const SqliteColumns &columns);
void setUseWithoutRowId(bool useWithoutRowId);
+ void setUseIfNotExists(bool useIfNotExists);
+ void setUseTemporaryTable(bool useTemporaryTable);
void clear();
void clearColumns();
- Utf8String sqlStatement() const;
+ Utils::SmallStringView sqlStatement() const;
bool isValid() const;
protected:
void bindColumnDefinitions() const;
void bindAll() const;
+ void bindWithoutRowId() const;
+ void bindIfNotExists() const;
+ void bindTemporary() const;
private:
- mutable SqlStatementBuilder sqlStatementBuilder;
- Utf8String tableName;
- QVector<ColumnDefinition> columnDefinitions;
- bool useWithoutRowId;
+ mutable SqlStatementBuilder m_sqlStatementBuilder;
+ Utils::SmallString m_tableName;
+ SqliteColumns m_columns;
+ bool m_useWithoutRowId = false;
+ bool m_useIfNotExits = false;
+ bool m_useTemporaryTable = false;
};
-}
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri
index 9160fba4cc..67c8c6b937 100644
--- a/src/libs/sqlite/sqlite-lib.pri
+++ b/src/libs/sqlite/sqlite-lib.pri
@@ -11,19 +11,14 @@ unix:!bsd: LIBS += -ldl
include(../3rdparty/sqlite/sqlite.pri)
SOURCES += \
- $$PWD/columndefinition.cpp \
- $$PWD/createtablecommand.cpp \
$$PWD/createtablesqlstatementbuilder.cpp \
$$PWD/sqlitedatabasebackend.cpp \
- $$PWD/sqlitedatabaseconnection.cpp \
- $$PWD/sqlitedatabaseconnectionproxy.cpp \
$$PWD/sqliteexception.cpp \
$$PWD/sqliteglobal.cpp \
$$PWD/sqlitereadstatement.cpp \
$$PWD/sqlitereadwritestatement.cpp \
$$PWD/sqlitestatement.cpp \
$$PWD/sqlitetransaction.cpp \
- $$PWD/sqliteworkerthread.cpp \
$$PWD/sqlitewritestatement.cpp \
$$PWD/sqlstatementbuilder.cpp \
$$PWD/sqlstatementbuilderexception.cpp \
@@ -31,22 +26,16 @@ SOURCES += \
$$PWD/utf8stringvector.cpp \
$$PWD/sqlitedatabase.cpp \
$$PWD/sqlitetable.cpp \
- $$PWD/sqlitecolumn.cpp \
- $$PWD/tablewriteworker.cpp \
- $$PWD/tablewriteworkerproxy.cpp
+ $$PWD/sqlitecolumn.cpp
HEADERS += \
- $$PWD/columndefinition.h \
$$PWD/createtablesqlstatementbuilder.h \
$$PWD/sqlitedatabasebackend.h \
- $$PWD/sqlitedatabaseconnection.h \
- $$PWD/sqlitedatabaseconnectionproxy.h \
$$PWD/sqliteexception.h \
$$PWD/sqliteglobal.h \
$$PWD/sqlitereadstatement.h \
$$PWD/sqlitereadwritestatement.h \
$$PWD/sqlitestatement.h \
$$PWD/sqlitetransaction.h \
- $$PWD/sqliteworkerthread.h \
$$PWD/sqlitewritestatement.h \
$$PWD/sqlstatementbuilder.h \
$$PWD/sqlstatementbuilderexception.h \
@@ -55,9 +44,7 @@ HEADERS += \
$$PWD/sqlitedatabase.h \
$$PWD/sqlitetable.h \
$$PWD/sqlitecolumn.h \
- $$PWD/tablewriteworker.h \
- $$PWD/tablewriteworkerproxy.h \
- $$PWD/createtablecommand.h
+ $$PWD/sqliteindex.h
DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA
diff --git a/src/libs/sqlite/sqlitecolumn.cpp b/src/libs/sqlite/sqlitecolumn.cpp
index 6f7adfd679..201f1fbcb9 100644
--- a/src/libs/sqlite/sqlitecolumn.cpp
+++ b/src/libs/sqlite/sqlitecolumn.cpp
@@ -25,57 +25,7 @@
#include "sqlitecolumn.h"
-SqliteColumn::SqliteColumn()
- : type_(ColumnType::Numeric),
- isPrimaryKey_(false)
-{
+namespace Sqlite {
-}
-void SqliteColumn::clear()
-{
- name_.clear();
- type_ = ColumnType::Numeric;
- isPrimaryKey_ = false;
-}
-
-void SqliteColumn::setName(const Utf8String &newName)
-{
- name_ = newName;
-}
-
-const Utf8String &SqliteColumn::name() const
-{
- return name_;
-}
-
-void SqliteColumn::setType(ColumnType newType)
-{
- type_ = newType;
-}
-
-ColumnType SqliteColumn::type() const
-{
- return type_;
-}
-
-void SqliteColumn::setIsPrimaryKey(bool isPrimaryKey)
-{
- isPrimaryKey_ = isPrimaryKey;
-}
-
-bool SqliteColumn::isPrimaryKey() const
-{
- return isPrimaryKey_;
-}
-
-Internal::ColumnDefinition SqliteColumn::columnDefintion() const
-{
- Internal::ColumnDefinition columnDefinition;
-
- columnDefinition.setName(name_);
- columnDefinition.setType(type_);
- columnDefinition.setIsPrimaryKey(isPrimaryKey_);
-
- return columnDefinition;
-}
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitecolumn.h b/src/libs/sqlite/sqlitecolumn.h
index 136691e36d..d6401d299b 100644
--- a/src/libs/sqlite/sqlitecolumn.h
+++ b/src/libs/sqlite/sqlitecolumn.h
@@ -25,32 +25,92 @@
#pragma once
-#include "columndefinition.h"
-#include "utf8string.h"
+#include "sqliteglobal.h"
-#include <QObject>
+#include <utils/smallstring.h>
-class SQLITE_EXPORT SqliteColumn : public QObject
+#include <functional>
+
+namespace Sqlite {
+
+class Column
{
- Q_OBJECT
public:
- SqliteColumn();
+ Column() = default;
+
+ Column(Utils::SmallString &&name,
+ ColumnType type = ColumnType::Numeric,
+ Contraint constraint = Contraint::NoConstraint)
+ : m_name(std::move(name)),
+ m_type(type),
+ m_constraint(constraint)
+ {}
+
+ void clear()
+ {
+ m_name.clear();
+ m_type = ColumnType::Numeric;
+ m_constraint = Contraint::NoConstraint;
+ }
+
+ void setName(Utils::SmallString &&newName)
+ {
+ m_name = newName;
+ }
- void clear();
+ const Utils::SmallString &name() const
+ {
+ return m_name;
+ }
- void setName(const Utf8String &newName);
- const Utf8String &name() const;
+ void setType(ColumnType newType)
+ {
+ m_type = newType;
+ }
- void setType(ColumnType newType);
- ColumnType type() const;
+ ColumnType type() const
+ {
+ return m_type;
+ }
- void setIsPrimaryKey(bool isPrimaryKey);
- bool isPrimaryKey() const;
+ void setContraint(Contraint constraint)
+ {
+ m_constraint = constraint;
+ }
- Internal::ColumnDefinition columnDefintion() const;
+ Contraint constraint() const
+ {
+ return m_constraint;
+ }
+
+ Utils::SmallString typeString() const
+ {
+ switch (m_type) {
+ case ColumnType::None: return {};
+ case ColumnType::Numeric: return "NUMERIC";
+ case ColumnType::Integer: return "INTEGER";
+ case ColumnType::Real: return "REAL";
+ case ColumnType::Text: return "TEXT";
+ }
+
+ Q_UNREACHABLE();
+ }
+
+ friend bool operator==(const Column &first, const Column &second)
+ {
+ return first.m_name == second.m_name
+ && first.m_type == second.m_type
+ && first.m_constraint == second.m_constraint;
+ }
private:
- Utf8String name_;
- ColumnType type_;
- bool isPrimaryKey_;
+ Utils::SmallString m_name;
+ ColumnType m_type = ColumnType::Numeric;
+ Contraint m_constraint = Contraint::NoConstraint;
};
+
+using SqliteColumns = std::vector<Column>;
+using SqliteColumnConstReference = std::reference_wrapper<const Column>;
+using SqliteColumnConstReferences = std::vector<SqliteColumnConstReference>;
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitedatabase.cpp b/src/libs/sqlite/sqlitedatabase.cpp
index 7fe349eeaf..aa265593c5 100644
--- a/src/libs/sqlite/sqlitedatabase.cpp
+++ b/src/libs/sqlite/sqlitedatabase.cpp
@@ -26,116 +26,106 @@
#include "sqlitedatabase.h"
#include "sqlitetable.h"
+#include "sqlitetransaction.h"
-SqliteDatabase::SqliteDatabase()
- : readDatabaseConnection(QStringLiteral("ReadWorker")),
- writeDatabaseConnection(QStringLiteral("WriterWorker")),
- journalMode_(JournalMode::Wal)
-{
- connect(&readDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsOpened, this, &SqliteDatabase::handleReadDatabaseConnectionIsOpened);
- connect(&writeDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsOpened, this, &SqliteDatabase::handleWriteDatabaseConnectionIsOpened);
- connect(&readDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsClosed, this, &SqliteDatabase::handleReadDatabaseConnectionIsClosed);
- connect(&writeDatabaseConnection, &SqliteDatabaseConnectionProxy::connectionIsClosed, this, &SqliteDatabase::handleWriteDatabaseConnectionIsClosed);
-}
+namespace Sqlite {
-SqliteDatabase::~SqliteDatabase()
+Database::Database()
+ : m_databaseBackend(*this)
{
- qDeleteAll(sqliteTables);
}
-void SqliteDatabase::open()
+Database::Database(Utils::PathString &&databaseFilePath)
+ : m_databaseBackend(*this)
{
- writeDatabaseConnection.setDatabaseFilePath(databaseFilePath());
- writeDatabaseConnection.setJournalMode(journalMode());
+ open(std::move(databaseFilePath));
}
-void SqliteDatabase::close()
+void Database::open()
{
- writeDatabaseConnection.close();
+ m_databaseBackend.open(m_databaseFilePath, m_openMode);
+ m_databaseBackend.setJournalMode(m_journalMode);
+ initializeTables();
+ m_isOpen = true;
}
-bool SqliteDatabase::isOpen() const
+void Database::open(Utils::PathString &&databaseFilePath)
{
- return readDatabaseConnection.isOpen() && writeDatabaseConnection.isOpen();
+ setDatabaseFilePath(std::move(databaseFilePath));
+ open();
}
-void SqliteDatabase::addTable(SqliteTable *newSqliteTable)
+void Database::close()
{
- newSqliteTable->setSqliteDatabase(this);
- sqliteTables.append(newSqliteTable);
+ m_isOpen = false;
+ m_databaseBackend.close();
}
-const QVector<SqliteTable *> &SqliteDatabase::tables() const
+bool Database::isOpen() const
{
- return sqliteTables;
+ return m_isOpen;
}
-void SqliteDatabase::setDatabaseFilePath(const QString &databaseFilePath)
+Table &Database::addTable()
{
- databaseFilePath_ = databaseFilePath;
-}
+ m_sqliteTables.emplace_back();
-const QString &SqliteDatabase::databaseFilePath() const
-{
- return databaseFilePath_;
+ return m_sqliteTables.back();
}
-void SqliteDatabase::setJournalMode(JournalMode journalMode)
+const std::vector<Table> &Database::tables() const
{
- journalMode_ = journalMode;
+ return m_sqliteTables;
}
-JournalMode SqliteDatabase::journalMode() const
+void Database::setDatabaseFilePath(Utils::PathString &&databaseFilePath)
{
- return journalMode_;
+ m_databaseFilePath = std::move(databaseFilePath);
}
-QThread *SqliteDatabase::writeWorkerThread() const
+const Utils::PathString &Database::databaseFilePath() const
{
- return writeDatabaseConnection.connectionThread();
+ return m_databaseFilePath;
}
-QThread *SqliteDatabase::readWorkerThread() const
+void Database::setJournalMode(JournalMode journalMode)
{
- return readDatabaseConnection.connectionThread();
+ m_journalMode = journalMode;
}
-void SqliteDatabase::handleReadDatabaseConnectionIsOpened()
+JournalMode Database::journalMode() const
{
- if (writeDatabaseConnection.isOpen() && readDatabaseConnection.isOpen()) {
- initializeTables();
- emit databaseIsOpened();
- }
+ return m_journalMode;
}
-void SqliteDatabase::handleWriteDatabaseConnectionIsOpened()
+void Database::setOpenMode(OpenMode openMode)
{
- readDatabaseConnection.setDatabaseFilePath(databaseFilePath());
+ m_openMode = openMode;
}
-void SqliteDatabase::handleReadDatabaseConnectionIsClosed()
+OpenMode Database::openMode() const
{
- if (!writeDatabaseConnection.isOpen() && !readDatabaseConnection.isOpen()) {
- shutdownTables();
- emit databaseIsClosed();
- }
+ return m_openMode;
}
-void SqliteDatabase::handleWriteDatabaseConnectionIsClosed()
+void Database::execute(Utils::SmallStringView sqlStatement)
{
- readDatabaseConnection.close();
+ m_databaseBackend.execute(sqlStatement);
}
-void SqliteDatabase::initializeTables()
+void Database::initializeTables()
{
- for (SqliteTable *table: tables())
- table->initialize();
+ ImmediateTransaction<Database> transaction(*this);
+
+ for (Table &table : m_sqliteTables)
+ table.initialize(*this);
+
+ transaction.commit();
}
-void SqliteDatabase::shutdownTables()
+DatabaseBackend &Database::backend()
{
- for (SqliteTable *table: tables())
- table->shutdown();
+ return m_databaseBackend;
}
-
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h
index 91454329ee..125bccaf24 100644
--- a/src/libs/sqlite/sqlitedatabase.h
+++ b/src/libs/sqlite/sqlitedatabase.h
@@ -25,55 +25,85 @@
#pragma once
-#include "sqlitedatabaseconnectionproxy.h"
+#include "sqlitedatabasebackend.h"
#include "sqliteglobal.h"
+#include "sqlitetable.h"
-#include <QString>
-#include <QVector>
+#include <utils/smallstring.h>
-class SqliteTable;
+#include <mutex>
+#include <vector>
-class SQLITE_EXPORT SqliteDatabase : public QObject
+namespace Sqlite {
+
+class SQLITE_EXPORT Database
{
- Q_OBJECT
+ template <typename Database>
+ friend class AbstractTransaction;
+ friend class Statement;
+ friend class Backend;
public:
- SqliteDatabase();
- ~SqliteDatabase();
+ using MutexType = std::mutex;
+
+ Database();
+ Database(Utils::PathString &&databaseFilePath);
+
+ Database(const Database &) = delete;
+ bool operator=(const Database &) = delete;
+
+ Database(Database &&) = delete;
+ bool operator=(Database &&) = delete;
void open();
+ void open(Utils::PathString &&databaseFilePath);
void close();
bool isOpen() const;
- void addTable(SqliteTable *newSqliteTable);
- const QVector<SqliteTable *> &tables() const;
+ Table &addTable();
+ const std::vector<Table> &tables() const;
- void setDatabaseFilePath(const QString &databaseFilePath);
- const QString &databaseFilePath() const;
+ void setDatabaseFilePath(Utils::PathString &&databaseFilePath);
+ const Utils::PathString &databaseFilePath() const;
void setJournalMode(JournalMode journalMode);
JournalMode journalMode() const;
- QThread *writeWorkerThread() const;
- QThread *readWorkerThread() const;
+ void setOpenMode(OpenMode openMode);
+ OpenMode openMode() const;
+
+ void execute(Utils::SmallStringView sqlStatement);
-signals:
- void databaseIsOpened();
- void databaseIsClosed();
+ DatabaseBackend &backend();
+
+ int64_t lastInsertedRowId() const
+ {
+ return m_databaseBackend.lastInsertedRowId();
+ }
+
+ int changesCount()
+ {
+ return m_databaseBackend.changesCount();
+ }
+
+ int totalChangesCount()
+ {
+ return m_databaseBackend.totalChangesCount();
+ }
private:
- void handleReadDatabaseConnectionIsOpened();
- void handleWriteDatabaseConnectionIsOpened();
- void handleReadDatabaseConnectionIsClosed();
- void handleWriteDatabaseConnectionIsClosed();
void initializeTables();
- void shutdownTables();
+ std::mutex &databaseMutex() { return m_databaseMutex; }
private:
- SqliteDatabaseConnectionProxy readDatabaseConnection;
- SqliteDatabaseConnectionProxy writeDatabaseConnection;
- QVector<SqliteTable*> sqliteTables;
- QString databaseFilePath_;
- JournalMode journalMode_;
+ Utils::PathString m_databaseFilePath;
+ DatabaseBackend m_databaseBackend;
+ std::vector<Table> m_sqliteTables;
+ std::mutex m_databaseMutex;
+ JournalMode m_journalMode = JournalMode::Wal;
+ OpenMode m_openMode = OpenMode::ReadWrite;
+ bool m_isOpen = false;
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp
index 31ea378d12..5c4fc95e73 100644
--- a/src/libs/sqlite/sqlitedatabasebackend.cpp
+++ b/src/libs/sqlite/sqlitedatabasebackend.cpp
@@ -31,6 +31,7 @@
#include "sqlitestatement.h"
#include "sqlitewritestatement.h"
+#include <QFileInfo>
#include <QThread>
#include <QDebug>
@@ -38,36 +39,27 @@
#include "sqlite3.h"
-#if defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
-#define QTC_THREAD_LOCAL __thread
-#else
-#define QTC_THREAD_LOCAL thread_local
-#endif
-
-#define SIZE_OF_BYTEARRAY_ARRAY(array) sizeof(array)/sizeof(QByteArray)
-
-QTC_THREAD_LOCAL SqliteDatabaseBackend *sqliteDatabaseBackend = nullptr;
+namespace Sqlite {
-SqliteDatabaseBackend::SqliteDatabaseBackend()
- : databaseHandle(nullptr),
- cachedTextEncoding(Utf8)
+DatabaseBackend::DatabaseBackend(Database &database)
+ : m_database(database),
+ m_databaseHandle(nullptr),
+ m_cachedTextEncoding(Utf8)
{
- sqliteDatabaseBackend = this;
}
-SqliteDatabaseBackend::~SqliteDatabaseBackend()
+DatabaseBackend::~DatabaseBackend()
{
closeWithoutException();
- sqliteDatabaseBackend = nullptr;
}
-void SqliteDatabaseBackend::setMmapSize(qint64 defaultSize, qint64 maximumSize)
+void DatabaseBackend::setMmapSize(qint64 defaultSize, qint64 maximumSize)
{
int resultCode = sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, defaultSize, maximumSize);
checkMmapSizeIsSet(resultCode);
}
-void SqliteDatabaseBackend::activateMultiThreading()
+void DatabaseBackend::activateMultiThreading()
{
int resultCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
checkIfMultithreadingIsActivated(resultCode);
@@ -78,39 +70,38 @@ static void sqliteLog(void*,int errorCode,const char *errorMessage)
qWarning() << sqlite3_errstr(errorCode) << errorMessage;
}
-void SqliteDatabaseBackend::activateLogging()
+void DatabaseBackend::activateLogging()
{
int resultCode = sqlite3_config(SQLITE_CONFIG_LOG, sqliteLog, nullptr);
checkIfLoogingIsActivated(resultCode);
}
-void SqliteDatabaseBackend::initializeSqliteLibrary()
+void DatabaseBackend::initializeSqliteLibrary()
{
int resultCode = sqlite3_initialize();
checkInitializeSqliteLibraryWasSuccesful(resultCode);
}
-void SqliteDatabaseBackend::shutdownSqliteLibrary()
+void DatabaseBackend::shutdownSqliteLibrary()
{
int resultCode = sqlite3_shutdown();
checkShutdownSqliteLibraryWasSuccesful(resultCode);
}
-void SqliteDatabaseBackend::checkpointFullWalLog()
+void DatabaseBackend::checkpointFullWalLog()
{
int resultCode = sqlite3_wal_checkpoint_v2(sqliteDatabaseHandle(), nullptr, SQLITE_CHECKPOINT_FULL, nullptr, nullptr);
checkIfLogCouldBeCheckpointed(resultCode);
}
-void SqliteDatabaseBackend::open(const QString &databaseFilePath)
+void DatabaseBackend::open(Utils::SmallStringView databaseFilePath, OpenMode mode)
{
checkCanOpenDatabase(databaseFilePath);
- QByteArray databaseUtf8Path = databaseFilePath.toUtf8();
- int resultCode = sqlite3_open_v2(databaseUtf8Path.data(),
- &databaseHandle,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
- NULL);
+ int resultCode = sqlite3_open_v2(databaseFilePath.data(),
+ &m_databaseHandle,
+ openMode(mode),
+ NULL);
checkDatabaseCouldBeOpened(resultCode);
@@ -119,110 +110,114 @@ void SqliteDatabaseBackend::open(const QString &databaseFilePath)
cacheTextEncoding();
}
-sqlite3 *SqliteDatabaseBackend::sqliteDatabaseHandle()
+sqlite3 *DatabaseBackend::sqliteDatabaseHandle() const
{
- checkDatabaseBackendIsNotNull();
checkDatabaseHandleIsNotNull();
- return threadLocalInstance()->databaseHandle;
+ return m_databaseHandle;
}
-void SqliteDatabaseBackend::setPragmaValue(const Utf8String &pragmaKey, const Utf8String &newPragmaValue)
+void DatabaseBackend::setPragmaValue(Utils::SmallStringView pragmaKey, Utils::SmallStringView newPragmaValue)
{
- SqliteReadWriteStatement::execute(Utf8StringLiteral("PRAGMA ") + pragmaKey + Utf8StringLiteral("='") + newPragmaValue + Utf8StringLiteral("'"));
- Utf8String pragmeValueInDatabase = SqliteReadWriteStatement::toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragmaKey);
+ execute(Utils::SmallString{"PRAGMA ", pragmaKey, "='", newPragmaValue, "'"});
+ Utils::SmallString pragmeValueInDatabase = toValue<Utils::SmallString>("PRAGMA " + pragmaKey);
checkPragmaValue(pragmeValueInDatabase, newPragmaValue);
}
-Utf8String SqliteDatabaseBackend::pragmaValue(const Utf8String &pragma) const
+Utils::SmallString DatabaseBackend::pragmaValue(Utils::SmallStringView pragma)
{
- return SqliteReadWriteStatement::toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragma);
+ return toValue<Utils::SmallString>("PRAGMA " + pragma);
}
-void SqliteDatabaseBackend::setJournalMode(JournalMode journalMode)
+void DatabaseBackend::setJournalMode(JournalMode journalMode)
{
- setPragmaValue(Utf8StringLiteral("journal_mode"), journalModeToPragma(journalMode));
+ setPragmaValue("journal_mode", journalModeToPragma(journalMode));
}
-JournalMode SqliteDatabaseBackend::journalMode() const
+JournalMode DatabaseBackend::journalMode()
{
- return pragmaToJournalMode(pragmaValue(Utf8StringLiteral("journal_mode")));
+ return pragmaToJournalMode(pragmaValue("journal_mode"));
}
-void SqliteDatabaseBackend::setTextEncoding(TextEncoding textEncoding)
+void DatabaseBackend::setTextEncoding(TextEncoding textEncoding)
{
- setPragmaValue(Utf8StringLiteral("encoding"), textEncodingToPragma(textEncoding));
+ setPragmaValue("encoding", textEncodingToPragma(textEncoding));
cacheTextEncoding();
}
-TextEncoding SqliteDatabaseBackend::textEncoding()
+TextEncoding DatabaseBackend::textEncoding()
{
- return cachedTextEncoding;
+ return m_cachedTextEncoding;
}
-Utf8StringVector SqliteDatabaseBackend::columnNames(const Utf8String &tableName)
+Utils::SmallStringVector DatabaseBackend::columnNames(Utils::SmallStringView tableName)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT * FROM ") + tableName);
+ ReadWriteStatement statement("SELECT * FROM " + tableName, m_database);
return statement.columnNames();
}
-int SqliteDatabaseBackend::changesCount()
+int DatabaseBackend::changesCount() const
{
return sqlite3_changes(sqliteDatabaseHandle());
}
-int SqliteDatabaseBackend::totalChangesCount()
+int DatabaseBackend::totalChangesCount() const
{
return sqlite3_total_changes(sqliteDatabaseHandle());
}
-void SqliteDatabaseBackend::close()
+int64_t DatabaseBackend::lastInsertedRowId() const
+{
+ return sqlite3_last_insert_rowid(sqliteDatabaseHandle());
+}
+
+void DatabaseBackend::execute(Utils::SmallStringView sqlStatement)
+{
+ ReadWriteStatement statement(sqlStatement, m_database);
+ statement.step();
+}
+
+void DatabaseBackend::close()
{
checkForOpenDatabaseWhichCanBeClosed();
- int resultCode = sqlite3_close(databaseHandle);
+ int resultCode = sqlite3_close(m_databaseHandle);
checkDatabaseClosing(resultCode);
- databaseHandle = nullptr;
-
-}
+ m_databaseHandle = nullptr;
-SqliteDatabaseBackend *SqliteDatabaseBackend::threadLocalInstance()
-{
- checkDatabaseBackendIsNotNull();
- return sqliteDatabaseBackend;
}
-bool SqliteDatabaseBackend::databaseIsOpen() const
+bool DatabaseBackend::databaseIsOpen() const
{
- return databaseHandle != nullptr;
+ return m_databaseHandle != nullptr;
}
-void SqliteDatabaseBackend::closeWithoutException()
+void DatabaseBackend::closeWithoutException()
{
- if (databaseHandle) {
- int resultCode = sqlite3_close_v2(databaseHandle);
- databaseHandle = nullptr;
+ if (m_databaseHandle) {
+ int resultCode = sqlite3_close_v2(m_databaseHandle);
+ m_databaseHandle = nullptr;
if (resultCode != SQLITE_OK)
qWarning() << "SqliteDatabaseBackend::closeWithoutException: Unexpected error at closing the database!";
}
}
-void SqliteDatabaseBackend::registerBusyHandler()
+void DatabaseBackend::registerBusyHandler()
{
sqlite3_busy_handler(sqliteDatabaseHandle(), &busyHandlerCallback, nullptr);
}
-void SqliteDatabaseBackend::registerRankingFunction()
+void DatabaseBackend::registerRankingFunction()
{
sqlite3_create_function_v2(sqliteDatabaseHandle(), "okapi_bm25", -1, SQLITE_ANY, 0, okapi_bm25, 0, 0, 0);
sqlite3_create_function_v2(sqliteDatabaseHandle(), "okapi_bm25f", -1, SQLITE_UTF8, 0, okapi_bm25f, 0, 0, 0);
sqlite3_create_function_v2(sqliteDatabaseHandle(), "okapi_bm25f_kb", -1, SQLITE_UTF8, 0, okapi_bm25f_kb, 0, 0, 0);
}
-int SqliteDatabaseBackend::busyHandlerCallback(void *, int counter)
+int DatabaseBackend::busyHandlerCallback(void *, int counter)
{
Q_UNUSED(counter);
#ifdef QT_DEBUG
@@ -233,158 +228,199 @@ int SqliteDatabaseBackend::busyHandlerCallback(void *, int counter)
return true;
}
-void SqliteDatabaseBackend::cacheTextEncoding()
+void DatabaseBackend::cacheTextEncoding()
{
- cachedTextEncoding = pragmaToTextEncoding(pragmaValue(Utf8StringLiteral("encoding")));
+ m_cachedTextEncoding = pragmaToTextEncoding(pragmaValue("encoding"));
}
-void SqliteDatabaseBackend::checkForOpenDatabaseWhichCanBeClosed()
+void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed()
{
- if (databaseHandle == nullptr)
- throwException("SqliteDatabaseBackend::close: database is not open so it can not be closed.");
+ if (m_databaseHandle == nullptr)
+ throw DatabaseIsAlreadyClosed("SqliteDatabaseBackend::close: database is not open so it can not be closed.");
}
-void SqliteDatabaseBackend::checkDatabaseClosing(int resultCode)
+void DatabaseBackend::checkDatabaseClosing(int resultCode)
{
switch (resultCode) {
case SQLITE_OK: return;
- default: throwException("SqliteDatabaseBackend::close: unknown error happens at closing!");
+ case SQLITE_BUSY: throw DatabaseIsBusy("SqliteDatabaseBackend::close: database is busy because of e.g. unfinalized statements and will stay open!");
+ default: throwUnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!");
}
}
-void SqliteDatabaseBackend::checkCanOpenDatabase(const QString &databaseFilePath)
+void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath)
{
if (databaseFilePath.isEmpty())
- throw SqliteException("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database file path is empty!");
+ throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because the file path is empty!");
+
+ if (!QFileInfo::exists(QFileInfo(QString(databaseFilePath)).path()))
+ throw WrongFilePath("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because of wrong file path!",
+ Utils::SmallString(databaseFilePath));
if (databaseIsOpen())
- throw SqliteException("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database is already open!");
+ throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because it is already open!");
}
-void SqliteDatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
+void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
{
switch (resultCode) {
case SQLITE_OK:
return;
default:
closeWithoutException();
- throw SqliteException("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", sqlite3_errmsg(sqliteDatabaseHandle()));
+ throw Exception("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", sqlite3_errmsg(sqliteDatabaseHandle()));
}
}
-void SqliteDatabaseBackend::checkPragmaValue(const Utf8String &databaseValue, const Utf8String &expectedValue)
+void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue,
+ Utils::SmallStringView expectedValue)
{
if (databaseValue != expectedValue)
- throwException("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!");
-}
-
-void SqliteDatabaseBackend::checkDatabaseHandleIsNotNull()
-{
- if (sqliteDatabaseBackend->databaseHandle == nullptr)
- throwException("SqliteDatabaseBackend: database is not open!");
+ throw PragmaValueNotSet("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!");
}
-void SqliteDatabaseBackend::checkDatabaseBackendIsNotNull()
+void DatabaseBackend::checkDatabaseHandleIsNotNull() const
{
- if (sqliteDatabaseBackend == nullptr)
- throwException("SqliteDatabaseBackend: database backend is not initialized!");
+ if (m_databaseHandle == nullptr)
+ throwDatabaseIsNotOpen("SqliteDatabaseBackend: database is not open!");
}
-void SqliteDatabaseBackend::checkIfMultithreadingIsActivated(int resultCode)
+void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode)
{
if (resultCode != SQLITE_OK)
throwException("SqliteDatabaseBackend::activateMultiThreading: multithreading can't be activated!");
}
-void SqliteDatabaseBackend::checkIfLoogingIsActivated(int resultCode)
+void DatabaseBackend::checkIfLoogingIsActivated(int resultCode)
{
if (resultCode != SQLITE_OK)
throwException("SqliteDatabaseBackend::activateLogging: logging can't be activated!");
}
-void SqliteDatabaseBackend::checkMmapSizeIsSet(int resultCode)
+void DatabaseBackend::checkMmapSizeIsSet(int resultCode)
{
if (resultCode != SQLITE_OK)
throwException("SqliteDatabaseBackend::checkMmapSizeIsSet: mmap size can't be changed!");
}
-void SqliteDatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode)
+void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode)
{
if (resultCode != SQLITE_OK)
throwException("SqliteDatabaseBackend::initializeSqliteLibrary: SqliteLibrary cannot initialized!");
}
-void SqliteDatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode)
+void DatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode)
{
if (resultCode != SQLITE_OK)
throwException("SqliteDatabaseBackend::shutdownSqliteLibrary: SqliteLibrary cannot be shutdowned!");
}
-void SqliteDatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode)
+void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode)
{
if (resultCode != SQLITE_OK)
throwException("SqliteDatabaseBackend::checkpointFullWalLog: WAL log could not be checkpointed!");
}
-int SqliteDatabaseBackend::indexOfPragma(const Utf8String pragma, const Utf8String pragmas[], size_t pragmaCount)
+namespace {
+template<std::size_t Size>
+int indexOfPragma(Utils::SmallStringView pragma, const Utils::SmallStringView (&pragmas)[Size])
{
- for (unsigned int index = 0; index < pragmaCount; index++) {
+ for (unsigned int index = 0; index < Size; index++) {
if (pragma == pragmas[index])
return int(index);
}
return -1;
-
+}
}
-static const Utf8String journalModeStrings[] = {
- Utf8StringLiteral("delete"),
- Utf8StringLiteral("truncate"),
- Utf8StringLiteral("persist"),
- Utf8StringLiteral("memory"),
- Utf8StringLiteral("wal")
+constexpr const Utils::SmallStringView journalModeStrings[] = {
+ "delete",
+ "truncate",
+ "persist",
+ "memory",
+ "wal"
};
-const Utf8String &SqliteDatabaseBackend::journalModeToPragma(JournalMode journalMode)
+Utils::SmallStringView DatabaseBackend::journalModeToPragma(JournalMode journalMode)
{
return journalModeStrings[int(journalMode)];
}
-JournalMode SqliteDatabaseBackend::pragmaToJournalMode(const Utf8String &pragma)
+JournalMode DatabaseBackend::pragmaToJournalMode(Utils::SmallStringView pragma)
{
- int index = indexOfPragma(pragma, journalModeStrings, SIZE_OF_BYTEARRAY_ARRAY(journalModeStrings));
+ int index = indexOfPragma(pragma, journalModeStrings);
if (index < 0)
- throwException("SqliteDatabaseBackend::pragmaToJournalMode: pragma can't be transformed in a journal mode enumeration!");
+ throwExceptionStatic("SqliteDatabaseBackend::pragmaToJournalMode: pragma can't be transformed in a journal mode enumeration!");
return static_cast<JournalMode>(index);
}
-static const Utf8String textEncodingStrings[] = {
- Utf8StringLiteral("UTF-8"),
- Utf8StringLiteral("UTF-16le"),
- Utf8StringLiteral("UTF-16be")
+constexpr const Utils::SmallStringView textEncodingStrings[] = {
+ "UTF-8",
+ "UTF-16le",
+ "UTF-16be"
};
-const Utf8String &SqliteDatabaseBackend::textEncodingToPragma(TextEncoding textEncoding)
+Utils::SmallStringView DatabaseBackend::textEncodingToPragma(TextEncoding textEncoding)
{
return textEncodingStrings[textEncoding];
}
-TextEncoding SqliteDatabaseBackend::pragmaToTextEncoding(const Utf8String &pragma)
+TextEncoding DatabaseBackend::pragmaToTextEncoding(Utils::SmallStringView pragma)
{
- int index = indexOfPragma(pragma, textEncodingStrings, SIZE_OF_BYTEARRAY_ARRAY(textEncodingStrings));
+ int index = indexOfPragma(pragma, textEncodingStrings);
if (index < 0)
- throwException("SqliteDatabaseBackend::pragmaToTextEncoding: pragma can't be transformed in a text encoding enumeration!");
+ throwExceptionStatic("SqliteDatabaseBackend::pragmaToTextEncoding: pragma can't be transformed in a text encoding enumeration!");
return static_cast<TextEncoding>(index);
}
-void SqliteDatabaseBackend::throwException(const char *whatHasHappens)
+int DatabaseBackend::openMode(OpenMode mode)
{
- if (sqliteDatabaseBackend && sqliteDatabaseBackend->databaseHandle)
- throw SqliteException(whatHasHappens, sqlite3_errmsg(sqliteDatabaseBackend->databaseHandle));
+ int sqliteMode = SQLITE_OPEN_CREATE;
+
+ switch (mode) {
+ case OpenMode::ReadOnly: sqliteMode |= SQLITE_OPEN_READONLY; break;
+ case OpenMode::ReadWrite: sqliteMode |= SQLITE_OPEN_READWRITE; break;
+ }
+
+ return sqliteMode;
+}
+
+void DatabaseBackend::throwExceptionStatic(const char *whatHasHappens)
+{
+ throw Exception(whatHasHappens);
+}
+
+void DatabaseBackend::throwException(const char *whatHasHappens) const
+{
+ if (m_databaseHandle)
+ throw Exception(whatHasHappens, sqlite3_errmsg(m_databaseHandle));
else
- throw SqliteException(whatHasHappens);
+ throw Exception(whatHasHappens);
+}
+
+void DatabaseBackend::throwUnknowError(const char *whatHasHappens) const
+{
+ throw UnknowError(whatHasHappens);
}
+
+void DatabaseBackend::throwDatabaseIsNotOpen(const char *whatHasHappens) const
+{
+ throw DatabaseIsNotOpen(whatHasHappens);
+}
+
+template <typename Type>
+Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement)
+{
+ ReadWriteStatement statement(sqlStatement, m_database);
+
+ statement.next();
+
+ return statement.fetchValue<Type>(0);
+}
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitedatabasebackend.h b/src/libs/sqlite/sqlitedatabasebackend.h
index 7d86519922..6ff56b11b2 100644
--- a/src/libs/sqlite/sqlitedatabasebackend.h
+++ b/src/libs/sqlite/sqlitedatabasebackend.h
@@ -27,51 +27,64 @@
#include "sqliteglobal.h"
-#include "utf8stringvector.h"
-
-#include <QStringList>
+#include <utils/smallstringvector.h>
struct sqlite3;
-class SQLITE_EXPORT SqliteDatabaseBackend
+namespace Sqlite {
+
+class Database;
+
+class SQLITE_EXPORT DatabaseBackend
{
public:
+ DatabaseBackend(Database &database);
+ ~DatabaseBackend();
+
+ DatabaseBackend(const Database &) = delete;
+ Database &operator=(const Database &) = delete;
- SqliteDatabaseBackend();
- ~SqliteDatabaseBackend();
+ DatabaseBackend(Database &&) = delete;
+ Database &operator=(Database &&) = delete;
- static void setMmapSize(qint64 defaultSize, qint64 maximumSize);
- static void activateMultiThreading();
- static void activateLogging();
- static void initializeSqliteLibrary();
- static void shutdownSqliteLibrary();
- static void checkpointFullWalLog();
+ void setMmapSize(qint64 defaultSize, qint64 maximumSize);
+ void activateMultiThreading();
+ void activateLogging();
+ void initializeSqliteLibrary();
+ void shutdownSqliteLibrary();
+ void checkpointFullWalLog();
- void open(const QString &databaseFilePath);
+ void open(Utils::SmallStringView databaseFilePath, OpenMode openMode);
void close();
void closeWithoutException();
- static SqliteDatabaseBackend *threadLocalInstance();
- static sqlite3* sqliteDatabaseHandle();
+ sqlite3* sqliteDatabaseHandle() const;
void setJournalMode(JournalMode journalMode);
- JournalMode journalMode() const;
+ JournalMode journalMode();
void setTextEncoding(TextEncoding textEncoding);
TextEncoding textEncoding();
+ Utils::SmallStringVector columnNames(Utils::SmallStringView tableName);
+ int changesCount() const;
+ int totalChangesCount() const;
- static Utf8StringVector columnNames(const Utf8String &tableName);
+ int64_t lastInsertedRowId() const;
- static int changesCount();
- static int totalChangesCount();
+ void execute(Utils::SmallStringView sqlStatement);
+
+ template <typename Type>
+ Type toValue(Utils::SmallStringView sqlStatement);
+
+ static int openMode(OpenMode);
protected:
bool databaseIsOpen() const;
- void setPragmaValue(const Utf8String &pragma, const Utf8String &value);
- Utf8String pragmaValue(const Utf8String &pragma) const;
+ void setPragmaValue(Utils::SmallStringView pragma, Utils::SmallStringView value);
+ Utils::SmallString pragmaValue(Utils::SmallStringView pragma);
void registerBusyHandler();
void registerRankingFunction();
@@ -81,28 +94,33 @@ protected:
void checkForOpenDatabaseWhichCanBeClosed();
void checkDatabaseClosing(int resultCode);
- void checkCanOpenDatabase(const QString &databaseFilePath);
+ void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath);
void checkDatabaseCouldBeOpened(int resultCode);
- void checkPragmaValue(const Utf8String &databaseValue, const Utf8String &expectedValue);
- static void checkDatabaseHandleIsNotNull();
- static void checkDatabaseBackendIsNotNull();
- static void checkIfMultithreadingIsActivated(int resultCode);
- static void checkIfLoogingIsActivated(int resultCode);
- static void checkMmapSizeIsSet(int resultCode);
- static void checkInitializeSqliteLibraryWasSuccesful(int resultCode);
- static void checkShutdownSqliteLibraryWasSuccesful(int resultCode);
- static void checkIfLogCouldBeCheckpointed(int resultCode);
-
- static int indexOfPragma(const Utf8String pragma, const Utf8String pragmas[], size_t pragmaCount);
- static const Utf8String &journalModeToPragma(JournalMode journalMode);
- static JournalMode pragmaToJournalMode(const Utf8String &pragma);
- static const Utf8String &textEncodingToPragma(TextEncoding textEncoding);
- static TextEncoding pragmaToTextEncoding(const Utf8String &pragma);
-
- Q_NORETURN static void throwException(const char *whatHasHappens);
+ void checkPragmaValue(Utils::SmallStringView databaseValue, Utils::SmallStringView expectedValue);
+ void checkDatabaseHandleIsNotNull() const;
+ void checkIfMultithreadingIsActivated(int resultCode);
+ void checkIfLoogingIsActivated(int resultCode);
+ void checkMmapSizeIsSet(int resultCode);
+ void checkInitializeSqliteLibraryWasSuccesful(int resultCode);
+ void checkShutdownSqliteLibraryWasSuccesful(int resultCode);
+ void checkIfLogCouldBeCheckpointed(int resultCode);
+
+ static Utils::SmallStringView journalModeToPragma(JournalMode journalMode);
+ static JournalMode pragmaToJournalMode(Utils::SmallStringView pragma);
+ Utils::SmallStringView textEncodingToPragma(TextEncoding textEncoding);
+ static TextEncoding pragmaToTextEncoding(Utils::SmallStringView pragma);
+
+
+ Q_NORETURN static void throwExceptionStatic(const char *whatHasHappens);
+ [[noreturn]] void throwException(const char *whatHasHappens) const;
+ [[noreturn]] void throwUnknowError(const char *whatHasHappens) const;
+ [[noreturn]] void throwDatabaseIsNotOpen(const char *whatHasHappens) const;
private:
- sqlite3 *databaseHandle;
- TextEncoding cachedTextEncoding;
+ Database &m_database;
+ sqlite3 *m_databaseHandle;
+ TextEncoding m_cachedTextEncoding;
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitedatabaseconnection.cpp b/src/libs/sqlite/sqlitedatabaseconnection.cpp
deleted file mode 100644
index f4fe79b7d4..0000000000
--- a/src/libs/sqlite/sqlitedatabaseconnection.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sqlitedatabaseconnection.h"
-
-#include "sqliteexception.h"
-#include "sqliteglobal.h"
-
-#include <sqlite3.h>
-
-#include <QDebug>
-
-#ifdef Q_OS_LINUX
-#include <cerrno>
-#include <cstring>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-SqliteDatabaseConnection::SqliteDatabaseConnection(QObject *parent) :
- QObject(parent)
-{
-}
-
-SqliteDatabaseConnection::~SqliteDatabaseConnection()
-{
-
-}
-
-sqlite3 *SqliteDatabaseConnection::currentSqliteDatabase()
-{
- return SqliteDatabaseBackend::sqliteDatabaseHandle();
-}
-
-void SqliteDatabaseConnection::setDatabaseFilePath(const QString &databaseFilePath)
-{
-
- prioritizeThreadDown();
-
- try {
- databaseBackend.open(databaseFilePath);
-
- emit databaseConnectionIsOpened();
- } catch (SqliteException &exception) {
- exception.printWarning();
- }
-}
-
-void SqliteDatabaseConnection::setJournalMode(JournalMode journalMode)
-{
- try {
- databaseBackend.setJournalMode(journalMode);
- } catch (SqliteException &exception) {
- exception.printWarning();
- }
-}
-
-void SqliteDatabaseConnection::close()
-{
- databaseBackend.closeWithoutException();
-
- emit databaseConnectionIsClosed();
-}
-
-void SqliteDatabaseConnection::prioritizeThreadDown()
-{
-#ifdef Q_OS_LINUX
- pid_t processId = syscall(SYS_gettid);
- int returnCode = setpriority(PRIO_PROCESS, processId, 10);
- if (returnCode == -1)
- qWarning() << "cannot renice" << strerror(errno);
-#endif
-}
diff --git a/src/libs/sqlite/sqlitedatabaseconnectionproxy.cpp b/src/libs/sqlite/sqlitedatabaseconnectionproxy.cpp
deleted file mode 100644
index 70fef05098..0000000000
--- a/src/libs/sqlite/sqlitedatabaseconnectionproxy.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sqlitedatabaseconnectionproxy.h"
-
-#include "sqlitedatabaseconnection.h"
-#include "sqliteworkerthread.h"
-
-#include <QCoreApplication>
-
-
-SqliteDatabaseConnectionProxy::SqliteDatabaseConnectionProxy(const QString &threadName) :
- QObject(),
- databaseConnectionIsOpen(false)
-{
-
- databaseConnectionThread = new SqliteWorkerThread;
- databaseConnectionThread->setObjectName(threadName);
-
- databaseConnectionThread->start(QThread::LowPriority);
-
- SqliteDatabaseConnection *connection = databaseConnectionThread->databaseConnection();
-
-
- connect(this, &SqliteDatabaseConnectionProxy::setDatabaseFilePath, connection, &SqliteDatabaseConnection::setDatabaseFilePath);
- connect(this, &SqliteDatabaseConnectionProxy::setJournalMode, connection, &SqliteDatabaseConnection::setJournalMode);
- connect(this, &SqliteDatabaseConnectionProxy::close, connection, &SqliteDatabaseConnection::close);
-
- connect(connection, &SqliteDatabaseConnection::databaseConnectionIsOpened, this, &SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsOpened);
- connect(connection, &SqliteDatabaseConnection::databaseConnectionIsClosed, this, &SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsClosed);
-
-}
-
-SqliteDatabaseConnectionProxy::~SqliteDatabaseConnectionProxy()
-{
- if (databaseConnectionThread) {
- databaseConnectionThread->quit();
- databaseConnectionThread->wait();
- databaseConnectionThread->deleteLater();
- }
-}
-
-QThread *SqliteDatabaseConnectionProxy::connectionThread() const
-{
- return databaseConnectionThread;
-}
-
-bool SqliteDatabaseConnectionProxy::isOpen() const
-{
- return databaseConnectionIsOpen;
-}
-
-void SqliteDatabaseConnectionProxy::registerTypes()
-{
- qRegisterMetaType<JournalMode>("JournalMode");
-}
-
-void SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsOpened()
-{
- databaseConnectionIsOpen = true;
-
- emit connectionIsOpened();
-}
-
-void SqliteDatabaseConnectionProxy::handleDatabaseConnectionIsClosed()
-{
- databaseConnectionIsOpen = false;
-
- emit connectionIsClosed();
-}
diff --git a/src/libs/sqlite/sqliteexception.cpp b/src/libs/sqlite/sqliteexception.cpp
index f4c8e0c976..d760ff2b7f 100644
--- a/src/libs/sqlite/sqliteexception.cpp
+++ b/src/libs/sqlite/sqliteexception.cpp
@@ -25,19 +25,18 @@
#include "sqliteexception.h"
+#include <utils/smallstringio.h>
+
#include <QDebug>
-SqliteException::SqliteException(const char *whatErrorHasHappen, const char *sqliteErrorMessage)
- : whatErrorHasHappen(whatErrorHasHappen),
- sqliteErrorMessage_(sqliteErrorMessage)
-{
-}
+namespace Sqlite {
-void SqliteException::printWarning() const
+void Exception::printWarning() const
{
- if (!sqliteErrorMessage_.isEmpty())
- qWarning() << whatErrorHasHappen << sqliteErrorMessage_;
+ if (!m_sqliteErrorMessage.isEmpty())
+ qWarning() << m_whatErrorHasHappen << m_sqliteErrorMessage;
else
- qWarning() << whatErrorHasHappen;
+ qWarning() << m_whatErrorHasHappen;
}
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h
index b778d39b58..319141d257 100644
--- a/src/libs/sqlite/sqliteexception.h
+++ b/src/libs/sqlite/sqliteexception.h
@@ -27,16 +27,232 @@
#include "sqliteglobal.h"
-#include <QByteArray>
+#include <utils/smallstring.h>
-class SQLITE_EXPORT SqliteException
+namespace Sqlite {
+
+class SQLITE_EXPORT Exception
{
public:
- SqliteException(const char *whatErrorHasHappen, const char *sqliteErrorMessage = 0);
+ Exception(const char *whatErrorHasHappen,
+ Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
+ : m_whatErrorHasHappen(whatErrorHasHappen),
+ m_sqliteErrorMessage(std::move(sqliteErrorMessage))
+ {
+ }
void printWarning() const;
private:
- const char *whatErrorHasHappen;
- QByteArray sqliteErrorMessage_;
+ const char *m_whatErrorHasHappen;
+ Utils::SmallString m_sqliteErrorMessage;
+};
+
+class StatementIsBusy : public Exception
+{
+public:
+ StatementIsBusy(const char *whatErrorHasHappen,
+ Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
+ {
+ }
+};
+
+class DatabaseIsBusy : public Exception
+{
+public:
+ DatabaseIsBusy(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class StatementHasError : public Exception
+{
+public:
+ StatementHasError(const char *whatErrorHasHappen,
+ Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
+ {
+ }
+};
+
+class StatementIsMisused : public Exception
+{
+public:
+ StatementIsMisused(const char *whatErrorHasHappen,
+ Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
+ {
+ }
+};
+
+class ContraintPreventsModification : public Exception
+{
+public:
+ ContraintPreventsModification(const char *whatErrorHasHappen,
+ Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
+ {
+ }
+};
+
+class NoValuesToFetch : public Exception
+{
+public:
+ NoValuesToFetch(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class InvalidColumnFetched : public Exception
+{
+public:
+ InvalidColumnFetched(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class BindingIndexIsOutOfRange : public Exception
+{
+public:
+ BindingIndexIsOutOfRange(const char *whatErrorHasHappen,
+ Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
+ {
+ }
+};
+
+class WrongBingingName : public Exception
+{
+public:
+ WrongBingingName(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class DatabaseIsNotOpen : public Exception
+{
+public:
+ DatabaseIsNotOpen(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class DatabaseCannotBeOpened : public Exception
+{
+public:
+ DatabaseCannotBeOpened(const char *whatErrorHasHappen,
+ Utils::SmallString &&errorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(errorMessage))
+ {
+ }
};
+
+class DatabaseFilePathIsEmpty : public DatabaseCannotBeOpened
+{
+public:
+ DatabaseFilePathIsEmpty(const char *whatErrorHasHappen)
+ : DatabaseCannotBeOpened(whatErrorHasHappen)
+ {
+ }
+};
+
+class DatabaseIsAlreadyOpen : public DatabaseCannotBeOpened
+{
+public:
+ DatabaseIsAlreadyOpen(const char *whatErrorHasHappen)
+ : DatabaseCannotBeOpened(whatErrorHasHappen)
+ {
+ }
+};
+
+class DatabaseCannotBeClosed : public Exception
+{
+public:
+ DatabaseCannotBeClosed(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class DatabaseIsAlreadyClosed : public DatabaseCannotBeClosed
+{
+public:
+ DatabaseIsAlreadyClosed(const char *whatErrorHasHappen)
+ : DatabaseCannotBeClosed(whatErrorHasHappen)
+ {
+ }
+};
+
+class WrongFilePath : public DatabaseCannotBeOpened
+{
+public:
+ WrongFilePath(const char *whatErrorHasHappen,
+ Utils::SmallString &&errorMessage = Utils::SmallString())
+ : DatabaseCannotBeOpened(whatErrorHasHappen, std::move(errorMessage))
+ {
+ }
+};
+
+class PragmaValueNotSet : public Exception
+{
+public:
+ PragmaValueNotSet(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class NotReadOnlySqlStatement : public Exception
+{
+public:
+ NotReadOnlySqlStatement(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class NotWriteSqlStatement : public Exception
+{
+public:
+ NotWriteSqlStatement(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class DeadLock : public Exception
+{
+public:
+ DeadLock(const char *whatErrorHasHappen)
+ : Exception(whatErrorHasHappen)
+ {
+ }
+};
+
+class UnknowError : public Exception
+{
+public:
+ UnknowError(const char *whatErrorHasHappen,
+ Utils::SmallString &&errorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(errorMessage))
+ {
+ }
+};
+
+class BindingTooBig : public Exception
+{
+public:
+ BindingTooBig(const char *whatErrorHasHappen,
+ Utils::SmallString &&errorMessage = Utils::SmallString())
+ : Exception(whatErrorHasHappen, std::move(errorMessage))
+ {
+ }
+};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqliteglobal.cpp b/src/libs/sqlite/sqliteglobal.cpp
index 90f2719b3b..3f9b05ce1c 100644
--- a/src/libs/sqlite/sqliteglobal.cpp
+++ b/src/libs/sqlite/sqliteglobal.cpp
@@ -25,15 +25,7 @@
#include "sqliteglobal.h"
-#include "createtablecommand.h"
namespace Sqlite {
-void registerTypes()
-{
- Internal::CreateTableCommand::registerType();
-
- qRegisterMetaType<JournalMode>("JournalMode");
-}
-
}
diff --git a/src/libs/sqlite/sqliteglobal.h b/src/libs/sqlite/sqliteglobal.h
index 9349230fab..af9d9ac36c 100644
--- a/src/libs/sqlite/sqliteglobal.h
+++ b/src/libs/sqlite/sqliteglobal.h
@@ -25,6 +25,8 @@
#pragma once
+#include <utils/smallstringfwd.h>
+
#include <QtGlobal>
#if defined(BUILD_SQLITE_LIBRARY)
@@ -35,12 +37,10 @@
# define SQLITE_EXPORT Q_DECL_IMPORT
#endif
-
namespace Sqlite {
-SQLITE_EXPORT void registerTypes();
-}
-enum class ColumnType {
+enum class ColumnType : char
+{
Numeric,
Integer,
Real,
@@ -48,11 +48,20 @@ enum class ColumnType {
None
};
-enum class ColumnConstraint {
+enum class Contraint : char
+{
+ NoConstraint,
+ PrimaryKey,
+ Unique
+};
+
+enum class ColumnConstraint : char
+{
PrimaryKey
};
-enum class JournalMode {
+enum class JournalMode : char
+{
Delete,
Truncate,
Persist,
@@ -60,7 +69,14 @@ enum class JournalMode {
Wal
};
-enum TextEncoding {
+enum class OpenMode : char
+{
+ ReadOnly,
+ ReadWrite
+};
+
+enum TextEncoding : char
+{
Utf8,
Utf16le,
Utf16be,
@@ -72,16 +88,4 @@ enum TextEncoding {
};
-QT_BEGIN_NAMESPACE
-template <typename T> class QVector;
-template <typename T> class QSet;
-template <class Key, class T> class QHash;
-template <class Key, class T> class QMap;
-class QVariant;
-QT_END_NAMESPACE
-
-class Utf8String;
-class Utf8StringVector;
-
-typedef QMap<Utf8String, QVariant> RowDictionary;
-typedef QVector<RowDictionary> RowDictionaries;
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqliteindex.h b/src/libs/sqlite/sqliteindex.h
new file mode 100644
index 0000000000..503a6cc341
--- /dev/null
+++ b/src/libs/sqlite/sqliteindex.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+
+#include "sqliteglobal.h"
+
+#include "sqliteexception.h"
+
+#include <utils/smallstringvector.h>
+
+namespace Sqlite {
+
+class Index
+{
+public:
+ Index(Utils::SmallString &&tableName, Utils::SmallStringVector &&columnNames)
+ : m_tableName(std::move(tableName)),
+ m_columnNames(std::move(columnNames))
+ {
+ }
+
+ Utils::SmallString sqlStatement() const
+ {
+ checkTableName();
+ checkColumns();
+
+ return {"CREATE INDEX IF NOT EXISTS index_",
+ m_tableName,
+ "_",
+ m_columnNames.join("_"),
+ " ON ",
+ m_tableName,
+ "(",
+ m_columnNames.join(", "),
+ ")"
+ };
+ }
+
+ void checkTableName() const
+ {
+ if (m_tableName.isEmpty())
+ throw Exception("SqliteIndex has not table name!");
+ }
+
+ void checkColumns() const
+ {
+ if (m_columnNames.empty())
+ throw Exception("SqliteIndex has no columns!");
+ }
+
+private:
+ Utils::SmallString m_tableName;
+ Utils::SmallStringVector m_columnNames;
+};
+
+using SqliteIndices = std::vector<Index>;
+
+} //
diff --git a/src/libs/sqlite/sqlitereadstatement.cpp b/src/libs/sqlite/sqlitereadstatement.cpp
index cc348768b0..9af95f1cff 100644
--- a/src/libs/sqlite/sqlitereadstatement.cpp
+++ b/src/libs/sqlite/sqlitereadstatement.cpp
@@ -27,14 +27,19 @@
#include "sqlite3.h"
-SqliteReadStatement::SqliteReadStatement(const Utf8String &sqlStatementUtf8)
- : SqliteStatement(sqlStatementUtf8)
+namespace Sqlite {
+
+ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement,
+ Database &database)
+ : Statement(sqlStatement, database)
{
checkIsReadOnlyStatement();
}
-void SqliteReadStatement::checkIsReadOnlyStatement()
+void ReadStatement::checkIsReadOnlyStatement()
{
if (!isReadOnlyStatement())
- throwException("SqliteStatement::SqliteReadStatement: is not read only statement!");
+ throw NotReadOnlySqlStatement("SqliteStatement::SqliteReadStatement: is not read only statement!");
}
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h
index 4f27c8657b..828d1f7c37 100644
--- a/src/libs/sqlite/sqlitereadstatement.h
+++ b/src/libs/sqlite/sqlitereadstatement.h
@@ -27,25 +27,20 @@
#include "sqlitestatement.h"
-class SQLITE_EXPORT SqliteReadStatement final : private SqliteStatement
+namespace Sqlite {
+
+class SQLITE_EXPORT ReadStatement final : private Statement
{
public:
- explicit SqliteReadStatement(const Utf8String &sqlStatementUtf8);
+ explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database);
- using SqliteStatement::next;
- using SqliteStatement::reset;
- using SqliteStatement::value;
- using SqliteStatement::values;
- using SqliteStatement::rowColumnValueMap;
- using SqliteStatement::twoColumnValueMap;
- using SqliteStatement::columnCount;
- using SqliteStatement::columnNames;
- using SqliteStatement::bind;
- using SqliteStatement::bindingIndexForName;
- using SqliteStatement::setBindingColumnNames;
- using SqliteStatement::bindingColumnNames;
- using SqliteStatement::toValue;
+ using Statement::value;
+ using Statement::values;
+ using Statement::toValue;
+ using Statement::database;
protected:
void checkIsReadOnlyStatement();
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitereadwritestatement.cpp b/src/libs/sqlite/sqlitereadwritestatement.cpp
index 3d6be2e61c..74190deae1 100644
--- a/src/libs/sqlite/sqlitereadwritestatement.cpp
+++ b/src/libs/sqlite/sqlitereadwritestatement.cpp
@@ -25,8 +25,12 @@
#include "sqlitereadwritestatement.h"
-SqliteReadWriteStatement::SqliteReadWriteStatement(const Utf8String &sqlStatementUft8)
- : SqliteStatement(sqlStatementUft8)
+namespace Sqlite {
+
+ReadWriteStatement::ReadWriteStatement(Utils::SmallStringView sqlStatement,
+ Database &database)
+ : Statement(sqlStatement, database)
{
}
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h
index cb3c0707d4..8645a6eae8 100644
--- a/src/libs/sqlite/sqlitereadwritestatement.h
+++ b/src/libs/sqlite/sqlitereadwritestatement.h
@@ -27,24 +27,22 @@
#include "sqlitestatement.h"
-class SQLITE_EXPORT SqliteReadWriteStatement final : private SqliteStatement
+namespace Sqlite {
+
+class SQLITE_EXPORT ReadWriteStatement final : private Statement
{
+ friend class DatabaseBackend;
+
public:
- explicit SqliteReadWriteStatement(const Utf8String &sqlStatementUft8);
+ ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database);
- using SqliteStatement::next;
- using SqliteStatement::step;
- using SqliteStatement::reset;
- using SqliteStatement::bind;
- using SqliteStatement::bindingIndexForName;
- using SqliteStatement::setBindingColumnNames;
- using SqliteStatement::bindingColumnNames;
- using SqliteStatement::write;
- using SqliteStatement::value;
- using SqliteStatement::values;
- using SqliteStatement::rowColumnValueMap;
- using SqliteStatement::columnCount;
- using SqliteStatement::columnNames;
- using SqliteStatement::toValue;
- using SqliteStatement::execute;
+ using Statement::execute;
+ using Statement::value;
+ using Statement::values;
+ using Statement::toValue;
+ using Statement::database;
+ using Statement::write;
+ using Statement::writeNamed;
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitestatement.cpp b/src/libs/sqlite/sqlitestatement.cpp
index cf0fa90418..0e70b5aaca 100644
--- a/src/libs/sqlite/sqlitestatement.cpp
+++ b/src/libs/sqlite/sqlitestatement.cpp
@@ -25,43 +25,43 @@
#include "sqlitestatement.h"
+#include "sqlitedatabase.h"
#include "sqlitedatabasebackend.h"
#include "sqliteexception.h"
-#include <QMutex>
-#include <QtGlobal>
-#include <QVariant>
-#include <QWaitCondition>
-
#include "sqlite3.h"
+#include <condition_variable>
+#include <mutex>
+
#if defined(__GNUC__)
# pragma GCC diagnostic ignored "-Wignored-qualifiers"
#endif
-SqliteStatement::SqliteStatement(const Utf8String &sqlStatementUtf8)
- : compiledStatement(nullptr, deleteCompiledStatement),
- bindingParameterCount(0),
- columnCount_(0),
- isReadyToFetchValues(false)
+namespace Sqlite {
+
+Statement::Statement(Utils::SmallStringView sqlStatement, Database &database)
+ : m_compiledStatement(nullptr, deleteCompiledStatement),
+ m_database(database),
+ m_bindingParameterCount(0),
+ m_columnCount(0),
+ m_isReadyToFetchValues(false)
{
- prepare(sqlStatementUtf8);
+ prepare(sqlStatement);
setBindingParameterCount();
setBindingColumnNamesFromStatement();
setColumnCount();
}
-void SqliteStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
+void Statement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
{
if (compiledStatement)
sqlite3_finalize(compiledStatement);
}
-class UnlockNotification {
-
+class UnlockNotification
+{
public:
- UnlockNotification() : fired(false) {};
-
static void unlockNotifyCallBack(void **arguments, int argumentCount)
{
for (int index = 0; index < argumentCount; index++) {
@@ -72,58 +72,62 @@ public:
void wakeupWaitCondition()
{
- mutex.lock();
- fired = 1;
- waitCondition.wakeAll();
- mutex.unlock();
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ m_fired = 1;
+ }
+ m_waitCondition.notify_all();
}
void wait()
{
- mutex.lock();
+ std::unique_lock<std::mutex> lock(m_mutex);
- if (!fired) {
- waitCondition.wait(&mutex);
- }
-
- mutex.unlock();
+ m_waitCondition.wait(lock, [&] () { return m_fired; });
}
private:
- bool fired;
- QWaitCondition waitCondition;
- QMutex mutex;
+ bool m_fired = false;
+ std::condition_variable m_waitCondition;
+ std::mutex m_mutex;
};
-void SqliteStatement::waitForUnlockNotify() const
+void Statement::waitForUnlockNotify() const
{
UnlockNotification unlockNotification;
- int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), UnlockNotification::unlockNotifyCallBack, &unlockNotification);
+ int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
+ UnlockNotification::unlockNotifyCallBack,
+ &unlockNotification);
- if (resultCode == SQLITE_OK)
- unlockNotification.wait();
- else
- throwException("SqliteStatement::waitForUnlockNotify: database is in a dead lock!");
+ if (resultCode == SQLITE_LOCKED)
+ throw DeadLock("SqliteStatement::waitForUnlockNotify: database is in a dead lock!");
+
+ unlockNotification.wait();
}
-void SqliteStatement::reset() const
+void Statement::reset() const
{
- int resultCode = sqlite3_reset(compiledStatement.get());
- if (resultCode != SQLITE_OK)
- throwException("SqliteStatement::reset: can't reset statement!");
+ int resultCode = sqlite3_reset(m_compiledStatement.get());
+ switch (resultCode) {
+ case SQLITE_OK: return;
+ case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
+ case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
+ case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!");
+ case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!");
+ }
- isReadyToFetchValues = false;
+ m_isReadyToFetchValues = false;
}
-bool SqliteStatement::next() const
+bool Statement::next() const
{
int resultCode;
do {
- resultCode = sqlite3_step(compiledStatement.get());
+ resultCode = sqlite3_step(m_compiledStatement.get());
if (resultCode == SQLITE_LOCKED) {
waitForUnlockNotify();
- sqlite3_reset(compiledStatement.get());
+ sqlite3_reset(m_compiledStatement.get());
}
} while (resultCode == SQLITE_LOCKED);
@@ -133,180 +137,102 @@ bool SqliteStatement::next() const
return checkForStepError(resultCode);
}
-void SqliteStatement::step() const
+void Statement::step() const
{
next();
}
-void SqliteStatement::write(const RowDictionary &rowDictionary)
-{
- bind(rowDictionary);
- step();
- reset();
-}
-
-void SqliteStatement::writeUnchecked(const RowDictionary &rowDictionary)
+void Statement::execute() const
{
- bindUnchecked(rowDictionary);
- step();
+ next();
reset();
}
-int SqliteStatement::columnCount() const
+int Statement::columnCount() const
{
- return columnCount_;
+ return m_columnCount;
}
-Utf8StringVector SqliteStatement::columnNames() const
+Utils::SmallStringVector Statement::columnNames() const
{
- Utf8StringVector columnNames;
- int columnCount = SqliteStatement::columnCount();
- columnNames.reserve(columnCount);
+ Utils::SmallStringVector columnNames;
+ int columnCount = Statement::columnCount();
+ columnNames.reserve(std::size_t(columnCount));
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++)
- columnNames.append(Utf8String(sqlite3_column_origin_name(compiledStatement.get(), columnIndex), -1));
+ columnNames.emplace_back(sqlite3_column_origin_name(m_compiledStatement.get(), columnIndex));
return columnNames;
}
-void SqliteStatement::bind(int index, int value)
+void Statement::bind(int index, int value)
{
- int resultCode = sqlite3_bind_int(compiledStatement.get(), index, value);
- if (resultCode != SQLITE_OK)
- throwException("SqliteStatement::bind: cant' bind 32 bit integer!");
+ int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
+ checkForBindingError(resultCode);
}
-void SqliteStatement::bind(int index, qint64 value)
+void Statement::bind(int index, long long value)
{
- int resultCode = sqlite3_bind_int64(compiledStatement.get(), index, value);
- if (resultCode != SQLITE_OK)
- throwException("SqliteStatement::bind: cant' bind 64 bit integer!");
+ int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
+ checkForBindingError(resultCode);
}
-void SqliteStatement::bind(int index, double value)
+void Statement::bind(int index, double value)
{
- int resultCode = sqlite3_bind_double(compiledStatement.get(), index, value);
- if (resultCode != SQLITE_OK)
- throwException("SqliteStatement::bind: cant' bind double!");
+ int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
+ checkForBindingError(resultCode);
}
-void SqliteStatement::bind(int index, const QString &text)
+void Statement::bind(int index, Utils::SmallStringView text)
{
- int resultCode;
- if (databaseTextEncoding() == Utf8) {
- QByteArray textUtf8 = text.toUtf8();
- resultCode = sqlite3_bind_text(compiledStatement.get(), index, textUtf8.constData(), textUtf8.size(), SQLITE_TRANSIENT);
- } else {
- resultCode = sqlite3_bind_text16(compiledStatement.get(), index, text.constData(), text.size() * 2, SQLITE_TRANSIENT);
- }
-
- if (resultCode != SQLITE_OK)
- throwException("SqliteStatement::bind: cant' not bind text!");
-}
-
-void SqliteStatement::bind(int index, const QByteArray &blob)
-{
- sqlite3_bind_blob(compiledStatement.get(), index, blob.constData(), blob.size(), SQLITE_TRANSIENT);
-}
-
-void SqliteStatement::bind(int index, const QVariant &value)
-{
- checkBindingIndex(index);
-
- switch (value.type()) {
- case QVariant::Bool:
- case QVariant::Int:
- bind(index, value.toInt());
- break;
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- bind(index, value.toLongLong());
- break;
- case QVariant::Double:
- bind(index, value.toDouble());
- break;
- case QVariant::String:
- bind(index, value.toString());
- break;
- case QVariant::ByteArray:
- bind(index, value.toByteArray());
- break;
- default:
- sqlite3_bind_null(compiledStatement.get(), index);
- }
+ int resultCode = sqlite3_bind_text(m_compiledStatement.get(),
+ index,
+ text.data(),
+ int(text.size()),
+ SQLITE_STATIC);
+ checkForBindingError(resultCode);
}
template <typename Type>
-void SqliteStatement::bind(const Utf8String &name, const Type &value)
+void Statement::bind(Utils::SmallStringView name, Type value)
{
int index = bindingIndexForName(name);
checkBindingName(index);
bind(index, value);
}
-template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const int &value);
-template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const qint64 &value);
-template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const double &value);
-template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const QString &text);
-template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const QByteArray &blob);
-template SQLITE_EXPORT void SqliteStatement::bind(const Utf8String &name, const QVariant &value);
+template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value);
+template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value);
+template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value);
+template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value);
+template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
-int SqliteStatement::bindingIndexForName(const Utf8String &name)
+int Statement::bindingIndexForName(Utils::SmallStringView name) const
{
- return sqlite3_bind_parameter_index(compiledStatement.get(), name.constData());
+ return sqlite3_bind_parameter_index(m_compiledStatement.get(), name.data());
}
-void SqliteStatement::bind(const RowDictionary &rowDictionary)
+void Statement::setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames)
{
- checkBindingValueMapIsEmpty(rowDictionary);
-
- int columnIndex = 1;
- foreach (const Utf8String &columnName, bindingColumnNames_) {
- checkParameterCanBeBound(rowDictionary, columnName);
- QVariant value = rowDictionary.value(columnName);
- bind(columnIndex, value);
- columnIndex += 1;
- }
-}
-
-void SqliteStatement::bindUnchecked(const RowDictionary &rowDictionary)
-{
- checkBindingValueMapIsEmpty(rowDictionary);
-
- int columnIndex = 1;
- foreach (const Utf8String &columnName, bindingColumnNames_) {
- if (rowDictionary.contains(columnName)) {
- QVariant value = rowDictionary.value(columnName);
- bind(columnIndex, value);
- }
- columnIndex += 1;
- }
+ m_bindingColumnNames = bindingColumnNames;
}
-void SqliteStatement::setBindingColumnNames(const Utf8StringVector &bindingColumnNames)
+const Utils::SmallStringVector &Statement::bindingColumnNames() const
{
- bindingColumnNames_ = bindingColumnNames;
+ return m_bindingColumnNames;
}
-const Utf8StringVector &SqliteStatement::bindingColumnNames() const
-{
- return bindingColumnNames_;
-}
-
-void SqliteStatement::execute(const Utf8String &sqlStatementUtf8)
-{
- SqliteStatement statement(sqlStatementUtf8);
- statement.step();
-}
-
-void SqliteStatement::prepare(const Utf8String &sqlStatementUtf8)
+void Statement::prepare(Utils::SmallStringView sqlStatement)
{
int resultCode;
do {
sqlite3_stmt *sqliteStatement = nullptr;
- resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(), sqlStatementUtf8.constData(), sqlStatementUtf8.byteSize(), &sqliteStatement, nullptr);
- compiledStatement.reset(sqliteStatement);
+ resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(),
+ sqlStatement.data(),
+ int(sqlStatement.size()),
+ &sqliteStatement,
+ nullptr);
+ m_compiledStatement.reset(sqliteStatement);
if (resultCode == SQLITE_LOCKED)
waitForUnlockNotify();
@@ -316,356 +242,310 @@ void SqliteStatement::prepare(const Utf8String &sqlStatementUtf8)
checkForPrepareError(resultCode);
}
-sqlite3 *SqliteStatement::sqliteDatabaseHandle()
+sqlite3 *Statement::sqliteDatabaseHandle() const
{
-return SqliteDatabaseBackend::sqliteDatabaseHandle();
+ return m_database.backend().sqliteDatabaseHandle();
}
-TextEncoding SqliteStatement::databaseTextEncoding()
+TextEncoding Statement::databaseTextEncoding()
{
- if (SqliteDatabaseBackend::threadLocalInstance())
- return SqliteDatabaseBackend::threadLocalInstance()->textEncoding();
-
- throwException("SqliteStatement::databaseTextEncoding: database backend instance is null!");
-
- Q_UNREACHABLE();
+ return m_database.backend().textEncoding();
}
-bool SqliteStatement::checkForStepError(int resultCode) const
+bool Statement::checkForStepError(int resultCode) const
{
switch (resultCode) {
case SQLITE_ROW: return true;
case SQLITE_DONE: return false;
- case SQLITE_BUSY: throwException("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
- case SQLITE_ERROR : throwException("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
- case SQLITE_MISUSE: throwException("SqliteStatement::stepStatement: was called inappropriately!");
- case SQLITE_CONSTRAINT: throwException("SqliteStatement::stepStatement: contraint prevent insert or update!");
+ case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
+ case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
+ case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!");
+ case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!");
}
- throwException("SqliteStatement::stepStatement: unknown error has happened");
+ throwUnknowError("SqliteStatement::stepStatement: unknown error has happened");
Q_UNREACHABLE();
}
-void SqliteStatement::checkForPrepareError(int resultCode) const
+void Statement::checkForPrepareError(int resultCode) const
{
switch (resultCode) {
case SQLITE_OK: return;
- case SQLITE_BUSY: throwException("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!");
- case SQLITE_ERROR : throwException("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!");
- case SQLITE_MISUSE: throwException("SqliteStatement::prepareStatement: was called inappropriately!");
+ case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!");
+ case SQLITE_ERROR : throwStatementHasError("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!");
+ case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::prepareStatement: was called inappropriately!");
}
- throwException("SqliteStatement::prepareStatement: unknown error has happened");
+ throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened");
}
-void SqliteStatement::setIfIsReadyToFetchValues(int resultCode) const
+void Statement::checkForBindingError(int resultCode) const
+{
+ switch (resultCode) {
+ case SQLITE_OK: return;
+ case SQLITE_TOOBIG: throwBingingTooBig("SqliteStatement::bind: string or blob are over size limits(SQLITE_LIMIT_LENGTH)!");
+ case SQLITE_RANGE : throwBindingIndexIsOutOfRange("SqliteStatement::bind: binding index is out of range!");
+ case SQLITE_NOMEM: throw std::bad_alloc();
+ }
+
+ throwUnknowError("SqliteStatement::bind: unknown error has happened");
+}
+
+void Statement::setIfIsReadyToFetchValues(int resultCode) const
{
if (resultCode == SQLITE_ROW)
- isReadyToFetchValues = true;
+ m_isReadyToFetchValues = true;
else
- isReadyToFetchValues = false;
+ m_isReadyToFetchValues = false;
}
-void SqliteStatement::checkIfIsReadyToFetchValues() const
+void Statement::checkIfIsReadyToFetchValues() const
{
- if (!isReadyToFetchValues)
- throwException("SqliteStatement::value: there are no values to fetch!");
+ if (!m_isReadyToFetchValues)
+ throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!");
}
-void SqliteStatement::checkColumnsAreValid(const QVector<int> &columns) const
+void Statement::checkColumnsAreValid(const std::vector<int> &columns) const
{
- foreach (int column, columns) {
- if (column < 0 || column >= columnCount_)
- throwException("SqliteStatement::values: column index out of bound!");
+ for (int column : columns) {
+ if (column < 0 || column >= m_columnCount)
+ throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
}
}
-void SqliteStatement::checkColumnIsValid(int column) const
+void Statement::checkColumnIsValid(int column) const
{
- if (column < 0 || column >= columnCount_)
- throwException("SqliteStatement::values: column index out of bound!");
+ if (column < 0 || column >= m_columnCount)
+ throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
}
-void SqliteStatement::checkBindingIndex(int index) const
+void Statement::checkBindingName(int index) const
{
- if (index <= 0 || index > bindingParameterCount)
- throwException("SqliteStatement::bind: binding index is out of bound!");
+ if (index <= 0 || index > m_bindingParameterCount)
+ throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!");
}
-void SqliteStatement::checkBindingName(int index) const
+void Statement::setBindingParameterCount()
{
- if (index <= 0 || index > bindingParameterCount)
- throwException("SqliteStatement::bind: binding name are not exists in this statement!");
+ m_bindingParameterCount = sqlite3_bind_parameter_count(m_compiledStatement.get());
}
-void SqliteStatement::checkParameterCanBeBound(const RowDictionary &rowDictionary, const Utf8String &columnName)
+Utils::SmallStringView chopFirstLetter(const char *rawBindingName)
{
- if (!rowDictionary.contains(columnName))
- throwException("SqliteStatement::bind: Not all parameters are bound!");
+ if (rawBindingName != nullptr)
+ return Utils::SmallStringView(++rawBindingName);
+
+ return Utils::SmallStringView("");
}
-void SqliteStatement::setBindingParameterCount()
+void Statement::setBindingColumnNamesFromStatement()
{
- bindingParameterCount = sqlite3_bind_parameter_count(compiledStatement.get());
+ for (int index = 1; index <= m_bindingParameterCount; index++) {
+ Utils::SmallStringView bindingName = chopFirstLetter(sqlite3_bind_parameter_name(m_compiledStatement.get(), index));
+ m_bindingColumnNames.push_back(Utils::SmallString(bindingName));
+ }
}
-Utf8String chopFirstLetter(const char *rawBindingName)
+void Statement::setColumnCount()
{
- QByteArray bindingName(rawBindingName);
- bindingName = bindingName.mid(1);
-
- return Utf8String::fromByteArray(bindingName);
+ m_columnCount = sqlite3_column_count(m_compiledStatement.get());
}
-void SqliteStatement::setBindingColumnNamesFromStatement()
+bool Statement::isReadOnlyStatement() const
{
- for (int index = 1; index <= bindingParameterCount; index++) {
- Utf8String bindingName = chopFirstLetter(sqlite3_bind_parameter_name(compiledStatement.get(), index));
- bindingColumnNames_.append(bindingName);
- }
+ return sqlite3_stmt_readonly(m_compiledStatement.get());
}
-void SqliteStatement::setColumnCount()
+void Statement::throwStatementIsBusy(const char *whatHasHappened) const
{
- columnCount_ = sqlite3_column_count(compiledStatement.get());
+ throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
-void SqliteStatement::checkBindingValueMapIsEmpty(const RowDictionary &rowDictionary) const
+void Statement::throwStatementHasError(const char *whatHasHappened) const
{
- if (rowDictionary.isEmpty())
- throwException("SqliteStatement::bind: can't bind empty row!");
+ throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
-bool SqliteStatement::isReadOnlyStatement() const
+void Statement::throwStatementIsMisused(const char *whatHasHappened) const
{
- return sqlite3_stmt_readonly(compiledStatement.get());
+ throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
-void SqliteStatement::throwException(const char *whatHasHappened)
+void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const
{
- throw SqliteException(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
+ throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
-QString SqliteStatement::columnName(int column) const
+void Statement::throwNoValuesToFetch(const char *whatHasHappened) const
{
- return QString::fromUtf8(sqlite3_column_name(compiledStatement.get(), column));
+ throw NoValuesToFetch(whatHasHappened);
}
-static bool columnIsBlob(sqlite3_stmt *sqlStatment, int column)
+void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const
{
- return sqlite3_column_type(sqlStatment, column) == SQLITE_BLOB;
+ throw InvalidColumnFetched(whatHasHappened);
}
-static QByteArray byteArrayForColumn(sqlite3_stmt *sqlStatment, int column)
+void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
{
- if (columnIsBlob(sqlStatment, column)) {
- const char *blob = static_cast<const char*>(sqlite3_column_blob(sqlStatment, column));
- int size = sqlite3_column_bytes(sqlStatment, column);
-
- return QByteArray(blob, size);
- }
-
- return QByteArray();
+ throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
-static QString textForColumn(sqlite3_stmt *sqlStatment, int column)
+void Statement::throwWrongBingingName(const char *whatHasHappened) const
{
- const QChar *text = static_cast<const QChar*>(sqlite3_column_text16(sqlStatment, column));
- int size = sqlite3_column_bytes16(sqlStatment, column) / 2;
+ throw WrongBingingName(whatHasHappened);
+}
- return QString(text, size);
+void Statement::throwUnknowError(const char *whatHasHappened) const
+{
+ if (sqliteDatabaseHandle())
+ throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
+ else
+ throw UnknowError(whatHasHappened);
}
-static Utf8String utf8TextForColumn(sqlite3_stmt *sqlStatment, int column)
+void Statement::throwBingingTooBig(const char *whatHasHappened) const
{
- const char *text = reinterpret_cast<const char*>(sqlite3_column_text(sqlStatment, column));
- int size = sqlite3_column_bytes(sqlStatment, column);
+ throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
+}
- return Utf8String(text, size);
+QString Statement::columnName(int column) const
+{
+ return QString::fromUtf8(sqlite3_column_name(m_compiledStatement.get(), column));
}
+Database &Statement::database() const
+{
+ return m_database;
+}
-static Utf8String convertedToUtf8StringForColumn(sqlite3_stmt *sqlStatment, int column)
+template <typename StringType>
+static StringType textForColumn(sqlite3_stmt *sqlStatment, int column)
{
- int dataType = sqlite3_column_type(sqlStatment, column);
- switch (dataType) {
- case SQLITE_INTEGER: return Utf8String::fromByteArray(QByteArray::number(sqlite3_column_int64(sqlStatment, column)));
- case SQLITE_FLOAT: return Utf8String::fromByteArray(QByteArray::number(sqlite3_column_double(sqlStatment, column)));
- case SQLITE_BLOB: return Utf8String();
- case SQLITE3_TEXT: return utf8TextForColumn(sqlStatment, column);
- case SQLITE_NULL: return Utf8String();
- }
+ const char *text = reinterpret_cast<const char*>(sqlite3_column_text(sqlStatment, column));
+ std::size_t size = std::size_t(sqlite3_column_bytes(sqlStatment, column));
- Q_UNREACHABLE();
+ return StringType(text, size);
}
-
-static QVariant variantForColumn(sqlite3_stmt *sqlStatment, int column)
+template <typename StringType>
+static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
{
int dataType = sqlite3_column_type(sqlStatment, column);
switch (dataType) {
- case SQLITE_INTEGER: return QVariant::fromValue(sqlite3_column_int64(sqlStatment, column));
- case SQLITE_FLOAT: return QVariant::fromValue(sqlite3_column_double(sqlStatment, column));
- case SQLITE_BLOB: return QVariant::fromValue(byteArrayForColumn(sqlStatment, column));
- case SQLITE3_TEXT: return QVariant::fromValue(textForColumn(sqlStatment, column));
- case SQLITE_NULL: return QVariant();
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ case SQLITE3_TEXT: return textForColumn<StringType>(sqlStatment, column);
+ case SQLITE_BLOB:
+ case SQLITE_NULL: return {};
}
Q_UNREACHABLE();
}
-template<>
-int SqliteStatement::value<int>(int column) const
+int Statement::fetchIntValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
- return sqlite3_column_int(compiledStatement.get(), column);
+ return sqlite3_column_int(m_compiledStatement.get(), column);
}
template<>
-qint64 SqliteStatement::value<qint64>(int column) const
+int Statement::fetchValue<int>(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
- return sqlite3_column_int64(compiledStatement.get(), column);
+ return fetchIntValue(column);
}
-template<>
-double SqliteStatement::value<double>(int column) const
+long Statement::fetchLongValue(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
- return sqlite3_column_double(compiledStatement.get(), column);
+ return long(fetchValue<long long>(column));
}
template<>
-QByteArray SqliteStatement::value<QByteArray>(int column) const
+long Statement::fetchValue<long>(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
- return byteArrayForColumn(compiledStatement.get(), column);
+ return fetchLongValue(column);
}
-template<>
-Utf8String SqliteStatement::value<Utf8String>(int column) const
+long long Statement::fetchLongLongValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
- return convertedToUtf8StringForColumn(compiledStatement.get(), column);
+ return sqlite3_column_int64(m_compiledStatement.get(), column);
}
template<>
-QString SqliteStatement::value<QString>(int column) const
+long long Statement::fetchValue<long long>(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
- return textForColumn(compiledStatement.get(), column);
+ return fetchLongLongValue(column);
}
-template<>
-QVariant SqliteStatement::value<QVariant>(int column) const
+double Statement::fetchDoubleValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
- return variantForColumn(compiledStatement.get(), column);
+ return sqlite3_column_double(m_compiledStatement.get(), column);
}
-template <typename ContainerType>
- ContainerType SqliteStatement::columnValues(const QVector<int> &columnIndices) const
+template<>
+double Statement::fetchValue<double>(int column) const
{
- typedef typename ContainerType::value_type ElementType;
- ContainerType valueContainer;
- valueContainer.reserve(columnIndices.count());
- for (int columnIndex : columnIndices)
- valueContainer += value<ElementType>(columnIndex);
-
- return valueContainer;
+ return fetchDoubleValue(column);
}
-QMap<QString, QVariant> SqliteStatement::rowColumnValueMap() const
+template<typename StringType>
+StringType Statement::fetchValue(int column) const
{
- QMap<QString, QVariant> values;
-
- reset();
-
- if (next()) {
- for (int column = 0; column < columnCount(); column++)
- values.insert(columnName(column), variantForColumn(compiledStatement.get(), column));
- }
-
- return values;
+ checkIfIsReadyToFetchValues();
+ checkColumnIsValid(column);
+ return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
}
-QMap<QString, QVariant> SqliteStatement::twoColumnValueMap() const
+Utils::SmallString Statement::fetchSmallStringValue(int column) const
{
- QMap<QString, QVariant> values;
-
- reset();
-
- while (next())
- values.insert(textForColumn(compiledStatement.get(), 0), variantForColumn(compiledStatement.get(), 1));
-
- return values;
+ return fetchValue<Utils::SmallString>(column);
}
-template <typename ContainerType>
-ContainerType SqliteStatement::values(const QVector<int> &columns, int size) const
+Utils::PathString Statement::fetchPathStringValue(int column) const
{
- checkColumnsAreValid(columns);
-
- ContainerType resultValues;
- resultValues.reserve(size);
-
- reset();
+ return fetchValue<Utils::PathString>(column);
+}
- while (next()) {
- resultValues += columnValues<ContainerType>(columns);
- }
+template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
+template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const;
- return resultValues;
+Utils::SmallString Statement::text(int column) const
+{
+ return fetchValue<Utils::SmallString>(column);
}
-template SQLITE_EXPORT QVector<QVariant> SqliteStatement::values<QVector<QVariant>>(const QVector<int> &columnIndices, int size) const;
-template SQLITE_EXPORT QVector<Utf8String> SqliteStatement::values<QVector<Utf8String>>(const QVector<int> &columnIndices, int size) const;
-
template <typename ContainerType>
-ContainerType SqliteStatement::values(int column) const
+ContainerType Statement::columnValues(const std::vector<int> &columnIndices) const
{
- typedef typename ContainerType::value_type ElementType;
- ContainerType resultValues;
-
- reset();
-
- while (next()) {
- resultValues += value<ElementType>(column);
- }
+ using ElementType = typename ContainerType::value_type;
+ ContainerType valueContainer;
+ valueContainer.reserve(columnIndices.size());
+ for (int columnIndex : columnIndices)
+ valueContainer.push_back(fetchValue<ElementType>(columnIndex));
- return resultValues;
+ return valueContainer;
}
-template SQLITE_EXPORT QVector<qint64> SqliteStatement::values<QVector<qint64>>(int column) const;
-template SQLITE_EXPORT QVector<double> SqliteStatement::values<QVector<double>>(int column) const;
-template SQLITE_EXPORT QVector<QByteArray> SqliteStatement::values<QVector<QByteArray>>(int column) const;
-template SQLITE_EXPORT Utf8StringVector SqliteStatement::values<Utf8StringVector>(int column) const;
-template SQLITE_EXPORT QVector<QString> SqliteStatement::values<QVector<QString>>(int column) const;
-
template <typename Type>
-Type SqliteStatement::toValue(const Utf8String &sqlStatementUtf8)
+Type Statement::toValue(Utils::SmallStringView sqlStatement, Database &database)
{
- SqliteStatement statement(sqlStatementUtf8);
+ Statement statement(sqlStatement, database);
statement.next();
- return statement.value<Type>(0);
+ return statement.fetchValue<Type>(0);
}
-template SQLITE_EXPORT int SqliteStatement::toValue<int>(const Utf8String &sqlStatementUtf8);
-template SQLITE_EXPORT qint64 SqliteStatement::toValue<qint64>(const Utf8String &sqlStatementUtf8);
-template SQLITE_EXPORT double SqliteStatement::toValue<double>(const Utf8String &sqlStatementUtf8);
-template SQLITE_EXPORT QString SqliteStatement::toValue<QString>(const Utf8String &sqlStatementUtf8);
-template SQLITE_EXPORT QByteArray SqliteStatement::toValue<QByteArray>(const Utf8String &sqlStatementUtf8);
-template SQLITE_EXPORT Utf8String SqliteStatement::toValue<Utf8String>(const Utf8String &sqlStatementUtf8);
-template SQLITE_EXPORT QVariant SqliteStatement::toValue<QVariant>(const Utf8String &sqlStatementUtf8);
+template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);
+template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::SmallStringView sqlStatement, Database &database);
+template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database);
+template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database);
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitestatement.h
index 4cdf5ac262..3e93b7ba8d 100644
--- a/src/libs/sqlite/sqlitestatement.h
+++ b/src/libs/sqlite/sqlitestatement.h
@@ -28,101 +28,373 @@
#include "sqliteglobal.h"
#include "sqliteexception.h"
-#include "utf8stringvector.h"
-#include <QString>
-#include <QVariant>
-#include <QVector>
+#include <utils/smallstringvector.h>
-#include <type_traits>
+#include <utils/optional.h>
+
+#include <cstdint>
#include <memory>
+#include <type_traits>
+#include <tuple>
+
+using std::int64_t;
struct sqlite3_stmt;
struct sqlite3;
-class SQLITE_EXPORT SqliteStatement
+namespace Sqlite {
+
+class Database;
+class DatabaseBackend;
+
+class SQLITE_EXPORT Statement
{
protected:
- explicit SqliteStatement(const Utf8String &sqlStatementUtf8);
+ explicit Statement(Utils::SmallStringView sqlStatement, Database &database);
- static void deleteCompiledStatement(sqlite3_stmt *compiledStatement);
+ static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement);
bool next() const;
void step() const;
+ void execute() const;
void reset() const;
+ int fetchIntValue(int column) const;
+ long fetchLongValue(int column) const;
+ long long fetchLongLongValue(int column) const;
+ double fetchDoubleValue(int column) const;
+ Utils::SmallString fetchSmallStringValue(int column) const;
+ Utils::PathString fetchPathStringValue(int column) const;
template<typename Type>
- Type value(int column) const;
+ Type fetchValue(int column) const;
+ Utils::SmallString text(int column) const;
int columnCount() const;
- Utf8StringVector columnNames() const;
+ Utils::SmallStringVector columnNames() const;
+
+ void bind(int index, int fetchValue);
+ void bind(int index, long long fetchValue);
+ void bind(int index, double fetchValue);
+ void bind(int index, Utils::SmallStringView fetchValue);
+
+ void bind(int index, uint value)
+ {
+ bind(index, static_cast<long long>(value));
+ }
- void bind(int index, int value);
- void bind(int index, qint64 value);
- void bind(int index, double value);
- void bind(int index, const QString &text);
- void bind(int index, const QByteArray &blob);
- void bind(int index, const QVariant &value);
+ void bind(int index, long value)
+ {
+ bind(index, static_cast<long long>(value));
+ }
+
+ void bindValues()
+ {
+ }
+
+ template<typename... ValueType>
+ void bindValues(const ValueType&... values)
+ {
+ bindValuesByIndex(1, values...);
+ }
+
+ template<typename... ValueType>
+ void write(const ValueType&... values)
+ {
+ bindValuesByIndex(1, values...);
+ execute();
+ }
+
+ template<typename... ValueType>
+ void bindNameValues(const ValueType&... values)
+ {
+ bindValuesByName(values...);
+ }
+
+ template<typename... ValueType>
+ void writeNamed(const ValueType&... values)
+ {
+ bindValuesByName(values...);
+ execute();
+ }
template <typename Type>
- void bind(const Utf8String &name, const Type &value);
+ void bind(Utils::SmallStringView name, Type fetchValue);
- int bindingIndexForName(const Utf8String &name);
+ int bindingIndexForName(Utils::SmallStringView name) const;
- void bind(const RowDictionary &rowDictionary);
- void bindUnchecked(const RowDictionary &rowDictionary);
+ void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames);
+ const Utils::SmallStringVector &bindingColumnNames() const;
- void setBindingColumnNames(const Utf8StringVector &bindingColumnNames);
- const Utf8StringVector &bindingColumnNames() const;
+ template <typename ResultType,
+ int ResultTypeCount = 1>
+ std::vector<ResultType> values(std::size_t reserveSize)
+ {
+ std::vector<ResultType> resultValues;
+ resultValues.reserve(reserveSize);
- template <typename ContainerType>
- ContainerType values(const QVector<int> &columns, int size = 0) const;
+ while (next())
+ emplaceBackValues<ResultTypeCount>(resultValues);
- template <typename ContainerType>
- ContainerType values(int column = 0) const;
+ reset();
- QMap<QString, QVariant> rowColumnValueMap() const;
- QMap<QString, QVariant> twoColumnValueMap() const;
+ return resultValues;
+ }
- static void execute(const Utf8String &sqlStatementUtf8);
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ typename... QueryTypes>
+ std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
+ {
+ std::vector<ResultType> resultValues;
+ resultValues.reserve(reserveSize);
- template <typename Type>
- static Type toValue(const Utf8String &sqlStatementUtf8);
+ bindValues(queryValues...);
- void prepare(const Utf8String &sqlStatementUtf8);
- void waitForUnlockNotify() const;
+ while (next())
+ emplaceBackValues<ResultTypeCount>(resultValues);
+
+ reset();
+
+ return resultValues;
+ }
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ typename QueryElementType>
+ std::vector<ResultType> values(std::size_t reserveSize,
+ const std::vector<QueryElementType> &queryValues)
+ {
+ std::vector<ResultType> resultValues;
+ resultValues.reserve(reserveSize);
+
+ for (const QueryElementType &queryValue : queryValues) {
+ bindValues(queryValue);
+
+ while (next())
+ emplaceBackValues<ResultTypeCount>(resultValues);
+
+ reset();
+ }
+
+ return resultValues;
+ }
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ typename... QueryElementTypes>
+ std::vector<ResultType> values(std::size_t reserveSize,
+ const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
+ {
+ using Container = std::vector<ResultType>;
+ Container resultValues;
+ resultValues.reserve(reserveSize);
+
+ for (const auto &queryTuple : queryTuples) {
+ bindTupleValues(queryTuple);
+
+ while (next())
+ emplaceBackValues<ResultTypeCount>(resultValues);
+
+ reset();
+ }
+
+ return resultValues;
+ }
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ typename... QueryTypes>
+ Utils::optional<ResultType> value( const QueryTypes&... queryValues)
+ {
+ Utils::optional<ResultType> resultValue;
+
+ bindValues(queryValues...);
- void write(const RowDictionary &rowDictionary);
- void writeUnchecked(const RowDictionary &rowDictionary);
+ if (next())
+ resultValue = assignValue<Utils::optional<ResultType>, ResultTypeCount>();
- static sqlite3 *sqliteDatabaseHandle();
- static TextEncoding databaseTextEncoding();
+ reset();
+ return resultValue;
+ }
+
+ template <typename Type>
+ static Type toValue(Utils::SmallStringView sqlStatement, Database &database);
+
+ void prepare(Utils::SmallStringView sqlStatement);
+ void waitForUnlockNotify() const;
+
+ sqlite3 *sqliteDatabaseHandle() const;
+ TextEncoding databaseTextEncoding();
bool checkForStepError(int resultCode) const;
void checkForPrepareError(int resultCode) const;
+ void checkForBindingError(int resultCode) const;
void setIfIsReadyToFetchValues(int resultCode) const;
void checkIfIsReadyToFetchValues() const;
- void checkColumnsAreValid(const QVector<int> &columns) const;
+ void checkColumnsAreValid(const std::vector<int> &columns) const;
void checkColumnIsValid(int column) const;
- void checkBindingIndex(int index) const;
void checkBindingName(int index) const;
- void checkParameterCanBeBound(const RowDictionary &rowDictionary, const Utf8String &columnName);
void setBindingParameterCount();
void setBindingColumnNamesFromStatement();
void setColumnCount();
- void checkBindingValueMapIsEmpty(const RowDictionary &rowDictionary) const;
bool isReadOnlyStatement() const;
- Q_NORETURN static void throwException(const char *whatHasHappened);
+ [[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const;
+ [[noreturn]] void throwStatementHasError(const char *whatHasHappened) const;
+ [[noreturn]] void throwStatementIsMisused(const char *whatHasHappened) const;
+ [[noreturn]] void throwConstraintPreventsModification(const char *whatHasHappened) const;
+ [[noreturn]] void throwNoValuesToFetch(const char *whatHasHappened) const;
+ [[noreturn]] void throwInvalidColumnFetched(const char *whatHasHappened) const;
+ [[noreturn]] void throwBindingIndexIsOutOfRange(const char *whatHasHappened) const;
+ [[noreturn]] void throwWrongBingingName(const char *whatHasHappened) const;
+ [[noreturn]] void throwUnknowError(const char *whatHasHappened) const;
+ [[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const;
template <typename ContainerType>
- ContainerType columnValues(const QVector<int> &columnIndices) const;
+ ContainerType columnValues(const std::vector<int> &columnIndices) const;
QString columnName(int column) const;
+ Database &database() const;
+
+protected:
+ explicit Statement(Utils::SmallStringView sqlStatement,
+ DatabaseBackend &databaseBackend);
+
+private:
+ class ValueGetter
+ {
+ public:
+ ValueGetter(Statement &statement, int column)
+ : statement(statement),
+ column(column)
+ {}
+
+ operator int()
+ {
+ return statement.fetchIntValue(column);
+ }
+
+ operator long()
+ {
+ return statement.fetchLongValue(column);
+ }
+
+ operator long long()
+ {
+ return statement.fetchLongLongValue(column);
+ }
+
+ operator double()
+ {
+ return statement.fetchDoubleValue(column);
+ }
+
+ operator Utils::SmallString()
+ {
+ return statement.fetchSmallStringValue(column);
+ }
+
+ operator Utils::PathString()
+ {
+ return statement.fetchPathStringValue(column);
+ }
+
+ Statement &statement;
+ int column;
+ };
+
+ template <typename ContainerType,
+ int... ColumnIndices>
+ void emplaceBackValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
+ {
+ container.emplace_back(ValueGetter(*this, ColumnIndices)...);
+ }
+
+ template <int ResultTypeCount,
+ typename ContainerType>
+ void emplaceBackValues(ContainerType &container)
+ {
+ emplaceBackValues(container, std::make_integer_sequence<int, ResultTypeCount>{});
+ }
+
+ template <typename ResultOptionalType,
+ int... ColumnIndices>
+ ResultOptionalType assignValue(std::integer_sequence<int, ColumnIndices...>)
+ {
+ return ResultOptionalType(Utils::in_place, ValueGetter(*this, ColumnIndices)...);
+ }
+
+ template <typename ResultOptionalType,
+ int ResultTypeCount>
+ ResultOptionalType assignValue()
+ {
+ return assignValue<ResultOptionalType>(std::make_integer_sequence<int, ResultTypeCount>{});
+ }
+
+ template<typename ValueType>
+ void bindValuesByIndex(int index, const ValueType &value)
+ {
+ bind(index, value);
+ }
+
+ template<typename ValueType, typename... ValueTypes>
+ void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values)
+ {
+ bind(index, value);
+ bindValuesByIndex(index + 1, values...);
+ }
+
+ template<typename ValueType>
+ void bindValuesByName(Utils::SmallStringView name, const ValueType &value)
+ {
+ bind(bindingIndexForName(name), value);
+ }
+
+ template<typename ValueType, typename... ValueTypes>
+ void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values)
+ {
+ bind(bindingIndexForName(name), value);
+ bindValuesByName(values...);
+ }
+
+ template <typename TupleType, std::size_t... ColumnIndices>
+ void bindTupleValuesElement(const TupleType &tuple, std::index_sequence<ColumnIndices...>)
+ {
+ bindValues(std::get<ColumnIndices>(tuple)...);
+ }
+
+ template <typename TupleType,
+ typename ColumnIndices = std::make_index_sequence<std::tuple_size<TupleType>::value>>
+ void bindTupleValues(const TupleType &element)
+ {
+ bindTupleValuesElement(element, ColumnIndices());
+ }
+
private:
- std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> compiledStatement;
- Utf8StringVector bindingColumnNames_;
- int bindingParameterCount;
- int columnCount_;
- mutable bool isReadyToFetchValues;
+ std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
+ Utils::SmallStringVector m_bindingColumnNames;
+ Database &m_database;
+ int m_bindingParameterCount;
+ int m_columnCount;
+ mutable bool m_isReadyToFetchValues;
};
+
+extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value);
+extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value);
+extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value);
+extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value);
+extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
+
+extern template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);
+extern template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::SmallStringView sqlStatement, Database &database);
+extern template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database);
+extern template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database);
+
+template <> SQLITE_EXPORT int Statement::fetchValue<int>(int column) const;
+template <> SQLITE_EXPORT long Statement::fetchValue<long>(int column) const;
+template <> SQLITE_EXPORT long long Statement::fetchValue<long long>(int column) const;
+template <> SQLITE_EXPORT double Statement::fetchValue<double>(int column) const;
+extern template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
+extern template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const;
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitetable.cpp b/src/libs/sqlite/sqlitetable.cpp
index 671afe1a7c..99b0e95938 100644
--- a/src/libs/sqlite/sqlitetable.cpp
+++ b/src/libs/sqlite/sqlitetable.cpp
@@ -25,90 +25,8 @@
#include "sqlitetable.h"
-#include "sqlitecolumn.h"
-#include "sqlitedatabase.h"
+namespace Sqlite {
-SqliteTable::SqliteTable()
- : withoutRowId(false)
-{
-}
-SqliteTable::~SqliteTable()
-{
- qDeleteAll(sqliteColumns);
-}
-
-void SqliteTable::setName(const Utf8String &name)
-{
- tableName = name;
-}
-
-const Utf8String &SqliteTable::name() const
-{
- return tableName;
-}
-
-void SqliteTable::setUseWithoutRowId(bool useWithoutWorId)
-{
- withoutRowId = useWithoutWorId;
-}
-
-bool SqliteTable::useWithoutRowId() const
-{
- return withoutRowId;
-}
-
-void SqliteTable::addColumn(SqliteColumn *newColumn)
-{
- sqliteColumns.append(newColumn);
-}
-
-const QVector<SqliteColumn *> &SqliteTable::columns() const
-{
- return sqliteColumns;
-}
-
-void SqliteTable::setSqliteDatabase(SqliteDatabase *database)
-{
- sqliteDatabase = database;
- writeWorker.moveWorkerToThread(sqliteDatabase->writeWorkerThread());
-}
-
-void SqliteTable::initialize()
-{
- writeWorker.connectWithWorker(this);
-
- writeWorker.createTable(createTableCommand());
-}
-
-void SqliteTable::shutdown()
-{
- writeWorker.disconnectWithWorker(this);
-}
-
-void SqliteTable::handleTableCreated()
-{
- emit tableIsReady();
-}
-
-Internal::CreateTableCommand SqliteTable::createTableCommand() const
-{
- Internal::CreateTableCommand createTableCommand;
-
- createTableCommand.tableName = tableName;
- createTableCommand.useWithoutRowId = withoutRowId;
- createTableCommand.definitions = createColumnDefintions();
-
- return createTableCommand;
-}
-
-QVector<Internal::ColumnDefinition> SqliteTable::createColumnDefintions() const
-{
- QVector<Internal::ColumnDefinition> columnDefintions;
-
- for (SqliteColumn *sqliteColumn: sqliteColumns)
- columnDefintions.append(sqliteColumn->columnDefintion());
-
- return columnDefintions;
-}
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitetable.h b/src/libs/sqlite/sqlitetable.h
index 16a0661909..d692bf6c23 100644
--- a/src/libs/sqlite/sqlitetable.h
+++ b/src/libs/sqlite/sqlitetable.h
@@ -25,52 +25,133 @@
#pragma once
+#include "createtablesqlstatementbuilder.h"
#include "sqliteglobal.h"
-#include "tablewriteworkerproxy.h"
-#include "utf8string.h"
+#include "sqlitecolumn.h"
+#include "sqliteindex.h"
+#include "sqliteexception.h"
-#include <QObject>
-#include <QVector>
+namespace Sqlite {
-class SqliteColumn;
-class SqliteDatabase;
+class Database;
-class SQLITE_EXPORT SqliteTable : public QObject
+class Table
{
- Q_OBJECT
+public:
+ Table(std::size_t reserve = 10)
+ {
+ m_sqliteColumns.reserve(reserve);
+ m_sqliteIndices.reserve(reserve);
+ }
- friend class Internal::TableWriteWorkerProxy;
+ void setName(Utils::SmallString &&name)
+ {
+ m_tableName = std::move(name);
+ }
-public:
- SqliteTable();
- ~SqliteTable();
+ Utils::SmallStringView name() const
+ {
+ return m_tableName;
+ }
+
+ void setUseWithoutRowId(bool useWithoutWorId)
+ {
+ m_withoutRowId = useWithoutWorId;
+ }
+
+ bool useWithoutRowId() const
+ {
+ return m_withoutRowId;
+ }
+
+ void setUseIfNotExists(bool useIfNotExists)
+ {
+ m_useIfNotExists = useIfNotExists;
+ }
+
+ void setUseTemporaryTable(bool useTemporaryTable)
+ {
+ m_useTemporaryTable = useTemporaryTable;
+ }
+
+ Column &addColumn(Utils::SmallString &&name,
+ ColumnType type = ColumnType::Numeric,
+ Contraint constraint = Contraint::NoConstraint)
+ {
+ m_sqliteColumns.emplace_back(std::move(name), type, constraint);
+
+ return m_sqliteColumns.back();
+ }
- void setName(const Utf8String &name);
- const Utf8String &name() const;
+ Index &addIndex(const SqliteColumnConstReferences &columns)
+ {
+ m_sqliteIndices.emplace_back(m_tableName.clone(), sqliteColumnNames(columns));
- void setUseWithoutRowId(bool useWithoutWorId);
- bool useWithoutRowId() const;
+ return m_sqliteIndices.back();
+ }
- void addColumn(SqliteColumn *newColumn);
- const QVector<SqliteColumn *> &columns() const;
+ const SqliteColumns &columns() const
+ {
+ return m_sqliteColumns;
+ }
- void setSqliteDatabase(SqliteDatabase *database);
+ bool isReady() const
+ {
+ return m_isReady;
+ }
- void initialize();
- void shutdown();
+ template <typename Database>
+ void initialize(Database &database)
+ {
+ CreateTableSqlStatementBuilder builder;
-signals:
- void tableIsReady();
+ builder.setTableName(m_tableName.clone());
+ builder.setUseWithoutRowId(m_withoutRowId);
+ builder.setUseIfNotExists(m_useIfNotExists);
+ builder.setUseTemporaryTable(m_useTemporaryTable);
+ builder.setColumns(m_sqliteColumns);
+
+ database.execute(builder.sqlStatement());
+
+ initializeIndices(database);
+
+ m_isReady = true;
+ }
+ template <typename Database>
+ void initializeIndices(Database &database)
+ {
+ for (const Index &index : m_sqliteIndices)
+ database.execute(index.sqlStatement());
+ }
+
+ friend bool operator==(const Table &first, const Table &second)
+ {
+ return first.m_tableName == second.m_tableName
+ && first.m_withoutRowId == second.m_withoutRowId
+ && first.m_useIfNotExists == second.m_useIfNotExists
+ && first.m_isReady == second.m_isReady
+ && first.m_sqliteColumns == second.m_sqliteColumns;
+ }
private:
- void handleTableCreated();
- Internal::CreateTableCommand createTableCommand() const;
- QVector<Internal::ColumnDefinition> createColumnDefintions() const;
+ Utils::SmallStringVector sqliteColumnNames(const SqliteColumnConstReferences &columns)
+ {
+ Utils::SmallStringVector columnNames;
+
+ for (const Column &column : columns)
+ columnNames.push_back(column.name());
+
+ return columnNames;
+ }
private:
- Internal::TableWriteWorkerProxy writeWorker;
- QVector<SqliteColumn*> sqliteColumns;
- Utf8String tableName;
- SqliteDatabase *sqliteDatabase;
- bool withoutRowId;
+ Utils::SmallString m_tableName;
+ SqliteColumns m_sqliteColumns;
+ SqliteIndices m_sqliteIndices;
+ bool m_withoutRowId = false;
+ bool m_useIfNotExists = false;
+ bool m_useTemporaryTable = false;
+ bool m_isReady = false;
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitetransaction.cpp b/src/libs/sqlite/sqlitetransaction.cpp
index 48283e9401..2ee17131c2 100644
--- a/src/libs/sqlite/sqlitetransaction.cpp
+++ b/src/libs/sqlite/sqlitetransaction.cpp
@@ -25,31 +25,10 @@
#include "sqlitetransaction.h"
+#include "sqlitedatabase.h"
+#include "sqlitedatabasebackend.h"
#include "sqlitewritestatement.h"
-SqliteAbstractTransaction::~SqliteAbstractTransaction()
-{
- if (!isAlreadyCommited)
- SqliteWriteStatement::execute(Utf8StringLiteral("ROLLBACK"));
-}
+namespace Sqlite {
-void SqliteAbstractTransaction::commit()
-{
- SqliteWriteStatement::execute(Utf8StringLiteral("COMMIT"));
- isAlreadyCommited = true;
-}
-
-SqliteTransaction::SqliteTransaction()
-{
- SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN"));
-}
-
-SqliteImmediateTransaction::SqliteImmediateTransaction()
-{
- SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN IMMEDIATE"));
-}
-
-SqliteExclusiveTransaction::SqliteExclusiveTransaction()
-{
- SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN EXCLUSIVE"));
-}
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h
index 3ff6c8c739..d271728bae 100644
--- a/src/libs/sqlite/sqlitetransaction.h
+++ b/src/libs/sqlite/sqlitetransaction.h
@@ -27,35 +27,73 @@
#include "sqliteglobal.h"
-class SQLITE_EXPORT SqliteAbstractTransaction
+#include <mutex>
+
+namespace Sqlite {
+
+class DatabaseBackend;
+class Database;
+
+template <typename Database>
+class AbstractTransaction
{
public:
- virtual ~SqliteAbstractTransaction();
+ ~AbstractTransaction()
+ {
+ if (!m_isAlreadyCommited)
+ m_database.execute("ROLLBACK");
+ }
- void commit();
+ void commit()
+ {
+ m_database.execute("COMMIT");
+ m_isAlreadyCommited = true;
+ }
+
+protected:
+ AbstractTransaction(Database &database)
+ : m_databaseLock(database.databaseMutex()),
+ m_database(database)
+ {
+ }
private:
- bool isAlreadyCommited = false;
+ std::lock_guard<typename Database::MutexType> m_databaseLock;
+ Database &m_database;
+ bool m_isAlreadyCommited = false;
};
-
-class SQLITE_EXPORT SqliteTransaction final : public SqliteAbstractTransaction
+template <typename Database>
+class DeferredTransaction final : public AbstractTransaction<Database>
{
public:
- SqliteTransaction();
-
+ DeferredTransaction(Database &database)
+ : AbstractTransaction<Database>(database)
+ {
+ database.execute("BEGIN");
+ }
};
-class SQLITE_EXPORT SqliteImmediateTransaction final : public SqliteAbstractTransaction
+template <typename Database>
+class ImmediateTransaction final : public AbstractTransaction<Database>
{
public:
- SqliteImmediateTransaction();
-
+ ImmediateTransaction(Database &database)
+ : AbstractTransaction<Database>(database)
+ {
+ database.execute("BEGIN IMMEDIATE");
+ }
};
-class SQLITE_EXPORT SqliteExclusiveTransaction final : public SqliteAbstractTransaction
+template <typename Database>
+class ExclusiveTransaction final : public AbstractTransaction<Database>
{
public:
- SqliteExclusiveTransaction();
-
+ ExclusiveTransaction(Database &database)
+ : AbstractTransaction<Database>(database)
+ {
+ database.execute("BEGIN EXCLUSIVE");
+ }
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqliteworkerthread.cpp b/src/libs/sqlite/sqliteworkerthread.cpp
deleted file mode 100644
index 8b02a16c7a..0000000000
--- a/src/libs/sqlite/sqliteworkerthread.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "sqliteworkerthread.h"
-
-#include "sqlitedatabaseconnection.h"
-
-#include <QMutexLocker>
-
-SqliteWorkerThread::SqliteWorkerThread(QObject *parent) :
- QThread(parent)
-{
-}
-
-void SqliteWorkerThread::run()
-{
- QMutexLocker locker(&connectionMutex);
-
- connection = new SqliteDatabaseConnection;
-
- locker.unlock();
- connectionChanged.wakeAll();
-
- QThread::run();
-
- locker.relock();
- delete connection;
- connection = 0;
-}
-
-SqliteDatabaseConnection *SqliteWorkerThread::databaseConnection() const
-{
- QMutexLocker locker(&connectionMutex);
- connectionChanged.wait(&connectionMutex);
-
- return connection;
-}
diff --git a/src/libs/sqlite/sqliteworkerthread.h b/src/libs/sqlite/sqliteworkerthread.h
deleted file mode 100644
index b76852434a..0000000000
--- a/src/libs/sqlite/sqliteworkerthread.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QMutex>
-#include <QPointer>
-#include <QThread>
-#include <QWaitCondition>
-
-class SqliteDatabaseConnection;
-
-class SqliteWorkerThread : public QThread
-{
- Q_OBJECT
-public:
- explicit SqliteWorkerThread(QObject *parent = 0);
-
- void run() override;
-
- SqliteDatabaseConnection *databaseConnection() const;
-
-private:
- mutable QMutex connectionMutex;
- mutable QWaitCondition connectionChanged;
- QPointer<SqliteDatabaseConnection> connection;
-};
diff --git a/src/libs/sqlite/sqlitewritestatement.cpp b/src/libs/sqlite/sqlitewritestatement.cpp
index 15fdfaccfe..26c8522b8a 100644
--- a/src/libs/sqlite/sqlitewritestatement.cpp
+++ b/src/libs/sqlite/sqlitewritestatement.cpp
@@ -25,14 +25,19 @@
#include "sqlitewritestatement.h"
-SqliteWriteStatement::SqliteWriteStatement(const Utf8String &sqlStatementUtf8)
- : SqliteStatement(sqlStatementUtf8)
+namespace Sqlite {
+
+WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement,
+ Database &database)
+ : Statement(sqlStatement, database)
{
checkIsWritableStatement();
}
-void SqliteWriteStatement::checkIsWritableStatement()
+void WriteStatement::checkIsWritableStatement()
{
if (isReadOnlyStatement())
- throwException("SqliteStatement::SqliteWriteStatement: is not a writable statement!");
+ throw NotWriteSqlStatement("SqliteStatement::SqliteWriteStatement: is not a writable statement!");
}
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitewritestatement.h b/src/libs/sqlite/sqlitewritestatement.h
index abfb27d741..ec00ae4e8f 100644
--- a/src/libs/sqlite/sqlitewritestatement.h
+++ b/src/libs/sqlite/sqlitewritestatement.h
@@ -27,22 +27,20 @@
#include "sqlitestatement.h"
-class SQLITE_EXPORT SqliteWriteStatement : private SqliteStatement
+namespace Sqlite {
+
+class SQLITE_EXPORT WriteStatement : private Statement
{
public:
- explicit SqliteWriteStatement(const Utf8String &sqlStatementUtf8);
+ explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database);
- using SqliteStatement::step;
- using SqliteStatement::reset;
- using SqliteStatement::bind;
- using SqliteStatement::bindUnchecked;
- using SqliteStatement::bindingIndexForName;
- using SqliteStatement::setBindingColumnNames;
- using SqliteStatement::bindingColumnNames;
- using SqliteStatement::write;
- using SqliteStatement::writeUnchecked;
- using SqliteStatement::execute;
+ using Statement::execute;
+ using Statement::database;
+ using Statement::write;
+ using Statement::writeNamed;
protected:
void checkIsWritableStatement();
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlstatementbuilder.cpp b/src/libs/sqlite/sqlstatementbuilder.cpp
index d100c2df1a..cfa08a2b7b 100644
--- a/src/libs/sqlite/sqlstatementbuilder.cpp
+++ b/src/libs/sqlite/sqlstatementbuilder.cpp
@@ -26,137 +26,164 @@
#include "sqlstatementbuilder.h"
#include "sqlstatementbuilderexception.h"
-#include "utf8stringvector.h"
+
+#include <utils/smallstringvector.h>
#include <algorithm>
-SqlStatementBuilder::SqlStatementBuilder(const Utf8String &sqlTemplate)
- : sqlTemplate(sqlTemplate)
+namespace Sqlite {
+
+SqlStatementBuilder::SqlStatementBuilder(Utils::SmallStringView sqlTemplate)
+ : m_sqlTemplate(std::move(sqlTemplate))
{
}
-void SqlStatementBuilder::bindEmptyText(const Utf8String &name)
+void SqlStatementBuilder::bindEmptyText(Utils::SmallString &&name)
{
clearSqlStatement();
checkIfPlaceHolderExists(name);
- changeBinding(name, Utf8String());
+ changeBinding(std::move(name), {});
}
-void SqlStatementBuilder::bind(const Utf8String &name, const Utf8String &text)
+void SqlStatementBuilder::bind(Utils::SmallString &&name, Utils::SmallString &&text)
{
clearSqlStatement();
checkBindingTextIsNotEmpty(text);
checkIfPlaceHolderExists(name);
- changeBinding(name, text);
+ changeBinding(std::move(name), std::move(text));
}
-void SqlStatementBuilder::bind(const Utf8String &name, const Utf8StringVector &textVector)
+void SqlStatementBuilder::bind(Utils::SmallString &&name, const Utils::SmallStringVector &textVector)
{
clearSqlStatement();
checkBindingTextVectorIsNotEmpty(textVector);
checkIfPlaceHolderExists(name);
- changeBinding(name, textVector.join(Utf8StringLiteral(", ")));
+ changeBinding(std::move(name), textVector.join(", "));
}
-void SqlStatementBuilder::bind(const Utf8String &name, int value)
+void SqlStatementBuilder::bind(Utils::SmallString &&name, int value)
{
clearSqlStatement();
checkIfPlaceHolderExists(name);
- changeBinding(name, Utf8String::number(value));
+ changeBinding(std::move(name), Utils::SmallString::number(value));
}
-void SqlStatementBuilder::bind(const Utf8String &name, const QVector<int> &integerVector)
+namespace {
+Utils::SmallStringVector integerVectorToStringVector(const std::vector<int> &integerVector)
+{
+ Utils::SmallStringVector stringVector;
+ stringVector.reserve(integerVector.size());
+
+ std::transform(integerVector.begin(),
+ integerVector.end(),
+ std::back_inserter(stringVector),
+ [] (int i) { return Utils::SmallString::number(i); });
+
+ return stringVector;
+}
+}
+void SqlStatementBuilder::bind(Utils::SmallString &&name, const std::vector<int> &integerVector)
{
clearSqlStatement();
checkBindingIntegerVectorIsNotEmpty(integerVector);
checkIfPlaceHolderExists(name);
- changeBinding(name, Utf8StringVector::fromIntegerVector(integerVector).join(Utf8StringLiteral(", ")));
+ changeBinding(std::move(name), integerVectorToStringVector(integerVector).join(", "));
}
-void SqlStatementBuilder::bindWithInsertTemplateParameters(const Utf8String &name, const Utf8StringVector &columns)
+void SqlStatementBuilder::bindWithInsertTemplateParameters(Utils::SmallString &&name,
+ const Utils::SmallStringVector &columns)
{
clearSqlStatement();
checkBindingTextVectorIsNotEmpty(columns);
checkIfPlaceHolderExists(name);
- changeBinding(name, insertTemplateParameters(columns));
+ changeBinding(std::move(name), insertTemplateParameters(columns));
}
-void SqlStatementBuilder::bindWithUpdateTemplateParameters(const Utf8String &name, const Utf8StringVector &columns)
+void SqlStatementBuilder::bindWithUpdateTemplateParameters(Utils::SmallString &&name,
+ const Utils::SmallStringVector &columns)
{
clearSqlStatement();
checkBindingTextVectorIsNotEmpty(columns);
checkIfPlaceHolderExists(name);
- changeBinding(name, updateTemplateParameters(columns));
+ changeBinding(std::move(name), updateTemplateParameters(columns));
}
-void SqlStatementBuilder::bindWithUpdateTemplateNames(const Utf8String &name, const Utf8StringVector &columns)
+void SqlStatementBuilder::bindWithUpdateTemplateNames(Utils::SmallString &&name,
+ const Utils::SmallStringVector &columns)
{
clearSqlStatement();
checkBindingTextVectorIsNotEmpty(columns);
checkIfPlaceHolderExists(name);
- changeBinding(name, updateTemplateNames(columns));
+ changeBinding(std::move(name), updateTemplateNames(columns));
}
void SqlStatementBuilder::clear()
{
- bindings.clear();
- sqlStatement_.clear();
+ m_bindings.clear();
+ m_sqlStatement.clear();
}
-const Utf8String SqlStatementBuilder::insertTemplateParameters(const Utf8StringVector &columns)
+Utils::SmallString SqlStatementBuilder::insertTemplateParameters(const Utils::SmallStringVector &columns)
{
- const Utf8StringVector templateParamters(columns.count(), Utf8StringLiteral("?"));
+ const Utils::SmallStringVector templateParamters(columns.size(), "?");
- return templateParamters.join(Utf8StringLiteral(", "));
+ return templateParamters.join(", ");
}
-const Utf8String SqlStatementBuilder::updateTemplateParameters(const Utf8StringVector &columns)
+Utils::SmallString SqlStatementBuilder::updateTemplateParameters(const Utils::SmallStringVector &columns)
{
- Utf8String templateParamters = columns.join(Utf8StringLiteral("=?, "));
- templateParamters.append(Utf8StringLiteral("=?"));
+ Utils::SmallString templateParamters = columns.join("=?, ");
+ templateParamters.append("=?");
return templateParamters;
}
-const Utf8String SqlStatementBuilder::updateTemplateNames(const Utf8StringVector &columns)
+Utils::SmallString SqlStatementBuilder::updateTemplateNames(const Utils::SmallStringVector &columns)
{
- Utf8StringVector templateNames;
+ Utils::SmallStringVector templateNames;
+ templateNames.reserve(columns.size());
+
+ auto convertToTemplateNames = [] (const Utils::SmallString &column) {
+ return Utils::SmallString::join({column, "=@", column});
+ };
- foreach (const Utf8String &columnName, columns)
- templateNames.append(columnName+Utf8StringLiteral("=@")+columnName);
+ std::transform(columns.begin(),
+ columns.end(),
+ std::back_inserter(templateNames),
+ convertToTemplateNames);
- return templateNames.join(Utf8StringLiteral(", "));
+ return templateNames.join(", ");
}
void SqlStatementBuilder::sortBindings() const
{
- std::sort(bindings.begin(), bindings.end(), [] (const BindingPair &lhs,const BindingPair &rhs)
+ std::sort(m_bindings.begin(), m_bindings.end(), [] (const BindingPair &lhs,const BindingPair &rhs)
{
- return lhs.first.byteSize() == rhs.first.byteSize() ? lhs.first.toByteArray() < rhs.first.toByteArray() : lhs.first.byteSize() > rhs.first.byteSize();
+ return lhs.first.size() == rhs.first.size() ? lhs.first < rhs.first : lhs.first.size() > rhs.first.size();
});
}
-Utf8String SqlStatementBuilder::sqlStatement() const
+Utils::SmallStringView SqlStatementBuilder::sqlStatement() const
{
if (!isBuild())
generateSqlStatement();
- return sqlStatement_;
+ return m_sqlStatement;
}
bool SqlStatementBuilder::isBuild() const
{
- return sqlStatement_.hasContent();
+ return m_sqlStatement.hasContent();
}
-Utf8String SqlStatementBuilder::columnTypeToString(ColumnType columnType)
+Utils::SmallString SqlStatementBuilder::columnTypeToString(ColumnType columnType)
{
switch (columnType) {
- case ColumnType::Numeric: return Utf8StringLiteral("NUMERIC");
- case ColumnType::Integer: return Utf8StringLiteral("INTEGER");
- case ColumnType::Real: return Utf8StringLiteral("REAL");
- case ColumnType::Text: return Utf8StringLiteral("TEXT");
- case ColumnType::None: return Utf8String();
+ case ColumnType::Numeric: return "NUMERIC";
+ case ColumnType::Integer: return "INTEGER";
+ case ColumnType::Real: return "REAL";
+ case ColumnType::Text: return "TEXT";
+ case ColumnType::None: return {};
}
Q_UNREACHABLE();
@@ -164,70 +191,71 @@ Utf8String SqlStatementBuilder::columnTypeToString(ColumnType columnType)
void SqlStatementBuilder::generateSqlStatement() const
{
- sqlStatement_ = sqlTemplate;
+ m_sqlStatement = m_sqlTemplate;
sortBindings();
- auto bindingIterator = bindings.cbegin();
- while (bindingIterator != bindings.cend()) {
- const Utf8String &placeHolderToken = bindingIterator->first;
- const Utf8String &replacementToken = bindingIterator->second;
- sqlStatement_.replace(placeHolderToken, replacementToken);
- ++bindingIterator;
+ for (const auto &entry : m_bindings) {
+ const Utils::SmallStringView placeHolderToken = entry.first;
+ const Utils::SmallStringView replacementToken = entry.second;
+ m_sqlStatement.replace(placeHolderToken, replacementToken);
}
checkIfNoPlaceHoldersAynmoreExists();
}
-void SqlStatementBuilder::changeBinding(const Utf8String &name, const Utf8String &text)
+void SqlStatementBuilder::changeBinding(Utils::SmallString &&name, Utils::SmallString &&text)
{
-
- auto findBindingIterator = std::find_if(bindings.begin(), bindings.end(), [name] (const BindingPair &binding) {
+ auto findBindingIterator = std::find_if(m_bindings.begin(),
+ m_bindings.end(),
+ [&] (const BindingPair &binding) {
return binding.first == name;
});
- if (findBindingIterator == bindings.end())
- bindings.push_back(std::make_pair(name, text));
+ if (findBindingIterator == m_bindings.end())
+ m_bindings.push_back(std::make_pair(std::move(name), std::move(text)));
else
- findBindingIterator->second = text;
+ findBindingIterator->second = std::move(text);
}
void SqlStatementBuilder::clearSqlStatement()
{
- sqlStatement_.clear();
+ m_sqlStatement.clear();
}
-void SqlStatementBuilder::checkIfPlaceHolderExists(const Utf8String &name) const
+void SqlStatementBuilder::checkIfPlaceHolderExists(Utils::SmallStringView name) const
{
- if (name.byteSize() < 2 || !name.startsWith('$') || !sqlTemplate.contains(name))
- throwException("SqlStatementBuilder::bind: placeholder name does not exists!", name.constData());
+ if (name.size() < 2 || !name.startsWith('$') || !m_sqlTemplate.contains(name))
+ throwException("SqlStatementBuilder::bind: placeholder name does not exists!", name.data());
}
void SqlStatementBuilder::checkIfNoPlaceHoldersAynmoreExists() const
{
- if (sqlStatement_.contains('$'))
- throwException("SqlStatementBuilder::bind: there are still placeholder in the sql statement!", sqlTemplate.constData());
+ if (m_sqlStatement.contains('$'))
+ throwException("SqlStatementBuilder::bind: there are still placeholder in the sql statement!", m_sqlTemplate.constData());
}
-void SqlStatementBuilder::checkBindingTextIsNotEmpty(const Utf8String &text) const
+void SqlStatementBuilder::checkBindingTextIsNotEmpty(Utils::SmallStringView text) const
{
if (text.isEmpty())
- throwException("SqlStatementBuilder::bind: binding text it empty!", sqlTemplate.constData());
+ throwException("SqlStatementBuilder::bind: binding text it empty!", m_sqlTemplate.constData());
}
-void SqlStatementBuilder::checkBindingTextVectorIsNotEmpty(const Utf8StringVector &textVector) const
+void SqlStatementBuilder::checkBindingTextVectorIsNotEmpty(const Utils::SmallStringVector &textVector) const
{
- if (textVector.isEmpty())
- throwException("SqlStatementBuilder::bind: binding text vector it empty!", sqlTemplate.constData());
+ if (textVector.empty())
+ throwException("SqlStatementBuilder::bind: binding text vector it empty!", m_sqlTemplate.constData());
}
-void SqlStatementBuilder::checkBindingIntegerVectorIsNotEmpty(const QVector<int> &integerVector) const
+void SqlStatementBuilder::checkBindingIntegerVectorIsNotEmpty(const std::vector<int> &integerVector) const
{
- if (integerVector.isEmpty())
- throwException("SqlStatementBuilder::bind: binding integer vector it empty!", sqlTemplate.constData());
+ if (integerVector.empty())
+ throwException("SqlStatementBuilder::bind: binding integer vector it empty!", m_sqlTemplate.constData());
}
void SqlStatementBuilder::throwException(const char *whatHasHappened, const char *errorMessage)
{
throw SqlStatementBuilderException(whatHasHappened, errorMessage);
}
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlstatementbuilder.h b/src/libs/sqlite/sqlstatementbuilder.h
index 6bc092900e..670455dc41 100644
--- a/src/libs/sqlite/sqlstatementbuilder.h
+++ b/src/libs/sqlite/sqlstatementbuilder.h
@@ -25,54 +25,63 @@
#pragma once
-#include "utf8string.h"
+#include "sqliteglobal.h"
+
+#include <utils/smallstringvector.h>
#include <utility>
#include <vector>
+namespace Sqlite {
+
class SQLITE_EXPORT SqlStatementBuilder
{
- using BindingPair = std::pair<Utf8String, Utf8String>;
+ using BindingPair = std::pair<Utils::SmallString, Utils::SmallString>;
public:
- SqlStatementBuilder(const Utf8String &sqlTemplate);
-
- void bindEmptyText(const Utf8String &name);
- void bind(const Utf8String &name, const Utf8String &text);
- void bind(const Utf8String &name, const Utf8StringVector &textVector);
- void bind(const Utf8String &name, int value);
- void bind(const Utf8String &name, const QVector<int> &integerVector);
- void bindWithInsertTemplateParameters(const Utf8String &name, const Utf8StringVector &columns);
- void bindWithUpdateTemplateParameters(const Utf8String &name, const Utf8StringVector &columns);
- void bindWithUpdateTemplateNames(const Utf8String &name, const Utf8StringVector &columns);
+ SqlStatementBuilder(Utils::SmallStringView m_sqlTemplate);
+
+ void bindEmptyText(Utils::SmallString &&name);
+ void bind(Utils::SmallString &&name, Utils::SmallString &&text);
+ void bind(Utils::SmallString &&name, const Utils::SmallStringVector &textVector);
+ void bind(Utils::SmallString &&name, int value);
+ void bind(Utils::SmallString &&name, const std::vector<int> &integerVector);
+ void bindWithInsertTemplateParameters(Utils::SmallString &&name,
+ const Utils::SmallStringVector &columns);
+ void bindWithUpdateTemplateParameters(Utils::SmallString &&name,
+ const Utils::SmallStringVector &columns);
+ void bindWithUpdateTemplateNames(Utils::SmallString &&name,
+ const Utils::SmallStringVector &columns);
void clear();
- Utf8String sqlStatement() const;
+ Utils::SmallStringView sqlStatement() const;
bool isBuild() const;
- static Utf8String columnTypeToString(ColumnType columnType);
+ static Utils::SmallString columnTypeToString(ColumnType columnType);
protected:
- static const Utf8String insertTemplateParameters(const Utf8StringVector &columns);
- static const Utf8String updateTemplateParameters(const Utf8StringVector &columns);
- static const Utf8String updateTemplateNames(const Utf8StringVector &columns);
+ static Utils::SmallString insertTemplateParameters(const Utils::SmallStringVector &columns);
+ static Utils::SmallString updateTemplateParameters(const Utils::SmallStringVector &columns);
+ static Utils::SmallString updateTemplateNames(const Utils::SmallStringVector &columns);
void sortBindings() const;
void generateSqlStatement() const;
- void changeBinding(const Utf8String &name, const Utf8String &text);
+ void changeBinding(Utils::SmallString &&name, Utils::SmallString &&text);
void clearSqlStatement();
- void checkIfPlaceHolderExists(const Utf8String &name) const;
+ void checkIfPlaceHolderExists(Utils::SmallStringView name) const;
void checkIfNoPlaceHoldersAynmoreExists() const;
- void checkBindingTextIsNotEmpty(const Utf8String &text) const;
- void checkBindingTextVectorIsNotEmpty(const Utf8StringVector &textVector) const;
- void checkBindingIntegerVectorIsNotEmpty(const QVector<int> &integerVector) const;
+ void checkBindingTextIsNotEmpty(Utils::SmallStringView text) const;
+ void checkBindingTextVectorIsNotEmpty(const Utils::SmallStringVector &textVector) const;
+ void checkBindingIntegerVectorIsNotEmpty(const std::vector<int> &integerVector) const;
Q_NORETURN static void throwException(const char *whatHasHappened, const char *errorMessage);
private:
- Utf8String sqlTemplate;
- mutable Utf8String sqlStatement_;
- mutable std::vector<BindingPair> bindings;
+ Utils::BasicSmallString<510> m_sqlTemplate;
+ mutable Utils::BasicSmallString<510> m_sqlStatement;
+ mutable std::vector<BindingPair> m_bindings;
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlstatementbuilderexception.cpp b/src/libs/sqlite/sqlstatementbuilderexception.cpp
index dcd814987f..82f5b4f792 100644
--- a/src/libs/sqlite/sqlstatementbuilderexception.cpp
+++ b/src/libs/sqlite/sqlstatementbuilderexception.cpp
@@ -25,7 +25,10 @@
#include "sqlstatementbuilderexception.h"
-SqlStatementBuilderException::SqlStatementBuilderException(const char *whatErrorHasHappen, const char *errorMessage)
- : SqliteException(whatErrorHasHappen, errorMessage)
-{
-}
+namespace Sqlite {
+
+
+
+
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlstatementbuilderexception.h b/src/libs/sqlite/sqlstatementbuilderexception.h
index 17e215ad4f..05d07c25a9 100644
--- a/src/libs/sqlite/sqlstatementbuilderexception.h
+++ b/src/libs/sqlite/sqlstatementbuilderexception.h
@@ -27,8 +27,12 @@
#include "sqliteexception.h"
-class SQLITE_EXPORT SqlStatementBuilderException : public SqliteException
+namespace Sqlite {
+
+class SQLITE_EXPORT SqlStatementBuilderException : public Exception
{
public:
- SqlStatementBuilderException(const char *whatErrorHasHappen, const char *errorMessage = 0);
+ using Exception::Exception;
};
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/tablewriteworker.cpp b/src/libs/sqlite/tablewriteworker.cpp
deleted file mode 100644
index ac84a43a5e..0000000000
--- a/src/libs/sqlite/tablewriteworker.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "tablewriteworker.h"
-
-#include "createtablesqlstatementbuilder.h"
-#include "sqlitetransaction.h"
-#include "sqlitewritestatement.h"
-
-namespace Internal {
-
-TableWriteWorker::TableWriteWorker(QObject *parent)
- : QObject(parent)
-{
-
-}
-
-TableWriteWorker::~TableWriteWorker()
-{
-
-}
-
-void TableWriteWorker::createTable(const CreateTableCommand &command)
-{
- try {
- CreateTableSqlStatementBuilder createTableSqlStatementBuilder;
-
- createTableSqlStatementBuilder.setTable(command.tableName);
- createTableSqlStatementBuilder.setUseWithoutRowId(command.useWithoutRowId);
- createTableSqlStatementBuilder.setColumnDefinitions(command.definitions);
-
- SqliteImmediateTransaction transaction;
- SqliteWriteStatement::execute(createTableSqlStatementBuilder.sqlStatement());
- transaction.commit();
-
- emit tableCreated();
- } catch (const SqliteException &exception) {
- exception.printWarning();
- }
-}
-
-} // namespace Internal
-
diff --git a/src/libs/sqlite/tablewriteworkerproxy.cpp b/src/libs/sqlite/tablewriteworkerproxy.cpp
deleted file mode 100644
index a36463b065..0000000000
--- a/src/libs/sqlite/tablewriteworkerproxy.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "tablewriteworkerproxy.h"
-
-#include "createtablecommand.h"
-#include "sqlitetable.h"
-#include "tablewriteworker.h"
-
-namespace Internal {
-
-TableWriteWorkerProxy::TableWriteWorkerProxy()
- : worker(new TableWriteWorker)
-{
-}
-
-TableWriteWorkerProxy::~TableWriteWorkerProxy()
-{
- delete worker;
-}
-
-void TableWriteWorkerProxy::connectWithWorker(SqliteTable *sqliterTable)
-{
- connect(this, &TableWriteWorkerProxy::createTable, worker, &TableWriteWorker::createTable);
- connect(worker, &TableWriteWorker::tableCreated, sqliterTable, &SqliteTable::handleTableCreated);
-}
-
-void TableWriteWorkerProxy::disconnectWithWorker(SqliteTable *sqliterTable)
-{
- disconnect(this, &TableWriteWorkerProxy::createTable, worker, &TableWriteWorker::createTable);
- disconnect(worker, &TableWriteWorker::tableCreated, sqliterTable, &SqliteTable::handleTableCreated);
-}
-
-void TableWriteWorkerProxy::moveWorkerToThread(QThread *workerThread)
-{
- worker->moveToThread(workerThread);
-}
-
-} // namespace Internal
-
diff --git a/src/libs/utils/images/dir.png b/src/libs/ssh/images/dir.png
index 57cec6bcd3..57cec6bcd3 100644
--- a/src/libs/utils/images/dir.png
+++ b/src/libs/ssh/images/dir.png
Binary files differ
diff --git a/src/libs/utils/images/help.png b/src/libs/ssh/images/help.png
index a12ef281d4..a12ef281d4 100644
--- a/src/libs/utils/images/help.png
+++ b/src/libs/ssh/images/help.png
Binary files differ
diff --git a/src/libs/utils/images/unknownfile.png b/src/libs/ssh/images/unknownfile.png
index 88f77592d1..88f77592d1 100644
--- a/src/libs/utils/images/unknownfile.png
+++ b/src/libs/ssh/images/unknownfile.png
Binary files differ
diff --git a/src/libs/ssh/sftpfilesystemmodel.cpp b/src/libs/ssh/sftpfilesystemmodel.cpp
index d3432c5528..b1a173759c 100644
--- a/src/libs/ssh/sftpfilesystemmodel.cpp
+++ b/src/libs/ssh/sftpfilesystemmodel.cpp
@@ -166,11 +166,11 @@ QVariant SftpFileSystemModel::data(const QModelIndex &index, int role) const
switch (node->fileInfo.type) {
case FileTypeRegular:
case FileTypeOther:
- return QIcon(":/utils/images/unknownfile.png");
+ return QIcon(":/ssh/images/unknownfile.png");
case FileTypeDirectory:
- return QIcon(":/utils/images/dir.png");
+ return QIcon(":/ssh/images/dir.png");
case FileTypeUnknown:
- return QIcon(":/utils/images/help.png"); // Shows a question mark.
+ return QIcon(":/ssh/images/help.png"); // Shows a question mark.
}
}
if (index.column() == 1) {
diff --git a/src/libs/ssh/ssh.pro b/src/libs/ssh/ssh.pro
index 27be1ec187..499540ac72 100644
--- a/src/libs/ssh/ssh.pro
+++ b/src/libs/ssh/ssh.pro
@@ -82,4 +82,6 @@ HEADERS = $$PWD/sshsendfacility_p.h \
FORMS = $$PWD/sshkeycreationdialog.ui
+RESOURCES += $$PWD/ssh.qrc
+
include(../3rdparty/botan/botan.pri)
diff --git a/src/libs/ssh/ssh.qbs b/src/libs/ssh/ssh.qbs
index 54dad5bf75..3aa95a16d5 100644
--- a/src/libs/ssh/ssh.qbs
+++ b/src/libs/ssh/ssh.qbs
@@ -22,6 +22,7 @@ Project {
"sftpoperation.cpp", "sftpoperation_p.h",
"sftpoutgoingpacket.cpp", "sftpoutgoingpacket_p.h",
"sftppacket.cpp", "sftppacket_p.h",
+ "ssh.qrc",
"sshagent.cpp", "sshagent_p.h",
"sshbotanconversions_p.h",
"sshcapabilities_p.h", "sshcapabilities.cpp",
diff --git a/src/libs/ssh/ssh.qrc b/src/libs/ssh/ssh.qrc
new file mode 100644
index 0000000000..4b0c6a8c51
--- /dev/null
+++ b/src/libs/ssh/ssh.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/ssh">
+ <file>images/dir.png</file>
+ <file>images/help.png</file>
+ <file>images/unknownfile.png</file>
+ </qresource>
+</RCC>
diff --git a/src/libs/ssh/sshagent.cpp b/src/libs/ssh/sshagent.cpp
index 1ada40fcd1..4e581fac0a 100644
--- a/src/libs/ssh/sshagent.cpp
+++ b/src/libs/ssh/sshagent.cpp
@@ -57,7 +57,7 @@ void SshAgent::refreshKeysImpl()
if (state() != Connected)
return;
const auto keysRequestIt = std::find_if(m_pendingRequests.constBegin(),
- m_pendingRequests.constEnd(), [this](const Request &r) { return r.isKeysRequest(); });
+ m_pendingRequests.constEnd(), [](const Request &r) { return r.isKeysRequest(); });
if (keysRequestIt != m_pendingRequests.constEnd()) {
qCDebug(sshLog) << "keys request already pending, not adding another one";
return;
diff --git a/src/libs/ssh/sshagent_p.h b/src/libs/ssh/sshagent_p.h
index 346d9aab9d..f30867b934 100644
--- a/src/libs/ssh/sshagent_p.h
+++ b/src/libs/ssh/sshagent_p.h
@@ -76,7 +76,7 @@ private:
QByteArray key;
QByteArray dataToSign;
- uint token;
+ uint token = 0;
};
struct Packet {
diff --git a/src/libs/ssh/sshexception_p.h b/src/libs/ssh/sshexception_p.h
index b51ce4b04c..94697df19e 100644
--- a/src/libs/ssh/sshexception_p.h
+++ b/src/libs/ssh/sshexception_p.h
@@ -31,6 +31,8 @@
#include <QCoreApplication>
#include <QString>
+#include <exception>
+
namespace QSsh {
namespace Internal {
@@ -57,25 +59,28 @@ enum SshErrorCode {
#define SSH_SERVER_EXCEPTION(error, errorString) \
SshServerException((error), (errorString), SSH_TR(errorString))
-struct SshServerException
+struct SshServerException : public std::exception
{
SshServerException(SshErrorCode error, const QByteArray &errorStringServer,
const QString &errorStringUser)
: error(error), errorStringServer(errorStringServer),
errorStringUser(errorStringUser) {}
+ const char *what() const noexcept override { return errorStringServer.constData(); }
const SshErrorCode error;
const QByteArray errorStringServer;
const QString errorStringUser;
};
-struct SshClientException
+struct SshClientException : public std::exception
{
SshClientException(SshError error, const QString &errorString)
- : error(error), errorString(errorString) {}
+ : error(error), errorString(errorString), errorStringPrintable(errorString.toLocal8Bit()) {}
+ const char *what() const noexcept override { return errorStringPrintable.constData(); }
const SshError error;
const QString errorString;
+ const QByteArray errorStringPrintable;
};
} // namespace Internal
diff --git a/src/libs/timeline/qml/MainView.qml b/src/libs/timeline/qml/MainView.qml
index e6aa2bb15e..2c0aa1258e 100644
--- a/src/libs/timeline/qml/MainView.qml
+++ b/src/libs/timeline/qml/MainView.qml
@@ -36,7 +36,6 @@ Rectangle {
property bool lockItemSelection : false
- signal updateCursorPosition
property string fileName: ""
property int lineNumber: -1
property int columnNumber: 0
@@ -242,7 +241,7 @@ Rectangle {
var newTypeId = model.typeId(selectedItem);
if (newTypeId !== typeId) {
typeId = newTypeId;
- root.updateCursorPosition();
+ timelineModelAggregator.updateCursorPosition();
}
} else {
selectedModel = -1;
diff --git a/src/libs/timeline/qml/lock_closed@2x.png b/src/libs/timeline/qml/lock_closed@2x.png
deleted file mode 100644
index 99bb0fc85d..0000000000
--- a/src/libs/timeline/qml/lock_closed@2x.png
+++ /dev/null
Binary files differ
diff --git a/src/libs/timeline/qml/lock_open@2x.png b/src/libs/timeline/qml/lock_open@2x.png
deleted file mode 100644
index b84580cb24..0000000000
--- a/src/libs/timeline/qml/lock_open@2x.png
+++ /dev/null
Binary files differ
diff --git a/src/libs/timeline/timelineabstractrenderer.h b/src/libs/timeline/timelineabstractrenderer.h
index 0412371efa..444e143171 100644
--- a/src/libs/timeline/timelineabstractrenderer.h
+++ b/src/libs/timeline/timelineabstractrenderer.h
@@ -35,8 +35,6 @@
namespace Timeline {
-class TimelineRenderPass;
-class TimelineRenderState;
class TIMELINE_EXPORT TimelineAbstractRenderer : public QQuickItem
{
diff --git a/src/libs/timeline/timelinemodelaggregator.h b/src/libs/timeline/timelinemodelaggregator.h
index fb0e5a1162..b017354330 100644
--- a/src/libs/timeline/timelinemodelaggregator.h
+++ b/src/libs/timeline/timelinemodelaggregator.h
@@ -61,6 +61,7 @@ public:
signals:
void modelsChanged();
void heightChanged();
+ void updateCursorPosition();
private:
class TimelineModelAggregatorPrivate;
diff --git a/src/libs/timeline/timelinerenderer.h b/src/libs/timeline/timelinerenderer.h
index 9965458d0b..09814d07f7 100644
--- a/src/libs/timeline/timelinerenderer.h
+++ b/src/libs/timeline/timelinerenderer.h
@@ -35,8 +35,6 @@
namespace Timeline {
-class TimelineRenderPass;
-class TimelineRenderState;
class TIMELINE_EXPORT TimelineRenderer : public TimelineAbstractRenderer
{
diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp
index abe01ada6e..29c531e1cc 100644
--- a/src/libs/utils/basetreeview.cpp
+++ b/src/libs/utils/basetreeview.cpp
@@ -355,7 +355,7 @@ void BaseTreeView::showEvent(QShowEvent *ev)
void BaseTreeView::showProgressIndicator()
{
if (!d->m_progressIndicator) {
- d->m_progressIndicator = new ProgressIndicator(ProgressIndicator::Large);
+ d->m_progressIndicator = new ProgressIndicator(ProgressIndicatorSize::Large);
d->m_progressIndicator->attachToWidget(this);
}
d->m_progressIndicator->show();
diff --git a/src/libs/utils/benchmarker.cpp b/src/libs/utils/benchmarker.cpp
new file mode 100644
index 0000000000..61f4f37d19
--- /dev/null
+++ b/src/libs/utils/benchmarker.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "benchmarker.h"
+
+#include <QLoggingCategory>
+
+static Q_LOGGING_CATEGORY(benchmarksLog, "qtc.benchmark");
+
+namespace Utils {
+
+Benchmarker::Benchmarker(const QString &testsuite, const QString &testcase,
+ const QString &tagData) :
+ m_tagData(tagData),
+ m_testsuite(testsuite),
+ m_testcase(testcase)
+{
+ m_timer.start();
+}
+
+Benchmarker::~Benchmarker()
+{
+ if (m_timer.isValid())
+ report(m_timer.elapsed());
+}
+
+void Benchmarker::report(qint64 ms)
+{
+ m_timer.invalidate();
+ report(m_testsuite, m_testcase, ms, m_tagData);
+}
+
+void Benchmarker::report(const QString &testsuite, const QString &testcase, qint64 ms,
+ const QString &tags)
+{
+ QString t = "unit=ms";
+ if (!tags.isEmpty())
+ t += "," + tags;
+
+ qCDebug(benchmarksLog, "%s::%s: %lld { %s }",
+ testsuite.toUtf8().data(), testcase.toUtf8().data(), ms, t.toUtf8().data());
+}
+
+
+} // namespace Utils
diff --git a/src/libs/utils/benchmarker.h b/src/libs/utils/benchmarker.h
new file mode 100644
index 0000000000..bcff6d341c
--- /dev/null
+++ b/src/libs/utils/benchmarker.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "utils_global.h"
+
+#include <QString>
+#include <QElapsedTimer>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT Benchmarker
+{
+public:
+ Benchmarker(const QString &testsuite, const QString &testcase,
+ const QString &tags = QString());
+ ~Benchmarker();
+
+ void report(qint64 ms);
+ static void report(const QString &testsuite, const QString &testcase, qint64 ms,
+ const QString &tags = QString());
+
+private:
+ QElapsedTimer m_timer;
+ QString m_tagData;
+ QString m_testsuite;
+ QString m_testcase;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/camelhumpmatcher.cpp b/src/libs/utils/camelhumpmatcher.cpp
new file mode 100644
index 0000000000..51206262d4
--- /dev/null
+++ b/src/libs/utils/camelhumpmatcher.cpp
@@ -0,0 +1,146 @@
+/**************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2017 BlackBerry Limited <qt@blackberry.com>
+** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "camelhumpmatcher.h"
+
+#include <QRegularExpression>
+#include <QString>
+
+/**
+ * \brief Creates a regexp that represents a specified camel hump pattern,
+ * underscores are not included.
+ *
+ * \param pattern the camel hump pattern
+ * \param caseSensitivity case sensitivity used for camel hump matching;
+ * does not affect wildcard style matching
+ * \return the regexp
+ */
+QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
+ const QString &pattern, CamelHumpMatcher::CaseSensitivity caseSensitivity)
+{
+ if (pattern.isEmpty())
+ return QRegularExpression();
+
+ /*
+ * This code builds a regular expression in order to more intelligently match
+ * camel-case and underscore names.
+ *
+ * For any but the first letter, the following replacements are made:
+ * A => [a-z0-9_]*A
+ * a => (?:[a-zA-Z0-9]*_)?a
+ *
+ * That means any sequence of lower-case or underscore characters can preceed an
+ * upper-case character. And any sequence of lower-case or upper case characters -
+ * followed by an underscore can preceed a lower-case character.
+ *
+ * Examples: (case sensitive mode)
+ * gAC matches getActionController
+ * gac matches get_action_controller
+ *
+ * It also implements the fully and first-letter-only case sensitivity.
+ */
+
+ QString keyRegExp;
+ bool first = true;
+ const QChar asterisk = '*';
+ const QChar question = '?';
+ const QLatin1String uppercaseWordFirst("(?<=\\b|[a-z0-9_])");
+ const QLatin1String lowercaseWordFirst("(?<=\\b|[A-Z0-9_])");
+ const QLatin1String uppercaseWordContinuation("[a-z0-9_]*");
+ const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?");
+ const QLatin1String upperSnakeWordContinuation("[A-Z0-9]*_");
+ keyRegExp += "(?:";
+ for (const QChar &c : pattern) {
+ if (!c.isLetter()) {
+ if (c == question)
+ keyRegExp += '.';
+ else if (c == asterisk)
+ keyRegExp += ".*";
+ else
+ keyRegExp += '(' + QRegularExpression::escape(c) + ')';
+ } else if (caseSensitivity == CaseSensitivity::CaseInsensitive ||
+ (caseSensitivity == CaseSensitivity::FirstLetterCaseSensitive && !first)) {
+
+ const QString upper = QRegularExpression::escape(c.toUpper());
+ const QString lower = QRegularExpression::escape(c.toLower());
+ keyRegExp += "(?:";
+ keyRegExp += first ? uppercaseWordFirst : uppercaseWordContinuation;
+ keyRegExp += '(' + upper + ')';
+ if (first) {
+ keyRegExp += '|' + lowercaseWordFirst + '(' + lower + ')';
+ } else {
+ keyRegExp += '|' + lowercaseWordContinuation + '(' + lower + ')';
+ keyRegExp += '|' + upperSnakeWordContinuation + '(' + upper + ')';
+ }
+ keyRegExp += ')';
+ } else {
+ if (!first) {
+ if (c.isUpper())
+ keyRegExp += uppercaseWordContinuation;
+ else
+ keyRegExp += lowercaseWordContinuation;
+ }
+ keyRegExp += QRegularExpression::escape(c);
+ }
+
+ first = false;
+ }
+ keyRegExp += ")|(" + QRegularExpression::escape(pattern) + ')';
+
+ return QRegularExpression(keyRegExp);
+}
+
+/*!
+ * \brief Returns a list of matched character positions and their matched lengths for the
+ * given regular expression \a match.
+ *
+ * The list is minimized by combining adjacent highlighting positions to a single position.
+ */
+CamelHumpMatcher::HighlightingPositions CamelHumpMatcher::highlightingPositions(
+ const QRegularExpressionMatch &match)
+{
+ HighlightingPositions result;
+
+ for (int i = 1, size = match.capturedTexts().size(); i < size; ++i) {
+ // skip unused positions, they can appear because upper- and lowercase
+ // checks for one character are done using two capture groups
+ if (match.capturedStart(i) < 0)
+ continue;
+
+ // check for possible highlighting continuation to keep the list minimal
+ if (!result.starts.isEmpty()
+ && (result.starts.last() + result.lengths.last() == match.capturedStart(i))) {
+ result.lengths.last() += match.capturedLength(i);
+ } else {
+ // no continuation, append as different chunk
+ result.starts.append(match.capturedStart(i));
+ result.lengths.append(match.capturedLength(i));
+ }
+ }
+
+ return result;
+}
diff --git a/src/libs/utils/camelhumpmatcher.h b/src/libs/utils/camelhumpmatcher.h
new file mode 100644
index 0000000000..8021c4ddf6
--- /dev/null
+++ b/src/libs/utils/camelhumpmatcher.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2017 BlackBerry Limited <qt@blackberry.com>
+** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "utils_global.h"
+
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+class QRegularExpression;
+class QRegularExpressionMatch;
+class QString;
+QT_END_NAMESPACE
+
+class QTCREATOR_UTILS_EXPORT CamelHumpMatcher
+{
+public:
+ enum class CaseSensitivity {
+ CaseInsensitive,
+ CaseSensitive,
+ FirstLetterCaseSensitive
+ };
+
+ class HighlightingPositions {
+ public:
+ QVector<int> starts;
+ QVector<int> lengths;
+ };
+
+ static QRegularExpression createCamelHumpRegExp(const QString &pattern,
+ CaseSensitivity caseSensitivity = CaseSensitivity::CaseInsensitive);
+ static HighlightingPositions highlightingPositions(const QRegularExpressionMatch &match);
+};
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index 60bf3ae4cc..1aee1cf908 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -57,6 +57,31 @@ public:
Q_GLOBAL_STATIC(SystemEnvironment, staticSystemEnvironment)
+static QMap<QString, QString>::iterator findKey(QMap<QString, QString> &input, Utils::OsType osType,
+ const QString &key)
+{
+ const Qt::CaseSensitivity casing
+ = (osType == Utils::OsTypeWindows) ? Qt::CaseInsensitive : Qt::CaseSensitive;
+ for (auto it = input.begin(); it != input.end(); ++it) {
+ if (key.compare(it.key(), casing) == 0)
+ return it;
+ }
+ return input.end();
+}
+
+static QMap<QString, QString>::const_iterator findKey(const QMap<QString, QString> &input,
+ Utils::OsType osType,
+ const QString &key)
+{
+ const Qt::CaseSensitivity casing
+ = (osType == Utils::OsTypeWindows) ? Qt::CaseInsensitive : Qt::CaseSensitive;
+ for (auto it = input.constBegin(); it != input.constEnd(); ++it) {
+ if (key.compare(it.key(), casing) == 0)
+ return it;
+ }
+ return input.constEnd();
+}
+
namespace Utils {
enum : char
@@ -88,14 +113,11 @@ QList<EnvironmentItem> EnvironmentItem::fromStringList(const QStringList &list)
QStringList EnvironmentItem::toStringList(const QList<EnvironmentItem> &list)
{
- QStringList result;
- for (const EnvironmentItem &item : list) {
+ return Utils::transform(list, [](const EnvironmentItem &item) {
if (item.operation == EnvironmentItem::Unset)
- result << QString(item.name);
- else
- result << QString(item.name + '=' + item.value);
- }
- return result;
+ return QString(item.name);
+ return QString(item.name + '=' + item.value);
+ });
}
static QString expand(const Environment *e, QString value)
@@ -207,10 +229,9 @@ Environment::Environment(const QStringList &env, OsType osType) : m_osType(osTyp
for (const QString &s : env) {
int i = s.indexOf('=', 1);
if (i >= 0) {
- if (m_osType == OsTypeWindows)
- m_values.insert(s.left(i).toUpper(), s.mid(i+1));
- else
- m_values.insert(s.left(i), s.mid(i+1));
+ const QString key = s.left(i);
+ const QString value = s.mid(i + 1);
+ set(key, value);
}
}
}
@@ -218,41 +239,40 @@ Environment::Environment(const QStringList &env, OsType osType) : m_osType(osTyp
QStringList Environment::toStringList() const
{
QStringList result;
- const QMap<QString, QString>::const_iterator end = m_values.constEnd();
- for (QMap<QString, QString>::const_iterator it = m_values.constBegin(); it != end; ++it) {
- QString entry = it.key();
- entry += '=';
- entry += it.value();
- result.push_back(entry);
- }
+ for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it)
+ result.append(it.key() + '=' + it.value());
return result;
}
QProcessEnvironment Environment::toProcessEnvironment() const
{
QProcessEnvironment result;
- const QMap<QString, QString>::const_iterator end = m_values.constEnd();
- for (QMap<QString, QString>::const_iterator it = m_values.constBegin(); it != end; ++it)
+ for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it)
result.insert(it.key(), it.value());
return result;
}
void Environment::set(const QString &key, const QString &value)
{
- m_values.insert(m_osType == OsTypeWindows ? key.toUpper() : key, value);
+ auto it = findKey(m_values, m_osType, key);
+ if (it == m_values.end())
+ m_values.insert(key, value);
+ else
+ it.value() = value;
}
void Environment::unset(const QString &key)
{
- m_values.remove(m_osType == OsTypeWindows ? key.toUpper() : key);
+ auto it = findKey(m_values, m_osType, key);
+ if (it != m_values.end())
+ m_values.erase(it);
}
void Environment::appendOrSet(const QString &key, const QString &value, const QString &sep)
{
- const QString &_key = m_osType == OsTypeWindows ? key.toUpper() : key;
- QMap<QString, QString>::iterator it = m_values.find(_key);
+ auto it = findKey(m_values, m_osType, key);
if (it == m_values.end()) {
- m_values.insert(_key, value);
+ m_values.insert(key, value);
} else {
// Append unless it is already there
const QString toAppend = sep + value;
@@ -263,10 +283,9 @@ void Environment::appendOrSet(const QString &key, const QString &value, const QS
void Environment::prependOrSet(const QString&key, const QString &value, const QString &sep)
{
- const QString &_key = m_osType == OsTypeWindows ? key.toUpper() : key;
- QMap<QString, QString>::iterator it = m_values.find(_key);
+ auto it = findKey(m_values, m_osType, key);
if (it == m_values.end()) {
- m_values.insert(_key, value);
+ m_values.insert(key, value);
} else {
// Prepend unless it is already there
const QString toPrepend = value + sep;
@@ -278,7 +297,7 @@ void Environment::prependOrSet(const QString&key, const QString &value, const QS
void Environment::appendOrSetPath(const QString &value)
{
appendOrSet("PATH", QDir::toNativeSeparators(value),
- QString(OsSpecificAspects(m_osType).pathListSeparator()));
+ QString(OsSpecificAspects(m_osType).pathListSeparator()));
}
void Environment::prependOrSetPath(const QString &value)
@@ -435,13 +454,14 @@ FileName Environment::searchInPath(const QString &executable,
QStringList Environment::path() const
{
- return m_values.value("PATH")
+ return value("PATH")
.split(OsSpecificAspects(m_osType).pathListSeparator(), QString::SkipEmptyParts);
}
QString Environment::value(const QString &key) const
{
- return m_values.value(key);
+ const auto it = findKey(m_values, m_osType, key);
+ return it != m_values.end() ? it.value() : QString();
}
QString Environment::key(Environment::const_iterator it) const
@@ -563,7 +583,7 @@ QString Environment::expandVariables(const QString &input) const
for (int vStart = -1, i = 0; i < result.length(); ) {
if (result.at(i++) == '%') {
if (vStart > 0) {
- const_iterator it = m_values.constFind(result.mid(vStart, i - vStart - 1).toUpper());
+ const_iterator it = findKey(m_values, m_osType, result.mid(vStart, i - vStart - 1));
if (it != m_values.constEnd()) {
result.replace(vStart - 1, i - vStart + 1, *it);
i = vStart - 1 + it->length();
diff --git a/src/libs/utils/fancylineedit.cpp b/src/libs/utils/fancylineedit.cpp
index 20a2673352..17455f45f1 100644
--- a/src/libs/utils/fancylineedit.cpp
+++ b/src/libs/utils/fancylineedit.cpp
@@ -38,6 +38,7 @@
#include <QStylePainter>
#include <QPropertyAnimation>
#include <QStyle>
+#include <QWindow>
/*!
\class Utils::FancyLineEdit
@@ -91,7 +92,6 @@ public:
HistoryCompleter *m_historyCompleter = 0;
FancyLineEdit::ValidationFunction m_validationFunction = &FancyLineEdit::validateWithValidator;
QString m_oldText;
- QPixmap m_pixmap[2];
QMenu *m_menu[2];
FancyLineEdit::State m_state = FancyLineEdit::Invalid;
bool m_menuTabFocusTrigger[2];
@@ -256,17 +256,17 @@ void FancyLineEdit::resizeEvent(QResizeEvent *)
updateButtonPositions();
}
-void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
+void FancyLineEdit::setButtonIcon(Side side, const QIcon &icon)
{
- d->m_iconbutton[side]->setPixmap(buttonPixmap);
+ d->m_iconbutton[side]->setIcon(icon);
updateMargins();
updateButtonPositions();
update();
}
-QPixmap FancyLineEdit::buttonPixmap(Side side) const
+QIcon FancyLineEdit::buttonIcon(Side side) const
{
- return d->m_pixmap[side];
+ return d->m_iconbutton[side]->icon();
}
void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
@@ -360,9 +360,9 @@ void FancyLineEdit::setFiltering(bool on)
QLatin1String("edit-clear-locationbar-rtl") :
QLatin1String("edit-clear-locationbar-ltr"),
QIcon::fromTheme(QLatin1String("edit-clear"),
- Icons::EDIT_CLEAR.pixmap()));
+ Icons::EDIT_CLEAR.icon()));
- setButtonPixmap(Right, icon.pixmap(16));
+ setButtonIcon(Right, icon);
setButtonVisible(Right, true);
setPlaceholderText(tr("Filter"));
setButtonToolTip(Right, tr("Clear text"));
@@ -517,15 +517,16 @@ IconButton::IconButton(QWidget *parent)
void IconButton::paintEvent(QPaintEvent *)
{
- const qreal pixmapRatio = m_pixmap.devicePixelRatio();
+ QWindow *window = this->window()->windowHandle();
+ const QPixmap iconPixmap = icon().pixmap(window, sizeHint());
QStylePainter painter(this);
- QRect pixmapRect = QRect(0, 0, m_pixmap.width()/pixmapRatio, m_pixmap.height()/pixmapRatio);
+ QRect pixmapRect(QPoint(), iconPixmap.size() / window->devicePixelRatio());
pixmapRect.moveCenter(rect().center());
if (m_autoHide)
painter.setOpacity(m_iconOpacity);
- painter.drawPixmap(pixmapRect, m_pixmap);
+ painter.drawPixmap(pixmapRect, iconPixmap);
if (hasFocus()) {
QStyleOptionFocusRect focusOption;
@@ -550,8 +551,8 @@ void IconButton::animateShow(bool visible)
QSize IconButton::sizeHint() const
{
- const qreal pixmapRatio = m_pixmap.devicePixelRatio();
- return QSize(m_pixmap.width()/pixmapRatio, m_pixmap.height()/pixmapRatio);
+ QWindow *window = this->window()->windowHandle();
+ return icon().actualSize(window, QSize(32, 16)); // Find flags icon can be wider than 16px
}
void IconButton::keyPressEvent(QKeyEvent *ke)
diff --git a/src/libs/utils/fancylineedit.h b/src/libs/utils/fancylineedit.h
index 9df78961bb..ba3918ab8f 100644
--- a/src/libs/utils/fancylineedit.h
+++ b/src/libs/utils/fancylineedit.h
@@ -45,12 +45,9 @@ class QTCREATOR_UTILS_EXPORT IconButton: public QAbstractButton
Q_OBJECT
Q_PROPERTY(float iconOpacity READ iconOpacity WRITE setIconOpacity)
Q_PROPERTY(bool autoHide READ hasAutoHide WRITE setAutoHide)
- Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap)
public:
explicit IconButton(QWidget *parent = 0);
void paintEvent(QPaintEvent *event);
- void setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; update(); }
- QPixmap pixmap() const { return m_pixmap; }
float iconOpacity() { return m_iconOpacity; }
void setIconOpacity(float value) { m_iconOpacity = value; update(); }
void animateShow(bool visible);
@@ -67,7 +64,7 @@ protected:
private:
float m_iconOpacity;
bool m_autoHide;
- QPixmap m_pixmap;
+ QIcon m_icon;
};
class QTCREATOR_UTILS_EXPORT FancyLineEdit : public CompletingLineEdit
@@ -86,8 +83,8 @@ public:
explicit FancyLineEdit(QWidget *parent = 0);
~FancyLineEdit();
- QPixmap buttonPixmap(Side side) const;
- void setButtonPixmap(Side side, const QPixmap &pixmap);
+ QIcon buttonIcon(Side side) const;
+ void setButtonIcon(Side side, const QIcon &icon);
QMenu *buttonMenu(Side side) const;
void setButtonMenu(Side side, QMenu *menu);
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index 338ae657d8..160d1b9dea 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -238,7 +238,7 @@ FileName FileUtils::resolveSymlinks(const FileName &path)
*/
FileName FileUtils::canonicalPath(const FileName &path)
{
- const QString result = QFileInfo(path.toString()).canonicalFilePath();
+ const QString result = path.toFileInfo().canonicalFilePath();
if (result.isEmpty())
return path;
return FileName::fromString(result);
@@ -592,7 +592,6 @@ QString FileName::fileName(int pathComponents) const
if (pathComponents < 0)
return *this;
const QChar slash = QLatin1Char('/');
- QTC_CHECK(!endsWith(slash));
int i = lastIndexOf(slash);
if (pathComponents == 0 || i == -1)
return mid(i + 1);
diff --git a/src/libs/utils/highlightingitemdelegate.cpp b/src/libs/utils/highlightingitemdelegate.cpp
index fe2525122c..c9bb43eb94 100644
--- a/src/libs/utils/highlightingitemdelegate.cpp
+++ b/src/libs/utils/highlightingitemdelegate.cpp
@@ -155,28 +155,37 @@ void HighlightingItemDelegate::drawText(QPainter *painter,
if (index.model()->hasChildren(index))
text += " (" + QString::number(index.model()->rowCount(index)) + ')';
- int searchTermStart = index.model()->data(index, int(HighlightingItemRole::StartColumn)).toInt();
- int searchTermLength = index.model()->data(index, int(HighlightingItemRole::Length)).toInt();
- if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) {
+ QVector<int> searchTermStarts =
+ index.model()->data(index, int(HighlightingItemRole::StartColumn)).value<QVector<int>>();
+ QVector<int> searchTermLengths =
+ index.model()->data(index, int(HighlightingItemRole::Length)).value<QVector<int>>();
+
+ if (searchTermStarts.isEmpty()) {
drawDisplay(painter, option, rect, text.replace('\t', m_tabString), {});
return;
}
// replace tabs with searchTerm bookkeeping
- int searchTermEnd = searchTermStart + searchTermLength;
const int tabDiff = m_tabString.size() - 1;
for (int i = 0; i < text.length(); i++) {
- if (text.at(i) == '\t') {
- text.replace(i, 1, m_tabString);
- if (i < searchTermStart) {
- searchTermStart += tabDiff;
- searchTermEnd += tabDiff;
- } else if (i < searchTermEnd) {
- searchTermEnd += tabDiff;
- searchTermLength += tabDiff;
- }
- i += tabDiff;
+ if (text.at(i) != '\t')
+ continue;
+
+ text.replace(i, 1, m_tabString);
+
+ // adjust highlighting length if tab is highlighted
+ for (int j = 0; j < searchTermStarts.size(); ++j) {
+ if (i >= searchTermStarts.at(j) && i < searchTermStarts.at(j) + searchTermLengths.at(j))
+ searchTermLengths[j] += tabDiff;
}
+
+ // adjust all following highlighting starts
+ for (int j = 0; j < searchTermStarts.size(); ++j) {
+ if (searchTermStarts.at(j) > i)
+ searchTermStarts[j] += tabDiff;
+ }
+
+ i += tabDiff;
}
const QColor highlightForeground =
@@ -187,7 +196,11 @@ void HighlightingItemDelegate::drawText(QPainter *painter,
highlightFormat.setForeground(highlightForeground);
highlightFormat.setBackground(highlightBackground);
- drawDisplay(painter, option, rect, text, {{searchTermStart, searchTermLength, highlightFormat}});
+ QVector<QTextLayout::FormatRange> formats;
+ for (int i = 0, size = searchTermStarts.size(); i < size; ++i)
+ formats.append({searchTermStarts.at(i), searchTermLengths.at(i), highlightFormat});
+
+ drawDisplay(painter, option, rect, text, formats);
}
// copied from QItemDelegate for drawDisplay
diff --git a/src/libs/utils/images/empty16.png b/src/libs/utils/images/empty16.png
new file mode 100644
index 0000000000..4d7beb8065
--- /dev/null
+++ b/src/libs/utils/images/empty16.png
Binary files differ
diff --git a/src/libs/utils/images/magnifier.png b/src/libs/utils/images/magnifier.png
index 6a7af805b8..692a32d9a3 100644
--- a/src/libs/utils/images/magnifier.png
+++ b/src/libs/utils/images/magnifier.png
Binary files differ
diff --git a/src/libs/utils/images/magnifier@2x.png b/src/libs/utils/images/magnifier@2x.png
index f6fce89a3c..60f93e10cb 100644
--- a/src/libs/utils/images/magnifier@2x.png
+++ b/src/libs/utils/images/magnifier@2x.png
Binary files differ
diff --git a/src/libs/utils/optional.h b/src/libs/utils/optional.h
index 1960297de4..e4f943259f 100644
--- a/src/libs/utils/optional.h
+++ b/src/libs/utils/optional.h
@@ -41,6 +41,8 @@ namespace Utils {
using std::experimental::optional;
// --> Utils::nullopt
using std::experimental::nullopt;
+// --> Utils::in_place
+using std::experimental::in_place;
// TODO: make_optional is a copy, since there is no sensible way to import functions in C++
template <class T>
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index a5f9688ace..ee5165e70a 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -51,11 +51,11 @@
static QString appBundleExpandedPath(const QString &path)
{
- if (Utils::HostOsInfo::hostOs() == Utils::OsTypeMac && path.endsWith(QLatin1String(".app"))) {
+ if (Utils::HostOsInfo::hostOs() == Utils::OsTypeMac && path.endsWith(".app")) {
// possibly expand to Foo.app/Contents/MacOS/Foo
QFileInfo info(path);
if (info.isDir()) {
- QString exePath = path + QLatin1String("/Contents/MacOS/") + info.completeBaseName();
+ QString exePath = path + "/Contents/MacOS/" + info.completeBaseName();
if (QFileInfo::exists(exePath))
return exePath;
}
@@ -110,16 +110,16 @@ bool BinaryVersionToolTipEventFilter::eventFilter(QObject *o, QEvent *e)
const QString version = BinaryVersionToolTipEventFilter::toolVersion(QDir::cleanPath(binary), m_arguments);
if (!version.isEmpty()) {
// Concatenate tooltips.
- QString tooltip = QLatin1String("<html><head/><body>");
+ QString tooltip = "<html><head/><body>";
const QString defaultValue = defaultToolTip();
if (!defaultValue.isEmpty()) {
- tooltip += QLatin1String("<p>");
+ tooltip += "<p>";
tooltip += defaultValue;
- tooltip += QLatin1String("</p>");
+ tooltip += "</p>";
}
- tooltip += QLatin1String("<pre>");
+ tooltip += "<pre>";
tooltip += version;
- tooltip += QLatin1String("</pre><body></html>");
+ tooltip += "</pre><body></html>";
le->setToolTip(tooltip);
}
}
@@ -150,7 +150,7 @@ private:
virtual QString defaultToolTip() const
{ return m_pathChooser->errorMessage(); }
- const PathChooser *m_pathChooser;
+ const PathChooser *m_pathChooser = nullptr;
};
// ------------------ PathChooserPrivate
@@ -162,8 +162,8 @@ public:
QString expandedPath(const QString &path) const;
- QHBoxLayout *m_hLayout;
- FancyLineEdit *m_lineEdit;
+ QHBoxLayout *m_hLayout = nullptr;
+ FancyLineEdit *m_lineEdit = nullptr;
PathChooser::Kind m_acceptingKind;
QString m_dialogTitleOverride;
@@ -171,15 +171,14 @@ public:
QString m_initialBrowsePathOverride;
QString m_baseDirectory;
Environment m_environment;
- BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter;
+ BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter = nullptr;
QList<QAbstractButton *> m_buttons;
};
PathChooserPrivate::PathChooserPrivate() :
m_hLayout(new QHBoxLayout),
m_lineEdit(new FancyLineEdit),
- m_acceptingKind(PathChooser::ExistingDirectory),
- m_binaryVersionToolTipEventFilter(0)
+ m_acceptingKind(PathChooser::ExistingDirectory)
{
}
@@ -194,7 +193,7 @@ QString PathChooserPrivate::expandedPath(const QString &input) const
switch (m_acceptingKind) {
case PathChooser::Command:
case PathChooser::ExistingCommand: {
- const FileName expanded = m_environment.searchInPath(path, QStringList(m_baseDirectory));
+ const FileName expanded = m_environment.searchInPath(path, {m_baseDirectory});
return expanded.isEmpty() ? path : expanded.toString();
}
case PathChooser::Any:
@@ -204,7 +203,7 @@ QString PathChooserPrivate::expandedPath(const QString &input) const
case PathChooser::File:
case PathChooser::SaveFile:
if (!m_baseDirectory.isEmpty() && QFileInfo(path).isRelative())
- return QFileInfo(m_baseDirectory + QLatin1Char('/') + path).absoluteFilePath();
+ return QFileInfo(m_baseDirectory + '/' + path).absoluteFilePath();
break;
}
return path;
@@ -337,7 +336,7 @@ QString PathChooser::expandedDirectory(const QString &input, const Environment &
if (path.isEmpty())
return path;
if (!baseDir.isEmpty() && QFileInfo(path).isRelative())
- return QFileInfo(baseDir + QLatin1Char('/') + path).absoluteFilePath();
+ return QFileInfo(baseDir + '/' + path).absoluteFilePath();
return path;
}
@@ -369,7 +368,8 @@ bool PathChooser::isReadOnly() const
void PathChooser::setReadOnly(bool b)
{
d->m_lineEdit->setReadOnly(b);
- foreach (QAbstractButton *button, d->m_buttons)
+ const auto buttons = d->m_buttons;
+ for (QAbstractButton *button : buttons)
button->setEnabled(!b);
}
@@ -663,7 +663,7 @@ FancyLineEdit *PathChooser::lineEdit() const
{
// HACK: Make it work with HistoryCompleter.
if (d->m_lineEdit->objectName().isEmpty())
- d->m_lineEdit->setObjectName(objectName() + QLatin1String("LineEdit"));
+ d->m_lineEdit->setObjectName(objectName() + "LineEdit");
return d->m_lineEdit;
}
@@ -695,7 +695,7 @@ void PathChooser::setCommandVersionArguments(const QStringList &arguments)
if (arguments.isEmpty()) {
if (d->m_binaryVersionToolTipEventFilter) {
delete d->m_binaryVersionToolTipEventFilter;
- d->m_binaryVersionToolTipEventFilter = 0;
+ d->m_binaryVersionToolTipEventFilter = nullptr;
}
} else {
if (!d->m_binaryVersionToolTipEventFilter)
diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h
index 17b572310d..94f4a19b49 100644
--- a/src/libs/utils/pathchooser.h
+++ b/src/libs/utils/pathchooser.h
@@ -62,7 +62,7 @@ class QTCREATOR_UTILS_EXPORT PathChooser : public QWidget
public:
static QString browseButtonLabel();
- explicit PathChooser(QWidget *parent = 0);
+ explicit PathChooser(QWidget *parent = nullptr);
virtual ~PathChooser();
enum Kind {
@@ -172,7 +172,7 @@ public slots:
void setOkColor(const QColor &okColor);
private:
- PathChooserPrivate *d;
+ PathChooserPrivate *d = nullptr;
static AboutToShowContextMenuHandler s_aboutToShowContextMenuHandler;
};
diff --git a/src/libs/utils/persistentsettings.h b/src/libs/utils/persistentsettings.h
index 4fba07ae61..3ea7fac904 100644
--- a/src/libs/utils/persistentsettings.h
+++ b/src/libs/utils/persistentsettings.h
@@ -26,6 +26,7 @@
#pragma once
#include "fileutils.h"
+#include "utils_global.h"
#include <QVariant>
diff --git a/src/libs/utils/progressindicator.cpp b/src/libs/utils/progressindicator.cpp
index 009d57c009..4efd987137 100644
--- a/src/libs/utils/progressindicator.cpp
+++ b/src/libs/utils/progressindicator.cpp
@@ -33,51 +33,114 @@
#include <QPainter>
#include <QPixmap>
-using namespace Utils;
+namespace {
-ProgressIndicator::ProgressIndicator(IndicatorSize size, QWidget *parent)
- : QWidget(parent),
- m_rotation(0)
-{
- setAttribute(Qt::WA_TransparentForMouseEvents);
- m_timer.setSingleShot(false);
- connect(&m_timer, &QTimer::timeout, this, &ProgressIndicator::step);
- setIndicatorSize(size);
-}
-
-static QString imageFileNameForIndicatorSize(ProgressIndicator::IndicatorSize size)
+static QString imageFileNameForIndicatorSize(Utils::ProgressIndicatorSize size)
{
switch (size) {
- case ProgressIndicator::Large:
- return QLatin1String(":/utils/images/progressindicator_big.png");
- case ProgressIndicator::Medium:
- return QLatin1String(":/utils/images/progressindicator_medium.png");
- case ProgressIndicator::Small:
- default:
+ case Utils::ProgressIndicatorSize::Large:
+ return QLatin1String(":/utils/images/progressindicator_big.png");
+ case Utils::ProgressIndicatorSize::Medium:
+ return QLatin1String(":/utils/images/progressindicator_medium.png");
+ case Utils::ProgressIndicatorSize::Small:
+ default:
return QLatin1String(":/utils/images/progressindicator_small.png");
}
}
-void ProgressIndicator::setIndicatorSize(ProgressIndicator::IndicatorSize size)
+} // namespace
+
+namespace Utils {
+
+ProgressIndicatorPainter::ProgressIndicatorPainter(ProgressIndicatorSize size)
+{
+ m_timer.setSingleShot(false);
+ QObject::connect(&m_timer, &QTimer::timeout, [this]() {
+ nextAnimationStep();
+ if (m_callback)
+ m_callback();
+ });
+
+ setIndicatorSize(size);
+}
+
+void ProgressIndicatorPainter::setIndicatorSize(ProgressIndicatorSize size)
{
m_size = size;
- m_rotationStep = size == Small ? 45 : 30;
- m_timer.setInterval(size == Small ? 100 : 80);
+ m_rotationStep = size == ProgressIndicatorSize::Small ? 45 : 30;
+ m_timer.setInterval(size == ProgressIndicatorSize::Small ? 100 : 80);
m_pixmap = Icon({{imageFileNameForIndicatorSize(size),
Theme::PanelTextColorMid}}, Icon::Tint).pixmap();
- updateGeometry();
}
-ProgressIndicator::IndicatorSize ProgressIndicator::indicatorSize() const
+ProgressIndicatorSize ProgressIndicatorPainter::indicatorSize() const
{
return m_size;
}
-QSize ProgressIndicator::sizeHint() const
+void ProgressIndicatorPainter::setUpdateCallback(const UpdateCallback &cb)
+{
+ m_callback = cb;
+}
+
+QSize ProgressIndicatorPainter::size() const
{
return m_pixmap.size() / m_pixmap.devicePixelRatio();
}
+// Paint indicator centered on the rect
+void ProgressIndicatorPainter::paint(QPainter &painter, const QRect &rect) const
+{
+ painter.save();
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+ QPoint translate(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
+ QTransform t;
+ t.translate(translate.x(), translate.y());
+ t.rotate(m_rotation);
+ t.translate(-translate.x(), -translate.y());
+ painter.setTransform(t);
+ QSize pixmapUserSize(m_pixmap.size() / m_pixmap.devicePixelRatio());
+ painter.drawPixmap(QPoint(rect.x() + ((rect.width() - pixmapUserSize.width()) / 2),
+ rect.y() + ((rect.height() - pixmapUserSize.height()) / 2)),
+ m_pixmap);
+ painter.restore();
+}
+
+void ProgressIndicatorPainter::startAnimation()
+{
+ QTC_ASSERT(m_callback, return);
+ m_timer.start();
+}
+
+void ProgressIndicatorPainter::stopAnimation()
+{
+ m_timer.stop();
+}
+
+void Utils::ProgressIndicatorPainter::nextAnimationStep()
+{
+ m_rotation = (m_rotation + m_rotationStep + 360) % 360;
+}
+
+ProgressIndicator::ProgressIndicator(ProgressIndicatorSize size, QWidget *parent)
+ : QWidget(parent), m_paint(size)
+{
+ setAttribute(Qt::WA_TransparentForMouseEvents);
+ m_paint.setUpdateCallback([this]() { update(); });
+ updateGeometry();
+}
+
+void ProgressIndicator::setIndicatorSize(ProgressIndicatorSize size)
+{
+ m_paint.setIndicatorSize(size);
+ updateGeometry();
+}
+
+QSize ProgressIndicator::sizeHint() const
+{
+ return m_paint.size();
+}
+
void ProgressIndicator::attachToWidget(QWidget *parent)
{
if (parentWidget())
@@ -91,27 +154,17 @@ void ProgressIndicator::attachToWidget(QWidget *parent)
void ProgressIndicator::paintEvent(QPaintEvent *)
{
QPainter p(this);
- p.setRenderHint(QPainter::SmoothPixmapTransform);
- QPoint translate(rect().width() / 2, rect().height() / 2);
- QTransform t;
- t.translate(translate.x(), translate.y());
- t.rotate(m_rotation);
- t.translate(-translate.x(), -translate.y());
- p.setTransform(t);
- QSize pixmapUserSize(m_pixmap.size() / m_pixmap.devicePixelRatio());
- p.drawPixmap(QPoint((rect().width() - pixmapUserSize.width()) / 2,
- (rect().height() - pixmapUserSize.height()) / 2),
- m_pixmap);
+ m_paint.paint(p, rect());
}
void ProgressIndicator::showEvent(QShowEvent *)
{
- m_timer.start();
+ m_paint.startAnimation();
}
void ProgressIndicator::hideEvent(QHideEvent *)
{
- m_timer.stop();
+ m_paint.stopAnimation();
}
bool ProgressIndicator::eventFilter(QObject *obj, QEvent *ev)
@@ -122,15 +175,10 @@ bool ProgressIndicator::eventFilter(QObject *obj, QEvent *ev)
return QWidget::eventFilter(obj, ev);
}
-void ProgressIndicator::step()
-{
- m_rotation = (m_rotation + m_rotationStep + 360) % 360;
- update();
-}
-
void ProgressIndicator::resizeToParent()
{
QTC_ASSERT(parentWidget(), return);
setGeometry(QRect(QPoint(0, 0), parentWidget()->size()));
}
+} // namespace Utils
diff --git a/src/libs/utils/progressindicator.h b/src/libs/utils/progressindicator.h
index 4fee8b1956..6713709c1b 100644
--- a/src/libs/utils/progressindicator.h
+++ b/src/libs/utils/progressindicator.h
@@ -30,44 +30,74 @@
#include <QTimer>
#include <QWidget>
+#include <functional>
+#include <memory>
+
namespace Utils {
namespace Internal { class ProgressIndicatorPrivate; }
+enum class ProgressIndicatorSize
+{
+ Small,
+ Medium,
+ Large
+};
+
+class QTCREATOR_UTILS_EXPORT ProgressIndicatorPainter
+{
+public:
+ using UpdateCallback = std::function<void()>;
+
+ ProgressIndicatorPainter(ProgressIndicatorSize size);
+ virtual ~ProgressIndicatorPainter() = default;
+
+ virtual void setIndicatorSize(ProgressIndicatorSize size);
+ ProgressIndicatorSize indicatorSize() const;
+
+ void setUpdateCallback(const UpdateCallback &cb);
+
+ QSize size() const;
+
+ void paint(QPainter &painter, const QRect &rect) const;
+
+ void startAnimation();
+ void stopAnimation();
+
+protected:
+ void nextAnimationStep();
+
+private:
+ ProgressIndicatorSize m_size = ProgressIndicatorSize::Small;
+ int m_rotationStep = 45;
+ int m_rotation = 0;
+ QTimer m_timer;
+ QPixmap m_pixmap;
+ UpdateCallback m_callback;
+};
+
class QTCREATOR_UTILS_EXPORT ProgressIndicator : public QWidget
{
Q_OBJECT
public:
- enum IndicatorSize {
- Small,
- Medium,
- Large
- };
-
- explicit ProgressIndicator(IndicatorSize size, QWidget *parent = 0);
+ explicit ProgressIndicator(ProgressIndicatorSize size, QWidget *parent = nullptr);
- void setIndicatorSize(IndicatorSize size);
- IndicatorSize indicatorSize() const;
+ void setIndicatorSize(ProgressIndicatorSize size);
- QSize sizeHint() const;
+ QSize sizeHint() const final;
void attachToWidget(QWidget *parent);
protected:
- void paintEvent(QPaintEvent *);
- void showEvent(QShowEvent *);
- void hideEvent(QHideEvent *);
- bool eventFilter(QObject *obj, QEvent *ev);
+ void paintEvent(QPaintEvent *) final;
+ void showEvent(QShowEvent *) final;
+ void hideEvent(QHideEvent *) final;
+ bool eventFilter(QObject *obj, QEvent *ev) final;
private:
- void step();
void resizeToParent();
- ProgressIndicator::IndicatorSize m_size;
- int m_rotationStep;
- int m_rotation;
- QTimer m_timer;
- QPixmap m_pixmap;
+ ProgressIndicatorPainter m_paint;
};
} // Utils
diff --git a/src/libs/utils/reloadpromptutils.cpp b/src/libs/utils/reloadpromptutils.cpp
index 798a4876a7..2270053be0 100644
--- a/src/libs/utils/reloadpromptutils.cpp
+++ b/src/libs/utils/reloadpromptutils.cpp
@@ -44,11 +44,11 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
if (modified) {
msg = QCoreApplication::translate("Utils::reloadPrompt",
- "The unsaved file <i>%1</i> has changed outside Qt Creator. "
+ "The unsaved file <i>%1</i> has been changed on disk. "
"Do you want to reload it and discard your changes?");
} else {
msg = QCoreApplication::translate("Utils::reloadPrompt",
- "The file <i>%1</i> has changed outside Qt Creator. Do you want to reload it?");
+ "The file <i>%1</i> has been changed on disk. Do you want to reload it?");
}
msg = msg.arg(fileName.fileName());
return reloadPrompt(title, msg, fileName.toUserOutput(), enableDiffOption, parent);
@@ -102,16 +102,16 @@ QTCREATOR_UTILS_EXPORT FileDeletedPromptAnswer
fileDeletedPrompt(const QString &fileName, bool triggerExternally, QWidget *parent)
{
const QString title = QCoreApplication::translate("Utils::fileDeletedPrompt",
- "File has been removed");
+ "File Has Been Removed");
QString msg;
if (triggerExternally) {
msg = QCoreApplication::translate("Utils::fileDeletedPrompt",
- "The file %1 has been removed outside Qt Creator. "
+ "The file %1 has been removed from disk. "
"Do you want to save it under a different name, or close "
"the editor?").arg(QDir::toNativeSeparators(fileName));
} else {
msg = QCoreApplication::translate("Utils::fileDeletedPrompt",
- "The file %1 was removed. "
+ "The file %1 has been removed from disk. "
"Do you want to save it under a different name, or close "
"the editor?").arg(QDir::toNativeSeparators(fileName));
}
diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp
index 59c7f97fd0..2c0cdee733 100644
--- a/src/libs/utils/shellcommand.cpp
+++ b/src/libs/utils/shellcommand.cpp
@@ -42,6 +42,8 @@
#include <QThread>
#include <QVariant>
+#include <numeric>
+
/*!
\fn void Utils::ProgressParser::parseProgress(const QString &text)
@@ -241,6 +243,14 @@ void ShellCommand::addTask(QFuture<void> &future)
Q_UNUSED(future);
}
+int ShellCommand::timeoutS() const
+{
+ return std::accumulate(d->m_jobs.cbegin(), d->m_jobs.cend(), 0,
+ [](int sum, const Internal::ShellCommandPrivate::Job &job) {
+ return sum + job.timeoutS;
+ });
+}
+
QString ShellCommand::workDirectory(const QString &wd) const
{
if (!wd.isEmpty())
@@ -413,6 +423,8 @@ SynchronousProcessResponse ShellCommand::runSynchronous(const FileName &binary,
connect(&process, &Utils::SynchronousProcess::stdErrBuffered,
this, [this, proxy](const QString &text)
{
+ if (d->m_progressParser)
+ d->m_progressParser->parseProgress(text);
if (!(d->m_flags & SuppressStdErr))
proxy->appendError(text);
if (d->m_progressiveOutput)
@@ -474,6 +486,11 @@ void ShellCommand::setProgressParser(ProgressParser *parser)
d->m_progressParser = parser;
}
+bool ShellCommand::hasProgressParser() const
+{
+ return d->m_progressParser;
+}
+
void ShellCommand::setProgressiveOutput(bool progressive)
{
d->m_progressiveOutput = progressive;
diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h
index ce5957c40a..c8bf38af11 100644
--- a/src/libs/utils/shellcommand.h
+++ b/src/libs/utils/shellcommand.h
@@ -136,6 +136,7 @@ public:
void setCodec(QTextCodec *codec);
void setProgressParser(ProgressParser *parser);
+ bool hasProgressParser() const;
void setProgressiveOutput(bool progressive);
void setOutputProxyFactory(const std::function<OutputProxy *()> &factory);
@@ -161,6 +162,7 @@ signals:
protected:
virtual unsigned processFlags() const;
virtual void addTask(QFuture<void> &future);
+ int timeoutS() const;
QString workDirectory(const QString &wd) const;
private:
diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h
index eb30158691..5b30662592 100644
--- a/src/libs/utils/smallstring.h
+++ b/src/libs/utils/smallstring.h
@@ -143,6 +143,7 @@ public:
}
BasicSmallString(std::initializer_list<Utils::SmallStringView> list)
+ : m_data(Internal::StringDataLayout<Size>())
{
std::size_t size = std::accumulate(list.begin(),
list.end(),
@@ -206,7 +207,9 @@ public:
BasicSmallString clonedString(m_data);
if (Q_UNLIKELY(hasAllocatedMemory()))
- new (&clonedString) BasicSmallString{m_data.allocated.data.pointer, m_data.allocated.data.size};
+ new (&clonedString) BasicSmallString{m_data.allocated.data.pointer,
+ m_data.allocated.data.size,
+ m_data.allocated.data.capacity};
return clonedString;
}
@@ -229,16 +232,23 @@ public:
return QString::fromUtf8(data(), int(size()));
}
+ SmallStringView toView() const
+ {
+ return SmallStringView(data(), size());
+ }
+
operator SmallStringView() const
{
return SmallStringView(data(), size());
}
+ explicit
operator QString() const
{
return toQString();
}
+ explicit
operator std::string() const
{
return std::string(data(), size());
@@ -255,8 +265,10 @@ public:
if (fitsNotInCapacity(newCapacity)) {
if (Q_UNLIKELY(hasAllocatedMemory())) {
m_data.allocated.data.pointer = Memory::reallocate(m_data.allocated.data.pointer,
- newCapacity + 1);
+ newCapacity + 1);
m_data.allocated.data.capacity = newCapacity;
+ } else if (newCapacity <= shortStringCapacity()) {
+ new (this) BasicSmallString{m_data.allocated.data.pointer, m_data.allocated.data.size};
} else {
const size_type oldSize = size();
newCapacity = std::max(newCapacity, oldSize);
@@ -310,22 +322,22 @@ public:
reverse_iterator rbegin() noexcept
{
- return reverse_iterator(end() - static_cast<std::size_t>(1));
+ return reverse_iterator(end());
}
reverse_iterator rend() noexcept
{
- return reverse_iterator(begin() - static_cast<std::size_t>(1));
+ return reverse_iterator(begin());
}
const_reverse_iterator rbegin() const noexcept
{
- return const_reverse_iterator(end() - static_cast<std::size_t>(1));
+ return const_reverse_iterator(end());
}
const_reverse_iterator rend() const noexcept
{
- return const_reverse_iterator(begin() - static_cast<std::size_t>(1));
+ return const_reverse_iterator(begin());
}
const_iterator begin() const noexcept
@@ -362,19 +374,17 @@ public:
return BasicSmallString(utf8ByteArray.constData(), uint(utf8ByteArray.size()));
}
+ // precondition: has to be null terminated
bool contains(SmallStringView subStringToSearch) const
{
- auto found = std::search(begin(),
- end(),
- subStringToSearch.begin(),
- subStringToSearch.end());
+ const char *found = std::strstr(data(), subStringToSearch.data());
- return found != end();
+ return found != nullptr;
}
bool contains(char characterToSearch) const
{
- auto found = std::strchr(data(), characterToSearch);
+ auto found = std::memchr(data(), characterToSearch, size());
return found != nullptr;
}
@@ -532,131 +542,93 @@ public:
}
static
- BasicSmallString join(std::initializer_list<BasicSmallString> list)
+ BasicSmallString join(std::initializer_list<SmallStringView> list)
{
size_type totalSize = 0;
- for (const BasicSmallString &string : list)
+ for (SmallStringView string : list)
totalSize += string.size();
BasicSmallString joinedString;
joinedString.reserve(totalSize);
- for (const BasicSmallString &string : list)
+ for (SmallStringView string : list)
joinedString.append(string);
return joinedString;
}
- char &operator[](std::size_t index)
- {
- return *(data() + index);
- }
-
- char operator[](std::size_t index) const
+ static
+ BasicSmallString number(int number)
{
- return *(data() + index);
- }
+ char buffer[12];
+ std::size_t size = itoa(number, buffer, 10);
- template<size_type ArraySize>
- friend bool operator==(const BasicSmallString& first, const char(&second)[ArraySize]) noexcept
- {
- return first == SmallStringView(second);
+ return BasicSmallString(buffer, size);
}
- template<size_type ArraySize>
- friend bool operator==(const char(&first)[ArraySize], const BasicSmallString& second) noexcept
+ static
+ BasicSmallString number(long long int number)
{
- return second == first;
- }
+ char buffer[22];
+ std::size_t size = itoa(number, buffer, 10);
- template<typename Type,
- typename = std::enable_if_t<std::is_pointer<Type>::value>
- >
- friend bool operator==(const BasicSmallString& first, Type second) noexcept
- {
- return first == SmallStringView(second);
+ return BasicSmallString(buffer, size);
}
- template<typename Type,
- typename = std::enable_if_t<std::is_pointer<Type>::value>
- >
- friend bool operator==(Type first, const BasicSmallString& second) noexcept
+ static
+ BasicSmallString number(double number)
{
- return second == first;
+ return std::to_string(number);
}
- friend bool operator==(const BasicSmallString& first, const SmallStringView& second) noexcept
+ char &operator[](std::size_t index)
{
- return first.size() == second.size()
- && std::memcmp(first.data(), second.data(), first.size()) == 0;
+ return *(data() + index);
}
- friend bool operator==(const SmallStringView& first, const BasicSmallString& second) noexcept
+ char operator[](std::size_t index) const
{
- return second == first;
+ return *(data() + index);
}
- friend bool operator!=(const BasicSmallString& first, const SmallStringView& second) noexcept
+ friend BasicSmallString operator+(const BasicSmallString &first, const BasicSmallString &second)
{
- return !(first == second);
- }
+ BasicSmallString text;
+ text.reserve(first.size() + second.size());
- friend bool operator!=(const SmallStringView& first, const BasicSmallString& second) noexcept
- {
- return second == first;
- }
+ text.append(first);
+ text.append(second);
- friend bool operator!=(const BasicSmallString& first, const BasicSmallString& second) noexcept
- {
- return !(first == second);
+ return text;
}
- template<size_type ArraySize>
- friend bool operator!=(const BasicSmallString& first, const char(&second)[ArraySize]) noexcept
+ friend BasicSmallString operator+(const BasicSmallString &first, SmallStringView second)
{
- return !(first == second);
- }
+ BasicSmallString text;
+ text.reserve(first.size() + second.size());
- template<size_type ArraySize>
- friend bool operator!=(const char(&first)[ArraySize], const BasicSmallString& second) noexcept
- {
- return second != first;
- }
+ text.append(first);
+ text.append(second);
- template<typename Type,
- typename = std::enable_if_t<std::is_pointer<Type>::value>
- >
- friend bool operator!=(const BasicSmallString& first, Type second) noexcept
- {
- return !(first == second);
+ return text;
}
- template<typename Type,
- typename = std::enable_if_t<std::is_pointer<Type>::value>
- >
- friend bool operator!=(Type first, const BasicSmallString& second) noexcept
+ friend BasicSmallString operator+(SmallStringView first, const BasicSmallString &second)
{
- return second != first;
+ return operator+(second, first);
}
- friend bool operator<(const BasicSmallString& first, SmallStringView second) noexcept
+ template<size_type ArraySize>
+ friend BasicSmallString operator+(const BasicSmallString &first, const char(&second)[ArraySize])
{
- if (first.size() != second.size())
- return first.size() < second.size();
-
- const int comparison = std::memcmp(first.data(), second.data(), first.size());
- return comparison < 0;
+ return operator+(first, SmallStringView(second));
}
- friend bool operator<(SmallStringView first, const BasicSmallString& second) noexcept
+ template<size_type ArraySize>
+ friend BasicSmallString operator+(const char(&first)[ArraySize], const BasicSmallString &second)
{
- if (first.size() != second.size())
- return first.size() < second.size();
-
- const int comparison = std::memcmp(first.data(), second.data(), first.size());
-
- return comparison < 0;
+ return operator+(SmallStringView(first), second);
}
unittest_public:
@@ -686,22 +658,34 @@ unittest_public:
{
const size_type cacheLineSize = 64;
- const auto divisionByCacheLineSize = std::div(int64_t(size), int64_t(cacheLineSize));
+ size_type cacheLineBlocks = (size - 1) / cacheLineSize;
+
+ return (cacheLineBlocks + 1) * cacheLineSize;
+ }
+
+ size_type countOccurrence(SmallStringView text)
+ {
+ auto found = begin();
+
+ size_type count = 0;
- size_type cacheLineBlocks = size_type(divisionByCacheLineSize.quot);
- const size_type supplement = divisionByCacheLineSize.rem ? 1 : 0;
+ while (true) {
+ found = std::search(found,
+ end(),
+ text.begin(),
+ text.end());
+ if (found == end())
+ break;
- cacheLineBlocks += supplement;
- int exponent;
- const double significand = std::frexp(cacheLineBlocks, &exponent);
- const double factorOneDotFiveSignificant = std::ceil(significand * 4.) / 4.;
- cacheLineBlocks = size_type(std::ldexp(factorOneDotFiveSignificant, exponent));
+ ++count;
+ found += text.size();
+ }
- return cacheLineBlocks * cacheLineSize;
+ return count;
}
private:
- BasicSmallString(Internal::StringDataLayout<Size> data) noexcept
+ BasicSmallString(const Internal::StringDataLayout<Size> &data) noexcept
: m_data(data)
{
}
@@ -751,41 +735,44 @@ private:
void replaceSmallerSized(SmallStringView fromText, SmallStringView toText)
{
- size_type newSize = size();
- reserve(newSize);
-
- auto start = begin();
-
- auto found = std::search(start,
+ auto found = std::search(begin(),
end(),
fromText.begin(),
fromText.end());
- size_type sizeDifference = 0;
-
- while (found != end()) {
- start = found + fromText.size();
-
- auto nextFound = std::search(start,
- end(),
- fromText.begin(),
- fromText.end());
-
- auto replacedTextEndPosition = found + fromText.size();
- auto replacementTextEndPosition = found + toText.size() - sizeDifference;
- auto replacementTextStartPosition = found - sizeDifference;
-
- std::memmove(replacementTextEndPosition.data(),
- replacedTextEndPosition.data(),
- nextFound - start);
- std::memcpy(replacementTextStartPosition.data(), toText.data(), toText.size());
+ if (found != end()) {
+ size_type newSize = size();
+ {
+ size_type foundIndex = found - begin();
+ reserve(newSize);
+ found = begin() + foundIndex;
+ }
+ size_type sizeDifference = 0;
+
+ while (found != end()) {
+ auto start = found + fromText.size();
+
+ auto nextFound = std::search(start,
+ end(),
+ fromText.begin(),
+ fromText.end());
+
+ auto replacedTextEndPosition = found + fromText.size();
+ auto replacementTextEndPosition = found + toText.size() - sizeDifference;
+ auto replacementTextStartPosition = found - sizeDifference;
+ std::memmove(replacementTextEndPosition.data(),
+ replacedTextEndPosition.data(),
+ std::distance(start, nextFound));
+ std::memcpy(replacementTextStartPosition.data(), toText.data(), toText.size());
+
+ sizeDifference += fromText.size() - toText.size();
+ found = nextFound;
+ }
- sizeDifference += fromText.size() - toText.size();
- found = nextFound;
+ newSize -= sizeDifference;
+ setSize(newSize);
+ at(newSize) = '\0';
}
- newSize -= sizeDifference;
- setSize(newSize);
- *end() = 0;
}
iterator replaceLargerSizedRecursive(size_type startIndex,
@@ -801,36 +788,32 @@ private:
auto foundIndex = found - begin();
if (found != end()) {
- startIndex = foundIndex + fromText.size();
-
- size_type newSizeDifference = sizeDifference + toText.size() - fromText.size();
+ size_type startNextSearchIndex = foundIndex + fromText.size();
+ size_type newSizeDifference = sizeDifference + (toText.size() - fromText.size());
- auto nextFound = replaceLargerSizedRecursive(startIndex,
+ auto nextFound = replaceLargerSizedRecursive(startNextSearchIndex,
fromText,
toText,
newSizeDifference);
- found = begin() + foundIndex;
- auto start = begin() + startIndex;
-
- auto replacedTextEndPosition = found + fromText.size();
- auto replacementTextEndPosition = found + fromText.size() + newSizeDifference;
- auto replacementTextStartPosition = found + sizeDifference;
+ auto startFound = begin() + foundIndex;
+ auto endOfFound = begin() + startNextSearchIndex;
+ auto replacedTextEndPosition = endOfFound;
+ auto replacementTextEndPosition = endOfFound + newSizeDifference;
+ auto replacementTextStartPosition = startFound + sizeDifference;
std::memmove(replacementTextEndPosition.data(),
replacedTextEndPosition.data(),
- nextFound - start);
+ std::distance(endOfFound, nextFound));
std::memcpy(replacementTextStartPosition.data(), toText.data(), toText.size());
- } else {
+ } else if (startIndex != 0) {
size_type newSize = size() + sizeDifference;
- reserve(optimalCapacity(newSize));
setSize(newSize);
- found = end();
- *end() = 0;
+ at(newSize) = 0;
}
- return found;
+ return begin() + foundIndex;
}
void replaceLargerSized(SmallStringView fromText, SmallStringView toText)
@@ -838,7 +821,15 @@ private:
size_type sizeDifference = 0;
size_type startIndex = 0;
- replaceLargerSizedRecursive(startIndex, fromText, toText, sizeDifference);
+ size_type replacementTextSizeDifference = toText.size() - fromText.size();
+ size_type occurrences = countOccurrence(fromText);
+ size_type newSize = size() + (replacementTextSizeDifference * occurrences);
+
+ if (occurrences > 0) {
+ reserve(optimalCapacity(newSize));
+
+ replaceLargerSizedRecursive(startIndex, fromText, toText, sizeDifference);
+ }
}
void setSize(size_type size)
@@ -849,6 +840,51 @@ private:
m_data.allocated.data.size = size;
}
+ static
+ std::size_t itoa(long long int number, char* string, uint base)
+ {
+ using llint = long long int;
+ using lluint = long long unsigned int;
+ std::size_t size = 0;
+ bool isNegative = false;
+ lluint unsignedNumber = 0;
+
+ if (number == 0)
+ {
+ string[size] = '0';
+ string[++size] = '\0';
+
+ return size;
+ }
+
+ if (number < 0 && base == 10)
+ {
+ isNegative = true;
+ if (number == std::numeric_limits<llint>::min())
+ unsignedNumber = lluint(std::numeric_limits<llint>::max()) + 1;
+ else
+ unsignedNumber = lluint(-number);
+ } else {
+ unsignedNumber = lluint(number);
+ }
+
+ while (unsignedNumber != 0)
+ {
+ int remainder = int(unsignedNumber % base);
+ string[size++] = (remainder > 9) ? char((remainder - 10) + 'a') : char(remainder + '0');
+ unsignedNumber /= base;
+ }
+
+ if (isNegative)
+ string[size++] = '-';
+
+ string[size] = '\0';
+
+ std::reverse(string, string+size);
+
+ return size;
+ }
+
private:
Internal::StringDataLayout<Size> m_data;
};
@@ -857,33 +893,6 @@ template<template<uint> class String, uint Size>
using isSameString = std::is_same<std::remove_reference_t<std::remove_cv_t<String<Size>>>,
BasicSmallString<Size>>;
-template<template<uint> class String,
- uint SizeOne,
- uint SizeTwo,
- typename = std::enable_if_t<isSameString<String, SizeOne>::value
- || isSameString<String, SizeTwo>::value>>
-bool operator==(const String<SizeOne> &first, const String<SizeTwo> &second) noexcept
-{
- return first.size() == second.size()
- && std::memcmp(first.data(), second.data(), first.size()) == 0;
-}
-
-
-template<template<uint> class String,
- uint SizeOne,
- uint SizeTwo,
- typename = std::enable_if_t<isSameString<String, SizeOne>::value
- || isSameString<String, SizeTwo>::value>>
-bool operator<(const String<SizeOne> &first, const String<SizeTwo> &second) noexcept
-{
- if (first.size() != second.size())
- return first.size() < second.size();
-
- const int comparison = std::memcmp(first.data(), second.data(), first.size() + 1);
-
- return comparison < 0;
-}
-
template<typename Key,
typename Value,
typename Hash = std::hash<Key>,
@@ -916,4 +925,30 @@ std::vector<Type> clone(const std::vector<Type> &vector)
using SmallString = BasicSmallString<31>;
using PathString = BasicSmallString<190>;
+inline
+SmallString operator+(SmallStringView first, SmallStringView second)
+{
+ SmallString text;
+ text.reserve(first.size() + second.size());
+
+ text.append(first);
+ text.append(second);
+
+ return text;
+}
+
+template<std::size_t Size>
+inline
+SmallString operator+(SmallStringView first, const char(&second)[Size])
+{
+ return operator+(first, SmallStringView(second));
+}
+
+template<std::size_t Size>
+inline
+SmallString operator+(const char(&first)[Size], SmallStringView second)
+{
+ return operator+(SmallStringView(first), second);
+}
+
} // namespace Utils
diff --git a/src/libs/utils/smallstringfwd.h b/src/libs/utils/smallstringfwd.h
index 90af2c7b42..f3b343f961 100644
--- a/src/libs/utils/smallstringfwd.h
+++ b/src/libs/utils/smallstringfwd.h
@@ -29,9 +29,15 @@ namespace Utils {
using uint = unsigned int;
+class SmallStringView;
template <uint Size>
class BasicSmallString;
using SmallString = BasicSmallString<31>;
using PathString = BasicSmallString<190>;
+inline
+int compare(SmallStringView first, SmallStringView second) noexcept;
+inline
+int reverseCompare(SmallStringView first, SmallStringView second) noexcept;
+
} // namespace Utils
diff --git a/src/libs/utils/smallstringio.h b/src/libs/utils/smallstringio.h
index e212fc8567..8e2b3f598b 100644
--- a/src/libs/utils/smallstringio.h
+++ b/src/libs/utils/smallstringio.h
@@ -62,7 +62,7 @@ QDataStream &operator>>(QDataStream &in, BasicSmallString<Size> &string)
char *data = string.data();
- in.readRawData(data, size);
+ in.readRawData(data, int(size));
}
return in;
@@ -79,42 +79,30 @@ QDebug &operator<<(QDebug &debug, const String &string)
}
template <uint Size>
-std::ostream &operator<<(std::ostream &stream, const BasicSmallString<Size> &string)
+std::ostream &operator<<(std::ostream &out, const BasicSmallString<Size> &string)
{
- using std::operator<<;
+ BasicSmallString<Size> formatedString = string.clone();
- stream.write(string.data(), std::streamsize(string.size()));
+ formatedString.replace("\n", "\\n");
+ formatedString.replace("\t", "\\t");
- return stream;
-}
+ out << "\"";
-inline
-std::ostream &operator<<(std::ostream &stream, SmallStringView string)
-{
- using std::operator<<;
+ out.write(formatedString.data(), std::streamsize(formatedString.size()));
- stream.write(string.data(), std::streamsize(string.size()));
+ out << "\"";
- return stream;
+ return out;
}
-template <uint Size>
-void PrintTo(const BasicSmallString<Size> &string, ::std::ostream *os)
+inline
+std::ostream &operator<<(std::ostream &out, SmallStringView string)
{
- BasicSmallString<Size> formatedString = string.clone();
-
- formatedString.replace("\n", "\\n");
- formatedString.replace("\t", "\\t");
-
- *os << "'";
-
- os->write(formatedString.data(), formatedString.size());
-
- *os<< "'";
+ return out << PathString(string);
}
-template <uint Size>
-QDataStream &operator<<(QDataStream &out, const BasicSmallStringVector<Size> &stringVector)
+template <typename String>
+QDataStream &operator<<(QDataStream &out, const BasicSmallStringVector<String> &stringVector)
{
out << quint64(stringVector.size());
@@ -124,8 +112,8 @@ QDataStream &operator<<(QDataStream &out, const BasicSmallStringVector<Size> &s
return out;
}
-template <uint Size>
-QDataStream &operator>>(QDataStream &in, BasicSmallStringVector<Size> &stringVector)
+template <typename String>
+QDataStream &operator>>(QDataStream &in, BasicSmallStringVector<String> &stringVector)
{
stringVector.clear();
@@ -136,7 +124,7 @@ QDataStream &operator>>(QDataStream &in, BasicSmallStringVector<Size> &stringVe
stringVector.reserve(size);
for (quint64 i = 0; i < size; ++i) {
- BasicSmallString<Size> string;
+ String string;
in >> string;
@@ -146,18 +134,18 @@ QDataStream &operator>>(QDataStream &in, BasicSmallStringVector<Size> &stringVe
return in;
}
-template <uint Size>
-QDebug operator<<(QDebug debug, const BasicSmallStringVector<Size> &stringVector)
+template <typename String>
+QDebug operator<<(QDebug debug, const BasicSmallStringVector<String> &stringVector)
{
- debug << "StringVector(" << stringVector.join(BasicSmallString<Size>(", ")).constData() << ")";
+ debug << "StringVector(" << stringVector.join(", ").constData() << ")";
return debug;
}
-template <uint Size>
-void PrintTo(const BasicSmallStringVector<Size> &textVector, ::std::ostream* os)
+template <typename String>
+std::ostream &operator<<(std::ostream &out, const BasicSmallStringVector<String> &textVector)
{
- *os << "[" << textVector.join(BasicSmallString<Size>(", ")).constData() << "]";
+ return out << "[" << textVector.join("\", \"") << "]";
}
} // namespace Utils
diff --git a/src/libs/utils/smallstringiterator.h b/src/libs/utils/smallstringiterator.h
index 026a8b78b5..1217e4bd2b 100644
--- a/src/libs/utils/smallstringiterator.h
+++ b/src/libs/utils/smallstringiterator.h
@@ -39,8 +39,10 @@ template <class Category,
typename Reference = Type&>
struct SmallStringIterator : public std::iterator<Category, Type, DistanceType, Pointer, Reference>
{
+ constexpr
SmallStringIterator() noexcept = default;
+ constexpr
SmallStringIterator(Pointer ptr) noexcept : pointer_(ptr)
{
}
diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h
index a9f2be5609..f831ac0aa9 100644
--- a/src/libs/utils/smallstringlayout.h
+++ b/src/libs/utils/smallstringlayout.h
@@ -92,7 +92,7 @@ struct ShortStringLayout {
template <uint MaximumShortStringDataAreaSize>
struct ALIGNAS_16 StringDataLayout {
- static_assert( MaximumShortStringDataAreaSize >= 15, "Size must be greater equal than 15 bytes!");
+ static_assert(MaximumShortStringDataAreaSize >= 15, "Size must be greater equal than 15 bytes!");
static_assert(MaximumShortStringDataAreaSize < 64
? ((MaximumShortStringDataAreaSize + 1) % 16) == 0
: ((MaximumShortStringDataAreaSize + 2) % 16) == 0,
@@ -139,9 +139,7 @@ struct ALIGNAS_16 StringDataLayout {
constexpr static
size_type shortStringCapacity() noexcept
{
- return MaximumShortStringDataAreaSize < 64
- ? MaximumShortStringDataAreaSize - 1
- : MaximumShortStringDataAreaSize - 2;
+ return MaximumShortStringDataAreaSize - 1;
}
union {
diff --git a/src/libs/utils/smallstringliteral.h b/src/libs/utils/smallstringliteral.h
index 3d5e1fef1e..eedcf45d13 100644
--- a/src/libs/utils/smallstringliteral.h
+++ b/src/libs/utils/smallstringliteral.h
@@ -56,21 +56,23 @@ public:
{
}
- const char *data() const
+ const char *data() const noexcept
{
return Q_LIKELY(isShortString()) ? m_data.shortString.string : m_data.allocated.data.pointer;
}
- size_type size() const
+ size_type size() const noexcept
{
return Q_LIKELY(isShortString()) ? m_data.shortString.shortStringSize : m_data.allocated.data.size;
}
+ constexpr
const_iterator begin() const noexcept
{
return data();
}
+ constexpr
const_iterator end() const noexcept
{
return data() + size();
@@ -78,12 +80,12 @@ public:
const_reverse_iterator rbegin() const noexcept
{
- return const_reverse_iterator(end() - static_cast<std::size_t>(1));
+ return const_reverse_iterator(end());
}
const_reverse_iterator rend() const noexcept
{
- return const_reverse_iterator(begin() - static_cast<std::size_t>(1));
+ return const_reverse_iterator(begin());
}
constexpr static
@@ -102,6 +104,7 @@ public:
return m_data.shortString.isReadOnlyReference;
}
+ constexpr
operator SmallStringView() const
{
return SmallStringView(data(), size());
diff --git a/src/libs/utils/smallstringvector.h b/src/libs/utils/smallstringvector.h
index 700a333ffb..ed1acc2e7b 100644
--- a/src/libs/utils/smallstringvector.h
+++ b/src/libs/utils/smallstringvector.h
@@ -35,25 +35,27 @@
namespace Utils {
-template<uint SmallStringSize>
-class BasicSmallStringVector : public std::vector<BasicSmallString<SmallStringSize>>
+template<typename String>
+class BasicSmallStringVector : public std::vector<String>
{
- using SmallString = BasicSmallString<SmallStringSize>;
- using Base = std::vector<SmallString>;
+ using Base = std::vector<String>;
+
public:
BasicSmallStringVector() = default;
+ using Base::Base;
+
explicit BasicSmallStringVector(const Base &stringVector)
: Base(stringVector.begin(), stringVector.end())
{
}
- BasicSmallStringVector(std::initializer_list<SmallString> list)
+ BasicSmallStringVector(std::initializer_list<String> list)
{
Base::reserve(list.size());
for (auto &&entry : list)
- Base::push_back(entry.clone());
+ Base::push_back(std::move(entry));
}
explicit BasicSmallStringVector(const QStringList &stringList)
@@ -79,7 +81,7 @@ public:
BasicSmallStringVector &operator=(BasicSmallStringVector &&)
noexcept(std::is_nothrow_move_assignable<Base>::value) = default;
- SmallString join(SmallString &&separator) const
+ SmallString join(SmallStringView separator) const
{
SmallString joinedString;
@@ -110,7 +112,7 @@ public:
return hasEntry;
}
- void append(SmallString &&string)
+ void append(String &&string)
{
push_back(std::move(string));
}
@@ -136,7 +138,8 @@ public:
QStringList qStringList;
qStringList.reserve(int(Base::size()));
- std::copy(Base::begin(), Base::end(), std::back_inserter(qStringList));
+ for (const auto &entry : *this)
+ qStringList.push_back(QString(entry));
return qStringList;
}
@@ -153,6 +156,9 @@ private:
}
};
-using SmallStringVector = BasicSmallStringVector<31>;
-using PathStringVector = BasicSmallStringVector<190>;
+
+
+using SmallStringVector = BasicSmallStringVector<BasicSmallString<31>>;
+using PathStringVector = BasicSmallStringVector<BasicSmallString<190>>;
+using StringViewVector = BasicSmallStringVector<SmallStringView>;
} // namespace Utils;
diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h
index 14be9bbb69..3d479195f1 100644
--- a/src/libs/utils/smallstringview.h
+++ b/src/libs/utils/smallstringview.h
@@ -27,7 +27,7 @@
#include "smallstringiterator.h"
-#include <QtGlobal>
+#include <QString>
#include <cstring>
#include <string>
@@ -67,6 +67,12 @@ public:
{
}
+ SmallStringView(const std::string &string) noexcept
+ : m_pointer(string.data()),
+ m_size(string.size())
+ {
+ }
+
static
SmallStringView fromUtf8(const char *const characterPointer)
{
@@ -74,22 +80,36 @@ public:
}
constexpr
- const char *data() const
+ const char *data() const noexcept
{
return m_pointer;
}
constexpr
- size_type size() const
+ size_type size() const noexcept
{
return m_size;
}
+ constexpr
+ size_type isEmpty() const noexcept
+ {
+ return m_size == 0;
+ }
+
+ constexpr
+ size_type empty() const noexcept
+ {
+ return m_size == 0;
+ }
+
+ constexpr
const_iterator begin() const noexcept
{
return data();
}
+ constexpr
const_iterator end() const noexcept
{
return data() + size();
@@ -97,12 +117,12 @@ public:
const_reverse_iterator rbegin() const noexcept
{
- return const_reverse_iterator(end() - static_cast<std::size_t>(1));
+ return const_reverse_iterator(end());
}
const_reverse_iterator rend() const noexcept
{
- return const_reverse_iterator(begin() - static_cast<std::size_t>(1));
+ return const_reverse_iterator(begin());
}
operator std::string() const
@@ -110,24 +130,105 @@ public:
return std::string(data(), size());
}
+ explicit operator QString() const
+ {
+ return QString::fromUtf8(data(), int(size()));
+ }
+
+ bool startsWith(SmallStringView subStringToSearch) const noexcept
+ {
+ if (size() >= subStringToSearch.size())
+ return !std::memcmp(m_pointer, subStringToSearch.data(), subStringToSearch.size());
+
+ return false;
+ }
+
+ bool startsWith(char characterToSearch) const noexcept
+ {
+ return m_pointer[0] == characterToSearch;
+ }
+
private:
const char *m_pointer;
size_type m_size;
};
inline
-bool operator==(const SmallStringView& first, const SmallStringView& second) noexcept
+bool operator==(SmallStringView first, SmallStringView second) noexcept
{
- if (Q_LIKELY(first.size() != second.size()))
- return false;
-
- return !std::memcmp(first.data(), second.data(), first.size());
+ return first.size() == second.size() && std::memcmp(first.data(), second.data(), first.size()) == 0;
}
inline
-bool operator!=(const SmallStringView& first, const SmallStringView& second) noexcept
+bool operator!=(SmallStringView first, SmallStringView second) noexcept
{
return !(first == second);
}
+inline
+int compare(SmallStringView first, SmallStringView second) noexcept
+{
+ int sizeDifference = int(first.size() - second.size());
+
+ if (sizeDifference == 0)
+ return std::memcmp(first.data(), second.data(), first.size());
+
+ return sizeDifference;
+}
+
+inline
+bool operator<(SmallStringView first, SmallStringView second) noexcept
+{
+ return compare(first, second) < 0;
+}
+
+inline
+bool operator>(SmallStringView first, SmallStringView second) noexcept
+{
+ return second < first;
+}
+
+namespace Internal {
+inline
+int reverse_memcmp(const char *first, const char *second, size_t n)
+{
+
+ const char *currentFirst = first + n;
+ const char *currentSecond = second + n;
+
+ while (n > 0)
+ {
+ // If the current characters differ, return an appropriately signed
+ // value; otherwise, keep searching backwards
+ if (*currentFirst != *currentSecond)
+ return *currentFirst - *currentSecond;
+
+ --currentFirst;
+ --currentSecond;
+ --n;
+ }
+
+ return 0;
+}
+}
+
+inline
+int reverseCompare(SmallStringView first, SmallStringView second) noexcept
+{
+ int sizeDifference = int(first.size() - second.size());
+
+ if (sizeDifference == 0)
+ return Internal::reverse_memcmp(first.data(), second.data(), first.size());
+
+ return sizeDifference;
+}
+
} // namespace Utils
+
+#ifdef __cpp_user_defined_literals
+inline
+constexpr Utils::SmallStringView operator""_sv(const char *const string, size_t size)
+{
+ return Utils::SmallStringView(string, size);
+}
+#endif
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index fd270a5a86..b70ea7b07c 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -34,6 +34,7 @@
#include <QFileInfo>
#include <QCommonStyle>
#include <QStyleOption>
+#include <QWindow>
#include <qmath.h>
// Clamps float color values within (0, 255)
@@ -397,7 +398,9 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect,
QPainter *p, QIcon::Mode iconMode, int dipRadius, const QColor &color, const QPoint &dipOffset)
{
QPixmap cache;
- QString pixmapName = QString::fromLatin1("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height());
+ const int devicePixelRatio = p->device()->devicePixelRatio();
+ QString pixmapName = QString::fromLatin1("icon %0 %1 %2 %3")
+ .arg(icon.cacheKey()).arg(iconMode).arg(rect.height()).arg(devicePixelRatio);
if (!QPixmapCache::find(pixmapName, cache)) {
// High-dpi support: The in parameters (rect, radius, offset) are in
@@ -405,9 +408,8 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect,
// return a high-dpi pixmap, which will in that case have a devicePixelRatio
// different than 1. The shadow drawing caluculations are done in device
// pixels.
- QWindow *window = QApplication::allWidgets().first()->windowHandle();
+ QWindow *window = dynamic_cast<QWidget*>(p->device())->window()->windowHandle();
QPixmap px = icon.pixmap(window, rect.size(), iconMode);
- int devicePixelRatio = qCeil(px.devicePixelRatio());
int radius = dipRadius * devicePixelRatio;
QPoint offset = dipOffset * devicePixelRatio;
cache = QPixmap(px.size() + QSize(radius * 2, radius * 2));
@@ -415,7 +417,8 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect,
QPainter cachePainter(&cache);
if (iconMode == QIcon::Disabled) {
- const bool hasDisabledState = icon.availableSizes(QIcon::Disabled).contains(px.size());
+ const bool hasDisabledState =
+ icon.availableSizes().count() == icon.availableSizes(QIcon::Disabled).count();
if (!hasDisabledState)
px = disabledSideBarIcon(icon.pixmap(window, rect.size()));
} else if (creatorTheme()->flag(Theme::ToolBarIconShadow)) {
diff --git a/src/plugins/texteditor/convenience.cpp b/src/libs/utils/textutils.cpp
index 8ee92147dd..65b7093c5a 100644
--- a/src/plugins/texteditor/convenience.cpp
+++ b/src/libs/utils/textutils.cpp
@@ -23,14 +23,14 @@
**
****************************************************************************/
-#include "convenience.h"
+#include "textutils.h"
#include <QTextDocument>
#include <QTextBlock>
#include <QTextCursor>
-namespace TextEditor {
-namespace Convenience {
+namespace Utils {
+namespace Text {
bool convertPosition(const QTextDocument *document, int pos, int *line, int *column)
{
@@ -95,6 +95,13 @@ static bool isValidIdentifierChar(const QChar &c)
|| c.isLowSurrogate();
}
+static bool isAfterOperatorKeyword(QTextCursor cursor)
+{
+ cursor.movePosition(QTextCursor::PreviousWord);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ return cursor.selectedText() == "operator";
+}
+
QTextCursor wordStartCursor(const QTextCursor &textCursor)
{
const int originalPosition = textCursor.position();
@@ -108,9 +115,11 @@ QTextCursor wordStartCursor(const QTextCursor &textCursor)
if (isValidIdentifierChar(c))
cursor.movePosition(QTextCursor::PreviousWord);
}
+ if (isAfterOperatorKeyword(cursor))
+ cursor.movePosition(QTextCursor::PreviousWord);
return cursor;
}
-} // Util
-} // TextEditor
+} // Text
+} // Utils
diff --git a/src/plugins/texteditor/convenience.h b/src/libs/utils/textutils.h
index f4302cd5f3..9e81884271 100644
--- a/src/plugins/texteditor/convenience.h
+++ b/src/libs/utils/textutils.h
@@ -25,30 +25,28 @@
#pragma once
-#include "texteditor_global.h"
+#include "utils_global.h"
#include <QString>
-QT_BEGIN_NAMESPACE
-class QTextDocument;
-class QTextCursor;
-QT_END_NAMESPACE
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+QT_FORWARD_DECLARE_CLASS(QTextCursor)
-namespace TextEditor {
-namespace Convenience {
+namespace Utils {
+namespace Text {
// line is 1-based, column is 0-based
-TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document,
- int pos,
- int *line, int *column);
+QTCREATOR_UTILS_EXPORT bool convertPosition(const QTextDocument *document,
+ int pos,
+ int *line, int *column);
-TEXTEDITOR_EXPORT QString textAt(QTextCursor tc, int pos, int length);
+QTCREATOR_UTILS_EXPORT QString textAt(QTextCursor tc, int pos, int length);
-TEXTEDITOR_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length);
+QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length);
-TEXTEDITOR_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
+QTCREATOR_UTILS_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
-TEXTEDITOR_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
+QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
-} // Util
-} // TextEditor
+} // Text
+} // Utils
diff --git a/src/libs/utils/theme/theme.cpp b/src/libs/utils/theme/theme.cpp
index 061ff335cc..7a4227cd75 100644
--- a/src/libs/utils/theme/theme.cpp
+++ b/src/libs/utils/theme/theme.cpp
@@ -172,7 +172,7 @@ void Theme::readSettings(QSettings &settings)
{
d->displayName = settings.value(QLatin1String("ThemeName"), QLatin1String("unnamed")).toString();
d->preferredStyles = settings.value(QLatin1String("PreferredStyles")).toStringList();
- d->preferredStyles.removeAll(QLatin1String(""));
+ d->preferredStyles.removeAll(QString());
d->defaultTextEditorColorScheme =
settings.value(QLatin1String("DefaultTextEditorColorScheme")).toString();
}
diff --git a/src/libs/utils/tooltip/tooltip.cpp b/src/libs/utils/tooltip/tooltip.cpp
index 47799b75a9..857ec071a7 100644
--- a/src/libs/utils/tooltip/tooltip.cpp
+++ b/src/libs/utils/tooltip/tooltip.cpp
@@ -305,9 +305,11 @@ bool ToolTip::eventFilter(QObject *o, QEvent *event)
switch (event->type()) {
case QEvent::KeyPress:
- case QEvent::KeyRelease:
+ case QEvent::KeyRelease: {
+ int key = static_cast<QKeyEvent *>(event)->key();
+ if (key == Qt::Key_Escape)
+ hideTipImmediately();
if (HostOsInfo::isMacHost()) {
- int key = static_cast<QKeyEvent *>(event)->key();
Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(event)->modifiers();
if (!(mody & Qt::KeyboardModifierMask)
&& key != Qt::Key_Shift && key != Qt::Key_Control
@@ -315,6 +317,7 @@ bool ToolTip::eventFilter(QObject *o, QEvent *event)
hideTipWithDelay();
}
break;
+ }
case QEvent::Leave:
if (o == m_tip && !m_tip->isAncestorOf(QApplication::focusWidget()))
hideTipWithDelay();
diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp
index 2b94d56311..61a6a8974c 100644
--- a/src/libs/utils/treemodel.cpp
+++ b/src/libs/utils/treemodel.cpp
@@ -966,6 +966,18 @@ QModelIndex BaseTreeModel::parent(const QModelIndex &idx) const
return createIndex(i, 0, static_cast<void*>(parent));
}
+QModelIndex BaseTreeModel::sibling(int row, int column, const QModelIndex &idx) const
+{
+ const TreeItem *item = itemForIndex(idx);
+ QTC_ASSERT(item, return QModelIndex());
+ QModelIndex result;
+ if (TreeItem *parent = item->parent()) {
+ if (TreeItem *sibl = parent->childAt(row))
+ result = createIndex(row, column, static_cast<void*>(sibl));
+ }
+ return result;
+}
+
int BaseTreeModel::rowCount(const QModelIndex &idx) const
{
CHECK_INDEX(idx);
@@ -974,8 +986,7 @@ int BaseTreeModel::rowCount(const QModelIndex &idx) const
if (idx.column() > 0)
return 0;
const TreeItem *item = itemForIndex(idx);
- QTC_ASSERT(item, return 0);
- return item->childCount();
+ return item ? item->childCount() : 0;
}
int BaseTreeModel::columnCount(const QModelIndex &idx) const
@@ -1053,9 +1064,10 @@ void BaseTreeModel::setRootItem(TreeItem *item)
QTC_ASSERT(item, return);
QTC_ASSERT(item->m_model == 0, return);
QTC_ASSERT(item->m_parent == 0, return);
+ QTC_ASSERT(item != m_root, return);
QTC_CHECK(m_root);
- emit layoutAboutToBeChanged();
+ beginResetModel();
if (m_root) {
QTC_CHECK(m_root->m_parent == 0);
QTC_CHECK(m_root->m_model == this);
@@ -1067,7 +1079,7 @@ void BaseTreeModel::setRootItem(TreeItem *item)
}
m_root = item;
item->propagateModel(this);
- emit layoutChanged();
+ endResetModel();
}
void BaseTreeModel::setHeader(const QStringList &displays)
@@ -1099,7 +1111,7 @@ TreeItem *BaseTreeModel::itemForIndex(const QModelIndex &idx) const
CHECK_INDEX(idx);
TreeItem *item = idx.isValid() ? static_cast<TreeItem*>(idx.internalPointer()) : m_root;
QTC_ASSERT(item, return 0);
- QTC_ASSERT(item->m_model == this, return 0);
+ QTC_ASSERT(item->m_model == static_cast<const BaseTreeModel *>(this), return 0);
return item;
}
diff --git a/src/libs/utils/treemodel.h b/src/libs/utils/treemodel.h
index 63818b27c2..41300b7dbc 100644
--- a/src/libs/utils/treemodel.h
+++ b/src/libs/utils/treemodel.h
@@ -188,6 +188,7 @@ protected:
QVariant data(const QModelIndex &idx, int role) const override;
QModelIndex index(int, int, const QModelIndex &idx = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &idx) const override;
+ QModelIndex sibling(int row, int column, const QModelIndex &idx) const override;
Qt::ItemFlags flags(const QModelIndex &idx) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
bool hasChildren(const QModelIndex &idx) const override;
@@ -314,7 +315,7 @@ public:
}
template <class Predicate>
- BestItem *findNonRooItem(const Predicate &pred) const {
+ BestItem *findNonRootItem(const Predicate &pred) const {
const auto pred0 = [pred](TreeItem *treeItem) -> bool { return pred(static_cast<BestItem *>(treeItem)); };
return static_cast<BestItem *>(m_root->findAnyChild(pred0));
}
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 924d9ba54f..822d247e90 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -21,7 +21,9 @@ win32: LIBS += -luser32 -lshell32
# PortsGatherer
win32: LIBS += -liphlpapi -lws2_32
-SOURCES += $$PWD/environment.cpp \
+SOURCES += \
+ $$PWD/benchmarker.cpp \
+ $$PWD/environment.cpp \
$$PWD/environmentmodel.cpp \
$$PWD/environmentdialog.cpp \
$$PWD/qtcprocess.cpp \
@@ -114,12 +116,15 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/runextensions.cpp \
$$PWD/utilsicons.cpp \
$$PWD/guard.cpp \
- $$PWD/highlightingitemdelegate.cpp
+ $$PWD/highlightingitemdelegate.cpp \
+ $$PWD/camelhumpmatcher.cpp \
+ $$PWD/textutils.cpp
win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
HEADERS += \
+ $$PWD/benchmarker.h \
$$PWD/environment.h \
$$PWD/environmentmodel.h \
$$PWD/environmentdialog.h \
@@ -242,7 +247,9 @@ HEADERS += \
$$PWD/optional.h \
$$PWD/../3rdparty/optional/optional.hpp \
$$PWD/qtcfallthrough.h \
- $$PWD/highlightingitemdelegate.h
+ $$PWD/highlightingitemdelegate.h \
+ $$PWD/camelhumpmatcher.h \
+ $$PWD/textutils.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index 0c0562acaf..d761c66890 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -48,10 +48,14 @@ Project {
"appmainwindow.h",
"basetreeview.cpp",
"basetreeview.h",
+ "benchmarker.cpp",
+ "benchmarker.h",
"bracematcher.cpp",
"bracematcher.h",
"buildablehelperlibrary.cpp",
"buildablehelperlibrary.h",
+ "camelhumpmatcher.cpp",
+ "camelhumpmatcher.h",
"categorysortfiltermodel.cpp",
"categorysortfiltermodel.h",
"changeset.cpp",
@@ -230,6 +234,8 @@ Project {
"textfieldcombobox.h",
"textfileformat.cpp",
"textfileformat.h",
+ "textutils.cpp",
+ "textutils.h",
"treemodel.cpp",
"treemodel.h",
"treeviewcombobox.cpp",
diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc
index da30fa3c51..63ca09e10f 100644
--- a/src/libs/utils/utils.qrc
+++ b/src/libs/utils/utils.qrc
@@ -35,7 +35,6 @@
<file>images/clean_pane_small@2x.png</file>
<file>images/compile_error_taskbar.png</file>
<file>images/compile_error_taskbar@2x.png</file>
- <file>images/dir.png</file>
<file>images/editcopy.png</file>
<file>images/editcopy@2x.png</file>
<file>images/editcut.png</file>
@@ -43,6 +42,7 @@
<file>images/editpaste.png</file>
<file>images/editpaste@2x.png</file>
<file>images/empty14.png</file>
+ <file>images/empty16.png</file>
<file>images/filenew.png</file>
<file>images/filenew@2x.png</file>
<file>images/fileopen.png</file>
@@ -88,12 +88,10 @@
<file>images/splitbutton_horizontal@2x.png</file>
<file>images/undo.png</file>
<file>images/undo@2x.png</file>
- <file>images/unknownfile.png</file>
<file>images/extension.png</file>
<file>images/extension@2x.png</file>
<file>images/progressbar.png</file>
<file>images/progressbar@2x.png</file>
- <file>images/help.png</file>
<file>images/editclear.png</file>
<file>images/editclear@2x.png</file>
<file>images/arrowdown.png</file>
diff --git a/src/libs/utils/utilsicons.cpp b/src/libs/utils/utilsicons.cpp
index 27db225e0c..271d3122f6 100644
--- a/src/libs/utils/utilsicons.cpp
+++ b/src/libs/utils/utilsicons.cpp
@@ -215,6 +215,7 @@ const Icon COLLAPSE_TOOLBAR({
const Icon PAN_TOOLBAR({
{QLatin1String(":/utils/images/pan.png"), Theme::IconsBaseColor}});
const Icon EMPTY14(":/utils/images/empty14.png");
+const Icon EMPTY16(":/utils/images/empty16.png");
const Icon OVERLAY_ADD({
{":/utils/images/iconoverlay_add_background.png", Theme::BackgroundColorNormal},
{":/utils/images/iconoverlay_add.png", Theme::IconsRunColor}}, Icon::Tint);
diff --git a/src/libs/utils/utilsicons.h b/src/libs/utils/utilsicons.h
index 2e3e083e19..5725e9a538 100644
--- a/src/libs/utils/utilsicons.h
+++ b/src/libs/utils/utilsicons.h
@@ -125,6 +125,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon COLLAPSE;
QTCREATOR_UTILS_EXPORT extern const Icon COLLAPSE_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon PAN_TOOLBAR;
QTCREATOR_UTILS_EXPORT extern const Icon EMPTY14;
+QTCREATOR_UTILS_EXPORT extern const Icon EMPTY16;
QTCREATOR_UTILS_EXPORT extern const Icon OVERLAY_ADD;
QTCREATOR_UTILS_EXPORT extern const Icon OVERLAY_WARNING;
QTCREATOR_UTILS_EXPORT extern const Icon OVERLAY_ERROR;
diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs
index 4fccdaddcf..e886ab8c3e 100644
--- a/src/plugins/android/android.qbs
+++ b/src/plugins/android/android.qbs
@@ -15,6 +15,7 @@ Project {
Depends { name: "QtSupport" }
Depends { name: "TextEditor" }
Depends { name: "Utils" }
+ Depends { name: "app_version_header" }
files: [
"android_global.h",
diff --git a/src/plugins/android/androidanalyzesupport.cpp b/src/plugins/android/androidanalyzesupport.cpp
index 59ccb047ca..391be4b500 100644
--- a/src/plugins/android/androidanalyzesupport.cpp
+++ b/src/plugins/android/androidanalyzesupport.cpp
@@ -42,7 +42,7 @@ AndroidQmlProfilerSupport::AndroidQmlProfilerSupport(RunControl *runControl)
auto profiler = runControl->createWorker(runControl->runMode());
profiler->addStartDependency(this);
- connect(runner, &AndroidRunner::qmlServerReady, [this, runner, profiler](const QUrl &server) {
+ connect(runner, &AndroidRunner::qmlServerReady, this, [this, profiler](const QUrl &server) {
profiler->recordData("QmlServerUrl", server);
reportStarted();
});
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index a8bb143a75..8ed1316a25 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -65,8 +65,6 @@ const char DeployActionKey[] = "Qt4ProjectManager.AndroidDeployQtStep.DeployQtAc
const char KeystoreLocationKey[] = "KeystoreLocation";
const char BuildTargetSdkKey[] = "BuildTargetSdk";
const char VerboseOutputKey[] = "VerboseOutput";
-const char UseGradleKey[] = "UseGradle";
-
class PasswordInputDialog : public QDialog {
public:
@@ -96,9 +94,6 @@ AndroidBuildApkStep::AndroidBuildApkStep(ProjectExplorer::BuildStepList *parent,
: ProjectExplorer::AbstractProcessStep(parent, id),
m_buildTargetSdk(AndroidConfig::apiLevelNameFor(AndroidConfigurations::currentConfig().highestAndroidSdk()))
{
- const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
- if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0))
- m_useGradle = AndroidConfigurations::currentConfig().useGrandle();
//: AndroidBuildApkStep default display name
setDefaultDisplayName(tr("Build Android APK"));
}
@@ -109,18 +104,10 @@ AndroidBuildApkStep::AndroidBuildApkStep(ProjectExplorer::BuildStepList *parent,
m_deployAction(other->deployAction()),
m_signPackage(other->signPackage()),
m_verbose(other->m_verbose),
- m_useGradle(other->m_useGradle),
m_openPackageLocation(other->m_openPackageLocation),
// leave m_openPackageLocationForRun at false
m_buildTargetSdk(other->m_buildTargetSdk)
{
- const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
- if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
- if (m_deployAction == DebugDeployment)
- m_deployAction = BundleLibrariesDeployment;
- if (m_useGradle)
- m_useGradle = false;
- }
}
bool AndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps)
@@ -142,11 +129,18 @@ bool AndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps)
return false;
const QVersionNumber sdkToolsVersion = AndroidConfigurations::currentConfig().sdkToolsVersion();
- if (sdkToolsVersion >= gradleScriptRevokedSdkVersion &&
- !version->sourcePath().appendPath("src/3rdparty/gradle").exists()) {
- emit addOutput(tr("The installed SDK tools version (%1) does not include Gradle scripts. The "
- "minimum Qt version required for Gradle build to work is %2")
- .arg(sdkToolsVersion.toString()).arg("5.9.0/5.6.3"), OutputFormat::Stderr);
+ if (sdkToolsVersion >= gradleScriptRevokedSdkVersion) {
+ if (!version->sourcePath().appendPath("src/3rdparty/gradle").exists()) {
+ emit addOutput(tr("The installed SDK tools version (%1) does not include Gradle "
+ "scripts. The minimum Qt version required for Gradle build to work "
+ "is %2").arg(sdkToolsVersion.toString()).arg("5.9.0/5.6.3"),
+ OutputFormat::Stderr);
+ return false;
+ }
+ } else if (version->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
+ emit addOutput(tr("The minimum Qt version required for Gradle build to work is %2. "
+ "It is recommended to install the latest Qt version.")
+ .arg("5.4.0"), OutputFormat::Stderr);
return false;
}
@@ -193,7 +187,7 @@ void AndroidBuildApkStep::processFinished(int exitCode, QProcess::ExitStatus sta
bool AndroidBuildApkStep::verifyKeystorePassword()
{
if (!m_keystorePath.exists()) {
- addOutput(tr("Cannot sign the package. Invalid keystore path(%1).")
+ addOutput(tr("Cannot sign the package. Invalid keystore path (%1).")
.arg(m_keystorePath.toString()), OutputFormat::ErrorMessage);
return false;
}
@@ -237,18 +231,14 @@ bool AndroidBuildApkStep::verifyCertificatePassword()
bool AndroidBuildApkStep::fromMap(const QVariantMap &map)
{
m_deployAction = AndroidDeployAction(map.value(DeployActionKey, BundleLibrariesDeployment).toInt());
- if ( m_deployAction == DebugDeployment
- && QtSupport::QtKitInformation::qtVersion(target()->kit())->qtVersion() < QtSupport::QtVersionNumber(5, 4, 0)) {
- m_deployAction = BundleLibrariesDeployment;
- }
-
+ if (m_deployAction > BundleLibrariesDeployment)
+ m_deployAction = BundleLibrariesDeployment; // BundleLibrariesDeployment used to be 2
m_keystorePath = Utils::FileName::fromString(map.value(KeystoreLocationKey).toString());
m_signPackage = false; // don't restore this
m_buildTargetSdk = map.value(BuildTargetSdkKey).toString();
if (m_buildTargetSdk.isEmpty())
m_buildTargetSdk = AndroidConfig::apiLevelNameFor(AndroidConfigurations::currentConfig().highestAndroidSdk());
m_verbose = map.value(VerboseOutputKey).toBool();
- m_useGradle = map.value(UseGradleKey).toBool();
return ProjectExplorer::BuildStep::fromMap(map);
}
@@ -259,7 +249,6 @@ QVariantMap AndroidBuildApkStep::toMap() const
map.insert(KeystoreLocationKey, m_keystorePath.toString());
map.insert(BuildTargetSdkKey, m_buildTargetSdk);
map.insert(VerboseOutputKey, m_verbose);
- map.insert(UseGradleKey, m_useGradle);
return map;
}
@@ -276,8 +265,7 @@ QString AndroidBuildApkStep::buildTargetSdk() const
void AndroidBuildApkStep::setBuildTargetSdk(const QString &sdk)
{
m_buildTargetSdk = sdk;
- if (m_useGradle)
- AndroidManager::updateGradleProperties(target());
+ AndroidManager::updateGradleProperties(target());
}
AndroidBuildApkStep::AndroidDeployAction AndroidBuildApkStep::deployAction() const
@@ -337,21 +325,6 @@ void AndroidBuildApkStep::setVerboseOutput(bool verbose)
m_verbose = verbose;
}
-bool AndroidBuildApkStep::useGradle() const
-{
- return m_useGradle;
-}
-
-void AndroidBuildApkStep::setUseGradle(bool b)
-{
- if (m_useGradle != b) {
- m_useGradle = b;
- if (m_useGradle)
- AndroidManager::updateGradleProperties(target());
- emit useGradleChanged();
- }
-}
-
bool AndroidBuildApkStep::addDebugger() const
{
return m_addDebugger;
diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h
index eae827eb15..ce9edebc11 100644
--- a/src/plugins/android/androidbuildapkstep.h
+++ b/src/plugins/android/androidbuildapkstep.h
@@ -44,7 +44,6 @@ public:
enum AndroidDeployAction
{
MinistroDeployment, // use ministro
- DebugDeployment,
BundleLibrariesDeployment
};
@@ -70,9 +69,6 @@ public:
bool verboseOutput() const;
void setVerboseOutput(bool verbose);
- bool useGradle() const;
- void setUseGradle(bool b);
-
bool addDebugger() const;
void setAddDebugger(bool debug);
@@ -82,9 +78,6 @@ public:
virtual Utils::FileName androidPackageSourceDir() const = 0;
void setDeployAction(AndroidDeployAction deploy);
-signals:
- void useGradleChanged();
-
protected:
Q_INVOKABLE void showInGraphicalShell();
@@ -102,7 +95,6 @@ protected:
AndroidDeployAction m_deployAction = BundleLibrariesDeployment;
bool m_signPackage = false;
bool m_verbose = false;
- bool m_useGradle = true; // Ant builds are deprecated.
bool m_openPackageLocation = false;
bool m_openPackageLocationForRun = false;
bool m_addDebugger = true;
diff --git a/src/plugins/android/androidbuildapkwidget.cpp b/src/plugins/android/androidbuildapkwidget.cpp
index 97dd4695bd..73c1ad531c 100644
--- a/src/plugins/android/androidbuildapkwidget.cpp
+++ b/src/plugins/android/androidbuildapkwidget.cpp
@@ -54,8 +54,6 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
{
m_ui->setupUi(this);
- m_ui->deprecatedInfoIconLabel->setPixmap(Utils::Icons::INFO.pixmap());
-
// Target sdk combobox
int minApiLevel = 9;
const AndroidConfig &config = AndroidConfigurations::currentConfig();
@@ -69,9 +67,6 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
case AndroidBuildApkStep::MinistroDeployment:
m_ui->ministroOption->setChecked(true);
break;
- case AndroidBuildApkStep::DebugDeployment:
- m_ui->temporaryQtOption->setChecked(true);
- break;
case AndroidBuildApkStep::BundleLibrariesDeployment:
m_ui->bundleQtOption->setChecked(true);
break;
@@ -91,12 +86,8 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
m_ui->signingDebugWarningIcon->setPixmap(Utils::Icons::WARNING.pixmap());
m_ui->signingDebugWarningIcon->hide();
m_ui->signingDebugWarningLabel->hide();
- m_ui->signingDebugDeployErrorIcon->setPixmap(Utils::Icons::CRITICAL.pixmap());
signPackageCheckBoxToggled(m_step->signPackage());
- m_ui->useGradleCheckBox->setEnabled(config.antScriptsAvailable());
- m_ui->useGradleCheckBox->setChecked(!config.antScriptsAvailable() ||
- m_step->useGradle());
m_ui->verboseOutputCheckBox->setChecked(m_step->verboseOutput());
m_ui->openPackageLocationCheckBox->setChecked(m_step->openPackageLocation());
m_ui->addDebuggerCheckBox->setChecked(m_step->addDebugger());
@@ -109,19 +100,9 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
// deployment options
connect(m_ui->ministroOption, &QAbstractButton::clicked,
this, &AndroidBuildApkWidget::setMinistro);
- connect(m_ui->temporaryQtOption, &QAbstractButton::clicked,
- this, &AndroidBuildApkWidget::setDeployLocalQtLibs);
connect(m_ui->bundleQtOption, &QAbstractButton::clicked,
this, &AndroidBuildApkWidget::setBundleQtLibs);
- connect(m_ui->ministroOption, &QAbstractButton::clicked,
- this, &AndroidBuildApkWidget::updateDebugDeploySigningWarning);
- connect(m_ui->temporaryQtOption, &QAbstractButton::clicked,
- this, &AndroidBuildApkWidget::updateDebugDeploySigningWarning);
- connect(m_ui->bundleQtOption, &QAbstractButton::clicked,
- this, &AndroidBuildApkWidget::updateDebugDeploySigningWarning);
- connect(m_ui->useGradleCheckBox, &QAbstractButton::toggled,
- this, &AndroidBuildApkWidget::useGradleCheckBoxToggled);
connect(m_ui->openPackageLocationCheckBox, &QAbstractButton::toggled,
this, &AndroidBuildApkWidget::openPackageLocationCheckBoxToggled);
connect(m_ui->verboseOutputCheckBox, &QAbstractButton::toggled,
@@ -147,11 +128,6 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
this, &AndroidBuildApkWidget::updateSigningWarning);
updateSigningWarning();
- updateDebugDeploySigningWarning();
- QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(step->target()->kit());
- bool qt54 = qt->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0);
- m_ui->temporaryQtOption->setVisible(qt54);
- m_ui->useGradleCheckBox->setVisible(qt54);
}
AndroidBuildApkWidget::~AndroidBuildApkWidget()
@@ -179,11 +155,6 @@ void AndroidBuildApkWidget::setMinistro()
m_step->setDeployAction(AndroidBuildApkStep::MinistroDeployment);
}
-void AndroidBuildApkWidget::setDeployLocalQtLibs()
-{
- m_step->setDeployAction(AndroidBuildApkStep::DebugDeployment);
-}
-
void AndroidBuildApkWidget::setBundleQtLibs()
{
m_step->setDeployAction(AndroidBuildApkStep::BundleLibrariesDeployment);
@@ -266,22 +237,3 @@ void AndroidBuildApkWidget::updateSigningWarning()
m_ui->signingDebugWarningLabel->setVisible(false);
}
}
-
-void AndroidBuildApkWidget::updateDebugDeploySigningWarning()
-{
- if (m_step->deployAction() == AndroidBuildApkStep::DebugDeployment) {
- m_ui->signingDebugDeployError->setVisible(true);
- m_ui->signingDebugDeployErrorIcon->setVisible(true);
- m_ui->signPackageCheckBox->setChecked(false);
- m_ui->signPackageCheckBox->setEnabled(false);
- } else {
- m_ui->signingDebugDeployError->setVisible(false);
- m_ui->signingDebugDeployErrorIcon->setVisible(false);
- m_ui->signPackageCheckBox->setEnabled(true);
- }
-}
-
-void AndroidBuildApkWidget::useGradleCheckBoxToggled(bool checked)
-{
- m_step->setUseGradle(checked);
-}
diff --git a/src/plugins/android/androidbuildapkwidget.h b/src/plugins/android/androidbuildapkwidget.h
index e4d46a99a2..3a0576d6df 100644
--- a/src/plugins/android/androidbuildapkwidget.h
+++ b/src/plugins/android/androidbuildapkwidget.h
@@ -52,14 +52,11 @@ public:
private:
void setTargetSdk(const QString &sdk);
void setMinistro();
- void setDeployLocalQtLibs();
void setBundleQtLibs();
void createKeyStore();
void certificatesAliasComboBoxCurrentIndexChanged(const QString &alias);
void certificatesAliasComboBoxActivated(const QString &alias);
void updateSigningWarning();
- void updateDebugDeploySigningWarning();
- void useGradleCheckBoxToggled(bool checked);
void openPackageLocationCheckBoxToggled(bool checked);
void verboseOutputCheckBoxToggled(bool checked);
void updateKeyStorePath(const QString &path);
diff --git a/src/plugins/android/androidbuildapkwidget.ui b/src/plugins/android/androidbuildapkwidget.ui
index fa3c1ef3d6..8e22e4043a 100644
--- a/src/plugins/android/androidbuildapkwidget.ui
+++ b/src/plugins/android/androidbuildapkwidget.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>819</width>
- <height>478</height>
+ <width>641</width>
+ <height>331</height>
</rect>
</property>
<property name="windowTitle">
@@ -117,37 +117,6 @@
</item>
</layout>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_5">
- <item>
- <widget class="QLabel" name="signingDebugDeployErrorIcon">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="signingDebugDeployError">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Signing an APK that uses &quot;Deploy local Qt libraries&quot; is not allowed.
-Deploying local Qt libraries is incompatible with Android 5.</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
</layout>
</widget>
</item>
@@ -176,66 +145,21 @@ Deploying local Qt libraries is incompatible with Android 5.</string>
<string>Advanced Actions</string>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QCheckBox" name="useGradleCheckBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Use Gradle (Ant builds are deprecated)</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="deprecatedInfoIconLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="toolTip">
- <string>Gradle builds are forced from Android SDK tools version 25.3.0 onwards as Ant scripts are no longer available.</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Preferred</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="0" colspan="3">
+ <item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="openPackageLocationCheckBox">
<property name="text">
<string>Open package location after build</string>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="3">
+ <item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="verboseOutputCheckBox">
<property name="text">
<string>Verbose output</string>
</property>
</widget>
</item>
- <item row="3" column="0" colspan="3">
+ <item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="addDebuggerCheckBox">
<property name="enabled">
<bool>false</bool>
@@ -280,17 +204,6 @@ Deploying local Qt libraries is incompatible with Android 5.</string>
</property>
</widget>
</item>
- <item>
- <widget class="QRadioButton" name="temporaryQtOption">
- <property name="toolTip">
- <string>Pushes local Qt libraries to device. You must have Qt libraries compiled for that platform.
-The APK will not be usable on any other device.</string>
- </property>
- <property name="text">
- <string>Deploy local Qt libraries to temporary directory</string>
- </property>
- </widget>
- </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp
index cba8f4d438..b52810e93f 100644
--- a/src/plugins/android/androidconfigurations.cpp
+++ b/src/plugins/android/androidconfigurations.cpp
@@ -84,16 +84,13 @@ using namespace Internal;
namespace {
const char jdkSettingsPath[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit";
- const QVersionNumber sdkToolsAntMissingVersion(25, 3, 0);
const QLatin1String SettingsGroup("AndroidConfigurations");
const QLatin1String SDKLocationKey("SDKLocation");
const QLatin1String NDKLocationKey("NDKLocation");
- const QLatin1String AntLocationKey("AntLocation");
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
const QLatin1String KeystoreLocationKey("KeystoreLocation");
const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation");
- const QLatin1String UseGradleKey("UseGradle");
const QLatin1String MakeExtraSearchDirectory("MakeExtraSearchDirectory");
const QLatin1String PartitionSizeKey("PartitionSize");
const QLatin1String ToolchainHostKey("ToolchainHost");
@@ -250,8 +247,6 @@ void AndroidConfig::load(const QSettings &settings)
m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
m_sdkLocation = FileName::fromString(settings.value(SDKLocationKey).toString());
m_ndkLocation = FileName::fromString(settings.value(NDKLocationKey).toString());
- m_antLocation = FileName::fromString(settings.value(AntLocationKey).toString());
- m_useGradle = settings.value(UseGradleKey, false).toBool();
m_openJDKLocation = FileName::fromString(settings.value(OpenJDKLocationKey).toString());
m_keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString());
m_toolchainHost = settings.value(ToolchainHostKey).toString();
@@ -267,7 +262,6 @@ void AndroidConfig::load(const QSettings &settings)
// persisten settings
m_sdkLocation = FileName::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
m_ndkLocation = FileName::fromString(reader.restoreValue(NDKLocationKey, m_ndkLocation.toString()).toString());
- m_antLocation = FileName::fromString(reader.restoreValue(AntLocationKey, m_antLocation.toString()).toString());
m_openJDKLocation = FileName::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
m_keystoreLocation = FileName::fromString(reader.restoreValue(KeystoreLocationKey, m_keystoreLocation.toString()).toString());
m_toolchainHost = reader.restoreValue(ToolchainHostKey, m_toolchainHost).toString();
@@ -291,8 +285,6 @@ void AndroidConfig::save(QSettings &settings) const
// user settings
settings.setValue(SDKLocationKey, m_sdkLocation.toString());
settings.setValue(NDKLocationKey, m_ndkLocation.toString());
- settings.setValue(AntLocationKey, m_antLocation.toString());
- settings.setValue(UseGradleKey, m_useGradle);
settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString());
settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString());
settings.setValue(PartitionSizeKey, m_partitionSize);
@@ -400,14 +392,6 @@ FileName AndroidConfig::androidToolPath() const
}
}
-FileName AndroidConfig::antToolPath() const
-{
- if (!m_antLocation.isEmpty())
- return m_antLocation;
- else
- return FileName::fromLatin1("ant");
-}
-
FileName AndroidConfig::emulatorToolPath() const
{
FileName path = m_sdkLocation;
@@ -775,6 +759,17 @@ QVersionNumber AndroidConfig::sdkToolsVersion() const
return version;
}
+QVersionNumber AndroidConfig::buildToolsVersion() const
+{
+ QVersionNumber maxVersion;
+ Utils::FileName buildtoolsDir = m_sdkLocation;
+ buildtoolsDir.appendPath("build-tools");
+ QDir buildToolsDir(buildtoolsDir.toString());
+ for (const QFileInfo &file: buildToolsDir.entryList(QDir::Dirs|QDir::NoDotAndDotDot))
+ maxVersion = qMax(maxVersion, QVersionNumber::fromString(file.fileName()));
+ return maxVersion;
+}
+
FileName AndroidConfig::ndkLocation() const
{
return m_ndkLocation;
@@ -833,16 +828,6 @@ void AndroidConfig::setNdkLocation(const FileName &ndkLocation)
m_NdkInformationUpToDate = false;
}
-FileName AndroidConfig::antLocation() const
-{
- return m_antLocation;
-}
-
-void AndroidConfig::setAntLocation(const FileName &antLocation)
-{
- m_antLocation = antLocation;
-}
-
FileName AndroidConfig::openJDKLocation() const
{
return m_openJDKLocation;
@@ -895,25 +880,6 @@ void AndroidConfig::setAutomaticKitCreation(bool b)
m_automaticKitCreation = b;
}
-bool AndroidConfig::antScriptsAvailable() const
-{
- return sdkToolsVersion() < sdkToolsAntMissingVersion;
-}
-
-bool AndroidConfig::useGrandle() const
-{
- if (antScriptsAvailable()) {
- return m_useGradle;
- }
- // Force gradle builds.
- return true;
-}
-
-void AndroidConfig::setUseGradle(bool b)
-{
- m_useGradle = b;
-}
-
///////////////////////////////////
// AndroidConfigurations
///////////////////////////////////
@@ -930,11 +896,10 @@ void AndroidConfigurations::setConfig(const AndroidConfig &devConfigs)
}
AndroidDeviceInfo AndroidConfigurations::showDeviceDialog(Project *project,
- int apiLevel, const QString &abi,
- Options options)
+ int apiLevel, const QString &abi)
{
QString serialNumber = defaultDevice(project, abi);
- AndroidDeviceDialog dialog(apiLevel, abi, options, serialNumber, Core::ICore::mainWindow());
+ AndroidDeviceDialog dialog(apiLevel, abi, serialNumber, Core::ICore::mainWindow());
AndroidDeviceInfo info = dialog.device();
if (dialog.saveDeviceSelection() && info.isValid()) {
const QString serialNumber = info.type == AndroidDeviceInfo::Hardware ?
@@ -1215,16 +1180,6 @@ void AndroidConfigurations::load()
settings->beginGroup(SettingsGroup);
m_config.load(*settings);
- if (m_config.antLocation().isEmpty()) {
- Environment env = Environment::systemEnvironment();
- FileName location = env.searchInPath(QLatin1String("ant"));
- QFileInfo fi = location.toFileInfo();
- if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
- m_config.setAntLocation(location);
- saveSettings = true;
- }
- }
-
if (m_config.openJDKLocation().isEmpty()) {
if (HostOsInfo::isLinuxHost()) {
Environment env = Environment::systemEnvironment();
diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h
index d5c59936d3..75b6dd16ab 100644
--- a/src/plugins/android/androidconfigurations.h
+++ b/src/plugins/android/androidconfigurations.h
@@ -113,14 +113,12 @@ public:
Utils::FileName sdkLocation() const;
void setSdkLocation(const Utils::FileName &sdkLocation);
QVersionNumber sdkToolsVersion() const;
+ QVersionNumber buildToolsVersion() const;
Utils::FileName ndkLocation() const;
QVersionNumber ndkVersion() const;
void setNdkLocation(const Utils::FileName &ndkLocation);
- Utils::FileName antLocation() const;
- void setAntLocation(const Utils::FileName &antLocation);
-
Utils::FileName openJDKLocation() const;
void setOpenJDKLocation(const Utils::FileName &openJDKLocation);
@@ -136,14 +134,8 @@ public:
bool automaticKitCreation() const;
void setAutomaticKitCreation(bool b);
- bool antScriptsAvailable() const;
-
- bool useGrandle() const;
- void setUseGradle(bool b);
-
Utils::FileName adbToolPath() const;
Utils::FileName androidToolPath() const;
- Utils::FileName antToolPath() const;
Utils::FileName emulatorToolPath() const;
Utils::FileName sdkManagerToolPath() const;
Utils::FileName avdManagerToolPath() const;
@@ -202,13 +194,11 @@ private:
Utils::FileName m_sdkLocation;
Utils::FileName m_ndkLocation;
- Utils::FileName m_antLocation;
Utils::FileName m_openJDKLocation;
Utils::FileName m_keystoreLocation;
QStringList m_makeExtraSearchDirectories;
unsigned m_partitionSize = 1024;
bool m_automaticKitCreation = true;
- bool m_useGradle = true; // Ant builds are deprecated.
//caches
mutable bool m_availableSdkPlatformsUpToDate = false;
@@ -232,8 +222,7 @@ public:
static AndroidConfigurations *instance();
static void updateAndroidDevice();
- enum Options { None, FilterAndroid5 };
- static AndroidDeviceInfo showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QString &abi, Options options);
+ static AndroidDeviceInfo showDeviceDialog(ProjectExplorer::Project *project, int apiLevel, const QString &abi);
static void setDefaultDevice(ProjectExplorer::Project *project, const QString &abi, const QString &serialNumber); // serial number or avd name
static QString defaultDevice(ProjectExplorer::Project *project, const QString &abi); // serial number or avd name
static void clearDefaultDevices(ProjectExplorer::Project *project);
diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp
index d6036231cb..e7ada2d28b 100644
--- a/src/plugins/android/androiddebugsupport.cpp
+++ b/src/plugins/android/androiddebugsupport.cpp
@@ -33,7 +33,6 @@
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerrunconfigurationaspect.h>
#include <debugger/debuggerruncontrol.h>
-#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
@@ -108,43 +107,40 @@ void AndroidDebugSupport::start()
Target *target = runConfig->target();
Kit *kit = target->kit();
- DebuggerStartParameters params;
- params.startMode = AttachToRemoteServer;
- params.displayName = AndroidManager::packageName(target);
- params.useContinueInsteadOfRun = true;
- params.attachPID = m_runner->pid();
+ setStartMode(AttachToRemoteServer);
+ setRunControlName(AndroidManager::packageName(target));
+ setUseContinueInsteadOfRun(true);
+ setAttachPid(m_runner->pid());
+
if (!Utils::HostOsInfo::isWindowsHost() &&
AndroidConfigurations::currentConfig().ndkVersion() >= QVersionNumber(11, 0, 0)) {
- params.useTargetAsync = true;
+ setUseTargetAsync(true);
}
+ QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit);
+
if (isCppDebugging()) {
- Utils::Port gdbServerPort = m_runner->gdbServerPort();
- params.symbolFile = target->activeBuildConfiguration()->buildDirectory().toString() + "/app_process";
- params.skipExecutableValidation = true;
- params.useExtendedRemote = true;
- params.remoteChannel = ":" + gdbServerPort.toString();
- params.solibSearchPath = AndroidManager::androidQtSupport(target)->soLibSearchPath(target);
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
- params.solibSearchPath.append(qtSoPaths(version));
- params.solibSearchPath.append(uniquePaths(AndroidManager::androidQtSupport(target)->androidExtraLibs(target)));
- params.sysRoot = AndroidConfigurations::currentConfig().ndkLocation().appendPath("platforms")
- .appendPath(QString("android-%1").arg(AndroidManager::minimumSDK(target)))
- .appendPath(toNdkArch(AndroidManager::targetArch(target))).toString();
+ AndroidQtSupport *qtSupport = AndroidManager::androidQtSupport(target);
+ QStringList solibSearchPath = qtSupport->soLibSearchPath(target);
+ solibSearchPath.append(qtSoPaths(qtVersion));
+ solibSearchPath.append(uniquePaths(qtSupport->androidExtraLibs(target)));
+ setSolibSearchPath(solibSearchPath);
+ setSymbolFile(target->activeBuildConfiguration()->buildDirectory().toString()
+ + "/app_process");
+ setSkipExecutableValidation(true);
+ setUseExtendedRemote(true);
+ setRemoteChannel(":" + m_runner->gdbServerPort().toString());
+ setSysRoot(AndroidConfigurations::currentConfig().ndkLocation().appendPath("platforms")
+ .appendPath(QString("android-%1").arg(AndroidManager::minimumSDK(target)))
+ .appendPath(toNdkArch(AndroidManager::targetArch(target))).toString());
}
if (isQmlDebugging()) {
- params.qmlServer.host = m_runner->qmlServerHost();
- params.qmlServer.port = m_runner->qmlServerPort();
+ setQmlServer(m_runner->qmlServer());
//TODO: Not sure if these are the right paths.
- QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
- if (version) {
- const QString qmlQtDir = version->qmakeProperty("QT_INSTALL_QML");
- params.additionalSearchDirectories = QStringList(qmlQtDir);
- }
+ if (qtVersion)
+ addSearchDirectory(qtVersion->qmakeProperty("QT_INSTALL_QML"));
}
- setStartParameters(params);
-
// FIXME: Move signal to base class and generalize handling.
connect(this, &DebuggerRunTool::aboutToNotifyInferiorSetupOk,
m_runner, &AndroidRunner::remoteDebuggerRunning);
diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp
index b4bfbc7bc1..79693a0896 100644
--- a/src/plugins/android/androiddeployqtstep.cpp
+++ b/src/plugins/android/androiddeployqtstep.cpp
@@ -161,12 +161,9 @@ bool AndroidDeployQtStep::init(QList<const BuildStep *> &earlierSteps)
}
int deviceAPILevel = AndroidManager::minimumSDK(target());
- AndroidConfigurations::Options options = AndroidConfigurations::None;
- if (androidBuildApkStep->deployAction() == AndroidBuildApkStep::DebugDeployment)
- options = AndroidConfigurations::FilterAndroid5;
AndroidDeviceInfo info = earlierDeviceInfo(earlierSteps, Id);
if (!info.isValid()) {
- info = AndroidConfigurations::showDeviceDialog(project(), deviceAPILevel, m_targetArch, options);
+ info = AndroidConfigurations::showDeviceDialog(project(), deviceAPILevel, m_targetArch);
m_deviceInfo = info; // Keep around for later steps
}
@@ -232,15 +229,12 @@ bool AndroidDeployQtStep::init(QList<const BuildStep *> &earlierSteps)
case AndroidBuildApkStep::MinistroDeployment:
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("ministro"));
break;
- case AndroidBuildApkStep::DebugDeployment:
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("debug"));
- break;
case AndroidBuildApkStep::BundleLibrariesDeployment:
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("bundled"));
break;
}
- if (androidBuildApkStep->useGradle())
- Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--gradle"));
+
+ Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--gradle"));
if (androidBuildApkStep->signPackage()) {
// The androiddeployqt tool is not really written to do stand-alone installations.
diff --git a/src/plugins/android/androiddevicedialog.cpp b/src/plugins/android/androiddevicedialog.cpp
index 451abf2dc5..67cd02e9f8 100644
--- a/src/plugins/android/androiddevicedialog.cpp
+++ b/src/plugins/android/androiddevicedialog.cpp
@@ -237,7 +237,7 @@ class AndroidDeviceModel : public QAbstractItemModel
{
Q_OBJECT
public:
- AndroidDeviceModel(int apiLevel, const QString &abi, AndroidConfigurations::Options options);
+ AndroidDeviceModel(int apiLevel, const QString &abi);
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
@@ -253,7 +253,6 @@ public:
private:
int m_apiLevel;
QString m_abi;
- AndroidConfigurations::Options m_options;
AndroidDeviceModelNode *m_root;
};
@@ -262,8 +261,8 @@ private:
/////////////////
// AndroidDeviceModel
/////////////////
-AndroidDeviceModel::AndroidDeviceModel(int apiLevel, const QString &abi, AndroidConfigurations::Options options)
- : m_apiLevel(apiLevel), m_abi(abi), m_options(options), m_root(0)
+AndroidDeviceModel::AndroidDeviceModel(int apiLevel, const QString &abi)
+ : m_apiLevel(apiLevel), m_abi(abi), m_root(0)
{
}
@@ -372,8 +371,6 @@ void AndroidDeviceModel::setDevices(const QVector<AndroidDeviceInfo> &devices)
} else if (device.sdk < m_apiLevel) {
error = AndroidDeviceDialog::tr("API Level of device is: %1.")
.arg(device.sdk);
- } else if (device.sdk > 20 && (m_options & AndroidConfigurations::FilterAndroid5)) {
- error = AndroidDeviceDialog::tr("Android 5 devices are incompatible with deploying Qt to a temporary directory.");
} else {
new AndroidDeviceModelNode(compatibleDevices, device);
continue;
@@ -417,10 +414,10 @@ static inline QString msgAdbListDevices()
return AndroidDeviceDialog::tr("<p>The adb tool in the Android SDK lists all connected devices if run via &quot;adb devices&quot;.</p>");
}
-AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi, AndroidConfigurations::Options options,
+AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi,
const QString &serialNumber, QWidget *parent) :
QDialog(parent),
- m_model(new AndroidDeviceModel(apiLevel, abi, options)),
+ m_model(new AndroidDeviceModel(apiLevel, abi)),
m_ui(new Ui::AndroidDeviceDialog),
m_apiLevel(apiLevel),
m_abi(abi),
@@ -462,7 +459,7 @@ AndroidDeviceDialog::AndroidDeviceDialog(int apiLevel, const QString &abi, Andro
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large, this);
+ m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large, this);
m_progressIndicator->attachToWidget(m_ui->deviceView);
if (serialNumber.isEmpty()) {
diff --git a/src/plugins/android/androiddevicedialog.h b/src/plugins/android/androiddevicedialog.h
index 8f957aa0b2..f882b0bfcd 100644
--- a/src/plugins/android/androiddevicedialog.h
+++ b/src/plugins/android/androiddevicedialog.h
@@ -52,7 +52,7 @@ class AndroidDeviceDialog : public QDialog
Q_OBJECT
public:
- explicit AndroidDeviceDialog(int apiLevel, const QString &abi, AndroidConfigurations::Options opts,
+ explicit AndroidDeviceDialog(int apiLevel, const QString &abi,
const QString &serialNumber, QWidget *parent = 0);
~AndroidDeviceDialog();
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index 54f2bdd482..3691d95900 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -341,7 +341,7 @@ void AndroidManager::cleanLibsOnDevice(ProjectExplorer::Target *target)
if (targetArch.isEmpty())
return;
const int deviceAPILevel = AndroidManager::minimumSDK(target);
- AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, targetArch, AndroidConfigurations::None);
+ AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, targetArch);
if (!info.isValid()) // aborted
return;
@@ -371,7 +371,7 @@ void AndroidManager::installQASIPackage(ProjectExplorer::Target *target, const Q
if (targetArch.isEmpty())
return;
const int deviceAPILevel = AndroidManager::minimumSDK(target);
- AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, targetArch, AndroidConfigurations::None);
+ AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, targetArch);
if (!info.isValid()) // aborted
return;
@@ -463,15 +463,6 @@ AndroidQtSupport *AndroidManager::androidQtSupport(ProjectExplorer::Target *targ
return 0;
}
-bool AndroidManager::useGradle(ProjectExplorer::Target *target)
-{
- if (!target)
- return false;
- AndroidBuildApkStep *buildApkStep
- = AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration());
- return buildApkStep && buildApkStep->useGradle();
-}
-
typedef QMap<QByteArray, QByteArray> GradleProperties;
static GradleProperties readGradleProperties(const QString &path)
@@ -543,7 +534,7 @@ bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
AndroidBuildApkStep *buildApkStep
= AndroidGlobal::buildStep<AndroidBuildApkStep>(target->activeBuildConfiguration());
- if (!buildApkStep || !buildApkStep->useGradle() || !buildApkStep->androidPackageSourceDir().appendPath(QLatin1String("gradlew")).exists())
+ if (!buildApkStep || !buildApkStep->androidPackageSourceDir().appendPath(QLatin1String("gradlew")).exists())
return false;
Utils::FileName wrapperProps(buildApkStep->androidPackageSourceDir());
@@ -570,16 +561,10 @@ bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target)
gradleProperties["buildDir"] = ".build";
gradleProperties["androidCompileSdkVersion"] = buildTargetSDK(target).split(QLatin1Char('-')).last().toLocal8Bit();
if (gradleProperties["androidBuildToolsVersion"].isEmpty()) {
- QVersionNumber maxVersion;
- QDir buildToolsDir(AndroidConfigurations::currentConfig().sdkLocation().appendPath(QLatin1String("build-tools")).toString());
- foreach (const QFileInfo &file, buildToolsDir.entryList(QDir::Dirs|QDir::NoDotAndDotDot)) {
- QVersionNumber ver = QVersionNumber::fromString(file.fileName());
- if (maxVersion < ver)
- maxVersion = ver;
- }
- if (maxVersion.isNull())
+ QVersionNumber buildtoolVersion = AndroidConfigurations::currentConfig().buildToolsVersion();
+ if (buildtoolVersion.isNull())
return false;
- gradleProperties["androidBuildToolsVersion"] = maxVersion.toString().toLocal8Bit();
+ gradleProperties["androidBuildToolsVersion"] = buildtoolVersion.toString().toLocal8Bit();
}
return mergeGradleProperties(gradlePropertiesPath, gradleProperties);
}
diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h
index ad50f45529..e9d8fc5062 100644
--- a/src/plugins/android/androidmanager.h
+++ b/src/plugins/android/androidmanager.h
@@ -87,7 +87,6 @@ public:
const QString &alias);
static bool checkForQt51Files(Utils::FileName fileName);
static AndroidQtSupport *androidQtSupport(ProjectExplorer::Target *target);
- static bool useGradle(ProjectExplorer::Target *target);
static bool updateGradleProperties(ProjectExplorer::Target *target);
static int findApiLevel(const Utils::FileName &platformPath);
};
diff --git a/src/plugins/android/androidpotentialkit.cpp b/src/plugins/android/androidpotentialkit.cpp
index c01c7d0ecc..8264415a12 100644
--- a/src/plugins/android/androidpotentialkit.cpp
+++ b/src/plugins/android/androidpotentialkit.cpp
@@ -27,6 +27,8 @@
#include "androidconstants.h"
#include "androidconfigurations.h"
+#include <app/app_version.h>
+
#include <utils/detailswidget.h>
#include <utils/utilsicons.h>
@@ -91,8 +93,9 @@ AndroidPotentialKitWidget::AndroidPotentialKitWidget(QWidget *parent)
auto layout = new QGridLayout(mainWidget);
layout->setMargin(0);
auto label = new QLabel;
- label->setText(tr("Qt Creator needs additional settings to enable Android support."
- " You can configure those settings in the Options dialog."));
+ label->setText(tr("%1 needs additional settings to enable Android support."
+ " You can configure those settings in the Options dialog.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
label->setWordWrap(true);
layout->addWidget(label, 0, 0, 1, 2);
diff --git a/src/plugins/android/androidqtsupport.cpp b/src/plugins/android/androidqtsupport.cpp
index 8cc4a86a9f..1e3aa8ce7d 100644
--- a/src/plugins/android/androidqtsupport.cpp
+++ b/src/plugins/android/androidqtsupport.cpp
@@ -41,11 +41,7 @@ Utils::FileName Android::AndroidQtSupport::apkPath(ProjectExplorer::Target *targ
if (!buildApkStep)
return Utils::FileName();
- QString apkPath;
- if (buildApkStep->useGradle())
- apkPath = QLatin1String("build/outputs/apk/android-build-");
- else
- apkPath = QLatin1String("bin/QtApp-");
+ QString apkPath("build/outputs/apk/android-build-");
if (buildApkStep->signPackage())
apkPath += QLatin1String("release.apk");
else
diff --git a/src/plugins/android/androidrunconfiguration.cpp b/src/plugins/android/androidrunconfiguration.cpp
index 79bfa1007f..f6a1e858a4 100644
--- a/src/plugins/android/androidrunconfiguration.cpp
+++ b/src/plugins/android/androidrunconfiguration.cpp
@@ -45,13 +45,8 @@ const char amStartArgsKey[] = "Android.AmStartArgsKey";
const char preStartShellCmdsKey[] = "Android.PreStartShellCmdListKey";
const char postFinishShellCmdsKey[] = "Android.PostFinishShellCmdListKey";
-AndroidRunConfiguration::AndroidRunConfiguration(Target *parent, Core::Id id)
- : RunConfiguration(parent, id)
-{
-}
-
-AndroidRunConfiguration::AndroidRunConfiguration(Target *parent, AndroidRunConfiguration *source)
- : RunConfiguration(parent, source)
+AndroidRunConfiguration::AndroidRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
}
diff --git a/src/plugins/android/androidrunconfiguration.h b/src/plugins/android/androidrunconfiguration.h
index 45b00d8a84..358871dc19 100644
--- a/src/plugins/android/androidrunconfiguration.h
+++ b/src/plugins/android/androidrunconfiguration.h
@@ -29,17 +29,13 @@
#include <projectexplorer/runconfiguration.h>
-QT_BEGIN_NAMESPACE
-class QToolButton;
-QT_END_NAMESPACE
-
namespace Android {
class ANDROID_EXPORT AndroidRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
public:
- AndroidRunConfiguration(ProjectExplorer::Target *parent, Core::Id id);
+ explicit AndroidRunConfiguration(ProjectExplorer::Target *target);
QWidget *createConfigurationWidget() override;
Utils::OutputFormatter *createOutputFormatter() const override;
@@ -51,15 +47,12 @@ public:
const QStringList &preStartShellCommands() const;
const QStringList &postFinishShellCommands() const;
-protected:
- AndroidRunConfiguration(ProjectExplorer::Target *parent, AndroidRunConfiguration *source);
-
private:
+ // FIXME: This appears to miss a copyFrom() implementation.
void setPreStartShellCommands(const QStringList &cmdList);
void setPostFinishShellCommands(const QStringList &cmdList);
void setAmStartExtraArgs(const QStringList &args);
-private:
QStringList m_amStartExtraArgs;
QStringList m_preStartShellCommands;
QStringList m_postFinishShellCommands;
diff --git a/src/plugins/android/androidrunconfigurationwidget.cpp b/src/plugins/android/androidrunconfigurationwidget.cpp
index a9560fdaaa..a7327ce917 100644
--- a/src/plugins/android/androidrunconfigurationwidget.cpp
+++ b/src/plugins/android/androidrunconfigurationwidget.cpp
@@ -69,9 +69,7 @@ AndroidRunConfigurationWidget::AndroidRunConfigurationWidget(QWidget *parent):
});
}
-AndroidRunConfigurationWidget::~AndroidRunConfigurationWidget()
-{
-}
+AndroidRunConfigurationWidget::~AndroidRunConfigurationWidget() = default;
void AndroidRunConfigurationWidget::setAmStartArgs(const QStringList &args)
{
diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp
index 04d87284af..5eaaaf5241 100644
--- a/src/plugins/android/androidrunner.cpp
+++ b/src/plugins/android/androidrunner.cpp
@@ -223,11 +223,8 @@ public:
void setAndroidRunnable(const AndroidRunnable &runnable);
void handleRemoteDebuggerRunning();
- Utils::Port localGdbServerPort() const { return m_localGdbServerPort; }
-
signals:
- void remoteProcessStarted(Utils::Port gdbServerPort, Utils::Port qmlServerPort,
- QString qmlServerHost, int pid);
+ void remoteProcessStarted(Utils::Port gdbServerPort, const QUrl &qmlServer, int pid);
void remoteProcessFinished(const QString &errString = QString());
void remoteOutput(const QString &output);
@@ -258,8 +255,7 @@ private:
bool m_useCppDebugger = false;
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
Utils::Port m_localGdbServerPort; // Local end of forwarded debug socket.
- QString m_qmlServerHost;
- Utils::Port m_qmlPort;
+ QUrl m_qmlServer;
QString m_pingFile;
QString m_pongFile;
QString m_gdbserverPath;
@@ -297,10 +293,9 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunControl *runControl, const AndroidRu
QTC_ASSERT(server.listen(QHostAddress::LocalHost)
|| server.listen(QHostAddress::LocalHostIPv6),
qDebug() << tr("No free ports available on host for QML debugging."));
- m_qmlServerHost = server.serverAddress().toString();
- m_qmlPort = Utils::Port(server.serverPort());
- } else {
- m_qmlPort = Utils::Port();
+ m_qmlServer.setScheme(urlTcpScheme());
+ m_qmlServer.setHost(server.serverAddress().toString());
+ m_qmlServer.setPort(server.serverPort());
}
m_adb = AndroidConfigurations::currentConfig().adbToolPath().toString();
@@ -418,7 +413,7 @@ void AndroidRunnerWorker::asyncStart()
if (m_qmlDebugServices != QmlDebug::NoQmlDebugServices) {
// currently forward to same port on device and host
- const QString port = QString("tcp:%1").arg(m_qmlPort.number());
+ const QString port = QString("tcp:%1").arg(m_qmlServer.port());
if (!runAdb({"forward", port, port}, &errorMessage)) {
emit remoteProcessFinished(tr("Failed to forward QML debugging ports. Reason: %1.")
.arg(errorMessage));
@@ -428,7 +423,7 @@ void AndroidRunnerWorker::asyncStart()
args << "-e" << "qml_debug" << "true"
<< "-e" << "qmljsdebugger"
<< QString("port:%1,block,services:%2")
- .arg(m_qmlPort.number()).arg(QmlDebug::qmlDebugServices(m_qmlDebugServices));
+ .arg(m_qmlServer.port()).arg(QmlDebug::qmlDebugServices(m_qmlDebugServices));
}
if (!runAdb(args, &errorMessage)) {
@@ -641,7 +636,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
} else {
// In debugging cases this will be funneled to the engine to actually start
// and attach gdb. Afterwards this ends up in handleRemoteDebuggerRunning() below.
- emit remoteProcessStarted(m_localGdbServerPort, m_qmlPort, m_qmlServerHost, m_processPID);
+ emit remoteProcessStarted(m_localGdbServerPort, m_qmlServer, m_processPID);
logcatReadStandardOutput();
QTC_ASSERT(!m_psIsAlive, /**/);
m_psIsAlive.reset(new QProcess);
@@ -785,13 +780,12 @@ void AndroidRunner::remoteErrorOutput(const QString &output)
m_outputParser.processOutput(output);
}
-void AndroidRunner::handleRemoteProcessStarted(Utils::Port gdbServerPort, Utils::Port qmlServerPort,
- QString qmlServerHost, int pid)
+void AndroidRunner::handleRemoteProcessStarted(Utils::Port gdbServerPort,
+ const QUrl &qmlServer, int pid)
{
m_pid = ProcessHandle(pid);
m_gdbServerPort = gdbServerPort;
- m_qmlServerHost = qmlServerHost;
- m_qmlServerPort = qmlServerPort;
+ m_qmlServer = qmlServer;
reportStarted();
}
@@ -821,8 +815,7 @@ void AndroidRunner::launchAVD()
// Get AVD info.
AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(
- m_target->project(), deviceAPILevel, targetArch,
- AndroidConfigurations::None);
+ m_target->project(), deviceAPILevel, targetArch);
AndroidManager::setDeviceSerialNumber(m_target, info.serialNumber);
m_androidRunnable.deviceSerialNumber = info.serialNumber;
emit androidRunnableChanged(m_androidRunnable);
diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h
index 6215cc49a5..c878f95e9a 100644
--- a/src/plugins/android/androidrunner.h
+++ b/src/plugins/android/androidrunner.h
@@ -57,8 +57,7 @@ public:
const AndroidRunnable &runnable() const { return m_androidRunnable; }
Utils::Port gdbServerPort() const { return m_gdbServerPort; }
- QString qmlServerHost() const { return m_qmlServerHost; }
- Utils::Port qmlServerPort() const { return m_qmlServerPort; }
+ QUrl qmlServer() const { return m_qmlServer; }
Utils::ProcessHandle pid() const { return m_pid; }
void start() override;
@@ -77,8 +76,7 @@ private:
void remoteOutput(const QString &output);
void remoteErrorOutput(const QString &output);
void gotRemoteOutput(const QString &output);
- void handleRemoteProcessStarted(Utils::Port gdbServerPort, Utils::Port qmlServerPort,
- QString qmlServerHost, int pid);
+ void handleRemoteProcessStarted(Utils::Port gdbServerPort, const QUrl &qmlServer, int pid);
void handleRemoteProcessFinished(const QString &errString = QString());
void checkAVD();
void launchAVD();
@@ -90,8 +88,7 @@ private:
QScopedPointer<AndroidRunnerWorker> m_worker;
QPointer<ProjectExplorer::Target> m_target;
Utils::Port m_gdbServerPort;
- QString m_qmlServerHost;
- Utils::Port m_qmlServerPort;
+ QUrl m_qmlServer;
Utils::ProcessHandle m_pid;
QmlDebug::QmlOutputParser m_outputParser;
};
diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp
index 85903aa1ad..ac518bdd21 100644
--- a/src/plugins/android/androidsdkmanager.cpp
+++ b/src/plugins/android/androidsdkmanager.cpp
@@ -83,12 +83,9 @@ static bool sdkManagerCommand(const AndroidConfig config, const QStringList &arg
proc.setTimeoutS(timeout);
proc.setTimeOutMessageBoxEnabled(true);
SynchronousProcessResponse response = proc.run(sdkManagerToolPath, args);
- if (response.result == SynchronousProcessResponse::Finished) {
- if (output)
- *output = response.allOutput();
- return true;
- }
- return false;
+ if (output)
+ *output = response.allOutput();
+ return response.result == SynchronousProcessResponse::Finished;
}
/*!
diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp
index a0a24ea087..d5c49623b1 100644
--- a/src/plugins/android/androidsettingswidget.cpp
+++ b/src/plugins/android/androidsettingswidget.cpp
@@ -134,37 +134,11 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
{
m_ui->setupUi(this);
- m_ui->deprecatedInfoIconLabel->setPixmap(Utils::Icons::INFO.pixmap());
-
- connect(&m_checkGdbWatcher, &QFutureWatcherBase::finished,
- this, &AndroidSettingsWidget::checkGdbFinished);
-
m_ui->SDKLocationPathChooser->setFileName(m_androidConfig.sdkLocation());
m_ui->SDKLocationPathChooser->setPromptDialogTitle(tr("Select Android SDK folder"));
m_ui->NDKLocationPathChooser->setFileName(m_androidConfig.ndkLocation());
m_ui->NDKLocationPathChooser->setPromptDialogTitle(tr("Select Android NDK folder"));
- QString dir;
- QString filter;
- if (Utils::HostOsInfo::isWindowsHost()) {
- dir = QDir::homePath() + QLatin1String("/ant.bat");
- filter = QLatin1String("ant (ant.bat)");
- } else if (Utils::HostOsInfo::isMacHost()) {
- // work around QTBUG-7739 that prohibits filters that don't start with *
- dir = QLatin1String("/usr/bin/ant");
- filter = QLatin1String("ant (*ant)");
- } else {
- dir = QLatin1String("/usr/bin/ant");
- filter = QLatin1String("ant (ant)");
- }
- m_ui->AntLocationPathChooser->setFileName(m_androidConfig.antLocation());
- m_ui->AntLocationPathChooser->setExpectedKind(Utils::PathChooser::Command);
- m_ui->AntLocationPathChooser->setPromptDialogTitle(tr("Select ant Script"));
- m_ui->AntLocationPathChooser->setInitialBrowsePathBackup(dir);
- m_ui->AntLocationPathChooser->setPromptDialogFilter(filter);
-
- updateGradleBuildUi();
-
m_ui->OpenJDKLocationPathChooser->setFileName(m_androidConfig.openJDKLocation());
m_ui->OpenJDKLocationPathChooser->setPromptDialogTitle(tr("Select JDK Path"));
m_ui->DataPartitionSizeSpinBox->setValue(m_androidConfig.partitionSize());
@@ -173,7 +147,6 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
m_ui->AVDTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_ui->AVDTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
- m_ui->downloadAntToolButton->setVisible(!Utils::HostOsInfo::isLinuxHost());
m_ui->downloadOpenJDKToolButton->setVisible(!Utils::HostOsInfo::isLinuxHost());
const QPixmap warningPixmap = Utils::Icons::WARNING.pixmap();
@@ -182,12 +155,8 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
const QPixmap errorPixmap = Utils::Icons::CRITICAL.pixmap();
m_ui->sdkWarningIconLabel->setPixmap(errorPixmap);
- m_ui->gdbWarningIconLabel->setPixmap(errorPixmap);
m_ui->ndkWarningIconLabel->setPixmap(errorPixmap);
- connect(m_ui->gdbWarningLabel, &QLabel::linkActivated,
- this, &AndroidSettingsWidget::showGdbWarningDialog);
-
connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished,
this, &AndroidSettingsWidget::updateAvds);
@@ -201,8 +170,6 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
this, &AndroidSettingsWidget::ndkLocationEditingFinished);
connect(m_ui->SDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
this, &AndroidSettingsWidget::sdkLocationEditingFinished);
- connect(m_ui->AntLocationPathChooser, &Utils::PathChooser::rawPathChanged,
- this, &AndroidSettingsWidget::antLocationEditingFinished);
connect(m_ui->OpenJDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
this, &AndroidSettingsWidget::openJDKLocationEditingFinished);
connect(m_ui->AVDAddPushButton, &QAbstractButton::clicked,
@@ -225,13 +192,8 @@ AndroidSettingsWidget::AndroidSettingsWidget(QWidget *parent)
this, &AndroidSettingsWidget::openSDKDownloadUrl);
connect(m_ui->downloadNDKToolButton, &QAbstractButton::clicked,
this, &AndroidSettingsWidget::openNDKDownloadUrl);
- connect(m_ui->downloadAntToolButton, &QAbstractButton::clicked,
- this, &AndroidSettingsWidget::openAntDownloadUrl);
connect(m_ui->downloadOpenJDKToolButton, &QAbstractButton::clicked,
this, &AndroidSettingsWidget::openOpenJDKDownloadUrl);
- connect(m_ui->UseGradleCheckBox, &QAbstractButton::toggled,
- this, &AndroidSettingsWidget::useGradleToggled);
-
}
AndroidSettingsWidget::~AndroidSettingsWidget()
@@ -240,58 +202,10 @@ AndroidSettingsWidget::~AndroidSettingsWidget()
m_futureWatcher.waitForFinished();
}
-// NOTE: Will be run via QFuture
-static QPair<QStringList, bool> checkGdbForBrokenPython(const QStringList &paths)
-{
- foreach (const QString &path, paths) {
- QTime timer;
- timer.start();
- QProcess proc;
- proc.setProcessChannelMode(QProcess::MergedChannels);
- proc.start(path);
- proc.waitForStarted();
-
- QByteArray output;
- while (proc.waitForReadyRead(300)) {
- output += proc.readAll();
- if (output.contains("(gdb)"))
- break;
- if (timer.elapsed() > 7 * 1000)
- return qMakePair(paths, true); // Took too long, abort
- }
-
- output.clear();
-
- proc.write("python import string\n");
- proc.write("python print(string.ascii_uppercase)\n");
- proc.write("python import struct\n");
- proc.write("quit\n");
- while (proc.waitForFinished(300)) {
- if (timer.elapsed() > 9 * 1000)
- return qMakePair(paths, true); // Took too long, abort
- }
- proc.waitForFinished();
-
- output = proc.readAll();
-
- bool error = output.contains("_PyObject_Free")
- || output.contains("_PyExc_IOError")
- || output.contains("_sysconfigdata_nd ")
- || !output.contains("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- if (error)
- return qMakePair(paths, error);
- }
- return qMakePair(paths, false);
-}
-
void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
{
if (mode & Sdk) {
- m_sdkState = Okay;
- if (m_androidConfig.sdkLocation().isEmpty())
- m_sdkState = NotSet;
- else if (!(sdkLocationIsValid() && sdkPlatformToolsInstalled()))
- m_sdkState = Error;
+ m_sdkState = verifySdkInstallation(&m_sdkInstallationError) ? Okay : Error;
}
if (mode & Ndk) {
@@ -299,8 +213,6 @@ void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
Utils::FileName platformPath = m_androidConfig.ndkLocation();
Utils::FileName toolChainPath = m_androidConfig.ndkLocation();
Utils::FileName sourcesPath = m_androidConfig.ndkLocation();
- m_ui->gdbWarningIconLabel->setVisible(false);
- m_ui->gdbWarningLabel->setVisible(false);
if (m_androidConfig.ndkLocation().isEmpty()) {
m_ndkState = NotSet;
} else if (!platformPath.appendPath(QLatin1String("platforms")).exists()
@@ -317,24 +229,6 @@ void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
= AndroidToolChainFactory::toolchainPathsForNdk(m_androidConfig.ndkLocation());
m_ndkCompilerCount = compilerPaths.count();
- // Check for a gdb with a broken python
- QStringList gdbPaths;
- foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
- if (ati.language == Core::Id(ProjectExplorer::Constants::C_LANGUAGE_ID))
- continue;
- // we only check the arm gdbs, that's indicative enough
- if (ati.abi.architecture() != ProjectExplorer::Abi::ArmArchitecture)
- continue;
- Utils::FileName gdbPath = m_androidConfig.gdbPath(ati.abi, ati.version);
- if (gdbPath.exists())
- gdbPaths << gdbPath.toString();
- }
-
- if (!gdbPaths.isEmpty()) {
- m_checkGdbWatcher.setFuture(Utils::runAsync(&checkGdbForBrokenPython, gdbPaths));
- m_gdbCheckPaths = gdbPaths;
- }
-
// See if we have qt versions for those toolchains
QSet<ProjectExplorer::Abi> toolchainsForAbi;
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
@@ -386,11 +280,7 @@ void AndroidSettingsWidget::applyToUi(AndroidSettingsWidget::Mode mode)
if (m_sdkState == Error) {
m_ui->sdkWarningIconLabel->setVisible(true);
m_ui->sdkWarningLabel->setVisible(true);
- Utils::FileName location = Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath());
- if (sdkLocationIsValid())
- m_ui->sdkWarningLabel->setText(tr("The Platform tools are missing. Please use the Android SDK Manager to install them."));
- else
- m_ui->sdkWarningLabel->setText(tr("\"%1\" does not seem to be an Android SDK top folder.").arg(location.toUserOutput()));
+ m_ui->sdkWarningLabel->setText(m_sdkInstallationError);
} else {
m_ui->sdkWarningIconLabel->setVisible(false);
m_ui->sdkWarningLabel->setVisible(false);
@@ -481,34 +371,48 @@ void AndroidSettingsWidget::updateAvds()
enableAvdControls();
}
-void AndroidSettingsWidget::updateGradleBuildUi()
+bool AndroidSettingsWidget::verifySdkInstallation(QString *errorDetails) const
{
- m_ui->UseGradleCheckBox->setEnabled(m_androidConfig.antScriptsAvailable());
- m_ui->UseGradleCheckBox->setChecked(!m_androidConfig.antScriptsAvailable() ||
- m_androidConfig.useGrandle());
-}
+ if (m_androidConfig.sdkLocation().isEmpty()) {
+ if (errorDetails)
+ *errorDetails = tr("Android SDK path not set.");
+ return false;
+ }
-bool AndroidSettingsWidget::sdkLocationIsValid() const
-{
- Utils::FileName androidExe = m_androidConfig.sdkLocation();
- Utils::FileName androidBat = m_androidConfig.sdkLocation();
- Utils::FileName emulator = m_androidConfig.sdkLocation();
- return (androidExe.appendPath(QLatin1String("/tools/android" QTC_HOST_EXE_SUFFIX)).exists()
- || androidBat.appendPath(QLatin1String("/tools/android" ANDROID_BAT_SUFFIX)).exists())
- && emulator.appendPath(QLatin1String("/tools/emulator" QTC_HOST_EXE_SUFFIX)).exists();
-}
+ if (!m_androidConfig.sdkLocation().exists()) {
+ if (errorDetails)
+ *errorDetails = tr("Android SDK path does not exist.");
+ return false;
+ }
-bool AndroidSettingsWidget::sdkPlatformToolsInstalled() const
-{
- Utils::FileName adb = m_androidConfig.sdkLocation();
- return adb.appendPath(QLatin1String("platform-tools/adb" QTC_HOST_EXE_SUFFIX)).exists();
+ if (m_androidConfig.sdkToolsVersion().isNull()) {
+ if (errorDetails)
+ *errorDetails = tr("The SDK path does not seem to be a valid Android SDK top folder.");
+ return false;
+ }
+
+ QStringList missingComponents;
+ if (!m_androidConfig.adbToolPath().exists())
+ missingComponents << "Platform Tools";
+
+ if (m_androidConfig.buildToolsVersion().isNull())
+ missingComponents << "Build Tools";
+
+ if (m_androidConfig.sdkTargets().isEmpty())
+ missingComponents << "Platform SDK";
+
+ if (!missingComponents.isEmpty() && errorDetails) {
+ *errorDetails = tr("Android SDK components missing (%1).\nUse Android SDK Manager to "
+ "manage SDK components.").arg(missingComponents.join(", "));
+ }
+
+ return missingComponents.isEmpty();
}
void AndroidSettingsWidget::saveSettings()
{
sdkLocationEditingFinished();
ndkLocationEditingFinished();
- antLocationEditingFinished();
openJDKLocationEditingFinished();
dataPartitionSizeEditingFinished();
AndroidConfigurations::setConfig(m_androidConfig);
@@ -517,13 +421,8 @@ void AndroidSettingsWidget::saveSettings()
void AndroidSettingsWidget::sdkLocationEditingFinished()
{
m_androidConfig.setSdkLocation(Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath()));
- updateGradleBuildUi();
check(Sdk);
-
- if (m_sdkState == Okay)
- searchForAnt(m_androidConfig.sdkLocation());
-
applyToUi(Sdk);
}
@@ -532,41 +431,9 @@ void AndroidSettingsWidget::ndkLocationEditingFinished()
m_androidConfig.setNdkLocation(Utils::FileName::fromUserInput(m_ui->NDKLocationPathChooser->rawPath()));
check(Ndk);
-
- if (m_ndkState == Okay)
- searchForAnt(m_androidConfig.ndkLocation());
-
applyToUi(Ndk);
}
-void AndroidSettingsWidget::searchForAnt(const Utils::FileName &location)
-{
- if (!m_androidConfig.antLocation().isEmpty())
- return;
- if (location.isEmpty())
- return;
- QDir parentFolder = location.toFileInfo().absoluteDir();
- foreach (const QString &file, parentFolder.entryList()) {
- if (file.startsWith(QLatin1String("apache-ant"))) {
- Utils::FileName ant = Utils::FileName::fromString(parentFolder.absolutePath());
- ant.appendPath(file).appendPath(QLatin1String("bin"));
- if (Utils::HostOsInfo::isWindowsHost())
- ant.appendPath(QLatin1String("ant.bat"));
- else
- ant.appendPath(QLatin1String("ant"));
- if (ant.exists()) {
- m_androidConfig.setAntLocation(ant);
- m_ui->AntLocationPathChooser->setFileName(ant);
- }
- }
- }
-}
-
-void AndroidSettingsWidget::antLocationEditingFinished()
-{
- m_androidConfig.setAntLocation(Utils::FileName::fromUserInput(m_ui->AntLocationPathChooser->rawPath()));
-}
-
void AndroidSettingsWidget::openJDKLocationEditingFinished()
{
m_androidConfig.setOpenJDKLocation(Utils::FileName::fromUserInput(m_ui->OpenJDKLocationPathChooser->rawPath()));
@@ -585,11 +452,6 @@ void AndroidSettingsWidget::openNDKDownloadUrl()
QDesktopServices::openUrl(QUrl::fromUserInput("https://developer.android.com/ndk/downloads/"));
}
-void AndroidSettingsWidget::openAntDownloadUrl()
-{
- QDesktopServices::openUrl(QUrl::fromUserInput("http://ant.apache.org/bindownload.cgi"));
-}
-
void AndroidSettingsWidget::openOpenJDKDownloadUrl()
{
QDesktopServices::openUrl(QUrl::fromUserInput("http://www.oracle.com/technetwork/java/javase/downloads/"));
@@ -658,30 +520,6 @@ void AndroidSettingsWidget::createKitToggled()
m_androidConfig.setAutomaticKitCreation(m_ui->CreateKitCheckBox->isChecked());
}
-void AndroidSettingsWidget::useGradleToggled()
-{
- m_androidConfig.setUseGradle(m_ui->UseGradleCheckBox->isChecked());
-}
-
-void AndroidSettingsWidget::checkGdbFinished()
-{
- QPair<QStringList, bool> result = m_checkGdbWatcher.future().result();
- if (result.first != m_gdbCheckPaths) // no longer relevant
- return;
- m_ui->gdbWarningIconLabel->setVisible(result.second);
- m_ui->gdbWarningLabel->setVisible(result.second);
-}
-
-void AndroidSettingsWidget::showGdbWarningDialog()
-{
- QMessageBox::warning(this,
- tr("Unsupported GDB"),
- tr("The GDB inside this NDK seems to not support Python. "
- "The Qt Project offers fixed GDB builds at: "
- "<a href=\"http://download.qt.io/official_releases/gdb/\">"
- "http://download.qt.io/official_releases/gdb/</a>"));
-}
-
void AndroidSettingsWidget::manageAVD()
{
if (m_avdManager->avdManagerUiToolAvailable()) {
diff --git a/src/plugins/android/androidsettingswidget.h b/src/plugins/android/androidsettingswidget.h
index 50be7c1049..3212754365 100644
--- a/src/plugins/android/androidsettingswidget.h
+++ b/src/plugins/android/androidsettingswidget.h
@@ -75,12 +75,9 @@ public:
private:
void sdkLocationEditingFinished();
void ndkLocationEditingFinished();
- void searchForAnt(const Utils::FileName &location);
- void antLocationEditingFinished();
void openJDKLocationEditingFinished();
void openSDKDownloadUrl();
void openNDKDownloadUrl();
- void openAntDownloadUrl();
void openOpenJDKDownloadUrl();
void addAVD();
void avdAdded();
@@ -90,25 +87,21 @@ private:
void dataPartitionSizeEditingFinished();
void manageAVD();
void createKitToggled();
- void useGradleToggled();
- void checkGdbFinished();
- void showGdbWarningDialog();
void updateAvds();
- void updateGradleBuildUi();
private:
enum Mode { Sdk = 1, Ndk = 2, Java = 4, All = Sdk | Ndk | Java };
enum State { NotSet = 0, Okay = 1, Error = 2 };
+ bool verifySdkInstallation(QString *errorDetails = nullptr) const;
void check(Mode mode);
void applyToUi(Mode mode);
- bool sdkLocationIsValid() const;
- bool sdkPlatformToolsInstalled() const;
void startUpdateAvd();
void enableAvdControls();
void disableAvdControls();
State m_sdkState;
+ QString m_sdkInstallationError;
State m_ndkState;
QString m_ndkErrorMessage;
int m_ndkCompilerCount;
@@ -119,8 +112,6 @@ private:
AndroidConfig m_androidConfig;
AvdModel m_AVDModel;
QFutureWatcher<AndroidConfig::CreateAvdInfo> m_futureWatcher;
- QFutureWatcher<QPair<QStringList, bool>> m_checkGdbWatcher;
- QStringList m_gdbCheckPaths;
QFutureWatcher<AndroidDeviceInfoList> m_virtualDevicesWatcher;
QString m_lastAddedAvd;
diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui
index 338c73da04..0d8bcb774d 100644
--- a/src/plugins/android/androidsettingswidget.ui
+++ b/src/plugins/android/androidsettingswidget.ui
@@ -14,25 +14,134 @@
<string>Android Configuration</string>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="OpenJDKLocationLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>JDK location:</string>
+ <item row="9" column="0" colspan="2">
+ <widget class="QFrame" name="AVDManagerFrame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
</property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
</property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="3" column="1">
+ <widget class="QPushButton" name="AVDStartPushButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Start...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="AVDManagerLabel">
+ <property name="text">
+ <string>AVD Manager</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="DataPartitionSizeLable">
+ <property name="text">
+ <string>System/data partition size:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="DataPartitionSizeSpinBox">
+ <property name="suffix">
+ <string> Mb</string>
+ </property>
+ <property name="maximum">
+ <number>99999</number>
+ </property>
+ <property name="value">
+ <number>1024</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="manageAVDPushButton">
+ <property name="text">
+ <string>Start AVD Manager...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="AVDRemovePushButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="AVDAddPushButton">
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" rowspan="4">
+ <widget class="QTableView" name="AVDTableView">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideMiddle</enum>
+ </property>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>129</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::PathChooser" name="OpenJDKLocationPathChooser" native="true"/>
</item>
+ <item row="2" column="1">
+ <widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true"/>
+ </item>
+ <item row="4" column="1">
+ <widget class="Utils::PathChooser" name="NDKLocationPathChooser" native="true"/>
+ </item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
@@ -66,10 +175,10 @@
</item>
</layout>
</item>
- <item row="0" column="2">
- <widget class="QToolButton" name="downloadOpenJDKToolButton">
+ <item row="4" column="2">
+ <widget class="QToolButton" name="downloadNDKToolButton">
<property name="toolTip">
- <string>Download JDK</string>
+ <string>Download Android NDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
@@ -93,13 +202,10 @@
</property>
</widget>
</item>
- <item row="2" column="1">
- <widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true"/>
- </item>
- <item row="2" column="2">
- <widget class="QToolButton" name="downloadSDKToolButton">
+ <item row="0" column="2">
+ <widget class="QToolButton" name="downloadOpenJDKToolButton">
<property name="toolTip">
- <string>Download Android SDK</string>
+ <string>Download JDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
@@ -107,62 +213,10 @@
</property>
</widget>
</item>
- <item row="3" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QLabel" name="sdkWarningIconLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="sdkWarningLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="NDKLocationLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Android NDK location:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="Utils::PathChooser" name="NDKLocationPathChooser" native="true"/>
- </item>
- <item row="4" column="2">
- <widget class="QToolButton" name="downloadNDKToolButton">
+ <item row="2" column="2">
+ <widget class="QToolButton" name="downloadSDKToolButton">
<property name="toolTip">
- <string>Download Android NDK</string>
+ <string>Download Android SDK</string>
</property>
<property name="icon">
<iconset resource="android.qrc">
@@ -170,13 +224,13 @@
</property>
</widget>
</item>
- <item row="5" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item row="8" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<item>
- <widget class="QLabel" name="gdbWarningIconLabel">
+ <widget class="QLabel" name="kitWarningIconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -189,29 +243,9 @@
</widget>
</item>
<item>
- <widget class="QLabel" name="gdbWarningLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>&lt;a href=&quot;xx&quot;&gt;The GDB in the NDK appears to have broken python support.&lt;/a&gt;</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="6" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <property name="spacing">
- <number>2</number>
- </property>
- <item>
- <widget class="QLabel" name="ndkWarningIconLabel">
+ <widget class="QLabel" name="kitWarningLabel">
<property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -219,24 +253,14 @@
<property name="text">
<string/>
</property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="toolchainFoundLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
+ <property name="wordWrap">
+ <bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
- <item row="8" column="1">
+ <item row="7" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="spacing">
<number>2</number>
@@ -262,13 +286,29 @@
</item>
</layout>
</item>
- <item row="9" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item row="4" column="0">
+ <widget class="QLabel" name="NDKLocationLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Android NDK location:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>2</number>
</property>
<item>
- <widget class="QLabel" name="kitWarningIconLabel">
+ <widget class="QLabel" name="ndkWarningIconLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -281,9 +321,9 @@
</widget>
</item>
<item>
- <widget class="QLabel" name="kitWarningLabel">
+ <widget class="QLabel" name="toolchainFoundLabel">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -291,70 +331,45 @@
<property name="text">
<string/>
</property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
</widget>
</item>
</layout>
</item>
- <item row="10" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout_7">
- <property name="spacing">
- <number>4</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
+ <item row="3" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
- <widget class="QCheckBox" name="UseGradleCheckBox">
+ <widget class="QLabel" name="sdkWarningIconLabel">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
- <string>Use Gradle instead of Ant (Ant builds are deprecated)</string>
- </property>
- <property name="checked">
- <bool>true</bool>
+ <string/>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="deprecatedInfoIconLabel">
+ <widget class="QLabel" name="sdkWarningLabel">
<property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="toolTip">
- <string>Gradle builds are forced from Android SDK tools version 25.3.0 onwards as Ant scripts are no longer available.</string>
- </property>
<property name="text">
<string/>
</property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
+ <property name="wordWrap">
+ <bool>true</bool>
</property>
- </spacer>
+ </widget>
</item>
</layout>
</item>
- <item row="11" column="0">
- <widget class="QLabel" name="AntLocationLabel">
+ <item row="0" column="0">
+ <widget class="QLabel" name="OpenJDKLocationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -362,146 +377,13 @@
</sizepolicy>
</property>
<property name="text">
- <string>Ant executable:</string>
+ <string>JDK location:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
- <item row="11" column="1">
- <widget class="Utils::PathChooser" name="AntLocationPathChooser" native="true"/>
- </item>
- <item row="11" column="2">
- <widget class="QToolButton" name="downloadAntToolButton">
- <property name="toolTip">
- <string>Download Ant</string>
- </property>
- <property name="icon">
- <iconset resource="android.qrc">
- <normaloff>:/android/images/download.png</normaloff>:/android/images/download.png</iconset>
- </property>
- </widget>
- </item>
- <item row="12" column="0" colspan="2">
- <widget class="QFrame" name="AVDManagerFrame">
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="3" column="1">
- <widget class="QPushButton" name="AVDStartPushButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Start...</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLabel" name="AVDManagerLabel">
- <property name="text">
- <string>AVD Manager</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="DataPartitionSizeLable">
- <property name="text">
- <string>System/data partition size:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="DataPartitionSizeSpinBox">
- <property name="suffix">
- <string> Mb</string>
- </property>
- <property name="maximum">
- <number>99999</number>
- </property>
- <property name="value">
- <number>1024</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="manageAVDPushButton">
- <property name="text">
- <string>Start AVD Manager...</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="2" column="1">
- <widget class="QPushButton" name="AVDRemovePushButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Remove</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QPushButton" name="AVDAddPushButton">
- <property name="text">
- <string>Add...</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0" rowspan="4">
- <widget class="QTableView" name="AVDTableView">
- <property name="selectionMode">
- <enum>QAbstractItemView::SingleSelection</enum>
- </property>
- <property name="selectionBehavior">
- <enum>QAbstractItemView::SelectRows</enum>
- </property>
- <property name="textElideMode">
- <enum>Qt::ElideMiddle</enum>
- </property>
- <attribute name="verticalHeaderVisible">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- <item row="4" column="1">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>129</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
</layout>
</widget>
<customwidgets>
diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp
index bb3b10ee92..3d89d3018d 100644
--- a/src/plugins/android/androidtoolchain.cpp
+++ b/src/plugins/android/androidtoolchain.cpp
@@ -213,7 +213,7 @@ QString AndroidToolChain::makeCommand(const Environment &env) const
if (HostOsInfo::isWindowsHost()) {
FileName tmp = env.searchInPath(QLatin1String("ma-make.exe"), extraDirectories);
if (!tmp.isEmpty())
- return QString();
+ return tmp.toString();
tmp = env.searchInPath(QLatin1String("mingw32-make"), extraDirectories);
return tmp.isEmpty() ? QLatin1String("mingw32-make") : tmp.toString();
}
diff --git a/src/plugins/android/images/androiddevice.png b/src/plugins/android/images/androiddevice.png
index f72af6020b..fd68e6aa3a 100644
--- a/src/plugins/android/images/androiddevice.png
+++ b/src/plugins/android/images/androiddevice.png
Binary files differ
diff --git a/src/plugins/android/images/androiddevice@2x.png b/src/plugins/android/images/androiddevice@2x.png
index 1a2116ba3e..b76fa15177 100644
--- a/src/plugins/android/images/androiddevice@2x.png
+++ b/src/plugins/android/images/androiddevice@2x.png
Binary files differ
diff --git a/src/plugins/autotest/autotest.qrc b/src/plugins/autotest/autotest.qrc
index a62ab49d8f..554a14344e 100644
--- a/src/plugins/autotest/autotest.qrc
+++ b/src/plugins/autotest/autotest.qrc
@@ -6,6 +6,7 @@
<file>images/leafsort.png</file>
<file>images/leafsort@2x.png</file>
<file>images/benchmark.png</file>
+ <file>images/benchmark@2x.png</file>
<file>images/runselected_boxes.png</file>
<file>images/runselected_boxes@2x.png</file>
<file>images/runselected_tickmarks.png</file>
diff --git a/src/plugins/autotest/autotestconstants.h b/src/plugins/autotest/autotestconstants.h
index 7c1aaa0dac..5a1accdde7 100644
--- a/src/plugins/autotest/autotestconstants.h
+++ b/src/plugins/autotest/autotestconstants.h
@@ -39,10 +39,20 @@ const char AUTOTEST_CONTEXT[] = "Auto Tests";
const char TASK_INDEX[] = "AutoTest.Task.Index";
const char TASK_PARSE[] = "AutoTest.Task.Parse";
const char AUTOTEST_SETTINGS_CATEGORY[] = "ZY.Tests";
-const char AUTOTEST_SETTINGS_TR[] = QT_TRANSLATE_NOOP("AutoTest", "Test Settings");
+const char AUTOTEST_SETTINGS_TR[] = QT_TRANSLATE_NOOP("AutoTest", "Testing");
const char FRAMEWORK_PREFIX[] = "AutoTest.Framework.";
const char SETTINGSPAGE_PREFIX[] = "A.AutoTest.";
const char SETTINGSGROUP[] = "Autotest";
} // namespace Constants
+
+namespace Internal {
+enum class TestRunMode
+{
+ Run,
+ RunWithoutDeploy,
+ Debug,
+ DebugWithoutDeploy
+};
+} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h
index 1420be31ad..632fc375e1 100644
--- a/src/plugins/autotest/autotesticons.h
+++ b/src/plugins/autotest/autotesticons.h
@@ -61,7 +61,9 @@ const Utils::Icon RESULT_BLACKLISTEDFAIL({
{":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestFailTextColor},
{":/projectexplorer/images/buildstepdisable.png", Utils::Theme::PanelTextColorDark}},
Utils::Icon::Tint | Utils::Icon::PunchEdges);
-const Utils::Icon RESULT_BENCHMARK(":/images/benchmark.png");
+const Utils::Icon RESULT_BENCHMARK({
+ {":/utils/images/filledcircle.png", Utils::Theme::BackgroundColorNormal},
+ {":/images/benchmark.png", Utils::Theme::PanelTextColorDark}}, Utils::Icon::Tint);
const Utils::Icon RESULT_MESSAGEDEBUG({
{":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestDebugTextColor}},
Utils::Icon::Tint);
diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp
index 3d00400ccd..316667ddf3 100644
--- a/src/plugins/autotest/autotestplugin.cpp
+++ b/src/plugins/autotest/autotestplugin.cpp
@@ -116,7 +116,7 @@ void AutotestPlugin::initializeMenuEntries()
action = new QAction(tr("Re&scan Tests"), this);
command = ActionManager::registerAction(action, Constants::ACTION_SCAN_ID);
command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+S")));
- connect(action, &QAction::triggered, [this] () {
+ connect(action, &QAction::triggered, this, [] () {
TestTreeModel::instance()->parser()->updateTestTree();
});
menu->addAction(command);
@@ -170,7 +170,7 @@ void AutotestPlugin::onRunAllTriggered()
TestRunner *runner = TestRunner::instance();
TestTreeModel *model = TestTreeModel::instance();
runner->setSelectedTests(model->getAllTestCases());
- runner->prepareToRunTests(TestRunner::Run);
+ runner->prepareToRunTests(TestRunMode::Run);
}
void AutotestPlugin::onRunSelectedTriggered()
@@ -178,7 +178,7 @@ void AutotestPlugin::onRunSelectedTriggered()
TestRunner *runner = TestRunner::instance();
TestTreeModel *model = TestTreeModel::instance();
runner->setSelectedTests(model->getSelectedTests());
- runner->prepareToRunTests(TestRunner::Run);
+ runner->prepareToRunTests(TestRunMode::Run);
}
void AutotestPlugin::updateMenuItemsEnabledState()
diff --git a/src/plugins/autotest/gtest/gtestconfiguration.cpp b/src/plugins/autotest/gtest/gtestconfiguration.cpp
index 7be52a69c1..3e146f2db7 100644
--- a/src/plugins/autotest/gtest/gtestconfiguration.cpp
+++ b/src/plugins/autotest/gtest/gtestconfiguration.cpp
@@ -27,7 +27,11 @@
#include "gtestconstants.h"
#include "gtestoutputreader.h"
#include "gtestsettings.h"
+#include "../autotestplugin.h"
#include "../testframeworkmanager.h"
+#include "../testsettings.h"
+
+#include <utils/algorithm.h>
namespace Autotest {
namespace Internal {
@@ -38,12 +42,46 @@ TestOutputReader *GTestConfiguration::outputReader(const QFutureInterface<TestRe
return new GTestOutputReader(fi, app, buildDirectory(), projectFile());
}
-QStringList GTestConfiguration::argumentsForTestRunner() const
+QStringList filterInterfering(const QStringList &provided, QStringList *omitted)
+{
+ static const QSet<QString> knownInterferingOptions { "--gtest_list_tests",
+ "--gtest_filter=",
+ "--gtest_also_run_disabled_tests",
+ "--gtest_repeat=",
+ "--gtest_shuffle",
+ "--gtest_random_seed=",
+ "--gtest_output=",
+ "--gtest_stream_result_to=",
+ "--gtest_break_on_failure",
+ "--gtest_throw_on_failure",
+ "--gtest_color="
+ };
+
+ QSet<QString> allowed = Utils::filtered(provided.toSet(), [] (const QString &arg) {
+ return Utils::allOf(knownInterferingOptions, [&arg] (const QString &interfering) {
+ return !arg.startsWith(interfering);
+ });
+ });
+
+ if (omitted) {
+ QSet<QString> providedSet = provided.toSet();
+ providedSet.subtract(allowed);
+ omitted->append(providedSet.toList());
+ }
+ return allowed.toList();
+}
+
+QStringList GTestConfiguration::argumentsForTestRunner(QStringList *omitted) const
{
static const Core::Id id
= Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(GTest::Constants::FRAMEWORK_NAME);
QStringList arguments;
+ if (AutotestPlugin::instance()->settings()->processArgs) {
+ arguments << filterInterfering(runnable().commandLineArguments.split(
+ ' ', QString::SkipEmptyParts), omitted);
+ }
+
const QStringList &testSets = testCases();
if (testSets.size())
arguments << "--gtest_filter=" + testSets.join(':');
@@ -62,7 +100,7 @@ QStringList GTestConfiguration::argumentsForTestRunner() const
if (gSettings->throwOnFailure)
arguments << "--gtest_throw_on_failure";
- if (runMode() == DebuggableTestConfiguration::Debug) {
+ if (isDebugRunMode()) {
if (gSettings->breakOnFailure)
arguments << "--gtest_break_on_failure";
}
diff --git a/src/plugins/autotest/gtest/gtestconfiguration.h b/src/plugins/autotest/gtest/gtestconfiguration.h
index 141e770937..9e2d63b1e9 100644
--- a/src/plugins/autotest/gtest/gtestconfiguration.h
+++ b/src/plugins/autotest/gtest/gtestconfiguration.h
@@ -36,7 +36,7 @@ public:
explicit GTestConfiguration() {}
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
QProcess *app) const override;
- QStringList argumentsForTestRunner() const override;
+ QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
};
} // namespace Internal
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp
index 1971203511..89f3e1a974 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.cpp
+++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp
@@ -74,18 +74,18 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
m_description = line;
if (m_iteration > 1)
m_description.append(' ' + tr("(iteration %1)").arg(m_iteration));
- TestResultPtr testResult = TestResultPtr(new GTestResult);
+ TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
testResult->setResult(Result::MessageInternal);
testResult->setDescription(m_description);
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
m_description.clear();
} else if (disabledTests.exactMatch(line)) {
- TestResultPtr testResult = TestResultPtr(new GTestResult);
+ TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
testResult->setResult(Result::MessageDisabledTests);
int disabled = disabledTests.cap(1).toInt();
testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled));
testResult->setLine(disabled); // misuse line property to hold number of disabled
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
m_description.clear();
}
return;
@@ -95,10 +95,9 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
GTestResult *testResult = createDefaultResult();
testResult->setResult(Result::MessageTestCaseEnd);
testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2)));
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
m_currentTestName.clear();
m_currentTestSet.clear();
- m_normalizedCurrentTestSet.clear();
} else if (newTestStarts.exactMatch(line)) {
setCurrentTestName(newTestStarts.cap(1));
TestResultPtr testResult = TestResultPtr(createDefaultResult());
@@ -109,24 +108,24 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
} else {
testResult->setDescription(tr("Executing test case %1").arg(m_currentTestName));
}
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
} else if (newTestSetStarts.exactMatch(line)) {
setCurrentTestSet(newTestSetStarts.cap(1));
- TestResultPtr testResult = TestResultPtr(new GTestResult);
+ TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
testResult->setResult(Result::MessageCurrentTest);
testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet));
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
m_description.clear();
} else if (testSetSuccess.exactMatch(line)) {
GTestResult *testResult = createDefaultResult();
testResult->setResult(Result::Pass);
testResult->setDescription(m_description);
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
m_description.clear();
testResult = createDefaultResult();
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2)));
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
} else if (testSetFail.exactMatch(line)) {
GTestResult *testResult = createDefaultResult();
@@ -150,12 +149,12 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
}
}
}
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
m_description.clear();
testResult = createDefaultResult();
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2)));
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
}
}
@@ -163,39 +162,21 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
void GTestOutputReader::setCurrentTestSet(const QString &testSet)
{
m_currentTestSet = testSet;
- m_normalizedCurrentTestSet = normalizeName(testSet);
}
void GTestOutputReader::setCurrentTestName(const QString &testName)
{
m_currentTestName = testName;
- m_normalizedTestName = normalizeTestName(testName);
-}
-
-QString GTestOutputReader::normalizeName(const QString &name) const
-{
- static QRegExp parameterIndex("/\\d+");
-
- QString nameWithoutParameterIndices = name;
- nameWithoutParameterIndices.remove(parameterIndex);
-
- return nameWithoutParameterIndices.split('/').last();
-}
-
-QString GTestOutputReader::normalizeTestName(const QString &testname) const
-{
- QString nameWithoutTypeParam = testname.split(',').first();
-
- return normalizeName(nameWithoutTypeParam);
}
GTestResult *GTestOutputReader::createDefaultResult() const
{
- GTestResult *result = new GTestResult(m_executable, m_currentTestName);
+ GTestResult *result = new GTestResult(m_executable, m_projectFile, m_currentTestName);
result->setTestSetName(m_currentTestSet);
result->setIteration(m_iteration);
- const TestTreeItem *testItem = findTestTreeItemForCurrentLine();
+ const TestTreeItem *testItem = result->findTestTreeItem();
+
if (testItem && testItem->line()) {
result->setFileName(testItem->filePath());
result->setLine(static_cast<int>(testItem->line()));
@@ -204,43 +185,5 @@ GTestResult *GTestOutputReader::createDefaultResult() const
return result;
}
-const TestTreeItem *GTestOutputReader::findTestTreeItemForCurrentLine() const
-{
- const auto item = TestTreeModel::instance()->findNonRooItem([&](const Utils::TreeItem *item) {
- const TestTreeItem &treeItem = static_cast<const TestTreeItem &>(*item);
- return matches(treeItem);
- });
-
- return static_cast<const TestTreeItem *>(item);
-}
-
-bool GTestOutputReader::matches(const TestTreeItem &treeItem) const
-{
- if (treeItem.proFile() != m_projectFile)
- return false;
-
- if (m_currentTestSet.isEmpty())
- return matchesTestCase(treeItem);
-
- return matchesTestFunctionOrSet(treeItem);
-}
-
-bool GTestOutputReader::matchesTestFunctionOrSet(const TestTreeItem &treeItem) const
-{
- if (treeItem.type() != TestTreeItem::TestFunctionOrSet)
- return false;
-
- const QString testItemTestSet = treeItem.parentItem()->name() + '.' + treeItem.name();
- return testItemTestSet == m_normalizedCurrentTestSet;
-}
-
-bool GTestOutputReader::matchesTestCase(const TestTreeItem &treeItem) const
-{
- if (treeItem.type() != TestTreeItem::TestCase)
- return false;
-
- return treeItem.name() == m_normalizedTestName;
-}
-
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h
index e46e29fcd3..ebe59cd64d 100644
--- a/src/plugins/autotest/gtest/gtestoutputreader.h
+++ b/src/plugins/autotest/gtest/gtestoutputreader.h
@@ -50,20 +50,12 @@ protected:
private:
void setCurrentTestSet(const QString &testSet);
void setCurrentTestName(const QString &testName);
- QString normalizeName(const QString &name) const;
- QString normalizeTestName(const QString &testname) const;
GTestResult *createDefaultResult() const;
- const TestTreeItem *findTestTreeItemForCurrentLine() const;
- bool matches(const TestTreeItem &treeItem) const;
- bool matchesTestFunctionOrSet(const TestTreeItem &treeItem) const;
- bool matchesTestCase(const TestTreeItem &treeItem) const;
QString m_executable;
QString m_projectFile;
QString m_currentTestName;
- QString m_normalizedTestName;
QString m_currentTestSet;
- QString m_normalizedCurrentTestSet;
QString m_description;
int m_iteration = 1;
};
diff --git a/src/plugins/autotest/gtest/gtestresult.cpp b/src/plugins/autotest/gtest/gtestresult.cpp
index cbccaea837..5945ebf5aa 100644
--- a/src/plugins/autotest/gtest/gtestresult.cpp
+++ b/src/plugins/autotest/gtest/gtestresult.cpp
@@ -24,17 +24,20 @@
****************************************************************************/
#include "gtestresult.h"
+#include "../testtreemodel.h"
+#include "../testtreeitem.h"
namespace Autotest {
namespace Internal {
-GTestResult::GTestResult(const QString &name)
- : TestResult(name)
+GTestResult::GTestResult(const QString &projectFile, const QString &name)
+ : TestResult(name), m_projectFile(projectFile)
{
}
-GTestResult::GTestResult(const QString &executable, const QString &name)
- : TestResult(executable, name)
+GTestResult::GTestResult(const QString &executable, const QString &projectFile,
+ const QString &name)
+ : TestResult(executable, name), m_projectFile(projectFile)
{
}
@@ -68,5 +71,60 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
return isTest() && gtOther->isTestSet();
}
+static QString normalizeName(const QString &name)
+{
+ static QRegExp parameterIndex("/\\d+");
+
+ QString nameWithoutParameterIndices = name;
+ nameWithoutParameterIndices.remove(parameterIndex);
+
+ return nameWithoutParameterIndices.split('/').last();
+}
+
+static QString normalizeTestName(const QString &testname)
+{
+ QString nameWithoutTypeParam = testname.split(',').first();
+
+ return normalizeName(nameWithoutTypeParam);
+}
+
+const TestTreeItem *GTestResult::findTestTreeItem() const
+{
+ const auto item = TestTreeModel::instance()->findNonRootItem([this](const Utils::TreeItem *item) {
+ const TestTreeItem &treeItem = static_cast<const TestTreeItem &>(*item);
+ return matches(treeItem);
+ });
+
+ return static_cast<const TestTreeItem *>(item);
+}
+
+bool GTestResult::matches(const TestTreeItem &treeItem) const
+{
+ if (treeItem.proFile() != m_projectFile)
+ return false;
+
+ if (isTest())
+ return matchesTestCase(treeItem);
+
+ return matchesTestFunctionOrSet(treeItem);
+}
+
+bool GTestResult::matchesTestFunctionOrSet(const TestTreeItem &treeItem) const
+{
+ if (treeItem.type() != TestTreeItem::TestFunctionOrSet)
+ return false;
+
+ const QString testItemTestSet = treeItem.parentItem()->name() + '.' + treeItem.name();
+ return testItemTestSet == normalizeName(m_testSetName);
+}
+
+bool GTestResult::matchesTestCase(const TestTreeItem &treeItem) const
+{
+ if (treeItem.type() != TestTreeItem::TestCase)
+ return false;
+
+ return treeItem.name() == normalizeTestName(name());
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/gtest/gtestresult.h b/src/plugins/autotest/gtest/gtestresult.h
index 491fe41662..88e5476085 100644
--- a/src/plugins/autotest/gtest/gtestresult.h
+++ b/src/plugins/autotest/gtest/gtestresult.h
@@ -33,17 +33,25 @@ namespace Internal {
class GTestResult : public TestResult
{
public:
- explicit GTestResult(const QString &name = QString());
- GTestResult(const QString &executable, const QString &name);
+ GTestResult(const QString &projectFile, const QString &name = QString());
+ GTestResult(const QString &executable, const QString &projectFile, const QString &name);
const QString outputString(bool selected) const override;
void setTestSetName(const QString &testSetName) { m_testSetName = testSetName; }
void setIteration(int iteration) { m_iteration = iteration; }
bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override;
+ virtual const TestTreeItem *findTestTreeItem() const override;
+
private:
bool isTest() const { return m_testSetName.isEmpty(); }
bool isTestSet() const { return !m_testSetName.isEmpty(); }
+
+ bool matches(const TestTreeItem &item) const;
+ bool matchesTestFunctionOrSet(const TestTreeItem &treeItem) const;
+ bool matchesTestCase(const TestTreeItem &treeItem) const;
+
QString m_testSetName;
+ QString m_projectFile;
int m_iteration = 1;
};
diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp
index f41afacf7a..3b2c680fe9 100644
--- a/src/plugins/autotest/gtest/gtesttreeitem.cpp
+++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp
@@ -29,6 +29,7 @@
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/session.h>
+#include <utils/algorithm.h>
#include <utils/qtcassert.h>
namespace Autotest {
@@ -115,7 +116,7 @@ TestConfiguration *GTestTreeItem::debugConfiguration() const
{
GTestConfiguration *config = static_cast<GTestConfiguration *>(testConfiguration());
if (config)
- config->setRunMode(DebuggableTestConfiguration::Debug);
+ config->setRunMode(TestRunMode::Debug);
return config;
}
@@ -293,9 +294,16 @@ QSet<QString> GTestTreeItem::internalTargets() const
QSet<QString> result;
const auto cppMM = CppTools::CppModelManager::instance();
const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject());
+ const QString file = filePath();
for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
- if (projectPart->projectFile == proFile())
+ if (projectPart->projectFile == proFile()
+ && Utils::anyOf(projectPart->files, [&file] (const CppTools::ProjectFile &pf) {
+ return pf.path == file;
+ })) {
result.insert(projectPart->buildSystemTarget + '|' + projectPart->projectFile);
+ if (projectPart->buildTargetType != CppTools::ProjectPart::Executable)
+ result.unite(TestTreeItem::dependingInternalTargets(cppMM, file));
+ }
}
return result;
}
diff --git a/src/plugins/autotest/images/benchmark.png b/src/plugins/autotest/images/benchmark.png
index c9d3c5b2b5..021ac069ad 100644
--- a/src/plugins/autotest/images/benchmark.png
+++ b/src/plugins/autotest/images/benchmark.png
Binary files differ
diff --git a/src/plugins/autotest/images/benchmark@2x.png b/src/plugins/autotest/images/benchmark@2x.png
new file mode 100644
index 0000000000..64eb95f7dc
--- /dev/null
+++ b/src/plugins/autotest/images/benchmark@2x.png
Binary files differ
diff --git a/src/plugins/autotest/images/text.png b/src/plugins/autotest/images/text.png
index b43b92e09a..7d4c35c70e 100644
--- a/src/plugins/autotest/images/text.png
+++ b/src/plugins/autotest/images/text.png
Binary files differ
diff --git a/src/plugins/autotest/images/text@2x.png b/src/plugins/autotest/images/text@2x.png
index c93133a2d7..534acad25b 100644
--- a/src/plugins/autotest/images/text@2x.png
+++ b/src/plugins/autotest/images/text@2x.png
Binary files differ
diff --git a/src/plugins/autotest/images/visual.png b/src/plugins/autotest/images/visual.png
index 092367618c..62fd49061f 100644
--- a/src/plugins/autotest/images/visual.png
+++ b/src/plugins/autotest/images/visual.png
Binary files differ
diff --git a/src/plugins/autotest/images/visual@2x.png b/src/plugins/autotest/images/visual@2x.png
index 1426597449..99e612fa34 100644
--- a/src/plugins/autotest/images/visual@2x.png
+++ b/src/plugins/autotest/images/visual@2x.png
Binary files differ
diff --git a/src/plugins/autotest/qtest/qttest_utils.cpp b/src/plugins/autotest/qtest/qttest_utils.cpp
index e596ae7183..a832a093ce 100644
--- a/src/plugins/autotest/qtest/qttest_utils.cpp
+++ b/src/plugins/autotest/qtest/qttest_utils.cpp
@@ -27,9 +27,11 @@
#include "qttesttreeitem.h"
#include "../testframeworkmanager.h"
+#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QByteArrayList>
+#include <QSet>
namespace Autotest {
namespace Internal {
@@ -83,6 +85,62 @@ QMultiHash<QString, QString> alternativeFiles(const Core::Id &id, const QStringL
return result;
}
+QStringList filterInterfering(const QStringList &provided, QStringList *omitted, bool isQuickTest)
+{
+ static const QSet<QString> knownInterferingSingleOptions {
+ "-txt", "-xml", "-csv", "-xunitxml", "-lightxml", "-silent", "-v1", "-v2", "-vs", "-vb",
+ "-functions", "-datatags", "-nocrashhandler", "-callgrind", "-perf", "-perfcounterlist",
+ "-tickcounter", "-eventcounter", "-help"
+ };
+ static const QSet<QString> knownInterferingOptionWithParameter = { "-o" };
+ static const QSet<QString> knownAllowedOptionsWithParameter {
+ "-eventdelay", "-keydelay", "-mousedelay", "-maxwarnings", "-perfcounter",
+ "-minimumvalue", "-minimumtotal", "-iterations", "-median"
+ };
+
+ // handle Quick options as well
+ static const QSet<QString> knownInterferingQuickOption = { "-qtquick1" };
+ static const QSet<QString> knownAllowedQuickOptionsWithParameter {
+ "-import", "-plugins", "-input"
+ };
+
+ QStringList allowed;
+ auto it = provided.cbegin();
+ auto end = provided.cend();
+ for ( ; it != end; ++it) {
+ QString currentOpt = *it;
+ if (knownAllowedOptionsWithParameter.contains(currentOpt)) {
+ allowed.append(currentOpt);
+ ++it;
+ QTC_ASSERT(it != end, return QStringList());
+ allowed.append(*it);
+ } else if (knownInterferingOptionWithParameter.contains(currentOpt)) {
+ if (omitted) {
+ omitted->append(currentOpt);
+ ++it;
+ QTC_ASSERT(it != end, return QStringList());
+ omitted->append(*it);
+ }
+ } else if (knownInterferingSingleOptions.contains(currentOpt)) {
+ if (omitted)
+ omitted->append(currentOpt);
+ } else if (isQuickTest) {
+ if (knownAllowedQuickOptionsWithParameter.contains(currentOpt)) {
+ allowed.append(currentOpt);
+ ++it;
+ QTC_ASSERT(it != end, return QStringList());
+ allowed.append(*it);
+ } else if (knownInterferingQuickOption.contains(currentOpt)) {
+ if (omitted)
+ omitted->append(currentOpt);
+ }
+ } else { // might be bad, but we cannot know anything
+ allowed.append(currentOpt);
+ }
+ }
+ return allowed;
+}
+
} // namespace QTestUtils
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/qtest/qttest_utils.h b/src/plugins/autotest/qtest/qttest_utils.h
index be4fb0a2ca..30dfa85055 100644
--- a/src/plugins/autotest/qtest/qttest_utils.h
+++ b/src/plugins/autotest/qtest/qttest_utils.h
@@ -36,6 +36,7 @@ namespace QTestUtils {
bool isQTestMacro(const QByteArray &macro);
QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id, const QStringList &files);
QMultiHash<QString, QString> alternativeFiles(const Core::Id &id, const QStringList &files);
+QStringList filterInterfering(const QStringList &provided, QStringList *omitted, bool isQuickTest);
} // namespace QTestUtils
} // namespace Internal
diff --git a/src/plugins/autotest/qtest/qttestconfiguration.cpp b/src/plugins/autotest/qtest/qttestconfiguration.cpp
index 0875ec18a6..bb8f62aacf 100644
--- a/src/plugins/autotest/qtest/qttestconfiguration.cpp
+++ b/src/plugins/autotest/qtest/qttestconfiguration.cpp
@@ -27,7 +27,10 @@
#include "qttestconstants.h"
#include "qttestoutputreader.h"
#include "qttestsettings.h"
+#include "qttest_utils.h"
+#include "../autotestplugin.h"
#include "../testframeworkmanager.h"
+#include "../testsettings.h"
namespace Autotest {
namespace Internal {
@@ -48,12 +51,17 @@ TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface<TestR
return new QtTestOutputReader(fi, app, buildDirectory(), QtTestOutputReader::PlainText);
}
-QStringList QtTestConfiguration::argumentsForTestRunner() const
+QStringList QtTestConfiguration::argumentsForTestRunner(QStringList *omitted) const
{
static const Core::Id id
= Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(QtTest::Constants::FRAMEWORK_NAME);
QStringList arguments;
+ if (AutotestPlugin::instance()->settings()->processArgs) {
+ arguments.append(QTestUtils::filterInterfering(
+ runnable().commandLineArguments.split(' ', QString::SkipEmptyParts),
+ omitted, false));
+ }
TestFrameworkManager *manager = TestFrameworkManager::instance();
auto qtSettings = qSharedPointerCast<QtTestSettings>(manager->settingsForTestFramework(id));
if (qtSettings.isNull())
@@ -73,7 +81,7 @@ QStringList QtTestConfiguration::argumentsForTestRunner() const
if (qtSettings->logSignalsSlots)
arguments << "-vs";
- if (runMode() == DebuggableTestConfiguration::Debug) {
+ if (isDebugRunMode()) {
if (qtSettings->noCrashHandler)
arguments << "-nocrashhandler";
}
diff --git a/src/plugins/autotest/qtest/qttestconfiguration.h b/src/plugins/autotest/qtest/qttestconfiguration.h
index f32737e765..1dbc73be20 100644
--- a/src/plugins/autotest/qtest/qttestconfiguration.h
+++ b/src/plugins/autotest/qtest/qttestconfiguration.h
@@ -36,7 +36,7 @@ public:
explicit QtTestConfiguration() {}
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
QProcess *app) const override;
- QStringList argumentsForTestRunner() const override;
+ QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
};
} // namespace Internal
diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp
index d1999bba39..5ffc4f2db9 100644
--- a/src/plugins/autotest/qtest/qttestoutputreader.cpp
+++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp
@@ -274,7 +274,7 @@ void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
testResult->setFileName(m_file);
testResult->setLine(m_lineNumber);
testResult->setDescription(m_description);
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
if (currentTag == QStringLiteral("Incident"))
m_dataTag.clear();
}
@@ -433,7 +433,7 @@ void QtTestOutputReader::sendCompleteInformation()
testResult->setFileName(m_file);
testResult->setLine(m_lineNumber);
testResult->setDescription(m_description);
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
}
void QtTestOutputReader::sendMessageCurrentTest()
@@ -441,7 +441,7 @@ void QtTestOutputReader::sendMessageCurrentTest()
TestResultPtr testResult = TestResultPtr(new QtTestResult);
testResult->setResult(Result::MessageCurrentTest);
testResult->setDescription(tr("Entering test function %1::%2").arg(m_className, m_testCase));
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
}
void QtTestOutputReader::sendStartMessage(bool isFunction)
@@ -450,7 +450,7 @@ void QtTestOutputReader::sendStartMessage(bool isFunction)
testResult->setResult(Result::MessageTestCaseStart);
testResult->setDescription(isFunction ? tr("Executing test function %1").arg(m_testCase)
: tr("Executing test case %1").arg(m_className));
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
}
void QtTestOutputReader::sendFinishMessage(bool isFunction)
@@ -464,7 +464,7 @@ void QtTestOutputReader::sendFinishMessage(bool isFunction)
testResult->setDescription(isFunction ? tr("Test function finished.")
: tr("Test finished."));
}
- m_futureInterface.reportResult(testResult);
+ reportResult(testResult);
}
// TODO factor out tr() strings to avoid duplication (see XML processing of Characters)
@@ -473,15 +473,15 @@ void QtTestOutputReader::handleAndSendConfigMessage(const QRegExp &config)
QtTestResult *testResult = createDefaultResult();
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("Qt version: %1").arg(config.cap(3)));
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
testResult = createDefaultResult();
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("Qt build: %1").arg(config.cap(2)));
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
testResult = createDefaultResult();
testResult->setResult(Result::MessageInternal);
testResult->setDescription(tr("QTest version: %1").arg(config.cap(1)));
- m_futureInterface.reportResult(TestResultPtr(testResult));
+ reportResult(TestResultPtr(testResult));
}
} // namespace Internal
diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp
index 93376cba7c..a262148ecc 100644
--- a/src/plugins/autotest/qtest/qttestparser.cpp
+++ b/src/plugins/autotest/qtest/qttestparser.cpp
@@ -85,8 +85,11 @@ static bool qtTestLibDefined(const QString &fileName)
{
const QList<CppTools::ProjectPart::Ptr> parts =
CppTools::CppModelManager::instance()->projectPart(fileName);
- if (parts.size() > 0)
- return parts.at(0)->projectDefines.contains("#define QT_TESTLIB_LIB");
+ if (parts.size() > 0) {
+ return Utils::anyOf(parts.at(0)->projectMacros, [] (const ProjectExplorer::Macro &macro) {
+ return macro.key == "QT_TESTLIB_LIB";
+ });
+ }
return false;
}
diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp
index 48fa4a9de9..850ba6dc54 100644
--- a/src/plugins/autotest/qtest/qttesttreeitem.cpp
+++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp
@@ -142,7 +142,7 @@ TestConfiguration *QtTestTreeItem::debugConfiguration() const
{
QtTestConfiguration *config = static_cast<QtTestConfiguration *>(testConfiguration());
if (config)
- config->setRunMode(DebuggableTestConfiguration::Debug);
+ config->setRunMode(TestRunMode::Debug);
return config;
}
diff --git a/src/plugins/autotest/quick/quicktestconfiguration.cpp b/src/plugins/autotest/quick/quicktestconfiguration.cpp
index 4d3241f0f2..88920e0352 100644
--- a/src/plugins/autotest/quick/quicktestconfiguration.cpp
+++ b/src/plugins/autotest/quick/quicktestconfiguration.cpp
@@ -27,7 +27,10 @@
#include "../qtest/qttestconstants.h"
#include "../qtest/qttestoutputreader.h"
#include "../qtest/qttestsettings.h"
+#include "../qtest/qttest_utils.h"
+#include "../autotestplugin.h"
#include "../testframeworkmanager.h"
+#include "../testsettings.h"
namespace Autotest {
namespace Internal {
@@ -47,12 +50,18 @@ TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface<Te
return new QtTestOutputReader(fi, app, buildDirectory(), QtTestOutputReader::PlainText);
}
-QStringList QuickTestConfiguration::argumentsForTestRunner() const
+QStringList QuickTestConfiguration::argumentsForTestRunner(QStringList *omitted) const
{
static const Core::Id id
= Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(QtTest::Constants::FRAMEWORK_NAME);
QStringList arguments;
+ if (AutotestPlugin::instance()->settings()->processArgs) {
+ arguments.append(QTestUtils::filterInterfering
+ (runnable().commandLineArguments.split(' ', QString::SkipEmptyParts),
+ omitted, true));
+ }
+
TestFrameworkManager *manager = TestFrameworkManager::instance();
auto qtSettings = qSharedPointerCast<QtTestSettings>(manager->settingsForTestFramework(id));
if (qtSettings.isNull())
diff --git a/src/plugins/autotest/quick/quicktestconfiguration.h b/src/plugins/autotest/quick/quicktestconfiguration.h
index 8ff754202b..ecab2f4a2f 100644
--- a/src/plugins/autotest/quick/quicktestconfiguration.h
+++ b/src/plugins/autotest/quick/quicktestconfiguration.h
@@ -36,7 +36,7 @@ public:
explicit QuickTestConfiguration() {}
TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
QProcess *app) const override;
- QStringList argumentsForTestRunner() const override;
+ QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const override;
void setUnnamedOnly(bool unnamedOnly);
bool unnamedOnly() const { return m_unnamedOnly; }
diff --git a/src/plugins/autotest/quick/quicktestframework.cpp b/src/plugins/autotest/quick/quicktestframework.cpp
index 17e2c449be..ef5423bb6f 100644
--- a/src/plugins/autotest/quick/quicktestframework.cpp
+++ b/src/plugins/autotest/quick/quicktestframework.cpp
@@ -37,7 +37,7 @@ ITestParser *QuickTestFramework::createTestParser() const
TestTreeItem *QuickTestFramework::createRootNode() const
{
- return new QuickTestTreeItem(QCoreApplication::translate("QuickTestFramework", "Quick Tests"),
+ return new QuickTestTreeItem(QCoreApplication::translate("QuickTestFramework", "Quick Test"),
QString(), TestTreeItem::Root);
}
diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp
index 0d897fe04e..46566952ff 100644
--- a/src/plugins/autotest/quick/quicktestparser.cpp
+++ b/src/plugins/autotest/quick/quicktestparser.cpp
@@ -89,20 +89,21 @@ static bool includesQtQuickTest(const CPlusPlus::Document::Ptr &doc,
static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM,
const QString &fileName)
{
- static const QByteArray qtsd(" QUICK_TEST_SOURCE_DIR ");
const QList<CppTools::ProjectPart::Ptr> parts = cppMM->projectPart(fileName);
if (parts.size() > 0) {
- QByteArray projDefines(parts.at(0)->projectDefines);
- for (const QByteArray &line : projDefines.split('\n')) {
- if (line.contains(qtsd)) {
- QByteArray result = line.mid(line.indexOf(qtsd) + qtsd.length());
- if (result.startsWith('"'))
- result.remove(result.length() - 1, 1).remove(0, 1);
- if (result.startsWith("\\\""))
- result.remove(result.length() - 2, 2).remove(0, 2);
- return QLatin1String(result);
- }
- }
+ const ProjectExplorer::Macros &macros = parts.at(0)->projectMacros;
+ auto found = std::find_if(
+ macros.begin(),
+ macros.end(),
+ [] (const ProjectExplorer::Macro &macro) { return macro.key == "QUICK_TEST_SOURCE_DIR"; });
+ if (found != macros.end()) {
+ QByteArray result = found->value;
+ if (result.startsWith('"'))
+ result.remove(result.length() - 1, 1).remove(0, 1);
+ if (result.startsWith("\\\""))
+ result.remove(result.length() - 2, 2).remove(0, 2);
+ return QLatin1String(result);
+ }
}
return QString();
}
diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp
index 9ebcdd48c6..3520269636 100644
--- a/src/plugins/autotest/quick/quicktesttreeitem.cpp
+++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp
@@ -292,6 +292,8 @@ QSet<QString> QuickTestTreeItem::internalTargets() const
const auto cppMM = CppTools::CppModelManager::instance();
const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject());
for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
+ if (projectPart->buildTargetType != CppTools::ProjectPart::Executable)
+ continue;
if (projectPart->projectFile == proFile()) {
result.insert(projectPart->buildSystemTarget + '|' + projectPart->projectFile);
break;
diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp
index ce0a655c2c..feb32c58db 100644
--- a/src/plugins/autotest/testcodeparser.cpp
+++ b/src/plugins/autotest/testcodeparser.cpp
@@ -402,7 +402,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars
parser->init(list);
QFuture<TestParseResultPtr> future = Utils::map(list,
- [this, codeParsers](QFutureInterface<TestParseResultPtr> &fi, const QString &file) {
+ [codeParsers](QFutureInterface<TestParseResultPtr> &fi, const QString &file) {
parseFileForTests(codeParsers, fi, file);
},
Utils::MapReduceOption::Unordered,
diff --git a/src/plugins/autotest/testconfiguration.cpp b/src/plugins/autotest/testconfiguration.cpp
index 7606b4827b..b4af50e8a9 100644
--- a/src/plugins/autotest/testconfiguration.cpp
+++ b/src/plugins/autotest/testconfiguration.cpp
@@ -26,7 +26,6 @@
#include "testconfiguration.h"
#include "testoutputreader.h"
#include "testrunconfiguration.h"
-#include "testrunner.h"
#include <cpptools/cppmodelmanager.h>
#include <cpptools/projectinfo.h>
@@ -73,11 +72,66 @@ static QString ensureExeEnding(const QString& file)
return Utils::HostOsInfo::withExecutableSuffix(file);
}
-void TestConfiguration::completeTestInformation(int runMode)
+void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguration *rc,
+ TestRunMode runMode)
+{
+ QTC_ASSERT(rc, return);
+ Project *project = SessionManager::startupProject();
+ if (!project)
+ return;
+
+ Target *target = project->activeTarget();
+ if (!target)
+ return;
+
+ if (!Utils::findOr(target->runConfigurations(), nullptr,
+ [&rc] (RunConfiguration *config) { return rc == config; })) {
+ return;
+ }
+
+ Runnable runnable = rc->runnable();
+ if (!runnable.is<StandardRunnable>())
+ return;
+ m_runnable = runnable.as<StandardRunnable>();
+ m_displayName = rc->displayName();
+ m_project = rc->project();
+
+ const QString buildSystemTarget = rc->buildSystemTarget();
+ BuildTargetInfo targetInfo
+ = Utils::findOrDefault(target->applicationTargets().list,
+ [&buildSystemTarget] (const BuildTargetInfo &bti) {
+ return bti.targetName == buildSystemTarget;
+ });
+ if (!targetInfo.targetFilePath.isEmpty())
+ m_runnable.executable = ensureExeEnding(targetInfo.targetFilePath.toString());
+
+ QString buildBase;
+ if (auto buildConfig = target->activeBuildConfiguration()) {
+ buildBase = buildConfig->buildDirectory().toString();
+ const QString projBase = m_project->projectDirectory().toString();
+ if (m_projectFile.startsWith(projBase))
+ m_buildDir = QFileInfo(buildBase + m_projectFile.mid(projBase.length())).absolutePath();
+ }
+ if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
+ m_runConfig = new TestRunConfiguration(rc->target(), this);
+}
+
+void TestConfiguration::completeTestInformation(TestRunMode runMode)
{
QTC_ASSERT(!m_projectFile.isEmpty(), return);
QTC_ASSERT(!m_buildTargets.isEmpty(), return);
+ if (m_origRunConfig) {
+ qCDebug(LOG) << "Using run configuration specified by user or found by first call";
+ completeTestInformation(m_origRunConfig, runMode);
+ if (hasExecutable()) {
+ qCDebug(LOG) << "Completed.\nRunnable:" << m_runnable.executable
+ << "\nArgs:" << m_runnable.commandLineArguments
+ << "\nWorking directory:" << m_runnable.workingDirectory;
+ return;
+ }
+ qCDebug(LOG) << "Failed to complete - using 'normal' way.";
+ }
Project *project = SessionManager::startupProject();
if (!project)
return;
@@ -91,7 +145,7 @@ void TestConfiguration::completeTestInformation(int runMode)
const QSet<QString> buildSystemTargets = m_buildTargets;
qCDebug(LOG) << "BuildSystemTargets\n " << buildSystemTargets;
- const BuildTargetInfo targetInfo
+ BuildTargetInfo targetInfo
= Utils::findOrDefault(target->applicationTargets().list,
[&buildSystemTargets] (const BuildTargetInfo &bti) {
return Utils::anyOf(buildSystemTargets, [&bti](const QString &b) {
@@ -102,12 +156,22 @@ void TestConfiguration::completeTestInformation(int runMode)
&& targWithProjectFile.at(1).startsWith(bti.projectFilePath.toString());
});
});
- if (!QTC_GUARD(!targetInfo.targetFilePath.isEmpty())) { // empty if BTI default created
+ // we might end up with an empty targetFilePath - e.g. when having a library we just link to
+ // there would be no BuildTargetInfo that could match
+ if (targetInfo.targetFilePath.isEmpty()) {
qCDebug(LOG) << "BuildTargetInfos";
- for (const BuildTargetInfo &bti : target->applicationTargets().list)
- qCDebug(LOG) << " " << bti.targetName << bti.projectFilePath << bti.targetFilePath;
+ const QList<BuildTargetInfo> buildTargets = target->applicationTargets().list;
+ // if there is only one build target just use it (but be honest that we're guessing)
+ if (buildTargets.size() == 1) {
+ targetInfo = buildTargets.first();
+ m_guessedConfiguration = true;
+ m_guessedFrom = targetInfo.targetName;
+ }
}
+
const QString localExecutable = ensureExeEnding(targetInfo.targetFilePath.toString());
+ if (localExecutable.isEmpty())
+ return;
QString buildBase;
if (auto buildConfig = target->activeBuildConfiguration()) {
@@ -154,12 +218,12 @@ void TestConfiguration::completeTestInformation(int runMode)
return b.startsWith(currentBST);
}))) {
qCDebug(LOG) << " Using this RunConfig.";
- m_executableFile = currentExecutable;
+ m_origRunConfig = runConfig;
+ m_runnable = stdRunnable;
+ m_runnable.executable = currentExecutable;
m_displayName = runConfig->displayName();
- m_workingDir = Utils::FileUtils::normalizePathName(stdRunnable.workingDirectory);
- m_environment = stdRunnable.environment;
m_project = project;
- if (runMode == TestRunner::Debug)
+ if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
m_runConfig = new TestRunConfiguration(runConfig->target(), this);
break;
}
@@ -169,9 +233,9 @@ void TestConfiguration::completeTestInformation(int runMode)
// or we might have end up using the (wrong) path of a locally installed executable
// for this case try the original executable path of the BuildTargetInfo (the executable
// before installation) to have at least something to execute
- if (m_executableFile.isEmpty() && !localExecutable.isEmpty())
- m_executableFile = localExecutable;
- if (m_displayName.isEmpty() && !m_executableFile.isEmpty()) {
+ if (!hasExecutable() && !localExecutable.isEmpty())
+ m_runnable.executable = localExecutable;
+ if (m_displayName.isEmpty() && hasExecutable()) {
qCDebug(LOG) << " Fallback";
// we failed to find a valid runconfiguration - but we've got the executable already
if (auto rc = target->activeRunConfiguration()) {
@@ -179,11 +243,11 @@ void TestConfiguration::completeTestInformation(int runMode)
Runnable runnable = rc->runnable();
if (runnable.is<StandardRunnable>()) {
StandardRunnable stdRunnable = runnable.as<StandardRunnable>();
- m_environment = stdRunnable.environment;
+ m_runnable.environment = stdRunnable.environment;
m_project = project;
m_guessedConfiguration = true;
m_guessedFrom = rc->displayName();
- if (runMode == TestRunner::Debug)
+ if (runMode == TestRunMode::Debug)
m_runConfig = new TestRunConfiguration(rc->target(), this);
}
} else {
@@ -219,7 +283,7 @@ void TestConfiguration::setTestCaseCount(int count)
void TestConfiguration::setExecutableFile(const QString &executableFile)
{
- m_executableFile = executableFile;
+ m_runnable.executable = executableFile;
}
void TestConfiguration::setProjectFile(const QString &projectFile)
@@ -229,7 +293,7 @@ void TestConfiguration::setProjectFile(const QString &projectFile)
void TestConfiguration::setWorkingDirectory(const QString &workingDirectory)
{
- m_workingDir = workingDirectory;
+ m_runnable.workingDirectory = workingDirectory;
}
void TestConfiguration::setBuildDirectory(const QString &buildDirectory)
@@ -244,7 +308,7 @@ void TestConfiguration::setDisplayName(const QString &displayName)
void TestConfiguration::setEnvironment(const Utils::Environment &env)
{
- m_environment = env;
+ m_runnable.environment = env;
}
void TestConfiguration::setProject(Project *project)
@@ -257,19 +321,24 @@ void TestConfiguration::setInternalTargets(const QSet<QString> &targets)
m_buildTargets = targets;
}
+void TestConfiguration::setOriginalRunConfiguration(RunConfiguration *runConfig)
+{
+ m_origRunConfig = runConfig;
+}
+
QString TestConfiguration::executableFilePath() const
{
- if (m_executableFile.isEmpty())
+ if (!hasExecutable())
return QString();
- QFileInfo commandFileInfo(m_executableFile);
+ QFileInfo commandFileInfo(m_runnable.executable);
if (commandFileInfo.isExecutable() && commandFileInfo.path() != ".") {
return commandFileInfo.absoluteFilePath();
} else if (commandFileInfo.path() == "."){
- QString fullCommandFileName = m_executableFile;
+ QString fullCommandFileName = m_runnable.executable;
// TODO: check if we can use searchInPath() from Utils::Environment
- const QStringList &pathList = m_environment.toProcessEnvironment().value("PATH").split(
- Utils::HostOsInfo::pathListSeparator());
+ const QStringList &pathList = m_runnable.environment.toProcessEnvironment().value("PATH")
+ .split(Utils::HostOsInfo::pathListSeparator());
foreach (const QString &path, pathList) {
QString filePath(path + QDir::separator() + fullCommandFileName);
@@ -282,8 +351,8 @@ QString TestConfiguration::executableFilePath() const
QString TestConfiguration::workingDirectory() const
{
- if (!m_workingDir.isEmpty()) {
- const QFileInfo info(m_workingDir);
+ if (!m_runnable.workingDirectory.isEmpty()) {
+ const QFileInfo info(m_runnable.workingDirectory);
if (info.isDir()) // ensure wanted working dir does exist
return info.absoluteFilePath();
}
@@ -292,5 +361,15 @@ QString TestConfiguration::workingDirectory() const
return executable.isEmpty() ? executable : QFileInfo(executable).absolutePath();
}
+bool DebuggableTestConfiguration::isDebugRunMode() const
+{
+ return m_runMode == TestRunMode::Debug || m_runMode == TestRunMode::DebugWithoutDeploy;
+}
+
+bool TestConfiguration::hasExecutable() const
+{
+ return !m_runnable.executable.isEmpty();
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/testconfiguration.h b/src/plugins/autotest/testconfiguration.h
index 248b9aaeb7..e35b0f0dd2 100644
--- a/src/plugins/autotest/testconfiguration.h
+++ b/src/plugins/autotest/testconfiguration.h
@@ -28,6 +28,7 @@
#include "autotestconstants.h"
#include <projectexplorer/project.h>
+#include <projectexplorer/runnables.h>
#include <utils/environment.h>
#include <QFutureInterface>
@@ -49,13 +50,13 @@ class TestRunConfiguration;
using TestResultPtr = QSharedPointer<TestResult>;
class TestConfiguration
-
{
public:
explicit TestConfiguration();
virtual ~TestConfiguration();
- void completeTestInformation(int runMode);
+ void completeTestInformation(TestRunMode runMode);
+ void completeTestInformation(ProjectExplorer::RunConfiguration *rc, TestRunMode runMode);
void setTestCases(const QStringList &testCases);
void setTestCaseCount(int count);
@@ -67,6 +68,7 @@ public:
void setEnvironment(const Utils::Environment &env);
void setProject(ProjectExplorer::Project *project);
void setInternalTargets(const QSet<QString> &targets);
+ void setOriginalRunConfiguration(ProjectExplorer::RunConfiguration *runConfig);
QStringList testCases() const { return m_testCases; }
int testCaseCount() const { return m_testCaseCount; }
@@ -75,51 +77,48 @@ public:
QString buildDirectory() const { return m_buildDir; }
QString projectFile() const { return m_projectFile; }
QString displayName() const { return m_displayName; }
- Utils::Environment environment() const { return m_environment; }
+ Utils::Environment environment() const { return m_runnable.environment; }
ProjectExplorer::Project *project() const { return m_project.data(); }
+ QSet<QString> internalTargets() const { return m_buildTargets; }
+ ProjectExplorer::RunConfiguration *originalRunConfiguration() const { return m_origRunConfig; }
TestRunConfiguration *runConfiguration() const { return m_runConfig; }
+ bool hasExecutable() const;
bool isGuessed() const { return m_guessedConfiguration; }
QString runConfigDisplayName() const { return m_guessedConfiguration ? m_guessedFrom
: m_displayName; }
+ ProjectExplorer::StandardRunnable runnable() const { return m_runnable; }
virtual TestOutputReader *outputReader(const QFutureInterface<TestResultPtr> &fi,
QProcess *app) const = 0;
- virtual QStringList argumentsForTestRunner() const = 0;
+ virtual QStringList argumentsForTestRunner(QStringList *omitted = nullptr) const = 0;
private:
QStringList m_testCases;
int m_testCaseCount = 0;
QString m_projectFile;
- QString m_executableFile;
- QString m_workingDir;
QString m_buildDir;
QString m_displayName;
QString m_guessedFrom;
- Utils::Environment m_environment;
QPointer<ProjectExplorer::Project> m_project;
bool m_guessedConfiguration = false;
- TestRunConfiguration *m_runConfig = 0;
+ TestRunConfiguration *m_runConfig = nullptr;
QSet<QString> m_buildTargets;
+ ProjectExplorer::RunConfiguration *m_origRunConfig = nullptr;
+ ProjectExplorer::StandardRunnable m_runnable;
};
class DebuggableTestConfiguration : public TestConfiguration
{
public:
- enum RunMode
- {
- Run,
- Debug
- };
-
- explicit DebuggableTestConfiguration(RunMode runMode = Run) : m_runMode(runMode) {}
+ explicit DebuggableTestConfiguration(TestRunMode runMode = TestRunMode::Run)
+ : m_runMode(runMode) {}
~DebuggableTestConfiguration() {}
- void setRunMode(RunMode mode) { m_runMode = mode; }
- RunMode runMode() const { return m_runMode; }
-
-
+ void setRunMode(TestRunMode mode) { m_runMode = mode; }
+ TestRunMode runMode() const { return m_runMode; }
+ bool isDebugRunMode() const;
private:
- RunMode m_runMode;
+ TestRunMode m_runMode;
};
} // namespace Internal
diff --git a/src/plugins/autotest/testnavigationwidget.cpp b/src/plugins/autotest/testnavigationwidget.cpp
index 5e34c666e0..aaeef64a1a 100644
--- a/src/plugins/autotest/testnavigationwidget.cpp
+++ b/src/plugins/autotest/testnavigationwidget.cpp
@@ -86,7 +86,7 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) :
connect(m_view, &TestTreeView::activated, this, &TestNavigationWidget::onItemActivated);
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Medium, this);
+ m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Medium, this);
m_progressIndicator->attachToWidget(m_view);
m_progressIndicator->hide();
@@ -136,13 +136,13 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event)
runThisTest->setEnabled(enabled);
connect(runThisTest, &QAction::triggered,
this, [this] () {
- onRunThisTestTriggered(TestRunner::Run);
+ onRunThisTestTriggered(TestRunMode::Run);
});
runWithoutDeploy = new QAction(tr("Run Without Deployment"), &menu);
runWithoutDeploy->setEnabled(enabled);
connect(runWithoutDeploy, &QAction::triggered,
this, [this] () {
- onRunThisTestTriggered(TestRunner::RunWithoutDeploy);
+ onRunThisTestTriggered(TestRunMode::RunWithoutDeploy);
});
}
if (item->canProvideDebugConfiguration()) {
@@ -150,13 +150,13 @@ void TestNavigationWidget::contextMenuEvent(QContextMenuEvent *event)
debugThisTest->setEnabled(enabled);
connect(debugThisTest, &QAction::triggered,
this, [this] () {
- onRunThisTestTriggered(TestRunner::Debug);
+ onRunThisTestTriggered(TestRunMode::Debug);
});
debugWithoutDeploy = new QAction(tr("Debug Without Deployment"), &menu);
debugWithoutDeploy->setEnabled(enabled);
connect(debugWithoutDeploy, &QAction::triggered,
this, [this] () {
- onRunThisTestTriggered(TestRunner::DebugWithoutDeploy);
+ onRunThisTestTriggered(TestRunMode::DebugWithoutDeploy);
});
}
}
@@ -291,7 +291,7 @@ void TestNavigationWidget::initializeFilterMenu()
m_filterMenu->addAction(action);
}
-void TestNavigationWidget::onRunThisTestTriggered(TestRunner::Mode runMode)
+void TestNavigationWidget::onRunThisTestTriggered(TestRunMode runMode)
{
const QModelIndexList selected = m_view->selectionModel()->selectedIndexes();
if (selected.isEmpty())
@@ -301,25 +301,7 @@ void TestNavigationWidget::onRunThisTestTriggered(TestRunner::Mode runMode)
return;
TestTreeItem *item = static_cast<TestTreeItem *>(sourceIndex.internalPointer());
- TestConfiguration *configuration;
- switch (runMode) {
- case TestRunner::Run:
- case TestRunner::RunWithoutDeploy:
- configuration = item->testConfiguration();
- break;
- case TestRunner::Debug:
- case TestRunner::DebugWithoutDeploy:
- configuration = item->debugConfiguration();
- break;
- default:
- configuration = nullptr;
- }
-
- if (configuration) {
- TestRunner *runner = TestRunner::instance();
- runner->setSelectedTests({configuration});
- runner->prepareToRunTests(runMode);
- }
+ TestRunner::instance()->runTest(runMode, item);
}
TestNavigationWidgetFactory::TestNavigationWidgetFactory()
diff --git a/src/plugins/autotest/testnavigationwidget.h b/src/plugins/autotest/testnavigationwidget.h
index 90031b4804..163547c9c1 100644
--- a/src/plugins/autotest/testnavigationwidget.h
+++ b/src/plugins/autotest/testnavigationwidget.h
@@ -72,7 +72,7 @@ private:
void onParsingStarted();
void onParsingFinished();
void initializeFilterMenu();
- void onRunThisTestTriggered(TestRunner::Mode runMode);
+ void onRunThisTestTriggered(TestRunMode runMode);
TestTreeModel *m_model;
TestTreeSortFilterModel *m_sortFilterModel;
diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp
index fea9237717..b17af8ec73 100644
--- a/src/plugins/autotest/testoutputreader.cpp
+++ b/src/plugins/autotest/testoutputreader.cpp
@@ -66,5 +66,11 @@ void TestOutputReader::processStdError(const QByteArray &output)
qWarning() << "AutoTest.Run: Ignored plain output:" << output;
}
+void TestOutputReader::reportResult(const TestResultPtr &result)
+{
+ m_futureInterface.reportResult(result);
+ m_hadValidOutput = true;
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/testoutputreader.h b/src/plugins/autotest/testoutputreader.h
index ff04d8f4ce..c9fe9cd19a 100644
--- a/src/plugins/autotest/testoutputreader.h
+++ b/src/plugins/autotest/testoutputreader.h
@@ -44,13 +44,17 @@ public:
virtual void processOutput(const QByteArray &outputLine) = 0;
virtual void processStdError(const QByteArray &output);
+ bool hadValidOutput() const { return m_hadValidOutput; }
signals:
void newOutputAvailable(const QByteArray &output);
protected:
+ void reportResult(const TestResultPtr &result);
QFutureInterface<TestResultPtr> m_futureInterface;
QProcess *m_testApplication; // not owned
QString m_buildDir;
+private:
+ bool m_hadValidOutput = false;
};
} // namespace Internal
diff --git a/src/plugins/autotest/testresult.cpp b/src/plugins/autotest/testresult.cpp
index 2dcd9dda70..96db2b10c6 100644
--- a/src/plugins/autotest/testresult.cpp
+++ b/src/plugins/autotest/testresult.cpp
@@ -58,6 +58,11 @@ const QString TestResult::outputString(bool selected) const
return selected ? m_description : m_description.split('\n').first();
}
+const TestTreeItem *TestResult::findTestTreeItem() const
+{
+ return nullptr;
+}
+
Result::Type TestResult::resultFromString(const QString &resultString)
{
if (resultString == "pass")
diff --git a/src/plugins/autotest/testresult.h b/src/plugins/autotest/testresult.h
index a7414f85d3..d094c345ed 100644
--- a/src/plugins/autotest/testresult.h
+++ b/src/plugins/autotest/testresult.h
@@ -35,6 +35,8 @@
namespace Autotest {
namespace Internal {
+class TestTreeItem;
+
namespace Result{
enum Type {
Pass, FIRST_TYPE = Pass,
@@ -76,6 +78,7 @@ public:
virtual ~TestResult() {}
virtual const QString outputString(bool selected) const;
+ virtual const TestTreeItem *findTestTreeItem() const;
QString executable() const { return m_executable; }
QString name() const { return m_name; }
diff --git a/src/plugins/autotest/testresultspane.cpp b/src/plugins/autotest/testresultspane.cpp
index 41c9e216e6..c3317fdfe9 100644
--- a/src/plugins/autotest/testresultspane.cpp
+++ b/src/plugins/autotest/testresultspane.cpp
@@ -144,7 +144,7 @@ TestResultsPane::TestResultsPane(QObject *parent) :
connect(m_treeView, &Utils::TreeView::customContextMenuRequested,
this, &TestResultsPane::onCustomContextMenuRequested);
connect(m_treeView, &ResultsTreeView::copyShortcutTriggered, [this] () {
- onCopyItemTriggered(m_treeView->currentIndex());
+ onCopyItemTriggered(getTestResult(m_treeView->currentIndex()));
});
connect(m_model, &TestResultModel::requestExpansion, [this] (QModelIndex idx) {
m_treeView->expand(m_filterModel->mapFromSource(idx));
@@ -423,14 +423,14 @@ void TestResultsPane::onRunAllTriggered()
{
TestRunner *runner = TestRunner::instance();
runner->setSelectedTests(TestTreeModel::instance()->getAllTestCases());
- runner->prepareToRunTests(TestRunner::Run);
+ runner->prepareToRunTests(TestRunMode::Run);
}
void TestResultsPane::onRunSelectedTriggered()
{
TestRunner *runner = TestRunner::instance();
runner->setSelectedTests(TestTreeModel::instance()->getSelectedTests());
- runner->prepareToRunTests(TestRunner::Run);
+ runner->prepareToRunTests(TestRunMode::Run);
}
void TestResultsPane::initializeFilterMenu()
@@ -562,11 +562,12 @@ void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
{
const bool resultsAvailable = m_filterModel->hasResults();
const bool enabled = !m_testRunning && resultsAvailable;
- const QModelIndex clicked = m_treeView->indexAt(pos);
+ const TestResult *clicked = getTestResult(m_treeView->indexAt(pos));
QMenu menu;
+
QAction *action = new QAction(tr("Copy"), &menu);
action->setShortcut(QKeySequence(QKeySequence::Copy));
- action->setEnabled(resultsAvailable);
+ action->setEnabled(resultsAvailable && clicked);
connect(action, &QAction::triggered, [this, clicked] () {
onCopyItemTriggered(clicked);
});
@@ -582,14 +583,36 @@ void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
connect(action, &QAction::triggered, this, &TestResultsPane::onSaveWholeTriggered);
menu.addAction(action);
+ action = new QAction(tr("Run This Test"), &menu);
+ action->setEnabled(clicked && clicked->findTestTreeItem());
+ connect(action, &QAction::triggered, this, [this, clicked] {
+ onRunThisTestTriggered(TestRunMode::Run, clicked);
+ });
+ menu.addAction(action);
+
+ action = new QAction(tr("Debug This Test"), &menu);
+ action->setEnabled(clicked && clicked->findTestTreeItem());
+ connect(action, &QAction::triggered, this, [this, clicked] {
+ onRunThisTestTriggered(TestRunMode::Debug, clicked);
+ });
+ menu.addAction(action);
+
menu.exec(m_treeView->mapToGlobal(pos));
}
-void TestResultsPane::onCopyItemTriggered(const QModelIndex &idx)
+const TestResult *TestResultsPane::getTestResult(const QModelIndex &idx)
{
if (!idx.isValid())
- return;
+ return nullptr;
+
const TestResult *result = m_filterModel->testResult(idx);
+ QTC_CHECK(result);
+
+ return result;
+}
+
+void TestResultsPane::onCopyItemTriggered(const TestResult *result)
+{
QTC_ASSERT(result, return);
QApplication::clipboard()->setText(result->outputString(true));
}
@@ -614,6 +637,16 @@ void TestResultsPane::onSaveWholeTriggered()
}
}
+void TestResultsPane::onRunThisTestTriggered(TestRunMode runMode, const TestResult *result)
+{
+ QTC_ASSERT(result, return);
+
+ const TestTreeItem *item = result->findTestTreeItem();
+
+ if (item)
+ TestRunner::instance()->runTest(runMode, item);
+}
+
void TestResultsPane::toggleOutputStyle()
{
const bool displayText = m_outputWidget->currentIndex() == 0;
diff --git a/src/plugins/autotest/testresultspane.h b/src/plugins/autotest/testresultspane.h
index 6b83705567..911396b193 100644
--- a/src/plugins/autotest/testresultspane.h
+++ b/src/plugins/autotest/testresultspane.h
@@ -52,6 +52,7 @@ namespace Internal {
class TestResultModel;
class TestResultFilterModel;
+class TestResult;
class ResultsTreeView : public Utils::TreeView
{
@@ -109,9 +110,11 @@ private:
void onScrollBarRangeChanged(int, int max);
void updateRunActions();
void onCustomContextMenuRequested(const QPoint &pos);
- void onCopyItemTriggered(const QModelIndex &idx);
+ const TestResult *getTestResult(const QModelIndex &idx);
+ void onCopyItemTriggered(const TestResult *result);
void onCopyWholeTriggered();
void onSaveWholeTriggered();
+ void onRunThisTestTriggered(TestRunMode runMode, const TestResult *result);
void toggleOutputStyle();
QString getWholeOutput(const QModelIndex &parent = QModelIndex());
diff --git a/src/plugins/autotest/testrunconfiguration.h b/src/plugins/autotest/testrunconfiguration.h
index 593746dab5..b0cd1c8e1d 100644
--- a/src/plugins/autotest/testrunconfiguration.h
+++ b/src/plugins/autotest/testrunconfiguration.h
@@ -47,8 +47,9 @@ class TestRunConfiguration : public ProjectExplorer::RunConfiguration
public:
TestRunConfiguration(ProjectExplorer::Target *parent, TestConfiguration *config)
- : ProjectExplorer::RunConfiguration(parent, "AutoTest.TestRunConfig")
+ : ProjectExplorer::RunConfiguration(parent)
{
+ initialize("AutoTest.TestRunConfig");
setDefaultDisplayName(tr("AutoTest Debug"));
// disable QmlDebugger that is enabled by default
diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp
index dccaebaaf1..4b95da0812 100644
--- a/src/plugins/autotest/testrunner.cpp
+++ b/src/plugins/autotest/testrunner.cpp
@@ -31,7 +31,9 @@
#include "testrunconfiguration.h"
#include "testsettings.h"
#include "testoutputreader.h"
+#include "testtreeitem.h"
+#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
@@ -39,19 +41,27 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorersettings.h>
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <utils/outputformat.h>
#include <utils/runextensions.h>
#include <utils/hostosinfo.h>
+#include <QComboBox>
+#include <QDialogButtonBox>
+#include <QFormLayout>
#include <QFuture>
#include <QFutureInterface>
+#include <QLabel>
+#include <QPushButton>
#include <QTime>
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
-#include <debugger/debuggerstartparameters.h>
+
+#include <utils/algorithm.h>
namespace Autotest {
namespace Internal {
@@ -97,6 +107,28 @@ void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
m_selectedTests = selected;
}
+void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
+{
+ TestConfiguration *configuration;
+ switch (mode) {
+ case TestRunMode::Run:
+ case TestRunMode::RunWithoutDeploy:
+ configuration = item->testConfiguration();
+ break;
+ case TestRunMode::Debug:
+ case TestRunMode::DebugWithoutDeploy:
+ configuration = item->debugConfiguration();
+ break;
+ default:
+ configuration = nullptr;
+ }
+
+ if (configuration) {
+ setSelectedTests({configuration});
+ prepareToRunTests(mode);
+ }
+}
+
static QString processInformation(const QProcess &proc)
{
QString information("\nCommand line: " + proc.program() + ' ' + proc.arguments().join(' '));
@@ -119,6 +151,15 @@ static QString rcInfo(const TestConfiguration * const config)
return info + " \"" + config->runConfigDisplayName() + '"';
}
+static QString constructOmittedDetailsString(const QStringList &omitted)
+{
+ QString details = TestRunner::tr("Omitted the following arguments specified on the run "
+ "configuration page for \"%1\":");
+ for (const QString &arg : omitted)
+ details += "\n" + arg;
+ return details;
+}
+
static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
const QList<TestConfiguration *> selectedTests,
const TestSettings &settings)
@@ -128,7 +169,7 @@ static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
QEventLoop eventLoop;
int testCaseCount = 0;
for (TestConfiguration *config : selectedTests) {
- config->completeTestInformation(TestRunner::Run);
+ config->completeTestInformation(TestRunMode::Run);
if (config->project()) {
testCaseCount += config->testCaseCount();
if (!omitRunConfigWarnings && config->isGuessed()) {
@@ -174,7 +215,13 @@ static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
continue;
}
- testProcess.setArguments(testConfiguration->argumentsForTestRunner());
+ QStringList omitted;
+ testProcess.setArguments(testConfiguration->argumentsForTestRunner(&omitted));
+ if (!omitted.isEmpty()) {
+ const QString &details = constructOmittedDetailsString(omitted);
+ futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
+ details.arg(testConfiguration->displayName()))));
+ }
testProcess.setWorkingDirectory(testConfiguration->workingDirectory());
if (Utils::HostOsInfo::isWindowsHost())
environment.insert("QT_LOGGING_TO_CONSOLE", "1");
@@ -210,6 +257,11 @@ static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
TestRunner::tr("Test for project \"%1\" crashed.")
.arg(testConfiguration->displayName()) + processInformation(testProcess)
+ rcInfo(testConfiguration))));
+ } else if (!outputReader->hadValidOutput()) {
+ futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
+ TestRunner::tr("Test for project \"%1\" did not produce any expected output.")
+ .arg(testConfiguration->displayName()) + processInformation(testProcess)
+ + rcInfo(testConfiguration))));
}
if (canceledByTimeout) {
@@ -225,7 +277,7 @@ static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
futureInterface.setProgressValue(testCaseCount);
}
-void TestRunner::prepareToRunTests(Mode mode)
+void TestRunner::prepareToRunTests(TestRunMode mode)
{
m_runMode = mode;
ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings =
@@ -258,8 +310,8 @@ void TestRunner::prepareToRunTests(Mode mode)
return;
}
- if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunner::DebugWithoutDeploy
- || mode == TestRunner::RunWithoutDeploy) {
+ if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunMode::DebugWithoutDeploy
+ || mode == TestRunMode::RunWithoutDeploy) {
runOrDebugTests();
} else if (project->hasActiveBuildSettings()) {
buildProject(project);
@@ -270,8 +322,69 @@ void TestRunner::prepareToRunTests(Mode mode)
}
}
+static QString firstTestCaseTarget(const TestConfiguration *config)
+{
+ const QSet<QString> &internalTargets = config->internalTargets();
+ int size = internalTargets.size();
+ if (size)
+ return (*internalTargets.begin()).split('|').first();
+ return TestRunner::tr("<unknown>");
+}
+
+static bool askUserForRunConfiguration(TestConfiguration *config)
+{
+ using namespace ProjectExplorer;
+ RunConfigurationSelectionDialog dialog(firstTestCaseTarget(config),
+ Core::ICore::dialogParent());
+ if (dialog.exec() == QDialog::Accepted) {
+ const QString dName = dialog.displayName();
+ if (dName.isEmpty())
+ return false;
+ // run configuration has been selected - fill config based on this one..
+ const QString exe = dialog.executable();
+ // paranoia... can the current startup project have changed meanwhile?
+ if (auto project = SessionManager::startupProject()) {
+ if (auto target = project->activeTarget()) {
+ RunConfiguration *runConfig
+ = Utils::findOr(target->runConfigurations(), nullptr,
+ [&dName, &exe] (const RunConfiguration *rc) {
+ if (rc->displayName() != dName)
+ return false;
+ if (!rc->runnable().is<StandardRunnable>())
+ return false;
+ StandardRunnable runnable = rc->runnable().as<StandardRunnable>();
+ return runnable.executable == exe;
+ });
+ if (runConfig) {
+ config->setOriginalRunConfiguration(runConfig);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
void TestRunner::runTests()
{
+ QList<TestConfiguration *> toBeRemoved;
+ for (TestConfiguration *config : m_selectedTests) {
+ config->completeTestInformation(TestRunMode::Run);
+ if (!config->hasExecutable())
+ if (!askUserForRunConfiguration(config))
+ toBeRemoved.append(config);
+ }
+ for (TestConfiguration *config : toBeRemoved)
+ m_selectedTests.removeOne(config);
+ qDeleteAll(toBeRemoved);
+ toBeRemoved.clear();
+ if (m_selectedTests.isEmpty()) {
+ emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
+ tr("No test cases left for execution. Canceling test run."))));
+ onFinished();
+ return;
+ }
+
QFuture<TestResultPtr> future = Utils::runAsync(&performTestRun, m_selectedTests,
*AutotestPlugin::instance()->settings());
m_futureWatcher.setFuture(future);
@@ -312,7 +425,12 @@ void TestRunner::debugTests()
QTC_ASSERT(m_selectedTests.size() == 1, onFinished();return);
TestConfiguration *config = m_selectedTests.first();
- config->completeTestInformation(Debug);
+ config->completeTestInformation(TestRunMode::Debug);
+ if (!config->hasExecutable()) {
+ if (askUserForRunConfiguration(config))
+ config->completeTestInformation(config->originalRunConfiguration(), TestRunMode::Debug);
+ }
+
if (!config->runConfiguration()) {
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
TestRunner::tr("Failed to get run configuration."))));
@@ -330,13 +448,6 @@ void TestRunner::debugTests()
return;
}
- Debugger::DebuggerStartParameters sp;
- sp.inferior.executable = commandFilePath;
- sp.inferior.commandLineArguments = config->argumentsForTestRunner().join(' ');
- sp.inferior.environment = config->environment();
- sp.inferior.workingDirectory = config->workingDirectory();
- sp.displayName = config->displayName();
-
QString errorMessage;
auto runControl = new ProjectExplorer::RunControl(config->runConfiguration(),
ProjectExplorer::Constants::DEBUG_RUN_MODE);
@@ -347,7 +458,18 @@ void TestRunner::debugTests()
return;
}
- (void) new Debugger::DebuggerRunTool(runControl, sp);
+ QStringList omitted;
+ ProjectExplorer::StandardRunnable inferior = config->runnable();
+ inferior.executable = commandFilePath;
+ inferior.commandLineArguments = config->argumentsForTestRunner(&omitted).join(' ');
+ if (!omitted.isEmpty()) {
+ const QString &details = constructOmittedDetailsString(omitted);
+ emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
+ details.arg(config->displayName()))));
+ }
+ auto debugger = new Debugger::DebuggerRunTool(runControl);
+ debugger->setInferior(inferior);
+ debugger->setRunControlName(config->displayName());
bool useOutputProcessor = true;
if (ProjectExplorer::Target *targ = config->project()->activeTarget()) {
@@ -369,7 +491,7 @@ void TestRunner::debugTests()
connect(outputreader, &TestOutputReader::newOutputAvailable,
TestResultsPane::instance(), &TestResultsPane::addOutput);
connect(runControl, &ProjectExplorer::RunControl::appendMessageRequested,
- this, [this, outputreader]
+ this, [outputreader]
(ProjectExplorer::RunControl *, const QString &msg, Utils::OutputFormat format) {
processOutput(outputreader, msg, format);
});
@@ -387,12 +509,12 @@ void TestRunner::debugTests()
void TestRunner::runOrDebugTests()
{
switch (m_runMode) {
- case Run:
- case RunWithoutDeploy:
+ case TestRunMode::Run:
+ case TestRunMode::RunWithoutDeploy:
runTests();
break;
- case Debug:
- case DebugWithoutDeploy:
+ case TestRunMode::Debug:
+ case TestRunMode::DebugWithoutDeploy:
debugTests();
break;
default:
@@ -435,5 +557,90 @@ void TestRunner::onFinished()
emit testRunFinished();
}
+/*************************************************************************************************/
+
+RunConfigurationSelectionDialog::RunConfigurationSelectionDialog(const QString &testsInfo,
+ QWidget *parent)
+ : QDialog(parent)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setWindowTitle(tr("Select Run Configuration"));
+
+ m_details = new QLabel(tr("Could not determine which run configuration to choose for running"
+ " tests (%1)").arg(testsInfo), this);
+ m_rcCombo = new QComboBox(this);
+ m_executable = new QLabel(this);
+ m_arguments = new QLabel(this);
+ m_workingDir = new QLabel(this);
+ m_buttonBox = new QDialogButtonBox(this);
+ m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
+ m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
+
+ auto line = new QFrame(this);
+ line->setFrameShape(QFrame::HLine);
+ line->setFrameShadow(QFrame::Sunken);
+
+ auto formLayout = new QFormLayout;
+ formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+ formLayout->addRow(m_details);
+ formLayout->addRow(tr("Run Configuration:"), m_rcCombo);
+ formLayout->addRow(line);
+ formLayout->addRow(tr("Executable:"), m_executable);
+ formLayout->addRow(tr("Arguments:"), m_arguments);
+ formLayout->addRow(tr("Working Directory:"), m_workingDir);
+ // TODO Device support
+ auto vboxLayout = new QVBoxLayout(this);
+ vboxLayout->addLayout(formLayout);
+ vboxLayout->addStretch();
+ vboxLayout->addWidget(line);
+ vboxLayout->addWidget(m_buttonBox);
+
+ connect(m_rcCombo, &QComboBox::currentTextChanged,
+ this, &RunConfigurationSelectionDialog::updateLabels);
+ connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ populate();
+}
+
+QString RunConfigurationSelectionDialog::displayName() const
+{
+ return m_rcCombo ? m_rcCombo->currentText() : QString();
+}
+
+QString RunConfigurationSelectionDialog::executable() const
+{
+ return m_executable ? m_executable->text() : QString();
+}
+
+void RunConfigurationSelectionDialog::populate()
+{
+ m_rcCombo->addItem(QString(), QStringList({QString(), QString(), QString()})); // empty default
+
+ if (auto project = ProjectExplorer::SessionManager::startupProject()) {
+ if (auto target = project->activeTarget()) {
+ for (ProjectExplorer::RunConfiguration *rc : target->runConfigurations()) {
+ if (rc->runnable().is<ProjectExplorer::StandardRunnable>()) {
+ auto runnable = rc->runnable().as<ProjectExplorer::StandardRunnable>();
+ const QStringList rcDetails = { runnable.executable,
+ runnable.commandLineArguments,
+ runnable.workingDirectory };
+ m_rcCombo->addItem(rc->displayName(), rcDetails);
+ }
+ }
+ }
+ }
+}
+
+void RunConfigurationSelectionDialog::updateLabels()
+{
+ int i = m_rcCombo->currentIndex();
+ const QStringList values = m_rcCombo->itemData(i).toStringList();
+ QTC_ASSERT(values.size() == 3, return);
+ m_executable->setText(values.at(0));
+ m_arguments->setText(values.at(1));
+ m_workingDir->setText(values.at(2));
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/testrunner.h b/src/plugins/autotest/testrunner.h
index cb796ae5a0..0638401ca0 100644
--- a/src/plugins/autotest/testrunner.h
+++ b/src/plugins/autotest/testrunner.h
@@ -28,10 +28,17 @@
#include "testconfiguration.h"
#include "testresult.h"
+#include <QDialog>
#include <QFutureWatcher>
#include <QObject>
#include <QProcess>
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QDialogButtonBox;
+class QLabel;
+QT_END_NAMESPACE
+
namespace ProjectExplorer {
class Project;
}
@@ -44,21 +51,14 @@ class TestRunner : public QObject
Q_OBJECT
public:
- enum Mode
- {
- Run,
- RunWithoutDeploy,
- Debug,
- DebugWithoutDeploy
- };
-
static TestRunner* instance();
~TestRunner();
void setSelectedTests(const QList<TestConfiguration *> &selected);
+ void runTest(TestRunMode mode, const TestTreeItem *item);
bool isTestRunning() const { return m_executingTests; }
- void prepareToRunTests(Mode mode);
+ void prepareToRunTests(TestRunMode mode);
signals:
void testRunStarted();
@@ -79,11 +79,29 @@ private:
QFutureWatcher<TestResultPtr> m_futureWatcher;
QList<TestConfiguration *> m_selectedTests;
bool m_executingTests;
- Mode m_runMode = Run;
+ TestRunMode m_runMode = TestRunMode::Run;
// temporarily used if building before running is necessary
QMetaObject::Connection m_buildConnect;
};
+class RunConfigurationSelectionDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit RunConfigurationSelectionDialog(const QString &testsInfo, QWidget *parent = nullptr);
+ QString displayName() const;
+ QString executable() const;
+private:
+ void populate();
+ void updateLabels();
+ QLabel *m_details;
+ QLabel *m_executable;
+ QLabel *m_arguments;
+ QLabel *m_workingDir;
+ QComboBox *m_rcCombo;
+ QDialogButtonBox *m_buttonBox;
+};
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/testsettings.cpp b/src/plugins/autotest/testsettings.cpp
index 0b24390b95..3756ef3cc2 100644
--- a/src/plugins/autotest/testsettings.cpp
+++ b/src/plugins/autotest/testsettings.cpp
@@ -41,6 +41,7 @@ static const char limitResultOutputKey[] = "LimitResultOutput";
static const char autoScrollKey[] = "AutoScrollResults";
static const char filterScanKey[] = "FilterScan";
static const char filtersKey[] = "WhiteListFilters";
+static const char processArgsKey[] = "ProcessArgs";
static const int defaultTimeout = 60000;
@@ -57,6 +58,7 @@ void TestSettings::toSettings(QSettings *s) const
s->setValue(omitRunConfigWarnKey, omitRunConfigWarn);
s->setValue(limitResultOutputKey, limitResultOutput);
s->setValue(autoScrollKey, autoScroll);
+ s->setValue(processArgsKey, processArgs);
s->setValue(filterScanKey, filterScan);
s->setValue(filtersKey, whiteListFilters);
// store frameworks and their current active state
@@ -73,6 +75,7 @@ void TestSettings::fromSettings(QSettings *s)
omitRunConfigWarn = s->value(omitRunConfigWarnKey, false).toBool();
limitResultOutput = s->value(limitResultOutputKey, true).toBool();
autoScroll = s->value(autoScrollKey, true).toBool();
+ processArgs = s->value(processArgsKey, false).toBool();
filterScan = s->value(filterScanKey, false).toBool();
whiteListFilters = s->value(filtersKey, QStringList()).toStringList();
// try to get settings for registered frameworks
diff --git a/src/plugins/autotest/testsettings.h b/src/plugins/autotest/testsettings.h
index b3e0893b9d..449a56f322 100644
--- a/src/plugins/autotest/testsettings.h
+++ b/src/plugins/autotest/testsettings.h
@@ -48,6 +48,7 @@ struct TestSettings
bool limitResultOutput = true;
bool autoScroll = true;
bool filterScan = false;
+ bool processArgs = false;
QHash<Core::Id, bool> frameworks;
QStringList whiteListFilters;
};
diff --git a/src/plugins/autotest/testsettingspage.cpp b/src/plugins/autotest/testsettingspage.cpp
index 4f2322ab03..92bf473b73 100644
--- a/src/plugins/autotest/testsettingspage.cpp
+++ b/src/plugins/autotest/testsettingspage.cpp
@@ -148,6 +148,7 @@ void TestSettingsWidget::setSettings(const TestSettings &settings)
m_ui.omitRunConfigWarnCB->setChecked(settings.omitRunConfigWarn);
m_ui.limitResultOutputCB->setChecked(settings.limitResultOutput);
m_ui.autoScrollCB->setChecked(settings.autoScroll);
+ m_ui.processArgsCB->setChecked(settings.processArgs);
m_ui.filterGroupBox->setChecked(settings.filterScan);
populateFrameworksListWidget(settings.frameworks);
populateFiltersWidget(settings.whiteListFilters);
@@ -161,6 +162,7 @@ TestSettings TestSettingsWidget::settings() const
result.omitRunConfigWarn = m_ui.omitRunConfigWarnCB->isChecked();
result.limitResultOutput = m_ui.limitResultOutputCB->isChecked();
result.autoScroll = m_ui.autoScrollCB->isChecked();
+ result.processArgs = m_ui.processArgsCB->isChecked();
result.filterScan = m_ui.filterGroupBox->isChecked();
result.frameworks = frameworks();
result.whiteListFilters = filters();
diff --git a/src/plugins/autotest/testsettingspage.ui b/src/plugins/autotest/testsettingspage.ui
index 9ab4a5951f..dd0d43ed11 100644
--- a/src/plugins/autotest/testsettingspage.ui
+++ b/src/plugins/autotest/testsettingspage.ui
@@ -74,6 +74,17 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="processArgsCB">
+ <property name="toolTip">
+ <string>Allow passing arguments specified on the respective run configuration.
+Warning: this is an experimental feature and might lead to failing to execute the test executable.</string>
+ </property>
+ <property name="text">
+ <string>Process arguments</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0">
<property name="spacing">
<number>6</number>
diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp
index d5fba23b2a..d27c689e5b 100644
--- a/src/plugins/autotest/testtreeitem.cpp
+++ b/src/plugins/autotest/testtreeitem.cpp
@@ -30,6 +30,7 @@
#include <cplusplus/Icons.h>
#include <cpptools/cppmodelmanager.h>
+#include <cpptools/cpptoolsreuse.h>
#include <texteditor/texteditor.h>
#include <QIcon>
@@ -286,10 +287,13 @@ bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const
QSet<QString> TestTreeItem::internalTargets() const
{
auto cppMM = CppTools::CppModelManager::instance();
- const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(filePath());
+ const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(m_filePath);
QSet<QString> targets;
- for (const CppTools::ProjectPart::Ptr part : projectParts)
+ for (const CppTools::ProjectPart::Ptr part : projectParts) {
targets.insert(part->buildSystemTarget + '|' + part->projectFile);
+ if (part->buildTargetType != CppTools::ProjectPart::Executable)
+ targets.unite(TestTreeItem::dependingInternalTargets(cppMM, m_filePath));
+ }
return targets;
}
@@ -356,5 +360,28 @@ TestTreeItem *TestTreeItem::findChildBy(CompareFunction compare) const
return nullptr;
}
+/*
+ * try to find build system target that depends on the given file - if the file is no header
+ * try to find the corresponding header and use this instead to find the respective target
+ */
+QSet<QString> TestTreeItem::dependingInternalTargets(CppTools::CppModelManager *cppMM,
+ const QString &file)
+{
+ QSet<QString> result;
+ QTC_ASSERT(cppMM, return result);
+ const CPlusPlus::Snapshot snapshot = cppMM->snapshot();
+ QTC_ASSERT(snapshot.contains(file), return result);
+ bool wasHeader;
+ const QString correspondingFile
+ = CppTools::correspondingHeaderOrSource(file, &wasHeader, CppTools::CacheUsage::ReadOnly);
+ const Utils::FileNameList dependingFiles = snapshot.filesDependingOn(
+ wasHeader ? file : correspondingFile);
+ for (const Utils::FileName &fn : dependingFiles) {
+ for (const CppTools::ProjectPart::Ptr part : cppMM->projectPart(fn))
+ result.insert(part->buildSystemTarget + '|' + part->projectFile);
+ }
+ return result;
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h
index 2c2c728a2c..f4a7d735db 100644
--- a/src/plugins/autotest/testtreeitem.h
+++ b/src/plugins/autotest/testtreeitem.h
@@ -28,6 +28,7 @@
#include <utils/treemodel.h>
#include <QList>
+#include <QSet>
#include <QString>
#include <QMetaType>
@@ -40,6 +41,8 @@ namespace {
};
}
+namespace CppTools { class CppModelManager; }
+
namespace Autotest {
namespace Internal {
@@ -114,6 +117,8 @@ public:
protected:
typedef std::function<bool(const TestTreeItem *)> CompareFunction;
TestTreeItem *findChildBy(CompareFunction compare) const;
+ static QSet<QString> dependingInternalTargets(CppTools::CppModelManager *cppMM,
+ const QString &file);
private:
void revalidateCheckState();
diff --git a/src/plugins/autotoolsprojectmanager/autogenstep.cpp b/src/plugins/autotoolsprojectmanager/autogenstep.cpp
index 09e9c9a75d..6f62126e9b 100644
--- a/src/plugins/autotoolsprojectmanager/autogenstep.cpp
+++ b/src/plugins/autotoolsprojectmanager/autogenstep.cpp
@@ -110,7 +110,7 @@ bool AutogenStep::init(QList<const BuildStep *> &earlierSteps)
pp->setEnvironment(bc->environment());
const QString projectDir(bc->target()->project()->projectDirectory().toString());
pp->setWorkingDirectory(projectDir);
- pp->setCommand(QLatin1String("./autogen.sh"));
+ pp->setCommand("./autogen.sh");
pp->setArguments(additionalArguments());
pp->resolveAll();
@@ -123,9 +123,9 @@ void AutogenStep::run(QFutureInterface<bool> &fi)
// Check whether we need to run autogen.sh
const QString projectDir(bc->target()->project()->projectDirectory().toString());
- const QFileInfo configureInfo(projectDir + QLatin1String("/configure"));
- const QFileInfo configureAcInfo(projectDir + QLatin1String("/configure.ac"));
- const QFileInfo makefileAmInfo(projectDir + QLatin1String("/Makefile.am"));
+ const QFileInfo configureInfo(projectDir + "/configure");
+ const QFileInfo configureAcInfo(projectDir + "/configure.ac");
+ const QFileInfo makefileAmInfo(projectDir + "/Makefile.am");
if (!configureInfo.exists()
|| configureInfo.lastModified() < configureAcInfo.lastModified()
@@ -173,13 +173,13 @@ QVariantMap AutogenStep::toMap() const
{
QVariantMap map(AbstractProcessStep::toMap());
- map.insert(QLatin1String(AUTOGEN_ADDITIONAL_ARGUMENTS_KEY), m_additionalArguments);
+ map.insert(AUTOGEN_ADDITIONAL_ARGUMENTS_KEY, m_additionalArguments);
return map;
}
bool AutogenStep::fromMap(const QVariantMap &map)
{
- m_additionalArguments = map.value(QLatin1String(AUTOGEN_ADDITIONAL_ARGUMENTS_KEY)).toString();
+ m_additionalArguments = map.value(AUTOGEN_ADDITIONAL_ARGUMENTS_KEY).toString();
return BuildStep::fromMap(map);
}
@@ -226,7 +226,7 @@ void AutogenStepConfigWidget::updateDetails()
param.setEnvironment(bc->environment());
const QString projectDir(bc->target()->project()->projectDirectory().toString());
param.setWorkingDirectory(projectDir);
- param.setCommand(QLatin1String("./autogen.sh"));
+ param.setCommand("./autogen.sh");
param.setArguments(m_autogenStep->additionalArguments());
m_summaryText = param.summary(displayName());
emit updateSummary();
diff --git a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp
index 5512f5ecb4..0277ca91c9 100644
--- a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp
+++ b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp
@@ -111,7 +111,7 @@ bool AutoreconfStep::init(QList<const BuildStep *> &earlierSteps)
pp->setEnvironment(bc->environment());
const QString projectDir(bc->target()->project()->projectDirectory().toString());
pp->setWorkingDirectory(projectDir);
- pp->setCommand(QLatin1String("autoreconf"));
+ pp->setCommand("autoreconf");
pp->setArguments(additionalArguments());
pp->resolveAll();
@@ -125,7 +125,7 @@ void AutoreconfStep::run(QFutureInterface<bool> &fi)
// Check whether we need to run autoreconf
const QString projectDir(bc->target()->project()->projectDirectory().toString());
- if (!QFileInfo::exists(projectDir + QLatin1String("/configure")))
+ if (!QFileInfo::exists(projectDir + "/configure"))
m_runAutoreconf = true;
if (!m_runAutoreconf) {
@@ -168,13 +168,13 @@ QVariantMap AutoreconfStep::toMap() const
{
QVariantMap map = AbstractProcessStep::toMap();
- map.insert(QLatin1String(AUTORECONF_ADDITIONAL_ARGUMENTS_KEY), m_additionalArguments);
+ map.insert(AUTORECONF_ADDITIONAL_ARGUMENTS_KEY, m_additionalArguments);
return map;
}
bool AutoreconfStep::fromMap(const QVariantMap &map)
{
- m_additionalArguments = map.value(QLatin1String(AUTORECONF_ADDITIONAL_ARGUMENTS_KEY)).toString();
+ m_additionalArguments = map.value(AUTORECONF_ADDITIONAL_ARGUMENTS_KEY).toString();
return BuildStep::fromMap(map);
}
@@ -221,7 +221,7 @@ void AutoreconfStepConfigWidget::updateDetails()
param.setEnvironment(bc->environment());
const QString projectDir(bc->target()->project()->projectDirectory().toString());
param.setWorkingDirectory(projectDir);
- param.setCommand(QLatin1String("autoreconf"));
+ param.setCommand("autoreconf");
param.setArguments(m_autoreconfStep->additionalArguments());
m_summaryText = param.summary(displayName());
emit updateSummary();
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsopenprojectwizard.cpp b/src/plugins/autotoolsprojectmanager/autotoolsopenprojectwizard.cpp
index 82bc2e0162..37a8d6fd92 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsopenprojectwizard.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsopenprojectwizard.cpp
@@ -81,7 +81,7 @@ BuildPathPage::BuildPathPage(AutotoolsOpenProjectWizard *w) : QWizardPage(w),
QLabel *label = new QLabel(this);
label->setWordWrap(true);
label->setText(tr("Please enter the directory in which you want to build your project. "
- "Qt Creator recommends to not use the source directory for building. "
+ "It is not recommended to use the source directory for building. "
"This ensures that the source directory remains clean and enables multiple builds "
"with different settings."));
fl->addWidget(label);
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp
index e4a89e9edc..01105d8497 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp
+++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp
@@ -119,6 +119,7 @@ Project::RestoreResult AutotoolsProject::fromMap(const QVariantMap &map, QString
void AutotoolsProject::loadProjectTree()
{
+ emitParsingStarted();
if (m_makefileParserThread) {
// The thread is still busy parsing a previus configuration.
// Wait until the thread has been finished and delete it.
@@ -218,7 +219,7 @@ void AutotoolsProject::makefileParsingFinished()
m_makefileParserThread->deleteLater();
m_makefileParserThread = nullptr;
- emit parsingFinished();
+ emitParsingFinished(true);
}
void AutotoolsProject::onFileChanged(const QString &file)
@@ -297,7 +298,7 @@ void AutotoolsProject::updateCppCodeModel()
? target->activeBuildConfiguration()->buildDirectory().toString() : QString();
rpp.setIncludePaths(filterIncludes(absSrc, absBuild, m_makefileParserThread->includePaths()));
- rpp.setDefines(m_makefileParserThread->defines());
+ rpp.setMacros(m_makefileParserThread->macros());
rpp.setFiles(m_files);
m_cppCodeModelUpdater->update({this, cToolChain, cxxToolChain, k, {rpp}});
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.h b/src/plugins/autotoolsprojectmanager/autotoolsproject.h
index 2183ee92b7..b9016bdcc0 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsproject.h
+++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.h
@@ -39,7 +39,6 @@ namespace AutotoolsProjectManager {
namespace Internal {
class MakefileParserThread;
-class AutotoolsTarget;
/**
* @brief Implementation of the ProjectExplorer::Project interface.
diff --git a/src/plugins/autotoolsprojectmanager/configurestep.cpp b/src/plugins/autotoolsprojectmanager/configurestep.cpp
index fbfd5f47e6..8fdb2c6728 100644
--- a/src/plugins/autotoolsprojectmanager/configurestep.cpp
+++ b/src/plugins/autotoolsprojectmanager/configurestep.cpp
@@ -58,9 +58,9 @@ static QString projectDirRelativeToBuildDir(BuildConfiguration *bc) {
QString projDirToBuildDir = buildDir.relativeFilePath(
bc->target()->project()->projectDirectory().toString());
if (projDirToBuildDir.isEmpty())
- return QLatin1String("./");
- if (!projDirToBuildDir.endsWith(QLatin1Char('/')))
- projDirToBuildDir.append(QLatin1Char('/'));
+ return QString("./");
+ if (!projDirToBuildDir.endsWith('/'))
+ projDirToBuildDir.append('/');
return projDirToBuildDir;
}
@@ -125,7 +125,7 @@ bool ConfigureStep::init(QList<const BuildStep *> &earlierSteps)
pp->setMacroExpander(bc->macroExpander());
pp->setEnvironment(bc->environment());
pp->setWorkingDirectory(bc->buildDirectory().toString());
- pp->setCommand(projectDirRelativeToBuildDir(bc) + QLatin1String("configure"));
+ pp->setCommand(projectDirRelativeToBuildDir(bc) + "configure");
pp->setArguments(additionalArguments());
pp->resolveAll();
@@ -138,8 +138,8 @@ void ConfigureStep::run(QFutureInterface<bool>& fi)
//Check whether we need to run configure
const QString projectDir(bc->target()->project()->projectDirectory().toString());
- const QFileInfo configureInfo(projectDir + QLatin1String("/configure"));
- const QFileInfo configStatusInfo(bc->buildDirectory().toString() + QLatin1String("/config.status"));
+ const QFileInfo configureInfo(projectDir + "/configure");
+ const QFileInfo configStatusInfo(bc->buildDirectory().toString() + "/config.status");
if (!configStatusInfo.exists()
|| configStatusInfo.lastModified() < configureInfo.lastModified()) {
@@ -191,13 +191,13 @@ QVariantMap ConfigureStep::toMap() const
{
QVariantMap map = AbstractProcessStep::toMap();
- map.insert(QLatin1String(CONFIGURE_ADDITIONAL_ARGUMENTS_KEY), m_additionalArguments);
+ map.insert(CONFIGURE_ADDITIONAL_ARGUMENTS_KEY, m_additionalArguments);
return map;
}
bool ConfigureStep::fromMap(const QVariantMap &map)
{
- m_additionalArguments = map.value(QLatin1String(CONFIGURE_ADDITIONAL_ARGUMENTS_KEY)).toString();
+ m_additionalArguments = map.value(CONFIGURE_ADDITIONAL_ARGUMENTS_KEY).toString();
return BuildStep::fromMap(map);
}
@@ -245,7 +245,7 @@ void ConfigureStepConfigWidget::updateDetails()
param.setMacroExpander(bc->macroExpander());
param.setEnvironment(bc->environment());
param.setWorkingDirectory(bc->buildDirectory().toString());
- param.setCommand(projectDirRelativeToBuildDir(bc) + QLatin1String("configure"));
+ param.setCommand(projectDirRelativeToBuildDir(bc) + "configure");
param.setArguments(m_configureStep->additionalArguments());
m_summaryText = param.summaryInWorkdir(displayName());
emit updateSummary();
diff --git a/src/plugins/autotoolsprojectmanager/makefileparser.cpp b/src/plugins/autotoolsprojectmanager/makefileparser.cpp
index 74e29054ec..9c3e32216b 100644
--- a/src/plugins/autotoolsprojectmanager/makefileparser.cpp
+++ b/src/plugins/autotoolsprojectmanager/makefileparser.cpp
@@ -108,9 +108,9 @@ QStringList MakefileParser::includePaths() const
return m_includePaths;
}
-QByteArray MakefileParser::defines() const
+ProjectExplorer::Macros MakefileParser::macros() const
{
- return m_defines;
+ return m_macros;
}
QStringList MakefileParser::cflags() const
@@ -449,11 +449,7 @@ bool MakefileParser::maybeParseDefine(const QString &term)
{
if (term.startsWith(QLatin1String("-D"))) {
QString def = term.mid(2); // remove the "-D"
- QByteArray data = def.toUtf8();
- int pos = data.indexOf('=');
- if (pos >= 0)
- data[pos] = ' ';
- m_defines += (QByteArray("#define ") + data + '\n');
+ m_macros += ProjectExplorer::Macro::fromKeyValue(def);
return true;
}
return false;
diff --git a/src/plugins/autotoolsprojectmanager/makefileparser.h b/src/plugins/autotoolsprojectmanager/makefileparser.h
index beaa1a57db..d6387bc29c 100644
--- a/src/plugins/autotoolsprojectmanager/makefileparser.h
+++ b/src/plugins/autotoolsprojectmanager/makefileparser.h
@@ -27,10 +27,13 @@
#pragma once
+#include <projectexplorer/projectmacro.h>
+
#include <QMutex>
#include <QStringList>
#include <QTextStream>
#include <QObject>
+#include <QVector>
QT_FORWARD_DECLARE_CLASS(QDir)
@@ -49,6 +52,8 @@ class MakefileParser : public QObject
{
Q_OBJECT
+ using Macros = ProjectExplorer::Macros;
+
public:
/**
* @param makefile Filename including path of the autotools
@@ -98,7 +103,7 @@ public:
* #define X12_HAS_DEPRECATED
* @endcode
*/
- QByteArray defines() const;
+ Macros macros() const;
/**
* @return List of compiler flags for C.
@@ -267,7 +272,7 @@ private:
QStringList m_sources; ///< Return value for MakefileParser::sources()
QStringList m_makefiles; ///< Return value for MakefileParser::makefiles()
QStringList m_includePaths; ///< Return value for MakefileParser::includePaths()
- QByteArray m_defines; ///< Return value for MakefileParser::defines()
+ Macros m_macros; ///< Return value for MakefileParser::macros()
QStringList m_cflags; ///< Return value for MakefileParser::cflags()
QStringList m_cxxflags; ///< Return value for MakefileParser::cxxflags()
QStringList m_cppflags; ///< The cpp flags, which will be part of both cflags and cxxflags
diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp
index cfe7e9757f..a33d39599b 100644
--- a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp
+++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp
@@ -61,10 +61,10 @@ QStringList MakefileParserThread::includePaths() const
return m_includePaths;
}
-QByteArray MakefileParserThread::defines() const
+ProjectExplorer::Macros MakefileParserThread::macros() const
{
QMutexLocker locker(&m_mutex);
- return m_defines;
+ return m_macros;
}
QStringList MakefileParserThread::cflags() const
@@ -109,7 +109,7 @@ void MakefileParserThread::run()
m_sources = m_parser.sources();
m_makefiles = m_parser.makefiles();
m_includePaths = m_parser.includePaths();
- m_defines = m_parser.defines();
+ m_macros = m_parser.macros();
m_cflags = m_parser.cflags();
m_cxxflags = m_parser.cxxflags();
}
diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.h b/src/plugins/autotoolsprojectmanager/makefileparserthread.h
index 94b965d133..3e16bdccc4 100644
--- a/src/plugins/autotoolsprojectmanager/makefileparserthread.h
+++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.h
@@ -29,9 +29,12 @@
#include "makefileparser.h"
+#include <projectexplorer/projectmacro.h>
+
#include <QMutex>
#include <QStringList>
#include <QThread>
+#include <QVector>
namespace AutotoolsProjectManager {
namespace Internal {
@@ -47,6 +50,8 @@ class MakefileParserThread : public QThread
{
Q_OBJECT
+ using Macros = ProjectExplorer::Macros;
+
public:
MakefileParserThread(const QString &makefile);
@@ -82,10 +87,10 @@ public:
QStringList includePaths() const;
/**
- * @return Concatenated defines. Should be invoked, after the signal
+ * @return Concatenated macros. Should be invoked, after the signal
* finished() has been emitted.
*/
- QByteArray defines() const;
+ Macros macros() const;
/**
* @return List of compiler flags for C. Should be invoked, after the signal
@@ -134,7 +139,7 @@ private:
QStringList m_sources; ///< Return value for MakefileParserThread::sources()
QStringList m_makefiles; ///< Return value for MakefileParserThread::makefiles()
QStringList m_includePaths; ///< Return value for MakefileParserThread::includePaths()
- QByteArray m_defines; ///< Return value for MakefileParserThread::defines()
+ Macros m_macros; ///< Return value for MakefileParserThread::macros()
QStringList m_cflags; ///< Return value for MakefileParserThread::cflags()
QStringList m_cxxflags; ///< Return value for MakefileParserThread::cxxflags()
};
diff --git a/src/plugins/autotoolsprojectmanager/makestep.cpp b/src/plugins/autotoolsprojectmanager/makestep.cpp
index ce8be4c9b9..3fb0ec4105 100644
--- a/src/plugins/autotoolsprojectmanager/makestep.cpp
+++ b/src/plugins/autotoolsprojectmanager/makestep.cpp
@@ -60,7 +60,7 @@ const char MAKE_STEP_ADDITIONAL_ARGUMENTS_KEY[] = "AutotoolsProjectManager.MakeS
// MakeStepFactory class
//////////////////////////
MakeStepFactory::MakeStepFactory(QObject *parent) : IBuildStepFactory(parent)
-{ setObjectName(QLatin1String("Autotools::MakeStepFactory")); }
+{ setObjectName("Autotools::MakeStepFactory"); }
QList<BuildStepInfo> MakeStepFactory::availableSteps(BuildStepList *parent) const
{
@@ -198,17 +198,17 @@ QVariantMap MakeStep::toMap() const
{
QVariantMap map = AbstractProcessStep::toMap();
- map.insert(QLatin1String(BUILD_TARGETS_KEY), m_buildTargets);
- map.insert(QLatin1String(MAKE_STEP_ADDITIONAL_ARGUMENTS_KEY), m_additionalArguments);
- map.insert(QLatin1String(CLEAN_KEY), m_clean);
+ map.insert(BUILD_TARGETS_KEY, m_buildTargets);
+ map.insert(MAKE_STEP_ADDITIONAL_ARGUMENTS_KEY, m_additionalArguments);
+ map.insert(CLEAN_KEY, m_clean);
return map;
}
bool MakeStep::fromMap(const QVariantMap &map)
{
- m_buildTargets = map.value(QLatin1String(BUILD_TARGETS_KEY)).toStringList();
- m_additionalArguments = map.value(QLatin1String(MAKE_STEP_ADDITIONAL_ARGUMENTS_KEY)).toString();
- m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool();
+ m_buildTargets = map.value(BUILD_TARGETS_KEY).toStringList();
+ m_additionalArguments = map.value(MAKE_STEP_ADDITIONAL_ARGUMENTS_KEY).toString();
+ m_clean = map.value(CLEAN_KEY).toBool();
return BuildStep::fromMap(map);
}
@@ -236,8 +236,15 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep) :
makeStep, &MakeStep::setAdditionalArguments);
connect(makeStep, &MakeStep::additionalArgumentsChanged,
this, &MakeStepConfigWidget::updateDetails);
- connect(m_makeStep->project(), &Project::environmentChanged,
- this, &MakeStepConfigWidget::updateDetails);
+ m_makeStep->project()->subscribeSignal(&BuildConfiguration::environmentChanged, this, [this]() {
+ if (static_cast<BuildConfiguration *>(sender())->isActive())
+ updateDetails();
+ });
+ connect(makeStep->project(), &Project::activeProjectConfigurationChanged,
+ this, [this](ProjectConfiguration *pc) {
+ if (pc && pc->isActive())
+ updateDetails();
+ });
}
QString MakeStepConfigWidget::displayName() const
@@ -269,7 +276,7 @@ void MakeStepConfigWidget::updateDetails()
param.setArguments(arguments);
m_summaryText = param.summary(displayName());
} else {
- m_summaryText = QLatin1String("<b>") + ToolChainKitInformation::msgNoToolChainInTarget() + QLatin1String("</b>");
+ m_summaryText = "<b>" + ToolChainKitInformation::msgNoToolChainInTarget() + "</b>";
}
emit updateSummary();
diff --git a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp
index 54ae4a596b..9b7b8606be 100644
--- a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp
+++ b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp
@@ -113,15 +113,19 @@ private:
};
BareMetalCustomRunConfiguration::BareMetalCustomRunConfiguration(ProjectExplorer::Target *parent)
- : BareMetalRunConfiguration(parent, runConfigId(), QString())
+ : BareMetalRunConfiguration(parent)
{
}
-BareMetalCustomRunConfiguration::BareMetalCustomRunConfiguration(ProjectExplorer::Target *parent,
- BareMetalCustomRunConfiguration *source)
- : BareMetalRunConfiguration(parent, source)
- , m_localExecutable(source->m_localExecutable)
+void BareMetalCustomRunConfiguration::initialize()
{
+ BareMetalRunConfiguration::initialize(runConfigId(), QString());
+}
+
+void BareMetalCustomRunConfiguration::copyFrom(const BareMetalCustomRunConfiguration *source)
+{
+ BareMetalRunConfiguration::copyFrom(source);
+ m_localExecutable = source->m_localExecutable;
}
bool BareMetalCustomRunConfiguration::isConfigured() const
diff --git a/src/plugins/baremetal/baremetalcustomrunconfiguration.h b/src/plugins/baremetal/baremetalcustomrunconfiguration.h
index 9c9118033a..30812fc3cd 100644
--- a/src/plugins/baremetal/baremetalcustomrunconfiguration.h
+++ b/src/plugins/baremetal/baremetalcustomrunconfiguration.h
@@ -36,11 +36,11 @@ class BareMetalCustomRunConfiguration : public BareMetalRunConfiguration
{
Q_OBJECT
public:
- BareMetalCustomRunConfiguration(ProjectExplorer::Target *parent);
- BareMetalCustomRunConfiguration(ProjectExplorer::Target *parent,
- BareMetalCustomRunConfiguration *source);
+ explicit BareMetalCustomRunConfiguration(ProjectExplorer::Target *parent);
+
+ void initialize();
+ void copyFrom(const BareMetalCustomRunConfiguration *source);
- bool isEnabled() const override { return true; }
bool isConfigured() const override;
ConfigurationState ensureConfigured(QString *errorMessage) override;
QWidget *createConfigurationWidget() override;
diff --git a/src/plugins/baremetal/baremetaldebugsupport.cpp b/src/plugins/baremetal/baremetaldebugsupport.cpp
index c4615daa6e..b6d85ae4bc 100644
--- a/src/plugins/baremetal/baremetaldebugsupport.cpp
+++ b/src/plugins/baremetal/baremetaldebugsupport.cpp
@@ -106,28 +106,32 @@ void BareMetalDebugSupport::start()
const GdbServerProvider *p = GdbServerProviderManager::findProvider(dev->gdbServerProviderId());
QTC_ASSERT(p, reportFailure(); return);
- Debugger::DebuggerStartParameters sp;
-
+#if 0
+ // Currently baremetal plugin does not provide way to configure deployments steps
+ // FIXME: Should it?
+ QString commands;
if (const BuildConfiguration *bc = target->activeBuildConfiguration()) {
if (BuildStepList *bsl = bc->stepList(BareMetalGdbCommandsDeployStep::stepId())) {
foreach (const BareMetalGdbCommandsDeployStep *bs, bsl->allOfType<BareMetalGdbCommandsDeployStep>()) {
- if (!sp.commandsAfterConnect.endsWith("\n"))
- sp.commandsAfterConnect.append("\n");
- sp.commandsAfterConnect.append(bs->gdbCommands());
+ if (!commands.endsWith("\n"))
+ commands.append("\n");
+ commands.append(bs->gdbCommands());
}
}
}
-
- sp.inferior.executable = bin;
- sp.inferior.commandLineArguments = rc->arguments();
- sp.symbolFile = bin;
- sp.startMode = AttachToRemoteServer;
- sp.commandsAfterConnect = p->initCommands();
- sp.commandsForReset = p->resetCommands();
- sp.remoteChannel = p->channel();
- sp.useContinueInsteadOfRun = true;
-
- setStartParameters(sp);
+ setCommandsAfterConnect(commands);
+#endif
+
+ StandardRunnable inferior;
+ inferior.executable = bin;
+ inferior.commandLineArguments = rc->arguments();
+ setInferior(inferior);
+ setSymbolFile(bin);
+ setStartMode(AttachToRemoteServer);
+ setCommandsAfterConnect(p->initCommands()); // .. and here?
+ setCommandsForReset(p->resetCommands());
+ setRemoteChannel(p->channel());
+ setUseContinueInsteadOfRun(true);
DebuggerRunTool::start();
}
diff --git a/src/plugins/baremetal/baremetalrunconfiguration.cpp b/src/plugins/baremetal/baremetalrunconfiguration.cpp
index 13a14fdbcb..c0155f7bf7 100644
--- a/src/plugins/baremetal/baremetalrunconfiguration.cpp
+++ b/src/plugins/baremetal/baremetalrunconfiguration.cpp
@@ -45,45 +45,33 @@ const char ProFileKey[] = "Qt4ProjectManager.MaemoRunConfiguration.ProFile";
const char WorkingDirectoryKey[] = "BareMetal.RunConfig.WorkingDirectory";
-BareMetalRunConfiguration::BareMetalRunConfiguration(Target *parent, BareMetalRunConfiguration *other)
- : RunConfiguration(parent, other),
- m_projectFilePath(other->m_projectFilePath),
- m_workingDirectory(other->m_workingDirectory)
+BareMetalRunConfiguration::BareMetalRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
- init();
-}
-
-BareMetalRunConfiguration::BareMetalRunConfiguration(Target *parent,
- const Core::Id id,
- const QString &projectFilePath)
- : RunConfiguration(parent, id),
- m_projectFilePath(projectFilePath)
-{
- addExtraAspect(new ArgumentsAspect(this, QLatin1String("Qt4ProjectManager.MaemoRunConfiguration.Arguments")));
- init();
-}
-
-void BareMetalRunConfiguration::init()
-{
- setDefaultDisplayName(defaultDisplayName());
-
- connect(target(), &Target::deploymentDataChanged,
+ addExtraAspect(new ArgumentsAspect(this, "Qt4ProjectManager.MaemoRunConfiguration.Arguments"));
+ connect(target, &Target::deploymentDataChanged,
this, &BareMetalRunConfiguration::handleBuildSystemDataUpdated);
- connect(target(), &Target::applicationTargetsChanged,
+ connect(target, &Target::applicationTargetsChanged,
this, &BareMetalRunConfiguration::handleBuildSystemDataUpdated);
- connect(target(), &Target::kitChanged,
+ connect(target, &Target::kitChanged,
this, &BareMetalRunConfiguration::handleBuildSystemDataUpdated); // Handles device changes, etc.
}
-bool BareMetalRunConfiguration::isEnabled() const
+void BareMetalRunConfiguration::copyFrom(const BareMetalRunConfiguration *other)
{
- m_disabledReason.clear(); // FIXME: Check this makes sense.
- return true;
+ RunConfiguration::copyFrom(other);
+ m_projectFilePath = other->m_projectFilePath;
+ m_workingDirectory = other->m_workingDirectory;
+
+ setDefaultDisplayName(defaultDisplayName());
}
-QString BareMetalRunConfiguration::disabledReason() const
+void BareMetalRunConfiguration::initialize(const Core::Id id, const QString &projectFilePath)
{
- return m_disabledReason;
+ RunConfiguration::initialize(id);
+ m_projectFilePath = projectFilePath;
+
+ setDefaultDisplayName(defaultDisplayName());
}
QWidget *BareMetalRunConfiguration::createConfigurationWidget()
@@ -165,11 +153,6 @@ QString BareMetalRunConfiguration::buildSystemTarget() const
return (bst == targets.list.constEnd()) ? QString() : bst->targetName;
}
-void BareMetalRunConfiguration::setDisabledReason(const QString &reason) const
-{
- m_disabledReason = reason;
-}
-
void BareMetalRunConfiguration::handleBuildSystemDataUpdated()
{
emit targetInformationChanged();
diff --git a/src/plugins/baremetal/baremetalrunconfiguration.h b/src/plugins/baremetal/baremetalrunconfiguration.h
index ef400cb203..c5e8e47b00 100644
--- a/src/plugins/baremetal/baremetalrunconfiguration.h
+++ b/src/plugins/baremetal/baremetalrunconfiguration.h
@@ -37,15 +37,12 @@ class BareMetalRunConfiguration : public ProjectExplorer::RunConfiguration
Q_OBJECT
Q_DISABLE_COPY(BareMetalRunConfiguration)
- friend class BareMetalRunConfigurationFactory;
+ friend class ProjectExplorer::IRunConfigurationFactory;
friend class BareMetalRunConfigurationWidget;
public:
- explicit BareMetalRunConfiguration(ProjectExplorer::Target *parent, Core::Id id,
- const QString &projectFilePath);
+ explicit BareMetalRunConfiguration(ProjectExplorer::Target *target);
- bool isEnabled() const override;
- QString disabledReason() const override;
QWidget *createConfigurationWidget() override;
Utils::OutputFormatter *createOutputFormatter() const override;
@@ -67,17 +64,15 @@ signals:
void targetInformationChanged() const;
protected:
- BareMetalRunConfiguration(ProjectExplorer::Target *parent, BareMetalRunConfiguration *source);
bool fromMap(const QVariantMap &map) override;
QString defaultDisplayName();
- void setDisabledReason(const QString &reason) const;
+ void initialize(Core::Id id, const QString &projectFilePath);
+ void copyFrom(const BareMetalRunConfiguration *source);
private:
void handleBuildSystemDataUpdated();
- void init();
QString m_projectFilePath;
- mutable QString m_disabledReason;
QString m_workingDirectory;
};
diff --git a/src/plugins/baremetal/baremetalrunconfigurationfactory.cpp b/src/plugins/baremetal/baremetalrunconfigurationfactory.cpp
index fc507345f3..4c0c34596a 100644
--- a/src/plugins/baremetal/baremetalrunconfigurationfactory.cpp
+++ b/src/plugins/baremetal/baremetalrunconfigurationfactory.cpp
@@ -107,7 +107,7 @@ RunConfiguration *BareMetalRunConfigurationFactory::doCreate(Target *parent, Cor
{
if (id == BareMetalCustomRunConfiguration::runConfigId())
return new BareMetalCustomRunConfiguration(parent);
- return new BareMetalRunConfiguration(parent, id, pathFromId(id));
+ return createHelper<BareMetalRunConfiguration>(parent, id, pathFromId(id));
}
RunConfiguration *BareMetalRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
@@ -120,10 +120,9 @@ RunConfiguration *BareMetalRunConfigurationFactory::doRestore(Target *parent, co
RunConfiguration *BareMetalRunConfigurationFactory::clone(Target *parent, RunConfiguration *source)
{
QTC_ASSERT(canClone(parent, source), return 0);
- if (BareMetalCustomRunConfiguration *old = qobject_cast<BareMetalCustomRunConfiguration *>(source))
- return new BareMetalCustomRunConfiguration(parent, old);
- BareMetalRunConfiguration *old = static_cast<BareMetalRunConfiguration*>(source);
- return new BareMetalRunConfiguration(parent,old);
+ if (qobject_cast<BareMetalCustomRunConfiguration *>(source))
+ return cloneHelper<BareMetalCustomRunConfiguration>(parent, source);
+ return cloneHelper<BareMetalRunConfiguration>(parent, source);
}
bool BareMetalRunConfigurationFactory::canHandle(const Target *target) const
diff --git a/src/plugins/baremetal/baremetalrunconfigurationwidget.cpp b/src/plugins/baremetal/baremetalrunconfigurationwidget.cpp
index 4973ba16a8..942702ca23 100644
--- a/src/plugins/baremetal/baremetalrunconfigurationwidget.cpp
+++ b/src/plugins/baremetal/baremetalrunconfigurationwidget.cpp
@@ -49,9 +49,6 @@ public:
{ }
BareMetalRunConfiguration * const runConfiguration;
- QWidget topWidget;
- QLabel disabledIcon;
- QLabel disabledReason;
QLineEdit workingDirLineEdit;
QLabel localExecutableLabel;
QFormLayout genericWidgetsLayout;
@@ -63,13 +60,9 @@ using namespace Internal;
BareMetalRunConfigurationWidget::BareMetalRunConfigurationWidget(BareMetalRunConfiguration *runConfiguration,
QWidget *parent)
- : QWidget(parent),d(new BareMetalRunConfigurationWidgetPrivate(runConfiguration))
+ : QWidget(parent), d(new BareMetalRunConfigurationWidgetPrivate(runConfiguration))
{
- QVBoxLayout *topLayout = new QVBoxLayout(this);
- topLayout->setMargin(0);
- addDisabledLabel(topLayout);
- topLayout->addWidget(&d->topWidget);
- QVBoxLayout *mainLayout = new QVBoxLayout(&d->topWidget);
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(0);
Utils::DetailsWidget *detailsContainer = new Utils::DetailsWidget(this);
@@ -97,9 +90,6 @@ BareMetalRunConfigurationWidget::BareMetalRunConfigurationWidget(BareMetalRunCon
this, &BareMetalRunConfigurationWidget::updateTargetInformation);
connect(&d->workingDirLineEdit, &QLineEdit::textEdited,
this, &BareMetalRunConfigurationWidget::handleWorkingDirectoryChanged);
- connect(d->runConfiguration, &ProjectExplorer::RunConfiguration::enabledChanged,
- this, &BareMetalRunConfigurationWidget::runConfigurationEnabledChange);
- runConfigurationEnabledChange();
}
BareMetalRunConfigurationWidget::~BareMetalRunConfigurationWidget()
@@ -107,18 +97,6 @@ BareMetalRunConfigurationWidget::~BareMetalRunConfigurationWidget()
delete d;
}
-void BareMetalRunConfigurationWidget::addDisabledLabel(QVBoxLayout *topLayout)
-{
- QHBoxLayout * const hl = new QHBoxLayout;
- hl->addStretch();
- d->disabledIcon.setPixmap(Utils::Icons::WARNING.pixmap());
- hl->addWidget(&d->disabledIcon);
- d->disabledReason.setVisible(false);
- hl->addWidget(&d->disabledReason);
- hl->addStretch();
- topLayout->addLayout(hl);
-}
-
void BareMetalRunConfigurationWidget::updateTargetInformation()
{
setLabelText(d->localExecutableLabel,
@@ -138,13 +116,4 @@ void BareMetalRunConfigurationWidget::setLabelText(QLabel &label, const QString
label.setText(regularText.isEmpty() ? errorMessage : regularText);
}
-void BareMetalRunConfigurationWidget::runConfigurationEnabledChange()
-{
- bool enabled = d->runConfiguration->isEnabled();
- d->topWidget.setEnabled(enabled);
- d->disabledIcon.setVisible(!enabled);
- d->disabledReason.setVisible(!enabled);
- d->disabledReason.setText(d->runConfiguration->disabledReason());
-}
-
} // namespace BareMetal
diff --git a/src/plugins/baremetal/baremetalrunconfigurationwidget.h b/src/plugins/baremetal/baremetalrunconfigurationwidget.h
index 76f9cc86b7..d5a5a271cd 100644
--- a/src/plugins/baremetal/baremetalrunconfigurationwidget.h
+++ b/src/plugins/baremetal/baremetalrunconfigurationwidget.h
@@ -46,9 +46,6 @@ public:
explicit BareMetalRunConfigurationWidget(BareMetalRunConfiguration *runConfiguration,
QWidget *parent = 0);
~BareMetalRunConfigurationWidget();
- void addDisabledLabel(QVBoxLayout *topLayout);
-
- Q_SLOT void runConfigurationEnabledChange();
private:
void updateTargetInformation();
diff --git a/src/plugins/baremetal/images/baremetaldevice.png b/src/plugins/baremetal/images/baremetaldevice.png
index 34ac48c118..cc7f96a7fd 100644
--- a/src/plugins/baremetal/images/baremetaldevice.png
+++ b/src/plugins/baremetal/images/baremetaldevice.png
Binary files differ
diff --git a/src/plugins/baremetal/images/baremetaldevice@2x.png b/src/plugins/baremetal/images/baremetaldevice@2x.png
index d1341f90ee..f99932ab5e 100644
--- a/src/plugins/baremetal/images/baremetaldevice@2x.png
+++ b/src/plugins/baremetal/images/baremetaldevice@2x.png
Binary files differ
diff --git a/src/plugins/bazaar/bazaarplugin.cpp b/src/plugins/bazaar/bazaarplugin.cpp
index 49b0d9f4af..a41710b24b 100644
--- a/src/plugins/bazaar/bazaarplugin.cpp
+++ b/src/plugins/bazaar/bazaarplugin.cpp
@@ -154,8 +154,7 @@ bool BazaarPlugin::initialize(const QStringList &arguments, QString *errorMessag
Context context(Constants::BAZAAR_CONTEXT);
m_client = new BazaarClient;
- auto vcsCtrl = new BazaarControl(m_client);
- initializeVcs(vcsCtrl, context);
+ auto vcsCtrl = initializeVcs<BazaarControl>(context, m_client);
connect(m_client, &VcsBaseClient::changed, vcsCtrl, &BazaarControl::changed);
addAutoReleasedObject(new OptionsPage(vcsCtrl));
@@ -510,6 +509,9 @@ void BazaarPlugin::createSubmitEditorActions()
void BazaarPlugin::commit()
{
+ if (!promptBeforeCommit())
+ return;
+
if (raiseSubmitEditor())
return;
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
index 0dcfbf7c0e..ec0065ed95 100644
--- a/src/plugins/beautifier/beautifierplugin.cpp
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -45,12 +45,12 @@
#include <diffeditor/differ.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
-#include <texteditor/convenience.h>
#include <texteditor/textdocument.h>
#include <texteditor/textdocumentlayout.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorconstants.h>
#include <utils/algorithm.h>
+#include <utils/textutils.h>
#include <utils/fileutils.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
@@ -169,7 +169,7 @@ QString sourceData(TextEditorWidget *editor, int startPos, int endPos)
{
return (startPos < 0)
? editor->toPlainText()
- : Convenience::textAt(editor->textCursor(), startPos, (endPos - startPos));
+ : Utils::Text::textAt(editor->textCursor(), startPos, (endPos - startPos));
}
bool isAutoFormatApplicable(const Core::IDocument *document,
@@ -496,6 +496,18 @@ QString BeautifierPlugin::msgFormatSelectedText()
return tr("Format &Selected Text");
}
+QString BeautifierPlugin::msgFormatAtCursor()
+{
+ //: Menu entry
+ return tr("&Format at Cursor");
+}
+
+QString BeautifierPlugin::msgDisableFormattingSelectedText()
+{
+ //: Menu entry
+ return tr("&Disable Formatting for Selected Text");
+}
+
QString BeautifierPlugin::msgCommandPromptDialogTitle(const QString &command)
{
//: File dialog title for path chooser when choosing binary
diff --git a/src/plugins/beautifier/beautifierplugin.h b/src/plugins/beautifier/beautifierplugin.h
index 14d6674ab8..f298063f0a 100644
--- a/src/plugins/beautifier/beautifierplugin.h
+++ b/src/plugins/beautifier/beautifierplugin.h
@@ -80,6 +80,8 @@ public:
static QString msgCannotGetConfigurationFile(const QString &command);
static QString msgFormatCurrentFile();
static QString msgFormatSelectedText();
+ static QString msgFormatAtCursor();
+ static QString msgDisableFormattingSelectedText();
static QString msgCommandPromptDialogTitle(const QString &command);
static void showError(const QString &error);
diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp
index 13f7caab24..97298ffc39 100644
--- a/src/plugins/beautifier/clangformat/clangformat.cpp
+++ b/src/plugins/beautifier/clangformat/clangformat.cpp
@@ -48,6 +48,7 @@
#include <QAction>
#include <QMenu>
+#include <QTextBlock>
namespace Beautifier {
namespace Internal {
@@ -82,11 +83,19 @@ bool ClangFormat::initialize()
menu->addAction(cmd);
connect(m_formatFile, &QAction::triggered, this, &ClangFormat::formatFile);
- m_formatRange = new QAction(BeautifierPlugin::msgFormatSelectedText(), this);
+ m_formatRange = new QAction(BeautifierPlugin::msgFormatAtCursor(), this);
cmd = Core::ActionManager::registerAction(m_formatRange,
- Constants::ClangFormat::ACTION_FORMATSELECTED);
+ Constants::ClangFormat::ACTION_FORMATATCURSOR);
menu->addAction(cmd);
- connect(m_formatRange, &QAction::triggered, this, &ClangFormat::formatSelectedText);
+ connect(m_formatRange, &QAction::triggered, this, &ClangFormat::formatAtCursor);
+
+ m_disableFormattingSelectedText
+ = new QAction(BeautifierPlugin::msgDisableFormattingSelectedText(), this);
+ cmd = Core::ActionManager::registerAction(
+ m_disableFormattingSelectedText, Constants::ClangFormat::ACTION_DISABLEFORMATTINGSELECTED);
+ menu->addAction(cmd);
+ connect(m_disableFormattingSelectedText, &QAction::triggered,
+ this, &ClangFormat::disableFormattingSelectedText);
Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
@@ -113,7 +122,7 @@ void ClangFormat::formatFile()
m_beautifierPlugin->formatCurrentFile(command());
}
-void ClangFormat::formatSelectedText()
+void ClangFormat::formatAtCursor()
{
const TextEditor::TextEditorWidget *widget
= TextEditor::TextEditorWidget::currentTextEditorWidget();
@@ -125,11 +134,53 @@ void ClangFormat::formatSelectedText()
const int offset = tc.selectionStart();
const int length = tc.selectionEnd() - offset;
m_beautifierPlugin->formatCurrentFile(command(offset, length));
- } else if (m_settings->formatEntireFileFallback()) {
- formatFile();
+ } else {
+ // Pretend that the current line was selected.
+ // Note that clang-format will extend the range to the next bigger
+ // syntactic construct if needed.
+ const QTextBlock block = tc.block();
+ const int offset = block.position();
+ const int length = block.length();
+ m_beautifierPlugin->formatCurrentFile(command(offset, length));
}
}
+void ClangFormat::disableFormattingSelectedText()
+{
+ TextEditor::TextEditorWidget *widget = TextEditor::TextEditorWidget::currentTextEditorWidget();
+ if (!widget)
+ return;
+
+ const QTextCursor tc = widget->textCursor();
+ if (!tc.hasSelection())
+ return;
+
+ // Insert start marker
+ const QTextBlock selectionStartBlock = tc.document()->findBlock(tc.selectionStart());
+ QTextCursor insertCursor(tc.document());
+ insertCursor.beginEditBlock();
+ insertCursor.setPosition(selectionStartBlock.position());
+ insertCursor.insertText("// clang-format off\n");
+ const int positionToRestore = tc.position();
+
+ // Insert end marker
+ QTextBlock selectionEndBlock = tc.document()->findBlock(tc.selectionEnd());
+ insertCursor.setPosition(selectionEndBlock.position() + selectionEndBlock.length() - 1);
+ insertCursor.insertText("\n// clang-format on");
+ insertCursor.endEditBlock();
+
+ // Reset the cursor position in order to clear the selection.
+ QTextCursor restoreCursor(tc.document());
+ restoreCursor.setPosition(positionToRestore);
+ widget->setTextCursor(restoreCursor);
+
+ // The indentation of these markers might be undesired, so reformat.
+ // This is not optimal because two undo steps will be needed to remove the markers.
+ const int reformatTextLength = insertCursor.position() - selectionStartBlock.position();
+ m_beautifierPlugin->formatCurrentFile(command(selectionStartBlock.position(),
+ reformatTextLength));
+}
+
Command ClangFormat::command() const
{
Command command;
diff --git a/src/plugins/beautifier/clangformat/clangformat.h b/src/plugins/beautifier/clangformat/clangformat.h
index 86037fac0c..34cccb5fbc 100644
--- a/src/plugins/beautifier/clangformat/clangformat.h
+++ b/src/plugins/beautifier/clangformat/clangformat.h
@@ -54,10 +54,12 @@ public:
private:
void formatFile();
- void formatSelectedText();
+ void formatAtCursor();
+ void disableFormattingSelectedText();
BeautifierPlugin *m_beautifierPlugin;
QAction *m_formatFile = nullptr;
QAction *m_formatRange = nullptr;
+ QAction *m_disableFormattingSelectedText = nullptr;
ClangFormatSettings *m_settings;
Command command(int offset, int length) const;
};
diff --git a/src/plugins/beautifier/clangformat/clangformatconstants.h b/src/plugins/beautifier/clangformat/clangformatconstants.h
index 837d332306..2c94b347a5 100644
--- a/src/plugins/beautifier/clangformat/clangformatconstants.h
+++ b/src/plugins/beautifier/clangformat/clangformatconstants.h
@@ -33,7 +33,8 @@ namespace ClangFormat {
const char DISPLAY_NAME[] = QT_TRANSLATE_NOOP("Beautifier::Internal::ClangFormat::ClangFormat", "ClangFormat");
const char ACTION_FORMATFILE[] = "ClangFormat.FormatFile";
-const char ACTION_FORMATSELECTED[] = "ClangFormat.FormatSelectedText";
+const char ACTION_FORMATATCURSOR[] = "ClangFormat.FormatAtCursor";
+const char ACTION_DISABLEFORMATTINGSELECTED[] = "ClangFormat.DisableFormattingSelectedText";
const char MENU_ID[] = "ClangFormat.Menu";
const char OPTION_ID[] = "ClangFormat";
const char SETTINGS_NAME[] = "clangformat";
diff --git a/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp b/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp
index ddac14461f..d9f881dc41 100644
--- a/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp
+++ b/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp
@@ -78,7 +78,6 @@ void ClangFormatOptionsPageWidget::restore()
const int fallbackStyleIndex = ui->fallbackStyle->findText(m_settings->fallbackStyle());
if (fallbackStyleIndex != -1)
ui->fallbackStyle->setCurrentIndex(fallbackStyleIndex);
- ui->formatEntireFileFallback->setChecked(m_settings->formatEntireFileFallback());
ui->configurations->setSettings(m_settings);
ui->configurations->setCurrentConfiguration(m_settings->customStyle());
@@ -96,7 +95,6 @@ void ClangFormatOptionsPageWidget::apply()
m_settings->setPredefinedStyle(ui->predefinedStyle->currentText());
m_settings->setFallbackStyle(ui->fallbackStyle->currentText());
m_settings->setCustomStyle(ui->configurations->currentConfiguration());
- m_settings->setFormatEntireFileFallback(ui->formatEntireFileFallback->isChecked());
m_settings->save();
// update since not all MIME types are accepted (invalids or duplicates)
diff --git a/src/plugins/beautifier/clangformat/clangformatoptionspage.ui b/src/plugins/beautifier/clangformat/clangformatoptionspage.ui
index c40b28c041..7d060611b4 100644
--- a/src/plugins/beautifier/clangformat/clangformatoptionspage.ui
+++ b/src/plugins/beautifier/clangformat/clangformatoptionspage.ui
@@ -20,6 +20,19 @@
<string>Options</string>
</property>
<layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="0">
+ <widget class="QRadioButton" name="useCustomizedStyle">
+ <property name="text">
+ <string>Use customized style:</string>
+ </property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="2">
+ <widget class="Beautifier::Internal::ConfigurationPanel" name="configurations" native="true"/>
+ </item>
<item row="0" column="0">
<widget class="QRadioButton" name="usePredefinedStyle">
<property name="sizePolicy">
@@ -62,29 +75,6 @@
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QRadioButton" name="useCustomizedStyle">
- <property name="text">
- <string>Use customized style:</string>
- </property>
- <property name="autoExclusive">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="1" colspan="2">
- <widget class="Beautifier::Internal::ConfigurationPanel" name="configurations" native="true"/>
- </item>
- <item row="3" column="0" colspan="2">
- <widget class="QCheckBox" name="formatEntireFileFallback">
- <property name="toolTip">
- <string>For action Format Selected Text.</string>
- </property>
- <property name="text">
- <string>Format entire file if no text was selected</string>
- </property>
- </widget>
- </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/beautifier/clangformat/clangformatsettings.cpp b/src/plugins/beautifier/clangformat/clangformatsettings.cpp
index f4c2189181..6369c60510 100644
--- a/src/plugins/beautifier/clangformat/clangformatsettings.cpp
+++ b/src/plugins/beautifier/clangformat/clangformatsettings.cpp
@@ -43,7 +43,6 @@ const char USE_PREDEFINED_STYLE[] = "usePredefinedStyle";
const char PREDEFINED_STYLE[] = "predefinedStyle";
const char FALLBACK_STYLE[] = "fallbackStyle";
const char CUSTOM_STYLE[] = "customStyle";
-const char FORMAT_ENTIRE_FILE_FALLBACK[] = "formatEntireFileFallback";
}
ClangFormatSettings::ClangFormatSettings() :
@@ -54,7 +53,6 @@ ClangFormatSettings::ClangFormatSettings() :
m_settings.insert(PREDEFINED_STYLE, "LLVM");
m_settings.insert(FALLBACK_STYLE, "Default");
m_settings.insert(CUSTOM_STYLE, QVariant());
- m_settings.insert(FORMAT_ENTIRE_FILE_FALLBACK, QVariant(true));
read();
}
@@ -215,16 +213,6 @@ void ClangFormatSettings::setCustomStyle(const QString &customStyle)
m_settings.insert(CUSTOM_STYLE, QVariant(customStyle));
}
-bool ClangFormatSettings::formatEntireFileFallback() const
-{
- return m_settings.value(FORMAT_ENTIRE_FILE_FALLBACK).toBool();
-}
-
-void ClangFormatSettings::setFormatEntireFileFallback(bool formatEntireFileFallback)
-{
- m_settings.insert(FORMAT_ENTIRE_FILE_FALLBACK, QVariant(formatEntireFileFallback));
-}
-
QStringList ClangFormatSettings::predefinedStyles() const
{
return {"LLVM", "Google", "Chromium", "Mozilla", "WebKit", "File"};
diff --git a/src/plugins/beautifier/clangformat/clangformatsettings.h b/src/plugins/beautifier/clangformat/clangformatsettings.h
index b8a62be6bd..4fca7ddc24 100644
--- a/src/plugins/beautifier/clangformat/clangformatsettings.h
+++ b/src/plugins/beautifier/clangformat/clangformatsettings.h
@@ -54,9 +54,6 @@ public:
QString customStyle() const;
void setCustomStyle(const QString &customStyle);
- bool formatEntireFileFallback() const;
- void setFormatEntireFileFallback(bool formatEntireFileFallback);
-
QStringList predefinedStyles() const;
QStringList fallbackStyles() const;
diff --git a/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp
index 80b42c11b4..62573c70fd 100644
--- a/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp
@@ -247,10 +247,33 @@ int ActivationSequenceContextProcessor::findStartOfName(
{
int position = startPosition;
QChar character;
+ if (position > 2 && assistInterface->characterAt(position - 1) == '>'
+ && assistInterface->characterAt(position - 2) != '-') {
+ uint unbalancedLessGreater = 1;
+ --position;
+ while (unbalancedLessGreater > 0 && position > 2) {
+ character = assistInterface->characterAt(--position);
+ // Do not count -> usage inside temlate argument list
+ if (character == '<')
+ --unbalancedLessGreater;
+ else if (character == '>' && assistInterface->characterAt(position-1) != '-')
+ ++unbalancedLessGreater;
+ }
+ position = skipPrecedingWhitespace(assistInterface, position) - 1;
+ }
+
do {
character = assistInterface->characterAt(--position);
} while (isValidIdentifierChar(character));
+ int prevPosition = skipPrecedingWhitespace(assistInterface, position);
+ if (assistInterface->characterAt(prevPosition) == ':'
+ && assistInterface->characterAt(prevPosition - 1) == ':') {
+ // Handle :: case - go recursive
+ prevPosition = skipPrecedingWhitespace(assistInterface, prevPosition - 2);
+ return findStartOfName(assistInterface, prevPosition + 1);
+ }
+
return position + 1;
}
diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.h b/src/plugins/clangcodemodel/clangassistproposalmodel.h
index 6a72214513..b71d256856 100644
--- a/src/plugins/clangcodemodel/clangassistproposalmodel.h
+++ b/src/plugins/clangcodemodel/clangassistproposalmodel.h
@@ -29,7 +29,7 @@
#include <texteditor/codeassist/genericproposalmodel.h>
-#include <clangbackendipc/clangbackendipc_global.h>
+#include <clangsupport/clangsupport_global.h>
namespace ClangCodeModel {
namespace Internal {
diff --git a/src/plugins/clangcodemodel/clangbackendcommunicator.cpp b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
new file mode 100644
index 0000000000..fc5603b0c0
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangbackendcommunicator.cpp
@@ -0,0 +1,581 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangbackendcommunicator.h"
+
+#include "clangbackendlogging.h"
+#include "clangcompletionassistprocessor.h"
+#include "clangmodelmanagersupport.h"
+#include "clangutils.h"
+
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
+
+#include <cpptools/abstracteditorsupport.h>
+#include <cpptools/baseeditordocumentprocessor.h>
+#include <cpptools/cppmodelmanager.h>
+#include <cpptools/editordocumenthandle.h>
+#include <cpptools/projectinfo.h>
+#include <cpptools/cpptoolsbridge.h>
+
+#include <texteditor/codeassist/functionhintproposal.h>
+#include <texteditor/codeassist/iassistprocessor.h>
+#include <texteditor/texteditor.h>
+
+#include <clangsupport/filecontainer.h>
+#include <clangsupport/clangcodemodelservermessages.h>
+
+#include <utils/qtcassert.h>
+
+#include <QDateTime>
+#include <QDir>
+#include <QTextBlock>
+
+using namespace CPlusPlus;
+using namespace ClangBackEnd;
+using namespace TextEditor;
+
+enum { backEndStartTimeOutInMs = 10000 };
+
+static QString backendProcessPath()
+{
+ return Core::ICore::libexecPath()
+ + QStringLiteral("/clangbackend")
+ + QStringLiteral(QTC_HOST_EXE_SUFFIX);
+}
+
+namespace ClangCodeModel {
+namespace Internal {
+
+class DummyBackendSender : public BackendSender
+{
+public:
+ DummyBackendSender() : BackendSender(nullptr) {}
+
+ void end() override {}
+ void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &) override {}
+ void updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &) override {}
+ void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &) override {}
+ void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &) override {}
+ void unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &) override {}
+ void registerUnsavedFilesForEditor(const RegisterUnsavedFilesForEditorMessage &) override {}
+ void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &) override {}
+ void completeCode(const CompleteCodeMessage &) override {}
+ void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &) override {}
+ void requestReferences(const RequestReferencesMessage &) override {}
+ void requestFollowSymbol(const RequestFollowSymbolMessage &) override {}
+ void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &) override {}
+};
+
+
+BackendCommunicator::BackendCommunicator()
+ : m_connection(&m_receiver)
+ , m_sender(new DummyBackendSender())
+{
+ m_backendStartTimeOut.setSingleShot(true);
+ connect(&m_backendStartTimeOut, &QTimer::timeout,
+ this, &BackendCommunicator::logStartTimeOut);
+
+ m_receiver.setAliveHandler([this]() { m_connection.resetProcessAliveTimer(); });
+
+ connect(Core::EditorManager::instance(), &Core::EditorManager::editorAboutToClose,
+ this, &BackendCommunicator::onEditorAboutToClose);
+ connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose,
+ this, &BackendCommunicator::setupDummySender);
+
+ initializeBackend();
+}
+
+BackendCommunicator::~BackendCommunicator()
+{
+ disconnect(&m_connection, 0, this, 0);
+}
+
+void BackendCommunicator::initializeBackend()
+{
+ const QString clangBackEndProcessPath = backendProcessPath();
+ if (!QFileInfo(clangBackEndProcessPath).exists()) {
+ logExecutableDoesNotExist();
+ return;
+ }
+ qCDebug(ipcLog) << "Starting" << clangBackEndProcessPath;
+
+ m_connection.setProcessAliveTimerInterval(30 * 1000);
+ m_connection.setProcessPath(clangBackEndProcessPath);
+
+ connect(&m_connection, &ConnectionClient::connectedToLocalSocket,
+ this, &BackendCommunicator::onConnectedToBackend);
+ connect(&m_connection, &ConnectionClient::disconnectedFromLocalSocket,
+ this, &BackendCommunicator::setupDummySender);
+
+ m_connection.startProcessAndConnectToServerAsynchronously();
+ m_backendStartTimeOut.start(backEndStartTimeOutInMs);
+}
+
+static QStringList projectPartOptions(const CppTools::ProjectPart::Ptr &projectPart)
+{
+ const QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
+ CppTools::ProjectFile::Unsupported); // No language option
+
+ return options;
+}
+
+static ProjectPartContainer toProjectPartContainer(
+ const CppTools::ProjectPart::Ptr &projectPart)
+{
+ const QStringList options = projectPartOptions(projectPart);
+
+ return ProjectPartContainer(projectPart->id(), Utf8StringVector(options));
+}
+
+static QVector<ProjectPartContainer> toProjectPartContainers(
+ const QVector<CppTools::ProjectPart::Ptr> projectParts)
+{
+ QVector<ProjectPartContainer> projectPartContainers;
+ projectPartContainers.reserve(projectParts.size());
+
+ foreach (const CppTools::ProjectPart::Ptr &projectPart, projectParts)
+ projectPartContainers << toProjectPartContainer(projectPart);
+
+ return projectPartContainers;
+}
+
+void BackendCommunicator::registerFallbackProjectPart()
+{
+ const auto projectPart = CppTools::CppModelManager::instance()->fallbackProjectPart();
+ const auto projectPartContainer = toProjectPartContainer(projectPart);
+
+ registerProjectPartsForEditor({projectPartContainer});
+}
+
+namespace {
+Utf8String currentCppEditorDocumentFilePath()
+{
+ Utf8String currentCppEditorDocumentFilePath;
+
+ const auto currentEditor = Core::EditorManager::currentEditor();
+ if (currentEditor && CppTools::CppModelManager::isCppEditor(currentEditor)) {
+ const auto currentDocument = currentEditor->document();
+ if (currentDocument)
+ currentCppEditorDocumentFilePath = currentDocument->filePath().toString();
+ }
+
+ return currentCppEditorDocumentFilePath;
+}
+
+void removeDuplicates(Utf8StringVector &visibleEditorDocumentsFilePaths)
+{
+ std::sort(visibleEditorDocumentsFilePaths.begin(),
+ visibleEditorDocumentsFilePaths.end());
+ const auto end = std::unique(visibleEditorDocumentsFilePaths.begin(),
+ visibleEditorDocumentsFilePaths.end());
+ visibleEditorDocumentsFilePaths.erase(end,
+ visibleEditorDocumentsFilePaths.end());
+}
+
+void removeNonCppEditors(QList<Core::IEditor*> &visibleEditors)
+{
+ const auto isNotCppEditor = [] (Core::IEditor *editor) {
+ return !CppTools::CppModelManager::isCppEditor(editor);
+ };
+
+ const auto end = std::remove_if(visibleEditors.begin(),
+ visibleEditors.end(),
+ isNotCppEditor);
+
+ visibleEditors.erase(end, visibleEditors.end());
+}
+
+Utf8StringVector visibleCppEditorDocumentsFilePaths()
+{
+ auto visibleEditors = CppTools::CppToolsBridge::visibleEditors();
+
+ removeNonCppEditors(visibleEditors);
+
+ Utf8StringVector visibleCppEditorDocumentsFilePaths;
+ visibleCppEditorDocumentsFilePaths.reserve(visibleEditors.size());
+
+ const auto editorFilePaths = [] (Core::IEditor *editor) {
+ return Utf8String(editor->document()->filePath().toString());
+ };
+
+ std::transform(visibleEditors.begin(),
+ visibleEditors.end(),
+ std::back_inserter(visibleCppEditorDocumentsFilePaths),
+ editorFilePaths);
+
+ removeDuplicates(visibleCppEditorDocumentsFilePaths);
+
+ return visibleCppEditorDocumentsFilePaths;
+}
+
+}
+
+void BackendCommunicator::updateTranslationUnitVisiblity()
+{
+ updateTranslationUnitVisiblity(currentCppEditorDocumentFilePath(), visibleCppEditorDocumentsFilePaths());
+}
+
+bool BackendCommunicator::isNotWaitingForCompletion() const
+{
+ return !m_receiver.isExpectingCodeCompletedMessage();
+}
+
+void BackendCommunicator::updateTranslationUnitVisiblity(const Utf8String &currentEditorFilePath,
+ const Utf8StringVector &visibleEditorsFilePaths)
+{
+ const UpdateVisibleTranslationUnitsMessage message(currentEditorFilePath, visibleEditorsFilePaths);
+ m_sender->updateVisibleTranslationUnits(message);
+}
+
+void BackendCommunicator::registerCurrentProjectParts()
+{
+ using namespace CppTools;
+
+ const QList<ProjectInfo> projectInfos = CppModelManager::instance()->projectInfos();
+ foreach (const ProjectInfo &projectInfo, projectInfos)
+ registerProjectsParts(projectInfo.projectParts());
+}
+
+void BackendCommunicator::restoreCppEditorDocuments()
+{
+ resetCppEditorDocumentProcessors();
+ registerVisibleCppEditorDocumentAndMarkInvisibleDirty();
+}
+
+void BackendCommunicator::resetCppEditorDocumentProcessors()
+{
+ using namespace CppTools;
+
+ const auto cppEditorDocuments = CppModelManager::instance()->cppEditorDocuments();
+ foreach (CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments)
+ cppEditorDocument->resetProcessor();
+}
+
+void BackendCommunicator::registerVisibleCppEditorDocumentAndMarkInvisibleDirty()
+{
+ CppTools::CppModelManager::instance()->updateCppEditorDocuments();
+}
+
+void BackendCommunicator::registerCurrentCodeModelUiHeaders()
+{
+ using namespace CppTools;
+
+ const auto editorSupports = CppModelManager::instance()->abstractEditorSupports();
+ foreach (const AbstractEditorSupport *es, editorSupports) {
+ const QString mappedPath
+ = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskPath(es->fileName());
+ updateUnsavedFile(mappedPath, es->contents(), es->revision());
+ }
+}
+
+void BackendCommunicator::registerProjectsParts(const QVector<CppTools::ProjectPart::Ptr> projectParts)
+{
+ const auto projectPartContainers = toProjectPartContainers(projectParts);
+ registerProjectPartsForEditor(projectPartContainers);
+}
+
+void BackendCommunicator::updateTranslationUnitFromCppEditorDocument(const QString &filePath)
+{
+ const CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath);
+
+ updateTranslationUnit(filePath, document->contents(), document->revision());
+}
+
+void BackendCommunicator::updateUnsavedFileFromCppEditorDocument(const QString &filePath)
+{
+ const CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath);
+
+ updateUnsavedFile(filePath, document->contents(), document->revision());
+}
+
+void BackendCommunicator::updateTranslationUnit(const QString &filePath,
+ const QByteArray &contents,
+ uint documentRevision)
+{
+ const bool hasUnsavedContent = true;
+
+ updateTranslationUnitsForEditor({{filePath,
+ Utf8String(),
+ Utf8String::fromByteArray(contents),
+ hasUnsavedContent,
+ documentRevision}});
+}
+
+void BackendCommunicator::updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision)
+{
+ const bool hasUnsavedContent = true;
+
+ // TODO: Send new only if changed
+ registerUnsavedFilesForEditor({{filePath,
+ Utf8String(),
+ Utf8String::fromByteArray(contents),
+ hasUnsavedContent,
+ documentRevision}});
+}
+
+static bool documentHasChanged(const QString &filePath, uint revision)
+{
+ if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath))
+ return document->sendTracker().shouldSendRevision(revision);
+
+ return true;
+}
+
+static void setLastSentDocumentRevision(const QString &filePath, uint revision)
+{
+ if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath))
+ document->sendTracker().setLastSentRevision(int(revision));
+}
+
+void BackendCommunicator::updateTranslationUnitWithRevisionCheck(const FileContainer &fileContainer)
+{
+ if (documentHasChanged(fileContainer.filePath(), fileContainer.documentRevision())) {
+ updateTranslationUnitsForEditor({fileContainer});
+ setLastSentDocumentRevision(fileContainer.filePath(),
+ fileContainer.documentRevision());
+ }
+}
+
+void BackendCommunicator::requestDocumentAnnotations(const FileContainer &fileContainer)
+{
+ const RequestDocumentAnnotationsMessage message(fileContainer);
+ m_sender->requestDocumentAnnotations(message);
+}
+
+QFuture<CppTools::CursorInfo> BackendCommunicator::requestReferences(
+ const FileContainer &fileContainer,
+ quint32 line,
+ quint32 column,
+ QTextDocument *textDocument,
+ const CppTools::SemanticInfo::LocalUseMap &localUses)
+{
+ const RequestReferencesMessage message(fileContainer, line, column);
+ m_sender->requestReferences(message);
+
+ return m_receiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument,
+ localUses);
+}
+
+QFuture<CppTools::SymbolInfo> BackendCommunicator::requestFollowSymbol(
+ const FileContainer &curFileContainer,
+ const QVector<Utf8String> &dependentFiles,
+ quint32 line,
+ quint32 column)
+{
+ const RequestFollowSymbolMessage message(curFileContainer,
+ dependentFiles,
+ line,
+ column);
+ m_sender->requestFollowSymbol(message);
+
+ return m_receiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber());
+}
+
+void BackendCommunicator::updateTranslationUnitWithRevisionCheck(Core::IDocument *document)
+{
+ const auto textDocument = qobject_cast<TextDocument*>(document);
+ const auto filePath = textDocument->filePath().toString();
+ const QString projectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
+
+ updateTranslationUnitWithRevisionCheck(FileContainer(filePath,
+ projectPartId,
+ Utf8StringVector(),
+ textDocument->document()->revision()));
+}
+
+void BackendCommunicator::updateChangeContentStartPosition(const QString &filePath, int position)
+{
+ if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath))
+ document->sendTracker().applyContentChange(position);
+}
+
+void BackendCommunicator::updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document)
+{
+ QTC_ASSERT(document, return);
+ if (Core::EditorManager::currentDocument() != document)
+ updateTranslationUnit(document);
+}
+
+void BackendCommunicator::updateTranslationUnit(Core::IDocument *document)
+{
+ updateTranslationUnitFromCppEditorDocument(document->filePath().toString());
+}
+
+void BackendCommunicator::updateUnsavedFile(Core::IDocument *document)
+{
+ QTC_ASSERT(document, return);
+
+ updateUnsavedFileFromCppEditorDocument(document->filePath().toString());
+}
+
+void BackendCommunicator::onConnectedToBackend()
+{
+ m_backendStartTimeOut.stop();
+
+ ++m_connectedCount;
+ if (m_connectedCount > 1)
+ logRestartedDueToUnexpectedFinish();
+
+ m_receiver.reset();
+ m_sender.reset(new BackendSender(&m_connection));
+
+ initializeBackendWithCurrentData();
+}
+
+void BackendCommunicator::onEditorAboutToClose(Core::IEditor *editor)
+{
+ if (auto *textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor))
+ m_receiver.deleteProcessorsOfEditorWidget(textEditor->editorWidget());
+}
+
+void BackendCommunicator::setupDummySender()
+{
+ m_sender.reset(new DummyBackendSender);
+}
+
+void BackendCommunicator::logExecutableDoesNotExist()
+{
+ const QString msg
+ = tr("Clang Code Model: Error: "
+ "The clangbackend executable \"%1\" does not exist.")
+ .arg(QDir::toNativeSeparators(backendProcessPath()));
+
+ logError(msg);
+}
+
+void BackendCommunicator::logStartTimeOut()
+{
+ const QString msg
+ = tr("Clang Code Model: Error: "
+ "The clangbackend executable \"%1\" could not be started (timeout after %2ms).")
+ .arg(QDir::toNativeSeparators(backendProcessPath()))
+ .arg(backEndStartTimeOutInMs);
+
+ logError(msg);
+}
+
+void BackendCommunicator::logRestartedDueToUnexpectedFinish()
+{
+ const QString msg
+ = tr("Clang Code Model: Error: "
+ "The clangbackend process has finished unexpectedly and was restarted.");
+
+ logError(msg);
+}
+
+void BackendCommunicator::logError(const QString &text)
+{
+ const QString textWithTimestamp = QDateTime::currentDateTime().toString(Qt::ISODate)
+ + ' ' + text;
+ Core::MessageManager::write(textWithTimestamp, Core::MessageManager::Flash);
+ qWarning("%s", qPrintable(textWithTimestamp));
+}
+
+void BackendCommunicator::initializeBackendWithCurrentData()
+{
+ registerFallbackProjectPart();
+ registerCurrentProjectParts();
+ registerCurrentCodeModelUiHeaders();
+ restoreCppEditorDocuments();
+ updateTranslationUnitVisiblity();
+
+ emit backendReinitialized();
+}
+
+BackendSender *BackendCommunicator::setBackendSender(BackendSender *sender)
+{
+ BackendSender *previousSender = m_sender.take();
+ m_sender.reset(sender);
+ return previousSender;
+}
+
+void BackendCommunicator::killBackendProcess()
+{
+ m_connection.processForTestOnly()->kill();
+}
+
+void BackendCommunicator::registerTranslationUnitsForEditor(const FileContainers &fileContainers)
+{
+ const RegisterTranslationUnitForEditorMessage message(fileContainers,
+ currentCppEditorDocumentFilePath(),
+ visibleCppEditorDocumentsFilePaths());
+ m_sender->registerTranslationUnitsForEditor(message);
+}
+
+void BackendCommunicator::updateTranslationUnitsForEditor(const FileContainers &fileContainers)
+{
+ const UpdateTranslationUnitsForEditorMessage message(fileContainers);
+ m_sender->updateTranslationUnitsForEditor(message);
+}
+
+void BackendCommunicator::unregisterTranslationUnitsForEditor(const FileContainers &fileContainers)
+{
+ const UnregisterTranslationUnitsForEditorMessage message(fileContainers);
+ m_sender->unregisterTranslationUnitsForEditor(message);
+}
+
+void BackendCommunicator::registerProjectPartsForEditor(
+ const ProjectPartContainers &projectPartContainers)
+{
+ const RegisterProjectPartsForEditorMessage message(projectPartContainers);
+ m_sender->registerProjectPartsForEditor(message);
+}
+
+void BackendCommunicator::unregisterProjectPartsForEditor(const QStringList &projectPartIds)
+{
+ const UnregisterProjectPartsForEditorMessage message((Utf8StringVector(projectPartIds)));
+ m_sender->unregisterProjectPartsForEditor(message);
+}
+
+void BackendCommunicator::registerUnsavedFilesForEditor(const FileContainers &fileContainers)
+{
+ const RegisterUnsavedFilesForEditorMessage message(fileContainers);
+ m_sender->registerUnsavedFilesForEditor(message);
+}
+
+void BackendCommunicator::unregisterUnsavedFilesForEditor(const FileContainers &fileContainers)
+{
+ const UnregisterUnsavedFilesForEditorMessage message(fileContainers);
+ m_sender->unregisterUnsavedFilesForEditor(message);
+}
+
+void BackendCommunicator::completeCode(ClangCompletionAssistProcessor *assistProcessor,
+ const QString &filePath,
+ quint32 line,
+ quint32 column,
+ const QString &projectFilePath,
+ qint32 funcNameStartLine,
+ qint32 funcNameStartColumn)
+{
+ const CompleteCodeMessage message(filePath, line, column, projectFilePath, funcNameStartLine,
+ funcNameStartColumn);
+ m_sender->completeCode(message);
+ m_receiver.addExpectedCodeCompletedMessage(message.ticketNumber(), assistProcessor);
+}
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendcommunicator.h
index 842d68f266..86054e566f 100644
--- a/src/plugins/clangcodemodel/clangbackendipcintegration.h
+++ b/src/plugins/clangcodemodel/clangbackendcommunicator.h
@@ -25,126 +25,42 @@
#pragma once
+#include "clangbackendreceiver.h"
+#include "clangbackendsender.h"
+
#include <cpptools/projectpart.h>
-#include <cpptools/cppcursorinfo.h>
-#include <clangbackendipc/clangcodemodelconnectionclient.h>
-#include <clangbackendipc/filecontainer.h>
-#include <clangbackendipc/clangcodemodelclientinterface.h>
-#include <clangbackendipc/projectpartcontainer.h>
+#include <clangsupport/clangcodemodelconnectionclient.h>
+#include <clangsupport/filecontainer.h>
+#include <clangsupport/projectpartcontainer.h>
#include <QFuture>
#include <QObject>
-#include <QPointer>
-#include <QSharedPointer>
-#include <QTextDocument>
#include <QVector>
-
-#include <functional>
+#include <QTimer>
namespace Core {
class IEditor;
class IDocument;
}
-namespace ClangBackEnd {
-class DocumentAnnotationsChangedMessage;
-}
-
-namespace TextEditor {
-class TextEditorWidget;
-class TextDocument;
-}
-
namespace ClangCodeModel {
namespace Internal {
-class ModelManagerSupportClang;
-
class ClangCompletionAssistProcessor;
-class IpcReceiver : public ClangBackEnd::ClangCodeModelClientInterface
-{
-public:
- IpcReceiver();
- ~IpcReceiver();
-
- using AliveHandler = std::function<void ()>;
- void setAliveHandler(const AliveHandler &handler);
-
- void addExpectedCodeCompletedMessage(quint64 ticket, ClangCompletionAssistProcessor *processor);
- void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget);
-
- QFuture<CppTools::CursorInfo>
- addExpectedReferencesMessage(quint64 ticket,
- QTextDocument *textDocument,
- const CppTools::SemanticInfo::LocalUseMap &localUses);
- bool isExpectingCodeCompletedMessage() const;
-
- void reset();
-
-private:
- void alive() override;
- void echo(const ClangBackEnd::EchoMessage &message) override;
- void codeCompleted(const ClangBackEnd::CodeCompletedMessage &message) override;
-
- void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override;
- void references(const ClangBackEnd::ReferencesMessage &message) override;
-
- void translationUnitDoesNotExist(const ClangBackEnd::TranslationUnitDoesNotExistMessage &) override {}
- void projectPartsDoNotExist(const ClangBackEnd::ProjectPartsDoNotExistMessage &) override {}
-
-private:
- AliveHandler m_aliveHandler;
- QHash<quint64, ClangCompletionAssistProcessor *> m_assistProcessorsTable;
-
- struct ReferencesEntry {
- ReferencesEntry() = default;
- ReferencesEntry(QFutureInterface<CppTools::CursorInfo> futureInterface,
- QTextDocument *textDocument,
- const CppTools::SemanticInfo::LocalUseMap &localUses)
- : futureInterface(futureInterface)
- , textDocument(textDocument)
- , localUses(localUses) {}
- QFutureInterface<CppTools::CursorInfo> futureInterface;
- QPointer<QTextDocument> textDocument;
- CppTools::SemanticInfo::LocalUseMap localUses;
- };
- QHash<quint64, ReferencesEntry> m_referencesTable;
-};
-
-class IpcSenderInterface
-{
-public:
- virtual ~IpcSenderInterface() {}
-
- virtual void end() = 0;
- virtual void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) = 0;
- virtual void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) = 0;
- virtual void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) = 0;
- virtual void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) = 0;
- virtual void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) = 0;
- virtual void registerUnsavedFilesForEditor(const ClangBackEnd::RegisterUnsavedFilesForEditorMessage &message) = 0;
- virtual void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) = 0;
- virtual void completeCode(const ClangBackEnd::CompleteCodeMessage &message) = 0;
- virtual void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) = 0;
- virtual void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) = 0;
- virtual void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) = 0;
-};
-
-class IpcCommunicator : public QObject
+class BackendCommunicator : public QObject
{
Q_OBJECT
public:
- using Ptr = QSharedPointer<IpcCommunicator>;
using FileContainer = ClangBackEnd::FileContainer;
using FileContainers = QVector<ClangBackEnd::FileContainer>;
using ProjectPartContainers = QVector<ClangBackEnd::ProjectPartContainer>;
public:
- IpcCommunicator();
- ~IpcCommunicator();
+ BackendCommunicator();
+ ~BackendCommunicator();
void registerTranslationUnitsForEditor(const FileContainers &fileContainers);
void updateTranslationUnitsForEditor(const FileContainers &fileContainers);
@@ -160,10 +76,16 @@ public:
quint32 column,
QTextDocument *textDocument,
const CppTools::SemanticInfo::LocalUseMap &localUses);
+ QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
+ const QVector<Utf8String> &dependentFiles,
+ quint32 line,
+ quint32 column);
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
quint32 line,
quint32 column,
- const QString &projectFilePath);
+ const QString &projectFilePath,
+ qint32 funcNameStartLine = -1,
+ qint32 funcNameStartColumn = -1);
void registerProjectsParts(const QVector<CppTools::ProjectPart::Ptr> projectParts);
@@ -184,7 +106,7 @@ public:
bool isNotWaitingForCompletion() const;
public: // for tests
- IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender);
+ BackendSender *setBackendSender(BackendSender *sender);
void killBackendProcess();
signals: // for tests
@@ -214,10 +136,10 @@ private:
const Utf8StringVector &visibleEditorsFilePaths);
private:
- IpcReceiver m_ipcReceiver;
+ BackendReceiver m_receiver;
ClangBackEnd::ClangCodeModelConnectionClient m_connection;
QTimer m_backendStartTimeOut;
- QScopedPointer<IpcSenderInterface> m_ipcSender;
+ QScopedPointer<BackendSender> m_sender;
int m_connectedCount = 0;
};
diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp
deleted file mode 100644
index bb4d4c3010..0000000000
--- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp
+++ /dev/null
@@ -1,866 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangbackendipcintegration.h"
-
-#include "clangcompletionassistprocessor.h"
-#include "clangeditordocumentprocessor.h"
-#include "clangmodelmanagersupport.h"
-#include "clangutils.h"
-
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/messagemanager.h>
-
-#include <cpptools/abstracteditorsupport.h>
-#include <cpptools/baseeditordocumentprocessor.h>
-#include <cpptools/cppmodelmanager.h>
-#include <cpptools/cpptoolsbridge.h>
-#include <cpptools/editordocumenthandle.h>
-#include <cpptools/projectinfo.h>
-
-#include <texteditor/codeassist/functionhintproposal.h>
-#include <texteditor/codeassist/iassistprocessor.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
-
-#include <clangbackendipc/clangcodemodelservermessages.h>
-#include <clangbackendipc/clangcodemodelclientmessages.h>
-#include <clangbackendipc/filecontainer.h>
-
-#include <cplusplus/Icons.h>
-
-#include <QDateTime>
-#include <QDir>
-#include <QElapsedTimer>
-#include <QLoggingCategory>
-#include <QProcess>
-#include <QTextBlock>
-
-static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.ipc")
-
-using namespace CPlusPlus;
-using namespace ClangCodeModel;
-using namespace ClangCodeModel::Internal;
-using namespace ClangBackEnd;
-using namespace TextEditor;
-
-static QString backendProcessPath()
-{
- return Core::ICore::libexecPath()
- + QStringLiteral("/clangbackend")
- + QStringLiteral(QTC_HOST_EXE_SUFFIX);
-}
-
-static bool printAliveMessageHelper()
-{
- const bool print = qEnvironmentVariableIntValue("QTC_CLANG_FORCE_VERBOSE_ALIVE");
- if (!print) {
- qCDebug(log) << "Hint: AliveMessage will not be printed. "
- "Force it by setting QTC_CLANG_FORCE_VERBOSE_ALIVE=1.";
- }
-
- return print;
-}
-
-static bool printAliveMessage()
-{
- static bool print = log().isDebugEnabled() ? printAliveMessageHelper() : false;
- return print;
-}
-
-IpcReceiver::IpcReceiver()
-{
-}
-
-IpcReceiver::~IpcReceiver()
-{
- reset();
-}
-
-void IpcReceiver::setAliveHandler(const IpcReceiver::AliveHandler &handler)
-{
- m_aliveHandler = handler;
-}
-
-void IpcReceiver::addExpectedCodeCompletedMessage(
- quint64 ticket,
- ClangCompletionAssistProcessor *processor)
-{
- QTC_ASSERT(processor, return);
- QTC_CHECK(!m_assistProcessorsTable.contains(ticket));
- m_assistProcessorsTable.insert(ticket, processor);
-}
-
-void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget)
-{
- QMutableHashIterator<quint64, ClangCompletionAssistProcessor *> it(m_assistProcessorsTable);
- while (it.hasNext()) {
- it.next();
- ClangCompletionAssistProcessor *assistProcessor = it.value();
- if (assistProcessor->textEditorWidget() == textEditorWidget) {
- delete assistProcessor;
- it.remove();
- }
- }
-}
-
-QFuture<CppTools::CursorInfo> IpcReceiver::addExpectedReferencesMessage(
- quint64 ticket,
- QTextDocument *textDocument,
- const CppTools::SemanticInfo::LocalUseMap &localUses)
-{
- QTC_CHECK(textDocument);
- QTC_CHECK(!m_referencesTable.contains(ticket));
-
- QFutureInterface<CppTools::CursorInfo> futureInterface;
- futureInterface.reportStarted();
-
- const ReferencesEntry entry{futureInterface, textDocument, localUses};
- m_referencesTable.insert(ticket, entry);
-
- return futureInterface.future();
-}
-
-bool IpcReceiver::isExpectingCodeCompletedMessage() const
-{
- return !m_assistProcessorsTable.isEmpty();
-}
-
-void IpcReceiver::reset()
-{
- // Clean up waiting assist processors
- qDeleteAll(m_assistProcessorsTable.begin(), m_assistProcessorsTable.end());
- m_assistProcessorsTable.clear();
-
- // Clean up futures for references
- for (ReferencesEntry &entry : m_referencesTable)
- entry.futureInterface.cancel();
- m_referencesTable.clear();
-}
-
-void IpcReceiver::alive()
-{
- if (printAliveMessage())
- qCDebug(log) << "<<< AliveMessage";
- QTC_ASSERT(m_aliveHandler, return);
- m_aliveHandler();
-}
-
-void IpcReceiver::echo(const EchoMessage &message)
-{
- qCDebug(log) << "<<<" << message;
-}
-
-void IpcReceiver::codeCompleted(const CodeCompletedMessage &message)
-{
- qCDebug(log) << "<<< CodeCompletedMessage with" << message.codeCompletions().size() << "items";
-
- const quint64 ticket = message.ticketNumber();
- QScopedPointer<ClangCompletionAssistProcessor> processor(m_assistProcessorsTable.take(ticket));
- if (processor) {
- processor->handleAvailableCompletions(message.codeCompletions(),
- message.neededCorrection());
- }
-}
-
-void IpcReceiver::documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message)
-{
- qCDebug(log) << "<<< DocumentAnnotationsChangedMessage with"
- << message.diagnostics().size() << "diagnostics"
- << message.highlightingMarks().size() << "highlighting marks"
- << message.skippedPreprocessorRanges().size() << "skipped preprocessor ranges";
-
- auto processor = ClangEditorDocumentProcessor::get(message.fileContainer().filePath());
-
- if (processor) {
- const QString projectPartId = message.fileContainer().projectPartId();
- const QString filePath = message.fileContainer().filePath();
- const QString documentProjectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
- if (projectPartId == documentProjectPartId) {
- const quint32 documentRevision = message.fileContainer().documentRevision();
- processor->updateCodeWarnings(message.diagnostics(),
- message.firstHeaderErrorDiagnostic(),
- documentRevision);
- processor->updateHighlighting(message.highlightingMarks(),
- message.skippedPreprocessorRanges(),
- documentRevision);
- }
- }
-}
-
-static
-CppTools::CursorInfo::Range toCursorInfoRange(const QTextDocument &textDocument,
- const SourceRangeContainer &sourceRange)
-{
- const SourceLocationContainer start = sourceRange.start();
- const SourceLocationContainer end = sourceRange.end();
- const unsigned length = end.column() - start.column();
-
- const QTextBlock block = textDocument.findBlockByNumber(static_cast<int>(start.line()) - 1);
- const int shift = ClangCodeModel::Utils::extraUtf8CharsShift(block.text(),
- static_cast<int>(start.column()));
- const uint column = start.column() - static_cast<uint>(shift);
-
- return CppTools::CursorInfo::Range(start.line(), column, length);
-}
-
-static
-CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument,
- const CppTools::SemanticInfo::LocalUseMap &localUses,
- const ReferencesMessage &message)
-{
- CppTools::CursorInfo result;
- const QVector<SourceRangeContainer> references = message.references();
-
- result.areUseRangesForLocalVariable = message.isLocalVariable();
- for (const SourceRangeContainer &reference : references)
- result.useRanges.append(toCursorInfoRange(textDocument, reference));
-
- result.useRanges.reserve(references.size());
- result.localUses = localUses;
-
- return result;
-}
-
-void IpcReceiver::references(const ReferencesMessage &message)
-{
- qCDebug(log) << "<<< ReferencesMessage with"
- << message.references().size() << "references";
-
- const quint64 ticket = message.ticketNumber();
- const ReferencesEntry entry = m_referencesTable.take(ticket);
- QFutureInterface<CppTools::CursorInfo> futureInterface = entry.futureInterface;
- QTC_CHECK(futureInterface != QFutureInterface<CppTools::CursorInfo>());
-
- if (futureInterface.isCanceled())
- return; // Editor document closed or a new request was issued making this result outdated.
-
- QTC_ASSERT(entry.textDocument, return);
- futureInterface.reportResult(toCursorInfo(*entry.textDocument, entry.localUses, message));
- futureInterface.reportFinished();
-}
-
-class IpcSender : public IpcSenderInterface
-{
-public:
- IpcSender(ClangBackEnd::ClangCodeModelConnectionClient &connectionClient)
- : m_connection(connectionClient)
- {}
-
- void end() override;
- void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) override;
- void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) override;
- void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) override;
- void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) override;
- void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) override;
- void registerUnsavedFilesForEditor(const ClangBackEnd::RegisterUnsavedFilesForEditorMessage &message) override;
- void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override;
- void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
- void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
- void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
- void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
-
-private:
- ClangBackEnd::ClangCodeModelConnectionClient &m_connection;
-};
-
-void IpcSender::end()
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << ClangBackEnd::EndMessage();
- m_connection.sendEndMessage();
-}
-
-void IpcSender::registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().registerTranslationUnitsForEditor(message);
-}
-
-void IpcSender::updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().updateTranslationUnitsForEditor(message);
-}
-
-void IpcSender::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().unregisterTranslationUnitsForEditor(message);
-}
-
-void IpcSender::registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().registerProjectPartsForEditor(message);
-}
-
-void IpcSender::unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().unregisterProjectPartsForEditor(message);
-}
-
-void IpcSender::registerUnsavedFilesForEditor(const RegisterUnsavedFilesForEditorMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().registerUnsavedFilesForEditor(message);
-}
-
-void IpcSender::unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().unregisterUnsavedFilesForEditor(message);
-}
-
-void IpcSender::completeCode(const CompleteCodeMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().completeCode(message);
-}
-
-void IpcSender::requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().requestDocumentAnnotations(message);
-}
-
-void IpcSender::requestReferences(const RequestReferencesMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().requestReferences(message);
-}
-
-void IpcSender::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
-{
- QTC_CHECK(m_connection.isConnected());
- qCDebug(log) << ">>>" << message;
- m_connection.serverProxy().updateVisibleTranslationUnits(message);
-}
-
-class DummyIpcSender : public IpcSenderInterface
-{
-public:
- void end() override {}
- void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &) override {}
- void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &) override {}
- void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &) override {}
- void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &) override {}
- void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &) override {}
- void registerUnsavedFilesForEditor(const ClangBackEnd::RegisterUnsavedFilesForEditorMessage &) override {}
- void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &) override {}
- void completeCode(const ClangBackEnd::CompleteCodeMessage &) override {}
- void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &) override {}
- void requestReferences(const ClangBackEnd::RequestReferencesMessage &) override {}
- void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &) override {}
-};
-
-enum { backEndStartTimeOutInMs = 10000 };
-
-IpcCommunicator::IpcCommunicator()
- : m_connection(&m_ipcReceiver)
- , m_ipcSender(new DummyIpcSender)
-{
- m_backendStartTimeOut.setSingleShot(true);
- connect(&m_backendStartTimeOut, &QTimer::timeout,
- this, &IpcCommunicator::logStartTimeOut);
-
- m_ipcReceiver.setAliveHandler([this]() { m_connection.resetProcessAliveTimer(); });
-
- connect(Core::EditorManager::instance(), &Core::EditorManager::editorAboutToClose,
- this, &IpcCommunicator::onEditorAboutToClose);
- connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose,
- this, &IpcCommunicator::setupDummySender);
-
- initializeBackend();
-}
-
-IpcCommunicator::~IpcCommunicator()
-{
- disconnect(&m_connection, 0, this, 0);
-}
-
-void IpcCommunicator::initializeBackend()
-{
- const QString clangBackEndProcessPath = backendProcessPath();
- if (!QFileInfo(clangBackEndProcessPath).exists()) {
- logExecutableDoesNotExist();
- return;
- }
- qCDebug(log) << "Starting" << clangBackEndProcessPath;
-
- m_connection.setProcessAliveTimerInterval(30 * 1000);
- m_connection.setProcessPath(clangBackEndProcessPath);
-
- connect(&m_connection, &ConnectionClient::connectedToLocalSocket,
- this, &IpcCommunicator::onConnectedToBackend);
- connect(&m_connection, &ConnectionClient::disconnectedFromLocalSocket,
- this, &IpcCommunicator::setupDummySender);
-
- m_connection.startProcessAndConnectToServerAsynchronously();
- m_backendStartTimeOut.start(backEndStartTimeOutInMs);
-}
-
-static QStringList projectPartOptions(const CppTools::ProjectPart::Ptr &projectPart)
-{
- const QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
- CppTools::ProjectFile::Unsupported); // No language option
-
- return options;
-}
-
-static ClangBackEnd::ProjectPartContainer toProjectPartContainer(
- const CppTools::ProjectPart::Ptr &projectPart)
-{
- const QStringList options = projectPartOptions(projectPart);
-
- return ClangBackEnd::ProjectPartContainer(projectPart->id(), Utf8StringVector(options));
-}
-
-static QVector<ClangBackEnd::ProjectPartContainer> toProjectPartContainers(
- const QVector<CppTools::ProjectPart::Ptr> projectParts)
-{
- QVector<ClangBackEnd::ProjectPartContainer> projectPartContainers;
- projectPartContainers.reserve(projectParts.size());
-
- foreach (const CppTools::ProjectPart::Ptr &projectPart, projectParts)
- projectPartContainers << toProjectPartContainer(projectPart);
-
- return projectPartContainers;
-}
-
-void IpcCommunicator::registerFallbackProjectPart()
-{
- const auto projectPart = CppTools::CppModelManager::instance()->fallbackProjectPart();
- const auto projectPartContainer = toProjectPartContainer(projectPart);
-
- registerProjectPartsForEditor({projectPartContainer});
-}
-
-namespace {
-Utf8String currentCppEditorDocumentFilePath()
-{
- Utf8String currentCppEditorDocumentFilePath;
-
- const auto currentEditor = Core::EditorManager::currentEditor();
- if (currentEditor && CppTools::CppModelManager::isCppEditor(currentEditor)) {
- const auto currentDocument = currentEditor->document();
- if (currentDocument)
- currentCppEditorDocumentFilePath = currentDocument->filePath().toString();
- }
-
- return currentCppEditorDocumentFilePath;
-}
-
-void removeDuplicates(Utf8StringVector &visibleEditorDocumentsFilePaths)
-{
- std::sort(visibleEditorDocumentsFilePaths.begin(),
- visibleEditorDocumentsFilePaths.end());
- const auto end = std::unique(visibleEditorDocumentsFilePaths.begin(),
- visibleEditorDocumentsFilePaths.end());
- visibleEditorDocumentsFilePaths.erase(end,
- visibleEditorDocumentsFilePaths.end());
-}
-
-void removeNonCppEditors(QList<Core::IEditor*> &visibleEditors)
-{
- const auto isNotCppEditor = [] (Core::IEditor *editor) {
- return !CppTools::CppModelManager::isCppEditor(editor);
- };
-
- const auto end = std::remove_if(visibleEditors.begin(),
- visibleEditors.end(),
- isNotCppEditor);
-
- visibleEditors.erase(end, visibleEditors.end());
-}
-
-Utf8StringVector visibleCppEditorDocumentsFilePaths()
-{
- auto visibleEditors = CppTools::CppToolsBridge::visibleEditors();
-
- removeNonCppEditors(visibleEditors);
-
- Utf8StringVector visibleCppEditorDocumentsFilePaths;
- visibleCppEditorDocumentsFilePaths.reserve(visibleEditors.size());
-
- const auto editorFilePaths = [] (Core::IEditor *editor) {
- return Utf8String(editor->document()->filePath().toString());
- };
-
- std::transform(visibleEditors.begin(),
- visibleEditors.end(),
- std::back_inserter(visibleCppEditorDocumentsFilePaths),
- editorFilePaths);
-
- removeDuplicates(visibleCppEditorDocumentsFilePaths);
-
- return visibleCppEditorDocumentsFilePaths;
-}
-
-}
-
-void IpcCommunicator::updateTranslationUnitVisiblity()
-{
- updateTranslationUnitVisiblity(currentCppEditorDocumentFilePath(), visibleCppEditorDocumentsFilePaths());
-}
-
-bool IpcCommunicator::isNotWaitingForCompletion() const
-{
- return !m_ipcReceiver.isExpectingCodeCompletedMessage();
-}
-
-void IpcCommunicator::updateTranslationUnitVisiblity(const Utf8String &currentEditorFilePath,
- const Utf8StringVector &visibleEditorsFilePaths)
-{
- const UpdateVisibleTranslationUnitsMessage message(currentEditorFilePath, visibleEditorsFilePaths);
- m_ipcSender->updateVisibleTranslationUnits(message);
-}
-
-void IpcCommunicator::registerCurrentProjectParts()
-{
- using namespace CppTools;
-
- const QList<ProjectInfo> projectInfos = CppModelManager::instance()->projectInfos();
- foreach (const ProjectInfo &projectInfo, projectInfos)
- registerProjectsParts(projectInfo.projectParts());
-}
-
-void IpcCommunicator::restoreCppEditorDocuments()
-{
- resetCppEditorDocumentProcessors();
- registerVisibleCppEditorDocumentAndMarkInvisibleDirty();
-}
-
-void IpcCommunicator::resetCppEditorDocumentProcessors()
-{
- using namespace CppTools;
-
- const auto cppEditorDocuments = CppModelManager::instance()->cppEditorDocuments();
- foreach (CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments)
- cppEditorDocument->resetProcessor();
-}
-
-void IpcCommunicator::registerVisibleCppEditorDocumentAndMarkInvisibleDirty()
-{
- CppTools::CppModelManager::instance()->updateCppEditorDocuments();
-}
-
-void IpcCommunicator::registerCurrentCodeModelUiHeaders()
-{
- using namespace CppTools;
-
- const auto editorSupports = CppModelManager::instance()->abstractEditorSupports();
- foreach (const AbstractEditorSupport *es, editorSupports) {
- const QString mappedPath
- = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskPath(es->fileName());
- updateUnsavedFile(mappedPath, es->contents(), es->revision());
- }
-}
-
-void IpcCommunicator::registerProjectsParts(const QVector<CppTools::ProjectPart::Ptr> projectParts)
-{
- const auto projectPartContainers = toProjectPartContainers(projectParts);
- registerProjectPartsForEditor(projectPartContainers);
-}
-
-void IpcCommunicator::updateTranslationUnitFromCppEditorDocument(const QString &filePath)
-{
- const CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath);
-
- updateTranslationUnit(filePath, document->contents(), document->revision());
-}
-
-void IpcCommunicator::updateUnsavedFileFromCppEditorDocument(const QString &filePath)
-{
- const CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath);
-
- updateUnsavedFile(filePath, document->contents(), document->revision());
-}
-
-namespace {
-
-
-}
-
-void IpcCommunicator::updateTranslationUnit(const QString &filePath,
- const QByteArray &contents,
- uint documentRevision)
-{
- const bool hasUnsavedContent = true;
-
- updateTranslationUnitsForEditor({{filePath,
- Utf8String(),
- Utf8String::fromByteArray(contents),
- hasUnsavedContent,
- documentRevision}});
-}
-
-void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision)
-{
- const bool hasUnsavedContent = true;
-
- // TODO: Send new only if changed
- registerUnsavedFilesForEditor({{filePath,
- Utf8String(),
- Utf8String::fromByteArray(contents),
- hasUnsavedContent,
- documentRevision}});
-}
-
-static bool documentHasChanged(const QString &filePath, uint revision)
-{
- if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath))
- return document->sendTracker().shouldSendRevision(revision);
-
- return true;
-}
-
-static void setLastSentDocumentRevision(const QString &filePath, uint revision)
-{
- if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath))
- document->sendTracker().setLastSentRevision(int(revision));
-}
-
-void IpcCommunicator::updateTranslationUnitWithRevisionCheck(const FileContainer &fileContainer)
-{
- if (documentHasChanged(fileContainer.filePath(), fileContainer.documentRevision())) {
- updateTranslationUnitsForEditor({fileContainer});
- setLastSentDocumentRevision(fileContainer.filePath(),
- fileContainer.documentRevision());
- }
-}
-
-void IpcCommunicator::requestDocumentAnnotations(const FileContainer &fileContainer)
-{
- const RequestDocumentAnnotationsMessage message(fileContainer);
- m_ipcSender->requestDocumentAnnotations(message);
-}
-
-QFuture<CppTools::CursorInfo> IpcCommunicator::requestReferences(
- const FileContainer &fileContainer,
- quint32 line,
- quint32 column,
- QTextDocument *textDocument,
- const CppTools::SemanticInfo::LocalUseMap &localUses)
-{
- const RequestReferencesMessage message(fileContainer, line, column);
- m_ipcSender->requestReferences(message);
-
- return m_ipcReceiver.addExpectedReferencesMessage(message.ticketNumber(), textDocument,
- localUses);
-}
-
-void IpcCommunicator::updateTranslationUnitWithRevisionCheck(Core::IDocument *document)
-{
- const auto textDocument = qobject_cast<TextDocument*>(document);
- const auto filePath = textDocument->filePath().toString();
- const QString projectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
-
- updateTranslationUnitWithRevisionCheck(FileContainer(filePath,
- projectPartId,
- Utf8StringVector(),
- textDocument->document()->revision()));
-}
-
-void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position)
-{
- if (CppTools::CppEditorDocumentHandle *document = ClangCodeModel::Utils::cppDocument(filePath))
- document->sendTracker().applyContentChange(position);
-}
-
-void IpcCommunicator::updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document)
-{
- QTC_ASSERT(document, return);
- if (Core::EditorManager::currentDocument() != document)
- updateTranslationUnit(document);
-}
-
-void IpcCommunicator::updateTranslationUnit(Core::IDocument *document)
-{
- updateTranslationUnitFromCppEditorDocument(document->filePath().toString());
-}
-
-void IpcCommunicator::updateUnsavedFile(Core::IDocument *document)
-{
- QTC_ASSERT(document, return);
-
- updateUnsavedFileFromCppEditorDocument(document->filePath().toString());
-}
-
-void IpcCommunicator::onConnectedToBackend()
-{
- m_backendStartTimeOut.stop();
-
- ++m_connectedCount;
- if (m_connectedCount > 1)
- logRestartedDueToUnexpectedFinish();
-
- m_ipcReceiver.reset();
- m_ipcSender.reset(new IpcSender(m_connection));
-
- initializeBackendWithCurrentData();
-}
-
-void IpcCommunicator::onEditorAboutToClose(Core::IEditor *editor)
-{
- if (auto *textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor))
- m_ipcReceiver.deleteProcessorsOfEditorWidget(textEditor->editorWidget());
-}
-
-void IpcCommunicator::setupDummySender()
-{
- m_ipcSender.reset(new DummyIpcSender);
-}
-
-void IpcCommunicator::logExecutableDoesNotExist()
-{
- const QString msg
- = tr("Clang Code Model: Error: "
- "The clangbackend executable \"%1\" does not exist.")
- .arg(QDir::toNativeSeparators(backendProcessPath()));
-
- logError(msg);
-}
-
-void IpcCommunicator::logStartTimeOut()
-{
- const QString msg
- = tr("Clang Code Model: Error: "
- "The clangbackend executable \"%1\" could not be started (timeout after %2ms).")
- .arg(QDir::toNativeSeparators(backendProcessPath()))
- .arg(backEndStartTimeOutInMs);
-
- logError(msg);
-}
-
-void IpcCommunicator::logRestartedDueToUnexpectedFinish()
-{
- const QString msg
- = tr("Clang Code Model: Error: "
- "The clangbackend process has finished unexpectedly and was restarted.");
-
- logError(msg);
-}
-
-void IpcCommunicator::logError(const QString &text)
-{
- const QString textWithTimestamp = QDateTime::currentDateTime().toString(Qt::ISODate)
- + ' ' + text;
- Core::MessageManager::write(textWithTimestamp, Core::MessageManager::Flash);
- qWarning("%s", qPrintable(textWithTimestamp));
-}
-
-void IpcCommunicator::initializeBackendWithCurrentData()
-{
- registerFallbackProjectPart();
- registerCurrentProjectParts();
- registerCurrentCodeModelUiHeaders();
- restoreCppEditorDocuments();
- updateTranslationUnitVisiblity();
-
- emit backendReinitialized();
-}
-
-IpcSenderInterface *IpcCommunicator::setIpcSender(IpcSenderInterface *ipcSender)
-{
- IpcSenderInterface *previousMessageSender = m_ipcSender.take();
- m_ipcSender.reset(ipcSender);
- return previousMessageSender;
-}
-
-void IpcCommunicator::killBackendProcess()
-{
- m_connection.processForTestOnly()->kill();
-}
-
-void IpcCommunicator::registerTranslationUnitsForEditor(const FileContainers &fileContainers)
-{
- const RegisterTranslationUnitForEditorMessage message(fileContainers,
- currentCppEditorDocumentFilePath(),
- visibleCppEditorDocumentsFilePaths());
- m_ipcSender->registerTranslationUnitsForEditor(message);
-}
-
-void IpcCommunicator::updateTranslationUnitsForEditor(const IpcCommunicator::FileContainers &fileContainers)
-{
- const UpdateTranslationUnitsForEditorMessage message(fileContainers);
- m_ipcSender->updateTranslationUnitsForEditor(message);
-}
-
-void IpcCommunicator::unregisterTranslationUnitsForEditor(const FileContainers &fileContainers)
-{
- const UnregisterTranslationUnitsForEditorMessage message(fileContainers);
- m_ipcSender->unregisterTranslationUnitsForEditor(message);
-}
-
-void IpcCommunicator::registerProjectPartsForEditor(
- const ProjectPartContainers &projectPartContainers)
-{
- const RegisterProjectPartsForEditorMessage message(projectPartContainers);
- m_ipcSender->registerProjectPartsForEditor(message);
-}
-
-void IpcCommunicator::unregisterProjectPartsForEditor(const QStringList &projectPartIds)
-{
- const UnregisterProjectPartsForEditorMessage message((Utf8StringVector(projectPartIds)));
- m_ipcSender->unregisterProjectPartsForEditor(message);
-}
-
-void IpcCommunicator::registerUnsavedFilesForEditor(const IpcCommunicator::FileContainers &fileContainers)
-{
- const RegisterUnsavedFilesForEditorMessage message(fileContainers);
- m_ipcSender->registerUnsavedFilesForEditor(message);
-}
-
-void IpcCommunicator::unregisterUnsavedFilesForEditor(const IpcCommunicator::FileContainers &fileContainers)
-{
- const UnregisterUnsavedFilesForEditorMessage message(fileContainers);
- m_ipcSender->unregisterUnsavedFilesForEditor(message);
-}
-
-void IpcCommunicator::completeCode(ClangCompletionAssistProcessor *assistProcessor,
- const QString &filePath,
- quint32 line,
- quint32 column,
- const QString &projectFilePath)
-{
- const CompleteCodeMessage message(filePath, line, column, projectFilePath);
- m_ipcSender->completeCode(message);
- m_ipcReceiver.addExpectedCodeCompletedMessage(message.ticketNumber(), assistProcessor);
-}
diff --git a/src/libs/sqlite/createtablecommand.cpp b/src/plugins/clangcodemodel/clangbackendlogging.cpp
index 590fda2e93..47118ca22d 100644
--- a/src/libs/sqlite/createtablecommand.cpp
+++ b/src/plugins/clangcodemodel/clangbackendlogging.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,14 +23,12 @@
**
****************************************************************************/
-#include "createtablecommand.h"
+#include "clangbackendlogging.h"
+namespace ClangCodeModel {
namespace Internal {
-void CreateTableCommand::registerType()
-{
- qRegisterMetaType<CreateTableCommand>("CreateTableCommand");
-}
+Q_LOGGING_CATEGORY(ipcLog, "qtc.clangcodemodel.ipc")
} // namespace Internal
-
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendlogging.h b/src/plugins/clangcodemodel/clangbackendlogging.h
new file mode 100644
index 0000000000..6e2e3ec689
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangbackendlogging.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QLoggingCategory>
+
+namespace ClangCodeModel { namespace Internal {
+
+Q_DECLARE_LOGGING_CATEGORY(ipcLog)
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
new file mode 100644
index 0000000000..9d620d6697
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangbackendreceiver.h"
+
+#include "clangbackendlogging.h"
+
+#include "clangcompletionassistprocessor.h"
+#include "clangeditordocumentprocessor.h"
+
+#include <cpptools/cpptoolsbridge.h>
+
+#include <clangsupport/clangcodemodelclientmessages.h>
+
+#include <QLoggingCategory>
+#include <QTextBlock>
+
+#include <utils/qtcassert.h>
+
+static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.ipc")
+
+using namespace ClangBackEnd;
+
+namespace ClangCodeModel {
+namespace Internal {
+
+static bool printAliveMessageHelper()
+{
+ const bool print = qEnvironmentVariableIntValue("QTC_CLANG_FORCE_VERBOSE_ALIVE");
+ if (!print) {
+ qCDebug(log) << "Hint: AliveMessage will not be printed. "
+ "Force it by setting QTC_CLANG_FORCE_VERBOSE_ALIVE=1.";
+ }
+
+ return print;
+}
+
+static bool printAliveMessage()
+{
+ static bool print = log().isDebugEnabled() ? printAliveMessageHelper() : false;
+ return print;
+}
+
+BackendReceiver::BackendReceiver()
+{
+}
+
+BackendReceiver::~BackendReceiver()
+{
+ reset();
+}
+
+void BackendReceiver::setAliveHandler(const BackendReceiver::AliveHandler &handler)
+{
+ m_aliveHandler = handler;
+}
+
+void BackendReceiver::addExpectedCodeCompletedMessage(
+ quint64 ticket,
+ ClangCompletionAssistProcessor *processor)
+{
+ QTC_ASSERT(processor, return);
+ QTC_CHECK(!m_assistProcessorsTable.contains(ticket));
+ m_assistProcessorsTable.insert(ticket, processor);
+}
+
+void BackendReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget)
+{
+ QMutableHashIterator<quint64, ClangCompletionAssistProcessor *> it(m_assistProcessorsTable);
+ while (it.hasNext()) {
+ it.next();
+ ClangCompletionAssistProcessor *assistProcessor = it.value();
+ if (assistProcessor->textEditorWidget() == textEditorWidget) {
+ delete assistProcessor;
+ it.remove();
+ }
+ }
+}
+
+QFuture<CppTools::CursorInfo> BackendReceiver::addExpectedReferencesMessage(
+ quint64 ticket,
+ QTextDocument *textDocument,
+ const CppTools::SemanticInfo::LocalUseMap &localUses)
+{
+ QTC_CHECK(textDocument);
+ QTC_CHECK(!m_referencesTable.contains(ticket));
+
+ QFutureInterface<CppTools::CursorInfo> futureInterface;
+ futureInterface.reportStarted();
+
+ const ReferencesEntry entry{futureInterface, textDocument, localUses};
+ m_referencesTable.insert(ticket, entry);
+
+ return futureInterface.future();
+}
+
+QFuture<CppTools::SymbolInfo> BackendReceiver::addExpectedRequestFollowSymbolMessage(quint64 ticket)
+{
+ QTC_CHECK(!m_followTable.contains(ticket));
+
+ QFutureInterface<CppTools::SymbolInfo> futureInterface;
+ futureInterface.reportStarted();
+
+ m_followTable.insert(ticket, futureInterface);
+
+ return futureInterface.future();
+}
+
+bool BackendReceiver::isExpectingCodeCompletedMessage() const
+{
+ return !m_assistProcessorsTable.isEmpty();
+}
+
+void BackendReceiver::reset()
+{
+ // Clean up waiting assist processors
+ qDeleteAll(m_assistProcessorsTable.begin(), m_assistProcessorsTable.end());
+ m_assistProcessorsTable.clear();
+
+ // Clean up futures for references
+ for (ReferencesEntry &entry : m_referencesTable)
+ entry.futureInterface.cancel();
+ m_referencesTable.clear();
+ for (QFutureInterface<CppTools::SymbolInfo> &futureInterface : m_followTable)
+ futureInterface.cancel();
+ m_followTable.clear();
+}
+
+void BackendReceiver::alive()
+{
+ if (printAliveMessage())
+ qCDebug(log) << "<<< AliveMessage";
+ QTC_ASSERT(m_aliveHandler, return);
+ m_aliveHandler();
+}
+
+void BackendReceiver::echo(const EchoMessage &message)
+{
+ qCDebug(log) << "<<<" << message;
+}
+
+void BackendReceiver::codeCompleted(const CodeCompletedMessage &message)
+{
+ qCDebug(log) << "<<< CodeCompletedMessage with" << message.codeCompletions().size() << "items";
+
+ const quint64 ticket = message.ticketNumber();
+ QScopedPointer<ClangCompletionAssistProcessor> processor(m_assistProcessorsTable.take(ticket));
+ if (processor) {
+ processor->handleAvailableCompletions(message.codeCompletions(),
+ message.neededCorrection());
+ }
+}
+
+void BackendReceiver::documentAnnotationsChanged(const DocumentAnnotationsChangedMessage &message)
+{
+ qCDebug(log) << "<<< DocumentAnnotationsChangedMessage with"
+ << message.diagnostics().size() << "diagnostics"
+ << message.highlightingMarks().size() << "highlighting marks"
+ << message.skippedPreprocessorRanges().size() << "skipped preprocessor ranges";
+
+ auto processor = ClangEditorDocumentProcessor::get(message.fileContainer().filePath());
+
+ if (processor) {
+ const QString projectPartId = message.fileContainer().projectPartId();
+ const QString filePath = message.fileContainer().filePath();
+ const QString documentProjectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
+ if (projectPartId == documentProjectPartId) {
+ const quint32 documentRevision = message.fileContainer().documentRevision();
+ processor->updateCodeWarnings(message.diagnostics(),
+ message.firstHeaderErrorDiagnostic(),
+ documentRevision);
+ processor->updateHighlighting(message.highlightingMarks(),
+ message.skippedPreprocessorRanges(),
+ documentRevision);
+ }
+ }
+}
+
+static
+CppTools::CursorInfo::Range toCursorInfoRange(const QTextDocument &textDocument,
+ const SourceRangeContainer &sourceRange)
+{
+ const SourceLocationContainer start = sourceRange.start();
+ const SourceLocationContainer end = sourceRange.end();
+ const unsigned length = end.column() - start.column();
+
+ const QTextBlock block = textDocument.findBlockByNumber(static_cast<int>(start.line()) - 1);
+ const int shift = ClangCodeModel::Utils::extraUtf8CharsShift(block.text(),
+ static_cast<int>(start.column()));
+ const uint column = start.column() - static_cast<uint>(shift);
+
+ return CppTools::CursorInfo::Range(start.line(), column, length);
+}
+
+static
+CppTools::CursorInfo toCursorInfo(const QTextDocument &textDocument,
+ const CppTools::SemanticInfo::LocalUseMap &localUses,
+ const ReferencesMessage &message)
+{
+ CppTools::CursorInfo result;
+ const QVector<SourceRangeContainer> references = message.references();
+
+ result.areUseRangesForLocalVariable = message.isLocalVariable();
+ for (const SourceRangeContainer &reference : references)
+ result.useRanges.append(toCursorInfoRange(textDocument, reference));
+
+ result.useRanges.reserve(references.size());
+ result.localUses = localUses;
+
+ return result;
+}
+
+static
+CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
+{
+ CppTools::SymbolInfo result;
+ const SourceRangeContainer &range = message.sourceRange();
+
+ const SourceLocationContainer start = range.start();
+ const SourceLocationContainer end = range.end();
+ result.startLine = static_cast<int>(start.line());
+ result.startColumn = static_cast<int>(start.column());
+ result.endLine = static_cast<int>(end.line());
+ result.endColumn = static_cast<int>(end.column());
+ result.fileName = start.filePath();
+
+ return result;
+}
+
+void BackendReceiver::references(const ReferencesMessage &message)
+{
+ qCDebug(log) << "<<< ReferencesMessage with"
+ << message.references().size() << "references";
+
+ const quint64 ticket = message.ticketNumber();
+ const ReferencesEntry entry = m_referencesTable.take(ticket);
+ QFutureInterface<CppTools::CursorInfo> futureInterface = entry.futureInterface;
+ QTC_CHECK(futureInterface != QFutureInterface<CppTools::CursorInfo>());
+
+ if (futureInterface.isCanceled())
+ return; // Editor document closed or a new request was issued making this result outdated.
+
+ QTC_ASSERT(entry.textDocument, return);
+ futureInterface.reportResult(toCursorInfo(*entry.textDocument, entry.localUses, message));
+ futureInterface.reportFinished();
+}
+
+void BackendReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
+{
+ qCDebug(log) << "<<< FollowSymbolMessage with"
+ << message.sourceRange() << "range";
+
+ const quint64 ticket = message.ticketNumber();
+ QFutureInterface<CppTools::SymbolInfo> futureInterface = m_followTable.take(ticket);
+ QTC_CHECK(futureInterface != QFutureInterface<CppTools::SymbolInfo>());
+
+ if (futureInterface.isCanceled())
+ return; // Editor document closed or a new request was issued making this result outdated.
+
+ futureInterface.reportResult(toSymbolInfo(message));
+ futureInterface.reportFinished();
+}
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.h b/src/plugins/clangcodemodel/clangbackendreceiver.h
new file mode 100644
index 0000000000..d67db73223
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <cpptools/cppcursorinfo.h>
+#include <cpptools/cppsymbolinfo.h>
+
+#include <clangsupport/clangcodemodelclientinterface.h>
+
+#include <QFuture>
+#include <QPointer>
+#include <QTextDocument>
+
+namespace TextEditor { class TextEditorWidget; }
+
+namespace ClangCodeModel {
+namespace Internal {
+
+class ClangCompletionAssistProcessor;
+
+class BackendReceiver : public ClangBackEnd::ClangCodeModelClientInterface
+{
+public:
+ BackendReceiver();
+ ~BackendReceiver() override;
+
+ using AliveHandler = std::function<void ()>;
+ void setAliveHandler(const AliveHandler &handler);
+
+ void addExpectedCodeCompletedMessage(quint64 ticket, ClangCompletionAssistProcessor *processor);
+ void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget);
+
+ QFuture<CppTools::CursorInfo>
+ addExpectedReferencesMessage(quint64 ticket,
+ QTextDocument *textDocument,
+ const CppTools::SemanticInfo::LocalUseMap &localUses);
+ QFuture<CppTools::SymbolInfo> addExpectedRequestFollowSymbolMessage(quint64 ticket);
+ bool isExpectingCodeCompletedMessage() const;
+
+ void reset();
+
+private:
+ void alive() override;
+ void echo(const ClangBackEnd::EchoMessage &message) override;
+ void codeCompleted(const ClangBackEnd::CodeCompletedMessage &message) override;
+
+ void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &message) override;
+ void references(const ClangBackEnd::ReferencesMessage &message) override;
+ void followSymbol(const ClangBackEnd::FollowSymbolMessage &message) override;
+
+private:
+ AliveHandler m_aliveHandler;
+ QHash<quint64, ClangCompletionAssistProcessor *> m_assistProcessorsTable;
+
+ struct ReferencesEntry {
+ ReferencesEntry() = default;
+ ReferencesEntry(QFutureInterface<CppTools::CursorInfo> futureInterface,
+ QTextDocument *textDocument,
+ const CppTools::SemanticInfo::LocalUseMap &localUses)
+ : futureInterface(futureInterface)
+ , textDocument(textDocument)
+ , localUses(localUses) {}
+ QFutureInterface<CppTools::CursorInfo> futureInterface;
+ QPointer<QTextDocument> textDocument;
+ CppTools::SemanticInfo::LocalUseMap localUses;
+ };
+ QHash<quint64, ReferencesEntry> m_referencesTable;
+
+ QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable;
+};
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendsender.cpp b/src/plugins/clangcodemodel/clangbackendsender.cpp
new file mode 100644
index 0000000000..b43b5dee4e
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangbackendsender.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangbackendsender.h"
+
+#include "clangbackendlogging.h"
+
+#include <clangsupport/clangcodemodelconnectionclient.h>
+#include <clangsupport/clangcodemodelservermessages.h>
+
+#include <utils/qtcassert.h>
+
+using namespace ClangBackEnd;
+
+namespace ClangCodeModel {
+namespace Internal {
+
+BackendSender::BackendSender(ClangCodeModelConnectionClient *connectionClient)
+ : m_connection(connectionClient)
+{}
+
+void BackendSender::end()
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << ClangBackEnd::EndMessage();
+ m_connection->sendEndMessage();
+}
+
+void BackendSender::registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().registerTranslationUnitsForEditor(message);
+}
+
+void BackendSender::updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().updateTranslationUnitsForEditor(message);
+}
+
+void BackendSender::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().unregisterTranslationUnitsForEditor(message);
+}
+
+void BackendSender::registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().registerProjectPartsForEditor(message);
+}
+
+void BackendSender::unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().unregisterProjectPartsForEditor(message);
+}
+
+void BackendSender::registerUnsavedFilesForEditor(const RegisterUnsavedFilesForEditorMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().registerUnsavedFilesForEditor(message);
+}
+
+void BackendSender::unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().unregisterUnsavedFilesForEditor(message);
+}
+
+void BackendSender::completeCode(const CompleteCodeMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().completeCode(message);
+}
+
+void BackendSender::requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().requestDocumentAnnotations(message);
+}
+
+void BackendSender::requestReferences(const RequestReferencesMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().requestReferences(message);
+}
+
+void BackendSender::requestFollowSymbol(const RequestFollowSymbolMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().requestFollowSymbol(message);
+}
+
+void BackendSender::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
+{
+ QTC_CHECK(m_connection->isConnected());
+ qCDebug(ipcLog) << ">>>" << message;
+ m_connection->serverProxy().updateVisibleTranslationUnits(message);
+}
+
+bool BackendSender::isConnected() const
+{
+ return m_connection && m_connection->isConnected();
+}
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbackendsender.h b/src/plugins/clangcodemodel/clangbackendsender.h
new file mode 100644
index 0000000000..ca9238ae65
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangbackendsender.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <clangsupport/clangcodemodelserverinterface.h>
+
+namespace ClangBackEnd { class ClangCodeModelConnectionClient; }
+
+namespace ClangCodeModel {
+namespace Internal {
+
+class BackendSender : public ClangBackEnd::ClangCodeModelServerInterface
+{
+public:
+ BackendSender(ClangBackEnd::ClangCodeModelConnectionClient *connectionClient);
+
+ void end() override;
+ void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) override;
+ void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) override;
+ void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) override;
+ void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) override;
+ void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) override;
+ void registerUnsavedFilesForEditor(const ClangBackEnd::RegisterUnsavedFilesForEditorMessage &message) override;
+ void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override;
+ void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
+ void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
+ void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
+ void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override;
+ void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) override;
+
+private:
+ bool isConnected() const;
+
+private:
+ ClangBackEnd::ClangCodeModelConnectionClient *m_connection = nullptr;
+};
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro
index 4b44cce6c6..9f632dd464 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.pro
+++ b/src/plugins/clangcodemodel/clangcodemodel.pro
@@ -9,7 +9,10 @@ SOURCES += \
clangassistproposal.cpp \
clangassistproposalitem.cpp \
clangassistproposalmodel.cpp \
- clangbackendipcintegration.cpp \
+ clangbackendcommunicator.cpp \
+ clangbackendlogging.cpp \
+ clangbackendreceiver.cpp \
+ clangbackendsender.cpp \
clangcodemodelplugin.cpp \
clangcompletionassistinterface.cpp \
clangcompletionassistprocessor.cpp \
@@ -23,6 +26,7 @@ SOURCES += \
clangeditordocumentprocessor.cpp \
clangfixitoperation.cpp \
clangfixitoperationsextractor.cpp \
+ clangfollowsymbol.cpp \
clangfunctionhintmodel.cpp \
clanghighlightingmarksreporter.cpp \
clangmodelmanagersupport.cpp \
@@ -39,7 +43,10 @@ HEADERS += \
clangassistproposal.h \
clangassistproposalitem.h \
clangassistproposalmodel.h \
- clangbackendipcintegration.h \
+ clangbackendcommunicator.h \
+ clangbackendlogging.h \
+ clangbackendreceiver.h \
+ clangbackendsender.h \
clangcodemodelplugin.h \
clangcompletionassistinterface.h \
clangcompletionassistprocessor.h \
@@ -54,6 +61,7 @@ HEADERS += \
clangeditordocumentprocessor.h \
clangfixitoperation.h \
clangfixitoperationsextractor.h \
+ clangfollowsymbol.h \
clangfunctionhintmodel.h \
clanghighlightingmarksreporter.h \
clangisdiagnosticrelatedtolocation.h \
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index eb46d8f2bd..cfee39fdbf 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -10,7 +10,7 @@ QtcPlugin {
Depends { name: "ProjectExplorer" }
Depends { name: "TextEditor" }
Depends { name: "Utils" }
- Depends { name: "ClangBackEndIpc" }
+ Depends { name: "ClangSupport" }
Depends { name: "libclang"; required: false }
pluginTestDepends: [
@@ -41,8 +41,14 @@ QtcPlugin {
"clangassistproposalitem.h",
"clangassistproposalmodel.cpp",
"clangassistproposalmodel.h",
- "clangbackendipcintegration.cpp",
- "clangbackendipcintegration.h",
+ "clangbackendcommunicator.cpp",
+ "clangbackendcommunicator.h",
+ "clangbackendlogging.cpp",
+ "clangbackendlogging.h",
+ "clangbackendreceiver.cpp",
+ "clangbackendreceiver.h",
+ "clangbackendsender.cpp",
+ "clangbackendsender.h",
"clangcodemodelplugin.cpp",
"clangcodemodelplugin.h",
"clangcodemodel.qrc",
@@ -71,6 +77,8 @@ QtcPlugin {
"clangfixitoperation.h",
"clangfixitoperationsextractor.cpp",
"clangfixitoperationsextractor.h",
+ "clangfollowsymbol.cpp",
+ "clangfollowsymbol.h",
"clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h",
"clanghighlightingmarksreporter.cpp",
diff --git a/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri b/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri
index 335569d766..9b44838b01 100644
--- a/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri
+++ b/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri
@@ -1,7 +1,7 @@
QTC_PLUGIN_NAME = ClangCodeModel
QTC_LIB_DEPENDS += \
utils \
- clangbackendipc
+ clangsupport
QTC_PLUGIN_DEPENDS += \
coreplugin \
cpptools \
diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp b/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp
index 57e2cbcdf1..0f5ec7bc1d 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp
@@ -31,7 +31,7 @@ namespace ClangCodeModel {
namespace Internal {
ClangCompletionAssistInterface::ClangCompletionAssistInterface(
- IpcCommunicator &ipcCommunicator,
+ BackendCommunicator &communicator,
const TextEditor::TextEditorWidget *textEditorWidget,
int position,
const QString &fileName,
@@ -39,7 +39,7 @@ ClangCompletionAssistInterface::ClangCompletionAssistInterface(
const CppTools::ProjectPartHeaderPaths &headerPaths,
const CPlusPlus::LanguageFeatures &features)
: AssistInterface(textEditorWidget->document(), position, fileName, reason)
- , m_ipcCommunicator(ipcCommunicator)
+ , m_communicator(communicator)
, m_headerPaths(headerPaths)
, m_languageFeatures(features)
, m_textEditorWidget(textEditorWidget)
@@ -71,9 +71,9 @@ const TextEditor::TextEditorWidget *ClangCompletionAssistInterface::textEditorWi
return m_textEditorWidget;
}
-IpcCommunicator &ClangCompletionAssistInterface::ipcCommunicator() const
+BackendCommunicator &ClangCompletionAssistInterface::communicator() const
{
- return m_ipcCommunicator;
+ return m_communicator;
}
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.h b/src/plugins/clangcodemodel/clangcompletionassistinterface.h
index fc0724777e..df198d8fcf 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistinterface.h
+++ b/src/plugins/clangcodemodel/clangcompletionassistinterface.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipcintegration.h"
+#include "clangbackendcommunicator.h"
#include "clangutils.h"
#include <texteditor/codeassist/assistinterface.h>
@@ -36,7 +36,7 @@ namespace Internal {
class ClangCompletionAssistInterface: public TextEditor::AssistInterface
{
public:
- ClangCompletionAssistInterface(IpcCommunicator &ipcCommunicator,
+ ClangCompletionAssistInterface(BackendCommunicator &communicator,
const TextEditor::TextEditorWidget *textEditorWidget,
int position,
const QString &fileName,
@@ -44,7 +44,7 @@ public:
const CppTools::ProjectPartHeaderPaths &headerPaths,
const CPlusPlus::LanguageFeatures &features);
- IpcCommunicator &ipcCommunicator() const;
+ BackendCommunicator &communicator() const;
bool objcEnabled() const;
const CppTools::ProjectPartHeaderPaths &headerPaths() const;
CPlusPlus::LanguageFeatures languageFeatures() const;
@@ -53,7 +53,7 @@ public:
void setHeaderPaths(const CppTools::ProjectPartHeaderPaths &headerPaths); // For tests
private:
- IpcCommunicator &m_ipcCommunicator;
+ BackendCommunicator &m_communicator;
QStringList m_options;
CppTools::ProjectPartHeaderPaths m_headerPaths;
CPlusPlus::LanguageFeatures m_languageFeatures;
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
index 9d84b3ba81..54d960ff03 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
@@ -42,16 +42,16 @@
#include <texteditor/codeassist/assistproposalitem.h>
#include <texteditor/codeassist/functionhintproposal.h>
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
-#include <texteditor/convenience.h>
#include <cplusplus/BackwardsScanner.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/Icons.h>
#include <cplusplus/SimpleLexer.h>
-#include <clangbackendipc/filecontainer.h>
+#include <clangsupport/filecontainer.h>
#include <utils/algorithm.h>
+#include <utils/textutils.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
@@ -253,7 +253,8 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
}
case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: {
m_sentRequestType = FunctionHintCompletion;
- const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray());
+ const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray(),
+ analyzer.functionNameStart());
setPerformWasApplicable(requestSent);
break;
}
@@ -494,12 +495,12 @@ void ClangCompletionAssistProcessor::sendFileContent(const QByteArray &customFil
// TODO: Revert custom modification after the completions
const UnsavedFileContentInfo info = unsavedFileContent(customFileContent);
- IpcCommunicator &ipcCommunicator = m_interface->ipcCommunicator();
- ipcCommunicator.updateTranslationUnitsForEditor({{m_interface->fileName(),
- Utf8String(),
- Utf8String::fromByteArray(info.unsavedContent),
- info.isDocumentModified,
- uint(m_interface->textDocument()->revision())}});
+ BackendCommunicator &communicator = m_interface->communicator();
+ communicator.updateTranslationUnitsForEditor({{m_interface->fileName(),
+ Utf8String(),
+ Utf8String::fromByteArray(info.unsavedContent),
+ info.isDocumentModified,
+ uint(m_interface->textDocument()->revision())}});
}
namespace {
bool shouldSendDocumentForCompletion(const QString &filePath,
@@ -548,27 +549,39 @@ void setLastCompletionPosition(const QString &filePath,
}
-bool ClangCompletionAssistProcessor::sendCompletionRequest(int position,
- const QByteArray &customFileContent)
+ClangCompletionAssistProcessor::Position
+ClangCompletionAssistProcessor::extractLineColumn(int position)
{
- int line, column;
- TextEditor::Convenience::convertPosition(m_interface->textDocument(), position, &line, &column);
+ if (position < 0)
+ return {-1, -1};
+
+ int line = -1, column = -1;
+ ::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column);
const QTextBlock block = m_interface->textDocument()->findBlock(position);
column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1;
+ return {line, column};
+}
+bool ClangCompletionAssistProcessor::sendCompletionRequest(int position,
+ const QByteArray &customFileContent,
+ int functionNameStartPosition)
+{
const QString filePath = m_interface->fileName();
- auto &ipcCommunicator = m_interface->ipcCommunicator();
+ auto &communicator = m_interface->communicator();
- if (shouldSendCodeCompletion(filePath, position)
- || ipcCommunicator.isNotWaitingForCompletion()) {
+ if (shouldSendCodeCompletion(filePath, position) || communicator.isNotWaitingForCompletion()) {
if (shouldSendDocumentForCompletion(filePath, position)) {
sendFileContent(customFileContent);
setLastDocumentRevision(filePath);
}
+ const Position cursorPosition = extractLineColumn(position);
+ const Position functionNameStart = extractLineColumn(functionNameStartPosition);
const QString projectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
- ipcCommunicator.completeCode(this, filePath, uint(line), uint(column), projectPartId);
+ communicator.completeCode(this, filePath, uint(cursorPosition.line),
+ uint(cursorPosition.column), projectPartId,
+ functionNameStart.line, functionNameStart.column);
setLastCompletionPosition(filePath, position);
return true;
}
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h
index 8b67116e87..0f23b1a0fe 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h
+++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h
@@ -29,7 +29,7 @@
#include <cpptools/cppcompletionassistprocessor.h>
-#include <clangbackendipc/codecompletion.h>
+#include <clangsupport/codecompletion.h>
#include <QCoreApplication>
#include <QTextCursor>
@@ -82,9 +82,14 @@ private:
UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const;
void sendFileContent(const QByteArray &customFileContent);
- bool sendCompletionRequest(int position, const QByteArray &customFileContent);
+ bool sendCompletionRequest(int position,
+ const QByteArray &customFileContent,
+ int functionNameStartPosition = -1);
private:
+ struct Position { int line; int column; };
+ Position extractLineColumn(int position);
+
QScopedPointer<const ClangCompletionAssistInterface> m_interface;
unsigned m_completionOperator;
enum CompletionRequestType { NormalCompletion, FunctionHintCompletion } m_sentRequestType;
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp b/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp
index 99abf8ab25..64b97957e7 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp
@@ -43,8 +43,8 @@
namespace ClangCodeModel {
namespace Internal {
-ClangCompletionAssistProvider::ClangCompletionAssistProvider(IpcCommunicator &ipcCommunicator)
- : m_ipcCommunicator(ipcCommunicator)
+ClangCompletionAssistProvider::ClangCompletionAssistProvider(BackendCommunicator &communicator)
+ : m_communicator(communicator)
{
}
@@ -67,7 +67,7 @@ TextEditor::AssistInterface *ClangCompletionAssistProvider::createAssistInterfac
{
const CppTools::ProjectPart::Ptr projectPart = Utils::projectPartForFileBasedOnProcessor(filePath);
if (projectPart) {
- return new ClangCompletionAssistInterface(m_ipcCommunicator,
+ return new ClangCompletionAssistInterface(m_communicator,
textEditorWidget,
position,
filePath,
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprovider.h b/src/plugins/clangcodemodel/clangcompletionassistprovider.h
index 7c1ac168be..12139b35d7 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistprovider.h
+++ b/src/plugins/clangcodemodel/clangcompletionassistprovider.h
@@ -25,7 +25,7 @@
#pragma once
-#include "clangbackendipcintegration.h"
+#include "clangbackendcommunicator.h"
#include <cpptools/cppcompletionassistprovider.h>
@@ -39,7 +39,7 @@ class ClangCompletionAssistProvider : public CppTools::CppCompletionAssistProvid
Q_OBJECT
public:
- ClangCompletionAssistProvider(IpcCommunicator &ipcCommunicator);
+ ClangCompletionAssistProvider(BackendCommunicator &communicator);
IAssistProvider::RunType runType() const override;
@@ -52,7 +52,7 @@ public:
TextEditor::AssistReason reason) const override;
private:
- IpcCommunicator &m_ipcCommunicator;
+ BackendCommunicator &m_communicator;
};
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
index 4a8f6b8a95..27eccbcf16 100644
--- a/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
+++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangbackendipc/codecompletion.h>
+#include <clangsupport/codecompletion.h>
#include <sqlite/utf8string.h>
diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp
index 00a8f96c6d..bb8308eada 100644
--- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp
+++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp
@@ -91,7 +91,7 @@ void ClangCompletionContextAnalyzer::analyze()
}
}
-bool ClangCompletionContextAnalyzer::looksLikeAFunctionCall(int endOfOperator) const
+int ClangCompletionContextAnalyzer::startOfFunctionCall(int endOfOperator) const
{
int index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface,
endOfOperator);
@@ -104,22 +104,24 @@ bool ClangCompletionContextAnalyzer::looksLikeAFunctionCall(int endOfOperator) c
const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface,
index);
if (functionNameStart == -1)
- return false;
+ return -1;
QTextCursor functionNameSelector(m_interface->textDocument());
functionNameSelector.setPosition(functionNameStart);
functionNameSelector.setPosition(index, QTextCursor::KeepAnchor);
const QString functionName = functionNameSelector.selectedText().trimmed();
- return !functionName.isEmpty();
+ return functionName.isEmpty() ? -1 : functionNameStart;
}
void ClangCompletionContextAnalyzer::setActionAndClangPosition(CompletionAction action,
- int position)
+ int position,
+ int functionNameStart)
{
QTC_CHECK(position >= -1);
m_completionAction = action;
m_positionForClang = position;
+ m_functionNameStart = functionNameStart;
}
void
@@ -157,15 +159,19 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio
// No function completion if cursor is not after '(' or ','
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
- } else if (looksLikeAFunctionCall(afterOperatorPosition)) {
- // Always pass the position right after '(' to libclang because
- // positions after the comma might be problematic if a preceding
- // argument is invalid code.
- setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
- m_positionForProposal);
- } else { // e.g. "(" without any function name in front
- m_positionForProposal = afterOperatorPosition;
- setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
+ } else {
+ const int functionNameStart = startOfFunctionCall(afterOperatorPosition);
+ if (functionNameStart >= 0) {
+ // Always pass the position right after '(' to libclang because
+ // positions after the comma might be problematic if a preceding
+ // argument is invalid code.
+ setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
+ m_positionForProposal,
+ functionNameStart);
+ } else { // e.g. "(" without any function name in front
+ m_positionForProposal = afterOperatorPosition;
+ setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
+ }
}
}
}
diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h
index 3aa3bc5804..113384c761 100644
--- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h
+++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.h
@@ -56,14 +56,17 @@ public:
unsigned completionOperator() const { return m_completionOperator; }
int positionForProposal() const { return m_positionForProposal; }
int positionForClang() const { return m_positionForClang; }
+ int functionNameStart() const { return m_functionNameStart; }
int positionEndOfExpression() const { return m_positionEndOfExpression; }
private:
ClangCompletionContextAnalyzer();
- bool looksLikeAFunctionCall(int endOfExpression) const;
+ int startOfFunctionCall(int endOfExpression) const;
- void setActionAndClangPosition(CompletionAction action, int position);
+ void setActionAndClangPosition(CompletionAction action,
+ int position,
+ int functionNameStart = -1);
void setAction(CompletionAction action);
bool handleNonFunctionCall(int position);
@@ -79,6 +82,7 @@ private:
CPlusPlus::Kind m_completionOperator = CPlusPlus::T_EOF_SYMBOL;
int m_positionForProposal = -1;
int m_positionForClang = -1;
+ int m_functionNameStart = -1;
int m_positionEndOfExpression = -1;
};
diff --git a/src/plugins/clangcodemodel/clangdiagnosticfilter.h b/src/plugins/clangcodemodel/clangdiagnosticfilter.h
index 9329d43ceb..0fe164ecf0 100644
--- a/src/plugins/clangcodemodel/clangdiagnosticfilter.h
+++ b/src/plugins/clangcodemodel/clangdiagnosticfilter.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangbackendipc/diagnosticcontainer.h>
+#include <clangsupport/diagnosticcontainer.h>
#include <QVector>
diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
index 1dd003c7c1..eb43f6556e 100644
--- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
+++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
@@ -33,11 +33,11 @@
#include <cpptools/cpptoolsconstants.h>
-#include <texteditor/convenience.h>
#include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h>
+#include <utils/textutils.h>
#include <utils/fileutils.h>
#include <utils/proxyaction.h>
#include <utils/qtcassert.h>
@@ -176,7 +176,7 @@ void addErrorSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagno
ClangBackEnd::SourceLocationContainer toSourceLocation(QTextDocument *textDocument, int position)
{
int line, column;
- if (TextEditor::Convenience::convertPosition(textDocument, position, &line, &column))
+ if (Utils::Text::convertPosition(textDocument, position, &line, &column))
return ClangBackEnd::SourceLocationContainer(Utf8String(), line, column);
return ClangBackEnd::SourceLocationContainer();
diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.h b/src/plugins/clangcodemodel/clangdiagnosticmanager.h
index 1321702c99..dff768a09d 100644
--- a/src/plugins/clangcodemodel/clangdiagnosticmanager.h
+++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.h
@@ -29,7 +29,7 @@
#include <texteditor/refactoroverlay.h>
-#include <clangbackendipc/diagnosticcontainer.h>
+#include <clangsupport/diagnosticcontainer.h>
#include <QList>
#include <QSet>
diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
index 3ea1bfb0ad..91fdfc67d6 100644
--- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
+++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangbackendipc/diagnosticcontainer.h>
+#include <clangsupport/diagnosticcontainer.h>
QT_BEGIN_NAMESPACE
class QLayout;
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
index 943c126c59..3d2f2f5267 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -25,7 +25,7 @@
#include "clangeditordocumentprocessor.h"
-#include "clangbackendipcintegration.h"
+#include "clangbackendcommunicator.h"
#include "clangdiagnostictooltipwidget.h"
#include "clangfixitoperation.h"
#include "clangfixitoperationsextractor.h"
@@ -47,7 +47,6 @@
#include <cpptools/cppworkingcopy.h>
#include <cpptools/editordocumenthandle.h>
-#include <texteditor/convenience.h>
#include <texteditor/displaysettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditor.h>
@@ -56,6 +55,7 @@
#include <cplusplus/CppDocument.h>
+#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
@@ -67,12 +67,12 @@ namespace ClangCodeModel {
namespace Internal {
ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
- IpcCommunicator &ipcCommunicator,
+ BackendCommunicator &communicator,
TextEditor::TextDocument *document)
: BaseEditorDocumentProcessor(document->document(), document->filePath().toString())
, m_document(*document)
, m_diagnosticManager(document)
- , m_ipcCommunicator(ipcCommunicator)
+ , m_communicator(communicator)
, m_parser(new ClangEditorDocumentParser(document->filePath().toString()))
, m_parserRevision(0)
, m_semanticHighlighter(document)
@@ -102,7 +102,7 @@ ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
m_parserWatcher.waitForFinished();
if (m_projectPart) {
- m_ipcCommunicator.unregisterTranslationUnitsForEditor(
+ m_communicator.unregisterTranslationUnitsForEditor(
{ClangBackEnd::FileContainer(filePath(), m_projectPart->id())});
}
}
@@ -225,6 +225,12 @@ toTextEditorBlocks(QTextDocument *textDocument,
}
}
+const QVector<ClangBackEnd::HighlightingMarkContainer>
+&ClangEditorDocumentProcessor::highlightingMarks() const
+{
+ return m_highlightingMarks;
+}
+
void ClangEditorDocumentProcessor::updateHighlighting(
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
@@ -234,6 +240,7 @@ void ClangEditorDocumentProcessor::updateHighlighting(
const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
+ m_highlightingMarks = highlightingMarks;
m_semanticHighlighter.setHighlightingRunner(
[highlightingMarks]() {
auto *reporter = new HighlightingMarksReporter(highlightingMarks);
@@ -246,10 +253,8 @@ void ClangEditorDocumentProcessor::updateHighlighting(
static int currentLine(const TextEditor::AssistInterface &assistInterface)
{
int line, column;
- TextEditor::Convenience::convertPosition(assistInterface.textDocument(),
- assistInterface.position(),
- &line,
- &column);
+ ::Utils::Text::convertPosition(assistInterface.textDocument(), assistInterface.position(),
+ &line, &column);
return line;
}
@@ -315,10 +320,10 @@ static QFuture<CppTools::CursorInfo> defaultCursorInfoFuture()
static bool convertPosition(const QTextCursor &textCursor, int *line, int *column)
{
- const bool converted = TextEditor::Convenience::convertPosition(textCursor.document(),
- textCursor.position(),
- line,
- column);
+ const bool converted = ::Utils::Text::convertPosition(textCursor.document(),
+ textCursor.position(),
+ line,
+ column);
QTC_CHECK(converted);
return converted;
}
@@ -338,11 +343,59 @@ ClangEditorDocumentProcessor::cursorInfo(const CppTools::CursorInfoParams &param
const CppTools::SemanticInfo::LocalUseMap localUses
= CppTools::BuiltinCursorInfo::findLocalUses(params.semanticInfo.doc, line, column);
- return m_ipcCommunicator.requestReferences(simpleFileContainer(),
- static_cast<quint32>(line),
- static_cast<quint32>(column),
- textDocument(),
- localUses);
+ return m_communicator.requestReferences(simpleFileContainer(),
+ static_cast<quint32>(line),
+ static_cast<quint32>(column),
+ textDocument(),
+ localUses);
+}
+
+static QVector<Utf8String> prioritizeByBaseName(const QString &curPath,
+ const ::Utils::FileNameList &fileDeps)
+{
+ QList<Utf8String> dependentFiles;
+ dependentFiles.reserve(fileDeps.size());
+ for (const ::Utils::FileName &dep: fileDeps)
+ dependentFiles.push_back(dep.toString());
+
+ const QString curFilename = QFileInfo(curPath).fileName();
+ if (CppTools::ProjectFile::isHeader(CppTools::ProjectFile::classify(curFilename))) {
+ const QString withoutExt = QFileInfo(curFilename).baseName();
+ int posToMove = 0;
+ // Move exact match to the first place and partial matches after it
+ for (int i = 0; i < dependentFiles.size(); ++i) {
+ const QString baseName = QFileInfo(dependentFiles[i]).baseName();
+ if (withoutExt == baseName) {
+ dependentFiles.move(i, 0);
+ posToMove++;
+ continue;
+ }
+ if (baseName.contains(withoutExt))
+ dependentFiles.move(i, posToMove++);
+ }
+ }
+ // Limit the number of scans (don't search for overrides)
+ if (dependentFiles.size() > 5)
+ dependentFiles.erase(dependentFiles.begin() + 5, dependentFiles.end());
+ return QVector<Utf8String>::fromList(dependentFiles);
+}
+
+QFuture<CppTools::SymbolInfo>
+ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column)
+{
+ QVector<Utf8String> dependentFiles;
+ CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
+ if (modelManager && !modelManager->projectPart(filePath()).isEmpty()) {
+ // This might be not so fast - index will change that
+ const ::Utils::FileNameList fileDeps
+ = modelManager->snapshot().filesDependingOn(filePath());
+ dependentFiles = prioritizeByBaseName(filePath(), fileDeps);
+ }
+
+ return m_communicator.requestFollowSymbol(simpleFileContainer(),
+ dependentFiles,
+ static_cast<quint32>(line),
+ static_cast<quint32>(column));
}
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
@@ -403,10 +456,10 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::Pr
if (m_projectPart) {
if (projectPart->id() == m_projectPart->id())
return;
- m_ipcCommunicator.unregisterTranslationUnitsForEditor({fileContainerWithArguments()});
+ m_communicator.unregisterTranslationUnitsForEditor({fileContainerWithArguments()});
}
- m_ipcCommunicator.registerTranslationUnitsForEditor(
+ m_communicator.registerTranslationUnitsForEditor(
{fileContainerWithArgumentsAndDocumentContent(projectPart)});
ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision());
}
@@ -416,7 +469,7 @@ void ClangEditorDocumentProcessor::updateTranslationUnitIfProjectPartExists()
if (m_projectPart) {
const ClangBackEnd::FileContainer fileContainer = fileContainerWithDocumentContent(m_projectPart->id());
- m_ipcCommunicator.updateTranslationUnitWithRevisionCheck(fileContainer);
+ m_communicator.updateTranslationUnitWithRevisionCheck(fileContainer);
}
}
@@ -424,7 +477,7 @@ void ClangEditorDocumentProcessor::requestDocumentAnnotations(const QString &pro
{
const auto fileContainer = fileContainerWithDocumentContent(projectpartId);
- m_ipcCommunicator.requestDocumentAnnotations(fileContainer);
+ m_communicator.requestDocumentAnnotations(fileContainer);
}
CppTools::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
index d7c27a79ff..a040cba256 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h
@@ -43,14 +43,14 @@ class FileContainer;
namespace ClangCodeModel {
namespace Internal {
-class IpcCommunicator;
+class BackendCommunicator;
class ClangEditorDocumentProcessor : public CppTools::BaseEditorDocumentProcessor
{
Q_OBJECT
public:
- ClangEditorDocumentProcessor(IpcCommunicator &ipcCommunicator,
+ ClangEditorDocumentProcessor(BackendCommunicator &communicator,
TextEditor::TextDocument *document);
~ClangEditorDocumentProcessor();
@@ -86,11 +86,14 @@ public:
void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override;
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override;
+ QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, int column) override;
ClangBackEnd::FileContainer fileContainerWithArguments() const;
void clearDiagnosticsWithFixIts();
+ const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks() const;
+
public:
static ClangEditorDocumentProcessor *get(const QString &filePath);
@@ -111,7 +114,7 @@ private:
private:
TextEditor::TextDocument &m_document;
ClangDiagnosticManager m_diagnosticManager;
- IpcCommunicator &m_ipcCommunicator;
+ BackendCommunicator &m_communicator;
QSharedPointer<ClangEditorDocumentParser> m_parser;
CppTools::ProjectPart::Ptr m_projectPart;
bool m_isProjectFile = false;
@@ -119,6 +122,7 @@ private:
QTimer m_updateTranslationUnitTimer;
unsigned m_parserRevision;
+ QVector<ClangBackEnd::HighlightingMarkContainer> m_highlightingMarks;
CppTools::SemanticHighlighter m_semanticHighlighter;
CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor;
};
diff --git a/src/plugins/clangcodemodel/clangfixitoperation.h b/src/plugins/clangcodemodel/clangfixitoperation.h
index e4183451b4..1270e98f36 100644
--- a/src/plugins/clangcodemodel/clangfixitoperation.h
+++ b/src/plugins/clangcodemodel/clangfixitoperation.h
@@ -27,7 +27,7 @@
#include <texteditor/quickfix.h>
-#include <clangbackendipc/fixitcontainer.h>
+#include <clangsupport/fixitcontainer.h>
#include <utils/changeset.h>
diff --git a/src/plugins/clangcodemodel/clangfixitoperationsextractor.h b/src/plugins/clangcodemodel/clangfixitoperationsextractor.h
index f0b1fb83ab..ee2da9a4b2 100644
--- a/src/plugins/clangcodemodel/clangfixitoperationsextractor.h
+++ b/src/plugins/clangcodemodel/clangfixitoperationsextractor.h
@@ -27,7 +27,7 @@
#include <texteditor/quickfix.h>
-#include <clangbackendipc/diagnosticcontainer.h>
+#include <clangsupport/diagnosticcontainer.h>
namespace ClangCodeModel {
diff --git a/src/plugins/clangcodemodel/clangfollowsymbol.cpp b/src/plugins/clangcodemodel/clangfollowsymbol.cpp
new file mode 100644
index 0000000000..66db810e4a
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangfollowsymbol.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangeditordocumentprocessor.h"
+#include "clangfollowsymbol.h"
+
+#include <texteditor/texteditor.h>
+
+#include <clangsupport/highlightingmarkcontainer.h>
+
+#include <utils/textutils.h>
+#include <utils/algorithm.h>
+
+namespace ClangCodeModel {
+namespace Internal {
+
+// Returns invalid Mark if it is not found at (line, column)
+static bool findMark(const QVector<ClangBackEnd::HighlightingMarkContainer> &marks,
+ uint line,
+ uint column,
+ ClangBackEnd::HighlightingMarkContainer &mark)
+{
+ mark = Utils::findOrDefault(marks,
+ [line, column](const ClangBackEnd::HighlightingMarkContainer &curMark) {
+ if (curMark.line() != line)
+ return false;
+ if (curMark.column() == column)
+ return true;
+ if (curMark.column() < column && curMark.column() + curMark.length() >= column)
+ return true;
+ return false;
+ });
+ if (mark.isInvalid())
+ return false;
+ return true;
+}
+
+static int getMarkPos(QTextCursor cursor, const ClangBackEnd::HighlightingMarkContainer &mark)
+{
+ cursor.setPosition(0);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, mark.line() - 1);
+ cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, mark.column() - 1);
+ return cursor.position();
+}
+
+static TextEditor::TextEditorWidget::Link linkAtCursor(QTextCursor cursor,
+ const QString &filePath,
+ uint line,
+ uint column,
+ ClangEditorDocumentProcessor *processor)
+{
+ using Link = TextEditor::TextEditorWidget::Link;
+
+ const QVector<ClangBackEnd::HighlightingMarkContainer> &marks
+ = processor->highlightingMarks();
+ ClangBackEnd::HighlightingMarkContainer mark;
+ if (!findMark(marks, line, column, mark))
+ return Link();
+
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ const QString tokenStr = cursor.selectedText();
+
+ Link token(filePath, mark.line(), mark.column());
+ token.linkTextStart = getMarkPos(cursor, mark);
+ token.linkTextEnd = token.linkTextStart + mark.length();
+ if (mark.isIncludeDirectivePath()) {
+ if (tokenStr != "include" && tokenStr != "#" && tokenStr != "<")
+ return token;
+ return Link();
+ }
+ if (mark.isIdentifier() || tokenStr == "operator")
+ return token;
+ return Link();
+}
+
+TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink(
+ const CppTools::CursorInEditor &data,
+ bool resolveTarget,
+ const CPlusPlus::Snapshot &,
+ const CPlusPlus::Document::Ptr &,
+ CppTools::SymbolFinder *,
+ bool)
+{
+ int lineNumber = 0, positionInBlock = 0;
+ QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
+ Utils::Text::convertPosition(cursor.document(), cursor.position(), &lineNumber,
+ &positionInBlock);
+
+ const uint line = lineNumber;
+ const uint column = positionInBlock + 1;
+
+ ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
+ data.filePath().toString());
+ if (!processor)
+ return Link();
+
+ if (!resolveTarget)
+ return linkAtCursor(cursor, data.filePath().toString(), line, column, processor);
+
+ QFuture<CppTools::SymbolInfo> info
+ = processor->requestFollowSymbol(static_cast<int>(line),
+ static_cast<int>(column));
+
+ if (info.isCanceled())
+ return Link();
+
+ while (!info.isFinished()) {
+ if (info.isCanceled())
+ return Link();
+ QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ }
+ CppTools::SymbolInfo result = info.result();
+
+ // We did not fail but the result is empty
+ if (result.fileName.isEmpty())
+ return Link();
+
+ return Link(result.fileName, result.startLine, result.startColumn - 1);
+}
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/libs/sqlite/createtablecommand.h b/src/plugins/clangcodemodel/clangfollowsymbol.h
index b4387e7ab7..5dcf5d389d 100644
--- a/src/libs/sqlite/createtablecommand.h
+++ b/src/plugins/clangcodemodel/clangfollowsymbol.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -25,25 +25,21 @@
#pragma once
-#include "columndefinition.h"
-#include "utf8string.h"
-
-#include <QMetaType>
-#include <QVector>
+#include <cpptools/followsymbolinterface.h>
+namespace ClangCodeModel {
namespace Internal {
-class CreateTableCommand
+class ClangFollowSymbol : public CppTools::FollowSymbolInterface
{
public:
- QVector<ColumnDefinition> definitions;
- Utf8String tableName;
- bool useWithoutRowId;
-
- static void registerType();
-
+ Link findLink(const CppTools::CursorInEditor &data,
+ bool resolveTarget,
+ const CPlusPlus::Snapshot &,
+ const CPlusPlus::Document::Ptr &,
+ CppTools::SymbolFinder *,
+ bool) override;
};
} // namespace Internal
-
-Q_DECLARE_METATYPE(Internal::CreateTableCommand)
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
index 67d58d9cb6..1641f24a71 100644
--- a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
+++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp
@@ -61,6 +61,15 @@ QString ClangFunctionHintModel::text(int index) const
return signatureWithEmphasizedCurrentParameter;
}
+QString ClangFunctionHintModel::id(int index) const
+{
+ QString chunks;
+ for (const ClangBackEnd::CodeCompletionChunk &chunk : m_functionSymbols.at(index).chunks())
+ chunks += chunk.text();
+
+ return chunks;
+}
+
int ClangFunctionHintModel::activeArgument(const QString &prefix) const
{
int activeArgumentNumber = 0;
diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.h b/src/plugins/clangcodemodel/clangfunctionhintmodel.h
index edfb2f6d74..9a848025a4 100644
--- a/src/plugins/clangcodemodel/clangfunctionhintmodel.h
+++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.h
@@ -40,6 +40,7 @@ public:
void reset() override;
int size() const override;
QString text(int index) const override;
+ QString id(int index) const override;
int activeArgument(const QString &prefix) const override;
private:
diff --git a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp
index 6090b73f41..747070a317 100644
--- a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp
+++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp
@@ -158,8 +158,15 @@ void HighlightingMarksReporter::run_internal()
if (isCanceled())
return;
- for (const auto &highlightingMark : m_highlightingMarks)
+ using ClangBackEnd::HighlightingType;
+
+ for (const auto &highlightingMark : m_highlightingMarks) {
+ const HighlightingType mainType = highlightingMark.types().mainHighlightingType;
+ if (mainType == HighlightingType::StringLiteral)
+ continue;
+
reportChunkWise(toHighlightingResult(highlightingMark));
+ }
if (isCanceled())
return;
diff --git a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.h b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.h
index af4f1773b0..379e2c55f6 100644
--- a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.h
+++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.h
@@ -32,7 +32,7 @@
#include <texteditor/semantichighlighter.h>
-#include <clangbackendipc/highlightingmarkcontainer.h>
+#include <clangsupport/highlightingmarkcontainer.h>
namespace ClangCodeModel {
diff --git a/src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h b/src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h
index 8d44634bac..2676bbffde 100644
--- a/src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h
+++ b/src/plugins/clangcodemodel/clangisdiagnosticrelatedtolocation.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangbackendipc/diagnosticcontainer.h>
+#include <clangsupport/diagnosticcontainer.h>
namespace ClangCodeModel {
namespace Internal {
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index a2dd65103b..df1e96869c 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -28,8 +28,10 @@
#include "clangconstants.h"
#include "clangeditordocumentprocessor.h"
#include "clangutils.h"
+#include "clangfollowsymbol.h"
#include <coreplugin/editormanager/editormanager.h>
+#include <cpptools/cppfollowsymbolundercursor.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/editordocumenthandle.h>
#include <cpptools/projectinfo.h>
@@ -38,9 +40,9 @@
#include <projectexplorer/project.h>
-#include <clangbackendipc/cmbregisterprojectsforeditormessage.h>
-#include <clangbackendipc/filecontainer.h>
-#include <clangbackendipc/projectpartcontainer.h>
+#include <clangsupport/cmbregisterprojectsforeditormessage.h>
+#include <clangsupport/filecontainer.h>
+#include <clangsupport/projectpartcontainer.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
@@ -52,17 +54,28 @@ using namespace ClangCodeModel::Internal;
static ModelManagerSupportClang *m_instance = 0;
+static bool useClangFollowSymbol()
+{
+ static bool use = qEnvironmentVariableIntValue("QTC_CLANG_FOLLOW_SYMBOL");
+ return use;
+}
+
static CppTools::CppModelManager *cppModelManager()
{
return CppTools::CppModelManager::instance();
}
ModelManagerSupportClang::ModelManagerSupportClang()
- : m_completionAssistProvider(m_ipcCommunicator)
+ : m_completionAssistProvider(m_communicator)
{
QTC_CHECK(!m_instance);
m_instance = this;
+ if (useClangFollowSymbol())
+ m_followSymbol.reset(new ClangFollowSymbol);
+ else
+ m_followSymbol.reset(new CppTools::FollowSymbolUnderCursor);
+
Core::EditorManager *editorManager = Core::EditorManager::instance();
connect(editorManager, &Core::EditorManager::editorOpened,
this, &ModelManagerSupportClang::onEditorOpened);
@@ -83,7 +96,7 @@ ModelManagerSupportClang::ModelManagerSupportClang()
connect(modelManager, &CppTools::CppModelManager::projectPartsRemoved,
this, &ModelManagerSupportClang::onProjectPartsRemoved);
- m_ipcCommunicator.registerFallbackProjectPart();
+ m_communicator.registerFallbackProjectPart();
}
ModelManagerSupportClang::~ModelManagerSupportClang()
@@ -96,15 +109,20 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis
return &m_completionAssistProvider;
}
+CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface()
+{
+ return *m_followSymbol;
+}
+
CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument)
{
- return new ClangEditorDocumentProcessor(m_ipcCommunicator, baseTextDocument);
+ return new ClangEditorDocumentProcessor(m_communicator, baseTextDocument);
}
void ModelManagerSupportClang::onCurrentEditorChanged(Core::IEditor *)
{
- m_ipcCommunicator.updateTranslationUnitVisiblity();
+ m_communicator.updateTranslationUnitVisiblity();
}
void ModelManagerSupportClang::connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument)
@@ -177,7 +195,7 @@ void ModelManagerSupportClang::onEditorOpened(Core::IEditor *editor)
void ModelManagerSupportClang::onEditorClosed(const QList<Core::IEditor *> &)
{
- m_ipcCommunicator.updateTranslationUnitVisiblity();
+ m_communicator.updateTranslationUnitVisiblity();
}
void ModelManagerSupportClang::onCppDocumentAboutToReloadOnTranslationUnit()
@@ -192,7 +210,7 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool
if (success) {
TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
connectToTextDocumentContentsChangedForTranslationUnit(textDocument);
- m_ipcCommunicator.updateTranslationUnitWithRevisionCheck(textDocument);
+ m_communicator.updateTranslationUnitWithRevisionCheck(textDocument);
}
}
@@ -211,9 +229,9 @@ void ModelManagerSupportClang::onCppDocumentContentsChangedOnTranslationUnit(int
{
Core::IDocument *document = qobject_cast<Core::IDocument *>(sender());
- m_ipcCommunicator.updateChangeContentStartPosition(document->filePath().toString(),
+ m_communicator.updateChangeContentStartPosition(document->filePath().toString(),
position);
- m_ipcCommunicator.updateTranslationUnitIfNotCurrentDocument(document);
+ m_communicator.updateTranslationUnitIfNotCurrentDocument(document);
clearDiagnosticFixIts(document->filePath().toString());
}
@@ -230,14 +248,14 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnUnsavedFile(bool suc
if (success) {
TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
connectToTextDocumentContentsChangedForUnsavedFile(textDocument);
- m_ipcCommunicator.updateUnsavedFile(textDocument);
+ m_communicator.updateUnsavedFile(textDocument);
}
}
void ModelManagerSupportClang::onCppDocumentContentsChangedOnUnsavedFile()
{
Core::IDocument *document = qobject_cast<Core::IDocument *>(sender());
- m_ipcCommunicator.updateUnsavedFile(document);
+ m_communicator.updateUnsavedFile(document);
}
void ModelManagerSupportClang::onAbstractEditorSupportContentsUpdated(const QString &filePath,
@@ -246,7 +264,7 @@ void ModelManagerSupportClang::onAbstractEditorSupportContentsUpdated(const QStr
QTC_ASSERT(!filePath.isEmpty(), return);
const QString mappedPath = m_uiHeaderOnDiskManager.createIfNeeded(filePath);
- m_ipcCommunicator.updateUnsavedFile(mappedPath, content, 0);
+ m_communicator.updateUnsavedFile(mappedPath, content, 0);
}
void ModelManagerSupportClang::onAbstractEditorSupportRemoved(const QString &filePath)
@@ -256,7 +274,7 @@ void ModelManagerSupportClang::onAbstractEditorSupportRemoved(const QString &fil
if (!cppModelManager()->cppEditorDocument(filePath)) {
const QString mappedPath = m_uiHeaderOnDiskManager.remove(filePath);
const QString projectPartId = Utils::projectPartIdForFile(filePath);
- m_ipcCommunicator.unregisterUnsavedFilesForEditor({{mappedPath, projectPartId}});
+ m_communicator.unregisterUnsavedFilesForEditor({{mappedPath, projectPartId}});
}
}
@@ -310,16 +328,16 @@ void ModelManagerSupportClang::onProjectPartsUpdated(ProjectExplorer::Project *p
const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project);
QTC_ASSERT(projectInfo.isValid(), return);
- m_ipcCommunicator.registerProjectsParts(projectInfo.projectParts());
- m_ipcCommunicator.registerFallbackProjectPart();
+ m_communicator.registerProjectsParts(projectInfo.projectParts());
+ m_communicator.registerFallbackProjectPart();
}
void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectPartIds)
{
if (!projectPartIds.isEmpty()) {
unregisterTranslationUnitsWithProjectParts(projectPartIds);
- m_ipcCommunicator.unregisterProjectPartsForEditor(projectPartIds);
- m_ipcCommunicator.registerFallbackProjectPart();
+ m_communicator.unregisterProjectPartsForEditor(projectPartIds);
+ m_communicator.registerFallbackProjectPart();
}
}
@@ -345,7 +363,7 @@ void ModelManagerSupportClang::unregisterTranslationUnitsWithProjectParts(
{
const auto processors = clangProcessorsWithProjectParts(projectPartIds);
foreach (ClangEditorDocumentProcessor *processor, processors) {
- m_ipcCommunicator.unregisterTranslationUnitsForEditor({processor->fileContainerWithArguments()});
+ m_communicator.unregisterTranslationUnitsForEditor({processor->fileContainerWithArguments()});
processor->clearProjectPart();
processor->run();
}
@@ -356,9 +374,9 @@ ModelManagerSupportClang *ModelManagerSupportClang::instance()
return m_instance;
}
-IpcCommunicator &ModelManagerSupportClang::ipcCommunicator()
+BackendCommunicator &ModelManagerSupportClang::communicator()
{
- return m_ipcCommunicator;
+ return m_communicator;
}
QString ModelManagerSupportClang::dummyUiHeaderOnDiskPath(const QString &filePath) const
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
index d315bbb359..f87ac11923 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
@@ -33,6 +33,8 @@
#include <QObject>
#include <QScopedPointer>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QMenu;
class QWidget;
@@ -40,6 +42,7 @@ QT_END_NAMESPACE
namespace Core { class IDocument; }
namespace TextEditor { class TextEditorWidget; }
+namespace CppTools { class FollowSymbolInterface; }
namespace ClangCodeModel {
namespace Internal {
@@ -57,8 +60,9 @@ public:
CppTools::CppCompletionAssistProvider *completionAssistProvider() override;
CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) override;
+ CppTools::FollowSymbolInterface &followSymbolInterface() override;
- IpcCommunicator &ipcCommunicator();
+ BackendCommunicator &communicator();
QString dummyUiHeaderOnDiskDirPath() const;
QString dummyUiHeaderOnDiskPath(const QString &filePath) const;
@@ -98,8 +102,9 @@ private:
private:
UiHeaderOnDiskManager m_uiHeaderOnDiskManager;
- IpcCommunicator m_ipcCommunicator;
+ BackendCommunicator m_communicator;
ClangCompletionAssistProvider m_completionAssistProvider;
+ std::unique_ptr<CppTools::FollowSymbolInterface> m_followSymbol;
};
class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider
diff --git a/src/plugins/clangcodemodel/clangtextmark.h b/src/plugins/clangcodemodel/clangtextmark.h
index ae5478168a..5c794d970c 100644
--- a/src/plugins/clangcodemodel/clangtextmark.h
+++ b/src/plugins/clangcodemodel/clangtextmark.h
@@ -25,8 +25,8 @@
#pragma once
-#include <clangbackendipc_global.h>
-#include <clangbackendipc/diagnosticcontainer.h>
+#include <clangsupport_global.h>
+#include <clangsupport/diagnosticcontainer.h>
#include <texteditor/textmark.h>
diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp
index e436ec275f..0058ee4023 100644
--- a/src/plugins/clangcodemodel/clangutils.cpp
+++ b/src/plugins/clangcodemodel/clangutils.cpp
@@ -70,46 +70,21 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, const QString &fil
return createClangOptions(pPart, fileKind);
}
-class LibClangOptionsBuilder : public ClangCompilerOptionsBuilder
+class LibClangOptionsBuilder final : public ClangCompilerOptionsBuilder
{
public:
- static QStringList build(const ProjectPart::Ptr &projectPart, ProjectFile::Kind fileKind)
+ LibClangOptionsBuilder(const ProjectPart &projectPart)
+ : ClangCompilerOptionsBuilder(projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR)
{
- if (projectPart.isNull())
- return QStringList();
-
- LibClangOptionsBuilder optionsBuilder(*projectPart.data());
-
- optionsBuilder.addWordWidth();
- optionsBuilder.addTargetTriple();
- optionsBuilder.addLanguageOption(fileKind);
- optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
- optionsBuilder.enableExceptions();
-
- optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
- optionsBuilder.addDefineFloat128ForMingw();
- optionsBuilder.addToolchainAndProjectDefines();
- optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015();
-
- optionsBuilder.addPredefinedMacrosAndHeaderPathsOptions();
- optionsBuilder.addWrappedQtHeadersIncludePath();
- optionsBuilder.addHeaderPathOptions();
- optionsBuilder.addDummyUiHeaderOnDiskIncludePath();
- optionsBuilder.addProjectConfigFileInclude();
-
- optionsBuilder.addMsvcCompatibilityVersion();
-
- optionsBuilder.addExtraOptions();
-
- return optionsBuilder.options();
}
-private:
- LibClangOptionsBuilder(const CppTools::ProjectPart &projectPart)
- : ClangCompilerOptionsBuilder(projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR)
+ void addExtraOptions() final
{
+ addDummyUiHeaderOnDiskIncludePath();
+ ClangCompilerOptionsBuilder::addExtraOptions();
}
+private:
void addDummyUiHeaderOnDiskIncludePath()
{
const QString path = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskDirPath();
@@ -125,7 +100,9 @@ private:
*/
QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind fileKind)
{
- return LibClangOptionsBuilder::build(pPart, fileKind);
+ if (!pPart)
+ return QStringList();
+ return LibClangOptionsBuilder(*pPart).build(fileKind, CompilerOptionsBuilder::PchUsage::None);
}
ProjectPart::Ptr projectPartForFile(const QString &filePath)
diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
index 07c10c0f7e..9165ccca29 100644
--- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
+++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
@@ -26,7 +26,6 @@
#include "clangcodecompletion_test.h"
#include "clangautomationutils.h"
-#include "../clangbackendipcintegration.h"
#include "../clangcompletionassistinterface.h"
#include "../clangmodelmanagersupport.h"
@@ -44,7 +43,7 @@
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
-#include <clangbackendipc/clangcodemodelservermessages.h>
+#include <clangsupport/clangcodemodelservermessages.h>
#include <utils/changeset.h>
#include <utils/qtcassert.h>
@@ -58,15 +57,9 @@ using namespace ClangCodeModel::Internal;
namespace {
-QString _(const char text[])
-{ return QString::fromUtf8(text); }
-
QString qrcPath(const QByteArray relativeFilePath)
{ return QLatin1String(":/unittests/ClangCodeModel/") + QString::fromUtf8(relativeFilePath); }
-QString fileName(const QString &filePath)
-{ return QFileInfo(filePath).fileName(); }
-
CppTools::Tests::TemporaryDir *globalTemporaryDir()
{
static CppTools::Tests::TemporaryDir dir;
@@ -74,77 +67,6 @@ CppTools::Tests::TemporaryDir *globalTemporaryDir()
return &dir;
}
-struct LogOutput
-{
- LogOutput(const QString &text) : text(text.toUtf8()) {}
- LogOutput(const char text[]) : text(text) {}
- QByteArray text;
-};
-
-void printRawLines(QTextStream &out, const QList<QByteArray> &lines)
-{
- foreach (const QByteArray &line, lines) {
- QByteArray rawLine = line;
- rawLine.prepend("\"");
- rawLine.append("\\n\"\n");
- out << rawLine;
- }
-}
-
-void printDifference(const LogOutput &actual, const LogOutput &expected)
-{
- QTextStream out(stderr);
-
- const QList<QByteArray> actualLines = actual.text.split('\n');
- const QList<QByteArray> expectedLines = expected.text.split('\n');
-
- out << "-- ACTUAL:\n";
- printRawLines(out, actualLines);
- out << "-- EXPECTED:\n";
- printRawLines(out, expectedLines);
-
- if (actualLines.size() != expectedLines.size()) {
- out << "-- DIFFERENCE IN LINE COUNT:\n"
- << " actual lines:" << actualLines.size() << '\n'
- << " expected lines:" << expectedLines.size() << '\n';
- }
-
- out << "-- FIRST LINE THAT DIFFERS:\n";
- auto actualLineIt = actualLines.cbegin();
- auto expectedLineIt = expectedLines.cbegin();
- int line = 1;
- forever {
- if (actualLineIt == actualLines.cend() && expectedLineIt != expectedLines.cend()) {
- out << " line: " << line << '\n';
- out << " actual: <none>\n";
- out << " expected: \"" << *expectedLineIt << "\"\n";
- } else if (actualLineIt != actualLines.cend() && expectedLineIt == expectedLines.cend()) {
- out << " line: " << line << '\n';
- out << " actual: \"" << *actualLineIt << "\"\n";
- out << " expected: <none>\n";
- } else {
- if (*actualLineIt != *expectedLineIt) {
- out << " line: " << line << '\n';
- out << " actual: \"" << *actualLineIt << "\"\n";
- out << " expected: \"" << *expectedLineIt << "\"\n";
- return;
- }
- }
-
- ++line;
- ++actualLineIt;
- ++expectedLineIt;
- }
-}
-
-bool compare(const LogOutput &actual, const LogOutput &expected)
-{
- const bool isEqual = actual.text == expected.text;
- if (!isEqual)
- printDifference(actual, expected);
- return isEqual;
-}
-
QByteArray readFile(const QString &filePath)
{
QFile file(filePath);
@@ -189,189 +111,6 @@ private:
Core::IDocument::ReloadSetting m_previousValue;
};
-class ChangeIpcSender
-{
-public:
- ChangeIpcSender(IpcSenderInterface *ipcSender)
- {
- auto &ipc = ModelManagerSupportClang::instance()->ipcCommunicator();
- m_previousSender = ipc.setIpcSender(ipcSender);
- }
-
- ~ChangeIpcSender()
- {
- auto &ipc = ModelManagerSupportClang::instance()->ipcCommunicator();
- ipc.setIpcSender(m_previousSender);
- }
-
-private:
- IpcSenderInterface *m_previousSender;
-};
-
-QString toString(const FileContainer &fileContainer)
-{
- QString out;
- QTextStream ts(&out);
- ts << " Path: " << fileName(fileContainer.filePath().toString())
- << " ProjectPart: " << fileName(fileContainer.projectPartId().toString()) << "\n";
- return out;
-}
-
-QString toString(const QVector<FileContainer> &fileContainers)
-{
- QString out;
- QTextStream ts(&out);
- foreach (const FileContainer &fileContainer, fileContainers)
- ts << toString(fileContainer);
- return out;
-}
-
-QString toString(const ProjectPartContainer &projectPartContainer)
-{
- QString out;
- QTextStream ts(&out);
- ts << " ProjectPartContainer"
- << " id: " << fileName(projectPartContainer.projectPartId().toString());
- return out;
-}
-
-QString toString(const QVector<ProjectPartContainer> &projectPartContainers)
-{
- QString out;
- QTextStream ts(&out);
- foreach (const ProjectPartContainer &projectPartContainer, projectPartContainers)
- ts << toString(projectPartContainer);
- return out;
-}
-
-QString toString(const EndMessage &)
-{
- return QLatin1String("EndMessage\n");
-}
-
-QString toString(const RegisterTranslationUnitForEditorMessage &message)
-{
- QString out;
- QTextStream ts(&out);
-
- ts << "RegisterTranslationUnitForEditorMessage\n"
- << toString(message.fileContainers());
- return out;
-}
-
-QString toString(const UpdateTranslationUnitsForEditorMessage &message)
-{
- QString out;
- QTextStream ts(&out);
-
- ts << "UpdateTranslationUnitForEditorMessage\n"
- << toString(message.fileContainers());
- return out;
-}
-
-QString toString(const UnregisterTranslationUnitsForEditorMessage &)
-{
- return QLatin1String("UnregisterTranslationUnitsForEditorMessage\n");
-}
-
-QString toString(const RegisterProjectPartsForEditorMessage &message)
-{
- QString out;
- QTextStream ts(&out);
-
- ts << "RegisterProjectPartsForEditorMessage\n"
- << toString(message.projectContainers()) << "\n";
- return out;
-}
-
-QString toString(const UnregisterProjectPartsForEditorMessage &message)
-{
- QString out;
- QTextStream ts(&out);
-
- ts << "UnregisterProjectPartsForEditorMessage\n"
- << message.projectPartIds().join(Utf8String::fromUtf8(",")).toByteArray() << "\n";
- return out;
-}
-
-QString toString(const RegisterUnsavedFilesForEditorMessage &message)
-{
- QString out;
- QTextStream ts(&out);
-
- ts << "RegisterUnsavedFilesForEditorMessage\n"
- << toString(message.fileContainers());
- return out;
-}
-
-QString toString(const UnregisterUnsavedFilesForEditorMessage &)
-{
- return QLatin1String("UnregisterUnsavedFilesForEditorMessage\n");
-}
-
-QString toString(const CompleteCodeMessage &)
-{
- return QLatin1String("CompleteCodeMessage\n");
-}
-
-QString toString(const RequestDocumentAnnotationsMessage &)
-{
- return QStringLiteral("RequestDocumentAnnotationsMessage\n");
-}
-
-QString toString(const RequestReferencesMessage &)
-{
- return QStringLiteral("RequestReferencesMessage\n");
-}
-
-QString toString(const UpdateVisibleTranslationUnitsMessage &)
-{
- return QStringLiteral("UpdateVisibleTranslationUnitsMessage\n");
-}
-
-class IpcSenderSpy : public IpcSenderInterface
-{
-public:
- void end() override
- { senderLog.append(toString(EndMessage())); }
-
- void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) override
- { senderLog.append(toString(message)); }
-
- void updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message) override
- { senderLog.append(toString(message)); }
-
- void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) override
- { senderLog.append(toString(message)); }
-
- void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message) override
- { senderLog.append(toString(message)); }
-
- void unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message) override
- { senderLog.append(toString(message)); }
-
- void registerUnsavedFilesForEditor(const RegisterUnsavedFilesForEditorMessage &message) override
- { senderLog.append(toString(message)); }
-
- void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override
- { senderLog.append(toString(message)); }
-
- void completeCode(const CompleteCodeMessage &message) override
- { senderLog.append(toString(message)); }
-
- void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override
- { senderLog.append(toString(message)); }
-
- void requestReferences(const RequestReferencesMessage &message) override
- { senderLog.append(toString(message)); }
-
- void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override
- { senderLog.append(toString(message)); }
-
-public:
- QString senderLog;
-};
-
class TestDocument
{
public:
@@ -504,7 +243,7 @@ bool OpenEditorAtCursorPosition::waitUntil(const std::function<bool ()> &conditi
}
CppTools::ProjectPart::Ptr createProjectPart(const QStringList &files,
- const QString &defines)
+ const ProjectExplorer::Macros &macros)
{
using namespace CppTools;
@@ -513,19 +252,19 @@ CppTools::ProjectPart::Ptr createProjectPart(const QStringList &files,
foreach (const QString &file, files)
projectPart->files.append(ProjectFile(file, ProjectFile::classify(file)));
projectPart->qtVersion = ProjectPart::NoQt;
- projectPart->projectDefines = defines.toUtf8();
+ projectPart->projectMacros = macros;
return projectPart;
}
CppTools::ProjectInfo createProjectInfo(ProjectExplorer::Project *project,
const QStringList &files,
- const QString &defines)
+ const ProjectExplorer::Macros &macros)
{
using namespace CppTools;
QTC_ASSERT(project, return ProjectInfo());
- const CppTools::ProjectPart::Ptr projectPart = createProjectPart(files, defines);
+ const CppTools::ProjectPart::Ptr projectPart = createProjectPart(files, macros);
ProjectInfo projectInfo = ProjectInfo(project);
projectInfo.appendProjectPart(projectPart);
return projectInfo;
@@ -535,11 +274,11 @@ class ProjectLoader
{
public:
ProjectLoader(const QStringList &projectFiles,
- const QString &projectDefines,
+ const ProjectExplorer::Macros &projectMacros,
bool testOnlyForCleanedProjects = false)
: m_project(0)
, m_projectFiles(projectFiles)
- , m_projectDefines(projectDefines)
+ , m_projectMacros(projectMacros)
, m_helper(0, testOnlyForCleanedProjects)
{
}
@@ -549,17 +288,17 @@ public:
m_project = m_helper.createProject(QLatin1String("testProject"));
const CppTools::ProjectInfo projectInfo = createProjectInfo(m_project,
m_projectFiles,
- m_projectDefines);
+ m_projectMacros);
const QSet<QString> filesIndexedAfterLoading = m_helper.updateProjectInfo(projectInfo);
return m_projectFiles.size() == filesIndexedAfterLoading.size();
}
- bool updateProject(const QString &updatedProjectDefines)
+ bool updateProject(const ProjectExplorer::Macros &updatedProjectMacros)
{
QTC_ASSERT(m_project, return false);
const CppTools::ProjectInfo updatedProjectInfo = createProjectInfo(m_project,
m_projectFiles,
- updatedProjectDefines);
+ updatedProjectMacros);
return updateProjectInfo(updatedProjectInfo);
}
@@ -573,7 +312,7 @@ private:
ProjectExplorer::Project *m_project;
QStringList m_projectFiles;
- QString m_projectDefines;
+ ProjectExplorer::Macros m_projectMacros;
CppTools::Tests::ModelManagerTestHelper m_helper;
};
@@ -857,8 +596,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCode()
const TestDocument testDocument("completionWithProject.cpp");
QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
- ProjectLoader projectLoader(QStringList(testDocument.filePath),
- _("#define PROJECT_CONFIGURATION_1\n"));
+ ProjectLoader projectLoader(QStringList(testDocument.filePath), {{"PROJECT_CONFIGURATION_1"}});
QVERIFY(projectLoader.load());
OpenEditorAtCursorPosition openEditor(testDocument);
@@ -883,7 +621,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeAfterChangingProje
{
// Check completion with project configuration 1
ProjectLoader projectLoader(QStringList(testDocument.filePath),
- _("#define PROJECT_CONFIGURATION_1\n"),
+ {{"PROJECT_CONFIGURATION_1"}},
/* testOnlyForCleanedProjects= */ true);
QVERIFY(projectLoader.load());
openEditor.waitUntilProjectPartChanged(QLatin1String("myproject.project"));
@@ -894,7 +632,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeAfterChangingProje
QVERIFY(!hasItem(proposal, "projectConfiguration2"));
// Check completion with project configuration 2
- QVERIFY(projectLoader.updateProject(_("#define PROJECT_CONFIGURATION_2\n")));
+ QVERIFY(projectLoader.updateProject({{"PROJECT_CONFIGURATION_2"}}));
proposal = completionResults(openEditor.editor());
QVERIFY(!hasItem(proposal, "projectConfiguration1"));
@@ -1056,85 +794,6 @@ void ClangCodeCompletionTest::testCompleteAfterChangingIncludedAndNotOpenHeaderE
QVERIFY(hasItem(proposal, "globalFromHeaderReloaded"));
}
-void ClangCodeCompletionTest::testUpdateBackendAfterRestart()
-{
- QSKIP("Must be rewritten with a more robust approach instead of sender log!");
- IpcSenderSpy spy;
- ChangeIpcSender changeIpcSender(&spy);
-
- CppTools::Tests::TemporaryCopiedDir testDir(qrcPath("qt-widgets-app"));
- QVERIFY(testDir.isValid());
-
- // Open file not part of any project...
- const TestDocument headerDocument("myheader.h", &testDir);
- QVERIFY(headerDocument.isCreated());
- OpenEditorAtCursorPosition openHeader(headerDocument);
- QVERIFY(openHeader.succeeded());
- // ... and modify it, so we have an unsaved file.
- insertTextAtTopOfEditor(openHeader.editor(), "int someGlobal;\n");
- // Open project ...
- MonitorGeneratedUiFile monitorGeneratedUiFile;
- const QString projectFilePath = testDir.absolutePath("qt-widgets-app.pro");
- CppTools::Tests::ProjectOpenerAndCloser projectManager;
- const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
- QVERIFY(projectInfo.isValid());
- QVERIFY(monitorGeneratedUiFile.waitUntilGenerated());
- // ...and a file of the project
- const QString completionFile = testDir.absolutePath("mainwindow.cpp");
- const TestDocument testDocument = TestDocument::fromExistingFile(completionFile);
- QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
- OpenEditorAtCursorPosition openSource(testDocument);
- QVERIFY(openSource.succeeded());
-
- // Check messages that would have been sent
- QVERIFY(compare(LogOutput(spy.senderLog),
- LogOutput(
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: myheader.h ProjectPart: \n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: myheader.h ProjectPart: \n"
- "RequestDiagnosticsMessage\n"
- " ProjectPartContainer id: qt-widgets-app.pro qt-widgets-app\n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: myheader.h ProjectPart: \n"
- "RequestDiagnosticsMessage\n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: myheader.h ProjectPart: \n"
- "RequestDiagnosticsMessage\n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: ui_mainwindow.h ProjectPart: \n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: myheader.h ProjectPart: \n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: mainwindow.cpp ProjectPart: qt-widgets-app.pro qt-widgets-app\n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: mainwindow.cpp ProjectPart: qt-widgets-app.pro qt-widgets-app\n"
- "RequestDiagnosticsMessage\n"
-
- )));
- spy.senderLog.clear();
-
- // Kill backend process...
- auto &ipcCommunicator = ModelManagerSupportClang::instance()->ipcCommunicator();
- ipcCommunicator.killBackendProcess();
- QSignalSpy waitForReinitializedBackend(&ipcCommunicator,
- SIGNAL(backendReinitialized()));
- QVERIFY(waitForReinitializedBackend.wait());
-
- // ...and check if code model backend would have been provided with current data
- QVERIFY(compare(LogOutput(spy.senderLog),
- LogOutput(
- "RegisterProjectPartsForEditorMessage\n"
- " ProjectPartContainer id: \n"
- "RegisterProjectPartsForEditorMessage\n"
- " ProjectPartContainer id: qt-widgets-app.pro qt-widgets-app\n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: myheader.h ProjectPart: \n"
- "RegisterTranslationUnitForEditorMessage\n"
- " Path: ui_mainwindow.h ProjectPart: \n"
- )));
-}
-
} // namespace Tests
} // namespace Internal
} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h
index 24b36da4f0..b2659d064d 100644
--- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h
+++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h
@@ -58,8 +58,6 @@ private slots:
void testCompleteAfterModifyingIncludedHeaderByRefactoringActions();
void testCompleteAfterChangingIncludedAndOpenHeaderExternally();
void testCompleteAfterChangingIncludedAndNotOpenHeaderExternally();
-
- void testUpdateBackendAfterRestart();
};
} // namespace Tests
diff --git a/src/plugins/clangpchmanager/clangpchmanager-source.pri b/src/plugins/clangpchmanager/clangpchmanager-source.pri
index fd5b61a24d..25d8d63730 100644
--- a/src/plugins/clangpchmanager/clangpchmanager-source.pri
+++ b/src/plugins/clangpchmanager/clangpchmanager-source.pri
@@ -11,12 +11,14 @@ HEADERS += \
$$PWD/pchmanagernotifierinterface.h \
$$PWD/pchmanagerconnectionclient.h \
$$PWD/clangpchmanager_global.h \
- $$PWD/projectupdater.h
+ $$PWD/projectupdater.h \
+ $$PWD/pchmanagerprojectupdater.h
SOURCES += \
$$PWD/pchmanagerclient.cpp \
$$PWD/pchmanagernotifierinterface.cpp \
$$PWD/pchmanagerconnectionclient.cpp \
- $$PWD/projectupdater.cpp
+ $$PWD/projectupdater.cpp \
+ $$PWD/pchmanagerprojectupdater.cpp
diff --git a/src/plugins/clangpchmanager/clangpchmanager_dependencies.pri b/src/plugins/clangpchmanager/clangpchmanager_dependencies.pri
index 281eca80d5..197da5a97c 100644
--- a/src/plugins/clangpchmanager/clangpchmanager_dependencies.pri
+++ b/src/plugins/clangpchmanager/clangpchmanager_dependencies.pri
@@ -1,7 +1,7 @@
QTC_PLUGIN_NAME = ClangPchManager
QTC_LIB_DEPENDS += \
utils \
- clangbackendipc
+ clangsupport
QTC_PLUGIN_DEPENDS += \
coreplugin \
cpptools
diff --git a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp
index 4c53696807..086b2fce8e 100644
--- a/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp
+++ b/src/plugins/clangpchmanager/clangpchmanagerplugin.cpp
@@ -52,7 +52,7 @@ class ClangPchManagerPluginData
public:
PchManagerClient pchManagerClient;
PchManagerConnectionClient connectionClient{&pchManagerClient};
- QtCreatorProjectUpdater projectUpdate{connectionClient.serverProxy(), pchManagerClient};
+ QtCreatorProjectUpdater<PchManagerProjectUpdater> projectUpdate{connectionClient.serverProxy(), pchManagerClient};
};
std::unique_ptr<ClangPchManagerPluginData> ClangPchManagerPlugin::d;
diff --git a/src/plugins/clangpchmanager/pchmanagerclient.cpp b/src/plugins/clangpchmanager/pchmanagerclient.cpp
index d901946fb6..60c0647653 100644
--- a/src/plugins/clangpchmanager/pchmanagerclient.cpp
+++ b/src/plugins/clangpchmanager/pchmanagerclient.cpp
@@ -43,7 +43,7 @@ void PchManagerClient::alive()
void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message)
{
for (const ClangBackEnd::ProjectPartPch &projectPartPch : message.projectPartPchs())
- precompiledHeaderUpdated(projectPartPch.id(), projectPartPch.path());
+ precompiledHeaderUpdated(QString(projectPartPch.id()), QString(projectPartPch.path()));
}
void PchManagerClient::precompiledHeaderRemoved(const QString &projectPartId)
diff --git a/src/plugins/clangpchmanager/pchmanagerprojectupdater.cpp b/src/plugins/clangpchmanager/pchmanagerprojectupdater.cpp
new file mode 100644
index 0000000000..d74ea2a7b0
--- /dev/null
+++ b/src/plugins/clangpchmanager/pchmanagerprojectupdater.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "pchmanagerprojectupdater.h"
+
+#include "pchmanagerclient.h"
+
+namespace ClangPchManager {
+
+PchManagerProjectUpdater::PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
+ PchManagerClient &client)
+ : ProjectUpdater(server),
+ m_client(client)
+{
+}
+
+void PchManagerProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
+{
+ ProjectUpdater::removeProjectParts(projectPartIds);
+
+ for (const QString &projectPartiId : projectPartIds)
+ m_client.precompiledHeaderRemoved(projectPartiId);
+}
+
+} // namespace ClangPchManager
diff --git a/src/plugins/clangpchmanager/pchmanagerprojectupdater.h b/src/plugins/clangpchmanager/pchmanagerprojectupdater.h
new file mode 100644
index 0000000000..0849554751
--- /dev/null
+++ b/src/plugins/clangpchmanager/pchmanagerprojectupdater.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "projectupdater.h"
+
+namespace ClangPchManager {
+
+class PchManagerProjectUpdater : public ProjectUpdater
+{
+public:
+ PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
+ PchManagerClient &client);
+
+ void removeProjectParts(const QStringList &projectPartIds);
+
+private:
+ PchManagerClient &m_client;
+};
+
+} // namespace ClangPchManager
diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp
index 9d5d7c7577..8327f85a22 100644
--- a/src/plugins/clangpchmanager/projectupdater.cpp
+++ b/src/plugins/clangpchmanager/projectupdater.cpp
@@ -52,10 +52,8 @@ public:
Utils::PathStringVector sources;
};
-ProjectUpdater::ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
- PchManagerClient &client)
- : m_server(server),
- m_client(client)
+ProjectUpdater::ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server)
+ : m_server(server)
{
}
@@ -75,9 +73,6 @@ void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
ClangBackEnd::RemovePchProjectPartsMessage message{Utils::SmallStringVector(projectPartIds)};
m_server.removePchProjectParts(std::move(message));
-
- for (const QString &projectPartiId : projectPartIds)
- m_client.precompiledHeaderRemoved(projectPartiId);
}
void ProjectUpdater::setExcludedPaths(Utils::PathStringVector &&excludedPaths)
@@ -113,35 +108,9 @@ HeaderAndSources ProjectUpdater::headerAndSourcesFromProjectPart(
QStringList ProjectUpdater::compilerArguments(CppTools::ProjectPart *projectPart)
{
- using CppTools::ClangCompilerOptionsBuilder;
-
- ClangCompilerOptionsBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR);
-
- builder.addWordWidth();
- builder.addTargetTriple();
- builder.addLanguageOption(CppTools::ProjectFile::CXXHeader);
- builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
- builder.enableExceptions();
-
- builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
- builder.addDefineFloat128ForMingw();
- builder.addToolchainAndProjectDefines();
- builder.undefineCppLanguageFeatureMacrosForMsvc2015();
-
- builder.addPredefinedMacrosAndHeaderPathsOptions();
- builder.addWrappedQtHeadersIncludePath();
- builder.addPrecompiledHeaderOptions(ClangCompilerOptionsBuilder::PchUsage::None);
- builder.addHeaderPathOptions();
- builder.addProjectConfigFileInclude();
-
- builder.addMsvcCompatibilityVersion();
-
- builder.add("-fmessage-length=0");
- builder.add("-fmacro-backtrace-limit=0");
- builder.add("-w");
- builder.add("-ferror-limit=100000");
-
- return builder.options();
+ using ClangCOBuilder = CppTools::ClangCompilerOptionsBuilder;
+ ClangCOBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR);
+ return builder.build(CppTools::ProjectFile::CXXHeader, ClangCOBuilder::PchUsage::None);
}
ClangBackEnd::V2::ProjectPartContainer ProjectUpdater::toProjectPartContainer(
diff --git a/src/plugins/clangpchmanager/projectupdater.h b/src/plugins/clangpchmanager/projectupdater.h
index 5850e0c7e9..e207a88971 100644
--- a/src/plugins/clangpchmanager/projectupdater.h
+++ b/src/plugins/clangpchmanager/projectupdater.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangpchmanager_global.h>
+#include "clangpchmanager_global.h"
#include <filecontainerv2.h>
@@ -35,7 +35,7 @@ class ProjectFile;
}
namespace ClangBackEnd {
-class PchManagerServerInterface;
+class ProjectManagementServerInterface;
namespace V2 {
class ProjectPartContainer;
@@ -51,11 +51,10 @@ namespace ClangPchManager {
class HeaderAndSources;
class PchManagerClient;
-class ProjectUpdater
+class CLANGPCHMANAGER_EXPORT ProjectUpdater
{
public:
- ProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
- PchManagerClient &client);
+ ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server);
void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts,
ClangBackEnd::V2::FileContainers &&generatedFiles);
@@ -77,8 +76,7 @@ unittest_public:
private:
Utils::PathStringVector m_excludedPaths;
- ClangBackEnd::PchManagerServerInterface &m_server;
- PchManagerClient &m_client;
+ ClangBackEnd::ProjectManagementServerInterface &m_server;
};
} // namespace ClangPchManager
diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp b/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp
index 6ac93c747a..53b37ee2b5 100644
--- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp
+++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp
@@ -26,26 +26,18 @@
#include "qtcreatorprojectupdater.h"
#include <cpptools/abstracteditorsupport.h>
-#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/project.h>
namespace ClangPchManager {
-static CppTools::CppModelManager *cppModelManager()
-{
- return CppTools::CppModelManager::instance();
-}
+namespace Internal {
-QtCreatorProjectUpdater::QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
- PchManagerClient &client)
- : ProjectUpdater(server, client)
+CppTools::CppModelManager *cppModelManager()
{
- connectToCppModelManager();
+ return CppTools::CppModelManager::instance();
}
-namespace {
-
std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles()
{
auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports();
@@ -85,30 +77,7 @@ std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project
convertToRawPointer);
return projectParts;
-}
-
-}
-void QtCreatorProjectUpdater::projectPartsUpdated(ProjectExplorer::Project *project)
-{
- updateProjectParts(createProjectParts(project), createGeneratedFiles());
-}
-
-void QtCreatorProjectUpdater::projectPartsRemoved(const QStringList &projectPartIds)
-{
- removeProjectParts(projectPartIds);
}
-
-void QtCreatorProjectUpdater::connectToCppModelManager()
-{
- connect(cppModelManager(),
- &CppTools::CppModelManager::projectPartsUpdated,
- this,
- &QtCreatorProjectUpdater::projectPartsUpdated);
- connect(cppModelManager(),
- &CppTools::CppModelManager::projectPartsRemoved,
- this,
- &QtCreatorProjectUpdater::projectPartsRemoved);
-}
-
+} // namespace Internal
} // namespace ClangPchManager
diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
index ec99eab50e..44858ef936 100644
--- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
+++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
@@ -25,7 +25,11 @@
#pragma once
-#include "projectupdater.h"
+#include "pchmanagerprojectupdater.h"
+
+#include <cpptools/cppmodelmanager.h>
+
+#include <filecontainerv2.h>
#include <QObject>
@@ -33,19 +37,57 @@ namespace ProjectExplorer {
class Project;
}
+namespace CppTools {
+class CppModelManager;
+}
+
namespace ClangPchManager {
-class QtCreatorProjectUpdater : public QObject, public ProjectUpdater
+namespace Internal {
+CLANGPCHMANAGER_EXPORT CppTools::CppModelManager *cppModelManager();
+CLANGPCHMANAGER_EXPORT std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles();
+CLANGPCHMANAGER_EXPORT std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project *project);
+}
+
+template <typename ProjectUpdaterType>
+class QtCreatorProjectUpdater : public ProjectUpdaterType
{
public:
- QtCreatorProjectUpdater(ClangBackEnd::PchManagerServerInterface &server,
- PchManagerClient &client);
+ template <typename ClientType>
+ QtCreatorProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
+ ClientType &client)
+ : ProjectUpdaterType(server, client)
+ {
+ connectToCppModelManager();
+ }
+
+ QtCreatorProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server)
+ : ProjectUpdaterType(server)
+ {
+ connectToCppModelManager();
+ }
+
+ void projectPartsUpdated(ProjectExplorer::Project *project)
+ {
+ ProjectUpdaterType::updateProjectParts(Internal::createProjectParts(project),
+ Internal::createGeneratedFiles());
+ }
- void projectPartsUpdated(ProjectExplorer::Project *project);
- void projectPartsRemoved(const QStringList &projectPartIds);
+ void projectPartsRemoved(const QStringList &projectPartIds)
+ {
+ ProjectUpdaterType::removeProjectParts(projectPartIds);
+ }
private:
- void connectToCppModelManager();
+ void connectToCppModelManager()
+ {
+ QObject::connect(Internal::cppModelManager(),
+ &CppTools::CppModelManager::projectPartsUpdated,
+ [&] (ProjectExplorer::Project *project) { projectPartsUpdated(project); });
+ QObject::connect(Internal::cppModelManager(),
+ &CppTools::CppModelManager::projectPartsRemoved,
+ [&] (const QStringList &projectPartIds) { projectPartsRemoved(projectPartIds); });
+ }
};
} // namespace ClangPchManager
diff --git a/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp b/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp
index 47ca0dbe79..e8ce90c297 100644
--- a/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp
+++ b/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp
@@ -52,9 +52,9 @@ void ClangQueryHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorW
Contexts contexts = m_highligher->contextsForLineAndColumn(uint(line), uint(column));
if (!messages.empty())
- setToolTip(QString("%1: %2").arg(messages[0].errorTypeText()).arg(messages[0].arguments().join(", ")));
+ setToolTip(QString("%1: %2").arg(QString(messages[0].errorTypeText())).arg(QString(messages[0].arguments().join(", "))));
else if (!contexts.empty())
- setToolTip(QString("%1: %2").arg(contexts[0].contextTypeText()).arg(contexts[0].arguments().join(", ")));
+ setToolTip(QString("%1: %2").arg(QString(contexts[0].contextTypeText())).arg(QString(contexts[0].arguments().join(", "))));
}
} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp
index d4e210c04e..14d8a1620e 100644
--- a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp
+++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp
@@ -155,31 +155,8 @@ Utils::SmallStringVector ClangQueryProjectsFindFilter::compilerArguments(CppTool
ClangCompilerOptionsBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR);
- builder.addWordWidth();
- builder.addTargetTriple();
- builder.addLanguageOption(fileKind);
- builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
- builder.enableExceptions();
-
- builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
- builder.addDefineFloat128ForMingw();
- builder.addToolchainAndProjectDefines();
- builder.undefineCppLanguageFeatureMacrosForMsvc2015();
-
- builder.addPredefinedMacrosAndHeaderPathsOptions();
- builder.addWrappedQtHeadersIncludePath();
- builder.addPrecompiledHeaderOptions(ClangCompilerOptionsBuilder::PchUsage::None);
- builder.addHeaderPathOptions();
- builder.addProjectConfigFileInclude();
-
- builder.addMsvcCompatibilityVersion();
-
- builder.add("-fmessage-length=0");
- builder.add("-fmacro-backtrace-limit=0");
- builder.add("-w");
- builder.add("-ferror-limit=1000000");
-
- return Utils::SmallStringVector(builder.options());
+ return Utils::SmallStringVector(builder.build(fileKind,
+ ClangCompilerOptionsBuilder::PchUsage::None));
}
QWidget *ClangQueryProjectsFindFilter::widget() const
diff --git a/src/plugins/clangrefactoring/clangrefactoring-source.pri b/src/plugins/clangrefactoring/clangrefactoring-source.pri
index 24102dfd99..b08d292190 100644
--- a/src/plugins/clangrefactoring/clangrefactoring-source.pri
+++ b/src/plugins/clangrefactoring/clangrefactoring-source.pri
@@ -11,7 +11,8 @@ HEADERS += \
$$PWD/clangqueryexamplehighlightmarker.h \
$$PWD/clangqueryhighlightmarker.h \
$$PWD/clangqueryexamplehighlighter.h \
- $$PWD/clangqueryhighlighter.h
+ $$PWD/clangqueryhighlighter.h \
+ $$PWD/refactoringprojectupdater.h
SOURCES += \
$$PWD/refactoringengine.cpp \
@@ -22,4 +23,5 @@ SOURCES += \
$$PWD/projectpartutilities.cpp \
$$PWD/clangqueryprojectsfindfilter.cpp \
$$PWD/clangqueryexamplehighlighter.cpp \
- $$PWD/clangqueryhighlighter.cpp
+ $$PWD/clangqueryhighlighter.cpp \
+ $$PWD/refactoringprojectupdater.cpp
diff --git a/src/plugins/clangrefactoring/clangrefactoring.pro b/src/plugins/clangrefactoring/clangrefactoring.pro
index 918398bef0..d60de99636 100644
--- a/src/plugins/clangrefactoring/clangrefactoring.pro
+++ b/src/plugins/clangrefactoring/clangrefactoring.pro
@@ -15,7 +15,10 @@ HEADERS += \
clangqueryexampletexteditorwidget.h \
clangquerytexteditorwidget.h \
baseclangquerytexteditorwidget.h \
- clangqueryhoverhandler.h
+ clangqueryhoverhandler.h \
+ symbolquery.h \
+ querysqlitestatementfactory.h \
+ sourcelocations.h
SOURCES += \
clangrefactoringplugin.cpp \
@@ -26,7 +29,8 @@ SOURCES += \
clangqueryexampletexteditorwidget.cpp \
clangquerytexteditorwidget.cpp \
baseclangquerytexteditorwidget.cpp \
- clangqueryhoverhandler.cpp
+ clangqueryhoverhandler.cpp \
+ symbolquery.cpp
FORMS += \
clangqueryprojectsfindfilter.ui
diff --git a/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri b/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri
index 15005bd689..8a08236177 100644
--- a/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri
+++ b/src/plugins/clangrefactoring/clangrefactoring_dependencies.pri
@@ -1,8 +1,9 @@
QTC_PLUGIN_NAME = ClangRefactoring
QTC_LIB_DEPENDS += \
utils \
- clangbackendipc
+ clangsupport
QTC_PLUGIN_DEPENDS += \
coreplugin \
cpptools \
- texteditor
+ texteditor \
+ clangpchmanager
diff --git a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp
index 921cc24005..a2638212d6 100644
--- a/src/plugins/clangrefactoring/clangrefactoringplugin.cpp
+++ b/src/plugins/clangrefactoring/clangrefactoringplugin.cpp
@@ -25,6 +25,8 @@
#include "clangrefactoringplugin.h"
+#include <clangpchmanager/qtcreatorprojectupdater.h>
+
#include <cpptools/cppmodelmanager.h>
#include <coreplugin/icore.h>
@@ -50,6 +52,7 @@ std::unique_ptr<ClangRefactoringPluginData> ClangRefactoringPlugin::d;
class ClangRefactoringPluginData
{
+ using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater<ClangPchManager::ProjectUpdater>;
public:
RefactoringClient refactoringClient;
ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient};
@@ -58,6 +61,9 @@ public:
QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(),
qtCreatorSearch,
refactoringClient};
+ ProjectUpdater projectUpdate{connectionClient.serverProxy()};
+
+
};
ClangRefactoringPlugin::ClangRefactoringPlugin()
@@ -90,6 +96,7 @@ void ClangRefactoringPlugin::extensionsInitialized()
ExtensionSystem::IPlugin::ShutdownFlag ClangRefactoringPlugin::aboutToShutdown()
{
ExtensionSystem::PluginManager::removeObject(&d->qtCreatorfindFilter);
+ CppTools::CppModelManager::setRefactoringEngine(nullptr);
d->refactoringClient.setRefactoringConnectionClient(nullptr);
d->refactoringClient.setRefactoringEngine(nullptr);
diff --git a/src/plugins/clangrefactoring/qtcreatorsearch.cpp b/src/plugins/clangrefactoring/qtcreatorsearch.cpp
index 61f317c22a..d5802c9c97 100644
--- a/src/plugins/clangrefactoring/qtcreatorsearch.cpp
+++ b/src/plugins/clangrefactoring/qtcreatorsearch.cpp
@@ -50,7 +50,9 @@ std::unique_ptr<SearchHandle> QtCreatorSearch::startNewSearch(const QString &sea
QObject::connect(searchResult,
&Core::SearchResult::activated,
- &QtCreatorSearch::openEditor);
+ [](const Core::SearchResultItem& item) {
+ Core::EditorManager::openEditorAtSearchResult(item);
+ });
auto searchHandle = std::unique_ptr<SearchHandle>(new QtCreatorSearchHandle(searchResult));
@@ -61,11 +63,4 @@ std::unique_ptr<SearchHandle> QtCreatorSearch::startNewSearch(const QString &sea
return searchHandle;
}
-void QtCreatorSearch::openEditor(const Core::SearchResultItem &item)
-{
- Core::EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
- item.mainRange.begin.line,
- item.mainRange.begin.column);
-}
-
} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/qtcreatorsearch.h b/src/plugins/clangrefactoring/qtcreatorsearch.h
index 68d884a180..ebef545d90 100644
--- a/src/plugins/clangrefactoring/qtcreatorsearch.h
+++ b/src/plugins/clangrefactoring/qtcreatorsearch.h
@@ -41,10 +41,7 @@ public:
QtCreatorSearch(Core::SearchResultWindow &searchResultWindow);
std::unique_ptr<SearchHandle> startNewSearch(const QString &searchLabel,
- const QString &searchTerm);
-
-private:
- static void openEditor(const Core::SearchResultItem &item);
+ const QString &searchTerm);
private:
Core::SearchResultWindow &searchResultWindow;
diff --git a/src/plugins/clangrefactoring/querysqlitestatementfactory.h b/src/plugins/clangrefactoring/querysqlitestatementfactory.h
new file mode 100644
index 0000000000..dec404f89b
--- /dev/null
+++ b/src/plugins/clangrefactoring/querysqlitestatementfactory.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+namespace ClangRefactoring {
+
+template<typename Database,
+ typename ReadStatement>
+class QuerySqliteStatementFactory
+{
+public:
+ using DatabaseType = Database;
+ using ReadStatementType = ReadStatement;
+
+ QuerySqliteStatementFactory(Database &database)
+ : database(database)
+ {}
+ Database &database;
+ ReadStatement selectLocationsForSymbolLocation{
+ "SELECT sourceId, line, column FROM locations WHERE symbolId = "
+ " (SELECT symbolId FROM locations WHERE sourceId="
+ " (SELECT sourceId FROM sources WHERE sourcePath =?)"
+ " AND line=? AND column=?) "
+ "ORDER BY sourceId, line, column",
+ database}; // alternatively SELECT l2.symbolid, l2.sourceId, l2.line, l2.column FROM locations AS l2, sources, locations AS l1 ON sources.sourceId = l1.sourceId AND l2.symbolId=l1.symbolId WHERE sourcePath = ? AND l1.line=? AND l1.column=? ORDER BY l2.sourceId, l2.line, l2.column
+ ReadStatement selectSourcePathForId{
+ "SELECT sourceId, sourcePath FROM sources WHERE sourceId = ?",
+ database};
+};
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/refactoringclient.cpp b/src/plugins/clangrefactoring/refactoringclient.cpp
index e4904b53cc..189e2bd480 100644
--- a/src/plugins/clangrefactoring/refactoringclient.cpp
+++ b/src/plugins/clangrefactoring/refactoringclient.cpp
@@ -154,7 +154,7 @@ void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextC
std::unordered_map<uint, QString> &filePaths)
{
m_searchHandle->addResult(filePaths[sourceRangeWithText.fileHash()],
- sourceRangeWithText.text(),
+ QString(sourceRangeWithText.text()),
{{int(sourceRangeWithText.start().line()),
int(sourceRangeWithText.start().column() - 1),
int(sourceRangeWithText.start().offset())},
diff --git a/src/plugins/clangrefactoring/refactoringengine.cpp b/src/plugins/clangrefactoring/refactoringengine.cpp
index e0d61ae908..696e38c468 100644
--- a/src/plugins/clangrefactoring/refactoringengine.cpp
+++ b/src/plugins/clangrefactoring/refactoringengine.cpp
@@ -34,6 +34,8 @@
#include <cpptools/clangcompileroptionsbuilder.h>
#include <cpptools/cpptoolsreuse.h>
+#include <texteditor/textdocument.h>
+
#include <QTextCursor>
#include <QTextDocument>
@@ -50,9 +52,7 @@ RefactoringEngine::RefactoringEngine(ClangBackEnd::RefactoringServerInterface &s
{
}
-void RefactoringEngine::startLocalRenaming(const QTextCursor &textCursor,
- const Utils::FileName &filePath,
- int revision,
+void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
CppTools::ProjectPart *projectPart,
RenameCallback &&renameSymbolsCallback)
{
@@ -62,26 +62,31 @@ void RefactoringEngine::startLocalRenaming(const QTextCursor &textCursor,
client.setLocalRenamingCallback(std::move(renameSymbolsCallback));
- Utils::SmallStringVector commandLine{ClangCompilerOptionsBuilder::build(
- projectPart,
- fileKindInProjectPart(projectPart, filePath.toString()),
- CppTools::getPchUsage(),
- CLANG_VERSION,
- CLANG_RESOURCE_DIR)};
+ QString filePath = data.filePath().toString();
+ QTextCursor textCursor = data.cursor();
+ ClangCompilerOptionsBuilder clangCOBuilder{*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR};
+ Utils::SmallStringVector commandLine{clangCOBuilder.build(
+ fileKindInProjectPart(projectPart, filePath),
+ CppTools::getPchUsage())};
- commandLine.push_back(filePath.toString());
+ commandLine.push_back(filePath);
- RequestSourceLocationsForRenamingMessage message(ClangBackEnd::FilePath(filePath.toString()),
+ RequestSourceLocationsForRenamingMessage message(ClangBackEnd::FilePath(filePath),
uint(textCursor.blockNumber() + 1),
uint(textCursor.positionInBlock() + 1),
textCursor.document()->toPlainText(),
std::move(commandLine),
- revision);
+ textCursor.document()->revision());
server.requestSourceLocationsForRenamingMessage(std::move(message));
}
+void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
+{
+ // TODO: implement
+}
+
bool RefactoringEngine::isUsable() const
{
return server.isUsable();
diff --git a/src/plugins/clangrefactoring/refactoringengine.h b/src/plugins/clangrefactoring/refactoringengine.h
index 453c52775c..83e67bfe27 100644
--- a/src/plugins/clangrefactoring/refactoringengine.h
+++ b/src/plugins/clangrefactoring/refactoringengine.h
@@ -39,11 +39,10 @@ class RefactoringEngine : public CppTools::RefactoringEngineInterface
public:
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server,
ClangBackEnd::RefactoringClientInterface &client);
- void startLocalRenaming(const QTextCursor &textCursor,
- const Utils::FileName &filePath,
- int revision,
+ void startLocalRenaming(const CppTools::CursorInEditor &data,
CppTools::ProjectPart *projectPart,
RenameCallback &&renameSymbolsCallback) override;
+ void startGlobalRenaming(const CppTools::CursorInEditor &data) override;
bool isUsable() const override;
void setUsable(bool isUsable);
diff --git a/src/plugins/clangrefactoring/refactoringprojectupdater.cpp b/src/plugins/clangrefactoring/refactoringprojectupdater.cpp
new file mode 100644
index 0000000000..07a9e97163
--- /dev/null
+++ b/src/plugins/clangrefactoring/refactoringprojectupdater.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "refactoringprojectupdater.h"
+
+namespace ClangRefactoring {
+
+RefactoringProjectUpdater::RefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
+ RefactoringClient &)
+ : ClangPchManager::ProjectUpdater(server)
+{
+
+}
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/refactoringprojectupdater.h b/src/plugins/clangrefactoring/refactoringprojectupdater.h
new file mode 100644
index 0000000000..3debed0c4d
--- /dev/null
+++ b/src/plugins/clangrefactoring/refactoringprojectupdater.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <clangpchmanager/projectupdater.h>
+
+namespace ClangRefactoring {
+
+class RefactoringClient;
+
+class RefactoringProjectUpdater : public ClangPchManager::ProjectUpdater
+{
+public:
+ RefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
+ RefactoringClient &client);
+};
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/sourcelocations.h b/src/plugins/clangrefactoring/sourcelocations.h
new file mode 100644
index 0000000000..9ae4241c01
--- /dev/null
+++ b/src/plugins/clangrefactoring/sourcelocations.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/smallstring.h>
+
+#include <cstdint>
+#include <vector>
+#include <tuple>
+#include <unordered_map>
+
+namespace ClangRefactoring {
+
+class SourceLocations
+{
+public:
+ struct Location
+ {
+ Location(qint64 sourceId, qint64 line, qint64 column)
+ : sourceId(sourceId), line(line), column(column)
+ {}
+
+ qint64 sourceId;
+ qint64 line;
+ qint64 column;
+ };
+
+ struct Source
+ {
+ Source(qint64 sourceId, Utils::PathString &&sourcePath)
+ : sourceId(sourceId), sourcePath(std::move(sourcePath))
+ {}
+
+ qint64 sourceId;
+ Utils::PathString sourcePath;
+ };
+
+ std::vector<Location> locations;
+ std::unordered_map<qint64, Utils::PathString> sources;
+};
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/symbolquery.cpp b/src/plugins/clangrefactoring/symbolquery.cpp
new file mode 100644
index 0000000000..a5f946266f
--- /dev/null
+++ b/src/plugins/clangrefactoring/symbolquery.cpp
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "symbolquery.h"
+
+namespace ClangRefactoring {
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangrefactoring/symbolquery.h b/src/plugins/clangrefactoring/symbolquery.h
new file mode 100644
index 0000000000..19faf97229
--- /dev/null
+++ b/src/plugins/clangrefactoring/symbolquery.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utils/smallstring.h>
+
+#include <sourcelocations.h>
+
+#include <algorithm>
+
+namespace ClangRefactoring {
+
+template <typename StatementFactory>
+class SymbolQuery
+{
+ using ReadStatement = typename StatementFactory::ReadStatementType;
+
+public:
+ using Location = SourceLocations::Location;
+ using Source = SourceLocations::Source;
+
+ SymbolQuery(StatementFactory &statementFactory)
+ : m_statementFactory(statementFactory)
+ {}
+
+ SourceLocations locationsAt(const Utils::PathString &filePath, uint line, uint utf8Column)
+ {
+ ReadStatement &locationsStatement = m_statementFactory.selectLocationsForSymbolLocation;
+
+ const std::size_t reserveSize = 128;
+
+ auto locations = locationsStatement.template values<Location, 3>(
+ reserveSize,
+ filePath,
+ line,
+ utf8Column);
+
+ const std::vector<qint64> sourceIds = uniqueSourceIds(locations);
+
+ ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId;
+
+ auto sources = sourcesStatement.template values<Source, 2>(
+ reserveSize,
+ sourceIds);
+
+ return {locations, sourcesToHashMap(sources)};
+ }
+
+ static
+ qint64 sourceId(const Location &location)
+ {
+ return location.sourceId;
+ }
+
+ static
+ std::vector<qint64> uniqueSourceIds(const std::vector<Location> &locations)
+ {
+ std::vector<qint64> ids;
+ ids.reserve(locations.size());
+
+ std::transform(locations.begin(),
+ locations.end(),
+ std::back_inserter(ids),
+ sourceId);
+
+ auto newEnd = std::unique(ids.begin(), ids.end());
+ ids.erase(newEnd, ids.end());
+
+ return ids;
+ }
+
+ static
+ std::unordered_map<qint64, Utils::PathString> sourcesToHashMap(const std::vector<Source> &sources)
+ {
+ std::unordered_map<qint64, Utils::PathString> dictonary;
+
+ for (const Source &source : sources)
+ dictonary.emplace(source.sourceId, std::move(source.sourcePath));
+
+ return dictonary;
+ }
+
+private:
+ StatementFactory &m_statementFactory;
+};
+
+} // namespace ClangRefactoring
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp
index e18b9747b8..c67b811f52 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp
@@ -130,21 +130,6 @@ bool ClangStaticAnalyzerPlugin::initialize(const QStringList &arguments, QString
addAutoReleasedObject(new ClangStaticAnalyzerTool);
addAutoReleasedObject(new ClangStaticAnalyzerOptionsPage);
- auto constraint = [](RunConfiguration *runConfiguration) {
- Target *target = runConfiguration->target();
- QTC_ASSERT(target, return false);
-
- Project *project = target->project();
- QTC_ASSERT(project, return false);
-
- const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
- return project->projectLanguages().contains(cxx)
- && ToolChainKitInformation::toolChain(target->kit(), cxx);
- };
-
- RunControl::registerWorker<ClangStaticAnalyzerToolRunner>
- (Constants::CLANGSTATICANALYZER_RUN_MODE, constraint, /*priority*/ -1);
-
return true;
}
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp
index 0cb7c976ee..c9ff00558d 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerpreconfiguredsessiontests.cpp
@@ -167,7 +167,7 @@ static QList<Target *> validTargets(Project *project)
const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
QTC_ASSERT(toolchain, return false);
bool hasClangExecutable;
- clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable);
+ clangExecutableFromSettings(&hasClangExecutable);
if (!hasClangExecutable) {
qWarning("Project \"%s\": Skipping target \"%s\" since no suitable clang was found for the toolchain.",
qPrintable(projectFileName),
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp
index ad6363bc0e..ef1c79b7bb 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp
@@ -35,10 +35,11 @@
#include <clangcodemodel/clangutils.h>
+#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
-#include <cpptools/compileroptionsbuilder.h>
+#include <cpptools/clangcompileroptionsbuilder.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cppprojectfile.h>
#include <cpptools/cpptoolsreuse.h>
@@ -46,8 +47,10 @@
#include <projectexplorer/abi.h>
#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/buildmanager.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorericons.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
@@ -55,6 +58,7 @@
#include <projectexplorer/toolchain.h>
#include <utils/algorithm.h>
+#include <utils/checkablemessagebox.h>
#include <utils/hostosinfo.h>
#include <utils/temporarydirectory.h>
@@ -63,71 +67,74 @@
using namespace CppTools;
using namespace ProjectExplorer;
+using namespace Utils;
static Q_LOGGING_CATEGORY(LOG, "qtc.clangstaticanalyzer.runcontrol")
namespace ClangStaticAnalyzer {
namespace Internal {
-ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runControl)
- : RunWorker(runControl)
+class ProjectBuilder : public RunWorker
{
- setDisplayName("ClangStaticAnalyzerRunner");
- runControl->setDisplayName(tr("Clang Static Analyzer"));
- runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
- setSupportsReRunning(false);
+public:
+ ProjectBuilder(RunControl *runControl, Project *project)
+ : RunWorker(runControl), m_project(project)
+ {
+ setDisplayName("ProjectBuilder");
+ }
- RunConfiguration *runConfiguration = runControl->runConfiguration();
- auto tool = ClangStaticAnalyzerTool::instance();
- tool->stopAction()->disconnect();
- connect(tool->stopAction(), &QAction::triggered, runControl, [&] {
- initiateStop();
- appendMessage(tr("Clang Static Analyzer stopped by user."),
- Utils::NormalMessageFormat);
- });
- tool->handleWorkerStart(this);
-
- ProjectInfo projectInfoBeforeBuild = tool->projectInfoBeforeBuild();
- QTC_ASSERT(projectInfoBeforeBuild.isValid(), return);
-
- QTC_ASSERT(runConfiguration, return);
- Target * const target = runConfiguration->target();
- QTC_ASSERT(target, return);
- Project * const project = target->project();
- QTC_ASSERT(project, return);
-
- // so pass on the updated Project Info unless no configuration change
- // (defines/includes/files) happened.
- const CppTools::ProjectInfo projectInfoAfterBuild
- = CppTools::CppModelManager::instance()->projectInfo(project);
-
- if (projectInfoAfterBuild.configurationOrFilesChanged(projectInfoBeforeBuild)) {
- // If it's more than a release/debug build configuration change, e.g.
- // a version control checkout, files might be not valid C++ anymore
- // or even gone, so better stop here.
+ bool success() const { return m_success; }
- tool->resetCursorAndProjectInfoBeforeBuild();
- reportFailure(tr(
- "The project configuration changed since the start of the Clang Static Analyzer. "
- "Please re-run with current configuration."));
- return;
- }
+private:
+ void start() final
+ {
+ Target *target = m_project->activeTarget();
+ QTC_ASSERT(target, reportFailure(); return);
+
+ BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
+ if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration())
+ buildType = buildConfig->buildType();
+
+ if (buildType == BuildConfiguration::Release) {
+ const QString wrongMode = ClangStaticAnalyzerTool::tr("Release");
+ const QString toolName = ClangStaticAnalyzerTool::tr("Clang Static Analyzer");
+ const QString title = ClangStaticAnalyzerTool::tr("Run %1 in %2 Mode?").arg(toolName)
+ .arg(wrongMode);
+ const QString message = ClangStaticAnalyzerTool::tr(
+ "<html><head/><body>"
+ "<p>You are trying to run the tool \"%1\" on an application in %2 mode. The tool is "
+ "designed to be used in Debug mode since enabled assertions can reduce the number of "
+ "false positives.</p>"
+ "<p>Do you want to continue and run the tool in %2 mode?</p>"
+ "</body></html>")
+ .arg(toolName).arg(wrongMode);
+ if (CheckableMessageBox::doNotAskAgainQuestion(Core::ICore::mainWindow(),
+ title, message, Core::ICore::settings(),
+ "ClangStaticAnalyzerCorrectModeWarning") != QDialogButtonBox::Yes)
+ {
+ reportFailure();
+ return;
+ }
+ }
- // Some projects provides CompilerCallData once a build is finished,
- QTC_ASSERT(!projectInfoAfterBuild.configurationOrFilesChanged(projectInfoBeforeBuild),
- return);
+ connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
+ this, &ProjectBuilder::onBuildFinished, Qt::QueuedConnection);
- m_projectInfo = projectInfoAfterBuild;
+ ProjectExplorerPlugin::buildProject(m_project);
+ }
- BuildConfiguration *buildConfiguration = target->activeBuildConfiguration();
- QTC_ASSERT(buildConfiguration, return);
- m_environment = buildConfiguration->environment();
+ void onBuildFinished(bool success)
+ {
+ disconnect(BuildManager::instance(), &BuildManager::buildQueueFinished,
+ this, &ProjectBuilder::onBuildFinished);
+ m_success = success;
+ reportDone();
+ }
- ToolChain *toolChain = ToolChainKitInformation::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
- QTC_ASSERT(toolChain, return);
- m_targetTriple = toolChain->originalTargetTriple();
- m_toolChainType = toolChain->typeId();
-}
+private:
+ QPointer<Project> m_project;
+ bool m_success = false;
+};
static void prependWordWidthArgumentIfNotIncluded(QStringList *arguments,
ProjectPart::ToolChainWordWidth wordWidth)
@@ -161,8 +168,7 @@ static void prependTargetTripleIfNotIncludedAndNotEmpty(QStringList *arguments,
}
// Removes (1) inputFile (2) -o <somePath>.
-QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStringList &arguments,
- bool isMsvc)
+QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStringList &arguments)
{
QStringList newArguments;
@@ -174,9 +180,6 @@ QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStri
} else if (argument == QLatin1String("-o")) {
skip = true;
continue;
- } else if (isMsvc && argument == QLatin1String("-target")) {
- skip = true;
- continue;
} else if (QDir::fromNativeSeparators(argument) == inputFile) {
continue; // TODO: Let it in?
}
@@ -188,55 +191,11 @@ QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStri
return newArguments;
}
-static QString createLanguageOptionMsvc(ProjectFile::Kind fileKind)
-{
- switch (fileKind) {
- case ProjectFile::CHeader:
- case ProjectFile::CSource:
- return QLatin1String("/TC");
- break;
- case ProjectFile::CXXHeader:
- case ProjectFile::CXXSource:
- return QLatin1String("/TP");
- break;
- default:
- break;
- }
- return QString();
-}
-
-class ClangStaticAnalyzerOptionsBuilder : public CompilerOptionsBuilder
+class ClangStaticAnalyzerOptionsBuilder final : public ClangCompilerOptionsBuilder
{
public:
- static QStringList build(const CppTools::ProjectPart &projectPart,
- CppTools::ProjectFile::Kind fileKind,
- PchUsage pchUsage)
- {
- ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart);
-
- optionsBuilder.addWordWidth();
- optionsBuilder.addTargetTriple();
- optionsBuilder.addLanguageOption(fileKind);
- optionsBuilder.addOptionsForLanguage(false);
- optionsBuilder.enableExceptions();
-
- optionsBuilder.addDefineFloat128ForMingw();
- optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
- const Core::Id type = projectPart.toolchainType;
- if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
- optionsBuilder.addDefines(projectPart.toolchainDefines);
- optionsBuilder.addDefines(projectPart.projectDefines);
- optionsBuilder.undefineClangVersionMacrosForMsvc();
- optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015();
- optionsBuilder.addHeaderPathOptions();
- optionsBuilder.addPrecompiledHeaderOptions(pchUsage);
- optionsBuilder.addMsvcCompatibilityVersion();
-
- return optionsBuilder.options();
- }
-
ClangStaticAnalyzerOptionsBuilder(const CppTools::ProjectPart &projectPart)
- : CompilerOptionsBuilder(projectPart)
+ : ClangCompilerOptionsBuilder(projectPart)
, m_isMsvcToolchain(m_projectPart.toolchainType
== ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
, m_isMinGWToolchain(m_projectPart.toolchainType
@@ -244,91 +203,28 @@ public:
{
}
-public:
- bool excludeHeaderPath(const QString &headerPath) const override
+ bool excludeHeaderPath(const QString &headerPath) const final
{
- if (CompilerOptionsBuilder::excludeHeaderPath(headerPath))
- return true;
if (m_isMinGWToolchain && headerPath.contains(m_projectPart.toolChainTargetTriple))
return true;
- return false;
+ return ClangCompilerOptionsBuilder::excludeHeaderPath(headerPath);
}
- void undefineClangVersionMacrosForMsvc()
+ void addPredefinedHeaderPathsOptions() final
{
- if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
- static QStringList macroNames {
- "__clang__",
- "__clang_major__",
- "__clang_minor__",
- "__clang_patchlevel__",
- "__clang_version__"
- };
-
- foreach (const QString &macroName, macroNames)
- add(QLatin1String("/U") + macroName);
+ add("-undef");
+ if (m_isMsvcToolchain) {
+ // exclude default clang path to use msvc includes
+ add("-nostdinc");
+ add("-nostdlibinc");
}
}
-private:
- void addTargetTriple() override
- {
- // For MSVC toolchains we use clang-cl.exe, so there is nothing to do here since
- // 1) clang-cl.exe does not understand the "-triple" option
- // 2) clang-cl.exe already hardcodes the right triple value (even if built with mingw)
- if (!m_isMsvcToolchain)
- CompilerOptionsBuilder::addTargetTriple();
- }
-
- void addLanguageOption(ProjectFile::Kind fileKind) override
- {
- if (m_isMsvcToolchain)
- add(createLanguageOptionMsvc(fileKind));
- else
- CompilerOptionsBuilder::addLanguageOption(fileKind);
- }
-
- void addOptionsForLanguage(bool checkForBorlandExtensions) override
- {
- if (m_isMsvcToolchain)
- return;
- CompilerOptionsBuilder::addOptionsForLanguage(checkForBorlandExtensions);
- }
-
- QString includeOption() const override
- {
- if (m_isMsvcToolchain)
- return QLatin1String("/FI");
- return CompilerOptionsBuilder::includeOption();
- }
-
- QString includeDirOption() const override
- {
- if (m_isMsvcToolchain)
- return QLatin1String("/I");
- return CompilerOptionsBuilder::includeDirOption();
- }
-
- QString defineOption() const override
- {
- if (m_isMsvcToolchain)
- return QLatin1String("/D");
- return CompilerOptionsBuilder::defineOption();
- }
+ void addExtraOptions() final {}
- QString undefineOption() const override
+ void addWrappedQtHeadersIncludePath() final
{
- if (m_isMsvcToolchain)
- return QLatin1String("/U");
- return CompilerOptionsBuilder::undefineOption();
- }
-
- void enableExceptions() override
- {
- if (m_isMsvcToolchain)
- add(QLatin1String("/EHsc"));
- else
- CompilerOptionsBuilder::enableExceptions();
+ // Empty, analyzer doesn't need them
}
private:
@@ -383,7 +279,7 @@ static QStringList tweakedArguments(const ProjectPart &projectPart,
{
const bool isMsvc = projectPart.toolchainType
== ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID;
- QStringList newArguments = inputAndOutputArgumentsRemoved(filePath, arguments, isMsvc);
+ QStringList newArguments = inputAndOutputArgumentsRemoved(filePath, arguments);
prependWordWidthArgumentIfNotIncluded(&newArguments, projectPart.toolChainWordWidth);
if (!isMsvc)
prependTargetTripleIfNotIncludedAndNotEmpty(&newArguments, targetTriple);
@@ -434,7 +330,7 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Pt
AnalyzeUnits unitsToAnalyze;
foreach (const ProjectPart::Ptr &projectPart, projectParts) {
- if (!projectPart->selectedForBuilding)
+ if (!projectPart->selectedForBuilding || !projectPart.data())
continue;
foreach (const ProjectFile &file, projectPart->files) {
@@ -445,7 +341,7 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Pt
if (ProjectFile::isSource(file.kind)) {
const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage();
const QStringList arguments
- = ClangStaticAnalyzerOptionsBuilder::build(*projectPart.data(), file.kind, pchUsage);
+ = ClangStaticAnalyzerOptionsBuilder(*projectPart).build(file.kind, pchUsage);
unitsToAnalyze << AnalyzeUnit(file.path, arguments);
}
}
@@ -501,39 +397,54 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
return debug;
}
-static QString executableForVersionCheck(Core::Id toolchainType, const QString &executable)
+ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runControl, Target *target)
+ : RunWorker(runControl), m_target(target)
{
- if (toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
- const QString suffix = QLatin1String("-cl.exe");
- if (executable.endsWith(suffix, Utils::HostOsInfo::fileNameCaseSensitivity())) {
- QString modified = executable;
- modified.chop(suffix.length());
- modified.append(QLatin1String(".exe"));
- return modified;
- }
- }
+ setDisplayName("ClangStaticAnalyzerRunner");
+ setSupportsReRunning(false);
- return executable;
+ m_projectBuilder = new ProjectBuilder(runControl, target->project());
+ addStartDependency(m_projectBuilder);
+
+ m_projectInfoBeforeBuild = CppTools::CppModelManager::instance()->projectInfo(target->project());
+
+ BuildConfiguration *buildConfiguration = target->activeBuildConfiguration();
+ QTC_ASSERT(buildConfiguration, return);
+ m_environment = buildConfiguration->environment();
+
+ ToolChain *toolChain = ToolChainKitInformation::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
+ QTC_ASSERT(toolChain, return);
+ m_targetTriple = toolChain->originalTargetTriple();
+ m_toolChainType = toolChain->typeId();
}
void ClangStaticAnalyzerToolRunner::start()
{
- m_success = false;
- ClangStaticAnalyzerTool::instance()->onEngineIsStarting();
+ m_success = m_projectBuilder->success();
+ if (!m_success) {
+ reportFailure();
+ return;
+ }
- connect(runControl(), &RunControl::stopped, this, [this] {
- ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success);
- });
+ m_projectInfo = CppTools::CppModelManager::instance()->projectInfo(m_target->project());
+
+ // Some projects provides CompilerCallData once a build is finished,
+ if (m_projectInfo.configurationOrFilesChanged(m_projectInfoBeforeBuild)) {
+ // If it's more than a release/debug build configuration change, e.g.
+ // a version control checkout, files might be not valid C++ anymore
+ // or even gone, so better stop here.
+ reportFailure(tr("The project configuration changed since the start of "
+ "the Clang Static Analyzer. Please re-run with current configuration."));
+ return;
+ }
- QTC_ASSERT(m_projectInfo.isValid(), reportFailure(); return);
const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath();
appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()),
Utils::NormalMessageFormat);
// Check clang executable
bool isValidClangExecutable;
- const QString executable = clangExecutableFromSettings(m_toolChainType,
- &isValidClangExecutable);
+ const QString executable = clangExecutableFromSettings(&isValidClangExecutable);
if (!isValidClangExecutable) {
const QString errorMessage = tr("Clang Static Analyzer: Invalid executable \"%1\", stop.")
.arg(executable);
@@ -545,13 +456,12 @@ void ClangStaticAnalyzerToolRunner::start()
}
// Check clang version
- const QString versionCheckExecutable = executableForVersionCheck(m_toolChainType, executable);
- const ClangExecutableVersion version = clangExecutableVersion(versionCheckExecutable);
+ const ClangExecutableVersion version = clangExecutableVersion(executable);
if (!version.isValid()) {
const QString warningMessage
= tr("Clang Static Analyzer: Running with possibly unsupported version, "
"could not determine version from executable \"%1\".")
- .arg(versionCheckExecutable);
+ .arg(executable);
appendMessage(warningMessage, Utils::StdErrFormat);
TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup();
@@ -630,7 +540,7 @@ void ClangStaticAnalyzerToolRunner::stop()
m_runners.clear();
m_unitsToProcess.clear();
m_progress.reportFinished();
- ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success);
+ //ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success);
reportStopped();
}
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h
index e75660287f..16d50f085c 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h
@@ -36,6 +36,7 @@ namespace ClangStaticAnalyzer {
namespace Internal {
class ClangStaticAnalyzerRunner;
+class ProjectBuilder;
class Diagnostic;
struct AnalyzeUnit {
@@ -52,14 +53,15 @@ class ClangStaticAnalyzerToolRunner : public ProjectExplorer::RunWorker
Q_OBJECT
public:
- explicit ClangStaticAnalyzerToolRunner(ProjectExplorer::RunControl *runControl);
-
- void start() override;
- void stop() override;
+ ClangStaticAnalyzerToolRunner(ProjectExplorer::RunControl *runControl,
+ ProjectExplorer::Target *target);
bool success() const { return m_success; } // For testing.
private:
+ void start() final;
+ void stop() final;
+
AnalyzeUnits sortedUnitsToAnalyze();
void analyzeNextFile();
ClangStaticAnalyzerRunner *createRunner();
@@ -74,6 +76,10 @@ private:
void finalize();
private:
+ QPointer<ProjectExplorer::Target> m_target;
+ ProjectBuilder *m_projectBuilder;
+
+ CppTools::ProjectInfo m_projectInfoBeforeBuild;
CppTools::ProjectInfo m_projectInfo;
QString m_targetTriple;
Core::Id m_toolChainType;
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp
index 461f31049b..1f5785f86b 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp
@@ -36,24 +36,19 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
-#include <cpptools/cppmodelmanager.h>
-
#include <debugger/analyzer/analyzermanager.h>
-#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/session.h>
+#include <projectexplorer/projectexplorericons.h>
#include <projectexplorer/target.h>
+#include <projectexplorer/session.h>
-#include <utils/checkablemessagebox.h>
#include <utils/fancymainwindow.h>
#include <utils/utilsicons.h>
#include <QAction>
-#include <QDockWidget>
-#include <QHBoxLayout>
#include <QLabel>
-#include <QListView>
#include <QSortFilterProxyModel>
#include <QToolButton>
@@ -65,21 +60,6 @@ using namespace Utils;
namespace ClangStaticAnalyzer {
namespace Internal {
-class DummyRunConfiguration : public RunConfiguration
-{
- Q_OBJECT
-
-public:
- DummyRunConfiguration(Target *parent)
- : RunConfiguration(parent, "ClangStaticAnalyzer.DummyRunConfig")
- {
- setDefaultDisplayName(tr("Clang Static Analyzer"));
- }
-
-private:
- QWidget *createConfigurationWidget() override { return 0; }
-};
-
static ClangStaticAnalyzerTool *s_instance;
ClangStaticAnalyzerTool::ClangStaticAnalyzerTool()
@@ -178,90 +158,43 @@ ClangStaticAnalyzerTool *ClangStaticAnalyzerTool::instance()
return s_instance;
}
-static bool dontStartAfterHintForDebugMode(Project *project)
+void ClangStaticAnalyzerTool::startTool()
{
- BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
- if (project) {
- if (const Target *target = project->activeTarget()) {
- if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration())
- buildType = buildConfig->buildType();
- }
- }
+ auto runControl = new RunControl(nullptr, Constants::CLANGSTATICANALYZER_RUN_MODE);
+ runControl->setDisplayName(tr("Clang Static Analyzer"));
+ runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
- if (buildType == BuildConfiguration::Release) {
- const QString wrongMode = ClangStaticAnalyzerTool::tr("Release");
- const QString toolName = ClangStaticAnalyzerTool::tr("Clang Static Analyzer");
- const QString title = ClangStaticAnalyzerTool::tr("Run %1 in %2 Mode?").arg(toolName)
- .arg(wrongMode);
- const QString message = ClangStaticAnalyzerTool::tr(
- "<html><head/><body>"
- "<p>You are trying to run the tool \"%1\" on an application in %2 mode. The tool is "
- "designed to be used in Debug mode since enabled assertions can reduce the number of "
- "false positives.</p>"
- "<p>Do you want to continue and run the tool in %2 mode?</p>"
- "</body></html>")
- .arg(toolName).arg(wrongMode);
- if (Utils::CheckableMessageBox::doNotAskAgainQuestion(Core::ICore::mainWindow(),
- title, message, Core::ICore::settings(),
- QLatin1String("ClangStaticAnalyzerCorrectModeWarning")) != QDialogButtonBox::Yes)
- return true;
- }
+ Project *project = SessionManager::startupProject();
+ QTC_ASSERT(project, return);
- return false;
-}
+ auto clangTool = new ClangStaticAnalyzerToolRunner(runControl, project->activeTarget());
-void ClangStaticAnalyzerTool::handleWorkerStart(RunWorker *runWorker)
-{
- RunControl *runControl = runWorker->runControl();
- Project *project = runControl->project();
- QTC_ASSERT(project, emit finished(false); return);
+ m_stopAction->disconnect();
+ connect(m_stopAction, &QAction::triggered, runControl, [runControl] {
+ runControl->appendMessage(tr("Clang Static Analyzer stopped by user."),
+ NormalMessageFormat);
+ runControl->initiateStop();
+ });
+
+ connect(runControl, &RunControl::stopped, this, [this, clangTool] {
+ bool success = clangTool->success();
+ setToolBusy(false);
+ m_running = false;
+ handleStateUpdate();
+ updateRunActions();
+ emit finished(success);
+ });
Debugger::selectPerspective(ClangStaticAnalyzerPerspectiveId);
+
m_diagnosticModel->clear();
- setBusyCursor(true);
+ setToolBusy(true);
m_diagnosticFilterModel->setProject(project);
- m_projectInfoBeforeBuild = CppTools::CppModelManager::instance()->projectInfo(project);
- QTC_ASSERT(m_projectInfoBeforeBuild.isValid(), emit finished(false); return);
m_running = true;
handleStateUpdate();
-
- m_toolBusy = true;
updateRunActions();
-}
-void ClangStaticAnalyzerTool::startTool()
-{
- Project *project = SessionManager::startupProject();
- QTC_ASSERT(project, return);
- Target *target = project->activeTarget();
- QTC_ASSERT(target, return);
- DummyRunConfiguration *& rc = m_runConfigs[target];
- if (!rc) {
- rc = new DummyRunConfiguration(target);
- connect(project, &Project::aboutToRemoveTarget, this,
- [this](Target *t) { m_runConfigs.remove(t); });
- const auto onProjectRemoved = [this](Project *p) {
- foreach (Target * const t, p->targets())
- m_runConfigs.remove(t);
- };
- connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, this,
- onProjectRemoved, Qt::UniqueConnection);
- }
- if (dontStartAfterHintForDebugMode(project))
- return;
-
- ProjectExplorerPlugin::runRunConfiguration(rc, Constants::CLANGSTATICANALYZER_RUN_MODE);
-}
-
-CppTools::ProjectInfo ClangStaticAnalyzerTool::projectInfoBeforeBuild() const
-{
- return m_projectInfoBeforeBuild;
-}
-
-void ClangStaticAnalyzerTool::resetCursorAndProjectInfoBeforeBuild()
-{
- setBusyCursor(false);
- m_projectInfoBeforeBuild = CppTools::ProjectInfo();
+ ProjectExplorerPlugin::startRunControl(runControl);
}
QList<Diagnostic> ClangStaticAnalyzerTool::diagnostics() const
@@ -269,27 +202,12 @@ QList<Diagnostic> ClangStaticAnalyzerTool::diagnostics() const
return m_diagnosticModel->diagnostics();
}
-void ClangStaticAnalyzerTool::onEngineIsStarting()
-{
- QTC_ASSERT(m_diagnosticModel, return);
-}
-
void ClangStaticAnalyzerTool::onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics)
{
QTC_ASSERT(m_diagnosticModel, return);
m_diagnosticModel->addDiagnostics(diagnostics);
}
-void ClangStaticAnalyzerTool::onEngineFinished(bool success)
-{
- resetCursorAndProjectInfoBeforeBuild();
- m_running = false;
- handleStateUpdate();
- emit finished(success);
- m_toolBusy = false;
- updateRunActions();
-}
-
void ClangStaticAnalyzerTool::updateRunActions()
{
if (m_toolBusy) {
@@ -297,19 +215,27 @@ void ClangStaticAnalyzerTool::updateRunActions()
m_startAction->setToolTip(tr("Clang Static Analyzer is still running."));
m_stopAction->setEnabled(true);
} else {
- QString whyNot = tr("Start Clang Static Analyzer.");
- bool canRun = ProjectExplorerPlugin::canRunStartupProject(
- Constants::CLANGSTATICANALYZER_RUN_MODE, &whyNot);
- m_startAction->setToolTip(whyNot);
+ QString toolTip = tr("Start Clang Static Analyzer.");
+ Project *project = SessionManager::startupProject();
+ Target *target = project ? project->activeTarget() : nullptr;
+ const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
+ bool canRun = target && project->projectLanguages().contains(cxx)
+ && ToolChainKitInformation::toolChain(target->kit(), cxx);
+ if (!canRun)
+ toolTip = tr("This is not C++ project");
+
+ m_startAction->setToolTip(toolTip);
m_startAction->setEnabled(canRun);
m_stopAction->setEnabled(false);
}
}
-void ClangStaticAnalyzerTool::setBusyCursor(bool busy)
+
+void ClangStaticAnalyzerTool::setToolBusy(bool busy)
{
QTC_ASSERT(m_diagnosticView, return);
QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
m_diagnosticView->setCursor(cursor);
+ m_toolBusy = busy;
}
void ClangStaticAnalyzerTool::handleStateUpdate()
@@ -324,8 +250,12 @@ void ClangStaticAnalyzerTool::handleStateUpdate()
m_goBack->setEnabled(issuesVisible > 1);
m_goNext->setEnabled(issuesVisible > 1);
- QString message = m_running ? tr("Clang Static Analyzer is running.")
- : tr("Clang Static Analyzer finished.");
+ QString message;
+ if (m_running)
+ message = tr("Clang Static Analyzer is running.");
+ else
+ message = tr("Clang Static Analyzer finished.");
+
message += QLatin1Char(' ');
if (issuesFound == 0) {
message += tr("No issues found.");
@@ -338,5 +268,3 @@ void ClangStaticAnalyzerTool::handleStateUpdate()
} // namespace Internal
} // namespace ClangStaticAnalyzer
-
-#include "clangstaticanalyzertool.moc"
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h
index 06550bce31..334ec07b93 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h
@@ -28,8 +28,6 @@
#include <projectexplorer/runconfiguration.h>
#include <cpptools/projectinfo.h>
-#include <QHash>
-
namespace ClangStaticAnalyzer {
namespace Internal {
@@ -37,7 +35,6 @@ class ClangStaticAnalyzerDiagnosticFilterModel;
class ClangStaticAnalyzerDiagnosticModel;
class ClangStaticAnalyzerDiagnosticView;
class Diagnostic;
-class DummyRunConfiguration;
const char ClangStaticAnalyzerPerspectiveId[] = "ClangStaticAnalyzer.Perspective";
const char ClangStaticAnalyzerDockId[] = "ClangStaticAnalyzer.Dock";
@@ -51,32 +48,21 @@ public:
~ClangStaticAnalyzerTool();
static ClangStaticAnalyzerTool *instance();
- QAction *stopAction() { return m_stopAction; }
-
- CppTools::ProjectInfo projectInfoBeforeBuild() const;
- void resetCursorAndProjectInfoBeforeBuild();
// For testing.
QList<Diagnostic> diagnostics() const;
void startTool();
- void handleWorkerStart(ProjectExplorer::RunWorker *runWorker);
-
- void onEngineIsStarting();
void onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics);
- void onEngineFinished(bool success);
signals:
void finished(bool success); // For testing.
private:
- void setBusyCursor(bool busy);
+ void setToolBusy(bool busy);
void handleStateUpdate();
void updateRunActions();
-private:
- CppTools::ProjectInfo m_projectInfoBeforeBuild;
-
ClangStaticAnalyzerDiagnosticModel *m_diagnosticModel = nullptr;
ClangStaticAnalyzerDiagnosticFilterModel *m_diagnosticFilterModel = nullptr;
ClangStaticAnalyzerDiagnosticView *m_diagnosticView = nullptr;
@@ -85,7 +71,6 @@ private:
QAction *m_stopAction = nullptr;
QAction *m_goBack = nullptr;
QAction *m_goNext = nullptr;
- QHash<ProjectExplorer::Target *, DummyRunConfiguration *> m_runConfigs;
bool m_running = false;
bool m_toolBusy = false;
};
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp
index 2ab8c18d9b..f589a978b3 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp
@@ -58,7 +58,7 @@ void ClangStaticAnalyzerUnitTests::initTestCase()
if (!toolchain)
QSKIP("This test requires that there is a kit with a toolchain.");
bool hasClangExecutable;
- clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable);
+ clangExecutableFromSettings(&hasClangExecutable);
if (!hasClangExecutable)
QSKIP("No clang suitable for analyzing found");
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
index a1a1bee67a..7a433aac49 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
@@ -50,7 +50,7 @@ static bool isFileExecutable(const QString &executablePath)
namespace ClangStaticAnalyzer {
namespace Internal {
-QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid)
+QString clangExecutableFromSettings(bool *isValid)
{
QString executable = ClangStaticAnalyzerSettings::instance()->clangExecutable();
if (executable.isEmpty()) {
@@ -62,14 +62,6 @@ QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid)
const Qt::CaseSensitivity caseSensitivity = Utils::HostOsInfo::fileNameCaseSensitivity();
const bool hasSuffix = executable.endsWith(hostExeSuffix, caseSensitivity);
- if (toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
- if (hasSuffix)
- executable.chop(hostExeSuffix.length());
- executable.append(QLatin1String("-cl"));
- if (hasSuffix)
- executable.append(hostExeSuffix);
- }
-
const QFileInfo fileInfo = QFileInfo(executable);
if (fileInfo.isAbsolute()) {
if (!hasSuffix)
@@ -126,7 +118,9 @@ ClangExecutableVersion clangExecutableVersion(const QString &executable)
Utils::SynchronousProcess runner;
runner.setEnvironment(environment.toStringList());
runner.setTimeoutS(10);
- // We would prefer "-dumpversion", but that one returns some old version number.
+ // We would prefer "-dumpversion", but that one is only there for GCC compatibility
+ // and returns some static/old version.
+ // See also https://bugs.llvm.org/show_bug.cgi?id=28597
const QStringList arguments(QLatin1String(("--version")));
const Utils::SynchronousProcessResponse response = runner.runBlocking(executable, arguments);
if (response.result != Utils::SynchronousProcessResponse::Finished)
diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
index e170d8b7f0..c18317237c 100644
--- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
+++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
@@ -41,7 +41,7 @@ namespace Internal {
bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0);
-QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid);
+QString clangExecutableFromSettings(bool *isValid);
QString createFullLocationString(const Debugger::DiagnosticLocation &location);
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index f4ba55d093..9eea4a6cfb 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -410,7 +410,7 @@ bool ClearCasePlugin::initialize(const QStringList & /*arguments */, QString *er
Context context(CLEARCASE_CONTEXT);
- initializeVcs(new ClearCaseControl(this), context);
+ initializeVcs<ClearCaseControl>(context, this);
m_clearcasePluginInstance = this;
connect(ICore::instance(), &ICore::coreAboutToClose, this, &ClearCasePlugin::closing);
@@ -837,6 +837,11 @@ void ClearCasePlugin::updateActions(VcsBasePlugin::ActionState as)
updateStatusActions();
}
+QString ClearCasePlugin::commitDisplayName() const
+{
+ return tr("check in", "\"commit\" action for ClearCase.");
+}
+
void ClearCasePlugin::checkOutCurrentFile()
{
const VcsBasePluginState state = currentState();
@@ -1206,6 +1211,9 @@ void ClearCasePlugin::startCheckInActivity()
* check in will start. */
void ClearCasePlugin::startCheckIn(const QString &workingDir, const QStringList &files)
{
+ if (!promptBeforeCommit())
+ return;
+
if (raiseSubmitEditor())
return;
@@ -1660,10 +1668,12 @@ bool ClearCasePlugin::vcsCheckIn(const QString &messageFile, const QStringList &
replaceActivity &= (activity != QLatin1String(Constants::KEEP_ACTIVITY));
if (replaceActivity && !vcsSetActivity(m_checkInView, title, activity))
return false;
+ QString message;
QFile msgFile(messageFile);
- msgFile.open(QFile::ReadOnly | QFile::Text);
- QString message = QString::fromLocal8Bit(msgFile.readAll().trimmed().constData());
- msgFile.close();
+ if (msgFile.open(QFile::ReadOnly | QFile::Text)) {
+ message = QString::fromLocal8Bit(msgFile.readAll().trimmed());
+ msgFile.close();
+ }
QStringList args;
args << QLatin1String("checkin");
if (message.isEmpty())
@@ -2315,7 +2325,7 @@ public:
m_editor(0)
{
ClearCasePlugin::instance()->setFakeCleartool(true);
- VcsManager::instance()->clearVersionControlCache();
+ VcsManager::clearVersionControlCache();
FileSaver srcSaver(fileName);
srcSaver.write(QByteArray());
diff --git a/src/plugins/clearcase/clearcaseplugin.h b/src/plugins/clearcase/clearcaseplugin.h
index d2db83a8ac..6aeacf6865 100644
--- a/src/plugins/clearcase/clearcaseplugin.h
+++ b/src/plugins/clearcase/clearcaseplugin.h
@@ -40,8 +40,6 @@
QT_BEGIN_NAMESPACE
class QAction;
-class QComboBox;
-class QDir;
template <typename T>
class QFutureInterface;
class QMutex;
@@ -199,6 +197,7 @@ private:
void syncSlot();
Q_INVOKABLE void updateStatusActions();
+ QString commitDisplayName() const final;
void checkOutCurrentFile();
void addCurrentFile();
void undoCheckOutCurrent();
diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp
index 86d9e0945f..b64898d2b4 100644
--- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp
@@ -44,6 +44,7 @@
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <QDir>
#include <QMessageBox>
#include <QPushButton>
#include <QSet>
@@ -61,10 +62,6 @@ BuildDirManager::BuildDirManager(CMakeBuildConfiguration *bc) :
m_buildConfiguration(bc)
{
QTC_ASSERT(bc, return);
-
- m_reparseTimer.setSingleShot(true);
-
- connect(&m_reparseTimer, &QTimer::timeout, this, &BuildDirManager::parse);
}
BuildDirManager::~BuildDirManager() = default;
@@ -72,12 +69,22 @@ BuildDirManager::~BuildDirManager() = default;
const Utils::FileName BuildDirManager::workDirectory() const
{
const Utils::FileName bdir = m_buildConfiguration->buildDirectory();
- if (bdir.exists())
+ const CMakeTool *cmake = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit());
+ if (bdir.exists()) {
return bdir;
+ } else {
+ if (cmake && cmake->autoCreateBuildDirectory()) {
+ if (!QDir().mkpath(bdir.toString()))
+ emitErrorOccured(tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput()));
+ return bdir;
+ }
+ }
if (!m_tempDir) {
m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX"));
- if (!m_tempDir->isValid())
- emitErrorOccured(tr("Failed to create temporary directory \"%1\".").arg(m_tempDir->path()));
+ if (!m_tempDir->isValid()) {
+ emitErrorOccured(tr("Failed to create temporary directory \"%1\".")
+ .arg(QDir::toNativeSeparators(m_tempDir->path())));
+ }
}
return Utils::FileName::fromString(m_tempDir->path());
}
@@ -198,7 +205,7 @@ void BuildDirManager::maybeForceReparseOnceReaderReady()
// The critical keys *must* be set in cmake configuration, so those were already
// handled above.
if (mustReparse || kcit != targetConfig.constEnd())
- parseOnceReaderReady(true);
+ emit requestReparse(true);
}
bool BuildDirManager::isParsing() const
@@ -221,7 +228,7 @@ void BuildDirManager::becameDirty()
if (!tool->isAutoRun())
return;
- m_reparseTimer.start(1000);
+ emit requestReparse(false);
}
void BuildDirManager::forceReparse()
@@ -261,11 +268,6 @@ void BuildDirManager::resetData()
m_buildTargets.clear();
}
-bool BuildDirManager::updateCMakeStateBeforeBuild()
-{
- return m_reparseTimer.isActive();
-}
-
bool BuildDirManager::persistCMakeState()
{
if (!m_tempDir)
@@ -444,7 +446,7 @@ void BuildDirManager::maybeForceReparse()
return;
if (!m_reader || !m_reader->hasData()) {
- forceReparse();
+ emit requestReparse(true);
return;
}
diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h
index 489ca67ff7..4db167d042 100644
--- a/src/plugins/cmakeprojectmanager/builddirmanager.h
+++ b/src/plugins/cmakeprojectmanager/builddirmanager.h
@@ -67,7 +67,6 @@ public:
void forceReparseWithoutCheckingForChanges();
void maybeForceReparse(); // Only reparse if the configuration has changed...
void resetData();
- bool updateCMakeStateBeforeBuild();
bool persistCMakeState();
void generateProjectTree(CMakeProjectNode *root,
@@ -83,6 +82,7 @@ public:
CMakeBuildConfiguration *buildConfiguration() const { return m_buildConfiguration; }
signals:
+ void requestReparse(bool urgent) const;
void configurationStarted() const;
void dataAvailable() const;
void errorOccured(const QString &err) const;
@@ -109,8 +109,6 @@ private:
mutable std::unique_ptr<Utils::TemporaryDirectory> m_tempDir = nullptr;
mutable CMakeConfig m_cmakeCache;
- QTimer m_reparseTimer;
-
std::unique_ptr<BuildDirReader> m_reader;
mutable QList<CMakeBuildTarget> m_buildTargets;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
index ef828919fa..399438680c 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
@@ -142,19 +142,22 @@ void CMakeBuildConfiguration::ctor()
target()->kit(),
displayName(), BuildConfiguration::Unknown));
+ connect(m_buildDirManager.get(), &BuildDirManager::requestReparse,
+ this, [this](bool urgent) { emit requestReparse(this, urgent); });
connect(m_buildDirManager.get(), &BuildDirManager::dataAvailable,
this, [this, project]() {
- project->updateProjectData(this);
clearError();
- emit dataAvailable();
+ project->handleParsingSuccess(this);
});
connect(m_buildDirManager.get(), &BuildDirManager::errorOccured,
- this, &CMakeBuildConfiguration::setError);
+ this, [this, project](const QString &msg) {
+ setError(msg);
+ project->handleParsingError(this);
+ });
connect(m_buildDirManager.get(), &BuildDirManager::configurationStarted,
- this, [this, project]() {
- project->handleParsingStarted();
+ this, [this]() {
clearError(ForceEnabledChanged::True);
- emit parsingStarted();
+ emit parsingStarted(this);
});
connect(this, &CMakeBuildConfiguration::environmentChanged,
@@ -187,7 +190,7 @@ bool CMakeBuildConfiguration::persistCMakeState()
bool CMakeBuildConfiguration::updateCMakeStateBeforeBuild()
{
- return m_buildDirManager->updateCMakeStateBeforeBuild();
+ return static_cast<CMakeProject *>(project())->mustUpdateCMakeStateBeforeBuild();
}
void CMakeBuildConfiguration::runCMake()
@@ -276,7 +279,7 @@ QList<ConfigModel::DataItem> CMakeBuildConfiguration::completeCMakeConfiguration
return QList<ConfigModel::DataItem>();
return Utils::transform(m_buildDirManager->parsedConfiguration(),
- [this](const CMakeConfigItem &i) {
+ [](const CMakeConfigItem &i) {
ConfigModel::DataItem j;
j.key = QString::fromUtf8(i.key);
j.value = QString::fromUtf8(i.value);
@@ -408,7 +411,7 @@ CMakeConfig CMakeBuildConfiguration::cmakeConfiguration() const
void CMakeBuildConfiguration::setError(const QString &message)
{
- QString oldMessage = m_error;
+ const QString oldMessage = m_error;
if (m_error != message)
m_error = message;
if (oldMessage.isEmpty() && !message.isEmpty())
@@ -525,9 +528,9 @@ QList<ProjectExplorer::BuildInfo *> CMakeBuildConfigurationFactory::availableSet
ProjectExplorer::BuildConfiguration *CMakeBuildConfigurationFactory::create(ProjectExplorer::Target *parent,
const ProjectExplorer::BuildInfo *info) const
{
- QTC_ASSERT(info->factory() == this, return 0);
- QTC_ASSERT(info->kitId == parent->kit()->id(), return 0);
- QTC_ASSERT(!info->displayName.isEmpty(), return 0);
+ QTC_ASSERT(info->factory() == this, return nullptr);
+ QTC_ASSERT(info->kitId == parent->kit()->id(), return nullptr);
+ QTC_ASSERT(!info->displayName.isEmpty(), return nullptr);
CMakeBuildInfo copy(*static_cast<const CMakeBuildInfo *>(info));
CMakeProject *project = static_cast<CMakeProject *>(parent->project());
@@ -568,7 +571,7 @@ bool CMakeBuildConfigurationFactory::canClone(const ProjectExplorer::Target *par
CMakeBuildConfiguration *CMakeBuildConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *source)
{
if (!canClone(parent, source))
- return 0;
+ return nullptr;
auto old = static_cast<CMakeBuildConfiguration *>(source);
return new CMakeBuildConfiguration(parent, old);
}
@@ -583,12 +586,11 @@ bool CMakeBuildConfigurationFactory::canRestore(const ProjectExplorer::Target *p
CMakeBuildConfiguration *CMakeBuildConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map)
{
if (!canRestore(parent, map))
- return 0;
- auto bc = new CMakeBuildConfiguration(parent);
+ return nullptr;
+ auto bc = std::make_unique<CMakeBuildConfiguration>(parent);
if (bc->fromMap(map))
- return bc;
- delete bc;
- return 0;
+ return bc.release();
+ return nullptr;
}
bool CMakeBuildConfigurationFactory::canHandle(const ProjectExplorer::Target *t) const
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
index 1796108574..45a45ede73 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h
@@ -97,12 +97,12 @@ public:
void buildTarget(const QString &buildTarget);
signals:
+ void requestReparse(CMakeBuildConfiguration *, bool isUrgent);
+ void parsingStarted(CMakeBuildConfiguration *);
+
void errorOccured(const QString &message);
void warningOccured(const QString &message);
- void parsingStarted();
- void dataAvailable();
-
protected:
CMakeBuildConfiguration(ProjectExplorer::Target *parent, CMakeBuildConfiguration *source);
bool fromMap(const QVariantMap &map) override;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
index fe85283ad2..8985a0799e 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.cpp
@@ -34,9 +34,11 @@
#include <coreplugin/icore.h>
#include <coreplugin/find/itemviewfind.h>
#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/target.h>
+#include <utils/asconst.h>
#include <utils/detailswidget.h>
#include <utils/fancylineedit.h>
#include <utils/headerviewstretcher.h>
@@ -46,12 +48,14 @@
#include <QBoxLayout>
#include <QCheckBox>
+#include <QComboBox>
#include <QFrame>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QSpacerItem>
+#include <QStyledItemDelegate>
#include <QMenu>
namespace CMakeProjectManager {
@@ -139,26 +143,34 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(tree, &Utils::TreeView::activated,
tree, [tree](const QModelIndex &idx) { tree->edit(idx); });
m_configView = tree;
+
+ m_configView->viewport()->installEventFilter(this);
+
m_configFilterModel->setSourceModel(m_configModel);
- m_configFilterModel->setFilterKeyColumn(2);
- m_configFilterModel->setFilterFixedString(QLatin1String("0"));
+ m_configFilterModel->setFilterKeyColumn(0);
+ m_configFilterModel->setFilterRole(ConfigModel::ItemIsAdvancedRole);
+ m_configFilterModel->setFilterFixedString("0");
+
m_configTextFilterModel->setSourceModel(m_configFilterModel);
+ m_configTextFilterModel->setSortRole(Qt::DisplayRole);
m_configTextFilterModel->setFilterKeyColumn(-1);
m_configTextFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+
m_configView->setModel(m_configTextFilterModel);
m_configView->setMinimumHeight(300);
- m_configView->setRootIsDecorated(false);
m_configView->setUniformRowHeights(true);
+ m_configView->setSortingEnabled(true);
+ m_configView->sortByColumn(0, Qt::AscendingOrder);
auto stretcher = new Utils::HeaderViewStretcher(m_configView->header(), 1);
m_configView->setSelectionMode(QAbstractItemView::SingleSelection);
m_configView->setSelectionBehavior(QAbstractItemView::SelectItems);
m_configView->setFrameShape(QFrame::NoFrame);
- m_configView->hideColumn(2); // Hide isAdvanced column
- m_configView->setItemDelegate(new ConfigModelItemDelegate(m_configView));
+ m_configView->setItemDelegate(new ConfigModelItemDelegate(m_buildConfiguration->project()->projectDirectory(),
+ m_configView));
QFrame *findWrapper = Core::ItemViewFind::createSearchableWrapper(m_configView, Core::ItemViewFind::LightColored);
findWrapper->setFrameStyle(QFrame::StyledPanel);
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large, findWrapper);
+ m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large, findWrapper);
m_progressIndicator->attachToWidget(findWrapper);
m_progressIndicator->raise();
m_progressIndicator->hide();
@@ -195,6 +207,9 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
mainLayout->addLayout(buttonLayout, row, 2);
+ connect(m_configView->selectionModel(), &QItemSelectionModel::currentChanged,
+ this, &CMakeBuildSettingsWidget::updateSelection);
+
++row;
m_reconfigureButton = new QPushButton(tr("Apply Configuration Changes"));
m_reconfigureButton->setEnabled(false);
@@ -204,21 +219,24 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
setError(bc->error());
setWarning(bc->warning());
- connect(project, &CMakeProject::parsingStarted, this, [this]() {
+ connect(project, &ProjectExplorer::Project::parsingStarted, this, [this]() {
updateButtonState();
m_showProgressTimer.start();
});
if (m_buildConfiguration->isParsing())
m_showProgressTimer.start();
- else
+ else {
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
+ m_configView->expandAll();
+ }
- connect(m_buildConfiguration, &CMakeBuildConfiguration::dataAvailable,
+ connect(m_buildConfiguration->target()->project(), &ProjectExplorer::Project::parsingFinished,
this, [this, buildDirChooser, stretcher]() {
- updateButtonState();
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
+ m_configView->expandAll();
stretcher->stretch();
+ updateButtonState();
buildDirChooser->triggerChanged(); // refresh valid state...
m_showProgressTimer.stop();
m_progressIndicator->hide();
@@ -228,6 +246,10 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_showProgressTimer.stop();
m_progressIndicator->hide();
});
+ connect(m_configTextFilterModel, &QAbstractItemModel::modelReset, this, [this, stretcher]() {
+ m_configView->expandAll();
+ stretcher->stretch();
+ });
connect(m_configModel, &QAbstractItemModel::dataChanged,
this, &CMakeBuildSettingsWidget::updateButtonState);
@@ -311,8 +333,15 @@ void CMakeBuildSettingsWidget::updateButtonState()
void CMakeBuildSettingsWidget::updateAdvancedCheckBox()
{
- // Switch between Qt::DisplayRole (everything is "0") and Qt::EditRole (advanced is "1").
- m_configFilterModel->setFilterRole(m_showAdvancedCheckBox->isChecked() ? Qt::EditRole : Qt::DisplayRole);
+ if (m_showAdvancedCheckBox->isChecked()) {
+ m_configFilterModel->setSourceModel(nullptr);
+ m_configTextFilterModel->setSourceModel(m_configModel);
+
+ } else {
+ m_configTextFilterModel->setSourceModel(nullptr);
+ m_configFilterModel->setSourceModel(m_configModel);
+ m_configTextFilterModel->setSourceModel(m_configFilterModel);
+ }
}
void CMakeBuildSettingsWidget::updateFromKit()
@@ -327,5 +356,84 @@ void CMakeBuildSettingsWidget::updateFromKit()
m_configModel->setKitConfiguration(configHash);
}
+static QModelIndex mapToSource(const QAbstractItemView *view, const QModelIndex &idx)
+{
+ if (!idx.isValid())
+ return idx;
+
+ QAbstractItemModel *model = view->model();
+ QModelIndex result = idx;
+ while (QSortFilterProxyModel *proxy = qobject_cast<QSortFilterProxyModel *>(model)) {
+ result = proxy->mapToSource(result);
+ model = proxy->sourceModel();
+ }
+ return result;
+}
+
+void CMakeBuildSettingsWidget::updateSelection(const QModelIndex &current, const QModelIndex &previous)
+{
+ Q_UNUSED(previous);
+ const QModelIndex currentModelIndex = mapToSource(m_configView, current);
+ if (currentModelIndex.isValid())
+ m_editButton->setEnabled(currentModelIndex.flags().testFlag(Qt::ItemIsEditable));
+}
+
+QAction *CMakeBuildSettingsWidget::createForceAction(int type, const QModelIndex &idx)
+{
+ ConfigModel::DataItem::Type t = static_cast<ConfigModel::DataItem::Type>(type);
+ QString typeString;
+ switch (type) {
+ case ConfigModel::DataItem::BOOLEAN:
+ typeString = tr("bool", "display string for cmake type BOOLEAN");
+ break;
+ case ConfigModel::DataItem::FILE:
+ typeString = tr("file", "display string for cmake type FILE");
+ break;
+ case ConfigModel::DataItem::DIRECTORY:
+ typeString = tr("directory", "display string for cmake type DIRECTORY");
+ break;
+ case ConfigModel::DataItem::STRING:
+ typeString = tr("string", "display string for cmake type STRING");
+ break;
+ case ConfigModel::DataItem::UNKNOWN:
+ return nullptr;
+ }
+ QAction *forceAction = new QAction(tr("Force to %1").arg(typeString), nullptr);
+ forceAction->setEnabled(m_configModel->canForceTo(idx, t));
+ connect(forceAction, &QAction::triggered,
+ this, [this, idx, t]() { m_configModel->forceTo(idx, t); });
+ return forceAction;
+}
+
+bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event)
+{
+ // handle context menu events:
+ if (target != m_configView->viewport() || event->type() != QEvent::ContextMenu)
+ return false;
+
+ auto e = static_cast<QContextMenuEvent *>(event);
+ const QModelIndex idx = mapToSource(m_configView, m_configView->indexAt(e->pos()));
+ if (!idx.isValid())
+ return false;
+
+ QMenu *menu = new QMenu(this);
+ connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater);
+
+ QAction *action = nullptr;
+ if ((action = createForceAction(ConfigModel::DataItem::BOOLEAN, idx)))
+ menu->addAction(action);
+ if ((action = createForceAction(ConfigModel::DataItem::FILE, idx)))
+ menu->addAction(action);
+ if ((action = createForceAction(ConfigModel::DataItem::DIRECTORY, idx)))
+ menu->addAction(action);
+ if ((action = createForceAction(ConfigModel::DataItem::STRING, idx)))
+ menu->addAction(action);
+
+ menu->move(e->globalPos());
+ menu->show();
+
+ return true;
+}
+
} // namespace Internal
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h
index e76a2a6bbf..e6e4b1e21c 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildsettingswidget.h
@@ -64,6 +64,11 @@ private:
void updateAdvancedCheckBox();
void updateFromKit();
+ void updateSelection(const QModelIndex &current, const QModelIndex &previous);
+ QAction *createForceAction(int type, const QModelIndex &idx);
+
+ bool eventFilter(QObject *target, QEvent *event);
+
CMakeBuildConfiguration *m_buildConfiguration;
QTreeView *m_configView;
ConfigModel *m_configModel;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
index ff2a3d2c9a..d512c5138b 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
@@ -71,7 +71,7 @@ const char ADD_RUNCONFIGURATION_TEXT[] = "Current executable";
static bool isCurrentExecutableTarget(const QString &target)
{
- return target == QLatin1String(ADD_RUNCONFIGURATION_TEXT);
+ return target == ADD_RUNCONFIGURATION_TEXT;
}
CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl) :
@@ -95,9 +95,9 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, CMakeBuildStep *bs) :
void CMakeBuildStep::ctor(BuildStepList *bsl)
{
- m_percentProgress = QRegExp(QLatin1String("^\\[\\s*(\\d*)%\\]"));
- m_ninjaProgress = QRegExp(QLatin1String("^\\[\\s*(\\d*)/\\s*(\\d*)"));
- m_ninjaProgressString = QLatin1String("[%f/%t "); // ninja: [33/100
+ m_percentProgress = QRegExp("^\\[\\s*(\\d*)%\\]");
+ m_ninjaProgress = QRegExp("^\\[\\s*(\\d*)/\\s*(\\d*)");
+ m_ninjaProgressString = "[%f/%t "; // ninja: [33/100
//: Default display name for the cmake make step.
setDefaultDisplayName(tr("CMake Build"));
@@ -119,7 +119,8 @@ void CMakeBuildStep::ctor(BuildStepList *bsl)
}
connect(target(), &Target::kitChanged, this, &CMakeBuildStep::cmakeCommandChanged);
- connect(bc, &CMakeBuildConfiguration::dataAvailable, this, &CMakeBuildStep::handleBuildTargetChanges);
+ connect(project(), &Project::parsingFinished,
+ this, &CMakeBuildStep::handleBuildTargetChanges);
}
CMakeBuildConfiguration *CMakeBuildStep::cmakeBuildConfiguration() const
@@ -150,23 +151,23 @@ QVariantMap CMakeBuildStep::toMap() const
{
QVariantMap map(AbstractProcessStep::toMap());
// Use QStringList for compatibility with old files
- map.insert(QLatin1String(BUILD_TARGETS_KEY), QStringList(m_buildTarget));
- map.insert(QLatin1String(TOOL_ARGUMENTS_KEY), m_toolArguments);
+ map.insert(BUILD_TARGETS_KEY, QStringList(m_buildTarget));
+ map.insert(TOOL_ARGUMENTS_KEY, m_toolArguments);
return map;
}
bool CMakeBuildStep::fromMap(const QVariantMap &map)
{
- if (map.value(QLatin1String(CLEAN_KEY), false).toBool()) {
+ if (map.value(CLEAN_KEY, false).toBool()) {
m_buildTarget = CMakeBuildStep::cleanTarget();
} else {
- const QStringList targetList = map.value(QLatin1String(BUILD_TARGETS_KEY)).toStringList();
+ const QStringList targetList = map.value(BUILD_TARGETS_KEY).toStringList();
if (!targetList.isEmpty())
m_buildTarget = targetList.last();
- m_toolArguments = map.value(QLatin1String(TOOL_ARGUMENTS_KEY)).toString();
+ m_toolArguments = map.value(TOOL_ARGUMENTS_KEY).toString();
}
- if (map.value(QLatin1String(ADD_RUNCONFIGURATION_ARGUMENT_KEY), false).toBool())
- m_buildTarget = QLatin1String(ADD_RUNCONFIGURATION_TEXT);
+ if (map.value(ADD_RUNCONFIGURATION_ARGUMENT_KEY, false).toBool())
+ m_buildTarget = ADD_RUNCONFIGURATION_TEXT;
return BuildStep::fromMap(map);
}
@@ -193,8 +194,8 @@ bool CMakeBuildStep::init(QList<const BuildStep *> &earlierSteps)
CMakeTool *tool = CMakeKitInformation::cmakeTool(target()->kit());
if (!tool || !tool->isValid()) {
emit addTask(Task(Task::Error,
- tr("Qt Creator needs a CMake Tool set up to build. "
- "Configure a CMake Tool in the kit options."),
+ tr("A CMake tool must be set up for building. "
+ "Configure a CMake tool in the kit options."),
Utils::FileName(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
canInit = false;
@@ -241,8 +242,8 @@ bool CMakeBuildStep::init(QList<const BuildStep *> &earlierSteps)
pp->setMacroExpander(bc->macroExpander());
Utils::Environment env = bc->environment();
Utils::Environment::setupEnglishOutput(&env);
- if (!env.value(QLatin1String("NINJA_STATUS")).startsWith(m_ninjaProgressString))
- env.set(QLatin1String("NINJA_STATUS"), m_ninjaProgressString + QLatin1String("%o/sec] "));
+ if (!env.value("NINJA_STATUS").startsWith(m_ninjaProgressString))
+ env.set("NINJA_STATUS", m_ninjaProgressString + "%o/sec] ");
pp->setEnvironment(env);
pp->setWorkingDirectory(bc->buildDirectory().toString());
pp->setCommand(cmakeCommand());
@@ -279,10 +280,8 @@ void CMakeBuildStep::run(QFutureInterface<bool> &fi)
}
if (mustDelay) {
- m_runTrigger = connect(bc, &CMakeBuildConfiguration::dataAvailable,
- this, [this, &fi]() { runImpl(fi); });
- m_errorTrigger = connect(bc, &CMakeBuildConfiguration::errorOccured,
- this, [this, &fi](const QString& em) { handleCMakeError(fi, em); });
+ m_runTrigger = connect(project(), &Project::parsingFinished,
+ this, [this, &fi](bool success) { handleProjectWasParsed(fi, success); });
} else {
runImpl(fi);
}
@@ -291,21 +290,18 @@ void CMakeBuildStep::run(QFutureInterface<bool> &fi)
void CMakeBuildStep::runImpl(QFutureInterface<bool> &fi)
{
// Do the actual build:
- disconnectTriggers();
AbstractProcessStep::run(fi);
}
-void CMakeBuildStep::handleCMakeError(QFutureInterface<bool> &fi, const QString& errorMessage)
-{
- disconnectTriggers();
- AbstractProcessStep::stdError(tr("Error parsing CMake: %1\n").arg(errorMessage));
- reportRunResult(fi, false);
-}
-
-void CMakeBuildStep::disconnectTriggers()
+void CMakeBuildStep::handleProjectWasParsed(QFutureInterface<bool> &fi, bool success)
{
disconnect(m_runTrigger);
- disconnect(m_errorTrigger);
+ if (success) {
+ runImpl(fi);
+ } else {
+ AbstractProcessStep::stdError(tr("Project did not parse successfully, can not build."));
+ reportRunResult(fi, false);
+ }
}
BuildStepConfigWidget *CMakeBuildStep::createConfigWidget()
@@ -384,8 +380,8 @@ QString CMakeBuildStep::allArguments(const CMakeRunConfiguration *rc) const
{
QString arguments;
- Utils::QtcProcess::addArg(&arguments, QLatin1String("--build"));
- Utils::QtcProcess::addArg(&arguments, QLatin1String("."));
+ Utils::QtcProcess::addArg(&arguments, "--build");
+ Utils::QtcProcess::addArg(&arguments, ".");
QString target;
@@ -393,17 +389,17 @@ QString CMakeBuildStep::allArguments(const CMakeRunConfiguration *rc) const
if (rc)
target = rc->buildSystemTarget();
else
- target = QLatin1String("<i>&lt;") + tr(ADD_RUNCONFIGURATION_TEXT) + QLatin1String("&gt;</i>");
+ target = "<i>&lt;" + tr(ADD_RUNCONFIGURATION_TEXT) + "&gt;</i>";
} else {
target = m_buildTarget;
}
- Utils::QtcProcess::addArg(&arguments, QLatin1String("--target"));
+ Utils::QtcProcess::addArg(&arguments, "--target");
Utils::QtcProcess::addArg(&arguments, target);
if (!m_toolArguments.isEmpty()) {
- Utils::QtcProcess::addArg(&arguments, QLatin1String("--"));
- arguments += QLatin1Char(' ') + m_toolArguments;
+ Utils::QtcProcess::addArg(&arguments, "--");
+ arguments += ' ' + m_toolArguments;
}
return arguments;
@@ -479,8 +475,15 @@ CMakeBuildStepConfigWidget::CMakeBuildStepConfigWidget(CMakeBuildStep *buildStep
connect(m_buildStep, &CMakeBuildStep::buildTargetsChanged, this, &CMakeBuildStepConfigWidget::buildTargetsChanged);
connect(m_buildStep, &CMakeBuildStep::targetToBuildChanged, this, &CMakeBuildStepConfigWidget::selectedBuildTargetsChanged);
- connect(static_cast<CMakeProject *>(m_buildStep->project()), &CMakeProject::environmentChanged,
- this, &CMakeBuildStepConfigWidget::updateDetails);
+ m_buildStep->project()->subscribeSignal(&BuildConfiguration::environmentChanged, this, [this]() {
+ if (static_cast<BuildConfiguration *>(sender())->isActive())
+ updateDetails();
+ });
+ connect(m_buildStep->project(), &Project::activeProjectConfigurationChanged,
+ this, [this](ProjectConfiguration *pc) {
+ if (pc && pc->isActive())
+ updateDetails();
+ });
}
void CMakeBuildStepConfigWidget::toolArgumentsEdited()
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
index 08cee9a01c..754aae52cb 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
@@ -104,14 +104,12 @@ private:
void ctor(ProjectExplorer::BuildStepList *bsl);
void runImpl(QFutureInterface<bool> &fi);
- void handleCMakeError(QFutureInterface<bool> &fi, const QString& errorMessage);
- void disconnectTriggers();
+ void handleProjectWasParsed(QFutureInterface<bool> &fi, bool success);
void handleBuildTargetChanges();
CMakeRunConfiguration *targetsActiveRunConfiguration() const;
QMetaObject::Connection m_runTrigger;
- QMetaObject::Connection m_errorTrigger;
QRegExp m_percentProgress;
QRegExp m_ninjaProgress;
diff --git a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp
index 591768f515..96cf7d138d 100644
--- a/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakecbpparser.cpp
@@ -30,6 +30,7 @@
#include <utils/fileutils.h>
#include <utils/stringutils.h>
#include <utils/algorithm.h>
+#include <projectexplorer/projectmacro.h>
#include <projectexplorer/projectnodes.h>
#include <QLoggingCategory>
@@ -71,8 +72,9 @@ void CMakeCbpParser::sortFiles()
qCDebug(log) << "# Pre Dump #";
qCDebug(log) << "###############";
foreach (const CMakeBuildTarget &target, m_buildTargets)
- qCDebug(log) << target.title << target.sourceDirectory <<
- target.includeFiles << target.defines << target.files << "\n";
+ qCDebug(log) << target.title << target.sourceDirectory << target.includeFiles
+ << ProjectExplorer::Macro::toByteArray(target.macros)
+ << target.files << "\n";
// find a good build target to fall back
int fallbackIndex = 0;
@@ -153,7 +155,9 @@ void CMakeCbpParser::sortFiles()
qCDebug(log) << "# After Dump #";
qCDebug(log) << "###############";
foreach (const CMakeBuildTarget &target, m_buildTargets)
- qCDebug(log) << target.title << target.sourceDirectory << target.includeFiles << target.defines << target.files << "\n";
+ qCDebug(log) << target.title << target.sourceDirectory << target.includeFiles
+ << ProjectExplorer::Macro::toByteArray(target.macros)
+ << target.files << "\n";
}
bool CMakeCbpParser::parseCbpFile(CMakeTool::PathMapper mapper, const FileName &fileName,
@@ -397,12 +401,8 @@ void CMakeCbpParser::parseAdd()
m_buildTarget.compilerOptions.append(compilerOption);
int macroNameIndex = compilerOption.indexOf("-D") + 2;
if (macroNameIndex != 1) {
- int assignIndex = compilerOption.indexOf('=', macroNameIndex);
- if (assignIndex != -1)
- compilerOption[assignIndex] = ' ';
- m_buildTarget.defines.append("#define ");
- m_buildTarget.defines.append(compilerOption.mid(macroNameIndex).toUtf8());
- m_buildTarget.defines.append('\n');
+ const QString keyValue = compilerOption.mid(macroNameIndex);
+ m_buildTarget.macros.append(ProjectExplorer::Macro::fromKeyValue(keyValue));
}
}
diff --git a/src/plugins/cmakeprojectmanager/cmakecbpparser.h b/src/plugins/cmakeprojectmanager/cmakecbpparser.h
index 6069b7d1ad..d1f5cf9569 100644
--- a/src/plugins/cmakeprojectmanager/cmakecbpparser.h
+++ b/src/plugins/cmakeprojectmanager/cmakecbpparser.h
@@ -38,7 +38,6 @@
namespace ProjectExplorer {
class FileNode;
-class Kit;
} // namespace ProjectExplorer
namespace CMakeProjectManager {
diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.h b/src/plugins/cmakeprojectmanager/cmakeeditor.h
index 7d5bda378c..93151db547 100644
--- a/src/plugins/cmakeprojectmanager/cmakeeditor.h
+++ b/src/plugins/cmakeprojectmanager/cmakeeditor.h
@@ -32,7 +32,6 @@ namespace CMakeProjectManager {
namespace Internal {
class CMakeEditorWidget;
-class CMakeSettingsPage;
class CMakeEditor : public TextEditor::BaseTextEditor
{
diff --git a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h
index 934d7b64e8..387addeac1 100644
--- a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h
+++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h
@@ -31,7 +31,6 @@
namespace CMakeProjectManager {
namespace Internal {
-class CMakeSettingsPage;
class CMakeFileCompletionAssist : public TextEditor::KeywordsCompletionAssistProcessor
{
diff --git a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp
index f0be80b42e..47eeef30a8 100644
--- a/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakekitconfigwidget.cpp
@@ -334,7 +334,7 @@ void CMakeGeneratorKitConfigWidget::changeGenerator()
for (auto it = generatorList.constBegin(); it != generatorList.constEnd(); ++it)
generatorCombo->addItem(it->name);
- auto updateDialog = [this, &generatorList, generatorCombo, extraGeneratorCombo,
+ auto updateDialog = [&generatorList, generatorCombo, extraGeneratorCombo,
platformEdit, toolsetEdit](const QString &name) {
auto it = std::find_if(generatorList.constBegin(), generatorList.constEnd(),
[name](const CMakeTool::Generator &g) { return g.name == name; });
diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
index 9e5962d3ae..3a52d6911c 100644
--- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp
@@ -29,6 +29,7 @@
#include "cmaketoolmanager.h"
#include "cmaketool.h"
+#include <app/app_version.h>
#include <projectexplorer/task.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/kit.h>
@@ -147,7 +148,7 @@ KitConfigWidget *CMakeKitInformation::createConfigWidget(Kit *k) const
void CMakeKitInformation::addToMacroExpander(Kit *k, Utils::MacroExpander *expander) const
{
expander->registerFileVariables("CMake:Executable", tr("Path to the cmake executable"),
- [this, k]() -> QString {
+ [k]() -> QString {
CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
return tool ? tool->cmakeExecutable().toString() : QString();
});
@@ -383,7 +384,8 @@ QList<Task> CMakeGeneratorKitInformation::validate(const Kit *k) const
if (!tool->hasServerMode() && info.extraGenerator != "CodeBlocks") {
result << Task(Task::Warning, tr("The selected CMake binary has no server-mode and the CMake "
"generator does not generate a CodeBlocks file. "
- "Qt Creator will not be able to parse CMake projects."),
+ "%1 will not be able to parse CMake projects.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME),
Utils::FileName(), -1, Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 988a39652a..2ab0037bd0 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -51,6 +51,7 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <utils/algorithm.h>
+#include <utils/asconst.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/hostosinfo.h>
@@ -76,12 +77,27 @@ using namespace Internal;
CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEMIMETYPE, fileName),
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this))
{
+ m_delayedParsingTimer.setSingleShot(true);
+
+ connect(&m_delayedParsingTimer, &QTimer::timeout,
+ this, [this]() { startParsingProject(PARSE); });
+
setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
setDisplayName(projectDirectory().fileName());
- connect(this, &CMakeProject::activeTargetChanged, this, &CMakeProject::handleActiveTargetChanged);
+ connect(this, &Project::activeProjectConfigurationChanged,
+ this, &CMakeProject::handleActiveProjectConfigurationChanged);
+
+ subscribeSignal(&CMakeBuildConfiguration::requestReparse,
+ this, [this](CMakeBuildConfiguration *bc, bool isUrgent) {
+ if (bc->isActive()) {
+ m_delayedParsingTimer.setInterval(isUrgent ? 0 : 1000);
+ m_delayedParsingTimer.start();
+ }
+ });
+
connect(&m_treeScanner, &TreeScanner::finished, this, &CMakeProject::handleTreeScanningFinished);
m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FileName &fn) {
@@ -116,8 +132,6 @@ CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEM
}
return type;
});
-
- scanProjectTree();
}
CMakeProject::~CMakeProject()
@@ -134,14 +148,11 @@ CMakeProject::~CMakeProject()
void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
{
- QTC_ASSERT(bc, return);
-
- Target *t = activeTarget();
- if (!t || t->activeBuildConfiguration() != bc)
- return;
+ Target *const t = activeTarget();
- if (!m_treeScanner.isFinished() || bc->isParsing())
- return;
+ QTC_ASSERT(bc, return);
+ QTC_ASSERT(bc == (t ? t->activeBuildConfiguration() : nullptr), return);
+ QTC_ASSERT(m_treeScanner.isFinished() && !bc->isParsing(), return);
Kit *k = t->kit();
@@ -189,8 +200,6 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
emit fileListChanged();
emit bc->emitBuildTypeChanged();
-
- emit parsingFinished();
}
void CMakeProject::updateQmlJSCodeModel()
@@ -252,12 +261,49 @@ bool CMakeProject::supportsKit(Kit *k, QString *errorMessage) const
void CMakeProject::runCMake()
{
- CMakeBuildConfiguration *bc = nullptr;
- if (activeTarget())
- bc = qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
+ if (isParsing())
+ return;
- if (bc)
+ startParsingProject(PARSE);
+}
+
+void CMakeProject::runCMakeAndScanProjectTree()
+{
+ if (isParsing())
+ return;
+
+ startParsingProject(static_cast<DataCollectionAction>(PARSE | SCAN));
+}
+
+void CMakeProject::startParsingProject(const CMakeProject::DataCollectionAction action)
+{
+ const bool runParse = action & PARSE;
+ const bool runScan = action & SCAN;
+
+ CMakeBuildConfiguration *bc = activeTarget()
+ ? qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration())
+ : nullptr;
+ if (!bc)
+ return;
+
+ if (!m_treeScanner.isFinished() || m_waitingForScan)
+ return;
+
+ emitParsingStarted();
+
+ m_waitingForParse = runParse;
+ m_waitingForScan = runScan;
+ m_combinedScanAndParseResult = true;
+
+ if (runParse)
bc->runCMake();
+
+ if (runScan) {
+ m_treeScanner.asyncScanForFiles(projectDirectory());
+ Core::ProgressManager::addTask(m_treeScanner.future(),
+ tr("Scan \"%1\" project tree").arg(displayName()),
+ "CMake.Scan.Tree");
+ }
}
void CMakeProject::buildCMakeTarget(const QString &buildTarget)
@@ -319,75 +365,84 @@ bool CMakeProject::setupTarget(Target *t)
return true;
}
-void CMakeProject::scanProjectTree()
+void CMakeProject::handleActiveProjectConfigurationChanged(ProjectConfiguration *pc)
{
- if (!m_treeScanner.isFinished())
+ if (auto bc = qobject_cast<CMakeBuildConfiguration *>(pc)) {
+ if (!bc->isActive())
+ return;
+ } else if (!qobject_cast<Target *>(pc)) {
return;
- m_treeScanner.asyncScanForFiles(projectDirectory());
- Core::ProgressManager::addTask(m_treeScanner.future(),
- tr("Scan \"%1\" project tree").arg(displayName()),
- "CMake.Scan.Tree");
+ }
+
+ for (Target *t : targets()) {
+ for (BuildConfiguration *bc : t->buildConfigurations()) {
+ auto i = qobject_cast<CMakeBuildConfiguration *>(bc);
+ QTC_ASSERT(i, continue);
+ if (i->isActive()) {
+ m_waitingForParse = true;
+ i->maybeForceReparse();
+ } else {
+ i->resetData();
+ }
+ }
+ }
}
-void CMakeProject::handleActiveTargetChanged()
+void CMakeProject::handleTreeScanningFinished()
{
- if (m_connectedTarget) {
- disconnect(m_connectedTarget, &Target::activeBuildConfigurationChanged,
- this, &CMakeProject::handleActiveBuildConfigurationChanged);
- disconnect(m_connectedTarget, &Target::kitChanged,
- this, &CMakeProject::handleActiveBuildConfigurationChanged);
- }
+ QTC_CHECK(m_waitingForScan);
+
+ qDeleteAll(m_allFiles);
+ m_allFiles = Utils::transform(m_treeScanner.release(), [](const FileNode *fn) { return fn; });
- m_connectedTarget = activeTarget();
+ auto t = activeTarget();
+ auto bc = qobject_cast<CMakeBuildConfiguration*>(t ? t->activeBuildConfiguration() : nullptr);
+ QTC_ASSERT(bc, return);
- if (m_connectedTarget) {
- connect(m_connectedTarget, &Target::activeBuildConfigurationChanged,
- this, &CMakeProject::handleActiveBuildConfigurationChanged);
- connect(m_connectedTarget, &Target::kitChanged,
- this, &CMakeProject::handleActiveBuildConfigurationChanged);
- }
+ m_combinedScanAndParseResult = m_combinedScanAndParseResult && true;
+ m_waitingForScan = false;
- handleActiveBuildConfigurationChanged();
+ combineScanAndParse(bc);
}
-void CMakeProject::handleActiveBuildConfigurationChanged()
+void CMakeProject::handleParsingSuccess(CMakeBuildConfiguration *bc)
{
- if (!activeTarget() || !activeTarget()->activeBuildConfiguration())
+ QTC_CHECK(m_waitingForParse);
+
+ if (!bc || !bc->isActive())
return;
- auto activeBc = qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
- foreach (Target *t, targets()) {
- foreach (BuildConfiguration *bc, t->buildConfigurations()) {
- auto i = qobject_cast<CMakeBuildConfiguration *>(bc);
- QTC_ASSERT(i, continue);
- if (i == activeBc)
- i->maybeForceReparse();
- else
- i->resetData();
- }
- }
+ m_waitingForParse = false;
+ m_combinedScanAndParseResult = m_combinedScanAndParseResult && true;
+
+ combineScanAndParse(bc);
}
-void CMakeProject::handleParsingStarted()
+void CMakeProject::handleParsingError(CMakeBuildConfiguration *bc)
{
- if (activeTarget() && activeTarget()->activeBuildConfiguration() == sender())
- emit parsingStarted();
+ QTC_CHECK(m_waitingForParse);
+
+ if (!bc || !bc->isActive())
+ return;
+
+ m_waitingForParse = false;
+ m_combinedScanAndParseResult = false;
+
+ combineScanAndParse(bc);
}
-void CMakeProject::handleTreeScanningFinished()
+
+void CMakeProject::combineScanAndParse(CMakeBuildConfiguration *bc)
{
- qDeleteAll(m_allFiles);
- m_allFiles = Utils::transform(m_treeScanner.release(), [](const FileNode *fn) { return fn; });
+ QTC_ASSERT(bc && bc->isActive(), return);
- auto t = activeTarget();
- if (!t)
+ if (m_waitingForParse || m_waitingForScan)
return;
- auto bc = qobject_cast<CMakeBuildConfiguration*>(t->activeBuildConfiguration());
- if (!bc)
- return;
+ if (m_combinedScanAndParseResult)
+ updateProjectData(bc);
- updateProjectData(bc);
+ emitParsingFinished(m_combinedScanAndParseResult);
}
CMakeBuildTarget CMakeProject::buildTargetForTitle(const QString &title)
@@ -455,7 +510,6 @@ void CMakeProject::updateTargetRunConfigurations(Target *t)
continue;
auto btIt = buildTargetHash.constFind(cmakeRc->title());
- cmakeRc->setEnabled(btIt != buildTargetHash.constEnd());
if (btIt != buildTargetHash.constEnd()) {
cmakeRc->setExecutable(btIt.value()->executable.toString());
cmakeRc->setBaseWorkingDirectory(btIt.value()->workingDirectory);
@@ -529,6 +583,11 @@ void CMakeProject::updateApplicationAndDeploymentTargets()
t->setDeploymentData(deploymentData);
}
+bool CMakeProject::mustUpdateCMakeStateBeforeBuild()
+{
+ return m_delayedParsingTimer.isActive();
+}
+
void CMakeProject::createGeneratedCodeModelSupport()
{
qDeleteAll(m_extraCompilers);
@@ -577,7 +636,7 @@ void CMakeBuildTarget::clear()
targetType = UtilityType;
includeFiles.clear();
compilerOptions.clear();
- defines.clear();
+ macros.clear();
files.clear();
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index 2b20a7479c..40d3382a64 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -30,19 +30,17 @@
#include "treescanner.h"
#include <projectexplorer/extracompiler.h>
+#include <projectexplorer/projectmacro.h>
#include <projectexplorer/project.h>
#include <utils/fileutils.h>
#include <QFuture>
#include <QHash>
+#include <QTimer>
#include <memory>
-QT_BEGIN_NAMESPACE
-class QFileSystemWatcher;
-QT_END_NAMESPACE
-
namespace CppTools { class CppProjectUpdater; }
namespace CMakeProjectManager {
@@ -72,7 +70,7 @@ public:
// code model
QList<Utils::FileName> includeFiles;
QStringList compilerOptions;
- QByteArray defines;
+ ProjectExplorer::Macros macros;
QList<Utils::FileName> files;
void clear();
@@ -98,17 +96,13 @@ public:
bool supportsKit(ProjectExplorer::Kit *k, QString *errorMessage = 0) const final;
void runCMake();
- void scanProjectTree();
+ void runCMakeAndScanProjectTree();
// Context menu actions:
void buildCMakeTarget(const QString &buildTarget);
ProjectExplorer::ProjectImporter *projectImporter() const final;
-signals:
- /// emitted when cmake is running:
- void parsingStarted();
-
protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final;
bool setupTarget(ProjectExplorer::Target *t) final;
@@ -116,11 +110,15 @@ protected:
private:
QList<CMakeBuildTarget> buildTargets() const;
- void handleActiveTargetChanged();
- void handleActiveBuildConfigurationChanged();
- void handleParsingStarted();
+ enum DataCollectionAction { PARSE = 1, SCAN = 2 };
+ void startParsingProject(const DataCollectionAction a);
+
+ void handleActiveProjectConfigurationChanged(ProjectExplorer::ProjectConfiguration *pc);
void handleTreeScanningFinished();
- void updateProjectData(Internal::CMakeBuildConfiguration *cmakeBc);
+ void handleParsingSuccess(Internal::CMakeBuildConfiguration *bc);
+ void handleParsingError(Internal::CMakeBuildConfiguration *bc);
+ void combineScanAndParse(Internal::CMakeBuildConfiguration *bc);
+ void updateProjectData(Internal::CMakeBuildConfiguration *bc);
void updateQmlJSCodeModel();
void createGeneratedCodeModelSupport();
@@ -128,7 +126,7 @@ private:
void updateTargetRunConfigurations(ProjectExplorer::Target *t);
void updateApplicationAndDeploymentTargets();
- ProjectExplorer::Target *m_connectedTarget = nullptr;
+ bool mustUpdateCMakeStateBeforeBuild();
// TODO probably need a CMake specific node structure
QList<CMakeBuildTarget> m_buildTargets;
@@ -136,10 +134,17 @@ private:
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
Internal::TreeScanner m_treeScanner;
+
+ bool m_waitingForScan = false;
+ bool m_waitingForParse = false;
+ bool m_combinedScanAndParseResult = false;
+
QHash<QString, bool> m_mimeBinaryCache;
QList<const ProjectExplorer::FileNode *> m_allFiles;
mutable std::unique_ptr<Internal::CMakeProjectImporter> m_projectImporter;
+ QTimer m_delayedParsingTimer;
+
friend class Internal::CMakeBuildConfiguration;
friend class Internal::CMakeBuildSettingsWidget;
};
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
index 7464261e8c..420e0d0bd2 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp
@@ -152,6 +152,5 @@ void CMakeManager::rescanProject(Project *project)
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
return;
- cmakeProject->scanProjectTree();
- cmakeProject->runCMake(); // by my experience: every rescan run requires cmake run too
+ cmakeProject->runCMakeAndScanProjectTree();// by my experience: every rescan run requires cmake run too
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
index c1d19514ea..0a045c19c0 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h
@@ -34,7 +34,6 @@ QT_END_NAMESPACE
namespace CMakeProjectManager {
namespace Internal {
-class CMakeSettingsPage;
class CMakeManager : public QObject
{
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
index 654234cbec..fb3c310464 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
@@ -12,6 +12,7 @@ QtcPlugin {
Depends { name: "ProjectExplorer" }
Depends { name: "TextEditor" }
Depends { name: "QtSupport" }
+ Depends { name: "app_version_header" }
pluginRecommends: [
"Designer"
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
index 56e35f019f..ae7afdd393 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
@@ -31,8 +31,6 @@
#include <utils/algorithm.h>
-#include <QApplication>
-
using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal;
@@ -57,13 +55,7 @@ bool CMakeInputsNode::showInSimpleTree() const
CMakeListsNode::CMakeListsNode(const Utils::FileName &cmakeListPath) :
ProjectExplorer::ProjectNode(cmakeListPath)
{
- static QIcon folderIcon;
- if (folderIcon.isNull()) {
- const QIcon overlayIcon(Constants::FILEOVERLAY_CMAKE);
- QPixmap dirPixmap = QApplication::style()->standardIcon(QStyle::SP_DirIcon).pixmap(QSize(16, 16));
-
- folderIcon.addPixmap(Core::FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
- }
+ static QIcon folderIcon = Core::FileIconProvider::directoryIcon(Constants::FILEOVERLAY_CMAKE);
setIcon(folderIcon);
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
index 79a59a528c..4a13231632 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp
@@ -114,8 +114,8 @@ void CMakeProjectPlugin::extensionsInitialized()
void CMakeProjectPlugin::updateContextActions()
{
Project *project = ProjectTree::currentProject();
- Node *node = ProjectTree::currentNode();
- CMakeTargetNode *targetNode = dynamic_cast<CMakeTargetNode *>(node);
+ const Node *node = ProjectTree::findCurrentNode();
+ const CMakeTargetNode *targetNode = dynamic_cast<const CMakeTargetNode *>(node);
// as targetNode can be deleted while the menu is open, we keep only the
const QString targetDisplayName = targetNode ? targetNode->displayName() : QString();
CMakeProject *cmProject = dynamic_cast<CMakeProject *>(project);
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h
index de3112184a..7f8524ff74 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h
@@ -34,7 +34,6 @@ namespace Utils { class ParameterAction; }
namespace CMakeProjectManager {
class CMakeProject;
-class CMakeToolManager;
namespace Internal {
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
index bfb4fcbc71..4b023aeb0c 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp
@@ -37,6 +37,7 @@
#include <projectexplorer/target.h>
#include <utils/detailswidget.h>
+#include <utils/fancylineedit.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -59,36 +60,36 @@ const char CMAKE_RC_PREFIX[] = "CMakeProjectManager.CMakeRunConfiguration.";
const char TITLE_KEY[] = "CMakeProjectManager.CMakeRunConfiguation.Title";
} // namespace
-CMakeRunConfiguration::CMakeRunConfiguration(Target *parent, Core::Id id, const QString &target,
- const Utils::FileName &workingDirectory, const QString &title) :
- RunConfiguration(parent, id),
- m_buildSystemTarget(target),
- m_executable(target),
- m_title(title)
+CMakeRunConfiguration::CMakeRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
addExtraAspect(new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()));
- addExtraAspect(new ArgumentsAspect(this, QStringLiteral("CMakeProjectManager.CMakeRunConfiguration.Arguments")));
- addExtraAspect(new TerminalAspect(this, QStringLiteral("CMakeProjectManager.CMakeRunConfiguration.UseTerminal")));
-
- auto wd = new WorkingDirectoryAspect(this, QStringLiteral("CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"));
- wd->setDefaultWorkingDirectory(workingDirectory);
- addExtraAspect(wd);
-
- ctor();
+ addExtraAspect(new ArgumentsAspect(this, "CMakeProjectManager.CMakeRunConfiguration.Arguments"));
+ addExtraAspect(new TerminalAspect(this, "CMakeProjectManager.CMakeRunConfiguration.UseTerminal"));
+ addExtraAspect(new WorkingDirectoryAspect(this, "CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"));
}
-CMakeRunConfiguration::CMakeRunConfiguration(Target *parent, CMakeRunConfiguration *source) :
- RunConfiguration(parent, source),
- m_buildSystemTarget(source->m_buildSystemTarget),
- m_executable(source->m_executable),
- m_title(source->m_title),
- m_enabled(source->m_enabled)
+void CMakeRunConfiguration::initialize(Core::Id id, const QString &target,
+ const Utils::FileName &workingDirectory, const QString &title)
{
- ctor();
+ RunConfiguration::initialize(id);
+ m_buildSystemTarget = target;
+ m_executable = target;
+ m_title = title;
+
+ extraAspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(workingDirectory);
+
+ setDefaultDisplayName(defaultDisplayName());
}
-void CMakeRunConfiguration::ctor()
+void CMakeRunConfiguration::copyFrom(const CMakeRunConfiguration *source)
{
+ RunConfiguration::copyFrom(source);
+
+ m_buildSystemTarget = source->m_buildSystemTarget;
+ m_executable = source->m_executable;
+ m_title = source->m_title;
+
setDefaultDisplayName(defaultDisplayName());
}
@@ -143,38 +144,39 @@ QString CMakeRunConfiguration::defaultDisplayName() const
{
if (m_title.isEmpty())
return tr("Run CMake kit");
- QString result = m_title;
- if (!m_enabled) {
- result += QLatin1Char(' ');
- result += tr("(disabled)");
- }
- return result;
+ return m_title;
}
-QWidget *CMakeRunConfiguration::createConfigurationWidget()
+void CMakeRunConfiguration::updateEnabledState()
{
- return new CMakeRunConfigurationWidget(this);
+ auto cp = qobject_cast<CMakeProject *>(target()->project());
+ if (!cp->hasBuildTarget(m_buildSystemTarget))
+ setEnabled(false);
+ else
+ RunConfiguration::updateEnabledState();
}
-void CMakeRunConfiguration::setEnabled(bool b)
+QWidget *CMakeRunConfiguration::createConfigurationWidget()
{
- if (m_enabled == b)
- return;
- m_enabled = b;
- emit enabledChanged();
- setDefaultDisplayName(defaultDisplayName());
+ return new CMakeRunConfigurationWidget(this);
}
-bool CMakeRunConfiguration::isEnabled() const
+QString CMakeRunConfiguration::disabledReason() const
{
- return m_enabled;
+ auto cp = qobject_cast<CMakeProject *>(target()->project());
+ QTC_ASSERT(cp, return QString());
+
+ if (!cp->hasBuildTarget(m_buildSystemTarget))
+ return tr("The project no longer builds the target associated with this run configuration.");
+ return RunConfiguration::disabledReason();
}
-QString CMakeRunConfiguration::disabledReason() const
+static void updateExecutable(CMakeRunConfiguration *rc, Utils::FancyLineEdit *fle)
{
- if (!m_enabled)
- return tr("The executable is not built by the current build configuration");
- return QString();
+ const Runnable runnable = rc->runnable();
+ fle->setText(runnable.is<StandardRunnable>()
+ ? Utils::FileName::fromString(runnable.as<StandardRunnable>().executable).toUserOutput()
+ : QString());
}
// Configuration widget
@@ -185,6 +187,16 @@ CMakeRunConfigurationWidget::CMakeRunConfigurationWidget(CMakeRunConfiguration *
fl->setMargin(0);
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
+ auto executableLabel = new QLabel(tr("Executable:"));
+ auto executable = new Utils::FancyLineEdit;
+ executable->setReadOnly(true);
+ executable->setPlaceholderText(tr("<unknown>"));
+ connect(cmakeRunConfiguration, &CMakeRunConfiguration::enabledChanged,
+ this, std::bind(updateExecutable, cmakeRunConfiguration, executable));
+ updateExecutable(cmakeRunConfiguration, executable);
+
+ fl->addRow(executableLabel, executable);
+
cmakeRunConfiguration->extraAspect<ArgumentsAspect>()->addToMainConfigurationWidget(this, fl);
cmakeRunConfiguration->extraAspect<WorkingDirectoryAspect>()->addToMainConfigurationWidget(this, fl);
cmakeRunConfiguration->extraAspect<TerminalAspect>()->addToMainConfigurationWidget(this, fl);
@@ -199,8 +211,6 @@ CMakeRunConfigurationWidget::CMakeRunConfigurationWidget(CMakeRunConfiguration *
auto vbx = new QVBoxLayout(this);
vbx->setMargin(0);
vbx->addWidget(detailsContainer);
-
- setEnabled(cmakeRunConfiguration->isEnabled());
}
// Factory
@@ -247,7 +257,7 @@ RunConfiguration *CMakeRunConfigurationFactory::doCreate(Target *parent, Core::I
CMakeProject *project = static_cast<CMakeProject *>(parent->project());
const QString title(buildTargetFromId(id));
const CMakeBuildTarget &ct = project->buildTargetForTitle(title);
- return new CMakeRunConfiguration(parent, id, title, ct.workingDirectory, ct.title);
+ return createHelper<CMakeRunConfiguration>(parent, id, title, ct.workingDirectory, ct.title);
}
bool CMakeRunConfigurationFactory::canClone(Target *parent, RunConfiguration *source) const
@@ -261,8 +271,7 @@ RunConfiguration *CMakeRunConfigurationFactory::clone(Target *parent, RunConfigu
{
if (!canClone(parent, source))
return 0;
- CMakeRunConfiguration *crc(static_cast<CMakeRunConfiguration *>(source));
- return new CMakeRunConfiguration(parent, crc);
+ return cloneHelper<CMakeRunConfiguration>(parent, source);
}
bool CMakeRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
@@ -275,7 +284,7 @@ bool CMakeRunConfigurationFactory::canRestore(Target *parent, const QVariantMap
RunConfiguration *CMakeRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
{
const Core::Id id = idFromMap(map);
- return new CMakeRunConfiguration(parent, id, buildTargetFromId(id), Utils::FileName(), QString());
+ return createHelper<CMakeRunConfiguration>(parent, id, buildTargetFromId(id), Utils::FileName(), QString());
}
QString CMakeRunConfigurationFactory::buildTargetFromId(Core::Id id)
diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
index 02ed4df607..1b4ceffc23 100644
--- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
+++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h
@@ -35,11 +35,10 @@ class CMakeRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
friend class CMakeRunConfigurationWidget;
- friend class CMakeRunConfigurationFactory;
+ friend class ProjectExplorer::IRunConfigurationFactory;
public:
- CMakeRunConfiguration(ProjectExplorer::Target *parent, Core::Id id, const QString &target,
- const Utils::FileName &workingDirectory, const QString &title);
+ explicit CMakeRunConfiguration(ProjectExplorer::Target *target);
ProjectExplorer::Runnable runnable() const override;
QWidget *createConfigurationWidget() override;
@@ -51,26 +50,25 @@ public:
QVariantMap toMap() const override;
- void setEnabled(bool b);
-
- bool isEnabled() const override;
QString disabledReason() const override;
QString buildSystemTarget() const final { return m_buildSystemTarget; }
-protected:
- CMakeRunConfiguration(ProjectExplorer::Target *parent, CMakeRunConfiguration *source);
+private:
+ void initialize(Core::Id id, const QString &target,
+ const Utils::FileName &workingDirectory, const QString &title);
+ void copyFrom(const CMakeRunConfiguration *source);
+
bool fromMap(const QVariantMap &map) override;
QString defaultDisplayName() const;
-private:
+ void updateEnabledState() final;
+
QString baseWorkingDirectory() const;
- void ctor();
- const QString m_buildSystemTarget;
+ QString m_buildSystemTarget;
QString m_executable;
QString m_title;
- bool m_enabled = true;
};
class CMakeRunConfigurationWidget : public QWidget
diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
index 8381323759..9f1b753892 100644
--- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
@@ -66,13 +66,13 @@ public:
CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const;
CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const;
- QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool isAutoDetected);
+ QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected);
void addCMakeTool(const CMakeTool *item, bool changed);
TreeItem *autoGroupItem() const;
TreeItem *manualGroupItem() const;
void reevaluateChangedFlag(CMakeToolTreeItem *item) const;
void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable,
- bool autoRun);
+ bool autoRun, bool autoCreate);
void removeCMakeTool(const Core::Id &id);
void apply();
@@ -95,16 +95,18 @@ public:
m_name(item->displayName()),
m_executable(item->cmakeExecutable()),
m_isAutoRun(item->isAutoRun()),
+ m_autoCreateBuildDirectory(item->autoCreateBuildDirectory()),
m_autodetected(item->isAutoDetected()),
m_changed(changed)
{}
CMakeToolTreeItem(const QString &name, const Utils::FileName &executable,
- bool autoRun, bool autodetected) :
+ bool autoRun, bool autoCreate, bool autodetected) :
m_id(Core::Id::fromString(QUuid::createUuid().toString())),
m_name(name),
m_executable(executable),
m_isAutoRun(autoRun),
+ m_autoCreateBuildDirectory(autoCreate),
m_autodetected(autodetected),
m_changed(true)
{}
@@ -143,6 +145,7 @@ public:
QString m_name;
FileName m_executable;
bool m_isAutoRun = true;
+ bool m_autoCreateBuildDirectory = false;
bool m_autodetected = false;
bool m_changed = true;
};
@@ -166,9 +169,10 @@ CMakeToolItemModel::CMakeToolItemModel()
}
QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable,
- const bool autoRun, const bool isAutoDetected)
+ const bool autoRun, const bool autoCreate,
+ const bool isAutoDetected)
{
- CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, isAutoDetected);
+ CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, autoCreate, isAutoDetected);
if (isAutoDetected)
autoGroupItem()->appendChild(item);
else
@@ -219,7 +223,8 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const
}
void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName,
- const FileName &executable, bool autoRun)
+ const FileName &executable, bool autoRun,
+ bool autoCreate)
{
CMakeToolTreeItem *treeItem = cmakeToolItem(id);
QTC_ASSERT(treeItem, return);
@@ -227,6 +232,7 @@ void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &disp
treeItem->m_name = displayName;
treeItem->m_executable = executable;
treeItem->m_isAutoRun = autoRun;
+ treeItem->m_autoCreateBuildDirectory = autoCreate;
reevaluateChangedFlag(treeItem);
}
@@ -262,6 +268,7 @@ void CMakeToolItemModel::apply()
cmake->setDisplayName(item->m_name);
cmake->setCMakeExecutable(item->m_executable);
cmake->setAutorun(item->m_isAutoRun);
+ cmake->setAutoCreateBuildDirectory(item->m_autoCreateBuildDirectory);
} else {
toRegister.append(item);
}
@@ -329,6 +336,7 @@ private:
CMakeToolItemModel *m_model;
QLineEdit *m_displayNameLineEdit;
QCheckBox *m_autoRunCheckBox;
+ QCheckBox *m_autoCreateBuildDirectoryCheckBox;
PathChooser *m_binaryChooser;
Core::Id m_id;
bool m_loadingItem;
@@ -349,11 +357,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
m_autoRunCheckBox->setText(tr("Autorun CMake"));
m_autoRunCheckBox->setToolTip(tr("Automatically run CMake after changes to CMake project files."));
+ m_autoCreateBuildDirectoryCheckBox = new QCheckBox;
+ m_autoCreateBuildDirectoryCheckBox->setText(tr("Auto-create build directories"));
+ m_autoCreateBuildDirectoryCheckBox->setToolTip(tr("Automatically create build directories for CMake projects."));
+
QFormLayout *formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
formLayout->addRow(m_autoRunCheckBox);
+ formLayout->addRow(m_autoCreateBuildDirectoryCheckBox);
connect(m_binaryChooser, &PathChooser::rawPathChanged,
this, &CMakeToolItemConfigWidget::store);
@@ -361,13 +374,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
this, &CMakeToolItemConfigWidget::store);
connect(m_autoRunCheckBox, &QCheckBox::toggled,
this, &CMakeToolItemConfigWidget::store);
+ connect(m_autoCreateBuildDirectoryCheckBox, &QCheckBox::toggled,
+ this, &CMakeToolItemConfigWidget::store);
}
void CMakeToolItemConfigWidget::store() const
{
if (!m_loadingItem && m_id.isValid())
m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(),
- m_autoRunCheckBox->checkState() == Qt::Checked);
+ m_autoRunCheckBox->checkState() == Qt::Checked,
+ m_autoCreateBuildDirectoryCheckBox->checkState() == Qt::Checked);
}
void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
@@ -387,6 +403,7 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
m_binaryChooser->setFileName(item->m_executable);
m_autoRunCheckBox->setChecked(item->m_isAutoRun);
+ m_autoCreateBuildDirectoryCheckBox->setChecked(item->m_autoCreateBuildDirectory);
m_id = item->m_id;
m_loadingItem = false;
@@ -492,7 +509,8 @@ void CMakeToolConfigWidget::cloneCMakeTool()
QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name),
m_currentItem->m_executable,
- m_currentItem->m_isAutoRun, false);
+ m_currentItem->m_isAutoRun,
+ m_currentItem->m_autoCreateBuildDirectory, false);
m_cmakeToolsView->setCurrentIndex(newItem);
}
@@ -500,7 +518,7 @@ void CMakeToolConfigWidget::cloneCMakeTool()
void CMakeToolConfigWidget::addCMakeTool()
{
QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")),
- FileName(), true, false);
+ FileName(), true, false, false);
m_cmakeToolsView->setCurrentIndex(newItem);
}
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp
index 1a107ccd55..9c071dacb8 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp
@@ -46,6 +46,7 @@ const char CMAKE_INFORMATION_ID[] = "Id";
const char CMAKE_INFORMATION_COMMAND[] = "Binary";
const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName";
const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun";
+const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory";
const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected";
@@ -68,6 +69,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected(fr
m_id = Core::Id::fromSetting(map.value(CMAKE_INFORMATION_ID));
m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString();
m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool();
+ m_autoCreateBuildDirectory = map.value(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, false).toBool();
//loading a CMakeTool from SDK is always autodetection
if (!fromSdk)
@@ -102,6 +104,15 @@ void CMakeTool::setAutorun(bool autoRun)
CMakeToolManager::notifyAboutUpdate(this);
}
+void CMakeTool::setAutoCreateBuildDirectory(bool autoBuildDir)
+{
+ if (m_autoCreateBuildDirectory == autoBuildDir)
+ return;
+
+ m_autoCreateBuildDirectory = autoBuildDir;
+ CMakeToolManager::notifyAboutUpdate(this);
+}
+
bool CMakeTool::isValid() const
{
if (!m_id.isValid())
@@ -142,6 +153,7 @@ QVariantMap CMakeTool::toMap() const
data.insert(CMAKE_INFORMATION_ID, m_id.toSetting());
data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString());
data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun);
+ data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory);
data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected);
return data;
}
@@ -162,6 +174,11 @@ bool CMakeTool::isAutoRun() const
return m_isAutoRun;
}
+bool CMakeTool::autoCreateBuildDirectory() const
+{
+ return m_autoCreateBuildDirectory;
+}
+
QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const
{
readInformation(QueryType::GENERATORS);
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h
index 5851c75bfc..95556cefd7 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.h
+++ b/src/plugins/cmakeprojectmanager/cmaketool.h
@@ -90,9 +90,11 @@ public:
void setCMakeExecutable(const Utils::FileName &executable);
void setAutorun(bool autoRun);
+ void setAutoCreateBuildDirectory(bool autoBuildDir);
Utils::FileName cmakeExecutable() const;
bool isAutoRun() const;
+ bool autoCreateBuildDirectory() const;
QList<Generator> supportedGenerators() const;
TextEditor::Keywords keywords();
bool hasServerMode() const;
@@ -127,6 +129,7 @@ private:
bool m_isAutoRun = true;
bool m_isAutoDetected = false;
+ bool m_autoCreateBuildDirectory = false;
mutable bool m_didAttemptToRun = false;
mutable bool m_didRun = false;
diff --git a/src/plugins/cmakeprojectmanager/configmodel.cpp b/src/plugins/cmakeprojectmanager/configmodel.cpp
index 7336a2a7a2..ff43d0cc63 100644
--- a/src/plugins/cmakeprojectmanager/configmodel.cpp
+++ b/src/plugins/cmakeprojectmanager/configmodel.cpp
@@ -25,12 +25,15 @@
#include "configmodel.h"
+#include <utils/asconst.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
#include <QCoreApplication>
#include <QFont>
+#include <QString>
+#include <QSortFilterProxyModel>
namespace CMakeProjectManager {
@@ -41,215 +44,165 @@ static bool isTrue(const QString &value)
|| lower == QStringLiteral("1") || lower == QStringLiteral("yes");
}
-ConfigModel::ConfigModel(QObject *parent) : QAbstractTableModel(parent)
-{ }
-
-int ConfigModel::rowCount(const QModelIndex &parent) const
+ConfigModel::ConfigModel(QObject *parent) : Utils::TreeModel<>(parent)
{
- return parent.isValid() ? 0 : m_configuration.count();
+ setHeader({tr("Key"), tr("Value")});
}
-int ConfigModel::columnCount(const QModelIndex &parent) const
+QVariant ConfigModel::data(const QModelIndex &idx, int role) const
{
- return parent.isValid() ? 0 : 3;
+ // Hide/show groups according to "isAdvanced" setting:
+ Utils::TreeItem *item = static_cast<Utils::TreeItem *>(idx.internalPointer());
+ if (role == ItemIsAdvancedRole && item->childCount() > 0) {
+ const bool hasNormalChildren = item->findAnyChild([](const Utils::TreeItem *ti) {
+ if (auto cmti = dynamic_cast<const Internal::ConfigModelTreeItem*>(ti))
+ return !cmti->dataItem->isAdvanced;
+ return false;
+ }) != nullptr;
+ return hasNormalChildren ? "0" : "1";
+ }
+ return Utils::TreeModel<>::data(idx, role);
}
-Qt::ItemFlags ConfigModel::flags(const QModelIndex &index) const
+ConfigModel::~ConfigModel() = default;
+
+void ConfigModel::appendConfiguration(const QString &key,
+ const QString &value,
+ const ConfigModel::DataItem::Type type,
+ const QString &description,
+ const QStringList &values)
{
- QTC_ASSERT(index.model() == this, return Qt::NoItemFlags);
- QTC_ASSERT(index.isValid(), return Qt::NoItemFlags);
- QTC_ASSERT(index.column() >= 0 && index.column() < columnCount(QModelIndex()), return Qt::NoItemFlags);
- QTC_ASSERT(index.row() >= 0 && index.row() < rowCount(QModelIndex()), return Qt::NoItemFlags);
+ DataItem item;
+ item.key = key;
+ item.type = type;
+ item.value = value;
+ item.description = description;
+ item.values = values;
- const InternalDataItem &item = itemAtRow(index.row());
+ InternalDataItem internalItem(item);
+ internalItem.isUserNew = true;
- if (index.column() == 1) {
- if (item.type == DataItem::BOOLEAN)
- return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
- else
- return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
- } else {
- Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
- if (item.isUserNew)
- return flags |= Qt::ItemIsEditable;
- return flags;
- }
+ if (m_kitConfiguration.contains(key))
+ internalItem.kitValue = m_kitConfiguration.value(key);
+
+ m_configuration.append(internalItem);
+ setConfiguration(m_configuration);
}
-QVariant ConfigModel::data(const QModelIndex &index, int role) const
+void ConfigModel::setConfiguration(const QList<DataItem> &config)
{
- QTC_ASSERT(index.model() == this, return QVariant());
- QTC_ASSERT(index.isValid(), return QVariant());
- QTC_ASSERT(index.row() >= 0 && index.row() < rowCount(QModelIndex()), return QVariant());
- QTC_ASSERT(index.column() >= 0 && index.column() < columnCount(QModelIndex()), return QVariant());
+ setConfiguration(Utils::transform(config, [](const DataItem &di) { return InternalDataItem(di); }));
+}
- const InternalDataItem &item = m_configuration[index.row()];
+void ConfigModel::setKitConfiguration(const QHash<QString, QString> &kitConfig)
+{
+ m_kitConfiguration = kitConfig;
- if (index.column() < 2) {
- switch (role) {
- case ItemTypeRole:
- return item.type;
- case ItemValuesRole:
- return item.values;
+ for (InternalDataItem &i : m_configuration) {
+ if (m_kitConfiguration.contains(i.key)) {
+ i.kitValue = m_kitConfiguration.value(i.key);
}
}
+ setConfiguration(m_configuration);
+}
- switch (index.column()) {
- case 0:
- switch (role) {
- case Qt::DisplayRole:
- return item.key.isEmpty() ? tr("<UNSET>") : item.key;
- case Qt::EditRole:
- return item.key;
- case Qt::ToolTipRole:
- return item.toolTip();
- case Qt::FontRole: {
- QFont font;
- font.setItalic(item.isCMakeChanged);
- font.setBold(item.isUserNew);
- font.setStrikeOut(!item.inCMakeCache && !item.isUserNew);
- return font;
- }
- default:
- return QVariant();
- }
- case 1: {
- const QString value = item.currentValue();
- const QString kitValue = m_kitConfiguartion.value(item.key);
+void ConfigModel::flush()
+{
+ setConfiguration(QList<InternalDataItem>());
+}
- switch (role) {
- case Qt::CheckStateRole:
- return (item.type == DataItem::BOOLEAN)
- ? QVariant(isTrue(value) ? Qt::Checked : Qt::Unchecked) : QVariant();
- case Qt::DisplayRole:
- return value;
- case Qt::EditRole:
- return (item.type == DataItem::BOOLEAN) ? QVariant(isTrue(value)) : QVariant(value);
- case Qt::FontRole: {
- QFont font;
- font.setBold(item.isUserChanged || item.isUserNew);
- font.setItalic(item.isCMakeChanged);
- return font;
- }
- case Qt::ForegroundRole:
- return Utils::creatorTheme()->color((!kitValue.isNull() && kitValue != value)
- ? Utils::Theme::TextColorHighlight : Utils::Theme::TextColorNormal);
- case Qt::ToolTipRole: {
- QString tooltip = item.toolTip();
- const QString kitValue = m_kitConfiguartion.value(item.key);
- if (!kitValue.isNull()) {
- if (!tooltip.isEmpty())
- tooltip.append("<br>");
- tooltip.append(tr("Kit value: %1").arg(kitValue));
- }
- return tooltip;
- }
- default:
- return QVariant();
- }
- }
- case 2:
- switch (role) {
- case Qt::EditRole:
- return "0";
- case Qt::DisplayRole:
- return QString::fromLatin1(item.isAdvanced ? "1" : "0");
- case Qt::CheckStateRole:
- return item.isAdvanced ? Qt::Checked : Qt::Unchecked;
- default:
- return QVariant();
- }
- default:
- return QVariant();
- }
+void ConfigModel::resetAllChanges()
+{
+ const QList<InternalDataItem> tmp
+ = Utils::filtered(m_configuration,
+ [](const InternalDataItem &i) { return !i.isUserNew; });
+
+ setConfiguration(Utils::transform(tmp, [](const InternalDataItem &i) {
+ InternalDataItem ni(i);
+ ni.newValue.clear();
+ ni.isUserChanged = false;
+ return ni;
+ }));
}
-bool ConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
+bool ConfigModel::hasChanges() const
{
- QTC_ASSERT(index.model() == this, return false);
- QTC_ASSERT(index.isValid(), return false);
- QTC_ASSERT(index.row() >= 0 && index.row() < rowCount(QModelIndex()), return false);
- QTC_ASSERT(index.column() >= 0 && index.column() < 2, return false);
+ return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isUserChanged || i.isUserNew; });
+}
- QString newValue = value.toString();
- if (role == Qt::CheckStateRole) {
- if (index.column() != 1)
- return false;
- newValue = QString::fromLatin1(value.toInt() == 0 ? "OFF" : "ON");
- } else if (role != Qt::EditRole) {
- return false;
- }
+bool ConfigModel::hasCMakeChanges() const
+{
+ return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isCMakeChanged; });
+}
- InternalDataItem &item = itemAtRow(index.row());
- switch (index.column()) {
- case 0:
- if (!item.key.isEmpty() && !item.isUserNew)
- return false;
- item.key = newValue;
- item.isUserNew = true;
- item.isUserChanged = false;
- emit dataChanged(index, index);
- return true;
- case 1:
- if (item.value == newValue) {
- item.newValue.clear();
- item.isUserChanged = false;
- } else {
- item.newValue = newValue;
- item.isUserChanged = true;
- }
- emit dataChanged(index, index);
- return true;
- case 2:
- default:
+bool ConfigModel::canForceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type) const
+{
+ if (idx.model() != const_cast<ConfigModel *>(this) || idx.column() != 1)
return false;
- }
+ Utils::TreeItem *item = itemForIndex(idx);
+ auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item);
+ return cmti && (cmti->dataItem->type != type);
}
-QVariant ConfigModel::headerData(int section, Qt::Orientation orientation, int role) const
+void ConfigModel::forceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type)
{
- if (orientation == Qt::Vertical || role != Qt::DisplayRole)
- return QVariant();
- switch (section) {
- case 0:
- return tr("Setting");
- case 1:
- return tr("Value");
- case 2:
- return tr("Advanced");
- default:
- return QVariant();
- }
+ QTC_ASSERT(canForceTo(idx, type), return);
+ Utils::TreeItem *item = itemForIndex(idx);
+ auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item);
+
+ cmti->dataItem->type = type;
+ const QModelIndex valueIdx = idx.sibling(idx.row(), 1);
+ emit dataChanged(valueIdx, valueIdx);
}
-void ConfigModel::appendConfiguration(const QString &key,
- const QString &value,
- const ConfigModel::DataItem::Type type,
- const QString &description,
- const QStringList &values)
+ConfigModel::DataItem ConfigModel::dataItemFromIndex(const QModelIndex &idx)
{
- DataItem item;
- item.key = key;
- item.type = type;
- item.value = value;
- item.description = description;
- item.values = values;
-
- InternalDataItem internalItem(item);
- internalItem.isUserNew = true;
+ const QAbstractItemModel *m = idx.model();
+ QModelIndex mIdx = idx;
+ while (auto sfpm = qobject_cast<const QSortFilterProxyModel *>(m)) {
+ m = sfpm->sourceModel();
+ mIdx = sfpm->mapToSource(mIdx);
+ }
+ auto model = qobject_cast<const ConfigModel *>(m);
+ QTC_ASSERT(model, return DataItem());
+ const QModelIndex modelIdx = mIdx;
+
+ Utils::TreeItem *item = model->itemForIndex(modelIdx);
+ auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item);
+
+ if (cmti && cmti->dataItem) {
+ DataItem di;
+ di.key = cmti->dataItem->key;
+ di.type = cmti->dataItem->type;
+ di.isHidden = cmti->dataItem->isHidden;
+ di.isAdvanced = cmti->dataItem->isAdvanced;
+ di.inCMakeCache = cmti->dataItem->inCMakeCache;
+ di.value = cmti->dataItem->currentValue();
+ di.description = cmti->dataItem->description;
+ di.values = cmti->dataItem->values;
+
+ return di;
+ }
+ return DataItem();
+}
- beginResetModel();
- m_configuration.append(internalItem);
- endResetModel();
+QList<ConfigModel::DataItem> ConfigModel::configurationChanges() const
+{
+ const QList<InternalDataItem> tmp
+ = Utils::filtered(m_configuration, [](const InternalDataItem &i) {
+ return i.isUserChanged || i.isUserNew || !i.inCMakeCache;
+ });
+ return Utils::transform(tmp, [](const InternalDataItem &item) {
+ DataItem newItem(item);
+ if (item.isUserChanged)
+ newItem.value = item.newValue;
+ return newItem;
+ });
}
-void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
+void ConfigModel::setConfiguration(const QList<ConfigModel::InternalDataItem> &config)
{
- QList<DataItem> tmp = config;
- Utils::sort(tmp,
- [](const ConfigModel::DataItem &i, const ConfigModel::DataItem &j) {
- return i.key < j.key;
- });
+ QList<InternalDataItem> tmp = config;
auto newIt = tmp.constBegin();
auto newEndIt = tmp.constEnd();
auto oldIt = m_configuration.constBegin();
@@ -261,7 +214,7 @@ void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
++newIt;
} else if (newIt->key < oldIt->key) {
// Add new entry:
- result << InternalDataItem(*newIt);
+ result << *newIt;
++newIt;
} else if (newIt->key > oldIt->key) {
// Keep old user settings, but skip other entries:
@@ -287,93 +240,230 @@ void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
result << InternalDataItem(*newIt);
}
- beginResetModel();
m_configuration = result;
- endResetModel();
-}
-void ConfigModel::setKitConfiguration(const QHash<QString, QString> &kitConfig)
-{
- m_kitConfiguartion = kitConfig;
+ generateTree();
}
-void ConfigModel::flush()
+static QString prefix(const QString &key)
{
- beginResetModel();
- m_configuration.clear();
- endResetModel();
+ int pos = key.indexOf('_');
+ if (pos > 0)
+ return key.left(pos);
+ return key;
}
-void ConfigModel::resetAllChanges()
+void ConfigModel::generateTree()
{
- const QList<InternalDataItem> tmp
- = Utils::filtered(m_configuration,
- [](const InternalDataItem &i) { return !i.isUserNew; });
+ QList<QString> prefixList;
+
+ // Generate nodes for *all* prefixes
+ QHash<QString, QList<Utils::TreeItem *>> prefixes;
+ for (const InternalDataItem &di : m_configuration) {
+ const QString p = prefix(di.key);
+ if (!prefixes.contains(p)) {
+ prefixes.insert(p, {});
+ prefixList.append(p);
+ }
+ }
- beginResetModel();
- m_configuration = Utils::transform(tmp, [](const InternalDataItem &i) -> InternalDataItem {
- InternalDataItem ni(i);
- ni.newValue.clear();
- ni.isUserChanged = false;
- return ni;
- });
- endResetModel();
+ // Fill prefix nodes:
+ for (InternalDataItem &di : m_configuration)
+ prefixes[prefix(di.key)].append(new Internal::ConfigModelTreeItem(&di));
+
+ Utils::TreeItem *root = new Utils::TreeItem;
+
+ for (const QString &p : Utils::asConst(prefixList)) {
+ const QList<Utils::TreeItem *> &prefixItemList = prefixes.value(p);
+ QTC_ASSERT(!prefixItemList.isEmpty(), continue);
+
+ if (prefixItemList.count() == 1) {
+ root->appendChild(prefixItemList.at(0));
+ } else {
+ Utils::TreeItem *sti = new Utils::StaticTreeItem(p);
+ for (Utils::TreeItem *const ti : prefixItemList)
+ sti->appendChild(ti);
+ root->appendChild(sti);
+ }
+ prefixes.remove(p);
+ }
+ QTC_CHECK(prefixes.isEmpty());
+
+ setRootItem(root);
}
-bool ConfigModel::hasChanges() const
+ConfigModel::InternalDataItem::InternalDataItem(const ConfigModel::DataItem &item) : DataItem(item)
+{ }
+
+QString ConfigModel::InternalDataItem::toolTip() const
{
- return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isUserChanged || i.isUserNew; });
+ QString desc = description;
+ if (isAdvanced)
+ desc += QCoreApplication::translate("CMakeProjectManager::ConfigModel", " (ADVANCED)");
+ QStringList tooltip(desc);
+ if (inCMakeCache) {
+ if (value != newValue)
+ tooltip << QCoreApplication::translate("CMakeProjectManager", "Current CMake: %1").arg(value);
+ } else {
+ tooltip << QCoreApplication::translate("CMakeProjectManager", "Not in CMakeCache.txt").arg(value);
+ }
+ if (!kitValue.isEmpty())
+ tooltip << QCoreApplication::translate("CMakeProjectManager::ConfigModel", "Current Kit: %1").arg(kitValue);
+ return tooltip.join("<br>");
}
-bool ConfigModel::hasCMakeChanges() const
+QString ConfigModel::InternalDataItem::currentValue() const
{
- return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isCMakeChanged; });
+ return isUserChanged ? newValue : value;
}
-QList<ConfigModel::DataItem> ConfigModel::configurationChanges() const
+namespace Internal {
+
+ConfigModelTreeItem::~ConfigModelTreeItem() = default;
+
+QVariant ConfigModelTreeItem::data(int column, int role) const
{
- const QList<InternalDataItem> tmp
- = Utils::filtered(m_configuration, [](const InternalDataItem &i) {
- return i.isUserChanged || i.isUserNew || !i.inCMakeCache;
- });
- return Utils::transform(tmp, [](const InternalDataItem &item) {
- DataItem newItem(item);
- if (item.isUserChanged)
- newItem.value = item.newValue;
- return newItem;
- });
+ QTC_ASSERT(column >= 0 && column < 2, return QVariant());
+
+ QTC_ASSERT(dataItem, return QVariant());
+
+ if (firstChild()) {
+ // Node with children: Only ever show name:
+ if (column == 0)
+ return dataItem->key;
+ return QVariant();
+ }
+
+ // Leaf node:
+ if (role == ConfigModel::ItemIsAdvancedRole)
+ return dataItem->isAdvanced ? "1" : "0";
+
+ switch (column) {
+ case 0:
+ switch (role) {
+ case Qt::DisplayRole:
+ return dataItem->key.isEmpty() ? QCoreApplication::translate("CMakeProjectManager::ConfigModel", "<UNSET>") : dataItem->key;
+ case Qt::EditRole:
+ return dataItem->key;
+ case Qt::ToolTipRole:
+ return toolTip();
+ case Qt::FontRole: {
+ QFont font;
+ font.setItalic(dataItem->isCMakeChanged);
+ font.setBold(dataItem->isUserNew);
+ font.setStrikeOut(!dataItem->inCMakeCache && !dataItem->isUserNew);
+ return font;
+ }
+ default:
+ return QVariant();
+ }
+ case 1: {
+ const QString value = currentValue();
+
+ switch (role) {
+ case Qt::CheckStateRole:
+ return (dataItem->type == ConfigModel::DataItem::BOOLEAN)
+ ? QVariant(isTrue(value) ? Qt::Checked : Qt::Unchecked) : QVariant();
+ case Qt::DisplayRole:
+ return value;
+ case Qt::EditRole:
+ return (dataItem->type == ConfigModel::DataItem::BOOLEAN) ? QVariant(isTrue(value)) : QVariant(value);
+ case Qt::FontRole: {
+ QFont font;
+ font.setBold(dataItem->isUserChanged || dataItem->isUserNew);
+ font.setItalic(dataItem->isCMakeChanged);
+ return font;
+ }
+ case Qt::ForegroundRole:
+ return Utils::creatorTheme()->color((!dataItem->kitValue.isNull() && dataItem->kitValue != value)
+ ? Utils::Theme::TextColorHighlight : Utils::Theme::TextColorNormal);
+ case Qt::ToolTipRole: {
+ return toolTip();
+ }
+ default:
+ return QVariant();
+ }
+ }
+ default:
+ return QVariant();
+ }
}
-ConfigModel::InternalDataItem &ConfigModel::itemAtRow(int row)
+bool ConfigModelTreeItem::setData(int column, const QVariant &value, int role)
{
- QTC_CHECK(row >= 0);
- return m_configuration[row];
+ QTC_ASSERT(column >= 0 && column < 2, return false);
+ QTC_ASSERT(dataItem, return false);
+
+ QString newValue = value.toString();
+ if (role == Qt::CheckStateRole) {
+ if (column != 1)
+ return false;
+ newValue = QString::fromLatin1(value.toInt() == 0 ? "OFF" : "ON");
+ } else if (role != Qt::EditRole) {
+ return false;
+ }
+
+ switch (column) {
+ case 0:
+ if (!dataItem->key.isEmpty() && !dataItem->isUserNew)
+ return false;
+ dataItem->key = newValue;
+ dataItem->isUserNew = true;
+ return true;
+ case 1:
+ if (dataItem->value == newValue) {
+ dataItem->newValue.clear();
+ dataItem->isUserChanged = false;
+ } else {
+ dataItem->newValue = newValue;
+ dataItem->isUserChanged = true;
+ }
+ return true;
+ default:
+ return false;
+ }
}
-const ConfigModel::InternalDataItem &ConfigModel::itemAtRow(int row) const
+Qt::ItemFlags ConfigModelTreeItem::flags(int column) const
{
- QTC_CHECK(row >= 0);
- return m_configuration[row];
-}
+ if (column < 0 || column >= 2)
+ return Qt::NoItemFlags;
-ConfigModel::InternalDataItem::InternalDataItem(const ConfigModel::DataItem &item) : DataItem(item)
-{ }
+ QTC_ASSERT(dataItem, return Qt::NoItemFlags);
-QString ConfigModel::InternalDataItem::toolTip() const
+ if (column == 1) {
+ if (dataItem->type == ConfigModel::DataItem::BOOLEAN)
+ return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
+ else
+ return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
+ } else {
+ Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ if (dataItem->isUserNew)
+ return flags |= Qt::ItemIsEditable;
+ return flags;
+ }
+}
+
+QString ConfigModelTreeItem::toolTip() const
{
- QStringList tooltip(description);
- if (inCMakeCache) {
- if (value != newValue)
- tooltip << QCoreApplication::translate("CMakeProjectManager", "Current CMake: %1").arg(value);
+ QTC_ASSERT(dataItem, return QString());
+ QStringList tooltip(dataItem->description);
+ if (!dataItem->kitValue.isEmpty())
+ tooltip << QCoreApplication::translate("CMakeProjectManager", "Value requested by Kit: %1").arg(dataItem->kitValue);
+ if (dataItem->inCMakeCache) {
+ if (dataItem->value != dataItem->newValue)
+ tooltip << QCoreApplication::translate("CMakeProjectManager", "Current CMake: %1").arg(dataItem->value);
} else {
- tooltip << QCoreApplication::translate("CMakeProjectManager", "Not in CMakeCache.txt").arg(value);
+ tooltip << QCoreApplication::translate("CMakeProjectManager", "Not in CMakeCache.txt");
}
return tooltip.join("<br>");
}
-QString ConfigModel::InternalDataItem::currentValue() const
+QString ConfigModelTreeItem::currentValue() const
{
- return isUserChanged ? newValue : value;
+ QTC_ASSERT(dataItem, return QString());
+ return dataItem->isUserChanged ? dataItem->newValue : dataItem->value;
}
+} // namespace Internal
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/configmodel.h b/src/plugins/cmakeprojectmanager/configmodel.h
index f9629f702f..626d487ac6 100644
--- a/src/plugins/cmakeprojectmanager/configmodel.h
+++ b/src/plugins/cmakeprojectmanager/configmodel.h
@@ -26,17 +26,19 @@
#pragma once
#include <QAbstractTableModel>
+#include <utils/treemodel.h>
namespace CMakeProjectManager {
-class ConfigModel : public QAbstractTableModel
+namespace Internal { class ConfigModelTreeItem; }
+
+class ConfigModel : public Utils::TreeModel<>
{
Q_OBJECT
public:
enum Roles {
- ItemTypeRole = Qt::UserRole,
- ItemValuesRole
+ ItemIsAdvancedRole = Qt::UserRole,
};
class DataItem {
@@ -54,14 +56,9 @@ public:
};
explicit ConfigModel(QObject *parent = nullptr);
+ ~ConfigModel() override;
- // QAbstractItemModel interface
- int rowCount(const QModelIndex &parent) const override;
- int columnCount(const QModelIndex &parent) const override;
- Qt::ItemFlags flags(const QModelIndex &index) const override;
- QVariant data(const QModelIndex &index, int role) const override;
- bool setData(const QModelIndex &index, const QVariant &value, int role) override;
- QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+ QVariant data(const QModelIndex &idx, int role) const final;
void appendConfiguration(const QString &key,
const QString &value = QString(),
@@ -76,6 +73,11 @@ public:
bool hasChanges() const;
bool hasCMakeChanges() const;
+ bool canForceTo(const QModelIndex &idx, const DataItem::Type type) const;
+ void forceTo(const QModelIndex &idx, const DataItem::Type type);
+
+ static DataItem dataItemFromIndex(const QModelIndex &idx);
+
QList<DataItem> configurationChanges() const;
private:
@@ -92,12 +94,35 @@ private:
bool isUserNew = false;
bool isCMakeChanged = false;
QString newValue;
+ QString kitValue;
};
- InternalDataItem &itemAtRow(int row);
- const InternalDataItem &itemAtRow(int row) const;
+ void setConfiguration(const QList<InternalDataItem> &config);
+ void generateTree();
+
QList<InternalDataItem> m_configuration;
- QHash<QString, QString> m_kitConfiguartion;
+ QHash<QString, QString> m_kitConfiguration;
+
+ friend class Internal::ConfigModelTreeItem;
+};
+
+namespace Internal {
+
+class ConfigModelTreeItem : public Utils::TreeItem
+{
+public:
+ ConfigModelTreeItem(ConfigModel::InternalDataItem *di = nullptr) : dataItem(di) {}
+ virtual ~ConfigModelTreeItem() override;
+
+ QVariant data(int column, int role) const final;
+ bool setData(int column, const QVariant &data, int role) final;
+ Qt::ItemFlags flags(int column) const final;
+
+ QString toolTip() const;
+ QString currentValue() const;
+
+ ConfigModel::InternalDataItem *dataItem;
};
+} // namespace Internal
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
index b2b19b837e..f5d24b5174 100644
--- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
+++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.cpp
@@ -19,59 +19,117 @@
#include "configmodelitemdelegate.h"
#include "configmodel.h"
+#include <utils/asconst.h>
+#include <utils/pathchooser.h>
+
#include <QComboBox>
+#include <QCheckBox>
+#include <QLineEdit>
+#include <QPainter>
namespace CMakeProjectManager {
-ConfigModelItemDelegate::ConfigModelItemDelegate(QObject* parent)
+ConfigModelItemDelegate::ConfigModelItemDelegate(const Utils::FileName &base, QObject* parent)
: QStyledItemDelegate(parent)
+ , m_base(base)
{ }
-ConfigModelItemDelegate::~ConfigModelItemDelegate()
-{ }
+QWidget *ConfigModelItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
-QWidget* ConfigModelItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
- // ComboBox ony in column 2
- if (index.column() != 1)
- return QStyledItemDelegate::createEditor(parent, option, index);
-
- auto model = index.model();
- auto values = model->data(index, ConfigModel::ItemValuesRole).toStringList();
- if (values.isEmpty())
- return QStyledItemDelegate::createEditor(parent, option, index);
+ if (index.column() == 1) {
+ ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
+ if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
+ auto edit = new Utils::PathChooser(parent);
+ edit->setFocusPolicy(Qt::StrongFocus);
+ edit->setBaseFileName(m_base);
+ edit->setAutoFillBackground(true);
+ if (data.type == ConfigModel::DataItem::FILE) {
+ edit->setExpectedKind(Utils::PathChooser::File);
+ edit->setPromptDialogTitle(tr("Select a file for %1").arg(data.key));
+ } else {
+ edit->setExpectedKind(Utils::PathChooser::Directory);
+ edit->setPromptDialogTitle(tr("Select a directory for %1").arg(data.key));
+ }
+ return edit;
+ } else if (!data.values.isEmpty()) {
+ auto edit = new QComboBox(parent);
+ edit->setFocusPolicy(Qt::StrongFocus);
+ for (const QString &s : Utils::asConst(data.values))
+ edit->addItem(s);
+ return edit;
+ } else if (data.type == ConfigModel::DataItem::BOOLEAN) {
+ auto edit = new QCheckBox(parent);
+ edit->setFocusPolicy(Qt::StrongFocus);
+ return edit;
+ } else if (data.type == ConfigModel::DataItem::STRING) {
+ auto edit = new QLineEdit(parent);
+ edit->setFocusPolicy(Qt::StrongFocus);
+ return edit;
+ }
+ }
- // Create the combobox and populate it
- auto cb = new QComboBox(parent);
- cb->addItems(values);
- cb->setEditable(true);
+ return QStyledItemDelegate::createEditor(parent, option, index);
+}
- return cb;
+void ConfigModelItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+ if (index.column() == 1) {
+ ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
+ if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
+ auto edit = static_cast<Utils::PathChooser *>(editor);
+ edit->setFileName(Utils::FileName::fromUserInput(data.value));
+ return;
+ } else if (!data.values.isEmpty()) {
+ auto edit = static_cast<QComboBox *>(editor);
+ edit->setCurrentText(data.value);
+ return;
+ } else if (data.type == ConfigModel::DataItem::BOOLEAN) {
+ auto edit = static_cast<QCheckBox *>(editor);
+ edit->setChecked(index.data(Qt::CheckStateRole).toBool());
+ edit->setText(data.value);
+ return;
+ } else if (data.type == ConfigModel::DataItem::STRING) {
+ auto edit = static_cast<QLineEdit *>(editor);
+ edit->setText(data.value);
+ return;
+ }
+ }
+ QStyledItemDelegate::setEditorData(editor, index);
}
-void ConfigModelItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
+void ConfigModelItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const
{
- if (QComboBox* cb = qobject_cast<QComboBox*>(editor)) {
- // get the index of the text in the combobox that matches the current value of the itenm
- QString currentText = index.data(Qt::EditRole).toString();
- int cbIndex = cb->findText(currentText);
- // if it is valid, adjust the combobox
- if (cbIndex >= 0)
- cb->setCurrentIndex(cbIndex);
- else
- cb->setEditText(currentText);
- } else {
- QStyledItemDelegate::setEditorData(editor, index);
+ if (index.column() == 1) {
+ ConfigModel::DataItem data = ConfigModel::dataItemFromIndex(index);
+ if (data.type == ConfigModel::DataItem::FILE || data.type == ConfigModel::DataItem::DIRECTORY) {
+ auto edit = static_cast<Utils::PathChooser *>(editor);
+ if (edit->rawPath() != data.value)
+ model->setData(index, edit->fileName().toUserOutput(), Qt::EditRole);
+ return;
+ } else if (!data.values.isEmpty()) {
+ auto edit = static_cast<QComboBox *>(editor);
+ model->setData(index, edit->currentText(), Qt::EditRole);
+ return;
+ } else if (data.type == ConfigModel::DataItem::BOOLEAN) {
+ auto edit = static_cast<QCheckBox *>(editor);
+ model->setData(index, edit->text(), Qt::EditRole);
+ } else if (data.type == ConfigModel::DataItem::STRING) {
+ auto edit = static_cast<QLineEdit *>(editor);
+ model->setData(index, edit->text(), Qt::EditRole);
+ }
}
+ QStyledItemDelegate::setModelData(editor, model, index);
}
-void ConfigModelItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
+QSize CMakeProjectManager::ConfigModelItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
{
- if (QComboBox* cb = qobject_cast<QComboBox*>(editor))
- // save the current text of the combo box as the current value of the item
- model->setData(index, cb->currentText(), Qt::EditRole);
- else
- QStyledItemDelegate::setModelData(editor, model, index);
+ Q_UNUSED(option);
+ Q_UNUSED(index);
+ return QSize(100, m_measurement.sizeHint().height());
}
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h
index 8c20f7b831..ce5571b6be 100644
--- a/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h
+++ b/src/plugins/cmakeprojectmanager/configmodelitemdelegate.h
@@ -18,20 +18,30 @@
#pragma once
+#include <QComboBox>
#include <QStyledItemDelegate>
+#include <utils/fileutils.h>
+
namespace CMakeProjectManager {
class ConfigModelItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
+
public:
- ConfigModelItemDelegate(QObject* parent=0);
- ~ConfigModelItemDelegate();
+ ConfigModelItemDelegate(const Utils::FileName &base, QObject *parent = nullptr);
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const final;
+ void setEditorData(QWidget *editor, const QModelIndex &index) const final;
+ void setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const final;
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const final;
- QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
- void setEditorData(QWidget* editor, const QModelIndex& index) const override;
- void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
+private:
+ Utils::FileName m_base;
+ QComboBox m_measurement;
};
} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp
index 04c69af89f..bc95970aa7 100644
--- a/src/plugins/cmakeprojectmanager/servermodereader.cpp
+++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp
@@ -32,6 +32,7 @@
#include "servermode.h"
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/fileiconprovider.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -44,6 +45,8 @@
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
+#include <QVector>
+
using namespace ProjectExplorer;
using namespace Utils;
@@ -56,7 +59,10 @@ const char CONFIGURE_TYPE[] = "configure";
const char CMAKE_INPUTS_TYPE[] = "cmakeInputs";
const char COMPUTE_TYPE[] = "compute";
+const char BACKTRACE_KEY[] = "backtrace";
+const char LINE_KEY[] = "line";
const char NAME_KEY[] = "name";
+const char PATH_KEY[] = "path";
const char SOURCE_DIRECTORY_KEY[] = "sourceDirectory";
const char SOURCES_KEY[] = "sources";
@@ -154,7 +160,6 @@ void ServerModeReader::resetData()
void ServerModeReader::parse(bool force)
{
emit configurationStarted();
- Core::MessageManager::write(tr("Starting to parse CMake project for Qt Creator."));
QTC_ASSERT(m_cmakeServer, return);
QVariantMap extra;
@@ -163,9 +168,13 @@ void ServerModeReader::parse(bool force)
[this](const CMakeConfigItem &i) {
return i.toArgument(m_parameters.expander);
});
+ Core::MessageManager::write(tr("Starting to parse CMake project, using: \"%1\".")
+ .arg(cacheArguments.join("\", \"")));
cacheArguments.prepend(QString()); // Work around a bug in CMake 3.7.0 and 3.7.1 where
// the first argument gets lost!
extra.insert("cacheArguments", QVariant(cacheArguments));
+ } else {
+ Core::MessageManager::write(tr("Starting to parse CMake project."));
}
m_future.reset(new QFutureInterface<void>());
@@ -307,10 +316,10 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root,
const FileName path = fn->filePath();
if (path.fileName().compare("CMakeLists.txt", HostOsInfo::fileNameCaseSensitivity()) == 0)
cmakeLists.append(fn);
- else if (path.isChildOf(m_parameters.sourceDirectory))
- cmakeFilesSource.append(fn);
else if (path.isChildOf(m_parameters.buildDirectory))
cmakeFilesBuild.append(fn);
+ else if (path.isChildOf(m_parameters.sourceDirectory))
+ cmakeFilesSource.append(fn);
else
cmakeFilesOther.append(fn);
}
@@ -338,14 +347,6 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps)
int counter = 0;
for (const FileGroup *fg : Utils::asConst(m_fileGroups)) {
++counter;
- const QString defineArg
- = transform(fg->defines, [](const QString &s) -> QString {
- QString result = QString::fromLatin1("#define ") + s;
- int assignIndex = result.indexOf('=');
- if (assignIndex != -1)
- result[assignIndex] = ' ';
- return result;
- }).join('\n');
const QStringList flags = QtcProcess::splitArgs(fg->compileFlags);
const QStringList includes = transform(fg->includePaths, [](const IncludePath *ip) { return ip->path.toString(); });
@@ -353,7 +354,7 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps)
rpp.setProjectFileLocation(fg->target->sourceDirectory.toString() + "/CMakeLists.txt");
rpp.setBuildSystemTarget(fg->target->name);
rpp.setDisplayName(fg->target->name + QString::number(counter));
- rpp.setDefines(defineArg.toUtf8());
+ rpp.setMacros(fg->macros);
rpp.setIncludePaths(includes);
CppTools::RawProjectPartFlags cProjectFlags;
@@ -366,6 +367,9 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps)
rpp.setFiles(transform(fg->sources, &FileName::toString));
+ const bool isExecutable = fg->target->type == "EXECUTABLE";
+ rpp.setBuildTargetType(isExecutable ? CppTools::ProjectPart::Executable
+ : CppTools::ProjectPart::Library);
rpps.append(rpp);
}
@@ -509,6 +513,8 @@ ServerModeReader::Target *ServerModeReader::extractTargetData(const QVariantMap
target->sourceDirectory = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
target->buildDirectory = FileName::fromString(data.value("buildDirectory").toString());
+ target->crossReferences = extractCrossReferences(data.value("crossReferences").toMap());
+
QDir srcDir(target->sourceDirectory.toString());
target->type = data.value("type").toString();
@@ -534,7 +540,9 @@ ServerModeReader::FileGroup *ServerModeReader::extractFileGroupData(const QVaria
auto fileGroup = new FileGroup;
fileGroup->target = t;
fileGroup->compileFlags = data.value("compileFlags").toString();
- fileGroup->defines = data.value("defines").toStringList();
+ fileGroup->macros = Utils::transform<QVector>(data.value("defines").toStringList(), [](const QString &s) {
+ return ProjectExplorer::Macro::fromKeyValue(s);
+ });
fileGroup->includePaths = transform(data.value("includePath").toList(),
[](const QVariant &i) -> IncludePath* {
const QVariantMap iData = i.toMap();
@@ -553,6 +561,72 @@ ServerModeReader::FileGroup *ServerModeReader::extractFileGroupData(const QVaria
return fileGroup;
}
+QList<ServerModeReader::CrossReference *> ServerModeReader::extractCrossReferences(const QVariantMap &data)
+{
+ QList<CrossReference *> crossReferences;
+
+ if (data.isEmpty())
+ return crossReferences;
+
+ auto cr = std::make_unique<CrossReference>();
+ cr->backtrace = extractBacktrace(data.value(BACKTRACE_KEY, QVariantList()).toList());
+ QTC_ASSERT(!cr->backtrace.isEmpty(), return {});
+ crossReferences.append(cr.release());
+
+ const QVariantList related = data.value("relatedStatements", QVariantList()).toList();
+ for (const QVariant &relatedData : related) {
+ auto cr = std::make_unique<CrossReference>();
+
+ // extract information:
+ const QVariantMap map = relatedData.toMap();
+ const QString typeString = map.value("type", QString()).toString();
+ if (typeString.isEmpty())
+ cr->type = CrossReference::TARGET;
+ else if (typeString == "target_link_libraries")
+ cr->type = CrossReference::LIBRARIES;
+ else if (typeString == "target_compile_defines")
+ cr->type = CrossReference::DEFINES;
+ else if (typeString == "target_include_directories")
+ cr->type = CrossReference::INCLUDES;
+ else
+ cr->type = CrossReference::UNKNOWN;
+ cr->backtrace = extractBacktrace(map.value(BACKTRACE_KEY, QVariantList()).toList());
+
+ // sanity check:
+ if (cr->backtrace.isEmpty())
+ continue;
+
+ // store information:
+ crossReferences.append(cr.release());
+ }
+ return crossReferences;
+}
+
+ServerModeReader::BacktraceItem *ServerModeReader::extractBacktraceItem(const QVariantMap &data)
+{
+ QTC_ASSERT(!data.isEmpty(), return nullptr);
+ auto item = std::make_unique<BacktraceItem>();
+
+ item->line = data.value(LINE_KEY, -1).toInt();
+ item->name = data.value(NAME_KEY, QString()).toString();
+ item->path = data.value(PATH_KEY, QString()).toString();
+
+ QTC_ASSERT(!item->path.isEmpty(), return nullptr);
+ return item.release();
+}
+
+QList<ServerModeReader::BacktraceItem *> ServerModeReader::extractBacktrace(const QVariantList &data)
+{
+ QList<BacktraceItem *> btResult;
+ for (const QVariant &bt : data) {
+ BacktraceItem *btItem = extractBacktraceItem(bt.toMap());
+ QTC_ASSERT(btItem, continue);
+
+ btResult.append(btItem);
+ }
+ return btResult;
+}
+
void ServerModeReader::extractCMakeInputsData(const QVariantMap &data)
{
const FileName src = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
@@ -607,7 +681,7 @@ void ServerModeReader::fixTarget(ServerModeReader::Target *target) const
for (const FileGroup *group : Utils::asConst(target->fileGroups)) {
if (group->includePaths.isEmpty() && group->compileFlags.isEmpty()
- && group->defines.isEmpty())
+ && group->macros.isEmpty())
continue;
const FileGroup *fallback = languageFallbacks.value(group->language);
@@ -633,13 +707,13 @@ void ServerModeReader::fixTarget(ServerModeReader::Target *target) const
(*it)->language = fallback->language.isEmpty() ? "CXX" : fallback->language;
if (*it == fallback
- || !(*it)->includePaths.isEmpty() || !(*it)->defines.isEmpty()
+ || !(*it)->includePaths.isEmpty() || !(*it)->macros.isEmpty()
|| !(*it)->compileFlags.isEmpty())
continue;
for (const IncludePath *ip : fallback->includePaths)
(*it)->includePaths.append(new IncludePath(*ip));
- (*it)->defines = fallback->defines;
+ (*it)->macros = fallback->macros;
(*it)->compileFlags = fallback->compileFlags;
}
}
@@ -725,6 +799,36 @@ void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer::
CMakeTargetNode *tNode = createTargetNode(cmakeListsNodes, t->sourceDirectory, t->name);
QTC_ASSERT(tNode, qDebug() << "No target node for" << t->sourceDirectory << t->name; continue);
tNode->setTargetInformation(t->artifacts, t->type);
+ QList<FolderNode::LocationInfo> info;
+ // Set up a default target path:
+ FileName targetPath = t->sourceDirectory;
+ targetPath.appendPath("CMakeLists.txt");
+ for (CrossReference *cr : Utils::asConst(t->crossReferences)) {
+ BacktraceItem *bt = cr->backtrace.isEmpty() ? nullptr : cr->backtrace.at(0);
+ if (bt) {
+ const QString btName = bt->name.toLower();
+ const FileName path = Utils::FileName::fromUserInput(bt->path);
+ QString dn;
+ if (cr->type != CrossReference::TARGET) {
+ if (path == targetPath) {
+ if (bt->line >= 0)
+ dn = tr("%1 in line %3").arg(btName).arg(bt->line);
+ else
+ dn = tr("%1").arg(btName);
+ } else {
+ if (bt->line >= 0)
+ dn = tr("%1 in %2:%3").arg(btName, path.toUserOutput()).arg(bt->line);
+ else
+ dn = tr("%1 in %2").arg(btName, path.toUserOutput());
+ }
+ } else {
+ dn = tr("Target Definition");
+ targetPath = path;
+ }
+ info.append(FolderNode::LocationInfo(dn, path, bt->line));
+ }
+ }
+ tNode->setLocationInfo(info);
addFileGroups(tNode, t->sourceDirectory, t->buildDirectory, t->fileGroups, knownHeaderNodes);
}
}
@@ -778,8 +882,10 @@ void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *>
if (root->isEmpty())
return;
+ static QIcon headerNodeIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_H);
auto headerNode = new VirtualFolderNode(root->filePath(), Node::DefaultPriority - 5);
headerNode->setDisplayName(tr("<Headers>"));
+ headerNode->setIcon(headerNodeIcon);
// knownHeaders are already listed in their targets:
QSet<Utils::FileName> seenHeaders = Utils::transform<QSet>(knownHeaders, &FileNode::filePath);
diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h
index 461bc00e05..bf5fe7337e 100644
--- a/src/plugins/cmakeprojectmanager/servermodereader.h
+++ b/src/plugins/cmakeprojectmanager/servermodereader.h
@@ -29,12 +29,13 @@
#include "servermode.h"
#include "cmakeparser.h"
+#include <QList>
+
#include <memory>
namespace CMakeProjectManager {
namespace Internal {
-class CMakeListsNode;
class ServerModeReader : public BuildDirReader
{
@@ -84,15 +85,33 @@ private:
Target *target = nullptr;
QString compileFlags;
- QStringList defines;
+ ProjectExplorer::Macros macros;
QList<IncludePath *> includePaths;
QString language;
QList<Utils::FileName> sources;
bool isGenerated;
};
+ struct BacktraceItem {
+ int line = -1;
+ QString path;
+ QString name;
+ };
+
+ struct CrossReference {
+ ~CrossReference() { qDeleteAll(backtrace); backtrace.clear(); }
+ QList<BacktraceItem *> backtrace;
+ enum Type { TARGET, LIBRARIES, DEFINES, INCLUDES, UNKNOWN };
+ Type type;
+ };
+
struct Target {
- ~Target() { qDeleteAll(fileGroups); fileGroups.clear(); }
+ ~Target() {
+ qDeleteAll(fileGroups);
+ fileGroups.clear();
+ qDeleteAll(crossReferences);
+ crossReferences.clear();
+ }
Project *project = nullptr;
QString name;
@@ -101,6 +120,7 @@ private:
Utils::FileName sourceDirectory;
Utils::FileName buildDirectory;
QList<FileGroup *> fileGroups;
+ QList<CrossReference *> crossReferences;
};
struct Project {
@@ -115,6 +135,9 @@ private:
Project *extractProjectData(const QVariantMap &data, QSet<QString> &knownTargets);
Target *extractTargetData(const QVariantMap &data, Project *p, QSet<QString> &knownTargets);
FileGroup *extractFileGroupData(const QVariantMap &data, const QDir &srcDir, Target *t);
+ QList<CrossReference *> extractCrossReferences(const QVariantMap &data);
+ QList<BacktraceItem *> extractBacktrace(const QVariantList &data);
+ BacktraceItem *extractBacktraceItem(const QVariantMap &data);
void extractCMakeInputsData(const QVariantMap &data);
void extractCacheData(const QVariantMap &data);
diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp
index eed99dad19..2fbe12d28d 100644
--- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp
+++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp
@@ -384,10 +384,13 @@ void TeaLeafReader::updateCodeModel(CppTools::RawProjectParts &rpps)
cxxProjectFlags.commandLineFlags = cxxflags;
rpp.setFlagsForCxx(cxxProjectFlags);
- rpp.setDefines(cbt.defines);
+ rpp.setMacros(cbt.macros);
rpp.setDisplayName(cbt.title);
rpp.setFiles(transform(cbt.files, [](const FileName &fn) { return fn.toString(); }));
+ const bool isExecutable = cbt.targetType == ExecutableType;
+ rpp.setBuildTargetType(isExecutable ? CppTools::ProjectPart::Executable
+ : CppTools::ProjectPart::Library);
rpps.append(rpp);
}
}
@@ -554,7 +557,7 @@ void TeaLeafReader::processCMakeOutput()
{
static QString rest;
rest = lineSplit(rest, m_cmakeProcess->readAllStandardOutput(),
- [this](const QString &s) { MessageManager::write(s); });
+ [](const QString &s) { MessageManager::write(s); });
}
void TeaLeafReader::processCMakeError()
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.h b/src/plugins/coreplugin/actionmanager/actionmanager.h
index 2f29eac491..e8c661b989 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager.h
@@ -35,7 +35,6 @@
QT_BEGIN_NAMESPACE
class QAction;
-class QSettings;
class QString;
QT_END_NAMESPACE
diff --git a/src/plugins/coreplugin/actionmanager/actionmanager_p.h b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
index 0269fc4992..5ac100ba78 100644
--- a/src/plugins/coreplugin/actionmanager/actionmanager_p.h
+++ b/src/plugins/coreplugin/actionmanager/actionmanager_p.h
@@ -34,18 +34,12 @@
#include <QMultiHash>
#include <QTimer>
-QT_BEGIN_NAMESPACE
-class QLabel;
-class QSettings;
-QT_END_NAMESPACE
-
namespace Core {
namespace Internal {
class Action;
class ActionContainerPrivate;
-class MainWindow;
class ActionManagerPrivate : public QObject
{
diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.h b/src/plugins/coreplugin/actionmanager/commandmappings.h
index 89abe7efb0..ddfd7ff280 100644
--- a/src/plugins/coreplugin/actionmanager/commandmappings.h
+++ b/src/plugins/coreplugin/actionmanager/commandmappings.h
@@ -30,7 +30,6 @@
#include <QWidget>
QT_BEGIN_NAMESPACE
-class QLineEdit;
class QTreeWidget;
class QTreeWidgetItem;
QT_END_NAMESPACE
diff --git a/src/plugins/coreplugin/actionmanager/commandsfile.cpp b/src/plugins/coreplugin/actionmanager/commandsfile.cpp
index 5eba33f8bd..d6bbd7f2cb 100644
--- a/src/plugins/coreplugin/actionmanager/commandsfile.cpp
+++ b/src/plugins/coreplugin/actionmanager/commandsfile.cpp
@@ -26,11 +26,10 @@
#include "commandsfile.h"
#include "command_p.h"
#include <coreplugin/dialogs/shortcutsettings.h>
+#include <coreplugin/icore.h>
#include <app/app_version.h>
-
#include <utils/qtcassert.h>
-
#include <utils/fileutils.h>
#include <QKeySequence>
@@ -137,8 +136,8 @@ bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
w.setAutoFormattingIndent(1); // Historical, used to be QDom.
w.writeStartDocument();
w.writeDTD(QLatin1String("<!DOCTYPE KeyboardMappingScheme>"));
- w.writeComment(QString::fromLatin1(" Written by Qt Creator %1, %2. ").
- arg(QLatin1String(Constants::IDE_VERSION_LONG),
+ w.writeComment(QString::fromLatin1(" Written by %1, %2. ").
+ arg(ICore::versionString(),
QDateTime::currentDateTime().toString(Qt::ISODate)));
w.writeStartElement(ctx.mappingElement);
foreach (const ShortcutItem *item, items) {
diff --git a/src/plugins/coreplugin/basefilewizardfactory.h b/src/plugins/coreplugin/basefilewizardfactory.h
index 61972f17e1..8e68fb0722 100644
--- a/src/plugins/coreplugin/basefilewizardfactory.h
+++ b/src/plugins/coreplugin/basefilewizardfactory.h
@@ -34,10 +34,8 @@
#include <QVariantMap>
QT_BEGIN_NAMESPACE
-class QIcon;
class QWizard;
class QWizardPage;
-class QDebug;
QT_END_NAMESPACE
namespace Utils { class Wizard; }
diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h
index 78c7ae6011..aa9b9fbbc2 100644
--- a/src/plugins/coreplugin/coreconstants.h
+++ b/src/plugins/coreplugin/coreconstants.h
@@ -207,7 +207,8 @@ const char TR_CLEAR_MENU[] = QT_TRANSLATE_NOOP("Core", "Clear Menu");
const char DEFAULT_BUILD_DIRECTORY[] = "../%{JS: Util.asciify(\"build-%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}\")}";
-const int TARGET_ICON_SIZE = 32;
+const int MODEBAR_ICON_SIZE = 34;
+const int DEFAULT_MAX_LINE_COUNT = 100000;
} // namespace Constants
} // namespace Core
diff --git a/src/plugins/coreplugin/corejsextensions.cpp b/src/plugins/coreplugin/corejsextensions.cpp
index 21017f8aac..7398d60a94 100644
--- a/src/plugins/coreplugin/corejsextensions.cpp
+++ b/src/plugins/coreplugin/corejsextensions.cpp
@@ -144,7 +144,7 @@ QString UtilsJsExtension::mktemp(const QString &pattern) const
QString UtilsJsExtension::asciify(const QString &input) const
{
QString result;
- for (const QChar c : input) {
+ for (const QChar &c : input) {
if (c.isPrint() && c.unicode() < 128)
result.append(c);
else
diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp
index c005b90eaa..b644906cd7 100644
--- a/src/plugins/coreplugin/coreplugin.cpp
+++ b/src/plugins/coreplugin/coreplugin.cpp
@@ -44,6 +44,7 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/fileutils.h>
+#include <app/app_version.h>
#include <extensionsystem/pluginerroroverview.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
@@ -183,18 +184,25 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
expander->registerVariable("CurrentTime:Locale", tr("The current time (Locale)."),
[]() { return QTime::currentTime().toString(Qt::DefaultLocaleShortDate); });
expander->registerVariable("Config:DefaultProjectDirectory", tr("The configured default directory for projects."),
- []() { return DocumentManager::projectsDirectory(); });
+ []() { return DocumentManager::projectsDirectory().toString(); });
expander->registerVariable("Config:LastFileDialogDirectory", tr("The directory last visited in a file dialog."),
[]() { return DocumentManager::fileDialogLastVisitedDirectory(); });
- expander->registerVariable("HostOs:isWindows", tr("Is Qt Creator running on Windows?"),
+ expander->registerVariable("HostOs:isWindows",
+ tr("Is %1 running on Windows?").arg(Constants::IDE_DISPLAY_NAME),
[]() { return QVariant(Utils::HostOsInfo::isWindowsHost()).toString(); });
- expander->registerVariable("HostOs:isOSX", tr("Is Qt Creator running on OS X?"),
+ expander->registerVariable("HostOs:isOSX",
+ tr("Is %1 running on OS X?").arg(Constants::IDE_DISPLAY_NAME),
[]() { return QVariant(Utils::HostOsInfo::isMacHost()).toString(); });
- expander->registerVariable("HostOs:isLinux", tr("Is Qt Creator running on Linux?"),
+ expander->registerVariable("HostOs:isLinux",
+ tr("Is %1 running on Linux?").arg(Constants::IDE_DISPLAY_NAME),
[]() { return QVariant(Utils::HostOsInfo::isLinuxHost()).toString(); });
- expander->registerVariable("HostOs:isUnix", tr("Is Qt Creator running on any unix-based platform?"),
+ expander->registerVariable("HostOs:isUnix",
+ tr("Is %1 running on any unix-based platform?")
+ .arg(Constants::IDE_DISPLAY_NAME),
[]() { return QVariant(Utils::HostOsInfo::isAnyUnixHost()).toString(); });
- expander->registerVariable("IDE:ResourcePath", tr("The directory where Qt Creator finds its pre-installed resources."),
+ expander->registerVariable("IDE:ResourcePath",
+ tr("The directory where %1 finds its pre-installed resources.")
+ .arg(Constants::IDE_DISPLAY_NAME),
[]() { return ICore::resourcePath(); });
expander->registerPrefix("CurrentDate:", tr("The current date (QDate formatstring)."),
[](const QString &fmt) { return QDate::currentDate().toString(fmt); });
@@ -203,7 +211,7 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
expander->registerVariable("UUID", tr("Generate a new UUID."),
[]() { return QUuid::createUuid().toString(); });
- expander->registerPrefix("#:", tr("A comment."), [](const QString &) { return QStringLiteral(""); });
+ expander->registerPrefix("#:", tr("A comment."), [](const QString &) { return QString(); });
// Make sure all wizards are there when the user might access the keyboard shortcuts:
connect(ICore::instance(), &ICore::optionsDialogRequested, []() { IWizardFactory::allWizardFactories(); });
diff --git a/src/plugins/coreplugin/coreplugin.h b/src/plugins/coreplugin/coreplugin.h
index 7a69887c36..2f86226a71 100644
--- a/src/plugins/coreplugin/coreplugin.h
+++ b/src/plugins/coreplugin/coreplugin.h
@@ -35,7 +35,6 @@ QT_END_NAMESPACE
namespace Utils {
class PathChooser;
-class Theme;
}
namespace Core {
diff --git a/src/plugins/coreplugin/dialogs/newdialog.h b/src/plugins/coreplugin/dialogs/newdialog.h
index 5d73546aa9..9461efae26 100644
--- a/src/plugins/coreplugin/dialogs/newdialog.h
+++ b/src/plugins/coreplugin/dialogs/newdialog.h
@@ -39,7 +39,6 @@ class QSortFilterProxyModel;
class QPushButton;
class QStandardItem;
class QStandardItemModel;
-class QStringList;
QT_END_NAMESPACE
namespace Core {
diff --git a/src/plugins/coreplugin/dialogs/openwithdialog.h b/src/plugins/coreplugin/dialogs/openwithdialog.h
index d93ea71d6d..a3f0db0366 100644
--- a/src/plugins/coreplugin/dialogs/openwithdialog.h
+++ b/src/plugins/coreplugin/dialogs/openwithdialog.h
@@ -30,7 +30,6 @@
namespace Core {
-class ICore;
namespace Internal {
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.h b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
index 1048ca0348..37d321fade 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.h
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
@@ -30,18 +30,12 @@
#include "ui_saveitemsdialog.h"
-QT_BEGIN_NAMESPACE
-class QCheckBox;
-QT_END_NAMESPACE
-
namespace Core {
class IDocument;
-class EditorManager;
namespace Internal {
-class MainWindow;
class SaveItemsDialog : public QDialog
{
diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.h b/src/plugins/coreplugin/dialogs/shortcutsettings.h
index 4607d68419..c3359f0064 100644
--- a/src/plugins/coreplugin/dialogs/shortcutsettings.h
+++ b/src/plugins/coreplugin/dialogs/shortcutsettings.h
@@ -36,7 +36,6 @@
QT_BEGIN_NAMESPACE
class QGroupBox;
-class QKeyEvent;
class QLabel;
QT_END_NAMESPACE
@@ -47,7 +46,6 @@ class Command;
namespace Internal {
class ActionManagerPrivate;
-class MainWindow;
struct ShortcutItem
{
diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp
index 30da372eaf..43b6cb212f 100644
--- a/src/plugins/coreplugin/documentmanager.cpp
+++ b/src/plugins/coreplugin/documentmanager.cpp
@@ -54,6 +54,7 @@
#include <QFile>
#include <QFileInfo>
#include <QFileSystemWatcher>
+#include <QLoggingCategory>
#include <QSettings>
#include <QTimer>
#include <QAction>
@@ -62,6 +63,8 @@
#include <QMenu>
#include <QMessageBox>
+Q_LOGGING_CATEGORY(log, "qtc.core.documentmanager")
+
/*!
\class Core::DocumentManager
\mainclass
@@ -124,6 +127,7 @@ struct FileStateItem
struct FileState
{
+ QString watchedFilePath;
QMap<IDocument *, FileStateItem> lastUpdatedState;
FileStateItem expected;
};
@@ -140,29 +144,29 @@ public:
void checkOnNextFocusChange();
void onApplicationFocusChange();
- QMap<QString, FileState> m_states;
- QSet<QString> m_changedFiles;
+ QMap<QString, FileState> m_states; // filePathKey -> FileState
+ QSet<QString> m_changedFiles; // watched file paths collected from file watcher notifications
QList<IDocument *> m_documentsWithoutWatch;
- QMap<IDocument *, QStringList> m_documentsWithWatch;
- QSet<QString> m_expectedFileNames;
+ QMap<IDocument *, QStringList> m_documentsWithWatch; // document -> list of filePathKeys
+ QSet<QString> m_expectedFileNames; // set of file names without normalization
QList<DocumentManager::RecentFile> m_recentFiles;
static const int m_maxRecentFiles = 7;
- QFileSystemWatcher *m_fileWatcher; // Delayed creation.
- QFileSystemWatcher *m_linkWatcher; // Delayed creation (only UNIX/if a link is seen).
- bool m_blockActivated;
+ QFileSystemWatcher *m_fileWatcher = nullptr; // Delayed creation.
+ QFileSystemWatcher *m_linkWatcher = nullptr; // Delayed creation (only UNIX/if a link is seen).
+ bool m_blockActivated = false;
bool m_checkOnFocusChange = false;
- QString m_lastVisitedDirectory;
+ QString m_lastVisitedDirectory = QDir::currentPath();
QString m_defaultLocationForNewFiles;
- QString m_projectsDirectory;
- bool m_useProjectsDirectory;
+ FileName m_projectsDirectory;
+ bool m_useProjectsDirectory = true;
QString m_buildDirectory;
// When we are calling into an IDocument
// we don't want to receive a changed()
// signal
// That makes the code easier
- IDocument *m_blockedIDocument;
+ IDocument *m_blockedIDocument = nullptr;
};
static DocumentManager *m_instance;
@@ -206,13 +210,7 @@ void DocumentManagerPrivate::onApplicationFocusChange()
m_instance->checkForReload();
}
-DocumentManagerPrivate::DocumentManagerPrivate() :
- m_fileWatcher(0),
- m_linkWatcher(0),
- m_blockActivated(false),
- m_lastVisitedDirectory(QDir::currentPath()),
- m_useProjectsDirectory(true),
- m_blockedIDocument(0)
+DocumentManagerPrivate::DocumentManagerPrivate()
{
connect(qApp, &QApplication::focusChanged, this, &DocumentManagerPrivate::onApplicationFocusChange);
}
@@ -234,7 +232,7 @@ DocumentManager::DocumentManager(QObject *parent)
readSettings();
if (d->m_useProjectsDirectory)
- setFileDialogLastVisitedDirectory(d->m_projectsDirectory);
+ setFileDialogLastVisitedDirectory(d->m_projectsDirectory.toString());
}
DocumentManager::~DocumentManager()
@@ -248,28 +246,37 @@ DocumentManager *DocumentManager::instance()
}
/* only called from addFileInfo(IDocument *) */
-static void addFileInfo(const QString &fileName, IDocument *document, bool isLink)
+static void addFileInfo(IDocument *document, const QString &filePath,
+ const QString &filePathKey, bool isLink)
{
FileStateItem state;
- if (!fileName.isEmpty()) {
- const QFileInfo fi(fileName);
+ if (!filePath.isEmpty()) {
+ qCDebug(log) << "adding document for" << filePath << "(" << filePathKey << ")";
+ const QFileInfo fi(filePath);
state.modified = fi.lastModified();
state.permissions = fi.permissions();
- // Add watcher if we don't have that already
- if (!d->m_states.contains(fileName))
- d->m_states.insert(fileName, FileState());
-
- QFileSystemWatcher *watcher = 0;
+ // Add state if we don't have already
+ if (!d->m_states.contains(filePathKey)) {
+ FileState state;
+ state.watchedFilePath = filePath;
+ d->m_states.insert(filePathKey, state);
+ }
+ // Add or update watcher on file path
+ // This is also used to update the watcher in case of saved (==replaced) files or
+ // update link targets, even if there are multiple documents registered for it
+ const QString watchedFilePath = d->m_states.value(filePathKey).watchedFilePath;
+ qCDebug(log) << "adding (" << (isLink ? "link" : "full") << ") watch for"
+ << watchedFilePath;
+ QFileSystemWatcher *watcher = nullptr;
if (isLink)
watcher = d->linkWatcher();
else
watcher = d->fileWatcher();
- if (!watcher->files().contains(fileName))
- watcher->addPath(fileName);
+ watcher->addPath(watchedFilePath);
- d->m_states[fileName].lastUpdatedState.insert(document, state);
+ d->m_states[filePathKey].lastUpdatedState.insert(document, state);
}
- d->m_documentsWithWatch[document].append(fileName); // inserts a new QStringList if not already there
+ d->m_documentsWithWatch[document].append(filePathKey); // inserts a new QStringList if not already there
}
/* Adds the IDocument's file and possibly it's final link target to both m_states
@@ -278,11 +285,19 @@ static void addFileInfo(const QString &fileName, IDocument *document, bool isLin
(The added file names are guaranteed to be absolute and cleaned.) */
static void addFileInfo(IDocument *document)
{
- const QString fixedName = DocumentManager::fixFileName(document->filePath().toString(), DocumentManager::KeepLinks);
- const QString fixedResolvedName = DocumentManager::fixFileName(document->filePath().toString(), DocumentManager::ResolveLinks);
- addFileInfo(fixedResolvedName, document, false);
- if (fixedName != fixedResolvedName)
- addFileInfo(fixedName, document, true);
+ const QString documentFilePath = document->filePath().toString();
+ const QString filePath = DocumentManager::cleanAbsoluteFilePath(
+ documentFilePath, DocumentManager::KeepLinks);
+ const QString filePathKey = DocumentManager::filePathKey(
+ documentFilePath, DocumentManager::KeepLinks);
+ const QString resolvedFilePath = DocumentManager::cleanAbsoluteFilePath(
+ documentFilePath, DocumentManager::ResolveLinks);
+ const QString resolvedFilePathKey = DocumentManager::filePathKey(
+ documentFilePath, DocumentManager::ResolveLinks);
+ const bool isLink = filePath != resolvedFilePath;
+ addFileInfo(document, filePath, filePathKey, isLink);
+ if (isLink)
+ addFileInfo(document, resolvedFilePath, resolvedFilePathKey, false);
}
/*!
@@ -330,12 +345,18 @@ static void removeFileInfo(IDocument *document)
foreach (const QString &fileName, d->m_documentsWithWatch.value(document)) {
if (!d->m_states.contains(fileName))
continue;
+ qCDebug(log) << "removing document (" << fileName << ")";
d->m_states[fileName].lastUpdatedState.remove(document);
if (d->m_states.value(fileName).lastUpdatedState.isEmpty()) {
- if (d->m_fileWatcher && d->m_fileWatcher->files().contains(fileName))
- d->m_fileWatcher->removePath(fileName);
- if (d->m_linkWatcher && d->m_linkWatcher->files().contains(fileName))
- d->m_linkWatcher->removePath(fileName);
+ const QString &watchedFilePath = d->m_states.value(fileName).watchedFilePath;
+ if (d->m_fileWatcher && d->m_fileWatcher->files().contains(watchedFilePath)) {
+ qCDebug(log) << "removing watch for" << watchedFilePath;
+ d->m_fileWatcher->removePath(watchedFilePath);
+ }
+ if (d->m_linkWatcher && d->m_linkWatcher->files().contains(watchedFilePath)) {
+ qCDebug(log) << "removing watch for" << watchedFilePath;
+ d->m_linkWatcher->removePath(watchedFilePath);
+ }
d->m_states.remove(fileName);
}
}
@@ -388,14 +409,14 @@ static void dump()
*/
void DocumentManager::renamedFile(const QString &from, const QString &to)
{
- const QString &fixedFrom = fixFileName(from, KeepLinks);
+ const QString &fromKey = filePathKey(from, KeepLinks);
// gather the list of IDocuments
QList<IDocument *> documentsToRename;
QMapIterator<IDocument *, QStringList> it(d->m_documentsWithWatch);
while (it.hasNext()) {
it.next();
- if (it.value().contains(fixedFrom))
+ if (it.value().contains(fromKey))
documentsToRename.append(it.key());
}
@@ -405,7 +426,7 @@ void DocumentManager::renamedFile(const QString &from, const QString &to)
removeFileInfo(document);
document->setFilePath(FileName::fromString(to));
addFileInfo(document);
- d->m_blockedIDocument = 0;
+ d->m_blockedIDocument = nullptr;
}
emit m_instance->allDocumentsRenamed(from, to);
}
@@ -478,23 +499,29 @@ void DocumentManager::checkForNewFileName()
}
/*!
- Returns a guaranteed cleaned path in native form. If the file exists,
- it will either be a cleaned absolute file path (fixmode == KeepLinks), or
- a cleaned canonical file path (fixmode == ResolveLinks).
+ Returns a guaranteed cleaned absolute file path for \a filePath in portable form.
+ Resolves symlinks if \a resolveMode is ResolveLinks.
*/
-QString DocumentManager::fixFileName(const QString &fileName, FixMode fixmode)
+QString DocumentManager::cleanAbsoluteFilePath(const QString &filePath, ResolveMode resolveMode)
{
- QString s = fileName;
- QFileInfo fi(s);
- if (fi.exists()) {
- if (fixmode == ResolveLinks)
- s = fi.canonicalFilePath();
- else
- s = QDir::cleanPath(fi.absoluteFilePath());
- } else {
- s = QDir::cleanPath(s);
+ QFileInfo fi(QDir::fromNativeSeparators(filePath));
+ if (fi.exists() && resolveMode == ResolveLinks) {
+ // if the filePath is no link, we want this method to return the same for both ResolveModes
+ // so wrap with absoluteFilePath because that forces drive letters upper case
+ return QFileInfo(fi.canonicalFilePath()).absoluteFilePath();
}
- s = QDir::toNativeSeparators(s);
+ return QDir::cleanPath(fi.absoluteFilePath());
+}
+
+/*!
+ Returns a representation of \a filePath that can be used as a key for maps.
+ (A cleaned absolute file path in portable form, that is all lowercase
+ if the file system is case insensitive (in the host OS settings).)
+ Resolves symlinks if \a resolveMode is ResolveLinks.
+*/
+QString DocumentManager::filePathKey(const QString &filePath, ResolveMode resolveMode)
+{
+ QString s = cleanAbsoluteFilePath(filePath, resolveMode);
if (HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
s = s.toLower();
return s;
@@ -533,14 +560,14 @@ void DocumentManager::expectFileChange(const QString &fileName)
}
/* only called from unblock and unexpect file change functions */
-static void updateExpectedState(const QString &fileName)
+static void updateExpectedState(const QString &filePathKey)
{
- if (fileName.isEmpty())
+ if (filePathKey.isEmpty())
return;
- if (d->m_states.contains(fileName)) {
- QFileInfo fi(fileName);
- d->m_states[fileName].expected.modified = fi.lastModified();
- d->m_states[fileName].expected.permissions = fi.permissions();
+ if (d->m_states.contains(filePathKey)) {
+ QFileInfo fi(d->m_states.value(filePathKey).watchedFilePath);
+ d->m_states[filePathKey].expected.modified = fi.lastModified();
+ d->m_states[filePathKey].expected.permissions = fi.permissions();
}
}
@@ -559,11 +586,11 @@ void DocumentManager::unexpectFileChange(const QString &fileName)
if (fileName.isEmpty())
return;
d->m_expectedFileNames.remove(fileName);
- const QString fixedName = fixFileName(fileName, KeepLinks);
- updateExpectedState(fixedName);
- const QString fixedResolvedName = fixFileName(fileName, ResolveLinks);
- if (fixedName != fixedResolvedName)
- updateExpectedState(fixedResolvedName);
+ const QString cleanAbsFilePath = cleanAbsoluteFilePath(fileName, KeepLinks);
+ updateExpectedState(filePathKey(fileName, KeepLinks));
+ const QString resolvedCleanAbsFilePath = cleanAbsoluteFilePath(fileName, ResolveLinks);
+ if (cleanAbsFilePath != resolvedCleanAbsFilePath)
+ updateExpectedState(filePathKey(fileName, ResolveLinks));
}
static bool saveModifiedFilesHelper(const QList<IDocument *> &documents,
@@ -587,7 +614,7 @@ static bool saveModifiedFilesHelper(const QList<IDocument *> &documents,
// There can be several IDocuments pointing to the same file
// Prefer one that is not readonly
// (even though it *should* not happen that the IDocuments are inconsistent with readonly)
- if (!modifiedDocumentsMap.key(name, 0) || !document->isFileReadOnly())
+ if (!modifiedDocumentsMap.key(name, nullptr) || !document->isFileReadOnly())
modifiedDocumentsMap.insert(document, name);
}
}
@@ -797,10 +824,17 @@ bool DocumentManager::saveAllModifiedDocumentsSilently(bool *canceled,
\a FailedToClose will contain a list of documents that could not be saved if passed into the
method.
*/
-bool DocumentManager::saveModifiedDocumentsSilently(const QList<IDocument *> &documents, bool *canceled,
+bool DocumentManager::saveModifiedDocumentsSilently(const QList<IDocument *> &documents,
+ bool *canceled,
QList<IDocument *> *failedToClose)
{
- return saveModifiedFilesHelper(documents, QString(), canceled, true, QString(), 0, failedToClose);
+ return saveModifiedFilesHelper(documents,
+ QString(),
+ canceled,
+ true,
+ QString(),
+ nullptr,
+ failedToClose);
}
/*!
@@ -907,8 +941,9 @@ void DocumentManager::changedFile(const QString &fileName)
{
const bool wasempty = d->m_changedFiles.isEmpty();
- if (d->m_states.contains(fileName))
+ if (d->m_states.contains(filePathKey(fileName, KeepLinks)))
d->m_changedFiles.insert(fileName);
+ qCDebug(log) << "file change notification for" << fileName;
if (wasempty && !d->m_changedFiles.isEmpty())
QTimer::singleShot(200, this, &DocumentManager::checkForReload);
@@ -948,18 +983,23 @@ void DocumentManager::checkForReload()
QMap<QString, IDocument::ChangeType> changeTypes;
QSet<IDocument *> changedIDocuments;
foreach (const QString &fileName, d->m_changedFiles) {
+ const QString fileKey = filePathKey(fileName, KeepLinks);
+ qCDebug(log) << "handling file change for" << fileName << "(" << fileKey << ")";
IDocument::ChangeType type = IDocument::TypeContents;
FileStateItem state;
QFileInfo fi(fileName);
if (!fi.exists()) {
+ qCDebug(log) << "file was removed";
type = IDocument::TypeRemoved;
} else {
state.modified = fi.lastModified();
state.permissions = fi.permissions();
+ qCDebug(log) << "file was modified, time:" << state.modified
+ << "permissions: " << state.permissions;
}
- currentStates.insert(fileName, state);
- changeTypes.insert(fileName, type);
- foreach (IDocument *document, d->m_states.value(fileName).lastUpdatedState.keys())
+ currentStates.insert(fileKey, state);
+ changeTypes.insert(fileKey, type);
+ foreach (IDocument *document, d->m_states.value(fileKey).lastUpdatedState.keys())
changedIDocuments.insert(document);
}
@@ -971,13 +1011,13 @@ void DocumentManager::checkForReload()
// we can't do the "resolving" already in expectFileChange, because
// if the resolved names are different when unexpectFileChange is called
// we would end up with never-unexpected file names
- QSet<QString> expectedFileNames;
+ QSet<QString> expectedFileKeys;
foreach (const QString &fileName, d->m_expectedFileNames) {
- const QString fixedName = fixFileName(fileName, KeepLinks);
- expectedFileNames.insert(fixedName);
- const QString fixedResolvedName = fixFileName(fileName, ResolveLinks);
- if (fixedName != fixedResolvedName)
- expectedFileNames.insert(fixedResolvedName);
+ const QString cleanAbsFilePath = cleanAbsoluteFilePath(fileName, KeepLinks);
+ expectedFileKeys.insert(filePathKey(fileName, KeepLinks));
+ const QString resolvedCleanAbsFilePath = cleanAbsoluteFilePath(fileName, ResolveLinks);
+ if (cleanAbsFilePath != resolvedCleanAbsFilePath)
+ expectedFileKeys.insert(filePathKey(fileName, ResolveLinks));
}
// handle the IDocuments
@@ -990,14 +1030,14 @@ void DocumentManager::checkForReload()
// find out the type & behavior from the two possible files
// behavior is internal if all changes are expected (and none removed)
// type is "max" of both types (remove > contents > permissions)
- foreach (const QString & fileName, d->m_documentsWithWatch.value(document)) {
+ foreach (const QString &fileKey, d->m_documentsWithWatch.value(document)) {
// was the file reported?
- if (!currentStates.contains(fileName))
+ if (!currentStates.contains(fileKey))
continue;
- FileStateItem currentState = currentStates.value(fileName);
- FileStateItem expectedState = d->m_states.value(fileName).expected;
- FileStateItem lastState = d->m_states.value(fileName).lastUpdatedState.value(document);
+ FileStateItem currentState = currentStates.value(fileKey);
+ FileStateItem expectedState = d->m_states.value(fileKey).expected;
+ FileStateItem lastState = d->m_states.value(fileKey).lastUpdatedState.value(document);
// did the file actually change?
if (lastState.modified == currentState.modified && lastState.permissions == currentState.permissions)
@@ -1010,12 +1050,12 @@ void DocumentManager::checkForReload()
// was the change unexpected?
if ((currentState.modified != expectedState.modified || currentState.permissions != expectedState.permissions)
- && !expectedFileNames.contains(fileName)) {
+ && !expectedFileKeys.contains(fileKey)) {
trigger = IDocument::TriggerExternal;
}
// find out the type
- IDocument::ChangeType fileChange = changeTypes.value(fileName);
+ IDocument::ChangeType fileChange = changeTypes.value(fileKey);
if (fileChange == IDocument::TypeRemoved)
type = IDocument::TypeRemoved;
else if (fileChange == IDocument::TypeContents && type == IDocument::TypePermissions)
@@ -1142,7 +1182,7 @@ void DocumentManager::checkForReload()
errorStrings << errorString;
}
- d->m_blockedIDocument = 0;
+ d->m_blockedIDocument = nullptr;
}
if (!filesToDiff.isEmpty()) {
@@ -1179,12 +1219,12 @@ void DocumentManager::addToRecentFiles(const QString &fileName, Id editorId)
{
if (fileName.isEmpty())
return;
- QString unifiedForm(fixFileName(fileName, KeepLinks));
+ QString fileKey = filePathKey(fileName, KeepLinks);
QMutableListIterator<RecentFile > it(d->m_recentFiles);
while (it.hasNext()) {
RecentFile file = it.next();
- QString recentUnifiedForm(fixFileName(file.first, DocumentManager::KeepLinks));
- if (unifiedForm == recentUnifiedForm)
+ QString recentFileKey(filePathKey(file.first, DocumentManager::KeepLinks));
+ if (fileKey == recentFileKey)
it.remove();
}
if (d->m_recentFiles.count() > d->m_maxRecentFiles)
@@ -1224,7 +1264,7 @@ void DocumentManager::saveSettings()
s->setValue(QLatin1String(editorsKeyC), recentEditorIds);
s->endGroup();
s->beginGroup(QLatin1String(directoryGroupC));
- s->setValue(QLatin1String(projectDirectoryKeyC), d->m_projectsDirectory);
+ s->setValue(QLatin1String(projectDirectoryKeyC), d->m_projectsDirectory.toString());
s->setValue(QLatin1String(useProjectDirectoryKeyC), d->m_useProjectsDirectory);
s->setValue(QLatin1String(buildDirectoryKeyC), d->m_buildDirectory);
s->endGroup();
@@ -1250,12 +1290,12 @@ void readSettings()
}
s->beginGroup(QLatin1String(directoryGroupC));
- const QString settingsProjectDir = s->value(QLatin1String(projectDirectoryKeyC),
- QString()).toString();
- if (!settingsProjectDir.isEmpty() && QFileInfo(settingsProjectDir).isDir())
+ const FileName settingsProjectDir = FileName::fromString(s->value(QLatin1String(projectDirectoryKeyC),
+ QString()).toString());
+ if (!settingsProjectDir.isEmpty() && settingsProjectDir.toFileInfo().isDir())
d->m_projectsDirectory = settingsProjectDir;
else
- d->m_projectsDirectory = PathChooser::homePath();
+ d->m_projectsDirectory = FileName::fromString(PathChooser::homePath());
d->m_useProjectsDirectory = s->value(QLatin1String(useProjectDirectoryKeyC),
d->m_useProjectsDirectory).toBool();
@@ -1315,7 +1355,7 @@ void DocumentManager::setDefaultLocationForNewFiles(const QString &location)
\sa setProjectsDirectory, setUseProjectsDirectory
*/
-QString DocumentManager::projectsDirectory()
+FileName DocumentManager::projectsDirectory()
{
return d->m_projectsDirectory;
}
@@ -1327,9 +1367,12 @@ QString DocumentManager::projectsDirectory()
\sa projectsDirectory, useProjectsDirectory
*/
-void DocumentManager::setProjectsDirectory(const QString &dir)
+void DocumentManager::setProjectsDirectory(const FileName &directory)
{
- d->m_projectsDirectory = dir;
+ if (d->m_projectsDirectory != directory) {
+ d->m_projectsDirectory = directory;
+ emit m_instance->projectsDirectoryChanged(d->m_projectsDirectory);
+ }
}
/*!
diff --git a/src/plugins/coreplugin/documentmanager.h b/src/plugins/coreplugin/documentmanager.h
index b259dfcaa5..0714cdf7bf 100644
--- a/src/plugins/coreplugin/documentmanager.h
+++ b/src/plugins/coreplugin/documentmanager.h
@@ -32,16 +32,12 @@
QT_BEGIN_NAMESPACE
class QStringList;
-class QAction;
-class QMainWindow;
-class QMenu;
QT_END_NAMESPACE
namespace Utils { class FileName; }
namespace Core {
-class IContext;
class IDocument;
namespace Internal {
@@ -53,7 +49,7 @@ class CORE_EXPORT DocumentManager : public QObject
{
Q_OBJECT
public:
- enum FixMode {
+ enum ResolveMode {
ResolveLinks,
KeepLinks
};
@@ -81,40 +77,50 @@ public:
static void saveSettings();
// helper functions
- static QString fixFileName(const QString &fileName, FixMode fixmode);
+ static QString cleanAbsoluteFilePath(const QString &filePath, ResolveMode resolveMode);
+ static QString filePathKey(const QString &filePath, ResolveMode resolveMode);
- static bool saveDocument(IDocument *document, const QString &fileName = QString(), bool *isReadOnly = 0);
+ static bool saveDocument(IDocument *document,
+ const QString &fileName = QString(),
+ bool *isReadOnly = nullptr);
static QStringList getOpenFileNames(const QString &filters,
const QString &path = QString(),
- QString *selectedFilter = 0);
- static QString getSaveFileName(const QString &title, const QString &pathIn,
- const QString &filter = QString(), QString *selectedFilter = 0);
+ QString *selectedFilter = nullptr);
+ static QString getSaveFileName(const QString &title,
+ const QString &pathIn,
+ const QString &filter = QString(),
+ QString *selectedFilter = nullptr);
static QString getSaveFileNameWithExtension(const QString &title, const QString &pathIn,
const QString &filter);
static QString getSaveAsFileName(const IDocument *document);
- static bool saveAllModifiedDocumentsSilently(bool *canceled = 0,
- QList<IDocument *> *failedToClose = 0);
- static bool saveModifiedDocumentsSilently(const QList<IDocument *> &documents, bool *canceled = 0,
- QList<IDocument *> *failedToClose = 0);
- static bool saveModifiedDocumentSilently(IDocument *document, bool *canceled = 0,
- QList<IDocument *> *failedToClose = 0);
-
- static bool saveAllModifiedDocuments(const QString &message = QString(), bool *canceled = 0,
+ static bool saveAllModifiedDocumentsSilently(bool *canceled = nullptr,
+ QList<IDocument *> *failedToClose = nullptr);
+ static bool saveModifiedDocumentsSilently(const QList<IDocument *> &documents,
+ bool *canceled = nullptr,
+ QList<IDocument *> *failedToClose = nullptr);
+ static bool saveModifiedDocumentSilently(IDocument *document,
+ bool *canceled = nullptr,
+ QList<IDocument *> *failedToClose = nullptr);
+
+ static bool saveAllModifiedDocuments(const QString &message = QString(),
+ bool *canceled = nullptr,
const QString &alwaysSaveMessage = QString(),
- bool *alwaysSave = 0,
- QList<IDocument *> *failedToClose = 0);
+ bool *alwaysSave = nullptr,
+ QList<IDocument *> *failedToClose = nullptr);
static bool saveModifiedDocuments(const QList<IDocument *> &documents,
- const QString &message = QString(), bool *canceled = 0,
+ const QString &message = QString(),
+ bool *canceled = nullptr,
const QString &alwaysSaveMessage = QString(),
- bool *alwaysSave = 0,
- QList<IDocument *> *failedToClose = 0);
+ bool *alwaysSave = nullptr,
+ QList<IDocument *> *failedToClose = nullptr);
static bool saveModifiedDocument(IDocument *document,
- const QString &message = QString(), bool *canceled = 0,
+ const QString &message = QString(),
+ bool *canceled = nullptr,
const QString &alwaysSaveMessage = QString(),
- bool *alwaysSave = 0,
- QList<IDocument *> *failedToClose = 0);
+ bool *alwaysSave = nullptr,
+ QList<IDocument *> *failedToClose = nullptr);
static QString fileDialogLastVisitedDirectory();
static void setFileDialogLastVisitedDirectory(const QString &);
@@ -127,8 +133,8 @@ public:
static bool useProjectsDirectory();
static void setUseProjectsDirectory(bool);
- static QString projectsDirectory();
- static void setProjectsDirectory(const QString &);
+ static Utils::FileName projectsDirectory();
+ static void setProjectsDirectory(const Utils::FileName &directory);
static QString buildDirectory();
static void setBuildDirectory(const QString &directory);
@@ -145,6 +151,7 @@ signals:
void allDocumentsRenamed(const QString &from, const QString &to);
/// emitted if one document changed its name e.g. due to save as
void documentRenamed(Core::IDocument *document, const QString &from, const QString &to);
+ void projectsDirectoryChanged(const Utils::FileName &directory);
protected:
bool eventFilter(QObject *obj, QEvent *e);
diff --git a/src/plugins/coreplugin/editormanager/documentmodel.cpp b/src/plugins/coreplugin/editormanager/documentmodel.cpp
index bf88039cc8..fb6bf68949 100644
--- a/src/plugins/coreplugin/editormanager/documentmodel.cpp
+++ b/src/plugins/coreplugin/editormanager/documentmodel.cpp
@@ -73,7 +73,7 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
const Utils::FileName fileName = entry->fileName();
QString fixedPath;
if (!fileName.isEmpty())
- fixedPath = DocumentManager::fixFileName(fileName.toString(), DocumentManager::ResolveLinks);
+ fixedPath = DocumentManager::filePathKey(fileName.toString(), DocumentManager::ResolveLinks);
// replace a non-loaded entry (aka 'suspended') if possible
int previousIndex = indexOfFilePath(fileName);
@@ -184,7 +184,7 @@ int DocumentModelPrivate::indexOfFilePath(const Utils::FileName &filePath) const
{
if (filePath.isEmpty())
return -1;
- const QString fixedPath = DocumentManager::fixFileName(filePath.toString(),
+ const QString fixedPath = DocumentManager::filePathKey(filePath.toString(),
DocumentManager::ResolveLinks);
return m_entries.indexOf(m_entryByFixedPath.value(fixedPath));
}
@@ -201,7 +201,7 @@ void DocumentModelPrivate::removeDocument(int idx)
const QString fileName = entry->fileName().toString();
if (!fileName.isEmpty()) {
- const QString fixedPath = DocumentManager::fixFileName(fileName,
+ const QString fixedPath = DocumentManager::filePathKey(fileName,
DocumentManager::ResolveLinks);
m_entryByFixedPath.remove(fixedPath);
}
@@ -298,7 +298,7 @@ void DocumentModelPrivate::itemChanged()
const QString fileName = document->filePath().toString();
QString fixedPath;
if (!fileName.isEmpty())
- fixedPath = DocumentManager::fixFileName(fileName, DocumentManager::ResolveLinks);
+ fixedPath = DocumentManager::filePathKey(fileName, DocumentManager::ResolveLinks);
DocumentModel::Entry *entry = m_entries.at(idx);
bool found = false;
// The entry's fileName might have changed, so find the previous fileName that was associated
@@ -367,6 +367,7 @@ DocumentModel::Entry *DocumentModelPrivate::removeEditor(IEditor *editor)
QTC_ASSERT(d->m_editors.contains(document), return nullptr);
d->m_editors[document].removeAll(editor);
DocumentModel::Entry *entry = DocumentModel::entryForDocument(document);
+ QTC_ASSERT(entry, return nullptr);
if (d->m_editors.value(document).isEmpty()) {
d->m_editors.remove(document);
entry->document = new IDocument;
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 9b2bd61748..261e3560d6 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -34,6 +34,8 @@
#include "documentmodel_p.h"
#include "ieditor.h"
+#include <app/app_version.h>
+
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
@@ -46,6 +48,7 @@
#include <coreplugin/editortoolbar.h>
#include <coreplugin/fileutils.h>
#include <coreplugin/findplaceholder.h>
+#include <coreplugin/find/searchresultitem.h>
#include <coreplugin/icore.h>
#include <coreplugin/imode.h>
#include <coreplugin/infobar.h>
@@ -248,6 +251,11 @@ void EditorManagerPrivate::init()
DocumentModel::init();
connect(ICore::instance(), &ICore::contextAboutToChange,
this, &EditorManagerPrivate::handleContextChange);
+ connect(qApp, &QApplication::applicationStateChanged,
+ this, [](Qt::ApplicationState state) {
+ if (state == Qt::ApplicationActive)
+ EditorManager::updateWindowTitles();
+ });
const Context editManagerContext(Constants::C_EDITORMANAGER);
// combined context for edit & design modes
@@ -380,7 +388,7 @@ void EditorManagerPrivate::init()
cmd = ActionManager::registerAction(m_splitAction, Constants::SPLIT, editManagerContext);
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+E,2") : tr("Ctrl+E,2")));
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
- connect(m_splitAction, &QAction::triggered, this, [this]() { split(Qt::Vertical); });
+ connect(m_splitAction, &QAction::triggered, this, []() { split(Qt::Vertical); });
m_splitSideBySideAction = new QAction(Utils::Icons::SPLIT_VERTICAL.icon(),
tr("Split Side by Side"), this);
@@ -394,7 +402,7 @@ void EditorManagerPrivate::init()
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+E,4") : tr("Ctrl+E,4")));
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_splitNewWindowAction, &QAction::triggered,
- this, [this]() { splitNewWindow(currentEditorView()); });
+ this, []() { splitNewWindow(currentEditorView()); });
m_removeCurrentSplitAction = new QAction(tr("Remove Current Split"), this);
cmd = ActionManager::registerAction(m_removeCurrentSplitAction, Constants::REMOVE_CURRENT_SPLIT, editManagerContext);
@@ -1789,7 +1797,7 @@ void EditorManagerPrivate::updateWindowTitleForDocument(IDocument *document, QWi
if (!windowTitle.isEmpty())
windowTitle.append(dashSep);
- windowTitle.append(tr("Qt Creator"));
+ windowTitle.append(Core::Constants::IDE_DISPLAY_NAME);
window->window()->setWindowTitle(windowTitle);
window->window()->setWindowFilePath(filePath);
@@ -2639,6 +2647,17 @@ IEditor *EditorManager::openEditorAt(const QString &fileName, int line, int colu
fileName, line, column, editorId, flags, newEditor);
}
+void EditorManager::openEditorAtSearchResult(const SearchResultItem &item, OpenEditorFlags flags)
+{
+ if (item.path.empty()) {
+ openEditor(QDir::fromNativeSeparators(item.text), Id(), flags);
+ return;
+ }
+
+ openEditorAt(QDir::fromNativeSeparators(item.path.first()), item.mainRange.begin.line,
+ item.mainRange.begin.column, Id(), flags);
+}
+
EditorManager::FilePathInfo EditorManager::splitLineAndColumnNumber(const QString &fullFilePath)
{
// :10:2 GCC/Clang-style
diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h
index 5c8c37113d..7b467ac1ac 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.h
+++ b/src/plugins/coreplugin/editormanager/editormanager.h
@@ -41,15 +41,11 @@ namespace Utils { class MimeType; }
namespace Core {
-class IContext;
class IEditor;
class IEditorFactory;
class IExternalEditor;
class IDocument;
-class IMode;
-class IVersionControl;
-
-class EditorToolBar;
+class SearchResultItem;
enum MakeWritableResult {
OpenedWithVersionControl,
@@ -59,13 +55,8 @@ enum MakeWritableResult {
};
namespace Internal {
-class EditorClosingCoreListener;
class EditorManagerPrivate;
-class EditorView;
class MainWindow;
-class OpenEditorsViewFactory;
-class OpenEditorsWindow;
-class SplitterOrView;
} // namespace Internal
class CORE_EXPORT EditorManagerPlaceHolder : public QWidget
@@ -114,6 +105,7 @@ public:
static IEditor *openEditorAt(const QString &fileName, int line, int column = 0,
Id editorId = Id(), OpenEditorFlags flags = NoFlags,
bool *newEditor = 0);
+ static void openEditorAtSearchResult(const SearchResultItem &item, OpenEditorFlags flags = NoFlags);
static IEditor *openEditorWithContents(Id editorId, QString *titlePattern = 0,
const QByteArray &contents = QByteArray(),
const QString &uniqueId = QString(),
diff --git a/src/plugins/coreplugin/editormanager/editorview.h b/src/plugins/coreplugin/editormanager/editorview.h
index abeb0f125e..6653616efd 100644
--- a/src/plugins/coreplugin/editormanager/editorview.h
+++ b/src/plugins/coreplugin/editormanager/editorview.h
@@ -41,8 +41,6 @@
#include <functional>
QT_BEGIN_NAMESPACE
-class QAction;
-class QComboBox;
class QFrame;
class QLabel;
class QMenu;
@@ -53,11 +51,9 @@ class QToolButton;
QT_END_NAMESPACE
namespace Core {
-class IContext;
class IDocument;
class IEditor;
class InfoBarDisplay;
-class DocumentModel;
class EditorToolBar;
namespace Internal {
diff --git a/src/plugins/coreplugin/editormanager/openeditorswindow.h b/src/plugins/coreplugin/editormanager/openeditorswindow.h
index e497411b77..9bd769bf8c 100644
--- a/src/plugins/coreplugin/editormanager/openeditorswindow.h
+++ b/src/plugins/coreplugin/editormanager/openeditorswindow.h
@@ -39,7 +39,6 @@ QT_END_NAMESPACE
namespace Core {
-class IDocument;
class IEditor;
namespace Internal {
@@ -51,7 +50,6 @@ public:
QSize sizeHint() const;
};
-class EditorHistoryItem;
class OpenEditorsWindow : public QFrame
{
diff --git a/src/plugins/coreplugin/externaltool.cpp b/src/plugins/coreplugin/externaltool.cpp
index 9903d58125..58abcae5b1 100644
--- a/src/plugins/coreplugin/externaltool.cpp
+++ b/src/plugins/coreplugin/externaltool.cpp
@@ -26,6 +26,7 @@
#include "externaltool.h"
#include "externaltoolmanager.h"
+#include "icore.h"
#include "idocument.h"
#include "messagemanager.h"
#include "documentmanager.h"
@@ -480,8 +481,8 @@ bool ExternalTool::save(QString *errorMessage) const
QXmlStreamWriter out(saver.file());
out.setAutoFormatting(true);
out.writeStartDocument(QLatin1String("1.0"));
- out.writeComment(QString::fromLatin1("Written on %1 by Qt Creator %2")
- .arg(QDateTime::currentDateTime().toString(), QLatin1String(Constants::IDE_VERSION_LONG)));
+ out.writeComment(QString::fromLatin1("Written on %1 by %2")
+ .arg(QDateTime::currentDateTime().toString(), ICore::versionString()));
out.writeStartElement(QLatin1String(kExternalTool));
out.writeAttribute(QLatin1String(kId), m_id);
out.writeTextElement(QLatin1String(kDescription), m_description);
diff --git a/src/plugins/coreplugin/externaltoolmanager.cpp b/src/plugins/coreplugin/externaltoolmanager.cpp
index c6ec74f28b..80d98243b6 100644
--- a/src/plugins/coreplugin/externaltoolmanager.cpp
+++ b/src/plugins/coreplugin/externaltoolmanager.cpp
@@ -77,7 +77,7 @@ ExternalToolManager::ExternalToolManager()
d->m_configureSeparator = new QAction(this);
d->m_configureSeparator->setSeparator(true);
d->m_configureAction = new QAction(ICore::msgShowOptionsDialog(), this);
- connect(d->m_configureAction, &QAction::triggered, [this] {
+ connect(d->m_configureAction, &QAction::triggered, this, [] {
ICore::showOptionsDialog(Constants::SETTINGS_ID_TOOLS);
});
diff --git a/src/plugins/coreplugin/fancyactionbar.cpp b/src/plugins/coreplugin/fancyactionbar.cpp
index 6cbaeea716..206e5e4d6e 100644
--- a/src/plugins/coreplugin/fancyactionbar.cpp
+++ b/src/plugins/coreplugin/fancyactionbar.cpp
@@ -178,7 +178,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
const QIcon::Mode iconMode = isEnabled() ? ((isDown() || isChecked()) ? QIcon::Active : QIcon::Normal)
: QIcon::Disabled;
- QRect iconRect(0, 0, Constants::TARGET_ICON_SIZE, Constants::TARGET_ICON_SIZE);
+ QRect iconRect(0, 0, Constants::MODEBAR_ICON_SIZE, Constants::MODEBAR_ICON_SIZE);
// draw popup texts
if (isTitledAction) {
@@ -203,7 +203,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
painter.setFont(normalFont);
QPoint textOffset = centerRect.center() - QPoint(iconRect.width()/2, iconRect.height()/2);
- textOffset = textOffset - QPoint(0, lineHeight + 4);
+ textOffset = textOffset - QPoint(0, lineHeight + 3);
QRectF r(0, textOffset.y(), rect().width(), lineHeight);
painter.setPen(creatorTheme()->color(isEnabled()
? Theme::PanelTextColorLight
@@ -218,8 +218,8 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
// draw build configuration name
textOffset = iconRect.center() + QPoint(iconRect.width()/2, iconRect.height()/2);
QRectF buildConfigRect[2];
- buildConfigRect[0] = QRectF(0, textOffset.y() + 5, rect().width(), lineHeight);
- buildConfigRect[1] = QRectF(0, textOffset.y() + 5 + lineHeight, rect().width(), lineHeight);
+ buildConfigRect[0] = QRectF(0, textOffset.y() + 4, rect().width(), lineHeight);
+ buildConfigRect[1] = QRectF(0, textOffset.y() + 4 + lineHeight, rect().width(), lineHeight);
painter.setFont(boldFont);
QVector<QString> splitBuildConfiguration(2);
const QString buildConfiguration = defaultAction()->property("subtitle").toString();
diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp
index e741aa87e6..cc0da7b753 100644
--- a/src/plugins/coreplugin/fancytabwidget.cpp
+++ b/src/plugins/coreplugin/fancytabwidget.cpp
@@ -25,6 +25,7 @@
#include "fancytabwidget.h"
#include "fancyactionbar.h"
+#include "coreconstants.h"
#include <utils/hostosinfo.h>
#include <utils/stylehelper.h>
@@ -48,9 +49,6 @@ using namespace Core;
using namespace Internal;
using namespace Utils;
-const int FancyTabBar::m_rounding = 22;
-const int FancyTabBar::m_textPadding = 4;
-
static const int kMenuButtonWidth = 16;
void FancyTab::fadeIn()
@@ -81,18 +79,12 @@ FancyTabBar::FancyTabBar(QWidget *parent)
m_hoverIndex = -1;
m_currentIndex = -1;
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
- setStyle(QStyleFactory::create(QLatin1String("windows")));
- setMinimumWidth(qMax(2 * m_rounding, 40));
+ setMinimumWidth(44);
setAttribute(Qt::WA_Hover, true);
setFocusPolicy(Qt::NoFocus);
setMouseTracking(true); // Needed for hover events
}
-FancyTabBar::~FancyTabBar()
-{
- delete style();
-}
-
QSize FancyTabBar::tabSizeHint(bool minimum) const
{
QFont boldFont(font());
@@ -333,7 +325,10 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
tabIconRect.adjust(0, 4, 0, -textHeight);
const QIcon::Mode iconMode = enabled ? (selected ? QIcon::Active : QIcon::Normal)
: QIcon::Disabled;
- StyleHelper::drawIconWithShadow(tab->icon, tabIconRect, painter, iconMode);
+ QRect iconRect(0, 0, Core::Constants::MODEBAR_ICON_SIZE, Core::Constants::MODEBAR_ICON_SIZE);
+ iconRect.moveCenter(tabIconRect.center());
+ iconRect = iconRect.intersected(tabIconRect);
+ StyleHelper::drawIconWithShadow(tab->icon, iconRect, painter, iconMode);
}
painter->setOpacity(1.0); //FIXME: was 0.7 before?
diff --git a/src/plugins/coreplugin/fancytabwidget.h b/src/plugins/coreplugin/fancytabwidget.h
index e6a871ea4e..5e71e4f183 100644
--- a/src/plugins/coreplugin/fancytabwidget.h
+++ b/src/plugins/coreplugin/fancytabwidget.h
@@ -74,7 +74,6 @@ class FancyTabBar : public QWidget
public:
FancyTabBar(QWidget *parent = 0);
- ~FancyTabBar();
bool event(QEvent *event);
@@ -122,8 +121,6 @@ signals:
void menuTriggered(int index, QMouseEvent *event);
private:
- static const int m_rounding;
- static const int m_textPadding;
QRect m_hoverRect;
int m_hoverIndex;
int m_currentIndex;
diff --git a/src/plugins/coreplugin/fileiconprovider.cpp b/src/plugins/coreplugin/fileiconprovider.cpp
index 4d6cf5ea48..e5606097cd 100644
--- a/src/plugins/coreplugin/fileiconprovider.cpp
+++ b/src/plugins/coreplugin/fileiconprovider.cpp
@@ -217,5 +217,18 @@ void registerIconOverlayForFilename(const QString &path, const QString &filename
instance()->registerIconOverlayForFilename(QIcon(path), filename);
}
+// Return a standard directory icon with the specified overlay:
+QIcon directoryIcon(const QString &overlay)
+{
+ // Overlay the SP_DirIcon with the custom icons
+ const QSize desiredSize = QSize(16, 16);
+
+ const QPixmap dirPixmap = QApplication::style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize);
+ const QIcon overlayIcon(overlay);
+ QIcon result;
+ result.addPixmap(Core::FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
+ return result;
+}
+
} // namespace FileIconProvider
} // namespace Core
diff --git a/src/plugins/coreplugin/fileiconprovider.h b/src/plugins/coreplugin/fileiconprovider.h
index dc7f57c299..9bfbc588e9 100644
--- a/src/plugins/coreplugin/fileiconprovider.h
+++ b/src/plugins/coreplugin/fileiconprovider.h
@@ -49,5 +49,7 @@ CORE_EXPORT void registerIconOverlayForFilename(const QString &path, const QStri
CORE_EXPORT void registerIconOverlayForMimeType(const QString &path, const QString &mimeType);
CORE_EXPORT void registerIconOverlayForMimeType(const QIcon &icon, const QString &mimeType);
+CORE_EXPORT QIcon directoryIcon(const QString &overlay);
+
} // namespace FileIconProvider
} // namespace Core
diff --git a/src/plugins/coreplugin/find/findplugin.cpp b/src/plugins/coreplugin/find/findplugin.cpp
index 9e8d3207be..7509d5c0df 100644
--- a/src/plugins/coreplugin/find/findplugin.cpp
+++ b/src/plugins/coreplugin/find/findplugin.cpp
@@ -192,7 +192,7 @@ void FindPrivate::setupMenu()
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F")));
mfindadvanced->addAction(cmd);
connect(m_openFindDialog, &QAction::triggered,
- this, [this] { Find::openFindDialog(nullptr); });
+ this, [] { Find::openFindDialog(nullptr); });
}
static QString filterActionName(const IFindFilter *filter)
@@ -220,8 +220,7 @@ void FindPrivate::setupFilterMenuItems()
cmd->setDefaultKeySequence(filter->defaultShortcut());
cmd->setAttribute(Command::CA_UpdateText);
mfindadvanced->addAction(cmd);
- connect(action, &QAction::triggered,
- this, [filter, action] { Find::openFindDialog(filter); });
+ connect(action, &QAction::triggered, this, [filter] { Find::openFindDialog(filter); });
connect(filter, &IFindFilter::enabledChanged, this, [filter, action] {
action->setEnabled(filter->isEnabled());
d->m_openFindDialog->setEnabled(d->isAnyFilterEnabled());
diff --git a/src/plugins/coreplugin/find/findtoolbar.cpp b/src/plugins/coreplugin/find/findtoolbar.cpp
index c4cfe718cf..8b9016d8f2 100644
--- a/src/plugins/coreplugin/find/findtoolbar.cpp
+++ b/src/plugins/coreplugin/find/findtoolbar.cpp
@@ -666,11 +666,11 @@ void FindToolBar::updateIcons()
bool regexp = effectiveFlags & FindRegularExpression;
bool preserveCase = effectiveFlags & FindPreserveCase;
if (!casesensitive && !wholewords && !regexp && !preserveCase) {
- const QPixmap pixmap = Utils::Icons::MAGNIFIER.pixmap();
- m_ui.findEdit->setButtonPixmap(Utils::FancyLineEdit::Left, pixmap);
+ const QIcon icon = Utils::Icons::MAGNIFIER.icon();
+ m_ui.findEdit->setButtonIcon(Utils::FancyLineEdit::Left, icon);
} else {
- m_ui.findEdit->setButtonPixmap(Utils::FancyLineEdit::Left,
- IFindFilter::pixmapForFindFlags(effectiveFlags));
+ m_ui.findEdit->setButtonIcon(Utils::FancyLineEdit::Left,
+ IFindFilter::pixmapForFindFlags(effectiveFlags));
}
}
diff --git a/src/plugins/coreplugin/find/searchresultwindow.h b/src/plugins/coreplugin/find/searchresultwindow.h
index f62c216311..a22f6ad0a2 100644
--- a/src/plugins/coreplugin/find/searchresultwindow.h
+++ b/src/plugins/coreplugin/find/searchresultwindow.h
@@ -39,11 +39,9 @@ QT_END_NAMESPACE
namespace Core {
namespace Internal {
- class SearchResultTreeView;
class SearchResultWindowPrivate;
class SearchResultWidget;
}
-class Find;
class SearchResultWindow;
class CORE_EXPORT SearchResult : public QObject
diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp
index fcf8d07f96..2a0036616e 100644
--- a/src/plugins/coreplugin/generalsettings.cpp
+++ b/src/plugins/coreplugin/generalsettings.cpp
@@ -164,7 +164,7 @@ void GeneralSettings::setLanguage(const QString &locale)
QSettings *settings = ICore::settings();
if (settings->value(QLatin1String("General/OverrideLanguage")).toString() != locale)
QMessageBox::information(ICore::mainWindow(), tr("Restart Required"),
- tr("The language change will take effect after a restart of Qt Creator."));
+ tr("The language change will take effect after restart."));
if (locale.isEmpty())
settings->remove(QLatin1String("General/OverrideLanguage"));
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index e5a1bc8a5f..ab2a7f9770 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -461,8 +461,9 @@ QString ICore::versionString()
QString ideVersionDescription;
if (QLatin1String(Constants::IDE_VERSION_LONG) != QLatin1String(Constants::IDE_VERSION_DISPLAY))
ideVersionDescription = tr(" (%1)").arg(QLatin1String(Constants::IDE_VERSION_LONG));
- return tr("Qt Creator %1%2").arg(QLatin1String(Constants::IDE_VERSION_DISPLAY),
- ideVersionDescription);
+ return tr("%1 %2%3").arg(QLatin1String(Constants::IDE_DISPLAY_NAME),
+ QLatin1String(Constants::IDE_VERSION_DISPLAY),
+ ideVersionDescription);
}
QString ICore::buildCompatibilityString()
diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h
index b2d789b6d8..89c6ada180 100644
--- a/src/plugins/coreplugin/icore.h
+++ b/src/plugins/coreplugin/icore.h
@@ -44,9 +44,7 @@ namespace Core {
class IWizardFactory;
class Context;
class IContext;
-class ProgressManager;
class SettingsDatabase;
-class VcsManager;
namespace Internal { class MainWindow; }
diff --git a/src/plugins/coreplugin/images/mode_Design.png b/src/plugins/coreplugin/images/mode_Design.png
index 268376e5fe..9f155db22a 100644
--- a/src/plugins/coreplugin/images/mode_Design.png
+++ b/src/plugins/coreplugin/images/mode_Design.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/mode_Design@2x.png b/src/plugins/coreplugin/images/mode_Design@2x.png
index 85e08c360b..ce1baa8c7a 100644
--- a/src/plugins/coreplugin/images/mode_Design@2x.png
+++ b/src/plugins/coreplugin/images/mode_Design@2x.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/mode_Edit.png b/src/plugins/coreplugin/images/mode_Edit.png
index 494f84baa7..fecee991ad 100644
--- a/src/plugins/coreplugin/images/mode_Edit.png
+++ b/src/plugins/coreplugin/images/mode_Edit.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/mode_Edit@2x.png b/src/plugins/coreplugin/images/mode_Edit@2x.png
index d223679dc3..032d37a222 100644
--- a/src/plugins/coreplugin/images/mode_Edit@2x.png
+++ b/src/plugins/coreplugin/images/mode_Edit@2x.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/mode_design_mask.png b/src/plugins/coreplugin/images/mode_design_mask.png
index 3225507f81..42013edf35 100644
--- a/src/plugins/coreplugin/images/mode_design_mask.png
+++ b/src/plugins/coreplugin/images/mode_design_mask.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/mode_design_mask@2x.png b/src/plugins/coreplugin/images/mode_design_mask@2x.png
index f4eced6284..2aef9018a8 100644
--- a/src/plugins/coreplugin/images/mode_design_mask@2x.png
+++ b/src/plugins/coreplugin/images/mode_design_mask@2x.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/mode_edit_mask.png b/src/plugins/coreplugin/images/mode_edit_mask.png
index 8e2a971f15..51197249c0 100644
--- a/src/plugins/coreplugin/images/mode_edit_mask.png
+++ b/src/plugins/coreplugin/images/mode_edit_mask.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/mode_edit_mask@2x.png b/src/plugins/coreplugin/images/mode_edit_mask@2x.png
index d683f154e0..389ac6dc4e 100644
--- a/src/plugins/coreplugin/images/mode_edit_mask@2x.png
+++ b/src/plugins/coreplugin/images/mode_edit_mask@2x.png
Binary files differ
diff --git a/src/plugins/coreplugin/iversioncontrol.cpp b/src/plugins/coreplugin/iversioncontrol.cpp
index 1c11437d6c..678e4ecc8c 100644
--- a/src/plugins/coreplugin/iversioncontrol.cpp
+++ b/src/plugins/coreplugin/iversioncontrol.cpp
@@ -140,21 +140,21 @@ namespace Core {
TestVersionControl::~TestVersionControl()
{
- VcsManager::instance()->clearVersionControlCache();
+ VcsManager::clearVersionControlCache();
}
void TestVersionControl::setManagedDirectories(const QHash<QString, QString> &dirs)
{
m_managedDirs = dirs;
m_dirCount = 0;
- VcsManager::instance()->clearVersionControlCache();
+ VcsManager::clearVersionControlCache();
}
void TestVersionControl::setManagedFiles(const QSet<QString> &files)
{
m_managedFiles = files;
m_fileCount = 0;
- VcsManager::instance()->clearVersionControlCache();
+ VcsManager::clearVersionControlCache();
}
bool TestVersionControl::managesDirectory(const QString &filename, QString *topLevel) const
diff --git a/src/plugins/coreplugin/iwizardfactory.cpp b/src/plugins/coreplugin/iwizardfactory.cpp
index 238f992a32..8e8afc304f 100644
--- a/src/plugins/coreplugin/iwizardfactory.cpp
+++ b/src/plugins/coreplugin/iwizardfactory.cpp
@@ -33,6 +33,7 @@
#include <extensionsystem/pluginspec.h>
#include <extensionsystem/pluginmanager.h>
+#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <utils/wizard.h>
@@ -255,9 +256,9 @@ QString IWizardFactory::runPath(const QString &defaultPath)
// Project wizards: Check for projects directory or
// use last visited directory of file dialog. Never start
// at current.
- path = DocumentManager::useProjectsDirectory() ?
- DocumentManager::projectsDirectory() :
- DocumentManager::fileDialogLastVisitedDirectory();
+ path = DocumentManager::useProjectsDirectory()
+ ? DocumentManager::projectsDirectory().toString()
+ : DocumentManager::fileDialogLastVisitedDirectory();
break;
default:
path = DocumentManager::fileDialogInitialDirectory();
@@ -287,7 +288,7 @@ Utils::Wizard *IWizardFactory::runWizard(const QString &path, QWidget *parent, I
s_reopenData.clear();
wizard->deleteLater();
});
- connect(wizard, &QObject::destroyed, this, [wizard]() {
+ connect(wizard, &QObject::destroyed, this, []() {
s_isWizardRunning = false;
s_currentWizard = nullptr;
s_inspectWizardAction->setEnabled(false);
diff --git a/src/plugins/coreplugin/jsexpander.cpp b/src/plugins/coreplugin/jsexpander.cpp
index 8eee995094..0c44512497 100644
--- a/src/plugins/coreplugin/jsexpander.cpp
+++ b/src/plugins/coreplugin/jsexpander.cpp
@@ -84,7 +84,7 @@ JsExpander::JsExpander()
QCoreApplication::translate("Core::JsExpander",
"Evaluate simple JavaScript statements.<br>"
"The statements may not contain '{' nor '}' characters."),
- [this](QString in) -> QString {
+ [](QString in) -> QString {
QString errorMessage;
QString result = JsExpander::evaluate(in, &errorMessage);
if (!errorMessage.isEmpty()) {
diff --git a/src/plugins/coreplugin/locator/basefilefilter.cpp b/src/plugins/coreplugin/locator/basefilefilter.cpp
index 4d7cb124f3..c992b88373 100644
--- a/src/plugins/coreplugin/locator/basefilefilter.cpp
+++ b/src/plugins/coreplugin/locator/basefilefilter.cpp
@@ -26,12 +26,12 @@
#include "basefilefilter.h"
#include <coreplugin/editormanager/editormanager.h>
+#include <utils/camelhumpmatcher.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <QDir>
-#include <QRegExp>
-#include <QStringMatcher>
+#include <QRegularExpression>
#include <QTimer>
using namespace Core;
@@ -100,16 +100,14 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QList<LocatorFilterEntry> goodEntries;
const QString entry = QDir::fromNativeSeparators(origEntry);
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
- const Qt::CaseSensitivity cs = caseSensitivity(fp.filePath);
- QStringMatcher matcher(fp.filePath, cs);
- QRegExp regexp(fp.filePath, cs, QRegExp::Wildcard);
+
+ const QRegularExpression regexp = createRegExp(entry);
if (!regexp.isValid()) {
d->m_current.clear(); // free memory
return betterEntries;
}
const QChar pathSeparator(QLatin1Char('/'));
const bool hasPathSeparator = fp.filePath.contains(pathSeparator);
- const bool hasWildcard = containsWildcard(fp.filePath);
const bool containsPreviousEntry = !d->m_current.previousEntry.isEmpty()
&& fp.filePath.contains(d->m_current.previousEntry);
const bool pathSeparatorAdded = !d->m_current.previousEntry.contains(pathSeparator)
@@ -136,27 +134,24 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QString path = d->m_current.iterator->filePath();
QString name = d->m_current.iterator->fileName();
QString matchText = hasPathSeparator ? path : name;
- int index = hasWildcard ? regexp.indexIn(matchText) : matcher.indexIn(matchText);
+ QRegularExpressionMatch match = regexp.match(matchText);
- if (index >= 0) {
+ if (match.hasMatch()) {
QFileInfo fi(path);
LocatorFilterEntry filterEntry(this, fi.fileName(), QString(path + fp.postfix));
filterEntry.fileName = path;
filterEntry.extraInfo = FileUtils::shortNativePath(FileName(fi));
LocatorFilterEntry::HighlightInfo::DataType hDataType = LocatorFilterEntry::HighlightInfo::DisplayName;
- int length = hasWildcard ? regexp.matchedLength() : fp.filePath.length();
- const bool betterMatch = index == 0;
+ const bool betterMatch = match.capturedStart() == 0;
if (hasPathSeparator) {
- const int indexCandidate = index + filterEntry.extraInfo.length() - path.length();
- const int cutOff = indexCandidate < 0 ? -indexCandidate : 0;
- index = qMax(indexCandidate, 0);
- length = qMax(length - cutOff, 1);
+ match = regexp.match(filterEntry.extraInfo);
hDataType = LocatorFilterEntry::HighlightInfo::ExtraInfo;
}
-
- if (index >= 0)
- filterEntry.highlightInfo = LocatorFilterEntry::HighlightInfo(index, length, hDataType);
+ const CamelHumpMatcher::HighlightingPositions positions =
+ CamelHumpMatcher::highlightingPositions(match);
+ filterEntry.highlightInfo =
+ LocatorFilterEntry::HighlightInfo(positions.starts, positions.lengths, hDataType);
if (betterMatch)
betterEntries.append(filterEntry);
diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp
index 3b5736f95b..1681544608 100644
--- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp
+++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp
@@ -26,6 +26,7 @@
#include "ilocatorfilter.h"
#include <coreplugin/coreconstants.h>
+#include <utils/camelhumpmatcher.h>
#include <QBoxLayout>
#include <QCheckBox>
@@ -34,6 +35,7 @@
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
+#include <QRegularExpression>
using namespace Core;
@@ -202,6 +204,31 @@ bool ILocatorFilter::containsWildcard(const QString &str)
}
/*!
+ * \brief Returns a simple regular expression to search for \a text.
+ *
+ * \a text may contain the simple '?' and '*' wildcards known from the shell.
+ * '?' matches exactly one character, '*' matches a number of characters
+ * (including none).
+ *
+ * The regular expression contains capture groups to allow highlighting
+ * matched characters after a match.
+ */
+static QRegularExpression createWildcardRegExp(const QString &text)
+{
+ QString pattern = '(' + text + ')';
+ pattern.replace('?', ").(");
+ pattern.replace('*', ").*(");
+ pattern.remove("()");
+ return QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption);
+}
+
+QRegularExpression ILocatorFilter::createRegExp(const QString &text)
+{
+ return containsWildcard(text) ? createWildcardRegExp(text)
+ : CamelHumpMatcher::createCamelHumpRegExp(text);
+}
+
+/*!
Specifies a title for configuration dialogs.
*/
QString ILocatorFilter::msgConfigureDialogTitle()
diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.h b/src/plugins/coreplugin/locator/ilocatorfilter.h
index e649a1c959..c0dd8ec426 100644
--- a/src/plugins/coreplugin/locator/ilocatorfilter.h
+++ b/src/plugins/coreplugin/locator/ilocatorfilter.h
@@ -46,13 +46,19 @@ struct LocatorFilterEntry
};
HighlightInfo(int startIndex, int length, DataType type = DataType::DisplayName)
- : startIndex(startIndex)
- , length(length)
+ : starts{startIndex}
+ , lengths{length}
, dataType(type)
{}
- int startIndex;
- int length;
+ HighlightInfo(QVector<int> startIndex, QVector<int> length, DataType type = DataType::DisplayName)
+ : starts(startIndex)
+ , lengths(length)
+ , dataType(type)
+ {}
+
+ QVector<int> starts;
+ QVector<int> lengths;
DataType dataType;
};
@@ -138,6 +144,7 @@ public:
static Qt::CaseSensitivity caseSensitivity(const QString &str);
static bool containsWildcard(const QString &str);
+ static QRegularExpression createRegExp(const QString &text);
static QString msgConfigureDialogTitle();
static QString msgPrefixLabel();
diff --git a/src/plugins/coreplugin/locator/locatorsettingspage.h b/src/plugins/coreplugin/locator/locatorsettingspage.h
index f9e4383d46..ed7143ae58 100644
--- a/src/plugins/coreplugin/locator/locatorsettingspage.h
+++ b/src/plugins/coreplugin/locator/locatorsettingspage.h
@@ -34,7 +34,6 @@
#include <QPointer>
QT_BEGIN_NAMESPACE
-class QListWidgetItem;
class QSortFilterProxyModel;
QT_END_NAMESPACE
diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp
index 9dbcde15f4..8d0dbe6292 100644
--- a/src/plugins/coreplugin/locator/locatorwidget.cpp
+++ b/src/plugins/coreplugin/locator/locatorwidget.cpp
@@ -217,7 +217,8 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
: ExtraInfoColumn;
if (highlightColumn == index.column()) {
const bool startIndexRole = role == int(HighlightingItemRole::StartColumn);
- return startIndexRole ? entry.highlightInfo.startIndex : entry.highlightInfo.length;
+ return startIndexRole ? QVariant::fromValue(entry.highlightInfo.starts)
+ : QVariant::fromValue(entry.highlightInfo.lengths);
}
break;
}
@@ -538,9 +539,9 @@ LocatorWidget::LocatorWidget(Locator *locator) :
layout->setMargin(0);
layout->addWidget(m_fileLineEdit);
- const QPixmap pixmap = Utils::Icons::MAGNIFIER.pixmap();
+ const QIcon icon = Utils::Icons::MAGNIFIER.icon();
m_fileLineEdit->setFiltering(true);
- m_fileLineEdit->setButtonPixmap(Utils::FancyLineEdit::Left, pixmap);
+ m_fileLineEdit->setButtonIcon(Utils::FancyLineEdit::Left, icon);
m_fileLineEdit->setButtonToolTip(Utils::FancyLineEdit::Left, tr("Options"));
m_fileLineEdit->setFocusPolicy(Qt::ClickFocus);
m_fileLineEdit->setButtonVisible(Utils::FancyLineEdit::Left, true);
@@ -572,7 +573,7 @@ LocatorWidget::LocatorWidget(Locator *locator) :
m_showPopupTimer.setSingleShot(true);
connect(&m_showPopupTimer, &QTimer::timeout, this, &LocatorWidget::showPopupNow);
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Small,
+ m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Small,
m_fileLineEdit);
m_progressIndicator->raise();
m_progressIndicator->hide();
diff --git a/src/plugins/coreplugin/locator/locatorwidget.h b/src/plugins/coreplugin/locator/locatorwidget.h
index c4ce3c4a14..6b645134cc 100644
--- a/src/plugins/coreplugin/locator/locatorwidget.h
+++ b/src/plugins/coreplugin/locator/locatorwidget.h
@@ -34,10 +34,7 @@
QT_BEGIN_NAMESPACE
class QAction;
-class QLabel;
-class QLineEdit;
class QMenu;
-class QTreeView;
QT_END_NAMESPACE
namespace Utils { class FancyLineEdit; }
diff --git a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp
index 16b14ba976..9f025ec698 100644
--- a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp
+++ b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp
@@ -27,15 +27,15 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
+#include <utils/camelhumpmatcher.h>
#include <utils/fileutils.h>
#include <QAbstractItemModel>
#include <QFileInfo>
#include <QMutexLocker>
-#include <QRegExp>
+#include <QRegularExpression>
using namespace Core;
-using namespace Core;
using namespace Core::Internal;
using namespace Utils;
@@ -61,7 +61,8 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
QList<LocatorFilterEntry> goodEntries;
QList<LocatorFilterEntry> betterEntries;
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
- QRegExp regexp(fp.filePath, caseSensitivity(fp.filePath), QRegExp::Wildcard);
+
+ const QRegularExpression regexp = createRegExp(entry);
if (!regexp.isValid())
return goodEntries;
@@ -72,13 +73,16 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
if (fileName.isEmpty())
continue;
QString displayName = editorEntry.displayName;
- const int index = regexp.indexIn(displayName);
- if (index >= 0) {
+ const QRegularExpressionMatch match = regexp.match(displayName);
+ if (match.hasMatch()) {
+ const CamelHumpMatcher::HighlightingPositions positions =
+ CamelHumpMatcher::highlightingPositions(match);
LocatorFilterEntry filterEntry(this, displayName, QString(fileName + fp.postfix));
filterEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName));
filterEntry.fileName = fileName;
- filterEntry.highlightInfo = {index, regexp.matchedLength()};
- if (index == 0)
+ filterEntry.highlightInfo.starts = positions.starts;
+ filterEntry.highlightInfo.lengths = positions.lengths;
+ if (match.capturedStart() == 0)
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 9010fd8da3..13d7036d8f 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -109,7 +109,7 @@ MainWindow::MainWindow() :
m_coreImpl(new ICore(this)),
m_lowPrioAdditionalContexts(Constants::C_GLOBAL),
m_settingsDatabase(new SettingsDatabase(QFileInfo(PluginManager::settings()->fileName()).path(),
- QLatin1String("QtCreator"),
+ QLatin1String(Constants::IDE_CASED_ID),
this)),
m_progressManager(new ProgressManagerPrivate),
m_jsExpander(new JsExpander),
@@ -130,10 +130,10 @@ MainWindow::MainWindow() :
HistoryCompleter::setSettings(PluginManager::settings());
- setWindowTitle(tr("Qt Creator"));
+ setWindowTitle(Constants::IDE_DISPLAY_NAME);
if (HostOsInfo::isLinuxHost())
QApplication::setWindowIcon(Icons::QTCREATORLOGO_BIG.icon());
- QCoreApplication::setApplicationName(QLatin1String("QtCreator"));
+ QCoreApplication::setApplicationName(QLatin1String(Constants::IDE_CASED_ID));
QCoreApplication::setApplicationVersion(QLatin1String(Constants::IDE_VERSION_LONG));
QCoreApplication::setOrganizationName(QLatin1String(Constants::IDE_SETTINGSVARIANT_STR));
QString baseName = QApplication::style()->objectName();
@@ -505,7 +505,7 @@ void MainWindow::registerDefaultActions()
cmd = ActionManager::registerAction(m_newAction, Constants::NEW);
cmd->setDefaultKeySequence(QKeySequence::New);
mfile->addAction(cmd, Constants::G_FILE_NEW);
- connect(m_newAction, &QAction::triggered, this, [this]() {
+ connect(m_newAction, &QAction::triggered, this, []() {
if (!ICore::isNewItemDialogRunning()) {
ICore::showNewItemDialog(tr("New File or Project", "Title of dialog"),
IWizardFactory::allWizardFactories(), QString());
@@ -741,9 +741,9 @@ void MainWindow::registerDefaultActions()
// About IDE Action
icon = QIcon::fromTheme(QLatin1String("help-about"));
if (HostOsInfo::isMacHost())
- tmpaction = new QAction(icon, tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
+ tmpaction = new QAction(icon, tr("About &%1").arg(Constants::IDE_DISPLAY_NAME), this); // it's convention not to add dots to the about menu
else
- tmpaction = new QAction(icon, tr("About &Qt Creator..."), this);
+ tmpaction = new QAction(icon, tr("About &%1...").arg(Constants::IDE_DISPLAY_NAME), this);
tmpaction->setMenuRole(QAction::AboutRole);
cmd = ActionManager::registerAction(tmpaction, Constants::ABOUT_QTCREATOR);
mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
diff --git a/src/plugins/coreplugin/mainwindow.h b/src/plugins/coreplugin/mainwindow.h
index 7a7042fd36..a50fa8b6a7 100644
--- a/src/plugins/coreplugin/mainwindow.h
+++ b/src/plugins/coreplugin/mainwindow.h
@@ -37,7 +37,6 @@
#include <functional>
QT_BEGIN_NAMESPACE
-class QSettings;
class QPrinter;
class QToolButton;
QT_END_NAMESPACE
@@ -47,10 +46,8 @@ namespace Core {
class StatusBarWidget;
class EditorManager;
class ExternalToolManager;
-class DocumentManager;
class HelpManager;
class IDocument;
-class IWizardFactory;
class JsExpander;
class MessageManager;
class ModeManager;
diff --git a/src/plugins/coreplugin/messagemanager.cpp b/src/plugins/coreplugin/messagemanager.cpp
index ee522b534a..f8d2b97506 100644
--- a/src/plugins/coreplugin/messagemanager.cpp
+++ b/src/plugins/coreplugin/messagemanager.cpp
@@ -38,6 +38,19 @@ MessageManager *MessageManager::instance()
return m_instance;
}
+void MessageManager::showOutputPane(Core::MessageManager::PrintToOutputPaneFlags flags)
+{
+ if (!m_messageOutputWindow)
+ return;
+ if (flags & Flash) {
+ m_messageOutputWindow->flash();
+ } else if (flags & Silent) {
+ // Do nothing
+ } else {
+ m_messageOutputWindow->popup(IOutputPane::Flag(int(flags)));
+ }
+}
+
MessageManager::MessageManager()
{
m_instance = this;
@@ -60,24 +73,11 @@ void MessageManager::init()
ExtensionSystem::PluginManager::addObject(m_messageOutputWindow);
}
-void MessageManager::showOutputPane()
-{
- if (m_messageOutputWindow)
- m_messageOutputWindow->popup(IOutputPane::ModeSwitch);
-}
-
void MessageManager::write(const QString &text, PrintToOutputPaneFlags flags)
{
if (!m_messageOutputWindow)
return;
- if (flags & Flash) {
- m_messageOutputWindow->flash();
- } else if (flags & Silent) {
- // Do nothing
- } else {
- m_messageOutputWindow->popup(IOutputPane::Flag(int(flags)));
- }
-
+ showOutputPane(flags);
m_messageOutputWindow->append(text + QLatin1Char('\n'));
}
diff --git a/src/plugins/coreplugin/messagemanager.h b/src/plugins/coreplugin/messagemanager.h
index 395ac75e5d..485807d76e 100644
--- a/src/plugins/coreplugin/messagemanager.h
+++ b/src/plugins/coreplugin/messagemanager.h
@@ -42,8 +42,6 @@ class CORE_EXPORT MessageManager : public QObject
public:
static MessageManager *instance();
- static void showOutputPane();
-
enum PrintToOutputPaneFlag {
NoModeSwitch = IOutputPane::NoModeSwitch,
ModeSwitch = IOutputPane::ModeSwitch,
@@ -55,6 +53,8 @@ public:
Q_DECLARE_FLAGS(PrintToOutputPaneFlags, PrintToOutputPaneFlag)
+ static void showOutputPane(Core::MessageManager::PrintToOutputPaneFlags flags = NoModeSwitch);
+
public slots:
static void write(const QString &text,
Core::MessageManager::PrintToOutputPaneFlags flags = NoModeSwitch);
diff --git a/src/plugins/coreplugin/mimetypemagicdialog.ui b/src/plugins/coreplugin/mimetypemagicdialog.ui
index f638354881..6dfcb1cacc 100644
--- a/src/plugins/coreplugin/mimetypemagicdialog.ui
+++ b/src/plugins/coreplugin/mimetypemagicdialog.ui
@@ -136,7 +136,7 @@
<bool>false</bool>
</property>
<property name="text">
- <string>&lt;i&gt;Note: Wide range values might impact Qt Creator's performance when opening files.&lt;/i&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Note: Wide range values might impact performance when opening files.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
diff --git a/src/plugins/coreplugin/mimetypesettings.cpp b/src/plugins/coreplugin/mimetypesettings.cpp
index 8573ae5f87..44b3413107 100644
--- a/src/plugins/coreplugin/mimetypesettings.cpp
+++ b/src/plugins/coreplugin/mimetypesettings.cpp
@@ -31,6 +31,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditorfactory.h>
#include <coreplugin/editormanager/iexternaleditor.h>
+
#include <utils/algorithm.h>
#include <utils/headerviewstretcher.h>
#include <utils/mimetypes/mimedatabase.h>
@@ -400,7 +401,7 @@ void MimeTypeSettingsPrivate::resetMimeTypes()
m_userModifiedMimeTypes.clear(); // settings file will be removed with next settings-save
QMessageBox::information(ICore::dialogParent(),
tr("Reset MIME Types"),
- tr("Changes will take effect after Qt Creator restart."));
+ tr("Changes will take effect after restart."));
}
void MimeTypeSettingsPrivate::setFilterPattern(const QString &pattern)
diff --git a/src/plugins/coreplugin/navigationwidget.h b/src/plugins/coreplugin/navigationwidget.h
index e2b49ee95c..0f43e4ce04 100644
--- a/src/plugins/coreplugin/navigationwidget.h
+++ b/src/plugins/coreplugin/navigationwidget.h
@@ -33,7 +33,6 @@
QT_BEGIN_NAMESPACE
class QSettings;
class QAbstractItemModel;
-class QStandardItemModel;
QT_END_NAMESPACE
namespace Core {
diff --git a/src/plugins/coreplugin/outputpanemanager.h b/src/plugins/coreplugin/outputpanemanager.h
index b8885dd21d..90dc7b04a0 100644
--- a/src/plugins/coreplugin/outputpanemanager.h
+++ b/src/plugins/coreplugin/outputpanemanager.h
@@ -32,9 +32,7 @@
QT_BEGIN_NAMESPACE
class QAction;
-class QComboBox;
class QLabel;
-class QSplitter;
class QStackedWidget;
class QTimeLine;
class QLabel;
diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp
index 7e3f83ac2b..2d69b09e54 100644
--- a/src/plugins/coreplugin/outputwindow.cpp
+++ b/src/plugins/coreplugin/outputwindow.cpp
@@ -64,7 +64,7 @@ public:
Qt::MouseButton mouseButtonPressed = Qt::NoButton;
bool m_zoomEnabled = false;
float m_originalFontSize = 0.;
- int maxLineCount = 100000;
+ int maxLineCount = Core::Constants::DEFAULT_MAX_LINE_COUNT;
QTextCursor cursor;
};
diff --git a/src/plugins/coreplugin/patchtool.cpp b/src/plugins/coreplugin/patchtool.cpp
index 10a48817de..724fabd133 100644
--- a/src/plugins/coreplugin/patchtool.cpp
+++ b/src/plugins/coreplugin/patchtool.cpp
@@ -88,6 +88,12 @@ static bool runPatchHelper(const QByteArray &input, const QString &workingDirect
return false;
}
+ if (!Utils::FileName::fromString(patch).exists()
+ && !Utils::Environment::systemEnvironment().searchInPath(patch).exists()) {
+ MessageManager::write(QApplication::translate("Core::PatchTool", "The patch-command configured in the general \"Environment\" settings does not exist."));
+ return false;
+ }
+
QProcess patchProcess;
if (!workingDirectory.isEmpty())
patchProcess.setWorkingDirectory(workingDirectory);
diff --git a/src/plugins/coreplugin/rightpane.h b/src/plugins/coreplugin/rightpane.h
index 4fb410f5eb..ab3aab18e7 100644
--- a/src/plugins/coreplugin/rightpane.h
+++ b/src/plugins/coreplugin/rightpane.h
@@ -36,7 +36,6 @@ QT_END_NAMESPACE
namespace Core {
-class IMode;
class RightPaneWidget;
class CORE_EXPORT RightPanePlaceHolder : public QWidget
diff --git a/src/plugins/coreplugin/shellcommand.cpp b/src/plugins/coreplugin/shellcommand.cpp
index 4f6a028e51..a236c906e4 100644
--- a/src/plugins/coreplugin/shellcommand.cpp
+++ b/src/plugins/coreplugin/shellcommand.cpp
@@ -28,6 +28,9 @@
#include "icore.h"
#include "progressmanager/progressmanager.h"
+#include <QFutureInterface>
+#include <QFutureWatcher>
+
namespace Core {
ShellCommand::ShellCommand(const QString &workingDirectory, const QProcessEnvironment &environment) :
@@ -40,7 +43,23 @@ ShellCommand::ShellCommand(const QString &workingDirectory, const QProcessEnviro
void ShellCommand::addTask(QFuture<void> &future)
{
const QString name = displayName();
- Core::ProgressManager::addTask(future, name, Core::Id::fromString(name + QLatin1String(".action")));
+ const auto id = Core::Id::fromString(name + QLatin1String(".action"));
+ if (hasProgressParser()) {
+ ProgressManager::addTask(future, name, id);
+ } else {
+ // add a timed tasked based on timeout
+ // we cannot access the future interface directly, so we need to create a new one
+ // with the same lifetime
+ auto fi = new QFutureInterface<void>();
+ auto watcher = new QFutureWatcher<void>();
+ connect(watcher, &QFutureWatcherBase::finished, [fi, watcher] {
+ fi->reportFinished();
+ delete fi;
+ watcher->deleteLater();
+ });
+ watcher->setFuture(future);
+ ProgressManager::addTimedTask(*fi, name, id, qMax(2, timeoutS() / 5)/*itsmagic*/);
+ }
}
void ShellCommand::coreAboutToClose()
diff --git a/src/plugins/coreplugin/sidebarwidget.h b/src/plugins/coreplugin/sidebarwidget.h
index fbc6c09acc..e6db3c2200 100644
--- a/src/plugins/coreplugin/sidebarwidget.h
+++ b/src/plugins/coreplugin/sidebarwidget.h
@@ -28,10 +28,8 @@
#include <QWidget>
QT_BEGIN_NAMESPACE
-class QSettings;
class QToolBar;
class QAction;
-class QToolButton;
QT_END_NAMESPACE
namespace Core {
diff --git a/src/plugins/coreplugin/systemsettings.cpp b/src/plugins/coreplugin/systemsettings.cpp
index 74d097e728..69f21929f8 100644
--- a/src/plugins/coreplugin/systemsettings.cpp
+++ b/src/plugins/coreplugin/systemsettings.cpp
@@ -31,6 +31,7 @@
#include "patchtool.h"
#include "vcsmanager.h"
+#include <app/app_version.h>
#include <utils/checkablemessagebox.h>
#include <utils/consoleprocess.h>
#include <utils/environment.h>
@@ -97,6 +98,11 @@ QWidget *SystemSettings::widget()
m_page->patchChooser->setHistoryCompleter(QLatin1String("General.PatchCommand.History"));
m_page->patchChooser->setPath(PatchTool::patchCommand());
m_page->autoSaveCheckBox->setChecked(EditorManagerPrivate::autoSaveEnabled());
+ m_page->autoSaveCheckBox->setToolTip(tr("Automatically creates temporary copies of "
+ "modified files. If %1 is restarted after "
+ "a crash or power failure, it asks whether to "
+ "recover the auto-saved content.")
+ .arg(Constants::IDE_DISPLAY_NAME));
m_page->autoSaveInterval->setValue(EditorManagerPrivate::autoSaveInterval());
m_page->autoSuspendCheckBox->setChecked(EditorManagerPrivate::autoSuspendEnabled());
m_page->autoSuspendMinDocumentCount->setValue(EditorManagerPrivate::autoSuspendMinDocumentCount());
diff --git a/src/plugins/coreplugin/systemsettings.ui b/src/plugins/coreplugin/systemsettings.ui
index b2928f9d47..4d36f3c918 100644
--- a/src/plugins/coreplugin/systemsettings.ui
+++ b/src/plugins/coreplugin/systemsettings.ui
@@ -22,10 +22,6 @@
<property name="text">
<string>?</string>
</property>
- <property name="icon">
- <iconset resource="../../libs/utils/utils.qrc">
- <normaloff>:/utils/images/help.png</normaloff>:/utils/images/help.png</iconset>
- </property>
</widget>
</item>
<item row="1" column="2">
@@ -86,9 +82,6 @@
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QCheckBox" name="autoSaveCheckBox">
- <property name="toolTip">
- <string>Automatically creates temporary copies of modified files. If Qt Creator is restarted after a crash or power failure, it asks whether to recover the auto-saved content.</string>
- </property>
<property name="text">
<string>Auto-save modified files</string>
</property>
@@ -309,7 +302,7 @@
<item>
<widget class="QLabel" name="autoSuspendLabel">
<property name="toolTip">
- <string>Minimum number of open documents that should be kept in memory. Increasing this number will lead to greater resource usage of Qt Creator when not manually closing documents.</string>
+ <string>Minimum number of open documents that should be kept in memory. Increasing this number will lead to greater resource usage when not manually closing documents.</string>
</property>
<property name="text">
<string>Files to keep open:</string>
@@ -389,8 +382,6 @@
<tabstop>warnBeforeOpeningBigFiles</tabstop>
<tabstop>bigFilesLimitSpinBox</tabstop>
</tabstops>
- <resources>
- <include location="../../libs/utils/utils.qrc"/>
- </resources>
+ <resources/>
<connections/>
</ui>
diff --git a/src/plugins/coreplugin/themechooser.cpp b/src/plugins/coreplugin/themechooser.cpp
index ff62406dba..18f0a4040b 100644
--- a/src/plugins/coreplugin/themechooser.cpp
+++ b/src/plugins/coreplugin/themechooser.cpp
@@ -179,7 +179,7 @@ void ThemeChooser::apply()
const QString currentThemeId = ThemeEntry::themeSetting().toString();
if (currentThemeId != themeId) {
QMessageBox::information(ICore::mainWindow(), tr("Restart Required"),
- tr("The theme change will take effect after a restart of Qt Creator."));
+ tr("The theme change will take effect after restart."));
// save filename of selected theme in global config
settings->setValue(QLatin1String(Constants::SETTINGS_THEME), themeId);
diff --git a/src/plugins/coreplugin/variablechooser.cpp b/src/plugins/coreplugin/variablechooser.cpp
index 109b81a8d8..5f675de7a3 100644
--- a/src/plugins/coreplugin/variablechooser.cpp
+++ b/src/plugins/coreplugin/variablechooser.cpp
@@ -107,7 +107,7 @@ public:
void createIconButton()
{
m_iconButton = new IconButton;
- m_iconButton->setPixmap(Utils::Icons::REPLACE.pixmap());
+ m_iconButton->setIcon(Utils::Icons::REPLACE.icon());
m_iconButton->setToolTip(VariableChooser::tr("Insert Variable"));
m_iconButton->hide();
connect(m_iconButton.data(), static_cast<void(QAbstractButton::*)(bool)>(&QAbstractButton::clicked),
@@ -457,11 +457,7 @@ void VariableChooserPrivate::updateDescription(const QModelIndex &index)
*/
int VariableChooserPrivate::buttonMargin() const
{
- int margin = m_iconButton->pixmap().width() + 8;
- if (q->style()->inherits("OxygenStyle"))
- margin = qMax(24, margin);
-
- return margin;
+ return 24;
}
void VariableChooserPrivate::updateButtonGeometry()
diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp
index 28ebd38270..e83f110ea5 100644
--- a/src/plugins/coreplugin/vcsmanager.cpp
+++ b/src/plugins/coreplugin/vcsmanager.cpp
@@ -37,6 +37,7 @@
#include <vcsbase/vcsbaseconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
+#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <QDir>
@@ -49,8 +50,6 @@
namespace Core {
-typedef QList<IVersionControl *> VersionControlList;
-
#if defined(WITH_TESTS)
const char TEST_PREFIX[] = "/8E3A9BA0-0B97-40DF-AEC1-2BDF9FC9EDBE/";
#endif
@@ -63,35 +62,29 @@ class VcsManagerPrivate
public:
class VcsInfo {
public:
+ VcsInfo() = default;
VcsInfo(IVersionControl *vc, const QString &tl) :
versionControl(vc), topLevel(tl)
{ }
+ VcsInfo(const VcsInfo &other) = default;
bool operator == (const VcsInfo &other) const
{
- return versionControl == other.versionControl &&
- topLevel == other.topLevel;
+ return versionControl == other.versionControl && topLevel == other.topLevel;
}
- IVersionControl *versionControl;
+ IVersionControl *versionControl = nullptr;
QString topLevel;
};
- ~VcsManagerPrivate()
- {
- qDeleteAll(m_vcsInfoList);
- }
-
- VcsInfo *findInCache(const QString &dir)
+ Utils::optional<VcsInfo> findInCache(const QString &dir)
{
- QTC_ASSERT(QDir(dir).isAbsolute(), return nullptr);
- QTC_ASSERT(!dir.endsWith(QLatin1Char('/')), return nullptr);
- QTC_ASSERT(QDir::fromNativeSeparators(dir) == dir, return nullptr);
+ QTC_ASSERT(QDir(dir).isAbsolute(), return Utils::nullopt);
+ QTC_ASSERT(!dir.endsWith(QLatin1Char('/')), return Utils::nullopt);
+ QTC_ASSERT(QDir::fromNativeSeparators(dir) == dir, return Utils::nullopt);
- const QMap<QString, VcsInfo *>::const_iterator it = m_cachedMatches.constFind(dir);
- if (it != m_cachedMatches.constEnd())
- return it.value();
- return nullptr;
+ const auto it = m_cachedMatches.constFind(dir);
+ return it == m_cachedMatches.constEnd() ? Utils::nullopt : Utils::make_optional(it.value());
}
void clearCache()
@@ -121,24 +114,10 @@ public:
|| topLevel == dir || topLevel.isEmpty(), return);
QTC_ASSERT((topLevel.isEmpty() && !vc) || (!topLevel.isEmpty() && vc), return);
- VcsInfo *newInfo = new VcsInfo(vc, topLevel);
- bool createdNewInfo(true);
- // Do we have a matching VcsInfo already?
- foreach (VcsInfo *i, m_vcsInfoList) {
- if (*i == *newInfo) {
- delete newInfo;
- newInfo = i;
- createdNewInfo = false;
- break;
- }
- }
- if (createdNewInfo)
- m_vcsInfoList.append(newInfo);
-
QString tmpDir = dir;
const QChar slash = QLatin1Char('/');
while (tmpDir.count() >= topLevel.count() && !tmpDir.isEmpty()) {
- m_cachedMatches.insert(tmpDir, newInfo);
+ m_cachedMatches.insert(tmpDir, VcsInfo(vc, topLevel));
// if no vc was found, this might mean we're inside a repo internal directory (.git)
// Cache only input directory, not parents
if (!vc)
@@ -151,8 +130,8 @@ public:
}
}
- QMap<QString, VcsInfo *> m_cachedMatches;
- QList<VcsInfo *> m_vcsInfoList;
+ QList<IVersionControl *> m_versionControlList;
+ QMap<QString, VcsInfo> m_cachedMatches;
IVersionControl *m_unconfiguredVcs = nullptr;
QStringList m_cachedAdditionalToolsPaths;
@@ -177,6 +156,12 @@ VcsManager::~VcsManager()
delete d;
}
+void VcsManager::addVersionControl(IVersionControl *vc)
+{
+ QTC_ASSERT(!d->m_versionControlList.contains(vc), return);
+ d->m_versionControlList.append(vc);
+}
+
VcsManager *VcsManager::instance()
{
return m_instance;
@@ -195,9 +180,9 @@ void VcsManager::extensionsInitialized()
}
}
-QList<IVersionControl *> VcsManager::versionControls()
+const QList<IVersionControl *> VcsManager::versionControls()
{
- return ExtensionSystem::PluginManager::getObjects<IVersionControl>();
+ return d->m_versionControlList;
}
IVersionControl *VcsManager::versionControl(Id id)
@@ -240,7 +225,7 @@ IVersionControl* VcsManager::findVersionControlForDirectory(const QString &input
if (directory[0].isLetter() && directory.indexOf(QLatin1Char(':') + QLatin1String(TEST_PREFIX)) == 1)
directory = directory.mid(2);
#endif
- VcsManagerPrivate::VcsInfo *cachedData = d->findInCache(directory);
+ auto cachedData = d->findInCache(directory);
if (cachedData) {
if (topLevelDirectory)
*topLevelDirectory = cachedData->topLevel;
@@ -341,9 +326,10 @@ QString VcsManager::findTopLevelForDirectory(const QString &directory)
QStringList VcsManager::repositories(const IVersionControl *vc)
{
QStringList result;
- foreach (const VcsManagerPrivate::VcsInfo *vi, d->m_vcsInfoList)
- if (vi->versionControl == vc)
- result.push_back(vi->topLevel);
+ for (auto it = d->m_cachedMatches.constBegin(); it != d->m_cachedMatches.constEnd(); ++it) {
+ if (it.value().versionControl == vc)
+ result.append(it.value().topLevel);
+ }
return result;
}
@@ -478,31 +464,6 @@ const char ID_VCS_B[] = "B";
typedef QHash<QString, QString> FileHash;
-template<class T>
-class ObjectPoolGuard
-{
-public:
- ObjectPoolGuard(T *watch) : m_watched(watch)
- {
- ExtensionSystem::PluginManager::addObject(watch);
- }
-
- explicit operator bool() { return m_watched; }
- bool operator !() { return !m_watched; }
- T &operator*() { return *m_watched; }
- T *operator->() { return m_watched; }
- T *value() { return m_watched; }
-
- ~ObjectPoolGuard()
- {
- ExtensionSystem::PluginManager::removeObject(m_watched);
- delete m_watched;
- }
-
-private:
- T *m_watched;
-};
-
static FileHash makeHash(const QStringList &list)
{
FileHash result;
@@ -577,8 +538,11 @@ void CorePlugin::testVcsManager_data()
void CorePlugin::testVcsManager()
{
// setup:
- ObjectPoolGuard<TestVersionControl> vcsA(new TestVersionControl(ID_VCS_A, QLatin1String("A")));
- ObjectPoolGuard<TestVersionControl> vcsB(new TestVersionControl(ID_VCS_B, QLatin1String("B")));
+ QList<IVersionControl *> orig = Core::d->m_versionControlList;
+ TestVersionControl *vcsA(new TestVersionControl(ID_VCS_A, QLatin1String("A")));
+ TestVersionControl *vcsB(new TestVersionControl(ID_VCS_B, QLatin1String("B")));
+
+ Core::d->m_versionControlList = {vcsA, vcsB};
// test:
QFETCH(QStringList, dirsVcsA);
@@ -622,7 +586,8 @@ void CorePlugin::testVcsManager()
}
// teardown:
- // handled by guards
+ qDeleteAll(Core::d->m_versionControlList);
+ Core::d->m_versionControlList = orig;
}
} // namespace Internal
diff --git a/src/plugins/coreplugin/vcsmanager.h b/src/plugins/coreplugin/vcsmanager.h
index 71e3adeaf8..147d7a4aee 100644
--- a/src/plugins/coreplugin/vcsmanager.h
+++ b/src/plugins/coreplugin/vcsmanager.h
@@ -56,9 +56,17 @@ class CORE_EXPORT VcsManager : public QObject
public:
static VcsManager *instance();
+ template <typename T, typename... Args>
+ static T *registerVersionControl(Args&&... args)
+ {
+ T *vc = new T(std::forward<Args>(args)...);
+ addVersionControl(vc);
+ return vc;
+ }
+
static void extensionsInitialized();
- static QList<IVersionControl *> versionControls();
+ static const QList<IVersionControl *> versionControls();
static IVersionControl *versionControl(Id id);
static void resetVersionControlForDirectory(const QString &inputDirectory);
@@ -92,17 +100,18 @@ public:
*/
static QStringList additionalToolsPath();
+ static void clearVersionControlCache();
+
signals:
void repositoryChanged(const QString &repository);
void configurationChanged(const IVersionControl *vcs);
-public slots:
- static void clearVersionControlCache();
-
private:
explicit VcsManager(QObject *parent = 0);
~VcsManager();
+ static void addVersionControl(IVersionControl *vc);
+
void handleConfigurationChanges();
friend class Core::Internal::MainWindow;
diff --git a/src/plugins/coreplugin/versiondialog.cpp b/src/plugins/coreplugin/versiondialog.cpp
index ded2e13dae..06962971ea 100644
--- a/src/plugins/coreplugin/versiondialog.cpp
+++ b/src/plugins/coreplugin/versiondialog.cpp
@@ -51,7 +51,7 @@ VersionDialog::VersionDialog(QWidget *parent)
if (Utils::HostOsInfo::isLinuxHost())
setWindowIcon(Icons::QTCREATORLOGO_BIG.icon());
- setWindowTitle(tr("About Qt Creator"));
+ setWindowTitle(tr("About %1").arg(Core::Constants::IDE_DISPLAY_NAME));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QGridLayout *layout = new QGridLayout(this);
layout->setSizeConstraint(QLayout::SetFixedSize);
diff --git a/src/plugins/coreplugin/windowsupport.cpp b/src/plugins/coreplugin/windowsupport.cpp
index 4af9d7343b..7d9c3ef6ad 100644
--- a/src/plugins/coreplugin/windowsupport.cpp
+++ b/src/plugins/coreplugin/windowsupport.cpp
@@ -31,6 +31,7 @@
#include "coreconstants.h"
#include "icore.h"
+#include <app/app_version.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
@@ -191,7 +192,7 @@ void WindowList::updateTitle(QWidget *window)
QTC_ASSERT(index >= 0, return);
QTC_ASSERT(index < m_windowActions.size(), return);
QString title = window->windowTitle();
- if (title.endsWith(QStringLiteral("- Qt Creator")))
+ if (title.endsWith(QStringLiteral("- ") + Constants::IDE_DISPLAY_NAME))
title.chop(12);
m_windowActions.at(index)->setText(title.trimmed());
}
diff --git a/src/plugins/cpaster/cpasterplugin.h b/src/plugins/cpaster/cpasterplugin.h
index e86b17983d..671fdbb71f 100644
--- a/src/plugins/cpaster/cpasterplugin.h
+++ b/src/plugins/cpaster/cpasterplugin.h
@@ -37,8 +37,6 @@ class QAction;
QT_END_NAMESPACE
namespace CodePaster {
-class CustomFetcher;
-class CustomPoster;
class Settings;
class Protocol;
diff --git a/src/plugins/cppeditor/cppautocompleter.cpp b/src/plugins/cppeditor/cppautocompleter.cpp
index 8c1315b973..6bc60d2093 100644
--- a/src/plugins/cppeditor/cppautocompleter.cpp
+++ b/src/plugins/cppeditor/cppautocompleter.cpp
@@ -86,6 +86,7 @@ QString CppAutoCompleter::insertParagraphSeparator(const QTextCursor &cursor) co
#ifdef WITH_TESTS
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorconstants.h"
#include "cppeditorplugin.h"
diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
index fed7c4c854..7a701ab692 100644
--- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
+++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp
@@ -25,7 +25,7 @@
#include "cppcodemodelinspectordialog.h"
#include "ui_cppcodemodelinspectordialog.h"
-#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditordocument.h"
#include <coreplugin/editormanager/editormanager.h>
@@ -35,6 +35,7 @@
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsbridge.h>
#include <cpptools/cppworkingcopy.h>
+#include <projectexplorer/projectmacro.h>
#include <projectexplorer/project.h>
#include <cplusplus/CppDocument.h>
@@ -49,6 +50,7 @@
#include <QSortFilterProxyModel>
#include <algorithm>
+#include <numeric>
using namespace CPlusPlus;
using namespace CppTools;
@@ -756,7 +758,7 @@ class MacrosModel : public QAbstractListModel
Q_OBJECT
public:
MacrosModel(QObject *parent);
- void configure(const QList<Macro> &macros);
+ void configure(const QList<CPlusPlus::Macro> &macros);
void clear();
enum Columns { LineNumberColumn, MacroColumn, ColumnCount };
@@ -767,14 +769,14 @@ public:
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:
- QList<Macro> m_macros;
+ QList<CPlusPlus::Macro> m_macros;
};
MacrosModel::MacrosModel(QObject *parent) : QAbstractListModel(parent)
{
}
-void MacrosModel::configure(const QList<Macro> &macros)
+void MacrosModel::configure(const QList<CPlusPlus::Macro> &macros)
{
emit layoutAboutToBeChanged();
m_macros = macros;
@@ -802,7 +804,7 @@ QVariant MacrosModel::data(const QModelIndex &index, int role) const
{
const int column = index.column();
if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column == MacroColumn)) {
- const Macro macro = m_macros.at(index.row());
+ const CPlusPlus::Macro macro = m_macros.at(index.row());
if (column == LineNumberColumn)
return macro.line();
else if (column == MacroColumn)
@@ -1614,7 +1616,8 @@ void CppCodeModelInspectorDialog::refresh()
}
// Merged entities
- dumper.dumpMergedEntities(cmmi->headerPaths(), cmmi->definedMacros());
+ dumper.dumpMergedEntities(cmmi->headerPaths(),
+ ProjectExplorer::Macro::toByteArray(cmmi->definedMacros()));
}
enum DocumentTabs {
@@ -1758,6 +1761,15 @@ void CppCodeModelInspectorDialog::clearProjectPartData()
partTabName(ProjectPartPrecompiledHeadersTab));
}
+static int defineCount(const ProjectExplorer::Macros &macros)
+{
+ using ProjectExplorer::Macro;
+ return int(std::count_if(
+ macros.begin(),
+ macros.end(),
+ [](const Macro &macro) { return macro.type == ProjectExplorer::MacroType::Define; }));
+}
+
void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &part)
{
QTC_ASSERT(part, return);
@@ -1788,6 +1800,7 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
{QString::fromLatin1("Callgroup Id"), callGroupId},
{QString::fromLatin1("Precompiled Headers"), precompiledHeaders},
{QString::fromLatin1("Selected For Building"), CMI::Utils::toString(part->selectedForBuilding)},
+ {QString::fromLatin1("Build Target Type"), CMI::Utils::toString(part->buildTargetType)},
{QString::fromLatin1("Language Version"), CMI::Utils::toString(part->languageVersion)},
{QString::fromLatin1("Language Extensions"), CMI::Utils::toString(part->languageExtensions)},
{QString::fromLatin1("Qt Version"), CMI::Utils::toString(part->qtVersion)}
@@ -1802,16 +1815,10 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
m_ui->projectPartTab->setTabText(ProjectPartFilesTab,
partTabName(ProjectPartFilesTab, part->files.size()));
- // Defines
- const QList<QByteArray> defineLines = part->toolchainDefines.split('\n')
- + part->projectDefines.split('\n');
- int numberOfDefines = 0;
- foreach (const QByteArray &line, defineLines) {
- if (line.startsWith("#define "))
- ++numberOfDefines;
- }
- m_ui->partToolchainDefinesEdit->setPlainText(QString::fromUtf8(part->toolchainDefines));
- m_ui->partProjectDefinesEdit->setPlainText(QString::fromUtf8(part->projectDefines));
+ int numberOfDefines = defineCount(part->toolChainMacros) + defineCount(part->projectMacros);
+
+ m_ui->partToolchainDefinesEdit->setPlainText(QString::fromUtf8(ProjectExplorer::Macro::toByteArray(part->toolChainMacros)));
+ m_ui->partProjectDefinesEdit->setPlainText(QString::fromUtf8(ProjectExplorer::Macro::toByteArray(part->projectMacros)));
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab,
partTabName(ProjectPartDefinesTab, numberOfDefines));
diff --git a/src/plugins/cppeditor/cppdoxygen_test.cpp b/src/plugins/cppeditor/cppdoxygen_test.cpp
index 6dde8cb4c0..639e0d5b8a 100644
--- a/src/plugins/cppeditor/cppdoxygen_test.cpp
+++ b/src/plugins/cppeditor/cppdoxygen_test.cpp
@@ -23,6 +23,8 @@
**
****************************************************************************/
+#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppdoxygen_test.h"
#include "cppeditortestcase.h"
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index c20d46ed40..a2b622a2f9 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -24,81 +24,12 @@
****************************************************************************/
#include "cppeditor.h"
-
#include "cppautocompleter.h"
-#include "cppdocumentationcommenthelper.h"
-#include "cppeditorconstants.h"
-#include "cppeditordocument.h"
-#include "cppeditorplugin.h"
-#include "cppfollowsymbolundercursor.h"
#include "cpphighlighter.h"
-#include "cpplocalrenaming.h"
-#include "cppminimizableinfobars.h"
-#include "cpppreprocessordialog.h"
-#include "cppquickfixassistant.h"
-#include "cppuseselectionsupdater.h"
-
-#include <clangbackendipc/sourcelocationscontainer.h>
-
-#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/editormanager/documentmodel.h>
-#include <coreplugin/infobar.h>
-#include <cpptools/cppcanonicalsymbol.h>
-#include <cpptools/cppchecksymbols.h>
-#include <cpptools/cppcodeformatter.h>
-#include <cpptools/cppcompletionassistprovider.h>
-#include <cpptools/cppeditoroutline.h>
-#include <cpptools/cppmodelmanager.h>
#include <cpptools/cppqtstyleindenter.h>
-#include <cpptools/cppselectionchanger.h>
-#include <cpptools/cppsemanticinfo.h>
-#include <cpptools/cpptoolsconstants.h>
-#include <cpptools/cpptoolsplugin.h>
-#include <cpptools/cpptoolsreuse.h>
-#include <cpptools/cpptoolssettings.h>
-#include <cpptools/cppworkingcopy.h>
-#include <cpptools/symbolfinder.h>
-#include <cpptools/refactoringengineinterface.h>
-
-#include <texteditor/behaviorsettings.h>
-#include <texteditor/completionsettings.h>
-#include <texteditor/convenience.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <texteditor/textdocument.h>
-#include <texteditor/textdocumentlayout.h>
-#include <texteditor/texteditorsettings.h>
-#include <texteditor/codeassist/assistproposalitem.h>
-#include <texteditor/codeassist/genericproposalmodel.h>
-#include <texteditor/codeassist/genericproposal.h>
-#include <texteditor/fontsettings.h>
-#include <texteditor/refactoroverlay.h>
-
-#include <projectexplorer/projecttree.h>
-
-#include <cplusplus/ASTPath.h>
-#include <cplusplus/FastPreprocessor.h>
-#include <cplusplus/MatchingText.h>
-#include <utils/qtcassert.h>
-#include <utils/utilsicons.h>
-
-#include <QApplication>
-#include <QAction>
-#include <QElapsedTimer>
-#include <QFutureWatcher>
-#include <QMenu>
-#include <QPointer>
-#include <QTextEdit>
-#include <QTimer>
-#include <QToolButton>
-
-enum { UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL = 200 };
-
-using namespace Core;
-using namespace CPlusPlus;
-using namespace CppTools;
-using namespace TextEditor;
namespace CppEditor {
namespace Internal {
@@ -108,931 +39,12 @@ CppEditor::CppEditor()
addContext(ProjectExplorer::Constants::CXX_LANGUAGE_ID);
}
-void CppEditor::decorateEditor(TextEditorWidget *editor)
+void CppEditor::decorateEditor(TextEditor::TextEditorWidget *editor)
{
editor->textDocument()->setSyntaxHighlighter(new CppHighlighter);
editor->textDocument()->setIndenter(new CppTools::CppQtStyleIndenter);
editor->setAutoCompleter(new CppAutoCompleter);
}
-class CppEditorWidgetPrivate
-{
-public:
- CppEditorWidgetPrivate(CppEditorWidget *q);
-
-public:
- QPointer<CppModelManager> m_modelManager;
-
- CppEditorDocument *m_cppEditorDocument;
- CppEditorOutline *m_cppEditorOutline;
-
- QTimer m_updateFunctionDeclDefLinkTimer;
-
- CppLocalRenaming m_localRenaming;
-
- SemanticInfo m_lastSemanticInfo;
-
- CppUseSelectionsUpdater m_useSelectionsUpdater;
-
- FunctionDeclDefLinkFinder *m_declDefLinkFinder;
- QSharedPointer<FunctionDeclDefLink> m_declDefLink;
-
- QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
-
- QAction *m_parseContextAction = nullptr;
- ParseContextWidget *m_parseContextWidget = nullptr;
- QToolButton *m_preprocessorButton = nullptr;
- MinimizableInfoBars::Actions m_showInfoBarActions;
-
- CppSelectionChanger m_cppSelectionChanger;
-};
-
-CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
- : m_modelManager(CppModelManager::instance())
- , m_cppEditorDocument(qobject_cast<CppEditorDocument *>(q->textDocument()))
- , m_cppEditorOutline(new CppEditorOutline(q))
- , m_localRenaming(q)
- , m_useSelectionsUpdater(q)
- , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q))
- , m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q))
- , m_cppSelectionChanger()
-{
-}
-
-CppEditorWidget::CppEditorWidget()
- : d(new CppEditorWidgetPrivate(this))
-{
- qRegisterMetaType<SemanticInfo>("CppTools::SemanticInfo");
-}
-
-void CppEditorWidget::finalizeInitialization()
-{
- d->m_cppEditorDocument = qobject_cast<CppEditorDocument *>(textDocument());
-
- setLanguageSettingsId(CppTools::Constants::CPP_SETTINGS_ID);
-
- // function combo box sorting
- connect(CppEditorPlugin::instance(), &CppEditorPlugin::outlineSortingChanged,
- outline(), &CppEditorOutline::setSorted);
-
- connect(d->m_cppEditorDocument, &CppEditorDocument::codeWarningsUpdated,
- this, &CppEditorWidget::onCodeWarningsUpdated);
- connect(d->m_cppEditorDocument, &CppEditorDocument::ifdefedOutBlocksUpdated,
- this, &CppEditorWidget::onIfdefedOutBlocksUpdated);
- connect(d->m_cppEditorDocument, &CppEditorDocument::cppDocumentUpdated,
- this, &CppEditorWidget::onCppDocumentUpdated);
- connect(d->m_cppEditorDocument, &CppEditorDocument::semanticInfoUpdated,
- this, [this](const CppTools::SemanticInfo &info) { updateSemanticInfo(info); });
-
- connect(d->m_declDefLinkFinder, &FunctionDeclDefLinkFinder::foundLink,
- this, &CppEditorWidget::onFunctionDeclDefLinkFound);
-
- connect(&d->m_useSelectionsUpdater,
- &CppUseSelectionsUpdater::selectionsForVariableUnderCursorUpdated,
- &d->m_localRenaming,
- &CppLocalRenaming::updateSelectionsForVariableUnderCursor);
-
- connect(&d->m_useSelectionsUpdater, &CppUseSelectionsUpdater::finished, this,
- [this] (SemanticInfo::LocalUseMap localUses) {
- d->m_lastSemanticInfo.localUsesUpdated = true;
- d->m_lastSemanticInfo.localUses = localUses;
- });
-
- connect(document(), &QTextDocument::contentsChange,
- &d->m_localRenaming, &CppLocalRenaming::onContentsChangeOfEditorWidgetDocument);
- connect(&d->m_localRenaming, &CppLocalRenaming::finished, [this] {
- cppEditorDocument()->recalculateSemanticInfoDetached();
- });
- connect(&d->m_localRenaming, &CppLocalRenaming::processKeyPressNormally,
- this, &CppEditorWidget::processKeyNormally);
- connect(this, &QPlainTextEdit::cursorPositionChanged,
- d->m_cppEditorOutline, &CppEditorOutline::updateIndex);
-
- connect(cppEditorDocument(), &CppEditorDocument::preprocessorSettingsChanged, this,
- [this](bool customSettings) {
- updateWidgetHighlighting(d->m_preprocessorButton, customSettings);
- });
-
- // set up function declaration - definition link
- d->m_updateFunctionDeclDefLinkTimer.setSingleShot(true);
- d->m_updateFunctionDeclDefLinkTimer.setInterval(UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL);
- connect(&d->m_updateFunctionDeclDefLinkTimer, &QTimer::timeout,
- this, &CppEditorWidget::updateFunctionDeclDefLinkNow);
- connect(this, &QPlainTextEdit::cursorPositionChanged, this, &CppEditorWidget::updateFunctionDeclDefLink);
- connect(this, &QPlainTextEdit::textChanged, this, &CppEditorWidget::updateFunctionDeclDefLink);
-
- // set up the use highlighitng
- connect(this, &CppEditorWidget::cursorPositionChanged, this, [this]() {
- if (!d->m_localRenaming.isActive())
- d->m_useSelectionsUpdater.scheduleUpdate();
-
- // Notify selection expander about the changed cursor.
- d->m_cppSelectionChanger.onCursorPositionChanged(textCursor());
- });
-
- // Toolbar: Outline/Overview combo box
- insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget());
-
- // Toolbar: Parse context
- ParseContextModel &parseContextModel = cppEditorDocument()->parseContextModel();
- d->m_parseContextWidget = new ParseContextWidget(parseContextModel, this);
- d->m_parseContextAction = insertExtraToolBarWidget(TextEditorWidget::Left,
- d->m_parseContextWidget);
- d->m_parseContextAction->setVisible(false);
- connect(&parseContextModel, &ParseContextModel::updated,
- this, [this](bool areMultipleAvailable) {
- d->m_parseContextAction->setVisible(areMultipleAvailable);
- });
-
- // Toolbar: '#' Button
- // TODO: Make "Additional Preprocessor Directives" also useful with Clang Code Model.
- if (!d->m_modelManager->isClangCodeModelActive()) {
- d->m_preprocessorButton = new QToolButton(this);
- d->m_preprocessorButton->setText(QLatin1String("#"));
- Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
- connect(cmd, &Command::keySequenceChanged,
- this, &CppEditorWidget::updatePreprocessorButtonTooltip);
- updatePreprocessorButtonTooltip();
- connect(d->m_preprocessorButton, &QAbstractButton::clicked,
- this, &CppEditorWidget::showPreProcessorWidget);
-
- insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton);
- }
-
- // Toolbar: Actions to show minimized info bars
- d->m_showInfoBarActions = MinimizableInfoBars::createShowInfoBarActions([this](QWidget *w) {
- return this->insertExtraToolBarWidget(TextEditorWidget::Left, w);
- });
- connect(&cppEditorDocument()->minimizableInfoBars(), &MinimizableInfoBars::showAction,
- this, &CppEditorWidget::onShowInfoBarAction);
-}
-
-void CppEditorWidget::finalizeInitializationAfterDuplication(TextEditorWidget *other)
-{
- QTC_ASSERT(other, return);
- CppEditorWidget *cppEditorWidget = qobject_cast<CppEditorWidget *>(other);
- QTC_ASSERT(cppEditorWidget, return);
-
- if (cppEditorWidget->isSemanticInfoValidExceptLocalUses())
- updateSemanticInfo(cppEditorWidget->semanticInfo());
- d->m_cppEditorOutline->update();
- const Id selectionKind = CodeWarningsSelection;
- setExtraSelections(selectionKind, cppEditorWidget->extraSelections(selectionKind));
-
- if (isWidgetHighlighted(cppEditorWidget->d->m_preprocessorButton))
- updateWidgetHighlighting(d->m_preprocessorButton, true);
-
- d->m_parseContextWidget->syncToModel();
- d->m_parseContextAction->setVisible(
- d->m_cppEditorDocument->parseContextModel().areMultipleAvailable());
-}
-
-CppEditorWidget::~CppEditorWidget()
-{
- // non-inline destructor, see section "Forward Declared Pointers" of QScopedPointer.
-}
-
-CppEditorDocument *CppEditorWidget::cppEditorDocument() const
-{
- return d->m_cppEditorDocument;
-}
-
-CppEditorOutline *CppEditorWidget::outline() const
-{
- return d->m_cppEditorOutline;
-}
-
-void CppEditorWidget::paste()
-{
- if (d->m_localRenaming.handlePaste())
- return;
-
- TextEditorWidget::paste();
-}
-
-void CppEditorWidget::cut()
-{
- if (d->m_localRenaming.handleCut())
- return;
-
- TextEditorWidget::cut();
-}
-
-void CppEditorWidget::selectAll()
-{
- if (d->m_localRenaming.handleSelectAll())
- return;
-
- TextEditorWidget::selectAll();
-}
-
-void CppEditorWidget::onCppDocumentUpdated()
-{
- d->m_cppEditorOutline->update();
-}
-
-void CppEditorWidget::onCodeWarningsUpdated(unsigned revision,
- const QList<QTextEdit::ExtraSelection> selections,
- const TextEditor::RefactorMarkers &refactorMarkers)
-{
- if (revision != documentRevision())
- return;
-
- setExtraSelections(TextEditorWidget::CodeWarningsSelection, selections);
- setRefactorMarkers(refactorMarkersWithoutClangMarkers() + refactorMarkers);
-}
-
-void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision,
- const QList<BlockRange> ifdefedOutBlocks)
-{
- if (revision != documentRevision())
- return;
- setIfdefedOutBlocks(ifdefedOutBlocks);
-}
-
-void CppEditorWidget::onShowInfoBarAction(const Id &id, bool show)
-{
- QAction *action = d->m_showInfoBarActions.value(id);
- QTC_ASSERT(action, return);
- action->setVisible(show);
-}
-
-void CppEditorWidget::findUsages()
-{
- if (!d->m_modelManager)
- return;
-
- SemanticInfo info = d->m_lastSemanticInfo;
- info.snapshot = CppModelManager::instance()->snapshot();
- info.snapshot.insert(info.doc);
-
- if (const Macro *macro = CppTools::findCanonicalMacro(textCursor(), info.doc)) {
- d->m_modelManager->findMacroUsages(*macro);
- } else {
- CanonicalSymbol cs(info.doc, info.snapshot);
- Symbol *canonicalSymbol = cs(textCursor());
- if (canonicalSymbol)
- d->m_modelManager->findUsages(canonicalSymbol, cs.context());
- }
-}
-
-void CppEditorWidget::renameUsages(const QString &replacement)
-{
- if (!d->m_modelManager)
- return;
-
- SemanticInfo info = d->m_lastSemanticInfo;
- info.snapshot = CppModelManager::instance()->snapshot();
- info.snapshot.insert(info.doc);
-
- if (const Macro *macro = CppTools::findCanonicalMacro(textCursor(), info.doc)) {
- d->m_modelManager->renameMacroUsages(*macro, replacement);
- } else {
- CanonicalSymbol cs(info.doc, info.snapshot);
- if (Symbol *canonicalSymbol = cs(textCursor()))
- if (canonicalSymbol->identifier() != 0)
- d->m_modelManager->renameUsages(canonicalSymbol, cs.context(), replacement);
- }
-}
-
-bool CppEditorWidget::selectBlockUp()
-{
- if (!behaviorSettings().m_smartSelectionChanging)
- return TextEditorWidget::selectBlockUp();
-
- QTextCursor cursor = textCursor();
- d->m_cppSelectionChanger.startChangeSelection();
- const bool changed =
- d->m_cppSelectionChanger.changeSelection(
- CppSelectionChanger::ExpandSelection,
- cursor,
- d->m_lastSemanticInfo.doc);
- if (changed)
- setTextCursor(cursor);
- d->m_cppSelectionChanger.stopChangeSelection();
-
- return changed;
-}
-
-bool CppEditorWidget::selectBlockDown()
-{
- if (!behaviorSettings().m_smartSelectionChanging)
- return TextEditorWidget::selectBlockDown();
-
- QTextCursor cursor = textCursor();
- d->m_cppSelectionChanger.startChangeSelection();
- const bool changed =
- d->m_cppSelectionChanger.changeSelection(
- CppSelectionChanger::ShrinkSelection,
- cursor,
- d->m_lastSemanticInfo.doc);
- if (changed)
- setTextCursor(cursor);
- d->m_cppSelectionChanger.stopChangeSelection();
-
- return changed;
-}
-
-void CppEditorWidget::updateWidgetHighlighting(QWidget *widget, bool highlight)
-{
- if (!widget)
- return;
-
- widget->setProperty("highlightWidget", highlight);
- widget->update();
-}
-
-bool CppEditorWidget::isWidgetHighlighted(QWidget *widget)
-{
- return widget ? widget->property("highlightWidget").toBool() : false;
-}
-
-void CppEditorWidget::renameSymbolUnderCursor()
-{
- if (refactoringEngine())
- renameSymbolUnderCursorClang();
- else
- renameSymbolUnderCursorBuiltin();
-}
-
-void CppEditorWidget::renameSymbolUnderCursorBuiltin()
-{
- updateSemanticInfo(d->m_cppEditorDocument->recalculateSemanticInfo(),
- /*updateUseSelectionSynchronously=*/ true);
-
- if (!d->m_localRenaming.start()) // Rename local symbol
- renameUsages(); // Rename non-local symbol or macro
-}
-
-namespace {
-
-QList<ProjectPart::Ptr> fetchProjectParts(CppTools::CppModelManager *modelManager,
- const Utils::FileName &filePath)
-{
- QList<ProjectPart::Ptr> projectParts = modelManager->projectPart(filePath);
-
- if (projectParts.isEmpty())
- projectParts = modelManager->projectPartFromDependencies(filePath);
- if (projectParts.isEmpty())
- projectParts.append(modelManager->fallbackProjectPart());
-
- return projectParts;
-}
-
-ProjectPart *findProjectPartForCurrentProject(const QList<ProjectPart::Ptr> &projectParts,
- ProjectExplorer::Project *currentProject)
-{
- auto found = std::find_if(projectParts.cbegin(),
- projectParts.cend(),
- [&] (const CppTools::ProjectPart::Ptr &projectPart) {
- return projectPart->project == currentProject;
- });
-
- if (found != projectParts.cend())
- return (*found).data();
-
- return 0;
-}
-
-}
-
-ProjectPart *CppEditorWidget::projectPart() const
-{
- if (!d->m_modelManager)
- return 0;
-
- auto projectParts = fetchProjectParts(d->m_modelManager, textDocument()->filePath());
-
- return findProjectPartForCurrentProject(projectParts,
- ProjectExplorer::ProjectTree::currentProject());
-}
-
-namespace {
-
-using ClangBackEnd::V2::SourceLocationContainer;
-using TextEditor::Convenience::selectAt;
-
-QTextCharFormat occurrencesTextCharFormat()
-{
- using TextEditor::TextEditorSettings;
-
- return TextEditorSettings::fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES);
-}
-
-QList<QTextEdit::ExtraSelection>
-sourceLocationsToExtraSelections(const std::vector<SourceLocationContainer> &sourceLocations,
- uint selectionLength,
- CppEditorWidget *cppEditorWidget)
-{
- const auto textCharFormat = occurrencesTextCharFormat();
-
- QList<QTextEdit::ExtraSelection> selections;
- selections.reserve(int(sourceLocations.size()));
-
- auto sourceLocationToExtraSelection = [&] (const SourceLocationContainer &sourceLocation) {
- QTextEdit::ExtraSelection selection;
-
- selection.cursor = selectAt(cppEditorWidget->textCursor(),
- sourceLocation.line(),
- sourceLocation.column(),
- selectionLength);
- selection.format = textCharFormat;
-
- return selection;
- };
-
-
- std::transform(sourceLocations.begin(),
- sourceLocations.end(),
- std::back_inserter(selections),
- sourceLocationToExtraSelection);
-
- return selections;
-};
-
-}
-
-void CppEditorWidget::renameSymbolUnderCursorClang()
-{
- using ClangBackEnd::SourceLocationsContainer;
-
- ProjectPart *theProjectPart = projectPart();
- if (refactoringEngine()->isUsable() && theProjectPart) {
- d->m_useSelectionsUpdater.abortSchedule();
-
- QPointer<CppEditorWidget> cppEditorWidget = this;
-
- auto renameSymbols = [=] (const QString &symbolName,
- const SourceLocationsContainer &sourceLocations,
- int revision) {
- if (cppEditorWidget) {
- viewport()->setCursor(Qt::IBeamCursor);
-
- if (revision == document()->revision()) {
- auto selections = sourceLocationsToExtraSelections(sourceLocations.sourceLocationContainers(),
- symbolName.size(),
- cppEditorWidget);
- setExtraSelections(TextEditor::TextEditorWidget::CodeSemanticsSelection,
- selections);
- d->m_localRenaming.updateSelectionsForVariableUnderCursor(selections);
- if (!d->m_localRenaming.start())
- renameUsages();
- }
- }
- };
-
- refactoringEngine()->startLocalRenaming(textCursor(),
- textDocument()->filePath(),
- document()->revision(),
- theProjectPart,
- std::move(renameSymbols));
-
- viewport()->setCursor(Qt::BusyCursor);
- }
-}
-
-void CppEditorWidget::updatePreprocessorButtonTooltip()
-{
- if (!d->m_preprocessorButton)
- return;
-
- Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
- QTC_ASSERT(cmd, return);
- d->m_preprocessorButton->setToolTip(cmd->action()->toolTip());
-}
-
-void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
-{
- if (!d->m_modelManager)
- return;
-
- if (!d->m_lastSemanticInfo.doc)
- return;
-
- // Find function declaration or definition under cursor
- Function *functionDefinitionSymbol = 0;
- Symbol *functionDeclarationSymbol = 0;
-
- ASTPath astPathFinder(d->m_lastSemanticInfo.doc);
- const QList<AST *> astPath = astPathFinder(textCursor());
-
- for (int i = 0, size = astPath.size(); i < size; ++i) {
- AST *ast = astPath.at(i);
- if (FunctionDefinitionAST *functionDefinitionAST = ast->asFunctionDefinition()) {
- if ((functionDefinitionSymbol = functionDefinitionAST->symbol))
- break; // Function definition found!
- } else if (SimpleDeclarationAST *simpleDeclaration = ast->asSimpleDeclaration()) {
- if (List<Symbol *> *symbols = simpleDeclaration->symbols) {
- if (Symbol *symbol = symbols->value) {
- if (symbol->isDeclaration() && symbol->type()->isFunctionType()) {
- functionDeclarationSymbol = symbol;
- break; // Function declaration found!
- }
- }
- }
- }
- }
-
- // Link to function definition/declaration
- CppEditorWidget::Link symbolLink;
- if (functionDeclarationSymbol) {
- symbolLink = linkToSymbol(d->m_modelManager->symbolFinder()
- ->findMatchingDefinition(functionDeclarationSymbol, d->m_modelManager->snapshot()));
- } else if (functionDefinitionSymbol) {
- const Snapshot snapshot = d->m_modelManager->snapshot();
- LookupContext context(d->m_lastSemanticInfo.doc, snapshot);
- ClassOrNamespace *binding = context.lookupType(functionDefinitionSymbol);
- const QList<LookupItem> declarations = context.lookup(functionDefinitionSymbol->name(),
- functionDefinitionSymbol->enclosingScope());
-
- QList<Symbol *> best;
- foreach (const LookupItem &r, declarations) {
- if (Symbol *decl = r.declaration()) {
- if (Function *funTy = decl->type()->asFunctionType()) {
- if (funTy->match(functionDefinitionSymbol)) {
- if (decl != functionDefinitionSymbol && binding == r.binding())
- best.prepend(decl);
- else
- best.append(decl);
- }
- }
- }
- }
-
- if (best.isEmpty())
- return;
- symbolLink = linkToSymbol(best.first());
- }
-
- // Open Editor at link position
- if (symbolLink.hasValidTarget())
- openLink(symbolLink, inNextSplit != alwaysOpenLinksInNextSplit());
-}
-
-CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor, bool resolveTarget,
- bool inNextSplit)
-{
- if (!d->m_modelManager)
- return Link();
-
- return d->m_followSymbolUnderCursor->findLink(cursor, resolveTarget,
- d->m_modelManager->snapshot(),
- d->m_lastSemanticInfo.doc,
- d->m_modelManager->symbolFinder(),
- inNextSplit);
-}
-
-unsigned CppEditorWidget::documentRevision() const
-{
- return document()->revision();
-}
-
-static bool isClangFixItAvailableMarker(const RefactorMarker &marker)
-{
- return marker.data.toString()
- == QLatin1String(CppTools::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID);
-}
-
-RefactorMarkers CppEditorWidget::refactorMarkersWithoutClangMarkers() const
-{
- RefactorMarkers clearedRefactorMarkers;
-
- foreach (const RefactorMarker &marker, refactorMarkers()) {
- if (isClangFixItAvailableMarker(marker))
- continue;
-
- clearedRefactorMarkers.append(marker);
- }
-
- return clearedRefactorMarkers;
-}
-
-RefactoringEngineInterface *CppEditorWidget::refactoringEngine() const
-{
- return CppTools::CppModelManager::refactoringEngine();
-}
-
-bool CppEditorWidget::isSemanticInfoValidExceptLocalUses() const
-{
- return d->m_lastSemanticInfo.doc
- && d->m_lastSemanticInfo.revision == documentRevision()
- && !d->m_lastSemanticInfo.snapshot.isEmpty();
-}
-
-bool CppEditorWidget::isSemanticInfoValid() const
-{
- return isSemanticInfoValidExceptLocalUses() && d->m_lastSemanticInfo.localUsesUpdated;
-}
-
-SemanticInfo CppEditorWidget::semanticInfo() const
-{
- return d->m_lastSemanticInfo;
-}
-
-bool CppEditorWidget::event(QEvent *e)
-{
- switch (e->type()) {
- case QEvent::ShortcutOverride:
- // handle escape manually if a rename is active
- if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape && d->m_localRenaming.isActive()) {
- e->accept();
- return true;
- }
- break;
- default:
- break;
- }
-
- return TextEditorWidget::event(e);
-}
-
-void CppEditorWidget::processKeyNormally(QKeyEvent *e)
-{
- TextEditorWidget::keyPressEvent(e);
-}
-
-void CppEditorWidget::contextMenuEvent(QContextMenuEvent *e)
-{
- // ### enable
- // updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
-
- QPointer<QMenu> menu(new QMenu(this));
-
- ActionContainer *mcontext = ActionManager::actionContainer(Constants::M_CONTEXT);
- QMenu *contextMenu = mcontext->menu();
-
- QMenu *quickFixMenu = new QMenu(tr("&Refactor"), menu);
- quickFixMenu->addAction(ActionManager::command(Constants::RENAME_SYMBOL_UNDER_CURSOR)->action());
-
- if (isSemanticInfoValidExceptLocalUses()) {
- d->m_useSelectionsUpdater.update(CppUseSelectionsUpdater::Synchronous);
- AssistInterface *interface = createAssistInterface(QuickFix, ExplicitlyInvoked);
- if (interface) {
- QScopedPointer<IAssistProcessor> processor(
- CppEditorPlugin::instance()->quickFixProvider()->createProcessor());
- QScopedPointer<IAssistProposal> proposal(processor->perform(interface));
- if (!proposal.isNull()) {
- auto model = static_cast<GenericProposalModel *>(proposal->model());
- for (int index = 0; index < model->size(); ++index) {
- auto item = static_cast<AssistProposalItem *>(model->proposalItem(index));
- QuickFixOperation::Ptr op = item->data().value<QuickFixOperation::Ptr>();
- QAction *action = quickFixMenu->addAction(op->description());
- connect(action, &QAction::triggered, this, [op] { op->perform(); });
- }
- delete model;
- }
- }
- }
-
- foreach (QAction *action, contextMenu->actions()) {
- menu->addAction(action);
- if (action->objectName() == QLatin1String(Constants::M_REFACTORING_MENU_INSERTION_POINT))
- menu->addMenu(quickFixMenu);
- }
-
- appendStandardContextMenuActions(menu);
-
- menu->exec(e->globalPos());
- if (!menu)
- return;
- delete menu;
-}
-
-void CppEditorWidget::keyPressEvent(QKeyEvent *e)
-{
- if (d->m_localRenaming.handleKeyPressEvent(e))
- return;
-
- if (handleStringSplitting(e))
- return;
-
- if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
- if (trySplitComment(this, semanticInfo().snapshot)) {
- e->accept();
- return;
- }
- }
-
- TextEditorWidget::keyPressEvent(e);
-}
-
-bool CppEditorWidget::handleStringSplitting(QKeyEvent *e) const
-{
- if (!TextEditorSettings::completionSettings().m_autoSplitStrings)
- return false;
-
- if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
- QTextCursor cursor = textCursor();
-
- const Kind stringKind = CPlusPlus::MatchingText::stringKindAtCursor(cursor);
- if (stringKind >= T_FIRST_STRING_LITERAL && stringKind < T_FIRST_RAW_STRING_LITERAL) {
- cursor.beginEditBlock();
- if (cursor.positionInBlock() > 0
- && cursor.block().text().at(cursor.positionInBlock() - 1) == QLatin1Char('\\')) {
- // Already escaped: simply go back to line, but do not indent.
- cursor.insertText(QLatin1String("\n"));
- } else if (e->modifiers() & Qt::ShiftModifier) {
- // With 'shift' modifier, escape the end of line character
- // and start at beginning of next line.
- cursor.insertText(QLatin1String("\\\n"));
- } else {
- // End the current string, and start a new one on the line, properly indented.
- cursor.insertText(QLatin1String("\"\n\""));
- textDocument()->autoIndent(cursor);
- }
- cursor.endEditBlock();
- e->accept();
- return true;
- }
- }
-
- return false;
-}
-
-void CppEditorWidget::slotCodeStyleSettingsChanged(const QVariant &)
-{
- QtStyleCodeFormatter formatter;
- formatter.invalidateCache(document());
-}
-
-void CppEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo,
- bool updateUseSelectionSynchronously)
-{
- if (semanticInfo.revision != documentRevision())
- return;
-
- d->m_lastSemanticInfo = semanticInfo;
-
- if (!d->m_localRenaming.isActive()) {
- const CppUseSelectionsUpdater::CallType type = updateUseSelectionSynchronously
- ? CppUseSelectionsUpdater::Synchronous
- : CppUseSelectionsUpdater::Asynchronous;
- d->m_useSelectionsUpdater.update(type);
- }
-
- // schedule a check for a decl/def link
- updateFunctionDeclDefLink();
-}
-
-AssistInterface *CppEditorWidget::createAssistInterface(AssistKind kind, AssistReason reason) const
-{
- if (kind == Completion) {
- if (CppCompletionAssistProvider *cap =
- qobject_cast<CppCompletionAssistProvider *>(cppEditorDocument()->completionAssistProvider())) {
- LanguageFeatures features = LanguageFeatures::defaultFeatures();
- if (Document::Ptr doc = d->m_lastSemanticInfo.doc)
- features = doc->languageFeatures();
- features.objCEnabled |= cppEditorDocument()->isObjCEnabled();
- return cap->createAssistInterface(
- textDocument()->filePath().toString(),
- this,
- features,
- position(),
- reason);
- }
- } else if (kind == QuickFix) {
- if (isSemanticInfoValid())
- return new CppQuickFixInterface(const_cast<CppEditorWidget *>(this), reason);
- } else {
- return TextEditorWidget::createAssistInterface(kind, reason);
- }
- return 0;
-}
-
-QSharedPointer<FunctionDeclDefLink> CppEditorWidget::declDefLink() const
-{
- return d->m_declDefLink;
-}
-
-void CppEditorWidget::onRefactorMarkerClicked(const RefactorMarker &marker)
-{
- if (marker.data.canConvert<FunctionDeclDefLink::Marker>()) {
- applyDeclDefLinkChanges(true);
- } else if (isClangFixItAvailableMarker(marker)) {
- int line, column;
- if (Convenience::convertPosition(document(), marker.cursor.position(), &line, &column)) {
- setTextCursor(marker.cursor);
- invokeAssist(TextEditor::QuickFix);
- }
- }
-}
-
-void CppEditorWidget::updateFunctionDeclDefLink()
-{
- const int pos = textCursor().selectionStart();
-
- // if there's already a link, abort it if the cursor is outside or the name changed
- // (adding a prefix is an exception since the user might type a return type)
- if (d->m_declDefLink
- && (pos < d->m_declDefLink->linkSelection.selectionStart()
- || pos > d->m_declDefLink->linkSelection.selectionEnd()
- || !d->m_declDefLink->nameSelection.selectedText().trimmed()
- .endsWith(d->m_declDefLink->nameInitial))) {
- abortDeclDefLink();
- return;
- }
-
- // don't start a new scan if there's one active and the cursor is already in the scanned area
- const QTextCursor scannedSelection = d->m_declDefLinkFinder->scannedSelection();
- if (!scannedSelection.isNull()
- && scannedSelection.selectionStart() <= pos
- && scannedSelection.selectionEnd() >= pos) {
- return;
- }
-
- d->m_updateFunctionDeclDefLinkTimer.start();
-}
-
-void CppEditorWidget::updateFunctionDeclDefLinkNow()
-{
- IEditor *editor = EditorManager::currentEditor();
- if (!editor || editor->widget() != this)
- return;
-
- const Snapshot semanticSnapshot = d->m_lastSemanticInfo.snapshot;
- const Document::Ptr semanticDoc = d->m_lastSemanticInfo.doc;
-
- if (d->m_declDefLink) {
- // update the change marker
- const Utils::ChangeSet changes = d->m_declDefLink->changes(semanticSnapshot);
- if (changes.isEmpty())
- d->m_declDefLink->hideMarker(this);
- else
- d->m_declDefLink->showMarker(this);
- return;
- }
-
- if (!isSemanticInfoValidExceptLocalUses())
- return;
-
- Snapshot snapshot = CppModelManager::instance()->snapshot();
- snapshot.insert(semanticDoc);
-
- d->m_declDefLinkFinder->startFindLinkAt(textCursor(), semanticDoc, snapshot);
-}
-
-void CppEditorWidget::onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink> link)
-{
- abortDeclDefLink();
- d->m_declDefLink = link;
- IDocument *targetDocument = DocumentModel::documentForFilePath( d->m_declDefLink->targetFile->fileName());
- if (textDocument() != targetDocument) {
- if (auto textDocument = qobject_cast<BaseTextDocument *>(targetDocument))
- connect(textDocument, &IDocument::contentsChanged,
- this, &CppEditorWidget::abortDeclDefLink);
- }
-
-}
-
-void CppEditorWidget::applyDeclDefLinkChanges(bool jumpToMatch)
-{
- if (!d->m_declDefLink)
- return;
- d->m_declDefLink->apply(this, jumpToMatch);
- abortDeclDefLink();
- updateFunctionDeclDefLink();
-}
-
-FollowSymbolUnderCursor *CppEditorWidget::followSymbolUnderCursorDelegate()
-{
- return d->m_followSymbolUnderCursor.data();
-}
-
-void CppEditorWidget::encourageApply()
-{
- if (d->m_localRenaming.encourageApply())
- return;
-
- TextEditorWidget::encourageApply();
-}
-
-void CppEditorWidget::abortDeclDefLink()
-{
- if (!d->m_declDefLink)
- return;
-
- IDocument *targetDocument = DocumentModel::documentForFilePath(d->m_declDefLink->targetFile->fileName());
- if (textDocument() != targetDocument) {
- if (auto textDocument = qobject_cast<BaseTextDocument *>(targetDocument))
- disconnect(textDocument, &IDocument::contentsChanged,
- this, &CppEditorWidget::abortDeclDefLink);
- }
-
- d->m_declDefLink->hideMarker(this);
- d->m_declDefLink.clear();
-}
-
-void CppEditorWidget::showPreProcessorWidget()
-{
- const QString filePath = textDocument()->filePath().toString();
-
- CppPreProcessorDialog dialog(filePath, this);
- if (dialog.exec() == QDialog::Accepted) {
- const QByteArray extraDirectives = dialog.extraPreprocessorDirectives().toUtf8();
- cppEditorDocument()->setExtraPreprocessorDirectives(extraDirectives);
- cppEditorDocument()->scheduleProcessDocument();
- }
-}
-
} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 5dc6ee7d49..fdc19cb6c3 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -25,28 +25,11 @@
#pragma once
-#include "cppfunctiondecldeflink.h"
-
#include <texteditor/texteditor.h>
-#include <QScopedPointer>
-
-namespace CppTools {
-class CppEditorOutline;
-class RefactoringEngineInterface;
-class SemanticInfo;
-class ProjectPart;
-}
-
namespace CppEditor {
namespace Internal {
-class CppEditorDocument;
-
-class CppEditorWidgetPrivate;
-class FollowSymbolUnderCursor;
-class FunctionDeclDefLink;
-
class CppEditor : public TextEditor::BaseTextEditor
{
Q_OBJECT
@@ -55,103 +38,6 @@ public:
CppEditor();
static void decorateEditor(TextEditor::TextEditorWidget *editor);
-
-};
-
-class CppEditorWidget : public TextEditor::TextEditorWidget
-{
- Q_OBJECT
-
-public:
- CppEditorWidget();
- ~CppEditorWidget() override;
-
- CppEditorDocument *cppEditorDocument() const;
- CppTools::CppEditorOutline *outline() const;
-
- CppTools::SemanticInfo semanticInfo() const;
- bool isSemanticInfoValidExceptLocalUses() const;
- bool isSemanticInfoValid() const;
-
- QSharedPointer<FunctionDeclDefLink> declDefLink() const;
- void applyDeclDefLinkChanges(bool jumpToMatch);
-
- TextEditor::AssistInterface *createAssistInterface(
- TextEditor::AssistKind kind,
- TextEditor::AssistReason reason) const override;
-
- FollowSymbolUnderCursor *followSymbolUnderCursorDelegate(); // exposed for tests
-
- void encourageApply() override;
-
- void paste() override;
- void cut() override;
- void selectAll() override;
-
- void switchDeclarationDefinition(bool inNextSplit);
- void showPreProcessorWidget();
-
- void findUsages();
- void renameSymbolUnderCursor();
- void renameUsages(const QString &replacement = QString());
-
- bool selectBlockUp() override;
- bool selectBlockDown() override;
-
- static void updateWidgetHighlighting(QWidget *widget, bool highlight);
- static bool isWidgetHighlighted(QWidget *widget);
-
-protected:
- bool event(QEvent *e) override;
- void contextMenuEvent(QContextMenuEvent *) override;
- void keyPressEvent(QKeyEvent *e) override;
- bool handleStringSplitting(QKeyEvent *e) const;
-
- Link findLinkAt(const QTextCursor &, bool resolveTarget = true,
- bool inNextSplit = false) override;
-
- void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker) override;
-
- void slotCodeStyleSettingsChanged(const QVariant &) override;
-
-private:
- void updateFunctionDeclDefLink();
- void updateFunctionDeclDefLinkNow();
- void abortDeclDefLink();
- void onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink> link);
-
- void onCppDocumentUpdated();
-
- void onCodeWarningsUpdated(unsigned revision,
- const QList<QTextEdit::ExtraSelection> selections,
- const TextEditor::RefactorMarkers &refactorMarkers);
- void onIfdefedOutBlocksUpdated(unsigned revision,
- const QList<TextEditor::BlockRange> ifdefedOutBlocks);
-
- void onShowInfoBarAction(const Core::Id &id, bool show);
-
- void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo,
- bool updateUseSelectionSynchronously = false);
- void updatePreprocessorButtonTooltip();
-
- void processKeyNormally(QKeyEvent *e);
-
- void finalizeInitialization() override;
- void finalizeInitializationAfterDuplication(TextEditorWidget *other) override;
-
- unsigned documentRevision() const;
-
- TextEditor::RefactorMarkers refactorMarkersWithoutClangMarkers() const;
-
- CppTools::RefactoringEngineInterface *refactoringEngine() const;
-
- void renameSymbolUnderCursorClang();
- void renameSymbolUnderCursorBuiltin();
-
- CppTools::ProjectPart *projectPart() const;
-
-private:
- QScopedPointer<CppEditorWidgetPrivate> d;
};
} // namespace Internal
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index 8efb3cd4f0..0bc3391ce8 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -11,8 +11,8 @@ HEADERS += \
cppeditorconstants.h \
cppeditorenums.h \
cppeditorplugin.h \
+ cppeditorwidget.h \
cppelementevaluator.h \
- cppfollowsymbolundercursor.h \
cppfunctiondecldeflink.h \
cpphighlighter.h \
cpphoverhandler.h \
@@ -28,8 +28,6 @@ HEADERS += \
cppquickfixes.h \
cpptypehierarchy.h \
cppuseselectionsupdater.h \
- cppvirtualfunctionassistprovider.h \
- cppvirtualfunctionproposalitem.h \
resourcepreviewhoverhandler.h
SOURCES += \
@@ -39,8 +37,8 @@ SOURCES += \
cppeditor.cpp \
cppeditordocument.cpp \
cppeditorplugin.cpp \
+ cppeditorwidget.cpp \
cppelementevaluator.cpp \
- cppfollowsymbolundercursor.cpp \
cppfunctiondecldeflink.cpp \
cpphighlighter.cpp \
cpphoverhandler.cpp \
@@ -56,8 +54,6 @@ SOURCES += \
cppquickfixes.cpp \
cpptypehierarchy.cpp \
cppuseselectionsupdater.cpp \
- cppvirtualfunctionassistprovider.cpp \
- cppvirtualfunctionproposalitem.cpp \
resourcepreviewhoverhandler.cpp
FORMS += \
diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs
index 32a403ea4c..5d8b17adb4 100644
--- a/src/plugins/cppeditor/cppeditor.qbs
+++ b/src/plugins/cppeditor/cppeditor.qbs
@@ -29,6 +29,8 @@ QtcPlugin {
"cppdocumentationcommenthelper.h",
"cppeditor.cpp",
"cppeditor.h",
+ "cppeditorwidget.cpp",
+ "cppeditorwidget.h",
"cppeditor.qrc",
"cppeditor_global.h",
"cppeditorconstants.h",
@@ -39,8 +41,6 @@ QtcPlugin {
"cppeditorplugin.h",
"cppelementevaluator.cpp",
"cppelementevaluator.h",
- "cppfollowsymbolundercursor.cpp",
- "cppfollowsymbolundercursor.h",
"cppfunctiondecldeflink.cpp",
"cppfunctiondecldeflink.h",
"cpphighlighter.cpp",
@@ -72,10 +72,6 @@ QtcPlugin {
"cpptypehierarchy.h",
"cppuseselectionsupdater.cpp",
"cppuseselectionsupdater.h",
- "cppvirtualfunctionassistprovider.cpp",
- "cppvirtualfunctionassistprovider.h",
- "cppvirtualfunctionproposalitem.cpp",
- "cppvirtualfunctionproposalitem.h",
"resourcepreviewhoverhandler.cpp",
"resourcepreviewhoverhandler.h",
]
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index 1fec96aae6..3f352f1ffe 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -28,7 +28,7 @@
#include "cppautocompleter.h"
#include "cppcodemodelinspectordialog.h"
#include "cppeditorconstants.h"
-#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditordocument.h"
#include "cpphighlighter.h"
#include "cpphoverhandler.h"
diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h
index a665394287..c1d86a6159 100644
--- a/src/plugins/cppeditor/cppeditorplugin.h
+++ b/src/plugins/cppeditor/cppeditorplugin.h
@@ -37,9 +37,7 @@ namespace TextEditor { class BaseTextEditor; }
namespace CppEditor {
namespace Internal {
-class CppEditorWidget;
class CppCodeModelInspectorDialog;
-class CppQuickFixCollector;
class CppQuickFixAssistProvider;
class CppEditorPlugin : public ExtensionSystem::IPlugin
@@ -93,6 +91,9 @@ private slots:
void test_FollowSymbolUnderCursor_data();
void test_FollowSymbolUnderCursor();
+ void test_FollowSymbolUnderCursor_QTCREATORBUG7903_data();
+ void test_FollowSymbolUnderCursor_QTCREATORBUG7903();
+
void test_FollowSymbolUnderCursor_followCall_data();
void test_FollowSymbolUnderCursor_followCall();
diff --git a/src/plugins/cppeditor/cppeditortestcase.cpp b/src/plugins/cppeditor/cppeditortestcase.cpp
index 7e62dbbc47..027523a02d 100644
--- a/src/plugins/cppeditor/cppeditortestcase.cpp
+++ b/src/plugins/cppeditor/cppeditortestcase.cpp
@@ -26,6 +26,7 @@
#include "cppeditortestcase.h"
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditordocument.h"
#include <coreplugin/editormanager/editormanager.h>
diff --git a/src/plugins/cppeditor/cppeditortestcase.h b/src/plugins/cppeditor/cppeditortestcase.h
index dafca4ec14..6eb9821bdd 100644
--- a/src/plugins/cppeditor/cppeditortestcase.h
+++ b/src/plugins/cppeditor/cppeditortestcase.h
@@ -25,8 +25,6 @@
#pragma once
-#include "cppeditor.h"
-
#include <cpptools/cpptoolstestcase.h>
#include <QVector>
diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp
new file mode 100644
index 0000000000..c14bb541be
--- /dev/null
+++ b/src/plugins/cppeditor/cppeditorwidget.cpp
@@ -0,0 +1,1085 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cppeditorwidget.h"
+
+#include "cppautocompleter.h"
+#include "cppdocumentationcommenthelper.h"
+#include "cppeditorconstants.h"
+#include "cppeditordocument.h"
+#include "cppeditorplugin.h"
+#include "cppfunctiondecldeflink.h"
+#include "cpphighlighter.h"
+#include "cpplocalrenaming.h"
+#include "cppminimizableinfobars.h"
+#include "cpppreprocessordialog.h"
+#include "cppquickfixassistant.h"
+#include "cppuseselectionsupdater.h"
+
+#include <clangsupport/sourcelocationscontainer.h>
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/editormanager/documentmodel.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/infobar.h>
+
+#include <cpptools/cppcanonicalsymbol.h>
+#include <cpptools/cppchecksymbols.h>
+#include <cpptools/cppcodeformatter.h>
+#include <cpptools/cppcompletionassistprovider.h>
+#include <cpptools/cppeditoroutline.h>
+#include <cpptools/cppmodelmanager.h>
+#include <cpptools/cppqtstyleindenter.h>
+#include <cpptools/cppselectionchanger.h>
+#include <cpptools/cppsemanticinfo.h>
+#include <cpptools/cpptoolsconstants.h>
+#include <cpptools/cpptoolsplugin.h>
+#include <cpptools/cpptoolsreuse.h>
+#include <cpptools/cpptoolssettings.h>
+#include <cpptools/cppworkingcopy.h>
+#include <cpptools/refactoringengineinterface.h>
+#include <cpptools/followsymbolinterface.h>
+#include <cpptools/symbolfinder.h>
+
+#include <texteditor/behaviorsettings.h>
+#include <texteditor/codeassist/assistproposalitem.h>
+#include <texteditor/codeassist/genericproposal.h>
+#include <texteditor/codeassist/genericproposalmodel.h>
+#include <texteditor/completionsettings.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/refactoroverlay.h>
+#include <texteditor/textdocument.h>
+#include <texteditor/textdocumentlayout.h>
+#include <texteditor/texteditorsettings.h>
+
+#include <projectexplorer/projecttree.h>
+
+#include <cplusplus/ASTPath.h>
+#include <cplusplus/FastPreprocessor.h>
+#include <cplusplus/MatchingText.h>
+#include <utils/progressindicator.h>
+#include <utils/qtcassert.h>
+#include <utils/textutils.h>
+#include <utils/utilsicons.h>
+
+#include <QAction>
+#include <QApplication>
+#include <QElapsedTimer>
+#include <QFutureWatcher>
+#include <QMenu>
+#include <QPointer>
+#include <QTextEdit>
+#include <QTimer>
+#include <QToolButton>
+#include <QWidgetAction>
+
+enum { UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL = 200 };
+
+using namespace Core;
+using namespace CPlusPlus;
+using namespace CppTools;
+using namespace TextEditor;
+
+namespace CppEditor {
+namespace Internal {
+
+class CppEditorWidgetPrivate
+{
+public:
+ CppEditorWidgetPrivate(CppEditorWidget *q);
+
+public:
+ QPointer<CppModelManager> m_modelManager;
+
+ CppEditorDocument *m_cppEditorDocument;
+ CppEditorOutline *m_cppEditorOutline;
+
+ QTimer m_updateFunctionDeclDefLinkTimer;
+ SemanticInfo m_lastSemanticInfo;
+
+ FunctionDeclDefLinkFinder *m_declDefLinkFinder;
+ QSharedPointer<FunctionDeclDefLink> m_declDefLink;
+
+ QAction *m_parseContextAction = nullptr;
+ ParseContextWidget *m_parseContextWidget = nullptr;
+ QToolButton *m_preprocessorButton = nullptr;
+ MinimizableInfoBars::Actions m_showInfoBarActions;
+
+ CppLocalRenaming m_localRenaming;
+ CppUseSelectionsUpdater m_useSelectionsUpdater;
+ CppSelectionChanger m_cppSelectionChanger;
+};
+
+CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
+ : m_modelManager(CppModelManager::instance())
+ , m_cppEditorDocument(qobject_cast<CppEditorDocument *>(q->textDocument()))
+ , m_cppEditorOutline(new CppEditorOutline(q))
+ , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q))
+ , m_localRenaming(q)
+ , m_useSelectionsUpdater(q)
+ , m_cppSelectionChanger()
+{}
+
+CppEditorWidget::CppEditorWidget()
+ : d(new CppEditorWidgetPrivate(this))
+{
+ qRegisterMetaType<SemanticInfo>("CppTools::SemanticInfo");
+}
+
+void CppEditorWidget::finalizeInitialization()
+{
+ d->m_cppEditorDocument = qobject_cast<CppEditorDocument *>(textDocument());
+
+ setLanguageSettingsId(CppTools::Constants::CPP_SETTINGS_ID);
+
+ // clang-format off
+ // function combo box sorting
+ connect(CppEditorPlugin::instance(), &CppEditorPlugin::outlineSortingChanged,
+ outline(), &CppEditorOutline::setSorted);
+
+ connect(d->m_cppEditorDocument, &CppEditorDocument::codeWarningsUpdated,
+ this, &CppEditorWidget::onCodeWarningsUpdated);
+ connect(d->m_cppEditorDocument, &CppEditorDocument::ifdefedOutBlocksUpdated,
+ this, &CppEditorWidget::onIfdefedOutBlocksUpdated);
+ connect(d->m_cppEditorDocument, &CppEditorDocument::cppDocumentUpdated,
+ this, &CppEditorWidget::onCppDocumentUpdated);
+ connect(d->m_cppEditorDocument, &CppEditorDocument::semanticInfoUpdated,
+ this, [this](const CppTools::SemanticInfo &info) { updateSemanticInfo(info); });
+
+ connect(d->m_declDefLinkFinder, &FunctionDeclDefLinkFinder::foundLink,
+ this, &CppEditorWidget::onFunctionDeclDefLinkFound);
+
+ connect(&d->m_useSelectionsUpdater,
+ &CppUseSelectionsUpdater::selectionsForVariableUnderCursorUpdated,
+ &d->m_localRenaming,
+ &CppLocalRenaming::updateSelectionsForVariableUnderCursor);
+
+ connect(&d->m_useSelectionsUpdater, &CppUseSelectionsUpdater::finished, this,
+ [this] (SemanticInfo::LocalUseMap localUses, bool success) {
+ if (success) {
+ d->m_lastSemanticInfo.localUsesUpdated = true;
+ d->m_lastSemanticInfo.localUses = localUses;
+ }
+ });
+
+ connect(document(), &QTextDocument::contentsChange,
+ &d->m_localRenaming, &CppLocalRenaming::onContentsChangeOfEditorWidgetDocument);
+ connect(&d->m_localRenaming, &CppLocalRenaming::finished, [this] {
+ cppEditorDocument()->recalculateSemanticInfoDetached();
+ });
+ connect(&d->m_localRenaming, &CppLocalRenaming::processKeyPressNormally,
+ this, &CppEditorWidget::processKeyNormally);
+ connect(this, &QPlainTextEdit::cursorPositionChanged,
+ d->m_cppEditorOutline, &CppEditorOutline::updateIndex);
+
+ connect(cppEditorDocument(), &CppEditorDocument::preprocessorSettingsChanged, this,
+ [this](bool customSettings) {
+ updateWidgetHighlighting(d->m_preprocessorButton, customSettings);
+ });
+
+ // set up function declaration - definition link
+ d->m_updateFunctionDeclDefLinkTimer.setSingleShot(true);
+ d->m_updateFunctionDeclDefLinkTimer.setInterval(UPDATE_FUNCTION_DECL_DEF_LINK_INTERVAL);
+ connect(&d->m_updateFunctionDeclDefLinkTimer, &QTimer::timeout,
+ this, &CppEditorWidget::updateFunctionDeclDefLinkNow);
+ connect(this, &QPlainTextEdit::cursorPositionChanged, this, &CppEditorWidget::updateFunctionDeclDefLink);
+ connect(this, &QPlainTextEdit::textChanged, this, &CppEditorWidget::updateFunctionDeclDefLink);
+
+ // set up the use highlighitng
+ connect(this, &CppEditorWidget::cursorPositionChanged, this, [this]() {
+ if (!d->m_localRenaming.isActive())
+ d->m_useSelectionsUpdater.scheduleUpdate();
+
+ // Notify selection expander about the changed cursor.
+ d->m_cppSelectionChanger.onCursorPositionChanged(textCursor());
+ });
+
+ // Toolbar: Outline/Overview combo box
+ insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget());
+
+ // Toolbar: Parse context
+ ParseContextModel &parseContextModel = cppEditorDocument()->parseContextModel();
+ d->m_parseContextWidget = new ParseContextWidget(parseContextModel, this);
+ d->m_parseContextAction = insertExtraToolBarWidget(TextEditorWidget::Left,
+ d->m_parseContextWidget);
+ d->m_parseContextAction->setVisible(false);
+ connect(&parseContextModel, &ParseContextModel::updated,
+ this, [this](bool areMultipleAvailable) {
+ d->m_parseContextAction->setVisible(areMultipleAvailable);
+ });
+ // clang-format on
+ // Toolbar: '#' Button
+ // TODO: Make "Additional Preprocessor Directives" also useful with Clang Code Model.
+ if (!d->m_modelManager->isClangCodeModelActive()) {
+ d->m_preprocessorButton = new QToolButton(this);
+ d->m_preprocessorButton->setText(QLatin1String("#"));
+ Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
+ connect(cmd, &Command::keySequenceChanged,
+ this, &CppEditorWidget::updatePreprocessorButtonTooltip);
+ updatePreprocessorButtonTooltip();
+ connect(d->m_preprocessorButton, &QAbstractButton::clicked,
+ this, &CppEditorWidget::showPreProcessorWidget);
+
+ insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton);
+ }
+
+ // Toolbar: Actions to show minimized info bars
+ d->m_showInfoBarActions = MinimizableInfoBars::createShowInfoBarActions([this](QWidget *w) {
+ return this->insertExtraToolBarWidget(TextEditorWidget::Left, w);
+ });
+ connect(&cppEditorDocument()->minimizableInfoBars(), &MinimizableInfoBars::showAction,
+ this, &CppEditorWidget::onShowInfoBarAction);
+}
+
+void CppEditorWidget::finalizeInitializationAfterDuplication(TextEditorWidget *other)
+{
+ QTC_ASSERT(other, return);
+ CppEditorWidget *cppEditorWidget = qobject_cast<CppEditorWidget *>(other);
+ QTC_ASSERT(cppEditorWidget, return);
+
+ if (cppEditorWidget->isSemanticInfoValidExceptLocalUses())
+ updateSemanticInfo(cppEditorWidget->semanticInfo());
+ d->m_cppEditorOutline->update();
+ const Id selectionKind = CodeWarningsSelection;
+ setExtraSelections(selectionKind, cppEditorWidget->extraSelections(selectionKind));
+
+ if (isWidgetHighlighted(cppEditorWidget->d->m_preprocessorButton))
+ updateWidgetHighlighting(d->m_preprocessorButton, true);
+
+ d->m_parseContextWidget->syncToModel();
+ d->m_parseContextAction->setVisible(
+ d->m_cppEditorDocument->parseContextModel().areMultipleAvailable());
+}
+
+CppEditorWidget::~CppEditorWidget()
+{
+ // non-inline destructor, see section "Forward Declared Pointers" of QScopedPointer.
+}
+
+CppEditorDocument *CppEditorWidget::cppEditorDocument() const
+{
+ return d->m_cppEditorDocument;
+}
+
+CppEditorOutline *CppEditorWidget::outline() const
+{
+ return d->m_cppEditorOutline;
+}
+
+void CppEditorWidget::paste()
+{
+ if (d->m_localRenaming.handlePaste())
+ return;
+
+ TextEditorWidget::paste();
+}
+
+void CppEditorWidget::cut()
+{
+ if (d->m_localRenaming.handleCut())
+ return;
+
+ TextEditorWidget::cut();
+}
+
+void CppEditorWidget::selectAll()
+{
+ if (d->m_localRenaming.handleSelectAll())
+ return;
+
+ TextEditorWidget::selectAll();
+}
+
+void CppEditorWidget::onCppDocumentUpdated()
+{
+ d->m_cppEditorOutline->update();
+}
+
+void CppEditorWidget::onCodeWarningsUpdated(unsigned revision,
+ const QList<QTextEdit::ExtraSelection> selections,
+ const TextEditor::RefactorMarkers &refactorMarkers)
+{
+ if (revision != documentRevision())
+ return;
+
+ setExtraSelections(TextEditorWidget::CodeWarningsSelection, selections);
+ setRefactorMarkers(refactorMarkersWithoutClangMarkers() + refactorMarkers);
+}
+
+void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision,
+ const QList<BlockRange> ifdefedOutBlocks)
+{
+ if (revision != documentRevision())
+ return;
+ setIfdefedOutBlocks(ifdefedOutBlocks);
+}
+
+void CppEditorWidget::onShowInfoBarAction(const Id &id, bool show)
+{
+ QAction *action = d->m_showInfoBarActions.value(id);
+ QTC_ASSERT(action, return);
+ action->setVisible(show);
+}
+
+void CppEditorWidget::findUsages()
+{
+ if (!d->m_modelManager)
+ return;
+
+ SemanticInfo info = d->m_lastSemanticInfo;
+ info.snapshot = CppModelManager::instance()->snapshot();
+ info.snapshot.insert(info.doc);
+
+ if (const Macro *macro = CppTools::findCanonicalMacro(textCursor(), info.doc)) {
+ d->m_modelManager->findMacroUsages(*macro);
+ } else {
+ CanonicalSymbol cs(info.doc, info.snapshot);
+ Symbol *canonicalSymbol = cs(textCursor());
+ if (canonicalSymbol)
+ d->m_modelManager->findUsages(canonicalSymbol, cs.context());
+ }
+}
+
+void CppEditorWidget::renameUsagesInternal(const QString &replacement)
+{
+ if (!d->m_modelManager)
+ return;
+
+ SemanticInfo info = d->m_lastSemanticInfo;
+ info.snapshot = CppModelManager::instance()->snapshot();
+ info.snapshot.insert(info.doc);
+
+ if (const Macro *macro = CppTools::findCanonicalMacro(textCursor(), info.doc)) {
+ d->m_modelManager->renameMacroUsages(*macro, replacement);
+ } else {
+ CanonicalSymbol cs(info.doc, info.snapshot);
+ if (Symbol *canonicalSymbol = cs(textCursor()))
+ if (canonicalSymbol->identifier() != 0)
+ d->m_modelManager->renameUsages(canonicalSymbol, cs.context(), replacement);
+ }
+}
+
+bool CppEditorWidget::selectBlockUp()
+{
+ if (!behaviorSettings().m_smartSelectionChanging)
+ return TextEditorWidget::selectBlockUp();
+
+ QTextCursor cursor = textCursor();
+ d->m_cppSelectionChanger.startChangeSelection();
+ const bool changed = d->m_cppSelectionChanger
+ .changeSelection(CppSelectionChanger::ExpandSelection,
+ cursor,
+ d->m_lastSemanticInfo.doc);
+ if (changed)
+ setTextCursor(cursor);
+ d->m_cppSelectionChanger.stopChangeSelection();
+
+ return changed;
+}
+
+bool CppEditorWidget::selectBlockDown()
+{
+ if (!behaviorSettings().m_smartSelectionChanging)
+ return TextEditorWidget::selectBlockDown();
+
+ QTextCursor cursor = textCursor();
+ d->m_cppSelectionChanger.startChangeSelection();
+ const bool changed = d->m_cppSelectionChanger
+ .changeSelection(CppSelectionChanger::ShrinkSelection,
+ cursor,
+ d->m_lastSemanticInfo.doc);
+ if (changed)
+ setTextCursor(cursor);
+ d->m_cppSelectionChanger.stopChangeSelection();
+
+ return changed;
+}
+
+void CppEditorWidget::updateWidgetHighlighting(QWidget *widget, bool highlight)
+{
+ if (!widget)
+ return;
+
+ widget->setProperty("highlightWidget", highlight);
+ widget->update();
+}
+
+bool CppEditorWidget::isWidgetHighlighted(QWidget *widget)
+{
+ return widget ? widget->property("highlightWidget").toBool() : false;
+}
+
+namespace {
+
+QList<ProjectPart::Ptr> fetchProjectParts(CppTools::CppModelManager *modelManager,
+ const Utils::FileName &filePath)
+{
+ QList<ProjectPart::Ptr> projectParts = modelManager->projectPart(filePath);
+
+ if (projectParts.isEmpty())
+ projectParts = modelManager->projectPartFromDependencies(filePath);
+ if (projectParts.isEmpty())
+ projectParts.append(modelManager->fallbackProjectPart());
+
+ return projectParts;
+}
+
+ProjectPart *findProjectPartForCurrentProject(const QList<ProjectPart::Ptr> &projectParts,
+ ProjectExplorer::Project *currentProject)
+{
+ auto found = std::find_if(projectParts.cbegin(),
+ projectParts.cend(),
+ [&](const CppTools::ProjectPart::Ptr &projectPart) {
+ return projectPart->project == currentProject;
+ });
+
+ if (found != projectParts.cend())
+ return (*found).data();
+
+ return 0;
+}
+
+} // namespace
+
+ProjectPart *CppEditorWidget::projectPart() const
+{
+ if (!d->m_modelManager)
+ return 0;
+
+ auto projectParts = fetchProjectParts(d->m_modelManager, textDocument()->filePath());
+
+ return findProjectPartForCurrentProject(projectParts,
+ ProjectExplorer::ProjectTree::currentProject());
+}
+
+namespace {
+
+using ClangBackEnd::V2::SourceLocationContainer;
+using Utils::Text::selectAt;
+
+QTextCharFormat occurrencesTextCharFormat()
+{
+ using TextEditor::TextEditorSettings;
+
+ return TextEditorSettings::fontSettings().toTextCharFormat(TextEditor::C_OCCURRENCES);
+}
+
+QList<QTextEdit::ExtraSelection> sourceLocationsToExtraSelections(
+ const std::vector<SourceLocationContainer> &sourceLocations,
+ uint selectionLength,
+ CppEditorWidget *cppEditorWidget)
+{
+ const auto textCharFormat = occurrencesTextCharFormat();
+
+ QList<QTextEdit::ExtraSelection> selections;
+ selections.reserve(int(sourceLocations.size()));
+
+ auto sourceLocationToExtraSelection = [&](const SourceLocationContainer &sourceLocation) {
+ QTextEdit::ExtraSelection selection;
+
+ selection.cursor = selectAt(cppEditorWidget->textCursor(),
+ sourceLocation.line(),
+ sourceLocation.column(),
+ selectionLength);
+ selection.format = textCharFormat;
+
+ return selection;
+ };
+
+ std::transform(sourceLocations.begin(),
+ sourceLocations.end(),
+ std::back_inserter(selections),
+ sourceLocationToExtraSelection);
+
+ return selections;
+};
+
+}
+
+void CppEditorWidget::renameSymbolUnderCursor()
+{
+ using ClangBackEnd::SourceLocationsContainer;
+
+ ProjectPart *projPart = projectPart();
+ if (!refactoringEngine().isUsable() || !projPart)
+ return;
+
+ d->m_useSelectionsUpdater.abortSchedule();
+
+ QPointer<CppEditorWidget> cppEditorWidget = this;
+
+ auto renameSymbols = [=](const QString &symbolName,
+ const SourceLocationsContainer &sourceLocations,
+ int revision) {
+ if (cppEditorWidget) {
+ viewport()->setCursor(Qt::IBeamCursor);
+
+ if (revision != document()->revision())
+ return;
+ if (sourceLocations.hasContent()) {
+ QList<QTextEdit::ExtraSelection> selections
+ = sourceLocationsToExtraSelections(sourceLocations.sourceLocationContainers(),
+ static_cast<uint>(symbolName.size()),
+ cppEditorWidget);
+ setExtraSelections(TextEditor::TextEditorWidget::CodeSemanticsSelection, selections);
+ d->m_localRenaming.updateSelectionsForVariableUnderCursor(selections);
+ }
+ if (!d->m_localRenaming.start()) {
+ refactoringEngine().startGlobalRenaming(
+ CppTools::CursorInEditor{textCursor(), textDocument()->filePath(), this});
+ }
+ }
+ };
+
+ viewport()->setCursor(Qt::BusyCursor);
+ refactoringEngine().startLocalRenaming(CppTools::CursorInEditor{textCursor(),
+ textDocument()->filePath(),
+ this},
+ projPart,
+ std::move(renameSymbols));
+}
+
+void CppEditorWidget::updatePreprocessorButtonTooltip()
+{
+ if (!d->m_preprocessorButton)
+ return;
+
+ Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
+ QTC_ASSERT(cmd, return );
+ d->m_preprocessorButton->setToolTip(cmd->action()->toolTip());
+}
+
+void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
+{
+ if (!d->m_modelManager)
+ return;
+
+ if (!d->m_lastSemanticInfo.doc)
+ return;
+
+ // Find function declaration or definition under cursor
+ Function *functionDefinitionSymbol = 0;
+ Symbol *functionDeclarationSymbol = 0;
+
+ ASTPath astPathFinder(d->m_lastSemanticInfo.doc);
+ const QList<AST *> astPath = astPathFinder(textCursor());
+
+ for (int i = 0, size = astPath.size(); i < size; ++i) {
+ AST *ast = astPath.at(i);
+ if (FunctionDefinitionAST *functionDefinitionAST = ast->asFunctionDefinition()) {
+ if ((functionDefinitionSymbol = functionDefinitionAST->symbol))
+ break; // Function definition found!
+ } else if (SimpleDeclarationAST *simpleDeclaration = ast->asSimpleDeclaration()) {
+ if (List<Symbol *> *symbols = simpleDeclaration->symbols) {
+ if (Symbol *symbol = symbols->value) {
+ if (symbol->isDeclaration() && symbol->type()->isFunctionType()) {
+ functionDeclarationSymbol = symbol;
+ break; // Function declaration found!
+ }
+ }
+ }
+ }
+ }
+
+ // Link to function definition/declaration
+ CppEditorWidget::Link symbolLink;
+ if (functionDeclarationSymbol) {
+ symbolLink = linkToSymbol(
+ d->m_modelManager->symbolFinder()
+ ->findMatchingDefinition(functionDeclarationSymbol, d->m_modelManager->snapshot()));
+ } else if (functionDefinitionSymbol) {
+ const Snapshot snapshot = d->m_modelManager->snapshot();
+ LookupContext context(d->m_lastSemanticInfo.doc, snapshot);
+ ClassOrNamespace *binding = context.lookupType(functionDefinitionSymbol);
+ const QList<LookupItem> declarations
+ = context.lookup(functionDefinitionSymbol->name(),
+ functionDefinitionSymbol->enclosingScope());
+
+ QList<Symbol *> best;
+ foreach (const LookupItem &r, declarations) {
+ if (Symbol *decl = r.declaration()) {
+ if (Function *funTy = decl->type()->asFunctionType()) {
+ if (funTy->match(functionDefinitionSymbol)) {
+ if (decl != functionDefinitionSymbol && binding == r.binding())
+ best.prepend(decl);
+ else
+ best.append(decl);
+ }
+ }
+ }
+ }
+
+ if (best.isEmpty())
+ return;
+ symbolLink = linkToSymbol(best.first());
+ }
+
+ // Open Editor at link position
+ if (symbolLink.hasValidTarget())
+ openLink(symbolLink, inNextSplit != alwaysOpenLinksInNextSplit());
+}
+
+CppEditorWidget::Link CppEditorWidget::findLinkAt(const QTextCursor &cursor,
+ bool resolveTarget,
+ bool inNextSplit)
+{
+ if (!d->m_modelManager)
+ return Link();
+
+ const Utils::FileName &filePath = textDocument()->filePath();
+
+ return followSymbolInterface().findLink(CppTools::CursorInEditor{cursor, filePath, this},
+ resolveTarget,
+ d->m_modelManager->snapshot(),
+ d->m_lastSemanticInfo.doc,
+ d->m_modelManager->symbolFinder(),
+ inNextSplit);
+}
+
+unsigned CppEditorWidget::documentRevision() const
+{
+ return document()->revision();
+}
+
+static bool isClangFixItAvailableMarker(const RefactorMarker &marker)
+{
+ return marker.data.toString()
+ == QLatin1String(CppTools::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID);
+}
+
+RefactorMarkers CppEditorWidget::refactorMarkersWithoutClangMarkers() const
+{
+ RefactorMarkers clearedRefactorMarkers;
+
+ foreach (const RefactorMarker &marker, refactorMarkers()) {
+ if (isClangFixItAvailableMarker(marker))
+ continue;
+
+ clearedRefactorMarkers.append(marker);
+ }
+
+ return clearedRefactorMarkers;
+}
+
+RefactoringEngineInterface &CppEditorWidget::refactoringEngine() const
+{
+ return CppTools::CppModelManager::refactoringEngine();
+}
+
+CppTools::FollowSymbolInterface &CppEditorWidget::followSymbolInterface() const
+{
+ return CppTools::CppModelManager::instance()->followSymbolInterface();
+}
+
+bool CppEditorWidget::isSemanticInfoValidExceptLocalUses() const
+{
+ return d->m_lastSemanticInfo.doc && d->m_lastSemanticInfo.revision == documentRevision()
+ && !d->m_lastSemanticInfo.snapshot.isEmpty();
+}
+
+bool CppEditorWidget::isSemanticInfoValid() const
+{
+ return isSemanticInfoValidExceptLocalUses() && d->m_lastSemanticInfo.localUsesUpdated;
+}
+
+SemanticInfo CppEditorWidget::semanticInfo() const
+{
+ return d->m_lastSemanticInfo;
+}
+
+bool CppEditorWidget::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::ShortcutOverride:
+ // handle escape manually if a rename is active
+ if (static_cast<QKeyEvent *>(e)->key() == Qt::Key_Escape && d->m_localRenaming.isActive()) {
+ e->accept();
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TextEditorWidget::event(e);
+}
+
+void CppEditorWidget::processKeyNormally(QKeyEvent *e)
+{
+ TextEditorWidget::keyPressEvent(e);
+}
+
+static void addRefactoringActions(QMenu *menu, AssistInterface *iface)
+{
+ if (!iface || !menu)
+ return;
+
+ using Processor = QScopedPointer<IAssistProcessor>;
+ using Proposal = QScopedPointer<IAssistProposal>;
+ using Model = QScopedPointer<GenericProposalModel>;
+
+ const Processor processor(CppEditorPlugin::instance()->quickFixProvider()->createProcessor());
+ const Proposal proposal(processor->perform(iface)); // OK, perform() takes ownership of iface.
+ if (proposal) {
+ Model model(static_cast<GenericProposalModel *>(proposal->model()));
+ for (int index = 0; index < model->size(); ++index) {
+ const auto item = static_cast<AssistProposalItem *>(model->proposalItem(index));
+ const QuickFixOperation::Ptr op = item->data().value<QuickFixOperation::Ptr>();
+ const QAction *action = menu->addAction(op->description());
+ QObject::connect(action, &QAction::triggered, menu, [op] { op->perform(); });
+ }
+ }
+}
+
+class ProgressIndicatorMenuItem : public QWidgetAction
+{
+ Q_OBJECT
+
+public:
+ ProgressIndicatorMenuItem(QObject *parent) : QWidgetAction(parent) {}
+
+protected:
+ QWidget *createWidget(QWidget *parent = nullptr) override
+ {
+ return new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Small, parent);
+ }
+};
+
+QMenu *CppEditorWidget::createRefactorMenu(QWidget *parent) const
+{
+ auto *menu = new QMenu(tr("&Refactor"), parent);
+ menu->addAction(ActionManager::command(Constants::RENAME_SYMBOL_UNDER_CURSOR)->action());
+
+ // ### enable
+ // updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
+
+ if (isSemanticInfoValidExceptLocalUses()) {
+ d->m_useSelectionsUpdater.abortSchedule();
+
+ const CppUseSelectionsUpdater::RunnerInfo runnerInfo = d->m_useSelectionsUpdater.update();
+ switch (runnerInfo) {
+ case CppUseSelectionsUpdater::RunnerInfo::AlreadyUpToDate:
+ addRefactoringActions(menu, createAssistInterface(QuickFix, ExplicitlyInvoked));
+ break;
+ case CppUseSelectionsUpdater::RunnerInfo::Started: {
+ // Update the refactor menu once we get the results.
+ auto *progressIndicatorMenuItem = new ProgressIndicatorMenuItem(menu);
+ menu->addAction(progressIndicatorMenuItem);
+
+ connect(&d->m_useSelectionsUpdater, &CppUseSelectionsUpdater::finished,
+ menu, [=] (SemanticInfo::LocalUseMap, bool success) {
+ QTC_CHECK(success);
+ menu->removeAction(progressIndicatorMenuItem);
+ addRefactoringActions(menu, createAssistInterface(QuickFix, ExplicitlyInvoked));
+ });
+ break;
+ }
+ case CppUseSelectionsUpdater::RunnerInfo::FailedToStart:
+ case CppUseSelectionsUpdater::RunnerInfo::Invalid:
+ QTC_CHECK(false && "Unexpected CppUseSelectionsUpdater runner result");
+ }
+ }
+
+ return menu;
+}
+
+static void appendCustomContextMenuActionsAndMenus(QMenu *menu, QMenu *refactorMenu)
+{
+ bool isRefactoringMenuAdded = false;
+ const QMenu *contextMenu = ActionManager::actionContainer(Constants::M_CONTEXT)->menu();
+ for (QAction *action : contextMenu->actions()) {
+ menu->addAction(action);
+ if (action->objectName() == Constants::M_REFACTORING_MENU_INSERTION_POINT) {
+ isRefactoringMenuAdded = true;
+ menu->addMenu(refactorMenu);
+ }
+ }
+
+ QTC_CHECK(isRefactoringMenuAdded);
+}
+
+void CppEditorWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ const QPointer<QMenu> menu(new QMenu(this));
+
+ appendCustomContextMenuActionsAndMenus(menu, createRefactorMenu(menu));
+ appendStandardContextMenuActions(menu);
+
+ menu->exec(e->globalPos());
+ if (menu)
+ delete menu; // OK, menu was not already deleted by closed editor widget.
+}
+
+void CppEditorWidget::keyPressEvent(QKeyEvent *e)
+{
+ if (d->m_localRenaming.handleKeyPressEvent(e))
+ return;
+
+ if (handleStringSplitting(e))
+ return;
+
+ if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
+ if (trySplitComment(this, semanticInfo().snapshot)) {
+ e->accept();
+ return;
+ }
+ }
+
+ TextEditorWidget::keyPressEvent(e);
+}
+
+bool CppEditorWidget::handleStringSplitting(QKeyEvent *e) const
+{
+ if (!TextEditorSettings::completionSettings().m_autoSplitStrings)
+ return false;
+
+ if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
+ QTextCursor cursor = textCursor();
+
+ const Kind stringKind = CPlusPlus::MatchingText::stringKindAtCursor(cursor);
+ if (stringKind >= T_FIRST_STRING_LITERAL && stringKind < T_FIRST_RAW_STRING_LITERAL) {
+ cursor.beginEditBlock();
+ if (cursor.positionInBlock() > 0
+ && cursor.block().text().at(cursor.positionInBlock() - 1) == QLatin1Char('\\')) {
+ // Already escaped: simply go back to line, but do not indent.
+ cursor.insertText(QLatin1String("\n"));
+ } else if (e->modifiers() & Qt::ShiftModifier) {
+ // With 'shift' modifier, escape the end of line character
+ // and start at beginning of next line.
+ cursor.insertText(QLatin1String("\\\n"));
+ } else {
+ // End the current string, and start a new one on the line, properly indented.
+ cursor.insertText(QLatin1String("\"\n\""));
+ textDocument()->autoIndent(cursor);
+ }
+ cursor.endEditBlock();
+ e->accept();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CppEditorWidget::slotCodeStyleSettingsChanged(const QVariant &)
+{
+ QtStyleCodeFormatter formatter;
+ formatter.invalidateCache(document());
+}
+
+void CppEditorWidget::updateSemanticInfo()
+{
+ updateSemanticInfo(d->m_cppEditorDocument->recalculateSemanticInfo(),
+ /*updateUseSelectionSynchronously=*/ true);
+}
+
+void CppEditorWidget::updateSemanticInfo(const SemanticInfo &semanticInfo,
+ bool updateUseSelectionSynchronously)
+{
+ if (semanticInfo.revision != documentRevision())
+ return;
+
+ d->m_lastSemanticInfo = semanticInfo;
+
+ if (!d->m_localRenaming.isActive()) {
+ const CppUseSelectionsUpdater::CallType type = updateUseSelectionSynchronously
+ ? CppUseSelectionsUpdater::CallType::Synchronous
+ : CppUseSelectionsUpdater::CallType::Asynchronous;
+ d->m_useSelectionsUpdater.update(type);
+ }
+
+ // schedule a check for a decl/def link
+ updateFunctionDeclDefLink();
+}
+
+AssistInterface *CppEditorWidget::createAssistInterface(AssistKind kind, AssistReason reason) const
+{
+ if (kind == Completion) {
+ if (CppCompletionAssistProvider *cap = qobject_cast<CppCompletionAssistProvider *>(
+ cppEditorDocument()->completionAssistProvider())) {
+ LanguageFeatures features = LanguageFeatures::defaultFeatures();
+ if (Document::Ptr doc = d->m_lastSemanticInfo.doc)
+ features = doc->languageFeatures();
+ features.objCEnabled |= cppEditorDocument()->isObjCEnabled();
+ return cap->createAssistInterface(textDocument()->filePath().toString(),
+ this,
+ features,
+ position(),
+ reason);
+ }
+ } else if (kind == QuickFix) {
+ if (isSemanticInfoValid())
+ return new CppQuickFixInterface(const_cast<CppEditorWidget *>(this), reason);
+ } else {
+ return TextEditorWidget::createAssistInterface(kind, reason);
+ }
+ return 0;
+}
+
+QSharedPointer<FunctionDeclDefLink> CppEditorWidget::declDefLink() const
+{
+ return d->m_declDefLink;
+}
+
+void CppEditorWidget::onRefactorMarkerClicked(const RefactorMarker &marker)
+{
+ if (marker.data.canConvert<FunctionDeclDefLink::Marker>()) {
+ applyDeclDefLinkChanges(true);
+ } else if (isClangFixItAvailableMarker(marker)) {
+ int line, column;
+ if (Utils::Text::convertPosition(document(), marker.cursor.position(), &line, &column)) {
+ setTextCursor(marker.cursor);
+ invokeAssist(TextEditor::QuickFix);
+ }
+ }
+}
+
+void CppEditorWidget::updateFunctionDeclDefLink()
+{
+ const int pos = textCursor().selectionStart();
+
+ // if there's already a link, abort it if the cursor is outside or the name changed
+ // (adding a prefix is an exception since the user might type a return type)
+ if (d->m_declDefLink
+ && (pos < d->m_declDefLink->linkSelection.selectionStart()
+ || pos > d->m_declDefLink->linkSelection.selectionEnd()
+ || !d->m_declDefLink->nameSelection.selectedText().trimmed().endsWith(
+ d->m_declDefLink->nameInitial))) {
+ abortDeclDefLink();
+ return;
+ }
+
+ // don't start a new scan if there's one active and the cursor is already in the scanned area
+ const QTextCursor scannedSelection = d->m_declDefLinkFinder->scannedSelection();
+ if (!scannedSelection.isNull() && scannedSelection.selectionStart() <= pos
+ && scannedSelection.selectionEnd() >= pos) {
+ return;
+ }
+
+ d->m_updateFunctionDeclDefLinkTimer.start();
+}
+
+void CppEditorWidget::updateFunctionDeclDefLinkNow()
+{
+ IEditor *editor = EditorManager::currentEditor();
+ if (!editor || editor->widget() != this)
+ return;
+
+ const Snapshot semanticSnapshot = d->m_lastSemanticInfo.snapshot;
+ const Document::Ptr semanticDoc = d->m_lastSemanticInfo.doc;
+
+ if (d->m_declDefLink) {
+ // update the change marker
+ const Utils::ChangeSet changes = d->m_declDefLink->changes(semanticSnapshot);
+ if (changes.isEmpty())
+ d->m_declDefLink->hideMarker(this);
+ else
+ d->m_declDefLink->showMarker(this);
+ return;
+ }
+
+ if (!isSemanticInfoValidExceptLocalUses())
+ return;
+
+ Snapshot snapshot = CppModelManager::instance()->snapshot();
+ snapshot.insert(semanticDoc);
+
+ d->m_declDefLinkFinder->startFindLinkAt(textCursor(), semanticDoc, snapshot);
+}
+
+void CppEditorWidget::onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink> link)
+{
+ abortDeclDefLink();
+ d->m_declDefLink = link;
+ IDocument *targetDocument = DocumentModel::documentForFilePath(
+ d->m_declDefLink->targetFile->fileName());
+ if (textDocument() != targetDocument) {
+ if (auto textDocument = qobject_cast<BaseTextDocument *>(targetDocument))
+ connect(textDocument,
+ &IDocument::contentsChanged,
+ this,
+ &CppEditorWidget::abortDeclDefLink);
+ }
+}
+
+void CppEditorWidget::applyDeclDefLinkChanges(bool jumpToMatch)
+{
+ if (!d->m_declDefLink)
+ return;
+ d->m_declDefLink->apply(this, jumpToMatch);
+ abortDeclDefLink();
+ updateFunctionDeclDefLink();
+}
+
+void CppEditorWidget::encourageApply()
+{
+ if (d->m_localRenaming.encourageApply())
+ return;
+
+ TextEditorWidget::encourageApply();
+}
+
+void CppEditorWidget::abortDeclDefLink()
+{
+ if (!d->m_declDefLink)
+ return;
+
+ IDocument *targetDocument = DocumentModel::documentForFilePath(
+ d->m_declDefLink->targetFile->fileName());
+ if (textDocument() != targetDocument) {
+ if (auto textDocument = qobject_cast<BaseTextDocument *>(targetDocument))
+ disconnect(textDocument,
+ &IDocument::contentsChanged,
+ this,
+ &CppEditorWidget::abortDeclDefLink);
+ }
+
+ d->m_declDefLink->hideMarker(this);
+ d->m_declDefLink.clear();
+}
+
+void CppEditorWidget::showPreProcessorWidget()
+{
+ const QString filePath = textDocument()->filePath().toString();
+
+ CppPreProcessorDialog dialog(filePath, this);
+ if (dialog.exec() == QDialog::Accepted) {
+ const QByteArray extraDirectives = dialog.extraPreprocessorDirectives().toUtf8();
+ cppEditorDocument()->setExtraPreprocessorDirectives(extraDirectives);
+ cppEditorDocument()->scheduleProcessDocument();
+ }
+}
+
+void CppEditorWidget::invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind,
+ TextEditor::IAssistProvider *provider)
+{
+ invokeAssist(assistKind, provider);
+}
+
+} // namespace Internal
+} // namespace CppEditor
+
+#include "cppeditorwidget.moc"
diff --git a/src/plugins/cppeditor/cppeditorwidget.h b/src/plugins/cppeditor/cppeditorwidget.h
new file mode 100644
index 0000000000..166ff10557
--- /dev/null
+++ b/src/plugins/cppeditor/cppeditorwidget.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <texteditor/texteditor.h>
+
+#include <cpptools/cppeditorwidgetinterface.h>
+
+#include <QScopedPointer>
+
+namespace CppTools {
+class CppEditorOutline;
+class RefactoringEngineInterface;
+class FollowSymbolInterface;
+class SemanticInfo;
+class ProjectPart;
+}
+
+namespace CppEditor {
+namespace Internal {
+
+class CppEditorDocument;
+
+class CppEditorWidgetPrivate;
+class FunctionDeclDefLink;
+
+class CppEditorWidget : public TextEditor::TextEditorWidget,
+ public CppTools::CppEditorWidgetInterface
+{
+ Q_OBJECT
+
+public:
+ CppEditorWidget();
+ ~CppEditorWidget() override;
+
+ CppEditorDocument *cppEditorDocument() const;
+ CppTools::CppEditorOutline *outline() const;
+
+ CppTools::SemanticInfo semanticInfo() const;
+ bool isSemanticInfoValidExceptLocalUses() const;
+ bool isSemanticInfoValid() const;
+
+ QSharedPointer<FunctionDeclDefLink> declDefLink() const;
+ void applyDeclDefLinkChanges(bool jumpToMatch);
+
+ TextEditor::AssistInterface *createAssistInterface(
+ TextEditor::AssistKind kind,
+ TextEditor::AssistReason reason) const override;
+
+ void encourageApply() override;
+
+ void paste() override;
+ void cut() override;
+ void selectAll() override;
+
+ void switchDeclarationDefinition(bool inNextSplit);
+ void showPreProcessorWidget() override;
+
+ void findUsages();
+ void renameSymbolUnderCursor();
+
+ bool selectBlockUp() override;
+ bool selectBlockDown() override;
+
+ static void updateWidgetHighlighting(QWidget *widget, bool highlight);
+ static bool isWidgetHighlighted(QWidget *widget);
+
+ void updateSemanticInfo() override;
+ void invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind,
+ TextEditor::IAssistProvider *provider) override;
+
+protected:
+ bool event(QEvent *e) override;
+ void contextMenuEvent(QContextMenuEvent *) override;
+ void keyPressEvent(QKeyEvent *e) override;
+ bool handleStringSplitting(QKeyEvent *e) const;
+
+ Link findLinkAt(const QTextCursor &, bool resolveTarget = true,
+ bool inNextSplit = false) override;
+
+ void onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker) override;
+
+ void slotCodeStyleSettingsChanged(const QVariant &) override;
+
+ void renameUsagesInternal(const QString &replacement) override;
+
+private:
+ void updateFunctionDeclDefLink();
+ void updateFunctionDeclDefLinkNow();
+ void abortDeclDefLink();
+ void onFunctionDeclDefLinkFound(QSharedPointer<FunctionDeclDefLink> link);
+
+ void onCppDocumentUpdated();
+
+ void onCodeWarningsUpdated(unsigned revision,
+ const QList<QTextEdit::ExtraSelection> selections,
+ const TextEditor::RefactorMarkers &refactorMarkers);
+ void onIfdefedOutBlocksUpdated(unsigned revision,
+ const QList<TextEditor::BlockRange> ifdefedOutBlocks);
+
+ void onShowInfoBarAction(const Core::Id &id, bool show);
+
+ void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo,
+ bool updateUseSelectionSynchronously = false);
+ void updatePreprocessorButtonTooltip();
+
+ void processKeyNormally(QKeyEvent *e);
+
+ void finalizeInitialization() override;
+ void finalizeInitializationAfterDuplication(TextEditorWidget *other) override;
+
+ unsigned documentRevision() const;
+
+ QMenu *createRefactorMenu(QWidget *parent) const;
+
+ TextEditor::RefactorMarkers refactorMarkersWithoutClangMarkers() const;
+
+ CppTools::FollowSymbolInterface &followSymbolInterface() const;
+ CppTools::RefactoringEngineInterface &refactoringEngine() const;
+
+ CppTools::ProjectPart *projectPart() const;
+
+private:
+ QScopedPointer<CppEditorWidgetPrivate> d;
+};
+
+} // namespace Internal
+} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppelementevaluator.h b/src/plugins/cppeditor/cppelementevaluator.h
index ffc6bd760a..5af04956ae 100644
--- a/src/plugins/cppeditor/cppelementevaluator.h
+++ b/src/plugins/cppeditor/cppelementevaluator.h
@@ -46,7 +46,6 @@ namespace CppTools { class CppModelManager; }
namespace CppEditor {
namespace Internal {
-class CppEditorWidget;
class CppElement;
class CppElementEvaluator
diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
index 9eaf09ab11..86bdf2a0cf 100644
--- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
+++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
@@ -25,7 +25,7 @@
#include "cppfunctiondecldeflink.h"
-#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppquickfixassistant.h"
#include <coreplugin/actionmanager/actionmanager.h>
diff --git a/src/plugins/cppeditor/cpphighlighter.h b/src/plugins/cppeditor/cpphighlighter.h
index 536ea30b6c..2e4b870b04 100644
--- a/src/plugins/cppeditor/cpphighlighter.h
+++ b/src/plugins/cppeditor/cpphighlighter.h
@@ -35,7 +35,6 @@ namespace CppEditor {
namespace Internal {
-class CppEditorWidget;
class CppHighlighter : public TextEditor::SyntaxHighlighter
{
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index 75b5913f17..dcb182435d 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -32,9 +32,9 @@
#include <cpptools/baseeditordocumentprocessor.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/editordocumenthandle.h>
-#include <texteditor/convenience.h>
#include <texteditor/texteditor.h>
+#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h>
@@ -63,7 +63,7 @@ bool editorDocumentProcessorHasDiagnosticAt(TextEditorWidget *editorWidget, int
{
if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
int line, column;
- if (Convenience::convertPosition(editorWidget->document(), pos, &line, &column))
+ if (Utils::Text::convertPosition(editorWidget->document(), pos, &line, &column))
return processor->hasDiagnosticsAt(line, column);
}
@@ -77,7 +77,7 @@ void processWithEditorDocumentProcessor(TextEditorWidget *editorWidget,
{
if (CppTools::BaseEditorDocumentProcessor *processor = editorDocumentProcessor(editorWidget)) {
int line, column;
- if (Convenience::convertPosition(editorWidget->document(), position, &line, &column)) {
+ if (Utils::Text::convertPosition(editorWidget->document(), position, &line, &column)) {
auto layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(2);
diff --git a/src/plugins/cppeditor/cppincludehierarchy.cpp b/src/plugins/cppeditor/cppincludehierarchy.cpp
index c47b39b21d..9baa067af1 100644
--- a/src/plugins/cppeditor/cppincludehierarchy.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchy.cpp
@@ -26,6 +26,7 @@
#include "cppincludehierarchy.h"
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorconstants.h"
#include "cppeditorplugin.h"
#include "cppelementevaluator.h"
@@ -407,7 +408,7 @@ void CppIncludeHierarchyWidget::perform()
m_inspectedFile->setText(m_editor->textDocument()->displayName());
m_inspectedFile->setLink(TextEditorWidget::Link(document));
- // expand "Includes" adn "Included by"
+ // expand "Includes" and "Included by"
m_treeView->expand(m_model.index(0, 0));
m_treeView->expand(m_model.index(1, 0));
diff --git a/src/plugins/cppeditor/cppincludehierarchy_test.cpp b/src/plugins/cppeditor/cppincludehierarchy_test.cpp
index 95995e732a..33a58400cc 100644
--- a/src/plugins/cppeditor/cppincludehierarchy_test.cpp
+++ b/src/plugins/cppeditor/cppincludehierarchy_test.cpp
@@ -23,6 +23,8 @@
**
****************************************************************************/
+#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorplugin.h"
#include "cppeditortestcase.h"
#include "cppincludehierarchy.h"
diff --git a/src/plugins/cppeditor/cppoutline.h b/src/plugins/cppeditor/cppoutline.h
index 9e28506027..2176fde2e2 100644
--- a/src/plugins/cppeditor/cppoutline.h
+++ b/src/plugins/cppeditor/cppoutline.h
@@ -26,6 +26,7 @@
#pragma once
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include <texteditor/ioutlinewidget.h>
diff --git a/src/plugins/cppeditor/cppparsecontext.cpp b/src/plugins/cppeditor/cppparsecontext.cpp
index 1519f0e71a..b3a3f1b1a3 100644
--- a/src/plugins/cppeditor/cppparsecontext.cpp
+++ b/src/plugins/cppeditor/cppparsecontext.cpp
@@ -25,7 +25,7 @@
#include "cppparsecontext.h"
-#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include <QAction>
#include <QDir>
diff --git a/src/plugins/cppeditor/cpppreprocessordialog.cpp b/src/plugins/cppeditor/cpppreprocessordialog.cpp
index 167e373a2d..f66ee92a89 100644
--- a/src/plugins/cppeditor/cpppreprocessordialog.cpp
+++ b/src/plugins/cppeditor/cpppreprocessordialog.cpp
@@ -27,6 +27,7 @@
#include "ui_cpppreprocessordialog.h"
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorconstants.h"
#include <projectexplorer/session.h>
diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp
index 7882fef70e..bfc35a67c4 100644
--- a/src/plugins/cppeditor/cppquickfix_test.cpp
+++ b/src/plugins/cppeditor/cppquickfix_test.cpp
@@ -23,6 +23,8 @@
**
****************************************************************************/
+#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorplugin.h"
#include "cppeditortestcase.h"
#include "cppquickfixassistant.h"
diff --git a/src/plugins/cppeditor/cppquickfixassistant.cpp b/src/plugins/cppeditor/cppquickfixassistant.cpp
index bde1f759bc..8ded187d88 100644
--- a/src/plugins/cppeditor/cppquickfixassistant.cpp
+++ b/src/plugins/cppeditor/cppquickfixassistant.cpp
@@ -26,7 +26,8 @@
#include "cppquickfixassistant.h"
#include "cppeditorconstants.h"
-#include "cppeditor.h"
+#include "cppeditorwidget.h"
+#include "cppquickfixes.h"
#include <cpptools/cppmodelmanager.h>
#include <texteditor/textdocument.h>
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 640fa794ef..9f51f15feb 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -25,16 +25,16 @@
#include "cppquickfixes.h"
-#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditordocument.h"
#include "cppfunctiondecldeflink.h"
#include "cppquickfixassistant.h"
-#include "cppvirtualfunctionassistprovider.h"
#include "cppinsertvirtualmethods.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
+#include <cpptools/cppvirtualfunctionassistprovider.h>
#include <cpptools/baseeditordocumentprocessor.h>
#include <cpptools/cppclassesfilter.h>
#include <cpptools/cppcodestylesettings.h>
@@ -2934,8 +2934,6 @@ public:
updateDescriptionAndPriority();
}
- void determineGetterSetterNames();
-
// Clones "other" in order to prevent all the initial detection made in the ctor.
GenerateGetterSetterOperation(const CppQuickFixInterface &interface,
GenerateGetterSetterOperation *other, OperationType type)
@@ -2968,6 +2966,28 @@ public:
return (m_type == GetterSetterType || m_type == SetterType);
}
+ void determineGetterSetterNames()
+ {
+ m_baseName = memberBaseName(m_variableString);
+ if (m_baseName.isEmpty())
+ m_baseName = QLatin1String("value");
+
+ // Getter Name
+ const CppCodeStyleSettings settings = CppCodeStyleSettings::currentProjectCodeStyle();
+ const bool hasValidBaseName = m_baseName != m_variableString;
+ const bool getPrefixIsAlreadyUsed = hasClassMemberWithGetPrefix(m_classSpecifier->symbol);
+ if (settings.preferGetterNameWithoutGetPrefix && hasValidBaseName && !getPrefixIsAlreadyUsed) {
+ m_getterName = m_baseName;
+ } else {
+ const QString baseNameWithCapital = m_baseName.left(1).toUpper() + m_baseName.mid(1);
+ m_getterName = QLatin1String("get") + baseNameWithCapital;
+ }
+
+ // Setter Name
+ const QString baseNameWithCapital = m_baseName.left(1).toUpper() + m_baseName.mid(1);
+ m_setterName = QLatin1String("set") + baseNameWithCapital;
+ }
+
void updateDescriptionAndPriority()
{
switch (m_type) {
@@ -3370,7 +3390,7 @@ public:
auto layout = new QFormLayout(&dlg);
auto funcNameEdit = new Utils::FancyLineEdit;
- funcNameEdit->setValidationFunction([this](Utils::FancyLineEdit *edit, QString *) {
+ funcNameEdit->setValidationFunction([](Utils::FancyLineEdit *edit, QString *) {
return ExtractFunctionOptions::isValidFunctionName(edit->text());
});
layout->addRow(QCoreApplication::translate("QuickFix::ExtractFunction",
@@ -6018,27 +6038,7 @@ void ExtraRefactoringOperations::match(const CppQuickFixInterface &interface,
}
}
-void GenerateGetterSetterOperation::determineGetterSetterNames()
-{
- m_baseName = memberBaseName(m_variableString);
- if (m_baseName.isEmpty())
- m_baseName = QLatin1String("value");
-
- // Getter Name
- const CppCodeStyleSettings settings = CppCodeStyleSettings::currentProjectCodeStyle();
- const bool hasValidBaseName = m_baseName != m_variableString;
- const bool getPrefixIsAlreadyUsed = hasClassMemberWithGetPrefix(m_classSpecifier->symbol);
- if (settings.preferGetterNameWithoutGetPrefix && hasValidBaseName && !getPrefixIsAlreadyUsed) {
- m_getterName = m_baseName;
- } else {
- const QString baseNameWithCapital = m_baseName.left(1).toUpper() + m_baseName.mid(1);
- m_getterName = QLatin1String("get") + baseNameWithCapital;
- }
- // Setter Name
- const QString baseNameWithCapital = m_baseName.left(1).toUpper() + m_baseName.mid(1);
- m_setterName = QLatin1String("set") + baseNameWithCapital;
-}
} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp
index 47ca64f9a2..cac2269de6 100644
--- a/src/plugins/cppeditor/cpptypehierarchy.cpp
+++ b/src/plugins/cppeditor/cpptypehierarchy.cpp
@@ -27,6 +27,7 @@
#include "cppeditorconstants.h"
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppelementevaluator.h"
#include "cppeditorplugin.h"
diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h
index 125fb58338..355f87065d 100644
--- a/src/plugins/cppeditor/cpptypehierarchy.h
+++ b/src/plugins/cppeditor/cpptypehierarchy.h
@@ -37,12 +37,9 @@ class QLabel;
class QModelIndex;
class QStackedLayout;
class QStandardItem;
-template <class> class QVector;
template <class> class QList;
QT_END_NAMESPACE
-namespace Core { class IEditor; }
-
namespace TextEditor { class TextEditorLinkLabel; }
namespace Utils {
@@ -55,7 +52,6 @@ namespace Internal {
class CppEditorWidget;
class CppClass;
-class CppClassLabel;
class CppTypeHierarchyModel : public QStandardItemModel
{
diff --git a/src/plugins/cppeditor/cppuseselections_test.cpp b/src/plugins/cppeditor/cppuseselections_test.cpp
index 943f1d4ec6..8de8048a89 100644
--- a/src/plugins/cppeditor/cppuseselections_test.cpp
+++ b/src/plugins/cppeditor/cppuseselections_test.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorplugin.h"
#include "cppeditortestcase.h"
diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
index ac071a02b0..da7a7a1d92 100644
--- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp
+++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp
@@ -25,11 +25,11 @@
#include "cppuseselectionsupdater.h"
-#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditordocument.h"
#include <cpptools/cpptoolsreuse.h>
-#include <texteditor/convenience.h>
+#include <utils/textutils.h>
#include <QTextBlock>
#include <QTextCursor>
@@ -66,21 +66,21 @@ void CppUseSelectionsUpdater::abortSchedule()
m_timer.stop();
}
-void CppUseSelectionsUpdater::update(CallType callType)
+CppUseSelectionsUpdater::RunnerInfo CppUseSelectionsUpdater::update(CallType callType)
{
auto *cppEditorWidget = qobject_cast<CppEditorWidget *>(m_editorWidget);
- QTC_ASSERT(cppEditorWidget, return);
+ QTC_ASSERT(cppEditorWidget, return RunnerInfo::FailedToStart);
auto *cppEditorDocument = qobject_cast<CppEditorDocument *>(cppEditorWidget->textDocument());
- QTC_ASSERT(cppEditorDocument, return);
+ QTC_ASSERT(cppEditorDocument, return RunnerInfo::FailedToStart);
CppTools::CursorInfoParams params;
params.semanticInfo = cppEditorWidget->semanticInfo();
- params.textCursor = TextEditor::Convenience::wordStartCursor(cppEditorWidget->textCursor());
+ params.textCursor = Utils::Text::wordStartCursor(cppEditorWidget->textCursor());
- if (callType == Asynchronous) {
+ if (callType == CallType::Asynchronous) {
if (isSameIdentifierAsBefore(params.textCursor))
- return;
+ return RunnerInfo::AlreadyUpToDate;
if (m_runnerWatcher)
m_runnerWatcher->cancel();
@@ -93,25 +93,28 @@ void CppUseSelectionsUpdater::update(CallType callType)
m_runnerWordStartPosition = params.textCursor.position();
m_runnerWatcher->setFuture(cppEditorDocument->cursorInfo(params));
+ return RunnerInfo::Started;
} else { // synchronous case
abortSchedule();
const int startRevision = cppEditorDocument->document()->revision();
QFuture<CursorInfo> future = cppEditorDocument->cursorInfo(params);
if (future.isCanceled())
- return;
+ return RunnerInfo::Invalid;
// QFuture::waitForFinished seems to block completely, not even
// allowing to process events from QLocalSocket.
while (!future.isFinished()) {
if (future.isCanceled())
- return;
+ return RunnerInfo::Invalid;
- QTC_ASSERT(startRevision == cppEditorDocument->document()->revision(), return);
+ QTC_ASSERT(startRevision == cppEditorDocument->document()->revision(),
+ return RunnerInfo::Invalid);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
processResults(future.result());
+ return RunnerInfo::Invalid;
}
}
@@ -134,18 +137,25 @@ void CppUseSelectionsUpdater::processResults(const CursorInfo &result)
updateUnusedSelections(result.unusedVariablesRanges);
emit selectionsForVariableUnderCursorUpdated(localVariableSelections);
- emit finished(result.localUses);
+ emit finished(result.localUses, true);
}
void CppUseSelectionsUpdater::onFindUsesFinished()
{
- QTC_ASSERT(m_runnerWatcher, return);
- if (m_runnerWatcher->isCanceled())
+ QTC_ASSERT(m_runnerWatcher,
+ emit finished(CppTools::SemanticInfo::LocalUseMap(), false); return);
+
+ if (m_runnerWatcher->isCanceled()) {
+ emit finished(CppTools::SemanticInfo::LocalUseMap(), false);
return;
- if (m_runnerRevision != m_editorWidget->document()->revision())
+ }
+ if (m_runnerRevision != m_editorWidget->document()->revision()) {
+ emit finished(CppTools::SemanticInfo::LocalUseMap(), false);
return;
+ }
if (m_runnerWordStartPosition
- != TextEditor::Convenience::wordStartCursor(m_editorWidget->textCursor()).position()) {
+ != Utils::Text::wordStartCursor(m_editorWidget->textCursor()).position()) {
+ emit finished(CppTools::SemanticInfo::LocalUseMap(), false);
return;
}
diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.h b/src/plugins/cppeditor/cppuseselectionsupdater.h
index 478a816f98..ec18b222f4 100644
--- a/src/plugins/cppeditor/cppuseselectionsupdater.h
+++ b/src/plugins/cppeditor/cppuseselectionsupdater.h
@@ -49,11 +49,12 @@ public:
void scheduleUpdate();
void abortSchedule();
- enum CallType { Synchronous, Asynchronous };
- void update(CallType callType = Asynchronous);
+ enum class CallType { Synchronous, Asynchronous };
+ enum class RunnerInfo { AlreadyUpToDate, Started, FailedToStart, Invalid }; // For async case.
+ RunnerInfo update(CallType callType = CallType::Asynchronous);
signals:
- void finished(CppTools::SemanticInfo::LocalUseMap localUses);
+ void finished(CppTools::SemanticInfo::LocalUseMap localUses, bool success);
void selectionsForVariableUnderCursorUpdated(const QList<QTextEdit::ExtraSelection> &);
private:
diff --git a/src/plugins/cppeditor/fileandtokenactions_test.cpp b/src/plugins/cppeditor/fileandtokenactions_test.cpp
index 9bf053bb94..463172d45b 100644
--- a/src/plugins/cppeditor/fileandtokenactions_test.cpp
+++ b/src/plugins/cppeditor/fileandtokenactions_test.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorplugin.h"
#include "cppeditortestcase.h"
#include "cppquickfix.h"
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index b2e1c98294..1f7576c49b 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -23,14 +23,17 @@
**
****************************************************************************/
+#include "cppeditor.h"
+#include "cppeditorwidget.h"
#include "cppeditorplugin.h"
#include "cppeditortestcase.h"
#include "cppelementevaluator.h"
-#include "cppfollowsymbolundercursor.h"
-#include "cppvirtualfunctionassistprovider.h"
-#include "cppvirtualfunctionproposalitem.h"
+#include <cpptools/cppfollowsymbolundercursor.h>
+#include <cpptools/cppvirtualfunctionassistprovider.h>
+#include <cpptools/cppvirtualfunctionproposalitem.h>
#include <cpptools/cpptoolstestcase.h>
+#include <cpptools/cppmodelmanager.h>
#include <texteditor/codeassist/genericproposalmodel.h>
#include <texteditor/codeassist/iassistprocessor.h>
@@ -324,19 +327,35 @@ F2TestCase::F2TestCase(CppEditorAction action,
switch (action) {
case FollowSymbolUnderCursorAction: {
CppEditorWidget *widget = initialTestFile->m_editorWidget;
- FollowSymbolUnderCursor *delegate = widget->followSymbolUnderCursorDelegate();
- VirtualFunctionAssistProvider *original = delegate->virtualFunctionAssistProvider();
+ FollowSymbolInterface &delegate = CppModelManager::instance()->followSymbolInterface();
+ auto* builtinFollowSymbol = dynamic_cast<FollowSymbolUnderCursor *>(&delegate);
+ if (!builtinFollowSymbol) {
+ if (filePaths.size() > 1)
+ QSKIP("Clang FollowSymbol does not currently support multiple files (except cpp+header)");
+ const QString curTestName = QLatin1String(QTest::currentTestFunction());
+ if (curTestName == "test_FollowSymbolUnderCursor_QObject_connect"
+ || curTestName == "test_FollowSymbolUnderCursor_virtualFunctionCall"
+ || curTestName == "test_FollowSymbolUnderCursor_QTCREATORBUG7903") {
+ QSKIP((curTestName + " is not supported by Clang FollowSymbol").toLatin1());
+ }
+
+ initialTestFile->m_editorWidget->openLinkUnderCursor();
+ break;
+ }
+
+ QSharedPointer<VirtualFunctionAssistProvider> original
+ = builtinFollowSymbol->virtualFunctionAssistProvider();
// Set test provider, run and get results
- QScopedPointer<VirtualFunctionTestAssistProvider> testProvider(
+ QSharedPointer<VirtualFunctionTestAssistProvider> testProvider(
new VirtualFunctionTestAssistProvider(widget));
- delegate->setVirtualFunctionAssistProvider(testProvider.data());
+ builtinFollowSymbol->setVirtualFunctionAssistProvider(testProvider);
initialTestFile->m_editorWidget->openLinkUnderCursor();
immediateVirtualSymbolResults = testProvider->m_immediateItems;
finalVirtualSymbolResults = testProvider->m_finalItems;
// Restore original test provider
- delegate->setVirtualFunctionAssistProvider(original);
+ builtinFollowSymbol->setVirtualFunctionAssistProvider(original);
break;
}
case SwitchBetweenMethodDeclarationDefinitionAction:
@@ -868,41 +887,6 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
"@Container<int> container;\n"
);
- QTest::newRow("using_QTCREATORBUG7903_globalNamespace") << _(
- "namespace NS {\n"
- "class Foo {};\n"
- "}\n"
- "using NS::$Foo;\n"
- "void fun()\n"
- "{\n"
- " @Foo foo;\n"
- "}\n"
- );
-
- QTest::newRow("using_QTCREATORBUG7903_namespace") << _(
- "namespace NS {\n"
- "class Foo {};\n"
- "}\n"
- "namespace NS1 {\n"
- "void fun()\n"
- "{\n"
- " using NS::$Foo;\n"
- " @Foo foo;\n"
- "}\n"
- "}\n"
- );
-
- QTest::newRow("using_QTCREATORBUG7903_insideFunction") << _(
- "namespace NS {\n"
- "class Foo {};\n"
- "}\n"
- "void fun()\n"
- "{\n"
- " using NS::$Foo;\n"
- " @Foo foo;\n"
- "}\n"
- );
-
QTest::newRow("matchFunctionSignature_Follow_1") << _(
"class Foo {\n"
" void @foo(int);\n"
@@ -941,6 +925,34 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
"};\n"
);
+ QTest::newRow("matchFunctionSignature_Follow_6") << _(
+ "class Foo {\n"
+ " void $foo(int);\n"
+ "};\n"
+ "void Foo::@foo(const volatile int) {}\n"
+ );
+
+ QTest::newRow("matchFunctionSignature_Follow_7") << _(
+ "class Foo {\n"
+ " void $foo(const volatile int);\n"
+ "};\n"
+ "void Foo::@foo(int) {}\n"
+ );
+
+ QTest::newRow("matchFunctionSignature_Follow_8") << _(
+ "class Foo {\n"
+ " void @$foo(int *);\n"
+ "};\n"
+ "void Foo::foo(const int *) {}\n"
+ );
+
+ QTest::newRow("matchFunctionSignature_Follow_9") << _(
+ "class Foo {\n"
+ " void @$foo(int&);\n"
+ "};\n"
+ "void Foo::foo(const int&) {}\n"
+ );
+
QTest::newRow("infiniteLoopLocalTypedef_QTCREATORBUG-11999") << _(
"template<class MyTree>\n"
"class TreeConstIterator\n"
@@ -963,6 +975,8 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
);
QTest::newRow("template_alias") << _(
+ "template<class T>"
+ "class Bar;"
"template<class $T>\n"
"using Foo = Bar<@T>;\n"
);
@@ -974,6 +988,51 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor()
F2TestCase(F2TestCase::FollowSymbolUnderCursorAction, singleDocument(source));
}
+void CppEditorPlugin::test_FollowSymbolUnderCursor_QTCREATORBUG7903_data()
+{
+ QTest::addColumn<QByteArray>("source");
+ QTest::newRow("using_QTCREATORBUG7903_globalNamespace") << _(
+ "namespace NS {\n"
+ "class Foo {};\n"
+ "}\n"
+ "using NS::$Foo;\n"
+ "void fun()\n"
+ "{\n"
+ " @Foo foo;\n"
+ "}\n"
+ );
+
+ QTest::newRow("using_QTCREATORBUG7903_namespace") << _(
+ "namespace NS {\n"
+ "class Foo {};\n"
+ "}\n"
+ "namespace NS1 {\n"
+ "void fun()\n"
+ "{\n"
+ " using NS::$Foo;\n"
+ " @Foo foo;\n"
+ "}\n"
+ "}\n"
+ );
+
+ QTest::newRow("using_QTCREATORBUG7903_insideFunction") << _(
+ "namespace NS {\n"
+ "class Foo {};\n"
+ "}\n"
+ "void fun()\n"
+ "{\n"
+ " using NS::$Foo;\n"
+ " @Foo foo;\n"
+ "}\n"
+ );
+}
+
+void CppEditorPlugin::test_FollowSymbolUnderCursor_QTCREATORBUG7903()
+{
+ QFETCH(QByteArray, source);
+ F2TestCase(F2TestCase::FollowSymbolUnderCursorAction, singleDocument(source));
+}
+
void CppEditorPlugin::test_FollowSymbolUnderCursor_followCall_data()
{
QTest::addColumn<QByteArray>("variableDeclaration"); // without semicolon, can be ""
diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h
index 3c9d864aeb..1ac31a6ebc 100644
--- a/src/plugins/cpptools/baseeditordocumentprocessor.h
+++ b/src/plugins/cpptools/baseeditordocumentprocessor.h
@@ -27,6 +27,7 @@
#include "baseeditordocumentparser.h"
#include "cppcursorinfo.h"
+#include "cppsymbolinfo.h"
#include "cppsemanticinfo.h"
#include "cpptools_global.h"
@@ -75,6 +76,7 @@ public:
virtual void setParserConfig(const BaseEditorDocumentParser::Configuration config);
virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) = 0;
+ virtual QFuture<SymbolInfo> requestFollowSymbol(int line, int column) = 0;
public:
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
diff --git a/src/plugins/cpptools/builtincursorinfo.cpp b/src/plugins/cpptools/builtincursorinfo.cpp
index 8902fa05ca..17f40c7d26 100644
--- a/src/plugins/cpptools/builtincursorinfo.cpp
+++ b/src/plugins/cpptools/builtincursorinfo.cpp
@@ -32,12 +32,11 @@
#include "cppsemanticinfo.h"
#include "cpptoolsreuse.h"
-#include <texteditor/convenience.h>
-
#include <cplusplus/CppDocument.h>
#include <cplusplus/Macro.h>
#include <cplusplus/TranslationUnit.h>
+#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
@@ -346,8 +345,7 @@ QFuture<CursorInfo> BuiltinCursorInfo::run(const CursorInfoParams &cursorInfoPar
const QTextCursor &textCursor = cursorInfoParams.textCursor;
int line, column;
- TextEditor::Convenience::convertPosition(textCursor.document(), textCursor.position(),
- &line, &column);
+ Utils::Text::convertPosition(textCursor.document(), textCursor.position(), &line, &column);
CanonicalSymbol canonicalSymbol(document, snapshot);
QString expression;
Scope *scope = canonicalSymbol.getScopeAndExpression(textCursor, &expression);
diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp
index ac3cf3ee2a..3fb407cb2d 100644
--- a/src/plugins/cpptools/builtineditordocumentparser.cpp
+++ b/src/plugins/cpptools/builtineditordocumentparser.cpp
@@ -26,6 +26,7 @@
#include "builtineditordocumentparser.h"
#include "cppsourceprocessor.h"
+#include <projectexplorer/projectmacro.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
@@ -91,9 +92,9 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
}
if (const ProjectPart::Ptr part = baseState.projectPartInfo.projectPart) {
- configFile += part->toolchainDefines;
+ configFile += ProjectExplorer::Macro::toByteArray(part->toolChainMacros);
configFile += overwrittenToolchainDefines(*part.data());
- configFile += part->projectDefines;
+ configFile += ProjectExplorer::Macro::toByteArray(part->projectMacros);
if (!part->projectConfigFile.isEmpty())
configFile += ProjectPart::readProjectConfigFile(part);
headerPaths = part->headerPaths;
diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp
index 95f4932e08..bfdabe5362 100644
--- a/src/plugins/cpptools/builtineditordocumentprocessor.cpp
+++ b/src/plugins/cpptools/builtineditordocumentprocessor.cpp
@@ -33,7 +33,6 @@
#include "cpptoolsreuse.h"
#include "cppworkingcopy.h"
-#include <texteditor/convenience.h>
#include <texteditor/fontsettings.h>
#include <texteditor/refactoroverlay.h>
#include <texteditor/texteditorsettings.h>
@@ -41,6 +40,7 @@
#include <cplusplus/CppDocument.h>
#include <cplusplus/SimpleLexer.h>
+#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
@@ -105,7 +105,7 @@ CppTools::CheckSymbols *createHighlighter(const CPlusPlus::Document::Ptr &doc,
typedef TextEditor::HighlightingResult Result;
QList<Result> macroUses;
- using TextEditor::Convenience::convertPosition;
+ using Utils::Text::convertPosition;
// Get macro definitions
foreach (const CPlusPlus::Macro& macro, doc->definedMacros()) {
diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.h b/src/plugins/cpptools/builtineditordocumentprocessor.h
index 32a50d6e23..800bff085a 100644
--- a/src/plugins/cpptools/builtineditordocumentprocessor.h
+++ b/src/plugins/cpptools/builtineditordocumentprocessor.h
@@ -52,6 +52,8 @@ public:
bool isParserRunning() const override;
QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) override;
+ QFuture<SymbolInfo> requestFollowSymbol(int, int) override
+ { return QFuture<SymbolInfo>(); }
private:
void onParserFinished(CPlusPlus::Document::Ptr document, CPlusPlus::Snapshot snapshot);
diff --git a/src/plugins/cpptools/clangcompileroptionsbuilder.cpp b/src/plugins/cpptools/clangcompileroptionsbuilder.cpp
index 160bf6b4c6..0b2209cc62 100644
--- a/src/plugins/cpptools/clangcompileroptionsbuilder.cpp
+++ b/src/plugins/cpptools/clangcompileroptionsbuilder.cpp
@@ -26,7 +26,6 @@
#include "clangcompileroptionsbuilder.h"
#include <coreplugin/icore.h>
-
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
@@ -38,46 +37,46 @@ namespace CppTools {
static QString creatorResourcePath()
{
#ifndef UNIT_TESTS
- return Core::ICore::instance()->libexecPath();
+ return Core::ICore::instance()->resourcePath();
#else
return QString();
#endif
}
-QStringList ClangCompilerOptionsBuilder::build(const CppTools::ProjectPart *projectPart,
- CppTools::ProjectFile::Kind fileKind,
- PchUsage pchUsage,
- const QString &clangVersion,
- const QString &clangResourceDirectory)
+static QString creatorLibexecPath()
{
- if (projectPart) {
- ClangCompilerOptionsBuilder builder(*projectPart, clangVersion, clangResourceDirectory);
-
- builder.addWordWidth();
- builder.addTargetTriple();
- builder.addLanguageOption(fileKind);
- builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
- builder.enableExceptions();
+#ifndef UNIT_TESTS
+ return Core::ICore::instance()->libexecPath();
+#else
+ return QString();
+#endif
+}
- builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
- builder.addDefineFloat128ForMingw();
- builder.addToolchainAndProjectDefines();
- builder.undefineCppLanguageFeatureMacrosForMsvc2015();
+QStringList ClangCompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind,
+ PchUsage pchUsage)
+{
+ addWordWidth();
+ addTargetTriple();
+ addLanguageOption(fileKind);
+ addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
+ enableExceptions();
- builder.addPredefinedMacrosAndHeaderPathsOptions();
- builder.addWrappedQtHeadersIncludePath();
- builder.addPrecompiledHeaderOptions(pchUsage);
- builder.addHeaderPathOptions();
- builder.addProjectConfigFileInclude();
+ addDefineFloat128ForMingw();
+ addToolchainAndProjectMacros();
+ undefineClangVersionMacrosForMsvc();
+ undefineCppLanguageFeatureMacrosForMsvc2015();
- builder.addMsvcCompatibilityVersion();
+ addPredefinedHeaderPathsOptions();
+ addWrappedQtHeadersIncludePath();
+ addPrecompiledHeaderOptions(pchUsage);
+ addHeaderPathOptions();
+ addProjectConfigFileInclude();
- builder.addExtraOptions();
+ addMsvcCompatibilityVersion();
- return builder.options();
- }
+ addExtraOptions();
- return QStringList();
+ return options();
}
ClangCompilerOptionsBuilder::ClangCompilerOptionsBuilder(const CppTools::ProjectPart &projectPart,
@@ -91,47 +90,35 @@ ClangCompilerOptionsBuilder::ClangCompilerOptionsBuilder(const CppTools::Project
bool ClangCompilerOptionsBuilder::excludeHeaderPath(const QString &path) const
{
- if (m_projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
- if (path.contains("lib/gcc/i686-apple-darwin"))
- return true;
+ if (m_projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID
+ && path.contains("lib/gcc/i686-apple-darwin")) {
+ return true;
}
return CompilerOptionsBuilder::excludeHeaderPath(path);
}
-void ClangCompilerOptionsBuilder::addPredefinedMacrosAndHeaderPathsOptions()
+void ClangCompilerOptionsBuilder::addPredefinedHeaderPathsOptions()
{
- if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
- addPredefinedMacrosAndHeaderPathsOptionsForMsvc();
- else
- addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc();
-}
-
-void ClangCompilerOptionsBuilder::addPredefinedMacrosAndHeaderPathsOptionsForMsvc()
-{
- add("-nostdinc");
add("-undef");
-}
+ add("-nostdinc");
+ add("-nostdlibinc");
-void ClangCompilerOptionsBuilder::addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc()
-{
- static const QString resourceDir = clangIncludeDirectory();
- if (QTC_GUARD(!resourceDir.isEmpty())) {
- add("-nostdlibinc");
- add("-I" + QDir::toNativeSeparators(resourceDir));
- add("-undef");
- }
+ if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
+ add(includeDirOption() + clangIncludeDirectory());
}
void ClangCompilerOptionsBuilder::addWrappedQtHeadersIncludePath()
{
- static const QString wrappedQtHeadersPath = creatorResourcePath()
- + "/cplusplus/wrappedQtHeaders";
+ static const QString resourcePath = creatorResourcePath();
+ static QString wrappedQtHeadersPath = resourcePath + "/cplusplus/wrappedQtHeaders";
+ QDir dir(wrappedQtHeadersPath);
+ QTC_ASSERT(QDir(wrappedQtHeadersPath).exists(), return;);
if (m_projectPart.qtVersion != CppTools::ProjectPart::NoQt) {
const QString wrappedQtCoreHeaderPath = wrappedQtHeadersPath + "/QtCore";
- add("-I" + QDir::toNativeSeparators(wrappedQtHeadersPath));
- add("-I" + QDir::toNativeSeparators(wrappedQtCoreHeaderPath));
+ add(includeDirOption() + QDir::toNativeSeparators(wrappedQtHeadersPath));
+ add(includeDirOption() + QDir::toNativeSeparators(wrappedQtCoreHeaderPath));
}
}
@@ -154,12 +141,26 @@ void ClangCompilerOptionsBuilder::addExtraOptions()
QString ClangCompilerOptionsBuilder::clangIncludeDirectory() const
{
- QDir dir(creatorResourcePath() + "/clang/lib/clang/" + m_clangVersion + "/include");
-
+ QDir dir(creatorLibexecPath() + "/clang/lib/clang/" + m_clangVersion + "/include");
if (!dir.exists() || !QFileInfo(dir, "stdint.h").exists())
dir = QDir(m_clangResourceDirectory);
+ return QDir::toNativeSeparators(dir.canonicalPath());
+}
- return dir.canonicalPath();
+void ClangCompilerOptionsBuilder::undefineClangVersionMacrosForMsvc()
+{
+ if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
+ static QStringList macroNames {
+ "__clang__",
+ "__clang_major__",
+ "__clang_minor__",
+ "__clang_patchlevel__",
+ "__clang_version__"
+ };
+
+ foreach (const QString &macroName, macroNames)
+ add(undefineOption() + macroName);
+ }
}
} // namespace CppTools
diff --git a/src/plugins/cpptools/clangcompileroptionsbuilder.h b/src/plugins/cpptools/clangcompileroptionsbuilder.h
index 4dadb6bed9..fbe2a5baad 100644
--- a/src/plugins/cpptools/clangcompileroptionsbuilder.h
+++ b/src/plugins/cpptools/clangcompileroptionsbuilder.h
@@ -34,33 +34,24 @@ namespace CppTools {
class CPPTOOLS_EXPORT ClangCompilerOptionsBuilder : public CompilerOptionsBuilder
{
public:
- static QStringList build(const ProjectPart *projectPart,
- ProjectFile::Kind fileKind,
- PchUsage pchUsage,
- const QString &clangVersion,
- const QString &clangResourceDirectory);
+ QStringList build(ProjectFile::Kind fileKind,
+ PchUsage pchUsage);
ClangCompilerOptionsBuilder(const ProjectPart &projectPart,
- const QString &clangVersion,
- const QString &clangResourceDirectory);
+ const QString &clangVersion = QString(),
+ const QString &clangResourceDirectory = QString());
- bool excludeHeaderPath(const QString &path) const override;
-
- void addPredefinedMacrosAndHeaderPathsOptions();
-
- void addPredefinedMacrosAndHeaderPathsOptionsForMsvc();
-
- void addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc();
+ virtual void addPredefinedHeaderPathsOptions();
+ virtual void addExtraOptions();
- void addWrappedQtHeadersIncludePath();
+ bool excludeHeaderPath(const QString &path) const override;
+ virtual void addWrappedQtHeadersIncludePath();
void addProjectConfigFileInclude();
- void addExtraOptions();
+ void undefineClangVersionMacrosForMsvc();
private:
QString clangIncludeDirectory() const;
-
-private:
QString m_clangVersion;
QString m_clangResourceDirectory;
};
diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
index 6b8a04ac33..288b5e3a8d 100644
--- a/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
+++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.cpp
@@ -28,6 +28,7 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
#include <QDebug>
#include <QInputDialog>
@@ -107,15 +108,61 @@ void ClangDiagnosticConfigsWidget::onRemoveButtonClicked()
syncConfigChooserToModel();
}
+static bool isAcceptedWarningOption(const QString &option)
+{
+ return option == "-w"
+ || option == "-pedantic"
+ || option == "-pedantic-errors";
+}
+
+// Reference:
+// https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+// https://clang.llvm.org/docs/DiagnosticsReference.html
+static bool isValidOption(const QString &option)
+{
+ if (option == "-Werror")
+ return false; // Avoid errors due to unknown or misspelled warnings.
+ return option.startsWith("-W") || isAcceptedWarningOption(option);
+}
+
+static QString validateDiagnosticOptions(const QStringList &options)
+{
+ // This is handy for testing, allow disabling validation.
+ if (qEnvironmentVariableIntValue("QTC_CLANG_NO_DIAGNOSTIC_CHECK"))
+ return QString();
+
+ for (const QString &option : options) {
+ if (!isValidOption(option))
+ return ClangDiagnosticConfigsWidget::tr("Option \"%1\" is invalid.").arg(option);
+ }
+
+ return QString();
+}
+
+static QStringList normalizeDiagnosticInputOptions(const QString &options)
+{
+ return options.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
+}
+
void ClangDiagnosticConfigsWidget::onDiagnosticOptionsEdited()
{
- const QString diagnosticOptions
- = m_ui->diagnosticOptionsTextEdit->document()->toPlainText().trimmed();
- const QStringList updatedCommandLine
- = diagnosticOptions.trimmed().split(QLatin1Char(' '), QString::SkipEmptyParts);
+ // Clean up input
+ const QString diagnosticOptions = m_ui->diagnosticOptionsTextEdit->document()->toPlainText();
+ const QStringList normalizedOptions = normalizeDiagnosticInputOptions(diagnosticOptions);
+
+ // Validate
+ const QString errorMessage = validateDiagnosticOptions(normalizedOptions);
+ updateValidityWidgets(errorMessage);
+ if (!errorMessage.isEmpty()) {
+ // Remember the entered options in case the user will switch back.
+ m_notAcceptedOptions.insert(currentConfigId(), diagnosticOptions);
+ return;
+ }
+ m_notAcceptedOptions.remove(currentConfigId());
+ // Commit valid changes
ClangDiagnosticConfig updatedConfig = currentConfig();
- updatedConfig.setCommandLineWarnings(updatedCommandLine);
+ updatedConfig.setCommandLineWarnings(normalizedOptions);
m_diagnosticConfigsModel.appendOrUpdate(updatedConfig);
emit customConfigsChanged(customConfigs());
@@ -167,8 +214,10 @@ void ClangDiagnosticConfigsWidget::syncOtherWidgetsToComboBox()
m_ui->removeButton->setEnabled(!config.isReadOnly());
// Update child widgets
- const QString commandLineWarnings = config.commandLineWarnings().join(QLatin1Char(' '));
- setDiagnosticOptions(commandLineWarnings);
+ const QString options = m_notAcceptedOptions.contains(config.id())
+ ? m_notAcceptedOptions.value(config.id())
+ : config.commandLineWarnings().join(QLatin1Char(' '));
+ setDiagnosticOptions(options);
m_ui->diagnosticOptionsTextEdit->setReadOnly(config.isReadOnly());
}
@@ -186,11 +235,35 @@ void ClangDiagnosticConfigsWidget::setDiagnosticOptions(const QString &options)
{
if (options != m_ui->diagnosticOptionsTextEdit->document()->toPlainText()) {
disconnectDiagnosticOptionsChanged();
+
m_ui->diagnosticOptionsTextEdit->document()->setPlainText(options);
+ const QString errorMessage
+ = validateDiagnosticOptions(normalizeDiagnosticInputOptions(options));
+ updateValidityWidgets(errorMessage);
+
connectDiagnosticOptionsChanged();
}
}
+void ClangDiagnosticConfigsWidget::updateValidityWidgets(const QString &errorMessage)
+{
+ QString validationResult;
+ const Utils::Icon *icon = nullptr;
+ QString styleSheet;
+ if (errorMessage.isEmpty()) {
+ icon = &Utils::Icons::INFO;
+ validationResult = tr("Configuration passes sanity checks.");
+ } else {
+ icon = &Utils::Icons::CRITICAL;
+ validationResult = tr("%1").arg(errorMessage);
+ styleSheet = "color: red;";
+ }
+
+ m_ui->validationResultIcon->setPixmap(icon->pixmap());
+ m_ui->validationResultLabel->setText(validationResult);
+ m_ui->validationResultLabel->setStyleSheet(styleSheet);
+}
+
void ClangDiagnosticConfigsWidget::connectConfigChooserCurrentIndex()
{
connect(m_ui->configChooserComboBox,
diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.h b/src/plugins/cpptools/clangdiagnosticconfigswidget.h
index e22de1b97d..ff11815a22 100644
--- a/src/plugins/cpptools/clangdiagnosticconfigswidget.h
+++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.h
@@ -30,6 +30,7 @@
#include "clangdiagnosticconfig.h"
#include "clangdiagnosticconfigsmodel.h"
+#include <QHash>
#include <QWidget>
namespace CppTools {
@@ -72,6 +73,7 @@ private:
const ClangDiagnosticConfig &currentConfig() const;
void setDiagnosticOptions(const QString &options);
+ void updateValidityWidgets(const QString &errorMessage);
void connectConfigChooserCurrentIndex();
void disconnectConfigChooserCurrentIndex();
@@ -81,6 +83,7 @@ private:
private:
Ui::ClangDiagnosticConfigsWidget *m_ui;
ClangDiagnosticConfigsModel m_diagnosticConfigsModel;
+ QHash<Core::Id, QString> m_notAcceptedOptions;
};
} // CppTools namespace
diff --git a/src/plugins/cpptools/clangdiagnosticconfigswidget.ui b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui
index 25d0c0b598..251868faca 100644
--- a/src/plugins/cpptools/clangdiagnosticconfigswidget.ui
+++ b/src/plugins/cpptools/clangdiagnosticconfigswidget.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>597</width>
+ <width>665</width>
<height>300</height>
</rect>
</property>
@@ -14,18 +14,6 @@
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -62,7 +50,38 @@
</layout>
</item>
<item>
- <widget class="QPlainTextEdit" name="diagnosticOptionsTextEdit"/>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="validationResultIcon">
+ <property name="text">
+ <string>ValidationIcon</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="validationResultLabel">
+ <property name="text">
+ <string>ValidationText</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="CppTools::WrappableLineEdit" name="diagnosticOptionsTextEdit"/>
</item>
<item>
<widget class="QLabel" name="label">
@@ -76,6 +95,13 @@
</item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>CppTools::WrappableLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header location="global">cpptools/wrappablelineedit.h</header>
+ </customwidget>
+ </customwidgets>
<tabstops>
<tabstop>configChooserComboBox</tabstop>
<tabstop>copyButton</tabstop>
diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp
index 170279c9b8..88a85e17cd 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.cpp
+++ b/src/plugins/cpptools/compileroptionsbuilder.cpp
@@ -48,44 +48,9 @@ void CompilerOptionsBuilder::add(const QString &option)
m_options.append(option);
}
-struct Macro {
- static Macro fromDefineDirective(const QByteArray &defineDirective);
- QByteArray toDefineOption(const QByteArray &option) const;
-
- QByteArray name;
- QByteArray value;
-};
-
-Macro Macro::fromDefineDirective(const QByteArray &defineDirective)
+void CompilerOptionsBuilder::addDefine(const ProjectExplorer::Macro &macro)
{
- const QByteArray str = defineDirective.mid(8);
- const int spaceIdx = str.indexOf(' ');
- const bool hasValue = spaceIdx != -1;
-
- Macro macro;
- macro.name = str.left(hasValue ? spaceIdx : str.size());
- if (hasValue)
- macro.value = str.mid(spaceIdx + 1);
-
- return macro;
-}
-
-QByteArray Macro::toDefineOption(const QByteArray &option) const
-{
- QByteArray result;
-
- result.append(option);
- result.append(name);
- result.append('=');
- if (!value.isEmpty())
- result.append(value);
-
- return result;
-}
-
-void CompilerOptionsBuilder::addDefine(const QByteArray &defineDirective)
-{
- m_options.append(defineDirectiveToDefineOption(defineDirective));
+ m_options.append(defineDirectiveToDefineOption(macro));
}
void CompilerOptionsBuilder::addWordWidth()
@@ -160,21 +125,21 @@ void CompilerOptionsBuilder::addPrecompiledHeaderOptions(PchUsage pchUsage)
m_options.append(result);
}
-void CompilerOptionsBuilder::addToolchainAndProjectDefines()
+void CompilerOptionsBuilder::addToolchainAndProjectMacros()
{
- addDefines(m_projectPart.toolchainDefines);
- addDefines(m_projectPart.projectDefines);
+ addMacros(m_projectPart.toolChainMacros);
+ addMacros(m_projectPart.projectMacros);
}
-void CompilerOptionsBuilder::addDefines(const QByteArray &defineDirectives)
+void CompilerOptionsBuilder::addMacros(const ProjectExplorer::Macros &macros)
{
QStringList result;
- foreach (QByteArray def, defineDirectives.split('\n')) {
- if (def.isEmpty() || excludeDefineDirective(def))
+ for (const ProjectExplorer::Macro &macro : macros) {
+ if (excludeDefineDirective(macro))
continue;
- const QString defineOption = defineDirectiveToDefineOption(def);
+ const QString defineOption = defineDirectiveToDefineOption(macro);
if (!result.contains(defineOption))
result.append(defineOption);
}
@@ -293,21 +258,6 @@ void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtension
m_options.append(opts);
}
-void CompilerOptionsBuilder::addDefineToAvoidIncludingGccOrMinGwIntrinsics()
-{
- // In gcc headers, lots of built-ins are referenced that clang does not understand.
- // Therefore, prevent the inclusion of the header that references them. Of course, this
- // will break if code actually requires stuff from there, but that should be the less common
- // case.
-
- const Core::Id type = m_projectPart.toolchainType;
- if (type == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID
- || type == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID) {
- addDefine("#define _X86INTRIN_H_INCLUDED");
- addDefine("#define BOOST_UUID_NO_SIMD");
- }
-}
-
static QByteArray toMsCompatibilityVersionFormat(const QByteArray &mscFullVer)
{
return mscFullVer.left(2)
@@ -315,14 +265,10 @@ static QByteArray toMsCompatibilityVersionFormat(const QByteArray &mscFullVer)
+ mscFullVer.mid(2, 2);
}
-static QByteArray msCompatibilityVersionFromDefines(const QByteArray &defineDirectives)
+static QByteArray msCompatibilityVersionFromDefines(const ProjectExplorer::Macros &macros)
{
- foreach (QByteArray defineDirective, defineDirectives.split('\n')) {
- if (defineDirective.isEmpty())
- continue;
-
- const Macro macro = Macro::fromDefineDirective(defineDirective);
- if (macro.name == "_MSC_FULL_VER")
+ for (const ProjectExplorer::Macro &macro : macros) {
+ if (macro.key == "_MSC_FULL_VER")
return toMsCompatibilityVersionFormat(macro.value);
}
@@ -332,8 +278,8 @@ static QByteArray msCompatibilityVersionFromDefines(const QByteArray &defineDire
void CompilerOptionsBuilder::addMsvcCompatibilityVersion()
{
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
- const QByteArray defines = m_projectPart.toolchainDefines + m_projectPart.projectDefines;
- const QByteArray msvcVersion = msCompatibilityVersionFromDefines(defines);
+ const ProjectExplorer::Macros macros = m_projectPart.toolChainMacros + m_projectPart.projectMacros;
+ const QByteArray msvcVersion = msCompatibilityVersionFromDefines(macros);
if (!msvcVersion.isEmpty()) {
const QString option = QLatin1String("-fms-compatibility-version=")
@@ -398,7 +344,7 @@ void CompilerOptionsBuilder::addDefineFloat128ForMingw()
// CLANG-UPGRADE-CHECK: Workaround still needed?
// https://llvm.org/bugs/show_bug.cgi?id=30685
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID)
- addDefine("#define __float128 short");
+ addDefine({"__float128", "short", ProjectExplorer::MacroType::Define});
}
QString CompilerOptionsBuilder::includeDirOption() const
@@ -406,12 +352,25 @@ QString CompilerOptionsBuilder::includeDirOption() const
return QLatin1String("-I");
}
-QString CompilerOptionsBuilder::defineDirectiveToDefineOption(const QByteArray &defineDirective)
+QByteArray CompilerOptionsBuilder::macroOption(const ProjectExplorer::Macro &macro) const
+{
+ switch (macro.type) {
+ case ProjectExplorer::MacroType::Define: return defineOption().toUtf8();
+ case ProjectExplorer::MacroType::Undefine: return undefineOption().toUtf8();
+ default: return QByteArray();
+ }
+}
+
+QByteArray CompilerOptionsBuilder::toDefineOption(const ProjectExplorer::Macro &macro) const
+{
+ return macro.toKeyValue(macroOption(macro));
+}
+
+QString CompilerOptionsBuilder::defineDirectiveToDefineOption(const ProjectExplorer::Macro &macro) const
{
- const Macro macro = Macro::fromDefineDirective(defineDirective);
- const QByteArray option = macro.toDefineOption(defineOption().toLatin1());
+ const QByteArray option = toDefineOption(macro);
- return QString::fromLatin1(option);
+ return QString::fromUtf8(option);
}
QString CompilerOptionsBuilder::defineOption() const
@@ -435,11 +394,11 @@ static bool isGccOrMinGwToolchain(const Core::Id &toolchainType)
|| toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID;
}
-bool CompilerOptionsBuilder::excludeDefineDirective(const QByteArray &defineDirective) const
+bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro &macro) const
{
// This is a quick fix for QTCREATORBUG-11501.
// TODO: do a proper fix, see QTCREATORBUG-11709.
- if (defineDirective.startsWith("#define __cplusplus"))
+ if (macro.key == "__cplusplus")
return true;
// gcc 4.9 has:
@@ -449,7 +408,7 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const QByteArray &defineDire
// override clang's own (non-macro, it seems) definitions of the symbols on the left-hand
// side.
if (isGccOrMinGwToolchain(m_projectPart.toolchainType)
- && defineDirective.contains("has_include")) {
+ && macro.key.contains("has_include")) {
return true;
}
@@ -459,14 +418,14 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const QByteArray &defineDire
// __builtin_va_arg_pack, which clang does not support (yet), so avoid
// including those.
if (m_projectPart.toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID
- && defineDirective.startsWith("#define _FORTIFY_SOURCE")) {
+ && macro.key == "_FORTIFY_SOURCE") {
return true;
}
// MinGW 6 supports some fancy asm output flags and uses them in an
// intrinsics header pulled in by windows.h. Clang does not know them.
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID
- && defineDirective.startsWith("#define __GCC_ASM_FLAG_OUTPUTS__")) {
+ && macro.key == "__GCC_ASM_FLAG_OUTPUTS__") {
return true;
}
diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h
index 75b0c4f530..8ca985dc28 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.h
+++ b/src/plugins/cpptools/compileroptionsbuilder.h
@@ -46,7 +46,7 @@ public:
// Add custom options
void add(const QString &option);
- void addDefine(const QByteArray &defineDirective);
+ void addDefine(const ProjectExplorer::Macro &marco);
// Add options based on project part
void addWordWidth();
@@ -54,20 +54,18 @@ public:
virtual void enableExceptions();
void addHeaderPathOptions();
void addPrecompiledHeaderOptions(PchUsage pchUsage);
- void addToolchainAndProjectDefines();
- void addDefines(const QByteArray &defineDirectives);
+ void addToolchainAndProjectMacros();
+ void addMacros(const ProjectExplorer::Macros &macros);
virtual void addLanguageOption(ProjectFile::Kind fileKind);
virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true);
- void addDefineToAvoidIncludingGccOrMinGwIntrinsics();
-
void addMsvcCompatibilityVersion();
void undefineCppLanguageFeatureMacrosForMsvc2015();
void addDefineFloat128ForMingw();
protected:
- virtual bool excludeDefineDirective(const QByteArray &defineDirective) const;
+ virtual bool excludeDefineDirective(const ProjectExplorer::Macro &macro) const;
virtual bool excludeHeaderPath(const QString &headerPath) const;
virtual QString defineOption() const;
@@ -78,7 +76,9 @@ protected:
const ProjectPart m_projectPart;
private:
- QString defineDirectiveToDefineOption(const QByteArray &defineDirective);
+ QByteArray macroOption(const ProjectExplorer::Macro &macro) const;
+ QByteArray toDefineOption(const ProjectExplorer::Macro &macro) const;
+ QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const;
QStringList m_options;
};
diff --git a/src/plugins/cpptools/cppcanonicalsymbol.cpp b/src/plugins/cpptools/cppcanonicalsymbol.cpp
index 0532ae8b2d..3f1869de63 100644
--- a/src/plugins/cpptools/cppcanonicalsymbol.cpp
+++ b/src/plugins/cpptools/cppcanonicalsymbol.cpp
@@ -26,10 +26,11 @@
#include "cppcanonicalsymbol.h"
#include <cpptools/cpptoolsreuse.h>
-#include <texteditor/convenience.h>
#include <cplusplus/ExpressionUnderCursor.h>
+#include <utils/textutils.h>
+
#include <QTextCursor>
#include <QTextDocument>
@@ -58,7 +59,7 @@ Scope *CanonicalSymbol::getScopeAndExpression(const QTextCursor &cursor, QString
QTextCursor tc = cursor;
int line, column;
- TextEditor::Convenience::convertPosition(cursor.document(), tc.position(), &line, &column);
+ Utils::Text::convertPosition(cursor.document(), tc.position(), &line, &column);
++column; // 1-based line and 1-based column
int pos = tc.position();
diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp
index 199f185d63..60f7bb3242 100644
--- a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp
+++ b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp
@@ -31,6 +31,7 @@
#include <app/app_version.h>
#include <coreplugin/icore.h>
#include <cpptools/cppprojectfile.h>
+#include <projectexplorer/projectmacro.h>
#include <projectexplorer/project.h>
#include <utils/algorithm.h>
#include <utils/temporarydirectory.h>
@@ -153,6 +154,18 @@ QString Utils::toString(ProjectPart::QtVersion qtVersion)
return QString();
}
+QString Utils::toString(ProjectPart::BuildTargetType buildTargetType)
+{
+#define CASE_BUILDTARGETTYPE(x) case ProjectPart::x: return QLatin1String(#x)
+ switch (buildTargetType) {
+ CASE_BUILDTARGETTYPE(Unknown);
+ CASE_BUILDTARGETTYPE(Executable);
+ CASE_BUILDTARGETTYPE(Library);
+ }
+#undef CASE_BUILDTARGETTYPE
+ return QString();
+}
+
QString Utils::toString(ProjectFile::Kind kind)
{
return QString::fromLatin1(projectFileKindToText(kind));
@@ -482,6 +495,7 @@ void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos)
m_out << i3 << "Project Name : " << projectName << "\n";
m_out << i3 << "Project File : " << projectFilePath << "\n";
m_out << i3 << "Selected For Building: " << part->selectedForBuilding << "\n";
+ m_out << i3 << "Build Target Type : " << Utils::toString(part->buildTargetType) << "\n";
m_out << i3 << "Lanugage Version : " << Utils::toString(part->languageVersion)<<"\n";
m_out << i3 << "Lanugage Extensions : " << Utils::toString(part->languageExtensions)
<< "\n";
@@ -495,15 +509,17 @@ void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos)
}
}
- if (!part->toolchainDefines.isEmpty()) {
+ if (!part->toolChainMacros.isEmpty()) {
m_out << i3 << "Toolchain Defines:{{{4\n";
- const QList<QByteArray> defineLines = part->toolchainDefines.split('\n');
+ const QList<QByteArray> defineLines =
+ ProjectExplorer::Macro::toByteArray(part->toolChainMacros).split('\n');
foreach (const QByteArray &defineLine, defineLines)
m_out << i4 << defineLine << "\n";
}
- if (!part->projectDefines.isEmpty()) {
+ if (!part->projectMacros.isEmpty()) {
m_out << i3 << "Project Defines:{{{4\n";
- const QList<QByteArray> defineLines = part->projectDefines.split('\n');
+ const QList<QByteArray> defineLines =
+ ProjectExplorer::Macro::toByteArray(part->projectMacros).split('\n');
foreach (const QByteArray &defineLine, defineLines)
m_out << i4 << defineLine << "\n";
}
diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.h b/src/plugins/cpptools/cppcodemodelinspectordumper.h
index d281722790..a21bb5acbd 100644
--- a/src/plugins/cpptools/cppcodemodelinspectordumper.h
+++ b/src/plugins/cpptools/cppcodemodelinspectordumper.h
@@ -50,6 +50,7 @@ struct CPPTOOLS_EXPORT Utils
static QString toString(CppTools::ProjectPart::LanguageVersion languageVersion);
static QString toString(CppTools::ProjectPart::LanguageExtensions languageExtension);
static QString toString(CppTools::ProjectPart::QtVersion qtVersion);
+ static QString toString(CppTools::ProjectPart::BuildTargetType buildTargetType);
static QString toString(const QVector<CppTools::ProjectFile> &projectFiles);
static QString toString(CppTools::ProjectFile::Kind kind);
static QString toString(CPlusPlus::Kind kind);
diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.ui b/src/plugins/cpptools/cppcodemodelsettingspage.ui
index 025b91dba9..36ce48f28a 100644
--- a/src/plugins/cpptools/cppcodemodelsettingspage.ui
+++ b/src/plugins/cpptools/cppcodemodelsettingspage.ui
@@ -30,10 +30,10 @@
<item>
<widget class="QCheckBox" name="ignorePCHCheckBox">
<property name="toolTip">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When pre-compiled headers are not ignored, the parsing for code completion and semantic highlighting will process the pre-compiled header before processing any file.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When precompiled headers are not ignored, the parsing for code completion and semantic highlighting will process the precompiled header before processing any file.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
- <string>Ignore pre-compiled headers</string>
+ <string>Ignore precompiled headers</string>
</property>
</widget>
</item>
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index b494476351..147ae4e455 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -30,12 +30,12 @@
#include "cpptoolstestcase.h"
#include <texteditor/codeassist/iassistproposal.h>
-#include <texteditor/convenience.h>
#include <texteditor/texteditor.h>
#include <texteditor/textdocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include <utils/changeset.h>
+#include <utils/textutils.h>
#include <utils/fileutils.h>
#include <QDebug>
@@ -127,8 +127,7 @@ public:
const int pos = proposal.d->basePosition();
const int length = m_position - pos;
- const QString prefix = Convenience::textAt(QTextCursor(m_textDocument), pos,
- length);
+ const QString prefix = Utils::Text::textAt(QTextCursor(m_textDocument), pos, length);
if (!prefix.isEmpty())
listmodel->filter(prefix);
if (listmodel->isSortable(prefix))
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index 26b139e647..9b7cdc4512 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -38,11 +38,11 @@
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/ifunctionhintproposalmodel.h>
#include <texteditor/codeassist/functionhintproposal.h>
-#include <texteditor/convenience.h>
#include <texteditor/snippets/snippet.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/completionsettings.h>
+#include <utils/textutils.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
@@ -1091,7 +1091,7 @@ int InternalCppCompletionAssistProcessor::startCompletionHelper()
}
int line = 0, column = 0;
- Convenience::convertPosition(m_interface->textDocument(), startOfExpression, &line, &column);
+ Utils::Text::convertPosition(m_interface->textDocument(), startOfExpression, &line, &column);
const QString fileName = m_interface->fileName();
return startCompletionInternal(fileName, line, column, expression, endOfExpression);
}
@@ -1124,7 +1124,8 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot());
int line = 0, column = 0;
- Convenience::convertPosition(m_interface->textDocument(), m_interface->position(), &line, &column);
+ Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(), &line,
+ &column);
Scope *scope = thisDocument->scopeAt(line, column);
if (!scope)
return false;
@@ -1902,7 +1903,7 @@ void InternalCppCompletionAssistProcessor::addMacros_helper(const Snapshot &snap
foreach (const Document::Include &i, doc->resolvedIncludes())
addMacros_helper(snapshot, i.resolvedFileName(), processed, definedMacros);
- foreach (const Macro &macro, doc->definedMacros()) {
+ foreach (const CPlusPlus::Macro &macro, doc->definedMacros()) {
const QString macroName = macro.nameToQString();
if (!macro.isHidden())
definedMacros->insert(macroName);
@@ -2014,7 +2015,8 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
// get current line and column
int lineSigned = 0, columnSigned = 0;
- Convenience::convertPosition(m_interface->textDocument(), m_interface->position(), &lineSigned, &columnSigned);
+ Utils::Text::convertPosition(m_interface->textDocument(), m_interface->position(),
+ &lineSigned, &columnSigned);
unsigned line = lineSigned, column = columnSigned;
// find a scope that encloses the current location, starting from the lastVisibileSymbol
diff --git a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp
index bc0584a0a5..440e53439f 100644
--- a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp
+++ b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp
@@ -30,9 +30,9 @@
#include <coreplugin/idocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
+#include <utils/camelhumpmatcher.h>
-#include <QRegExp>
-#include <QStringMatcher>
+#include <QRegularExpression>
using namespace CppTools::Internal;
using namespace CPlusPlus;
@@ -66,12 +66,10 @@ QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
{
QList<Core::LocatorFilterEntry> goodEntries;
QList<Core::LocatorFilterEntry> betterEntries;
- const Qt::CaseSensitivity cs = caseSensitivity(entry);
- QStringMatcher matcher(entry, cs);
- QRegExp regexp(entry, cs, QRegExp::Wildcard);
+
+ const QRegularExpression regexp = createRegExp(entry);
if (!regexp.isValid())
return goodEntries;
- bool hasWildcard = containsWildcard(entry);
foreach (IndexItem::Ptr info, itemsOfCurrentDocument()) {
if (future.isCanceled())
@@ -83,29 +81,30 @@ QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
else if (info->type() == IndexItem::Function)
matchString += info->symbolType();
- int index = hasWildcard ? regexp.indexIn(matchString) : matcher.indexIn(matchString);
- if (index >= 0) {
- const bool betterMatch = index == 0;
+ QRegularExpressionMatch match = regexp.match(matchString);
+ if (match.hasMatch()) {
+ const bool betterMatch = match.capturedStart() == 0;
QVariant id = qVariantFromValue(info);
QString name = matchString;
QString extraInfo = info->symbolScope();
if (info->type() == IndexItem::Function) {
if (info->unqualifiedNameAndScope(matchString, &name, &extraInfo)) {
name += info->symbolType();
- index = hasWildcard ? regexp.indexIn(name) : matcher.indexIn(name);
+ match = regexp.match(name);
}
}
Core::LocatorFilterEntry filterEntry(this, name, id, info->icon());
filterEntry.extraInfo = extraInfo;
- if (index < 0) {
- index = hasWildcard ? regexp.indexIn(extraInfo) : matcher.indexIn(extraInfo);
+ if (!match.hasMatch()) {
+ match = regexp.match(extraInfo);
filterEntry.highlightInfo.dataType = Core::LocatorFilterEntry::HighlightInfo::ExtraInfo;
}
- if (index >= 0) {
- filterEntry.highlightInfo.startIndex = index;
- filterEntry.highlightInfo.length = hasWildcard ? regexp.matchedLength() : entry.length();
- }
+ const CamelHumpMatcher::HighlightingPositions positions =
+ CamelHumpMatcher::highlightingPositions(match);
+ filterEntry.highlightInfo.starts = positions.starts;
+ filterEntry.highlightInfo.lengths = positions.lengths;
+
if (betterMatch)
betterEntries.append(filterEntry);
else
diff --git a/src/plugins/cpptools/cppeditorwidgetinterface.h b/src/plugins/cpptools/cppeditorwidgetinterface.h
new file mode 100644
index 0000000000..309fa581cd
--- /dev/null
+++ b/src/plugins/cpptools/cppeditorwidgetinterface.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "cpptools_global.h"
+
+#include <texteditor/codeassist/assistenums.h>
+
+#include <QString>
+
+namespace TextEditor { class IAssistProvider; }
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT CppEditorWidgetInterface
+{
+public:
+ void renameUsages(const QString &replacement = QString())
+ {
+ return renameUsagesInternal(replacement);
+ }
+
+ virtual void showPreProcessorWidget() = 0;
+ virtual void updateSemanticInfo() = 0;
+ virtual void renameUsagesInternal(const QString &replacement) = 0;
+
+ virtual void invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind,
+ TextEditor::IAssistProvider *provider) = 0;
+};
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp
index c069b3514e..fa3f48a04a 100644
--- a/src/plugins/cpptools/cppfindreferences.cpp
+++ b/src/plugins/cpptools/cppfindreferences.cpp
@@ -370,7 +370,9 @@ void CppFindReferences::findAll_helper(SearchResult *search, Symbol *symbol,
return;
}
connect(search, &SearchResult::activated,
- this, &CppFindReferences::openEditor);
+ [](const SearchResultItem& item) {
+ Core::EditorManager::openEditorAtSearchResult(item);
+ });
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
const WorkingCopy workingCopy = m_modelManager->workingCopy();
@@ -580,7 +582,7 @@ static void searchFinished(SearchResult *search, QFutureWatcher<Usage> *watcher)
auto renameCheckBox = qobject_cast<QCheckBox *>(search->additionalReplaceWidget());
if (renameCheckBox) {
- renameCheckBox->setText(CppFindReferences::tr("Re&name %1 files").arg(filesToRename.size()));
+ renameCheckBox->setText(CppFindReferences::tr("Re&name %n files", nullptr, filesToRename.size()));
renameCheckBox->setToolTip(CppFindReferences::tr("Files:\n%1").arg(filesToRename.join('\n')));
renameCheckBox->setVisible(true);
}
@@ -589,31 +591,19 @@ static void searchFinished(SearchResult *search, QFutureWatcher<Usage> *watcher)
watcher->deleteLater();
}
-void CppFindReferences::openEditor(const SearchResultItem &item)
-{
- if (item.path.size() > 0) {
- EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
- item.mainRange.begin.line,
- item.mainRange.begin.column);
- } else {
- EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
- }
-}
-
-
namespace {
class FindMacroUsesInFile: public std::unary_function<QString, QList<Usage> >
{
const WorkingCopy workingCopy;
const Snapshot snapshot;
- const Macro &macro;
+ const CPlusPlus::Macro &macro;
QFutureInterface<Usage> *future;
public:
FindMacroUsesInFile(const WorkingCopy &workingCopy,
const Snapshot snapshot,
- const Macro &macro,
+ const CPlusPlus::Macro &macro,
QFutureInterface<Usage> *future)
: workingCopy(workingCopy), snapshot(snapshot), macro(macro), future(future)
{ }
@@ -632,7 +622,7 @@ restart_search:
usages.clear();
foreach (const Document::MacroUse &use, doc->macroUses()) {
- const Macro &useMacro = use.macro();
+ const CPlusPlus::Macro &useMacro = use.macro();
if (useMacro.fileName() == macro.fileName()) { // Check if this is a match, but possibly against an outdated document.
if (source.isEmpty())
@@ -687,7 +677,7 @@ restart_search:
static void findMacroUses_helper(QFutureInterface<Usage> &future,
const WorkingCopy workingCopy,
const Snapshot snapshot,
- const Macro macro)
+ const CPlusPlus::Macro macro)
{
const Utils::FileName sourceFile = Utils::FileName::fromString(macro.fileName());
Utils::FileNameList files{sourceFile};
@@ -704,12 +694,13 @@ static void findMacroUses_helper(QFutureInterface<Usage> &future,
future.setProgressValue(files.size());
}
-void CppFindReferences::findMacroUses(const Macro &macro)
+void CppFindReferences::findMacroUses(const CPlusPlus::Macro &macro)
{
findMacroUses(macro, QString(), false);
}
-void CppFindReferences::findMacroUses(const Macro &macro, const QString &replacement, bool replace)
+void CppFindReferences::findMacroUses(const CPlusPlus::Macro &macro, const QString &replacement,
+ bool replace)
{
SearchResult *search = SearchResultWindow::instance()->startNewSearch(
tr("C++ Macro Usages:"),
@@ -727,7 +718,9 @@ void CppFindReferences::findMacroUses(const Macro &macro, const QString &replace
SearchResultWindow::instance()->popup(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
connect(search, &SearchResult::activated,
- this, &CppFindReferences::openEditor);
+ [](const Core::SearchResultItem& item) {
+ Core::EditorManager::openEditorAtSearchResult(item);
+ });
const Snapshot snapshot = m_modelManager->snapshot();
const WorkingCopy workingCopy = m_modelManager->workingCopy();
@@ -753,7 +746,7 @@ void CppFindReferences::findMacroUses(const Macro &macro, const QString &replace
connect(progress, &FutureProgress::clicked, search, &SearchResult::popup);
}
-void CppFindReferences::renameMacroUses(const Macro &macro, const QString &replacement)
+void CppFindReferences::renameMacroUses(const CPlusPlus::Macro &macro, const QString &replacement)
{
const QString textToReplace = replacement.isEmpty() ? macro.nameToQString() : replacement;
findMacroUses(macro, textToReplace, true);
diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h
index 422eedb0c9..2dece06883 100644
--- a/src/plugins/cpptools/cppfindreferences.h
+++ b/src/plugins/cpptools/cppfindreferences.h
@@ -77,7 +77,6 @@ public:
void renameMacroUses(const CPlusPlus::Macro &macro, const QString &replacement = QString());
private:
- void openEditor(const Core::SearchResultItem &item);
void onReplaceButtonClicked(const QString &text, const QList<Core::SearchResultItem> &items, bool preserveCase);
void searchAgain();
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp
index 6e95cc63fc..ed82a3f9a8 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
+++ b/src/plugins/cpptools/cppfollowsymbolundercursor.cpp
@@ -24,8 +24,11 @@
****************************************************************************/
#include "cppfollowsymbolundercursor.h"
-#include "cppeditor.h"
#include "cppvirtualfunctionassistprovider.h"
+#include "cppmodelmanager.h"
+#include "functionutils.h"
+#include "cpptoolsreuse.h"
+#include "symbolfinder.h"
#include <cplusplus/ASTPath.h>
#include <cplusplus/BackwardsScanner.h>
@@ -33,24 +36,20 @@
#include <cplusplus/ResolveExpression.h>
#include <cplusplus/SimpleLexer.h>
#include <cplusplus/TypeOfExpression.h>
-#include <cpptools/cppmodelmanager.h>
-#include <cpptools/functionutils.h>
-#include <cpptools/cpptoolsreuse.h>
-#include <cpptools/symbolfinder.h>
#include <texteditor/textdocumentlayout.h>
+#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <QList>
#include <QSet>
using namespace CPlusPlus;
-using namespace CppTools;
-using namespace CppEditor;
-using namespace CppEditor::Internal;
using namespace TextEditor;
typedef TextEditorWidget::Link Link;
+namespace CppTools {
+
namespace {
class VirtualFunctionHelper {
@@ -297,9 +296,9 @@ inline LookupItem skipForwardDeclarations(const QList<LookupItem> &resolvedSymbo
return result;
}
-CppEditorWidget::Link attemptFuncDeclDef(const QTextCursor &cursor,
- CppEditorWidget *, Snapshot snapshot, const Document::Ptr &document,
- SymbolFinder *symbolFinder)
+Link attemptFuncDeclDef(const QTextCursor &cursor, Snapshot snapshot,
+ const Document::Ptr &document,
+ SymbolFinder *symbolFinder)
{
Link result;
QTC_ASSERT(document, return result);
@@ -459,15 +458,9 @@ QString expressionUnderCursorAsString(const QTextCursor &textCursor,
} // anonymous namespace
-FollowSymbolUnderCursor::FollowSymbolUnderCursor(CppEditorWidget *widget)
- : m_widget(widget)
- , m_virtualFunctionAssistProvider(new VirtualFunctionAssistProvider)
-{
-}
-
-FollowSymbolUnderCursor::~FollowSymbolUnderCursor()
+FollowSymbolUnderCursor::FollowSymbolUnderCursor()
+ : m_virtualFunctionAssistProvider(new VirtualFunctionAssistProvider)
{
- delete m_virtualFunctionAssistProvider;
}
static int skipMatchingParentheses(const Tokens &tokens, int idx, int initialDepth)
@@ -487,17 +480,27 @@ static int skipMatchingParentheses(const Tokens &tokens, int idx, int initialDep
return j;
}
-TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &cursor,
- bool resolveTarget, const Snapshot &theSnapshot, const Document::Ptr &documentFromSemanticInfo,
- SymbolFinder *symbolFinder, bool inNextSplit)
+Link FollowSymbolUnderCursor::findLink(
+ const CppTools::CursorInEditor &data,
+ bool resolveTarget,
+ const Snapshot &theSnapshot,
+ const Document::Ptr &documentFromSemanticInfo,
+ SymbolFinder *symbolFinder,
+ bool inNextSplit)
{
Link link;
+ int lineNumber = 0, positionInBlock = 0;
+ QTextCursor cursor = data.cursor();
+ QTextDocument *document = cursor.document();
+ Utils::Text::convertPosition(document, cursor.position(), &lineNumber, &positionInBlock);
+ const unsigned line = lineNumber;
+ const unsigned column = positionInBlock + 1;
+
Snapshot snapshot = theSnapshot;
// Move to end of identifier
QTextCursor tc = cursor;
- QTextDocument *document = m_widget->document();
QChar ch = document->characterAt(tc.position());
while (CppTools::isValidIdentifierChar(ch)) {
tc.movePosition(QTextCursor::NextCharacter);
@@ -512,18 +515,13 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
while (document->characterAt(pos).isSpace())
++pos;
if (document->characterAt(pos) == QLatin1Char('(')) {
- link = attemptFuncDeclDef(cursor, m_widget, snapshot, documentFromSemanticInfo,
+ link = attemptFuncDeclDef(cursor, snapshot, documentFromSemanticInfo,
symbolFinder);
if (link.hasValidLinkText())
return link;
}
}
- int lineNumber = 0, positionInBlock = 0;
- m_widget->convertPosition(cursor.position(), &lineNumber, &positionInBlock);
- const unsigned line = lineNumber;
- const unsigned column = positionInBlock + 1;
-
// Try to find a signal or slot inside SIGNAL() or SLOT()
int beginOfToken = 0;
int endOfToken = 0;
@@ -589,7 +587,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
&& unsigned(positionInBlock) <= tk.utf16charsEnd()) {
cursorRegionReached = true;
if (tk.is(T_OPERATOR)) {
- link = attemptFuncDeclDef(cursor, m_widget, theSnapshot,
+ link = attemptFuncDeclDef(cursor, theSnapshot,
documentFromSemanticInfo, symbolFinder);
if (link.hasValidLinkText())
return link;
@@ -597,7 +595,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
QTextCursor c = cursor;
c.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor,
positionInBlock - tokens.at(i - 1).utf16charsBegin());
- link = attemptFuncDeclDef(c, m_widget, theSnapshot, documentFromSemanticInfo,
+ link = attemptFuncDeclDef(c, theSnapshot, documentFromSemanticInfo,
symbolFinder);
if (link.hasValidLinkText())
return link;
@@ -608,8 +606,11 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
}
}
+ CppEditorWidgetInterface *editorWidget = data.editorWidget();
+ if (!editorWidget)
+ return link;
// Now we prefer the doc from the snapshot with macros expanded.
- Document::Ptr doc = snapshot.document(m_widget->textDocument()->filePath());
+ Document::Ptr doc = snapshot.document(data.filePath());
if (!doc) {
doc = documentFromSemanticInfo;
if (!doc)
@@ -658,7 +659,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
} else if (const Document::MacroUse *use = doc->findMacroUseAt(endOfToken - 1)) {
const QString fileName = use->macro().fileName();
if (fileName == CppModelManager::editorConfigurationFileName()) {
- m_widget->showPreProcessorWidget();
+ editorWidget->showPreProcessorWidget();
} else if (fileName != CppModelManager::configurationFileName()) {
const Macro &macro = use->macro();
link.targetFileName = macro.fileName();
@@ -692,7 +693,7 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
if (Symbol *d = r.declaration()) {
if (d->isDeclaration() || d->isFunction()) {
const QString fileName = QString::fromUtf8(d->fileName(), d->fileNameLength());
- if (m_widget->textDocument()->filePath().toString() == fileName) {
+ if (data.filePath().toString() == fileName) {
if (unsigned(lineNumber) == d->line()
&& unsigned(positionInBlock) >= d->column()) { // TODO: check the end
result = r; // take the symbol under cursor.
@@ -701,8 +702,8 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
}
} else if (d->isUsingDeclaration()) {
int tokenBeginLineNumber = 0, tokenBeginColumnNumber = 0;
- m_widget->convertPosition(beginOfToken, &tokenBeginLineNumber,
- &tokenBeginColumnNumber);
+ Utils::Text::convertPosition(document, beginOfToken, &tokenBeginLineNumber,
+ &tokenBeginColumnNumber);
if (unsigned(tokenBeginLineNumber) > d->line()
|| (unsigned(tokenBeginLineNumber) == d->line()
&& unsigned(tokenBeginColumnNumber) > d->column())) {
@@ -731,7 +732,8 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
params.openInNextSplit = inNextSplit;
if (m_virtualFunctionAssistProvider->configure(params)) {
- m_widget->invokeAssist(FollowSymbol, m_virtualFunctionAssistProvider);
+ editorWidget->invokeTextEditorWidgetAssist(
+ FollowSymbol,m_virtualFunctionAssistProvider.data());
m_virtualFunctionAssistProvider->clearParams();
}
@@ -780,12 +782,15 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
return Link();
}
-VirtualFunctionAssistProvider *FollowSymbolUnderCursor::virtualFunctionAssistProvider()
+QSharedPointer<VirtualFunctionAssistProvider> FollowSymbolUnderCursor::virtualFunctionAssistProvider()
{
return m_virtualFunctionAssistProvider;
}
-void FollowSymbolUnderCursor::setVirtualFunctionAssistProvider(VirtualFunctionAssistProvider *provider)
+void FollowSymbolUnderCursor::setVirtualFunctionAssistProvider(
+ const QSharedPointer<VirtualFunctionAssistProvider> &provider)
{
m_virtualFunctionAssistProvider = provider;
}
+
+} // namespace CppTools
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.h b/src/plugins/cpptools/cppfollowsymbolundercursor.h
index 3121fe00e8..8e93a7097d 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.h
+++ b/src/plugins/cpptools/cppfollowsymbolundercursor.h
@@ -25,41 +25,30 @@
#pragma once
-#include <cplusplus/CppDocument.h>
-#include <texteditor/texteditor.h>
+#include "followsymbolinterface.h"
-QT_BEGIN_NAMESPACE
-class QTextCursor;
-QT_END_NAMESPACE
+namespace CppTools {
-namespace CppTools { class SymbolFinder; }
-
-namespace CppEditor {
-namespace Internal {
-
-class CppEditorWidget;
class VirtualFunctionAssistProvider;
-class FollowSymbolUnderCursor
+class CPPTOOLS_EXPORT FollowSymbolUnderCursor : public CppTools::FollowSymbolInterface
{
public:
- typedef TextEditor::TextEditorWidget::Link Link;
-
- FollowSymbolUnderCursor(CppEditorWidget *widget);
- ~FollowSymbolUnderCursor();
+ FollowSymbolUnderCursor();
- Link findLink(const QTextCursor &cursor, bool resolveTarget,
+ Link findLink(const CppTools::CursorInEditor &data,
+ bool resolveTarget,
const CPlusPlus::Snapshot &snapshot,
const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
- CppTools::SymbolFinder *symbolFinder, bool inNextSplit);
+ CppTools::SymbolFinder *symbolFinder,
+ bool inNextSplit) override;
- VirtualFunctionAssistProvider *virtualFunctionAssistProvider();
- void setVirtualFunctionAssistProvider(VirtualFunctionAssistProvider *provider);
+ QSharedPointer<VirtualFunctionAssistProvider> virtualFunctionAssistProvider();
+ void setVirtualFunctionAssistProvider(
+ const QSharedPointer<VirtualFunctionAssistProvider> &provider);
private:
- CppEditorWidget *m_widget;
- VirtualFunctionAssistProvider *m_virtualFunctionAssistProvider;
+ QSharedPointer<VirtualFunctionAssistProvider> m_virtualFunctionAssistProvider;
};
-} // namespace Internal
-} // namespace CppEditor
+} // namespace CppTools
diff --git a/src/plugins/cpptools/cpplocatorfilter.cpp b/src/plugins/cpptools/cpplocatorfilter.cpp
index f8bf53dd32..f113462217 100644
--- a/src/plugins/cpptools/cpplocatorfilter.cpp
+++ b/src/plugins/cpptools/cpplocatorfilter.cpp
@@ -28,9 +28,9 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
+#include <utils/camelhumpmatcher.h>
-#include <QRegExp>
-#include <QStringMatcher>
+#include <QRegularExpression>
#include <algorithm>
@@ -72,34 +72,36 @@ QList<Core::LocatorFilterEntry> CppLocatorFilter::matchesFor(
{
QList<Core::LocatorFilterEntry> goodEntries;
QList<Core::LocatorFilterEntry> betterEntries;
- const Qt::CaseSensitivity cs = caseSensitivity(entry);
- QStringMatcher matcher(entry, cs);
- QRegExp regexp(entry, cs, QRegExp::Wildcard);
- if (!regexp.isValid())
- return goodEntries;
- bool hasWildcard = containsWildcard(entry);
+ QList<Core::LocatorFilterEntry> bestEntries;
+ const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
bool hasColonColon = entry.contains(QLatin1String("::"));
const IndexItem::ItemType wanted = matchTypes();
+ const QRegularExpression regexp = createRegExp(entry);
+ if (!regexp.isValid())
+ return goodEntries;
+
m_data->filterAllFiles([&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult {
if (future.isCanceled())
return IndexItem::Break;
if (info->type() & wanted) {
- const QString matchString = hasColonColon ? info->scopedSymbolName() : info->symbolName();
- int index = hasWildcard ? regexp.indexIn(matchString) : matcher.indexIn(matchString);
- if (index >= 0) {
- const bool betterMatch = index == 0;
+ QString matchString = hasColonColon ? info->scopedSymbolName() : info->symbolName();
+ QRegularExpressionMatch match = regexp.match(matchString);
+ if (match.hasMatch()) {
Core::LocatorFilterEntry filterEntry = filterEntryFromIndexItem(info);
- if (matchString != filterEntry.displayName) {
- index = hasWildcard ? regexp.indexIn(filterEntry.displayName)
- : matcher.indexIn(filterEntry.displayName);
- }
-
- if (index >= 0)
- filterEntry.highlightInfo = {index, (hasWildcard ? regexp.matchedLength() : entry.length())};
-
- if (betterMatch)
+ // Highlight the matched characters, therefore it may be necessary
+ // to update the match if the displayName is different from matchString
+ if (matchString != filterEntry.displayName)
+ match = regexp.match(filterEntry.displayName);
+ const CamelHumpMatcher::HighlightingPositions positions =
+ CamelHumpMatcher::highlightingPositions(match);
+ filterEntry.highlightInfo.starts = positions.starts;
+ filterEntry.highlightInfo.lengths = positions.lengths;
+
+ if (matchString.startsWith(entry, caseSensitivityForPrefix))
+ bestEntries.append(filterEntry);
+ else if (matchString.contains(entry, caseSensitivityForPrefix))
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
@@ -116,9 +118,12 @@ QList<Core::LocatorFilterEntry> CppLocatorFilter::matchesFor(
Utils::sort(goodEntries, Core::LocatorFilterEntry::compareLexigraphically);
if (betterEntries.size() < 1000)
Utils::sort(betterEntries, Core::LocatorFilterEntry::compareLexigraphically);
+ if (bestEntries.size() < 1000)
+ Utils::sort(bestEntries, Core::LocatorFilterEntry::compareLexigraphically);
- betterEntries += goodEntries;
- return betterEntries;
+ bestEntries += betterEntries;
+ bestEntries += goodEntries;
+ return bestEntries;
}
void CppLocatorFilter::accept(Core::LocatorFilterEntry selection,
diff --git a/src/plugins/cpptools/cpplocatorfilter_test.cpp b/src/plugins/cpptools/cpplocatorfilter_test.cpp
index 27258855d8..501a396eb1 100644
--- a/src/plugins/cpptools/cpplocatorfilter_test.cpp
+++ b/src/plugins/cpptools/cpplocatorfilter_test.cpp
@@ -190,6 +190,16 @@ void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter_data()
<< ResultData(_("myFunction(bool, int)"), _("<anonymous namespace> (file1.cpp)"))
);
+ QTest::newRow("CppFunctionsFilter-Sorting")
+ << testFile
+ << cppFunctionsFilter
+ << _("pos")
+ << (QList<ResultData>()
+ << ResultData(_("positiveNumber()"), testFileShort)
+ << ResultData(_("getPosition()"), testFileShort)
+ << ResultData(_("pointOfService()"), testFileShort)
+ );
+
QTest::newRow("CppFunctionsFilter-WithNamespacePrefix")
<< testFile
<< cppFunctionsFilter
@@ -280,6 +290,9 @@ void CppToolsPlugin::test_cpplocatorfilters_CppCurrentDocumentFilter()
QList<ResultData> expectedResults = QList<ResultData>()
<< ResultData(_("int myVariable"), _(""))
<< ResultData(_("myFunction(bool, int)"), _(""))
+ << ResultData(_("pointOfService()"), _(""))
+ << ResultData(_("getPosition()"), _(""))
+ << ResultData(_("positiveNumber()"), _(""))
<< ResultData(_("MyEnum"), _(""))
<< ResultData(_("int V1"), _("MyEnum"))
<< ResultData(_("int V2"), _("MyEnum"))
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index d2493e2e45..da45301782 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -33,12 +33,14 @@
#include "cppindexingsupport.h"
#include "cppmodelmanagersupportinternal.h"
#include "cpprefactoringchanges.h"
+#include "cpprefactoringengine.h"
#include "cppsourceprocessor.h"
#include "cpptoolsconstants.h"
#include "cpptoolsplugin.h"
#include "cpptoolsreuse.h"
#include "editordocumenthandle.h"
#include "symbolfinder.h"
+#include "followsymbolinterface.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
@@ -47,6 +49,7 @@
#include <texteditor/textdocument.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/projectmacro.h>
#include <projectexplorer/session.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/fileutils.h>
@@ -138,7 +141,7 @@ public:
bool m_dirty;
QStringList m_projectFiles;
ProjectPartHeaderPaths m_headerPaths;
- QByteArray m_definedMacros;
+ ProjectExplorer::Macros m_definedMacros;
// Editor integration
mutable QMutex m_cppEditorDocumentsMutex;
@@ -163,7 +166,8 @@ public:
QTimer m_delayedGcTimer;
// Refactoring
- RefactoringEngineInterface *m_refactoringEngine = nullptr;
+ CppRefactoringEngine m_builtInRefactoringEngine;
+ RefactoringEngineInterface *m_refactoringEngine { &m_builtInRefactoringEngine };
};
} // namespace Internal
@@ -265,12 +269,20 @@ QString CppModelManager::editorConfigurationFileName()
void CppModelManager::setRefactoringEngine(RefactoringEngineInterface *refactoringEngine)
{
- instance()->d->m_refactoringEngine = refactoringEngine;
+ if (refactoringEngine)
+ instance()->d->m_refactoringEngine = refactoringEngine;
+ else
+ instance()->d->m_refactoringEngine = &instance()->d->m_builtInRefactoringEngine;
}
-RefactoringEngineInterface *CppModelManager::refactoringEngine()
+RefactoringEngineInterface &CppModelManager::refactoringEngine()
{
- return instance()->d->m_refactoringEngine;
+ return *instance()->d->m_refactoringEngine;
+}
+
+FollowSymbolInterface &CppModelManager::followSymbolInterface() const
+{
+ return d->m_activeModelManagerSupport->followSymbolInterface();
}
QString CppModelManager::configurationFileName()
@@ -446,35 +458,31 @@ ProjectPartHeaderPaths CppModelManager::internalHeaderPaths() const
return headerPaths;
}
-static void addUnique(const QList<QByteArray> &defs, QByteArray *macros, QSet<QByteArray> *alreadyIn)
+static void addUnique(const ProjectExplorer::Macros &newMacros,
+ ProjectExplorer::Macros &macros,
+ QSet<ProjectExplorer::Macro> &alreadyIn)
{
- Q_ASSERT(macros);
- Q_ASSERT(alreadyIn);
-
- foreach (const QByteArray &def, defs) {
- if (def.trimmed().isEmpty())
- continue;
- if (!alreadyIn->contains(def)) {
- macros->append(def);
- macros->append('\n');
- alreadyIn->insert(def);
+ for (const ProjectExplorer::Macro &macro : newMacros) {
+ if (!alreadyIn.contains(macro)) {
+ macros += macro;
+ alreadyIn.insert(macro);
}
}
}
-QByteArray CppModelManager::internalDefinedMacros() const
+ProjectExplorer::Macros CppModelManager::internalDefinedMacros() const
{
- QByteArray macros;
- QSet<QByteArray> alreadyIn;
+ ProjectExplorer::Macros macros;
+ QSet<ProjectExplorer::Macro> alreadyIn;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(d->m_projectToProjectsInfo);
while (it.hasNext()) {
it.next();
const ProjectInfo pinfo = it.value();
- foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) {
- addUnique(part->toolchainDefines.split('\n'), &macros, &alreadyIn);
- addUnique(part->projectDefines.split('\n'), &macros, &alreadyIn);
+ for (const ProjectPart::Ptr &part : pinfo.projectParts()) {
+ addUnique(part->toolChainMacros, macros, alreadyIn);
+ addUnique(part->projectMacros, macros, alreadyIn);
if (!part->projectConfigFile.isEmpty())
- macros += ProjectPart::readProjectConfigFile(part);
+ macros += ProjectExplorer::Macro::toMacros(ProjectPart::readProjectConfigFile(part));
}
}
return macros;
@@ -491,7 +499,8 @@ void CppModelManager::dumpModelManagerConfiguration(const QString &logFileId)
dumper.dumpProjectInfos(projectInfos());
dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
dumper.dumpWorkingCopy(workingCopy());
- dumper.dumpMergedEntities(headerPaths(), definedMacros());
+ dumper.dumpMergedEntities(headerPaths(),
+ ProjectExplorer:: Macro::toByteArray(definedMacros()));
}
QSet<AbstractEditorSupport *> CppModelManager::abstractEditorSupports() const
@@ -569,12 +578,12 @@ void CppModelManager::renameUsages(Symbol *symbol,
d->m_findReferences->renameUsages(symbol, context, replacement);
}
-void CppModelManager::findMacroUsages(const Macro &macro)
+void CppModelManager::findMacroUsages(const CPlusPlus::Macro &macro)
{
d->m_findReferences->findMacroUses(macro);
}
-void CppModelManager::renameMacroUsages(const Macro &macro, const QString &replacement)
+void CppModelManager::renameMacroUsages(const CPlusPlus::Macro &macro, const QString &replacement)
{
d->m_findReferences->renameMacroUses(macro, replacement);
}
@@ -603,7 +612,7 @@ WorkingCopy CppModelManager::buildWorkingCopyList()
// Add the project configuration file
QByteArray conf = codeModelConfiguration();
- conf += definedMacros();
+ conf += ProjectExplorer::Macro::toByteArray(definedMacros());
workingCopy.insert(configurationFileName(), conf);
return workingCopy;
@@ -991,7 +1000,7 @@ ProjectPart::Ptr CppModelManager::fallbackProjectPart()
{
ProjectPart::Ptr part(new ProjectPart);
- part->projectDefines = definedMacros();
+ part->projectMacros = definedMacros();
part->headerPaths = headerPaths();
// Do not activate ObjectiveCExtensions since this will lead to the
@@ -1270,7 +1279,7 @@ void CppModelManager::setHeaderPaths(const ProjectPartHeaderPaths &headerPaths)
d->m_headerPaths = headerPaths;
}
-QByteArray CppModelManager::definedMacros()
+ProjectExplorer::Macros CppModelManager::definedMacros()
{
QMutexLocker locker(&d->m_projectMutex);
ensureUpdated();
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 97a93fce60..df04beec3a 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -54,6 +54,7 @@ class CppEditorDocumentHandle;
class CppIndexingSupport;
class ModelManagerSupportProvider;
class RefactoringEngineInterface;
+class FollowSymbolInterface;
class SymbolFinder;
class WorkingCopy;
@@ -152,6 +153,7 @@ public:
CppCompletionAssistProvider *completionAssistProvider() const;
BaseEditorDocumentProcessor *editorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) const;
+ FollowSymbolInterface &followSymbolInterface() const;
void setIndexingSupport(CppIndexingSupport *indexingSupport);
CppIndexingSupport *indexingSupport();
@@ -163,7 +165,7 @@ public:
// Use this *only* for auto tests
void setHeaderPaths(const ProjectPartHeaderPaths &headerPaths);
- QByteArray definedMacros();
+ ProjectExplorer::Macros definedMacros();
void enableGarbageCollector(bool enable);
@@ -178,7 +180,7 @@ public:
static QString editorConfigurationFileName();
static void setRefactoringEngine(RefactoringEngineInterface *refactoringEngine);
- static RefactoringEngineInterface *refactoringEngine();
+ static RefactoringEngineInterface &refactoringEngine();
void renameIncludes(const QString &oldFileName, const QString &newFileName);
@@ -229,7 +231,7 @@ private:
void ensureUpdated();
QStringList internalProjectFiles() const;
ProjectPartHeaderPaths internalHeaderPaths() const;
- QByteArray internalDefinedMacros() const;
+ ProjectExplorer::Macros internalDefinedMacros() const;
void dumpModelManagerConfiguration(const QString &logFileId);
diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp
index 35f9931f21..c50c12402c 100644
--- a/src/plugins/cpptools/cppmodelmanager_test.cpp
+++ b/src/plugins/cpptools/cppmodelmanager_test.cpp
@@ -187,7 +187,7 @@ void CppToolsPlugin::test_modelmanager_paths_are_clean()
ProjectPart::Ptr part(new ProjectPart);
part->qtVersion = ProjectPart::Qt5;
- part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
+ part->projectMacros = {ProjectExplorer::Macro("OH_BEHAVE", "-1")};
part->headerPaths = {HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath),
HeaderPath(testDataDir.frameworksDir(false), HeaderPath::FrameworkPath)};
pi.appendProjectPart(part);
@@ -219,7 +219,7 @@ void CppToolsPlugin::test_modelmanager_framework_headers()
ProjectPart::Ptr part(new ProjectPart);
part->qtVersion = ProjectPart::Qt5;
- part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
+ part->projectMacros = {{"OH_BEHAVE", "-1"}};
part->headerPaths = {HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath),
HeaderPath(testDataDir.frameworksDir(false), HeaderPath::FrameworkPath)};
const QString &source = testDataDir.fileFromSourcesDir(
@@ -268,7 +268,7 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
ProjectPart::Ptr part(new ProjectPart);
part->qtVersion = ProjectPart::Qt5;
- part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
+ part->projectMacros = {{"OH_BEHAVE", "-1"}};
part->headerPaths = {HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath)};
part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
pi.appendProjectPart(part);
@@ -286,7 +286,7 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
QVERIFY(macrosInHeaderBefore.first().name() == "test_modelmanager_refresh_h");
// Introduce a define that will enable another define once the document is reparsed.
- part->projectDefines = QByteArray("#define TEST_DEFINE 1\n");
+ part->projectMacros = {{"TEST_DEFINE", "1"}};
pi = ProjectInfo(project);
pi.appendProjectPart(part);
@@ -334,13 +334,13 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times()
QSet<QString> refreshedFiles;
CPlusPlus::Document::Ptr document;
- QByteArray defines = "#define FIRST_DEFINE";
+ ProjectExplorer::Macros macros = {{"FIRST_DEFINE"}};
for (int i = 0; i < 2; ++i) {
pi = ProjectInfo(project);
ProjectPart::Ptr part(new ProjectPart);
// Simulate project configuration change by having different defines each time.
- defines += "\n#define ANOTHER_DEFINE";
- part->projectDefines = defines;
+ macros += {"ANOTHER_DEFINE"};
+ part->projectMacros = macros;
part->qtVersion = ProjectPart::Qt5;
part->files.append(ProjectFile(testHeader1, ProjectFile::CXXHeader));
part->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader));
@@ -762,7 +762,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource));
part1->files.append(ProjectFile(header, ProjectFile::CXXHeader));
part1->qtVersion = ProjectPart::NoQt;
- part1->projectDefines = QByteArray("#define SUB1\n");
+ part1->projectMacros = {{"SUB1"}};
part1->headerPaths = {HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath)};
ProjectPart::Ptr part2(new ProjectPart);
@@ -770,7 +770,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
part2->files.append(ProjectFile(main2File, ProjectFile::CXXSource));
part2->files.append(ProjectFile(header, ProjectFile::CXXHeader));
part2->qtVersion = ProjectPart::NoQt;
- part2->projectDefines = QByteArray("#define SUB2\n");
+ part2->projectMacros = {{"SUB2"}};
part2->headerPaths = {HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath)};
ProjectInfo pi = ProjectInfo(project);
diff --git a/src/plugins/cpptools/cppmodelmanagersupport.h b/src/plugins/cpptools/cppmodelmanagersupport.h
index cfef02e1a0..cb74f00efd 100644
--- a/src/plugins/cpptools/cppmodelmanagersupport.h
+++ b/src/plugins/cpptools/cppmodelmanagersupport.h
@@ -36,6 +36,7 @@ namespace CppTools {
class BaseEditorDocumentProcessor;
class CppCompletionAssistProvider;
+class FollowSymbolInterface;
class CPPTOOLS_EXPORT ModelManagerSupport
{
@@ -48,6 +49,7 @@ public:
virtual CppCompletionAssistProvider *completionAssistProvider() = 0;
virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) = 0;
+ virtual FollowSymbolInterface &followSymbolInterface() = 0;
};
class CPPTOOLS_EXPORT ModelManagerSupportProvider
diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
index b875465344..c03e2ed57e 100644
--- a/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
+++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.cpp
@@ -25,8 +25,11 @@
#include "cppcompletionassist.h"
#include "cppmodelmanagersupportinternal.h"
+#include "cppfollowsymbolundercursor.h"
#include "builtineditordocumentprocessor.h"
+#include <app/app_version.h>
+
#include <QCoreApplication>
using namespace CppTools;
@@ -40,7 +43,7 @@ QString ModelManagerSupportProviderInternal::id() const
QString ModelManagerSupportProviderInternal::displayName() const
{
return QCoreApplication::translate("ModelManagerSupportInternal::displayName",
- "Qt Creator Built-in");
+ "%1 Built-in").arg(Core::Constants::IDE_DISPLAY_NAME);
}
ModelManagerSupport::Ptr ModelManagerSupportProviderInternal::createModelManagerSupport()
@@ -49,7 +52,8 @@ ModelManagerSupport::Ptr ModelManagerSupportProviderInternal::createModelManager
}
ModelManagerSupportInternal::ModelManagerSupportInternal()
- : m_completionAssistProvider(new InternalCompletionAssistProvider)
+ : m_completionAssistProvider(new InternalCompletionAssistProvider),
+ m_followSymbol(new FollowSymbolUnderCursor)
{
}
@@ -67,3 +71,8 @@ CppCompletionAssistProvider *ModelManagerSupportInternal::completionAssistProvid
{
return m_completionAssistProvider.data();
}
+
+FollowSymbolInterface &ModelManagerSupportInternal::followSymbolInterface()
+{
+ return *m_followSymbol;
+}
diff --git a/src/plugins/cpptools/cppmodelmanagersupportinternal.h b/src/plugins/cpptools/cppmodelmanagersupportinternal.h
index 0a2290f595..cd35ea5abc 100644
--- a/src/plugins/cpptools/cppmodelmanagersupportinternal.h
+++ b/src/plugins/cpptools/cppmodelmanagersupportinternal.h
@@ -40,12 +40,14 @@ public:
ModelManagerSupportInternal();
virtual ~ModelManagerSupportInternal();
- virtual CppCompletionAssistProvider *completionAssistProvider();
- virtual BaseEditorDocumentProcessor *editorDocumentProcessor(
- TextEditor::TextDocument *baseTextDocument);
+ CppCompletionAssistProvider *completionAssistProvider() final;
+ BaseEditorDocumentProcessor *editorDocumentProcessor(
+ TextEditor::TextDocument *baseTextDocument) final;
+ FollowSymbolInterface &followSymbolInterface() final;
private:
QScopedPointer<CppCompletionAssistProvider> m_completionAssistProvider;
+ QScopedPointer<FollowSymbolInterface> m_followSymbol;
};
class ModelManagerSupportProviderInternal : public ModelManagerSupportProvider
diff --git a/src/plugins/cpptools/cppprojectinfogenerator.cpp b/src/plugins/cpptools/cppprojectinfogenerator.cpp
index bff5d36ec4..4a32d255fc 100644
--- a/src/plugins/cpptools/cppprojectinfogenerator.cpp
+++ b/src/plugins/cpptools/cppprojectinfogenerator.cpp
@@ -143,7 +143,7 @@ private:
if (!m_tcInfo.predefinedMacrosRunner)
return; // No compiler set in kit.
- m_projectPart.toolchainDefines = m_tcInfo.predefinedMacrosRunner(m_flags.commandLineFlags);
+ m_projectPart.toolChainMacros = m_tcInfo.predefinedMacrosRunner(m_flags.commandLineFlags);
}
private:
@@ -186,8 +186,9 @@ static ProjectPart::Ptr projectPartFromRawProjectPart(const RawProjectPart &rawP
part->projectFileColumn = rawProjectPart.projectFileColumn;
part->callGroupId = rawProjectPart.callGroupId;
part->buildSystemTarget = rawProjectPart.buildSystemTarget;
+ part->buildTargetType = rawProjectPart.buildTargetType;
part->qtVersion = rawProjectPart.qtVersion;
- part->projectDefines = rawProjectPart.projectDefines;
+ part->projectMacros = rawProjectPart.projectMacros;
part->headerPaths = rawProjectPart.headerPaths;
part->precompiledHeaders = rawProjectPart.precompiledHeaders;
part->selectedForBuilding = rawProjectPart.selectedForBuilding;
diff --git a/src/plugins/cpptools/cpprawprojectpart.cpp b/src/plugins/cpptools/cpprawprojectpart.cpp
index 3668f8caec..fc66420323 100644
--- a/src/plugins/cpptools/cpprawprojectpart.cpp
+++ b/src/plugins/cpptools/cpprawprojectpart.cpp
@@ -81,9 +81,9 @@ void RawProjectPart::setQtVersion(ProjectPart::QtVersion qtVersion)
this->qtVersion = qtVersion;
}
-void RawProjectPart::setDefines(const QByteArray &defines)
+void RawProjectPart::setMacros(const ProjectExplorer::Macros &macros)
{
- this->projectDefines = defines;
+ this->projectMacros = macros;
}
void RawProjectPart::setHeaderPaths(const ProjectPartHeaderPaths &headerPaths)
@@ -133,4 +133,9 @@ void RawProjectPart::setFlagsForCxx(const RawProjectPartFlags &flags)
flagsForCxx = flags;
}
+void RawProjectPart::setBuildTargetType(ProjectPart::BuildTargetType type)
+{
+ buildTargetType = type;
+}
+
} // namespace CppTools
diff --git a/src/plugins/cpptools/cpprawprojectpart.h b/src/plugins/cpptools/cpprawprojectpart.h
index 18f0591ec2..cc4a1ee878 100644
--- a/src/plugins/cpptools/cpprawprojectpart.h
+++ b/src/plugins/cpptools/cpprawprojectpart.h
@@ -67,7 +67,7 @@ public:
void setQtVersion(ProjectPart::QtVersion qtVersion);
- void setDefines(const QByteArray &defines);
+ void setMacros(const ProjectExplorer::Macros &macros);
void setHeaderPaths(const ProjectPartHeaderPaths &headerPaths);
void setIncludePaths(const QStringList &includePaths);
@@ -78,6 +78,7 @@ public:
void setFlagsForC(const RawProjectPartFlags &flags);
void setFlagsForCxx(const RawProjectPartFlags &flags);
+ void setBuildTargetType(ProjectPart::BuildTargetType type);
public:
QString displayName;
QString projectFile;
@@ -88,7 +89,7 @@ public:
QString buildSystemTarget;
QStringList precompiledHeaders;
ProjectPartHeaderPaths headerPaths;
- QByteArray projectDefines;
+ ProjectExplorer::Macros projectMacros;
ProjectPart::QtVersion qtVersion = ProjectPart::UnknownQt;
bool selectedForBuilding = true;
@@ -97,6 +98,7 @@ public:
QStringList files;
FileClassifier fileClassifier;
+ ProjectPart::BuildTargetType buildTargetType = ProjectPart::BuildTargetType::Unknown;
};
using RawProjectParts = QVector<RawProjectPart>;
diff --git a/src/plugins/cpptools/cpprefactoringengine.cpp b/src/plugins/cpptools/cpprefactoringengine.cpp
new file mode 100644
index 0000000000..705a8ecc99
--- /dev/null
+++ b/src/plugins/cpptools/cpprefactoringengine.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "cpprefactoringengine.h"
+#include "texteditor/texteditor.h"
+
+#include "utils/qtcassert.h"
+
+namespace CppTools {
+
+void CppRefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
+ CppTools::ProjectPart *,
+ RenameCallback &&renameSymbolsCallback)
+{
+ CppEditorWidgetInterface *editorWidget = data.editorWidget();
+ QTC_ASSERT(editorWidget, renameSymbolsCallback(QString(),
+ ClangBackEnd::SourceLocationsContainer(),
+ 0); return;);
+ editorWidget->updateSemanticInfo();
+ // Call empty callback
+ renameSymbolsCallback(QString(),
+ ClangBackEnd::SourceLocationsContainer(),
+ data.cursor().document()->revision());
+}
+
+void CppRefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &data)
+{
+ CppEditorWidgetInterface *editorWidget = data.editorWidget();
+ QTC_ASSERT(editorWidget, return;);
+ editorWidget->renameUsages();
+}
+
+} // namespace CppEditor
diff --git a/src/plugins/cpptools/cpprefactoringengine.h b/src/plugins/cpptools/cpprefactoringengine.h
new file mode 100644
index 0000000000..acbf02e5e6
--- /dev/null
+++ b/src/plugins/cpptools/cpprefactoringengine.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "refactoringengineinterface.h"
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT CppRefactoringEngine : public RefactoringEngineInterface
+{
+public:
+ void startLocalRenaming(const CppTools::CursorInEditor &data,
+ CppTools::ProjectPart *projectPart,
+ RenameCallback &&renameSymbolsCallback) override;
+ void startGlobalRenaming(const CppTools::CursorInEditor &data) override;
+
+ bool isUsable() const override { return true; }
+};
+
+} // namespace CppEditor
diff --git a/src/plugins/cpptools/cppselectionchanger.cpp b/src/plugins/cpptools/cppselectionchanger.cpp
index cee56aa21f..5ac29f97ca 100644
--- a/src/plugins/cpptools/cppselectionchanger.cpp
+++ b/src/plugins/cpptools/cppselectionchanger.cpp
@@ -25,7 +25,7 @@
#include "cppselectionchanger.h"
-#include <texteditor/convenience.h>
+#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <QDebug>
@@ -34,7 +34,7 @@
#include <QTextDocument>
using namespace CPlusPlus;
-using namespace TextEditor::Convenience;
+using namespace Utils::Text;
enum {
debug = false
diff --git a/src/plugins/cpptools/cppsourceprocessor.cpp b/src/plugins/cpptools/cppsourceprocessor.cpp
index fc28a6135e..507e33c90b 100644
--- a/src/plugins/cpptools/cppsourceprocessor.cpp
+++ b/src/plugins/cpptools/cppsourceprocessor.cpp
@@ -62,11 +62,12 @@ static Q_LOGGING_CATEGORY(log, "qtc.cpptools.sourceprocessor")
namespace {
-inline QByteArray generateFingerPrint(const QList<Macro> &definedMacros, const QByteArray &code)
+inline QByteArray generateFingerPrint(const QList<CPlusPlus::Macro> &definedMacros,
+ const QByteArray &code)
{
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData(code);
- foreach (const Macro &macro, definedMacros) {
+ foreach (const CPlusPlus::Macro &macro, definedMacros) {
if (macro.isHidden()) {
static const QByteArray undef("#undef ");
hash.addData(undef);
@@ -98,10 +99,10 @@ inline Message messageNoFileContents(Document::Ptr &document, const QString &fil
return Message(Message::Warning, document->fileName(), line, /*column =*/ 0, text);
}
-inline const Macro revision(const WorkingCopy &workingCopy,
- const Macro &macro)
+inline const CPlusPlus::Macro revision(const WorkingCopy &workingCopy,
+ const CPlusPlus::Macro &macro)
{
- Macro newMacro(macro);
+ CPlusPlus::Macro newMacro(macro);
newMacro.setFileRevision(workingCopy.get(macro.fileName()).second);
return newMacro;
}
@@ -316,7 +317,7 @@ QString CppSourceProcessor::resolveFile_helper(const QString &fileName,
return QString();
}
-void CppSourceProcessor::macroAdded(const Macro &macro)
+void CppSourceProcessor::macroAdded(const CPlusPlus::Macro &macro)
{
if (!m_currentDoc)
return;
@@ -325,7 +326,7 @@ void CppSourceProcessor::macroAdded(const Macro &macro)
}
void CppSourceProcessor::passedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charsOffset,
- unsigned line, const Macro &macro)
+ unsigned line, const CPlusPlus::Macro &macro)
{
if (!m_currentDoc)
return;
@@ -347,7 +348,7 @@ void CppSourceProcessor::failedMacroDefinitionCheck(unsigned bytesOffset, unsign
}
void CppSourceProcessor::notifyMacroReference(unsigned bytesOffset, unsigned utf16charOffset,
- unsigned line, const Macro &macro)
+ unsigned line, const CPlusPlus::Macro &macro)
{
if (!m_currentDoc)
return;
@@ -359,7 +360,7 @@ void CppSourceProcessor::notifyMacroReference(unsigned bytesOffset, unsigned utf
}
void CppSourceProcessor::startExpandingMacro(unsigned bytesOffset, unsigned utf16charOffset,
- unsigned line, const Macro &macro,
+ unsigned line, const CPlusPlus::Macro &macro,
const QVector<MacroArgumentReference> &actuals)
{
if (!m_currentDoc)
@@ -371,7 +372,7 @@ void CppSourceProcessor::startExpandingMacro(unsigned bytesOffset, unsigned utf1
line, actuals);
}
-void CppSourceProcessor::stopExpandingMacro(unsigned, const Macro &)
+void CppSourceProcessor::stopExpandingMacro(unsigned, const CPlusPlus::Macro &)
{
if (!m_currentDoc)
return;
diff --git a/src/plugins/cpptools/cppsymbolinfo.h b/src/plugins/cpptools/cppsymbolinfo.h
new file mode 100644
index 0000000000..dcd00dd3c2
--- /dev/null
+++ b/src/plugins/cpptools/cppsymbolinfo.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "cpptools_global.h"
+
+#include <QString>
+
+namespace CppTools {
+
+class CPPTOOLS_EXPORT SymbolInfo
+{
+public:
+ int startLine = 0;
+ int startColumn = 0;
+ int endLine = 0;
+ int endColumn = 0;
+ QString fileName;
+};
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index 8381a3fdfa..c9ca4e4c18 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -29,11 +29,13 @@ HEADERS += \
cppcompletionassistprovider.h \
cppcursorinfo.h \
cppcurrentdocumentfilter.h \
- cppeditoroutline.h \
cppdoxygen.h \
+ cppeditoroutline.h \
+ cppeditorwidgetinterface.h \
cppfileiterationorder.h \
cppfilesettingspage.h \
cppfindreferences.h \
+ cppfollowsymbolundercursor.h \
cppfunctionsfilter.h \
cppincludesfilter.h \
cppindexingsupport.h \
@@ -49,6 +51,7 @@ HEADERS += \
cppqtstyleindenter.h \
cpprawprojectpart.h \
cpprefactoringchanges.h \
+ cpprefactoringengine.h \
cppselectionchanger.h \
cppsemanticinfo.h \
cppsemanticinfoupdater.h \
@@ -60,9 +63,12 @@ HEADERS += \
cpptoolsplugin.h \
cpptoolsreuse.h \
cpptoolssettings.h \
+ cppvirtualfunctionassistprovider.h \
+ cppvirtualfunctionproposalitem.h \
cppworkingcopy.h \
doxygengenerator.h \
editordocumenthandle.h \
+ followsymbolinterface.h \
functionutils.h \
generatedcodemodelsupport.h \
includeutils.h \
@@ -87,6 +93,9 @@ HEADERS += \
cppprojectfilecategorizer.h \
clangcompileroptionsbuilder.h \
cppprojectpartchooser.h \
+ cppsymbolinfo.h \
+ cursorineditor.h \
+ wrappablelineedit.h \
SOURCES += \
abstracteditorsupport.cpp \
@@ -119,6 +128,7 @@ SOURCES += \
cppfileiterationorder.cpp \
cppfilesettingspage.cpp \
cppfindreferences.cpp \
+ cppfollowsymbolundercursor.cpp \
cppfunctionsfilter.cpp \
cppincludesfilter.cpp \
cppindexingsupport.cpp \
@@ -134,6 +144,7 @@ SOURCES += \
cppqtstyleindenter.cpp \
cpprawprojectpart.cpp \
cpprefactoringchanges.cpp \
+ cpprefactoringengine.cpp \
cppselectionchanger.cpp \
cppsemanticinfoupdater.cpp \
cppsourceprocessor.cpp \
@@ -141,6 +152,8 @@ SOURCES += \
cpptoolsplugin.cpp \
cpptoolsreuse.cpp \
cpptoolssettings.cpp \
+ cppvirtualfunctionassistprovider.cpp \
+ cppvirtualfunctionproposalitem.cpp \
cppworkingcopy.cpp \
doxygengenerator.cpp \
editordocumenthandle.cpp \
@@ -165,6 +178,7 @@ SOURCES += \
cppprojectfilecategorizer.cpp \
clangcompileroptionsbuilder.cpp \
cppprojectpartchooser.cpp \
+ wrappablelineedit.cpp \
FORMS += \
clangdiagnosticconfigswidget.ui \
diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs
index 2fcda3ae10..cad4da41a5 100644
--- a/src/plugins/cpptools/cpptools.qbs
+++ b/src/plugins/cpptools/cpptools.qbs
@@ -90,6 +90,7 @@ Project {
"cppdoxygen.h",
"cppeditoroutline.cpp",
"cppeditoroutline.h",
+ "cppeditorwidgetinterface.h",
"cppfileiterationorder.cpp",
"cppfileiterationorder.h",
"cppfilesettingspage.cpp",
@@ -97,6 +98,8 @@ Project {
"cppfilesettingspage.ui",
"cppfindreferences.cpp",
"cppfindreferences.h",
+ "cppfollowsymbolundercursor.cpp",
+ "cppfollowsymbolundercursor.h",
"cppfunctionsfilter.cpp",
"cppfunctionsfilter.h",
"cppincludesfilter.cpp",
@@ -133,6 +136,8 @@ Project {
"cpprawprojectpart.h",
"cpprefactoringchanges.cpp",
"cpprefactoringchanges.h",
+ "cpprefactoringengine.cpp",
+ "cpprefactoringengine.h",
"cppselectionchanger.cpp",
"cppselectionchanger.h",
"cppsemanticinfo.h",
@@ -157,12 +162,18 @@ Project {
"cpptoolsreuse.h",
"cpptoolssettings.cpp",
"cpptoolssettings.h",
+ "cppvirtualfunctionassistprovider.cpp",
+ "cppvirtualfunctionassistprovider.h",
+ "cppvirtualfunctionproposalitem.cpp",
+ "cppvirtualfunctionproposalitem.h",
"cppworkingcopy.cpp",
"cppworkingcopy.h",
+ "cursorineditor.h",
"doxygengenerator.cpp",
"doxygengenerator.h",
"editordocumenthandle.cpp",
"editordocumenthandle.h",
+ "followsymbolinterface.h",
"functionutils.cpp",
"functionutils.h",
"generatedcodemodelsupport.cpp",
@@ -173,6 +184,8 @@ Project {
"indexitem.h",
"insertionpointlocator.cpp",
"insertionpointlocator.h",
+ "wrappablelineedit.cpp",
+ "wrappablelineedit.h",
"projectinfo.cpp",
"projectinfo.h",
"projectpart.cpp",
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index e8fe2145f2..af192cb082 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -205,10 +205,10 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
Utils::MacroExpander *expander = Utils::globalMacroExpander();
expander->registerVariable("Cpp:LicenseTemplate",
tr("The license template."),
- [this]() { return CppToolsPlugin::licenseTemplate(); });
+ []() { return CppToolsPlugin::licenseTemplate(); });
expander->registerFileVariables("Cpp:LicenseTemplatePath",
tr("The configured path to the license template"),
- [this]() { return CppToolsPlugin::licenseTemplatePath().toString(); });
+ []() { return CppToolsPlugin::licenseTemplatePath().toString(); });
return true;
}
@@ -357,7 +357,8 @@ static int commonFilePathLength(const QString &s1, const QString &s2)
static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
const QStringList &candidateFileNames,
- const ProjectExplorer::Project *project)
+ const ProjectExplorer::Project *project,
+ CacheUsage cacheUsage)
{
QString bestFileName;
int compareValue = 0;
@@ -376,8 +377,10 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
if (!bestFileName.isEmpty()) {
const QFileInfo candidateFi(bestFileName);
QTC_ASSERT(candidateFi.isFile(), return QString());
- m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath();
- m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath();
+ if (cacheUsage == CacheUsage::ReadWrite) {
+ m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath();
+ m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath();
+ }
return candidateFi.absoluteFilePath();
}
@@ -386,7 +389,7 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
} // namespace Internal
-QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
+QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, CacheUsage cacheUsage)
{
using namespace Internal;
@@ -437,9 +440,11 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath);
const QFileInfo candidateFi(normalized);
if (candidateFi.isFile()) {
- m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
- if (!isHeader || !baseName.endsWith(privateHeaderSuffix))
- m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
+ if (cacheUsage == CacheUsage::ReadWrite) {
+ m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
+ if (!isHeader || !baseName.endsWith(privateHeaderSuffix))
+ m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
+ }
return candidateFi.absoluteFilePath();
}
}
@@ -449,7 +454,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject();
if (currentProject) {
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
- currentProject);
+ currentProject, cacheUsage);
if (!path.isEmpty())
return path;
@@ -462,7 +467,8 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
if (project == currentProject)
continue; // We have already checked the current project.
- const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames, project);
+ const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
+ project, cacheUsage);
if (!path.isEmpty())
return path;
}
diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp
index fcb3c8b878..bd011c0c05 100644
--- a/src/plugins/cpptools/cpptoolsreuse.cpp
+++ b/src/plugins/cpptools/cpptoolsreuse.cpp
@@ -32,11 +32,11 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/idocument.h>
#include <coreplugin/messagemanager.h>
-#include <texteditor/convenience.h>
#include <cplusplus/Overview.h>
#include <cplusplus/LookupContext.h>
#include <utils/algorithm.h>
+#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <QDebug>
@@ -216,7 +216,7 @@ const Macro *findCanonicalMacro(const QTextCursor &cursor, Document::Ptr documen
QTC_ASSERT(document, return 0);
int line, column;
- TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &line, &column);
+ Utils::Text::convertPosition(cursor.document(), cursor.position(), &line, &column);
if (const Macro *macro = document->findMacroDefinitionAt(line)) {
QTextCursor macroCursor = cursor;
diff --git a/src/plugins/cpptools/cpptoolsreuse.h b/src/plugins/cpptools/cpptoolsreuse.h
index 46ef50d7b1..89183bb0b8 100644
--- a/src/plugins/cpptools/cpptoolsreuse.h
+++ b/src/plugins/cpptools/cpptoolsreuse.h
@@ -68,7 +68,10 @@ bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,
const CPlusPlus::Macro CPPTOOLS_EXPORT *findCanonicalMacro(const QTextCursor &cursor,
CPlusPlus::Document::Ptr document);
-QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0);
+enum class CacheUsage { ReadWrite, ReadOnly };
+
+QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0,
+ CacheUsage cacheUsage = CacheUsage::ReadWrite);
void CPPTOOLS_EXPORT switchHeaderSource();
class CppCodeModelSettings;
diff --git a/src/plugins/cpptools/cpptoolsunittestfiles.pri b/src/plugins/cpptools/cpptoolsunittestfiles.pri
index 6960ccbde9..48c70fce6e 100644
--- a/src/plugins/cpptools/cpptoolsunittestfiles.pri
+++ b/src/plugins/cpptools/cpptoolsunittestfiles.pri
@@ -1,11 +1,7 @@
-# Currently there are no tests for the project explorer plugin, but we include
-# headers from it that needs to have the export/import adapted for Windows.
shared {
DEFINES += CPPTOOLS_LIBRARY
- DEFINES += PROJECTEXPLORER_LIBRARY
} else {
DEFINES += CPPTOOLS_STATIC_LIBRARY
- DEFINES += PROJECTEXPLORER_STATIC_LIBRARY
}
HEADERS += \
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cpptools/cppvirtualfunctionassistprovider.cpp
index 74444e0e79..5711eb912c 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
+++ b/src/plugins/cpptools/cppvirtualfunctionassistprovider.cpp
@@ -24,21 +24,19 @@
****************************************************************************/
#include "cppvirtualfunctionassistprovider.h"
-
-#include "cppeditorconstants.h"
#include "cppvirtualfunctionproposalitem.h"
+#include "cpptoolsreuse.h"
+#include "functionutils.h"
+#include "symbolfinder.h"
+#include "typehierarchybuilder.h"
+
#include <cplusplus/Icons.h>
#include <cplusplus/Overview.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
-#include <cpptools/cpptoolsreuse.h>
-#include <cpptools/functionutils.h>
-#include <cpptools/symbolfinder.h>
-#include <cpptools/typehierarchybuilder.h>
-
#include <texteditor/codeassist/genericproposalmodel.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/genericproposalwidget.h>
@@ -50,10 +48,10 @@
#include <utils/qtcassert.h>
using namespace CPlusPlus;
-using namespace CppEditor::Internal;
-using namespace CppTools;
using namespace TextEditor;
+namespace CppTools {
+
/// Activate current item with the same shortcut that is configured for Follow Symbol Under Cursor.
/// This is limited to single-key shortcuts without modifiers.
class VirtualFunctionProposalWidget : public GenericProposalWidget
@@ -106,9 +104,9 @@ public:
bool openInSplit)
: GenericProposal(cursorPos, items)
, m_openInSplit(openInSplit)
- {}
-
- bool isFragile() const override { return true; }
+ {
+ setFragile(true);
+ }
IAssistProposalWidget *createWidget() const override
{ return new VirtualFunctionProposalWidget(m_openInSplit); }
@@ -211,3 +209,5 @@ IAssistProcessor *VirtualFunctionAssistProvider::createProcessor() const
{
return new VirtualFunctionAssistProcessor(m_params);
}
+
+} // namespace CppTools
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cpptools/cppvirtualfunctionassistprovider.h
index 363981b7ca..08ff2018d4 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h
+++ b/src/plugins/cpptools/cppvirtualfunctionassistprovider.h
@@ -25,6 +25,8 @@
#pragma once
+#include "cpptools_global.h"
+
#include <texteditor/codeassist/iassistprovider.h>
#include <cplusplus/CppDocument.h>
@@ -34,10 +36,9 @@
#include <QSharedPointer>
#include <QTextCursor>
-namespace CppEditor {
-namespace Internal {
+namespace CppTools {
-class VirtualFunctionAssistProvider : public TextEditor::IAssistProvider
+class CPPTOOLS_EXPORT VirtualFunctionAssistProvider : public TextEditor::IAssistProvider
{
public:
VirtualFunctionAssistProvider();
@@ -64,5 +65,4 @@ private:
Parameters m_params;
};
-} // namespace Internal
-} // namespace CppEditor
+} // namespace CppTools
diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp b/src/plugins/cpptools/cppvirtualfunctionproposalitem.cpp
index 44bd8d01cf..474aecac46 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.cpp
+++ b/src/plugins/cpptools/cppvirtualfunctionproposalitem.cpp
@@ -25,11 +25,11 @@
#include "cppvirtualfunctionproposalitem.h"
-#include "cppeditorconstants.h"
+#include <cppeditor/cppeditorconstants.h>
#include <coreplugin/editormanager/editormanager.h>
-using namespace CppEditor::Internal;
+namespace CppTools {
VirtualFunctionProposalItem::VirtualFunctionProposalItem(
const TextEditor::TextEditorWidget::Link &link, bool openInSplit)
@@ -52,3 +52,5 @@ void VirtualFunctionProposalItem::apply(TextEditor::TextDocumentManipulatorInter
CppEditor::Constants::CPPEDITOR_ID,
flags);
}
+
+} // namespace CppTools
diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h b/src/plugins/cpptools/cppvirtualfunctionproposalitem.h
index 5d86d4b390..19bb7715ea 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h
+++ b/src/plugins/cpptools/cppvirtualfunctionproposalitem.h
@@ -25,13 +25,14 @@
#pragma once
+#include "cpptools_global.h"
+
#include <texteditor/texteditor.h>
#include <texteditor/codeassist/assistproposalitem.h>
-namespace CppEditor {
-namespace Internal {
+namespace CppTools {
-class VirtualFunctionProposalItem final : public TextEditor::AssistProposalItem
+class CPPTOOLS_EXPORT VirtualFunctionProposalItem final : public TextEditor::AssistProposalItem
{
public:
VirtualFunctionProposalItem(const TextEditor::TextEditorWidget::Link &link,
@@ -46,5 +47,4 @@ private:
bool m_openInSplit;
};
-} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cpptools/cursorineditor.h b/src/plugins/cpptools/cursorineditor.h
new file mode 100644
index 0000000000..18097e5dbd
--- /dev/null
+++ b/src/plugins/cpptools/cursorineditor.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "cppeditorwidgetinterface.h"
+
+#include <utils/fileutils.h>
+
+#include <QTextCursor>
+
+namespace CppTools {
+
+class CursorInEditor
+{
+public:
+ CursorInEditor(const QTextCursor &cursor, const Utils::FileName &filePath,
+ CppEditorWidgetInterface *editorWidget = nullptr)
+ : m_cursor(cursor)
+ , m_filePath(filePath)
+ , m_editorWidget(editorWidget)
+ {}
+ CppEditorWidgetInterface *editorWidget() const { return m_editorWidget; }
+ const QTextCursor &cursor() const { return m_cursor; }
+ const Utils::FileName &filePath() const { return m_filePath; }
+private:
+ QTextCursor m_cursor;
+ Utils::FileName m_filePath;
+ CppEditorWidgetInterface *m_editorWidget = nullptr;
+};
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/doxygengenerator.cpp b/src/plugins/cpptools/doxygengenerator.cpp
index e94ce3468e..39e2e25275 100644
--- a/src/plugins/cpptools/doxygengenerator.cpp
+++ b/src/plugins/cpptools/doxygengenerator.cpp
@@ -25,11 +25,10 @@
#include "doxygengenerator.h"
-#include <texteditor/convenience.h>
-
#include <cplusplus/CppDocument.h>
#include <cplusplus/SimpleLexer.h>
+#include <utils/textutils.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
@@ -73,10 +72,8 @@ void DoxygenGenerator::setAddLeadingAsterisks(bool add)
static int lineBeforeCursor(const QTextCursor &cursor)
{
int line, column;
- const bool converted = TextEditor::Convenience::convertPosition(cursor.document(),
- cursor.position(),
- &line,
- &column);
+ const bool converted = Utils::Text::convertPosition(cursor.document(), cursor.position(), &line,
+ &column);
QTC_ASSERT(converted, return std::numeric_limits<int>::max());
return line - 1;
diff --git a/src/plugins/cpptools/followsymbolinterface.h b/src/plugins/cpptools/followsymbolinterface.h
new file mode 100644
index 0000000000..1d662ae65a
--- /dev/null
+++ b/src/plugins/cpptools/followsymbolinterface.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "cpptools_global.h"
+#include "cursorineditor.h"
+
+#include <cplusplus/CppDocument.h>
+
+#include <texteditor/texteditor.h>
+
+namespace CppTools {
+
+class SymbolFinder;
+
+class CPPTOOLS_EXPORT FollowSymbolInterface
+{
+public:
+ using Link = TextEditor::TextEditorWidget::Link;
+
+ virtual ~FollowSymbolInterface() {}
+ virtual Link findLink(const CursorInEditor &data,
+ bool resolveTarget,
+ const CPlusPlus::Snapshot &snapshot,
+ const CPlusPlus::Document::Ptr &documentFromSemanticInfo,
+ SymbolFinder *symbolFinder,
+ bool inNextSplit) = 0;
+};
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/projectinfo.cpp b/src/plugins/cpptools/projectinfo.cpp
index 1ca95e3e9c..e0dbee363f 100644
--- a/src/plugins/cpptools/projectinfo.cpp
+++ b/src/plugins/cpptools/projectinfo.cpp
@@ -160,13 +160,10 @@ void ProjectInfo::finish()
m_sourceFiles.insert(file.path);
// Update defines
- m_defines.append(part->toolchainDefines);
- m_defines.append(part->projectDefines);
- if (!part->projectConfigFile.isEmpty()) {
- m_defines.append('\n');
- m_defines += ProjectPart::readProjectConfigFile(part);
- m_defines.append('\n');
- }
+ m_defines.append(part->toolChainMacros);
+ m_defines.append(part->projectMacros);
+ if (!part->projectConfigFile.isEmpty())
+ m_defines += ProjectExplorer::Macro::toMacros(ProjectPart::readProjectConfigFile(part));
}
}
diff --git a/src/plugins/cpptools/projectinfo.h b/src/plugins/cpptools/projectinfo.h
index 9096322989..ee016f5b3e 100644
--- a/src/plugins/cpptools/projectinfo.h
+++ b/src/plugins/cpptools/projectinfo.h
@@ -123,7 +123,7 @@ private:
// The members below are (re)calculated from the project parts with finish()
ProjectPartHeaderPaths m_headerPaths;
QSet<QString> m_sourceFiles;
- QByteArray m_defines;
+ ProjectExplorer::Macros m_defines;
};
} // namespace CppTools
diff --git a/src/plugins/cpptools/projectpart.cpp b/src/plugins/cpptools/projectpart.cpp
index 6a87adf93f..e77e079c80 100644
--- a/src/plugins/cpptools/projectpart.cpp
+++ b/src/plugins/cpptools/projectpart.cpp
@@ -25,6 +25,8 @@
#include "projectpart.h"
+#include <utils/algorithm.h>
+
#include <QFile>
#include <QDir>
#include <QTextStream>
@@ -43,16 +45,9 @@ void ProjectPart::updateLanguageFeatures()
if (!hasQt) {
languageFeatures.qtKeywordsEnabled = false;
} else {
- const QByteArray noKeywordsMacro = "#define QT_NO_KEYWORDS";
- const int noKeywordsIndex = projectDefines.indexOf(noKeywordsMacro);
- if (noKeywordsIndex == -1) {
- languageFeatures.qtKeywordsEnabled = true;
- } else {
- const char nextChar = projectDefines.at(noKeywordsIndex + noKeywordsMacro.length());
- // Detect "#define QT_NO_KEYWORDS" and "#define QT_NO_KEYWORDS 1", but exclude
- // "#define QT_NO_KEYWORDS_FOO"
- languageFeatures.qtKeywordsEnabled = nextChar != '\n' && nextChar != ' ';
- }
+ languageFeatures.qtKeywordsEnabled = !Utils::contains(
+ projectMacros,
+ [] (const ProjectExplorer::Macro &macro) { return macro.key == "QT_NO_KEYWORDS"; });
}
}
diff --git a/src/plugins/cpptools/projectpart.h b/src/plugins/cpptools/projectpart.h
index c04a18c61f..51b620f0c3 100644
--- a/src/plugins/cpptools/projectpart.h
+++ b/src/plugins/cpptools/projectpart.h
@@ -31,6 +31,7 @@
#include "projectpartheaderpath.h"
#include <projectexplorer/projectexplorer_global.h>
+#include <projectexplorer/projectmacro.h>
#include <coreplugin/id.h>
@@ -90,6 +91,12 @@ public:
WordWidth64Bit,
};
+ enum BuildTargetType {
+ Unknown,
+ Executable,
+ Library
+ };
+
using Ptr = QSharedPointer<ProjectPart>;
public:
@@ -118,7 +125,7 @@ public:
QStringList precompiledHeaders;
ProjectPartHeaderPaths headerPaths;
- QByteArray projectDefines;
+ ProjectExplorer::Macros projectMacros;
LanguageVersion languageVersion = LatestCxxVersion;
LanguageExtensions languageExtensions = NoExtensions;
@@ -130,9 +137,10 @@ public:
Core::Id toolchainType;
bool isMsvc2015Toolchain = false;
- QByteArray toolchainDefines;
+ ProjectExplorer::Macros toolChainMacros;
ToolChainWordWidth toolChainWordWidth = WordWidth32Bit;
QString toolChainTargetTriple;
+ BuildTargetType buildTargetType = Unknown;
};
} // namespace CppTools
diff --git a/src/plugins/cpptools/refactoringengineinterface.h b/src/plugins/cpptools/refactoringengineinterface.h
index 2076a379d8..afb6025c03 100644
--- a/src/plugins/cpptools/refactoringengineinterface.h
+++ b/src/plugins/cpptools/refactoringengineinterface.h
@@ -25,18 +25,20 @@
#pragma once
+#include "cpptools_global.h"
+#include "cursorineditor.h"
+
#include <utils/fileutils.h>
-#include <clangbackendipc/sourcelocationscontainer.h>
-#include <clangbackendipc/refactoringclientinterface.h>
+#include <clangsupport/sourcelocationscontainer.h>
+#include <clangsupport/refactoringclientinterface.h>
-QT_BEGIN_NAMESPACE
-class QTextCursor;
-QT_END_NAMESPACE
+namespace TextEditor {
+class TextEditorWidget;
+} // namespace TextEditor
namespace CppTools {
-class CppEditorWidget;
class ProjectPart;
enum class CallType
@@ -45,19 +47,18 @@ enum class CallType
Asynchronous
};
-class RefactoringEngineInterface
+// NOTE: This interface is not supposed to be owned as an interface pointer
+class CPPTOOLS_EXPORT RefactoringEngineInterface
{
public:
using RenameCallback = ClangBackEnd::RefactoringClientInterface::RenameCallback;
- virtual void startLocalRenaming(const QTextCursor &textCursor,
- const Utils::FileName &filePath,
- int revision,
+ virtual void startLocalRenaming(const CursorInEditor &data,
CppTools::ProjectPart *projectPart,
RenameCallback &&renameSymbolsCallback) = 0;
+ virtual void startGlobalRenaming(const CursorInEditor &data) = 0;
virtual bool isUsable() const = 0;
-
};
} // namespace CppTools
diff --git a/src/plugins/cpptools/wrappablelineedit.cpp b/src/plugins/cpptools/wrappablelineedit.cpp
new file mode 100644
index 0000000000..786486a23f
--- /dev/null
+++ b/src/plugins/cpptools/wrappablelineedit.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "wrappablelineedit.h"
+
+#include <QMimeData>
+
+namespace CppTools {
+
+WrappableLineEdit::WrappableLineEdit(QWidget *parent)
+ : QPlainTextEdit(parent)
+{
+ setMaximumBlockCount(1); // Restrict to a single line.
+}
+
+void WrappableLineEdit::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ return; // Eat these to avoid new lines.
+ case Qt::Key_Backtab:
+ case Qt::Key_Tab:
+ // Let the parent handle these because they might be used for navigation purposes.
+ event->ignore();
+ return;
+ default:
+ return QPlainTextEdit::keyPressEvent(event);
+ }
+}
+
+void WrappableLineEdit::insertFromMimeData(const QMimeData *source)
+{
+ insertPlainText(source->text().simplified()); // Filter out new lines.
+}
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/wrappablelineedit.h b/src/plugins/cpptools/wrappablelineedit.h
new file mode 100644
index 0000000000..411a2d49a9
--- /dev/null
+++ b/src/plugins/cpptools/wrappablelineedit.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QPlainTextEdit>
+
+namespace CppTools {
+
+class WrappableLineEdit : public QPlainTextEdit
+{
+ Q_OBJECT
+
+public:
+ explicit WrappableLineEdit(QWidget *parent = nullptr);
+
+protected:
+ void keyPressEvent(QKeyEvent *event) override;
+ void insertFromMimeData(const QMimeData *source) override;
+};
+
+} // namespace CppTools
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 9360051f2b..e312cda639 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -198,7 +198,7 @@ bool CvsPlugin::initialize(const QStringList &arguments, QString *errorMessage)
Context context(CVS_CONTEXT);
- initializeVcs(new CvsControl(this), context);
+ initializeVcs<CvsControl>(context, this);
m_cvsPluginInstance = this;
@@ -651,6 +651,9 @@ void CvsPlugin::startCommitAll()
* commit will start. */
void CvsPlugin::startCommit(const QString &workingDir, const QString &file)
{
+ if (!promptBeforeCommit())
+ return;
+
if (raiseSubmitEditor())
return;
if (isCommitEditorOpen()) {
diff --git a/src/plugins/cvs/cvssettings.cpp b/src/plugins/cvs/cvssettings.cpp
index 10fb8c51e7..12a46bba26 100644
--- a/src/plugins/cvs/cvssettings.cpp
+++ b/src/plugins/cvs/cvssettings.cpp
@@ -44,7 +44,7 @@ CvsSettings::CvsSettings()
{
setSettingsGroup(QLatin1String("CVS"));
declareKey(binaryPathKey, QLatin1String("cvs" QTC_HOST_EXE_SUFFIX));
- declareKey(cvsRootKey, QLatin1String(""));
+ declareKey(cvsRootKey, QString());
declareKey(diffOptionsKey, QLatin1String("-du"));
declareKey(describeByCommitIdKey, true);
declareKey(diffIgnoreWhiteSpaceKey, false);
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index ab80f73c16..df579b8a60 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -2012,7 +2012,7 @@ bool BreakHandler::contextMenuEvent(const ItemViewEvent &ev)
addAction(menu, tr("Synchronize Breakpoints"),
Internal::hasSnapshots(),
- [this] { Internal::synchronizeBreakpoints(); });
+ [] { Internal::synchronizeBreakpoints(); });
menu->addSeparator();
menu->addAction(action(UseToolTipsInBreakpointsView));
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index b8f240e5d8..c903e34e44 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -180,7 +180,7 @@ namespace Internal {
static inline bool isCreatorConsole(const DebuggerRunParameters &sp)
{
- return !boolSetting(UseCdbConsole) && sp.useTerminal
+ return !boolSetting(UseCdbConsole) && sp.inferior.runMode == ApplicationLauncher::Console
&& (sp.startMode == StartInternal || sp.startMode == StartExternal);
}
@@ -194,22 +194,10 @@ public:
CdbEngine::CommandHandler handler;
};
-static inline bool validMode(DebuggerStartMode sm)
+// Accessed by DebuggerRunTool
+DebuggerEngine *createCdbEngine()
{
- return sm != NoStartMode;
-}
-
-// Accessed by RunControlFactory
-DebuggerEngine *createCdbEngine(QStringList *errors, DebuggerStartMode sm)
-{
- if (HostOsInfo::isWindowsHost()) {
- if (validMode(sm))
- return new CdbEngine();
- errors->append(CdbEngine::tr("Internal error: Invalid start parameters passed for the CDB engine."));
- } else {
- errors->append(CdbEngine::tr("Unsupported CDB host system."));
- }
- return 0;
+ return new CdbEngine;
}
void addCdbOptionPages(QList<Core::IOptionsPage *> *opts)
@@ -428,7 +416,7 @@ void CdbEngine::consoleStubProcessStarted()
attachParameters.inferior.commandLineArguments.clear();
attachParameters.attachPID = ProcessHandle(m_consoleStub->applicationPID());
attachParameters.startMode = AttachExternal;
- attachParameters.useTerminal = false;
+ attachParameters.inferior.runMode = ApplicationLauncher::Gui; // Force no terminal.
showMessage(QString("Attaching to %1...").arg(attachParameters.attachPID.pid()), LogMisc);
QString errorMessage;
if (!launchCDB(attachParameters, &errorMessage)) {
@@ -445,7 +433,7 @@ void CdbEngine::consoleStubExited()
void CdbEngine::createFullBacktrace()
{
- runCommand({"~*kp", BuiltinCommand, [this](const DebuggerResponse &response) {
+ runCommand({"~*kp", BuiltinCommand, [](const DebuggerResponse &response) {
Internal::openTextEditor("Backtrace $", response.data.data());
}});
}
@@ -455,9 +443,6 @@ void CdbEngine::setupEngine()
if (debug)
qDebug(">setupEngine");
- if (!prepareCommand())
- return;
-
init();
if (!m_logTime.elapsed())
m_logTime.start();
@@ -545,7 +530,7 @@ bool CdbEngine::launchCDB(const DebuggerRunParameters &sp, QString *errorMessage
// register idle (debuggee stop) notification
<< "-c"
<< ".idle_cmd " + m_extensionCommandPrefix + "idle";
- if (sp.useTerminal) // Separate console
+ if (sp.inferior.runMode == ApplicationLauncher::Console) // Separate console
arguments << "-2";
if (boolSetting(IgnoreFirstChanceAccessViolation))
arguments << "-x";
@@ -613,7 +598,8 @@ bool CdbEngine::launchCDB(const DebuggerRunParameters &sp, QString *errorMessage
// Make sure that QTestLib uses OutputDebugString for logging.
const QString qtLoggingToConsoleKey = QStringLiteral("QT_LOGGING_TO_CONSOLE");
- if (!sp.useTerminal && !inferiorEnvironment.hasKey(qtLoggingToConsoleKey))
+ if (sp.inferior.runMode != ApplicationLauncher::Console
+ && !inferiorEnvironment.hasKey(qtLoggingToConsoleKey))
inferiorEnvironment.set(qtLoggingToConsoleKey, QString(QLatin1Char('0')));
m_process.setEnvironment(mergeEnvironment(inferiorEnvironment.toStringList(),
@@ -843,17 +829,9 @@ void CdbEngine::shutdownEngine()
}
}
-void CdbEngine::abortDebugger()
+void CdbEngine::abortDebuggerProcess()
{
- if (isDying()) {
- // We already tried. Try harder.
- showMessage("ABORTING DEBUGGER. SECOND TIME.");
- m_process.kill();
- } else {
- // Be friendly the first time. This will change targetState().
- showMessage("ABORTING DEBUGGER. FIRST TIME.");
- quitDebugger();
- }
+ m_process.kill();
}
void CdbEngine::processFinished()
@@ -1426,7 +1404,7 @@ void CdbEngine::postDisassemblerCommand(quint64 address, quint64 endAddress,
str << "u " << hex <<hexPrefixOn << address << ' ' << endAddress;
DebuggerCommand cmd;
cmd.function = ba;
- cmd.callback = [this, agent](const DebuggerResponse &response) {
+ cmd.callback = [agent](const DebuggerResponse &response) {
// Parse: "00000000`77606060 cc int 3"
agent->setContents(parseCdbDisassembler(response.data.data()));
};
@@ -2514,7 +2492,7 @@ void CdbEngine::parseOutputLine(QString line)
// output(32): ModLoad: 00007ffb 00007ffb C:\Windows\system32\KERNEL32.DLL
QRegExp moduleRegExp("[0-9a-fA-F]+(`[0-9a-fA-F]+)? [0-9a-fA-F]+(`[0-9a-fA-F]+)? (.*)");
if (moduleRegExp.indexIn(line) > -1)
- showStatusMessage(tr("Module loaded: ") + moduleRegExp.cap(3).trimmed(), 3000);
+ showStatusMessage(tr("Module loaded: %1").arg(moduleRegExp.cap(3).trimmed()), 3000);
} else {
showMessage(line, LogMisc);
}
diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h
index 30bccb4a11..7a80e48dba 100644
--- a/src/plugins/debugger/cdb/cdbengine.h
+++ b/src/plugins/debugger/cdb/cdbengine.h
@@ -70,7 +70,7 @@ public:
void runEngine() override;
void shutdownInferior() override;
void shutdownEngine() override;
- void abortDebugger() override;
+ void abortDebuggerProcess() override;
void detachDebugger() override;
bool hasCapability(unsigned cap) const override;
void watchPoint(const QPoint &) override;
diff --git a/src/plugins/debugger/cdb/cdboptionspagewidget.ui b/src/plugins/debugger/cdb/cdboptionspagewidget.ui
index 4b80ff1d26..38f434688c 100644
--- a/src/plugins/debugger/cdb/cdboptionspagewidget.ui
+++ b/src/plugins/debugger/cdb/cdboptionspagewidget.ui
@@ -44,7 +44,7 @@
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="consoleCheckBox">
<property name="toolTip">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Uses CDB's native console instead of Qt Creator's console for console applications. The native console does not prompt on application exit. It is suitable for diagnosing cases in which the application does not start up properly in Qt Creator's console and the subsequent attach fails.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Uses CDB's native console for console applications. This overrides the setting in Environment &gt; System. The native console does not prompt on application exit. It is suitable for diagnosing cases in which the application does not start up properly in the configured console and the subsequent attach fails.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use CDB &amp;console</string>
diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp
index 2f510a4184..7aeb3a7cb5 100644
--- a/src/plugins/debugger/commonoptionspage.cpp
+++ b/src/plugins/debugger/commonoptionspage.cpp
@@ -32,6 +32,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/variablechooser.h>
+#include <app/app_version.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
@@ -129,7 +130,9 @@ QWidget *CommonOptionsPage::widget()
checkBoxSwitchModeOnExit->setText(tr("Switch to previous mode on debugger exit"));
auto checkBoxBringToForegroundOnInterrrupt = new QCheckBox(behaviorBox);
- checkBoxBringToForegroundOnInterrrupt->setText(tr("Bring Qt Creator to foreground when application interrupts"));
+ checkBoxBringToForegroundOnInterrrupt->setText(
+ tr("Bring %1 to foreground when application interrupts")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
auto checkBoxShowQmlObjectTree = new QCheckBox(behaviorBox);
checkBoxShowQmlObjectTree->setToolTip(tr("Shows QML object tree in Locals and Expressions when connected and not stepping."));
@@ -140,8 +143,12 @@ QWidget *CommonOptionsPage::widget()
checkBoxBreakpointsFullPath->setText(tr("Set breakpoints using a full absolute path"));
auto checkBoxRegisterForPostMortem = new QCheckBox(behaviorBox);
- checkBoxRegisterForPostMortem->setToolTip(tr("Registers Qt Creator for debugging crashed applications."));
- checkBoxRegisterForPostMortem->setText(tr("Use Qt Creator for post-mortem debugging"));
+ checkBoxRegisterForPostMortem->setToolTip(
+ tr("Registers %1 for debugging crashed applications.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
+ checkBoxRegisterForPostMortem->setText(
+ tr("Use %1 for post-mortem debugging")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
auto checkBoxWarnOnReleaseBuilds = new QCheckBox(behaviorBox);
checkBoxWarnOnReleaseBuilds->setText(tr("Warn when debugging \"Release\" builds"));
@@ -308,13 +315,13 @@ QWidget *LocalsAndExpressionsOptionsPage::widget()
label->setText(QLatin1String("<html><head/><body>\n<p>")
+ tr("The debugging helpers are used to produce a nice "
"display of objects of certain types like QString or "
- "std::map in the &quot;Locals and Expressions&quot; view. ")
+ "std::map in the &quot;Locals and Expressions&quot; view.")
+ QLatin1String("</p></body></html>"));
auto groupBoxCustomDumperCommands = new QGroupBox(debuggingHelperGroupBox);
groupBoxCustomDumperCommands->setTitle(tr("Debugging Helper Customization"));
groupBoxCustomDumperCommands->setToolTip(tr(
- "<html><head/><body><p>Python commands entered here will be executed after Qt Creator's "
+ "<html><head/><body><p>Python commands entered here will be executed after built-in "
"debugging helpers have been loaded and fully initialized. You can load additional "
"debugging helpers or modify existing ones here.</p></body></html>"));
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index c8c67b01fe..f5a34aa0d5 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -29,7 +29,6 @@ HEADERS += \
debuggerprotocol.h \
debuggerrunconfigurationaspect.h \
debuggerruncontrol.h \
- debuggerstartparameters.h \
debuggerkitconfigwidget.h \
debuggerkitinformation.h \
disassembleragent.h \
diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index b27af6cff6..08faeb3d1e 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -20,6 +20,7 @@ Project {
Depends { name: "ProjectExplorer" }
Depends { name: "QtSupport" }
Depends { name: "TextEditor" }
+ Depends { name: "app_version_header" }
pluginTestDepends: [
"QmakeProjectManager"
@@ -58,7 +59,6 @@ Project {
"debuggerrunconfigurationaspect.cpp", "debuggerrunconfigurationaspect.h",
"debuggerruncontrol.cpp", "debuggerruncontrol.h",
"debuggersourcepathmappingwidget.cpp", "debuggersourcepathmappingwidget.h",
- "debuggerstartparameters.h",
"debuggertooltipmanager.cpp", "debuggertooltipmanager.h",
"disassembleragent.cpp", "disassembleragent.h",
"disassemblerlines.cpp", "disassemblerlines.h",
@@ -108,14 +108,9 @@ Project {
name: "gdb"
prefix: "gdb/"
files: [
- "attachgdbadapter.cpp", "attachgdbadapter.h",
- "coregdbadapter.cpp", "coregdbadapter.h",
"gdbengine.cpp", "gdbengine.h",
"gdboptionspage.cpp",
- "gdbplainengine.cpp", "gdbplainengine.h",
- "remotegdbserveradapter.cpp", "remotegdbserveradapter.h",
"startgdbserverdialog.cpp", "startgdbserverdialog.h",
- "termgdbadapter.cpp", "termgdbadapter.h"
]
}
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 0cac2e2628..1027c773c1 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -120,6 +120,7 @@ enum DebuggerStartMode
AttachCore, // Attach to a core file
AttachToRemoteServer, // Attach to a running gdbserver
AttachToRemoteProcess, // Attach to a running remote process
+ AttachToQmlServer, // Attach to a running QmlServer
StartRemoteProcess // Start and attach to a remote process
};
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp
index 60ddebcd71..64e1721f4d 100644
--- a/src/plugins/debugger/debuggerdialogs.cpp
+++ b/src/plugins/debugger/debuggerdialogs.cpp
@@ -26,7 +26,6 @@
#include "debuggerdialogs.h"
#include "debuggerkitinformation.h"
-#include "debuggerstartparameters.h"
#include "debuggerruncontrol.h"
#include "cdb/cdbengine.h"
@@ -34,10 +33,14 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runnables.h>
#include <projectexplorer/toolchain.h>
+
+#include <app/app_version.h>
#include <utils/pathchooser.h>
#include <utils/fancylineedit.h>
#include <utils/qtcassert.h>
+#include <ssh/sshconnection.h>
+
#include <QButtonGroup>
#include <QCheckBox>
#include <QComboBox>
@@ -226,7 +229,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
setWindowTitle(tr("Start Debugger"));
d->kitChooser = new KitChooser(this);
- d->kitChooser->setKitPredicate([this](const Kit *k) {
+ d->kitChooser->setKitPredicate([](const Kit *k) {
return !DebuggerKitInformation::configurationErrors(k);
});
d->kitChooser->populate();
@@ -264,7 +267,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
d->serverStartScriptPathChooser->setPromptDialogTitle(tr("Select Server Start Script"));
d->serverStartScriptPathChooser->setToolTip(tr(
"This option can be used to point to a script that will be used "
- "to start a debug server. If the field is empty, Qt Creator's "
+ "to start a debug server. If the field is empty, "
"default methods to set up debug servers will be used."));
d->serverStartScriptLabel = new QLabel(tr("&Server start script:"), this);
d->serverStartScriptLabel->setBuddy(d->serverStartScriptPathChooser);
@@ -365,9 +368,8 @@ void StartApplicationDialog::updateState()
d->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(okEnabled);
}
-bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit **kit)
+void StartApplicationDialog::run(bool attachRemote)
{
- const bool attachRemote = rp->startMode == AttachToRemoteServer;
const QString settingsGroup = QLatin1String("DebugMode");
const QString arrayName = QLatin1String("StartApplication");
@@ -387,7 +389,7 @@ bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit
settings->endArray();
settings->endGroup();
- StartApplicationDialog dialog(parent);
+ StartApplicationDialog dialog(ICore::dialogParent());
dialog.setHistory(history);
dialog.setParameters(history.back());
if (!attachRemote) {
@@ -399,11 +401,14 @@ bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit
dialog.d->channelOverrideEdit->setVisible(false);
}
if (dialog.exec() != QDialog::Accepted)
- return false;
+ return;
Kit *k = dialog.d->kitChooser->currentKit();
IDevice::ConstPtr dev = DeviceKitInformation::device(k);
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, k);
+
const StartApplicationParameters newParameters = dialog.parameters();
if (newParameters != history.back()) {
history.append(newParameters);
@@ -419,29 +424,39 @@ bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit
settings->endGroup();
}
- rp->inferior.executable = newParameters.runnable.executable;
+ StandardRunnable inferior = newParameters.runnable;
const QString inputAddress = dialog.d->channelOverrideEdit->text();
if (!inputAddress.isEmpty())
- rp->remoteChannel = inputAddress;
+ debugger->setRemoteChannel(inputAddress);
else
- rp->remoteChannel = QString("%1:%2").arg(dev->sshParameters().host).arg(newParameters.serverPort);
- rp->displayName = newParameters.displayName();
- rp->inferior.workingDirectory = newParameters.runnable.workingDirectory;
- rp->inferior.runMode = newParameters.runnable.runMode;
- rp->needFixup = false;
- rp->useTerminal = newParameters.runnable.runMode == ApplicationLauncher::Console;
- if (!newParameters.runnable.commandLineArguments.isEmpty())
- rp->inferior.commandLineArguments = newParameters.runnable.commandLineArguments;
- rp->breakOnMain = newParameters.breakAtMain;
- rp->serverStartScript = newParameters.serverStartScript;
- rp->debugInfoLocation = newParameters.debugInfoLocation;
+ debugger->setRemoteChannel(dev->sshParameters().host, newParameters.serverPort);
+ debugger->setRunControlName(newParameters.displayName());
+ debugger->setBreakOnMain(newParameters.breakAtMain);
+ debugger->setDebugInfoLocation(newParameters.debugInfoLocation);
+ debugger->setInferior(inferior);
+ debugger->setServerStartScript(newParameters.serverStartScript); // Note: This requires inferior.
+ debugger->setNeedFixup(false);
bool isLocal = !dev || (dev->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
if (!attachRemote)
- rp->startMode = isLocal ? StartExternal : StartRemoteProcess;
- if (kit)
- *kit = k;
- return true;
+ debugger->setStartMode(isLocal ? StartExternal : StartRemoteProcess);
+
+ if (attachRemote) {
+ debugger->setStartMode(AttachToRemoteServer);
+ debugger->setCloseMode(KillAtClose);
+ debugger->setUseContinueInsteadOfRun(true);
+ }
+ debugger->startRunControl();
+}
+
+void StartApplicationDialog::attachToRemoteServer()
+{
+ run(true);
+}
+
+void StartApplicationDialog::startAndDebugApplication()
+{
+ run(false);
}
StartApplicationParameters StartApplicationDialog::parameters() const
@@ -560,15 +575,16 @@ static QString cdbRemoteHelp()
const QString ext32 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(false));
const QString ext64 = QDir::toNativeSeparators(CdbEngine::extensionLibraryName(true));
return StartRemoteCdbDialog::tr(
- "<html><body><p>The remote CDB needs to load the matching Qt Creator CDB extension "
- "(<code>%1</code> or <code>%2</code>, respectively).</p><p>Copy it onto the remote machine and set the "
- "environment variable <code>%3</code> to point to its folder.</p><p>"
- "Launch the remote CDB as <code>%4 &lt;executable&gt;</code> "
+ "<html><body><p>The remote CDB needs to load the matching %1 CDB extension "
+ "(<code>%2</code> or <code>%3</code>, respectively).</p><p>Copy it onto the remote machine and set the "
+ "environment variable <code>%4</code> to point to its folder.</p><p>"
+ "Launch the remote CDB as <code>%5 &lt;executable&gt;</code> "
"to use TCP/IP as communication protocol.</p><p>Enter the connection parameters as:</p>"
- "<pre>%5</pre></body></html>").
- arg(ext32, ext64, QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"),
- QLatin1String("cdb.exe -server tcp:port=1234"),
- QLatin1String(cdbConnectionSyntax));
+ "<pre>%6</pre></body></html>")
+ .arg(Core::Constants::IDE_DISPLAY_NAME,
+ ext32, ext64, QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"),
+ QLatin1String("cdb.exe -server tcp:port=1234"),
+ QLatin1String(cdbConnectionSyntax));
}
StartRemoteCdbDialog::StartRemoteCdbDialog(QWidget *parent) :
diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h
index b291dbbe26..d9f3790a14 100644
--- a/src/plugins/debugger/debuggerdialogs.h
+++ b/src/plugins/debugger/debuggerdialogs.h
@@ -72,7 +72,8 @@ public:
explicit StartApplicationDialog(QWidget *parent);
~StartApplicationDialog();
- static bool run(QWidget *parent, DebuggerRunParameters *rp, ProjectExplorer::Kit **kit);
+ static void attachToRemoteServer();
+ static void startAndDebugApplication();
private:
void historyIndexChanged(int);
@@ -81,6 +82,7 @@ private:
void setParameters(const StartApplicationParameters &p);
void setHistory(const QList<StartApplicationParameters> &l);
void onChannelOverrideChanged(const QString &channel);
+ static void run(bool);
StartApplicationDialogPrivate *d;
};
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 93a2d69aad..ad58dc42da 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -30,7 +30,6 @@
#include "debuggercore.h"
#include "debuggericons.h"
#include "debuggerruncontrol.h"
-#include "debuggerstartparameters.h"
#include "debuggertooltipmanager.h"
#include "breakhandler.h"
@@ -107,9 +106,7 @@ QDebug operator<<(QDebug str, const DebuggerRunParameters &sp)
<< " debugger environment=<" << sp.debugger.environment.size() << " variables>"
<< " workingDir=" << sp.inferior.workingDirectory
<< " attachPID=" << sp.attachPID.pid()
- << " useTerminal=" << sp.useTerminal
<< " remoteChannel=" << sp.remoteChannel
- << " serverStartScript=" << sp.serverStartScript
<< " abi=" << sp.toolChainAbi.toString() << '\n';
return str;
}
@@ -331,7 +328,7 @@ public:
// The state we had before something unexpected happend.
DebuggerState m_lastGoodState = DebuggerNotReady;
- Terminal m_terminal;
+// Terminal m_terminal;
ProcessHandle m_inferiorPid;
ModulesHandler m_modulesHandler;
@@ -535,14 +532,11 @@ void DebuggerEngine::start()
fp->setKeepOnFinish(FutureProgress::HideOnFinish);
d->m_progress.reportStarted();
- DebuggerRunParameters &rp = runParameters();
+ const DebuggerRunParameters &rp = runParameters();
d->m_inferiorPid = rp.attachPID.isValid() ? rp.attachPID : ProcessHandle();
if (d->m_inferiorPid.isValid())
runControl()->setApplicationProcessHandle(d->m_inferiorPid);
- if (isNativeMixedActive())
- rp.inferior.environment.set("QV4_FORCE_INTERPRETER", "1");
-
action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability));
QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
@@ -550,18 +544,18 @@ void DebuggerEngine::start()
d->m_lastGoodState = DebuggerNotReady;
d->m_progress.setProgressValue(200);
- d->m_terminal.setup();
- if (d->m_terminal.isUsable()) {
- connect(&d->m_terminal, &Terminal::stdOutReady, [this](const QString &msg) {
- d->m_runTool->appendMessage(msg, Utils::StdOutFormatSameLine);
- });
- connect(&d->m_terminal, &Terminal::stdErrReady, [this](const QString &msg) {
- d->m_runTool->appendMessage(msg, Utils::StdErrFormatSameLine);
- });
- connect(&d->m_terminal, &Terminal::error, [this](const QString &msg) {
- d->m_runTool->appendMessage(msg, Utils::ErrorMessageFormat);
- });
- }
+// d->m_terminal.setup();
+// if (d->m_terminal.isUsable()) {
+// connect(&d->m_terminal, &Terminal::stdOutReady, [this](const QString &msg) {
+// d->m_runTool->appendMessage(msg, Utils::StdOutFormatSameLine);
+// });
+// connect(&d->m_terminal, &Terminal::stdErrReady, [this](const QString &msg) {
+// d->m_runTool->appendMessage(msg, Utils::StdErrFormatSameLine);
+// });
+// connect(&d->m_terminal, &Terminal::error, [this](const QString &msg) {
+// d->m_runTool->appendMessage(msg, Utils::ErrorMessageFormat);
+// });
+// }
d->queueSetupEngine();
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
@@ -633,11 +627,6 @@ const DebuggerRunParameters &DebuggerEngine::runParameters() const
return runTool()->runParameters();
}
-DebuggerRunParameters &DebuggerEngine::runParameters()
-{
- return runTool()->runParameters();
-}
-
DebuggerState DebuggerEngine::state() const
{
return d->m_state;
@@ -730,7 +719,6 @@ void DebuggerEnginePrivate::doSetupEngine()
{
m_engine->showMessage("CALL: SETUP ENGINE");
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state());
- m_engine->validateExecutable();
m_engine->setupEngine();
}
@@ -1239,30 +1227,6 @@ QString DebuggerEngine::nativeStartupCommands() const
runParameters().additionalStartupCommands}).join('\n'));
}
-bool DebuggerEngine::prepareCommand()
-{
- if (HostOsInfo::isWindowsHost()) {
- DebuggerRunParameters &rp = runParameters();
- QtcProcess::SplitError perr;
- rp.inferior.commandLineArguments =
- QtcProcess::prepareArgs(rp.inferior.commandLineArguments, &perr,
- HostOsInfo::hostOs(), nullptr,
- &rp.inferior.workingDirectory).toWindowsArgs();
- if (perr != QtcProcess::SplitOk) {
- // perr == BadQuoting is never returned on Windows
- // FIXME? QTCREATORBUG-2809
- showMessage("ADAPTER START FAILED");
- const QString title = tr("Adapter start failed");
- const QString msg = tr("Debugging complex command lines "
- "is currently not supported on Windows.");
- ICore::showWarningWithOptions(title, msg);
- notifyEngineSetupFailed();
- return false;
- }
- }
- return true;
-}
-
void DebuggerEngine::updateBreakpointMarker(const Breakpoint &bp)
{
d->m_disassemblerAgent.updateBreakpointMarker(bp);
@@ -1379,8 +1343,17 @@ void DebuggerEngine::quitDebugger()
void DebuggerEngine::abortDebugger()
{
- // Overridden in e.g. GdbEngine.
- quitDebugger();
+ if (!isDying()) {
+ // Be friendly the first time. This will change targetState().
+ showMessage("ABORTING DEBUGGER. FIRST TIME.");
+ quitDebugger();
+ } else {
+ // We already tried. Try harder.
+ showMessage("ABORTING DEBUGGER. SECOND TIME.");
+ abortDebuggerProcess();
+ if (runControl())
+ runControl()->initiateFinish();
+ }
}
void DebuggerEngine::requestInterruptInferior()
@@ -1404,9 +1377,10 @@ DebuggerRunTool *DebuggerEngine::runTool() const
return d->m_runTool.data();
}
-Terminal *DebuggerEngine::terminal() const
+TerminalRunner *DebuggerEngine::terminal() const
{
- return &d->m_terminal;
+ QTC_ASSERT(d->m_runTool, return nullptr);
+ return d->m_runTool->terminalRunner();
}
void DebuggerEngine::selectWatchData(const QString &)
@@ -1771,42 +1745,30 @@ void DebuggerEngine::setStateDebugging(bool on)
d->m_isStateDebugging = on;
}
-void DebuggerEngine::validateExecutable()
+void DebuggerRunParameters::validateExecutable()
{
- DebuggerRunParameters *sp = &runParameters();
- if (sp->skipExecutableValidation)
- return;
- if (sp->languages == QmlLanguage)
- return;
-
- QString symbolFile = sp->symbolFile;
- if (symbolFile.isEmpty())
- symbolFile = sp->inferior.executable;
- if (symbolFile.isEmpty())
- return;
-
const bool warnOnRelease = boolSetting(WarnOnReleaseBuilds);
bool warnOnInappropriateDebugger = false;
QString detailedWarning;
- switch (sp->toolChainAbi.binaryFormat()) {
+ switch (toolChainAbi.binaryFormat()) {
case Abi::PEFormat: {
QString preferredDebugger;
- if (sp->toolChainAbi.osFlavor() == Abi::WindowsMSysFlavor) {
- if (sp->cppEngineType == CdbEngineType)
+ if (toolChainAbi.osFlavor() == Abi::WindowsMSysFlavor) {
+ if (cppEngineType == CdbEngineType)
preferredDebugger = "GDB";
- } else if (sp->cppEngineType != CdbEngineType) {
+ } else if (cppEngineType != CdbEngineType) {
// osFlavor() is MSVC, so the recommended debugger is CDB
preferredDebugger = "CDB";
}
if (!preferredDebugger.isEmpty()) {
warnOnInappropriateDebugger = true;
- detailedWarning = tr(
+ detailedWarning = DebuggerEngine::tr(
"The inferior is in the Portable Executable format.\n"
"Selecting %1 as debugger would improve the debugging "
"experience for this binary format.").arg(preferredDebugger);
break;
}
- if (warnOnRelease && sp->cppEngineType == CdbEngineType) {
+ if (warnOnRelease && cppEngineType == CdbEngineType) {
if (!symbolFile.endsWith(".exe", Qt::CaseInsensitive))
symbolFile.append(".exe");
QString errorMessage;
@@ -1823,9 +1785,9 @@ void DebuggerEngine::validateExecutable()
break;
}
case Abi::ElfFormat: {
- if (sp->cppEngineType == CdbEngineType) {
+ if (cppEngineType == CdbEngineType) {
warnOnInappropriateDebugger = true;
- detailedWarning = tr(
+ detailedWarning = DebuggerEngine::tr(
"The inferior is in the ELF format.\n"
"Selecting GDB or LLDB as debugger would improve the debugging "
"experience for this binary format.");
@@ -1898,7 +1860,7 @@ void DebuggerEngine::validateExecutable()
QRegExp exp = itExp->first;
int index = exp.indexIn(string);
if (index != -1) {
- sp->sourcePathMap.insert(string.left(index) + exp.cap(1), itExp->second);
+ sourcePathMap.insert(string.left(index) + exp.cap(1), itExp->second);
found = true;
break;
}
@@ -1917,8 +1879,9 @@ void DebuggerEngine::validateExecutable()
return;
foreach (const QByteArray &name, interesting) {
- const QString found = seen.contains(name) ? tr("Found.") : tr("Not found.");
- detailedWarning.append('\n' + tr("Section %1: %2").arg(QString::fromUtf8(name)).arg(found));
+ const QString found = seen.contains(name) ? DebuggerEngine::tr("Found.")
+ : DebuggerEngine::tr("Not found.");
+ detailedWarning.append('\n' + DebuggerEngine::tr("Section %1: %2").arg(QString::fromUtf8(name)).arg(found));
}
break;
}
@@ -1926,14 +1889,14 @@ void DebuggerEngine::validateExecutable()
return;
}
if (warnOnInappropriateDebugger) {
- AsynchronousMessageBox::information(tr("Warning"),
- tr("The selected debugger may be inappropriate for the inferior.\n"
+ AsynchronousMessageBox::information(DebuggerEngine::tr("Warning"),
+ DebuggerEngine::tr("The selected debugger may be inappropriate for the inferior.\n"
"Examining symbols and setting breakpoints by file name and line number "
"may fail.\n")
+ '\n' + detailedWarning);
} else if (warnOnRelease) {
- AsynchronousMessageBox::information(tr("Warning"),
- tr("This does not seem to be a \"Debug\" build.\n"
+ AsynchronousMessageBox::information(DebuggerEngine::tr("Warning"),
+ DebuggerEngine::tr("This does not seem to be a \"Debug\" build.\n"
"Setting breakpoints by file name and line number may fail.")
+ '\n' + detailedWarning);
}
@@ -2028,10 +1991,8 @@ void DebuggerEngine::checkState(DebuggerState state, const char *file, int line)
bool DebuggerEngine::isNativeMixedEnabled() const
{
- if (DebuggerRunTool *rt = runTool()) {
- const DebuggerRunParameters &runParams = rt->runParameters();
- return runParams.nativeMixedEnabled && (runParams.languages & QmlLanguage);
- }
+ if (DebuggerRunTool *rt = runTool())
+ return rt->runParameters().isNativeMixedDebugging();
return false;
}
@@ -2050,6 +2011,11 @@ bool DebuggerEngine::isNativeMixedActiveFrame() const
return frame.language == QmlLanguage;
}
+bool DebuggerRunParameters::isNativeMixedDebugging() const
+{
+ return nativeMixedEnabled && isCppDebugging && isQmlDebugging;
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 04e1196ad4..5178cb631c 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -29,7 +29,6 @@
#include "debuggerconstants.h"
#include "debuggeritem.h"
#include "debuggerprotocol.h"
-#include "debuggerstartparameters.h"
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/runnables.h>
@@ -46,10 +45,7 @@ QT_END_NAMESPACE
namespace Core { class IOptionsPage; }
-namespace Utils {
-class MacroExpander;
-class ProcessHandle;
-} // Utils
+namespace Utils { class MacroExpander; }
namespace Debugger {
@@ -78,18 +74,65 @@ class QmlCppEngine;
class DebuggerToolTipContext;
class MemoryViewSetupData;
class Terminal;
+class TerminalRunner;
class ThreadId;
-class DebuggerRunParameters : public DebuggerStartParameters
+class DebuggerRunParameters
{
public:
- DebuggerRunParameters() {}
- DebuggerRunParameters(const DebuggerStartParameters &sp) : DebuggerStartParameters(sp) {}
+ DebuggerStartMode startMode = NoStartMode;
+ DebuggerCloseMode closeMode = KillAtClose;
+
+ ProjectExplorer::StandardRunnable inferior;
+ QString displayName; // Used in the Snapshots view.
+ Utils::Environment stubEnvironment;
+ Utils::ProcessHandle attachPID;
+ QStringList solibSearchPath;
+
+ // Used by Qml debugging.
+ QUrl qmlServer;
+
+ // Used by general remote debugging.
+ QString remoteChannel;
+ bool useExtendedRemote = false; // Whether to use GDB's target extended-remote or not.
+ QString symbolFile;
+
+ // Used by Mer plugin (3rd party)
+ QMap<QString, QString> sourcePathMap;
+
+ // Used by baremetal plugin
+ QString commandsForReset; // commands used for resetting the inferior
+ bool useContinueInsteadOfRun = false; // if connected to a hw debugger run is not possible but continue is used
+ QString commandsAfterConnect; // additional commands to post after connection to debug target
+
+ // Used by Valgrind
+ QStringList expectedSignals;
+
+ // For QNX debugging
+ bool useCtrlCStub = false;
+
+ // Used by Android to avoid false positives on warnOnRelease
+ bool skipExecutableValidation = false;
+ bool useTargetAsync = false;
+ QStringList additionalSearchDirectories;
+
+ // Used by iOS.
+ QString platform;
+ QString deviceSymbolsRoot;
+ bool continueAfterAttach = false;
+ QString sysRoot;
+
+ // Used by general core file debugging. Public access requested in QTCREATORBUG-17158.
+ QString coreFile;
+
+ // Macro-expanded and passed to debugger startup.
+ QString additionalStartupCommands;
DebuggerEngineType masterEngineType = NoEngineType;
DebuggerEngineType cppEngineType = NoEngineType;
- DebuggerLanguages languages = NoLanguage;
+ bool isCppDebugging = true;
+ bool isQmlDebugging = false;
bool breakOnMain = false;
bool multiProcess = false; // Whether to set detach-on-fork off.
@@ -98,7 +141,6 @@ public:
QString startMessage; // First status message shown.
QString debugInfoLocation; // Gdb "set-debug-file-directory".
QStringList debugSourceLocation; // Gdb "directory"
- QString serverStartScript;
bool isSnapshot = false; // Set if created internally.
ProjectExplorer::Abi toolChainAbi;
@@ -114,10 +156,15 @@ public:
bool nativeMixedEnabled = false;
+ bool isNativeMixedDebugging() const;
+ void validateExecutable();
+
Utils::MacroExpander *macroExpander = 0;
// For Debugger testing.
int testCase = 0;
+
+ QStringList validationErrors;
};
class UpdateParameters
@@ -195,7 +242,7 @@ public:
virtual ~DebuggerEngine();
const DebuggerRunParameters &runParameters() const;
- DebuggerRunParameters &runParameters();
+
virtual void setRunTool(DebuggerRunTool *runTool);
DebuggerRunTool *runTool() const;
@@ -316,7 +363,8 @@ public:
virtual void resetLocation();
virtual void gotoLocation(const Internal::Location &location);
virtual void quitDebugger(); // called when pressing the stop button
- virtual void abortDebugger(); // called from the debug menu action
+
+ void abortDebugger(); // called from the debug menu action
void updateViews();
bool isSlaveEngine() const;
@@ -336,50 +384,49 @@ public:
QString expand(const QString &string) const;
QString nativeStartupCommands() const;
- bool prepareCommand();
-
protected:
// The base notify*() function implementation should be sufficient
// in most cases, but engines are free to override them to do some
// engine specific cleanup like stopping timers etc.
- virtual void notifyEngineSetupOk();
- virtual void notifyEngineSetupFailed();
- virtual void notifyEngineRunFailed();
+ void notifyEngineSetupOk();
+ void notifyEngineSetupFailed();
+ void notifyEngineRunFailed();
- virtual void notifyInferiorSetupOk();
- virtual void notifyInferiorSetupFailed();
+ void notifyInferiorSetupOk();
+ void notifyInferiorSetupFailed();
- virtual void notifyEngineRunAndInferiorRunOk();
- virtual void notifyEngineRunAndInferiorStopOk();
- virtual void notifyEngineRunOkAndInferiorUnrunnable(); // Called by CoreAdapter.
+ void notifyEngineRunAndInferiorRunOk();
+ void notifyEngineRunAndInferiorStopOk();
+ void notifyEngineRunOkAndInferiorUnrunnable(); // Called by CoreAdapter.
// Use notifyInferiorRunRequested() plus notifyInferiorRunOk() instead.
- //virtual void notifyInferiorSpontaneousRun();
+ // void notifyInferiorSpontaneousRun();
+
+ void notifyInferiorRunRequested();
+ void notifyInferiorRunOk();
+ void notifyInferiorRunFailed();
- virtual void notifyInferiorRunRequested();
- virtual void notifyInferiorRunOk();
- virtual void notifyInferiorRunFailed();
+ void notifyInferiorStopOk();
+ void notifyInferiorSpontaneousStop();
+ void notifyInferiorStopFailed();
- virtual void notifyInferiorStopOk();
- virtual void notifyInferiorSpontaneousStop();
- virtual void notifyInferiorStopFailed();
+ public: // FIXME: Remove, currently needed for Android.
+ void notifyInferiorExited();
- public:
- virtual void notifyInferiorExited();
+ protected:
void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus,
const QString &backendName);
-protected:
virtual void setState(DebuggerState state, bool forced = false);
- virtual void notifyInferiorShutdownOk();
- virtual void notifyInferiorShutdownFailed();
+ void notifyInferiorShutdownOk();
+ void notifyInferiorShutdownFailed();
- virtual void notifyEngineSpontaneousShutdown();
- virtual void notifyEngineShutdownOk();
- virtual void notifyEngineShutdownFailed();
+ void notifyEngineSpontaneousShutdown();
+ void notifyEngineShutdownOk();
+ void notifyEngineShutdownFailed();
- virtual void notifyEngineIll();
+ void notifyEngineIll();
virtual void setupEngine() = 0;
virtual void setupInferior() = 0;
@@ -407,12 +454,14 @@ protected:
virtual void frameUp();
virtual void frameDown();
+ virtual void abortDebuggerProcess() {} // second attempt
+
virtual void doUpdateLocals(const UpdateParameters &params);
void setMasterEngine(DebuggerEngine *masterEngine);
ProjectExplorer::RunControl *runControl() const;
- Terminal *terminal() const;
+ TerminalRunner *terminal() const;
static QString msgStopped(const QString &reason = QString());
static QString msgStoppedBySignal(const QString &meaning, const QString &name);
@@ -425,8 +474,6 @@ protected:
bool isStateDebugging() const;
void setStateDebugging(bool on);
- void validateExecutable();
-
virtual void setupSlaveInferior();
virtual void setupSlaveEngine();
virtual void runSlaveEngine();
@@ -464,8 +511,6 @@ private:
QPointer<DebuggerEngine> m_engine;
};
-ProjectExplorer::RunControl *createAndScheduleRun(const DebuggerRunParameters &rp, ProjectExplorer::Kit *kit);
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp
index 5bc634fed8..d5ab9d0aae 100644
--- a/src/plugins/debugger/debuggerkitinformation.cpp
+++ b/src/plugins/debugger/debuggerkitinformation.cpp
@@ -300,26 +300,26 @@ KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const
void DebuggerKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
expander->registerVariable("Debugger:Name", tr("Name of Debugger"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const DebuggerItem *item = debugger(kit);
return item ? item->displayName() : tr("Unknown debugger");
});
expander->registerVariable("Debugger:Type", tr("Type of Debugger Backend"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const DebuggerItem *item = debugger(kit);
return item ? item->engineTypeName() : tr("Unknown debugger type");
});
expander->registerVariable("Debugger:Version", tr("Debugger"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const DebuggerItem *item = debugger(kit);
return item && !item->version().isEmpty()
? item->version() : tr("Unknown debugger version");
});
expander->registerVariable("Debugger:Abi", tr("Debugger"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const DebuggerItem *item = debugger(kit);
return item && !item->abis().isEmpty()
? item->abiNames().join(QLatin1Char(' '))
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index c992fe8507..5e378ac20c 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -26,7 +26,6 @@
#include "debuggerplugin.h"
#include "debuggermainwindow.h"
-#include "debuggerstartparameters.h"
#include "debuggeractions.h"
#include "debuggerinternalconstants.h"
#include "debuggercore.h"
@@ -67,6 +66,8 @@
#include "analyzer/analyzerconstants.h"
#include "analyzer/analyzermanager.h"
+#include <app/app_version.h>
+
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
@@ -103,6 +104,7 @@
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
#include <projectexplorer/toolchain.h>
+#include <ssh/sshconnection.h>
#include <texteditor/texteditor.h>
#include <texteditor/textdocument.h>
@@ -635,6 +637,7 @@ public:
bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized();
void aboutToShutdown();
+ void doShutdown();
void connectEngine(DebuggerRunTool *runTool);
void disconnectEngine() { connectEngine(0); }
@@ -731,10 +734,8 @@ public:
void onModeChanged(Id mode);
void updateDebugWithoutDeployMenu();
- void startAndDebugApplication();
void startRemoteCdbSession();
void startRemoteServerAndAttachToProcess();
- void attachToRemoteServer();
void attachToRunningApplication();
void attachToUnstartedApplicationDialog();
void attachToQmlPort();
@@ -763,8 +764,6 @@ public:
void aboutToUnloadSession();
void aboutToSaveSession();
- void coreShutdown();
-
public:
void updateDebugActions();
@@ -970,14 +969,12 @@ public:
ActionContainer *m_menu = 0;
- QHash<DebuggerLanguage, Core::Context> m_contextsForLanguage;
-
Project *m_previousProject = 0;
QPointer<Target> m_previousTarget;
QPointer<RunConfiguration> m_previousRunConfiguration;
Id m_previousMode;
- QVector<QPair<DebuggerRunParameters, Kit *>> m_scheduledStarts;
+ QVector<DebuggerRunTool *> m_scheduledStarts;
ProxyAction *m_visibleStartAction = 0;
ProxyAction *m_hiddenStopAction = 0;
@@ -1052,6 +1049,7 @@ public:
DebuggerPlugin *m_plugin = 0;
SnapshotHandler *m_snapshotHandler = 0;
+ QTimer m_shutdownTimer;
bool m_shuttingDown = false;
QPointer<DebuggerEngine> m_previouslyActiveEngine;
QPointer<DebuggerRunTool> m_currentRunTool;
@@ -1073,11 +1071,6 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin)
dd = this;
m_plugin = plugin;
-
-// m_toolBars.insert(CppLanguage, 0);
-// m_toolBars.insert(QmlLanguage, 0);
- m_contextsForLanguage.insert(CppLanguage, Context(C_CPPDEBUGGER));
- m_contextsForLanguage.insert(QmlLanguage, Context(C_QMLDEBUGGER));
}
DebuggerPluginPrivate::~DebuggerPluginPrivate()
@@ -1107,17 +1100,11 @@ static QString msgParameterMissing(const QString &a)
return DebuggerPlugin::tr("Option \"%1\" is missing the parameter.").arg(a);
}
-static Kit *guessKitFromParameters(const DebuggerRunParameters &rp)
+static Kit *guessKitFromAbis(const QList<Abi> &abis)
{
Kit *kit = 0;
// Try to find a kit via ABI.
- QList<Abi> abis;
- if (rp.toolChainAbi.isValid())
- abis.push_back(rp.toolChainAbi);
- else if (!rp.inferior.executable.isEmpty())
- abis = Abi::abisOfBinary(FileName::fromString(rp.inferior.executable));
-
if (!abis.isEmpty()) {
// Try exact abis.
kit = KitManager::kit([abis](const Kit *k) {
@@ -1152,60 +1139,73 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
*errorMessage = msgParameterMissing(*it);
return false;
}
- Kit *kit = 0;
- DebuggerRunParameters rp;
- qulonglong pid = it->toULongLong();
- if (pid) {
- rp.startMode = AttachExternal;
- rp.closeMode = DetachAtClose;
- rp.attachPID = ProcessHandle(pid);
- rp.displayName = tr("Process %1").arg(rp.attachPID.pid());
- rp.startMessage = tr("Attaching to local process %1.").arg(rp.attachPID.pid());
- } else {
- rp.startMode = StartExternal;
- QStringList args = it->split(QLatin1Char(','));
+ const qulonglong pid = it->toULongLong();
+ const QStringList args = it->split(',');
+
+ Kit *kit = nullptr;
+ DebuggerStartMode startMode = StartExternal;
+ QString executable;
+ QString remoteChannel;
+ QString coreFile;
+ bool useTerminal = false;
+
+ if (!pid) {
foreach (const QString &arg, args) {
- QString key = arg.section(QLatin1Char('='), 0, 0);
- QString val = arg.section(QLatin1Char('='), 1, 1);
+ const QString key = arg.section('=', 0, 0);
+ const QString val = arg.section('=', 1, 1);
if (val.isEmpty()) {
if (key.isEmpty()) {
continue;
- } else if (rp.inferior.executable.isEmpty()) {
- rp.inferior.executable = key;
+ } else if (executable.isEmpty()) {
+ executable = key;
} else {
*errorMessage = DebuggerPlugin::tr("Only one executable allowed.");
return false;
}
- }
- if (key == QLatin1String("server")) {
- rp.startMode = AttachToRemoteServer;
- rp.remoteChannel = val;
- rp.displayName = tr("Remote: \"%1\"").arg(rp.remoteChannel);
- rp.startMessage = tr("Attaching to remote server %1.").arg(rp.remoteChannel);
- } else if (key == QLatin1String("core")) {
- rp.startMode = AttachCore;
- rp.closeMode = DetachAtClose;
- rp.coreFile = val;
- rp.displayName = tr("Core file \"%1\"").arg(rp.coreFile);
- rp.startMessage = tr("Attaching to core file %1.").arg(rp.coreFile);
- } else if (key == QLatin1String("terminal")) {
- rp.useTerminal = bool(val.toInt());
- } else if (key == QLatin1String("kit")) {
+ } else if (key == "kit") {
kit = KitManager::kit(Id::fromString(val));
+ } else if (key == "server") {
+ startMode = AttachToRemoteServer;
+ remoteChannel = remoteChannel;
+ } else if (key == "core") {
+ startMode = AttachCore;
+ coreFile = val;
+ } else if (key == "terminal") {
+ useTerminal = true;
}
}
}
- if (rp.startMode == StartExternal) {
- rp.displayName = tr("Executable file \"%1\"").arg(rp.inferior.executable);
- rp.startMessage = tr("Debugging file %1.").arg(rp.inferior.executable);
+ if (!kit)
+ kit = guessKitFromAbis(Abi::abisOfBinary(FileName::fromString(executable)));
+
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, kit);
+ if (pid) {
+ debugger->setStartMode(AttachExternal);
+ debugger->setCloseMode(DetachAtClose);
+ debugger->setAttachPid(pid);
+ debugger->setRunControlName(tr("Process %1").arg(pid));
+ debugger->setStartMessage(tr("Attaching to local process %1.").arg(pid));
+ } else if (startMode == AttachToRemoteServer) {
+ debugger->setStartMode(AttachToRemoteServer);
+ debugger->setRemoteChannel(remoteChannel);
+ debugger->setRunControlName(tr("Remote: \"%1\"").arg(remoteChannel));
+ debugger->setStartMessage(tr("Attaching to remote server %1.").arg(remoteChannel));
+ } else if (startMode == AttachCore) {
+ debugger->setStartMode(AttachCore);
+ debugger->setCloseMode(DetachAtClose);
+ debugger->setCoreFileName(coreFile);
+ debugger->setRunControlName(tr("Core file \"%1\"").arg(coreFile));
+ debugger->setStartMessage(tr("Attaching to core file %1.").arg(coreFile));
+ } else {
+ debugger->setStartMode(StartExternal);
+ debugger->setInferiorExecutable(executable);
+ debugger->setRunControlName(tr("Executable file \"%1\"").arg(executable));
+ debugger->setStartMessage(tr("Debugging file %1.").arg(executable));
}
- rp.inferior.environment = Utils::Environment::systemEnvironment();
- rp.stubEnvironment = Utils::Environment::systemEnvironment();
- rp.debugger.environment = Utils::Environment::systemEnvironment();
+ debugger->setUseTerminal(useTerminal);
- if (!kit)
- kit = guessKitFromParameters(rp);
- m_scheduledStarts.append(QPair<DebuggerRunParameters, Kit *>(rp, kit));
+ m_scheduledStarts.append(debugger);
return true;
}
// -wincrashevent <event-handle>:<pid>. A handle used for
@@ -1219,18 +1219,20 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
*errorMessage = msgParameterMissing(*it);
return false;
}
- DebuggerRunParameters rp;
- rp.startMode = AttachCrashedExternal;
- rp.crashParameter = it->section(QLatin1Char(':'), 0, 0);
- rp.attachPID = ProcessHandle(it->section(QLatin1Char(':'), 1, 1).toULongLong());
- rp.displayName = tr("Crashed process %1").arg(rp.attachPID.pid());
- rp.startMessage = tr("Attaching to crashed process %1").arg(rp.attachPID.pid());
- if (!rp.attachPID.isValid()) {
+ qint64 pid = it->section(':', 1, 1).toULongLong();
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, findUniversalCdbKit());
+ debugger->setStartMode(AttachCrashedExternal);
+ debugger->setCrashParameter(it->section(':', 0, 0));
+ debugger->setAttachPid(pid);
+ debugger->setRunControlName(tr("Crashed process %1").arg(pid));
+ debugger->setStartMessage(tr("Attaching to crashed process %1").arg(pid));
+ if (pid < 1) {
*errorMessage = DebuggerPlugin::tr("The parameter \"%1\" of option \"%2\" "
"does not match the pattern <handle>:<pid>.").arg(*it, option);
return false;
}
- m_scheduledStarts.append(QPair<DebuggerRunParameters, Kit *>(rp, findUniversalCdbKit()));
+ m_scheduledStarts.append(debugger);
return true;
}
@@ -1316,8 +1318,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_debuggerSettings = new DebuggerSettings;
m_debuggerSettings->readSettings();
- connect(ICore::instance(), &ICore::coreAboutToClose, this, &DebuggerPluginPrivate::coreShutdown);
-
const Context cppDebuggercontext(C_CPPDEBUGGER);
const Context qmljsDebuggercontext(C_QMLDEBUGGER);
@@ -1497,7 +1497,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
act = m_startAndDebugApplicationAction = new QAction(this);
act->setText(tr("Start and Debug External Application..."));
- connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::startAndDebugApplication);
+ connect(act, &QAction::triggered, this, &StartApplicationDialog::startAndDebugApplication);
act = m_attachToCoreAction = new QAction(this);
act->setText(tr("Load Core File..."));
@@ -1505,7 +1505,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
act = m_attachToRemoteServerAction = new QAction(this);
act->setText(tr("Attach to Running Debug Server..."));
- connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::attachToRemoteServer);
+ connect(act, &QAction::triggered, this, &StartApplicationDialog::attachToRemoteServer);
act = m_startRemoteServerAction = new QAction(this);
act->setText(tr("Start Debug Server Attached to Process..."));
@@ -1934,14 +1934,6 @@ void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
setProxyAction(m_visibleStartAction, Id(Constants::DEBUG));
}
-void DebuggerPluginPrivate::startAndDebugApplication()
-{
- DebuggerRunParameters rp;
- Kit *kit;
- if (StartApplicationDialog::run(ICore::dialogParent(), &rp, &kit))
- createAndScheduleRun(rp, kit);
-}
-
void DebuggerPluginPrivate::attachCore()
{
AttachCoreDialog dlg(ICore::dialogParent());
@@ -1965,48 +1957,39 @@ void DebuggerPluginPrivate::attachCore()
setConfigValue("LastExternalStartScript", dlg.overrideStartScript());
setConfigValue("LastForceLocalCoreFile", dlg.forcesLocalCoreFile());
- QString display = dlg.useLocalCoreFile() ? dlg.localCoreFile() : dlg.remoteCoreFile();
- DebuggerRunParameters rp;
- rp.masterEngineType = DebuggerKitInformation::engineType(dlg.kit());
- rp.inferior.executable = dlg.localExecutableFile();
- rp.coreFile = dlg.localCoreFile();
- rp.displayName = tr("Core file \"%1\"").arg(display);
- rp.startMode = AttachCore;
- rp.closeMode = DetachAtClose;
- rp.overrideStartScript = dlg.overrideStartScript();
- createAndScheduleRun(rp, dlg.kit());
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, dlg.kit());
+ debugger->setInferiorExecutable(dlg.localExecutableFile());
+ debugger->setCoreFileName(dlg.localCoreFile());
+ debugger->setRunControlName(tr("Core file \"%1\"")
+ .arg(dlg.useLocalCoreFile() ? dlg.localCoreFile() : dlg.remoteCoreFile()));
+ debugger->setStartMode(AttachCore);
+ debugger->setCloseMode(DetachAtClose);
+ debugger->setOverrideStartScript(dlg.overrideStartScript());
+ debugger->startRunControl();
}
void DebuggerPluginPrivate::startRemoteCdbSession()
{
const QString connectionKey = "CdbRemoteConnection";
- DebuggerRunParameters rp;
Kit *kit = findUniversalCdbKit();
QTC_ASSERT(kit, return);
- rp.startMode = AttachToRemoteServer;
- rp.closeMode = KillAtClose;
+
StartRemoteCdbDialog dlg(ICore::dialogParent());
QString previousConnection = configValue(connectionKey).toString();
if (previousConnection.isEmpty())
- previousConnection = QLatin1String("localhost:1234");
+ previousConnection = "localhost:1234";
dlg.setConnection(previousConnection);
if (dlg.exec() != QDialog::Accepted)
return;
- rp.remoteChannel = dlg.connection();
- setConfigValue(connectionKey, rp.remoteChannel);
- createAndScheduleRun(rp, kit);
-}
+ setConfigValue(connectionKey, dlg.connection());
-void DebuggerPluginPrivate::attachToRemoteServer()
-{
- DebuggerRunParameters rp;
- Kit *kit;
- rp.startMode = AttachToRemoteServer;
- rp.useContinueInsteadOfRun = true;
- if (StartApplicationDialog::run(ICore::dialogParent(), &rp, &kit)) {
- rp.closeMode = KillAtClose;
- createAndScheduleRun(rp, kit);
- }
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, kit);
+ debugger->setStartMode(AttachToRemoteServer);
+ debugger->setCloseMode(KillAtClose);
+ debugger->setRemoteChannel(dlg.connection());
+ debugger->startRunControl();
}
void DebuggerPluginPrivate::startRemoteServerAndAttachToProcess()
@@ -2089,9 +2072,11 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
const Abi tcAbi = ToolChainKitInformation::targetAbi(kit);
const bool isWindows = (tcAbi.os() == Abi::WindowsOS);
if (isWindows && isWinProcessBeingDebugged(process.pid)) {
- AsynchronousMessageBox::warning(tr("Process Already Under Debugger Control"),
- tr("The process %1 is already under the control of a debugger.\n"
- "Qt Creator cannot attach to it.").arg(process.pid));
+ AsynchronousMessageBox::warning(
+ tr("Process Already Under Debugger Control"),
+ tr("The process %1 is already under the control of a debugger.\n"
+ "%2 cannot attach to it.").arg(process.pid)
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
return 0;
}
@@ -2101,32 +2086,31 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
return 0;
}
- DebuggerRunParameters rp;
- rp.attachPID = ProcessHandle(process.pid);
- rp.displayName = tr("Process %1").arg(process.pid);
- rp.inferior.executable = process.exe;
- rp.startMode = AttachExternal;
- rp.closeMode = DetachAtClose;
- rp.continueAfterAttach = contAfterAttach;
- return createAndScheduleRun(rp, kit);
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, kit);
+ debugger->setAttachPid(ProcessHandle(process.pid));
+ debugger->setRunControlName(tr("Process %1").arg(process.pid));
+ debugger->setInferiorExecutable(process.exe);
+ debugger->setStartMode(AttachExternal);
+ debugger->setCloseMode(DetachAtClose);
+ debugger->setContinueAfterAttach(contAfterAttach);
+
+ debugger->startRunControl();
+
+ return debugger->runControl();
}
void DebuggerPlugin::attachExternalApplication(RunControl *rc)
{
- DebuggerRunParameters rp;
- rp.attachPID = rc->applicationProcessHandle();
- rp.displayName = tr("Process %1").arg(rp.attachPID.pid());
- rp.startMode = AttachExternal;
- rp.closeMode = DetachAtClose;
- rp.toolChainAbi = rc->abi();
- rp.languages = CppLanguage;
- if (RunConfiguration *runConfig = rc->runConfiguration()) {
- auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- (void) new DebuggerRunTool(runControl, rp);
- ProjectExplorerPlugin::startRunControl(runControl);
- } else {
- createAndScheduleRun(rp, guessKitFromParameters(rp));
- }
+ ProcessHandle pid = rc->applicationProcessHandle();
+ RunConfiguration *runConfig = rc->runConfiguration();
+ auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, guessKitFromAbis({rc->abi()}));
+ debugger->setAttachPid(pid);
+ debugger->setRunControlName(tr("Process %1").arg(pid.pid()));
+ debugger->setStartMode(AttachExternal);
+ debugger->setCloseMode(DetachAtClose);
+ debugger->startRunControl();
}
void DebuggerPlugin::getEnginesState(QByteArray *json) const
@@ -2154,14 +2138,11 @@ void DebuggerPlugin::getEnginesState(QByteArray *json) const
void DebuggerPluginPrivate::attachToQmlPort()
{
- DebuggerRunParameters rp;
AttachToQmlPortDialog dlg(ICore::mainWindow());
const QVariant qmlServerPort = configValue("LastQmlServerPort");
if (qmlServerPort.isValid())
dlg.setPort(qmlServerPort.toInt());
- else if (rp.qmlServer.port.isValid())
- dlg.setPort(rp.qmlServer.port.number());
else
dlg.setPort(-1);
@@ -2178,35 +2159,20 @@ void DebuggerPluginPrivate::attachToQmlPort()
setConfigValue("LastProfile", kit->id().toSetting());
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
- if (device) {
- QSsh::SshConnectionParameters sshParameters = device->sshParameters();
- rp.remoteChannel = QString("%1:%2").arg(sshParameters.host).arg(sshParameters.port);
- QUrl toolControl = device->toolControlChannel(IDevice::QmlControlChannel);
- rp.qmlServer.host = toolControl.host();
- }
- rp.qmlServer.port = Utils::Port(dlg.port());
- rp.startMode = AttachToRemoteProcess;
- rp.closeMode = KillAtClose;
- rp.languages = QmlLanguage;
- rp.masterEngineType = QmlEngineType;
+ QTC_ASSERT(device, return);
- //
- // get files from all the projects in the session
- //
- QList<Project *> projects = SessionManager::projects();
- if (Project *startupProject = SessionManager::startupProject()) {
- // startup project first
- projects.removeOne(startupProject);
- projects.insert(0, startupProject);
- }
- QStringList sourceFiles;
- foreach (Project *project, projects)
- sourceFiles << project->files(Project::SourceFiles);
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, kit);
+
+ QUrl qmlServer = device->toolControlChannel(IDevice::QmlControlChannel);
+ qmlServer.setPort(dlg.port());
+ debugger->setQmlServer(qmlServer);
- rp.projectSourceDirectory =
- !projects.isEmpty() ? projects.first()->projectDirectory().toString() : QString();
- rp.projectSourceFiles = sourceFiles;
- createAndScheduleRun(rp, kit);
+ QSsh::SshConnectionParameters sshParameters = device->sshParameters();
+ debugger->setRemoteChannel(sshParameters.host, sshParameters.port);
+ debugger->setStartMode(AttachToQmlServer);
+
+ debugger->startRunControl();
}
void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value)
@@ -2219,8 +2185,8 @@ void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &valu
void DebuggerPluginPrivate::runScheduled()
{
- for (const QPair<DebuggerRunParameters, Kit *> pair : m_scheduledStarts)
- createAndScheduleRun(pair.first, pair.second);
+ for (DebuggerRunTool *debugger : m_scheduledStarts)
+ debugger->startRunControl();
}
void DebuggerPluginPrivate::editorOpened(IEditor *editor)
@@ -2312,7 +2278,7 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
auto act = menu->addAction(args.address
? DebuggerEngine::tr("Run to Address 0x%1").arg(args.address, 0, 16)
: DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber));
- connect(act, &QAction::triggered, [this, args] {
+ connect(act, &QAction::triggered, this, [args] {
DebuggerEngine *engine = currentEngine();
QTC_ASSERT(engine, return);
engine->executeRunToLine(args);
@@ -2322,7 +2288,7 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
auto act = menu->addAction(args.address
? DebuggerEngine::tr("Jump to Address 0x%1").arg(args.address, 0, 16)
: DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber));
- connect(act, &QAction::triggered, [this, args] {
+ connect(act, &QAction::triggered, this, [args] {
DebuggerEngine *engine = currentEngine();
QTC_ASSERT(engine, return);
engine->executeJumpToLine(args);
@@ -2337,7 +2303,7 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
const QString text = tr("Disassemble Function \"%1\"")
.arg(frame.function);
auto act = new QAction(text, menu);
- connect(act, &QAction::triggered, [this, frame] {
+ connect(act, &QAction::triggered, this, [frame] {
DebuggerEngine *engine = currentEngine();
QTC_ASSERT(engine, return);
engine->openDisassemblerView(Location(frame));
@@ -2820,13 +2786,23 @@ void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
m_mainWindow->showStatusMessage(msg, timeout);
}
-void DebuggerPluginPrivate::coreShutdown()
+void DebuggerPluginPrivate::aboutToShutdown()
{
m_shuttingDown = true;
- if (currentEngine()) {
- if (currentEngine()->state() != Debugger::DebuggerNotReady)
- currentEngine()->abortDebugger();
+
+ disconnect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, nullptr);
+
+ m_mainWindow->saveCurrentPerspective();
+ m_shutdownTimer.setInterval(0);
+ m_shutdownTimer.setSingleShot(true);
+ connect(&m_shutdownTimer, &QTimer::timeout, this, &DebuggerPluginPrivate::doShutdown);
+ if (DebuggerEngine *engine = currentEngine()) {
+ if (engine->state() != Debugger::DebuggerNotReady) {
+ engine->abortDebugger();
+ m_shutdownTimer.setInterval(3000);
+ }
}
+ m_shutdownTimer.start();
}
const CPlusPlus::Snapshot &cppCodeModelSnapshot()
@@ -2902,24 +2878,23 @@ static void createNewDock(QWidget *widget)
dockWidget->show();
}
-static QString formatStartParameters(DebuggerRunParameters &sp)
+static QString formatStartParameters(const DebuggerRunTool *debugger)
{
+ const DebuggerRunParameters &sp = debugger->runParameters();
QString rc;
QTextStream str(&rc);
str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode
<< "\nABI: " << sp.toolChainAbi.toString() << '\n';
str << "Languages: ";
- if (sp.languages == AnyLanguage)
- str << "any ";
- if (sp.languages & CppLanguage)
+ if (sp.isCppDebugging)
str << "c++ ";
- if (sp.languages & QmlLanguage)
+ if (sp.isQmlDebugging)
str << "qml";
str << '\n';
if (!sp.inferior.executable.isEmpty()) {
str << "Executable: " << QDir::toNativeSeparators(sp.inferior.executable)
<< ' ' << sp.inferior.commandLineArguments;
- if (sp.useTerminal)
+ if (debugger->terminalRunner())
str << " [terminal]";
str << '\n';
if (!sp.inferior.workingDirectory.isEmpty())
@@ -2940,9 +2915,8 @@ static QString formatStartParameters(DebuggerRunParameters &sp)
}
if (!sp.remoteChannel.isEmpty())
str << "Remote: " << sp.remoteChannel << '\n';
- if (!sp.qmlServer.host.isEmpty())
- str << "QML server: " << sp.qmlServer.host << ':'
- << (sp.qmlServer.port.isValid() ? sp.qmlServer.port.number() : -1) << '\n';
+ if (!sp.qmlServer.host().isEmpty())
+ str << "QML server: " << sp.qmlServer.host() << ':' << sp.qmlServer.port() << '\n';
str << "Sysroot: " << sp.sysRoot << '\n';
str << "Debug Source Location: " << sp.debugSourceLocation.join(QLatin1Char(':')) << '\n';
return rc;
@@ -2955,7 +2929,7 @@ void DebuggerPluginPrivate::runControlStarted(DebuggerRunTool *runTool)
.arg(runTool->engine()->objectName())
.arg(runTool->runParameters().toolChainAbi.toString());
showStatusMessage(message);
- showMessage(formatStartParameters(runTool->runParameters()), LogDebug);
+ showMessage(formatStartParameters(runTool), LogDebug);
showMessage(m_debuggerSettings->dump(), LogDebug);
m_snapshotHandler->appendSnapshot(runTool);
connectEngine(runTool);
@@ -2965,11 +2939,13 @@ void DebuggerPluginPrivate::runControlFinished(DebuggerRunTool *runTool)
{
if (runTool && runTool->engine())
runTool->engine()->handleFinished();
- if (m_shuttingDown)
- return;
showStatusMessage(tr("Debugger finished."));
m_snapshotHandler->removeSnapshot(runTool);
if (m_snapshotHandler->size() == 0) {
+ if (m_shuttingDown) {
+ doShutdown();
+ return;
+ }
// Last engine quits.
disconnectEngine();
if (boolSetting(SwitchModeOnExit))
@@ -3147,11 +3123,9 @@ void showModuleSections(const QString &moduleName, const Sections &sections)
createNewDock(w);
}
-void DebuggerPluginPrivate::aboutToShutdown()
+void DebuggerPluginPrivate::doShutdown()
{
- disconnect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, nullptr);
-
- m_mainWindow->saveCurrentPerspective();
+ m_shutdownTimer.stop();
delete m_mainWindow;
m_mainWindow = 0;
@@ -3167,6 +3141,7 @@ void DebuggerPluginPrivate::aboutToShutdown()
delete m_mode;
m_mode = 0;
+ emit m_plugin->asynchronousShutdownFinished();
}
void updateState(DebuggerRunTool *runTool)
@@ -3329,7 +3304,7 @@ IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
{
removeObject(this);
dd->aboutToShutdown();
- return SynchronousShutdown;
+ return AsynchronousShutdown;
}
QObject *DebuggerPlugin::remoteCommand(const QStringList &options,
@@ -3386,17 +3361,19 @@ void DebuggerPluginPrivate::updateActiveLanguages()
{
if (!dd->m_currentRunTool)
return;
- const DebuggerLanguages languages = dd->m_currentRunTool->runParameters().languages;
+ const DebuggerRunParameters &rp = dd->m_currentRunTool->runParameters();
// Id perspective = (languages & QmlLanguage) && !(languages & CppLanguage)
// ? QmlPerspectiveId : CppPerspectiveId;
// m_mainWindow->restorePerspective(perspective);
- for (DebuggerLanguage language: {QmlLanguage, CppLanguage}) {
- const Context context = m_contextsForLanguage.value(language);
- if (languages & language)
- ICore::addAdditionalContext(context);
- else
- ICore::removeAdditionalContext(context);
- }
+ if (rp.isCppDebugging)
+ ICore::addAdditionalContext(Context(C_CPPDEBUGGER));
+ else
+ ICore::removeAdditionalContext(Context(C_CPPDEBUGGER));
+
+ if (rp.isQmlDebugging)
+ ICore::addAdditionalContext(Context(C_QMLDEBUGGER));
+ else
+ ICore::removeAdditionalContext(Context(C_QMLDEBUGGER));
}
void DebuggerPluginPrivate::onModeChanged(Id mode)
@@ -3666,25 +3643,23 @@ void DebuggerUnitTests::testStateMachine()
ProjectExplorerPlugin::buildProject(SessionManager::startupProject());
loop.exec();
- ExecuteOnDestruction guard([] () {
- EditorManager::closeAllEditors(false);
- });
- DebuggerRunParameters rp;
+ ExecuteOnDestruction guard([] { EditorManager::closeAllEditors(false); });
+
Target *t = SessionManager::startupProject()->activeTarget();
QVERIFY(t);
RunConfiguration *rc = t->activeRunConfiguration();
QVERIFY(rc);
- rp.inferior = rc->runnable().as<StandardRunnable>();
- rp.testCase = TestNoBoundsOfCurrentFunction;
auto runControl = new RunControl(rc, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- auto runTool = new DebuggerRunTool(runControl, rp);
+ auto debugger = new DebuggerRunTool(runControl);
- connect(runTool, &DebuggerRunTool::stopped, this, [this] {
- QTestEventLoop::instance().exitLoop();
- });
+ debugger->setInferior(rc->runnable().as<StandardRunnable>());
+ debugger->setTestCase(TestNoBoundsOfCurrentFunction);
+
+ connect(debugger, &DebuggerRunTool::stopped,
+ &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
- ProjectExplorerPlugin::startRunControl(runControl);
+ debugger->startRunControl();
QTestEventLoop::instance().enterLoop(5);
}
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index f2c7036557..236d52afec 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "debuggerruncontrol.h"
+#include "terminal.h"
#include "analyzer/analyzermanager.h"
#include "console/console.h"
@@ -33,7 +34,6 @@
#include "debuggerkitinformation.h"
#include "debuggerplugin.h"
#include "debuggerrunconfigurationaspect.h"
-#include "debuggerstartparameters.h"
#include "breakhandler.h"
#include "shared/peutils.h"
@@ -58,10 +58,13 @@
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/messagebox.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
#include <qtsupport/qtkitinformation.h>
+#include <ssh/sshconnection.h>
+
#include <QTcpServer>
using namespace Debugger::Internal;
@@ -73,15 +76,111 @@ enum { debug = 0 };
namespace Debugger {
namespace Internal {
-DebuggerEngine *createCdbEngine(QStringList *error, DebuggerStartMode sm);
-DebuggerEngine *createGdbEngine(bool useTerminal, DebuggerStartMode sm);
+DebuggerEngine *createCdbEngine();
+DebuggerEngine *createGdbEngine();
DebuggerEngine *createPdbEngine();
-DebuggerEngine *createQmlEngine(bool useTerminal);
-DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal);
+DebuggerEngine *createQmlEngine();
+DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine);
DebuggerEngine *createLldbEngine();
-} // namespace Internal
+class LocalProcessRunner : public RunWorker
+{
+public:
+ LocalProcessRunner(RunControl *runControl, const StandardRunnable &runnable)
+ : RunWorker(runControl), m_runnable(runnable)
+ {
+ connect(&m_proc, &QProcess::errorOccurred,
+ this, &LocalProcessRunner::handleError);
+ connect(&m_proc, &QProcess::readyReadStandardOutput,
+ this, &LocalProcessRunner::handleStandardOutput);
+ connect(&m_proc, &QProcess::readyReadStandardError,
+ this, &LocalProcessRunner::handleStandardError);
+ connect(&m_proc, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ this, &LocalProcessRunner::handleFinished);
+ }
+
+ void start() override
+ {
+ m_proc.setCommand(m_runnable.executable, m_runnable.commandLineArguments);
+ m_proc.start();
+ }
+
+ void stop() override
+ {
+ m_proc.terminate();
+ }
+
+ void handleStandardOutput()
+ {
+ const QByteArray ba = m_proc.readAllStandardOutput();
+ const QString msg = QString::fromLocal8Bit(ba, ba.length());
+ showMessage(msg, LogOutput);
+ showMessage(msg, AppOutput);
+ }
+
+ void handleStandardError()
+ {
+ const QByteArray ba = m_proc.readAllStandardError();
+ const QString msg = QString::fromLocal8Bit(ba, ba.length());
+ showMessage(msg, LogOutput);
+ showMessage(msg, AppError);
+ }
+
+ void handleFinished()
+ {
+ if (m_proc.exitStatus() == QProcess::NormalExit && m_proc.exitCode() == 0) {
+ // all good.
+ reportDone();
+ } else {
+ reportFailure(tr("Upload failed: %1").arg(m_proc.errorString()));
+ }
+ }
+
+ void handleError(QProcess::ProcessError error)
+ {
+ QString msg;
+ switch (error) {
+ case QProcess::FailedToStart:
+ msg = tr("The upload process failed to start. Shell missing?");
+ break;
+ case QProcess::Crashed:
+ msg = tr("The upload process crashed some time after starting "
+ "successfully.");
+ break;
+ case QProcess::Timedout:
+ msg = tr("The last waitFor...() function timed out. "
+ "The state of QProcess is unchanged, and you can try calling "
+ "waitFor...() again.");
+ break;
+ case QProcess::WriteError:
+ msg = tr("An error occurred when attempting to write "
+ "to the upload process. For example, the process may not be running, "
+ "or it may have closed its input channel.");
+ break;
+ case QProcess::ReadError:
+ msg = tr("An error occurred when attempting to read from "
+ "the upload process. For example, the process may not be running.");
+ break;
+ default:
+ msg = tr("An unknown error in the upload process occurred. "
+ "This is the default return value of error().");
+ }
+
+ showMessage(msg, StatusBar);
+ Core::AsynchronousMessageBox::critical(tr("Error"), msg);
+ }
+
+ StandardRunnable m_runnable;
+ Utils::QtcProcess m_proc;
+};
+
+class DebuggerRunToolPrivate
+{
+public:
+ QPointer<TerminalRunner> terminalRunner;
+};
+} // namespace Internal
static bool breakOnMainNextTime = false;
@@ -90,6 +189,237 @@ void DebuggerRunTool::setBreakOnMainNextTime()
breakOnMainNextTime = true;
}
+void DebuggerRunTool::setStartMode(DebuggerStartMode startMode)
+{
+ if (startMode == AttachToQmlServer) {
+ m_runParameters.startMode = AttachToRemoteProcess;
+ m_runParameters.isCppDebugging = false;
+ m_runParameters.isQmlDebugging = true;
+ m_runParameters.masterEngineType = QmlEngineType;
+ m_runParameters.closeMode = KillAtClose;
+
+ // FIXME: This is horribly wrong.
+ // get files from all the projects in the session
+ QList<Project *> projects = SessionManager::projects();
+ if (Project *startupProject = SessionManager::startupProject()) {
+ // startup project first
+ projects.removeOne(startupProject);
+ projects.insert(0, startupProject);
+ }
+ foreach (Project *project, projects)
+ m_runParameters.projectSourceFiles.append(project->files(Project::SourceFiles));
+ if (!projects.isEmpty())
+ m_runParameters.projectSourceDirectory = projects.first()->projectDirectory().toString();
+
+ } else {
+ m_runParameters.startMode = startMode;
+ }
+}
+
+void DebuggerRunTool::setCloseMode(DebuggerCloseMode closeMode)
+{
+ m_runParameters.closeMode = closeMode;
+}
+
+void DebuggerRunTool::setAttachPid(ProcessHandle pid)
+{
+ m_runParameters.attachPID = pid;
+}
+
+void DebuggerRunTool::setAttachPid(qint64 pid)
+{
+ m_runParameters.attachPID = ProcessHandle(pid);
+}
+
+void DebuggerRunTool::setSysRoot(const QString &sysRoot)
+{
+ m_runParameters.sysRoot = sysRoot;
+}
+
+void DebuggerRunTool::setSymbolFile(const QString &symbolFile)
+{
+ if (symbolFile.isEmpty())
+ reportFailure(tr("Cannot debug: Local executable is not set."));
+ m_runParameters.symbolFile = symbolFile;
+}
+
+void DebuggerRunTool::setRemoteChannel(const QString &channel)
+{
+ m_runParameters.remoteChannel = channel;
+}
+
+void DebuggerRunTool::setRemoteChannel(const QString &host, int port)
+{
+ m_runParameters.remoteChannel = QString("%1:%2").arg(host).arg(port);
+}
+
+void DebuggerRunTool::setUseExtendedRemote(bool on)
+{
+ m_runParameters.useExtendedRemote = on;
+}
+
+void DebuggerRunTool::setUseContinueInsteadOfRun(bool on)
+{
+ m_runParameters.useContinueInsteadOfRun = on;
+}
+
+void DebuggerRunTool::setUseTargetAsync(bool on)
+{
+ m_runParameters.useTargetAsync = on;
+}
+
+void DebuggerRunTool::setContinueAfterAttach(bool on)
+{
+ m_runParameters.continueAfterAttach = on;
+}
+
+void DebuggerRunTool::setSkipExecutableValidation(bool on)
+{
+ m_runParameters.skipExecutableValidation = on;
+}
+
+void DebuggerRunTool::setUseCtrlCStub(bool on)
+{
+ m_runParameters.useCtrlCStub = on;
+}
+
+void DebuggerRunTool::setBreakOnMain(bool on)
+{
+ m_runParameters.breakOnMain = on;
+}
+
+void DebuggerRunTool::setUseTerminal(bool on)
+{
+ if (on && !d->terminalRunner && m_runParameters.cppEngineType == GdbEngineType) {
+ d->terminalRunner = new TerminalRunner(this);
+ addStartDependency(d->terminalRunner);
+ }
+ if (!on && d->terminalRunner) {
+ QTC_CHECK(false); // User code can only switch from no terminal to one terminal.
+ }
+}
+
+void DebuggerRunTool::setCommandsAfterConnect(const QString &commands)
+{
+ m_runParameters.commandsAfterConnect = commands;
+}
+
+void DebuggerRunTool::setCommandsForReset(const QString &commands)
+{
+ m_runParameters.commandsForReset = commands;
+}
+
+void DebuggerRunTool::setServerStartScript(const QString &serverStartScript)
+{
+ if (!serverStartScript.isEmpty()) {
+ // Provide script information about the environment
+ StandardRunnable serverStarter;
+ serverStarter.executable = serverStartScript;
+ QtcProcess::addArg(&serverStarter.commandLineArguments, m_runParameters.inferior.executable);
+ QtcProcess::addArg(&serverStarter.commandLineArguments, m_runParameters.remoteChannel);
+ addStartDependency(new LocalProcessRunner(runControl(), serverStarter));
+ }
+}
+
+void DebuggerRunTool::setDebugInfoLocation(const QString &debugInfoLocation)
+{
+ m_runParameters.debugInfoLocation = debugInfoLocation;
+}
+
+void DebuggerRunTool::setQmlServer(const QUrl &qmlServer)
+{
+ m_runParameters.qmlServer = qmlServer;
+}
+
+void DebuggerRunTool::setIosPlatform(const QString &platform)
+{
+ m_runParameters.platform = platform;
+}
+
+void DebuggerRunTool::setDeviceSymbolsRoot(const QString &deviceSymbolsRoot)
+{
+ m_runParameters.deviceSymbolsRoot = deviceSymbolsRoot;
+}
+
+void DebuggerRunTool::setTestCase(int testCase)
+{
+ m_runParameters.testCase = testCase;
+}
+
+void DebuggerRunTool::setOverrideStartScript(const QString &script)
+{
+ m_runParameters.overrideStartScript = script;
+}
+
+void DebuggerRunTool::setInferior(const Runnable &runnable)
+{
+ QTC_ASSERT(runnable.is<StandardRunnable>(), reportFailure(); return);
+ m_runParameters.inferior = runnable.as<StandardRunnable>();
+ setUseTerminal(m_runParameters.inferior.runMode == ApplicationLauncher::Console);
+}
+
+void DebuggerRunTool::setInferiorExecutable(const QString &executable)
+{
+ m_runParameters.inferior.executable = executable;
+}
+
+void DebuggerRunTool::setRunControlName(const QString &name)
+{
+ m_runParameters.displayName = name;
+}
+
+void DebuggerRunTool::setStartMessage(const QString &msg)
+{
+ m_runParameters.startMessage = msg;
+}
+
+void DebuggerRunTool::setCoreFileName(const QString &coreFile, bool isSnapshot)
+{
+ m_runParameters.coreFile = coreFile;
+ m_runParameters.isSnapshot = isSnapshot;
+}
+
+void DebuggerRunTool::appendInferiorCommandLineArgument(const QString &arg)
+{
+ if (!m_runParameters.inferior.commandLineArguments.isEmpty())
+ m_runParameters.inferior.commandLineArguments.append(' ');
+ m_runParameters.inferior.commandLineArguments.append(arg);
+}
+
+void DebuggerRunTool::prependInferiorCommandLineArgument(const QString &arg)
+{
+ if (!m_runParameters.inferior.commandLineArguments.isEmpty())
+ m_runParameters.inferior.commandLineArguments.prepend(' ');
+ m_runParameters.inferior.commandLineArguments.prepend(arg);
+}
+
+void DebuggerRunTool::addQmlServerInferiorCommandLineArgumentIfNeeded()
+{
+ if (isQmlDebugging() && isCppDebugging()) {
+ using namespace QmlDebug;
+ int qmlServerPort = m_runParameters.qmlServer.port();
+ QTC_ASSERT(qmlServerPort > 0, reportFailure(); return);
+ QString mode = QString("port:%1").arg(qmlServerPort);
+ QString qmlServerArg = qmlDebugCommandLineArguments(QmlDebuggerServices, mode, true);
+ prependInferiorCommandLineArgument(qmlServerArg);
+ }
+}
+
+void DebuggerRunTool::setCrashParameter(const QString &event)
+{
+ m_runParameters.crashParameter = event;
+}
+
+void DebuggerRunTool::addExpectedSignal(const QString &signal)
+{
+ m_runParameters.expectedSignals.append(signal);
+}
+
+void DebuggerRunTool::addSearchDirectory(const QString &dir)
+{
+ m_runParameters.additionalSearchDirectories.append(dir);
+}
+
static QLatin1String engineTypeName(DebuggerEngineType et)
{
switch (et) {
@@ -120,23 +450,84 @@ void DebuggerRunTool::start()
TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_DEBUGINFO);
TaskHub::clearTasks(Debugger::Constants::TASK_CATEGORY_DEBUGGER_RUNTIME);
- setupEngine();
- DebuggerEngine *engine = m_engine;
-
- QTC_ASSERT(engine, return);
- const DebuggerRunParameters &rp = engine->runParameters();
// User canceled input dialog asking for executable when working on library project.
- if (rp.startMode == StartInternal
- && rp.inferior.executable.isEmpty()
- && rp.interpreter.isEmpty()) {
- reportFailure(tr("No executable specified.") + '\n');
+ if (m_runParameters.startMode == StartInternal
+ && m_runParameters.inferior.executable.isEmpty()
+ && m_runParameters.interpreter.isEmpty()) {
+ reportFailure(tr("No executable specified."));
+ return;
+ }
+
+ // QML and/or mixed are not prepared for it.
+ setSupportsReRunning(!m_runParameters.isQmlDebugging);
+
+ // FIXME: Disabled due to Android. Make Android device report available ports instead.
+// int portsUsed = portsUsedByDebugger();
+// if (portsUsed > device()->freePorts().count()) {
+// reportFailure(tr("Cannot debug: Not enough free ports available."));
+// return;
+// }
+
+ if (!fixupParameters())
+ return;
+
+ Utils::globalMacroExpander()->registerFileVariables(
+ "DebuggedExecutable", tr("Debugged executable"),
+ [this] { return m_runParameters.inferior.executable; }
+ );
+
+ runControl()->setDisplayName(m_runParameters.displayName);
+
+ DebuggerEngine *cppEngine = nullptr;
+ if (!m_engine) {
+ switch (m_runParameters.cppEngineType) {
+ case GdbEngineType:
+ cppEngine = createGdbEngine();
+ break;
+ case CdbEngineType:
+ if (!HostOsInfo::isWindowsHost()) {
+ reportFailure(tr("Unsupported CDB host system."));
+ return;
+ }
+ cppEngine = createCdbEngine();
+ break;
+ case LldbEngineType:
+ cppEngine = createLldbEngine();
+ break;
+ case PdbEngineType: // FIXME: Yes, Python counts as C++...
+ cppEngine = createPdbEngine();
+ break;
+ default:
+ QTC_CHECK(false);
+ break;
+ }
+ }
+
+ switch (m_runParameters.masterEngineType) {
+ case QmlEngineType:
+ m_engine = createQmlEngine();
+ break;
+ case QmlCppEngineType:
+ if (cppEngine)
+ m_engine = createQmlCppEngine(cppEngine);
+ break;
+ default:
+ m_engine = cppEngine;
+ break;
+ }
+
+ if (!m_engine) {
+ reportFailure(DebuggerPlugin::tr("Unable to create a debugging engine of the type \"%1\"").
+ arg(engineTypeName(m_runParameters.masterEngineType)));
return;
}
- if (rp.startMode == StartInternal) {
+ m_engine->setRunTool(this);
+
+ if (m_runParameters.startMode == StartInternal) {
QStringList unhandledIds;
foreach (Breakpoint bp, breakHandler()->allBreakpoints()) {
- if (bp.isEnabled() && !engine->acceptsBreakpoint(bp))
+ if (bp.isEnabled() && !m_engine->acceptsBreakpoint(bp))
unhandledIds.append(bp.id().toString());
}
if (!unhandledIds.isEmpty()) {
@@ -160,7 +551,7 @@ void DebuggerRunTool::start()
appendMessage(tr("Debugging starts"), NormalMessageFormat);
Internal::runControlStarted(this);
- engine->start();
+ m_engine->start();
}
void DebuggerRunTool::startFailed()
@@ -183,14 +574,19 @@ void DebuggerRunTool::debuggingFinished()
reportStopped();
}
-DebuggerRunParameters &DebuggerRunTool::runParameters()
+const DebuggerRunParameters &DebuggerRunTool::runParameters() const
{
return m_runParameters;
}
-const DebuggerRunParameters &DebuggerRunTool::runParameters() const
+bool DebuggerRunTool::isCppDebugging() const
{
- return m_runParameters;
+ return m_runParameters.isCppDebugging;
+}
+
+bool DebuggerRunTool::isQmlDebugging() const
+{
+ return m_runParameters.isQmlDebugging;
}
int DebuggerRunTool::portsUsedByDebugger() const
@@ -198,6 +594,11 @@ int DebuggerRunTool::portsUsedByDebugger() const
return isCppDebugging() + isQmlDebugging();
}
+void DebuggerRunTool::setSolibSearchPath(const QStringList &list)
+{
+ m_runParameters.solibSearchPath = list;
+}
+
void DebuggerRunTool::notifyInferiorIll()
{
m_engine->notifyInferiorIll();
@@ -219,191 +620,34 @@ void DebuggerRunTool::abortDebugger()
m_engine->abortDebugger();
}
-///////////////////////////////////////////////////////////////////////
-//
-// DebuggerRunControlCreator
-//
-///////////////////////////////////////////////////////////////////////
-
-namespace Internal {
-
-// Re-used for Combined C++/QML engine.
-DebuggerEngine *createEngine(DebuggerEngineType cppEngineType,
- DebuggerEngineType et,
- DebuggerStartMode sm,
- bool useTerminal,
- QStringList *errors)
+bool DebuggerRunTool::fixupParameters()
{
- DebuggerEngine *engine = nullptr;
- switch (et) {
- case GdbEngineType:
- engine = createGdbEngine(useTerminal, sm);
- break;
- case CdbEngineType:
- engine = createCdbEngine(errors, sm);
- break;
- case PdbEngineType:
- engine = createPdbEngine();
- break;
- case QmlEngineType:
- engine = createQmlEngine(useTerminal);
- break;
- case LldbEngineType:
- engine = createLldbEngine();
- break;
- case QmlCppEngineType: {
- DebuggerEngine *cppEngine = createEngine(cppEngineType, cppEngineType, sm, useTerminal, errors);
- if (cppEngine) {
- engine = createQmlCppEngine(cppEngine, useTerminal);
- } else {
- errors->append(DebuggerPlugin::tr("The debugging engine required for combined "
- "QML/C++ debugging could not be created: %1"));
- }
- break;
- }
- default:
- errors->append(DebuggerPlugin::tr("Unknown debugger type \"%1\"")
- .arg(engineTypeName(et)));
- }
- if (!engine)
- errors->append(DebuggerPlugin::tr("Unable to create a debugging engine of the type \"%1\"").
- arg(engineTypeName(et)));
- return engine;
-}
-
-static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, QStringList &m_errors)
-{
- RunConfiguration *runConfig = runControl->runConfiguration();
- if (!runConfig)
- return false;
-
- const Kit *kit = runConfig->target()->kit();
- QTC_ASSERT(kit, return false);
-
- // Extract as much as possible from available RunConfiguration.
- const Runnable runnable = runConfig->runnable();
- if (rp.needFixup && runnable.is<StandardRunnable>()) {
- // FIXME: Needed for core dump which stores the executable in inferior, but not in runConfig
- // executable.
- const QString prevExecutable = rp.inferior.executable;
- rp.inferior = runnable.as<StandardRunnable>();
- if (rp.inferior.executable.isEmpty())
- rp.inferior.executable = prevExecutable;
- rp.useTerminal = rp.inferior.runMode == ApplicationLauncher::Console;
- // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
- rp.inferior.workingDirectory = FileUtils::normalizePathName(rp.inferior.workingDirectory);
- }
-
- // We might get an executable from a local PID.
- if (rp.needFixup && rp.inferior.executable.isEmpty() && rp.attachPID.isValid()) {
- foreach (const DeviceProcessItem &p, DeviceProcessList::localProcesses()) {
- if (p.pid == rp.attachPID.pid()) {
- rp.inferior.executable = p.exe;
- break;
- }
- }
- }
-
- rp.macroExpander = kit->macroExpander();
+ DebuggerRunParameters &rp = m_runParameters;
if (rp.symbolFile.isEmpty())
rp.symbolFile = rp.inferior.executable;
- rp.debugger = DebuggerKitInformation::runnable(kit);
- const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH");
- if (!envBinary.isEmpty())
- rp.debugger.executable = QString::fromLocal8Bit(envBinary);
-
- if (rp.needFixup) {
- if (auto envAspect = runConfig->extraAspect<EnvironmentAspect>()) {
- rp.inferior.environment = envAspect->environment(); // Correct.
- rp.stubEnvironment = rp.inferior.environment; // FIXME: Wrong, but contains DYLD_IMAGE_SUFFIX
-
- // Copy over DYLD_IMAGE_SUFFIX etc
- for (auto var : QStringList({"DYLD_IMAGE_SUFFIX", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH"}))
- if (rp.inferior.environment.hasKey(var))
- rp.debugger.environment.set(var, rp.inferior.environment.value(var));
- }
- }
- if (Project *project = runConfig->target()->project()) {
- rp.projectSourceDirectory = project->projectDirectory().toString();
- rp.projectSourceFiles = project->files(Project::SourceFiles);
- }
-
- rp.toolChainAbi = ToolChainKitInformation::targetAbi(kit);
-
- bool ok = false;
- int nativeMixedOverride = qgetenv("QTC_DEBUGGER_NATIVE_MIXED").toInt(&ok);
- if (ok)
- rp.nativeMixedEnabled = bool(nativeMixedOverride);
-
- rp.cppEngineType = DebuggerKitInformation::engineType(kit);
- if (rp.sysRoot.isEmpty())
- rp.sysRoot = SysRootKitInformation::sysRoot(kit).toString();
-
- if (rp.displayName.isEmpty())
- rp.displayName = runConfig->displayName();
-
- if (runConfig->property("supportsDebugger").toBool()) {
- QString mainScript = runConfig->property("mainScript").toString();
- QString interpreter = runConfig->property("interpreter").toString();
- if (!interpreter.isEmpty() && mainScript.endsWith(".py")) {
- rp.mainScript = mainScript;
- rp.interpreter = interpreter;
- QString args = runConfig->property("arguments").toString();
- if (!args.isEmpty()) {
- if (!rp.inferior.commandLineArguments.isEmpty())
- rp.inferior.commandLineArguments.append(QLatin1Char(' '));
- rp.inferior.commandLineArguments.append(args);
- }
- rp.masterEngineType = PdbEngineType;
- }
- }
-
- if (auto debuggerAspect = runConfig->extraAspect<DebuggerRunConfigurationAspect>()) {
- rp.multiProcess = debuggerAspect->useMultiProcess();
- if (rp.languages == NoLanguage) {
- if (debuggerAspect->useCppDebugger())
- rp.languages |= CppLanguage;
- if (debuggerAspect->useQmlDebugger())
- rp.languages |= QmlLanguage;
- }
- }
+ rp.stubEnvironment = rp.inferior.environment; // FIXME: Wrong, but contains DYLD_IMAGE_SUFFIX
- // This can happen e.g. when started from the command line.
- if (rp.languages == NoLanguage)
- rp.languages = CppLanguage;
+ // Copy over DYLD_IMAGE_SUFFIX etc
+ for (auto var : QStringList({"DYLD_IMAGE_SUFFIX", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH"}))
+ if (rp.inferior.environment.hasKey(var))
+ rp.debugger.environment.set(var, rp.inferior.environment.value(var));
// validate debugger if C++ debugging is enabled
- if (rp.languages & CppLanguage) {
- const QList<Task> tasks = DebuggerKitInformation::validateDebugger(kit);
- if (!tasks.isEmpty()) {
- foreach (const Task &t, tasks) {
- if (t.type == Task::Warning)
- continue;
- m_errors.append(t.description);
- }
- if (!m_errors.isEmpty())
- return false;
- }
+ if (rp.isCppDebugging && !rp.validationErrors.isEmpty()) {
+ reportFailure(rp.validationErrors.join('\n'));
+ return false;
}
- IDevice::ConstPtr device = runControl->device();
- if (rp.languages & QmlLanguage) {
- if (device && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
- if (rp.qmlServer.host.isEmpty() || !rp.qmlServer.port.isValid()) {
- QTcpServer server;
- const bool canListen = server.listen(QHostAddress::LocalHost)
- || server.listen(QHostAddress::LocalHostIPv6);
- if (!canListen) {
- m_errors.append(DebuggerPlugin::tr("Not enough free ports for QML debugging.") + ' ');
+ if (rp.isQmlDebugging) {
+ if (device() && device()->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
+ if (rp.qmlServer.port() <= 0) {
+ rp.qmlServer = ProjectExplorer::urlFromLocalHostAndFreePort();
+ if (rp.qmlServer.port() <= 0) {
+ reportFailure(DebuggerPlugin::tr("Not enough free ports for QML debugging."));
return false;
}
- TcpServerConnection conn;
- conn.host = server.serverAddress().toString();
- conn.port = Utils::Port(server.serverPort());
- rp.qmlServer = conn;
}
-
// Makes sure that all bindings go through the JavaScript engine, so that
// breakpoints are actually hit!
const QString optimizerKey = "QML_DISABLE_OPTIMIZER";
@@ -425,9 +669,9 @@ static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, Q
}
if (rp.masterEngineType == NoEngineType) {
- if (rp.languages & QmlLanguage) {
+ if (rp.isQmlDebugging) {
QmlDebug::QmlDebugServicesPreset service;
- if (rp.languages & CppLanguage) {
+ if (rp.isCppDebugging) {
if (rp.nativeMixedEnabled) {
service = QmlDebug::QmlNativeDebuggerServices;
} else {
@@ -439,10 +683,10 @@ static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, Q
service = QmlDebug::QmlDebuggerServices;
}
if (rp.startMode != AttachExternal && rp.startMode != AttachCrashedExternal) {
- QtcProcess::addArg(&rp.inferior.commandLineArguments,
- (rp.languages & CppLanguage) && rp.nativeMixedEnabled ?
- QmlDebug::qmlDebugNativeArguments(service, false) :
- QmlDebug::qmlDebugTcpArguments(service, rp.qmlServer.port));
+ QString qmlarg = rp.isCppDebugging && rp.nativeMixedEnabled
+ ? QmlDebug::qmlDebugNativeArguments(service, false)
+ : QmlDebug::qmlDebugTcpArguments(service, Port(rp.qmlServer.port()));
+ QtcProcess::addArg(&rp.inferior.commandLineArguments, qmlarg);
}
}
}
@@ -458,36 +702,42 @@ static bool fixupParameters(DebuggerRunParameters &rp, RunControl *runControl, Q
breakOnMainNextTime = false;
}
- return true;
-}
+ if (HostOsInfo::isWindowsHost()) {
+ QtcProcess::SplitError perr;
+ rp.inferior.commandLineArguments =
+ QtcProcess::prepareArgs(rp.inferior.commandLineArguments, &perr,
+ HostOsInfo::hostOs(), nullptr,
+ &rp.inferior.workingDirectory).toWindowsArgs();
+ if (perr != QtcProcess::SplitOk) {
+ // perr == BadQuoting is never returned on Windows
+ // FIXME? QTCREATORBUG-2809
+ reportFailure(DebuggerPlugin::tr("Debugging complex command lines "
+ "is currently not supported on Windows."));
+ return false;
+ }
+ }
-} // Internal
+ if (rp.isNativeMixedDebugging())
+ rp.inferior.environment.set("QV4_FORCE_INTERPRETER", "1");
-static DebuggerRunConfigurationAspect *debuggerAspect(const RunControl *runControl)
-{
- return runControl->runConfiguration()->extraAspect<DebuggerRunConfigurationAspect>();
-}
+ if (rp.isCppDebugging && !rp.skipExecutableValidation)
+ rp.validateExecutable();
-static bool cppDebugging(const RunControl *runControl)
-{
- auto aspect = debuggerAspect(runControl);
- return aspect ? aspect->useCppDebugger() : true; // For cases like valgrind-with-gdb.
+ return true;
}
-static bool qmlDebugging(const RunControl *runControl)
+Internal::TerminalRunner *DebuggerRunTool::terminalRunner() const
{
- auto aspect = debuggerAspect(runControl);
- return aspect ? aspect->useQmlDebugger() : false; // For cases like valgrind-with-gdb.
+ return d->terminalRunner;
}
-/// DebuggerRunTool
-
-DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
- : RunWorker(runControl),
- m_isCppDebugging(cppDebugging(runControl)),
- m_isQmlDebugging(qmlDebugging(runControl))
+DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit)
+ : RunWorker(runControl), d(new DebuggerRunToolPrivate)
{
setDisplayName("DebuggerRunTool");
+
+ RunConfiguration *runConfig = runControl->runConfiguration();
+
runControl->setIcon(ProjectExplorer::Icons::DEBUG_START_SMALL_TOOLBAR);
runControl->setPromptToStop([](bool *optionalPrompt) {
return RunControl::showPromptToStopDialog(
@@ -498,62 +748,75 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
" Would you still like to terminate it?"),
QString(), QString(), optionalPrompt);
});
-}
-
-DebuggerRunTool::DebuggerRunTool(RunControl *runControl, const DebuggerStartParameters &sp)
- : DebuggerRunTool(runControl)
-{
- setStartParameters(sp);
-}
-DebuggerRunTool::DebuggerRunTool(RunControl *runControl, const DebuggerRunParameters &rp)
- : DebuggerRunTool(runControl)
-{
- setRunParameters(rp);
-}
+ if (runConfig)
+ m_runParameters.displayName = runConfig->displayName();
-void DebuggerRunTool::setStartParameters(const DebuggerStartParameters &sp)
-{
- setRunParameters(sp);
-}
+ if (runConfig && !kit)
+ kit = runConfig->target()->kit();
+ QTC_ASSERT(kit, return);
-void DebuggerRunTool::setRunParameters(const DebuggerRunParameters &rp)
-{
- m_runParameters = rp;
-}
+ m_runParameters.cppEngineType = DebuggerKitInformation::engineType(kit);
+ m_runParameters.sysRoot = SysRootKitInformation::sysRoot(kit).toString();
+ m_runParameters.macroExpander = kit->macroExpander();
+ m_runParameters.debugger = DebuggerKitInformation::runnable(kit);
-void DebuggerRunTool::setupEngine()
-{
- // QML and/or mixed are not prepared for it.
- setSupportsReRunning(!(m_runParameters.languages & QmlLanguage));
+ Runnable r = runnable();
+ if (r.is<StandardRunnable>()) {
+ m_runParameters.inferior = r.as<StandardRunnable>();
+ // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
+ m_runParameters.inferior.workingDirectory =
+ FileUtils::normalizePathName(m_runParameters.inferior.workingDirectory);
+ setUseTerminal(m_runParameters.inferior.runMode == ApplicationLauncher::Console);
+ }
- // FIXME: Disabled due to Android. Make Android device report available ports instead.
-// int portsUsed = portsUsedByDebugger();
-// if (portsUsed > device()->freePorts().count()) {
-// reportFailure(tr("Cannot debug: Not enough free ports available."));
-// return;
-// }
+ if (auto aspect = runConfig ? runConfig->extraAspect<DebuggerRunConfigurationAspect>() : nullptr) {
+ m_runParameters.isCppDebugging = aspect->useCppDebugger();
+ m_runParameters.isQmlDebugging = aspect->useQmlDebugger();
+ m_runParameters.multiProcess = aspect->useMultiProcess();
+ }
- if (Internal::fixupParameters(m_runParameters, runControl(), m_errors)) {
- m_engine = createEngine(m_runParameters.cppEngineType,
- m_runParameters.masterEngineType,
- m_runParameters.startMode,
- m_runParameters.useTerminal,
- &m_errors);
- if (!m_engine) {
- reportFailure(m_errors.join('\n'));
- return;
- }
+ const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH");
+ if (!envBinary.isEmpty())
+ m_runParameters.debugger.executable = QString::fromLocal8Bit(envBinary);
- Utils::globalMacroExpander()->registerFileVariables(
- "DebuggedExecutable", tr("Debugged executable"),
- [this] { return m_runParameters.inferior.executable; }
- );
+ Project *project = runConfig ? runConfig->target()->project() : nullptr;
+ if (project) {
+ m_runParameters.projectSourceDirectory = project->projectDirectory().toString();
+ m_runParameters.projectSourceFiles = project->files(Project::SourceFiles);
}
- runControl()->setDisplayName(m_runParameters.displayName);
+ m_runParameters.toolChainAbi = ToolChainKitInformation::targetAbi(kit);
- m_engine->setRunTool(this);
+ bool ok = false;
+ int nativeMixedOverride = qgetenv("QTC_DEBUGGER_NATIVE_MIXED").toInt(&ok);
+ if (ok)
+ m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride);
+
+ // This will only be shown in some cases, but we don't want to access
+ // the kit at that time anymore.
+ const QList<Task> tasks = DebuggerKitInformation::validateDebugger(kit);
+ for (const Task &t : tasks) {
+ if (t.type != Task::Warning)
+ m_runParameters.validationErrors.append(t.description);
+ }
+
+ if (runConfig && runConfig->property("supportsDebugger").toBool()) {
+ const QString mainScript = runConfig->property("mainScript").toString();
+ const QString interpreter = runConfig->property("interpreter").toString();
+ if (!interpreter.isEmpty() && mainScript.endsWith(".py")) {
+ m_runParameters.mainScript = mainScript;
+ m_runParameters.interpreter = interpreter;
+ const QString args = runConfig->property("arguments").toString();
+ if (!args.isEmpty()) {
+ if (!m_runParameters.inferior.commandLineArguments.isEmpty())
+ m_runParameters.inferior.commandLineArguments.append(' ');
+ m_runParameters.inferior.commandLineArguments.append(args);
+ }
+ m_runParameters.cppEngineType = PdbEngineType;
+ m_runParameters.masterEngineType = PdbEngineType;
+ }
+ }
}
DebuggerEngine *DebuggerRunTool::activeEngine() const
@@ -561,7 +824,12 @@ DebuggerEngine *DebuggerRunTool::activeEngine() const
return m_engine ? m_engine->activeEngine() : nullptr;
}
-void DebuggerRunTool::appendSolibSearchPath(const QString &str)
+void DebuggerRunTool::startRunControl()
+{
+ ProjectExplorerPlugin::startRunControl(runControl());
+}
+
+void DebuggerRunTool::addSolibSearchDir(const QString &str)
{
QString path = str;
path.replace("%{sysroot}", m_runParameters.sysRoot);
@@ -577,6 +845,7 @@ DebuggerRunTool::~DebuggerRunTool()
engine->disconnect();
delete engine;
}
+ delete d;
}
void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout)
@@ -606,44 +875,6 @@ void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout)
//
////////////////////////////////////////////////////////////////////////
-namespace Internal {
-
-/**
- * Used for direct "special" starts from actions in the debugger plugin.
- */
-
-class DummyProject : public Project
-{
-public:
- DummyProject() : Project(QString(""), FileName::fromString("")) {}
-};
-
-RunConfiguration *dummyRunConfigForKit(ProjectExplorer::Kit *kit)
-{
- QTC_ASSERT(kit, return nullptr); // Caller needs to look for a suitable kit.
- Project *project = SessionManager::startupProject();
- Target *target = project ? project->target(kit) : nullptr;
- if (!target || !target->activeRunConfiguration()) {
- project = new DummyProject;
- target = project->createTarget(kit);
- }
- QTC_ASSERT(target, return nullptr);
- auto runConfig = target->activeRunConfiguration();
- return runConfig;
-}
-
-RunControl *createAndScheduleRun(const DebuggerRunParameters &rp, Kit *kit)
-{
- RunConfiguration *runConfig = dummyRunConfigForKit(kit);
- QTC_ASSERT(runConfig, return nullptr);
- auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- (void) new DebuggerRunTool(runControl, rp);
- ProjectExplorerPlugin::startRunControl(runControl);
- return runControl;
-}
-
-} // Internal
-
// GdbServerPortGatherer
GdbServerPortsGatherer::GdbServerPortsGatherer(RunControl *runControl)
@@ -661,6 +892,19 @@ GdbServerPortsGatherer::~GdbServerPortsGatherer()
{
}
+QString GdbServerPortsGatherer::gdbServerChannel() const
+{
+ const QString host = device()->sshParameters().host;
+ return QString("%1:%2").arg(host).arg(m_gdbServerPort.number());
+}
+
+QUrl GdbServerPortsGatherer::qmlServer() const
+{
+ QUrl server = device()->toolControlChannel(IDevice::QmlControlChannel);
+ server.setPort(m_qmlServerPort.number());
+ return server;
+}
+
void GdbServerPortsGatherer::start()
{
appendMessage(tr("Checking available ports..."), NormalMessageFormat);
@@ -670,7 +914,7 @@ void GdbServerPortsGatherer::start()
void GdbServerPortsGatherer::handlePortListReady()
{
Utils::PortList portList = device()->freePorts();
- appendMessage(tr("Found %1 free ports").arg(portList.count()), NormalMessageFormat);
+ appendMessage(tr("Found %n free ports.", nullptr, portList.count()), NormalMessageFormat);
if (m_useGdbServer) {
m_gdbServerPort = m_portsGatherer.getNextFreePort(&portList);
if (!m_gdbServerPort.isValid()) {
@@ -685,7 +929,8 @@ void GdbServerPortsGatherer::handlePortListReady()
return;
}
}
- reportDone();
+// reportDone();
+ reportStarted();
}
// GdbServerRunner
diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h
index ec5dffaac0..794ee3ee6b 100644
--- a/src/plugins/debugger/debuggerruncontrol.h
+++ b/src/plugins/debugger/debuggerruncontrol.h
@@ -32,29 +32,30 @@
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
+#include <ssh/sshconnection.h> // FIXME: Remove after downstream was adapted
+#include <QHostAddress> // FIXME: Remove after downstream was adapted
+
namespace Debugger {
-class DebuggerStartParameters;
+namespace Internal {
+class TerminalRunner;
+class DebuggerRunToolPrivate;
+} // Internal
class DEBUGGER_EXPORT DebuggerRunTool : public ProjectExplorer::RunWorker
{
Q_OBJECT
public:
- DebuggerRunTool(ProjectExplorer::RunControl *runControl); // Use.
-
- DebuggerRunTool(ProjectExplorer::RunControl *runControl,
- const DebuggerStartParameters &sp); // Use rarely.
- DebuggerRunTool(ProjectExplorer::RunControl *runControl,
- const Internal::DebuggerRunParameters &rp); // FIXME: Don't use.
+ explicit DebuggerRunTool(ProjectExplorer::RunControl *runControl,
+ ProjectExplorer::Kit *kit = nullptr);
~DebuggerRunTool();
- void setStartParameters(const DebuggerStartParameters &sp); // Use rarely.
- void setRunParameters(const Internal::DebuggerRunParameters &rp); // FIXME: Don't use.
-
Internal::DebuggerEngine *engine() const { return m_engine; }
Internal::DebuggerEngine *activeEngine() const;
+ void startRunControl();
+
void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1);
void start() override;
@@ -68,31 +69,81 @@ public:
void abortDebugger();
void debuggingFinished();
- Internal::DebuggerRunParameters &runParameters();
const Internal::DebuggerRunParameters &runParameters() const;
void startDying() { m_isDying = true; }
bool isDying() const { return m_isDying; }
- bool isCppDebugging() const { return m_isCppDebugging; }
- bool isQmlDebugging() const { return m_isQmlDebugging; }
+ bool isCppDebugging() const;
+ bool isQmlDebugging() const;
int portsUsedByDebugger() const;
- void appendSolibSearchPath(const QString &str);
+ void setSolibSearchPath(const QStringList &list);
+ void addSolibSearchDir(const QString &str);
static void setBreakOnMainNextTime();
+ void setInferior(const ProjectExplorer::Runnable &runnable);
+ void setInferiorExecutable(const QString &executable);
+ void setRunControlName(const QString &name);
+ void setStartMessage(const QString &msg);
+ void appendInferiorCommandLineArgument(const QString &arg);
+ void prependInferiorCommandLineArgument(const QString &arg);
+ void addQmlServerInferiorCommandLineArgumentIfNeeded();
+
+ void setCrashParameter(const QString &event);
+
+ void addExpectedSignal(const QString &signal);
+ void addSearchDirectory(const QString &dir);
+
+ void setStartMode(DebuggerStartMode startMode);
+ void setCloseMode(DebuggerCloseMode closeMode);
+
+ void setAttachPid(Utils::ProcessHandle pid);
+ void setAttachPid(qint64 pid);
+
+ void setSysRoot(const QString &sysRoot);
+ void setSymbolFile(const QString &symbolFile);
+ void setRemoteChannel(const QString &channel);
+ void setRemoteChannel(const QString &host, int port);
+
+ void setUseExtendedRemote(bool on);
+ void setUseContinueInsteadOfRun(bool on);
+ void setUseTargetAsync(bool on);
+ void setContinueAfterAttach(bool on);
+ void setSkipExecutableValidation(bool on);
+ void setUseCtrlCStub(bool on);
+ void setBreakOnMain(bool on);
+ void setUseTerminal(bool on);
+
+ void setCommandsAfterConnect(const QString &commands);
+ void setCommandsForReset(const QString &commands);
+
+ void setServerStartScript(const QString &serverStartScript);
+ void setDebugInfoLocation(const QString &debugInfoLocation);
+
+ void setQmlServer(const QUrl &qmlServer);
+
+ void setCoreFileName(const QString &core, bool isSnapshot = false);
+
+ void setIosPlatform(const QString &platform);
+ void setDeviceSymbolsRoot(const QString &deviceSymbolsRoot);
+
+ void setNeedFixup(bool) {} // FIXME: Remove after use in QtAppMan is gone.
+ void setTestCase(int testCase);
+ void setOverrideStartScript(const QString &script);
+
+ Internal::TerminalRunner *terminalRunner() const;
+
signals:
void aboutToNotifyInferiorSetupOk();
private:
- void setupEngine();
+ bool fixupParameters();
+ Internal::DebuggerRunToolPrivate *d;
QPointer<Internal::DebuggerEngine> m_engine; // Master engine
Internal::DebuggerRunParameters m_runParameters;
- QStringList m_errors;
bool m_isDying = false;
- const bool m_isCppDebugging;
- const bool m_isQmlDebugging;
};
class DEBUGGER_EXPORT GdbServerPortsGatherer : public ProjectExplorer::RunWorker
@@ -106,10 +157,12 @@ public:
void setUseGdbServer(bool useIt) { m_useGdbServer = useIt; }
bool useGdbServer() const { return m_useGdbServer; }
Utils::Port gdbServerPort() const { return m_gdbServerPort; }
+ QString gdbServerChannel() const;
void setUseQmlServer(bool useIt) { m_useQmlServer = useIt; }
bool useQmlServer() const { return m_useQmlServer; }
Utils::Port qmlServerPort() const { return m_qmlServerPort; }
+ QUrl qmlServer() const;
private:
void start() override;
diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
index 313cecefd7..f1a5e17d35 100644
--- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
+++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp
@@ -215,7 +215,7 @@ DebuggerSourcePathMappingWidget::DebuggerSourcePathMappingWidget(QWidget *parent
"at which the modules where built, for example, while "
"doing remote debugging.</p>"
"<p>If source is specified as a regular expression by starting it with an "
- "open parenthesis, Qt Creator matches the paths in the ELF with the "
+ "open parenthesis, the paths in the ELF are matched with the "
"regular expression to automatically determine the source path.</p>"
"<p>Example: <b>(/home/.*/Project)/KnownSubDir -> D:\\Project</b> will "
"substitute ELF built by any user to your local project directory.</p>"));
diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h
index db055341ce..da1bca1723 100644
--- a/src/plugins/debugger/debuggerstartparameters.h
+++ b/src/plugins/debugger/debuggerstartparameters.h
@@ -1,112 +1,2 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-#pragma once
-
-#include "debugger_global.h"
-#include "debuggerconstants.h"
-
-#include <ssh/sshconnection.h>
-#include <utils/environment.h>
-#include <utils/port.h>
-#include <utils/processhandle.h>
-#include <projectexplorer/abi.h>
-#include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/runnables.h>
-#include <projectexplorer/devicesupport/idevice.h>
-
-#include <QMetaType>
-#include <QVector>
-#include <QPointer>
-
-namespace Debugger {
-
-// Note: This is part of the "soft interface" of the debugger plugin.
-// Do not add anything that needs implementation in a .cpp file.
-
-class DEBUGGER_EXPORT TcpServerConnection
-{
-public:
- QString host;
- Utils::Port port;
-};
-
-class DEBUGGER_EXPORT DebuggerStartParameters
-{
-public:
- DebuggerStartMode startMode = NoStartMode;
- DebuggerCloseMode closeMode = KillAtClose;
-
- ProjectExplorer::StandardRunnable inferior;
- QString displayName; // Used in the Snapshots view.
- Utils::Environment stubEnvironment;
- Utils::ProcessHandle attachPID;
- QStringList solibSearchPath;
- bool useTerminal = false;
- bool needFixup = true; // FIXME: Make false the default...
-
- // Used by Qml debugging.
- TcpServerConnection qmlServer;
-
- // Used by general remote debugging.
- QString remoteChannel;
- bool useExtendedRemote = false; // Whether to use GDB's target extended-remote or not.
- QString symbolFile;
-
- // Used by Mer plugin (3rd party)
- QMap<QString, QString> sourcePathMap;
-
- // Used by baremetal plugin
- QString commandsForReset; // commands used for resetting the inferior
- bool useContinueInsteadOfRun = false; // if connected to a hw debugger run is not possible but continue is used
- QString commandsAfterConnect; // additional commands to post after connection to debug target
-
- // Used by Valgrind
- QStringList expectedSignals;
-
- // For QNX debugging
- bool useCtrlCStub = false;
-
- // Used by Android to avoid false positives on warnOnRelease
- bool skipExecutableValidation = false;
- bool useTargetAsync = false;
- QStringList additionalSearchDirectories;
-
- // Used by iOS.
- QString platform;
- QString deviceSymbolsRoot;
- bool continueAfterAttach = false;
- QString sysRoot;
-
- // Used by general core file debugging. Public access requested in QTCREATORBUG-17158.
- QString coreFile;
-
- // Macro-expanded and passed to debugger startup.
- QString additionalStartupCommands;
-};
-
-} // namespace Debugger
-
-Q_DECLARE_METATYPE(Debugger::DebuggerStartParameters)
+// Remove after downstream was adapted
diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp
index 7e2b01b7bd..6ed4255247 100644
--- a/src/plugins/debugger/disassembleragent.cpp
+++ b/src/plugins/debugger/disassembleragent.cpp
@@ -30,7 +30,6 @@
#include "debuggercore.h"
#include "debuggerengine.h"
#include "debuggerinternalconstants.h"
-#include "debuggerstartparameters.h"
#include "disassemblerlines.h"
#include "sourceutils.h"
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp
deleted file mode 100644
index 519647d703..0000000000
--- a/src/plugins/debugger/gdb/attachgdbadapter.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "attachgdbadapter.h"
-
-#include <coreplugin/messagebox.h>
-
-#include <debugger/debuggerprotocol.h>
-#include <debugger/debuggerstartparameters.h>
-
-#include <utils/qtcassert.h>
-#include <utils/qtcfallthrough.h>
-
-namespace Debugger {
-namespace Internal {
-
-GdbAttachEngine::GdbAttachEngine(bool useTerminal)
- : GdbEngine(useTerminal)
-{
-}
-
-void GdbAttachEngine::setupEngine()
-{
- QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
- showMessage("TRYING TO START ADAPTER");
-
- startGdb();
-}
-
-void GdbAttachEngine::setupInferior()
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- // Task 254674 does not want to remove them
- //qq->breakHandler()->removeAllBreakpoints();
- handleInferiorPrepared();
-}
-
-void GdbAttachEngine::runEngine()
-{
- QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
- const qint64 pid = runParameters().attachPID.pid();
- showStatusMessage(tr("Attaching to process %1.").arg(pid));
- runCommand({"attach " + QString::number(pid),
- [this](const DebuggerResponse &r) { handleAttach(r); }});
- // In some cases we get only output like
- // "Could not attach to process. If your uid matches the uid of the target\n"
- // "process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try\n"
- // " again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf\n"
- // " ptrace: Operation not permitted.\n"
- // but no(!) ^ response. Use a second command to force *some* output
- runCommand({"print 24"});
-}
-
-void GdbAttachEngine::handleAttach(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == EngineRunRequested || state() == InferiorStopOk,
- qDebug() << state());
- switch (response.resultClass) {
- case ResultDone:
- case ResultRunning:
- showMessage("INFERIOR ATTACHED");
- if (state() == EngineRunRequested) {
- // Happens e.g. for "Attach to unstarted application"
- // We will get a '*stopped' later that we'll interpret as 'spontaneous'
- // So acknowledge the current state and put a delayed 'continue' in the pipe.
- showMessage(tr("Attached to running application"), StatusBar);
- notifyEngineRunAndInferiorRunOk();
- } else {
- // InferiorStopOk, e.g. for "Attach to running application".
- // The *stopped came in between sending the 'attach' and
- // receiving its '^done'.
- if (runParameters().continueAfterAttach)
- continueInferiorInternal();
- }
- break;
- case ResultError:
- if (response.data["msg"].data() == "ptrace: Operation not permitted.") {
- QString msg = msgPtraceError(runParameters().startMode);
- showStatusMessage(tr("Failed to attach to application: %1").arg(msg));
- Core::AsynchronousMessageBox::warning(tr("Debugger Error"), msg);
- notifyEngineIll();
- break;
- }
- Q_FALLTHROUGH(); // if msg != "ptrace: ..."
- default:
- showStatusMessage(tr("Failed to attach to application: %1")
- .arg(QString(response.data["msg"].data())));
- notifyEngineIll();
- }
-}
-
-void GdbAttachEngine::interruptInferior2()
-{
- interruptLocalInferior(runParameters().attachPID.pid());
-}
-
-void GdbAttachEngine::shutdownEngine()
-{
- notifyAdapterShutdownOk();
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp
deleted file mode 100644
index df6d040ccd..0000000000
--- a/src/plugins/debugger/gdb/coregdbadapter.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "coregdbadapter.h"
-
-#include <coreplugin/messagebox.h>
-
-#include <debugger/debuggercore.h>
-#include <debugger/debuggerprotocol.h>
-#include <debugger/debuggerstartparameters.h>
-
-#include <utils/fileutils.h>
-#include <utils/qtcassert.h>
-#include <utils/synchronousprocess.h>
-#include <utils/temporarydirectory.h>
-#include <utils/temporaryfile.h>
-
-#include <QDir>
-
-using namespace Utils;
-using namespace ProjectExplorer;
-
-namespace Debugger {
-namespace Internal {
-
-#define CB(callback) [this](const DebuggerResponse &r) { callback(r); }
-#define CHECK_STATE(s) do { checkState(s, __FILE__, __LINE__); } while (0)
-
-///////////////////////////////////////////////////////////////////////
-//
-// CoreGdbAdapter
-//
-///////////////////////////////////////////////////////////////////////
-
-GdbCoreEngine::GdbCoreEngine(bool useTerminal)
- : GdbEngine(useTerminal)
-{}
-
-GdbCoreEngine::~GdbCoreEngine()
-{
- if (m_coreUnpackProcess) {
- m_coreUnpackProcess->blockSignals(true);
- m_coreUnpackProcess->terminate();
- m_coreUnpackProcess->deleteLater();
- m_coreUnpackProcess = 0;
- if (m_tempCoreFile.isOpen())
- m_tempCoreFile.close();
- }
- if (!m_tempCoreName.isEmpty()) {
- QFile tmpFile(m_tempCoreName);
- tmpFile.remove();
- }
-}
-
-void GdbCoreEngine::setupEngine()
-{
- QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
- showMessage("TRYING TO START ADAPTER");
-
- const DebuggerRunParameters &rp = runParameters();
- m_executable = rp.inferior.executable;
- QFileInfo fi(rp.coreFile);
- m_coreName = fi.absoluteFilePath();
-
- unpackCoreIfNeeded();
-}
-
-static QString findExecutableFromName(const QString &fileNameFromCore, const QString &coreFile)
-{
- if (fileNameFromCore.isEmpty())
- return fileNameFromCore;
- QFileInfo fi(fileNameFromCore);
- if (fi.isFile())
- return fileNameFromCore;
-
- // turn the filename into an absolute path, using the location of the core as a hint
- QString absPath;
- if (fi.isAbsolute()) {
- absPath = fileNameFromCore;
- } else {
- QFileInfo coreInfo(coreFile);
- QDir coreDir = coreInfo.dir();
- absPath = FileUtils::resolvePath(coreDir.absolutePath(), fileNameFromCore);
- }
- if (QFileInfo(absPath).isFile() || absPath.isEmpty())
- return absPath;
-
- // remove possible trailing arguments
- QLatin1Char sep(' ');
- QStringList pathFragments = absPath.split(sep);
- while (pathFragments.size() > 0) {
- QString joined_path = pathFragments.join(sep);
- if (QFileInfo(joined_path).isFile()) {
- return joined_path;
- }
- pathFragments.pop_back();
- }
-
- return QString();
-}
-
-GdbCoreEngine::CoreInfo
-GdbCoreEngine::readExecutableNameFromCore(const StandardRunnable &debugger, const QString &coreFile)
-{
- CoreInfo cinfo;
-#if 0
- ElfReader reader(coreFile);
- cinfo.rawStringFromCore = QString::fromLocal8Bit(reader.readCoreName(&cinfo.isCore));
- cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile);
-#else
- QStringList args;
- args.append(QLatin1String("-nx"));
- args.append(QLatin1String("-batch"));
- args.append(QLatin1String("-c"));
- args.append(coreFile);
-
- SynchronousProcess proc;
- QStringList envLang = QProcess::systemEnvironment();
- Utils::Environment::setupEnglishOutput(&envLang);
- proc.setEnvironment(envLang);
- SynchronousProcessResponse response = proc.runBlocking(debugger.executable, args);
-
- if (response.result == SynchronousProcessResponse::Finished) {
- QString output = response.stdOut();
- // Core was generated by `/data/dev/creator-2.6/bin/qtcreator'.
- // Program terminated with signal 11, Segmentation fault.
- int pos1 = output.indexOf("Core was generated by");
- if (pos1 != -1) {
- pos1 += 23;
- int pos2 = output.indexOf('\'', pos1);
- if (pos2 != -1) {
- cinfo.isCore = true;
- cinfo.rawStringFromCore = output.mid(pos1, pos2 - pos1);
- cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile);
- }
- }
- }
-#endif
- return cinfo;
-}
-
-void GdbCoreEngine::continueSetupEngine()
-{
- bool isCore = true;
- if (m_coreUnpackProcess) {
- isCore = m_coreUnpackProcess->exitCode() == 0;
- m_coreUnpackProcess->deleteLater();
- m_coreUnpackProcess = 0;
- if (m_tempCoreFile.isOpen())
- m_tempCoreFile.close();
- }
- if (isCore && m_executable.isEmpty()) {
- GdbCoreEngine::CoreInfo cinfo =
- readExecutableNameFromCore(runParameters().debugger, coreFileName());
-
- if (cinfo.isCore) {
- m_executable = cinfo.foundExecutableName;
- if (m_executable.isEmpty()) {
- Core::AsynchronousMessageBox::warning(
- tr("Error Loading Symbols"),
- tr("No executable to load symbols from specified core."));
- notifyEngineSetupFailed();
- return;
- }
- }
- }
- if (isCore) {
- startGdb();
- } else {
- Core::AsynchronousMessageBox::warning(
- tr("Error Loading Core File"),
- tr("The specified file does not appear to be a core file."));
- notifyEngineSetupFailed();
- }
-}
-
-void GdbCoreEngine::writeCoreChunk()
-{
- m_tempCoreFile.write(m_coreUnpackProcess->readAll());
-}
-
-void GdbCoreEngine::setupInferior()
-{
- CHECK_STATE(InferiorSetupRequested);
- setLinuxOsAbi();
- // Do that first, otherwise no symbols are loaded.
- QFileInfo fi(m_executable);
- QString path = fi.absoluteFilePath();
- runCommand({"-file-exec-and-symbols \"" + path + '"',
- CB(handleFileExecAndSymbols)});
-}
-
-void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
-{
- CHECK_STATE(InferiorSetupRequested);
- QString core = coreFileName();
- if (response.resultClass == ResultDone) {
- showMessage(tr("Symbols found."), StatusBar);
- handleInferiorPrepared();
- } else {
- QString msg = tr("No symbols found in core file <i>%1</i>.").arg(core)
- + ' ' + tr("This can be caused by a path length limitation "
- "in the core file.")
- + ' ' + tr("Try to specify the binary using the "
- "<i>Debug->Start Debugging->Attach to Core</i> dialog.");
- notifyInferiorSetupFailed(msg);
- }
-}
-
-void GdbCoreEngine::runEngine()
-{
- CHECK_STATE(EngineRunRequested);
- runCommand({"target core " + coreFileName(), CB(handleTargetCore)});
-}
-
-void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response)
-{
- CHECK_STATE(EngineRunRequested);
- notifyEngineRunOkAndInferiorUnrunnable();
- showMessage(tr("Attached to core."), StatusBar);
- if (response.resultClass == ResultError) {
- // We'll accept any kind of error e.g. &"Cannot access memory at address 0x2abc2a24\n"
- // Even without the stack, the user can find interesting stuff by exploring
- // the memory, globals etc.
- showStatusMessage(tr("Attach to core \"%1\" failed:").arg(runParameters().coreFile)
- + '\n' + response.data["msg"].data()
- + '\n' + tr("Continuing nevertheless."));
- }
- // Due to the auto-solib-add off setting, we don't have any
- // symbols yet. Load them in order of importance.
- reloadStack();
- reloadModulesInternal();
- runCommand({"p 5", CB(handleRoundTrip)});
-}
-
-void GdbCoreEngine::handleRoundTrip(const DebuggerResponse &response)
-{
- CHECK_STATE(InferiorUnrunnable);
- Q_UNUSED(response);
- loadSymbolsForStack();
- handleStop3();
- QTimer::singleShot(1000, this, &GdbEngine::loadAllSymbols);
-}
-
-void GdbCoreEngine::interruptInferior()
-{
- // A core never runs, so this cannot be called.
- QTC_CHECK(false);
-}
-
-void GdbCoreEngine::shutdownEngine()
-{
- notifyAdapterShutdownOk();
-}
-
-static QString tempCoreFilename()
-{
- Utils::TemporaryFile tmp("tmpcore-XXXXXX");
- tmp.open();
- return tmp.fileName();
-}
-
-void GdbCoreEngine::unpackCoreIfNeeded()
-{
- QStringList arguments;
- const QString msg = "Unpacking core file to %1";
- if (m_coreName.endsWith(QLatin1String(".lzo"))) {
- m_tempCoreName = tempCoreFilename();
- showMessage(msg.arg(m_tempCoreName));
- arguments << QLatin1String("-o") << m_tempCoreName << QLatin1String("-x") << m_coreName;
- m_coreUnpackProcess = new QProcess(this);
- m_coreUnpackProcess->setWorkingDirectory(Utils::TemporaryDirectory::masterDirectoryPath());
- m_coreUnpackProcess->start(QLatin1String("lzop"), arguments);
- connect(m_coreUnpackProcess, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
- this, &GdbCoreEngine::continueSetupEngine);
- } else if (m_coreName.endsWith(QLatin1String(".gz"))) {
- m_tempCoreName = tempCoreFilename();
- showMessage(msg.arg(m_tempCoreName));
- m_tempCoreFile.setFileName(m_tempCoreName);
- m_tempCoreFile.open(QFile::WriteOnly);
- arguments << QLatin1String("-c") << QLatin1String("-d") << m_coreName;
- m_coreUnpackProcess = new QProcess(this);
- m_coreUnpackProcess->setWorkingDirectory(Utils::TemporaryDirectory::masterDirectoryPath());
- m_coreUnpackProcess->start(QLatin1String("gzip"), arguments);
- connect(m_coreUnpackProcess, &QProcess::readyRead, this, &GdbCoreEngine::writeCoreChunk);
- connect(m_coreUnpackProcess, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
- this, &GdbCoreEngine::continueSetupEngine);
- } else {
- continueSetupEngine();
- }
-}
-
-QString GdbCoreEngine::coreFileName() const
-{
- return m_tempCoreName.isEmpty() ? m_coreName : m_tempCoreName;
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h
deleted file mode 100644
index b4b7081455..0000000000
--- a/src/plugins/debugger/gdb/coregdbadapter.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "gdbengine.h"
-
-#include <QFile>
-
-namespace Debugger {
-namespace Internal {
-
-class GdbCoreEngine : public GdbEngine
-{
- Q_OBJECT
-
-public:
- explicit GdbCoreEngine(bool useTerminal);
- ~GdbCoreEngine() override;
-
- struct CoreInfo
- {
- QString rawStringFromCore;
- QString foundExecutableName; // empty if no corresponding exec could be found
- bool isCore = false;
- };
- static CoreInfo readExecutableNameFromCore(const ProjectExplorer::StandardRunnable &debugger,
- const QString &coreFile);
-
-private:
- void setupEngine() override;
- void setupInferior() override;
- void runEngine() override;
- void interruptInferior() override;
- void shutdownEngine() override;
-
- void handleFileExecAndSymbols(const DebuggerResponse &response);
- void handleTargetCore(const DebuggerResponse &response);
- void handleRoundTrip(const DebuggerResponse &response);
- void unpackCoreIfNeeded();
- QString coreFileName() const;
- QString coreName() const;
-
- void continueSetupEngine();
- void writeCoreChunk();
-
-private:
- QString m_executable;
- QString m_coreName;
- QString m_tempCoreName;
- QProcess *m_coreUnpackProcess = nullptr;
- QFile m_tempCoreFile;
-};
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/gdb.pri b/src/plugins/debugger/gdb/gdb.pri
index 3bed54bcc4..4e0883fa03 100644
--- a/src/plugins/debugger/gdb/gdb.pri
+++ b/src/plugins/debugger/gdb/gdb.pri
@@ -1,18 +1,8 @@
HEADERS += \
$$PWD/gdbengine.h \
- $$PWD/attachgdbadapter.h \
- $$PWD/coregdbadapter.h \
- $$PWD/termgdbadapter.h \
- $$PWD/remotegdbserveradapter.h \
- $$PWD/gdbplainengine.h \
$$PWD/startgdbserverdialog.h
SOURCES += \
$$PWD/gdbengine.cpp \
$$PWD/gdboptionspage.cpp \
- $$PWD/attachgdbadapter.cpp \
- $$PWD/coregdbadapter.cpp \
- $$PWD/termgdbadapter.cpp \
- $$PWD/remotegdbserveradapter.cpp \
- $$PWD/gdbplainengine.cpp \
$$PWD/startgdbserverdialog.cpp
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index a49f469b87..2370d6f22f 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -25,13 +25,6 @@
#include "gdbengine.h"
-#include "attachgdbadapter.h"
-#include "coregdbadapter.h"
-#include "gdbplainengine.h"
-#include "termgdbadapter.h"
-#include "remotegdbserveradapter.h"
-
-#include <debugger/debuggerstartparameters.h>
#include <debugger/debuggerinternalconstants.h>
#include <debugger/debuggerruncontrol.h>
#include <debugger/disassemblerlines.h>
@@ -66,15 +59,17 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/taskhub.h>
+#include <app/app_version.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/savedaction.h>
+#include <utils/synchronousprocess.h>
+#include <utils/temporarydirectory.h>
#include <utils/temporaryfile.h>
-#include <QBuffer>
#include <QDirIterator>
#include <QMessageBox>
#include <QProcess>
@@ -96,11 +91,6 @@ enum { debugPending = 0 };
#define CHECK_STATE(s) do { checkState(s, __FILE__, __LINE__); } while (0)
-QString GdbEngine::tooltipIName(const QString &exp)
-{
- return "tooltip." + toHex(exp);
-}
-
static bool stateAcceptsGdbCommands(DebuggerState state)
{
switch (state) {
@@ -147,11 +137,6 @@ static bool isMostlyHarmlessMessage(const QStringRef &msg)
"Invalid argument\\n";
}
-static QString mainFunction(const DebuggerRunParameters &rp)
-{
- return QLatin1String(rp.toolChainAbi.os() == Abi::WindowsOS && !rp.useTerminal ? "qMain" : "main");
-}
-
///////////////////////////////////////////////////////////////////////
//
// Debuginfo Taskhandler
@@ -204,27 +189,12 @@ private:
//
///////////////////////////////////////////////////////////////////////
-GdbEngine::GdbEngine(bool useTerminal)
+GdbEngine::GdbEngine()
{
setObjectName("GdbEngine");
- m_busy = false;
- m_gdbVersion = 100;
- m_pythonVersion = 0;
- m_isQnxGdb = false;
- m_registerNamesListed = false;
- m_sourcesListUpdating = false;
- m_oldestAcceptableToken = -1;
- m_nonDiscardableCount = 0;
m_gdbOutputCodec = QTextCodec::codecForLocale();
m_inferiorOutputCodec = QTextCodec::codecForLocale();
- m_pendingBreakpointRequests = 0;
- m_commandsDoneCallback = 0;
- m_stackNeeded = false;
- m_terminalTrap = useTerminal;
- m_systemDumpersLoaded = false;
- m_rerunPending = false;
- m_inUpdateLocals = false;
m_debugInfoTaskHandler = new DebugInfoTaskHandler(this);
//ExtensionSystem::PluginManager::addObject(m_debugInfoTaskHandler);
@@ -241,10 +211,29 @@ GdbEngine::GdbEngine(bool useTerminal)
this, &GdbEngine::reloadLocals);
connect(action(UseDynamicType), &SavedAction::valueChanged,
this, &GdbEngine::reloadLocals);
+
+ // Output
+ connect(&m_outputCollector, &OutputCollector::byteDelivery,
+ this, &GdbEngine::readDebuggeeOutput);
}
GdbEngine::~GdbEngine()
{
+ if (isCoreEngine()) {
+ if (m_coreUnpackProcess) {
+ m_coreUnpackProcess->blockSignals(true);
+ m_coreUnpackProcess->terminate();
+ m_coreUnpackProcess->deleteLater();
+ m_coreUnpackProcess = nullptr;
+ if (m_tempCoreFile.isOpen())
+ m_tempCoreFile.close();
+ }
+ if (!m_tempCoreName.isEmpty()) {
+ QFile tmpFile(m_tempCoreName);
+ tmpFile.remove();
+ }
+ }
+
//ExtensionSystem::PluginManager::removeObject(m_debugInfoTaskHandler);
delete m_debugInfoTaskHandler;
m_debugInfoTaskHandler = 0;
@@ -253,35 +242,14 @@ GdbEngine::~GdbEngine()
disconnect();
}
-DebuggerStartMode GdbEngine::startMode() const
-{
- return runParameters().startMode;
-}
-
QString GdbEngine::failedToStartMessage()
{
return tr("The gdb process failed to start.");
}
-#if 0
-static void dump(const char *first, const char *middle, const QString & to)
-{
- QString ba(first, middle - first);
- Q_UNUSED(to)
- // note that qDebug cuts off output after a certain size... (bug?)
- qDebug("\n>>>>> %s\n%s\n====\n%s\n<<<<<\n",
- qPrintable(currentTime()),
- qPrintable(QString(ba).trimmed()),
- qPrintable(to.trimmed()));
- //qDebug() << "";
- //qDebug() << qPrintable(currentTime())
- // << " Reading response: " << QString(ba).trimmed() << "\n";
-}
-#endif
-
// Parse "~:gdb: unknown target exception 0xc0000139 at 0x77bef04e\n"
// and return an exception message
-static inline QString msgWinException(const QString &data, unsigned *exCodeIn = 0)
+static QString msgWinException(const QString &data, unsigned *exCodeIn = 0)
{
if (exCodeIn)
*exCodeIn = 0;
@@ -786,10 +754,10 @@ void GdbEngine::readGdbStandardOutput()
void GdbEngine::interruptInferior()
{
- CHECK_STATE(InferiorStopRequested);
+ // A core never runs, so this cannot be called.
+ QTC_ASSERT(!isCoreEngine(), return);
- if (terminal()->sendInterrupt())
- return;
+ CHECK_STATE(InferiorStopRequested);
if (usesExecInterrupt()) {
runCommand({"-exec-interrupt"});
@@ -798,33 +766,26 @@ void GdbEngine::interruptInferior()
showMessage("TRYING TO INTERRUPT INFERIOR");
if (HostOsInfo::isWindowsHost() && !m_isQnxGdb) {
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state(); notifyInferiorStopFailed());
- QTC_ASSERT(!m_signalOperation, notifyInferiorStopFailed());
- m_signalOperation = runTool()->device()->signalOperation();
- QTC_ASSERT(m_signalOperation, notifyInferiorStopFailed(); return);
- connect(m_signalOperation.data(), &DeviceProcessSignalOperation::finished,
- this, &GdbEngine::handleInterruptDeviceInferior);
-
- m_signalOperation->setDebuggerCommand(runParameters().debugger.executable);
- m_signalOperation->interruptProcess(inferiorPid());
+ DeviceProcessSignalOperation::Ptr signalOperation = runTool()->device()->signalOperation();
+ QTC_ASSERT(signalOperation, notifyInferiorStopFailed(); return);
+ connect(signalOperation.data(), &DeviceProcessSignalOperation::finished,
+ this, [this, signalOperation](const QString &error) {
+ if (error.isEmpty()) {
+ showMessage("Interrupted " + QString::number(inferiorPid()));
+ notifyInferiorStopOk();
+ } else {
+ showMessage(error, LogError);
+ notifyInferiorStopFailed();
+ }
+ });
+ signalOperation->setDebuggerCommand(runParameters().debugger.executable);
+ signalOperation->interruptProcess(inferiorPid());
} else {
interruptInferior2();
}
}
}
-void GdbEngine::handleInterruptDeviceInferior(const QString &error)
-{
- if (error.isEmpty()) {
- showMessage("Interrupted " + QString::number(inferiorPid()));
- notifyInferiorStopOk();
- } else {
- showMessage(error, LogError);
- notifyInferiorStopFailed();
- }
- m_signalOperation->disconnect(this);
- m_signalOperation.clear();
-}
-
void GdbEngine::runCommand(const DebuggerCommand &command)
{
const int token = ++currentToken();
@@ -1023,7 +984,7 @@ void GdbEngine::handleResultRecord(DebuggerResponse *response)
//notifyInferiorIll();
//showStatusMessage(tr("Executable failed: %1").arg(msg));
//shutdown();
- //Core::AsynchronousMessageBox::critical(tr("Executable failed"), msg);
+ //AsynchronousMessageBox::critical(tr("Executable failed"), msg);
} else if (msg.contains("Cannot insert breakpoint")) {
// For breakpoints set by address to non-existent addresses we
// might get something like "6^error,msg="Warning:\nCannot insert
@@ -1093,7 +1054,7 @@ void GdbEngine::handleResultRecord(DebuggerResponse *response)
Abi abi = rp.toolChainAbi;
if (abi.os() == Abi::WindowsOS
&& cmd.function.startsWith("attach")
- && (rp.startMode == AttachExternal || rp.useTerminal))
+ && (rp.startMode == AttachExternal || terminal()))
{
// Ignore spurious 'running' responses to 'attach'.
} else {
@@ -1254,11 +1215,13 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
{
// Ignore trap on Windows terminals, which results in
// spurious "* stopped" message.
- if (m_terminalTrap && (!data.isValid() || !data["reason"].isValid())
- && Abi::hostAbi().os() == Abi::WindowsOS) {
- m_terminalTrap = false;
- showMessage("IGNORING TERMINAL SIGTRAP", LogMisc);
- return;
+ if (m_expectTerminalTrap) {
+ m_expectTerminalTrap = false;
+ if ((!data.isValid() || !data["reason"].isValid())
+ && Abi::hostAbi().os() == Abi::WindowsOS) {
+ showMessage("IGNORING TERMINAL SIGTRAP", LogMisc);
+ return;
+ }
}
if (isDying()) {
@@ -1293,7 +1256,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// Ignore signals from the process stub.
const GdbMi frame = data["frame"];
const QString func = frame["from"].data();
- if (runParameters().useTerminal
+ if (terminal()
&& data["reason"].data() == "signal-received"
&& data["signal-name"].data() == "SIGSTOP"
&& (func.endsWith("/ld-linux.so.2")
@@ -1385,8 +1348,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// This is gdb 7+'s initial *stopped in response to attach that
// appears before the ^done is seen.
notifyEngineRunAndInferiorStopOk();
- const DebuggerRunParameters &rp = runParameters();
- if (rp.useTerminal)
+ if (terminal())
continueInferiorInternal();
return;
} else {
@@ -1511,7 +1473,7 @@ void GdbEngine::handleStop2(const GdbMi &data)
bool isStopperThread = false;
if (rp.toolChainAbi.os() == Abi::WindowsOS
- && rp.useTerminal
+ && terminal()
&& reason == "signal-received"
&& data["signal-name"].data() == "SIGTRAP")
{
@@ -1643,8 +1605,9 @@ void GdbEngine::handlePythonSetup(const DebuggerResponse &response)
QString out = "<p>"
+ tr("The selected build of GDB supports Python scripting, "
"but the used version %1.%2 is not sufficient for "
- "Qt Creator. Supported versions are Python 2.7 and 3.x.")
- .arg(pythonMajor).arg(pythonMinor);
+ "%3. Supported versions are Python 2.7 and 3.x.")
+ .arg(pythonMajor).arg(pythonMinor)
+ .arg(Core::Constants::IDE_DISPLAY_NAME);
showStatusMessage(out);
AsynchronousMessageBox::critical(tr("Execution Error"), out);
}
@@ -1656,7 +1619,8 @@ void GdbEngine::handlePythonSetup(const DebuggerResponse &response)
QString msg = response.data["msg"].data();
if (msg.contains("Python scripting is not supported in this copy of GDB.")) {
QString out1 = "The selected build of GDB does not support Python scripting.";
- QString out2 = "It cannot be used in Qt Creator.";
+ QString out2 = QStringLiteral("It cannot be used in %1.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME);
showStatusMessage(out1 + ' ' + out2);
AsynchronousMessageBox::critical(tr("Execution Error"), out1 + "<br>" + out2);
}
@@ -1866,7 +1830,7 @@ void GdbEngine::setLinuxOsAbi()
void GdbEngine::detachDebugger()
{
CHECK_STATE(InferiorStopOk);
- QTC_ASSERT(startMode() != AttachCore, qDebug() << startMode());
+ QTC_ASSERT(m_startMode != AttachCore, qDebug() << m_startMode);
DebuggerCommand cmd("detach", ExitRequest);
cmd.callback = [this](const DebuggerResponse &) {
CHECK_STATE(InferiorStopOk);
@@ -2357,7 +2321,7 @@ QString GdbEngine::breakpointLocation(const BreakpointParameters &data)
if (data.type == BreakpointAtCatch)
return QLatin1String("__cxa_begin_catch");
if (data.type == BreakpointAtMain)
- return mainFunction(runParameters());
+ return mainFunction();
if (data.type == BreakpointByFunction)
return '"' + data.functionName + '"';
if (data.type == BreakpointByAddress)
@@ -3298,9 +3262,6 @@ void GdbEngine::createSnapshot()
void GdbEngine::handleMakeSnapshot(const DebuggerResponse &response, const QString &coreFile)
{
if (response.resultClass == ResultDone) {
- DebuggerRunParameters rp = runParameters();
- rp.startMode = AttachCore;
- rp.coreFile = coreFile;
//snapshot.setDate(QDateTime::currentDateTime());
StackFrames frames = stackHandler()->frames();
QString function = "<unknown>";
@@ -3308,11 +3269,13 @@ void GdbEngine::handleMakeSnapshot(const DebuggerResponse &response, const QStri
const StackFrame &frame = frames.at(0);
function = frame.function + ":" + QString::number(frame.line);
}
- rp.displayName = function + ": " + QDateTime::currentDateTime().toString();
- rp.isSnapshot = true;
+ QTC_ASSERT(runControl()->runConfiguration(), return);
auto rc = new RunControl(runControl()->runConfiguration(), ProjectExplorer::Constants::DEBUG_RUN_MODE);
- (void) new DebuggerRunTool(rc, rp);
- ProjectExplorerPlugin::startRunControl(rc);
+ auto debugger = new DebuggerRunTool(rc);
+ debugger->setStartMode(AttachCore);
+ debugger->setRunControlName(function + ": " + QDateTime::currentDateTime().toString());
+ debugger->setCoreFileName(coreFile, true);
+ debugger->startRunControl();
} else {
QString msg = response.data["msg"].data();
AsynchronousMessageBox::critical(tr("Snapshot Creation Error"),
@@ -3813,6 +3776,7 @@ void GdbEngine::startGdb(const QStringList &args)
showMessage("ENABLING TEST CASE: " + QString::number(test));
m_gdbProc.disconnect(); // From any previous runs
+ m_expectTerminalTrap = terminal();
const DebuggerRunParameters &rp = runParameters();
if (rp.debugger.executable.isEmpty()) {
@@ -3964,8 +3928,8 @@ void GdbEngine::startGdb(const QStringList &args)
// Don't use ConsoleCommand, otherwise Mac won't markup the output.
const QString dumperSourcePath = ICore::resourcePath() + "/debugger/";
- if (terminal()->isUsable())
- runCommand({"set inferior-tty " + QString::fromUtf8(terminal()->slaveDevice())});
+ //if (terminal()->isUsable())
+ // runCommand({"set inferior-tty " + QString::fromUtf8(terminal()->slaveDevice())});
const QFileInfo gdbBinaryFile(rp.debugger.executable);
const QString uninstalledData = gdbBinaryFile.absolutePath() + "/data-directory/python";
@@ -3990,6 +3954,8 @@ void GdbEngine::startGdb(const QStringList &args)
void GdbEngine::handleGdbStartFailed()
{
+ if (isPlainEngine())
+ m_outputCollector.shutdown();
}
void GdbEngine::loadInitScript()
@@ -4003,7 +3969,7 @@ void GdbEngine::loadInitScript()
tr("Cannot find debugger initialization script"),
tr("The debugger settings point to a script file at \"%1\" "
"which is not accessible. If a script file is not needed, "
- "consider clearing that entry to avoid this warning. "
+ "consider clearing that entry to avoid this warning."
).arg(script));
}
} else {
@@ -4072,17 +4038,9 @@ void GdbEngine::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus)
notifyDebuggerProcessFinished(exitCode, exitStatus, "GDB");
}
-void GdbEngine::abortDebugger()
+void GdbEngine::abortDebuggerProcess()
{
- if (isDying()) {
- // We already tried. Try harder.
- showMessage("ABORTING DEBUGGER. SECOND TIME.");
- m_gdbProc.kill();
- } else {
- // Be friendly the first time. This will change targetState().
- showMessage("ABORTING DEBUGGER. FIRST TIME.");
- quitDebugger();
- }
+ m_gdbProc.kill();
}
void GdbEngine::resetInferior()
@@ -4115,14 +4073,6 @@ void GdbEngine::handleAdapterStartFailed(const QString &msg, Id settingsIdHint)
notifyEngineSetupFailed();
}
-void GdbEngine::notifyInferiorSetupFailed()
-{
- // FIXME: that's not enough to stop gdb from getting confused
- // by a timeout of the adapter.
- //resetCommandQueue();
- DebuggerEngine::notifyInferiorSetupFailed();
-}
-
void GdbEngine::prepareForRestart()
{
m_rerunPending = false;
@@ -4145,7 +4095,7 @@ void GdbEngine::handleInferiorPrepared()
//runCommand("set follow-exec-mode new");
if (rp.breakOnMain)
- runCommand({"tbreak " + mainFunction(rp)});
+ runCommand({"tbreak " + mainFunction()});
// Initial attempt to set breakpoints.
if (rp.startMode != AttachCore) {
@@ -4200,7 +4150,7 @@ void GdbEngine::handleDebugInfoLocation(const DebuggerResponse &response)
}
}
-void GdbEngine::notifyInferiorSetupFailed(const QString &msg)
+void GdbEngine::notifyInferiorSetupFailedHelper(const QString &msg)
{
showStatusMessage(tr("Failed to start application:") + ' ' + msg);
if (state() == EngineSetupFailed) {
@@ -4209,7 +4159,7 @@ void GdbEngine::notifyInferiorSetupFailed(const QString &msg)
}
showMessage("INFERIOR START FAILED");
AsynchronousMessageBox::critical(tr("Failed to start application"), msg);
- DebuggerEngine::notifyInferiorSetupFailed();
+ notifyInferiorSetupFailed();
}
void GdbEngine::handleAdapterCrashed(const QString &msg)
@@ -4236,7 +4186,7 @@ void GdbEngine::handleAdapterCrashed(const QString &msg)
void GdbEngine::createFullBacktrace()
{
DebuggerCommand cmd("thread apply all bt full", NeedsTemporaryStop | ConsoleCommand);
- cmd.callback = [this](const DebuggerResponse &response) {
+ cmd.callback = [](const DebuggerResponse &response) {
if (response.resultClass == ResultDone) {
Internal::openTextEditor("Backtrace $",
response.consoleStreamOutput + response.logStreamOutput);
@@ -4320,7 +4270,7 @@ QString GdbEngine::msgConnectRemoteServerFailed(const QString &why)
void GdbEngine::interruptLocalInferior(qint64 pid)
{
- QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state(); return);
+ CHECK_STATE(InferiorStopRequested);
if (pid <= 0) {
showMessage("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED", LogError);
return;
@@ -4339,27 +4289,806 @@ void GdbEngine::debugLastCommand()
runCommand(m_lastDebuggableCommand);
}
-//
-// Factory
-//
+bool GdbEngine::isPlainEngine() const
+{
+ return !isCoreEngine() && !isAttachEngine() && !isRemoteEngine() && !terminal();
+}
+
+bool GdbEngine::isCoreEngine() const
+{
+ return m_startMode == AttachCore;
+}
+
+bool GdbEngine::isRemoteEngine() const
+{
+ return m_startMode == StartRemoteProcess || m_startMode == AttachToRemoteServer;
+}
+
+bool GdbEngine::isAttachEngine() const
+{
+ return m_startMode == AttachExternal;
+}
+
+bool GdbEngine::isTermEngine() const
+{
+ return !isCoreEngine() && !isAttachEngine() && !isRemoteEngine() && terminal();
+}
+
+void GdbEngine::setupEngine()
+{
+ m_startMode = runParameters().startMode;
+
+ CHECK_STATE(EngineSetupRequested);
+ showMessage("TRYING TO START ADAPTER");
+
+ if (isAttachEngine()) {
+
+ startGdb();
+
+ } else if (isRemoteEngine()) {
+
+ if (HostOsInfo::isWindowsHost())
+ m_gdbProc.setUseCtrlCStub(runParameters().useCtrlCStub); // This is only set for QNX
+
+ startGdb();
+
+ } else if (isTermEngine()) {
+
+ showMessage("TRYING TO START ADAPTER");
+
+ startGdb();
+
+ } else if (isCoreEngine()) {
+
+ CHECK_STATE(EngineSetupRequested);
+ showMessage("TRYING TO START ADAPTER");
+
+ const DebuggerRunParameters &rp = runParameters();
+ m_executable = rp.inferior.executable;
+ QFileInfo fi(rp.coreFile);
+ m_coreName = fi.absoluteFilePath();
+
+ unpackCoreIfNeeded();
+
+ } else if (isPlainEngine()) {
+
+ QStringList gdbArgs;
+
+ if (!m_outputCollector.listen()) {
+ handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
+ .arg(m_outputCollector.errorString()));
+ return;
+ }
+ gdbArgs.append("--tty=" + m_outputCollector.serverName());
+
+ startGdb(gdbArgs);
+ }
+}
+
+void GdbEngine::setupInferior()
+{
+ CHECK_STATE(InferiorSetupRequested);
+
+ if (isAttachEngine()) {
+ // Task 254674 does not want to remove them
+ //qq->breakHandler()->removeAllBreakpoints();
+ handleInferiorPrepared();
+
+ } else if (isRemoteEngine()) {
+
+ setLinuxOsAbi();
+ const DebuggerRunParameters &rp = runParameters();
+ QString symbolFile;
+ if (!rp.symbolFile.isEmpty()) {
+ QFileInfo fi(rp.symbolFile);
+ symbolFile = fi.absoluteFilePath();
+ }
+
+ //const QByteArray sysroot = sp.sysroot.toLocal8Bit();
+ //const QByteArray remoteArch = sp.remoteArchitecture.toLatin1();
+ const QString args = runParameters().inferior.commandLineArguments;
+
+ // if (!remoteArch.isEmpty())
+ // postCommand("set architecture " + remoteArch);
+ if (!rp.solibSearchPath.isEmpty()) {
+ DebuggerCommand cmd("appendSolibSearchPath");
+ cmd.arg("path", rp.solibSearchPath);
+ cmd.arg("separator", HostOsInfo::pathListSeparator());
+ runCommand(cmd);
+ }
+
+ if (!args.isEmpty())
+ runCommand({"-exec-arguments " + args});
+
+ setEnvironmentVariables();
+
+ // This has to be issued before 'target remote'. On pre-7.0 the
+ // command is not present and will result in ' No symbol table is
+ // loaded. Use the "file" command.' as gdb tries to set the
+ // value of a variable with name 'target-async'.
+ //
+ // Testing with -list-target-features which was introduced at
+ // the same time would not work either, as this need an existing
+ // target.
+ //
+ // Using it even without a target and having it fail might still
+ // be better as:
+ // Some external comment: '[but] "set target-async on" with a native
+ // windows gdb will work, but then fail when you actually do
+ // "run"/"attach", I think..
+
+
+ // gdb/mi/mi-main.c:1958: internal-error:
+ // mi_execute_async_cli_command: Assertion `is_running (inferior_ptid)'
+ // failed.\nA problem internal to GDB has been detected,[...]
+ if (usesTargetAsync())
+ runCommand({"set target-async on", CB(handleSetTargetAsync)});
+
+ if (symbolFile.isEmpty()) {
+ showMessage(tr("No symbol file given."), StatusBar);
+ callTargetRemote();
+ return;
+ }
+
+ if (!symbolFile.isEmpty()) {
+ runCommand({"-file-exec-and-symbols \"" + symbolFile + '"',
+ CB(handleFileExecAndSymbols)});
+ }
+
+ } else if (isCoreEngine()) {
+
+ setLinuxOsAbi();
+ // Do that first, otherwise no symbols are loaded.
+ QFileInfo fi(m_executable);
+ QString path = fi.absoluteFilePath();
+ runCommand({"-file-exec-and-symbols \"" + path + '"',
+ CB(handleFileExecAndSymbols)});
+
+ } else if (isTermEngine()) {
+
+ const qint64 attachedPID = terminal()->applicationPid();
+ const qint64 attachedMainThreadID = terminal()->applicationMainThreadId();
+ notifyInferiorPid(ProcessHandle(attachedPID));
+ const QString msg = (attachedMainThreadID != -1)
+ ? QString("Going to attach to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
+ : QString("Going to attach to %1").arg(attachedPID);
+ showMessage(msg, LogMisc);
+ handleInferiorPrepared();
+
+ } else if (isPlainEngine()) {
+
+ setEnvironmentVariables();
+ const DebuggerRunParameters &rp = runParameters();
+ if (!rp.inferior.workingDirectory.isEmpty())
+ runCommand({"cd " + rp.inferior.workingDirectory});
+ if (!rp.inferior.commandLineArguments.isEmpty()) {
+ QString args = rp.inferior.commandLineArguments;
+ runCommand({"-exec-arguments " + args});
+ }
+
+ QString executable = QFileInfo(runParameters().inferior.executable).absoluteFilePath();
+ runCommand({"-file-exec-and-symbols \"" + executable + '"',
+ CB(handleFileExecAndSymbols)});
+ }
+}
+
+void GdbEngine::runEngine()
+{
+ CHECK_STATE(EngineRunRequested);
+
+ if (isAttachEngine()) {
+
+ const qint64 pid = runParameters().attachPID.pid();
+ showStatusMessage(tr("Attaching to process %1.").arg(pid));
+ runCommand({"attach " + QString::number(pid),
+ [this](const DebuggerResponse &r) { handleAttach(r); }});
+ // In some cases we get only output like
+ // "Could not attach to process. If your uid matches the uid of the target\n"
+ // "process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try\n"
+ // " again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf\n"
+ // " ptrace: Operation not permitted.\n"
+ // but no(!) ^ response. Use a second command to force *some* output
+ runCommand({"print 24"});
+
+ } else if (isRemoteEngine()) {
+
+ if (runParameters().useContinueInsteadOfRun) {
+ notifyEngineRunAndInferiorStopOk();
+ continueInferiorInternal();
+ } else {
+ runCommand({"-exec-run", DebuggerCommand::RunRequest, CB(handleExecRun)});
+ }
+
+ } else if (isCoreEngine()) {
+
+ runCommand({"target core " + coreFileName(), CB(handleTargetCore)});
+
+ } else if (isTermEngine()) {
+
+ const qint64 attachedPID = terminal()->applicationPid();
+ const qint64 mainThreadId = terminal()->applicationMainThreadId();
+ runCommand({"attach " + QString::number(attachedPID),
+ [this, mainThreadId](const DebuggerResponse &r) {
+ handleStubAttached(r, mainThreadId);
+ }});
+
+ } else if (isPlainEngine()) {
+
+ if (runParameters().useContinueInsteadOfRun)
+ runCommand({"-exec-continue", DebuggerCommand::RunRequest, CB(handleExecuteContinue)});
+ else
+ runCommand({"-exec-run", DebuggerCommand::RunRequest, CB(handleExecRun)});
+
+ }
+}
+
+void GdbEngine::handleAttach(const DebuggerResponse &response)
+{
+ if (isAttachEngine()) {
+
+ QTC_ASSERT(state() == EngineRunRequested || state() == InferiorStopOk, qDebug() << state());
+ switch (response.resultClass) {
+ case ResultDone:
+ case ResultRunning:
+ showMessage("INFERIOR ATTACHED");
+ if (state() == EngineRunRequested) {
+ // Happens e.g. for "Attach to unstarted application"
+ // We will get a '*stopped' later that we'll interpret as 'spontaneous'
+ // So acknowledge the current state and put a delayed 'continue' in the pipe.
+ showMessage(tr("Attached to running application"), StatusBar);
+ notifyEngineRunAndInferiorRunOk();
+ } else {
+ // InferiorStopOk, e.g. for "Attach to running application".
+ // The *stopped came in between sending the 'attach' and
+ // receiving its '^done'.
+ if (runParameters().continueAfterAttach)
+ continueInferiorInternal();
+ }
+ break;
+ case ResultError:
+ if (response.data["msg"].data() == "ptrace: Operation not permitted.") {
+ QString msg = msgPtraceError(runParameters().startMode);
+ showStatusMessage(tr("Failed to attach to application: %1").arg(msg));
+ AsynchronousMessageBox::warning(tr("Debugger Error"), msg);
+ notifyEngineIll();
+ break;
+ }
+ showStatusMessage(tr("Failed to attach to application: %1")
+ .arg(QString(response.data["msg"].data())));
+ notifyEngineIll();
+ break;
+ default:
+ showStatusMessage(tr("Failed to attach to application: %1")
+ .arg(QString(response.data["msg"].data())));
+ notifyEngineIll();
+ break;
+ }
+
+ } else if (isRemoteEngine()) {
+
+ CHECK_STATE(InferiorSetupRequested);
+ switch (response.resultClass) {
+ case ResultDone:
+ case ResultRunning: {
+ showMessage("INFERIOR ATTACHED");
+ showMessage(msgAttachedToStoppedInferior(), StatusBar);
+ handleInferiorPrepared();
+ break;
+ }
+ case ResultError:
+ if (response.data["msg"].data() == "ptrace: Operation not permitted.") {
+ notifyInferiorSetupFailedHelper(msgPtraceError(runParameters().startMode));
+ break;
+ }
+ notifyInferiorSetupFailedHelper(response.data["msg"].data());
+ break;
+ default:
+ notifyInferiorSetupFailedHelper(response.data["msg"].data());
+ break;
+ }
+
+ }
+}
+
+void GdbEngine::interruptInferior2()
+{
+ if (isAttachEngine()) {
+
+ interruptLocalInferior(runParameters().attachPID.pid());
+
+ } else if (isRemoteEngine()) {
+
+ CHECK_STATE(InferiorStopRequested);
+ if (usesTargetAsync()) {
+ runCommand({"-exec-interrupt", CB(handleInterruptInferior)});
+ } else if (m_isQnxGdb && HostOsInfo::isWindowsHost()) {
+ m_gdbProc.interrupt();
+ } else {
+ qint64 pid = m_gdbProc.processId();
+ bool ok = interruptProcess(pid, GdbEngineType, &m_errorString);
+ if (!ok) {
+ // FIXME: Extra state needed?
+ showMessage("NOTE: INFERIOR STOP NOT POSSIBLE");
+ showStatusMessage(tr("Interrupting not possible"));
+ notifyInferiorRunOk();
+ }
+ }
+
+ } else if (isTermEngine() || isPlainEngine()) {
-DebuggerEngine *createGdbEngine(bool useTerminal, DebuggerStartMode sm)
+ interruptLocalInferior(inferiorPid());
+
+ }
+}
+
+void GdbEngine::shutdownEngine()
+{
+ if (isPlainEngine()) {
+ showMessage(QString("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
+ m_outputCollector.shutdown();
+ }
+
+ notifyAdapterShutdownOk();
+}
+
+void GdbEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
+{
+ CHECK_STATE(InferiorSetupRequested);
+
+ if (isRemoteEngine()) {
+ if (response.resultClass == ResultDone) {
+ callTargetRemote();
+ } else {
+ QString reason = response.data["msg"].data();
+ QString msg = tr("Reading debug information failed:") + '\n' + reason;
+ if (reason.endsWith("No such file or directory.")) {
+ showMessage("INFERIOR STARTUP: BINARY NOT FOUND");
+ showMessage(msg, StatusBar);
+ callTargetRemote(); // Proceed nevertheless.
+ } else {
+ notifyInferiorSetupFailedHelper(msg);
+ }
+ }
+
+ } else if (isCoreEngine()) {
+
+ QString core = coreFileName();
+ if (response.resultClass == ResultDone) {
+ showMessage(tr("Symbols found."), StatusBar);
+ handleInferiorPrepared();
+ } else {
+ QString msg = tr("No symbols found in core file <i>%1</i>.").arg(core)
+ + ' ' + tr("This can be caused by a path length limitation "
+ "in the core file.")
+ + ' ' + tr("Try to specify the binary using the "
+ "<i>Debug->Start Debugging->Attach to Core</i> dialog.");
+ notifyInferiorSetupFailedHelper(msg);
+ }
+
+ } else if (isPlainEngine()) {
+
+ if (response.resultClass == ResultDone) {
+ handleInferiorPrepared();
+ } else {
+ QString msg = response.data["msg"].data();
+ // Extend the message a bit in unknown cases.
+ if (!msg.endsWith("File format not recognized"))
+ msg = tr("Starting executable failed:") + '\n' + msg;
+ notifyInferiorSetupFailedHelper(msg);
+ }
+
+ }
+}
+
+void GdbEngine::handleExecRun(const DebuggerResponse &response)
+{
+ CHECK_STATE(EngineRunRequested);
+
+ if (isRemoteEngine()) {
+
+ if (response.resultClass == ResultRunning) {
+ notifyEngineRunAndInferiorRunOk();
+ showMessage("INFERIOR STARTED");
+ showMessage(msgInferiorSetupOk(), StatusBar);
+ } else {
+ showMessage(response.data["msg"].data());
+ notifyEngineRunFailed();
+ }
+
+ } else if (isPlainEngine()) {
+
+ if (response.resultClass == ResultRunning) {
+ notifyEngineRunAndInferiorRunOk(); // For gdb < 7.0
+ //showStatusMessage(tr("Running..."));
+ showMessage("INFERIOR STARTED");
+ showMessage(msgInferiorSetupOk(), StatusBar);
+ // FIXME: That's the wrong place for it.
+ if (boolSetting(EnableReverseDebugging))
+ runCommand({"target record"});
+ } else {
+ QString msg = response.data["msg"].data();
+ //QTC_CHECK(status() == InferiorRunOk);
+ //interruptInferior();
+ showMessage(msg);
+ notifyEngineRunFailed();
+ }
+
+ }
+}
+
+void GdbEngine::handleSetTargetAsync(const DebuggerResponse &response)
+{
+ CHECK_STATE(InferiorSetupRequested);
+ if (response.resultClass == ResultError)
+ qDebug() << "Adapter too old: does not support asynchronous mode.";
+}
+
+void GdbEngine::callTargetRemote()
+{
+ QString channel = runParameters().remoteChannel;
+
+ // Don't touch channels with explicitly set protocols.
+ if (!channel.startsWith("tcp:") && !channel.startsWith("udp:")
+ && !channel.startsWith("file:") && channel.contains(':')
+ && !channel.startsWith('|'))
+ {
+ // "Fix" the IPv6 case with host names without '['...']'
+ if (!channel.startsWith('[') && channel.count(':') >= 2) {
+ channel.insert(0, '[');
+ channel.insert(channel.lastIndexOf(':'), ']');
+ }
+ channel = "tcp:" + channel;
+ }
+
+ if (m_isQnxGdb)
+ runCommand({"target qnx " + channel, CB(handleTargetQnx)});
+ else if (runParameters().useExtendedRemote)
+ runCommand({"target extended-remote " + channel, CB(handleTargetExtendedRemote)});
+ else
+ runCommand({"target remote " + channel, CB(handleTargetRemote)});
+}
+
+void GdbEngine::handleTargetRemote(const DebuggerResponse &response)
+{
+ CHECK_STATE(InferiorSetupRequested);
+ if (response.resultClass == ResultDone) {
+ // gdb server will stop the remote application itself.
+ showMessage("INFERIOR STARTED");
+ showMessage(msgAttachedToStoppedInferior(), StatusBar);
+ QString commands = expand(stringSetting(GdbPostAttachCommands));
+ if (!commands.isEmpty())
+ runCommand({commands, NativeCommand});
+ handleInferiorPrepared();
+ } else {
+ // 16^error,msg="hd:5555: Connection timed out."
+ notifyInferiorSetupFailedHelper(msgConnectRemoteServerFailed(response.data["msg"].data()));
+ }
+}
+
+void GdbEngine::handleTargetExtendedRemote(const DebuggerResponse &response)
+{
+ CHECK_STATE(InferiorSetupRequested);
+ if (response.resultClass == ResultDone) {
+ showMessage("ATTACHED TO GDB SERVER STARTED");
+ showMessage(msgAttachedToStoppedInferior(), StatusBar);
+ QString commands = expand(stringSetting(GdbPostAttachCommands));
+ if (!commands.isEmpty())
+ runCommand({commands, NativeCommand});
+ if (runParameters().attachPID.isValid()) { // attach to pid if valid
+ // gdb server will stop the remote application itself.
+ runCommand({"attach " + QString::number(runParameters().attachPID.pid()),
+ CB(handleTargetExtendedAttach)});
+ } else if (!runParameters().inferior.executable.isEmpty()) {
+ runCommand({"-gdb-set remote exec-file " + runParameters().inferior.executable,
+ CB(handleTargetExtendedAttach)});
+ } else {
+ const QString title = tr("No Remote Executable or Process ID Specified");
+ const QString msg = tr(
+ "No remote executable could be determined from your build system files.<p>"
+ "In case you use qmake, consider adding<p>"
+ "&nbsp;&nbsp;&nbsp;&nbsp;target.path = /tmp/your_executable # path on device<br>"
+ "&nbsp;&nbsp;&nbsp;&nbsp;INSTALLS += target</p>"
+ "to your .pro file.");
+ QMessageBox *mb = showMessageBox(QMessageBox::Critical, title, msg,
+ QMessageBox::Ok | QMessageBox::Cancel);
+ mb->button(QMessageBox::Cancel)->setText(tr("Continue Debugging"));
+ mb->button(QMessageBox::Ok)->setText(tr("Stop Debugging"));
+ if (mb->exec() == QMessageBox::Ok) {
+ showMessage("KILLING DEBUGGER AS REQUESTED BY USER");
+ notifyInferiorSetupFailedHelper(title);
+ } else {
+ showMessage("CONTINUE DEBUGGER AS REQUESTED BY USER");
+ handleInferiorPrepared(); // This will likely fail.
+ }
+ }
+ } else {
+ notifyInferiorSetupFailedHelper(msgConnectRemoteServerFailed(response.data["msg"].data()));
+ }
+}
+
+void GdbEngine::handleTargetExtendedAttach(const DebuggerResponse &response)
+{
+ CHECK_STATE(InferiorSetupRequested);
+ if (response.resultClass == ResultDone) {
+ // gdb server will stop the remote application itself.
+ handleInferiorPrepared();
+ } else {
+ notifyInferiorSetupFailedHelper(msgConnectRemoteServerFailed(response.data["msg"].data()));
+ }
+}
+
+void GdbEngine::handleTargetQnx(const DebuggerResponse &response)
+{
+ CHECK_STATE(InferiorSetupRequested);
+ if (response.resultClass == ResultDone) {
+ // gdb server will stop the remote application itself.
+ showMessage("INFERIOR STARTED");
+ showMessage(msgAttachedToStoppedInferior(), StatusBar);
+
+ const DebuggerRunParameters &rp = runParameters();
+ const QString remoteExecutable = rp.inferior.executable;
+ if (rp.attachPID.isValid())
+ runCommand({"attach " + QString::number(rp.attachPID.pid()), CB(handleAttach)});
+ else if (!remoteExecutable.isEmpty())
+ runCommand({"set nto-executable " + remoteExecutable, CB(handleSetNtoExecutable)});
+ else
+ handleInferiorPrepared();
+ } else {
+ // 16^error,msg="hd:5555: Connection timed out."
+ notifyInferiorSetupFailedHelper(response.data["msg"].data());
+ }
+}
+
+void GdbEngine::handleSetNtoExecutable(const DebuggerResponse &response)
{
- switch (sm) {
- case AttachCore:
- return new GdbCoreEngine(useTerminal);
- case StartRemoteProcess:
- case AttachToRemoteServer:
- return new GdbRemoteServerEngine(useTerminal);
- case AttachExternal:
- return new GdbAttachEngine(useTerminal);
+ CHECK_STATE(InferiorSetupRequested);
+ switch (response.resultClass) {
+ case ResultDone:
+ case ResultRunning: {
+ showMessage("EXECUTABLE SET");
+ showMessage(msgAttachedToStoppedInferior(), StatusBar);
+ handleInferiorPrepared();
+ break;
+ }
+ case ResultError:
default:
- if (useTerminal)
- return new GdbTermEngine(useTerminal);
- return new GdbPlainEngine(useTerminal);
+ notifyInferiorSetupFailedHelper(response.data["msg"].data());
+ }
+}
+
+void GdbEngine::handleInterruptInferior(const DebuggerResponse &response)
+{
+ if (response.resultClass == ResultDone) {
+ // The gdb server will trigger extra output that we will pick up
+ // to do a proper state transition.
+ } else {
+ // FIXME: On some gdb versions like git 170ffa5d7dd this produces
+ // >810^error,msg="mi_cmd_exec_interrupt: Inferior not executing."
+ notifyInferiorStopOk();
+ }
+}
+
+void GdbEngine::handleStubAttached(const DebuggerResponse &response, qint64 mainThreadId)
+{
+ // InferiorStopOk can happen if the "*stopped" in response to the
+ // 'attach' comes in before its '^done'
+ QTC_ASSERT(state() == EngineRunRequested || state() == InferiorStopOk, qDebug() << state());
+
+ switch (response.resultClass) {
+ case ResultDone:
+ case ResultRunning:
+ if (runParameters().toolChainAbi.os() == ProjectExplorer::Abi::WindowsOS) {
+ QString errorMessage;
+ // Resume thread that was suspended by console stub process (see stub code).
+ if (winResumeThread(mainThreadId, &errorMessage)) {
+ showMessage(QString("Inferior attached, thread %1 resumed").
+ arg(mainThreadId), LogMisc);
+ } else {
+ showMessage(QString("Inferior attached, unable to resume thread %1: %2").
+ arg(mainThreadId).arg(errorMessage),
+ LogWarning);
+ }
+ notifyEngineRunAndInferiorStopOk();
+ continueInferiorInternal();
+ } else {
+ showMessage("INFERIOR ATTACHED AND RUNNING");
+ //notifyEngineRunAndInferiorRunOk();
+ // Wait for the upcoming *stopped and handle it there.
+ }
+ break;
+ case ResultError:
+ if (response.data["msg"].data() == "ptrace: Operation not permitted.") {
+ showMessage(msgPtraceError(runParameters().startMode));
+ notifyEngineRunFailed();
+ break;
+ }
+ showMessage(response.data["msg"].data());
+ notifyEngineIll();
+ break;
+ default:
+ showMessage(QString("Invalid response %1").arg(response.resultClass));
+ notifyEngineIll();
+ break;
+ }
+}
+
+static QString findExecutableFromName(const QString &fileNameFromCore, const QString &coreFile)
+{
+ if (fileNameFromCore.isEmpty())
+ return fileNameFromCore;
+ QFileInfo fi(fileNameFromCore);
+ if (fi.isFile())
+ return fileNameFromCore;
+
+ // turn the filename into an absolute path, using the location of the core as a hint
+ QString absPath;
+ if (fi.isAbsolute()) {
+ absPath = fileNameFromCore;
+ } else {
+ QFileInfo coreInfo(coreFile);
+ QDir coreDir = coreInfo.dir();
+ absPath = FileUtils::resolvePath(coreDir.absolutePath(), fileNameFromCore);
+ }
+ if (QFileInfo(absPath).isFile() || absPath.isEmpty())
+ return absPath;
+
+ // remove possible trailing arguments
+ QLatin1Char sep(' ');
+ QStringList pathFragments = absPath.split(sep);
+ while (pathFragments.size() > 0) {
+ QString joined_path = pathFragments.join(sep);
+ if (QFileInfo(joined_path).isFile()) {
+ return joined_path;
+ }
+ pathFragments.pop_back();
+ }
+
+ return QString();
+}
+
+CoreInfo CoreInfo::readExecutableNameFromCore(const StandardRunnable &debugger, const QString &coreFile)
+{
+ CoreInfo cinfo;
+#if 0
+ ElfReader reader(coreFile);
+ cinfo.rawStringFromCore = QString::fromLocal8Bit(reader.readCoreName(&cinfo.isCore));
+ cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile);
+#else
+ QStringList args = {"-nx", "-batch", "-c", coreFile};
+
+ SynchronousProcess proc;
+ QStringList envLang = QProcess::systemEnvironment();
+ Utils::Environment::setupEnglishOutput(&envLang);
+ proc.setEnvironment(envLang);
+ SynchronousProcessResponse response = proc.runBlocking(debugger.executable, args);
+
+ if (response.result == SynchronousProcessResponse::Finished) {
+ QString output = response.stdOut();
+ // Core was generated by `/data/dev/creator-2.6/bin/qtcreator'.
+ // Program terminated with signal 11, Segmentation fault.
+ int pos1 = output.indexOf("Core was generated by");
+ if (pos1 != -1) {
+ pos1 += 23;
+ int pos2 = output.indexOf('\'', pos1);
+ if (pos2 != -1) {
+ cinfo.isCore = true;
+ cinfo.rawStringFromCore = output.mid(pos1, pos2 - pos1);
+ cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile);
+ }
+ }
+ }
+#endif
+ return cinfo;
+}
+
+void GdbEngine::continueSetupEngine()
+{
+ if (isCoreEngine()) {
+ bool isCore = true;
+ if (m_coreUnpackProcess) {
+ isCore = m_coreUnpackProcess->exitCode() == 0;
+ m_coreUnpackProcess->deleteLater();
+ m_coreUnpackProcess = 0;
+ if (m_tempCoreFile.isOpen())
+ m_tempCoreFile.close();
+ }
+ if (isCore && m_executable.isEmpty()) {
+ CoreInfo cinfo =
+ CoreInfo::readExecutableNameFromCore(runParameters().debugger, coreFileName());
+
+ if (cinfo.isCore) {
+ m_executable = cinfo.foundExecutableName;
+ if (m_executable.isEmpty()) {
+ AsynchronousMessageBox::warning(tr("Error Loading Symbols"),
+ tr("No executable to load symbols from specified core."));
+ notifyEngineSetupFailed();
+ return;
+ }
+ }
+ }
+ if (isCore) {
+ startGdb();
+ } else {
+ AsynchronousMessageBox::warning(tr("Error Loading Core File"),
+ tr("The specified file does not appear to be a core file."));
+ notifyEngineSetupFailed();
+ }
}
}
+void GdbEngine::handleTargetCore(const DebuggerResponse &response)
+{
+ CHECK_STATE(EngineRunRequested);
+ notifyEngineRunOkAndInferiorUnrunnable();
+ showMessage(tr("Attached to core."), StatusBar);
+ if (response.resultClass == ResultError) {
+ // We'll accept any kind of error e.g. &"Cannot access memory at address 0x2abc2a24\n"
+ // Even without the stack, the user can find interesting stuff by exploring
+ // the memory, globals etc.
+ showStatusMessage(tr("Attach to core \"%1\" failed:").arg(runParameters().coreFile)
+ + '\n' + response.data["msg"].data()
+ + '\n' + tr("Continuing nevertheless."));
+ }
+ // Due to the auto-solib-add off setting, we don't have any
+ // symbols yet. Load them in order of importance.
+ reloadStack();
+ reloadModulesInternal();
+ runCommand({"p 5", CB(handleCoreRoundTrip)});
+}
+
+void GdbEngine::handleCoreRoundTrip(const DebuggerResponse &response)
+{
+ CHECK_STATE(InferiorUnrunnable);
+ Q_UNUSED(response);
+ loadSymbolsForStack();
+ handleStop3();
+ QTimer::singleShot(1000, this, &GdbEngine::loadAllSymbols);
+}
+
+static QString tempCoreFilename()
+{
+ Utils::TemporaryFile tmp("tmpcore-XXXXXX");
+ tmp.open();
+ return tmp.fileName();
+}
+
+void GdbEngine::unpackCoreIfNeeded()
+{
+ QStringList arguments;
+ const QString msg = "Unpacking core file to %1";
+ if (m_coreName.endsWith(".lzo")) {
+ m_tempCoreName = tempCoreFilename();
+ showMessage(msg.arg(m_tempCoreName));
+ arguments << "-o" << m_tempCoreName << "-x" << m_coreName;
+ m_coreUnpackProcess = new QProcess(this);
+ m_coreUnpackProcess->setWorkingDirectory(TemporaryDirectory::masterDirectoryPath());
+ m_coreUnpackProcess->start("lzop", arguments);
+ connect(m_coreUnpackProcess, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ this, &GdbEngine::continueSetupEngine);
+ } else if (m_coreName.endsWith(".gz")) {
+ m_tempCoreName = tempCoreFilename();
+ showMessage(msg.arg(m_tempCoreName));
+ m_tempCoreFile.setFileName(m_tempCoreName);
+ m_tempCoreFile.open(QFile::WriteOnly);
+ arguments << "-c" << "-d" << m_coreName;
+ m_coreUnpackProcess = new QProcess(this);
+ m_coreUnpackProcess->setWorkingDirectory(TemporaryDirectory::masterDirectoryPath());
+ m_coreUnpackProcess->start("gzip", arguments);
+ connect(m_coreUnpackProcess, &QProcess::readyRead, this, [this] {
+ m_tempCoreFile.write(m_coreUnpackProcess->readAll());
+ });
+ connect(m_coreUnpackProcess, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ this, &GdbEngine::continueSetupEngine);
+ } else {
+ continueSetupEngine();
+ }
+}
+
+QString GdbEngine::coreFileName() const
+{
+ return m_tempCoreName.isEmpty() ? m_coreName : m_tempCoreName;
+}
+
void GdbEngine::doUpdateLocals(const UpdateParameters &params)
{
m_pendingBreakpointRequests = 0;
@@ -4423,6 +5152,21 @@ QString GdbEngine::msgPtraceError(DebuggerStartMode sm)
"For more details, see /etc/sysctl.d/10-ptrace.conf\n");
}
+QString GdbEngine::mainFunction() const
+{
+ const DebuggerRunParameters &rp = runParameters();
+ return QLatin1String(rp.toolChainAbi.os() == Abi::WindowsOS && !terminal() ? "qMain" : "main");
+}
+
+//
+// Factory
+//
+
+DebuggerEngine *createGdbEngine()
+{
+ return new GdbEngine;
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 70abb82f1e..506f68c34c 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -33,66 +33,68 @@
#include <debugger/watchutils.h>
#include <debugger/debuggeritem.h>
#include <debugger/debuggertooltipmanager.h>
+#include <debugger/outputcollector.h>
#include <coreplugin/id.h>
-#include <projectexplorer/devicesupport/idevice.h>
#include <utils/qtcprocess.h>
+#include <utils/consoleprocess.h>
#include <QProcess>
#include <QTextCodec>
-#include <QTime>
#include <QTimer>
-#include <functional>
-
namespace Debugger {
namespace Internal {
-class GdbProcess;
+class BreakpointParameters;
+class BreakpointResponse;
class DebugInfoTask;
class DebugInfoTaskHandler;
class DebuggerResponse;
+class DisassemblerAgentCookie;
class GdbMi;
class MemoryAgentCookie;
-class BreakpointParameters;
-class BreakpointResponse;
+class TerminalRunner;
-class DisassemblerAgentCookie;
-class DisassemblerLines;
+struct CoreInfo
+{
+ QString rawStringFromCore;
+ QString foundExecutableName; // empty if no corresponding exec could be found
+ bool isCore = false;
+
+ static CoreInfo readExecutableNameFromCore(const ProjectExplorer::StandardRunnable &debugger,
+ const QString &coreFile);
+};
class GdbEngine : public DebuggerEngine
{
Q_OBJECT
public:
- explicit GdbEngine(bool useTerminal);
- ~GdbEngine() override;
+ GdbEngine();
+ ~GdbEngine() final;
private: ////////// General Interface //////////
- DebuggerEngine *cppEngine() override { return this; }
+ DebuggerEngine *cppEngine() final { return this; }
- virtual void handleGdbStartFailed();
- void notifyInferiorSetupFailed() override;
- void prepareForRestart() override;
+ void handleGdbStartFailed();
+ void prepareForRestart() final;
- bool hasCapability(unsigned) const override;
- void detachDebugger() override;
- void shutdownInferior() override;
- void abortDebugger() override;
- void resetInferior() override;
+ bool hasCapability(unsigned) const final;
+ void detachDebugger() final;
+ void shutdownInferior() final;
+ void abortDebuggerProcess() final;
+ void resetInferior() final;
- bool acceptsDebuggerCommands() const override;
- void executeDebuggerCommand(const QString &command, DebuggerLanguages languages) override;
+ bool acceptsDebuggerCommands() const final;
+ void executeDebuggerCommand(const QString &command, DebuggerLanguages languages) final;
-private: ////////// General State //////////
+ ////////// General State //////////
- DebuggerStartMode startMode() const;
- void reloadLocals();
-
- bool m_registerNamesListed;
+ bool m_registerNamesListed = false;
-protected: ////////// Gdb Process Management //////////
+ ////////// Gdb Process Management //////////
void startGdb(const QStringList &args = QStringList());
void handleInferiorShutdown(const DebuggerResponse &response);
@@ -115,8 +117,8 @@ protected: ////////// Gdb Process Management //////////
void handleDebugInfoLocation(const DebuggerResponse &response);
- // The adapter is still running just fine, but it failed to acquire a debuggee.
- void notifyInferiorSetupFailed(const QString &msg);
+ // The engine is still running just fine, but it failed to acquire a debuggee.
+ void notifyInferiorSetupFailedHelper(const QString &msg);
void notifyAdapterShutdownOk();
void notifyAdapterShutdownFailed();
@@ -125,10 +127,6 @@ protected: ////////// Gdb Process Management //////////
// Make sure to clean up everything before emitting this signal.
void handleAdapterCrashed(const QString &msg);
-private:
- friend class GdbPlainEngine;
- friend class GdbCoreEngine;
- void handleInterruptDeviceInferior(const QString &error);
void handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus);
void handleGdbError(QProcess::ProcessError error);
void readGdbStandardOutput();
@@ -141,17 +139,16 @@ private:
QTextCodec::ConverterState m_inferiorOutputCodecState;
QByteArray m_inbuffer;
- bool m_busy;
+ bool m_busy = false;
// Name of the convenience variable containing the last
// known function return value.
QString m_resultVarName;
-protected: ////////// Gdb Command Management //////////
+ ////////// Gdb Command Management //////////
- void runCommand(const DebuggerCommand &command) override;
+ void runCommand(const DebuggerCommand &command) final;
-private:
void commandTimeout();
void setTokenBarrier();
@@ -169,19 +166,19 @@ private:
// This contains the first token number for the current round
// of evaluation. Responses with older tokens are considers
// out of date and discarded.
- int m_oldestAcceptableToken;
- int m_nonDiscardableCount;
+ int m_oldestAcceptableToken = -1;
+ int m_nonDiscardableCount = 0;
- int m_pendingBreakpointRequests; // Watch updating commands in flight
+ int m_pendingBreakpointRequests = 0; // Watch updating commands in flight
typedef void (GdbEngine::*CommandsDoneCallback)();
// This function is called after all previous responses have been received.
- CommandsDoneCallback m_commandsDoneCallback;
+ CommandsDoneCallback m_commandsDoneCallback = nullptr;
+
+ bool m_rerunPending = false;
- bool m_rerunPending;
+ ////////// Gdb Output, State & Capability Handling //////////
-private: ////////// Gdb Output, State & Capability Handling //////////
-protected:
Q_INVOKABLE void handleResponse(const QString &buff);
void handleAsyncOutput(const QString &asyncClass, const GdbMi &result);
void handleStopResponse(const GdbMi &data);
@@ -191,42 +188,40 @@ protected:
void handleStop3();
void resetCommandQueue();
- bool isSynchronous() const override { return true; }
+ bool isSynchronous() const final { return true; }
// Gdb initialization sequence
void handleShowVersion(const DebuggerResponse &response);
void handleListFeatures(const DebuggerResponse &response);
void handlePythonSetup(const DebuggerResponse &response);
- int m_gdbVersion; // 7.6.1 is 70601
- int m_pythonVersion; // 2.7.2 is 20702
- bool m_isQnxGdb;
+ int m_gdbVersion = 100; // 7.6.1 is 70601
+ int m_pythonVersion = 0; // 2.7.2 is 20702
+ bool m_isQnxGdb = false;
-private: ////////// Inferior Management //////////
+ ////////// Inferior Management //////////
// This should be always the last call in a function.
- bool stateAcceptsBreakpointChanges() const override;
- bool acceptsBreakpoint(Breakpoint bp) const override;
- void insertBreakpoint(Breakpoint bp) override;
- void removeBreakpoint(Breakpoint bp) override;
- void changeBreakpoint(Breakpoint bp) override;
-
- void executeStep() override;
- void executeStepOut() override;
- void executeNext() override;
- void executeStepI() override;
- void executeNextI() override;
-
- protected:
+ bool stateAcceptsBreakpointChanges() const final;
+ bool acceptsBreakpoint(Breakpoint bp) const final;
+ void insertBreakpoint(Breakpoint bp) final;
+ void removeBreakpoint(Breakpoint bp) final;
+ void changeBreakpoint(Breakpoint bp) final;
+
+ void executeStep() final;
+ void executeStepOut() final;
+ void executeNext() final;
+ void executeStepI() final;
+ void executeNextI() final;
+
void continueInferiorInternal();
- void continueInferior() override;
- void interruptInferior() override;
- virtual void interruptInferior2() {}
+ void continueInferior() final;
+ void interruptInferior() final;
- void executeRunToLine(const ContextData &data) override;
- void executeRunToFunction(const QString &functionName) override;
- void executeJumpToLine(const ContextData &data) override;
- void executeReturn() override;
+ void executeRunToLine(const ContextData &data) final;
+ void executeRunToFunction(const QString &functionName) final;
+ void executeJumpToLine(const ContextData &data) final;
+ void executeReturn() final;
void handleExecuteContinue(const DebuggerResponse &response);
void handleExecuteStep(const DebuggerResponse &response);
@@ -237,10 +232,10 @@ private: ////////// Inferior Management //////////
QString msgPtraceError(DebuggerStartMode sm);
-private: ////////// View & Data Stuff //////////
+ ////////// View & Data Stuff //////////
- void selectThread(ThreadId threadId) override;
- void activateFrame(int index) override;
+ void selectThread(ThreadId threadId) final;
+ void activateFrame(int index) final;
void handleAutoContinueInferior();
//
@@ -268,14 +263,13 @@ private: ////////// View & Data Stuff //////////
//
// Modules specific stuff
//
- protected:
- void loadSymbols(const QString &moduleName) override;
- void loadAllSymbols() override;
- void loadSymbolsForStack() override;
- void requestModuleSymbols(const QString &moduleName) override;
- void requestModuleSections(const QString &moduleName) override;
- void reloadModules() override;
- void examineModules() override;
+ void loadSymbols(const QString &moduleName) final;
+ void loadAllSymbols() final;
+ void loadSymbolsForStack() final;
+ void requestModuleSymbols(const QString &moduleName) final;
+ void requestModuleSections(const QString &moduleName) final;
+ void reloadModules() final;
+ void examineModules() final;
void reloadModulesInternal();
void handleModulesList(const DebuggerResponse &response);
@@ -284,14 +278,14 @@ private: ////////// View & Data Stuff //////////
//
// Snapshot specific stuff
//
- virtual void createSnapshot() override;
+ void createSnapshot() final;
void handleMakeSnapshot(const DebuggerResponse &response, const QString &coreFile);
//
// Register specific stuff
//
- void reloadRegisters() override;
- void setRegisterValue(const QString &name, const QString &value) override;
+ void reloadRegisters() final;
+ void setRegisterValue(const QString &name, const QString &value) final;
void handleRegisterListNames(const DebuggerResponse &response);
void handleRegisterListing(const DebuggerResponse &response);
void handleRegisterListValues(const DebuggerResponse &response);
@@ -302,7 +296,7 @@ private: ////////// View & Data Stuff //////////
// Disassembler specific stuff
//
// Chain of fallbacks: PointMixed -> PointPlain -> RangeMixed -> RangePlain.
- void fetchDisassembler(DisassemblerAgent *agent) override;
+ void fetchDisassembler(DisassemblerAgent *agent) final;
void fetchDisassemblerByCliPointMixed(const DisassemblerAgentCookie &ac);
void fetchDisassemblerByCliRangeMixed(const DisassemblerAgentCookie &ac);
void fetchDisassemblerByCliRangePlain(const DisassemblerAgentCookie &ac);
@@ -311,7 +305,7 @@ private: ////////// View & Data Stuff //////////
//
// Source file specific stuff
//
- void reloadSourceFiles() override;
+ void reloadSourceFiles() final;
void reloadSourceFilesInternal();
void handleQuerySources(const DebuggerResponse &response);
@@ -323,13 +317,12 @@ private: ////////// View & Data Stuff //////////
QMap<QString, QString> m_fullToShortName;
QMultiMap<QString, QString> m_baseNameToFullName;
- bool m_sourcesListUpdating;
+ bool m_sourcesListUpdating = false;
//
// Stack specific stuff
//
-protected:
- void updateAll() override;
+ void updateAll() final;
void handleStackListFrames(const DebuggerResponse &response, bool isFull);
void handleStackSelectThread(const DebuggerResponse &response);
void handleThreadListIds(const DebuggerResponse &response);
@@ -337,20 +330,21 @@ protected:
void handleThreadNames(const DebuggerResponse &response);
DebuggerCommand stackCommand(int depth);
void reloadStack();
- void reloadFullStack() override;
- void loadAdditionalQmlStack() override;
+ void reloadFullStack() final;
+ void loadAdditionalQmlStack() final;
int currentFrame() const;
//
// Watch specific stuff
//
- virtual void assignValueInDebugger(WatchItem *item,
- const QString &expr, const QVariant &value) override;
+ void reloadLocals();
+ void assignValueInDebugger(WatchItem *item,
+ const QString &expr, const QVariant &value) final;
- void fetchMemory(MemoryAgent *agent, quint64 addr, quint64 length) override;
+ void fetchMemory(MemoryAgent *agent, quint64 addr, quint64 length) final;
void fetchMemoryHelper(const MemoryAgentCookie &cookie);
void handleChangeMemory(const DebuggerResponse &response);
- void changeMemory(MemoryAgent *agent, quint64 addr, const QByteArray &data) override;
+ void changeMemory(MemoryAgent *agent, quint64 addr, const QByteArray &data) final;
void handleFetchMemory(const DebuggerResponse &response, MemoryAgentCookie ac);
void showToolTip();
@@ -361,7 +355,7 @@ protected:
void createFullBacktrace();
- void doUpdateLocals(const UpdateParameters &parameters) override;
+ void doUpdateLocals(const UpdateParameters &parameters) final;
void handleFetchVariables(const DebuggerResponse &response);
void setLocals(const QList<GdbMi> &locals);
@@ -369,7 +363,7 @@ protected:
//
// Dumper Management
//
- void reloadDebuggingHelpers() override;
+ void reloadDebuggingHelpers() final;
//
// Convenience Functions
@@ -377,20 +371,18 @@ protected:
void showExecutionError(const QString &message);
QString failedToStartMessage();
- static QString tooltipIName(const QString &exp);
-
// For short-circuiting stack and thread list evaluation.
- bool m_stackNeeded;
+ bool m_stackNeeded = false;
// For suppressing processing *stopped and *running responses
// while updating locals.
- bool m_inUpdateLocals;
+ bool m_inUpdateLocals = false;
// HACK:
QString m_currentThread;
QString m_lastWinException;
QString m_lastMissingDebugInfo;
- bool m_terminalTrap;
+ bool m_expectTerminalTrap = false;
bool usesExecInterrupt() const;
bool usesTargetAsync() const;
@@ -404,7 +396,7 @@ protected:
void requestDebugInformation(const DebugInfoTask &task);
DebugInfoTaskHandler *m_debugInfoTaskHandler;
- bool m_systemDumpersLoaded;
+ bool m_systemDumpersLoaded = false;
static QString msgGdbStopFailed(const QString &why);
static QString msgInferiorStopFailed(const QString &why);
@@ -413,16 +405,63 @@ protected:
static QString msgInferiorRunOk();
static QString msgConnectRemoteServerFailed(const QString &why);
- void debugLastCommand() override;
+ void debugLastCommand() final;
DebuggerCommand m_lastDebuggableCommand;
-protected:
+ bool isPlainEngine() const;
+ bool isCoreEngine() const;
+ bool isRemoteEngine() const;
+ bool isAttachEngine() const;
+ bool isTermEngine() const;
+
+ void setupEngine() final;
+ void setupInferior() final;
+ void runEngine() final;
+ void shutdownEngine() final;
+
+ void interruptInferior2();
+
+ // Plain
+ void handleExecRun(const DebuggerResponse &response);
+ void handleFileExecAndSymbols(const DebuggerResponse &response);
+
+ // Attach
+ void handleAttach(const DebuggerResponse &response);
+
+ // Remote
+ void callTargetRemote();
+ void handleSetTargetAsync(const DebuggerResponse &response);
+ void handleTargetRemote(const DebuggerResponse &response);
+ void handleTargetExtendedRemote(const DebuggerResponse &response);
+ void handleTargetExtendedAttach(const DebuggerResponse &response);
+ void handleTargetQnx(const DebuggerResponse &response);
+ void handleSetNtoExecutable(const DebuggerResponse &response);
+ void handleInterruptInferior(const DebuggerResponse &response);
void interruptLocalInferior(qint64 pid);
-protected:
+ // Terminal
+ void handleStubAttached(const DebuggerResponse &response, qint64 mainThreadId);
+
+ // Core
+ void handleTargetCore(const DebuggerResponse &response);
+ void handleCoreRoundTrip(const DebuggerResponse &response);
+ void unpackCoreIfNeeded();
+ QString coreFileName() const;
+ QString coreName() const;
+
+ void continueSetupEngine();
+ QString mainFunction() const;
+
+ QString m_executable;
+ QString m_coreName;
+ QString m_tempCoreName;
+ QProcess *m_coreUnpackProcess = nullptr;
+ QFile m_tempCoreFile;
+
Utils::QtcProcess m_gdbProc;
+ OutputCollector m_outputCollector;
QString m_errorString;
- ProjectExplorer::DeviceProcessSignalOperation::Ptr m_signalOperation;
+ DebuggerStartMode m_startMode = NoStartMode;
};
} // namespace Internal
diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp
index cecf8ccaea..822e7d8b8c 100644
--- a/src/plugins/debugger/gdb/gdboptionspage.cpp
+++ b/src/plugins/debugger/gdb/gdboptionspage.cpp
@@ -86,11 +86,11 @@ GdbOptionsPageWidget::GdbOptionsPageWidget()
auto labelGdbWatchdogTimeout = new QLabel(groupBoxGeneral);
labelGdbWatchdogTimeout->setText(GdbOptionsPage::tr("GDB timeout:"));
labelGdbWatchdogTimeout->setToolTip(GdbOptionsPage::tr(
- "The number of seconds Qt Creator will wait before it terminates\n"
- "a non-responsive GDB process. The default value of 20 seconds should\n"
- "be sufficient for most applications, but there are situations when\n"
- "loading big libraries or listing source files takes much longer than\n"
- "that on slow machines. In this case, the value should be increased."));
+ "The number of seconds before a non-responsive GDB process is terminated.\n"
+ "The default value of 20 seconds should be sufficient for most\n"
+ "applications, but there are situations when loading big libraries or\n"
+ "listing source files takes much longer than that on slow machines.\n"
+ "In this case, the value should be increased."));
auto spinBoxGdbWatchdogTimeout = new QSpinBox(groupBoxGeneral);
spinBoxGdbWatchdogTimeout->setToolTip(labelGdbWatchdogTimeout->toolTip());
diff --git a/src/plugins/debugger/gdb/gdbplainengine.cpp b/src/plugins/debugger/gdb/gdbplainengine.cpp
deleted file mode 100644
index d957336891..0000000000
--- a/src/plugins/debugger/gdb/gdbplainengine.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "gdbplainengine.h"
-
-#include <debugger/debuggeractions.h>
-#include <debugger/debuggercore.h>
-#include <debugger/debuggerprotocol.h>
-#include <debugger/debuggerstartparameters.h>
-
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
-
-#include <QFileInfo>
-
-namespace Debugger {
-namespace Internal {
-
-#define CB(callback) [this](const DebuggerResponse &r) { callback(r); }
-
-GdbPlainEngine::GdbPlainEngine(bool useTerminal)
- : GdbEngine(useTerminal)
-{
- // Output
- connect(&m_outputCollector, &OutputCollector::byteDelivery,
- this, &GdbEngine::readDebuggeeOutput);
-}
-
-void GdbPlainEngine::setupInferior()
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- setEnvironmentVariables();
- const DebuggerRunParameters &rp = runParameters();
- if (!rp.inferior.workingDirectory.isEmpty())
- runCommand({"cd " + rp.inferior.workingDirectory});
- if (!rp.inferior.commandLineArguments.isEmpty()) {
- QString args = rp.inferior.commandLineArguments;
- runCommand({"-exec-arguments " + args});
- }
-
- QString executable = QFileInfo(runParameters().inferior.executable).absoluteFilePath();
- runCommand({"-file-exec-and-symbols \"" + executable + '"',
- CB(handleFileExecAndSymbols)});
-}
-
-void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- if (response.resultClass == ResultDone) {
- handleInferiorPrepared();
- } else {
- QString msg = response.data["msg"].data();
- // Extend the message a bit in unknown cases.
- if (!msg.endsWith("File format not recognized"))
- msg = tr("Starting executable failed:") + '\n' + msg;
- notifyInferiorSetupFailed(msg);
- }
-}
-
-void GdbPlainEngine::runEngine()
-{
- if (runParameters().useContinueInsteadOfRun)
- runCommand({"-exec-continue", DebuggerCommand::RunRequest, CB(handleExecuteContinue)});
- else
- runCommand({"-exec-run", DebuggerCommand::RunRequest, CB(handleExecRun)});
-}
-
-void GdbPlainEngine::handleExecRun(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
- if (response.resultClass == ResultRunning) {
- notifyEngineRunAndInferiorRunOk(); // For gdb < 7.0
- //showStatusMessage(tr("Running..."));
- showMessage("INFERIOR STARTED");
- showMessage(msgInferiorSetupOk(), StatusBar);
- // FIXME: That's the wrong place for it.
- if (boolSetting(EnableReverseDebugging))
- runCommand({"target record"});
- } else {
- QString msg = response.data["msg"].data();
- //QTC_CHECK(status() == InferiorRunOk);
- //interruptInferior();
- showMessage(msg);
- notifyEngineRunFailed();
- }
-}
-
-void GdbPlainEngine::setupEngine()
-{
- QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
- showMessage("TRYING TO START ADAPTER");
-
- if (!prepareCommand())
- return;
-
- QStringList gdbArgs;
-
- if (!m_outputCollector.listen()) {
- handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
- .arg(m_outputCollector.errorString()));
- return;
- }
- gdbArgs.append("--tty=" + m_outputCollector.serverName());
-
- startGdb(gdbArgs);
-}
-
-void GdbPlainEngine::handleGdbStartFailed()
-{
- m_outputCollector.shutdown();
-}
-
-void GdbPlainEngine::interruptInferior2()
-{
- interruptLocalInferior(inferiorPid());
-}
-
-void GdbPlainEngine::shutdownEngine()
-{
- showMessage(QString("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
- m_outputCollector.shutdown();
- notifyAdapterShutdownOk();
-}
-
-} // namespace Debugger
-} // namespace Internal
diff --git a/src/plugins/debugger/gdb/gdbplainengine.h b/src/plugins/debugger/gdb/gdbplainengine.h
deleted file mode 100644
index a2f6e04a6b..0000000000
--- a/src/plugins/debugger/gdb/gdbplainengine.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "gdbengine.h"
-#include <debugger/outputcollector.h>
-
-namespace Debugger {
-namespace Internal {
-
-class GdbPlainEngine : public GdbEngine
-{
- // Needs tr - Context
- Q_OBJECT
-
-public:
- explicit GdbPlainEngine(bool useTerminal);
-
-private:
- void handleExecRun(const DebuggerResponse &response);
- void handleFileExecAndSymbols(const DebuggerResponse &response);
-
- void setupInferior() override;
- void runEngine() override;
- void setupEngine() override;
- void handleGdbStartFailed() override;
- void interruptInferior2() override;
- void shutdownEngine() override;
-
- OutputCollector m_outputCollector;
-};
-
-} // namespace Debugger
-} // namespace Internal
diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
deleted file mode 100644
index 20dfce0261..0000000000
--- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp
+++ /dev/null
@@ -1,459 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "remotegdbserveradapter.h"
-
-#include <debugger/debuggeractions.h>
-#include <debugger/debuggercore.h>
-#include <debugger/debuggerprotocol.h>
-#include <debugger/debuggerruncontrol.h>
-#include <debugger/procinterrupt.h>
-
-#include <coreplugin/messagebox.h>
-
-#include <utils/hostosinfo.h>
-#include <utils/qtcfallthrough.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-
-#include <QAbstractButton>
-#include <QFileInfo>
-#include <QMessageBox>
-
-using namespace Utils;
-
-namespace Debugger {
-namespace Internal {
-
-#define CB(callback) [this](const DebuggerResponse &r) { callback(r); }
-
-///////////////////////////////////////////////////////////////////////
-//
-// RemoteGdbAdapter
-//
-///////////////////////////////////////////////////////////////////////
-
-GdbRemoteServerEngine::GdbRemoteServerEngine(bool useTerminal)
- : GdbEngine(useTerminal)
-{
- connect(&m_uploadProc, &QProcess::errorOccurred, this, &GdbRemoteServerEngine::uploadProcError);
- connect(&m_uploadProc, &QProcess::readyReadStandardOutput,
- this, &GdbRemoteServerEngine::readUploadStandardOutput);
- connect(&m_uploadProc, &QProcess::readyReadStandardError,
- this, &GdbRemoteServerEngine::readUploadStandardError);
- connect(&m_uploadProc, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
- this, &GdbRemoteServerEngine::uploadProcFinished);
-}
-
-void GdbRemoteServerEngine::setupEngine()
-{
- if (HostOsInfo::isWindowsHost())
- m_gdbProc.setUseCtrlCStub(runParameters().useCtrlCStub); // This is only set for QNX
-
- QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
- showMessage("TRYING TO START ADAPTER");
- QString serverStartScript = runParameters().serverStartScript;
- if (!serverStartScript.isEmpty()) {
-
- // Provide script information about the environment
- QString arglist;
- QtcProcess::addArg(&arglist, serverStartScript);
- QtcProcess::addArg(&arglist, runParameters().inferior.executable);
- QtcProcess::addArg(&arglist, runParameters().remoteChannel);
-
- m_uploadProc.start(arglist);
- m_uploadProc.waitForStarted();
- m_uploadProc.waitForFinished();
- }
-
- startGdb();
-}
-
-void GdbRemoteServerEngine::uploadProcError(QProcess::ProcessError error)
-{
- QString msg;
- switch (error) {
- case QProcess::FailedToStart:
- msg = tr("The upload process failed to start. Shell missing?");
- break;
- case QProcess::Crashed:
- msg = tr("The upload process crashed some time after starting "
- "successfully.");
- break;
- case QProcess::Timedout:
- msg = tr("The last waitFor...() function timed out. "
- "The state of QProcess is unchanged, and you can try calling "
- "waitFor...() again.");
- break;
- case QProcess::WriteError:
- msg = tr("An error occurred when attempting to write "
- "to the upload process. For example, the process may not be running, "
- "or it may have closed its input channel.");
- break;
- case QProcess::ReadError:
- msg = tr("An error occurred when attempting to read from "
- "the upload process. For example, the process may not be running.");
- break;
- default:
- msg = tr("An unknown error in the upload process occurred. "
- "This is the default return value of error().");
- }
-
- showMessage(msg, StatusBar);
- Core::AsynchronousMessageBox::critical(tr("Error"), msg);
-}
-
-void GdbRemoteServerEngine::readUploadStandardOutput()
-{
- const QByteArray ba = m_uploadProc.readAllStandardOutput();
- const QString msg = QString::fromLocal8Bit(ba, ba.length());
- showMessage(msg, LogOutput);
- showMessage(msg, AppOutput);
-}
-
-void GdbRemoteServerEngine::readUploadStandardError()
-{
- const QByteArray ba = m_uploadProc.readAllStandardError();
- const QString msg = QString::fromLocal8Bit(ba, ba.length());
- showMessage(msg, LogOutput);
- showMessage(msg, AppError);
-}
-
-void GdbRemoteServerEngine::uploadProcFinished()
-{
- if (m_uploadProc.exitStatus() == QProcess::NormalExit && m_uploadProc.exitCode() == 0) {
- // all good.
- } else {
- runTool()->reportFailure(tr("Upload failed: %1").arg(m_uploadProc.errorString()));
- }
-}
-
-void GdbRemoteServerEngine::setupInferior()
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- setLinuxOsAbi();
- const DebuggerRunParameters &rp = runParameters();
- QString symbolFile;
- if (!rp.symbolFile.isEmpty()) {
- QFileInfo fi(rp.symbolFile);
- symbolFile = fi.absoluteFilePath();
- }
-
- //const QByteArray sysroot = sp.sysroot.toLocal8Bit();
- //const QByteArray remoteArch = sp.remoteArchitecture.toLatin1();
- const QString args = runParameters().inferior.commandLineArguments;
-
-// if (!remoteArch.isEmpty())
-// postCommand("set architecture " + remoteArch);
- if (!rp.solibSearchPath.isEmpty()) {
- DebuggerCommand cmd("appendSolibSearchPath");
- cmd.arg("path", rp.solibSearchPath);
- cmd.arg("separator", HostOsInfo::pathListSeparator());
- runCommand(cmd);
- }
-
- if (!args.isEmpty())
- runCommand({"-exec-arguments " + args});
-
- setEnvironmentVariables();
-
- // This has to be issued before 'target remote'. On pre-7.0 the
- // command is not present and will result in ' No symbol table is
- // loaded. Use the "file" command.' as gdb tries to set the
- // value of a variable with name 'target-async'.
- //
- // Testing with -list-target-features which was introduced at
- // the same time would not work either, as this need an existing
- // target.
- //
- // Using it even without a target and having it fail might still
- // be better as:
- // Some external comment: '[but] "set target-async on" with a native
- // windows gdb will work, but then fail when you actually do
- // "run"/"attach", I think..
-
-
- // gdb/mi/mi-main.c:1958: internal-error:
- // mi_execute_async_cli_command: Assertion `is_running (inferior_ptid)'
- // failed.\nA problem internal to GDB has been detected,[...]
- if (usesTargetAsync())
- runCommand({"set target-async on", CB(handleSetTargetAsync)});
-
- if (symbolFile.isEmpty()) {
- showMessage(tr("No symbol file given."), StatusBar);
- callTargetRemote();
- return;
- }
-
- if (!symbolFile.isEmpty()) {
- runCommand({"-file-exec-and-symbols \"" + symbolFile + '"',
- CB(handleFileExecAndSymbols)});
- }
-}
-
-void GdbRemoteServerEngine::handleSetTargetAsync(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- if (response.resultClass == ResultError)
- qDebug() << "Adapter too old: does not support asynchronous mode.";
-}
-
-void GdbRemoteServerEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- if (response.resultClass == ResultDone) {
- callTargetRemote();
- } else {
- QString reason = response.data["msg"].data();
- QString msg = tr("Reading debug information failed:") + '\n' + reason;
- if (reason.endsWith("No such file or directory.")) {
- showMessage("INFERIOR STARTUP: BINARY NOT FOUND");
- showMessage(msg, StatusBar);
- callTargetRemote(); // Proceed nevertheless.
- } else {
- notifyInferiorSetupFailed(msg);
- }
- }
-}
-
-void GdbRemoteServerEngine::callTargetRemote()
-{
- QString channel = runParameters().remoteChannel;
-
- // Don't touch channels with explicitly set protocols.
- if (!channel.startsWith("tcp:") && !channel.startsWith("udp:")
- && !channel.startsWith("file:") && channel.contains(':')
- && !channel.startsWith('|'))
- {
- // "Fix" the IPv6 case with host names without '['...']'
- if (!channel.startsWith('[') && channel.count(':') >= 2) {
- channel.insert(0, '[');
- channel.insert(channel.lastIndexOf(':'), ']');
- }
- channel = "tcp:" + channel;
- }
-
- if (m_isQnxGdb)
- runCommand({"target qnx " + channel, CB(handleTargetQnx)});
- else if (runParameters().useExtendedRemote)
- runCommand({"target extended-remote " + channel, CB(handleTargetExtendedRemote)});
- else
- runCommand({"target remote " + channel, CB(handleTargetRemote)});
-}
-
-void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- if (response.resultClass == ResultDone) {
- // gdb server will stop the remote application itself.
- showMessage("INFERIOR STARTED");
- showMessage(msgAttachedToStoppedInferior(), StatusBar);
- QString commands = expand(stringSetting(GdbPostAttachCommands));
- if (!commands.isEmpty())
- runCommand({commands, NativeCommand});
- handleInferiorPrepared();
- } else {
- // 16^error,msg="hd:5555: Connection timed out."
- notifyInferiorSetupFailed(msgConnectRemoteServerFailed(response.data["msg"].data()));
- }
-}
-
-void GdbRemoteServerEngine::handleTargetExtendedRemote(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- if (response.resultClass == ResultDone) {
- showMessage("ATTACHED TO GDB SERVER STARTED");
- showMessage(msgAttachedToStoppedInferior(), StatusBar);
- QString commands = expand(stringSetting(GdbPostAttachCommands));
- if (!commands.isEmpty())
- runCommand({commands, NativeCommand});
- if (runParameters().attachPID.isValid()) { // attach to pid if valid
- // gdb server will stop the remote application itself.
- runCommand({"attach " + QString::number(runParameters().attachPID.pid()),
- CB(handleTargetExtendedAttach)});
- } else if (!runParameters().inferior.executable.isEmpty()) {
- runCommand({"-gdb-set remote exec-file " + runParameters().inferior.executable,
- CB(handleTargetExtendedAttach)});
- } else {
- const QString title = tr("No Remote Executable or Process ID Specified");
- const QString msg = tr(
- "No remote executable could be determined from your build system files.<p>"
- "In case you use qmake, consider adding<p>"
- "&nbsp;&nbsp;&nbsp;&nbsp;target.path = /tmp/your_executable # path on device<br>"
- "&nbsp;&nbsp;&nbsp;&nbsp;INSTALLS += target</p>"
- "to your .pro file.");
- QMessageBox *mb = showMessageBox(QMessageBox::Critical, title, msg,
- QMessageBox::Ok | QMessageBox::Cancel);
- mb->button(QMessageBox::Cancel)->setText(tr("Continue Debugging"));
- mb->button(QMessageBox::Ok)->setText(tr("Stop Debugging"));
- if (mb->exec() == QMessageBox::Ok) {
- showMessage("KILLING DEBUGGER AS REQUESTED BY USER");
- notifyInferiorSetupFailed(title);
- } else {
- showMessage("CONTINUE DEBUGGER AS REQUESTED BY USER");
- handleInferiorPrepared(); // This will likely fail.
- }
- }
- } else {
- notifyInferiorSetupFailed(msgConnectRemoteServerFailed(response.data["msg"].data()));
- }
-}
-
-void GdbRemoteServerEngine::handleTargetExtendedAttach(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- if (response.resultClass == ResultDone) {
- // gdb server will stop the remote application itself.
- handleInferiorPrepared();
- } else {
- notifyInferiorSetupFailed(msgConnectRemoteServerFailed(response.data["msg"].data()));
- }
-}
-
-void GdbRemoteServerEngine::handleTargetQnx(const DebuggerResponse &response)
-{
- QTC_ASSERT(m_isQnxGdb, qDebug() << m_isQnxGdb);
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- if (response.resultClass == ResultDone) {
- // gdb server will stop the remote application itself.
- showMessage("INFERIOR STARTED");
- showMessage(msgAttachedToStoppedInferior(), StatusBar);
-
- const DebuggerRunParameters &rp = isMasterEngine() ? runParameters() : masterEngine()->runParameters();
- const QString remoteExecutable = rp.inferior.executable;
- if (rp.attachPID.isValid())
- runCommand({"attach " + QString::number(rp.attachPID.pid()), CB(handleAttach)});
- else if (!remoteExecutable.isEmpty())
- runCommand({"set nto-executable " + remoteExecutable, CB(handleSetNtoExecutable)});
- else
- handleInferiorPrepared();
- } else {
- // 16^error,msg="hd:5555: Connection timed out."
- notifyInferiorSetupFailed(response.data["msg"].data());
- }
-}
-
-void GdbRemoteServerEngine::handleAttach(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- switch (response.resultClass) {
- case ResultDone:
- case ResultRunning: {
- showMessage("INFERIOR ATTACHED");
- showMessage(msgAttachedToStoppedInferior(), StatusBar);
- handleInferiorPrepared();
- break;
- }
- case ResultError:
- if (response.data["msg"].data() == "ptrace: Operation not permitted.") {
- notifyInferiorSetupFailed(msgPtraceError(runParameters().startMode));
- break;
- }
- Q_FALLTHROUGH(); // if msg != "ptrace: ..."
- default:
- notifyInferiorSetupFailed(response.data["msg"].data());
- }
-}
-
-void GdbRemoteServerEngine::handleSetNtoExecutable(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- switch (response.resultClass) {
- case ResultDone:
- case ResultRunning: {
- showMessage("EXECUTABLE SET");
- showMessage(msgAttachedToStoppedInferior(), StatusBar);
- handleInferiorPrepared();
- break;
- }
- case ResultError:
- default:
- notifyInferiorSetupFailed(response.data["msg"].data());
- }
-}
-
-void GdbRemoteServerEngine::runEngine()
-{
- QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
-
- if (runParameters().useContinueInsteadOfRun) {
- notifyEngineRunAndInferiorStopOk();
- continueInferiorInternal();
- } else {
- runCommand({"-exec-run", DebuggerCommand::RunRequest, CB(handleExecRun)});
- }
-}
-
-void GdbRemoteServerEngine::handleExecRun(const DebuggerResponse &response)
-{
- QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
- if (response.resultClass == ResultRunning) {
- notifyEngineRunAndInferiorRunOk();
- showMessage("INFERIOR STARTED");
- showMessage(msgInferiorSetupOk(), StatusBar);
- } else {
- showMessage(response.data["msg"].data());
- notifyEngineRunFailed();
- }
-}
-
-void GdbRemoteServerEngine::interruptInferior2()
-{
- QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
- if (usesTargetAsync()) {
- runCommand({"-exec-interrupt", CB(handleInterruptInferior)});
- } else if (m_isQnxGdb && HostOsInfo::isWindowsHost()) {
- m_gdbProc.interrupt();
- } else {
- qint64 pid = m_gdbProc.processId();
- bool ok = interruptProcess(pid, GdbEngineType, &m_errorString);
- if (!ok) {
- // FIXME: Extra state needed?
- showMessage("NOTE: INFERIOR STOP NOT POSSIBLE");
- showStatusMessage(tr("Interrupting not possible"));
- notifyInferiorRunOk();
- }
- }
-}
-
-void GdbRemoteServerEngine::handleInterruptInferior(const DebuggerResponse &response)
-{
- if (response.resultClass == ResultDone) {
- // The gdb server will trigger extra output that we will pick up
- // to do a proper state transition.
- } else {
- // FIXME: On some gdb versions like git 170ffa5d7dd this produces
- // >810^error,msg="mi_cmd_exec_interrupt: Inferior not executing."
- notifyInferiorStopOk();
- }
-}
-
-void GdbRemoteServerEngine::shutdownEngine()
-{
- notifyAdapterShutdownOk();
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.h b/src/plugins/debugger/gdb/remotegdbserveradapter.h
deleted file mode 100644
index 0f042b669a..0000000000
--- a/src/plugins/debugger/gdb/remotegdbserveradapter.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "gdbengine.h"
-
-namespace Debugger {
-namespace Internal {
-
-class GdbRemoteServerEngine : public GdbEngine
-{
- Q_OBJECT
-
-public:
- explicit GdbRemoteServerEngine(bool useTerminal);
-
-private:
- void setupEngine() override;
- void setupInferior() override;
- void runEngine() override;
- void interruptInferior2() override;
- void shutdownEngine() override;
-
- void readUploadStandardOutput();
- void readUploadStandardError();
- void uploadProcError(QProcess::ProcessError error);
- void uploadProcFinished();
- void callTargetRemote();
-
- void handleSetTargetAsync(const DebuggerResponse &response);
- void handleFileExecAndSymbols(const DebuggerResponse &response);
- void handleTargetRemote(const DebuggerResponse &response);
- void handleTargetExtendedRemote(const DebuggerResponse &response);
- void handleTargetExtendedAttach(const DebuggerResponse &response);
- void handleTargetQnx(const DebuggerResponse &response);
- void handleAttach(const DebuggerResponse &response);
- void handleSetNtoExecutable(const DebuggerResponse &response);
- void handleInterruptInferior(const DebuggerResponse &response);
- void handleExecRun(const DebuggerResponse &response);
-
- QProcess m_uploadProc;
-};
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/startgdbserverdialog.cpp b/src/plugins/debugger/gdb/startgdbserverdialog.cpp
index 1a583f6f5c..a9596269ca 100644
--- a/src/plugins/debugger/gdb/startgdbserverdialog.cpp
+++ b/src/plugins/debugger/gdb/startgdbserverdialog.cpp
@@ -207,14 +207,17 @@ void GdbServerStarter::attach(int port)
return;
}
- DebuggerRunParameters rp;
- rp.masterEngineType = GdbEngineType;
- rp.remoteChannel = QString("%1:%2").arg(d->device->sshParameters().host).arg(port);
- rp.displayName = tr("Remote: \"%1\"").arg(rp.remoteChannel);
- rp.inferior.executable = localExecutable;
- rp.startMode = AttachToRemoteServer;
- rp.closeMode = KillAtClose;
- createAndScheduleRun(rp, d->kit);
+ QString remoteChannel = QString("%1:%2").arg(d->device->sshParameters().host).arg(port);
+
+ auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new DebuggerRunTool(runControl, d->kit);
+ debugger->setRemoteChannel(remoteChannel);
+ debugger->setRunControlName(tr("Remote: \"%1\"").arg(remoteChannel));
+ debugger->setInferiorExecutable(localExecutable);
+ debugger->setStartMode(AttachToRemoteServer);
+ debugger->setCloseMode(KillAtClose);
+
+ debugger->startRunControl();
}
void GdbServerStarter::handleProcessClosed(int status)
diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp
deleted file mode 100644
index 60a66cb9f7..0000000000
--- a/src/plugins/debugger/gdb/termgdbadapter.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "termgdbadapter.h"
-
-#include <debugger/debuggercore.h>
-#include <debugger/debuggerprotocol.h>
-#include <debugger/debuggerstartparameters.h>
-#include <debugger/shared/hostutils.h>
-
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/messagebox.h>
-
-using namespace Utils;
-
-namespace Debugger {
-namespace Internal {
-
-///////////////////////////////////////////////////////////////////////
-//
-// TermGdbAdapter
-//
-///////////////////////////////////////////////////////////////////////
-
-GdbTermEngine::GdbTermEngine(bool useTerminal)
- : GdbEngine(useTerminal)
-{
- if (HostOsInfo::isWindowsHost()) {
- // Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
- m_stubProc.setMode(ConsoleProcess::Suspend);
- else
- m_stubProc.setMode(ConsoleProcess::Debug);
- } else {
- m_stubProc.setMode(ConsoleProcess::Debug);
- m_stubProc.setSettings(Core::ICore::settings());
- }
-}
-
-GdbTermEngine::~GdbTermEngine()
-{
- m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
-}
-
-void GdbTermEngine::setupEngine()
-{
- QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
- showMessage("TRYING TO START ADAPTER");
-
-// Currently, adapters are not re-used
-// // We leave the console open, so recycle it now.
-// m_stubProc.blockSignals(true);
-// m_stubProc.stop();
-// m_stubProc.blockSignals(false);
-
- if (!prepareCommand())
- return;
-
- m_stubProc.setWorkingDirectory(runParameters().inferior.workingDirectory);
- // Set environment + dumper preload.
- m_stubProc.setEnvironment(runParameters().stubEnvironment);
-
- connect(&m_stubProc, &ConsoleProcess::processError,
- this, &GdbTermEngine::stubError);
- connect(&m_stubProc, &ConsoleProcess::processStarted,
- this, &GdbTermEngine::stubStarted);
- connect(&m_stubProc, &ConsoleProcess::stubStopped,
- this, &GdbTermEngine::stubExited);
- // FIXME: Starting the stub implies starting the inferior. This is
- // fairly unclean as far as the state machine and error reporting go.
-
- if (!m_stubProc.start(runParameters().inferior.executable,
- runParameters().inferior.commandLineArguments)) {
- // Error message for user is delivered via a signal.
- handleAdapterStartFailed(QString());
- return;
- }
-}
-
-void GdbTermEngine::stubStarted()
-{
- startGdb();
-}
-
-void GdbTermEngine::handleGdbStartFailed()
-{
- m_stubProc.stop();
-}
-
-void GdbTermEngine::setupInferior()
-{
- QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- const qint64 attachedPID = m_stubProc.applicationPID();
- const qint64 attachedMainThreadID = m_stubProc.applicationMainThreadID();
- notifyInferiorPid(ProcessHandle(attachedPID));
- const QString msg = (attachedMainThreadID != -1)
- ? QString("Going to attach to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
- : QString("Going to attach to %1").arg(attachedPID);
- showMessage(msg, LogMisc);
- handleInferiorPrepared();
-}
-
-void GdbTermEngine::runEngine()
-{
- QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
- const qint64 attachedPID = m_stubProc.applicationPID();
- runCommand({"attach " + QString::number(attachedPID),
- [this](const DebuggerResponse &r) { handleStubAttached(r); }});
-}
-
-void GdbTermEngine::handleStubAttached(const DebuggerResponse &response)
-{
- // InferiorStopOk can happen if the "*stopped" in response to the
- // 'attach' comes in before its '^done'
- QTC_ASSERT(state() == EngineRunRequested || state() == InferiorStopOk,
- qDebug() << state());
-
- switch (response.resultClass) {
- case ResultDone:
- case ResultRunning:
- if (runParameters().toolChainAbi.os() == ProjectExplorer::Abi::WindowsOS) {
- QString errorMessage;
- // Resume thread that was suspended by console stub process (see stub code).
- const qint64 mainThreadId = m_stubProc.applicationMainThreadID();
- if (winResumeThread(mainThreadId, &errorMessage)) {
- showMessage(QString("Inferior attached, thread %1 resumed").
- arg(mainThreadId), LogMisc);
- } else {
- showMessage(QString("Inferior attached, unable to resume thread %1: %2").
- arg(mainThreadId).arg(errorMessage),
- LogWarning);
- }
- notifyEngineRunAndInferiorStopOk();
- continueInferiorInternal();
- } else {
- showMessage("INFERIOR ATTACHED AND RUNNING");
- //notifyEngineRunAndInferiorRunOk();
- // Wait for the upcoming *stopped and handle it there.
- }
- break;
- case ResultError:
- if (response.data["msg"].data() == "ptrace: Operation not permitted.") {
- showMessage(msgPtraceError(runParameters().startMode));
- notifyEngineRunFailed();
- break;
- }
- showMessage(response.data["msg"].data());
- notifyEngineIll();
- break;
- default:
- showMessage(QString("Invalid response %1").arg(response.resultClass));
- notifyEngineIll();
- break;
- }
-}
-
-void GdbTermEngine::interruptInferior2()
-{
- interruptLocalInferior(inferiorPid());
-}
-
-void GdbTermEngine::stubError(const QString &msg)
-{
- Core::AsynchronousMessageBox::critical(tr("Debugger Error"), msg);
- notifyEngineIll();
-}
-
-void GdbTermEngine::stubExited()
-{
- if (state() == EngineShutdownRequested || state() == DebuggerFinished) {
- showMessage("STUB EXITED EXPECTEDLY");
- return;
- }
- showMessage("STUB EXITED");
- notifyEngineIll();
-}
-
-void GdbTermEngine::shutdownEngine()
-{
- notifyAdapterShutdownOk();
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/images/debugger_continue.png b/src/plugins/debugger/images/debugger_continue.png
index 6ec4eddc1a..e15d7e7262 100644
--- a/src/plugins/debugger/images/debugger_continue.png
+++ b/src/plugins/debugger/images/debugger_continue.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_continue@2x.png b/src/plugins/debugger/images/debugger_continue@2x.png
index 69552eb980..d28c87d835 100644
--- a/src/plugins/debugger/images/debugger_continue@2x.png
+++ b/src/plugins/debugger/images/debugger_continue@2x.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_continue_1_mask.png b/src/plugins/debugger/images/debugger_continue_1_mask.png
index 522e5f36cc..1f5c0c5655 100644
--- a/src/plugins/debugger/images/debugger_continue_1_mask.png
+++ b/src/plugins/debugger/images/debugger_continue_1_mask.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_continue_1_mask@2x.png b/src/plugins/debugger/images/debugger_continue_1_mask@2x.png
index 217ddc826f..e3e06daa9d 100644
--- a/src/plugins/debugger/images/debugger_continue_1_mask@2x.png
+++ b/src/plugins/debugger/images/debugger_continue_1_mask@2x.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_continue_2_mask.png b/src/plugins/debugger/images/debugger_continue_2_mask.png
index 756ba959f0..8b83259ed1 100644
--- a/src/plugins/debugger/images/debugger_continue_2_mask.png
+++ b/src/plugins/debugger/images/debugger_continue_2_mask.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_continue_2_mask@2x.png b/src/plugins/debugger/images/debugger_continue_2_mask@2x.png
index a4801fa6ba..860f76ca18 100644
--- a/src/plugins/debugger/images/debugger_continue_2_mask@2x.png
+++ b/src/plugins/debugger/images/debugger_continue_2_mask@2x.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_interrupt.png b/src/plugins/debugger/images/debugger_interrupt.png
index f61bf0881b..fccdf1149e 100644
--- a/src/plugins/debugger/images/debugger_interrupt.png
+++ b/src/plugins/debugger/images/debugger_interrupt.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_interrupt@2x.png b/src/plugins/debugger/images/debugger_interrupt@2x.png
index 6c99c073db..8e493ca1f2 100644
--- a/src/plugins/debugger/images/debugger_interrupt@2x.png
+++ b/src/plugins/debugger/images/debugger_interrupt@2x.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_interrupt_mask.png b/src/plugins/debugger/images/debugger_interrupt_mask.png
index 87f195f5c0..52f4f275b9 100644
--- a/src/plugins/debugger/images/debugger_interrupt_mask.png
+++ b/src/plugins/debugger/images/debugger_interrupt_mask.png
Binary files differ
diff --git a/src/plugins/debugger/images/debugger_interrupt_mask@2x.png b/src/plugins/debugger/images/debugger_interrupt_mask@2x.png
index 6c477085d7..c779400017 100644
--- a/src/plugins/debugger/images/debugger_interrupt_mask@2x.png
+++ b/src/plugins/debugger/images/debugger_interrupt_mask@2x.png
Binary files differ
diff --git a/src/plugins/debugger/images/mode_debug.png b/src/plugins/debugger/images/mode_debug.png
index 55bdf6bc50..32a93258f1 100644
--- a/src/plugins/debugger/images/mode_debug.png
+++ b/src/plugins/debugger/images/mode_debug.png
Binary files differ
diff --git a/src/plugins/debugger/images/mode_debug@2x.png b/src/plugins/debugger/images/mode_debug@2x.png
index 0dc56c6d93..2bb24b99ee 100644
--- a/src/plugins/debugger/images/mode_debug@2x.png
+++ b/src/plugins/debugger/images/mode_debug@2x.png
Binary files differ
diff --git a/src/plugins/debugger/images/mode_debug_mask.png b/src/plugins/debugger/images/mode_debug_mask.png
index ed72f606c4..fe7b6819a5 100644
--- a/src/plugins/debugger/images/mode_debug_mask.png
+++ b/src/plugins/debugger/images/mode_debug_mask.png
Binary files differ
diff --git a/src/plugins/debugger/images/mode_debug_mask@2x.png b/src/plugins/debugger/images/mode_debug_mask@2x.png
index 510c817c82..5340947ec7 100644
--- a/src/plugins/debugger/images/mode_debug_mask@2x.png
+++ b/src/plugins/debugger/images/mode_debug_mask@2x.png
Binary files differ
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 256f3ce4ee..e9f4e78bfb 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -31,8 +31,8 @@
#include <debugger/debuggerinternalconstants.h>
#include <debugger/debuggermainwindow.h>
#include <debugger/debuggerprotocol.h>
-#include <debugger/debuggerstartparameters.h>
#include <debugger/debuggertooltipmanager.h>
+#include <debugger/terminal.h>
#include <debugger/breakhandler.h>
#include <debugger/disassemblerlines.h>
@@ -99,7 +99,6 @@ LldbEngine::LldbEngine()
LldbEngine::~LldbEngine()
{
- m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
m_lldbProc.disconnect();
}
@@ -156,78 +155,16 @@ void LldbEngine::shutdownEngine()
{
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
m_lldbProc.kill();
- if (runParameters().useTerminal)
- m_stubProc.stop();
notifyEngineShutdownOk();
}
-void LldbEngine::abortDebugger()
+void LldbEngine::abortDebuggerProcess()
{
- if (isDying()) {
- // We already tried. Try harder.
- showMessage("ABORTING DEBUGGER. SECOND TIME.");
- m_lldbProc.kill();
- } else {
- // Be friendly the first time. This will change targetState().
- showMessage("ABORTING DEBUGGER. FIRST TIME.");
- quitDebugger();
- }
+ m_lldbProc.kill();
}
void LldbEngine::setupEngine()
{
- // FIXME: We can't handle terminals yet.
- if (runParameters().useTerminal) {
- qWarning("Run in Terminal is not supported yet with the LLDB backend");
- showMessage(tr("Run in Terminal is not supported with the LLDB backend."), AppError);
- runParameters().useTerminal = false;
- }
-
- if (runParameters().useTerminal) {
- QTC_CHECK(false); // See above.
- if (HostOsInfo::isWindowsHost()) {
- // Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
- m_stubProc.setMode(ConsoleProcess::Suspend);
- else
- m_stubProc.setMode(ConsoleProcess::Debug);
- } else {
- m_stubProc.setMode(ConsoleProcess::Debug);
- m_stubProc.setSettings(ICore::settings());
- }
-
- QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
- showMessage("TRYING TO START ADAPTER");
-
- // Currently, adapters are not re-used
- // // We leave the console open, so recycle it now.
- // m_stubProc.blockSignals(true);
- // m_stubProc.stop();
- // m_stubProc.blockSignals(false);
-
- if (!prepareCommand())
- return;
-
- m_stubProc.setWorkingDirectory(runParameters().inferior.workingDirectory);
- // Set environment + dumper preload.
- m_stubProc.setEnvironment(runParameters().stubEnvironment);
-
- connect(&m_stubProc, &ConsoleProcess::processError, this, &LldbEngine::stubError);
- connect(&m_stubProc, &ConsoleProcess::processStarted, this, &LldbEngine::stubStarted);
- connect(&m_stubProc, &ConsoleProcess::stubStopped, this, &LldbEngine::stubExited);
- // FIXME: Starting the stub implies starting the inferior. This is
- // fairly unclean as far as the state machine and error reporting go.
-
- if (!m_stubProc.start(runParameters().inferior.executable,
- runParameters().inferior.commandLineArguments)) {
- // Error message for user is delivered via a signal.
- //handleAdapterStartFailed(QString());
- notifyEngineSetupFailed();
- return;
- }
-
- }
-
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
startLldb();
}
@@ -318,17 +255,17 @@ void LldbEngine::setupInferior()
DebuggerCommand cmd2("setupInferior");
cmd2.arg("executable", executable);
cmd2.arg("breakonmain", rp.breakOnMain);
- cmd2.arg("useterminal", rp.useTerminal);
+ cmd2.arg("useterminal", bool(terminal()));
cmd2.arg("startmode", rp.startMode);
cmd2.arg("nativemixed", isNativeMixedActive());
cmd2.arg("workingdirectory", rp.inferior.workingDirectory);
cmd2.arg("environment", rp.inferior.environment.toStringList());
cmd2.arg("processargs", args.toUnixArgs());
- if (rp.useTerminal) {
+ if (terminal()) {
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
- const qint64 attachedPID = m_stubProc.applicationPID();
- const qint64 attachedMainThreadID = m_stubProc.applicationMainThreadID();
+ const qint64 attachedPID = terminal()->applicationPid();
+ const qint64 attachedMainThreadID = terminal()->applicationMainThreadId();
const QString msg = (attachedMainThreadID != -1)
? QString::fromLatin1("Attaching to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
: QString::fromLatin1("Attaching to %1").arg(attachedPID);
@@ -584,7 +521,7 @@ void LldbEngine::removeBreakpoint(Breakpoint bp)
if (response.id.isValid()) {
DebuggerCommand cmd("removeBreakpoint");
cmd.arg("lldbid", response.id.toString());
- cmd.callback = [this, bp](const DebuggerResponse &) {
+ cmd.callback = [bp](const DebuggerResponse &) {
QTC_CHECK(bp.state() == BreakpointRemoveProceeding);
Breakpoint bp0 = bp;
bp0.notifyBreakpointRemoveOk();
@@ -689,7 +626,7 @@ void LldbEngine::requestModuleSymbols(const QString &moduleName)
{
DebuggerCommand cmd("fetchSymbols");
cmd.arg("module", moduleName);
- cmd.callback = [this, moduleName](const DebuggerResponse &response) {
+ cmd.callback = [moduleName](const DebuggerResponse &response) {
const GdbMi &symbols = response.data["symbols"];
QString moduleName = response.data["module"].data();
Symbols syms;
@@ -1053,7 +990,7 @@ void LldbEngine::fetchMemory(MemoryAgent *agent, quint64 addr, quint64 length)
DebuggerCommand cmd("fetchMemory");
cmd.arg("address", addr);
cmd.arg("length", length);
- cmd.callback = [this, agent](const DebuggerResponse &response) {
+ cmd.callback = [agent](const DebuggerResponse &response) {
qulonglong addr = response.data["address"].toAddress();
QByteArray ba = QByteArray::fromHex(response.data["contents"].data().toUtf8());
agent->addData(addr, ba);
@@ -1067,7 +1004,7 @@ void LldbEngine::changeMemory(MemoryAgent *agent, quint64 addr, const QByteArray
DebuggerCommand cmd("writeMemory");
cmd.arg("address", addr);
cmd.arg("data", QString::fromUtf8(data.toHex()));
- cmd.callback = [this](const DebuggerResponse &response) { Q_UNUSED(response); };
+ cmd.callback = [](const DebuggerResponse &response) { Q_UNUSED(response); };
runCommand(cmd);
}
@@ -1119,25 +1056,5 @@ DebuggerEngine *createLldbEngine()
return new LldbEngine;
}
-void LldbEngine::stubStarted()
-{
- startLldb();
-}
-
-void LldbEngine::stubError(const QString &msg)
-{
- AsynchronousMessageBox::critical(tr("Debugger Error"), msg);
-}
-
-void LldbEngine::stubExited()
-{
- if (state() == EngineShutdownRequested || state() == DebuggerFinished) {
- showMessage("STUB EXITED EXPECTEDLY");
- return;
- }
- showMessage("STUB EXITED");
- notifyEngineIll();
-}
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h
index 19932d56c7..9bc4a0b7c9 100644
--- a/src/plugins/debugger/lldb/lldbengine.h
+++ b/src/plugins/debugger/lldb/lldbengine.h
@@ -78,7 +78,7 @@ private:
void runEngine() override;
void shutdownInferior() override;
void shutdownEngine() override;
- void abortDebugger() override;
+ void abortDebuggerProcess() override;
bool canHandleToolTip(const DebuggerToolTipContext &) const override;
@@ -154,12 +154,6 @@ private:
QHash<int, DebuggerCommand> m_commandForToken;
DebuggerCommandSequence m_onStop;
-
- // Console handling.
- void stubError(const QString &msg);
- void stubExited();
- void stubStarted();
- Utils::ConsoleProcess m_stubProc;
};
} // namespace Internal
diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp
index d0e8d87636..8b0b1bf271 100644
--- a/src/plugins/debugger/loadcoredialog.cpp
+++ b/src/plugins/debugger/loadcoredialog.cpp
@@ -25,14 +25,14 @@
#include "loadcoredialog.h"
-#include "debuggerstartparameters.h"
#include "debuggerdialogs.h"
#include "debuggerkitinformation.h"
-#include "gdb/coregdbadapter.h"
+#include "gdb/gdbengine.h"
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <ssh/sftpfilesystemmodel.h>
+#include <ssh/sshconnection.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/temporaryfile.h>
@@ -364,7 +364,7 @@ void AttachCoreDialog::coreFileChanged(const QString &core)
Kit *k = d->kitChooser->currentKit();
QTC_ASSERT(k, return);
StandardRunnable debugger = DebuggerKitInformation::runnable(k);
- GdbCoreEngine::CoreInfo cinfo = GdbCoreEngine::readExecutableNameFromCore(debugger, core);
+ CoreInfo cinfo = CoreInfo::readExecutableNameFromCore(debugger, core);
if (!cinfo.foundExecutableName.isEmpty())
d->localExecFileName->setFileName(FileName::fromString(cinfo.foundExecutableName));
else if (!d->localExecFileName->isValid() && !cinfo.rawStringFromCore.isEmpty())
diff --git a/src/plugins/debugger/logwindow.cpp b/src/plugins/debugger/logwindow.cpp
index 22c2e73ed9..98dc0f9143 100644
--- a/src/plugins/debugger/logwindow.cpp
+++ b/src/plugins/debugger/logwindow.cpp
@@ -43,6 +43,9 @@
#include <QToolButton>
#include <aggregation/aggregate.h>
+
+#include <app/app_version.h>
+
#include <coreplugin/findplaceholder.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/find/basetextfind.h>
@@ -432,12 +435,13 @@ LogWindow::LogWindow(QWidget *parent)
showOutput(LogWarning,
tr("Note: This log contains possibly confidential information about your machine, "
"environment variables, in-memory data of the processes you are debugging, and more. "
- "It is never transferred over the internet by Qt Creator, and only stored "
+ "It is never transferred over the internet by %1, and only stored "
"to disk if you manually use the respective option from the context menu, or through "
- "mechanisms that are not under Qt Creator's control, for instance in swap files.\n"
+ "mechanisms that are not under the control of %1, for instance in swap files.\n"
"You may be asked to share the contents of this log when reporting bugs related "
"to debugger operation. In this case, make sure your submission does not "
- "contain data you do not want to or you are not allowed to share.\n\n"));
+ "contain data you do not want to or you are not allowed to share.\n\n")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
}
void LogWindow::executeLine()
diff --git a/src/plugins/debugger/memoryagent.cpp b/src/plugins/debugger/memoryagent.cpp
index 0142d53d4d..8e79ff994e 100644
--- a/src/plugins/debugger/memoryagent.cpp
+++ b/src/plugins/debugger/memoryagent.cpp
@@ -27,7 +27,6 @@
#include "breakhandler.h"
#include "debuggerengine.h"
-#include "debuggerstartparameters.h"
#include "debuggercore.h"
#include "debuggerinternalconstants.h"
#include "registerhandler.h"
diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp
index e37c44ccbb..5139989b0e 100644
--- a/src/plugins/debugger/moduleshandler.cpp
+++ b/src/plugins/debugger/moduleshandler.cpp
@@ -196,7 +196,7 @@ bool ModulesModel::contextMenuEvent(const ItemViewEvent &ev)
addAction(menu, tr("Show Dependencies of \"%1\"").arg(moduleName),
tr("Show Dependencies"),
moduleNameValid && !moduleName.isEmpty() && HostOsInfo::isWindowsHost(),
- [this, modulePath] { QProcess::startDetached("depends", {modulePath}); });
+ [modulePath] { QProcess::startDetached("depends", {modulePath}); });
addAction(menu, tr("Load Symbols for All Modules"),
enabled && canLoadSymbols,
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index 6334f18a3a..5e74ac920e 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -30,7 +30,6 @@
#include <debugger/debuggerdialogs.h>
#include <debugger/debuggerplugin.h>
#include <debugger/debuggerprotocol.h>
-#include <debugger/debuggerstartparameters.h>
#include <debugger/debuggertooltipmanager.h>
#include <debugger/threaddata.h>
diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp
index d8d0a66404..77e5204dc9 100644
--- a/src/plugins/debugger/qml/qmlcppengine.cpp
+++ b/src/plugins/debugger/qml/qmlcppengine.cpp
@@ -29,7 +29,6 @@
#include <debugger/debuggercore.h>
#include <debugger/debuggerruncontrol.h>
#include <debugger/debuggertooltipmanager.h>
-#include <debugger/debuggerstartparameters.h>
#include <debugger/breakhandler.h>
#include <debugger/stackhandler.h>
#include <debugger/threaddata.h>
@@ -49,9 +48,9 @@ enum { debug = 0 };
#define CHECK_STATE(s) do { checkState(s, __FILE__, __LINE__); } while (0)
-DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal)
+DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine)
{
- return new QmlCppEngine(cppEngine, useTerminal);
+ return new QmlCppEngine(cppEngine);
}
@@ -61,10 +60,10 @@ DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal)
//
////////////////////////////////////////////////////////////////////////
-QmlCppEngine::QmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal)
+QmlCppEngine::QmlCppEngine(DebuggerEngine *cppEngine)
{
setObjectName("QmlCppEngine");
- m_qmlEngine = new QmlEngine(useTerminal);
+ m_qmlEngine = new QmlEngine;
m_qmlEngine->setMasterEngine(this);
m_cppEngine = cppEngine;
m_cppEngine->setMasterEngine(this);
@@ -378,36 +377,6 @@ void QmlCppEngine::setupEngine()
m_cppEngine->setupSlaveEngine();
}
-void QmlCppEngine::notifyEngineRunAndInferiorRunOk()
-{
- EDEBUG("\nMASTER NOTIFY ENGINE RUN AND INFERIOR RUN OK");
- DebuggerEngine::notifyEngineRunAndInferiorRunOk();
-}
-
-void QmlCppEngine::notifyInferiorRunOk()
-{
- EDEBUG("\nMASTER NOTIFY INFERIOR RUN OK");
- DebuggerEngine::notifyInferiorRunOk();
-}
-
-void QmlCppEngine::notifyInferiorSpontaneousStop()
-{
- EDEBUG("\nMASTER SPONTANEOUS STOP OK");
- DebuggerEngine::notifyInferiorSpontaneousStop();
-}
-
-void QmlCppEngine::notifyInferiorShutdownOk()
-{
- EDEBUG("\nMASTER INFERIOR SHUTDOWN OK");
- DebuggerEngine::notifyInferiorShutdownOk();
-}
-
-void QmlCppEngine::notifyInferiorSetupOk()
-{
- EDEBUG("\nMASTER INFERIOR SETUP OK");
- DebuggerEngine::notifyInferiorSetupOk();
-}
-
void QmlCppEngine::setupInferior()
{
EDEBUG("\nMASTER SETUP INFERIOR");
@@ -441,10 +410,10 @@ void QmlCppEngine::quitDebugger()
m_cppEngine->quitDebugger();
}
-void QmlCppEngine::abortDebugger()
+void QmlCppEngine::abortDebuggerProcess()
{
EDEBUG("\nMASTER ABORT DEBUGGER");
- m_cppEngine->abortDebugger();
+ m_cppEngine->abortDebuggerProcess();
}
void QmlCppEngine::setState(DebuggerState newState, bool forced)
diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h
index 52442d0e89..1a6bffb7c5 100644
--- a/src/plugins/debugger/qml/qmlcppengine.h
+++ b/src/plugins/debugger/qml/qmlcppengine.h
@@ -37,7 +37,7 @@ class QmlCppEngine : public DebuggerEngine
Q_OBJECT
public:
- QmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal);
+ explicit QmlCppEngine(DebuggerEngine *cppEngine);
~QmlCppEngine() override;
bool canDisplayTooltip() const override;
@@ -112,14 +112,8 @@ protected:
void shutdownInferior() override;
void shutdownEngine() override;
void quitDebugger() override;
- void abortDebugger() override;
+ void abortDebuggerProcess() override;
- void notifyInferiorRunOk() override;
- void notifyInferiorSpontaneousStop() override;
- void notifyEngineRunAndInferiorRunOk() override;
- void notifyInferiorShutdownOk() override;
-
- void notifyInferiorSetupOk() override;
void loadAdditionalQmlStack() override;
private:
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 4dc8280851..b3a719a15e 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -57,6 +57,7 @@
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
+#include <app/app_version.h>
#include <utils/treemodel.h>
#include <utils/basetreeview.h>
#include <utils/qtcassert.h>
@@ -66,6 +67,7 @@
#include <QDir>
#include <QDockWidget>
#include <QFileInfo>
+#include <QHostAddress>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
@@ -139,15 +141,14 @@ typedef QHash<int, LookupData> LookupItems; // id -> (iname, exp)
class QmlEnginePrivate : public QmlDebugClient
{
public:
- QmlEnginePrivate(QmlEngine *engine_, QmlDebugConnection *connection_)
- : QmlDebugClient("V8Debugger", connection_),
+ QmlEnginePrivate(QmlEngine *engine_, QmlDebugConnection *connection)
+ : QmlDebugClient("V8Debugger", connection),
engine(engine_),
- inspectorAgent(engine, connection_),
- connection(connection_)
+ inspectorAgent(engine, connection)
{}
- void messageReceived(const QByteArray &data);
- void stateChanged(State state);
+ void messageReceived(const QByteArray &data) override;
+ void stateChanged(State state) override;
void continueDebugging(StepAction stepAction);
@@ -189,17 +190,6 @@ public:
void checkForFinishedUpdate();
ConsoleItem *constructLogItemTree(const QmlV8ObjectData &objectData);
- void filterApplicationMessage(ProjectExplorer::RunControl *runControl,
- const QString &msg, Utils::OutputFormat format)
- {
- if (runControl != engine->runControl())
- return;
- if (format == StdErrFormatSameLine
- || format == StdOutFormatSameLine
- || format == DebugFormat)
- outputParser.processOutput(msg);
- }
-
public:
QHash<int, QmlV8ObjectData> refVals; // The mapping of target object handles to retrieved values.
int sequence = -1;
@@ -223,9 +213,7 @@ public:
InteractiveInterpreter interpreter;
ApplicationLauncher applicationLauncher;
QmlInspectorAgent inspectorAgent;
- QmlOutputParser outputParser;
- QTimer noDebugOutputTimer;
QList<quint32> queryIds;
bool retryOnConnectFail = false;
bool automaticConnect = false;
@@ -233,7 +221,6 @@ public:
bool contextEvaluate = false;
QTimer connectionTimer;
- QmlDebug::QmlDebugConnection *connection;
QmlDebug::QDebugMessageClient *msgClient = 0;
QHash<int, QmlCallback> callbackForToken;
@@ -258,10 +245,11 @@ static void updateDocument(IDocument *document, const QTextDocument *textDocumen
//
///////////////////////////////////////////////////////////////////////
-QmlEngine::QmlEngine(bool useTerminal)
+QmlEngine::QmlEngine()
: d(new QmlEnginePrivate(this, new QmlDebugConnection(this)))
{
setObjectName("QmlEngine");
+ QmlDebugConnection *connection = d->connection();
connect(stackHandler(), &StackHandler::stackChanged,
this, &QmlEngine::updateCurrentContext);
@@ -277,28 +265,6 @@ QmlEngine::QmlEngine(bool useTerminal)
connect(&d->applicationLauncher, &ApplicationLauncher::processStarted,
this, &QmlEngine::handleLauncherStarted);
- d->outputParser.setNoOutputText(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput());
- connect(&d->outputParser, &QmlOutputParser::waitingForConnectionOnPort,
- this, &QmlEngine::beginConnection);
- connect(&d->outputParser, &QmlOutputParser::noOutputMessage,
- this, [this] { tryToConnect(); });
- connect(&d->outputParser, &QmlOutputParser::errorMessage,
- this, &QmlEngine::appStartupFailed);
-
- // Only wait 8 seconds for the 'Waiting for connection' on application output,
- // then just try to connect (application output might be redirected / blocked)
- d->noDebugOutputTimer.setSingleShot(true);
- d->noDebugOutputTimer.setInterval(8000);
- connect(&d->noDebugOutputTimer, &QTimer::timeout,
- this, [this] { tryToConnect(); });
-
- // we won't get any debug output
- if (useTerminal) {
- d->noDebugOutputTimer.setInterval(0);
- d->retryOnConnectFail = true;
- d->automaticConnect = true;
- }
-
debuggerConsole()->setScriptEvaluator([this](const QString &expr) {
executeDebuggerCommand(expr, QmlLanguage);
});
@@ -308,21 +274,21 @@ QmlEngine::QmlEngine(bool useTerminal)
connect(&d->connectionTimer, &QTimer::timeout,
this, &QmlEngine::checkConnectionState);
- connect(d->connection, &QmlDebugConnection::logStateChange,
+ connect(connection, &QmlDebugConnection::logStateChange,
this, &QmlEngine::showConnectionStateMessage);
- connect(d->connection, &QmlDebugConnection::logError, this,
+ connect(connection, &QmlDebugConnection::logError, this,
[this](const QString &error) { showMessage("QML Debugger: " + error, LogWarning); });
- connect(d->connection, &QmlDebugConnection::connectionFailed,
+ connect(connection, &QmlDebugConnection::connectionFailed,
this, &QmlEngine::connectionFailed);
- connect(d->connection, &QmlDebugConnection::connected,
+ connect(connection, &QmlDebugConnection::connected,
&d->connectionTimer, &QTimer::stop);
- connect(d->connection, &QmlDebugConnection::connected,
+ connect(connection, &QmlDebugConnection::connected,
this, &QmlEngine::connectionEstablished);
- connect(d->connection, &QmlDebugConnection::disconnected,
+ connect(connection, &QmlDebugConnection::disconnected,
this, &QmlEngine::disconnected);
- d->msgClient = new QDebugMessageClient(d->connection);
+ d->msgClient = new QDebugMessageClient(connection);
connect(d->msgClient, &QDebugMessageClient::newState,
this, [this](QmlDebugClient::State state) {
logServiceStateChange(d->msgClient->name(), d->msgClient->serviceVersion(), state);
@@ -354,15 +320,6 @@ void QmlEngine::setState(DebuggerState state, bool forced)
updateCurrentContext();
}
-void QmlEngine::setRunTool(DebuggerRunTool *runTool)
-{
- DebuggerEngine::setRunTool(runTool);
-
- d->startupMessageFilterConnection = connect(
- runTool->runControl(), &RunControl::appendMessageRequested,
- d, &QmlEnginePrivate::filterApplicationMessage);
-}
-
void QmlEngine::setupInferior()
{
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
@@ -378,7 +335,7 @@ void QmlEngine::handleLauncherStarted()
// FIXME: The QmlEngine never calls notifyInferiorPid() triggering the
// raising, so do it here manually for now.
runControl()->applicationProcessHandle().activate();
- d->noDebugOutputTimer.start();
+ tryToConnect();
}
void QmlEngine::appMessage(const QString &msg, Utils::OutputFormat /* format */)
@@ -394,29 +351,27 @@ void QmlEngine::connectionEstablished()
notifyEngineRunAndInferiorRunOk();
}
-void QmlEngine::tryToConnect(Utils::Port port)
+void QmlEngine::tryToConnect()
{
- showMessage("QML Debugger: No application output received in time, trying to connect ...", LogStatus);
+ showMessage("QML Debugger: Trying to connect ...", LogStatus);
d->retryOnConnectFail = true;
if (state() == EngineRunRequested) {
if (isSlaveEngine()) {
// Probably cpp is being debugged and hence we did not get the output yet.
if (!masterEngine()->isDying())
- beginConnection(port);
+ beginConnection();
else
appStartupFailed(tr("No application output received in time"));
} else {
- beginConnection(port);
+ beginConnection();
}
} else {
d->automaticConnect = true;
}
}
-void QmlEngine::beginConnection(Utils::Port port)
+void QmlEngine::beginConnection()
{
- d->noDebugOutputTimer.stop();
-
if (state() != EngineRunRequested && d->retryOnConnectFail)
return;
@@ -424,11 +379,12 @@ void QmlEngine::beginConnection(Utils::Port port)
QObject::disconnect(d->startupMessageFilterConnection);
- QString host = runParameters().qmlServer.host;
+ QString host = runParameters().qmlServer.host();
// Use localhost as default
if (host.isEmpty())
host = QHostAddress(QHostAddress::LocalHost).toString();
+ // FIXME: Not needed?
/*
* Let plugin-specific code override the port printed by the application. This is necessary
* in the case of port forwarding, when the port the application listens on is not the same that
@@ -440,13 +396,13 @@ void QmlEngine::beginConnection(Utils::Port port)
* the connection will be closed again (instead of returning the "connection refused"
* error that we expect).
*/
- if (runParameters().qmlServer.port.isValid())
- port = runParameters().qmlServer.port;
+ int port = runParameters().qmlServer.port();
- if (!d->connection || d->connection->isConnected())
+ QmlDebugConnection *connection = d->connection();
+ if (!connection || connection->isConnected())
return;
- d->connection->connectToHost(host, port.number());
+ connection->connectToHost(host, port);
//A timeout to check the connection state
d->connectionTimer.start();
@@ -462,7 +418,7 @@ void QmlEngine::connectionStartupFailed()
QMessageBox *infoBox = new QMessageBox(ICore::mainWindow());
infoBox->setIcon(QMessageBox::Critical);
- infoBox->setWindowTitle(tr("Qt Creator"));
+ infoBox->setWindowTitle(Core::Constants::IDE_DISPLAY_NAME);
infoBox->setText(tr("Could not connect to the in-process QML debugger."
"\nDo you want to retry?"));
infoBox->setStandardButtons(QMessageBox::Retry | QMessageBox::Cancel |
@@ -483,7 +439,7 @@ void QmlEngine::appStartupFailed(const QString &errorMessage)
if (isMasterEngine()) {
QMessageBox *infoBox = new QMessageBox(ICore::mainWindow());
infoBox->setIcon(QMessageBox::Critical);
- infoBox->setWindowTitle(tr("Qt Creator"));
+ infoBox->setWindowTitle(Core::Constants::IDE_DISPLAY_NAME);
infoBox->setText(error);
infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help);
infoBox->setDefaultButton(QMessageBox::Ok);
@@ -552,24 +508,30 @@ void QmlEngine::closeConnection()
if (d->connectionTimer.isActive()) {
d->connectionTimer.stop();
} else {
- if (d->connection)
- d->connection->close();
+ if (QmlDebugConnection *connection = d->connection())
+ connection->close();
}
}
void QmlEngine::runEngine()
{
+ // we won't get any debug output
+ if (!terminal()) {
+ d->retryOnConnectFail = true;
+ d->automaticConnect = true;
+ }
+
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
if (!isSlaveEngine()) {
if (runParameters().startMode == AttachToRemoteServer)
- d->noDebugOutputTimer.start();
+ tryToConnect();
else if (runParameters().startMode == AttachToRemoteProcess)
beginConnection();
else
startApplicationLauncher();
} else {
- d->noDebugOutputTimer.start();
+ tryToConnect();
}
}
@@ -594,39 +556,6 @@ void QmlEngine::stopApplicationLauncher()
}
}
-// FIXME: Is the timeout raise still needed? Since the RunWorker conversion,
-// the debugger tool only starts when the remote setup has all interesting
-// ports gathered, so much less chance for waiting on longer operations.
-//void QmlEngine::notifyEngineRemoteSetupFinished()
-//{
-// QObject::disconnect(d->startupMessageFilterConnection);
-// switch (state()) {
-// case InferiorSetupOk:
-// // FIXME: This is not a legal transition, but we need to
-// // get to EngineSetupOk somehow from InferiorSetupOk.
-// // fallthrough. QTCREATORBUG-14089.
-// case EngineSetupRequested:
-// notifyEngineSetupOk();
-// break;
-// case EngineSetupOk:
-// case EngineRunRequested:
-// // QTCREATORBUG-17718: On Android while doing debugging in mixed mode, the QML debug engine
-// // sometimes reports EngineSetupOK after the EngineRunRequested thus overwriting the state
-// // which eventually results into app to waiting for the QML engine connection.
-// // Skipping the EngineSetupOK in aforementioned case.
-// // Nothing to do here. The setup is already done.
-// break;
-// default:
-// QTC_ASSERT(false, qDebug() << "Unexpected state" << state());
-// }
-
-// // The remote setup can take while especialy with mixed debugging.
-// // Just waiting for 8 seconds is not enough. Increase the timeout
-// // to 60 s
-// // In case we get an output the d->outputParser will start the connection.
-// d->noDebugOutputTimer.setInterval(60000);
-//}
-
void QmlEngine::shutdownInferior()
{
// End session.
@@ -649,7 +578,6 @@ void QmlEngine::shutdownEngine()
clearExceptionSelection();
debuggerConsole()->setScriptEvaluator(ScriptEvaluator());
- d->noDebugOutputTimer.stop();
// double check (ill engine?):
stopApplicationLauncher();
@@ -1095,7 +1023,6 @@ bool QmlEngine::hasCapability(unsigned cap) const
void QmlEngine::quitDebugger()
{
- d->noDebugOutputTimer.stop();
d->automaticConnect = false;
d->retryOnConnectFail = false;
shutdownInferior();
@@ -1268,7 +1195,10 @@ void QmlEngine::checkConnectionState()
bool QmlEngine::isConnected() const
{
- return d->connection->isConnected();
+ if (QmlDebugConnection *connection = d->connection())
+ return connection->isConnected();
+ else
+ return false;
}
void QmlEngine::showConnectionStateMessage(const QString &message)
@@ -1526,7 +1456,7 @@ void QmlEnginePrivate::setBreakpoint(const QString type, const QString target,
// }
// }
if (type == EVENT) {
- QPacket rs(connection->currentDataStreamVersion());
+ QPacket rs(dataStreamVersion());
rs << target.toUtf8() << enabled;
engine->showMessage(QString("%1 %2 %3")
.arg(BREAKONSIGNAL, target, QLatin1String(enabled ? "enabled" : "disabled")), LogInput);
@@ -1746,7 +1676,7 @@ void QmlEnginePrivate::runDirectCommand(const QString &type, const QByteArray &m
engine->showMessage(QString("%1 %2").arg(type, QString::fromLatin1(msg)), LogInput);
- QPacket rs(connection->currentDataStreamVersion());
+ QPacket rs(dataStreamVersion());
rs << cmd << type.toLatin1() << msg;
if (state() == Enabled)
@@ -1768,7 +1698,7 @@ void QmlEnginePrivate::memorizeRefs(const QVariant &refs)
void QmlEnginePrivate::messageReceived(const QByteArray &data)
{
- QPacket ds(connection->currentDataStreamVersion(), data);
+ QPacket ds(dataStreamVersion(), data);
QByteArray command;
ds >> command;
@@ -2550,9 +2480,9 @@ void QmlEnginePrivate::flushSendBuffer()
sendBuffer.clear();
}
-DebuggerEngine *createQmlEngine(bool useTerminal)
+DebuggerEngine *createQmlEngine()
{
- return new QmlEngine(useTerminal);
+ return new QmlEngine;
}
} // Internal
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index 1319f98e56..36d89800a7 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -43,11 +43,9 @@ class QmlEngine : public DebuggerEngine
Q_OBJECT
public:
- explicit QmlEngine(bool useTerminal);
+ QmlEngine();
~QmlEngine() override;
- void setRunTool(DebuggerRunTool *runTool) override;
-
void logServiceStateChange(const QString &service, float version,
QmlDebug::QmlDebugClient::State newState);
void logServiceActivity(const QString &service, const QString &logMessage);
@@ -59,8 +57,8 @@ private:
void errorMessageBoxFinished(int result);
void updateCurrentContext();
- void tryToConnect(Utils::Port port = Utils::Port());
- void beginConnection(Utils::Port port = Utils::Port());
+ void tryToConnect();
+ void beginConnection();
void handleLauncherStarted();
void connectionEstablished();
void connectionStartupFailed();
diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp
index 0cf5de70c7..5ae39c1af5 100644
--- a/src/plugins/debugger/registerhandler.cpp
+++ b/src/plugins/debugger/registerhandler.cpp
@@ -742,8 +742,10 @@ bool RegisterHandler::contextMenuEvent(const ItemViewEvent &ev)
? registerSubItem->parent()->m_format
: HexadecimalFormat;
- auto addFormatAction = [this, menu, currentFormat, registerItem](const QString &display, RegisterFormat format) {
- addCheckableAction(menu, display, registerItem, currentFormat == format, [this, registerItem, format] {
+ auto addFormatAction =
+ [menu, currentFormat, registerItem](const QString &display, RegisterFormat format) {
+ addCheckableAction(menu, display, registerItem, currentFormat == format,
+ [registerItem, format] {
registerItem->m_format = format;
registerItem->update();
});
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index 0afb0ba9bc..a4f6c650e2 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -418,7 +418,7 @@ bool StackHandler::contextMenuEvent(const ItemViewEvent &ev)
});
addAction(menu, tr("Disassemble Function..."), true,
- [this, address] {
+ [this] {
const StackFrame frame = inputFunctionForDisassembly();
if (!frame.function.isEmpty())
m_engine->openDisassemblerView(Location(frame));
diff --git a/src/plugins/debugger/terminal.cpp b/src/plugins/debugger/terminal.cpp
index c4f4ba0ba9..09dcdb156c 100644
--- a/src/plugins/debugger/terminal.cpp
+++ b/src/plugins/debugger/terminal.cpp
@@ -25,11 +25,16 @@
#include "terminal.h"
+#include "debuggerruncontrol.h"
+
#include <QDebug>
#include <QIODevice>
#include <QSocketNotifier>
+#include <coreplugin/icore.h>
+
#include <utils/qtcassert.h>
+#include <utils/hostosinfo.h>
#ifdef Q_OS_UNIX
# define DEBUGGER_USE_TERMINAL
@@ -45,6 +50,10 @@
# include <sys/stat.h>
#endif
+using namespace Core;
+using namespace ProjectExplorer;
+using namespace Utils;
+
namespace Debugger {
namespace Internal {
@@ -159,6 +168,67 @@ void Terminal::onSlaveReaderActivated(int fd)
#endif
}
+TerminalRunner::TerminalRunner(DebuggerRunTool *debugger)
+ : RunWorker(debugger->runControl())
+{
+ setDisplayName("TerminalRunner");
+
+ const DebuggerRunParameters &rp = debugger->runParameters();
+ m_stubRunnable = rp.inferior;
+ m_stubRunnable.environment = rp.stubEnvironment;
+ m_stubRunnable.workingDirectory = rp.inferior.workingDirectory;
+
+ connect(&m_stubProc, &ConsoleProcess::processError,
+ this, &TerminalRunner::stubError);
+ connect(&m_stubProc, &ConsoleProcess::processStarted,
+ this, &TerminalRunner::stubStarted);
+ connect(&m_stubProc, &ConsoleProcess::stubStopped,
+ this, &TerminalRunner::stubExited);
+}
+
+void TerminalRunner::start()
+{
+ m_stubProc.setEnvironment(m_stubRunnable.environment);
+ m_stubProc.setWorkingDirectory(m_stubRunnable.workingDirectory);
+
+ if (HostOsInfo::isWindowsHost()) {
+ // Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
+ m_stubProc.setMode(ConsoleProcess::Suspend);
+ else
+ m_stubProc.setMode(ConsoleProcess::Debug);
+ } else {
+ m_stubProc.setMode(ConsoleProcess::Debug);
+ m_stubProc.setSettings(Core::ICore::settings());
+ }
+
+ // Error message for user is delivered via a signal.
+ m_stubProc.start(m_stubRunnable.executable, m_stubRunnable.commandLineArguments);
+}
+
+void TerminalRunner::stop()
+{
+ m_stubProc.stop();
+ reportStopped();
+}
+
+void TerminalRunner::stubStarted()
+{
+ m_applicationPid = m_stubProc.applicationPID();
+ m_applicationMainThreadId = m_stubProc.applicationMainThreadID();
+ reportStarted();
+}
+
+void TerminalRunner::stubError(const QString &msg)
+{
+ reportFailure(msg);
+}
+
+void TerminalRunner::stubExited()
+{
+ reportStopped();
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/terminal.h b/src/plugins/debugger/terminal.h
index 67b3bf851a..0745373e0e 100644
--- a/src/plugins/debugger/terminal.h
+++ b/src/plugins/debugger/terminal.h
@@ -28,7 +28,15 @@
#include <QCoreApplication>
#include <QSocketNotifier>
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runnables.h>
+
+#include <utils/consoleprocess.h>
+
namespace Debugger {
+
+class DebuggerRunTool;
+
namespace Internal {
class Terminal : public QObject
@@ -60,5 +68,28 @@ private:
QByteArray m_slaveName;
};
+
+class TerminalRunner : public ProjectExplorer::RunWorker
+{
+public:
+ explicit TerminalRunner(DebuggerRunTool *runControl);
+
+ qint64 applicationPid() const { return m_applicationPid; }
+ qint64 applicationMainThreadId() const { return m_applicationMainThreadId; }
+
+private:
+ void start() final;
+ void stop() final;
+
+ void stubStarted();
+ void stubExited();
+ void stubError(const QString &msg);
+
+ Utils::ConsoleProcess m_stubProc;
+ ProjectExplorer::StandardRunnable m_stubRunnable;
+ qint64 m_applicationPid = 0;
+ qint64 m_applicationMainThreadId = 0;
+};
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 32aaa3bbc0..96194f869a 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -46,6 +46,7 @@
#include <texteditor/syntaxhighlighter.h>
+#include <app/app_version.h>
#include <utils/algorithm.h>
#include <utils/basetreeview.h>
#include <utils/checkablemessagebox.h>
@@ -271,7 +272,7 @@ public:
setTabsClosable(true);
connect(this, &QTabWidget::tabCloseRequested, this, &SeparatedView::closeTab);
setWindowFlags(windowFlags() | Qt::Window);
- setWindowTitle(WatchHandler::tr("Debugger - Qt Creator"));
+ setWindowTitle(WatchHandler::tr("Debugger - %1").arg(Core::Constants::IDE_DISPLAY_NAME));
QVariant geometry = sessionValue("DebuggerSeparateWidgetGeometry");
if (geometry.isValid()) {
@@ -516,7 +517,7 @@ void WatchModel::reinitialize(bool includeInspectData)
WatchItem *WatchModel::findItem(const QString &iname) const
{
- return findNonRooItem([iname](WatchItem *item) { return item->iname == iname; });
+ return findNonRootItem([iname](WatchItem *item) { return item->iname == iname; });
}
static QString parentName(const QString &iname)
@@ -1678,7 +1679,7 @@ bool WatchModel::contextMenuEvent(const ItemViewEvent &ev)
addAction(menu, tr("Close Editor Tooltips"),
DebuggerToolTipManager::hasToolTips(),
- [this] { DebuggerToolTipManager::closeAllToolTips(); });
+ [] { DebuggerToolTipManager::closeAllToolTips(); });
addAction(menu, tr("Copy View Contents to Clipboard"),
true,
@@ -1686,7 +1687,7 @@ bool WatchModel::contextMenuEvent(const ItemViewEvent &ev)
addAction(menu, tr("Copy Current Value to Clipboard"),
item,
- [this, item] { copyToClipboard(item->value); });
+ [item] { copyToClipboard(item->value); });
// addAction(menu, tr("Copy Selected Rows to Clipboard"),
// selectionModel()->hasSelection(),
@@ -1790,7 +1791,7 @@ QMenu *WatchModel::createMemoryMenu(WatchItem *item)
addAction(menu, tr("Open Memory Editor Showing Stack Layout"),
item && item->isLocal(),
- [this, item, pos] { addStackLayoutMemoryView(false, pos); });
+ [this, pos] { addStackLayoutMemoryView(false, pos); });
addAction(menu, tr("Open Memory Editor..."),
true,
@@ -1834,8 +1835,6 @@ QMenu *WatchModel::createFormatMenu(WatchItem *item)
addBaseChangeAction(tr("Show Unprintable Characters as Octal"), 8);
addBaseChangeAction(tr("Show Unprintable Characters as Hexadecimal"), 16);
- QAction *act = 0;
-
const QString spacer = " ";
menu->addSeparator();
@@ -1857,7 +1856,7 @@ QMenu *WatchModel::createFormatMenu(WatchItem *item)
for (int format : alternativeFormats) {
addCheckableAction(menu, spacer + nameForFormat(format), true, format == individualFormat,
- [this, act, format, iname] {
+ [this, format, iname] {
setIndividualFormat(iname, format);
m_engine->updateLocals();
});
@@ -1877,7 +1876,7 @@ QMenu *WatchModel::createFormatMenu(WatchItem *item)
for (int format : alternativeFormats) {
addCheckableAction(menu, spacer + nameForFormat(format), true, format == typeFormat,
- [this, act, format, item] {
+ [this, format, item] {
setTypeFormat(item->type, format);
m_engine->updateLocals();
});
@@ -2093,7 +2092,7 @@ void WatchHandler::notifyUpdateStarted(const UpdateParameters &updateParameters)
void WatchHandler::notifyUpdateFinished()
{
QList<WatchItem *> toRemove;
- m_model->forSelectedItems([this, &toRemove](WatchItem *item) {
+ m_model->forSelectedItems([&toRemove](WatchItem *item) {
if (item->outdated) {
toRemove.append(item);
return false;
diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp
index 8a4f0af3de..a0fc7c47a2 100644
--- a/src/plugins/designer/formeditorplugin.cpp
+++ b/src/plugins/designer/formeditorplugin.cpp
@@ -82,7 +82,7 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error)
#ifdef CPP_ENABLED
IWizardFactory::registerFactoryCreator(
- [this]() -> QList<IWizardFactory *> {
+ []() -> QList<IWizardFactory *> {
IWizardFactory *wizard = new FormClassWizard;
wizard->setCategory(QLatin1String(Core::Constants::WIZARD_CATEGORY_QT));
wizard->setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::WIZARD_TR_CATEGORY_QT));
diff --git a/src/plugins/diffeditor/diffeditor.h b/src/plugins/diffeditor/diffeditor.h
index 0777aed00e..6da073439d 100644
--- a/src/plugins/diffeditor/diffeditor.h
+++ b/src/plugins/diffeditor/diffeditor.h
@@ -35,7 +35,6 @@ QT_BEGIN_NAMESPACE
class QComboBox;
class QSpinBox;
class QToolBar;
-class QToolButton;
class QStackedWidget;
QT_END_NAMESPACE
diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
index 6197da5296..6e7b947bb1 100644
--- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
+++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
@@ -65,7 +65,7 @@ DiffEditorWidgetController::DiffEditorWidgetController(QWidget *diffEditorWidget
void DiffEditorWidgetController::setDocument(DiffEditorDocument *document)
{
if (!m_progressIndicator) {
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large);
+ m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large);
m_progressIndicator->attachToWidget(m_diffEditorWidget);
m_progressIndicator->hide();
}
diff --git a/src/plugins/diffeditor/differ.cpp b/src/plugins/diffeditor/differ.cpp
index 63a0014d37..3dd8d90dd3 100644
--- a/src/plugins/diffeditor/differ.cpp
+++ b/src/plugins/diffeditor/differ.cpp
@@ -1275,7 +1275,7 @@ QStringList Differ::encode(const QString &text1,
QString *encodedText2)
{
QStringList lines;
- lines.append(QLatin1String("")); // don't use code: 0
+ lines.append(QString()); // don't use code: 0
QMap<QString, int> lineToCode;
*encodedText1 = encode(text1, &lines, &lineToCode);
diff --git a/src/plugins/diffeditor/diffview.h b/src/plugins/diffeditor/diffview.h
index 34c473d00c..cbdc2cbdfd 100644
--- a/src/plugins/diffeditor/diffview.h
+++ b/src/plugins/diffeditor/diffview.h
@@ -37,7 +37,6 @@ namespace TextEditor { class TextEditorWidget; }
namespace DiffEditor {
-class DiffEditorController;
class FileData;
namespace Internal {
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
index 2b03308c9e..4f97494b80 100644
--- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h
+++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
@@ -44,7 +44,6 @@ QT_END_NAMESPACE
namespace DiffEditor {
-class DiffEditorController;
class FileData;
namespace Internal {
diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.h b/src/plugins/diffeditor/unifieddiffeditorwidget.h
index c05d05e9af..3e697f7b43 100644
--- a/src/plugins/diffeditor/unifieddiffeditorwidget.h
+++ b/src/plugins/diffeditor/unifieddiffeditorwidget.h
@@ -35,11 +35,6 @@ class DisplaySettings;
class FontSettings;
}
-QT_BEGIN_NAMESPACE
-class QSplitter;
-class QTextCharFormat;
-QT_END_NAMESPACE
-
namespace DiffEditor {
class ChunkData;
diff --git a/src/plugins/fakevim/fakevimoptions.ui b/src/plugins/fakevim/fakevimoptions.ui
index 8db93d585f..db3cb7df45 100644
--- a/src/plugins/fakevim/fakevimoptions.ui
+++ b/src/plugins/fakevim/fakevimoptions.ui
@@ -92,7 +92,7 @@
<item row="6" column="1">
<widget class="QCheckBox" name="checkBoxPassControlKey">
<property name="toolTip">
- <string>Passes key sequences like Ctrl-S to Qt Creator core instead of interpreting them in FakeVim. This gives easier access to Qt Creator core functionality at the price of losing some features of FakeVim.</string>
+ <string>Does not interpret key sequences like Ctrl-S in FakeVim but handles them as regular shortcuts. This gives easier access to core functionality at the price of losing some features of FakeVim.</string>
</property>
<property name="text">
<string>Pass control key</string>
@@ -123,7 +123,7 @@
<item row="7" column="0">
<widget class="QCheckBox" name="checkBoxPassKeys">
<property name="toolTip">
- <string>Lets Qt Creator handle some key presses in insert mode so that code can be properly completed and expanded.</string>
+ <string>Does not interpret some key presses in insert mode so that code can be properly completed and expanded.</string>
</property>
<property name="text">
<string>Pass keys in insert mode</string>
diff --git a/src/plugins/genericprojectmanager/genericmakestep.cpp b/src/plugins/genericprojectmanager/genericmakestep.cpp
index 8569a994ef..be9f30854d 100644
--- a/src/plugins/genericprojectmanager/genericmakestep.cpp
+++ b/src/plugins/genericprojectmanager/genericmakestep.cpp
@@ -232,7 +232,7 @@ GenericMakeStepConfigWidget::GenericMakeStepConfigWidget(GenericMakeStep *makeSt
m_ui->makeLineEdit->setText(m_makeStep->m_makeCommand);
m_ui->makeArgumentsLineEdit->setText(m_makeStep->m_makeArguments);
- updateMakeOverrrideLabel();
+ updateMakeOverrideLabel();
updateDetails();
connect(m_ui->targetsList, &QListWidget::itemChanged,
@@ -243,17 +243,26 @@ GenericMakeStepConfigWidget::GenericMakeStepConfigWidget(GenericMakeStep *makeSt
this, &GenericMakeStepConfigWidget::makeArgumentsLineEditTextEdited);
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
- this, &GenericMakeStepConfigWidget::updateMakeOverrrideLabel);
+ this, &GenericMakeStepConfigWidget::updateMakeOverrideLabel);
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
this, &GenericMakeStepConfigWidget::updateDetails);
connect(m_makeStep->target(), &Target::kitChanged,
- this, &GenericMakeStepConfigWidget::updateMakeOverrrideLabel);
-
- connect(pro, &GenericProject::environmentChanged,
- this, &GenericMakeStepConfigWidget::updateMakeOverrrideLabel);
- connect(pro, &GenericProject::environmentChanged,
- this, &GenericMakeStepConfigWidget::updateDetails);
+ this, &GenericMakeStepConfigWidget::updateMakeOverrideLabel);
+
+ pro->subscribeSignal(&BuildConfiguration::environmentChanged, this, [this]() {
+ if (static_cast<BuildConfiguration *>(sender())->isActive()) {
+ updateMakeOverrideLabel();
+ updateDetails();
+ }
+ });
+ connect(pro, &Project::activeProjectConfigurationChanged,
+ this, [this](ProjectConfiguration *pc) {
+ if (pc && pc->isActive()) {
+ updateMakeOverrideLabel();
+ updateDetails();
+ }
+ });
}
GenericMakeStepConfigWidget::~GenericMakeStepConfigWidget()
@@ -266,7 +275,7 @@ QString GenericMakeStepConfigWidget::displayName() const
return tr("Make", "GenericMakestep display name.");
}
-void GenericMakeStepConfigWidget::updateMakeOverrrideLabel()
+void GenericMakeStepConfigWidget::updateMakeOverrideLabel()
{
BuildConfiguration *bc = m_makeStep->buildConfiguration();
if (!bc)
diff --git a/src/plugins/genericprojectmanager/genericmakestep.h b/src/plugins/genericprojectmanager/genericmakestep.h
index 4228de35ee..de23ffda39 100644
--- a/src/plugins/genericprojectmanager/genericmakestep.h
+++ b/src/plugins/genericprojectmanager/genericmakestep.h
@@ -91,7 +91,7 @@ private:
void itemChanged(QListWidgetItem *item);
void makeLineEditTextEdited();
void makeArgumentsLineEditTextEdited();
- void updateMakeOverrrideLabel();
+ void updateMakeOverrideLabel();
void updateDetails();
Ui::GenericMakeStep *m_ui;
diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp
index 11d57bc6b1..104f52bc05 100644
--- a/src/plugins/genericprojectmanager/genericproject.cpp
+++ b/src/plugins/genericprojectmanager/genericproject.cpp
@@ -126,7 +126,7 @@ public:
bool showInSimpleTree() const override { return true; }
- bool supportsAction(ProjectAction action, Node *) const override
+ bool supportsAction(ProjectAction action, const Node *) const override
{
return action == AddNewFile
|| action == AddExistingFile
@@ -336,6 +336,7 @@ void GenericProject::parseProject(RefreshOptions options)
void GenericProject::refresh(RefreshOptions options)
{
+ emitParsingStarted();
parseProject(options);
if (options & Files) {
@@ -362,7 +363,7 @@ void GenericProject::refresh(RefreshOptions options)
}
refreshCppCodeModel();
- emit parsingFinished();
+ emitParsingFinished(true);
}
/**
@@ -501,7 +502,7 @@ Project::RestoreResult GenericProject::fromMap(const QVariantMap &map, QString *
continue;
}
if (!t->activeRunConfiguration())
- t->addRunConfiguration(new CustomExecutableRunConfiguration(t));
+ t->addRunConfiguration(IRunConfigurationFactory::createHelper<CustomExecutableRunConfiguration>(t));
}
m_activeTarget = activeTarget();
diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.qbs b/src/plugins/genericprojectmanager/genericprojectmanager.qbs
index be30ddffad..cb062d1f52 100644
--- a/src/plugins/genericprojectmanager/genericprojectmanager.qbs
+++ b/src/plugins/genericprojectmanager/genericprojectmanager.qbs
@@ -12,6 +12,7 @@ QtcPlugin {
Depends { name: "TextEditor" }
Depends { name: "ProjectExplorer" }
Depends { name: "QtSupport" }
+ Depends { name: "app_version_header" }
pluginTestDepends: [
"CppEditor",
diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.cpp b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
index c91abba26d..f38be2003b 100644
--- a/src/plugins/genericprojectmanager/genericprojectwizard.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectwizard.cpp
@@ -31,6 +31,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/customwizard/customwizard.h>
+#include <app/app_version.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/filewizardpage.h>
@@ -115,7 +116,8 @@ GenericProjectWizard::GenericProjectWizard()
setDisplayName(tr("Import Existing Project"));
setId("Z.Makefile");
setDescription(tr("Imports existing projects that do not use qmake, CMake or Autotools. "
- "This allows you to use Qt Creator as a code editor."));
+ "This allows you to use %1 as a code editor.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
setCategory(QLatin1String(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY));
setDisplayCategory(QLatin1String(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY_DISPLAY));
setFlags(Core::IWizardFactory::PlatformIndependent);
diff --git a/src/plugins/git/branchdialog.h b/src/plugins/git/branchdialog.h
index a967dc3bdf..9d95dd59da 100644
--- a/src/plugins/git/branchdialog.h
+++ b/src/plugins/git/branchdialog.h
@@ -36,7 +36,6 @@ namespace Internal {
namespace Ui { class BranchDialog; }
-class BranchAddDialog;
class BranchModel;
/**
diff --git a/src/plugins/git/changeselectiondialog.h b/src/plugins/git/changeselectiondialog.h
index 5fad19b836..b87ce10eed 100644
--- a/src/plugins/git/changeselectiondialog.h
+++ b/src/plugins/git/changeselectiondialog.h
@@ -33,10 +33,6 @@
#include <QProcessEnvironment>
QT_BEGIN_NAMESPACE
-class QPushButton;
-class QLabel;
-class QLineEdit;
-class QPlainTextEdit;
class QProcess;
class QStringListModel;
QT_END_NAMESPACE
diff --git a/src/plugins/git/gerrit/gerritdialog.cpp b/src/plugins/git/gerrit/gerritdialog.cpp
index 21ccef371a..be1d79af90 100644
--- a/src/plugins/git/gerrit/gerritdialog.cpp
+++ b/src/plugins/git/gerrit/gerritdialog.cpp
@@ -97,7 +97,7 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
m_progressIndicatorTimer.setSingleShot(true);
m_progressIndicatorTimer.setInterval(50); // don't show progress for < 50ms tasks
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large,
+ m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large,
m_ui->treeView);
m_progressIndicator->attachToWidget(m_ui->treeView->viewport());
m_progressIndicator->hide();
diff --git a/src/plugins/git/gerrit/gerritmodel.h b/src/plugins/git/gerrit/gerritmodel.h
index d9efd0edd2..213de67db9 100644
--- a/src/plugins/git/gerrit/gerritmodel.h
+++ b/src/plugins/git/gerrit/gerritmodel.h
@@ -32,10 +32,6 @@
#include <QSharedPointer>
#include <QDateTime>
-QT_BEGIN_NAMESPACE
-class QUrl;
-QT_END_NAMESPACE
-
namespace Gerrit {
namespace Internal {
class QueryContext;
diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp
index b9f4fca201..5e088aa5a8 100644
--- a/src/plugins/git/gerrit/gerritplugin.cpp
+++ b/src/plugins/git/gerrit/gerritplugin.cpp
@@ -520,7 +520,7 @@ QString GerritPlugin::findLocalRepository(QString project, const QString &branch
} // for repositories
// No match, do we have a projects folder?
if (DocumentManager::useProjectsDirectory())
- return DocumentManager::projectsDirectory();
+ return DocumentManager::projectsDirectory().toString();
return QDir::currentPath();
}
diff --git a/src/plugins/git/gerrit/gerritplugin.h b/src/plugins/git/gerrit/gerritplugin.h
index 2915f9b2b3..404a2c9f25 100644
--- a/src/plugins/git/gerrit/gerritplugin.h
+++ b/src/plugins/git/gerrit/gerritplugin.h
@@ -32,10 +32,6 @@
#include <QSharedPointer>
#include <QPair>
-QT_BEGIN_NAMESPACE
-class QAction;
-QT_END_NAMESPACE
-
namespace Core {
class ActionContainer;
class Command;
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index ae1c324c30..f2cdc4750d 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -694,7 +694,7 @@ void GitClient::diffFiles(const QString &workingDirectory,
+ QLatin1String(".DiffFiles.") + workingDirectory;
requestReload(documentId,
workingDirectory, tr("Git Diff Files"),
- [this, workingDirectory, stagedFileNames, unstagedFileNames]
+ [workingDirectory, stagedFileNames, unstagedFileNames]
(IDocument *doc) -> DiffEditorController* {
return new FileListDiffController(doc, workingDirectory,
stagedFileNames, unstagedFileNames);
@@ -707,7 +707,7 @@ void GitClient::diffProject(const QString &workingDirectory, const QString &proj
+ QLatin1String(".DiffProject.") + workingDirectory;
requestReload(documentId,
workingDirectory, tr("Git Diff Project"),
- [this, workingDirectory, projectDirectory]
+ [workingDirectory, projectDirectory]
(IDocument *doc) -> DiffEditorController* {
return new ProjectDiffController(doc, workingDirectory, {projectDirectory});
});
@@ -719,7 +719,7 @@ void GitClient::diffRepository(const QString &workingDirectory)
+ QLatin1String(".DiffRepository.") + workingDirectory;
requestReload(documentId,
workingDirectory, tr("Git Diff Repository"),
- [this, workingDirectory](IDocument *doc) -> DiffEditorController* {
+ [workingDirectory](IDocument *doc) -> DiffEditorController* {
return new RepositoryDiffController(doc, workingDirectory);
});
}
@@ -731,7 +731,7 @@ void GitClient::diffFile(const QString &workingDirectory, const QString &fileNam
const QString documentId = QLatin1String(Constants::GIT_PLUGIN)
+ QLatin1String(".DifFile.") + sourceFile;
requestReload(documentId, sourceFile, title,
- [this, workingDirectory, fileName]
+ [workingDirectory, fileName]
(IDocument *doc) -> DiffEditorController* {
return new FileDiffController(doc, workingDirectory, fileName);
});
@@ -744,7 +744,7 @@ void GitClient::diffBranch(const QString &workingDirectory,
const QString documentId = QLatin1String(Constants::GIT_PLUGIN)
+ QLatin1String(".DiffBranch.") + branchName;
requestReload(documentId, workingDirectory, title,
- [this, workingDirectory, branchName]
+ [workingDirectory, branchName]
(IDocument *doc) -> DiffEditorController* {
return new BranchDiffController(doc, workingDirectory, branchName);
});
@@ -851,7 +851,7 @@ void GitClient::show(const QString &source, const QString &id, const QString &na
const QString documentId = QLatin1String(Constants::GIT_PLUGIN)
+ QLatin1String(".Show.") + id;
requestReload(documentId, source, title,
- [this, workingDirectory, id]
+ [workingDirectory, id]
(IDocument *doc) -> DiffEditorController* {
return new ShowController(doc, workingDirectory, id);
});
@@ -1768,7 +1768,7 @@ bool GitClient::cleanList(const QString &workingDirectory, const QString &module
const QString relativeBase = modulePath.isEmpty() ? QString() : modulePath + '/';
const QString prefix = "Would remove ";
const QStringList removeLines = Utils::filtered(
- splitLines(resp.stdOut()), [&prefix](const QString &s) {
+ splitLines(resp.stdOut()), [](const QString &s) {
return s.startsWith("Would remove ");
});
*files = Utils::transform(removeLines, [&relativeBase, &prefix](const QString &s) -> QString {
@@ -2863,8 +2863,7 @@ bool GitClient::canRebase(const QString &workingDirectory) const
void GitClient::rebase(const QString &workingDirectory, const QString &argument)
{
- VcsCommand *command = vcsExecAbortable(workingDirectory, {"rebase", argument});
- GitProgressParser::attachToCommand(command);
+ vcsExecAbortable(workingDirectory, {"rebase", argument}, true);
}
void GitClient::cherryPick(const QString &workingDirectory, const QString &argument)
@@ -2880,7 +2879,8 @@ void GitClient::revert(const QString &workingDirectory, const QString &argument)
// Executes a command asynchronously. Work tree is expected to be clean.
// Stashing is handled prior to this call.
VcsCommand *GitClient::vcsExecAbortable(const QString &workingDirectory,
- const QStringList &arguments)
+ const QStringList &arguments,
+ bool createProgressParser)
{
QTC_ASSERT(!arguments.isEmpty(), return nullptr);
@@ -2890,8 +2890,10 @@ VcsCommand *GitClient::vcsExecAbortable(const QString &workingDirectory,
command->setCookie(workingDirectory);
command->addFlags(VcsCommand::ShowSuccessMessage);
command->addJob(vcsBinary(), arguments, 0);
- command->execute();
ConflictHandler::attachToCommand(command, abortCommand);
+ if (createProgressParser)
+ GitProgressParser::attachToCommand(command);
+ command->execute();
return command;
}
@@ -2929,8 +2931,7 @@ void GitClient::interactiveRebase(const QString &workingDirectory, const QString
arguments << commit + '^';
if (fixup)
m_disableEditor = true;
- VcsCommand *command = vcsExecAbortable(workingDirectory, arguments);
- GitProgressParser::attachToCommand(command);
+ vcsExecAbortable(workingDirectory, arguments, true);
if (fixup)
m_disableEditor = false;
}
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 7563f24531..7d26709c40 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -53,7 +53,6 @@ namespace VcsBase {
}
namespace DiffEditor {
-class DiffEditorDocument;
class DiffEditorController;
}
@@ -125,7 +124,9 @@ public:
Utils::FileName vcsBinary() const override;
unsigned gitVersion(QString *errorMessage = nullptr) const;
- VcsBase::VcsCommand *vcsExecAbortable(const QString &workingDirectory, const QStringList &arguments);
+ VcsBase::VcsCommand *vcsExecAbortable(const QString &workingDirectory,
+ const QStringList &arguments,
+ bool createProgressParser = false);
QString findRepositoryForDirectory(const QString &dir) const;
QString findGitDirForRepository(const QString &repositoryDir) const;
diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h
index d776d2ff5d..f074f8fedd 100644
--- a/src/plugins/git/giteditor.h
+++ b/src/plugins/git/giteditor.h
@@ -29,10 +29,6 @@
#include <QRegExp>
-QT_BEGIN_NAMESPACE
-class QVariant;
-QT_END_NAMESPACE
-
namespace Git {
namespace Internal {
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 5070fef544..a310e132cb 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -296,10 +296,10 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
m_gitClient = new GitClient;
- initializeVcs(new GitVersionControl(m_gitClient), context);
+ auto vc = initializeVcs<GitVersionControl>(context, m_gitClient);
// Create the settings Page
- auto settingsPage = new SettingsPage(versionControl());
+ auto settingsPage = new SettingsPage(vc);
addAutoReleasedObject(settingsPage);
connect(settingsPage, &SettingsPage::settingsChanged,
this, &GitPlugin::updateRepositoryBrowserAction);
@@ -926,6 +926,9 @@ void GitPlugin::gitGui()
void GitPlugin::startCommit(CommitType commitType)
{
+ if (!promptBeforeCommit())
+ return;
+
if (raiseSubmitEditor())
return;
if (isCommitEditorOpen()) {
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index 790f0959a8..2772cddcb9 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -39,9 +39,7 @@
#include <functional>
QT_BEGIN_NAMESPACE
-class QFile;
class QAction;
-class QFileInfo;
QT_END_NAMESPACE
namespace Core {
@@ -61,7 +59,6 @@ namespace Internal {
class GitVersionControl;
class GitClient;
-class GitSubmitEditor;
class CommitData;
class StashDialog;
class BranchDialog;
diff --git a/src/plugins/git/gitsubmiteditor.h b/src/plugins/git/gitsubmiteditor.h
index 04f031901e..40948f3b98 100644
--- a/src/plugins/git/gitsubmiteditor.h
+++ b/src/plugins/git/gitsubmiteditor.h
@@ -37,7 +37,6 @@ namespace VcsBase { class SubmitFileModel; }
namespace Git {
namespace Internal {
-class GitClient;
class GitSubmitEditorWidget;
class GitSubmitEditorPanelData;
diff --git a/src/plugins/git/mergetool.h b/src/plugins/git/mergetool.h
index f905cf25a0..d5d3d45f64 100644
--- a/src/plugins/git/mergetool.h
+++ b/src/plugins/git/mergetool.h
@@ -36,8 +36,6 @@ QT_END_NAMESPACE
namespace Git {
namespace Internal {
-class GitClient;
-
class MergeTool : public QObject
{
Q_OBJECT
diff --git a/src/plugins/git/remotemodel.cpp b/src/plugins/git/remotemodel.cpp
index 7cd14b1258..59164963d6 100644
--- a/src/plugins/git/remotemodel.cpp
+++ b/src/plugins/git/remotemodel.cpp
@@ -188,9 +188,6 @@ bool RemoteModel::refresh(const QString &workingDirectory, QString *errorMessage
QMap<QString,QString> remotesList
= GitPlugin::client()->synchronousRemotesList(workingDirectory, errorMessage);
- if (remotesList.isEmpty())
- return false;
-
beginResetModel();
m_remotes.clear();
const QList<QString> remotes = remotesList.keys();
diff --git a/src/plugins/git/remotemodel.h b/src/plugins/git/remotemodel.h
index 467d9de3b5..6ac83e32fa 100644
--- a/src/plugins/git/remotemodel.h
+++ b/src/plugins/git/remotemodel.h
@@ -32,8 +32,6 @@
namespace Git {
namespace Internal {
-class GitClient;
-
class RemoteModel : public QAbstractTableModel {
Q_OBJECT
public:
diff --git a/src/plugins/git/settingspage.h b/src/plugins/git/settingspage.h
index 205bda707e..3e2ca9087d 100644
--- a/src/plugins/git/settingspage.h
+++ b/src/plugins/git/settingspage.h
@@ -32,10 +32,6 @@
#include <QPointer>
#include <QWidget>
-QT_BEGIN_NAMESPACE
-class QSettings;
-QT_END_NAMESPACE
-
namespace VcsBase {
class VcsBaseClientSettings;
} // namespace VcsBase
diff --git a/src/plugins/git/stashdialog.h b/src/plugins/git/stashdialog.h
index a64857b318..bf72509094 100644
--- a/src/plugins/git/stashdialog.h
+++ b/src/plugins/git/stashdialog.h
@@ -30,7 +30,6 @@
QT_BEGIN_NAMESPACE
class QSortFilterProxyModel;
class QPushButton;
-class QModelIndex;
QT_END_NAMESPACE
namespace Git {
diff --git a/src/plugins/help/centralwidget.h b/src/plugins/help/centralwidget.h
index 088487e349..1796088fa9 100644
--- a/src/plugins/help/centralwidget.h
+++ b/src/plugins/help/centralwidget.h
@@ -32,8 +32,6 @@
namespace Help {
namespace Internal {
-class HelpViewer;
-class PrintHelper;
class CentralWidget : public HelpWidget
{
diff --git a/src/plugins/help/generalsettingspage.h b/src/plugins/help/generalsettingspage.h
index 0bfca8fdc6..7b5fe53146 100644
--- a/src/plugins/help/generalsettingspage.h
+++ b/src/plugins/help/generalsettingspage.h
@@ -33,7 +33,6 @@
namespace Help {
namespace Internal {
-class CentralWidget;
class GeneralSettingsPage : public Core::IOptionsPage
{
diff --git a/src/plugins/help/helpplugin.h b/src/plugins/help/helpplugin.h
index d6985733ef..52eb5a7370 100644
--- a/src/plugins/help/helpplugin.h
+++ b/src/plugins/help/helpplugin.h
@@ -35,16 +35,11 @@
#include <QStringList>
QT_BEGIN_NAMESPACE
-class QAction;
-class QMenu;
-class QToolButton;
class QUrl;
QT_END_NAMESPACE
namespace Core {
-class MiniSplitter;
class SideBar;
-class SideBarItem;
} // Core
namespace Utils { class StyledBar; }
@@ -54,12 +49,10 @@ namespace Internal {
class CentralWidget;
class DocSettingsPage;
class FilterSettingsPage;
-class GeneralSettingsPage;
class HelpMode;
class HelpViewer;
class LocalHelpManager;
class OpenPagesManager;
-class SearchWidget;
class SearchTaskHandler;
class HelpPlugin : public ExtensionSystem::IPlugin
diff --git a/src/plugins/help/helpwidget.h b/src/plugins/help/helpwidget.h
index 3e27d28619..cd1fffa424 100644
--- a/src/plugins/help/helpwidget.h
+++ b/src/plugins/help/helpwidget.h
@@ -33,7 +33,6 @@
QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
-class QFont;
class QMenu;
class QPrinter;
class QStackedWidget;
diff --git a/src/plugins/help/images/mode_help.png b/src/plugins/help/images/mode_help.png
index 7247e639eb..e2e3eb64d1 100644
--- a/src/plugins/help/images/mode_help.png
+++ b/src/plugins/help/images/mode_help.png
Binary files differ
diff --git a/src/plugins/help/images/mode_help@2x.png b/src/plugins/help/images/mode_help@2x.png
index ae8db24fd7..51e4ed8ff8 100644
--- a/src/plugins/help/images/mode_help@2x.png
+++ b/src/plugins/help/images/mode_help@2x.png
Binary files differ
diff --git a/src/plugins/help/images/mode_help_mask.png b/src/plugins/help/images/mode_help_mask.png
index 43eb4d120b..144871e854 100644
--- a/src/plugins/help/images/mode_help_mask.png
+++ b/src/plugins/help/images/mode_help_mask.png
Binary files differ
diff --git a/src/plugins/help/images/mode_help_mask@2x.png b/src/plugins/help/images/mode_help_mask@2x.png
index 611769bd96..50f12d8e11 100644
--- a/src/plugins/help/images/mode_help_mask@2x.png
+++ b/src/plugins/help/images/mode_help_mask@2x.png
Binary files differ
diff --git a/src/plugins/help/searchwidget.h b/src/plugins/help/searchwidget.h
index d06a597b32..e0ad8ebab5 100644
--- a/src/plugins/help/searchwidget.h
+++ b/src/plugins/help/searchwidget.h
@@ -34,7 +34,6 @@
QT_BEGIN_NAMESPACE
class QHelpSearchEngine;
class QHelpSearchResultWidget;
-class QMouseEvent;
class QUrl;
QT_END_NAMESPACE
diff --git a/src/plugins/imageviewer/imageviewerplugin.cpp b/src/plugins/imageviewer/imageviewerplugin.cpp
index 6d1419da44..6a453eb90e 100644
--- a/src/plugins/imageviewer/imageviewerplugin.cpp
+++ b/src/plugins/imageviewer/imageviewerplugin.cpp
@@ -64,56 +64,56 @@ void ImageViewerPlugin::extensionsInitialized()
{
QAction *a = registerNewAction(Constants::ACTION_ZOOM_IN, tr("Zoom In"),
QKeySequence(tr("Ctrl++")));
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->zoomIn();
});
a = registerNewAction(Constants::ACTION_ZOOM_OUT, tr("Zoom Out"),
QKeySequence(tr("Ctrl+-")));
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->zoomOut();
});
a = registerNewAction(Constants::ACTION_ORIGINAL_SIZE, tr("Original Size"),
QKeySequence(Core::UseMacShortcuts ? tr("Meta+0") : tr("Ctrl+0")));
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->resetToOriginalSize();
});
a = registerNewAction(Constants::ACTION_FIT_TO_SCREEN, tr("Fit to Screen"),
QKeySequence(tr("Ctrl+=")));
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->fitToScreen();
});
a = registerNewAction(Constants::ACTION_BACKGROUND, tr("Switch Background"),
QKeySequence(tr("Ctrl+[")));
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->switchViewBackground();
});
a = registerNewAction(Constants::ACTION_OUTLINE, tr("Switch Outline"),
QKeySequence(tr("Ctrl+]")));
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->switchViewOutline();
});
a = registerNewAction(Constants::ACTION_TOGGLE_ANIMATION, tr("Toggle Animation"),
QKeySequence());
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->togglePlay();
});
a = registerNewAction(Constants::ACTION_EXPORT_IMAGE, tr("Export Image"),
QKeySequence());
- connect(a, &QAction::triggered, this, [this]() {
+ connect(a, &QAction::triggered, this, []() {
if (ImageViewer *iv = currentImageViewer())
iv->exportImage();
});
diff --git a/src/plugins/ios/images/iosdevice.png b/src/plugins/ios/images/iosdevice.png
index 9b3fabeaf3..892e09c778 100644
--- a/src/plugins/ios/images/iosdevice.png
+++ b/src/plugins/ios/images/iosdevice.png
Binary files differ
diff --git a/src/plugins/ios/images/iosdevice@2x.png b/src/plugins/ios/images/iosdevice@2x.png
index 1e078270c6..89bbaf0347 100644
--- a/src/plugins/ios/images/iosdevice@2x.png
+++ b/src/plugins/ios/images/iosdevice@2x.png
Binary files differ
diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp
index f7f0dc7219..c088b1ede4 100644
--- a/src/plugins/ios/iosbuildstep.cpp
+++ b/src/plugins/ios/iosbuildstep.cpp
@@ -60,17 +60,13 @@ const char BUILD_ARGUMENTS_KEY[] = "Ios.IosBuildStep.XcodeArguments";
const char CLEAN_KEY[] = "Ios.IosBuildStep.Clean";
IosBuildStep::IosBuildStep(BuildStepList *parent) :
- AbstractProcessStep(parent, Id(IOS_BUILD_STEP_ID)),
- m_useDefaultArguments(true),
- m_clean(false)
+ AbstractProcessStep(parent, Id(IOS_BUILD_STEP_ID))
{
ctor();
}
IosBuildStep::IosBuildStep(BuildStepList *parent, const Id id) :
- AbstractProcessStep(parent, id),
- m_useDefaultArguments(true),
- m_clean(false)
+ AbstractProcessStep(parent, id)
{
ctor();
}
@@ -264,7 +260,15 @@ IosBuildStepConfigWidget::IosBuildStepConfigWidget(IosBuildStep *buildStep)
this, &IosBuildStepConfigWidget::updateDetails);
connect(m_buildStep->target(), &Target::kitChanged,
this, &IosBuildStepConfigWidget::updateDetails);
- connect(pro, &Project::environmentChanged, this, &IosBuildStepConfigWidget::updateDetails);
+ pro->subscribeSignal(&BuildConfiguration::environmentChanged, this, [this]() {
+ if (static_cast<BuildConfiguration *>(sender())->isActive())
+ updateDetails();
+ });
+ connect(pro, &Project::activeProjectConfigurationChanged,
+ this, [this](ProjectConfiguration *pc) {
+ if (pc && pc->isActive())
+ updateDetails();
+ });
}
IosBuildStepConfigWidget::~IosBuildStepConfigWidget()
diff --git a/src/plugins/ios/iosbuildstep.h b/src/plugins/ios/iosbuildstep.h
index 05caaf9303..047eb799f9 100644
--- a/src/plugins/ios/iosbuildstep.h
+++ b/src/plugins/ios/iosbuildstep.h
@@ -74,9 +74,8 @@ private:
QStringList m_baseBuildArguments;
QStringList m_extraArguments;
- QString m_buildCommand;
- bool m_useDefaultArguments;
- bool m_clean;
+ bool m_useDefaultArguments = true;
+ bool m_clean = false;
};
class IosBuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget
diff --git a/src/plugins/ios/iosdsymbuildstep.cpp b/src/plugins/ios/iosdsymbuildstep.cpp
index c6c5ce0227..3d876621e9 100644
--- a/src/plugins/ios/iosdsymbuildstep.cpp
+++ b/src/plugins/ios/iosdsymbuildstep.cpp
@@ -260,7 +260,15 @@ IosPresetBuildStepConfigWidget::IosPresetBuildStepConfigWidget(IosPresetBuildSte
this, &IosPresetBuildStepConfigWidget::updateDetails);
connect(m_buildStep->target(), &Target::kitChanged,
this, &IosPresetBuildStepConfigWidget::updateDetails);
- connect(pro, &Project::environmentChanged, this, &IosPresetBuildStepConfigWidget::updateDetails);
+ pro->subscribeSignal(&BuildConfiguration::environmentChanged, this, [this]() {
+ if (static_cast<BuildConfiguration *>(sender())->isActive())
+ updateDetails();
+ });
+ connect(pro, &Project::activeProjectConfigurationChanged,
+ this, [this](ProjectConfiguration *pc) {
+ if (pc && pc->isActive())
+ updateDetails();
+ });
}
IosPresetBuildStepConfigWidget::~IosPresetBuildStepConfigWidget()
diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp
index 093f9100e4..d1c5cc6984 100644
--- a/src/plugins/ios/iosrunconfiguration.cpp
+++ b/src/plugins/ios/iosrunconfiguration.cpp
@@ -94,65 +94,37 @@ private:
QComboBox *m_deviceTypeComboBox;
};
-IosRunConfiguration::IosRunConfiguration(Target *parent, Core::Id id, const FileName &path)
- : RunConfiguration(parent, id)
- , m_profilePath(path)
+IosRunConfiguration::IosRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
- addExtraAspect(new ArgumentsAspect(this, QLatin1String("Ios.run_arguments")));
- init();
-}
+ addExtraAspect(new ArgumentsAspect(this, "Ios.run_arguments"));
-IosRunConfiguration::IosRunConfiguration(Target *parent, IosRunConfiguration *source)
- : RunConfiguration(parent, source)
- , m_profilePath(source->m_profilePath)
-{
- init();
-}
-
-void IosRunConfiguration::init()
-{
- QmakeProject *project = static_cast<QmakeProject *>(target()->project());
- m_parseSuccess = project->validParse(m_profilePath);
- m_parseInProgress = project->parseInProgress(m_profilePath);
- m_lastIsEnabled = isEnabled();
- m_lastDisabledReason = disabledReason();
- updateDisplayNames();
connect(DeviceManager::instance(), &DeviceManager::updated,
this, &IosRunConfiguration::deviceChanges);
connect(KitManager::instance(), &KitManager::kitsChanged,
this, &IosRunConfiguration::deviceChanges);
- connect(project, &QmakeProject::proFileUpdated,
- this, &IosRunConfiguration::proFileUpdated);
}
-void IosRunConfiguration::enabledCheck()
+
+void IosRunConfiguration::initialize(Core::Id id, const FileName &path)
{
- bool newIsEnabled = isEnabled();
- QString newDisabledReason = disabledReason();
- if (newDisabledReason != m_lastDisabledReason || newIsEnabled != m_lastIsEnabled) {
- m_lastDisabledReason = newDisabledReason;
- m_lastIsEnabled = newIsEnabled;
- emit enabledChanged();
- }
-}
+ RunConfiguration::initialize(id);
+ m_profilePath = path;
-void IosRunConfiguration::deviceChanges() {
updateDisplayNames();
- enabledCheck();
}
-void IosRunConfiguration::proFileUpdated(QmakeProFile *pro, bool success,
- bool parseInProgress)
+void IosRunConfiguration::copyFrom(const IosRunConfiguration *source)
{
- if (m_profilePath != pro->filePath())
- return;
- m_parseSuccess = success;
- m_parseInProgress = parseInProgress;
- if (success && !parseInProgress) {
- updateDisplayNames();
- emit localExecutableChanged();
- }
- enabledCheck();
+ RunConfiguration::copyFrom(source);
+ m_profilePath = source->m_profilePath;
+
+ updateDisplayNames();
+}
+
+void IosRunConfiguration::deviceChanges() {
+ updateDisplayNames();
+ updateEnabledState();
}
QWidget *IosRunConfiguration::createConfigurationWidget()
@@ -182,6 +154,21 @@ void IosRunConfiguration::updateDisplayNames()
setDisplayName(tr("Run %1 on %2").arg(applicationName()).arg(devName));
}
+void IosRunConfiguration::updateEnabledState()
+{
+ Core::Id devType = DeviceTypeKitInformation::deviceTypeId(target()->kit());
+ if (devType != Constants::IOS_DEVICE_TYPE && devType != Constants::IOS_SIMULATOR_TYPE) {
+ setEnabled(false);
+ return;
+ }
+ IDevice::ConstPtr dev = DeviceKitInformation::device(target()->kit());
+ if (dev.isNull() || dev->deviceState() != IDevice::DeviceReadyToUse) {
+ setEnabled(false);
+ return;
+ }
+ return RunConfiguration::updateEnabledState();
+}
+
IosDeployStep *IosRunConfiguration::deployStep() const
{
DeployConfiguration *config = target()->activeDeployConfiguration();
@@ -287,26 +274,8 @@ QString IosRunConfiguration::buildSystemTarget() const
return static_cast<QmakeProject *>(target()->project())->mapProFilePathToTarget(m_profilePath);
}
-bool IosRunConfiguration::isEnabled() const
-{
- if (m_parseInProgress || !m_parseSuccess)
- return false;
- Core::Id devType = DeviceTypeKitInformation::deviceTypeId(target()->kit());
- if (devType != Constants::IOS_DEVICE_TYPE && devType != Constants::IOS_SIMULATOR_TYPE)
- return false;
- IDevice::ConstPtr dev = DeviceKitInformation::device(target()->kit());
- if (dev.isNull() || dev->deviceState() != IDevice::DeviceReadyToUse)
- return false;
- return RunConfiguration::isEnabled();
-}
-
QString IosRunConfiguration::disabledReason() const
{
- if (m_parseInProgress)
- return tr("The .pro file \"%1\" is currently being parsed.").arg(m_profilePath.fileName());
- if (!m_parseSuccess)
- return static_cast<QmakeProject *>(target()->project())
- ->disabledReasonForRunConfiguration(m_profilePath);
Core::Id devType = DeviceTypeKitInformation::deviceTypeId(target()->kit());
if (devType != Constants::IOS_DEVICE_TYPE && devType != Constants::IOS_SIMULATOR_TYPE)
return tr("Kit has incorrect device type for running on iOS devices.");
diff --git a/src/plugins/ios/iosrunconfiguration.h b/src/plugins/ios/iosrunconfiguration.h
index 9a33177e8c..86401ea094 100644
--- a/src/plugins/ios/iosrunconfiguration.h
+++ b/src/plugins/ios/iosrunconfiguration.h
@@ -44,10 +44,9 @@ class IosRunConfigurationWidget;
class IosRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
- friend class IosRunConfigurationFactory;
public:
- IosRunConfiguration(ProjectExplorer::Target *parent, Core::Id id, const Utils::FileName &path);
+ explicit IosRunConfiguration(ProjectExplorer::Target *target);
QWidget *createConfigurationWidget() override;
Utils::OutputFormatter *createOutputFormatter() const override;
@@ -58,7 +57,6 @@ public:
QString applicationName() const;
Utils::FileName bundleDirectory() const;
Utils::FileName localExecutable() const;
- bool isEnabled() const override;
QString disabledReason() const override;
IosDeviceType deviceType() const;
void setDeviceType(const IosDeviceType &deviceType);
@@ -68,25 +66,20 @@ public:
QString buildSystemTarget() const final;
-protected:
- IosRunConfiguration(ProjectExplorer::Target *parent, IosRunConfiguration *source);
-
signals:
void localExecutableChanged();
private:
- void proFileUpdated(QmakeProjectManager::QmakeProFile *pro, bool success, bool parseInProgress);
+ friend class ProjectExplorer::IRunConfigurationFactory;
+ void initialize(Core::Id id, const Utils::FileName &path);
+ void copyFrom(const IosRunConfiguration *source);
+
void deviceChanges();
- void init();
- void enabledCheck();
friend class IosRunConfigurationWidget;
void updateDisplayNames();
+ void updateEnabledState() final;
Utils::FileName m_profilePath;
- QString m_lastDisabledReason;
- bool m_lastIsEnabled;
- bool m_parseInProgress;
- bool m_parseSuccess;
IosDeviceType m_deviceType;
};
diff --git a/src/plugins/ios/iosrunfactories.cpp b/src/plugins/ios/iosrunfactories.cpp
index c41dcb8263..de36ec7948 100644
--- a/src/plugins/ios/iosrunfactories.cpp
+++ b/src/plugins/ios/iosrunfactories.cpp
@@ -108,8 +108,7 @@ RunConfiguration *IosRunConfigurationFactory::clone(Target *parent, RunConfigura
if (!canClone(parent, source))
return 0;
- IosRunConfiguration *old = qobject_cast<IosRunConfiguration *>(source);
- return new IosRunConfiguration(parent, old);
+ return cloneHelper<IosRunConfiguration>(parent, source);
}
bool IosRunConfigurationFactory::canHandle(Target *t) const
@@ -133,13 +132,13 @@ QList<RunConfiguration *> IosRunConfigurationFactory::runConfigurationsForNode(T
RunConfiguration *IosRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
- return new IosRunConfiguration(parent, id, pathFromId(id));
+ return createHelper<IosRunConfiguration>(parent, id, pathFromId(id));
}
RunConfiguration *IosRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
{
Core::Id id = ProjectExplorer::idFromMap(map);
- return new IosRunConfiguration(parent, id, pathFromId(id));
+ return createHelper<IosRunConfiguration>(parent, id, pathFromId(id));
}
} // namespace Internal
diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp
index a57dbd461f..18264317bb 100644
--- a/src/plugins/ios/iosrunner.cpp
+++ b/src/plugins/ios/iosrunner.cpp
@@ -440,11 +440,10 @@ void IosDebugSupport::start()
RunConfiguration *runConfig = runControl()->runConfiguration();
- DebuggerStartParameters params;
if (device()->type() == Ios::Constants::IOS_DEVICE_TYPE) {
IosDevice::ConstPtr dev = device().dynamicCast<const IosDevice>();
- params.startMode = AttachToRemoteProcess;
- params.platform = "remote-ios";
+ setStartMode(AttachToRemoteProcess);
+ setIosPlatform("remote-ios");
QString osVersion = dev->osVersion();
FileName deviceSdk1 = FileName::fromString(QDir::homePath()
+ "/Library/Developer/Xcode/iOS DeviceSupport/"
@@ -467,25 +466,25 @@ void IosDebugSupport::start()
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
}
}
- params.deviceSymbolsRoot = deviceSdk;
+ setDeviceSymbolsRoot(deviceSdk);
} else {
- params.startMode = AttachExternal;
- params.platform = "ios-simulator";
+ setStartMode(AttachExternal);
+ setIosPlatform("ios-simulator");
}
auto iosRunConfig = qobject_cast<IosRunConfiguration *>(runConfig);
- params.displayName = iosRunConfig->applicationName();
- params.continueAfterAttach = true;
+ setRunControlName(iosRunConfig->applicationName());
+ setContinueAfterAttach(true);
Utils::Port gdbServerPort = m_runner->gdbServerPort();
Utils::Port qmlServerPort = m_runner->qmlServerPort();
- params.attachPID = ProcessHandle(m_runner->pid());
+ setAttachPid(ProcessHandle(m_runner->pid()));
const bool cppDebug = isCppDebugging();
const bool qmlDebug = isQmlDebugging();
if (cppDebug) {
- params.inferior.executable = iosRunConfig->localExecutable().toString();
- params.remoteChannel = "connect://localhost:" + gdbServerPort.toString();
+ setInferiorExecutable(iosRunConfig->localExecutable().toString());
+ setRemoteChannel("connect://localhost:" + gdbServerPort.toString());
FileName xcodeInfo = IosConfigurations::developerPath().parentDir().appendPath("Info.plist");
bool buggyLldb = false;
@@ -514,21 +513,20 @@ void IosDebugSupport::start()
}
}
+ QUrl qmlServer;
if (qmlDebug) {
QTcpServer server;
QTC_ASSERT(server.listen(QHostAddress::LocalHost)
|| server.listen(QHostAddress::LocalHostIPv6), return);
- params.qmlServer.host = server.serverAddress().toString();
+ qmlServer.setHost(server.serverAddress().toString());
if (!cppDebug)
- params.startMode = AttachToRemoteServer;
+ setStartMode(AttachToRemoteServer);
}
- if (qmlServerPort.isValid()) {
- params.qmlServer.port = qmlServerPort;
- params.inferior.commandLineArguments.replace("%qml_port%", qmlServerPort.toString());
- }
+ if (qmlServerPort.isValid())
+ qmlServer.setPort(qmlServerPort.number());
- setStartParameters(params);
+ setQmlServer(qmlServer);
DebuggerRunTool::start();
}
diff --git a/src/plugins/ios/iossettingswidget.cpp b/src/plugins/ios/iossettingswidget.cpp
index 6e99dadca2..0cb54bd28b 100644
--- a/src/plugins/ios/iossettingswidget.cpp
+++ b/src/plugins/ios/iossettingswidget.cpp
@@ -148,7 +148,7 @@ void IosSettingsWidget::onCreate()
QPointer<SimulatorOperationDialog> statusDialog = new SimulatorOperationDialog(this);
statusDialog->setAttribute(Qt::WA_DeleteOnClose);
statusDialog->addMessage(tr("Creating simulator device..."), Utils::NormalMessageFormat);
- const auto onSimulatorCreate = [this, statusDialog](const QString &name,
+ const auto onSimulatorCreate = [statusDialog](const QString &name,
const SimulatorControl::ResponseData &response) {
if (response.success) {
statusDialog->addMessage(tr("Simulator device (%1) created.\nUDID: %2")
diff --git a/src/plugins/macros/imacrohandler.cpp b/src/plugins/macros/imacrohandler.cpp
index 15d36b6358..b9b3fbf2f4 100644
--- a/src/plugins/macros/imacrohandler.cpp
+++ b/src/plugins/macros/imacrohandler.cpp
@@ -67,55 +67,31 @@ using namespace Macros::Internal;
the macro event.
*/
-class IMacroHandler::IMacroHandlerPrivate
-{
-public:
- IMacroHandlerPrivate();
-
- Macro *currentMacro;
-};
-
-IMacroHandler::IMacroHandlerPrivate::IMacroHandlerPrivate() :
- currentMacro(0)
-{
-}
-
-
// ---------- IMacroHandler ------------
-IMacroHandler::IMacroHandler():
- d(new IMacroHandlerPrivate)
-{
-}
-
-IMacroHandler::~IMacroHandler()
-{
- delete d;
-}
-
void IMacroHandler::startRecording(Macro* macro)
{
- d->currentMacro = macro;
+ m_currentMacro = macro;
}
void IMacroHandler::endRecordingMacro(Macro* macro)
{
Q_UNUSED(macro)
- d->currentMacro = 0;
+ m_currentMacro = nullptr;
}
void IMacroHandler::addMacroEvent(const MacroEvent& event)
{
- if (d->currentMacro)
- d->currentMacro->append(event);
+ if (m_currentMacro)
+ m_currentMacro->append(event);
}
void IMacroHandler::setCurrentMacro(Macro *macro)
{
- d->currentMacro = macro;
+ m_currentMacro = macro;
}
bool IMacroHandler::isRecording() const
{
- return d->currentMacro != 0;
+ return m_currentMacro != nullptr;
}
diff --git a/src/plugins/macros/imacrohandler.h b/src/plugins/macros/imacrohandler.h
index e05e4c063c..b7c38a57ac 100644
--- a/src/plugins/macros/imacrohandler.h
+++ b/src/plugins/macros/imacrohandler.h
@@ -39,9 +39,6 @@ class IMacroHandler: public QObject
Q_OBJECT
public:
- IMacroHandler();
- ~IMacroHandler();
-
virtual void startRecording(Macro* macro);
virtual void endRecordingMacro(Macro* macro);
@@ -58,8 +55,7 @@ protected:
private:
friend class MacroManager;
- class IMacroHandlerPrivate;
- IMacroHandlerPrivate *d;
+ Macro *m_currentMacro = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/macros/macroevent.h b/src/plugins/macros/macroevent.h
index 72ae9942d4..9cf82ac28f 100644
--- a/src/plugins/macros/macroevent.h
+++ b/src/plugins/macros/macroevent.h
@@ -31,7 +31,6 @@
#include <QVariant>
QT_BEGIN_NAMESPACE
-class QByteArray;
class QDataStream;
QT_END_NAMESPACE
diff --git a/src/plugins/macros/macrolocatorfilter.h b/src/plugins/macros/macrolocatorfilter.h
index f8dc657753..d16553db3a 100644
--- a/src/plugins/macros/macrolocatorfilter.h
+++ b/src/plugins/macros/macrolocatorfilter.h
@@ -31,7 +31,6 @@
namespace Macros {
-class MacroManager;
namespace Internal {
diff --git a/src/plugins/macros/macromanager.cpp b/src/plugins/macros/macromanager.cpp
index 81fe1c4d41..8b6e5b0117 100644
--- a/src/plugins/macros/macromanager.cpp
+++ b/src/plugins/macros/macromanager.cpp
@@ -96,8 +96,8 @@ public:
MacroManager *q;
QMap<QString, Macro *> macros;
QMap<QString, QAction *> actions;
- Macro *currentMacro;
- bool isRecording;
+ Macro *currentMacro = nullptr;
+ bool isRecording = false;
QList<IMacroHandler*> handlers;
@@ -115,9 +115,7 @@ public:
};
MacroManager::MacroManagerPrivate::MacroManagerPrivate(MacroManager *qq):
- q(qq),
- currentMacro(0),
- isRecording(false)
+ q(qq)
{
// Load existing macros
initialize();
@@ -179,7 +177,7 @@ void MacroManager::MacroManagerPrivate::removeMacro(const QString &name)
// Remove macro from the map
Macro *macro = macros.take(name);
if (macro == currentMacro)
- currentMacro = 0;
+ currentMacro = nullptr;
delete macro;
}
@@ -243,7 +241,7 @@ void MacroManager::MacroManagerPrivate::showSaveDialog()
// ---------- MacroManager ------------
-MacroManager *MacroManager::m_instance = 0;
+MacroManager *MacroManager::m_instance = nullptr;
MacroManager::MacroManager(QObject *parent) :
QObject(parent),
diff --git a/src/plugins/macros/macromanager.h b/src/plugins/macros/macromanager.h
index 9fb6cb18ad..18779b7df3 100644
--- a/src/plugins/macros/macromanager.h
+++ b/src/plugins/macros/macromanager.h
@@ -28,10 +28,6 @@
#include <QObject>
#include <QMap>
-QT_BEGIN_NAMESPACE
-class QAction;
-QT_END_NAMESPACE
-
namespace Macros {
namespace Internal {
diff --git a/src/plugins/macros/macrooptionswidget.h b/src/plugins/macros/macrooptionswidget.h
index 95a7e07fd0..2e570c2a08 100644
--- a/src/plugins/macros/macrooptionswidget.h
+++ b/src/plugins/macros/macrooptionswidget.h
@@ -38,7 +38,6 @@ QT_END_NAMESPACE
namespace Macros {
namespace Internal {
-class MacroSettings;
namespace Ui { class MacroOptionsWidget; }
diff --git a/src/plugins/macros/macrosplugin.cpp b/src/plugins/macros/macrosplugin.cpp
index 7230bf29c9..38be1c5f8d 100644
--- a/src/plugins/macros/macrosplugin.cpp
+++ b/src/plugins/macros/macrosplugin.cpp
@@ -48,10 +48,6 @@
using namespace Macros::Internal;
-MacrosPlugin::MacrosPlugin() : m_macroManager(0)
-{
-}
-
MacrosPlugin::~MacrosPlugin()
{
delete m_macroManager;
diff --git a/src/plugins/macros/macrosplugin.h b/src/plugins/macros/macrosplugin.h
index dcb14694b8..2b1263c824 100644
--- a/src/plugins/macros/macrosplugin.h
+++ b/src/plugins/macros/macrosplugin.h
@@ -38,14 +38,13 @@ class MacrosPlugin : public ExtensionSystem::IPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Macros.json")
public:
- MacrosPlugin();
~MacrosPlugin();
bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized();
private:
- MacroManager *m_macroManager;
+ MacroManager *m_macroManager = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/macros/texteditormacrohandler.cpp b/src/plugins/macros/texteditormacrohandler.cpp
index 6626f103f4..0dc766d9ed 100644
--- a/src/plugins/macros/texteditormacrohandler.cpp
+++ b/src/plugins/macros/texteditormacrohandler.cpp
@@ -53,8 +53,7 @@ static quint8 AUTOREP = 4;
static quint8 COUNT = 5;
-TextEditorMacroHandler::TextEditorMacroHandler():
- IMacroHandler()
+TextEditorMacroHandler::TextEditorMacroHandler()
{
Core::EditorManager *editorManager = Core::EditorManager::instance();
connect(editorManager, &Core::EditorManager::currentEditorChanged,
@@ -140,5 +139,5 @@ void TextEditorMacroHandler::closeEditor(Core::IEditor *editor)
Q_UNUSED(editor);
if (isRecording() && m_currentEditor && m_currentEditor->widget())
m_currentEditor->widget()->removeEventFilter(this);
- m_currentEditor = 0;
+ m_currentEditor = nullptr;
}
diff --git a/src/plugins/macros/texteditormacrohandler.h b/src/plugins/macros/texteditormacrohandler.h
index 1c4cda35ac..251986a3e2 100644
--- a/src/plugins/macros/texteditormacrohandler.h
+++ b/src/plugins/macros/texteditormacrohandler.h
@@ -53,7 +53,7 @@ public:
void closeEditor(Core::IEditor *editor);
private:
- TextEditor::BaseTextEditor *m_currentEditor;
+ TextEditor::BaseTextEditor *m_currentEditor = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h
index e3763439a3..8f23e0d76e 100644
--- a/src/plugins/mercurial/mercurialclient.h
+++ b/src/plugins/mercurial/mercurialclient.h
@@ -30,7 +30,6 @@
namespace Mercurial {
namespace Internal {
-class MercurialDiffParameters;
class MercurialClient : public VcsBase::VcsBaseClient
{
diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp
index 8254f91d67..5c12b42c51 100644
--- a/src/plugins/mercurial/mercurialplugin.cpp
+++ b/src/plugins/mercurial/mercurialplugin.cpp
@@ -37,12 +37,12 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/documentmanager.h>
#include <coreplugin/id.h>
#include <coreplugin/vcsmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
-#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/locator/commandlocator.h>
@@ -122,12 +122,11 @@ bool MercurialPlugin::initialize(const QStringList & /* arguments */, QString *
Core::Context context(Constants::MERCURIAL_CONTEXT);
m_client = new MercurialClient;
- initializeVcs(new MercurialControl(m_client), context);
+ auto vc = initializeVcs<MercurialControl>(context, m_client);
- addAutoReleasedObject(new OptionsPage(versionControl()));
+ addAutoReleasedObject(new OptionsPage(vc));
- connect(m_client, &VcsBaseClient::changed,
- static_cast<MercurialControl *>(versionControl()), &MercurialControl::changed);
+ connect(m_client, &VcsBaseClient::changed, vc, &MercurialControl::changed);
connect(m_client, &MercurialClient::needUpdate, this, &MercurialPlugin::update);
const auto describeFunc = [this](const QString &source, const QString &id) {
@@ -495,6 +494,9 @@ void MercurialPlugin::createSubmitEditorActions()
void MercurialPlugin::commit()
{
+ if (!promptBeforeCommit())
+ return;
+
if (raiseSubmitEditor())
return;
diff --git a/src/plugins/mercurial/mercurialplugin.h b/src/plugins/mercurial/mercurialplugin.h
index 231f03effc..890238b375 100644
--- a/src/plugins/mercurial/mercurialplugin.h
+++ b/src/plugins/mercurial/mercurialplugin.h
@@ -37,11 +37,7 @@ QT_END_NAMESPACE
namespace Core {
class ActionContainer;
-class ActionManager;
class CommandLocator;
-class ICore;
-class Id;
-class IEditor;
} // namespace Core
namespace Utils { class ParameterAction; }
@@ -52,9 +48,6 @@ namespace Internal {
class OptionsPage;
class MercurialClient;
-class MercurialControl;
-class MercurialEditorWidget;
-class MercurialSettings;
class MercurialPlugin : public VcsBase::VcsBasePlugin
{
diff --git a/src/plugins/modeleditor/actionhandler.cpp b/src/plugins/modeleditor/actionhandler.cpp
index 2bb98d85b8..016a0ad027 100644
--- a/src/plugins/modeleditor/actionhandler.cpp
+++ b/src/plugins/modeleditor/actionhandler.cpp
@@ -46,20 +46,20 @@ namespace Internal {
class ActionHandler::ActionHandlerPrivate {
public:
Core::Context context;
- QAction *undoAction = 0;
- QAction *redoAction = 0;
- QAction *cutAction = 0;
- QAction *copyAction = 0;
- QAction *pasteAction = 0;
- QAction *removeAction = 0;
- QAction *deleteAction = 0;
- QAction *selectAllAction = 0;
- QAction *openParentDiagramAction = 0;
- QAction *synchronizeBrowserAction = 0;
- QAction *exportDiagramAction = 0;
- QAction *zoomInAction = 0;
- QAction *zoomOutAction = 0;
- QAction *resetZoomAction = 0;
+ QAction *undoAction = nullptr;
+ QAction *redoAction = nullptr;
+ QAction *cutAction = nullptr;
+ QAction *copyAction = nullptr;
+ QAction *pasteAction = nullptr;
+ QAction *removeAction = nullptr;
+ QAction *deleteAction = nullptr;
+ QAction *selectAllAction = nullptr;
+ QAction *openParentDiagramAction = nullptr;
+ QAction *synchronizeBrowserAction = nullptr;
+ QAction *exportDiagramAction = nullptr;
+ QAction *zoomInAction = nullptr;
+ QAction *zoomOutAction = nullptr;
+ QAction *resetZoomAction = nullptr;
};
ActionHandler::ActionHandler(const Core::Context &context, QObject *parent)
@@ -160,7 +160,7 @@ void ActionHandler::createActions()
d->removeAction = removeCommand->action();
Core::Command *deleteCommand = registerCommand(
Constants::DELETE_SELECTED_ELEMENTS, [this]() { deleteSelectedElements(); }, d->context, true,
- tr("&Delete"), QKeySequence(QStringLiteral("Ctrl+D")));
+ tr("&Delete"), QKeySequence("Ctrl+D"));
medit->addAction(deleteCommand, Core::Constants::G_EDIT_COPYPASTE);
d->deleteAction = deleteCommand->action();
d->selectAllAction = registerCommand(Core::Constants::SELECTALL, [this]() { selectAll(); }, d->context)->action();
@@ -180,26 +180,26 @@ void ActionHandler::createActions()
Core::Command *zoomInCommand = registerCommand(
Constants::ZOOM_IN, [this]() { zoomIn(); }, d->context, true,
- tr("Zoom In"), QKeySequence(QStringLiteral("Ctrl++")));
+ tr("Zoom In"), QKeySequence("Ctrl++"));
menuModelEditor->addAction(zoomInCommand);
d->zoomInAction = zoomInCommand->action();
Core::Command *zoomOutCommand = registerCommand(
Constants::ZOOM_OUT, [this]() { zoomOut(); }, d->context, true,
- tr("Zoom Out"), QKeySequence(QStringLiteral("Ctrl+-")));
+ tr("Zoom Out"), QKeySequence("Ctrl+-"));
menuModelEditor->addAction(zoomOutCommand);
d->zoomOutAction = zoomOutCommand->action();
Core::Command *resetZoomCommand = registerCommand(
Constants::RESET_ZOOM, [this]() { resetZoom(); }, d->context, true,
- tr("Reset Zoom"), QKeySequence(QStringLiteral("Ctrl+0")));
+ tr("Reset Zoom"), QKeySequence("Ctrl+0"));
menuModelEditor->addAction(resetZoomCommand);
d->zoomOutAction = resetZoomCommand->action();
d->openParentDiagramAction = registerCommand(
Constants::OPEN_PARENT_DIAGRAM, [this]() { openParentDiagram(); }, Core::Context(), true,
- tr("Open Parent Diagram"), QKeySequence(QStringLiteral("Ctrl+Shift+P")))->action();
- d->openParentDiagramAction->setIcon(QIcon(QStringLiteral(":/modeleditor/up.png")));
+ tr("Open Parent Diagram"), QKeySequence("Ctrl+Shift+P"))->action();
+ d->openParentDiagramAction->setIcon(QIcon(":/modeleditor/up.png"));
registerCommand(Constants::ACTION_ADD_PACKAGE, nullptr, Core::Context(), true, tr("Add Package"));
registerCommand(Constants::ACTION_ADD_COMPONENT, nullptr, Core::Context(), true, tr("Add Component"));
registerCommand(Constants::ACTION_ADD_CLASS, nullptr, Core::Context(), true, tr("Add Class"));
diff --git a/src/plugins/modeleditor/actionhandler.h b/src/plugins/modeleditor/actionhandler.h
index af2793d3fe..e2ad8f7e02 100644
--- a/src/plugins/modeleditor/actionhandler.h
+++ b/src/plugins/modeleditor/actionhandler.h
@@ -50,7 +50,7 @@ class ActionHandler :
class ActionHandlerPrivate;
public:
- ActionHandler(const Core::Context &context, QObject *parent = 0);
+ ActionHandler(const Core::Context &context, QObject *parent = nullptr);
~ActionHandler();
public:
diff --git a/src/plugins/modeleditor/classviewcontroller.cpp b/src/plugins/modeleditor/classviewcontroller.cpp
index 059c800a92..32cd3d1ac2 100644
--- a/src/plugins/modeleditor/classviewcontroller.cpp
+++ b/src/plugins/modeleditor/classviewcontroller.cpp
@@ -78,7 +78,7 @@ void ClassViewController::appendClassDeclarationsFromSymbol(CPlusPlus::Symbol *s
QString className = overview.prettyName(
CPlusPlus::LookupContext::fullyQualifiedName(symbol));
// Ignore private class created by Q_OBJECT macro
- if (!className.endsWith(QStringLiteral("::QPrivateSignal")))
+ if (!className.endsWith("::QPrivateSignal"))
classNames->insert(className);
}
diff --git a/src/plugins/modeleditor/classviewcontroller.h b/src/plugins/modeleditor/classviewcontroller.h
index 4bf67d480e..f953420452 100644
--- a/src/plugins/modeleditor/classviewcontroller.h
+++ b/src/plugins/modeleditor/classviewcontroller.h
@@ -38,7 +38,7 @@ class ClassViewController :
Q_OBJECT
public:
- explicit ClassViewController(QObject *parent = 0);
+ explicit ClassViewController(QObject *parent = nullptr);
~ClassViewController() = default;
QSet<QString> findClassDeclarations(const QString &fileName);
diff --git a/src/plugins/modeleditor/componentviewcontroller.cpp b/src/plugins/modeleditor/componentviewcontroller.cpp
index c90aaa49b2..b9fadc2bd1 100644
--- a/src/plugins/modeleditor/componentviewcontroller.cpp
+++ b/src/plugins/modeleditor/componentviewcontroller.cpp
@@ -64,7 +64,7 @@ private:
QString m_elementName;
QStringList m_elementsPath;
int m_maxPathLength = 0;
- qmt::MComponent *m_bestComponent = 0;
+ qmt::MComponent *m_bestComponent = nullptr;
};
void FindComponentFromFilePath::setFilePath(const QString &filePath)
@@ -131,7 +131,7 @@ private:
bool haveDependency(const qmt::MObject *source, const QList<qmt::MPackage *> &targets);
private:
- qmt::ModelController *m_modelController = 0;
+ qmt::ModelController *m_modelController = nullptr;
QMultiHash<QString, Node> m_filePaths;
};
@@ -167,7 +167,7 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
if (!haveDependency(component, includeComponent)) {
auto dependency = new qmt::MDependency;
dependency->setFlags(qmt::MElement::ReverseEngineered);
- dependency->setStereotypes(QStringList() << QStringLiteral("include"));
+ dependency->setStereotypes(QStringList() << "include");
dependency->setDirection(qmt::MDependency::AToB);
dependency->setSource(component->uid());
dependency->setTarget(includeComponent->uid());
@@ -190,7 +190,7 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
int componentHighestAncestorIndex = componentAncestors.size() - 1;
int includeComponentHighestAncestorIndex = includeComponentAncestors.size() - 1;
- QTC_ASSERT(componentAncestors.at(componentHighestAncestorIndex) == includeComponentAncestors.at(includeComponentHighestAncestorIndex), return);
+ QMT_ASSERT(componentAncestors.at(componentHighestAncestorIndex) == includeComponentAncestors.at(includeComponentHighestAncestorIndex), return);
while (componentHighestAncestorIndex > 0 && includeComponentHighestAncestorIndex > 0) {
if (componentAncestors.at(componentHighestAncestorIndex) != includeComponentAncestors.at(includeComponentHighestAncestorIndex))
break;
@@ -211,7 +211,7 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
auto dependency = new qmt::MDependency;
dependency->setFlags(qmt::MElement::ReverseEngineered);
// TODO set stereotype for testing purpose
- dependency->setStereotypes(QStringList() << QStringLiteral("same stereotype"));
+ dependency->setStereotypes(QStringList() << "same stereotype");
dependency->setDirection(qmt::MDependency::AToB);
dependency->setSource(componentAncestors.at(index1)->uid());
dependency->setTarget(includeComponentAncestors.at(index2)->uid());
@@ -232,7 +232,7 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
auto dependency = new qmt::MDependency;
dependency->setFlags(qmt::MElement::ReverseEngineered);
// TODO set stereotype for testing purpose
- dependency->setStereotypes(QStringList() << QStringLiteral("ancestor"));
+ dependency->setStereotypes(QStringList() << "ancestor");
dependency->setDirection(qmt::MDependency::AToB);
dependency->setSource(componentAncestors.at(componentHighestAncestorIndex)->uid());
dependency->setTarget(includeComponentAncestors.at(includeComponentHighestAncestorIndex)->uid());
@@ -247,7 +247,7 @@ void UpdateIncludeDependenciesVisitor::visitMComponent(qmt::MComponent *componen
auto dependency = new qmt::MDependency;
dependency->setFlags(qmt::MElement::ReverseEngineered);
// TODO set stereotype for testing purpose
- dependency->setStereotypes(QStringList() << QStringLiteral("parents"));
+ dependency->setStereotypes(QStringList() << "parents");
dependency->setDirection(qmt::MDependency::AToB);
dependency->setSource(componentAncestors.at(0)->uid());
dependency->setTarget(includeComponentAncestors.at(0)->uid());
@@ -360,8 +360,8 @@ bool UpdateIncludeDependenciesVisitor::haveDependency(const qmt::MObject *source
class ComponentViewController::ComponentViewControllerPrivate {
public:
- PxNodeUtilities *pxnodeUtilities = 0;
- qmt::DiagramSceneController *diagramSceneController = 0;
+ PxNodeUtilities *pxnodeUtilities = nullptr;
+ qmt::DiagramSceneController *diagramSceneController = nullptr;
};
ComponentViewController::ComponentViewController(QObject *parent)
@@ -408,7 +408,7 @@ void ComponentViewController::doCreateComponentModel(const ProjectExplorer::Fold
{
foreach (const ProjectExplorer::FileNode *fileNode, folderNode->fileNodes()) {
QString componentName = qmt::NameController::convertFileNameToElementName(fileNode->filePath().toString());
- qmt::MComponent *component = 0;
+ qmt::MComponent *component = nullptr;
bool isSource = false;
CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(fileNode->filePath().toString());
switch (kind) {
@@ -441,7 +441,7 @@ void ComponentViewController::doCreateComponentModel(const ProjectExplorer::Fold
if (d->pxnodeUtilities->findSameObject(relativeElements, component)) {
delete component;
} else {
- qmt::MPackage *requestedRootPackage = d->diagramSceneController->findSuitableParentPackage(0, diagram);
+ qmt::MPackage *requestedRootPackage = d->diagramSceneController->findSuitableParentPackage(nullptr, diagram);
qmt::MPackage *bestParentPackage = d->pxnodeUtilities->createBestMatchingPackagePath(requestedRootPackage, relativeElements);
d->diagramSceneController->modelController()->addObject(bestParentPackage, component);
}
diff --git a/src/plugins/modeleditor/componentviewcontroller.h b/src/plugins/modeleditor/componentviewcontroller.h
index 321805ab40..a0a70b73b8 100644
--- a/src/plugins/modeleditor/componentviewcontroller.h
+++ b/src/plugins/modeleditor/componentviewcontroller.h
@@ -47,7 +47,7 @@ class ComponentViewController :
class ComponentViewControllerPrivate;
public:
- explicit ComponentViewController(QObject *parent = 0);
+ explicit ComponentViewController(QObject *parent = nullptr);
~ComponentViewController();
void setPxNodeUtilties(PxNodeUtilities *pxnodeUtilities);
diff --git a/src/plugins/modeleditor/diagramsviewmanager.h b/src/plugins/modeleditor/diagramsviewmanager.h
index 0811d6cd70..62ecff23cc 100644
--- a/src/plugins/modeleditor/diagramsviewmanager.h
+++ b/src/plugins/modeleditor/diagramsviewmanager.h
@@ -46,7 +46,7 @@ class DiagramsViewManager :
Q_OBJECT
public:
- explicit DiagramsViewManager(QObject *parent = 0);
+ explicit DiagramsViewManager(QObject *parent = nullptr);
~DiagramsViewManager() = default;
signals:
diff --git a/src/plugins/modeleditor/dragtool.h b/src/plugins/modeleditor/dragtool.h
index 5764f97ec6..844b8189c2 100644
--- a/src/plugins/modeleditor/dragtool.h
+++ b/src/plugins/modeleditor/dragtool.h
@@ -39,7 +39,7 @@ class DragTool :
public:
DragTool(const QIcon &icon, const QString &title, const QString &newElementId,
- const QString &stereotype, QWidget *parent = 0);
+ const QString &stereotype, QWidget *parent = nullptr);
~DragTool();
QSize sizeHint() const override;
diff --git a/src/plugins/modeleditor/editordiagramview.cpp b/src/plugins/modeleditor/editordiagramview.cpp
index 09621c2335..5e2fe5b65e 100644
--- a/src/plugins/modeleditor/editordiagramview.cpp
+++ b/src/plugins/modeleditor/editordiagramview.cpp
@@ -40,7 +40,7 @@ namespace Internal {
class EditorDiagramView::EditorDiagramViewPrivate {
public:
- PxNodeController *pxNodeController = 0;
+ PxNodeController *pxNodeController = nullptr;
};
EditorDiagramView::EditorDiagramView(QWidget *parent)
@@ -49,7 +49,7 @@ EditorDiagramView::EditorDiagramView(QWidget *parent)
{
auto droputils = new Utils::DropSupport(
this,
- [this](QDropEvent *event, Utils::DropSupport *dropSupport)
+ [](QDropEvent *event, Utils::DropSupport *dropSupport)
-> bool { return dropSupport->isValueDrop(event); });
connect(droputils, &Utils::DropSupport::valuesDropped,
this, &EditorDiagramView::dropProjectExplorerNodes);
diff --git a/src/plugins/modeleditor/editordiagramview.h b/src/plugins/modeleditor/editordiagramview.h
index 0a90af0161..984445d68f 100644
--- a/src/plugins/modeleditor/editordiagramview.h
+++ b/src/plugins/modeleditor/editordiagramview.h
@@ -39,7 +39,7 @@ class EditorDiagramView :
class EditorDiagramViewPrivate;
public:
- explicit EditorDiagramView(QWidget *parent = 0);
+ explicit EditorDiagramView(QWidget *parent = nullptr);
~EditorDiagramView() override;
signals:
diff --git a/src/plugins/modeleditor/elementtasks.cpp b/src/plugins/modeleditor/elementtasks.cpp
index ed120c3523..3ace1bec41 100644
--- a/src/plugins/modeleditor/elementtasks.cpp
+++ b/src/plugins/modeleditor/elementtasks.cpp
@@ -59,8 +59,8 @@ namespace Internal {
class ElementTasks::ElementTasksPrivate {
public:
- qmt::DocumentController *documentController = 0;
- ComponentViewController *componentViewController = 0;
+ qmt::DocumentController *documentController = nullptr;
+ ComponentViewController *componentViewController = nullptr;
};
ElementTasks::ElementTasks(QObject *parent)
@@ -106,7 +106,7 @@ bool ElementTasks::hasClassDefinition(const qmt::MElement *element) const
if (auto klass = dynamic_cast<const qmt::MClass *>(element)) {
QString qualifiedClassName = klass->umlNamespace().isEmpty()
? klass->name()
- : klass->umlNamespace() + QStringLiteral("::") + klass->name();
+ : klass->umlNamespace() + "::" + klass->name();
CppTools::CppClassesFilter *classesFilter = ExtensionSystem::PluginManager::getObject<CppTools::CppClassesFilter>();
if (!classesFilter)
@@ -142,7 +142,7 @@ void ElementTasks::openClassDefinition(const qmt::MElement *element)
if (auto klass = dynamic_cast<const qmt::MClass *>(element)) {
QString qualifiedClassName = klass->umlNamespace().isEmpty()
? klass->name()
- : klass->umlNamespace() + QStringLiteral("::") + klass->name();
+ : klass->umlNamespace() + "::" + klass->name();
CppTools::CppClassesFilter *classesFilter = ExtensionSystem::PluginManager::getObject<CppTools::CppClassesFilter>();
if (!classesFilter)
@@ -274,7 +274,7 @@ bool ElementTasks::hasDiagram(const qmt::MElement *element) const
qmt::FindDiagramVisitor visitor;
element->accept(&visitor);
const qmt::MDiagram *diagram = visitor.diagram();
- return diagram != 0;
+ return diagram != nullptr;
}
bool ElementTasks::hasDiagram(const qmt::DElement *element, const qmt::MDiagram *diagram) const
@@ -373,7 +373,7 @@ void ElementTasks::openParentDiagram(const qmt::DElement *element, const qmt::ME
bool ElementTasks::mayCreateDiagram(const qmt::MElement *element) const
{
- return dynamic_cast<const qmt::MPackage *>(element) != 0;
+ return dynamic_cast<const qmt::MPackage *>(element) != nullptr;
}
bool ElementTasks::mayCreateDiagram(const qmt::DElement *element,
@@ -401,7 +401,7 @@ void ElementTasks::createAndOpenDiagram(const qmt::MElement *element)
auto newDiagram = new qmt::MCanvasDiagram();
newDiagram->setName(package->name());
qmt::MPackage *parentPackage = d->documentController->modelController()->findObject<qmt::MPackage>(package->uid());
- QTC_ASSERT(parentPackage, delete newDiagram; return);
+ QMT_ASSERT(parentPackage, delete newDiagram; return);
d->documentController->modelController()->addObject(parentPackage, newDiagram);
ModelEditorPlugin::modelsManager()->openDiagram(
d->documentController->projectController()->project()->uid(),
@@ -424,7 +424,7 @@ bool ElementTasks::extendContextMenu(const qmt::DElement *delement, const qmt::M
{
bool extended = false;
if (dynamic_cast<const qmt::DPackage *>(delement)) {
- menu->addAction(new qmt::ContextMenuAction(tr("Update Include Dependencies"), QStringLiteral("updateIncludeDependencies"), menu));
+ menu->addAction(new qmt::ContextMenuAction(tr("Update Include Dependencies"), "updateIncludeDependencies", menu));
extended = true;
}
return extended;
diff --git a/src/plugins/modeleditor/elementtasks.h b/src/plugins/modeleditor/elementtasks.h
index fa2fc53cdc..458c31e54b 100644
--- a/src/plugins/modeleditor/elementtasks.h
+++ b/src/plugins/modeleditor/elementtasks.h
@@ -43,7 +43,7 @@ class ElementTasks :
class ElementTasksPrivate;
public:
- ElementTasks(QObject *parent = 0);
+ ElementTasks(QObject *parent = nullptr);
~ElementTasks();
void setDocumentController(qmt::DocumentController *documentController);
diff --git a/src/plugins/modeleditor/extdocumentcontroller.cpp b/src/plugins/modeleditor/extdocumentcontroller.cpp
index 72e960461b..e9c125215d 100644
--- a/src/plugins/modeleditor/extdocumentcontroller.cpp
+++ b/src/plugins/modeleditor/extdocumentcontroller.cpp
@@ -38,8 +38,8 @@ namespace Internal {
class ExtDocumentController::ExtDocumentControllerPrivate {
public:
- ElementTasks *elementTasks = 0;
- PxNodeController *pxNodeController = 0;
+ ElementTasks *elementTasks = nullptr;
+ PxNodeController *pxNodeController = nullptr;
};
ExtDocumentController::ExtDocumentController(QObject *parent)
diff --git a/src/plugins/modeleditor/extdocumentcontroller.h b/src/plugins/modeleditor/extdocumentcontroller.h
index 667403b82e..44a3fc716a 100644
--- a/src/plugins/modeleditor/extdocumentcontroller.h
+++ b/src/plugins/modeleditor/extdocumentcontroller.h
@@ -40,7 +40,7 @@ class ExtDocumentController :
class ExtDocumentControllerPrivate;
public:
- explicit ExtDocumentController(QObject *parent = 0);
+ explicit ExtDocumentController(QObject *parent = nullptr);
~ExtDocumentController();
ElementTasks *elementTasks() const;
diff --git a/src/plugins/modeleditor/extpropertiesmview.cpp b/src/plugins/modeleditor/extpropertiesmview.cpp
index 529f251dca..a0c19b7141 100644
--- a/src/plugins/modeleditor/extpropertiesmview.cpp
+++ b/src/plugins/modeleditor/extpropertiesmview.cpp
@@ -57,7 +57,7 @@ void ExtPropertiesMView::visitMPackage(const qmt::MPackage *package)
qmt::PropertiesView::MView::visitMPackage(package);
if (m_modelElements.size() == 1 && !package->owner()) {
qmt::Project *project = m_projectController->project();
- if (m_configPath == 0) {
+ if (!m_configPath) {
m_configPath = new Utils::PathChooser(m_topWidget);
m_configPath->setPromptDialogTitle(tr("Select Custom Configuration Folder"));
m_configPath->setExpectedKind(Utils::PathChooser::ExistingDirectory);
@@ -78,7 +78,7 @@ void ExtPropertiesMView::visitMPackage(const qmt::MPackage *package)
m_configPath->setPath(QFileInfo(projectDir, project->configPath()).canonicalFilePath());
}
}
- if (m_configPathInfo == 0) {
+ if (!m_configPathInfo) {
m_configPathInfo = new QLabel(m_topWidget);
addRow(QString(), m_configPathInfo, "configpathinfo");
}
diff --git a/src/plugins/modeleditor/extpropertiesmview.h b/src/plugins/modeleditor/extpropertiesmview.h
index 673fcd9d39..f9f2564ce2 100644
--- a/src/plugins/modeleditor/extpropertiesmview.h
+++ b/src/plugins/modeleditor/extpropertiesmview.h
@@ -49,9 +49,9 @@ private:
void onConfigPathChanged(const QString &path);
private:
- qmt::ProjectController *m_projectController = 0;
- Utils::PathChooser *m_configPath = 0;
- QLabel *m_configPathInfo = 0;
+ qmt::ProjectController *m_projectController = nullptr;
+ Utils::PathChooser *m_configPath = nullptr;
+ QLabel *m_configPathInfo = nullptr;
};
} // namespace Interal
diff --git a/src/plugins/modeleditor/jsextension.h b/src/plugins/modeleditor/jsextension.h
index be2479fd68..74c7cbc892 100644
--- a/src/plugins/modeleditor/jsextension.h
+++ b/src/plugins/modeleditor/jsextension.h
@@ -35,7 +35,7 @@ class JsExtension : public QObject
Q_OBJECT
public:
- JsExtension(QObject *parent = 0) : QObject(parent) { }
+ JsExtension(QObject *parent = nullptr) : QObject(parent) { }
Q_INVOKABLE QString fileNameToElementName(const QString &file);
Q_INVOKABLE QString elementNameToFileName(const QString &element);
diff --git a/src/plugins/modeleditor/modeldocument.cpp b/src/plugins/modeleditor/modeldocument.cpp
index e75ff0760e..eef5ce60dc 100644
--- a/src/plugins/modeleditor/modeldocument.cpp
+++ b/src/plugins/modeleditor/modeldocument.cpp
@@ -48,7 +48,7 @@ namespace Internal {
class ModelDocument::ModelDocumentPrivate {
public:
- ExtDocumentController *documentController = 0;
+ ExtDocumentController *documentController = nullptr;
};
ModelDocument::ModelDocument(QObject *parent)
diff --git a/src/plugins/modeleditor/modeldocument.h b/src/plugins/modeleditor/modeldocument.h
index f83085866a..5f7a99cd56 100644
--- a/src/plugins/modeleditor/modeldocument.h
+++ b/src/plugins/modeleditor/modeldocument.h
@@ -41,7 +41,7 @@ class ModelDocument :
class ModelDocumentPrivate;
public:
- explicit ModelDocument(QObject *parent = 0);
+ explicit ModelDocument(QObject *parent = nullptr);
~ModelDocument();
signals:
diff --git a/src/plugins/modeleditor/modeleditor.cpp b/src/plugins/modeleditor/modeleditor.cpp
index ea30818f5a..9602c72c15 100644
--- a/src/plugins/modeleditor/modeleditor.cpp
+++ b/src/plugins/modeleditor/modeleditor.cpp
@@ -107,30 +107,30 @@ static const double ZOOM_FACTOR = 1.05;
class ModelEditor::ModelEditorPrivate
{
public:
- UiController *uiController = 0;
- ActionHandler *actionHandler = 0;
- ModelDocument *document = 0;
- qmt::PropertiesView *propertiesView = 0;
- Core::MiniSplitter *rightSplitter = 0;
- QWidget *leftGroup = 0;
- QHBoxLayout *leftGroupLayout = 0;
- QToolBox *leftToolBox = 0;
- QStackedWidget *diagramStack = 0;
- EditorDiagramView *diagramView = 0;
- QLabel *noDiagramLabel = 0;
- DiagramsViewManager *diagramsViewManager = 0;
- Core::MiniSplitter *rightHorizSplitter = 0;
- qmt::ModelTreeView *modelTreeView = 0;
- qmt::TreeModelManager *modelTreeViewServant = 0;
- QScrollArea *propertiesScrollArea = 0;
- QWidget *propertiesGroupWidget = 0;
- QWidget *toolbar = 0;
- QComboBox *diagramSelector = 0;
+ UiController *uiController = nullptr;
+ ActionHandler *actionHandler = nullptr;
+ ModelDocument *document = nullptr;
+ qmt::PropertiesView *propertiesView = nullptr;
+ Core::MiniSplitter *rightSplitter = nullptr;
+ QWidget *leftGroup = nullptr;
+ QHBoxLayout *leftGroupLayout = nullptr;
+ QToolBox *leftToolBox = nullptr;
+ QStackedWidget *diagramStack = nullptr;
+ EditorDiagramView *diagramView = nullptr;
+ QLabel *noDiagramLabel = nullptr;
+ DiagramsViewManager *diagramsViewManager = nullptr;
+ Core::MiniSplitter *rightHorizSplitter = nullptr;
+ qmt::ModelTreeView *modelTreeView = nullptr;
+ qmt::TreeModelManager *modelTreeViewServant = nullptr;
+ QScrollArea *propertiesScrollArea = nullptr;
+ QWidget *propertiesGroupWidget = nullptr;
+ QWidget *toolbar = nullptr;
+ QComboBox *diagramSelector = nullptr;
SelectedArea selectedArea = SelectedArea::Nothing;
QString lastExportDirPath;
- QAction *syncBrowserWithDiagramAction = 0;
- QAction *syncDiagramWithBrowserAction = 0;
- QAction *syncEachOtherAction = 0;
+ QAction *syncBrowserWithDiagramAction = nullptr;
+ QAction *syncDiagramWithBrowserAction = nullptr;
+ QAction *syncEachOtherAction = nullptr;
};
ModelEditor::ModelEditor(UiController *uiController, ActionHandler *actionHandler, QWidget *parent)
@@ -217,7 +217,7 @@ void ModelEditor::init(QWidget *parent)
d->leftToolBox = new QToolBox(d->leftGroup);
// Windows style does not truncate the tab label to a very small width (GTK+ does)
- static QStyle *windowsStyle = QStyleFactory().create(QStringLiteral("Windows"));
+ static QStyle *windowsStyle = QStyleFactory().create("Windows");
if (windowsStyle)
d->leftToolBox->setStyle(windowsStyle);
// TODO improve this (and the diagram colors) for use with dark theme
@@ -321,19 +321,19 @@ void ModelEditor::init(QWidget *parent)
toolbarLayout->addWidget(
createToolbarCommandButton(Constants::ACTION_ADD_PACKAGE, [this]() { onAddPackage(); },
- QIcon(QStringLiteral(":/modelinglib/48x48/package.png")),
+ QIcon(":/modelinglib/48x48/package.png"),
tr("Add Package"), d->toolbar));
toolbarLayout->addWidget(
createToolbarCommandButton(Constants::ACTION_ADD_COMPONENT, [this]() { onAddComponent(); },
- QIcon(QStringLiteral(":/modelinglib/48x48/component.png")),
+ QIcon(":/modelinglib/48x48/component.png"),
tr("Add Component"), d->toolbar));
toolbarLayout->addWidget(
createToolbarCommandButton(Constants::ACTION_ADD_CLASS, [this]() { onAddClass(); },
- QIcon(QStringLiteral(":/modelinglib/48x48/class.png")),
+ QIcon(":/modelinglib/48x48/class.png"),
tr("Add Class"), d->toolbar));
toolbarLayout->addWidget(
createToolbarCommandButton(Constants::ACTION_ADD_CANVAS_DIAGRAM, [this]() { onAddCanvasDiagram(); },
- QIcon(QStringLiteral(":/modelinglib/48x48/canvas-diagram.png")),
+ QIcon(":/modelinglib/48x48/canvas-diagram.png"),
tr("Add Canvas Diagram"), d->toolbar));
toolbarLayout->addSpacing(20);
@@ -341,13 +341,13 @@ void ModelEditor::init(QWidget *parent)
syncToggleButton->setDefaultAction(d->actionHandler->synchronizeBrowserAction());
QMenu *syncMenu = new QMenu(syncToggleButton);
QActionGroup *syncGroup = new QActionGroup(syncMenu);
- d->syncBrowserWithDiagramAction = syncMenu->addAction(QStringLiteral("Synchronize Structure with Diagram"));
+ d->syncBrowserWithDiagramAction = syncMenu->addAction(tr("Synchronize Structure with Diagram"));
d->syncBrowserWithDiagramAction->setCheckable(true);
d->syncBrowserWithDiagramAction->setActionGroup(syncGroup);
- d->syncDiagramWithBrowserAction = syncMenu->addAction(QStringLiteral("Synchronize Diagram with Structure"));
+ d->syncDiagramWithBrowserAction = syncMenu->addAction(tr("Synchronize Diagram with Structure"));
d->syncDiagramWithBrowserAction->setCheckable(true);
d->syncDiagramWithBrowserAction->setActionGroup(syncGroup);
- d->syncEachOtherAction = syncMenu->addAction(QStringLiteral("Keep Synchronized"));
+ d->syncEachOtherAction = syncMenu->addAction(tr("Keep Synchronized"));
d->syncEachOtherAction->setCheckable(true);
d->syncEachOtherAction->setActionGroup(syncGroup);
syncToggleButton->setMenu(syncMenu);
@@ -363,7 +363,7 @@ void ModelEditor::initDocument()
d->diagramView->setPxNodeController(documentController->pxNodeController());
- QTC_CHECK(!d->diagramsViewManager);
+ QMT_CHECK(!d->diagramsViewManager);
d->diagramsViewManager = new DiagramsViewManager(this);
//connect(diagramsViewManager, &DiagramsViewManager::someDiagramOpened,
// documentController->diagramsManager(), &qmt::DiagramsManager::someDiagramOpened);
@@ -578,13 +578,13 @@ void ModelEditor::exportDiagram()
QString suffix = QFileInfo(fileName).suffix().toLower();
// TODO use QFileDialog::selectedNameFilter() as fallback if no suffix is given
if (suffix.isEmpty()) {
- suffix = QStringLiteral("png");
- fileName += QStringLiteral(".png");
+ suffix = "png";
+ fileName += ".png";
}
- if (suffix == QStringLiteral("pdf"))
+ if (suffix == "pdf")
success = sceneModel->exportPdf(fileName);
#ifndef QT_NO_SVG
- else if (suffix == QStringLiteral("svg"))
+ else if (suffix == "svg")
success = sceneModel->exportSvg(fileName);
#endif // QT_NO_SVG
else
@@ -622,7 +622,7 @@ void ModelEditor::resetZoom()
qmt::MPackage *ModelEditor::guessSelectedPackage() const
{
- qmt::MPackage *package = 0;
+ qmt::MPackage *package = nullptr;
switch (d->selectedArea) {
case SelectedArea::Nothing:
package = d->modelTreeViewServant->selectedPackage();
@@ -661,13 +661,13 @@ void ModelEditor::updateSelectedArea(SelectedArea selectedArea)
bool canExportDiagram = false;
QList<qmt::MElement *> propertiesModelElements;
QList<qmt::DElement *> propertiesDiagramElements;
- qmt::MDiagram *propertiesDiagram = 0;
+ qmt::MDiagram *propertiesDiagram = nullptr;
qmt::MDiagram *activeDiagram = currentDiagram();
switch (d->selectedArea) {
case SelectedArea::Nothing:
canSelectAll = activeDiagram && !activeDiagram->diagramElements().isEmpty();
- canExportDiagram = activeDiagram != 0;
+ canExportDiagram = activeDiagram != nullptr;
break;
case SelectedArea::Diagram:
{
@@ -696,7 +696,7 @@ void ModelEditor::updateSelectedArea(SelectedArea selectedArea)
}
case SelectedArea::TreeView:
{
- canExportDiagram = activeDiagram != 0;
+ canExportDiagram = activeDiagram != nullptr;
bool hasSelection = !d->modelTreeViewServant->selectedObjects().isEmpty();
bool hasSingleSelection = d->modelTreeViewServant->selectedObjects().indices().size() == 1;
canCutCopyDelete = hasSelection && !d->modelTreeViewServant->isRootPackageSelected();
@@ -767,9 +767,9 @@ void ModelEditor::clearProperties()
if (d->propertiesGroupWidget) {
QWidget *scrollWidget = d->propertiesScrollArea->takeWidget();
Q_UNUSED(scrollWidget); // avoid warning in release mode
- QTC_CHECK(scrollWidget == d->propertiesGroupWidget);
+ QMT_CHECK(scrollWidget == d->propertiesGroupWidget);
d->propertiesGroupWidget->deleteLater();
- d->propertiesGroupWidget = 0;
+ d->propertiesGroupWidget = nullptr;
}
}
@@ -801,8 +801,8 @@ QToolButton *ModelEditor::createToolbarCommandButton(const Core::Id &id, const s
bool ModelEditor::updateButtonIconByTheme(QAbstractButton *button, const QString &name)
{
- QTC_ASSERT(button, return false);
- QTC_ASSERT(!name.isEmpty(), return false);
+ QMT_ASSERT(button, return false);
+ QMT_ASSERT(!name.isEmpty(), return false);
if (QIcon::hasThemeIcon(name)) {
button->setIcon(QIcon::fromTheme(name));
@@ -1003,7 +1003,7 @@ void ModelEditor::initToolbars()
[=](const qmt::Toolbar &lhs, const qmt::Toolbar &rhs) { return lhs.priority() > rhs.priority(); });
foreach (const qmt::Toolbar &toolbar, toolbars) {
QWidget *toolBar = toolBars.value(toolbar.id());
- QLayout *toolBarLayout = 0;
+ QLayout *toolBarLayout = nullptr;
if (!toolBar) {
toolBar = new QWidget(d->leftToolBox);
toolBar->setProperty(PROPERTYNAME_TOOLBARID, toolbar.id());
@@ -1015,7 +1015,7 @@ void ModelEditor::initToolbars()
toolBars.insert(toolbar.id(), toolBar);
} else {
toolBarLayout = toolBar->layout();
- QTC_ASSERT(toolBarLayout, continue);
+ QMT_ASSERT(toolBarLayout, continue);
}
foreach (const qmt::Toolbar::Tool &tool, toolbar.tools()) {
switch (tool.m_toolType) {
@@ -1025,27 +1025,30 @@ void ModelEditor::initToolbars()
qmt::StereotypeIcon::Element stereotypeIconElement = qmt::StereotypeIcon::ElementAny;
qmt::StyleEngine::ElementType styleEngineElementType = qmt::StyleEngine::TypeOther;
if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_PACKAGE)) {
- iconPath = QStringLiteral(":/modelinglib/48x48/package.png");
+ iconPath = ":/modelinglib/48x48/package.png";
stereotypeIconElement = qmt::StereotypeIcon::ElementPackage;
styleEngineElementType = qmt::StyleEngine::TypePackage;
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_COMPONENT)) {
- iconPath = QStringLiteral(":/modelinglib/48x48/component.png");
+ iconPath = ":/modelinglib/48x48/component.png";
stereotypeIconElement = qmt::StereotypeIcon::ElementComponent;
styleEngineElementType = qmt::StyleEngine::TypeComponent;
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_CLASS)) {
- iconPath = QStringLiteral(":/modelinglib/48x48/class.png");
+ iconPath = ":/modelinglib/48x48/class.png";
stereotypeIconElement = qmt::StereotypeIcon::ElementClass;
styleEngineElementType = qmt::StyleEngine::TypeClass;
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_ITEM)) {
- iconPath = QStringLiteral(":/modelinglib/48x48/item.png");
+ iconPath = ":/modelinglib/48x48/item.png";
stereotypeIconElement = qmt::StereotypeIcon::ElementItem;
styleEngineElementType = qmt::StyleEngine::TypeItem;
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_ANNOTATION)) {
- iconPath = QStringLiteral(":/modelinglib/48x48/annotation.png");
+ iconPath = ":/modelinglib/48x48/annotation.png";
styleEngineElementType = qmt::StyleEngine::TypeAnnotation;
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_BOUNDARY)) {
- iconPath = QStringLiteral(":/modelinglib/48x48/boundary.png");
+ iconPath = ":/modelinglib/48x48/boundary.png";
styleEngineElementType = qmt::StyleEngine::TypeBoundary;
+ } else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_SWIMLANE)) {
+ iconPath = ":/modelinglib/48x48/swimlane.png";
+ styleEngineElementType = qmt::StyleEngine::TypeSwimlane;
}
QIcon icon;
if (!tool.m_stereotype.isEmpty() && stereotypeIconElement != qmt::StereotypeIcon::ElementAny) {
@@ -1075,7 +1078,7 @@ void ModelEditor::initToolbars()
// fallback if no toolbar was defined
if (!toolBars.isEmpty()) {
- QString generalId = QStringLiteral("General");
+ QString generalId = "General";
auto toolBar = new QWidget(d->leftToolBox);
toolBar->setProperty(PROPERTYNAME_TOOLBARID, generalId);
auto toolBarLayout = new QVBoxLayout(toolBar);
@@ -1084,40 +1087,44 @@ void ModelEditor::initToolbars()
d->leftToolBox->insertItem(0, toolBar, generalId);
toolBars.insert(generalId, toolBar);
toolBarLayout->addWidget(
- new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/package.png")),
+ new DragTool(QIcon(":/modelinglib/48x48/package.png"),
tr("Package"), QLatin1String(qmt::ELEMENT_TYPE_PACKAGE),
QString(), toolBar));
toolBarLayout->addWidget(
- new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/component.png")),
+ new DragTool(QIcon(":/modelinglib/48x48/component.png"),
tr("Component"), QLatin1String(qmt::ELEMENT_TYPE_COMPONENT),
QString(), toolBar));
toolBarLayout->addWidget(
- new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/class.png")),
+ new DragTool(QIcon(":/modelinglib/48x48/class.png"),
tr("Class"), QLatin1String(qmt::ELEMENT_TYPE_CLASS),
QString(), toolBar));
toolBarLayout->addWidget(
- new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/item.png")),
+ new DragTool(QIcon(":/modelinglib/48x48/item.png"),
tr("Item"), QLatin1String(qmt::ELEMENT_TYPE_ITEM),
QString(), toolBar));
auto horizLine1 = new QFrame(d->leftToolBox);
horizLine1->setFrameShape(QFrame::HLine);
toolBarLayout->addWidget(horizLine1);
toolBarLayout->addWidget(
- new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/annotation.png")),
+ new DragTool(QIcon(":/modelinglib/48x48/annotation.png"),
tr("Annotation"), QLatin1String(qmt::ELEMENT_TYPE_ANNOTATION),
QString(), toolBar));
toolBarLayout->addWidget(
- new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/boundary.png")),
+ new DragTool(QIcon(":/modelinglib/48x48/boundary.png"),
tr("Boundary"), QLatin1String(qmt::ELEMENT_TYPE_BOUNDARY),
QString(), toolBar));
+ toolBarLayout->addWidget(
+ new DragTool(QIcon(":/modelinglib/48x48/swimlane.png"),
+ tr("Swimlane"), QLatin1String(qmt::ELEMENT_TYPE_SWIMLANE),
+ QString(), toolBar));
}
// add stretch to all layouts and calculate width of tool bar
int maxWidth = 48;
foreach (QWidget *toolBar, toolBars) {
- QTC_ASSERT(toolBar, continue);
+ QMT_ASSERT(toolBar, continue);
auto layout = qobject_cast<QBoxLayout *>(toolBar->layout());
- QTC_ASSERT(layout, continue);
+ QMT_ASSERT(layout, continue);
layout->addStretch(1);
toolBar->adjustSize();
if (maxWidth < toolBar->width())
@@ -1209,7 +1216,7 @@ void ModelEditor::addDiagramToSelector(const qmt::MDiagram *diagram)
int i = d->diagramSelector->findData(diagramUid);
if (i >= 0)
d->diagramSelector->removeItem(i);
- d->diagramSelector->insertItem(0, QIcon(QStringLiteral(":/modelinglib/48x48/canvas-diagram.png")), diagramLabel, diagramUid);
+ d->diagramSelector->insertItem(0, QIcon(":/modelinglib/48x48/canvas-diagram.png"), diagramLabel, diagramUid);
d->diagramSelector->setCurrentIndex(0);
while (d->diagramSelector->count() > 20)
d->diagramSelector->removeItem(d->diagramSelector->count() - 1);
@@ -1257,7 +1264,7 @@ QString ModelEditor::buildDiagramLabel(const qmt::MDiagram *diagram)
owner = owner->owner();
}
if (!path.isEmpty()) {
- label += QStringLiteral(" [");
+ label += " [";
label += path.last();
for (int i = path.count() - 2; i >= 0; --i) {
label += QLatin1Char('.');
diff --git a/src/plugins/modeleditor/modeleditor.h b/src/plugins/modeleditor/modeleditor.h
index 7c51751a90..2d4aaa26d7 100644
--- a/src/plugins/modeleditor/modeleditor.h
+++ b/src/plugins/modeleditor/modeleditor.h
@@ -65,7 +65,7 @@ class ModelEditor :
public:
explicit ModelEditor(UiController *uiController, ActionHandler *actionHandler,
- QWidget *parent = 0);
+ QWidget *parent = nullptr);
~ModelEditor();
Core::IDocument *document() override;
diff --git a/src/plugins/modeleditor/modeleditor_plugin.cpp b/src/plugins/modeleditor/modeleditor_plugin.cpp
index 756809f907..acaa8f24dc 100644
--- a/src/plugins/modeleditor/modeleditor_plugin.cpp
+++ b/src/plugins/modeleditor/modeleditor_plugin.cpp
@@ -57,15 +57,15 @@
namespace ModelEditor {
namespace Internal {
-ModelEditorPlugin *pluginInstance = 0;
+ModelEditorPlugin *pluginInstance = nullptr;
class ModelEditorPlugin::ModelEditorPluginPrivate
{
public:
- ModelsManager *modelsManager = 0;
- UiController *uiController = 0;
- ModelEditorFactory *modelFactory = 0;
- SettingsController *settingsController = 0;
+ ModelsManager *modelsManager = nullptr;
+ UiController *uiController = nullptr;
+ ModelEditorFactory *modelFactory = nullptr;
+ SettingsController *settingsController = nullptr;
};
ModelEditorPlugin::ModelEditorPlugin()
diff --git a/src/plugins/modeleditor/modeleditorfactory.cpp b/src/plugins/modeleditor/modeleditorfactory.cpp
index ab6bf6746e..da20bd8679 100644
--- a/src/plugins/modeleditor/modeleditorfactory.cpp
+++ b/src/plugins/modeleditor/modeleditorfactory.cpp
@@ -37,8 +37,8 @@ namespace Internal {
class ModelEditorFactory::ModelEditorFactoryPrivate
{
public:
- UiController *uiController = 0;
- ActionHandler *actionHandler = 0;
+ UiController *uiController = nullptr;
+ ActionHandler *actionHandler = nullptr;
};
ModelEditorFactory::ModelEditorFactory(UiController *uiController, QObject *parent)
diff --git a/src/plugins/modeleditor/modeleditorfactory.h b/src/plugins/modeleditor/modeleditorfactory.h
index 972a1ae44e..ca06f7da40 100644
--- a/src/plugins/modeleditor/modeleditorfactory.h
+++ b/src/plugins/modeleditor/modeleditorfactory.h
@@ -40,7 +40,7 @@ class ModelEditorFactory :
class ModelEditorFactoryPrivate;
public:
- explicit ModelEditorFactory(UiController *uiController, QObject *parent = 0);
+ explicit ModelEditorFactory(UiController *uiController, QObject *parent = nullptr);
~ModelEditorFactory();
Core::IEditor *createEditor() override;
diff --git a/src/plugins/modeleditor/modelindexer.cpp b/src/plugins/modeleditor/modelindexer.cpp
index 062244a1fe..476edaae26 100644
--- a/src/plugins/modeleditor/modelindexer.cpp
+++ b/src/plugins/modeleditor/modelindexer.cpp
@@ -89,7 +89,7 @@ public:
private:
QString m_file;
- ProjectExplorer::Project *m_project = 0;
+ ProjectExplorer::Project *m_project = nullptr;
QDateTime m_lastModified;
};
@@ -234,12 +234,12 @@ class ModelIndexer::ModelIndexerPrivate
public:
~ModelIndexerPrivate()
{
- QTC_CHECK(filesQueue.isEmpty());
- QTC_CHECK(queuedFilesSet.isEmpty());
- QTC_CHECK(indexedModels.isEmpty());
- QTC_CHECK(indexedModelsByUid.isEmpty());
- QTC_CHECK(indexedDiagramReferences.isEmpty());
- QTC_CHECK(indexedDiagramReferencesByDiagramUid.isEmpty());
+ QMT_CHECK(filesQueue.isEmpty());
+ QMT_CHECK(queuedFilesSet.isEmpty());
+ QMT_CHECK(indexedModels.isEmpty());
+ QMT_CHECK(indexedModelsByUid.isEmpty());
+ QMT_CHECK(indexedDiagramReferences.isEmpty());
+ QMT_CHECK(indexedDiagramReferencesByDiagramUid.isEmpty());
delete indexerThread;
}
@@ -255,7 +255,7 @@ public:
QHash<QString, ModelIndexer::IndexedDiagramReference *> indexedDiagramReferences;
QHash<qmt::Uid, QSet<ModelIndexer::IndexedDiagramReference *> > indexedDiagramReferencesByDiagramUid;
- ModelIndexer::IndexerThread *indexerThread = 0;
+ ModelIndexer::IndexerThread *indexerThread = nullptr;
};
void ModelIndexer::IndexerThread::onQuitIndexerThread()
@@ -350,7 +350,7 @@ QString ModelIndexer::findModel(const qmt::Uid &modelUid)
if (indexedModels.isEmpty())
return QString();
IndexedModel *indexedModel = *indexedModels.cbegin();
- QTC_ASSERT(indexedModel, return QString());
+ QMT_ASSERT(indexedModel, return QString());
return indexedModel->file();
}
@@ -363,8 +363,8 @@ QString ModelIndexer::findDiagram(const qmt::Uid &modelUid, const qmt::Uid &diag
if (indexedDiagramReferences.isEmpty())
return QString();
IndexedDiagramReference *indexedDiagramReference = *indexedDiagramReferences.cbegin();
- QTC_ASSERT(indexedDiagramReference, return QString());
- QTC_ASSERT(indexedDiagramReference->modelUid() == modelUid, return QString());
+ QMT_ASSERT(indexedDiagramReference, return QString());
+ QMT_ASSERT(indexedDiagramReference->modelUid() == modelUid, return QString());
return indexedDiagramReference->file();
}
@@ -377,7 +377,7 @@ void ModelIndexer::onProjectAdded(ProjectExplorer::Project *project)
void ModelIndexer::onAboutToRemoveProject(ProjectExplorer::Project *project)
{
- disconnect(project, &ProjectExplorer::Project::fileListChanged, this, 0);
+ disconnect(project, &ProjectExplorer::Project::fileListChanged, this, nullptr);
forgetProject(project);
}
@@ -440,7 +440,7 @@ void ModelIndexer::scanProject(ProjectExplorer::Project *project)
while (!filesQueue.isEmpty()) {
QueuedFile queuedFile = filesQueue.takeFirst();
if (!d->queuedFilesSet.contains(queuedFile)) {
- QTC_CHECK(!d->filesQueue.contains(queuedFile));
+ QMT_CHECK(!d->filesQueue.contains(queuedFile));
d->filesQueue.append(queuedFile);
d->queuedFilesSet.insert(queuedFile);
filesAreQueued = true;
@@ -481,9 +481,9 @@ void ModelIndexer::forgetProject(ProjectExplorer::Project *project)
// remove file from queue
QueuedFile queuedFile(file, project);
if (d->queuedFilesSet.contains(queuedFile)) {
- QTC_CHECK(d->filesQueue.contains(queuedFile));
+ QMT_CHECK(d->filesQueue.contains(queuedFile));
d->filesQueue.removeOne(queuedFile);
- QTC_CHECK(!d->filesQueue.contains(queuedFile));
+ QMT_CHECK(!d->filesQueue.contains(queuedFile));
d->queuedFilesSet.remove(queuedFile);
}
removeModelFile(file, project);
@@ -503,9 +503,9 @@ void ModelIndexer::removeModelFile(const QString &file, ProjectExplorer::Project
d->indexedModels.remove(file);
// remove indexedModel from set of indexedModelsByUid
- QTC_CHECK(d->indexedModelsByUid.contains(indexedModel->modelUid()));
+ QMT_CHECK(d->indexedModelsByUid.contains(indexedModel->modelUid()));
QSet<IndexedModel *> indexedModels = d->indexedModelsByUid.value(indexedModel->modelUid());
- QTC_CHECK(indexedModels.contains(indexedModel));
+ QMT_CHECK(indexedModels.contains(indexedModel));
indexedModels.remove(indexedModel);
if (indexedModels.isEmpty())
d->indexedModelsByUid.remove(indexedModel->modelUid());
@@ -522,7 +522,7 @@ void ModelIndexer::removeDiagramReferenceFile(const QString &file,
{
IndexedDiagramReference *indexedDiagramReference = d->indexedDiagramReferences.value(file);
if (indexedDiagramReference) {
- QTC_CHECK(indexedDiagramReference->owningProjects().contains(project));
+ QMT_CHECK(indexedDiagramReference->owningProjects().contains(project));
qCDebug(logger) << "remove diagram reference file "
<< file << " from project " << project->displayName();
indexedDiagramReference->removeOwningProject(project);
@@ -531,9 +531,9 @@ void ModelIndexer::removeDiagramReferenceFile(const QString &file,
d->indexedDiagramReferences.remove(file);
// remove indexedDiagramReference from set of indexedDiagramReferecesByDiagramUid
- QTC_CHECK(d->indexedDiagramReferencesByDiagramUid.contains(indexedDiagramReference->diagramUid()));
+ QMT_CHECK(d->indexedDiagramReferencesByDiagramUid.contains(indexedDiagramReference->diagramUid()));
QSet<IndexedDiagramReference *> indexedDiagramReferences = d->indexedDiagramReferencesByDiagramUid.value(indexedDiagramReference->diagramUid());
- QTC_CHECK(indexedDiagramReferences.contains(indexedDiagramReference));
+ QMT_CHECK(indexedDiagramReferences.contains(indexedDiagramReference));
indexedDiagramReferences.remove(indexedDiagramReference);
if (indexedDiagramReferences.isEmpty()) {
d->indexedDiagramReferencesByDiagramUid.remove(
diff --git a/src/plugins/modeleditor/modelindexer.h b/src/plugins/modeleditor/modelindexer.h
index d392f386ea..da925977b6 100644
--- a/src/plugins/modeleditor/modelindexer.h
+++ b/src/plugins/modeleditor/modelindexer.h
@@ -53,7 +53,7 @@ class ModelIndexer :
const ModelIndexer::QueuedFile &rhs);
public:
- ModelIndexer(QObject *parent = 0);
+ ModelIndexer(QObject *parent = nullptr);
~ModelIndexer();
signals:
diff --git a/src/plugins/modeleditor/modelsmanager.cpp b/src/plugins/modeleditor/modelsmanager.cpp
index ab51ced73b..89d691ddc6 100644
--- a/src/plugins/modeleditor/modelsmanager.cpp
+++ b/src/plugins/modeleditor/modelsmanager.cpp
@@ -69,8 +69,8 @@ public:
ManagedModel() = default;
ManagedModel(ExtDocumentController *m_documentController,ModelDocument *m_modelDocument);
- ExtDocumentController *m_documentController = 0;
- ModelDocument *m_modelDocument = 0;
+ ExtDocumentController *m_documentController = nullptr;
+ ModelDocument *m_modelDocument = nullptr;
};
ModelsManager::ManagedModel::ManagedModel(ExtDocumentController *documentController,
@@ -88,11 +88,11 @@ public:
}
QList<ModelsManager::ManagedModel> managedModels;
- ModelIndexer *modelIndexer = 0;
+ ModelIndexer *modelIndexer = nullptr;
QList<Core::IDocument *> documentsToBeClosed;
- QAction *openDiagramContextMenuItem = 0;
- ProjectExplorer::Node *contextMenuOwnerNode = 0;
+ QAction *openDiagramContextMenuItem = nullptr;
+ ProjectExplorer::Node *contextMenuOwnerNode = nullptr;
};
ModelsManager::ModelsManager(QObject *parent)
@@ -123,7 +123,7 @@ ModelsManager::ModelsManager(QObject *parent)
ModelsManager::~ModelsManager()
{
- QTC_CHECK(d->managedModels.isEmpty());
+ QMT_CHECK(d->managedModels.isEmpty());
delete d->modelIndexer;
delete d;
}
@@ -150,7 +150,7 @@ void ModelsManager::releaseModel(ExtDocumentController *documentController)
return;
}
}
- QTC_CHECK(false);
+ QMT_CHECK(false);
}
void ModelsManager::openDiagram(const qmt::Uid &modelUid, const qmt::Uid &diagramUid)
@@ -158,7 +158,7 @@ void ModelsManager::openDiagram(const qmt::Uid &modelUid, const qmt::Uid &diagra
foreach (const ManagedModel &managedModel, d->managedModels) {
if (managedModel.m_documentController->projectController()->project()->uid() == modelUid) {
qmt::MDiagram *diagram = managedModel.m_documentController->modelController()->findObject<qmt::MDiagram>(diagramUid);
- QTC_ASSERT(diagram, continue);
+ QMT_ASSERT(diagram, continue);
openDiagram(managedModel.m_documentController, diagram);
return;
}
@@ -182,14 +182,14 @@ void ModelsManager::onAboutToShowContextMenu(ProjectExplorer::Project *project,
if (canOpenDiagram)
d->contextMenuOwnerNode = node;
else
- d->contextMenuOwnerNode = 0;
+ d->contextMenuOwnerNode = nullptr;
d->openDiagramContextMenuItem->setVisible(canOpenDiagram);
}
void ModelsManager::onOpenDiagramFromProjectExplorer()
{
- if (ProjectExplorer::ProjectTree::instance()->currentNode() == d->contextMenuOwnerNode) {
- qmt::MDiagram *diagram = 0;
+ if (ProjectExplorer::ProjectTree::findCurrentNode() == d->contextMenuOwnerNode) {
+ qmt::MDiagram *diagram = nullptr;
foreach (const ManagedModel &managedModel, d->managedModels) {
if ((diagram = managedModel.m_documentController->pxNodeController()->findDiagramForExplorerNode(d->contextMenuOwnerNode))) {
openDiagram(managedModel.m_documentController, diagram);
diff --git a/src/plugins/modeleditor/modelsmanager.h b/src/plugins/modeleditor/modelsmanager.h
index 743a0f3a57..09b1e29055 100644
--- a/src/plugins/modeleditor/modelsmanager.h
+++ b/src/plugins/modeleditor/modelsmanager.h
@@ -53,7 +53,7 @@ class ModelsManager :
class ModelsManagerPrivate;
public:
- explicit ModelsManager(QObject *parent = 0);
+ explicit ModelsManager(QObject *parent = nullptr);
~ModelsManager();
ExtDocumentController *createModel(ModelDocument *modelDocument);
diff --git a/src/plugins/modeleditor/openelementvisitor.cpp b/src/plugins/modeleditor/openelementvisitor.cpp
index 05cca71e39..2429297528 100644
--- a/src/plugins/modeleditor/openelementvisitor.cpp
+++ b/src/plugins/modeleditor/openelementvisitor.cpp
@@ -37,6 +37,7 @@
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/dassociation.h"
+#include "qmt/diagram/dconnection.h"
#include "qmt/model/melement.h"
#include "qmt/model/mpackage.h"
@@ -121,6 +122,11 @@ void OpenDiagramElementVisitor::visitDAssociation(const qmt::DAssociation *assoc
visitDRelation(association);
}
+void OpenDiagramElementVisitor::visitDConnection(const qmt::DConnection *connection)
+{
+ visitDRelation(connection);
+}
+
void OpenDiagramElementVisitor::visitDAnnotation(const qmt::DAnnotation *annotation)
{
Q_UNUSED(annotation);
@@ -131,6 +137,11 @@ void OpenDiagramElementVisitor::visitDBoundary(const qmt::DBoundary *boundary)
Q_UNUSED(boundary);
}
+void OpenDiagramElementVisitor::visitDSwimlane(const qmt::DSwimlane *swimlane)
+{
+ Q_UNUSED(swimlane);
+}
+
void OpenModelElementVisitor::setElementTasks(ElementTasks *elementTasks)
{
m_elementTasks = elementTasks;
@@ -199,5 +210,10 @@ void OpenModelElementVisitor::visitMAssociation(const qmt::MAssociation *associa
Q_UNUSED(association);
}
+void OpenModelElementVisitor::visitMConnection(const qmt::MConnection *connection)
+{
+ Q_UNUSED(connection);
+}
+
} // namespace Internal
} // namespace ModelEditor
diff --git a/src/plugins/modeleditor/openelementvisitor.h b/src/plugins/modeleditor/openelementvisitor.h
index 48e0408076..de13828b89 100644
--- a/src/plugins/modeleditor/openelementvisitor.h
+++ b/src/plugins/modeleditor/openelementvisitor.h
@@ -42,23 +42,25 @@ public:
void setModelController(qmt::ModelController *modelController);
void setElementTasks(ElementTasks *elementTasks);
- void visitDElement(const qmt::DElement *element);
- void visitDObject(const qmt::DObject *object);
- void visitDPackage(const qmt::DPackage *package);
- void visitDClass(const qmt::DClass *klass);
- void visitDComponent(const qmt::DComponent *component);
- void visitDDiagram(const qmt::DDiagram *diagram);
- void visitDItem(const qmt::DItem *item);
- void visitDRelation(const qmt::DRelation *relation);
- void visitDInheritance(const qmt::DInheritance *inheritance);
- void visitDDependency(const qmt::DDependency *dependency);
- void visitDAssociation(const qmt::DAssociation *association);
- void visitDAnnotation(const qmt::DAnnotation *annotation);
- void visitDBoundary(const qmt::DBoundary *boundary);
+ void visitDElement(const qmt::DElement *element) override;
+ void visitDObject(const qmt::DObject *object) override;
+ void visitDPackage(const qmt::DPackage *package) override;
+ void visitDClass(const qmt::DClass *klass) override;
+ void visitDComponent(const qmt::DComponent *component) override;
+ void visitDDiagram(const qmt::DDiagram *diagram) override;
+ void visitDItem(const qmt::DItem *item) override;
+ void visitDRelation(const qmt::DRelation *relation) override;
+ void visitDInheritance(const qmt::DInheritance *inheritance) override;
+ void visitDDependency(const qmt::DDependency *dependency) override;
+ void visitDAssociation(const qmt::DAssociation *association) override;
+ void visitDConnection(const qmt::DConnection *connection) override;
+ void visitDAnnotation(const qmt::DAnnotation *annotation) override;
+ void visitDBoundary(const qmt::DBoundary *boundary) override;
+ void visitDSwimlane(const qmt::DSwimlane *swimlane) override;
private:
- qmt::ModelController *m_modelController = 0;
- ElementTasks *m_elementTasks = 0;
+ qmt::ModelController *m_modelController = nullptr;
+ ElementTasks *m_elementTasks = nullptr;
};
class OpenModelElementVisitor :
@@ -79,9 +81,10 @@ public:
void visitMDependency(const qmt::MDependency *dependency) override;
void visitMInheritance(const qmt::MInheritance *inheritance) override;
void visitMAssociation(const qmt::MAssociation *association) override;
+ void visitMConnection(const qmt::MConnection *connection) override;
private:
- ElementTasks *m_elementTasks = 0;
+ ElementTasks *m_elementTasks = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/modeleditor/pxnodecontroller.cpp b/src/plugins/modeleditor/pxnodecontroller.cpp
index 79ceb8a914..61e2f36541 100644
--- a/src/plugins/modeleditor/pxnodecontroller.cpp
+++ b/src/plugins/modeleditor/pxnodecontroller.cpp
@@ -91,10 +91,10 @@ public:
class PxNodeController::PxNodeControllerPrivate
{
public:
- PxNodeUtilities *pxnodeUtilities = 0;
- ComponentViewController *componentViewController = 0;
- ClassViewController *classViewController = 0;
- qmt::DiagramSceneController *diagramSceneController = 0;
+ PxNodeUtilities *pxnodeUtilities = nullptr;
+ ComponentViewController *componentViewController = nullptr;
+ ClassViewController *classViewController = nullptr;
+ qmt::DiagramSceneController *diagramSceneController = nullptr;
QString anchorFolder;
};
@@ -135,8 +135,8 @@ void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node,
qmt::DElement *topMostElementAtPos, const QPointF &pos,
qmt::MDiagram *diagram)
{
- QTC_ASSERT(node, return);
- QTC_ASSERT(diagram, return);
+ QMT_ASSERT(node, return);
+ QMT_ASSERT(diagram, return);
QString elementName = qmt::NameController::convertFileNameToElementName(
node->filePath().toString());
@@ -174,10 +174,10 @@ void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node,
QString stereotype;
switch (node->nodeType()) {
case ProjectExplorer::NodeType::VirtualFolder:
- stereotype = QStringLiteral("virtual folder");
+ stereotype = "virtual folder";
break;
case ProjectExplorer::NodeType::Project:
- stereotype = QStringLiteral("project");
+ stereotype = "project";
break;
default:
break;
@@ -208,7 +208,7 @@ void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node,
bool PxNodeController::hasDiagramForExplorerNode(const ProjectExplorer::Node *node)
{
- return findDiagramForExplorerNode(node) != 0;
+ return findDiagramForExplorerNode(node) != nullptr;
}
qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplorer::Node *node)
@@ -252,7 +252,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore
}
if (found) {
- QTC_ASSERT(relativeIndex >= relativeElements.size(), return 0);
+ QMT_ASSERT(relativeIndex >= relativeElements.size(), return nullptr);
// complete package chain found so check for appropriate diagram within deepest package
qmt::MDiagram *diagram = d->diagramSceneController->findDiagramBySearchId(
package, package->name());
@@ -269,7 +269,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore
}
// complete sub-package structure scanned but did not found the desired object
- return 0;
+ return nullptr;
}
void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *action,
@@ -277,8 +277,8 @@ void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *actio
qmt::DElement *topMostElementAtPos,
const QPointF &pos, qmt::MDiagram *diagram)
{
- qmt::MObject *newObject = 0;
- qmt::MDiagram *newDiagramInObject = 0;
+ qmt::MObject *newObject = nullptr;
+ qmt::MDiagram *newDiagramInObject = nullptr;
switch (action->type) {
case MenuAction::TYPE_ADD_COMPONENT:
@@ -329,7 +329,7 @@ void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *actio
if (qmt::MObject *existingObject = d->pxnodeUtilities->findSameObject(relativeElements, package)) {
delete package;
package = dynamic_cast<qmt::MPackage *>(existingObject);
- QTC_ASSERT(package, return);
+ QMT_ASSERT(package, return);
d->diagramSceneController->addExistingModelElement(package->uid(), pos, diagram);
} else {
qmt::MPackage *requestedRootPackage = d->diagramSceneController->findSuitableParentPackage(topMostElementAtPos, diagram);
@@ -348,13 +348,13 @@ void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *actio
if (newObject) {
d->diagramSceneController->modelController()->undoController()->beginMergeSequence(tr("Drop Node"));
- qmt::MObject *parentForDiagram = 0;
+ qmt::MObject *parentForDiagram = nullptr;
QStringList relativeElements = qmt::NameController::buildElementsPath(
d->pxnodeUtilities->calcRelativePath(node, d->anchorFolder),
- dynamic_cast<qmt::MPackage *>(newObject) != 0);
+ dynamic_cast<qmt::MPackage *>(newObject) != nullptr);
if (qmt::MObject *existingObject = d->pxnodeUtilities->findSameObject(relativeElements, newObject)) {
delete newObject;
- newObject = 0;
+ newObject = nullptr;
d->diagramSceneController->addExistingModelElement(existingObject->uid(), pos, diagram);
parentForDiagram = existingObject;
} else {
@@ -367,7 +367,7 @@ void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *actio
// if requested and not existing then create new diagram in package
if (newDiagramInObject) {
auto package = dynamic_cast<qmt::MPackage *>(parentForDiagram);
- QTC_ASSERT(package, return);
+ QMT_ASSERT(package, return);
if (d->diagramSceneController->findDiagramBySearchId(package, newDiagramInObject->name()))
delete newDiagramInObject;
else
diff --git a/src/plugins/modeleditor/pxnodecontroller.h b/src/plugins/modeleditor/pxnodecontroller.h
index 7eee19e66a..7f5d570a9b 100644
--- a/src/plugins/modeleditor/pxnodecontroller.h
+++ b/src/plugins/modeleditor/pxnodecontroller.h
@@ -49,7 +49,7 @@ class PxNodeController :
class MenuAction;
public:
- explicit PxNodeController(QObject *parent = 0);
+ explicit PxNodeController(QObject *parent = nullptr);
~PxNodeController();
ComponentViewController *componentViewController() const;
diff --git a/src/plugins/modeleditor/pxnodeutilities.cpp b/src/plugins/modeleditor/pxnodeutilities.cpp
index 31fede39fb..34f830fb41 100644
--- a/src/plugins/modeleditor/pxnodeutilities.cpp
+++ b/src/plugins/modeleditor/pxnodeutilities.cpp
@@ -44,7 +44,7 @@ namespace Internal {
class PxNodeUtilities::PxNodeUtilitiesPrivate {
public:
- qmt::DiagramSceneController *diagramSceneController = 0;
+ qmt::DiagramSceneController *diagramSceneController = nullptr;
};
PxNodeUtilities::PxNodeUtilities(QObject *parent)
@@ -100,7 +100,7 @@ qmt::MPackage *PxNodeUtilities::createBestMatchingPackagePath(
int maxChainLength = -1;
int minChainDepth = -1;
- qmt::MPackage *bestParentPackage = 0;
+ qmt::MPackage *bestParentPackage = nullptr;
while (!roots.isEmpty()) {
qmt::MPackage *package = roots.first().first;
@@ -144,7 +144,7 @@ qmt::MPackage *PxNodeUtilities::createBestMatchingPackagePath(
if (found)
return package; // complete chain found, innermost package is already the result
- QTC_CHECK(!(relativeIndex == maxChainLength && minChainDepth < 0));
+ QMT_CHECK(!(relativeIndex == maxChainLength && minChainDepth < 0));
if (relativeIndex >= 1
&& (relativeIndex > maxChainLength
|| (relativeIndex == maxChainLength && depth < minChainDepth))) {
@@ -154,14 +154,14 @@ qmt::MPackage *PxNodeUtilities::createBestMatchingPackagePath(
}
}
- QTC_CHECK(maxChainLength < relativeElements.size());
+ QMT_CHECK(maxChainLength < relativeElements.size());
if (!bestParentPackage) {
- QTC_CHECK(maxChainLength == -1);
- QTC_CHECK(minChainDepth == -1);
+ QMT_CHECK(maxChainLength == -1);
+ QMT_CHECK(minChainDepth == -1);
maxChainLength = 0;
bestParentPackage = suggestedParentPackage;
} else {
- QTC_CHECK(maxChainLength >= 1);
+ QMT_CHECK(maxChainLength >= 1);
}
int i = maxChainLength;
@@ -215,7 +215,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement
}
if (found) {
- QTC_CHECK(relativeIndex >= relativeElements.size());
+ QMT_CHECK(relativeIndex >= relativeElements.size());
// chain was found so check for given object within deepest package
QString objectSearchId = qmt::NameController::calcElementNameSearchId(object->name());
foreach (const qmt::Handle<qmt::MObject> &handle, package->children()) {
@@ -231,7 +231,7 @@ qmt::MObject *PxNodeUtilities::findSameObject(const QStringList &relativeElement
}
// complete sub-package structure scanned but did not found the desired object
- return 0;
+ return nullptr;
}
} // namespace Internal
diff --git a/src/plugins/modeleditor/pxnodeutilities.h b/src/plugins/modeleditor/pxnodeutilities.h
index 1aea2f1b9a..fd620de63e 100644
--- a/src/plugins/modeleditor/pxnodeutilities.h
+++ b/src/plugins/modeleditor/pxnodeutilities.h
@@ -45,7 +45,7 @@ class PxNodeUtilities :
class PxNodeUtilitiesPrivate;
public:
- explicit PxNodeUtilities(QObject *parent = 0);
+ explicit PxNodeUtilities(QObject *parent = nullptr);
~PxNodeUtilities();
void setDiagramSceneController(qmt::DiagramSceneController *diagramSceneController);
diff --git a/src/plugins/modeleditor/settingscontroller.h b/src/plugins/modeleditor/settingscontroller.h
index 9400cd6282..90371b66a7 100644
--- a/src/plugins/modeleditor/settingscontroller.h
+++ b/src/plugins/modeleditor/settingscontroller.h
@@ -40,7 +40,7 @@ class SettingsController :
Q_OBJECT
public:
- explicit SettingsController(QObject *parent = 0);
+ explicit SettingsController(QObject *parent = nullptr);
signals:
void resetSettings();
diff --git a/src/plugins/modeleditor/uicontroller.h b/src/plugins/modeleditor/uicontroller.h
index c31f630bca..9dacf6d069 100644
--- a/src/plugins/modeleditor/uicontroller.h
+++ b/src/plugins/modeleditor/uicontroller.h
@@ -41,7 +41,7 @@ class UiController :
class UiControllerPrivate;
public:
- explicit UiController(QObject *parent = 0);
+ explicit UiController(QObject *parent = nullptr);
~UiController();
signals:
diff --git a/src/plugins/nim/project/nimcompilerbuildstep.cpp b/src/plugins/nim/project/nimcompilerbuildstep.cpp
index 232afc2950..8f366488ff 100644
--- a/src/plugins/nim/project/nimcompilerbuildstep.cpp
+++ b/src/plugins/nim/project/nimcompilerbuildstep.cpp
@@ -130,7 +130,7 @@ BuildStepConfigWidget *NimCompilerBuildStep::createConfigWidget()
bool NimCompilerBuildStep::fromMap(const QVariantMap &map)
{
AbstractProcessStep::fromMap(map);
- m_userCompilerOptions = map[Constants::C_NIMCOMPILERBUILDSTEP_USERCOMPILEROPTIONS].toString().split(QLatin1Char('|'));
+ m_userCompilerOptions = map[Constants::C_NIMCOMPILERBUILDSTEP_USERCOMPILEROPTIONS].toString().split('|');
m_defaultOptions = static_cast<DefaultBuildOptions>(map[Constants::C_NIMCOMPILERBUILDSTEP_DEFAULTBUILDOPTIONS].toInt());
m_targetNimFile = FileName::fromString(map[Constants::C_NIMCOMPILERBUILDSTEP_TARGETNIMFILE].toString());
updateProcessParameters();
@@ -140,7 +140,7 @@ bool NimCompilerBuildStep::fromMap(const QVariantMap &map)
QVariantMap NimCompilerBuildStep::toMap() const
{
QVariantMap result = AbstractProcessStep::toMap();
- result[Constants::C_NIMCOMPILERBUILDSTEP_USERCOMPILEROPTIONS] = m_userCompilerOptions.join(QLatin1Char('|'));
+ result[Constants::C_NIMCOMPILERBUILDSTEP_USERCOMPILEROPTIONS] = m_userCompilerOptions.join('|');
result[Constants::C_NIMCOMPILERBUILDSTEP_DEFAULTBUILDOPTIONS] = m_defaultOptions;
result[Constants::C_NIMCOMPILERBUILDSTEP_TARGETNIMFILE] = m_targetNimFile.toString();
return result;
diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp
index 8910bd42af..c6d28a3974 100644
--- a/src/plugins/nim/project/nimproject.cpp
+++ b/src/plugins/nim/project/nimproject.cpp
@@ -127,6 +127,7 @@ void NimProject::collectProjectFiles()
void NimProject::updateProject()
{
+ emitParsingStarted();
const QStringList oldFiles = m_files;
m_files.clear();
@@ -152,7 +153,7 @@ void NimProject::updateProject()
newRoot->setDisplayName(displayName());
newRoot->addNestedNodes(fileNodes);
setRootProjectNode(newRoot);
- emit parsingFinished();
+ emitParsingFinished(true);
}
bool NimProject::supportsKit(Kit *k, QString *errorMessage) const
diff --git a/src/plugins/nim/project/nimprojectnode.cpp b/src/plugins/nim/project/nimprojectnode.cpp
index 223c6f950d..7604fb3a6d 100644
--- a/src/plugins/nim/project/nimprojectnode.cpp
+++ b/src/plugins/nim/project/nimprojectnode.cpp
@@ -37,7 +37,7 @@ NimProjectNode::NimProjectNode(NimProject &project,
, m_project(project)
{}
-bool NimProjectNode::supportsAction(ProjectAction action, Node *node) const
+bool NimProjectNode::supportsAction(ProjectAction action, const Node *node) const
{
switch (node->nodeType()) {
case NodeType::File:
diff --git a/src/plugins/nim/project/nimprojectnode.h b/src/plugins/nim/project/nimprojectnode.h
index 05270846f9..317d4be555 100644
--- a/src/plugins/nim/project/nimprojectnode.h
+++ b/src/plugins/nim/project/nimprojectnode.h
@@ -38,7 +38,7 @@ class NimProjectNode : public ProjectExplorer::ProjectNode
public:
NimProjectNode(NimProject &project, const Utils::FileName &projectFilePath);
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *) override;
bool removeFiles(const QStringList &filePaths, QStringList *) override;
bool deleteFiles(const QStringList &) override;
diff --git a/src/plugins/nim/project/nimrunconfiguration.cpp b/src/plugins/nim/project/nimrunconfiguration.cpp
index 7b9e43ab47..cbf31afd1b 100644
--- a/src/plugins/nim/project/nimrunconfiguration.cpp
+++ b/src/plugins/nim/project/nimrunconfiguration.cpp
@@ -44,9 +44,8 @@ using namespace Utils;
namespace Nim {
-NimRunConfiguration::NimRunConfiguration(Target *parent, Core::Id id)
- : RunConfiguration(parent, id)
- , m_buildConfiguration(nullptr)
+NimRunConfiguration::NimRunConfiguration(Target *target)
+ : RunConfiguration(target)
, m_workingDirectoryAspect(new WorkingDirectoryAspect(this, Nim::Constants::C_NIMRUNCONFIGURATION_WORKINGDIRECTORYASPECT_ID))
, m_argumentAspect(new ArgumentsAspect(this, Nim::Constants::C_NIMRUNCONFIGURATION_ARGUMENTASPECT_ID))
, m_terminalAspect(new TerminalAspect(this, Nim::Constants::C_NIMRUNCONFIGURATION_TERMINALASPECT_ID))
@@ -62,9 +61,8 @@ NimRunConfiguration::NimRunConfiguration(Target *parent, Core::Id id)
setDefaultDisplayName(tr(Constants::C_NIMRUNCONFIGURATION_DEFAULT_DISPLAY));
// Connect target signals
- connect(this->target(), &Target::activeBuildConfigurationChanged,
+ connect(target, &Target::activeBuildConfigurationChanged,
this, &NimRunConfiguration::updateConfiguration);
-
updateConfiguration();
}
diff --git a/src/plugins/nim/project/nimrunconfiguration.h b/src/plugins/nim/project/nimrunconfiguration.h
index 6769b4f307..5ab1ce6130 100644
--- a/src/plugins/nim/project/nimrunconfiguration.h
+++ b/src/plugins/nim/project/nimrunconfiguration.h
@@ -43,7 +43,7 @@ class NimRunConfiguration : public ProjectExplorer::RunConfiguration
Q_OBJECT
public:
- NimRunConfiguration(ProjectExplorer::Target *parent, Core::Id id);
+ explicit NimRunConfiguration(ProjectExplorer::Target *target);
QWidget *createConfigurationWidget() override;
ProjectExplorer::Runnable runnable() const override;
@@ -65,7 +65,7 @@ private:
void setActiveBuildConfiguration(NimBuildConfiguration *activeBuildConfiguration);
QString m_executable;
- NimBuildConfiguration *m_buildConfiguration;
+ NimBuildConfiguration *m_buildConfiguration = nullptr;
ProjectExplorer::WorkingDirectoryAspect* m_workingDirectoryAspect;
ProjectExplorer::ArgumentsAspect* m_argumentAspect;
ProjectExplorer::TerminalAspect* m_terminalAspect;
diff --git a/src/plugins/nim/project/nimrunconfigurationfactory.cpp b/src/plugins/nim/project/nimrunconfigurationfactory.cpp
index 7b00593017..5bce6e297e 100644
--- a/src/plugins/nim/project/nimrunconfigurationfactory.cpp
+++ b/src/plugins/nim/project/nimrunconfigurationfactory.cpp
@@ -80,7 +80,8 @@ RunConfiguration *NimRunConfigurationFactory::clone(Target *parent, RunConfigura
{
QTC_ASSERT(parent, return nullptr);
QTC_ASSERT(product, return nullptr);
- std::unique_ptr<NimRunConfiguration> result(new NimRunConfiguration(parent, Constants::C_NIMRUNCONFIGURATION_ID));
+ std::unique_ptr<NimRunConfiguration> result(
+ createHelper<NimRunConfiguration>(parent, Constants::C_NIMRUNCONFIGURATION_ID));
return result->fromMap(product->toMap()) ? result.release() : nullptr;
}
@@ -94,14 +95,13 @@ bool NimRunConfigurationFactory::canHandle(Target *parent) const
RunConfiguration *NimRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
- Q_UNUSED(id);
- return new NimRunConfiguration(parent, id);
+ return createHelper<NimRunConfiguration>(parent, id);
}
RunConfiguration *NimRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
{
Q_UNUSED(map);
- auto result = new NimRunConfiguration(parent, idFromMap(map));
+ auto result = createHelper<NimRunConfiguration>(parent, idFromMap(map));
result->fromMap(map);
return result;
}
diff --git a/src/plugins/nim/project/nimrunconfigurationwidget.cpp b/src/plugins/nim/project/nimrunconfigurationwidget.cpp
index 74ea801937..0fc0b671a6 100644
--- a/src/plugins/nim/project/nimrunconfigurationwidget.cpp
+++ b/src/plugins/nim/project/nimrunconfigurationwidget.cpp
@@ -45,14 +45,6 @@ NimRunConfigurationWidget::NimRunConfigurationWidget(NimRunConfiguration *rc,
fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
rc->extraAspect<ArgumentsAspect>()->addToMainConfigurationWidget(this, fl);
rc->extraAspect<TerminalAspect>()->addToMainConfigurationWidget(this,fl);
- connect(rc, &NimRunConfiguration::enabledChanged, this, &NimRunConfigurationWidget::updateUi);
- updateUi();
}
-
-void NimRunConfigurationWidget::updateUi()
-{
- setEnabled(m_rc->isEnabled());
-}
-
-}
+} // namespace Nim
diff --git a/src/plugins/nim/project/nimrunconfigurationwidget.h b/src/plugins/nim/project/nimrunconfigurationwidget.h
index 9c47bf1d06..7e5e096bf0 100644
--- a/src/plugins/nim/project/nimrunconfigurationwidget.h
+++ b/src/plugins/nim/project/nimrunconfigurationwidget.h
@@ -39,9 +39,7 @@ public:
explicit NimRunConfigurationWidget(NimRunConfiguration *rc, QWidget *parent = 0);
private:
- void updateUi();
-
NimRunConfiguration* m_rc;
};
-}
+} // namespace Nim
diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp
index 6c8fd0f32b..3605b5bcb6 100644
--- a/src/plugins/nim/project/nimtoolchain.cpp
+++ b/src/plugins/nim/project/nimtoolchain.cpp
@@ -82,9 +82,9 @@ ToolChain::PredefinedMacrosRunner NimToolChain::createPredefinedMacrosRunner() c
return ToolChain::PredefinedMacrosRunner();
}
-QByteArray NimToolChain::predefinedMacros(const QStringList &) const
+Macros NimToolChain::predefinedMacros(const QStringList &) const
{
- return QByteArray();
+ return Macros();
}
ToolChain::CompilerFlags NimToolChain::compilerFlags(const QStringList &) const
diff --git a/src/plugins/nim/project/nimtoolchain.h b/src/plugins/nim/project/nimtoolchain.h
index 7061a9751b..2da07dd2e2 100644
--- a/src/plugins/nim/project/nimtoolchain.h
+++ b/src/plugins/nim/project/nimtoolchain.h
@@ -41,7 +41,7 @@ public:
bool isValid() const override;
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
- QByteArray predefinedMacros(const QStringList &flags) const final;
+ ProjectExplorer::Macros predefinedMacros(const QStringList &flags) const final;
CompilerFlags compilerFlags(const QStringList &flags) const final;
ProjectExplorer::WarningFlags warningFlags(const QStringList &flags) const final;
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index ba5ed219c7..0278cd6403 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -183,7 +183,7 @@ bool PerforcePlugin::initialize(const QStringList & /* arguments */, QString *er
Q_UNUSED(errorMessage)
Context context(PERFORCE_CONTEXT);
- initializeVcs(new PerforceVersionControl(this), context);
+ initializeVcs<PerforceVersionControl>(context, this);
m_instance = this;
@@ -556,6 +556,8 @@ void PerforcePlugin::printOpenedFileList()
void PerforcePlugin::startSubmitProject()
{
+ if (!promptBeforeCommit())
+ return;
if (raiseSubmitEditor())
return;
@@ -1225,6 +1227,11 @@ void PerforceDiffConfig::triggerReRun()
emit reRunDiff(effectiveParameters);
}
+QString PerforcePlugin::commitDisplayName() const
+{
+ return tr("submit", "\"commit\" action for perforce");
+}
+
void PerforcePlugin::p4Diff(const QString &workingDir, const QStringList &files)
{
PerforceDiffParameters p;
diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h
index ae90276f97..814969537a 100644
--- a/src/plugins/perforce/perforceplugin.h
+++ b/src/plugins/perforce/perforceplugin.h
@@ -113,6 +113,7 @@ private slots:
#endif
private:
+ QString commitDisplayName() const final;
void p4Diff(const PerforceDiffParameters &p);
void openCurrentFile();
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index 4a99590d82..90a27134a5 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -322,37 +322,41 @@ Abi::Abi(const Architecture &a, const OS &o,
m_architecture(a), m_os(o), m_osFlavor(of), m_binaryFormat(f), m_wordWidth(w)
{
switch (m_os) {
- case Abi::UnknownOS:
+ case UnknownOS:
m_osFlavor = UnknownFlavor;
break;
- case Abi::LinuxOS:
+ case LinuxOS:
if (m_osFlavor < GenericLinuxFlavor || m_osFlavor > AndroidLinuxFlavor)
m_osFlavor = UnknownFlavor;
break;
- case Abi::BsdOS:
+ case BsdOS:
if (m_osFlavor < FreeBsdFlavor || m_osFlavor > OpenBsdFlavor)
m_osFlavor = UnknownFlavor;
break;
- case Abi::DarwinOS:
+ case DarwinOS:
if (m_osFlavor < GenericDarwinFlavor || m_osFlavor > GenericDarwinFlavor)
m_osFlavor = UnknownFlavor;
break;
- case Abi::UnixOS:
+ case UnixOS:
if (m_osFlavor < GenericUnixFlavor || m_osFlavor > SolarisUnixFlavor)
m_osFlavor = UnknownFlavor;
break;
- case Abi::WindowsOS:
+ case WindowsOS:
if (m_osFlavor < WindowsMsvc2005Flavor || m_osFlavor > WindowsCEFlavor)
m_osFlavor = UnknownFlavor;
break;
- case Abi::VxWorks:
+ case VxWorks:
if (m_osFlavor != VxWorksFlavor)
m_osFlavor = VxWorksFlavor;
break;
- case Abi::QnxOS:
+ case QnxOS:
if (m_osFlavor != GenericQnxFlavor)
m_osFlavor = UnknownFlavor;
break;
+ case BareMetalOS:
+ if (m_osFlavor != GenericBareMetalFlavor)
+ m_osFlavor = GenericBareMetalFlavor;
+ break;
}
}
@@ -360,105 +364,107 @@ Abi::Abi(const QString &abiString) :
m_architecture(UnknownArchitecture), m_os(UnknownOS),
m_osFlavor(UnknownFlavor), m_binaryFormat(UnknownFormat), m_wordWidth(0)
{
- const QVector<QStringRef> abiParts = abiString.splitRef(QLatin1Char('-'));
+ const QVector<QStringRef> abiParts = abiString.splitRef('-');
if (abiParts.count() >= 1) {
- if (abiParts.at(0) == QLatin1String("unknown"))
+ if (abiParts.at(0) == "unknown")
m_architecture = UnknownArchitecture;
- else if (abiParts.at(0) == QLatin1String("arm"))
+ else if (abiParts.at(0) == "arm")
m_architecture = ArmArchitecture;
- else if (abiParts.at(0) == QLatin1String("aarch64"))
+ else if (abiParts.at(0) == "aarch64")
m_architecture = ArmArchitecture;
- else if (abiParts.at(0) == QLatin1String("x86"))
+ else if (abiParts.at(0) == "avr")
+ m_architecture = AvrArchitecture;
+ else if (abiParts.at(0) == "x86")
m_architecture = X86Architecture;
- else if (abiParts.at(0) == QLatin1String("mips"))
+ else if (abiParts.at(0) == "mips")
m_architecture = MipsArchitecture;
- else if (abiParts.at(0) == QLatin1String("ppc"))
+ else if (abiParts.at(0) == "ppc")
m_architecture = PowerPCArchitecture;
- else if (abiParts.at(0) == QLatin1String("itanium"))
+ else if (abiParts.at(0) == "itanium")
m_architecture = ItaniumArchitecture;
- else if (abiParts.at(0) == QLatin1String("sh"))
+ else if (abiParts.at(0) == "sh")
m_architecture = ShArchitecture;
else
return;
}
if (abiParts.count() >= 2) {
- if (abiParts.at(1) == QLatin1String("unknown"))
+ if (abiParts.at(1) == "unknown")
m_os = UnknownOS;
- else if (abiParts.at(1) == QLatin1String("linux"))
+ else if (abiParts.at(1) == "linux")
m_os = LinuxOS;
- else if (abiParts.at(1) == QLatin1String("bsd"))
+ else if (abiParts.at(1) == "bsd")
m_os = BsdOS;
- else if (abiParts.at(1) == QLatin1String("darwin")
- || abiParts.at(1) == QLatin1String("macos"))
+ else if (abiParts.at(1) == "darwin"
+ || abiParts.at(1) == "macos")
m_os = DarwinOS;
- else if (abiParts.at(1) == QLatin1String("unix"))
+ else if (abiParts.at(1) == "unix")
m_os = UnixOS;
- else if (abiParts.at(1) == QLatin1String("windows"))
+ else if (abiParts.at(1) == "windows")
m_os = WindowsOS;
- else if (abiParts.at(1) == QLatin1String("vxworks"))
+ else if (abiParts.at(1) == "vxworks")
m_os = VxWorks;
- else if (abiParts.at(1) == QLatin1String("qnx"))
+ else if (abiParts.at(1) == "qnx")
m_os = QnxOS;
else
return;
}
if (abiParts.count() >= 3) {
- if (abiParts.at(2) == QLatin1String("unknown"))
+ if (abiParts.at(2) == "unknown")
m_osFlavor = UnknownFlavor;
- else if (abiParts.at(2) == QLatin1String("generic") && m_os == LinuxOS)
+ else if (abiParts.at(2) == "generic" && m_os == LinuxOS)
m_osFlavor = GenericLinuxFlavor;
- else if (abiParts.at(2) == QLatin1String("android") && m_os == LinuxOS)
+ else if (abiParts.at(2) == "android" && m_os == LinuxOS)
m_osFlavor = AndroidLinuxFlavor;
- else if (abiParts.at(2) == QLatin1String("generic") && m_os == QnxOS)
+ else if (abiParts.at(2) == "generic" && m_os == QnxOS)
m_osFlavor = GenericQnxFlavor;
- else if (abiParts.at(2) == QLatin1String("freebsd") && m_os == BsdOS)
+ else if (abiParts.at(2) == "freebsd" && m_os == BsdOS)
m_osFlavor = FreeBsdFlavor;
- else if (abiParts.at(2) == QLatin1String("netbsd") && m_os == BsdOS)
+ else if (abiParts.at(2) == "netbsd" && m_os == BsdOS)
m_osFlavor = NetBsdFlavor;
- else if (abiParts.at(2) == QLatin1String("openbsd") && m_os == BsdOS)
+ else if (abiParts.at(2) == "openbsd" && m_os == BsdOS)
m_osFlavor = OpenBsdFlavor;
- else if (abiParts.at(2) == QLatin1String("generic") && m_os == DarwinOS)
+ else if (abiParts.at(2) == "generic" && m_os == DarwinOS)
m_osFlavor = GenericDarwinFlavor;
- else if (abiParts.at(2) == QLatin1String("generic") && m_os == UnixOS)
+ else if (abiParts.at(2) == "generic" && m_os == UnixOS)
m_osFlavor = GenericUnixFlavor;
- else if (abiParts.at(2) == QLatin1String("solaris") && m_os == UnixOS)
+ else if (abiParts.at(2) == "solaris" && m_os == UnixOS)
m_osFlavor = SolarisUnixFlavor;
- else if (abiParts.at(2) == QLatin1String("msvc2005") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msvc2005" && m_os == WindowsOS)
m_osFlavor = WindowsMsvc2005Flavor;
- else if (abiParts.at(2) == QLatin1String("msvc2008") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msvc2008" && m_os == WindowsOS)
m_osFlavor = WindowsMsvc2008Flavor;
- else if (abiParts.at(2) == QLatin1String("msvc2010") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msvc2010" && m_os == WindowsOS)
m_osFlavor = WindowsMsvc2010Flavor;
- else if (abiParts.at(2) == QLatin1String("msvc2012") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msvc2012" && m_os == WindowsOS)
m_osFlavor = WindowsMsvc2012Flavor;
- else if (abiParts.at(2) == QLatin1String("msvc2013") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msvc2013" && m_os == WindowsOS)
m_osFlavor = WindowsMsvc2013Flavor;
- else if (abiParts.at(2) == QLatin1String("msvc2015") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msvc2015" && m_os == WindowsOS)
m_osFlavor = WindowsMsvc2015Flavor;
- else if (abiParts.at(2) == QLatin1String("msvc2017") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msvc2017" && m_os == WindowsOS)
m_osFlavor = WindowsMsvc2017Flavor;
- else if (abiParts.at(2) == QLatin1String("msys") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "msys" && m_os == WindowsOS)
m_osFlavor = WindowsMSysFlavor;
- else if (abiParts.at(2) == QLatin1String("ce") && m_os == WindowsOS)
+ else if (abiParts.at(2) == "ce" && m_os == WindowsOS)
m_osFlavor = WindowsCEFlavor;
- else if (abiParts.at(2) == QLatin1String("vxworks") && m_os == VxWorks)
+ else if (abiParts.at(2) == "vxworks" && m_os == VxWorks)
m_osFlavor = VxWorksFlavor;
else
return;
}
if (abiParts.count() >= 4) {
- if (abiParts.at(3) == QLatin1String("unknown"))
+ if (abiParts.at(3) == "unknown")
m_binaryFormat = UnknownFormat;
- else if (abiParts.at(3) == QLatin1String("elf"))
+ else if (abiParts.at(3) == "elf")
m_binaryFormat = ElfFormat;
- else if (abiParts.at(3) == QLatin1String("pe"))
+ else if (abiParts.at(3) == "pe")
m_binaryFormat = PEFormat;
- else if (abiParts.at(3) == QLatin1String("mach_o"))
+ else if (abiParts.at(3) == "mach_o")
m_binaryFormat = MachOFormat;
- else if (abiParts.at(3) == QLatin1String("qml_rt"))
+ else if (abiParts.at(3) == "qml_rt")
m_binaryFormat = RuntimeQmlFormat;
else
return;
@@ -466,7 +472,7 @@ Abi::Abi(const QString &abiString) :
if (abiParts.count() >= 5) {
const QStringRef &bits = abiParts.at(4);
- if (!bits.endsWith(QLatin1String("bit")))
+ if (!bits.endsWith("bit"))
return;
bool ok = false;
@@ -487,89 +493,95 @@ Abi Abi::abiFromTargetTriplet(const QString &triple)
if (machine.isEmpty())
return Abi();
- const QVector<QStringRef> parts = machine.splitRef(QRegExp(QLatin1String("[ /-]")));
+ const QVector<QStringRef> parts = machine.splitRef(QRegExp("[ /-]"));
- Abi::Architecture arch = Abi::UnknownArchitecture;
- Abi::OS os = Abi::UnknownOS;
- Abi::OSFlavor flavor = Abi::UnknownFlavor;
- Abi::BinaryFormat format = Abi::UnknownFormat;
+ Architecture arch = UnknownArchitecture;
+ OS os = UnknownOS;
+ OSFlavor flavor = UnknownFlavor;
+ BinaryFormat format = UnknownFormat;
unsigned char width = 0;
int unknownCount = 0;
for (const QStringRef &p : parts) {
- if (p == QLatin1String("unknown") || p == QLatin1String("pc") || p == QLatin1String("none")
- || p == QLatin1String("gnu") || p == QLatin1String("uclibc")
- || p == QLatin1String("86_64") || p == QLatin1String("redhat")
- || p == QLatin1String("gnueabi") || p == QLatin1String("w64")) {
+ if (p == "unknown" || p == "pc" || p == "none"
+ || p == "gnu" || p == "uclibc"
+ || p == "86_64" || p == "redhat"
+ || p == "gnueabi" || p == "w64") {
continue;
- } else if (p == QLatin1String("i386") || p == QLatin1String("i486") || p == QLatin1String("i586")
- || p == QLatin1String("i686") || p == QLatin1String("x86")) {
- arch = Abi::X86Architecture;
+ } else if (p == "i386" || p == "i486" || p == "i586"
+ || p == "i686" || p == "x86") {
+ arch = X86Architecture;
width = 32;
- } else if (p.startsWith(QLatin1String("arm"))) {
- arch = Abi::ArmArchitecture;
- width = p.contains(QLatin1String("64")) ? 64 : 32;
- } else if (p.startsWith(QLatin1String("aarch64"))) {
- arch = Abi::ArmArchitecture;
+ } else if (p.startsWith("arm")) {
+ arch = ArmArchitecture;
+ width = p.contains("64") ? 64 : 32;
+ } else if (p.startsWith("aarch64")) {
+ arch = ArmArchitecture;
width = 64;
- } else if (p.startsWith(QLatin1String("mips"))) {
- arch = Abi::MipsArchitecture;
- width = p.contains(QLatin1String("64")) ? 64 : 32;
- } else if (p == QLatin1String("x86_64") || p == QLatin1String("amd64")) {
- arch = Abi::X86Architecture;
+ } else if (p == "avr") {
+ arch = AvrArchitecture;
+ os = BareMetalOS;
+ flavor = GenericBareMetalFlavor;
+ format = ElfFormat;
+ width = 16;
+ } else if (p.startsWith("mips")) {
+ arch = MipsArchitecture;
+ width = p.contains("64") ? 64 : 32;
+ } else if (p == "x86_64" || p == "amd64") {
+ arch = X86Architecture;
width = 64;
- } else if (p == QLatin1String("powerpc64")) {
- arch = Abi::PowerPCArchitecture;
+ } else if (p == "powerpc64") {
+ arch = PowerPCArchitecture;
width = 64;
- } else if (p == QLatin1String("powerpc")) {
- arch = Abi::PowerPCArchitecture;
+ } else if (p == "powerpc") {
+ arch = PowerPCArchitecture;
width = 32;
- } else if (p == QLatin1String("linux") || p == QLatin1String("linux6e")) {
- os = Abi::LinuxOS;
- if (flavor == Abi::UnknownFlavor)
- flavor = Abi::GenericLinuxFlavor;
- format = Abi::ElfFormat;
- } else if (p == QLatin1String("android")) {
- flavor = Abi::AndroidLinuxFlavor;
- } else if (p == QLatin1String("androideabi")) {
- flavor = Abi::AndroidLinuxFlavor;
- } else if (p.startsWith(QLatin1String("freebsd"))) {
- os = Abi::BsdOS;
- if (flavor == Abi::UnknownFlavor)
- flavor = Abi::FreeBsdFlavor;
- format = Abi::ElfFormat;
- } else if (p.startsWith(QLatin1String("openbsd"))) {
- os = Abi::BsdOS;
- if (flavor == Abi::UnknownFlavor)
- flavor = Abi::OpenBsdFlavor;
- format = Abi::ElfFormat;
- } else if (p == QLatin1String("mingw32") || p == QLatin1String("win32")
- || p == QLatin1String("mingw32msvc") || p == QLatin1String("msys")
- || p == QLatin1String("cygwin") || p == QLatin1String("windows")) {
- arch = Abi::X86Architecture;
- os = Abi::WindowsOS;
- flavor = Abi::WindowsMSysFlavor;
- format = Abi::PEFormat;
- } else if (p == QLatin1String("apple")) {
- os = Abi::DarwinOS;
- flavor = Abi::GenericDarwinFlavor;
- format = Abi::MachOFormat;
- } else if (p == QLatin1String("darwin10")) {
+ } else if (p == "linux" || p == "linux6e") {
+ os = LinuxOS;
+ if (flavor == UnknownFlavor)
+ flavor = GenericLinuxFlavor;
+ format = ElfFormat;
+ } else if (p == "android") {
+ flavor = AndroidLinuxFlavor;
+ } else if (p == "androideabi") {
+ flavor = AndroidLinuxFlavor;
+ } else if (p.startsWith("freebsd")) {
+ os = BsdOS;
+ if (flavor == UnknownFlavor)
+ flavor = FreeBsdFlavor;
+ format = ElfFormat;
+ } else if (p.startsWith("openbsd")) {
+ os = BsdOS;
+ if (flavor == UnknownFlavor)
+ flavor = OpenBsdFlavor;
+ format = ElfFormat;
+ } else if (p == "mingw32" || p == "win32"
+ || p == "mingw32msvc" || p == "msys"
+ || p == "cygwin" || p == "windows") {
+ arch = X86Architecture;
+ os = WindowsOS;
+ flavor = WindowsMSysFlavor;
+ format = PEFormat;
+ } else if (p == "apple") {
+ os = DarwinOS;
+ flavor = GenericDarwinFlavor;
+ format = MachOFormat;
+ } else if (p == "darwin10") {
width = 64;
- } else if (p == QLatin1String("darwin9")) {
+ } else if (p == "darwin9") {
width = 32;
- } else if (p == QLatin1String("gnueabi")) {
- format = Abi::ElfFormat;
- } else if (p == QLatin1String("wrs")) {
+ } else if (p == "gnueabi") {
+ format = ElfFormat;
+ } else if (p == "wrs") {
continue;
- } else if (p == QLatin1String("vxworks")) {
- os = Abi::VxWorks;
- flavor = Abi::VxWorksFlavor;
- format = Abi::ElfFormat;
- } else if (p.startsWith(QLatin1String("qnx"))) {
- os = Abi::QnxOS;
- flavor = Abi::GenericQnxFlavor;
- format = Abi::ElfFormat;
+ } else if (p == "vxworks") {
+ os = VxWorks;
+ flavor = VxWorksFlavor;
+ format = ElfFormat;
+ } else if (p.startsWith("qnx")) {
+ os = QnxOS;
+ flavor = GenericQnxFlavor;
+ format = ElfFormat;
} else {
++unknownCount;
}
@@ -580,14 +592,9 @@ Abi Abi::abiFromTargetTriplet(const QString &triple)
QString Abi::toString() const
{
- QStringList dn;
- dn << toString(m_architecture);
- dn << toString(m_os);
- dn << toString(m_osFlavor);
- dn << toString(m_binaryFormat);
- dn << toString(m_wordWidth);
-
- return dn.join(QLatin1Char('-'));
+ const QStringList dn = {toString(m_architecture), toString(m_os), toString(m_osFlavor),
+ toString(m_binaryFormat), toString(m_wordWidth)};
+ return dn.join('-');
}
bool Abi::operator != (const Abi &other) const
@@ -662,6 +669,8 @@ QString Abi::toString(const Architecture &a)
switch (a) {
case ArmArchitecture:
return QLatin1String("arm");
+ case AvrArchitecture:
+ return QLatin1String("avr");
case X86Architecture:
return QLatin1String("x86");
case MipsArchitecture:
@@ -695,6 +704,8 @@ QString Abi::toString(const OS &o)
return QLatin1String("vxworks");
case QnxOS:
return QLatin1String("qnx");
+ case BareMetalOS:
+ return QLatin1String("baremetal");
case UnknownOS: // fall through!
default:
return QLatin1String("unknown");
@@ -704,45 +715,46 @@ QString Abi::toString(const OS &o)
QString Abi::toString(const OSFlavor &of)
{
switch (of) {
- case Abi::GenericLinuxFlavor:
+ case GenericLinuxFlavor:
return QLatin1String("generic");
- case Abi::AndroidLinuxFlavor:
+ case AndroidLinuxFlavor:
return QLatin1String("android");
- case Abi::FreeBsdFlavor:
+ case FreeBsdFlavor:
return QLatin1String("freebsd");
- case Abi::NetBsdFlavor:
+ case NetBsdFlavor:
return QLatin1String("netbsd");
- case Abi::OpenBsdFlavor:
+ case OpenBsdFlavor:
return QLatin1String("openbsd");
- case Abi::GenericDarwinFlavor:
+ case GenericDarwinFlavor:
return QLatin1String("generic");
- case Abi::GenericUnixFlavor:
+ case GenericUnixFlavor:
return QLatin1String("generic");
- case Abi::SolarisUnixFlavor:
+ case SolarisUnixFlavor:
return QLatin1String("solaris");
- case Abi::WindowsMsvc2005Flavor:
+ case WindowsMsvc2005Flavor:
return QLatin1String("msvc2005");
- case Abi::WindowsMsvc2008Flavor:
+ case WindowsMsvc2008Flavor:
return QLatin1String("msvc2008");
- case Abi::WindowsMsvc2010Flavor:
+ case WindowsMsvc2010Flavor:
return QLatin1String("msvc2010");
- case Abi::WindowsMsvc2012Flavor:
+ case WindowsMsvc2012Flavor:
return QLatin1String("msvc2012");
- case Abi::WindowsMsvc2013Flavor:
+ case WindowsMsvc2013Flavor:
return QLatin1String("msvc2013");
- case Abi::WindowsMsvc2015Flavor:
+ case WindowsMsvc2015Flavor:
return QLatin1String("msvc2015");
- case Abi::WindowsMsvc2017Flavor:
+ case WindowsMsvc2017Flavor:
return QLatin1String("msvc2017");
- case Abi::WindowsMSysFlavor:
+ case WindowsMSysFlavor:
return QLatin1String("msys");
- case Abi::WindowsCEFlavor:
+ case WindowsCEFlavor:
return QLatin1String("ce");
- case Abi::VxWorksFlavor:
+ case VxWorksFlavor:
return QLatin1String("vxworks");
- case Abi::GenericQnxFlavor:
+ case GenericQnxFlavor:
+ case GenericBareMetalFlavor:
return QLatin1String("generic");
- case Abi::UnknownFlavor: // fall through!
+ case UnknownFlavor: // fall through!
default:
return QLatin1String("unknown");
}
@@ -777,24 +789,25 @@ QList<Abi::OSFlavor> Abi::flavorsForOs(const Abi::OS &o)
QList<OSFlavor> result;
switch (o) {
case BsdOS:
- return result << FreeBsdFlavor << OpenBsdFlavor << NetBsdFlavor << UnknownFlavor;
+ return {FreeBsdFlavor, OpenBsdFlavor, NetBsdFlavor, UnknownFlavor};
case LinuxOS:
- return result << GenericLinuxFlavor << AndroidLinuxFlavor << UnknownFlavor;
+ return {GenericLinuxFlavor, AndroidLinuxFlavor, UnknownFlavor};
case DarwinOS:
- return result << GenericDarwinFlavor << UnknownFlavor;
+ return {GenericDarwinFlavor, UnknownFlavor};
case UnixOS:
- return result << GenericUnixFlavor << SolarisUnixFlavor << UnknownFlavor;
+ return {GenericUnixFlavor, SolarisUnixFlavor, UnknownFlavor};
case WindowsOS:
- return result << WindowsMsvc2005Flavor << WindowsMsvc2008Flavor << WindowsMsvc2010Flavor
- << WindowsMsvc2012Flavor << WindowsMsvc2013Flavor << WindowsMsvc2015Flavor
- << WindowsMsvc2017Flavor
- << WindowsMSysFlavor << WindowsCEFlavor << UnknownFlavor;
+ return {WindowsMsvc2005Flavor, WindowsMsvc2008Flavor, WindowsMsvc2010Flavor,
+ WindowsMsvc2012Flavor, WindowsMsvc2013Flavor, WindowsMsvc2015Flavor,
+ WindowsMsvc2017Flavor , WindowsMSysFlavor, WindowsCEFlavor, UnknownFlavor};
case VxWorks:
- return result << VxWorksFlavor << UnknownFlavor;
+ return {VxWorksFlavor, UnknownFlavor};
case QnxOS:
- return result << GenericQnxFlavor << UnknownFlavor;
+ return {GenericQnxFlavor, UnknownFlavor};
+ case BareMetalOS:
+ return {GenericBareMetalFlavor};
case UnknownOS:
- return result << UnknownFlavor;
+ return {UnknownFlavor};
default:
break;
}
@@ -896,7 +909,7 @@ QList<Abi> Abi::abisOfBinary(const Utils::FileName &path)
const QString fileName = QString::fromLocal8Bit(data.mid(0, 16));
quint64 fileNameOffset = 0;
- if (fileName.startsWith(QLatin1String("#1/")))
+ if (fileName.startsWith("#1/"))
fileNameOffset = fileName.midRef(3).toInt();
const QString fileLength = QString::fromLatin1(data.mid(48, 10));
@@ -904,11 +917,10 @@ QList<Abi> Abi::abisOfBinary(const Utils::FileName &path)
offset += fileLength.toInt() + 60 /* header */;
tmp.append(abiOf(data.mid(toSkip)));
- if (tmp.isEmpty() && fileName == QLatin1String("/0 "))
+ if (tmp.isEmpty() && fileName == "/0 ")
tmp = parseCoffHeader(data.mid(toSkip, 20)); // This might be windws...
- if (!tmp.isEmpty()
- && tmp.at(0).binaryFormat() != Abi::MachOFormat)
+ if (!tmp.isEmpty() && tmp.at(0).binaryFormat() != MachOFormat)
break;
offset += (offset % 2); // ar is 2 byte aligned
@@ -955,7 +967,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary_data()
QString prefix = QString::fromLocal8Bit(qgetenv("QTC_TEST_EXTRADATALOCATION"));
if (prefix.isEmpty())
return;
- prefix += QLatin1String("/projectexplorer/abi");
+ prefix += "/projectexplorer/abi";
QFileInfo fi(prefix);
if (!fi.exists() || !fi.isDir())
@@ -1074,7 +1086,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary()
QFETCH(QString, file);
QFETCH(QStringList, abis);
- QList<ProjectExplorer::Abi> result = Abi::abisOfBinary(Utils::FileName::fromString(file));
+ QList<Abi> result = Abi::abisOfBinary(Utils::FileName::fromString(file));
QCOMPARE(result.count(), abis.count());
for (int i = 0; i < abis.count(); ++i)
QCOMPARE(result.at(i).toString(), abis.at(i));
@@ -1082,7 +1094,7 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary()
void ProjectExplorer::ProjectExplorerPlugin::testFlavorForOs()
{
- QList<QList<ProjectExplorer::Abi::OSFlavor> > flavorLists;
+ QList<QList<Abi::OSFlavor> > flavorLists;
for (int i = 0; i != static_cast<int>(Abi::UnknownOS); ++i)
flavorLists.append(Abi::flavorsForOs(static_cast<Abi::OS>(i)));
@@ -1214,6 +1226,11 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiFromTargetTriplet_data()
QTest::newRow("aarch64-unknown-linux-gnu") << int(Abi::ArmArchitecture)
<< int(Abi::LinuxOS) << int(Abi::GenericLinuxFlavor)
<< int(Abi::ElfFormat) << 64;
+
+ // Yes, that's the entire triplet
+ QTest::newRow("avr") << int(Abi::AvrArchitecture)
+ << int(Abi::BareMetalOS) << int(Abi::GenericBareMetalFlavor)
+ << int(Abi::ElfFormat) << 16;
}
void ProjectExplorer::ProjectExplorerPlugin::testAbiFromTargetTriplet()
@@ -1226,7 +1243,8 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiFromTargetTriplet()
const Abi expectedAbi = Abi(Abi::Architecture(architecture),
Abi::OS(os), Abi::OSFlavor(osFlavor),
- Abi::BinaryFormat(binaryFormat), (unsigned char)wordWidth);
+ Abi::BinaryFormat(binaryFormat),
+ static_cast<unsigned char>(wordWidth));
QCOMPARE(Abi::abiFromTargetTriplet(QLatin1String(QTest::currentDataTag())), expectedAbi);
}
diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h
index 06157aa81b..3fc3cbe1b1 100644
--- a/src/plugins/projectexplorer/abi.h
+++ b/src/plugins/projectexplorer/abi.h
@@ -48,6 +48,7 @@ public:
MipsArchitecture,
PowerPCArchitecture,
ShArchitecture,
+ AvrArchitecture,
UnknownArchitecture
};
@@ -59,6 +60,7 @@ public:
WindowsOS,
VxWorks,
QnxOS,
+ BareMetalOS,
UnknownOS
};
@@ -90,10 +92,10 @@ public:
WindowsMSysFlavor,
WindowsCEFlavor,
+ // Embedded
VxWorksFlavor,
-
- // QNX
GenericQnxFlavor,
+ GenericBareMetalFlavor,
UnknownFlavor
};
diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp
index 121e2b43b4..44d961ba08 100644
--- a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp
+++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp
@@ -118,7 +118,7 @@ ToolChain::PredefinedMacrosRunner AbstractMsvcToolChain::createPredefinedMacrosR
};
}
-QByteArray AbstractMsvcToolChain::predefinedMacros(const QStringList &cxxflags) const
+ProjectExplorer::Macros AbstractMsvcToolChain::predefinedMacros(const QStringList &cxxflags) const
{
return createPredefinedMacrosRunner()(cxxflags);
}
@@ -277,13 +277,6 @@ bool AbstractMsvcToolChain::canClone() const
return true;
}
-// Function must be thread-safe!
-QByteArray AbstractMsvcToolChain::msvcPredefinedMacros(const QStringList,
- const Utils::Environment&) const
-{
- return QByteArray();
-}
-
bool AbstractMsvcToolChain::generateEnvironmentSettings(const Utils::Environment &env,
const QString &batchFile,
const QString &batchArgs,
diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.h b/src/plugins/projectexplorer/abstractmsvctoolchain.h
index 9a96faea0e..0851e09cc0 100644
--- a/src/plugins/projectexplorer/abstractmsvctoolchain.h
+++ b/src/plugins/projectexplorer/abstractmsvctoolchain.h
@@ -53,7 +53,7 @@ public:
QString originalTargetTriple() const override;
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
- QByteArray predefinedMacros(const QStringList &cxxflags) const override;
+ Macros predefinedMacros(const QStringList &cxxflags) const override;
CompilerFlags compilerFlags(const QStringList &cxxflags) const override;
WarningFlags warningFlags(const QStringList &cflags) const override;
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
@@ -92,13 +92,14 @@ protected:
static void inferWarningsForLevel(int warningLevel, WarningFlags &flags);
virtual Utils::Environment readEnvironmentSetting(const Utils::Environment& env) const = 0;
- virtual QByteArray msvcPredefinedMacros(const QStringList cxxflags,
- const Utils::Environment& env) const;
+ // Function must be thread-safe!
+ virtual Macros msvcPredefinedMacros(const QStringList cxxflags,
+ const Utils::Environment& env) const = 0;
Utils::FileName m_debuggerCommand;
mutable QMutex *m_predefinedMacrosMutex = nullptr;
- mutable QByteArray m_predefinedMacros;
+ mutable Macros m_predefinedMacros;
mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment.
mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC
mutable QMutex *m_headerPathsMutex = nullptr;
diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp
index 09007fe8b2..676b1de19b 100644
--- a/src/plugins/projectexplorer/appoutputpane.cpp
+++ b/src/plugins/projectexplorer/appoutputpane.cpp
@@ -397,6 +397,8 @@ void AppOutputPane::updateBehaviorSettings()
void AppOutputPane::createNewOutputWindow(RunControl *rc)
{
+ QTC_ASSERT(rc, return);
+
connect(rc, &RunControl::aboutToStart,
this, &AppOutputPane::slotRunControlChanged);
connect(rc, &RunControl::started,
@@ -418,7 +420,7 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
if (tab.runControl)
tab.runControl->initiateFinish();
tab.runControl = rc;
- tab.window->setFormatter(rc ? rc->outputFormatter() : nullptr);
+ tab.window->setFormatter(rc->outputFormatter());
handleOldOutput(tab.window);
@@ -532,9 +534,9 @@ void AppOutputPane::stopRunControl()
if (rc->isRunning() && optionallyPromptToStop(rc))
rc->initiateStop();
- else if (rc->isStarting()) {
+ else {
QTC_CHECK(false);
- rc->initiateStop();
+ rc->forceStop();
}
if (debug)
diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
index 2d7a9588f8..61a66a1206 100644
--- a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
+++ b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
@@ -26,6 +26,7 @@
#include "baseprojectwizarddialog.h"
#include <coreplugin/documentmanager.h>
+#include <utils/fileutils.h>
#include <utils/projectintropage.h>
#include <QDir>
@@ -144,7 +145,7 @@ void BaseProjectWizardDialog::slotAccepted()
{
if (d->introPage->useAsDefaultPath()) {
// Store the path as default path for new projects if desired.
- Core::DocumentManager::setProjectsDirectory(path());
+ Core::DocumentManager::setProjectsDirectory(Utils::FileName::fromString(path()));
Core::DocumentManager::setUseProjectsDirectory(true);
}
}
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index 3464c033f6..705d9b9b96 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -52,9 +52,10 @@ static const char BUILDDIRECTORY_KEY[] = "ProjectExplorer.BuildConfiguration.Bui
namespace ProjectExplorer {
BuildConfiguration::BuildConfiguration(Target *target, Core::Id id) :
- ProjectConfiguration(target, id),
+ ProjectConfiguration(target),
m_clearSystemEnvironment(false)
{
+ initialize(id);
Q_ASSERT(target);
auto bsl = new BuildStepList(this, Core::Id(Constants::BUILDSTEPS_BUILD));
//: Display name of the build build step list. Used as part of the labels in the project window.
@@ -76,11 +77,12 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id) :
}
BuildConfiguration::BuildConfiguration(Target *target, BuildConfiguration *source) :
- ProjectConfiguration(target, source),
+ ProjectConfiguration(target),
m_clearSystemEnvironment(source->m_clearSystemEnvironment),
m_userEnvironmentChanges(source->m_userEnvironmentChanges),
m_buildDirectory(source->m_buildDirectory)
{
+ copyFrom(source);
Q_ASSERT(target);
// Do not clone stepLists here, do that in the derived constructor instead
// otherwise BuildStepFactories might reject to set up a BuildStep for us
@@ -226,6 +228,11 @@ Target *BuildConfiguration::target() const
return static_cast<Target *>(parent());
}
+Project *BuildConfiguration::project() const
+{
+ return target()->project();
+}
+
Utils::Environment BuildConfiguration::baseEnvironment() const
{
Utils::Environment result;
@@ -318,6 +325,11 @@ QString BuildConfiguration::buildTypeName(BuildConfiguration::BuildType type)
}
}
+bool BuildConfiguration::isActive() const
+{
+ return target()->isActive() && target()->activeBuildConfiguration() == this;
+}
+
///
// IBuildConfigurationFactory
///
diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h
index 03d42d4dbd..cc30d2ba44 100644
--- a/src/plugins/projectexplorer/buildconfiguration.h
+++ b/src/plugins/projectexplorer/buildconfiguration.h
@@ -73,6 +73,7 @@ public:
QVariantMap toMap() const override;
Target *target() const;
+ Project *project() const override;
virtual bool isEnabled() const;
virtual QString disabledReason() const;
@@ -87,6 +88,8 @@ public:
static QString buildTypeName(BuildType type);
+ bool isActive() const override;
+
signals:
void environmentChanged();
void buildDirectoryChanged();
diff --git a/src/plugins/projectexplorer/buildconfigurationmodel.cpp b/src/plugins/projectexplorer/buildconfigurationmodel.cpp
deleted file mode 100644
index b8ef079f38..0000000000
--- a/src/plugins/projectexplorer/buildconfigurationmodel.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "buildconfigurationmodel.h"
-#include "target.h"
-#include "buildconfiguration.h"
-
-#include <utils/algorithm.h>
-
-using namespace ProjectExplorer;
-
-/*!
- \class ProjectExplorer::BuildConfigurationModel
- \brief The BuildConfigurationModel class is a model to represent the build
- configurations of a target.
-
- To be used in the dropdown lists of comboboxes.
- Automatically adjusts itself to added and removed BuildConfigurations.
- Very similar to the Run Configuration Model.
-
- TODO might it possible to share code without making the code a complete mess.
-*/
-
-class BuildConfigurationComparer
-{
-public:
- bool operator()(BuildConfiguration *a, BuildConfiguration *b)
- {
- return a->displayName() < b->displayName();
- }
-};
-
-BuildConfigurationModel::BuildConfigurationModel(Target *target, QObject *parent)
- : QAbstractListModel(parent),
- m_target(target)
-{
- m_buildConfigurations = m_target->buildConfigurations();
- Utils::sort(m_buildConfigurations, BuildConfigurationComparer());
-
- connect(target, &Target::addedBuildConfiguration,
- this, &BuildConfigurationModel::addedBuildConfiguration);
- connect(target, &Target::removedBuildConfiguration,
- this, &BuildConfigurationModel::removedBuildConfiguration);
-
- foreach (BuildConfiguration *bc, m_buildConfigurations)
- connect(bc, &ProjectConfiguration::displayNameChanged,
- this, &BuildConfigurationModel::displayNameChanged);
-}
-
-int BuildConfigurationModel::rowCount(const QModelIndex &parent) const
-{
- return parent.isValid() ? 0 : m_buildConfigurations.size();
-}
-
-int BuildConfigurationModel::columnCount(const QModelIndex &parent) const
-{
- return parent.isValid() ? 0 : 1;
-}
-
-void BuildConfigurationModel::displayNameChanged()
-{
- auto rc = qobject_cast<BuildConfiguration *>(sender());
- if (!rc)
- return;
-
- BuildConfigurationComparer compare;
- // Find the old position
- int oldPos = m_buildConfigurations.indexOf(rc);
-
- if (oldPos >= 1 && compare(m_buildConfigurations.at(oldPos), m_buildConfigurations.at(oldPos - 1))) {
- // We need to move up
- int newPos = oldPos - 1;
- while (newPos >= 0 && compare(m_buildConfigurations.at(oldPos), m_buildConfigurations.at(newPos))) {
- --newPos;
- }
- ++newPos;
-
- beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
- m_buildConfigurations.insert(newPos, rc);
- m_buildConfigurations.removeAt(oldPos + 1);
- endMoveRows();
- // Not only did we move, we also changed...
- emit dataChanged(index(newPos, 0), index(newPos,0));
- } else if (oldPos < m_buildConfigurations.size() - 1
- && compare(m_buildConfigurations.at(oldPos + 1), m_buildConfigurations.at(oldPos))) {
- // We need to move down
- int newPos = oldPos + 1;
- while (newPos < m_buildConfigurations.size()
- && compare(m_buildConfigurations.at(newPos), m_buildConfigurations.at(oldPos))) {
- ++newPos;
- }
- beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
- m_buildConfigurations.insert(newPos, rc);
- m_buildConfigurations.removeAt(oldPos);
- endMoveRows();
-
- // We need to subtract one since removing at the old place moves the newIndex down
- emit dataChanged(index(newPos - 1, 0), index(newPos - 1, 0));
- } else {
- emit dataChanged(index(oldPos, 0), index(oldPos, 0));
- }
-}
-
-QVariant BuildConfigurationModel::data(const QModelIndex &index, int role) const
-{
- if (role == Qt::DisplayRole) {
- const int row = index.row();
- if (row < m_buildConfigurations.size())
- return m_buildConfigurations.at(row)->displayName();
- }
-
- return QVariant();
-}
-
-BuildConfiguration *BuildConfigurationModel::buildConfigurationAt(int i)
-{
- if (i > m_buildConfigurations.size() || i < 0)
- return 0;
- return m_buildConfigurations.at(i);
-}
-
-BuildConfiguration *BuildConfigurationModel::buildConfigurationFor(const QModelIndex &idx)
-{
- if (idx.row() > m_buildConfigurations.size() || idx.row() < 0)
- return 0;
- return m_buildConfigurations.at(idx.row());
-}
-
-QModelIndex BuildConfigurationModel::indexFor(BuildConfiguration *rc)
-{
- int idx = m_buildConfigurations.indexOf(rc);
- if (idx == -1)
- return QModelIndex();
- return index(idx, 0);
-}
-
-void BuildConfigurationModel::addedBuildConfiguration(BuildConfiguration *bc)
-{
- // Find the right place to insert
- BuildConfigurationComparer compare;
- int i = 0;
- for (; i < m_buildConfigurations.size(); ++i) {
- if (compare(bc, m_buildConfigurations.at(i)))
- break;
- }
-
- beginInsertRows(QModelIndex(), i, i);
- m_buildConfigurations.insert(i, bc);
- endInsertRows();
-
-
- connect(bc, &ProjectConfiguration::displayNameChanged,
- this, &BuildConfigurationModel::displayNameChanged);
-}
-
-void BuildConfigurationModel::removedBuildConfiguration(BuildConfiguration *bc)
-{
- int i = m_buildConfigurations.indexOf(bc);
- beginRemoveRows(QModelIndex(), i, i);
- m_buildConfigurations.removeAt(i);
- endRemoveRows();
-}
diff --git a/src/plugins/projectexplorer/buildconfigurationmodel.h b/src/plugins/projectexplorer/buildconfigurationmodel.h
deleted file mode 100644
index b5712f85fc..0000000000
--- a/src/plugins/projectexplorer/buildconfigurationmodel.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QAbstractItemModel>
-
-namespace ProjectExplorer {
-class Target;
-class BuildConfiguration;
-
-// Documentation inside.
-class BuildConfigurationModel : public QAbstractListModel
-{
- Q_OBJECT
-public:
- explicit BuildConfigurationModel(Target *target, QObject *parent = nullptr);
-
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-
- BuildConfiguration *buildConfigurationAt(int i);
- BuildConfiguration *buildConfigurationFor(const QModelIndex &idx);
- QModelIndex indexFor(BuildConfiguration *rc);
-
-private:
- void addedBuildConfiguration(ProjectExplorer::BuildConfiguration*);
- void removedBuildConfiguration(ProjectExplorer::BuildConfiguration*);
- void displayNameChanged();
-
- Target *m_target;
- QList<BuildConfiguration *> m_buildConfigurations;
-};
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/buildenvironmentwidget.cpp b/src/plugins/projectexplorer/buildenvironmentwidget.cpp
index f7f253d94b..3177f7e6b1 100644
--- a/src/plugins/projectexplorer/buildenvironmentwidget.cpp
+++ b/src/plugins/projectexplorer/buildenvironmentwidget.cpp
@@ -53,7 +53,7 @@ BuildEnvironmentWidget::BuildEnvironmentWidget(BuildConfiguration *bc) :
m_buildConfiguration = bc;
- connect(m_buildConfiguration->target(), &Target::environmentChanged,
+ connect(m_buildConfiguration, &BuildConfiguration::environmentChanged,
this, &BuildEnvironmentWidget::environmentChanged);
m_clearSystemEnvironmentCheckBox->setChecked(!m_buildConfiguration->useSystemEnvironment());
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index 6319a59aea..a144680a74 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -29,7 +29,7 @@
#include "project.h"
#include "target.h"
#include "buildconfiguration.h"
-#include "buildconfigurationmodel.h"
+#include "projectconfigurationmodel.h"
#include "session.h"
#include <utils/qtcassert.h>
@@ -218,7 +218,7 @@ void BuildSettingsWidget::updateBuildSettings()
void BuildSettingsWidget::currentIndexChanged(int index)
{
auto model = static_cast<BuildConfigurationModel *>(m_buildConfigurationComboBox->model());
- BuildConfiguration *buildConfiguration = model->buildConfigurationAt(index);
+ auto buildConfiguration = qobject_cast<BuildConfiguration *>(model->projectConfigurationAt(index));
SessionManager::setActiveBuildConfiguration(m_target, buildConfiguration, SetActive::Cascade);
}
diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp
index d428b0bef3..40c31f0c9f 100644
--- a/src/plugins/projectexplorer/buildstep.cpp
+++ b/src/plugins/projectexplorer/buildstep.cpp
@@ -112,15 +112,17 @@ static const char buildStepEnabledKey[] = "ProjectExplorer.BuildStep.Enabled";
using namespace ProjectExplorer;
BuildStep::BuildStep(BuildStepList *bsl, Core::Id id) :
- ProjectConfiguration(bsl, id), m_enabled(true)
+ ProjectConfiguration(bsl), m_enabled(true)
{
+ initialize(id);
Q_ASSERT(bsl);
ctor();
}
BuildStep::BuildStep(BuildStepList *bsl, BuildStep *bs) :
- ProjectConfiguration(bsl, bs), m_enabled(bs->m_enabled)
+ ProjectConfiguration(bsl), m_enabled(bs->m_enabled)
{
+ copyFrom(bs);
Q_ASSERT(bsl);
setDisplayName(bs->displayName());
ctor();
@@ -136,14 +138,14 @@ void BuildStep::ctor()
bool BuildStep::fromMap(const QVariantMap &map)
{
- m_enabled = map.value(QLatin1String(buildStepEnabledKey), true).toBool();
+ m_enabled = map.value(buildStepEnabledKey, true).toBool();
return ProjectConfiguration::fromMap(map);
}
QVariantMap BuildStep::toMap() const
{
QVariantMap map = ProjectConfiguration::toMap();
- map.insert(QLatin1String(buildStepEnabledKey), m_enabled);
+ map.insert(buildStepEnabledKey, m_enabled);
return map;
}
@@ -178,6 +180,11 @@ void BuildStep::reportRunResult(QFutureInterface<bool> &fi, bool success)
fi.reportFinished();
}
+bool BuildStep::isActive() const
+{
+ return projectConfiguration()->isActive();
+}
+
/*!
If this function returns \c true, the user cannot delete this build step for
this target and the user is prevented from changing the order in which
diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h
index bd907d9dde..2fe6ee1960 100644
--- a/src/plugins/projectexplorer/buildstep.h
+++ b/src/plugins/projectexplorer/buildstep.h
@@ -70,7 +70,7 @@ public:
DeployConfiguration *deployConfiguration() const;
ProjectConfiguration *projectConfiguration() const;
Target *target() const;
- Project *project() const;
+ Project *project() const override;
enum class OutputFormat {
Stdout, Stderr, // These are for forwarded output from external tools
@@ -81,6 +81,8 @@ public:
static void reportRunResult(QFutureInterface<bool> &fi, bool success);
+ bool isActive() const override;
+
signals:
/// Adds a \p task to the Issues pane.
/// Do note that for linking compile output with tasks, you should first emit the task
@@ -97,7 +99,7 @@ signals:
private:
void ctor();
- bool m_enabled;
+ bool m_enabled = true;
};
class PROJECTEXPLORER_EXPORT BuildStepInfo
diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp
index 51b25fe204..0cb7e618a5 100644
--- a/src/plugins/projectexplorer/buildsteplist.cpp
+++ b/src/plugins/projectexplorer/buildsteplist.cpp
@@ -45,14 +45,16 @@ const char STEPS_PREFIX[] = "ProjectExplorer.BuildStepList.Step.";
} // namespace
BuildStepList::BuildStepList(QObject *parent, Core::Id id) :
- ProjectConfiguration(parent, id)
+ ProjectConfiguration(parent)
{
Q_ASSERT(parent);
+ initialize(id);
}
BuildStepList::BuildStepList(QObject *parent, BuildStepList *source) :
- ProjectConfiguration(parent, source)
+ ProjectConfiguration(parent)
{
+ copyFrom(source);
setDisplayName(source->displayName());
Q_ASSERT(parent);
// do not clone the steps here:
@@ -116,6 +118,11 @@ void BuildStepList::cloneSteps(BuildStepList *source)
}
}
+bool BuildStepList::isActive() const
+{
+ return qobject_cast<ProjectConfiguration *>(parent())->isActive();
+}
+
bool BuildStepList::fromMap(const QVariantMap &map)
{
// We need the ID set before trying to restore the steps!
@@ -198,3 +205,8 @@ Target *BuildStepList::target() const
return dc->target();
return 0;
}
+
+Project *BuildStepList::project() const
+{
+ return target()->project();
+}
diff --git a/src/plugins/projectexplorer/buildsteplist.h b/src/plugins/projectexplorer/buildsteplist.h
index 1ca131e2eb..8a1c6659bc 100644
--- a/src/plugins/projectexplorer/buildsteplist.h
+++ b/src/plugins/projectexplorer/buildsteplist.h
@@ -78,11 +78,14 @@ public:
BuildStep *at(int position);
Target *target() const;
+ Project *project() const override;
virtual QVariantMap toMap() const override;
virtual bool fromMap(const QVariantMap &map) override;
void cloneSteps(BuildStepList *source);
+ bool isActive() const override;
+
signals:
void stepInserted(int position);
void aboutToRemoveStep(int position);
diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp
index fb56d5d2c6..2f1e4f75a0 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.cpp
+++ b/src/plugins/projectexplorer/compileoutputwindow.cpp
@@ -35,6 +35,7 @@
#include <coreplugin/outputwindow.h>
#include <coreplugin/find/basetextfind.h>
#include <coreplugin/icore.h>
+#include <coreplugin/coreconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/fontsettings.h>
@@ -55,7 +56,6 @@ using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
namespace {
-const int MAX_LINECOUNT = 100000;
const char SETTINGS_KEY[] = "ProjectExplorer/CompileOutput/Zoom";
const char C_COMPILE_OUTPUT[] = "ProjectExplorer.CompileOutput";
}
@@ -159,7 +159,7 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
m_outputWindow->setWindowIcon(Icons::WINDOW.icon());
m_outputWindow->setReadOnly(true);
m_outputWindow->setUndoRedoEnabled(false);
- m_outputWindow->setMaxLineCount(MAX_LINECOUNT);
+ m_outputWindow->setMaxLineCount(Core::Constants::DEFAULT_MAX_LINE_COUNT);
// Let selected text be colored as if the text edit was editable,
// otherwise the highlight for searching is too light
@@ -199,8 +199,8 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
m_handler = new ShowOutputTaskHandler(this);
ExtensionSystem::PluginManager::addObject(m_handler);
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
- this, &CompileOutputWindow::updateWordWrapMode);
- updateWordWrapMode();
+ this, &CompileOutputWindow::updateFromSettings);
+ updateFromSettings();
}
CompileOutputWindow::~CompileOutputWindow()
@@ -223,9 +223,10 @@ void CompileOutputWindow::updateZoomEnabled()
m_outputWindow->setWheelZoomEnabled(zoomEnabled);
}
-void CompileOutputWindow::updateWordWrapMode()
+void CompileOutputWindow::updateFromSettings()
{
m_outputWindow->setWordWrapEnabled(ProjectExplorerPlugin::projectExplorerSettings().wrapAppOutput);
+ m_outputWindow->setMaxLineCount(ProjectExplorerPlugin::projectExplorerSettings().maxBuildOutputLines);
}
bool CompileOutputWindow::hasFocus() const
@@ -323,7 +324,7 @@ void CompileOutputWindow::registerPositionOf(const Task &task, int linkedOutputL
if (linkedOutputLines <= 0)
return;
int blocknumber = m_outputWindow->document()->blockCount();
- if (blocknumber > MAX_LINECOUNT)
+ if (blocknumber > m_outputWindow->maxLineCount())
return;
const int startLine = blocknumber - linkedOutputLines + 1 - skipLines;
diff --git a/src/plugins/projectexplorer/compileoutputwindow.h b/src/plugins/projectexplorer/compileoutputwindow.h
index 043b07001b..3e9e3b0b51 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.h
+++ b/src/plugins/projectexplorer/compileoutputwindow.h
@@ -82,7 +82,7 @@ public:
void flush();
private:
- void updateWordWrapMode();
+ void updateFromSettings();
void updateZoomEnabled();
CompileOutputTextEdit *m_outputWindow;
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
index dc2dbc9603..c349e85089 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
@@ -82,32 +82,32 @@ private:
CustomExecutableConfigurationWidget *m_widget;
};
-
-void CustomExecutableRunConfiguration::ctor()
-{
- setDefaultDisplayName(defaultDisplayName());
-}
-
-CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *parent) :
- RunConfiguration(parent, CUSTOM_EXECUTABLE_ID)
+CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
addExtraAspect(new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()));
addExtraAspect(new ArgumentsAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.Arguments"));
addExtraAspect(new TerminalAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal"));
- if (parent->activeBuildConfiguration())
+}
+
+void CustomExecutableRunConfiguration::initialize()
+{
+ RunConfiguration::initialize(CUSTOM_EXECUTABLE_ID);
+ if (target()->activeBuildConfiguration())
m_workingDirectory = Constants::DEFAULT_WORKING_DIR;
else
m_workingDirectory = Constants::DEFAULT_WORKING_DIR_ALTERNATE;
- ctor();
+
+ setDefaultDisplayName(defaultDisplayName());
}
-CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *parent,
- CustomExecutableRunConfiguration *source) :
- RunConfiguration(parent, source),
- m_executable(source->m_executable),
- m_workingDirectory(source->m_workingDirectory)
+void CustomExecutableRunConfiguration::copyFrom(const CustomExecutableRunConfiguration *source)
{
- ctor();
+ RunConfiguration::copyFrom(source);
+ m_executable = source->m_executable;
+ m_workingDirectory = source->m_workingDirectory;
+
+ setDefaultDisplayName(defaultDisplayName());
}
// Note: Qt4Project deletes all empty customexecrunconfigs for which isConfigured() == false.
@@ -336,7 +336,7 @@ RunConfiguration *
CustomExecutableRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
Q_UNUSED(id);
- return new CustomExecutableRunConfiguration(parent);
+ return createHelper<CustomExecutableRunConfiguration>(parent);
}
bool CustomExecutableRunConfigurationFactory::canRestore(Target *parent,
@@ -352,7 +352,7 @@ RunConfiguration *
CustomExecutableRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
{
Q_UNUSED(map);
- return new CustomExecutableRunConfiguration(parent);
+ return createHelper<CustomExecutableRunConfiguration>(parent);
}
bool CustomExecutableRunConfigurationFactory::canClone(Target *parent,
@@ -366,7 +366,7 @@ CustomExecutableRunConfigurationFactory::clone(Target *parent, RunConfiguration
{
if (!canClone(parent, source))
return 0;
- return new CustomExecutableRunConfiguration(parent, static_cast<CustomExecutableRunConfiguration*>(source));
+ return cloneHelper<CustomExecutableRunConfiguration>(parent, source);
}
bool CustomExecutableRunConfigurationFactory::canHandle(Target *parent) const
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.h b/src/plugins/projectexplorer/customexecutablerunconfiguration.h
index 972ec74ea4..65cdec20c4 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.h
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.h
@@ -35,17 +35,15 @@ class CustomExecutableDialog;
namespace Internal { class CustomExecutableConfigurationWidget; }
-class CustomExecutableRunConfigurationFactory;
-
class PROJECTEXPLORER_EXPORT CustomExecutableRunConfiguration : public RunConfiguration
{
Q_OBJECT
// the configuration widget needs to setExecutable setWorkingDirectory and setCommandLineArguments
friend class Internal::CustomExecutableConfigurationWidget;
- friend class CustomExecutableRunConfigurationFactory;
+ friend class ProjectExplorer::IRunConfigurationFactory;
public:
- explicit CustomExecutableRunConfiguration(Target *parent);
+ explicit CustomExecutableRunConfiguration(Target *target);
~CustomExecutableRunConfiguration() override;
/**
@@ -68,8 +66,8 @@ signals:
void changed();
protected:
- CustomExecutableRunConfiguration(Target *parent,
- CustomExecutableRunConfiguration *source);
+ void initialize();
+ void copyFrom(const CustomExecutableRunConfiguration *source);
virtual bool fromMap(const QVariantMap &map) override;
QString defaultDisplayName() const;
diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp
index 06a3b041e8..dc0989eed1 100644
--- a/src/plugins/projectexplorer/customtoolchain.cpp
+++ b/src/plugins/projectexplorer/customtoolchain.cpp
@@ -32,6 +32,7 @@
#include "customparser.h"
#include "customparserconfigdialog.h"
#include "projectexplorerconstants.h"
+#include "projectmacro.h"
#include "toolchainmanager.h"
#include <utils/algorithm.h>
@@ -118,39 +119,24 @@ bool CustomToolChain::isValid() const
ToolChain::PredefinedMacrosRunner CustomToolChain::createPredefinedMacrosRunner() const
{
- const QStringList theMacros = m_predefinedMacros;
+ const Macros theMacros = m_predefinedMacros;
// This runner must be thread-safe!
return [theMacros](const QStringList &cxxflags){
QByteArray result;
- QStringList macros = theMacros;
+ Macros macros = theMacros;
for (const QString &cxxFlag : cxxflags) {
- if (cxxFlag.startsWith(QLatin1String("-D"))) {
- macros << cxxFlag.mid(2).trimmed();
- } else if (cxxFlag.startsWith(QLatin1String("-U"))) {
- const QString &removedName = cxxFlag.mid(2).trimmed();
- for (int i = macros.size() - 1; i >= 0; --i) {
- const QString &m = macros.at(i);
- if (m.left(m.indexOf(QLatin1Char('='))) == removedName)
- macros.removeAt(i);
- }
- }
- }
- for (const QString &str : Utils::asConst(macros)) {
- QByteArray ba = str.toUtf8();
- int equals = ba.indexOf('=');
- if (equals == -1) {
- result += "#define " + ba.trimmed() + '\n';
- } else {
- result += "#define " + ba.left(equals).trimmed() + ' '
- + ba.mid(equals + 1).trimmed() + '\n';
- }
+ if (cxxFlag.startsWith(QLatin1String("-D")))
+ macros.append(Macro::fromKeyValue(cxxFlag.mid(2).trimmed()));
+ else if (cxxFlag.startsWith(QLatin1String("-U")) && !cxxFlag.contains('='))
+ macros.append({cxxFlag.mid(2).trimmed().toUtf8(), MacroType::Undefine});
+
}
- return result;
+ return macros;
};
}
-QByteArray CustomToolChain::predefinedMacros(const QStringList &cxxflags) const
+Macros CustomToolChain::predefinedMacros(const QStringList &cxxflags) const
{
return createPredefinedMacrosRunner()(cxxflags);
}
@@ -169,16 +155,16 @@ WarningFlags CustomToolChain::warningFlags(const QStringList &cxxflags) const
return WarningFlags::Default;
}
-const QStringList &CustomToolChain::rawPredefinedMacros() const
+const Macros &CustomToolChain::rawPredefinedMacros() const
{
return m_predefinedMacros;
}
-void CustomToolChain::setPredefinedMacros(const QStringList &list)
+void CustomToolChain::setPredefinedMacros(const Macros &macros)
{
- if (m_predefinedMacros == list)
+ if (m_predefinedMacros == macros)
return;
- m_predefinedMacros = list;
+ m_predefinedMacros = macros;
toolChainUpdated();
}
@@ -323,7 +309,8 @@ QVariantMap CustomToolChain::toMap() const
data.insert(QLatin1String(compilerCommandKeyC), m_compilerCommand.toString());
data.insert(QLatin1String(makeCommandKeyC), m_makeCommand.toString());
data.insert(QLatin1String(targetAbiKeyC), m_targetAbi.toString());
- data.insert(QLatin1String(predefinedMacrosKeyC), m_predefinedMacros);
+ QStringList macros = Utils::transform<QList>(m_predefinedMacros, [](const Macro &m) { return QString::fromUtf8(m.toByteArray()); });
+ data.insert(QLatin1String(predefinedMacrosKeyC), macros);
data.insert(QLatin1String(headerPathsKeyC), headerPathsList());
data.insert(QLatin1String(cxx11FlagsKeyC), m_cxx11Flags);
data.insert(QLatin1String(mkspecsKeyC), mkspecs());
@@ -352,7 +339,8 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
m_compilerCommand = FileName::fromString(data.value(QLatin1String(compilerCommandKeyC)).toString());
m_makeCommand = FileName::fromString(data.value(QLatin1String(makeCommandKeyC)).toString());
m_targetAbi = Abi(data.value(QLatin1String(targetAbiKeyC)).toString());
- m_predefinedMacros = data.value(QLatin1String(predefinedMacrosKeyC)).toStringList();
+ const QStringList macros = data.value(QLatin1String(predefinedMacrosKeyC)).toStringList();
+ m_predefinedMacros = Macro::toMacros(macros.join('\n').toUtf8());
setHeaderPaths(data.value(QLatin1String(headerPathsKeyC)).toStringList());
m_cxx11Flags = data.value(QLatin1String(cxx11FlagsKeyC)).toStringList();
setMkspecs(data.value(QLatin1String(mkspecsKeyC)).toString());
@@ -526,11 +514,16 @@ public:
return static_cast<QPlainTextEdit *>(widget());
}
- inline QStringList entries() const
+ QStringList entries() const
{
return textEditWidget()->toPlainText().split(QLatin1Char('\n'), QString::SkipEmptyParts);
}
+ QString text() const
+ {
+ return textEditWidget()->toPlainText();
+ }
+
// not accurate, counts empty lines (except last)
int entryCount() const
{
@@ -656,7 +649,7 @@ void CustomToolChainConfigWidget::applyImpl()
tc->setCompilerCommand(m_compilerCommand->fileName());
tc->setMakeCommand(m_makeCommand->fileName());
tc->setTargetAbi(m_abiWidget->currentAbi());
- tc->setPredefinedMacros(m_predefinedDetails->entries());
+ tc->setPredefinedMacros(Macro::toMacros(m_predefinedDetails->text().toUtf8()));
tc->setHeaderPaths(m_headerDetails->entries());
tc->setCxx11Flags(m_cxx11Flags->text().split(QLatin1Char(',')));
tc->setMkspecs(m_mkspecs->text());
@@ -673,8 +666,8 @@ void CustomToolChainConfigWidget::setFromToolchain()
m_compilerCommand->setFileName(tc->compilerCommand());
m_makeCommand->setFileName(FileName::fromString(tc->makeCommand(Environment())));
m_abiWidget->setAbis(QList<Abi>(), tc->targetAbi());
- m_predefinedMacros->setPlainText(tc->rawPredefinedMacros().join(QLatin1Char('\n')));
- m_headerPaths->setPlainText(tc->headerPathsList().join(QLatin1Char('\n')));
+ m_predefinedMacros->setPlainText(QString::fromUtf8(Macro::toByteArray(tc->rawPredefinedMacros())));
+ m_headerPaths->setPlainText(tc->headerPathsList().join('\n'));
m_cxx11Flags->setText(tc->cxx11Flags().join(QLatin1Char(',')));
m_mkspecs->setText(tc->mkspecs());
int index = m_errorParserComboBox->findData(tc->outputParserId().toSetting());
@@ -690,7 +683,7 @@ bool CustomToolChainConfigWidget::isDirtyImpl() const
return m_compilerCommand->fileName() != tc->compilerCommand()
|| m_makeCommand->path() != tc->makeCommand(Environment())
|| m_abiWidget->currentAbi() != tc->targetAbi()
- || m_predefinedDetails->entries() != tc->rawPredefinedMacros()
+ || Macro::toMacros(m_predefinedDetails->text().toUtf8()) != tc->rawPredefinedMacros()
|| m_headerDetails->entries() != tc->headerPathsList()
|| m_cxx11Flags->text().split(QLatin1Char(',')) != tc->cxx11Flags()
|| m_mkspecs->text() != tc->mkspecs()
diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h
index fa5ec68ed0..75ba190c66 100644
--- a/src/plugins/projectexplorer/customtoolchain.h
+++ b/src/plugins/projectexplorer/customtoolchain.h
@@ -72,11 +72,11 @@ public:
bool isValid() const override;
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
- QByteArray predefinedMacros(const QStringList &cxxflags) const override;
+ Macros predefinedMacros(const QStringList &cxxflags) const override;
CompilerFlags compilerFlags(const QStringList &cxxflags) const override;
WarningFlags warningFlags(const QStringList &cxxflags) const override;
- const QStringList &rawPredefinedMacros() const;
- void setPredefinedMacros(const QStringList &list);
+ const Macros &rawPredefinedMacros() const;
+ void setPredefinedMacros(const Macros &macros);
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
QList<HeaderPath> systemHeaderPaths(const QStringList &cxxFlags,
@@ -124,7 +124,7 @@ private:
Utils::FileName m_makeCommand;
Abi m_targetAbi;
- QStringList m_predefinedMacros;
+ Macros m_predefinedMacros;
QList<HeaderPath> m_systemHeaderPaths;
QStringList m_cxx11Flags;
Utils::FileNameList m_mkspecs;
diff --git a/src/plugins/projectexplorer/dependenciespanel.cpp b/src/plugins/projectexplorer/dependenciespanel.cpp
index fed8a6a653..595b5ca5a7 100644
--- a/src/plugins/projectexplorer/dependenciespanel.cpp
+++ b/src/plugins/projectexplorer/dependenciespanel.cpp
@@ -29,7 +29,9 @@
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
+
#include <utils/detailswidget.h>
+#include <utils/algorithm.h>
#include <QDebug>
#include <QSize>
@@ -47,10 +49,8 @@ namespace Internal {
DependenciesModel::DependenciesModel(Project *project, QObject *parent)
: QAbstractListModel(parent)
, m_project(project)
- , m_projects(SessionManager::projects())
{
- // We can't select ourselves as a dependency
- m_projects.removeAll(m_project);
+ resetModel();
SessionManager *sessionManager = SessionManager::instance();
connect(sessionManager, &SessionManager::projectRemoved,
@@ -59,7 +59,6 @@ DependenciesModel::DependenciesModel(Project *project, QObject *parent)
this, &DependenciesModel::resetModel);
connect(sessionManager, &SessionManager::sessionLoaded,
this, &DependenciesModel::resetModel);
-// qDebug()<<"Dependencies Model"<<this<<"for project"<<project<<"("<<project->file()->fileName()<<")";
}
void DependenciesModel::resetModel()
@@ -67,6 +66,9 @@ void DependenciesModel::resetModel()
beginResetModel();
m_projects = SessionManager::projects();
m_projects.removeAll(m_project);
+ Utils::sort(m_projects, [](Project *a, Project *b) {
+ return a->displayName() < b->displayName();
+ });
endResetModel();
}
diff --git a/src/plugins/projectexplorer/deployconfiguration.cpp b/src/plugins/projectexplorer/deployconfiguration.cpp
index 119d9a057c..6f44d135b1 100644
--- a/src/plugins/projectexplorer/deployconfiguration.cpp
+++ b/src/plugins/projectexplorer/deployconfiguration.cpp
@@ -41,8 +41,9 @@ const char BUILD_STEP_LIST_PREFIX[] = "ProjectExplorer.BuildConfiguration.BuildS
const char DEFAULT_DEPLOYCONFIGURATION_ID[] = "ProjectExplorer.DefaultDeployConfiguration";
DeployConfiguration::DeployConfiguration(Target *target, Core::Id id) :
- ProjectConfiguration(target, id)
+ ProjectConfiguration(target)
{
+ ProjectConfiguration::initialize(id);
Q_ASSERT(target);
m_stepList = new BuildStepList(this, Core::Id(Constants::BUILDSTEPS_DEPLOY));
//: Display name of the deploy build step list. Used as part of the labels in the project window.
@@ -53,8 +54,9 @@ DeployConfiguration::DeployConfiguration(Target *target, Core::Id id) :
}
DeployConfiguration::DeployConfiguration(Target *target, DeployConfiguration *source) :
- ProjectConfiguration(target, source)
+ ProjectConfiguration(target)
{
+ ProjectConfiguration::copyFrom(source);
Q_ASSERT(target);
// Do not clone stepLists here, do that in the derived constructor instead
// otherwise BuildStepFactories might reject to set up a BuildStep for us
@@ -141,6 +143,16 @@ Target *DeployConfiguration::target() const
return static_cast<Target *>(parent());
}
+Project *DeployConfiguration::project() const
+{
+ return target()->project();
+}
+
+bool DeployConfiguration::isActive() const
+{
+ return target()->isActive() && target()->activeDeployConfiguration() == this;
+}
+
void DeployConfiguration::cloneSteps(DeployConfiguration *source)
{
if (source == this)
diff --git a/src/plugins/projectexplorer/deployconfiguration.h b/src/plugins/projectexplorer/deployconfiguration.h
index aec33fd308..db3b37c5c3 100644
--- a/src/plugins/projectexplorer/deployconfiguration.h
+++ b/src/plugins/projectexplorer/deployconfiguration.h
@@ -59,6 +59,9 @@ public:
virtual QString disabledReason() const;
Target *target() const;
+ Project *project() const override;
+
+ bool isActive() const override;
signals:
void enabledChanged();
diff --git a/src/plugins/projectexplorer/deployconfigurationmodel.cpp b/src/plugins/projectexplorer/deployconfigurationmodel.cpp
deleted file mode 100644
index b0e5dc70eb..0000000000
--- a/src/plugins/projectexplorer/deployconfigurationmodel.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "deployconfigurationmodel.h"
-#include "target.h"
-#include "deployconfiguration.h"
-
-#include <utils/algorithm.h>
-
-using namespace ProjectExplorer;
-
-/*!
- \class ProjectExplorer::DeployConfigurationModel
-
- \brief The DeployConfigurationModel class provides a model to represent
- the run configurations of a target.
-
- To be used in drop down lists of comboboxes. Automatically adjusts
- itself to added and removed deploy configurations.
-*/
-
-class DeployConfigurationComparer
-{
-public:
- bool operator()(DeployConfiguration *a, DeployConfiguration *b)
- {
- return a->displayName() < b->displayName();
- }
-};
-
-DeployConfigurationModel::DeployConfigurationModel(Target *target, QObject *parent) :
- QAbstractListModel(parent),
- m_target(target)
-{
- m_deployConfigurations = m_target->deployConfigurations();
- Utils::sort(m_deployConfigurations, DeployConfigurationComparer());
-
- connect(target, &Target::addedDeployConfiguration,
- this, &DeployConfigurationModel::addedDeployConfiguration);
- connect(target, &Target::removedDeployConfiguration,
- this, &DeployConfigurationModel::removedDeployConfiguration);
-
- foreach (DeployConfiguration *dc, m_deployConfigurations) {
- connect(dc, &ProjectConfiguration::displayNameChanged,
- this, &DeployConfigurationModel::displayNameChanged);
- }
-}
-
-int DeployConfigurationModel::rowCount(const QModelIndex &parent) const
-{
- return parent.isValid() ? 0 : m_deployConfigurations.size();
-}
-
-int DeployConfigurationModel::columnCount(const QModelIndex &parent) const
-{
- return parent.isValid() ? 0 : 1;
-}
-
-void DeployConfigurationModel::displayNameChanged()
-{
- auto dc = qobject_cast<DeployConfiguration *>(sender());
- if (!dc)
- return;
-
- DeployConfigurationComparer compare;
- // Find the old position
- int oldPos = m_deployConfigurations.indexOf(dc);
-
- if (oldPos >= 1 && compare(m_deployConfigurations.at(oldPos), m_deployConfigurations.at(oldPos - 1))) {
- // We need to move up
- int newPos = oldPos - 1;
- while (newPos >= 0 && compare(m_deployConfigurations.at(oldPos), m_deployConfigurations.at(newPos))) {
- --newPos;
- }
- ++newPos;
-
- beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
- m_deployConfigurations.insert(newPos, dc);
- m_deployConfigurations.removeAt(oldPos + 1);
- endMoveRows();
- // Not only did we move, we also changed...
- emit dataChanged(index(newPos, 0), index(newPos,0));
- } else if (oldPos < m_deployConfigurations.size() - 1
- && compare(m_deployConfigurations.at(oldPos + 1), m_deployConfigurations.at(oldPos))) {
- // We need to move down
- int newPos = oldPos + 1;
- while (newPos < m_deployConfigurations.size()
- && compare(m_deployConfigurations.at(newPos), m_deployConfigurations.at(oldPos))) {
- ++newPos;
- }
- beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
- m_deployConfigurations.insert(newPos, dc);
- m_deployConfigurations.removeAt(oldPos);
- endMoveRows();
-
- // We need to subtract one since removing at the old place moves the newIndex down
- emit dataChanged(index(newPos - 1, 0), index(newPos - 1, 0));
- } else {
- emit dataChanged(index(oldPos, 0), index(oldPos, 0));
- }
-}
-
-QVariant DeployConfigurationModel::data(const QModelIndex &index, int role) const
-{
- if (role == Qt::DisplayRole) {
- const int row = index.row();
- if (row < m_deployConfigurations.size())
- return m_deployConfigurations.at(row)->displayName();
- }
-
- return QVariant();
-}
-
-DeployConfiguration *DeployConfigurationModel::deployConfigurationAt(int i)
-{
- if (i > m_deployConfigurations.size() || i < 0)
- return nullptr;
- return m_deployConfigurations.at(i);
-}
-
-DeployConfiguration *DeployConfigurationModel::deployConfigurationFor(const QModelIndex &idx)
-{
- if (idx.row() > m_deployConfigurations.size() || idx.row() < 0)
- return nullptr;
- return m_deployConfigurations.at(idx.row());
-}
-
-QModelIndex DeployConfigurationModel::indexFor(DeployConfiguration *rc)
-{
- int idx = m_deployConfigurations.indexOf(rc);
- if (idx == -1)
- return QModelIndex();
- return index(idx, 0);
-}
-
-void DeployConfigurationModel::addedDeployConfiguration(DeployConfiguration *dc)
-{
- // Find the right place to insert
- DeployConfigurationComparer compare;
- int i = 0;
- for (; i < m_deployConfigurations.size(); ++i) {
- if (compare(dc, m_deployConfigurations.at(i)))
- break;
- }
-
- beginInsertRows(QModelIndex(), i, i);
- m_deployConfigurations.insert(i, dc);
- endInsertRows();
-
- connect(dc, &ProjectConfiguration::displayNameChanged,
- this, &DeployConfigurationModel::displayNameChanged);
-}
-
-void DeployConfigurationModel::removedDeployConfiguration(DeployConfiguration *dc)
-{
- int i = m_deployConfigurations.indexOf(dc);
- if (i < 0)
- return;
- beginRemoveRows(QModelIndex(), i, i);
- m_deployConfigurations.removeAt(i);
- endRemoveRows();
-}
diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
index 2167f9ddbb..f7c85ce0c7 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
@@ -191,7 +191,7 @@ void PortsGatherer::start()
});
connect(&m_portsGatherer, &DeviceUsedPortsGatherer::portListReady, this, [this] {
m_portList = device()->freePorts();
- appendMessage(tr("Found %1 free ports").arg(m_portList.count()) + '\n', NormalMessageFormat);
+ appendMessage(tr("Found %n free ports.", nullptr, m_portList.count()) + '\n', NormalMessageFormat);
reportStarted();
});
m_portsGatherer.start(device());
diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
index e784536d3a..10c452b027 100644
--- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
+++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp
@@ -45,8 +45,8 @@ public:
SshDeviceProcessPrivate(SshDeviceProcess *q) : q(q) {}
SshDeviceProcess * const q;
- bool serverSupportsSignals;
- QSsh::SshConnection *connection;
+ bool serverSupportsSignals = false;
+ QSsh::SshConnection *connection = nullptr;
QSsh::SshRemoteProcess::Ptr process;
StandardRunnable runnable;
QString errorMessage;
@@ -55,8 +55,8 @@ public:
QTimer killTimer;
QByteArray stdOut;
QByteArray stdErr;
- int exitCode;
- enum State { Inactive, Connecting, Connected, ProcessRunning } state;
+ int exitCode = -1;
+ enum State { Inactive, Connecting, Connected, ProcessRunning } state = Inactive;
void setState(State newState);
void doSignal(QSsh::SshRemoteProcess::Signal signal);
@@ -65,9 +65,6 @@ public:
SshDeviceProcess::SshDeviceProcess(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcess(device, parent), d(new SshDeviceProcessPrivate(this))
{
- d->connection = 0;
- d->state = SshDeviceProcessPrivate::Inactive;
- setSshServerSupportsSignals(false);
connect(&d->killTimer, &QTimer::timeout, this, &SshDeviceProcess::handleKillOperationTimeout);
}
diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp
index 59fd6b9675..ab02000440 100644
--- a/src/plugins/projectexplorer/extracompiler.cpp
+++ b/src/plugins/projectexplorer/extracompiler.cpp
@@ -381,13 +381,13 @@ ProcessExtraCompiler::~ProcessExtraCompiler()
void ProcessExtraCompiler::run(const QByteArray &sourceContents)
{
- ContentProvider contents = [this, sourceContents]() { return sourceContents; };
+ ContentProvider contents = [sourceContents]() { return sourceContents; };
runImpl(contents);
}
void ProcessExtraCompiler::run(const Utils::FileName &fileName)
{
- ContentProvider contents = [this, fileName]() {
+ ContentProvider contents = [fileName]() {
QFile file(fileName.toString());
if (!file.open(QFile::ReadOnly | QFile::Text))
return QByteArray();
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp
index 8742c885cf..f981545c69 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.cpp
+++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp
@@ -26,71 +26,47 @@
#include "foldernavigationwidget.h"
#include "projectexplorer.h"
-#include <extensionsystem/pluginmanager.h>
-
#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/fileutils.h>
-#include <coreplugin/find/findplugin.h>
-
-#include <texteditor/findinfiles.h>
+#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
-#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
-#include <utils/elidinglabel.h>
-#include <utils/itemviews.h>
+#include <utils/navigationtreeview.h>
#include <utils/utilsicons.h>
-#include <QDebug>
+#include <QComboBox>
+#include <QHeaderView>
#include <QSize>
+#include <QTimer>
#include <QFileSystemModel>
#include <QVBoxLayout>
#include <QToolButton>
-#include <QSortFilterProxyModel>
#include <QAction>
#include <QMenu>
-#include <QFileDialog>
#include <QContextMenuEvent>
#include <QDir>
#include <QFileInfo>
-enum { debug = 0 };
+const int PATH_ROLE = Qt::UserRole;
+const int ID_ROLE = Qt::UserRole + 1;
+const int SORT_ROLE = Qt::UserRole + 2;
+
+const char PROJECTSDIRECTORYROOT_ID[] = "A.Projects";
namespace ProjectExplorer {
namespace Internal {
-// Hide the '.' entry.
-class DotRemovalFilter : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
- explicit DotRemovalFilter(QObject *parent = nullptr);
-protected:
- virtual bool filterAcceptsRow(int source_row, const QModelIndex &parent) const;
- Qt::DropActions supportedDragActions() const;
-};
-
-DotRemovalFilter::DotRemovalFilter(QObject *parent) : QSortFilterProxyModel(parent)
-{ }
+static FolderNavigationWidgetFactory *m_instance = nullptr;
-bool DotRemovalFilter::filterAcceptsRow(int source_row, const QModelIndex &parent) const
-{
- const QVariant fileName = sourceModel()->data(parent.child(source_row, 0));
- if (Utils::HostOsInfo::isAnyUnixHost())
- if (sourceModel()->data(parent) == QLatin1String("/") && fileName == QLatin1String(".."))
- return false;
- return fileName != QLatin1String(".");
-}
-
-Qt::DropActions DotRemovalFilter::supportedDragActions() const
-{
- return sourceModel()->supportedDragActions();
-}
+QVector<FolderNavigationWidgetFactory::RootDirectory>
+ FolderNavigationWidgetFactory::m_rootDirectories;
// FolderNavigationModel: Shows path as tooltip.
class FolderNavigationModel : public QFileSystemModel
@@ -117,42 +93,46 @@ Qt::DropActions FolderNavigationModel::supportedDragActions() const
return Qt::MoveAction;
}
+static void showOnlyFirstColumn(QTreeView *view)
+{
+ const int columnCount = view->header()->count();
+ for (int i = 1; i < columnCount; ++i)
+ view->setColumnHidden(i, true);
+}
+
/*!
- \class FolderNavigationWidget
+ \class FolderNavigationWidget
+
+ Shows a file system tree, with the root directory selectable from a dropdown.
- Shows a file system folder
- */
+ \internal
+*/
FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent),
- m_listView(new Utils::ListView(this)),
+ m_listView(new Utils::NavigationTreeView(this)),
m_fileSystemModel(new FolderNavigationModel(this)),
m_filterHiddenFilesAction(new QAction(tr("Show Hidden Files"), this)),
- m_filterModel(new DotRemovalFilter(this)),
- m_title(new Utils::ElidingLabel(this)),
- m_toggleSync(new QToolButton(this))
+ m_toggleSync(new QToolButton(this)),
+ m_rootSelector(new QComboBox)
{
m_fileSystemModel->setResolveSymlinks(false);
m_fileSystemModel->setIconProvider(Core::FileIconProvider::iconProvider());
- QDir::Filters filters = QDir::AllDirs | QDir::Files | QDir::Drives
- | QDir::Readable| QDir::Writable
- | QDir::Executable | QDir::Hidden;
+ QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot;
if (Utils::HostOsInfo::isWindowsHost()) // Symlinked directories can cause file watcher warnings on Win32.
filters |= QDir::NoSymLinks;
m_fileSystemModel->setFilter(filters);
- m_filterModel->setSourceModel(m_fileSystemModel);
+ m_fileSystemModel->setRootPath(QString());
m_filterHiddenFilesAction->setCheckable(true);
setHiddenFilesFilter(false);
m_listView->setIconSize(QSize(16,16));
- m_listView->setModel(m_filterModel);
- m_listView->setFrameStyle(QFrame::NoFrame);
- m_listView->setAttribute(Qt::WA_MacShowFocusRect, false);
+ m_listView->setModel(m_fileSystemModel);
m_listView->setDragEnabled(true);
m_listView->setDragDropMode(QAbstractItemView::DragOnly);
+ showOnlyFirstColumn(m_listView);
setFocusProxy(m_listView);
auto layout = new QVBoxLayout();
- layout->addWidget(m_title);
+ layout->addWidget(m_rootSelector);
layout->addWidget(m_listView);
- m_title->setMargin(5);
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
setLayout(layout);
@@ -164,13 +144,26 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent
// connections
connect(m_listView, &QAbstractItemView::activated,
- this, &FolderNavigationWidget::slotOpenItem);
+ this, [this](const QModelIndex &index) { openItem(index); });
connect(m_filterHiddenFilesAction, &QAction::toggled,
this, &FolderNavigationWidget::setHiddenFilesFilter);
connect(m_toggleSync, &QAbstractButton::clicked,
this, &FolderNavigationWidget::toggleAutoSynchronization);
- connect(m_filterModel, &QAbstractItemModel::layoutChanged,
- this, &FolderNavigationWidget::ensureCurrentIndex);
+ connect(m_rootSelector,
+ static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this,
+ [this](int index) {
+ const auto directory = m_rootSelector->itemData(index).value<Utils::FileName>();
+ m_rootSelector->setToolTip(directory.toString());
+ setRootDirectory(directory);
+ });
+ connect(m_rootSelector,
+ static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ this,
+ [this] {
+ if (m_autoSync && Core::EditorManager::currentEditor())
+ selectFile(Core::EditorManager::currentEditor()->document()->filePath());
+ });
}
void FolderNavigationWidget::toggleAutoSynchronization()
@@ -178,6 +171,54 @@ void FolderNavigationWidget::toggleAutoSynchronization()
setAutoSynchronization(!m_autoSync);
}
+static bool itemLessThan(QComboBox *combo,
+ int index,
+ const FolderNavigationWidgetFactory::RootDirectory &directory)
+{
+ return combo->itemData(index, SORT_ROLE).toInt() < directory.sortValue
+ || (combo->itemData(index, SORT_ROLE).toInt() == directory.sortValue
+ && combo->itemData(index, Qt::DisplayRole).toString() < directory.displayName);
+}
+
+void FolderNavigationWidget::insertRootDirectory(
+ const FolderNavigationWidgetFactory::RootDirectory &directory)
+{
+ // Find existing. Do not remove yet, to not mess up the current selection.
+ int previousIndex = 0;
+ while (previousIndex < m_rootSelector->count()
+ && m_rootSelector->itemData(previousIndex, ID_ROLE).toString() != directory.id)
+ ++previousIndex;
+ // Insert sorted.
+ int index = 0;
+ while (index < m_rootSelector->count() && itemLessThan(m_rootSelector, index, directory))
+ ++index;
+ m_rootSelector->insertItem(index, directory.displayName);
+ if (index <= previousIndex) // item was inserted, update previousIndex
+ ++previousIndex;
+ m_rootSelector->setItemData(index, qVariantFromValue(directory.path), PATH_ROLE);
+ m_rootSelector->setItemData(index, directory.id, ID_ROLE);
+ m_rootSelector->setItemData(index, directory.sortValue, SORT_ROLE);
+ m_rootSelector->setItemData(index, directory.path.toUserOutput(), Qt::ToolTipRole);
+ if (m_rootSelector->currentIndex() == previousIndex)
+ m_rootSelector->setCurrentIndex(index);
+ if (previousIndex < m_rootSelector->count())
+ m_rootSelector->removeItem(previousIndex);
+ if (m_autoSync) // we might find a better root for current selection now
+ setCurrentEditor(Core::EditorManager::currentEditor());
+}
+
+void FolderNavigationWidget::removeRootDirectory(const QString &id)
+{
+ for (int i = 0; i < m_rootSelector->count(); ++i) {
+ if (m_rootSelector->itemData(i, ID_ROLE).toString() == id) {
+ m_rootSelector->removeItem(i);
+ break;
+ }
+ }
+ if (m_autoSync) // we might need to find a new root for current selection
+ setCurrentEditor(Core::EditorManager::currentEditor());
+}
+
bool FolderNavigationWidget::autoSynchronization() const
{
return m_autoSync;
@@ -193,148 +234,95 @@ void FolderNavigationWidget::setAutoSynchronization(bool sync)
if (m_autoSync) {
connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
- this, &FolderNavigationWidget::setCurrentFile);
- setCurrentFile(Core::EditorManager::currentEditor());
+ this, &FolderNavigationWidget::setCurrentEditor);
+ setCurrentEditor(Core::EditorManager::currentEditor());
} else {
disconnect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
- this, &FolderNavigationWidget::setCurrentFile);
+ this, &FolderNavigationWidget::setCurrentEditor);
}
}
-void FolderNavigationWidget::setCurrentFile(Core::IEditor *editor)
+void FolderNavigationWidget::setCurrentEditor(Core::IEditor *editor)
{
if (!editor)
return;
-
- const QString filePath = editor->document()->filePath().toString();
- // Try to find directory of current file
- bool pathOpened = false;
- if (!filePath.isEmpty()) {
- const QFileInfo fi(filePath);
- if (fi.exists())
- pathOpened = setCurrentDirectory(fi.absolutePath());
- }
- if (!pathOpened) // Default to home.
- setCurrentDirectory(Utils::PathChooser::homePath());
-
- // Select the current file.
- if (pathOpened) {
- const QModelIndex fileIndex = m_fileSystemModel->index(filePath);
- if (fileIndex.isValid()) {
- QItemSelectionModel *selections = m_listView->selectionModel();
- const QModelIndex mainIndex = m_filterModel->mapFromSource(fileIndex);
- selections->setCurrentIndex(mainIndex, QItemSelectionModel::SelectCurrent
- | QItemSelectionModel::Clear);
- m_listView->scrollTo(mainIndex);
- }
- }
+ const Utils::FileName filePath = editor->document()->filePath();
+ // switch to most fitting root
+ const int bestRootIndex = bestRootForFile(filePath);
+ m_rootSelector->setCurrentIndex(bestRootIndex);
+ // select
+ selectFile(filePath);
}
-bool FolderNavigationWidget::setCurrentDirectory(const QString &directory)
+void FolderNavigationWidget::selectFile(const Utils::FileName &filePath)
{
- const QString newDirectory = directory.isEmpty() ? QDir::rootPath() : directory;
- if (debug)
- qDebug() << "setcurdir" << directory << newDirectory;
- // Set the root path on the model instead of changing the top index
- // of the view to cause the model to clean out its file watchers.
- const QModelIndex index = m_fileSystemModel->setRootPath(newDirectory);
- if (!index.isValid()) {
- setCurrentTitle(QString(), QString());
- return false;
- }
- QModelIndex oldRootIndex = m_listView->rootIndex();
- QModelIndex newRootIndex = m_filterModel->mapFromSource(index);
- m_listView->setRootIndex(newRootIndex);
- const QDir current(QDir::cleanPath(newDirectory));
- setCurrentTitle(current.dirName(),
- QDir::toNativeSeparators(current.absolutePath()));
- if (oldRootIndex.parent() == newRootIndex) { // cdUp, so select the old directory
- m_listView->setCurrentIndex(oldRootIndex);
- m_listView->scrollTo(oldRootIndex, QAbstractItemView::EnsureVisible);
+ const QModelIndex fileIndex = m_fileSystemModel->index(filePath.toString());
+ if (fileIndex.isValid()) {
+ // TODO This only scrolls to the right position if all directory contents are loaded.
+ // Unfortunately listening to directoryLoaded was still not enough (there might also
+ // be some delayed sorting involved?).
+ // Use magic timer for scrolling.
+ m_listView->setCurrentIndex(fileIndex);
+ QTimer::singleShot(200, this, [this, filePath] {
+ const QModelIndex fileIndex = m_fileSystemModel->index(filePath.toString());
+ m_listView->scrollTo(fileIndex);
+ });
}
-
- return !directory.isEmpty();
}
-QString FolderNavigationWidget::currentDirectory() const
+void FolderNavigationWidget::setRootDirectory(const Utils::FileName &directory)
{
- return m_fileSystemModel->rootPath();
+ const QModelIndex index = m_fileSystemModel->setRootPath(directory.toString());
+ m_listView->setRootIndex(index);
}
-void FolderNavigationWidget::slotOpenItem(const QModelIndex &viewIndex)
+int FolderNavigationWidget::bestRootForFile(const Utils::FileName &filePath)
{
- if (viewIndex.isValid())
- openItem(m_filterModel->mapToSource(viewIndex));
+ int index = 0; // Computer is default
+ int commonLength = 0;
+ for (int i = 1; i < m_rootSelector->count(); ++i) {
+ const auto root = m_rootSelector->itemData(i).value<Utils::FileName>();
+ if (filePath.isChildOf(root) && root.length() > commonLength) {
+ index = i;
+ commonLength = root.length();
+ }
+ }
+ return index;
}
-void FolderNavigationWidget::openItem(const QModelIndex &srcIndex, bool openDirectoryAsProject)
+void FolderNavigationWidget::openItem(const QModelIndex &index)
{
- const QString fileName = m_fileSystemModel->fileName(srcIndex);
- if (fileName == QLatin1String("."))
- return;
- if (fileName == QLatin1String("..")) {
- // cd up: Special behaviour: The fileInfo of ".." is that of the parent directory.
- const QString parentPath = m_fileSystemModel->fileInfo(srcIndex).absoluteFilePath();
- setCurrentDirectory(parentPath);
+ if (!index.isValid())
return;
- }
- const QString path = m_fileSystemModel->filePath(srcIndex);
- if (m_fileSystemModel->isDir(srcIndex)) {
- const QFileInfo fi = m_fileSystemModel->fileInfo(srcIndex);
+ const QString path = m_fileSystemModel->filePath(index);
+ if (m_fileSystemModel->isDir(index)) {
+ const QFileInfo fi = m_fileSystemModel->fileInfo(index);
if (!fi.isReadable() || !fi.isExecutable())
return;
// Try to find project files in directory and open those.
- if (openDirectoryAsProject) {
- const QStringList projectFiles = FolderNavigationWidget::projectFilesInDirectory(path);
- if (!projectFiles.isEmpty())
- Core::ICore::instance()->openFiles(projectFiles);
- return;
- }
- // Change to directory
- setCurrentDirectory(path);
- return;
+ const QStringList projectFiles = FolderNavigationWidget::projectFilesInDirectory(path);
+ if (!projectFiles.isEmpty())
+ Core::ICore::instance()->openFiles(projectFiles);
+ } else {
+ // Open editor
+ Core::EditorManager::openEditor(path);
}
- // Open file.
- Core::ICore::instance()->openFiles(QStringList(path));
-}
-
-void FolderNavigationWidget::setCurrentTitle(QString dirName, const QString &fullPath)
-{
- if (dirName.isEmpty())
- dirName = fullPath;
- m_title->setText(dirName);
- m_title->setToolTip(fullPath);
-}
-
-QModelIndex FolderNavigationWidget::currentItem() const
-{
- const QModelIndex current = m_listView->currentIndex();
- if (current.isValid())
- return m_filterModel->mapToSource(current);
- return QModelIndex();
-}
-
-// Format the text for the "open" action of the context menu according
-// to the selectect entry
-static inline QString actionOpenText(const QFileSystemModel *model,
- const QModelIndex &index)
-{
- if (!index.isValid())
- return FolderNavigationWidget::tr("Open");
- const QString fileName = model->fileName(index);
- if (fileName == QLatin1String(".."))
- return FolderNavigationWidget::tr("Open Parent Folder");
- return FolderNavigationWidget::tr("Open \"%1\"").arg(fileName);
}
void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
{
QMenu menu;
// Open current item
- const QModelIndex current = currentItem();
+ const QModelIndex current = m_listView->currentIndex();
const bool hasCurrentItem = current.isValid();
- QAction *actionOpen = menu.addAction(actionOpenText(m_fileSystemModel, current));
- actionOpen->setEnabled(hasCurrentItem);
+ QAction *actionOpen = nullptr;
+ if (hasCurrentItem) {
+ const QString fileName = m_fileSystemModel->fileName(current);
+ if (m_fileSystemModel->isDir(current))
+ actionOpen = menu.addAction(tr("Open Project in \"%1\"").arg(fileName));
+ else
+ actionOpen = menu.addAction(tr("Open \"%1\"").arg(fileName));
+ }
// we need dummy DocumentModel::Entry with absolute file path in it
// to get EditorManager::addNativeDirAndOpenWithActions() working
@@ -344,17 +332,6 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
fakeEntry.document = &document;
Core::EditorManager::addNativeDirAndOpenWithActions(&menu, &fakeEntry);
- const bool isDirectory = hasCurrentItem && m_fileSystemModel->isDir(current);
- QAction *actionOpenDirectoryAsProject = 0;
- if (isDirectory && m_fileSystemModel->fileName(current) != QLatin1String("..")) {
- actionOpenDirectoryAsProject =
- menu.addAction(tr("Open Project in \"%1\"")
- .arg(m_fileSystemModel->fileName(current)));
- }
-
- // Open file dialog to choose a path starting from current
- QAction *actionChooseFolder = menu.addAction(tr("Choose Folder..."));
-
QAction *action = menu.exec(ev->globalPos());
if (!action)
return;
@@ -362,12 +339,6 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
ev->accept();
if (action == actionOpen) { // Handle open file.
openItem(current);
- } else if (action == actionOpenDirectoryAsProject) {
- openItem(current, true);
- } else if (action == actionChooseFolder) { // Open file dialog
- const QString newPath = QFileDialog::getExistingDirectory(this, tr("Choose Folder"), currentDirectory());
- if (!newPath.isEmpty())
- setCurrentDirectory(newPath);
}
}
@@ -387,17 +358,6 @@ bool FolderNavigationWidget::hiddenFilesFilter() const
return m_filterHiddenFilesAction->isChecked();
}
-void FolderNavigationWidget::ensureCurrentIndex()
-{
- QModelIndex index = m_listView->currentIndex();
- if (!index.isValid()
- || index.parent() != m_listView->rootIndex()) {
- index = m_listView->rootIndex().child(0, 0);
- m_listView->setCurrentIndex(index);
- }
- m_listView->scrollTo(index);
-}
-
QStringList FolderNavigationWidget::projectFilesInDirectory(const QString &path)
{
QDir dir(path);
@@ -410,16 +370,41 @@ QStringList FolderNavigationWidget::projectFilesInDirectory(const QString &path)
// --------------------FolderNavigationWidgetFactory
FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
{
+ m_instance = this;
setDisplayName(tr("File System"));
setPriority(400);
setId("File System");
setActivationSequence(QKeySequence(Core::UseMacShortcuts ? tr("Meta+Y") : tr("Alt+Y")));
+ insertRootDirectory({QLatin1String("A.Computer"),
+ 0 /*sortValue*/,
+ FolderNavigationWidget::tr("Computer"),
+ Utils::FileName()});
+ insertRootDirectory({QLatin1String("A.Home"),
+ 10 /*sortValue*/,
+ FolderNavigationWidget::tr("Home"),
+ Utils::FileName::fromString(QDir::homePath())});
+ updateProjectsDirectoryRoot();
+ connect(Core::DocumentManager::instance(),
+ &Core::DocumentManager::projectsDirectoryChanged,
+ this,
+ &FolderNavigationWidgetFactory::updateProjectsDirectoryRoot);
}
Core::NavigationView FolderNavigationWidgetFactory::createWidget()
{
- Core::NavigationView n;
auto fnw = new FolderNavigationWidget;
+ for (const RootDirectory &root : m_rootDirectories)
+ fnw->insertRootDirectory(root);
+ connect(this,
+ &FolderNavigationWidgetFactory::rootDirectoryAdded,
+ fnw,
+ &FolderNavigationWidget::insertRootDirectory);
+ connect(this,
+ &FolderNavigationWidgetFactory::rootDirectoryRemoved,
+ fnw,
+ &FolderNavigationWidget::removeRootDirectory);
+
+ Core::NavigationView n;
n.widget = fnw;
auto filter = new QToolButton;
filter->setIcon(Utils::Icons::FILTER.icon());
@@ -450,7 +435,38 @@ void FolderNavigationWidgetFactory::restoreSettings(QSettings *settings, int pos
fnw->setHiddenFilesFilter(settings->value(baseKey + QLatin1String(".HiddenFilesFilter"), false).toBool());
fnw->setAutoSynchronization(settings->value(baseKey + QLatin1String(".SyncWithEditor"), true).toBool());
}
+
+void FolderNavigationWidgetFactory::insertRootDirectory(const RootDirectory &directory)
+{
+ const int index = rootIndex(directory.id);
+ if (index < 0)
+ m_rootDirectories.append(directory);
+ else
+ m_rootDirectories[index] = directory;
+ emit m_instance->rootDirectoryAdded(directory);
+}
+
+void FolderNavigationWidgetFactory::removeRootDirectory(const QString &id)
+{
+ const int index = rootIndex(id);
+ QTC_ASSERT(index >= 0, return );
+ m_rootDirectories.removeAt(index);
+ emit m_instance->rootDirectoryRemoved(id);
+}
+
+int FolderNavigationWidgetFactory::rootIndex(const QString &id)
+{
+ return Utils::indexOf(m_rootDirectories,
+ [id](const RootDirectory &entry) { return entry.id == id; });
+}
+
+void FolderNavigationWidgetFactory::updateProjectsDirectoryRoot()
+{
+ insertRootDirectory({QLatin1String(PROJECTSDIRECTORYROOT_ID),
+ 20 /*sortValue*/,
+ FolderNavigationWidget::tr("Projects"),
+ Core::DocumentManager::projectsDirectory()});
+}
+
} // namespace Internal
} // namespace ProjectExplorer
-
-#include "foldernavigationwidget.moc"
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h
index 3b4b37fa2f..11e2bbc9ec 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.h
+++ b/src/plugins/projectexplorer/foldernavigationwidget.h
@@ -26,23 +26,57 @@
#pragma once
#include <coreplugin/inavigationwidgetfactory.h>
+#include <utils/fileutils.h>
#include <QWidget>
-namespace Utils { class ListView; }
namespace Core { class IEditor; }
+namespace Utils {
+class NavigationTreeView;
+}
+
QT_BEGIN_NAMESPACE
-class QLabel;
-class QSortFilterProxyModel;
-class QModelIndex;
-class QFileSystemModel;
class QAction;
+class QComboBox;
+class QFileSystemModel;
+class QModelIndex;
QT_END_NAMESPACE
namespace ProjectExplorer {
namespace Internal {
+class FolderNavigationWidgetFactory : public Core::INavigationWidgetFactory
+{
+ Q_OBJECT
+
+public:
+ struct RootDirectory {
+ QString id;
+ int sortValue;
+ QString displayName;
+ Utils::FileName path;
+ };
+
+ FolderNavigationWidgetFactory();
+
+ Core::NavigationView createWidget() override;
+ void saveSettings(QSettings *settings, int position, QWidget *widget) override;
+ void restoreSettings(QSettings *settings, int position, QWidget *widget) override;
+
+ static void insertRootDirectory(const RootDirectory &directory);
+ static void removeRootDirectory(const QString &id);
+
+signals:
+ void rootDirectoryAdded(const RootDirectory &directory);
+ void rootDirectoryRemoved(const QString &id);
+
+private:
+ static int rootIndex(const QString &id);
+ void updateProjectsDirectoryRoot();
+ static QVector<RootDirectory> m_rootDirectories;
+};
+
class FolderNavigationWidget : public QWidget
{
Q_OBJECT
@@ -58,45 +92,30 @@ public:
void setAutoSynchronization(bool sync);
void toggleAutoSynchronization();
-private:
- void setCurrentFile(Core::IEditor *editor);
- void slotOpenItem(const QModelIndex &viewIndex);
- void setHiddenFilesFilter(bool filter);
- void ensureCurrentIndex();
+ void insertRootDirectory(const FolderNavigationWidgetFactory::RootDirectory &directory);
+ void removeRootDirectory(const QString &id);
protected:
void contextMenuEvent(QContextMenuEvent *ev) override;
private:
- void setCurrentTitle(QString dirName, const QString &fullPath);
- bool setCurrentDirectory(const QString &directory);
- void openItem(const QModelIndex &srcIndex, bool openDirectoryAsProject = false);
- QModelIndex currentItem() const;
- QString currentDirectory() const;
-
- Utils::ListView *m_listView;
- QFileSystemModel *m_fileSystemModel;
- QAction *m_filterHiddenFilesAction;
- QSortFilterProxyModel *m_filterModel;
- QLabel *m_title;
+ void setHiddenFilesFilter(bool filter);
+ void setCurrentEditor(Core::IEditor *editor);
+ void selectFile(const Utils::FileName &filePath);
+ void setRootDirectory(const Utils::FileName &directory);
+ int bestRootForFile(const Utils::FileName &filePath);
+ void openItem(const QModelIndex &index);
+
+ Utils::NavigationTreeView *m_listView = nullptr;
+ QFileSystemModel *m_fileSystemModel = nullptr;
+ QAction *m_filterHiddenFilesAction = nullptr;
bool m_autoSync = false;
- QToolButton *m_toggleSync;
+ QToolButton *m_toggleSync = nullptr;
+ QComboBox *m_rootSelector = nullptr;
// FolderNavigationWidgetFactory needs private members to build a menu
friend class FolderNavigationWidgetFactory;
};
-class FolderNavigationWidgetFactory : public Core::INavigationWidgetFactory
-{
- Q_OBJECT
-
-public:
- FolderNavigationWidgetFactory();
-
- Core::NavigationView createWidget() override;
- void saveSettings(QSettings *settings, int position, QWidget *widget) override;
- void restoreSettings(QSettings *settings, int position, QWidget *widget) override;
-};
-
} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index 56a744b01f..1948fdc178 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -28,6 +28,7 @@
#include "gcctoolchainfactories.h"
#include "gccparser.h"
#include "linuxiccparser.h"
+#include "projectmacro.h"
#include "projectexplorerconstants.h"
#include "toolchainmanager.h"
@@ -42,11 +43,13 @@
#include <QBuffer>
#include <QCoreApplication>
+#include <QDir>
#include <QFileInfo>
-
-#include <QLineEdit>
#include <QFormLayout>
+#include <QLineEdit>
+#include <QRegularExpression>
+#include <algorithm>
#include <memory>
using namespace Utils;
@@ -65,6 +68,7 @@ static const char compilerPlatformLinkerFlagsKeyC[] = "ProjectExplorer.GccToolCh
static const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi";
static const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.OriginalTargetTriple";
static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
+static const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+)(?:-([\\d.]+))?$";
static const int CACHE_SIZE = 16;
@@ -117,6 +121,11 @@ HeaderPathsCache::Cache HeaderPathsCache::cache() const
return m_cache;
}
+MacroCache::MacroCache() : m_mutex(QMutex::Recursive)
+{
+ m_cache.reserve(CACHE_SIZE + 1);
+}
+
MacroCache::MacroCache(const MacroCache &other)
: MacroCache()
{
@@ -124,40 +133,21 @@ MacroCache::MacroCache(const MacroCache &other)
m_cache = other.cache();
}
-void MacroCache::insert(const QStringList &compilerCommand, const QByteArray &macros)
+void MacroCache::insert(const QStringList &compilerCommand, const Macros &macros)
{
- if (macros.isNull())
+ QMutexLocker locker(&m_mutex);
+ if (macros.isEmpty() || unlockedCheck(compilerCommand).isEmpty())
return;
- CacheItem runResults;
- QByteArray data = macros;
- runResults.first = compilerCommand;
- if (macros.isNull())
- data = QByteArray("");
- runResults.second = data;
-
- QMutexLocker locker(&m_mutex);
- if (check(compilerCommand).isNull()) {
- m_cache.push_back(runResults);
- if (m_cache.size() > CACHE_SIZE)
- m_cache.pop_front();
- }
+ m_cache.push_back(qMakePair(compilerCommand, macros));
+ if (m_cache.size() > CACHE_SIZE)
+ m_cache.pop_front();
}
-QByteArray MacroCache::check(const QStringList &compilerCommand) const
+Macros MacroCache::check(const QStringList &compilerCommand) const
{
QMutexLocker locker(&m_mutex);
- for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it) {
- if (it->first == compilerCommand) {
- // Increase cached item priority
- CacheItem pair = *it;
- m_cache.erase(it);
- m_cache.push_back(pair);
-
- return pair.second;
- }
- }
- return QByteArray();
+ return unlockedCheck(compilerCommand);
}
MacroCache::Cache MacroCache::cache() const
@@ -166,6 +156,16 @@ MacroCache::Cache MacroCache::cache() const
return m_cache;
}
+Macros MacroCache::unlockedCheck(const QStringList &compilerCommand) const
+{
+ auto it = std::stable_partition(m_cache.begin(), m_cache.end(), [&](const CacheItem &ci) {
+ return ci.first == compilerCommand;
+ });
+ if (it != m_cache.end())
+ return it->second;
+ return {};
+}
+
static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, const QStringList &env)
{
if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable())
@@ -187,30 +187,35 @@ static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, cons
return response.allOutput().toUtf8();
}
-static const QStringList gccPredefinedMacrosOptions()
+static const QStringList gccPredefinedMacrosOptions(Core::Id languageId)
{
- return QStringList({"-xc++", "-E", "-dM"});
+ const QString langOption = languageId == Constants::CXX_LANGUAGE_ID
+ ? QLatin1String("-xc++") : QLatin1String("-xc");
+ return QStringList({langOption, "-E", "-dM"});
}
-static QByteArray gccPredefinedMacros(const FileName &gcc, const QStringList &args, const QStringList &env)
+static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc,
+ const QStringList &args,
+ const QStringList &env)
{
QStringList arguments = args;
arguments << "-";
- QByteArray predefinedMacros = runGcc(gcc, arguments, env);
+ ProjectExplorer::Macros predefinedMacros = Macro::toMacros(runGcc(gcc, arguments, env));
// Sanity check in case we get an error message instead of real output:
- QTC_CHECK(predefinedMacros.isNull() || predefinedMacros.startsWith("#define "));
+ QTC_CHECK(predefinedMacros.isEmpty()
+ || predefinedMacros.front().type == ProjectExplorer::MacroType::Define);
if (HostOsInfo::isMacHost()) {
// Turn off flag indicating Apple's blocks support
- const QByteArray blocksDefine("#define __BLOCKS__ 1");
- const QByteArray blocksUndefine("#undef __BLOCKS__");
+ const ProjectExplorer::Macro blocksDefine("__BLOCKS__", "1");
+ const ProjectExplorer::Macro blocksUndefine("__BLOCKS__", ProjectExplorer::MacroType::Undefine);
const int idx = predefinedMacros.indexOf(blocksDefine);
if (idx != -1)
- predefinedMacros.replace(idx, blocksDefine.length(), blocksUndefine);
+ predefinedMacros[idx] = blocksUndefine;
// Define __strong and __weak (used for Apple's GC extension of C) to be empty
- predefinedMacros.append("#define __strong\n");
- predefinedMacros.append("#define __weak\n");
+ predefinedMacros.append({"__strong"});
+ predefinedMacros.append({"__weak"});
}
return predefinedMacros;
}
@@ -257,7 +262,7 @@ QList<HeaderPath> GccToolChain::gccHeaderPaths(const FileName &gcc, const QStrin
return systemHeaderPaths;
}
-static QList<Abi> guessGccAbi(const QString &m, const QByteArray &macros)
+static QList<Abi> guessGccAbi(const QString &m, const ProjectExplorer::Macros &macros)
{
QList<Abi> abiList;
@@ -270,17 +275,13 @@ static QList<Abi> guessGccAbi(const QString &m, const QByteArray &macros)
Abi::OSFlavor flavor = guessed.osFlavor();
Abi::BinaryFormat format = guessed.binaryFormat();
int width = guessed.wordWidth();
- const QByteArray mscVer = "#define _MSC_VER ";
-
- if (macros.contains("#define __SIZEOF_SIZE_T__ 8"))
- width = 64;
- else if (macros.contains("#define __SIZEOF_SIZE_T__ 4"))
- width = 32;
- int mscVerIndex = macros.indexOf(mscVer);
- if (mscVerIndex != -1) {
- mscVerIndex += mscVer.length();
- const int eol = macros.indexOf('\n', mscVerIndex);
- const int msvcVersion = macros.mid(mscVerIndex, eol - mscVerIndex).toInt();
+
+ const Macro sizeOfMacro = Utils::findOrDefault(macros, [](const Macro &m) { return m.key == "__SIZEOF_SIZE_T__"; });
+ if (sizeOfMacro.isValid() && sizeOfMacro.type == MacroType::Define)
+ width = sizeOfMacro.value.toInt() * 8;
+ const Macro &mscVerMacro = Utils::findOrDefault(macros, [](const Macro &m) { return m.key == "_MSC_VER"; });
+ if (mscVerMacro.type == MacroType::Define) {
+ const int msvcVersion = mscVerMacro.value.toInt();
flavor = Abi::flavorForMsvcVersion(msvcVersion);
}
@@ -299,7 +300,7 @@ static QList<Abi> guessGccAbi(const QString &m, const QByteArray &macros)
static GccToolChain::DetectedAbisResult guessGccAbi(const FileName &path, const QStringList &env,
- const QByteArray &macros,
+ const ProjectExplorer::Macros &macros,
const QStringList &extraArgs = QStringList())
{
if (path.isEmpty())
@@ -360,10 +361,15 @@ void GccToolChain::setOriginalTargetTriple(const QString &targetTriple)
QString GccToolChain::defaultDisplayName() const
{
- if (!m_targetAbi.isValid())
- return typeDisplayName();
+ QString type = typeDisplayName();
+ const QRegularExpression regexp(binaryRegexp);
+ const QRegularExpressionMatch match = regexp.match(m_compilerCommand.fileName());
+ if (match.lastCapturedIndex() >= 1)
+ type += ' ' + match.captured(1);
+ if (m_targetAbi.architecture() == Abi::UnknownArchitecture || m_targetAbi.wordWidth() == 0)
+ return type;
return QCoreApplication::translate("ProjectExplorer::GccToolChain",
- "%1 (%2, %3 %4 in %5)").arg(typeDisplayName(),
+ "%1 (%2, %3 %4 in %5)").arg(type,
ToolChainManager::displayNameOfLanguageId(language()),
Abi::toString(m_targetAbi.architecture()),
Abi::toString(m_targetAbi.wordWidth()),
@@ -425,14 +431,32 @@ bool GccToolChain::isValid() const
static Utils::FileName findLocalCompiler(const Utils::FileName &compilerPath,
const Environment &env)
{
- const Utils::FileName path = env.searchInPath(compilerPath.fileName(), QStringList(),
- [](const QString &pathEntry) {
- return !pathEntry.contains("icecc")
- && !pathEntry.contains("distcc");
+ // Find the "real" compiler if icecc, distcc or similar are in use. Ignore ccache, since that
+ // is local already.
+
+ // Get the path to the compiler, ignoring direct calls to icecc and distcc as we can not
+ // do anything about those.
+ const Utils::FileName compilerDir = compilerPath.parentDir();
+ const QString compilerDirString = compilerDir.toString();
+ if (!compilerDirString.contains("icecc") && !compilerDirString.contains("distcc"))
+ return compilerPath;
+
+ QStringList pathComponents = env.path();
+ auto it = std::find_if(pathComponents.begin(), pathComponents.end(),
+ [compilerDir](const QString &p) {
+ return Utils::FileName::fromString(p) == compilerDir;
});
+ if (it != pathComponents.end()) {
+ std::rotate(pathComponents.begin(), it, pathComponents.end());
+ pathComponents.removeFirst(); // remove directory of compilerPath
+ // No need to put it at the end again, it is in PATH anyway...
+ }
+
+ // This effectively searches the PATH twice, once via pathComponents and once via PATH itself:
+ // searchInPath filters duplicates, so that will not hurt.
+ const Utils::FileName path = env.searchInPath(compilerPath.fileName(), pathComponents);
- QTC_ASSERT(!path.isEmpty(), return compilerPath);
- return path;
+ return path.isEmpty() ? compilerPath : path;
}
ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() const
@@ -445,12 +469,13 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c
OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter;
QTC_CHECK(reinterpretOptions);
MacroCache *macroCache = &m_predefinedMacrosCache;
+ Core::Id lang = language();
// This runner must be thread-safe!
- return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, macroCache]
+ return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, macroCache, lang]
(const QStringList &cxxflags) {
QStringList allCxxflags = platformCodeGenFlags + cxxflags; // add only cxxflags is empty?
- QStringList arguments = gccPredefinedMacrosOptions();
+ QStringList arguments = gccPredefinedMacrosOptions(lang);
for (int iArg = 0; iArg < allCxxflags.length(); ++iArg) {
const QString &a = allCxxflags.at(iArg);
if (a.startsWith("--gcc-toolchain=")) {
@@ -483,8 +508,8 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c
}
arguments = reinterpretOptions(arguments);
- QByteArray macros = macroCache->check(arguments);
- if (!macros.isNull())
+ Macros macros = macroCache->check(arguments);
+ if (!macros.isEmpty())
return macros;
macros = gccPredefinedMacros(findLocalCompiler(compilerCommand, env),
@@ -505,7 +530,7 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c
* adds _OPENMP macro, for full list of macro search by word "when" on this page:
* http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
*/
-QByteArray GccToolChain::predefinedMacros(const QStringList &cxxflags) const
+ProjectExplorer::Macros GccToolChain::predefinedMacros(const QStringList &cxxflags) const
{
return createPredefinedMacrosRunner()(cxxflags);
}
@@ -689,6 +714,8 @@ void GccToolChain::addCommandPathToEnvironment(const FileName &command, Environm
env.prependOrSetPath(command.parentDir().toString());
}
+GccToolChain::GccToolChain(const GccToolChain &) = default;
+
void GccToolChain::addToEnvironment(Environment &env) const
{
addCommandPathToEnvironment(m_compilerCommand, env);
@@ -886,7 +913,7 @@ GccToolChain::DetectedAbisResult GccToolChain::detectSupportedAbis() const
{
Environment env = Environment::systemEnvironment();
addToEnvironment(env);
- QByteArray macros = predefinedMacros(QStringList());
+ ProjectExplorer::Macros macros = predefinedMacros(QStringList());
return guessGccAbi(findLocalCompiler(m_compilerCommand, env),
env.toStringList(),
macros,
@@ -929,10 +956,37 @@ ToolChain *GccToolChainFactory::create(Core::Id language)
QList<ToolChain *> GccToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{
QList<ToolChain *> tcs;
+ QList<ToolChain *> known = alreadyKnown;
tcs.append(autoDetectToolchains("g++", Abi::hostAbi(), Constants::CXX_LANGUAGE_ID,
Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown));
tcs.append(autoDetectToolchains("gcc", Abi::hostAbi(), Constants::C_LANGUAGE_ID,
Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown));
+ known.append(tcs);
+ if (HostOsInfo::isLinuxHost()) {
+ const QRegularExpression regexp(binaryRegexp);
+ for (const QString &dir : QStringList({ "/usr/bin", "/usr/local/bin" })) {
+ QDir binDir(dir);
+ auto gccProbe = [&](const QString &name, Core::Id language) {
+ for (const QString &entry : binDir.entryList(
+ {"*-" + name, name + "-*", "*-" + name + "-*"},
+ QDir::Files | QDir::Executable)) {
+ const QString fileName = FileName::fromString(entry).fileName();
+ if (fileName == "c89-gcc" || fileName == "c99-gcc")
+ continue;
+ const QRegularExpressionMatch match = regexp.match(fileName);
+ if (!match.hasMatch())
+ continue;
+ const bool isNative = fileName.startsWith(name);
+ const Abi abi = isNative ? Abi::hostAbi() : Abi();
+ tcs.append(autoDetectToolchains(entry, abi, language,
+ Constants::GCC_TOOLCHAIN_TYPEID, known));
+ known.append(tcs);
+ }
+ };
+ gccProbe("g++", Constants::CXX_LANGUAGE_ID);
+ gccProbe("gcc", Constants::C_LANGUAGE_ID);
+ }
+ }
return tcs;
}
@@ -981,11 +1035,11 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolchains(const QString &comp
const FileName compilerPath = systemEnvironment.searchInPath(compiler);
if (compilerPath.isEmpty())
return result;
+ const FileName canonicalPath = FileUtils::canonicalPath(compilerPath);
result = Utils::filtered(alreadyKnown, [requiredTypeId, compilerPath](ToolChain *tc) {
- return tc->typeId() == requiredTypeId
- && tc->compilerCommand() == compilerPath;
- });
+ return tc->typeId() == requiredTypeId && tc->compilerCommand() == compilerPath;
+ });
if (!result.isEmpty()) {
for (ToolChain *tc : result) {
if (tc->isAutoDetected())
@@ -996,15 +1050,17 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolchains(const QString &comp
result = autoDetectToolChain(compilerPath, language, requiredAbi);
- const Abi alternateAbi = Abi(requiredAbi.architecture(), requiredAbi.os(),
- requiredAbi.osFlavor(), requiredAbi.binaryFormat(), 32);
- ToolChain *abiTc = Utils::findOrDefault(result, [&requiredAbi, &alternateAbi](const ToolChain *tc) {
- return requiredAbi == tc->targetAbi()
- || (requiredAbi.wordWidth() == 64 && tc->targetAbi() == alternateAbi);
- });
- if (!abiTc) {
- qDeleteAll(result);
- result.clear();
+ if (!requiredAbi.isNull()) {
+ const Abi alternateAbi = Abi(requiredAbi.architecture(), requiredAbi.os(),
+ requiredAbi.osFlavor(), requiredAbi.binaryFormat(), 32);
+ ToolChain *abiTc = Utils::findOrDefault(result, [&requiredAbi, &alternateAbi](const ToolChain *tc) {
+ return requiredAbi == tc->targetAbi()
+ || (requiredAbi.wordWidth() == 64 && tc->targetAbi() == alternateAbi);
+ });
+ if (!abiTc) {
+ qDeleteAll(result);
+ result.clear();
+ }
}
return result;
@@ -1019,8 +1075,9 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &comp
Environment systemEnvironment = Environment::systemEnvironment();
GccToolChain::addCommandPathToEnvironment(compilerPath, systemEnvironment);
const FileName localCompilerPath = findLocalCompiler(compilerPath, systemEnvironment);
- QByteArray macros
- = gccPredefinedMacros(localCompilerPath, gccPredefinedMacrosOptions(), systemEnvironment.toStringList());
+ Macros macros
+ = gccPredefinedMacros(localCompilerPath, gccPredefinedMacrosOptions(language),
+ systemEnvironment.toStringList());
const GccToolChain::DetectedAbisResult detectedAbis = guessGccAbi(localCompilerPath,
systemEnvironment.toStringList(),
macros);
@@ -1171,7 +1228,8 @@ void GccToolChainConfigWidget::handleCompilerCommandChange()
if (haveCompiler) {
Environment env = Environment::systemEnvironment();
GccToolChain::addCommandPathToEnvironment(path, env);
- QStringList args = gccPredefinedMacrosOptions() + splitString(m_platformCodeGenFlagsLineEdit->text());
+ QStringList args = gccPredefinedMacrosOptions(Constants::CXX_LANGUAGE_ID)
+ + splitString(m_platformCodeGenFlagsLineEdit->text());
const FileName localCompilerPath = findLocalCompiler(path, env);
m_macros = gccPredefinedMacros(localCompilerPath, args, env.toStringList());
abiList = guessGccAbi(localCompilerPath, env.toStringList(), m_macros,
@@ -1722,7 +1780,7 @@ void ProjectExplorerPlugin::testGccAbiGuessing()
QFETCH(QByteArray, macros);
QFETCH(QStringList, abiList);
- QList<Abi> al = guessGccAbi(input, macros);
+ QList<Abi> al = guessGccAbi(input, ProjectExplorer::Macro::toMacros(macros));
QCOMPARE(al.count(), abiList.count());
for (int i = 0; i < al.count(); ++i)
QCOMPARE(al.at(i).toString(), abiList.at(i));
diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h
index 0399b1ec14..a3c4b4eaca 100644
--- a/src/plugins/projectexplorer/gcctoolchain.h
+++ b/src/plugins/projectexplorer/gcctoolchain.h
@@ -51,7 +51,7 @@ class LinuxIccToolChainFactory;
// GccToolChain
// --------------------------------------------------------------------------
-class PROJECTEXPLORER_EXPORT HeaderPathsCache
+class HeaderPathsCache
{
public:
HeaderPathsCache() : m_mutex(QMutex::Recursive) {}
@@ -69,20 +69,22 @@ private:
mutable Cache m_cache;
};
-class PROJECTEXPLORER_EXPORT MacroCache
+class MacroCache
{
public:
- MacroCache() : m_mutex(QMutex::Recursive) {}
+ MacroCache();
MacroCache(const MacroCache &other);
- void insert(const QStringList &compilerCommand, const QByteArray &macros);
- QByteArray check(const QStringList &compilerCommand) const;
+ void insert(const QStringList &compilerCommand, const Macros &macros);
+ Macros check(const QStringList &compilerCommand) const;
protected:
- using CacheItem = QPair<QStringList, QByteArray>;
- using Cache = QList<CacheItem>;
+ using CacheItem = QPair<QStringList, Macros>;
+ using Cache = QVector<CacheItem>;
Cache cache() const;
private:
+ // Does not lock!
+ Macros unlockedCheck(const QStringList &compilerCommand) const;
mutable QMutex m_mutex;
mutable Cache m_cache;
};
@@ -104,7 +106,7 @@ public:
WarningFlags warningFlags(const QStringList &cflags) const override;
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
- QByteArray predefinedMacros(const QStringList &cxxflags) const override;
+ Macros predefinedMacros(const QStringList &cxxflags) const override;
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
QList<HeaderPath> systemHeaderPaths(const QStringList &cxxflags,
@@ -147,14 +149,16 @@ public:
};
protected:
- GccToolChain(const GccToolChain &) = default;
+ using CacheItem = QPair<QStringList, Macros>;
+ using GccCache = QVector<CacheItem>;
+
+ GccToolChain(const GccToolChain &);
void setCompilerCommand(const Utils::FileName &path);
void setSupportedAbis(const QList<Abi> &m_abis);
void setOriginalTargetTriple(const QString &targetTriple);
-
- void setMacroCache(const QStringList &allCxxflags, const QByteArray &macros) const;
- QByteArray macroCache(const QStringList &allCxxflags) const;
+ void setMacroCache(const QStringList &allCxxflags, const Macros &macroCache) const;
+ Macros macroCache(const QStringList &allCxxflags) const;
virtual QString defaultDisplayName() const;
virtual CompilerFlags defaultCompilerFlags() const;
diff --git a/src/plugins/projectexplorer/gcctoolchainfactories.h b/src/plugins/projectexplorer/gcctoolchainfactories.h
index 4417fc712f..e4c0a583e9 100644
--- a/src/plugins/projectexplorer/gcctoolchainfactories.h
+++ b/src/plugins/projectexplorer/gcctoolchainfactories.h
@@ -99,7 +99,7 @@ private:
AbiWidget *m_abiWidget;
bool m_isReadOnly = false;
- QByteArray m_macros;
+ ProjectExplorer::Macros m_macros;
};
// --------------------------------------------------------------------------
diff --git a/src/plugins/projectexplorer/images/build.png b/src/plugins/projectexplorer/images/build.png
index e4590537ed..76bdf9a460 100644
--- a/src/plugins/projectexplorer/images/build.png
+++ b/src/plugins/projectexplorer/images/build.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/build@2x.png b/src/plugins/projectexplorer/images/build@2x.png
index bb2b17ebc4..b3e3c581a3 100644
--- a/src/plugins/projectexplorer/images/build@2x.png
+++ b/src/plugins/projectexplorer/images/build@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/build_hammerhandle_mask.png b/src/plugins/projectexplorer/images/build_hammerhandle_mask.png
index 8759e4204f..15e318ac4a 100644
--- a/src/plugins/projectexplorer/images/build_hammerhandle_mask.png
+++ b/src/plugins/projectexplorer/images/build_hammerhandle_mask.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/build_hammerhandle_mask@2x.png b/src/plugins/projectexplorer/images/build_hammerhandle_mask@2x.png
index 04304d35f8..8b2525dbf4 100644
--- a/src/plugins/projectexplorer/images/build_hammerhandle_mask@2x.png
+++ b/src/plugins/projectexplorer/images/build_hammerhandle_mask@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/build_hammerhead_mask.png b/src/plugins/projectexplorer/images/build_hammerhead_mask.png
index 31a174fd17..98f11810b3 100644
--- a/src/plugins/projectexplorer/images/build_hammerhead_mask.png
+++ b/src/plugins/projectexplorer/images/build_hammerhead_mask.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/build_hammerhead_mask@2x.png b/src/plugins/projectexplorer/images/build_hammerhead_mask@2x.png
index 4bc0b4b7fc..ec7ecd42b0 100644
--- a/src/plugins/projectexplorer/images/build_hammerhead_mask@2x.png
+++ b/src/plugins/projectexplorer/images/build_hammerhead_mask@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/build_small.png b/src/plugins/projectexplorer/images/build_small.png
deleted file mode 100644
index 991f2c0c30..0000000000
--- a/src/plugins/projectexplorer/images/build_small.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/projectexplorer/images/buildhammerhandle.png b/src/plugins/projectexplorer/images/buildhammerhandle.png
new file mode 100644
index 0000000000..6c7c8a00e0
--- /dev/null
+++ b/src/plugins/projectexplorer/images/buildhammerhandle.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/buildhammerhandle@2x.png b/src/plugins/projectexplorer/images/buildhammerhandle@2x.png
new file mode 100644
index 0000000000..5e67dc5ab9
--- /dev/null
+++ b/src/plugins/projectexplorer/images/buildhammerhandle@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/buildhammerhead.png b/src/plugins/projectexplorer/images/buildhammerhead.png
new file mode 100644
index 0000000000..2f7fd76a1a
--- /dev/null
+++ b/src/plugins/projectexplorer/images/buildhammerhead.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/buildhammerhead@2x.png b/src/plugins/projectexplorer/images/buildhammerhead@2x.png
new file mode 100644
index 0000000000..374166321c
--- /dev/null
+++ b/src/plugins/projectexplorer/images/buildhammerhead@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/debugger_beetle_mask.png b/src/plugins/projectexplorer/images/debugger_beetle_mask.png
index b041005b3a..816aacc339 100644
--- a/src/plugins/projectexplorer/images/debugger_beetle_mask.png
+++ b/src/plugins/projectexplorer/images/debugger_beetle_mask.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/debugger_beetle_mask@2x.png b/src/plugins/projectexplorer/images/debugger_beetle_mask@2x.png
index f4f7098ee3..c240532d29 100644
--- a/src/plugins/projectexplorer/images/debugger_beetle_mask@2x.png
+++ b/src/plugins/projectexplorer/images/debugger_beetle_mask@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/debugger_start.png b/src/plugins/projectexplorer/images/debugger_start.png
index 973d1fad52..0e7cd1a672 100644
--- a/src/plugins/projectexplorer/images/debugger_start.png
+++ b/src/plugins/projectexplorer/images/debugger_start.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/debugger_start@2x.png b/src/plugins/projectexplorer/images/debugger_start@2x.png
index e29d9b603d..ab7cc15f7a 100644
--- a/src/plugins/projectexplorer/images/debugger_start@2x.png
+++ b/src/plugins/projectexplorer/images/debugger_start@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/desktopdevice.png b/src/plugins/projectexplorer/images/desktopdevice.png
index 2323f95b6f..10909fdd1d 100644
--- a/src/plugins/projectexplorer/images/desktopdevice.png
+++ b/src/plugins/projectexplorer/images/desktopdevice.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/desktopdevice@2x.png b/src/plugins/projectexplorer/images/desktopdevice@2x.png
index 8abf5f330a..4fd9ca8a16 100644
--- a/src/plugins/projectexplorer/images/desktopdevice@2x.png
+++ b/src/plugins/projectexplorer/images/desktopdevice@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/devicestatusindicator.png b/src/plugins/projectexplorer/images/devicestatusindicator.png
index 2b13d25aa2..44e045cfb4 100644
--- a/src/plugins/projectexplorer/images/devicestatusindicator.png
+++ b/src/plugins/projectexplorer/images/devicestatusindicator.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/devicestatusindicator@2x.png b/src/plugins/projectexplorer/images/devicestatusindicator@2x.png
index 4cb3a5d42d..7f03474cd0 100644
--- a/src/plugins/projectexplorer/images/devicestatusindicator@2x.png
+++ b/src/plugins/projectexplorer/images/devicestatusindicator@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/mode_project.png b/src/plugins/projectexplorer/images/mode_project.png
index 67fc372046..cb4856b325 100644
--- a/src/plugins/projectexplorer/images/mode_project.png
+++ b/src/plugins/projectexplorer/images/mode_project.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/mode_project@2x.png b/src/plugins/projectexplorer/images/mode_project@2x.png
index f0b7fdae0e..264cece448 100644
--- a/src/plugins/projectexplorer/images/mode_project@2x.png
+++ b/src/plugins/projectexplorer/images/mode_project@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/mode_project_mask.png b/src/plugins/projectexplorer/images/mode_project_mask.png
index beffa6722b..6e6092b7ad 100644
--- a/src/plugins/projectexplorer/images/mode_project_mask.png
+++ b/src/plugins/projectexplorer/images/mode_project_mask.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/mode_project_mask@2x.png b/src/plugins/projectexplorer/images/mode_project_mask@2x.png
index bd195752ac..3538453911 100644
--- a/src/plugins/projectexplorer/images/mode_project_mask@2x.png
+++ b/src/plugins/projectexplorer/images/mode_project_mask@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/rebuildhammerhandles.png b/src/plugins/projectexplorer/images/rebuildhammerhandles.png
index d0c117da13..181b4f3881 100644
--- a/src/plugins/projectexplorer/images/rebuildhammerhandles.png
+++ b/src/plugins/projectexplorer/images/rebuildhammerhandles.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/rebuildhammerhandles@2x.png b/src/plugins/projectexplorer/images/rebuildhammerhandles@2x.png
index 9ea2b3a871..a9742c822e 100644
--- a/src/plugins/projectexplorer/images/rebuildhammerhandles@2x.png
+++ b/src/plugins/projectexplorer/images/rebuildhammerhandles@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/rebuildhammerheads.png b/src/plugins/projectexplorer/images/rebuildhammerheads.png
index 24de5314c9..b683bd8bd4 100644
--- a/src/plugins/projectexplorer/images/rebuildhammerheads.png
+++ b/src/plugins/projectexplorer/images/rebuildhammerheads.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/rebuildhammerheads@2x.png b/src/plugins/projectexplorer/images/rebuildhammerheads@2x.png
index 50f8757d19..ac71ffc9cc 100644
--- a/src/plugins/projectexplorer/images/rebuildhammerheads@2x.png
+++ b/src/plugins/projectexplorer/images/rebuildhammerheads@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/run.png b/src/plugins/projectexplorer/images/run.png
index 2df52b8e7f..7650f12206 100644
--- a/src/plugins/projectexplorer/images/run.png
+++ b/src/plugins/projectexplorer/images/run.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/run@2x.png b/src/plugins/projectexplorer/images/run@2x.png
index 9e6e984d7c..f55a9bd37c 100644
--- a/src/plugins/projectexplorer/images/run@2x.png
+++ b/src/plugins/projectexplorer/images/run@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/run_mask.png b/src/plugins/projectexplorer/images/run_mask.png
index aaaf05ce22..d08de1ad5f 100644
--- a/src/plugins/projectexplorer/images/run_mask.png
+++ b/src/plugins/projectexplorer/images/run_mask.png
Binary files differ
diff --git a/src/plugins/projectexplorer/images/run_mask@2x.png b/src/plugins/projectexplorer/images/run_mask@2x.png
index 38f6445c25..72af48223e 100644
--- a/src/plugins/projectexplorer/images/run_mask@2x.png
+++ b/src/plugins/projectexplorer/images/run_mask@2x.png
Binary files differ
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
index d7b284e877..80e39bec98 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp
@@ -438,7 +438,8 @@ QWidget *LineEditField::createWidget(const QString &displayName, JsonFieldPage *
void LineEditField::setup(JsonFieldPage *page, const QString &name)
{
- auto w = static_cast<FancyLineEdit *>(widget());
+ auto w = qobject_cast<FancyLineEdit *>(widget());
+ QTC_ASSERT(w, return);
page->registerFieldWithName(name, w);
QObject::connect(w, &FancyLineEdit::textChanged,
page, [this, page]() -> void { m_isModified = true; emit page->completeChanged(); });
@@ -454,7 +455,8 @@ bool LineEditField::validate(MacroExpander *expander, QString *message)
m_isValidating = true;
- auto w = static_cast<FancyLineEdit *>(widget());
+ auto w = qobject_cast<FancyLineEdit *>(widget());
+ QTC_ASSERT(w, return false);
if (w->isEnabled()) {
if (m_isModified) {
@@ -478,9 +480,8 @@ bool LineEditField::validate(MacroExpander *expander, QString *message)
void LineEditField::initializeData(MacroExpander *expander)
{
- QTC_ASSERT(widget(), return);
-
- auto w = static_cast<FancyLineEdit *>(widget());
+ auto w = qobject_cast<FancyLineEdit *>(widget());
+ QTC_ASSERT(w, return);
m_isValidating = true;
w->setText(expander->expand(m_defaultText));
w->setPlaceholderText(m_placeholderText);
@@ -525,7 +526,8 @@ QWidget *TextEditField::createWidget(const QString &displayName, JsonFieldPage *
void TextEditField::setup(JsonFieldPage *page, const QString &name)
{
- auto w = static_cast<QTextEdit *>(widget());
+ auto w = qobject_cast<QTextEdit *>(widget());
+ QTC_ASSERT(w, return);
page->registerFieldWithName(name, w, "plainText", SIGNAL(textChanged()));
QObject::connect(w, &QTextEdit::textChanged, page, &QWizardPage::completeChanged);
}
@@ -535,7 +537,8 @@ bool TextEditField::validate(MacroExpander *expander, QString *message)
if (!JsonFieldPage::Field::validate(expander, message))
return false;
- auto w = static_cast<QTextEdit *>(widget());
+ auto w = qobject_cast<QTextEdit *>(widget());
+ QTC_ASSERT(w, return false);
if (!w->isEnabled() && !m_disabledText.isNull() && m_currentText.isNull()) {
m_currentText = w->toHtml();
@@ -550,7 +553,8 @@ bool TextEditField::validate(MacroExpander *expander, QString *message)
void TextEditField::initializeData(MacroExpander *expander)
{
- auto w = static_cast<QTextEdit *>(widget());
+ auto w = qobject_cast<QTextEdit *>(widget());
+ QTC_ASSERT(w, return);
w->setPlainText(expander->expand(m_defaultText));
}
@@ -614,14 +618,15 @@ QWidget *PathChooserField::createWidget(const QString &displayName, JsonFieldPag
void PathChooserField::setEnabled(bool e)
{
- QTC_ASSERT(widget(), return);
- auto w = static_cast<PathChooser *>(widget());
+ auto w = qobject_cast<PathChooser *>(widget());
+ QTC_ASSERT(w, return);
w->setReadOnly(!e);
}
void PathChooserField::setup(JsonFieldPage *page, const QString &name)
{
- auto w = static_cast<PathChooser *>(widget());
+ auto w = qobject_cast<PathChooser *>(widget());
+ QTC_ASSERT(w, return);
page->registerFieldWithName(name, w, "path", SIGNAL(rawPathChanged(QString)));
QObject::connect(w, &PathChooser::rawPathChanged,
page, [page](QString) { page->completeChanged(); });
@@ -632,14 +637,15 @@ bool PathChooserField::validate(MacroExpander *expander, QString *message)
if (!JsonFieldPage::Field::validate(expander, message))
return false;
- auto w = static_cast<PathChooser *>(widget());
+ auto w = qobject_cast<PathChooser *>(widget());
+ QTC_ASSERT(w, return false);
return w->isValid();
}
void PathChooserField::initializeData(MacroExpander *expander)
{
- QTC_ASSERT(widget(), return);
- auto w = static_cast<PathChooser *>(widget());
+ auto w = qobject_cast<PathChooser *>(widget());
+ QTC_ASSERT(w, return);
w->setBaseDirectory(expander->expand(m_basePath));
w->setExpectedKind(m_kind);
@@ -686,7 +692,8 @@ QWidget *CheckBoxField::createWidget(const QString &displayName, JsonFieldPage *
void CheckBoxField::setup(JsonFieldPage *page, const QString &name)
{
- auto w = static_cast<TextFieldCheckBox *>(widget());
+ auto w = qobject_cast<TextFieldCheckBox *>(widget());
+ QTC_ASSERT(w, return);
QObject::connect(w, &TextFieldCheckBox::clicked,
page, [this, page]() { m_isModified = true; page->completeChanged();});
page->registerFieldWithName(name, w, "compareText", SIGNAL(textChanged(QString)));
@@ -698,7 +705,8 @@ bool CheckBoxField::validate(MacroExpander *expander, QString *message)
return false;
if (!m_isModified) {
- auto w = static_cast<TextFieldCheckBox *>(widget());
+ auto w = qobject_cast<TextFieldCheckBox *>(widget());
+ QTC_ASSERT(w, return false);
w->setChecked(JsonWizard::boolFromVariant(m_checkedExpression, expander));
}
return true;
@@ -706,9 +714,8 @@ bool CheckBoxField::validate(MacroExpander *expander, QString *message)
void CheckBoxField::initializeData(MacroExpander *expander)
{
+ auto w = qobject_cast<TextFieldCheckBox *>(widget());
QTC_ASSERT(widget(), return);
-
- auto w = static_cast<TextFieldCheckBox *>(widget());
w->setTrueText(expander->expand(m_checkedValue));
w->setFalseText(expander->expand(m_uncheckedValue));
@@ -821,7 +828,8 @@ QWidget *ComboBoxField::createWidget(const QString &displayName, JsonFieldPage *
void ComboBoxField::setup(JsonFieldPage *page, const QString &name)
{
- auto w = static_cast<TextFieldComboBox *>(widget());
+ auto w = qobject_cast<TextFieldComboBox *>(widget());
+ QTC_ASSERT(w, return);
page->registerFieldWithName(name, w, "indexText", SIGNAL(text4Changed(QString)));
QObject::connect(w, &TextFieldComboBox::text4Changed,
page, [page](QString) { page->completeChanged(); });
@@ -832,7 +840,8 @@ bool ComboBoxField::validate(MacroExpander *expander, QString *message)
if (!JsonFieldPage::Field::validate(expander, message))
return false;
- auto w = static_cast<TextFieldComboBox *>(widget());
+ auto w = qobject_cast<TextFieldComboBox *>(widget());
+ QTC_ASSERT(w, return false);
if (!w->isEnabled() && m_disabledIndex >= 0 && m_savedIndex < 0) {
m_savedIndex = w->currentIndex();
w->setCurrentIndex(m_disabledIndex);
@@ -846,7 +855,8 @@ bool ComboBoxField::validate(MacroExpander *expander, QString *message)
void ComboBoxField::initializeData(MacroExpander *expander)
{
- auto w = static_cast<TextFieldComboBox *>(widget());
+ auto w = qobject_cast<TextFieldComboBox *>(widget());
+ QTC_ASSERT(widget(), return);
QStringList tmpItems
= Utils::transform(m_itemList,
[expander](const QString &i) { return expander->expand(i); });
diff --git a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp
index b23b000d30..45f332a2de 100644
--- a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp
+++ b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp
@@ -28,6 +28,7 @@
#include <coreplugin/documentmanager.h>
+#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <QDir>
@@ -51,7 +52,7 @@ bool JsonProjectPage::validatePage()
{
if (isComplete() && useAsDefaultPath()) {
// Store the path as default path for new projects if desired.
- Core::DocumentManager::setProjectsDirectory(path());
+ Core::DocumentManager::setProjectsDirectory(Utils::FileName::fromString(path()));
Core::DocumentManager::setUseProjectsDirectory(true);
}
diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp
index c6fb97cffe..a4d7b608f6 100644
--- a/src/plugins/projectexplorer/kit.cpp
+++ b/src/plugins/projectexplorer/kit.cpp
@@ -381,7 +381,7 @@ QIcon Kit::icon() const
if (!d->m_cachedIcon.isNull())
return d->m_cachedIcon;
- if (d->m_iconPath.exists()) {
+ if (!d->m_iconPath.isEmpty() && d->m_iconPath.exists()) {
d->m_cachedIcon = QIcon(d->m_iconPath.toString());
return d->m_cachedIcon;
}
diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp
index f340f086dc..34578f64b8 100644
--- a/src/plugins/projectexplorer/kitinformation.cpp
+++ b/src/plugins/projectexplorer/kitinformation.cpp
@@ -101,7 +101,7 @@ KitInformation::ItemList SysRootKitInformation::toUserOutput(const Kit *k) const
void SysRootKitInformation::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
{
- expander->registerFileVariables("SysRoot", tr("Sys Root"), [this, kit]() -> QString {
+ expander->registerFileVariables("SysRoot", tr("Sys Root"), [kit]() -> QString {
return SysRootKitInformation::sysRoot(kit).toString();
});
}
@@ -190,7 +190,8 @@ QList<Task> ToolChainKitInformation::validate(const Kit *k) const
result << tc->validateKit(k);
}
if (targetAbis.count() != 1) {
- result << Task(Task::Error, tr("Compilers produce code for different ABIs."),
+ result << Task(Task::Error, tr("Compilers produce code for different ABIs: %1")
+ .arg(Utils::transform(targetAbis, &Abi::toString).toList().join(", ")),
Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM));
}
}
@@ -335,24 +336,24 @@ void ToolChainKitInformation::addToMacroExpander(Kit *kit, Utils::MacroExpander
{
// Compatibility with Qt Creator < 4.2:
expander->registerVariable("Compiler:Name", tr("Compiler"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const ToolChain *tc = toolChain(kit, Constants::CXX_LANGUAGE_ID);
return tc ? tc->displayName() : tr("None");
});
expander->registerVariable("Compiler:Executable", tr("Path to the compiler executable"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const ToolChain *tc = toolChain(kit, Constants::CXX_LANGUAGE_ID);
return tc ? tc->compilerCommand().toString() : QString();
});
expander->registerPrefix("Compiler:Name", tr("Compiler for different languages"),
- [this, kit](const QString &ls) -> QString {
+ [kit](const QString &ls) -> QString {
const ToolChain *tc = toolChain(kit, findLanguage(ls));
return tc ? tc->displayName() : tr("None");
});
expander->registerPrefix("Compiler:Executable", tr("Compiler executable for different languages"),
- [this, kit](const QString &ls) -> QString {
+ [kit](const QString &ls) -> QString {
const ToolChain *tc = toolChain(kit, findLanguage(ls));
return tc ? tc->compilerCommand().toString() : QString();
});
@@ -518,7 +519,7 @@ void ToolChainKitInformation::kitsWereLoaded()
void ToolChainKitInformation::toolChainUpdated(ToolChain *tc)
{
- for (Kit *k : KitManager::kits([tc, this](const Kit *k) { return toolChain(k, tc->language()) == tc; }))
+ for (Kit *k : KitManager::kits([tc](const Kit *k) { return toolChain(k, tc->language()) == tc; }))
notifyAboutUpdate(k);
}
@@ -691,27 +692,27 @@ KitInformation::ItemList DeviceKitInformation::toUserOutput(const Kit *k) const
void DeviceKitInformation::addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const
{
expander->registerVariable("Device:HostAddress", tr("Host address"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
return device ? device->sshParameters().host : QString();
});
expander->registerVariable("Device:SshPort", tr("SSH port"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
return device ? QString::number(device->sshParameters().port) : QString();
});
expander->registerVariable("Device:UserName", tr("User name"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
return device ? device->sshParameters().userName : QString();
});
expander->registerVariable("Device:KeyFile", tr("Private key file"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
return device ? device->sshParameters().privateKeyFile : QString();
});
expander->registerVariable("Device:Name", tr("Device name"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
const IDevice::ConstPtr device = DeviceKitInformation::device(kit);
return device ? device->displayName() : QString();
});
diff --git a/src/plugins/projectexplorer/localenvironmentaspect.cpp b/src/plugins/projectexplorer/localenvironmentaspect.cpp
index edc9e8a761..9d7cd8dcdc 100644
--- a/src/plugins/projectexplorer/localenvironmentaspect.cpp
+++ b/src/plugins/projectexplorer/localenvironmentaspect.cpp
@@ -88,7 +88,9 @@ LocalEnvironmentAspect::LocalEnvironmentAspect(RunConfiguration *parent,
const BaseEnvironmentModifier &modifier) :
EnvironmentAspect(parent), m_baseEnvironmentModifier(modifier)
{
- connect(parent->target(), &Target::environmentChanged,
+ parent->target()->subscribeSignal(&BuildConfiguration::environmentChanged,
+ this, &LocalEnvironmentAspect::buildEnvironmentHasChanged);
+ connect(parent->target(), &Target::activeBuildConfigurationChanged,
this, &LocalEnvironmentAspect::buildEnvironmentHasChanged);
}
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index d1efd49bb6..d21af387ac 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -23,12 +23,20 @@
**
****************************************************************************/
-#include "miniprojecttargetselector.h"
-#include "kit.h"
+#include "buildconfiguration.h"
+#include "deployconfiguration.h"
#include "kitconfigwidget.h"
+#include "kit.h"
#include "kitmanager.h"
-#include "target.h"
+#include "kitmanager.h"
+#include "miniprojecttargetselector.h"
+#include "projectexplorer.h"
#include "projectexplorericons.h"
+#include "project.h"
+#include "projectmodels.h"
+#include "runconfiguration.h"
+#include "session.h"
+#include "target.h"
#include <utils/algorithm.h>
#include <utils/styledbar.h>
@@ -39,23 +47,16 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/modemanager.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/session.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/deployconfiguration.h>
-#include <projectexplorer/kitmanager.h>
-#include <projectexplorer/projectmodels.h>
-#include <projectexplorer/runconfiguration.h>
-
#include <QGuiApplication>
#include <QTimer>
#include <QLayout>
#include <QLabel>
+#include <QList>
#include <QListWidget>
#include <QStatusBar>
#include <QKeyEvent>
#include <QPainter>
+#include <QPixmap>
#include <QStyleFactory>
#include <QAction>
#include <QItemDelegate>
@@ -64,21 +65,21 @@ static QIcon createCenteredIcon(const QIcon &icon, const QIcon &overlay)
{
QPixmap targetPixmap;
const qreal appDevicePixelRatio = qApp->devicePixelRatio();
- int deviceSpaceIconSize = Core::Constants::TARGET_ICON_SIZE * appDevicePixelRatio;
+ const int deviceSpaceIconSize = static_cast<int>(Core::Constants::MODEBAR_ICON_SIZE * appDevicePixelRatio);
targetPixmap = QPixmap(deviceSpaceIconSize, deviceSpaceIconSize);
targetPixmap.setDevicePixelRatio(appDevicePixelRatio);
targetPixmap.fill(Qt::transparent);
QPainter painter(&targetPixmap); // painter in user space
- QPixmap pixmap = icon.pixmap(Core::Constants::TARGET_ICON_SIZE); // already takes app devicePixelRatio into account
+ QPixmap pixmap = icon.pixmap(Core::Constants::MODEBAR_ICON_SIZE); // already takes app devicePixelRatio into account
qreal pixmapDevicePixelRatio = pixmap.devicePixelRatio();
- painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2,
- (Core::Constants::TARGET_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap);
+ painter.drawPixmap((Core::Constants::MODEBAR_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2,
+ (Core::Constants::MODEBAR_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap);
if (!overlay.isNull()) {
- pixmap = overlay.pixmap(Core::Constants::TARGET_ICON_SIZE); // already takes app devicePixelRatio into account
+ pixmap = overlay.pixmap(Core::Constants::MODEBAR_ICON_SIZE); // already takes app devicePixelRatio into account
pixmapDevicePixelRatio = pixmap.devicePixelRatio();
- painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2,
- (Core::Constants::TARGET_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap);
+ painter.drawPixmap((Core::Constants::MODEBAR_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2,
+ (Core::Constants::MODEBAR_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap);
}
return QIcon(targetPixmap);
@@ -695,10 +696,10 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
m_listWidgets[i] = new GenericListWidget(this);
}
+ // Validate state: At this point the session is still empty!
Project *startup = SessionManager::startupProject();
- changeStartupProject(startup);
- if (startup)
- activeTargetChanged(startup->activeTarget());
+ QTC_CHECK(!startup);
+ QTC_CHECK(SessionManager::projects().isEmpty());
connect(m_summaryLabel, &QLabel::linkActivated,
this, &MiniProjectTargetSelector::switchToProjectsMode);
@@ -719,13 +720,23 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
this, &MiniProjectTargetSelector::kitChanged);
connect(m_listWidgets[TARGET], &GenericListWidget::changeActiveProjectConfiguration,
- this, &MiniProjectTargetSelector::setActiveTarget);
+ this, [this](ProjectConfiguration *pc) {
+ SessionManager::setActiveTarget(m_project, static_cast<Target *>(pc), SetActive::Cascade);
+ });
connect(m_listWidgets[BUILD], &GenericListWidget::changeActiveProjectConfiguration,
- this, &MiniProjectTargetSelector::setActiveBuildConfiguration);
+ this, [this](ProjectConfiguration *pc) {
+ SessionManager::setActiveBuildConfiguration(m_project->activeTarget(),
+ static_cast<BuildConfiguration *>(pc), SetActive::Cascade);
+ });
connect(m_listWidgets[DEPLOY], &GenericListWidget::changeActiveProjectConfiguration,
- this, &MiniProjectTargetSelector::setActiveDeployConfiguration);
+ this, [this](ProjectConfiguration *pc) {
+ SessionManager::setActiveDeployConfiguration(m_project->activeTarget(),
+ static_cast<DeployConfiguration *>(pc), SetActive::Cascade);
+ });
connect(m_listWidgets[RUN], &GenericListWidget::changeActiveProjectConfiguration,
- this, &MiniProjectTargetSelector::setActiveRunConfiguration);
+ this, [this](ProjectConfiguration *pc) {
+ m_project->activeTarget()->setActiveRunConfiguration(static_cast<RunConfiguration *>(pc));
+ });
}
bool MiniProjectTargetSelector::event(QEvent *event)
@@ -959,34 +970,13 @@ void MiniProjectTargetSelector::doLayout(bool keepSize)
move(moveTo);
}
-void MiniProjectTargetSelector::setActiveTarget(ProjectConfiguration *pc)
-{
- SessionManager::setActiveTarget(m_project, static_cast<Target *>(pc),
- SetActive::Cascade);
-}
-
-void MiniProjectTargetSelector::setActiveBuildConfiguration(ProjectConfiguration *pc)
-{
- SessionManager::setActiveBuildConfiguration(m_target, static_cast<BuildConfiguration *>(pc), SetActive::Cascade);
-}
-
-void MiniProjectTargetSelector::setActiveDeployConfiguration(ProjectConfiguration *pc)
-{
- SessionManager::setActiveDeployConfiguration(m_target, static_cast<DeployConfiguration *>(pc), SetActive::Cascade);
-}
-
-void MiniProjectTargetSelector::setActiveRunConfiguration(ProjectConfiguration *pc)
-{
- m_target->setActiveRunConfiguration(static_cast<RunConfiguration *>(pc));
-}
-
void MiniProjectTargetSelector::projectAdded(Project *project)
{
- connect(project, &Project::addedTarget,
- this, &MiniProjectTargetSelector::slotAddedTarget);
+ connect(project, &Project::addedProjectConfiguration,
+ this, &MiniProjectTargetSelector::handleNewProjectConfiguration);
- connect(project, &Project::removedTarget,
- this, &MiniProjectTargetSelector::slotRemovedTarget);
+ connect(project, &Project::removedProjectConfiguration,
+ this, &MiniProjectTargetSelector::handleRemovalOfProjectConfiguration);
foreach (Target *t, project->targets())
addedTarget(t);
@@ -1000,11 +990,11 @@ void MiniProjectTargetSelector::projectAdded(Project *project)
void MiniProjectTargetSelector::projectRemoved(Project *project)
{
- disconnect(project, &Project::addedTarget,
- this, &MiniProjectTargetSelector::slotAddedTarget);
+ disconnect(project, &Project::addedProjectConfiguration,
+ this, &MiniProjectTargetSelector::handleNewProjectConfiguration);
- disconnect(project, &Project::removedTarget,
- this, &MiniProjectTargetSelector::slotRemovedTarget);
+ disconnect(project, &Project::removedProjectConfiguration,
+ this, &MiniProjectTargetSelector::handleRemovalOfProjectConfiguration);
foreach (Target *t, project->targets())
removedTarget(t);
@@ -1016,25 +1006,67 @@ void MiniProjectTargetSelector::projectRemoved(Project *project)
updateRunListVisible();
}
-void MiniProjectTargetSelector::addedTarget(Target *target)
+void MiniProjectTargetSelector::handleNewProjectConfiguration(ProjectConfiguration *pc)
{
- connect(target, &Target::addedBuildConfiguration,
- this, &MiniProjectTargetSelector::slotAddedBuildConfiguration);
- connect(target, &Target::removedBuildConfiguration,
- this, &MiniProjectTargetSelector::slotRemovedBuildConfiguration);
+ if (auto t = qobject_cast<Target *>(pc)) {
+ addedTarget(t);
+ updateTargetListVisible();
+ updateBuildListVisible();
+ updateDeployListVisible();
+ updateRunListVisible();
+ return;
+ }
+ if (auto bc = qobject_cast<BuildConfiguration *>(pc)) {
+ if (addedBuildConfiguration(bc))
+ updateBuildListVisible();
+ return;
+ }
+ if (auto dc = qobject_cast<DeployConfiguration *>(pc)) {
+ if (addedDeployConfiguration(dc))
+ updateDeployListVisible();
+ return;
+ }
+ if (auto rc = qobject_cast<RunConfiguration *>(pc)) {
+ if (addedRunConfiguration(rc))
+ updateRunListVisible();
+ return;
+ }
+}
- connect(target, &Target::addedDeployConfiguration,
- this, &MiniProjectTargetSelector::slotAddedDeployConfiguration);
- connect(target, &Target::removedDeployConfiguration,
- this, &MiniProjectTargetSelector::slotRemovedDeployConfiguration);
+void MiniProjectTargetSelector::handleRemovalOfProjectConfiguration(ProjectConfiguration *pc)
+{
+ if (auto t = qobject_cast<Target *>(pc)) {
+ removedTarget(t);
+
+ updateTargetListVisible();
+ updateBuildListVisible();
+ updateDeployListVisible();
+ updateRunListVisible();
+ return;
+ }
+ if (auto bc = qobject_cast<BuildConfiguration *>(pc)) {
+ if (removedBuildConfiguration(bc))
+ updateBuildListVisible();
+ return;
+ }
+ if (auto dc = qobject_cast<DeployConfiguration *>(pc)) {
+ if (removedDeployConfiguration(dc))
+ updateDeployListVisible();
+ return;
+ }
+ if (auto rc = qobject_cast<RunConfiguration *>(pc)) {
+ if (removedRunConfiguration(rc))
+ updateRunListVisible();
+ return;
+ }
+}
- connect(target, &Target::addedRunConfiguration,
- this, &MiniProjectTargetSelector::slotAddedRunConfiguration);
- connect(target, &Target::removedRunConfiguration,
- this, &MiniProjectTargetSelector::slotRemovedRunConfiguration);
+void MiniProjectTargetSelector::addedTarget(Target *target)
+{
+ if (target->project() != m_project)
+ return;
- if (target->project() == m_project)
- m_listWidgets[TARGET]->addProjectConfiguration(target);
+ m_listWidgets[TARGET]->addProjectConfiguration(target);
foreach (BuildConfiguration *bc, target->buildConfigurations())
addedBuildConfiguration(bc);
@@ -1044,34 +1076,12 @@ void MiniProjectTargetSelector::addedTarget(Target *target)
addedRunConfiguration(rc);
}
-void MiniProjectTargetSelector::slotAddedTarget(Target *target)
-{
- addedTarget(target);
- updateTargetListVisible();
- updateBuildListVisible();
- updateDeployListVisible();
- updateRunListVisible();
-}
-
void MiniProjectTargetSelector::removedTarget(Target *target)
{
- disconnect(target, &Target::addedBuildConfiguration,
- this, &MiniProjectTargetSelector::slotAddedBuildConfiguration);
- disconnect(target, &Target::removedBuildConfiguration,
- this, &MiniProjectTargetSelector::slotRemovedBuildConfiguration);
-
- disconnect(target, &Target::addedDeployConfiguration,
- this, &MiniProjectTargetSelector::slotAddedDeployConfiguration);
- disconnect(target, &Target::removedDeployConfiguration,
- this, &MiniProjectTargetSelector::slotRemovedDeployConfiguration);
-
- disconnect(target, &Target::addedRunConfiguration,
- this, &MiniProjectTargetSelector::slotAddedRunConfiguration);
- disconnect(target, &Target::removedRunConfiguration,
- this, &MiniProjectTargetSelector::slotRemovedRunConfiguration);
+ if (target->project() != m_project)
+ return;
- if (target->project() == m_project)
- m_listWidgets[TARGET]->removeProjectConfiguration(target);
+ m_listWidgets[TARGET]->removeProjectConfiguration(target);
foreach (BuildConfiguration *bc, target->buildConfigurations())
removedBuildConfiguration(bc);
@@ -1081,93 +1091,57 @@ void MiniProjectTargetSelector::removedTarget(Target *target)
removedRunConfiguration(rc);
}
-void MiniProjectTargetSelector::slotRemovedTarget(Target *target)
-{
- removedTarget(target);
-
- updateTargetListVisible();
- updateBuildListVisible();
- updateDeployListVisible();
- updateRunListVisible();
-}
-
-
-void MiniProjectTargetSelector::addedBuildConfiguration(BuildConfiguration *bc)
+bool MiniProjectTargetSelector::addedBuildConfiguration(BuildConfiguration *bc)
{
- if (bc->target() == m_target)
- m_listWidgets[BUILD]->addProjectConfiguration(bc);
-}
+ if (bc->target() != m_project->activeTarget())
+ return false;
-void MiniProjectTargetSelector::slotAddedBuildConfiguration(BuildConfiguration *bc)
-{
- if (bc->target() == m_target)
- m_listWidgets[BUILD]->addProjectConfiguration(bc);
- updateBuildListVisible();
+ m_listWidgets[BUILD]->addProjectConfiguration(bc);
+ return true;
}
-void MiniProjectTargetSelector::removedBuildConfiguration(BuildConfiguration *bc)
+bool MiniProjectTargetSelector::removedBuildConfiguration(BuildConfiguration *bc)
{
- if (bc->target() == m_target)
- m_listWidgets[BUILD]->removeProjectConfiguration(bc);
-}
+ if (bc->target() != m_project->activeTarget())
+ return false;
-void MiniProjectTargetSelector::slotRemovedBuildConfiguration(BuildConfiguration *bc)
-{
- if (bc->target() == m_target)
- m_listWidgets[BUILD]->removeProjectConfiguration(bc);
- updateBuildListVisible();
+ m_listWidgets[BUILD]->removeProjectConfiguration(bc);
+ return true;
}
-void MiniProjectTargetSelector::addedDeployConfiguration(DeployConfiguration *dc)
+bool MiniProjectTargetSelector::addedDeployConfiguration(DeployConfiguration *dc)
{
- if (dc->target() == m_target)
- m_listWidgets[DEPLOY]->addProjectConfiguration(dc);
-}
+ if (dc->target() != m_project->activeTarget())
+ return false;
-void MiniProjectTargetSelector::slotAddedDeployConfiguration(DeployConfiguration *dc)
-{
- if (dc->target() == m_target)
- m_listWidgets[DEPLOY]->addProjectConfiguration(dc);
- updateDeployListVisible();
+ m_listWidgets[DEPLOY]->addProjectConfiguration(dc);
+ return true;
}
-void MiniProjectTargetSelector::removedDeployConfiguration(DeployConfiguration *dc)
+bool MiniProjectTargetSelector::removedDeployConfiguration(DeployConfiguration *dc)
{
- if (dc->target() == m_target)
- m_listWidgets[DEPLOY]->removeProjectConfiguration(dc);
-}
+ if (dc->target() != m_project->activeTarget())
+ return false;
-void MiniProjectTargetSelector::slotRemovedDeployConfiguration(DeployConfiguration *dc)
-{
- if (dc->target() == m_target)
- m_listWidgets[DEPLOY]->removeProjectConfiguration(dc);
- updateDeployListVisible();
+ m_listWidgets[DEPLOY]->removeProjectConfiguration(dc);
+ return true;
}
-
-void MiniProjectTargetSelector::addedRunConfiguration(RunConfiguration *rc)
+bool MiniProjectTargetSelector::addedRunConfiguration(RunConfiguration *rc)
{
- if (rc->target() == m_target)
- m_listWidgets[RUN]->addProjectConfiguration(rc);
-}
+ if (rc->target() != m_project->activeTarget())
+ return false;
-void MiniProjectTargetSelector::slotAddedRunConfiguration(RunConfiguration *rc)
-{
- if (rc->target() == m_target)
- m_listWidgets[RUN]->addProjectConfiguration(rc);
- updateRunListVisible();
+ m_listWidgets[RUN]->addProjectConfiguration(rc);
+ return true;
}
-void MiniProjectTargetSelector::removedRunConfiguration(RunConfiguration *rc)
+bool MiniProjectTargetSelector::removedRunConfiguration(RunConfiguration *rc)
{
- if (rc->target() == m_target)
- m_listWidgets[RUN]->removeProjectConfiguration(rc);
-}
+ if (rc->target() != m_project->activeTarget())
+ return false;
-void MiniProjectTargetSelector::slotRemovedRunConfiguration(RunConfiguration *rc)
-{
- if (rc->target() == m_target)
- m_listWidgets[RUN]->removeProjectConfiguration(rc);
- updateRunListVisible();
+ m_listWidgets[RUN]->removeProjectConfiguration(rc);
+ return true;
}
void MiniProjectTargetSelector::updateProjectListVisible()
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h
index 07f8da0906..0c2e51a4f4 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.h
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.h
@@ -148,14 +148,8 @@ public:
private:
void projectAdded(ProjectExplorer::Project *project);
void projectRemoved(ProjectExplorer::Project *project);
- void slotAddedTarget(ProjectExplorer::Target *target);
- void slotRemovedTarget(ProjectExplorer::Target *target);
- void slotAddedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc);
- void slotRemovedBuildConfiguration(ProjectExplorer::BuildConfiguration *bc);
- void slotAddedDeployConfiguration(ProjectExplorer::DeployConfiguration *dc);
- void slotRemovedDeployConfiguration(ProjectExplorer::DeployConfiguration *dc);
- void slotAddedRunConfiguration(ProjectExplorer::RunConfiguration *rc);
- void slotRemovedRunConfiguration(ProjectExplorer::RunConfiguration *rc);
+ void handleNewProjectConfiguration(ProjectConfiguration *pc);
+ void handleRemovalOfProjectConfiguration(ProjectConfiguration *pc);
void changeStartupProject(ProjectExplorer::Project *project);
void activeTargetChanged(ProjectExplorer::Target *target);
@@ -164,22 +158,17 @@ private:
void activeDeployConfigurationChanged(ProjectExplorer::DeployConfiguration *dc);
void activeRunConfigurationChanged(ProjectExplorer::RunConfiguration *rc);
- void setActiveTarget(ProjectExplorer::ProjectConfiguration *pc);
- void setActiveBuildConfiguration(ProjectExplorer::ProjectConfiguration *pc);
- void setActiveDeployConfiguration(ProjectExplorer::ProjectConfiguration *pc);
- void setActiveRunConfiguration(ProjectExplorer::ProjectConfiguration *pc);
-
void delayedHide();
void updateActionAndSummary();
void switchToProjectsMode();
void addedTarget(Target *target);
void removedTarget(Target *target);
- void addedBuildConfiguration(BuildConfiguration* bc);
- void removedBuildConfiguration(BuildConfiguration* bc);
- void addedDeployConfiguration(DeployConfiguration *dc);
- void removedDeployConfiguration(DeployConfiguration *dc);
- void addedRunConfiguration(RunConfiguration *rc);
- void removedRunConfiguration(RunConfiguration *rc);
+ bool addedBuildConfiguration(BuildConfiguration* bc);
+ bool removedBuildConfiguration(BuildConfiguration* bc);
+ bool addedDeployConfiguration(DeployConfiguration *dc);
+ bool removedDeployConfiguration(DeployConfiguration *dc);
+ bool addedRunConfiguration(RunConfiguration *rc);
+ bool removedRunConfiguration(RunConfiguration *rc);
void updateProjectListVisible();
void updateTargetListVisible();
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 2562b7fcc4..2ff34dbcb8 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -410,31 +410,18 @@ static QByteArray msvcCompilationFile()
//
// [1] https://msdn.microsoft.com/en-us/library/b0084kay.aspx
// [2] http://stackoverflow.com/questions/3665537/how-to-find-out-cl-exes-built-in-macros
-QByteArray MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
- const Utils::Environment &env) const
+Macros MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
+ const Utils::Environment &env) const
{
- QByteArray predefinedMacros;
+ Macros predefinedMacros;
QStringList toProcess;
- foreach (const QString &arg, cxxflags) {
+ for (const QString &arg : cxxflags) {
if (arg.startsWith(QLatin1String("/D"))) {
- QString define = arg.mid(2);
- int pos = define.indexOf(QLatin1Char('='));
- if (pos < 0) {
- predefinedMacros += "#define ";
- predefinedMacros += define.toLocal8Bit();
- predefinedMacros += '\n';
- } else {
- predefinedMacros += "#define ";
- predefinedMacros += define.left(pos).toLocal8Bit();
- predefinedMacros += ' ';
- predefinedMacros += define.mid(pos + 1).toLocal8Bit();
- predefinedMacros += '\n';
- }
+ const QString define = arg.mid(2);
+ predefinedMacros.append(Macro::fromKeyValue(define));
} else if (arg.startsWith(QLatin1String("/U"))) {
- predefinedMacros += "#undef ";
- predefinedMacros += arg.mid(2).toLocal8Bit();
- predefinedMacros += '\n';
+ predefinedMacros.append({arg.mid(2).toLocal8Bit(), ProjectExplorer::MacroType::Undefine});
} else if (arg.startsWith(QLatin1String("-I"))) {
// Include paths should not have any effect on defines
} else {
@@ -468,18 +455,8 @@ QByteArray MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
const QStringList output = Utils::filtered(response.stdOut().split('\n'),
[](const QString &s) { return s.startsWith('V'); });
- foreach (const QString& line, output) {
- QStringList split = line.split('=');
- const QString key = split.at(0).mid(1);
- QString value = split.at(1);
- predefinedMacros += "#define ";
- predefinedMacros += key.toUtf8();
- predefinedMacros += ' ';
- predefinedMacros += value.toUtf8();
- predefinedMacros += '\n';
- }
- if (debug)
- qDebug() << "msvcPredefinedMacros" << predefinedMacros;
+ for (const QString &line : output)
+ predefinedMacros.append(Macro::fromKeyValue(line.mid(1)));
return predefinedMacros;
}
diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h
index fd341177eb..3dcb715286 100644
--- a/src/plugins/projectexplorer/msvctoolchain.h
+++ b/src/plugins/projectexplorer/msvctoolchain.h
@@ -82,8 +82,8 @@ protected:
Utils::Environment readEnvironmentSetting(const Utils::Environment& env) const final;
// Function must be thread-safe!
- QByteArray msvcPredefinedMacros(const QStringList cxxflags,
- const Utils::Environment &env) const override;
+ Macros msvcPredefinedMacros(const QStringList cxxflags,
+ const Utils::Environment &env) const override;
private:
QList<Utils::EnvironmentItem> environmentModifications() const;
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index 09475e24b8..7215b28eb8 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -52,6 +52,7 @@
#include <utils/qtcassert.h>
#include <limits>
+#include <memory>
/*!
\class ProjectExplorer::Project
@@ -126,20 +127,27 @@ bool ProjectDocument::reload(QString *errorString, Core::IDocument::ReloadFlag f
class ProjectPrivate
{
public:
- ProjectPrivate(Core::IDocument *document) : m_document(document) { }
+ ProjectPrivate(const QString &mimeType, const Utils::FileName &fileName,
+ const ProjectDocument::ProjectCallback &callback)
+ {
+ m_document = std::make_unique<ProjectDocument>(mimeType, fileName, callback);
+ }
+
~ProjectPrivate();
Core::Id m_id;
- Core::IDocument *m_document = nullptr;
+ bool m_isParsing = false;
+ bool m_hasParsingData = false;
+ std::unique_ptr<Core::IDocument> m_document;
ProjectNode *m_rootProjectNode = nullptr;
- ContainerNode *m_containerNode = nullptr;
+ std::unique_ptr<ContainerNode> m_containerNode;
QList<Target *> m_targets;
Target *m_activeTarget = nullptr;
EditorConfiguration m_editorConfiguration;
Core::Context m_projectContext;
Core::Context m_projectLanguages;
QVariantMap m_pluginSettings;
- Internal::UserFileAccessor *m_accessor = nullptr;
+ std::unique_ptr<Internal::UserFileAccessor> m_accessor;
QString m_displayName;
@@ -151,32 +159,28 @@ public:
ProjectPrivate::~ProjectPrivate()
{
+ qDeleteAll(m_targets);
+
// Make sure our root node is null when deleting
ProjectNode *oldNode = m_rootProjectNode;
m_rootProjectNode = nullptr;
delete oldNode;
-
- delete m_containerNode;
-
- delete m_document;
- delete m_accessor;
}
Project::Project(const QString &mimeType, const Utils::FileName &fileName,
const ProjectDocument::ProjectCallback &callback) :
- d(new ProjectPrivate(new ProjectDocument(mimeType, fileName, callback)))
+ d(new ProjectPrivate(mimeType, fileName, callback))
{
d->m_macroExpander.setDisplayName(tr("Project"));
d->m_macroExpander.registerVariable("Project:Name", tr("Project Name"),
[this] { return displayName(); });
// Only set up containernode after d is set so that it will find the project directory!
- d->m_containerNode = new ContainerNode(this);
+ d->m_containerNode = std::make_unique<ContainerNode>(this);
}
Project::~Project()
{
- qDeleteAll(d->m_targets);
delete d;
}
@@ -194,7 +198,7 @@ Core::Id Project::id() const
Core::IDocument *Project::document() const
{
QTC_CHECK(d->m_document);
- return d->m_document;
+ return d->m_document.get();
}
Utils::FileName Project::projectFilePath() const
@@ -219,20 +223,6 @@ QString Project::makeUnique(const QString &preferredName, const QStringList &use
return tryName;
}
-void Project::changeEnvironment()
-{
- auto t = qobject_cast<Target *>(sender());
- if (t == activeTarget())
- emit environmentChanged();
-}
-
-void Project::changeBuildConfigurationEnabled()
-{
- auto t = qobject_cast<Target *>(sender());
- if (t == activeTarget())
- emit buildConfigurationEnabledChanged();
-}
-
void Project::addTarget(Target *t)
{
QTC_ASSERT(t && !d->m_targets.contains(t), return);
@@ -243,10 +233,11 @@ void Project::addTarget(Target *t)
// add it
d->m_targets.push_back(t);
- connect(t, &Target::environmentChanged, this, &Project::changeEnvironment);
- connect(t, &Target::buildConfigurationEnabledChanged,
- this, &Project::changeBuildConfigurationEnabled);
- connect(t, &Target::buildDirectoryChanged, this, &Project::onBuildDirectoryChanged);
+ connect(t, &Target::addedProjectConfiguration, this, &Project::addedProjectConfiguration);
+ connect(t, &Target::aboutToRemoveProjectConfiguration, this, &Project::aboutToRemoveProjectConfiguration);
+ connect(t, &Target::removedProjectConfiguration, this, &Project::removedProjectConfiguration);
+ connect(t, &Target::activeProjectConfigurationChanged, this, &Project::activeProjectConfigurationChanged);
+ emit addedProjectConfiguration(t);
emit addedTarget(t);
// check activeTarget:
@@ -270,9 +261,11 @@ bool Project::removeTarget(Target *target)
SessionManager::setActiveTarget(this, d->m_targets.at(0), SetActive::Cascade);
}
+ emit aboutToRemoveProjectConfiguration(target);
emit aboutToRemoveTarget(target);
d->m_targets.removeOne(target);
emit removedTarget(target);
+ emit removedProjectConfiguration(target);
delete target;
return true;
@@ -293,9 +286,8 @@ void Project::setActiveTarget(Target *target)
if ((!target && !d->m_targets.isEmpty()) ||
(target && d->m_targets.contains(target) && d->m_activeTarget != target)) {
d->m_activeTarget = target;
+ emit activeProjectConfigurationChanged(d->m_activeTarget);
emit activeTargetChanged(d->m_activeTarget);
- emit environmentChanged();
- emit buildConfigurationEnabledChanged();
}
}
@@ -462,6 +454,24 @@ bool Project::setupTarget(Target *t)
return true;
}
+void Project::emitParsingStarted()
+{
+ QTC_ASSERT(!d->m_isParsing, return);
+
+ d->m_isParsing = true;
+ d->m_hasParsingData = false;
+ emit parsingStarted();
+}
+
+void Project::emitParsingFinished(bool success)
+{
+ QTC_ASSERT(d->m_isParsing, return);
+
+ d->m_isParsing = false;
+ d->m_hasParsingData = success;
+ emit parsingFinished(success);
+}
+
void Project::setDisplayName(const QString &name)
{
if (name == d->m_displayName)
@@ -493,7 +503,7 @@ void Project::setRootProjectNode(ProjectNode *root)
ProjectNode *oldNode = d->m_rootProjectNode;
d->m_rootProjectNode = root;
if (root) {
- root->setParentFolderNode(d->m_containerNode);
+ root->setParentFolderNode(d->m_containerNode.get());
// Only announce non-null root, null is only used when project is destroyed.
// In that case SessionManager::projectRemoved() triggers the update.
ProjectTree::emitSubtreeChanged(root);
@@ -531,7 +541,7 @@ void Project::saveSettings()
{
emit aboutToSaveSettings();
if (!d->m_accessor)
- d->m_accessor = new Internal::UserFileAccessor(this);
+ d->m_accessor = std::make_unique<Internal::UserFileAccessor>(this);
if (!targets().isEmpty())
d->m_accessor->saveSettings(toMap(), Core::ICore::mainWindow());
}
@@ -539,7 +549,7 @@ void Project::saveSettings()
Project::RestoreResult Project::restoreSettings(QString *errorMessage)
{
if (!d->m_accessor)
- d->m_accessor = new Internal::UserFileAccessor(this);
+ d->m_accessor = std::make_unique<Internal::UserFileAccessor>(this);
QVariantMap map(d->m_accessor->restoreSettings(Core::ICore::mainWindow()));
RestoreResult result = fromMap(map, errorMessage);
if (result == RestoreResult::Ok)
@@ -633,7 +643,7 @@ ProjectNode *Project::rootProjectNode() const
ContainerNode *Project::containerNode() const
{
- return d->m_containerNode;
+ return d->m_containerNode.get();
}
Project::RestoreResult Project::fromMap(const QVariantMap &map, QString *errorMessage)
@@ -811,6 +821,16 @@ Utils::MacroExpander *Project::macroExpander() const
return &d->m_macroExpander;
}
+bool Project::isParsing() const
+{
+ return d->m_isParsing;
+}
+
+bool Project::hasParsingData() const
+{
+ return d->m_hasParsingData;
+}
+
ProjectImporter *Project::projectImporter() const
{
return nullptr;
@@ -836,11 +856,4 @@ void Project::setPreferredKitPredicate(const Kit::Predicate &predicate)
d->m_preferredKitPredicate = predicate;
}
-void Project::onBuildDirectoryChanged()
-{
- auto target = qobject_cast<Target *>(sender());
- if (target && target == activeTarget())
- emit buildDirectoryChanged();
-}
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index f76a1513de..9329fc3c43 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -28,6 +28,7 @@
#include "projectexplorer_export.h"
#include "kit.h"
+#include "subscription.h"
#include <coreplugin/id.h>
#include <coreplugin/idocument.h>
@@ -49,6 +50,7 @@ class ContainerNode;
class EditorConfiguration;
class NamedWidget;
class Node;
+class ProjectConfiguration;
class ProjectImporter;
class ProjectNode;
class ProjectPrivate;
@@ -85,7 +87,8 @@ public:
enum ModelRoles {
// Absolute file path
FilePathRole = QFileSystemModel::FilePathRole,
- EnabledRole
+ EnabledRole,
+ isParsingRole
};
Project(const QString &mimeType, const Utils::FileName &fileName,
@@ -163,6 +166,27 @@ public:
void setup(QList<const BuildInfo *> infoList);
Utils::MacroExpander *macroExpander() const;
+ bool isParsing() const;
+ bool hasParsingData() const;
+
+ template<typename S, typename R, typename T, typename ...Args1, typename ...Args2>
+ void subscribeSignal(void (S::*sig)(Args1...), R*recv, T (R::*sl)(Args2...)) {
+ new Internal::ProjectSubscription([sig, recv, sl, this](ProjectConfiguration *pc) {
+ if (S* sender = qobject_cast<S*>(pc))
+ return connect(sender, sig, recv, sl);
+ return QMetaObject::Connection();
+ }, recv, this);
+ }
+
+ template<typename S, typename R, typename T, typename ...Args1>
+ void subscribeSignal(void (S::*sig)(Args1...), R*recv, T sl) {
+ new Internal::ProjectSubscription([sig, recv, sl, this](ProjectConfiguration *pc) {
+ if (S* sender = qobject_cast<S*>(pc))
+ return connect(sender, sig, recv, sl);
+ return QMetaObject::Connection();
+ }, recv, this);
+ }
+
signals:
void displayNameChanged();
void fileListChanged();
@@ -170,27 +194,38 @@ signals:
// Note: activeTarget can be 0 (if no targets are defined).
void activeTargetChanged(ProjectExplorer::Target *target);
+ void aboutToRemoveProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
+ void removedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
+ void addedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
+
+ // *ANY* active project configuration changed somewhere in the tree. This might not be
+ // the one that would get started right now, since some part of the tree in between might
+ // not be active.
+ void activeProjectConfigurationChanged(ProjectExplorer::ProjectConfiguration *pc);
+
void aboutToRemoveTarget(ProjectExplorer::Target *target);
void removedTarget(ProjectExplorer::Target *target);
void addedTarget(ProjectExplorer::Target *target);
- void environmentChanged();
- void buildConfigurationEnabledChanged();
-
- void buildDirectoryChanged();
-
void settingsLoaded();
void aboutToSaveSettings();
void projectContextUpdated();
void projectLanguagesUpdated();
- void parsingFinished();
+ void parsingStarted();
+ void parsingFinished(bool success);
protected:
virtual RestoreResult fromMap(const QVariantMap &map, QString *errorMessage);
virtual bool setupTarget(Target *t);
+ // Helper methods to manage parsing state and signalling
+ // Call in GUI thread before the actual parsing starts
+ void emitParsingStarted();
+ // Call in GUI thread right after the actual parsing is done
+ void emitParsingFinished(bool success);
+
void setDisplayName(const QString &name);
void setRequiredKitPredicate(const Kit::Predicate &predicate);
void setPreferredKitPredicate(const Kit::Predicate &predicate);
@@ -205,10 +240,6 @@ protected:
virtual void projectLoaded(); // Called when the project is fully loaded.
private:
- void changeEnvironment();
- void changeBuildConfigurationEnabled();
- void onBuildDirectoryChanged();
-
void setActiveTarget(Target *target);
ProjectPrivate *d;
diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp
index 2958bb12ed..0362c747c9 100644
--- a/src/plugins/projectexplorer/projectconfiguration.cpp
+++ b/src/plugins/projectexplorer/projectconfiguration.cpp
@@ -31,16 +31,21 @@ const char CONFIGURATION_ID_KEY[] = "ProjectExplorer.ProjectConfiguration.Id";
const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayName";
const char DEFAULT_DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DefaultDisplayName";
-ProjectConfiguration::ProjectConfiguration(QObject *parent, Core::Id id) : QObject(parent),
- m_id(id)
-{ setObjectName(id.toString()); }
+ProjectConfiguration::ProjectConfiguration(QObject *parent)
+ : QObject(parent)
+{}
-ProjectConfiguration::ProjectConfiguration(QObject *parent, const ProjectConfiguration *source) :
- QObject(parent),
- m_id(source->m_id),
- m_defaultDisplayName(source->m_defaultDisplayName)
+void ProjectConfiguration::initialize(Core::Id id)
+{
+ m_id = id;
+ setObjectName(id.toString());
+}
+
+void ProjectConfiguration::copyFrom(const ProjectConfiguration *source)
{
Q_ASSERT(source);
+ m_id = source->m_id;
+ m_defaultDisplayName = source->m_defaultDisplayName;
m_displayName = tr("Clone of %1").arg(source->displayName());
}
@@ -123,3 +128,26 @@ QString ProjectExplorer::displayNameFromMap(const QVariantMap &map)
{
return map.value(QLatin1String(DISPLAY_NAME_KEY), QString()).toString();
}
+
+bool StatefulProjectConfiguration::isEnabled() const
+{
+ return m_isEnabled;
+}
+
+StatefulProjectConfiguration::StatefulProjectConfiguration(QObject *parent) :
+ ProjectConfiguration(parent)
+{ }
+
+void StatefulProjectConfiguration::copyFrom(const StatefulProjectConfiguration *source)
+{
+ ProjectConfiguration::copyFrom(source);
+ m_isEnabled = source->m_isEnabled;
+}
+
+void StatefulProjectConfiguration::setEnabled(bool enabled)
+{
+ if (enabled == m_isEnabled)
+ return;
+ m_isEnabled = enabled;
+ emit enabledChanged();
+}
diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h
index ad3f2ca797..38fe375e02 100644
--- a/src/plugins/projectexplorer/projectconfiguration.h
+++ b/src/plugins/projectexplorer/projectconfiguration.h
@@ -65,13 +65,18 @@ public:
Utils::MacroExpander *macroExpander() { return &m_macroExpander; }
const Utils::MacroExpander *macroExpander() const { return &m_macroExpander; }
+ virtual Project *project() const = 0;
+
+ virtual bool isActive() const = 0;
+
signals:
void displayNameChanged();
void toolTipChanged();
protected:
- ProjectConfiguration(QObject *parent, Core::Id id);
- ProjectConfiguration(QObject *parent, const ProjectConfiguration *source);
+ ProjectConfiguration(QObject *parent);
+ void initialize(Core::Id id);
+ void copyFrom(const ProjectConfiguration *source);
private:
Core::Id m_id;
@@ -81,6 +86,30 @@ private:
Utils::MacroExpander m_macroExpander;
};
+class PROJECTEXPLORER_EXPORT StatefulProjectConfiguration : public ProjectConfiguration
+{
+ Q_OBJECT
+
+public:
+ StatefulProjectConfiguration() = default;
+
+ bool isEnabled() const;
+
+ virtual QString disabledReason() const = 0;
+
+signals:
+ void enabledChanged();
+
+protected:
+ StatefulProjectConfiguration(QObject *parent);
+ void copyFrom(const StatefulProjectConfiguration *source);
+
+ void setEnabled(bool enabled);
+
+private:
+ bool m_isEnabled = false;
+};
+
// helper functions:
PROJECTEXPLORER_EXPORT Core::Id idFromMap(const QVariantMap &map);
PROJECTEXPLORER_EXPORT QString displayNameFromMap(const QVariantMap &map);
diff --git a/src/plugins/projectexplorer/projectconfigurationmodel.cpp b/src/plugins/projectexplorer/projectconfigurationmodel.cpp
new file mode 100644
index 0000000000..f27f1bf55b
--- /dev/null
+++ b/src/plugins/projectexplorer/projectconfigurationmodel.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "projectconfigurationmodel.h"
+
+#include "buildconfiguration.h"
+#include "deployconfiguration.h"
+#include "runconfiguration.h"
+#include "target.h"
+#include "projectconfiguration.h"
+
+#include <utils/algorithm.h>
+
+using namespace ProjectExplorer;
+
+/*!
+ \class ProjectExplorer::BuildConfigurationModel
+ \brief The BuildConfigurationModel class is a model to represent the build
+ configurations of a target.
+
+ To be used in the dropdown lists of comboboxes.
+ Automatically adjusts itself to added and removed BuildConfigurations.
+ Very similar to the Run Configuration Model.
+
+ TODO might it possible to share code without making the code a complete mess.
+*/
+
+namespace {
+
+const auto ComparisonOperator =
+ [](const ProjectConfiguration *a, const ProjectConfiguration *b) {
+ return a->displayName() < b->displayName();
+ };
+
+} // namespace
+
+ProjectConfigurationModel::ProjectConfigurationModel(Target *target, FilterFunction filter,
+ QObject *parent) :
+ QAbstractListModel(parent),
+ m_target(target),
+ m_filter(filter)
+{
+ m_projectConfigurations = Utils::filtered(m_target->projectConfigurations(), m_filter);
+ Utils::sort(m_projectConfigurations, ComparisonOperator);
+
+ connect(target, &Target::addedProjectConfiguration,
+ this, &ProjectConfigurationModel::addedProjectConfiguration);
+ connect(target, &Target::removedProjectConfiguration,
+ this, &ProjectConfigurationModel::removedProjectConfiguration);
+
+ foreach (ProjectConfiguration *pc, m_projectConfigurations)
+ connect(pc, &ProjectConfiguration::displayNameChanged,
+ this, &ProjectConfigurationModel::displayNameChanged);
+}
+
+int ProjectConfigurationModel::rowCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : m_projectConfigurations.size();
+}
+
+int ProjectConfigurationModel::columnCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : 1;
+}
+
+void ProjectConfigurationModel::displayNameChanged()
+{
+ auto pc = qobject_cast<ProjectConfiguration *>(sender());
+ if (!pc)
+ return;
+
+ // Find the old position
+ int oldPos = m_projectConfigurations.indexOf(pc);
+ if (oldPos < 0)
+ return;
+
+ if (oldPos >= 1 && ComparisonOperator(m_projectConfigurations.at(oldPos), m_projectConfigurations.at(oldPos - 1))) {
+ // We need to move up
+ int newPos = oldPos - 1;
+ while (newPos >= 0 && ComparisonOperator(m_projectConfigurations.at(oldPos), m_projectConfigurations.at(newPos))) {
+ --newPos;
+ }
+ ++newPos;
+
+ beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
+ m_projectConfigurations.insert(newPos, pc);
+ m_projectConfigurations.removeAt(oldPos + 1);
+ endMoveRows();
+ // Not only did we move, we also changed...
+ emit dataChanged(index(newPos, 0), index(newPos,0));
+ } else if (oldPos < m_projectConfigurations.size() - 1
+ && ComparisonOperator(m_projectConfigurations.at(oldPos + 1), m_projectConfigurations.at(oldPos))) {
+ // We need to move down
+ int newPos = oldPos + 1;
+ while (newPos < m_projectConfigurations.size()
+ && ComparisonOperator(m_projectConfigurations.at(newPos), m_projectConfigurations.at(oldPos))) {
+ ++newPos;
+ }
+ beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
+ m_projectConfigurations.insert(newPos, pc);
+ m_projectConfigurations.removeAt(oldPos);
+ endMoveRows();
+
+ // We need to subtract one since removing at the old place moves the newIndex down
+ emit dataChanged(index(newPos - 1, 0), index(newPos - 1, 0));
+ } else {
+ emit dataChanged(index(oldPos, 0), index(oldPos, 0));
+ }
+}
+
+QVariant ProjectConfigurationModel::data(const QModelIndex &index, int role) const
+{
+ if (role == Qt::DisplayRole) {
+ const int row = index.row();
+ if (row < m_projectConfigurations.size())
+ return m_projectConfigurations.at(row)->displayName();
+ }
+
+ return QVariant();
+}
+
+ProjectConfiguration *ProjectConfigurationModel::projectConfigurationAt(int i)
+{
+ if (i > m_projectConfigurations.size() || i < 0)
+ return nullptr;
+ return m_projectConfigurations.at(i);
+}
+
+ProjectConfiguration *ProjectConfigurationModel::projectConfigurationFor(const QModelIndex &idx)
+{
+ if (idx.row() > m_projectConfigurations.size() || idx.row() < 0)
+ return nullptr;
+ return m_projectConfigurations.at(idx.row());
+}
+
+QModelIndex ProjectConfigurationModel::indexFor(ProjectConfiguration *pc)
+{
+ int idx = m_projectConfigurations.indexOf(pc);
+ if (idx == -1)
+ return QModelIndex();
+ return index(idx, 0);
+}
+
+void ProjectConfigurationModel::addedProjectConfiguration(ProjectConfiguration *pc)
+{
+ if (!m_filter(pc))
+ return;
+
+ // Find the right place to insert
+ int i = 0;
+ for (; i < m_projectConfigurations.size(); ++i) {
+ if (ComparisonOperator(pc, m_projectConfigurations.at(i)))
+ break;
+ }
+
+ beginInsertRows(QModelIndex(), i, i);
+ m_projectConfigurations.insert(i, pc);
+ endInsertRows();
+
+ connect(pc, &ProjectConfiguration::displayNameChanged,
+ this, &ProjectConfigurationModel::displayNameChanged);
+}
+
+void ProjectConfigurationModel::removedProjectConfiguration(ProjectConfiguration *pc)
+{
+ int i = m_projectConfigurations.indexOf(pc);
+ if (i < 0)
+ return;
+ beginRemoveRows(QModelIndex(), i, i);
+ m_projectConfigurations.removeAt(i);
+ endRemoveRows();
+}
+
+BuildConfigurationModel::BuildConfigurationModel(Target *t, QObject *parent) :
+ ProjectConfigurationModel(t,
+ [](const ProjectConfiguration *pc) {
+ return qobject_cast<const BuildConfiguration *>(pc) != nullptr;
+ },
+ parent)
+{ }
+
+DeployConfigurationModel::DeployConfigurationModel(Target *t, QObject *parent) :
+ ProjectConfigurationModel(t,
+ [](const ProjectConfiguration *pc) {
+ return qobject_cast<const DeployConfiguration *>(pc) != nullptr;
+ },
+ parent)
+{ }
+
+RunConfigurationModel::RunConfigurationModel(Target *t, QObject *parent) :
+ ProjectConfigurationModel(t,
+ [](const ProjectConfiguration *pc) {
+ return qobject_cast<const RunConfiguration *>(pc) != nullptr;
+ },
+ parent)
+{ }
diff --git a/src/plugins/projectexplorer/runconfigurationmodel.h b/src/plugins/projectexplorer/projectconfigurationmodel.h
index 8af2566b95..adc1a00402 100644
--- a/src/plugins/projectexplorer/runconfigurationmodel.h
+++ b/src/plugins/projectexplorer/projectconfigurationmodel.h
@@ -27,32 +27,56 @@
#include <QAbstractItemModel>
+#include <functional>
+
namespace ProjectExplorer {
class Target;
-class RunConfiguration;
+class ProjectConfiguration;
// Documentation inside.
-class RunConfigurationModel : public QAbstractListModel
+class ProjectConfigurationModel : public QAbstractListModel
{
Q_OBJECT
-
public:
- explicit RunConfigurationModel(Target *target, QObject *parent = nullptr);
+ using FilterFunction = std::function<bool(const ProjectConfiguration *)>;
+
+ explicit ProjectConfigurationModel(Target *target, FilterFunction filter,
+ QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- RunConfiguration *runConfigurationAt(int i);
- RunConfiguration *runConfigurationFor(const QModelIndex &idx);
- QModelIndex indexFor(RunConfiguration *rc);
+ ProjectConfiguration *projectConfigurationAt(int i);
+ ProjectConfiguration *projectConfigurationFor(const QModelIndex &idx);
+ QModelIndex indexFor(ProjectConfiguration *pc);
private:
- void addedRunConfiguration(ProjectExplorer::RunConfiguration*);
- void removedRunConfiguration(ProjectExplorer::RunConfiguration*);
+ void addedProjectConfiguration(ProjectConfiguration *pc);
+ void removedProjectConfiguration(ProjectConfiguration *pc);
void displayNameChanged();
+
Target *m_target;
- QList<RunConfiguration *> m_runConfigurations;
+ FilterFunction m_filter;
+ QList<ProjectConfiguration *> m_projectConfigurations;
+};
+
+class BuildConfigurationModel : public ProjectConfigurationModel
+{
+public:
+ explicit BuildConfigurationModel(Target *t, QObject *parent = nullptr);
+};
+
+class DeployConfigurationModel : public ProjectConfigurationModel
+{
+public:
+ explicit DeployConfigurationModel(Target *t, QObject *parent = nullptr);
+};
+
+class RunConfigurationModel : public ProjectConfigurationModel
+{
+public:
+ explicit RunConfigurationModel(Target *t, QObject *parent = nullptr);
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index acd546e09b..118d8f37b9 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -94,6 +94,7 @@
#include "projecttree.h"
#include "projectwelcomepage.h"
+#include <app/app_version.h>
#include <extensionsystem/pluginspec.h>
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>
@@ -235,6 +236,9 @@ const char G_BUILD_RUN[] = "ProjectExplorer.Group.Run";
const char G_BUILD_CANCEL[] = "ProjectExplorer.Group.BuildCancel";
const char RUNMENUCONTEXTMENU[] = "Project.RunMenu";
+const char FOLDER_OPEN_LOCATIONS_CONTEXT_MENU[] = "Project.F.OpenLocation.CtxMenu";
+const char PROJECT_OPEN_LOCATIONS_CONTEXT_MENU[] = "Project.P.OpenLocation.CtxMenu";
+const char SUBPROJECT_OPEN_LOCATIONS_CONTEXT_MENU[] = "Project.S.OpenLocation.CtxMenu";
} // namespace Constants
@@ -275,6 +279,7 @@ public:
void deploy(QList<Project *>);
int queue(QList<Project *>, QList<Id> stepIds);
void updateContextMenuActions();
+ void updateLocationSubMenus();
void executeRunConfiguration(RunConfiguration *, Core::Id mode);
QPair<bool, QString> buildSettingsEnabledForSession();
QPair<bool, QString> buildSettingsEnabled(const Project *pro);
@@ -611,7 +616,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
addAutoReleasedObject(new ConfigTaskHandler(Task::compilerMissingTask(),
Constants::KITS_SETTINGS_PAGE_ID));
- ICore::addPreCloseListener([this]() -> bool { return coreAboutToClose(); });
+ ICore::addPreCloseListener([]() -> bool { return coreAboutToClose(); });
dd->m_outputPane = new AppOutputPane;
addAutoReleasedObject(dd->m_outputPane);
@@ -655,7 +660,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
const IDevice::ConstPtr device = runnable.as<StandardRunnable>().device;
if (device && device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return true;
- Target *target = runConfiguration ? runConfiguration->target() : nullptr;
+ Target *target = runConfiguration->target();
Kit *kit = target ? target->kit() : nullptr;
return DeviceTypeKitInformation::deviceTypeId(kit) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
};
@@ -686,6 +691,22 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
ActionContainer *menubar =
ActionManager::actionContainer(Core::Constants::MENU_BAR);
+ // context menu sub menus:
+ ActionContainer *folderOpenLocationCtxMenu =
+ ActionManager::createMenu(Constants::FOLDER_OPEN_LOCATIONS_CONTEXT_MENU);
+ folderOpenLocationCtxMenu->menu()->setTitle(tr("Open..."));
+ folderOpenLocationCtxMenu->setOnAllDisabledBehavior(ActionContainer::Show);
+
+ ActionContainer *subProjectOpenLocationCtxMenu =
+ ActionManager::createMenu(Constants::SUBPROJECT_OPEN_LOCATIONS_CONTEXT_MENU);
+ subProjectOpenLocationCtxMenu->menu()->setTitle(tr("Open..."));
+ subProjectOpenLocationCtxMenu->setOnAllDisabledBehavior(ActionContainer::Show);
+
+ ActionContainer *projectOpenLocationCtxMenu =
+ ActionManager::createMenu(Constants::PROJECT_OPEN_LOCATIONS_CONTEXT_MENU);
+ projectOpenLocationCtxMenu->menu()->setTitle(tr("Open..."));
+ projectOpenLocationCtxMenu->setOnAllDisabledBehavior(ActionContainer::Show);
+
// build menu
ActionContainer *mbuild =
ActionManager::createMenu(Constants::M_BUILDPROJECT);
@@ -721,6 +742,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
msessionContextMenu->appendGroup(Constants::G_PROJECT_TREE);
mprojectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
+ mprojectContextMenu->appendGroup(Constants::G_FOLDER_LOCATIONS);
mprojectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
mprojectContextMenu->appendGroup(Constants::G_PROJECT_RUN);
mprojectContextMenu->appendGroup(Constants::G_PROJECT_REBUILD);
@@ -728,22 +750,33 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
mprojectContextMenu->appendGroup(Constants::G_PROJECT_LAST);
mprojectContextMenu->appendGroup(Constants::G_PROJECT_TREE);
+ mprojectContextMenu->addMenu(projectOpenLocationCtxMenu, Constants::G_FOLDER_LOCATIONS);
+ connect(mprojectContextMenu->menu(), &QMenu::aboutToShow,
+ dd, &ProjectExplorerPluginPrivate::updateLocationSubMenus);
+
msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FIRST);
+ msubProjectContextMenu->appendGroup(Constants::G_FOLDER_LOCATIONS);
msubProjectContextMenu->appendGroup(Constants::G_PROJECT_BUILD);
msubProjectContextMenu->appendGroup(Constants::G_PROJECT_RUN);
msubProjectContextMenu->appendGroup(Constants::G_PROJECT_FILES);
msubProjectContextMenu->appendGroup(Constants::G_PROJECT_LAST);
msubProjectContextMenu->appendGroup(Constants::G_PROJECT_TREE);
+ msubProjectContextMenu->addMenu(subProjectOpenLocationCtxMenu, Constants::G_FOLDER_LOCATIONS);
+ connect(msubProjectContextMenu->menu(), &QMenu::aboutToShow,
+ dd, &ProjectExplorerPluginPrivate::updateLocationSubMenus);
+
ActionContainer *runMenu = ActionManager::createMenu(Constants::RUNMENUCONTEXTMENU);
runMenu->setOnAllDisabledBehavior(ActionContainer::Hide);
const QIcon runSideBarIcon = Utils::Icon::sideBarIcon(Icons::RUN, Icons::RUN_FLAT);
const QIcon runIcon = Utils::Icon::combinedIcon({Utils::Icons::RUN_SMALL.icon(),
runSideBarIcon});
+
runMenu->menu()->setIcon(runIcon);
runMenu->menu()->setTitle(tr("Run"));
msubProjectContextMenu->addMenu(runMenu, ProjectExplorer::Constants::G_PROJECT_RUN);
+ mfolderContextMenu->appendGroup(Constants::G_FOLDER_LOCATIONS);
mfolderContextMenu->appendGroup(Constants::G_FOLDER_FILES);
mfolderContextMenu->appendGroup(Constants::G_FOLDER_OTHER);
mfolderContextMenu->appendGroup(Constants::G_FOLDER_CONFIG);
@@ -760,6 +793,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd->m_openWithMenu = openWith->menu();
dd->m_openWithMenu->setTitle(tr("Open With"));
+ mfolderContextMenu->addMenu(folderOpenLocationCtxMenu, Constants::G_FOLDER_LOCATIONS);
+ connect(mfolderContextMenu->menu(), &QMenu::aboutToShow,
+ dd, &ProjectExplorerPluginPrivate::updateLocationSubMenus);
+
//
// Separators
//
@@ -1156,7 +1193,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(ICore::instance(), &ICore::saveSettingsRequested,
dd, &ProjectExplorerPluginPrivate::savePersistentSettings);
- connect(EditorManager::instance(), &EditorManager::autoSaved, this, [this] {
+ connect(EditorManager::instance(), &EditorManager::autoSaved, this, [] {
if (!dd->m_shuttingDown && !SessionManager::loadingSession())
SessionManager::save();
});
@@ -1205,7 +1242,9 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd->m_projectExplorerSettings.prompToStopRunControl =
s->value(QLatin1String("ProjectExplorer/Settings/PromptToStopRunControl"), false).toBool();
dd->m_projectExplorerSettings.maxAppOutputLines =
- s->value(QLatin1String("ProjectExplorer/Settings/MaxAppOutputLines"), 100000).toInt();
+ s->value(QLatin1String("ProjectExplorer/Settings/MaxAppOutputLines"), Core::Constants::DEFAULT_MAX_LINE_COUNT).toInt();
+ dd->m_projectExplorerSettings.maxBuildOutputLines =
+ s->value(QLatin1String("ProjectExplorer/Settings/MaxBuildOutputLines"), Core::Constants::DEFAULT_MAX_LINE_COUNT).toInt();
dd->m_projectExplorerSettings.environmentId =
QUuid(s->value(QLatin1String("ProjectExplorer/Settings/EnvironmentId")).toByteArray());
if (dd->m_projectExplorerSettings.environmentId.isNull())
@@ -1228,79 +1267,78 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd, &ProjectExplorerPlugin::openNewProjectDialog);
connect(dd->m_loadAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::loadAction);
- connect(dd->m_buildProjectOnlyAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_buildProjectOnlyAction, &QAction::triggered, dd, [] {
dd->queue({ SessionManager::startupProject() }, { Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_buildAction, &QAction::triggered,
- dd, [this] {
+ connect(dd->m_buildAction, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(SessionManager::startupProject()),
{ Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_buildActionContextMenu, &QAction::triggered, dd, [this] {
+ connect(dd->m_buildActionContextMenu, &QAction::triggered, dd, [] {
dd->queue({ ProjectTree::currentProject() }, { Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_buildDependenciesActionContextMenu, &QAction::triggered, dd, [this] {
+ connect(dd->m_buildDependenciesActionContextMenu, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(ProjectTree::currentProject()),
{ Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_buildSessionAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_buildSessionAction, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(), { Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_rebuildProjectOnlyAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_rebuildProjectOnlyAction, &QAction::triggered, dd, [] {
dd->queue({ SessionManager::startupProject() },
{ Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_rebuildAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_rebuildAction, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(SessionManager::startupProject()),
{ Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_rebuildActionContextMenu, &QAction::triggered, dd, [this] {
+ connect(dd->m_rebuildActionContextMenu, &QAction::triggered, dd, [] {
dd->queue({ ProjectTree::currentProject() },
{ Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_rebuildDependenciesActionContextMenu, &QAction::triggered, dd, [this] {
+ connect(dd->m_rebuildDependenciesActionContextMenu, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(ProjectTree::currentProject()),
{ Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_rebuildSessionAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_rebuildSessionAction, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(),
{ Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD) });
});
- connect(dd->m_deployProjectOnlyAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_deployProjectOnlyAction, &QAction::triggered, dd, [] {
dd->deploy({ SessionManager::startupProject() });
});
- connect(dd->m_deployAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_deployAction, &QAction::triggered, dd, [] {
dd->deploy(SessionManager::projectOrder(SessionManager::startupProject()));
});
- connect(dd->m_deployActionContextMenu, &QAction::triggered, dd, [this] {
+ connect(dd->m_deployActionContextMenu, &QAction::triggered, dd, [] {
dd->deploy({ ProjectTree::currentProject() });
});
- connect(dd->m_deploySessionAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_deploySessionAction, &QAction::triggered, dd, [] {
dd->deploy(SessionManager::projectOrder());
});
- connect(dd->m_cleanProjectOnlyAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_cleanProjectOnlyAction, &QAction::triggered, dd, [] {
dd->queue({ SessionManager::startupProject() }, { Id(Constants::BUILDSTEPS_CLEAN) });
});
- connect(dd->m_cleanAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_cleanAction, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(SessionManager::startupProject()),
{ Id(Constants::BUILDSTEPS_CLEAN) });
});
- connect(dd->m_cleanActionContextMenu, &QAction::triggered, dd, [this] {
+ connect(dd->m_cleanActionContextMenu, &QAction::triggered, dd, [] {
dd->queue({ ProjectTree::currentProject() }, { Id(Constants::BUILDSTEPS_CLEAN) });
});
- connect(dd->m_cleanDependenciesActionContextMenu, &QAction::triggered, dd, [this] {
+ connect(dd->m_cleanDependenciesActionContextMenu, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(ProjectTree::currentProject()),
{ Id(Constants::BUILDSTEPS_CLEAN) });
});
- connect(dd->m_cleanSessionAction, &QAction::triggered, dd, [this] {
+ connect(dd->m_cleanSessionAction, &QAction::triggered, dd, [] {
dd->queue(SessionManager::projectOrder(), { Id(Constants::BUILDSTEPS_CLEAN) });
});
connect(dd->m_runAction, &QAction::triggered,
- dd, [this]() { m_instance->runStartupProject(Constants::NORMAL_RUN_MODE); });
+ dd, []() { m_instance->runStartupProject(Constants::NORMAL_RUN_MODE); });
connect(dd->m_runActionContextMenu, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::runProjectContextMenu);
connect(dd->m_runWithoutDeployAction, &QAction::triggered,
- dd, [this]() { m_instance->runStartupProject(Constants::NORMAL_RUN_MODE, true); });
+ dd, []() { m_instance->runStartupProject(Constants::NORMAL_RUN_MODE, true); });
connect(dd->m_cancelBuildAction, &QAction::triggered,
BuildManager::instance(), &BuildManager::cancel);
connect(dd->m_unloadAction, &QAction::triggered,
@@ -1358,7 +1396,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
Utils::MacroExpander *expander = Utils::globalMacroExpander();
expander->registerFileVariables(Constants::VAR_CURRENTPROJECT_PREFIX,
tr("Current project's main file."),
- [this]() -> QString {
+ []() -> QString {
Utils::FileName projectFilePath;
if (Project *project = ProjectTree::currentProject())
projectFilePath = project->projectFilePath();
@@ -1374,7 +1412,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
expander->registerVariable(Constants::VAR_CURRENTPROJECT_NAME,
tr("The name of the current project."),
- [this]() -> QString {
+ []() -> QString {
Project *project = ProjectTree::currentProject();
return project ? project->displayName() : QString();
});
@@ -1443,7 +1481,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
expander->registerVariable(Constants::VAR_CURRENTRUN_NAME,
tr("The currently active run configuration's name."),
- [this]() -> QString {
+ []() -> QString {
if (Target *target = activeTarget()) {
if (RunConfiguration *rc = target->activeRunConfiguration())
return rc->displayName();
@@ -1453,7 +1491,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
expander->registerFileVariables("CurrentRun:Executable",
tr("The currently active run configuration's executable (if applicable)."),
- [this]() -> QString {
+ []() -> QString {
if (Target *target = activeTarget()) {
if (RunConfiguration *rc = target->activeRunConfiguration()) {
if (rc->runnable().is<StandardRunnable>())
@@ -1575,7 +1613,7 @@ void ProjectExplorerPlugin::extensionsInitialized()
QStringList filterStrings;
auto factory = new IDocumentFactory;
- factory->setOpener([this](QString fileName) -> IDocument* {
+ factory->setOpener([](QString fileName) -> IDocument* {
const QFileInfo fi(fileName);
if (fi.isDir())
fileName = FolderNavigationWidget::projectFilesInDirectory(fi.absoluteFilePath()).value(0, fileName);
@@ -1721,6 +1759,7 @@ void ProjectExplorerPluginPrivate::savePersistentSettings()
s->setValue(QLatin1String("ProjectExplorer/Settings/AutoRestoreLastSession"), dd->m_projectExplorerSettings.autorestoreLastSession);
s->setValue(QLatin1String("ProjectExplorer/Settings/PromptToStopRunControl"), dd->m_projectExplorerSettings.prompToStopRunControl);
s->setValue(QLatin1String("ProjectExplorer/Settings/MaxAppOutputLines"), dd->m_projectExplorerSettings.maxAppOutputLines);
+ s->setValue(QLatin1String("ProjectExplorer/Settings/MaxBuildOutputLines"), dd->m_projectExplorerSettings.maxBuildOutputLines);
s->setValue(QLatin1String("ProjectExplorer/Settings/EnvironmentId"), dd->m_projectExplorerSettings.environmentId.toByteArray());
s->setValue(QLatin1String("ProjectExplorer/Settings/StopBeforeBuild"), dd->m_projectExplorerSettings.stopBeforeBuild);
}
@@ -2118,11 +2157,11 @@ QList<QPair<QString, QString> > ProjectExplorerPluginPrivate::recentProjects() c
});
}
-static QString pathOrDirectoryFor(Node *node, bool dir)
+static QString pathOrDirectoryFor(const Node *node, bool dir)
{
Utils::FileName path = node->filePath();
QString location;
- FolderNode *folder = node->asFolderNode();
+ const FolderNode *folder = node->asFolderNode();
if (node->nodeType() == NodeType::VirtualFolder && folder) {
// Virtual Folder case
// If there are files directly below or no subfolders, take the folder path
@@ -2156,12 +2195,12 @@ static QString pathOrDirectoryFor(Node *node, bool dir)
return location;
}
-static QString pathFor(Node *node)
+static QString pathFor(const Node *node)
{
return pathOrDirectoryFor(node, false);
}
-static QString directoryFor(Node *node)
+static QString directoryFor(const Node *node)
{
return pathOrDirectoryFor(node, true);
}
@@ -2412,8 +2451,8 @@ void ProjectExplorerPlugin::buildProject(Project *p)
void ProjectExplorerPluginPrivate::runProjectContextMenu()
{
- Node *node = ProjectTree::currentNode();
- ProjectNode *projectNode = node ? node->asProjectNode() : nullptr;
+ const Node *node = ProjectTree::findCurrentNode();
+ const ProjectNode *projectNode = node ? node->asProjectNode() : nullptr;
if (projectNode == ProjectTree::currentProject()->rootProjectNode() || !projectNode) {
m_instance->runProject(ProjectTree::currentProject(), Constants::NORMAL_RUN_MODE);
} else {
@@ -2506,9 +2545,10 @@ bool ProjectExplorerPlugin::coreAboutToClose()
QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Close"), QMessageBox::AcceptRole);
QPushButton *cancelClose = box.addButton(tr("Do Not Close"), QMessageBox::RejectRole);
box.setDefaultButton(cancelClose);
- box.setWindowTitle(tr("Close Qt Creator?"));
+ box.setWindowTitle(tr("Close %1?").arg(Core::Constants::IDE_DISPLAY_NAME));
box.setText(tr("A project is currently being built."));
- box.setInformativeText(tr("Do you want to cancel the build process and close Qt Creator anyway?"));
+ box.setInformativeText(tr("Do you want to cancel the build process and close %1 anyway?")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
box.exec();
if (box.clickedButton() != closeAnyway)
return false;
@@ -2588,17 +2628,25 @@ void ProjectExplorerPluginPrivate::projectAdded(Project *pro)
if (m_projectsMode)
m_projectsMode->setEnabled(true);
// more specific action en and disabling ?
- connect(pro, &Project::buildConfigurationEnabledChanged,
- this, &ProjectExplorerPluginPrivate::updateActions);
+ pro->subscribeSignal(&BuildConfiguration::enabledChanged, this, [this]() {
+ auto bc = qobject_cast<BuildConfiguration *>(sender());
+ if (bc && bc->isActive() && bc->project() == SessionManager::startupProject()) {
+ updateActions();
+ emit m_instance->updateRunActions();
+ }
+ });
+ pro->subscribeSignal(&RunConfiguration::requestRunActionsUpdate, this, [this]() {
+ auto rc = qobject_cast<RunConfiguration *>(sender());
+ if (rc && rc->isActive() && rc->project() == SessionManager::startupProject())
+ emit m_instance->updateRunActions();
+ });
}
-void ProjectExplorerPluginPrivate::projectRemoved(Project * pro)
+void ProjectExplorerPluginPrivate::projectRemoved(Project *pro)
{
+ Q_UNUSED(pro);
if (m_projectsMode)
m_projectsMode->setEnabled(SessionManager::hasProjects());
- // more specific action en and disabling ?
- disconnect(pro, &Project::buildConfigurationEnabledChanged,
- this, &ProjectExplorerPluginPrivate::updateActions);
}
void ProjectExplorerPluginPrivate::projectDisplayNameChanged(Project *pro)
@@ -2668,15 +2716,6 @@ void ProjectExplorerPluginPrivate::activeRunConfigurationChanged()
rc = startupProject->activeTarget()->activeRunConfiguration();
if (rc == previousRunConfiguration)
return;
- if (previousRunConfiguration) {
- disconnect(previousRunConfiguration.data(), &RunConfiguration::requestRunActionsUpdate,
- m_instance, &ProjectExplorerPlugin::updateRunActions);
- }
- previousRunConfiguration = rc;
- if (rc) {
- connect(rc, &RunConfiguration::requestRunActionsUpdate,
- m_instance, &ProjectExplorerPlugin::updateRunActions);
- }
emit m_instance->updateRunActions();
}
@@ -2689,15 +2728,7 @@ void ProjectExplorerPluginPrivate::activeBuildConfigurationChanged()
bc = startupProject->activeTarget()->activeBuildConfiguration();
if (bc == previousBuildConfiguration)
return;
- if (previousBuildConfiguration) {
- disconnect(previousBuildConfiguration.data(), &BuildConfiguration::enabledChanged,
- m_instance, &ProjectExplorerPlugin::updateRunActions);
- }
- previousBuildConfiguration = bc;
- if (bc) {
- connect(bc, &BuildConfiguration::enabledChanged,
- m_instance, &ProjectExplorerPlugin::updateRunActions);
- }
+ updateActions();
emit m_instance->updateRunActions();
}
@@ -2949,14 +2980,14 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
runMenu->menu()->clear();
runMenu->menu()->menuAction()->setVisible(false);
- Node *currentNode = ProjectTree::currentNode();
+ const Node *currentNode = ProjectTree::findCurrentNode();
if (currentNode && currentNode->managingProject()) {
ProjectNode *pn;
- if (ContainerNode *cn = currentNode->asContainerNode())
+ if (const ContainerNode *cn = currentNode->asContainerNode())
pn = cn->rootProjectNode();
else
- pn = currentNode->asProjectNode();
+ pn = const_cast<ProjectNode*>(currentNode->asProjectNode());
if (pn) {
if (ProjectTree::currentProject() && pn == ProjectTree::currentProject()->rootProjectNode()) {
@@ -3011,7 +3042,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_removeFileAction->setVisible(!enableDelete || enableRemove);
m_renameFileAction->setEnabled(supports(Rename));
const bool currentNodeIsTextFile = isTextFile(
- ProjectTree::currentNode()->filePath().toString());
+ currentNode->filePath().toString());
m_diffFileAction->setEnabled(isDiffServiceAvailable()
&& currentNodeIsTextFile && TextEditor::TextDocument::currentTextDocument());
@@ -3019,7 +3050,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_duplicateFileAction->setEnabled(supports(DuplicateFile));
EditorManager::populateOpenWithMenu(m_openWithMenu,
- ProjectTree::currentNode()->filePath().toString());
+ currentNode->filePath().toString());
}
if (supports(HidePathActions)) {
@@ -3043,10 +3074,53 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
}
}
+void ProjectExplorerPluginPrivate::updateLocationSubMenus()
+{
+ static QList<QAction *> actions;
+ qDeleteAll(actions); // This will also remove these actions from the menus!
+ actions.clear();
+
+ ActionContainer *projectMenuContainer
+ = ActionManager::actionContainer(Constants::PROJECT_OPEN_LOCATIONS_CONTEXT_MENU);
+ QMenu *projectMenu = projectMenuContainer->menu();
+ QTC_CHECK(projectMenu->actions().isEmpty());
+
+ ActionContainer *folderMenuContainer
+ = ActionManager::actionContainer(Constants::FOLDER_OPEN_LOCATIONS_CONTEXT_MENU);
+ QMenu *folderMenu = folderMenuContainer->menu();
+ QTC_CHECK(folderMenu->actions().isEmpty());
+
+ const FolderNode *const fn
+ = ProjectTree::findCurrentNode() ? ProjectTree::findCurrentNode()->asFolderNode() : nullptr;
+ const QList<FolderNode::LocationInfo> locations
+ = fn ? fn->locationInfo() : QList<FolderNode::LocationInfo>();
+
+ const bool isVisible = !locations.isEmpty();
+ projectMenu->menuAction()->setVisible(isVisible);
+ folderMenu->menuAction()->setVisible(isVisible);
+
+ if (!isVisible)
+ return;
+
+ for (const FolderNode::LocationInfo &li : locations) {
+ const int line = li.line;
+ const Utils::FileName path = li.path;
+ QAction *action = new QAction(li.displayName, nullptr);
+ connect(action, &QAction::triggered, this, [line, path]() {
+ Core::EditorManager::openEditorAt(path.toString(), line);
+ });
+
+ projectMenu->addAction(action);
+ folderMenu->addAction(action);
+
+ actions.append(action);
+ }
+}
+
void ProjectExplorerPluginPrivate::addNewFile()
{
- QTC_ASSERT(ProjectTree::currentNode(), return);
- Node *currentNode = ProjectTree::currentNode();
+ Node* currentNode = ProjectTree::findCurrentNode();
+ QTC_ASSERT(currentNode, return);
QString location = directoryFor(currentNode);
QVariantMap map;
@@ -3069,8 +3143,8 @@ void ProjectExplorerPluginPrivate::addNewFile()
void ProjectExplorerPluginPrivate::addNewSubproject()
{
- QTC_ASSERT(ProjectTree::currentNode(), return);
- Node *currentNode = ProjectTree::currentNode();
+ Node* currentNode = ProjectTree::findCurrentNode();
+ QTC_ASSERT(currentNode, return);
QString location = directoryFor(currentNode);
if (currentNode->nodeType() == NodeType::Project
@@ -3096,13 +3170,13 @@ void ProjectExplorerPluginPrivate::addNewSubproject()
void ProjectExplorerPluginPrivate::handleAddExistingFiles()
{
- Node *node = ProjectTree::currentNode();
+ Node *node = ProjectTree::findCurrentNode();
FolderNode *folderNode = node ? node->asFolderNode() : nullptr;
QTC_ASSERT(folderNode, return);
QStringList fileNames = QFileDialog::getOpenFileNames(ICore::mainWindow(),
- tr("Add Existing Files"), directoryFor(ProjectTree::currentNode()));
+ tr("Add Existing Files"), directoryFor(node));
if (fileNames.isEmpty())
return;
@@ -3111,12 +3185,12 @@ void ProjectExplorerPluginPrivate::handleAddExistingFiles()
void ProjectExplorerPluginPrivate::addExistingDirectory()
{
- Node *node = ProjectTree::currentNode();
+ Node *node = ProjectTree::findCurrentNode();
FolderNode *folderNode = node ? node->asFolderNode() : nullptr;
QTC_ASSERT(folderNode, return);
- SelectableFilesDialogAddDirectory dialog(Utils::FileName::fromString(directoryFor(ProjectTree::currentNode())),
+ SelectableFilesDialogAddDirectory dialog(Utils::FileName::fromString(directoryFor(node)),
Utils::FileNameList(), ICore::mainWindow());
dialog.setAddFileFilter(folderNode->addFileFilter());
@@ -3152,7 +3226,7 @@ void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStri
void ProjectExplorerPluginPrivate::removeProject()
{
- Node *node = ProjectTree::currentNode();
+ Node *node = ProjectTree::findCurrentNode();
if (!node)
return;
ProjectNode *subProjectNode = node->managingProject();
@@ -3169,31 +3243,35 @@ void ProjectExplorerPluginPrivate::removeProject()
void ProjectExplorerPluginPrivate::openFile()
{
- QTC_ASSERT(ProjectTree::currentNode(), return);
- EditorManager::openEditor(ProjectTree::currentNode()->filePath().toString());
+ const Node *currentNode = ProjectTree::findCurrentNode();
+ QTC_ASSERT(currentNode, return);
+ EditorManager::openEditor(currentNode->filePath().toString());
}
void ProjectExplorerPluginPrivate::searchOnFileSystem()
{
- QTC_ASSERT(ProjectTree::currentNode(), return);
- TextEditor::FindInFiles::findOnFileSystem(pathFor(ProjectTree::currentNode()));
+ const Node *currentNode = ProjectTree::findCurrentNode();
+ QTC_ASSERT(currentNode, return);
+ TextEditor::FindInFiles::findOnFileSystem(pathFor(currentNode));
}
void ProjectExplorerPluginPrivate::showInGraphicalShell()
{
- QTC_ASSERT(ProjectTree::currentNode(), return);
- FileUtils::showInGraphicalShell(ICore::mainWindow(), pathFor(ProjectTree::currentNode()));
+ Node *currentNode = ProjectTree::findCurrentNode();
+ QTC_ASSERT(currentNode, return);
+ FileUtils::showInGraphicalShell(ICore::mainWindow(), pathFor(currentNode));
}
void ProjectExplorerPluginPrivate::openTerminalHere()
{
- QTC_ASSERT(ProjectTree::currentNode(), return);
- FileUtils::openTerminal(directoryFor(ProjectTree::currentNode()));
+ const Node *currentNode = ProjectTree::findCurrentNode();
+ QTC_ASSERT(currentNode, return);
+ FileUtils::openTerminal(directoryFor(currentNode));
}
void ProjectExplorerPluginPrivate::removeFile()
{
- Node *currentNode = ProjectTree::currentNode();
+ const Node *currentNode = ProjectTree::findCurrentNode();
QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
const Utils::FileName filePath = currentNode->filePath();
@@ -3203,7 +3281,7 @@ void ProjectExplorerPluginPrivate::removeFile()
const bool deleteFile = removeFileDialog.isDeleteFileChecked();
// Re-read the current node, in case the project is re-parsed while the dialog is open
- if (currentNode != ProjectTree::currentNode()) {
+ if (currentNode != ProjectTree::findCurrentNode()) {
currentNode = ProjectTreeWidget::nodeForFile(filePath);
QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
}
@@ -3228,7 +3306,7 @@ void ProjectExplorerPluginPrivate::removeFile()
void ProjectExplorerPluginPrivate::duplicateFile()
{
- Node *currentNode = ProjectTree::currentNode();
+ Node *currentNode = ProjectTree::findCurrentNode();
QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
FileNode *fileNode = currentNode->asFileNode();
@@ -3259,7 +3337,7 @@ void ProjectExplorerPluginPrivate::duplicateFile()
void ProjectExplorerPluginPrivate::deleteFile()
{
- Node *currentNode = ProjectTree::currentNode();
+ Node *currentNode = ProjectTree::findCurrentNode();
QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
FileNode *fileNode = currentNode->asFileNode();
@@ -3320,7 +3398,7 @@ void ProjectExplorerPluginPrivate::handleDiffFile()
return;
// current item's file
- Node *currentNode = ProjectTree::currentNode();
+ Node *currentNode = ProjectTree::findCurrentNode();
QTC_ASSERT(currentNode && currentNode->nodeType() == NodeType::File, return);
FileNode *fileNode = currentNode->asFileNode();
@@ -3358,8 +3436,9 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath)
.arg(projectFileName)
.arg(QDir::toNativeSeparators(oldFilePath))
.arg(QDir::toNativeSeparators(newFilePath)));
- if (res == QMessageBox::Yes)
- FileUtils::renameFile(oldFilePath, newFilePath);
+ if (res == QMessageBox::Yes) {
+ QTC_CHECK(FileUtils::renameFile(oldFilePath, newFilePath));
+ }
});
return;
@@ -3457,7 +3536,9 @@ QStringList ProjectExplorerPlugin::projectFilePatterns()
void ProjectExplorerPlugin::openOpenProjectDialog()
{
- const QString path = DocumentManager::useProjectsDirectory() ? DocumentManager::projectsDirectory() : QString();
+ const QString path = DocumentManager::useProjectsDirectory()
+ ? DocumentManager::projectsDirectory().toString()
+ : QString();
const QStringList files = DocumentManager::getOpenFileNames(dd->m_projectFilterString, path);
if (!files.isEmpty())
ICore::openFiles(files, ICore::SwitchMode);
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 21d97fb2c2..979a3e865d 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -21,6 +21,7 @@ HEADERS += projectexplorer.h \
projectimporter.h \
projectwindow.h \
removetaskhandler.h \
+ subscription.h \
targetsetuppage.h \
targetsetupwidget.h \
kit.h \
@@ -33,11 +34,11 @@ HEADERS += projectexplorer.h \
kitmanagerconfigwidget.h \
kitmodel.h \
kitoptionspage.h \
+ projectconfigurationmodel.h \
buildmanager.h \
buildsteplist.h \
compileoutputwindow.h \
deployconfiguration.h \
- deployconfigurationmodel.h \
namedwidget.h \
target.h \
targetsettingspanel.h \
@@ -94,8 +95,6 @@ HEADERS += projectexplorer.h \
ldparser.h \
linuxiccparser.h \
runconfigurationaspects.h \
- runconfigurationmodel.h \
- buildconfigurationmodel.h \
processparameters.h \
abstractprocessstep.h \
taskhub.h \
@@ -150,7 +149,8 @@ HEADERS += projectexplorer.h \
projectexplorer_global.h \
extracompiler.h \
customexecutableconfigurationwidget.h \
- customexecutablerunconfiguration.h
+ customexecutablerunconfiguration.h \
+ projectmacro.h
SOURCES += projectexplorer.cpp \
abi.cpp \
@@ -163,12 +163,14 @@ SOURCES += projectexplorer.cpp \
environmentaspectwidget.cpp \
gcctoolchain.cpp \
importwidget.cpp \
+ projectconfigurationmodel.cpp \
runnables.cpp \
localenvironmentaspect.cpp \
osparser.cpp \
projectimporter.cpp \
projectwindow.cpp \
removetaskhandler.cpp \
+ subscription.cpp \
targetsetuppage.cpp \
targetsetupwidget.cpp \
kit.cpp \
@@ -184,7 +186,6 @@ SOURCES += projectexplorer.cpp \
buildsteplist.cpp \
compileoutputwindow.cpp \
deployconfiguration.cpp \
- deployconfigurationmodel.cpp \
namedwidget.cpp \
target.cpp \
targetsettingspanel.cpp \
@@ -238,8 +239,6 @@ SOURCES += projectexplorer.cpp \
ldparser.cpp \
linuxiccparser.cpp \
runconfigurationaspects.cpp \
- runconfigurationmodel.cpp \
- buildconfigurationmodel.cpp \
taskhub.cpp \
processparameters.cpp \
appoutputpane.cpp \
@@ -286,7 +285,8 @@ SOURCES += projectexplorer.cpp \
projectexplorericons.cpp \
extracompiler.cpp \
customexecutableconfigurationwidget.cpp \
- customexecutablerunconfiguration.cpp
+ customexecutablerunconfiguration.cpp \
+ projectmacro.cpp
FORMS += processstep.ui \
editorsettingspropertiespage.ui \
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index 47bc9d3947..2b643f69a7 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -13,6 +13,7 @@ Project {
Depends { name: "Core" }
Depends { name: "TextEditor" }
+ Depends { name: "app_version_header" }
cpp.defines: base.concat("QTC_CPU=X86Architecture")
@@ -29,7 +30,6 @@ Project {
"appoutputpane.cpp", "appoutputpane.h",
"baseprojectwizarddialog.cpp", "baseprojectwizarddialog.h",
"buildconfiguration.cpp", "buildconfiguration.h",
- "buildconfigurationmodel.cpp", "buildconfigurationmodel.h",
"buildenvironmentwidget.cpp", "buildenvironmentwidget.h",
"buildinfo.cpp", "buildinfo.h",
"buildmanager.cpp", "buildmanager.h",
@@ -54,7 +54,6 @@ Project {
"dependenciespanel.cpp", "dependenciespanel.h",
"deployablefile.cpp", "deployablefile.h",
"deployconfiguration.cpp", "deployconfiguration.h",
- "deployconfigurationmodel.cpp", "deployconfigurationmodel.h",
"deploymentdata.h",
"deploymentdataview.cpp",
"deploymentdataview.h",
@@ -100,6 +99,7 @@ Project {
"processstep.cpp", "processstep.h", "processstep.ui",
"project.cpp", "project.h",
"projectconfiguration.cpp", "projectconfiguration.h",
+ "projectconfigurationmodel.cpp", "projectconfigurationmodel.h",
"projectexplorer.cpp", "projectexplorer.h",
"projectexplorer.qrc",
"projectexplorer_export.h",
@@ -110,6 +110,7 @@ Project {
"projectexplorersettingspage.cpp", "projectexplorersettingspage.h", "projectexplorersettingspage.ui",
"projectfilewizardextension.cpp", "projectfilewizardextension.h",
"projectimporter.cpp", "projectimporter.h",
+ "projectmacro.cpp", "projectmacro.h",
"projectmacroexpander.cpp", "projectmacroexpander.h",
"projectmanager.h",
"projectmodels.cpp", "projectmodels.h",
@@ -124,7 +125,6 @@ Project {
"runnables.cpp", "runnables.h",
"runconfiguration.cpp", "runconfiguration.h",
"runconfigurationaspects.cpp", "runconfigurationaspects.h",
- "runconfigurationmodel.cpp", "runconfigurationmodel.h",
"runsettingspropertiespage.cpp", "runsettingspropertiespage.h",
"selectablefilesmodel.cpp", "selectablefilesmodel.h",
"session.cpp", "session.h",
@@ -134,6 +134,7 @@ Project {
"settingsaccessor.cpp", "settingsaccessor.h",
"showineditortaskhandler.cpp", "showineditortaskhandler.h",
"showoutputtaskhandler.cpp", "showoutputtaskhandler.h",
+ "subscription.cpp", "subscription.h",
"target.cpp", "target.h",
"targetsettingspanel.cpp", "targetsettingspanel.h",
"targetsetuppage.cpp", "targetsetuppage.h",
diff --git a/src/plugins/projectexplorer/projectexplorer.qrc b/src/plugins/projectexplorer/projectexplorer.qrc
index 85e1a5a4ad..649c3e658f 100644
--- a/src/plugins/projectexplorer/projectexplorer.qrc
+++ b/src/plugins/projectexplorer/projectexplorer.qrc
@@ -1,6 +1,5 @@
<RCC>
<qresource prefix="/projectexplorer">
- <file>images/build_small.png</file>
<file>images/category_buildrun.png</file>
<file>images/closetab.png</file>
<file>images/debugger_start.png</file>
@@ -12,6 +11,10 @@
<file>images/mode_project_mask.png</file>
<file>images/mode_project_mask@2x.png</file>
<file>images/projectexplorer.png</file>
+ <file>images/buildhammerhandle.png</file>
+ <file>images/buildhammerhandle@2x.png</file>
+ <file>images/buildhammerhead.png</file>
+ <file>images/buildhammerhead@2x.png</file>
<file>images/rebuildhammerhandles.png</file>
<file>images/rebuildhammerhandles@2x.png</file>
<file>images/rebuildhammerheads.png</file>
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 13dfe2431a..f0f4b2762a 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -73,6 +73,7 @@ const char G_PROJECT_FILES[] = "Project.Group.Files";
const char G_PROJECT_TREE[] = "Project.Group.Tree";
const char G_PROJECT_LAST[] = "Project.Group.Last";
+const char G_FOLDER_LOCATIONS[] = "ProjectFolder.Group.Locations";
const char G_FOLDER_FILES[] = "ProjectFolder.Group.Files";
const char G_FOLDER_OTHER[] = "ProjectFolder.Group.Other";
const char G_FOLDER_CONFIG[] = "ProjectFolder.Group.Config";
diff --git a/src/plugins/projectexplorer/projectexplorericons.cpp b/src/plugins/projectexplorer/projectexplorericons.cpp
index e86fe915bc..cd1913838d 100644
--- a/src/plugins/projectexplorer/projectexplorericons.cpp
+++ b/src/plugins/projectexplorer/projectexplorericons.cpp
@@ -34,10 +34,14 @@ const Icon BUILD(":/projectexplorer/images/build.png");
const Icon BUILD_FLAT({
{":/projectexplorer/images/build_hammerhandle_mask.png", Theme::IconsBuildHammerHandleColor},
{":/projectexplorer/images/build_hammerhead_mask.png", Theme::IconsBuildHammerHeadColor}});
-const Icon BUILD_SMALL(":/projectexplorer/images/build_small.png");
+const Icon BUILD_SMALL({
+ {":/projectexplorer/images/buildhammerhandle.png", Theme::IconsBuildHammerHandleColor},
+ {":/projectexplorer/images/buildhammerhead.png", Theme::IconsBuildHammerHeadColor}}, Icon::Tint);
const Icon REBUILD({
{":/projectexplorer/images/rebuildhammerhandles.png", Theme::IconsBuildHammerHandleColor},
- {":/projectexplorer/images/rebuildhammerheads.png", Theme::IconsBuildHammerHeadColor}}, Icon::Tint);
+ {":/projectexplorer/images/buildhammerhandle.png", Theme::IconsBuildHammerHandleColor},
+ {":/projectexplorer/images/rebuildhammerheads.png", Theme::IconsBuildHammerHeadColor},
+ {":/projectexplorer/images/buildhammerhead.png", Theme::IconsBuildHammerHeadColor}}, Icon::Tint);
const Icon RUN(":/projectexplorer/images/run.png");
const Icon RUN_FLAT({
{":/projectexplorer/images/run_mask.png", Theme::IconsRunToolBarColor}});
diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h
index a2759d66e3..e0d4b8088c 100644
--- a/src/plugins/projectexplorer/projectexplorersettings.h
+++ b/src/plugins/projectexplorer/projectexplorersettings.h
@@ -25,6 +25,8 @@
#pragma once
+#include <coreplugin/coreconstants.h>
+
#include <QUuid>
namespace ProjectExplorer {
@@ -47,7 +49,8 @@ public:
bool useJom = true;
bool autorestoreLastSession = false; // This option is set in the Session Manager!
bool prompToStopRunControl = false;
- int maxAppOutputLines = 100000;
+ int maxAppOutputLines = Core::Constants::DEFAULT_MAX_LINE_COUNT;
+ int maxBuildOutputLines = Core::Constants::DEFAULT_MAX_LINE_COUNT;
StopBeforeBuild stopBeforeBuild = StopBeforeBuild::StopNone;
// Add a UUid which is used to identify the development environment.
@@ -71,6 +74,7 @@ inline bool operator==(const ProjectExplorerSettings &p1, const ProjectExplorerS
&& p1.autorestoreLastSession == p2.autorestoreLastSession
&& p1.prompToStopRunControl == p2.prompToStopRunControl
&& p1.maxAppOutputLines == p2.maxAppOutputLines
+ && p1.maxBuildOutputLines == p2.maxBuildOutputLines
&& p1.environmentId == p2.environmentId
&& p1.stopBeforeBuild == p2.stopBeforeBuild;
}
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettingspage.cpp
index 115413b47a..9d7f8b1c8b 100644
--- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp
+++ b/src/plugins/projectexplorer/projectexplorersettingspage.cpp
@@ -109,6 +109,7 @@ ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const
m_settings.useJom = m_ui.jomCheckbox->isChecked();
m_settings.prompToStopRunControl = m_ui.promptToStopRunControlCheckBox->isChecked();
m_settings.maxAppOutputLines = m_ui.maxAppOutputBox->value();
+ m_settings.maxBuildOutputLines = m_ui.maxBuildOutputBox->value();
m_settings.stopBeforeBuild = static_cast<ProjectExplorerSettings::StopBeforeBuild>(m_ui.stopBeforeBuildComboBox->currentIndex());
return m_settings;
}
@@ -128,7 +129,8 @@ void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &
m_ui.jomCheckbox->setChecked(m_settings.useJom);
m_ui.promptToStopRunControlCheckBox->setChecked(m_settings.prompToStopRunControl);
m_ui.maxAppOutputBox->setValue(m_settings.maxAppOutputLines);
- m_ui.stopBeforeBuildComboBox->setCurrentIndex(static_cast<int>(pes.stopBeforeBuild));
+ m_ui.maxBuildOutputBox->setValue(m_settings.maxBuildOutputLines);
+ m_ui.stopBeforeBuildComboBox->setCurrentIndex(static_cast<int>(m_settings.stopBeforeBuild));
}
QString ProjectExplorerSettingsWidget::projectsDirectory() const
@@ -196,7 +198,7 @@ QWidget *ProjectExplorerSettingsPage::widget()
if (!m_widget) {
m_widget = new ProjectExplorerSettingsWidget;
m_widget->setSettings(ProjectExplorerPlugin::projectExplorerSettings());
- m_widget->setProjectsDirectory(Core::DocumentManager::projectsDirectory());
+ m_widget->setProjectsDirectory(Core::DocumentManager::projectsDirectory().toString());
m_widget->setUseProjectsDirectory(Core::DocumentManager::useProjectsDirectory());
m_widget->setBuildDirectory(Core::DocumentManager::buildDirectory());
}
@@ -207,7 +209,8 @@ void ProjectExplorerSettingsPage::apply()
{
if (m_widget) {
ProjectExplorerPlugin::setProjectExplorerSettings(m_widget->settings());
- Core::DocumentManager::setProjectsDirectory(m_widget->projectsDirectory());
+ Core::DocumentManager::setProjectsDirectory(
+ Utils::FileName::fromString(m_widget->projectsDirectory()));
Core::DocumentManager::setUseProjectsDirectory(m_widget->useProjectsDirectory());
Core::DocumentManager::setBuildDirectory(m_widget->buildDirectory());
}
diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.ui b/src/plugins/projectexplorer/projectexplorersettingspage.ui
index 7ea652cc17..4a51b8b274 100644
--- a/src/plugins/projectexplorer/projectexplorersettingspage.ui
+++ b/src/plugins/projectexplorer/projectexplorersettingspage.ui
@@ -120,14 +120,14 @@
<number>0</number>
</property>
<item>
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="limitBuildOutputLabel">
<property name="text">
- <string>Limit application output to </string>
+ <string>Limit build output to </string>
</property>
</widget>
</item>
<item>
- <widget class="QSpinBox" name="maxAppOutputBox">
+ <widget class="QSpinBox" name="maxBuildOutputBox">
<property name="minimum">
<number>500</number>
</property>
@@ -143,7 +143,7 @@
</widget>
</item>
<item>
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="limitBuildOutputLabel_2">
<property name="text">
<string>lines</string>
</property>
@@ -159,6 +159,54 @@
</property>
</widget>
</item>
+ <item row="4" column="1">
+ <widget class="QWidget" name="widget_1" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Limit application output to</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="maxAppOutputBox">
+ <property name="minimum">
+ <number>500</number>
+ </property>
+ <property name="maximum">
+ <number>1000000</number>
+ </property>
+ <property name="singleStep">
+ <number>500</number>
+ </property>
+ <property name="value">
+ <number>100000</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>lines</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item row="5" column="0">
<widget class="QCheckBox" name="showDebugOutputCheckBox">
<property name="text">
diff --git a/src/plugins/projectexplorer/projectexplorerunittestfiles.pri b/src/plugins/projectexplorer/projectexplorerunittestfiles.pri
new file mode 100644
index 0000000000..6b005059e6
--- /dev/null
+++ b/src/plugins/projectexplorer/projectexplorerunittestfiles.pri
@@ -0,0 +1,12 @@
+shared {
+ DEFINES += PROJECTEXPLORER_LIBRARY
+} else {
+ DEFINES += PROJECTEXPLORER_STATIC_LIBRARY
+}
+
+HEADERS += \
+ $$PWD/projectmacro.h
+
+SOURCES += \
+ $$PWD/projectmacro.cpp
+
diff --git a/src/plugins/projectexplorer/projectmacro.cpp b/src/plugins/projectexplorer/projectmacro.cpp
new file mode 100644
index 0000000000..5d2824f01d
--- /dev/null
+++ b/src/plugins/projectexplorer/projectmacro.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "projectmacro.h"
+
+#include <utils/algorithm.h>
+#include <cctype>
+
+namespace ProjectExplorer {
+
+bool Macro::isValid() const
+{
+ return !key.isEmpty() && type != MacroType::Invalid;
+}
+
+QByteArray Macro::toByteArray() const
+{
+ switch (type) {
+ case MacroType::Define: {
+ if (value.isEmpty())
+ return QByteArray("#define ") + key;
+ return QByteArray("#define ") + key + ' ' + value;
+ }
+ case MacroType::Undefine: return QByteArray("#undef ") + key;
+ case MacroType::Invalid: break;
+ }
+
+ return QByteArray();
+}
+
+QByteArray Macro::toByteArray(const Macros &macros)
+{
+ QByteArray text;
+
+ for (const Macro &macro : macros) {
+ const QByteArray macroText = macro.toByteArray();
+ if (!macroText.isEmpty())
+ text += macroText + '\n';
+ }
+
+ return text;
+}
+
+QByteArray Macro::toByteArray(const QVector<Macros> &macrosVector)
+{
+ QByteArray text;
+
+ for (const Macros &macros : macrosVector)
+ text += toByteArray(macros);
+
+ return text;
+}
+
+Macros Macro::toMacros(const QByteArray &text)
+{
+ return tokensLinesToMacros(tokenizeLines(splitLines(text)));
+}
+
+Macro Macro::fromKeyValue(const QString &utf16text)
+{
+ return fromKeyValue(utf16text.toUtf8());
+}
+
+Macro Macro::fromKeyValue(const QByteArray &text)
+{
+ QByteArray key;
+ QByteArray value;
+ MacroType type = MacroType::Invalid;
+
+ if (!text.isEmpty()) {
+ type = MacroType::Define;
+
+ int index = text.indexOf('=');
+
+ if (index != -1) {
+ key = text.left(index).trimmed();
+ value = text.mid(index + 1).trimmed();
+ } else {
+ key = text.trimmed();
+ value = "1";
+ }
+ }
+
+ return Macro(key, value, type);
+}
+
+QByteArray Macro::toKeyValue(const QByteArray &prefix) const
+{
+ QByteArray keyValue;
+ if (type != MacroType::Invalid)
+ keyValue = prefix;
+
+ if (value.isEmpty())
+ keyValue += key + '=';
+ else if (value == "1")
+ keyValue += key;
+ else
+ keyValue += key + '=' + value;
+
+ return keyValue;
+}
+
+static void removeCarriageReturn(QByteArray &line)
+{
+ if (line.endsWith('\r'))
+ line.truncate(line.size() - 1);
+}
+
+static void removeCarriageReturns(QList<QByteArray> &lines)
+{
+ for (QByteArray &line : lines)
+ removeCarriageReturn(line);
+}
+
+QList<QByteArray> Macro::splitLines(const QByteArray &text)
+{
+ QList<QByteArray> splitLines = text.split('\n');
+
+ splitLines.removeAll("");
+ removeCarriageReturns(splitLines);
+
+ return splitLines;
+}
+
+QByteArray Macro::removeNonsemanticSpaces(QByteArray line)
+{
+ auto begin = line.begin();
+ auto end = line.end();
+ bool notInString = true;
+
+ auto newEnd = std::unique(begin, end, [&] (char first, char second) {
+ notInString = notInString && first != '\"';
+ return notInString && (first == '#' || std::isspace(first)) && std::isspace(second);
+ });
+
+ line.truncate(line.size() - int(std::distance(newEnd, end)));
+
+ return line.trimmed();
+}
+
+QList<QByteArray> Macro::tokenizeLine(const QByteArray &line)
+{
+ const QByteArray normalizedLine = removeNonsemanticSpaces(line);
+
+ const auto begin = normalizedLine.begin();
+ auto first = std::find(normalizedLine.begin(), normalizedLine.end(), ' ');
+ auto second = std::find(std::next(first), normalizedLine.end(), ' ');
+ const auto end = normalizedLine.end();
+
+ QList<QByteArray> tokens;
+
+ if (first != end) {
+ tokens.append(QByteArray(begin, int(std::distance(begin, first))));
+
+ std::advance(first, 1);
+ tokens.append(QByteArray(first, int(std::distance(first, second))));
+
+ if (second != end) {
+ std::advance(second, 1);
+ tokens.append(QByteArray(second, int(std::distance(second, end))));
+ }
+ }
+
+ return tokens;
+}
+
+QList<QList<QByteArray>> Macro::tokenizeLines(const QList<QByteArray> &lines)
+{
+ QList<QList<QByteArray>> tokensLines = Utils::transform(lines, &Macro::tokenizeLine);
+
+ return tokensLines;
+}
+
+Macro Macro::tokensToMacro(const QList<QByteArray> &tokens)
+{
+ Macro macro;
+
+ if (tokens.size() >= 2 && tokens[0] == "#define") {
+ macro.type = MacroType::Define;
+ macro.key = tokens[1];
+
+ if (tokens.size() >= 3)
+ macro.value = tokens[2];
+ }
+
+ return macro;
+}
+
+Macros Macro::tokensLinesToMacros(const QList<QList<QByteArray>> &tokensLines)
+{
+ Macros macros;
+ macros.reserve(tokensLines.size());
+
+ for (const QList<QByteArray> &tokens : tokensLines) {
+ Macro macro = tokensToMacro(tokens);
+
+ if (macro.type != MacroType::Invalid)
+ macros.push_back(std::move(macro));
+ }
+
+ return macros;
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectmacro.h b/src/plugins/projectexplorer/projectmacro.h
new file mode 100644
index 0000000000..2a4537aaf8
--- /dev/null
+++ b/src/plugins/projectexplorer/projectmacro.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "projectexplorer_export.h"
+
+#include <QByteArray>
+#include <QHash>
+#include <QVector>
+
+namespace ProjectExplorer {
+
+enum class MacroType
+{
+ Invalid,
+ Define,
+ Undefine
+};
+
+class Macro;
+
+using Macros = QVector<Macro>;
+
+class PROJECTEXPLORER_EXPORT Macro
+{
+public:
+ Macro() = default;
+
+ Macro(QByteArray key, QByteArray value, MacroType type = MacroType::Define)
+ : key(key), value(value), type(type)
+ {}
+
+ Macro(QByteArray key, MacroType type = MacroType::Define)
+ : key(key), type(type)
+ {}
+
+ bool isValid() const;
+
+ QByteArray toByteArray() const;
+ static QByteArray toByteArray(const Macros &macros);
+ static QByteArray toByteArray(const QVector<Macros> &macross);
+
+ static Macros toMacros(const QByteArray &text);
+
+ // define Foo will be converted to Foo=1
+ static Macro fromKeyValue(const QString &utf16text);
+ static Macro fromKeyValue(const QByteArray &text);
+ QByteArray toKeyValue(const QByteArray &prefix) const;
+
+public:
+ QByteArray key;
+ QByteArray value;
+ MacroType type = MacroType::Invalid;
+
+private:
+ static QList<QByteArray> splitLines(const QByteArray &text);
+ static QByteArray removeNonsemanticSpaces(QByteArray line);
+ static QList<QByteArray> tokenizeLine(const QByteArray &line);
+ static QList<QList<QByteArray>> tokenizeLines(const QList<QByteArray> &lines);
+ static Macro tokensToMacro(const QList<QByteArray> &tokens);
+ static Macros tokensLinesToMacros(const QList<QList<QByteArray>> &tokensLines);
+};
+
+inline
+uint qHash(const Macro &macro)
+{
+ using QT_PREPEND_NAMESPACE(qHash);
+ return qHash(macro.key) ^ qHash(macro.value) ^ qHash(int(macro.type));
+}
+
+inline
+bool operator==(const Macro &first, const Macro &second)
+{
+ return first.type == second.type
+ && first.key == second.key
+ && first.value == second.value;
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index 17504821ac..f22618a3c5 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -32,15 +32,18 @@
#include "session.h"
#include <coreplugin/fileiconprovider.h>
+#include <utils/utilsicons.h>
#include <utils/algorithm.h>
#include <utils/dropsupport.h>
+#include <utils/theme/theme.h>
-#include <QDebug>
#include <QFileInfo>
#include <QFont>
#include <QMimeData>
#include <QLoggingCategory>
+#include <functional>
+
using namespace Utils;
namespace ProjectExplorer {
@@ -106,10 +109,19 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
}
case Qt::DecorationRole: {
if (folderNode) {
- result = folderNode->icon();
+ static QIcon emptyIcon = Utils::Icons::EMPTY16.icon();
if (ContainerNode *containerNode = folderNode->asContainerNode()) {
- if (ProjectNode *projectNode = containerNode->rootProjectNode())
- result = projectNode->icon();
+ WrapperNode *wn = wrapperForNode(node);
+ Project *project = Utils::findOrDefault(SessionManager::projects(), [this, wn](const Project *p) {
+ return nodeForProject(p) == wn;
+ });
+ if (project && project->isParsing())
+ result = emptyIcon;
+ else
+ result = containerNode->rootProjectNode() ? containerNode->rootProjectNode()->icon() :
+ folderNode->icon();
+ } else {
+ result = folderNode->icon();
}
} else {
result = Core::FileIconProvider::icon(node->filePath().toString());
@@ -133,6 +145,17 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
result = node->isEnabled();
break;
}
+ case Project::isParsingRole: {
+ const Project *project = nullptr;
+ if (node->asContainerNode()) {
+ WrapperNode *wn = wrapperForNode(node);
+ project = Utils::findOrDefault(SessionManager::projects(), [this, wn](const Project *p) {
+ return nodeForProject(p) == wn;
+ });
+ }
+ result = project ? project->isParsing() : false;
+ break;
+ }
}
}
@@ -229,6 +252,13 @@ void FlatModel::addOrRebuildProjectModel(Project *project)
emit requestExpansion(container->index());
}
+void FlatModel::parsingStateChanged(Project *project)
+{
+ const WrapperNode *const node = nodeForProject(project);
+ const QModelIndex nodeIdx = indexForNode(node->m_node);
+ emit dataChanged(nodeIdx, nodeIdx);
+}
+
void FlatModel::updateSubtree(FolderNode *node)
{
// FIXME: This is still excessive, should be limited to the affected subtree.
@@ -265,6 +295,12 @@ ExpandData FlatModel::expandDataForNode(const Node *node) const
void FlatModel::handleProjectAdded(Project *project)
{
+ QTC_ASSERT(project, return);
+
+ connect(project, &Project::parsingStarted,
+ this, [this, project]() { parsingStateChanged(project); });
+ connect(project, &Project::parsingFinished,
+ this, [this, project]() { parsingStateChanged(project); });
addOrRebuildProjectModel(project);
}
@@ -273,7 +309,7 @@ void FlatModel::handleProjectRemoved(Project *project)
destroyItem(nodeForProject(project));
}
-WrapperNode *FlatModel::nodeForProject(Project *project)
+WrapperNode *FlatModel::nodeForProject(const Project *project) const
{
QTC_ASSERT(project, return nullptr);
ContainerNode *containerNode = project->containerNode();
@@ -359,7 +395,7 @@ QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const
WrapperNode *FlatModel::wrapperForNode(const Node *node) const
{
- return findNonRooItem([this, node](WrapperNode *item) {
+ return findNonRootItem([node](WrapperNode *item) {
return item->m_node == node;
});
}
diff --git a/src/plugins/projectexplorer/projectmodels.h b/src/plugins/projectexplorer/projectmodels.h
index a0041a7bcd..80fdbbc36d 100644
--- a/src/plugins/projectexplorer/projectmodels.h
+++ b/src/plugins/projectexplorer/projectmodels.h
@@ -49,7 +49,7 @@ class WrapperNode : public Utils::TypedTreeItem<WrapperNode>
{
public:
explicit WrapperNode(Node *node) : m_node(node) {}
- QPointer<Node> m_node;
+ Node *m_node = nullptr;
};
class FlatModel : public Utils::TreeModel<WrapperNode, WrapperNode>
@@ -102,9 +102,11 @@ private:
void saveExpandData();
void handleProjectAdded(Project *project);
void handleProjectRemoved(Project *project);
- WrapperNode *nodeForProject(Project *project);
+ WrapperNode *nodeForProject(const Project *project) const;
void addOrRebuildProjectModel(Project *project);
+ void parsingStateChanged(Project *project);
+
QTimer m_timer;
QSet<ExpandData> m_toExpand;
};
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index a3e7203e34..91ff23f5fa 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -253,7 +253,7 @@ bool Node::isGenerated() const
return (m_flags & FlagIsGenerated) == FlagIsGenerated;
}
-bool Node::supportsAction(ProjectAction, Node *) const
+bool Node::supportsAction(ProjectAction, const Node *) const
{
return false;
}
@@ -408,7 +408,7 @@ FileNode::scanForFilesWithVersionControls(const Utils::FileName &directory,
return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, versionControls);
}
-bool FileNode::supportsAction(ProjectAction action, Node *node) const
+bool FileNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == InheritedFromParent)
return true;
@@ -643,13 +643,23 @@ void FolderNode::setIcon(const QIcon &icon)
m_icon = icon;
}
+void FolderNode::setLocationInfo(const QList<FolderNode::LocationInfo> &info)
+{
+ m_locations = info;
+}
+
+const QList<FolderNode::LocationInfo> FolderNode::locationInfo() const
+{
+ return m_locations;
+}
+
QString FolderNode::addFileFilter() const
{
FolderNode *fn = parentFolderNode();
return fn ? fn->addFileFilter() : QString();
}
-bool FolderNode::supportsAction(ProjectAction action, Node *node) const
+bool FolderNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == InheritedFromParent)
return true;
@@ -832,7 +842,7 @@ bool ProjectNode::renameFile(const QString &filePath, const QString &newFilePath
return false;
}
-bool ProjectNode::supportsAction(ProjectAction, Node *) const
+bool ProjectNode::supportsAction(ProjectAction, const Node *) const
{
return false;
}
@@ -887,9 +897,9 @@ QString ContainerNode::displayName() const
return name;
}
-bool ContainerNode::supportsAction(ProjectAction action, Node *node) const
+bool ContainerNode::supportsAction(ProjectAction action, const Node *node) const
{
- Node *rootNode = m_project->rootProjectNode();
+ const Node *rootNode = m_project->rootProjectNode();
return rootNode && rootNode->supportsAction(action, node);
}
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index 376e50192f..c0cc25a04d 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -29,7 +29,6 @@
#include <QFutureInterface>
#include <QIcon>
-#include <QObject>
#include <QStringList>
#include <utils/fileutils.h>
@@ -98,9 +97,8 @@ class ProjectNode;
class ContainerNode;
// Documentation inside.
-class PROJECTEXPLORER_EXPORT Node : public QObject
+class PROJECTEXPLORER_EXPORT Node
{
- Q_OBJECT
public:
enum PriorityLevel {
DefaultPriority = 0,
@@ -134,7 +132,7 @@ public:
bool listInProject() const;
bool isGenerated() const;
- virtual bool supportsAction(ProjectAction action, Node *node) const;
+ virtual bool supportsAction(ProjectAction action, const Node *node) const;
void setEnabled(bool enabled);
void setAbsoluteFilePathAndLine(const Utils::FileName &filePath, int line);
@@ -203,7 +201,7 @@ public:
const std::function<FileNode *(const Utils::FileName &fileName)> factory,
const QList<Core::IVersionControl *> &versionControls,
QFutureInterface<QList<FileNode *>> *future = nullptr);
- bool supportsAction(ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectAction action, const Node *node) const override;
private:
FileType m_fileType;
@@ -247,9 +245,21 @@ public:
void setDisplayName(const QString &name);
void setIcon(const QIcon &icon);
+ class LocationInfo {
+ public:
+ LocationInfo(const QString &dn, const Utils::FileName &p, const int l = -1) :
+ path(p), line(l), displayName(dn) { }
+
+ Utils::FileName path;
+ int line = -1;
+ QString displayName;
+ };
+ void setLocationInfo(const QList<LocationInfo> &info);
+ const QList<LocationInfo> locationInfo() const;
+
virtual QString addFileFilter() const;
- bool supportsAction(ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectAction action, const Node *node) const override;
virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0);
virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0);
@@ -285,6 +295,7 @@ public:
protected:
QList<Node *> m_nodes;
+ QList<LocationInfo> m_locations;
private:
QString m_displayName;
@@ -317,7 +328,7 @@ public:
bool deleteFiles(const QStringList &filePaths) override;
bool canRenameFile(const QString &filePath, const QString &newFilePath) override;
bool renameFile(const QString &filePath, const QString &newFilePath) override;
- bool supportsAction(ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectAction action, const Node *node) const override;
// by default returns false
virtual bool deploysFolder(const QString &folder) const;
@@ -339,7 +350,7 @@ public:
ContainerNode(Project *project);
QString displayName() const final;
- bool supportsAction(ProjectAction action, Node *node) const final;
+ bool supportsAction(ProjectAction action, const Node *node) const final;
ContainerNode *asContainerNode() final { return this; }
const ContainerNode *asContainerNode() const final { return this; }
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index 5f4a0b780e..606ad41f24 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -65,10 +65,10 @@ ProjectTree::ProjectTree(QObject *parent) : QObject(parent)
s_instance = this;
connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
- this, &ProjectTree::documentManagerCurrentFileChanged);
+ this, &ProjectTree::update);
connect(qApp, &QApplication::focusChanged,
- this, &ProjectTree::focusChanged);
+ this, &ProjectTree::update);
connect(SessionManager::instance(), &SessionManager::projectAdded,
this, &ProjectTree::sessionChanged);
@@ -92,8 +92,8 @@ ProjectTree::~ProjectTree()
void ProjectTree::aboutToShutDown()
{
disconnect(qApp, &QApplication::focusChanged,
- s_instance, &ProjectTree::focusChanged);
- s_instance->update(nullptr, nullptr);
+ s_instance, &ProjectTree::update);
+ s_instance->setCurrent(nullptr, nullptr);
qDeleteAll(s_instance->m_projectTreeWidgets);
QTC_CHECK(s_instance->m_projectTreeWidgets.isEmpty());
}
@@ -108,8 +108,9 @@ Project *ProjectTree::currentProject()
return s_instance->m_currentProject;
}
-Node *ProjectTree::currentNode()
+Node *ProjectTree::findCurrentNode()
{
+ s_instance->update();
return s_instance->m_currentNode;
}
@@ -133,21 +134,21 @@ void ProjectTree::nodeChanged(ProjectTreeWidget *widget)
s_instance->updateFromProjectTreeWidget(widget);
}
-void ProjectTree::focusChanged()
-{
- s_instance->updateFromFocus();
-}
-
-void ProjectTree::updateFromFocus(bool invalidCurrentNode)
+void ProjectTree::update()
{
ProjectTreeWidget *focus = m_focusForContextMenu;
- if (!focus)
+ static QPointer<ProjectTreeWidget> lastFocusedProjectTreeWidget;
+ if (!focus) {
focus = Utils::findOrDefault(m_projectTreeWidgets, &ProjectTree::hasFocus);
+ lastFocusedProjectTreeWidget = focus;
+ }
+ if (!focus)
+ focus = lastFocusedProjectTreeWidget;
if (focus)
updateFromProjectTreeWidget(focus);
else
- updateFromDocumentManager(invalidCurrentNode);
+ updateFromDocumentManager();
}
void ProjectTree::updateFromProjectTreeWidget(ProjectTreeWidget *widget)
@@ -155,26 +156,17 @@ void ProjectTree::updateFromProjectTreeWidget(ProjectTreeWidget *widget)
Node *currentNode = widget->currentNode();
Project *project = SessionManager::projectForNode(currentNode);
- update(currentNode, project);
+ setCurrent(currentNode, project);
}
-void ProjectTree::documentManagerCurrentFileChanged()
+void ProjectTree::updateFromDocumentManager()
{
- updateFromFocus();
-}
-
-void ProjectTree::updateFromDocumentManager(bool invalidCurrentNode)
-{
- Core::IDocument *document = Core::EditorManager::currentDocument();
- const FileName fileName = document ? document->filePath() : FileName();
-
- Node *currentNode = nullptr;
- if (!invalidCurrentNode && m_currentNode && m_currentNode->filePath() == fileName)
- currentNode = m_currentNode;
- else
- currentNode = ProjectTreeWidget::nodeForFile(fileName);
-
- updateFromNode(currentNode);
+ if (Core::IDocument *document = Core::EditorManager::currentDocument()) {
+ const FileName fileName = document->filePath();
+ updateFromNode(ProjectTreeWidget::nodeForFile(fileName));
+ } else {
+ updateFromNode(nullptr);
+ }
}
void ProjectTree::updateFromNode(Node *node)
@@ -185,12 +177,12 @@ void ProjectTree::updateFromNode(Node *node)
else
project = SessionManager::startupProject();
- update(node, project);
+ setCurrent(node, project);
foreach (ProjectTreeWidget *widget, m_projectTreeWidgets)
widget->sync(node);
}
-void ProjectTree::update(Node *node, Project *project)
+void ProjectTree::setCurrent(Node *node, Project *project)
{
const bool changedProject = project != m_currentProject;
if (changedProject) {
@@ -243,7 +235,7 @@ void ProjectTree::sessionChanged()
Core::DocumentManager::setDefaultLocationForNewFiles(SessionManager::startupProject()->projectDirectory().toString());
else
Core::DocumentManager::setDefaultLocationForNewFiles(QString());
- updateFromFocus();
+ update();
}
void ProjectTree::updateContext()
diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h
index 7f61a2ee78..3d880d8355 100644
--- a/src/plugins/projectexplorer/projecttree.h
+++ b/src/plugins/projectexplorer/projecttree.h
@@ -51,7 +51,7 @@ public:
static ProjectTree *instance();
static Project *currentProject();
- static Node *currentNode();
+ static Node *findCurrentNode();
// Integration with ProjectTreeWidget
static void registerWidget(Internal::ProjectTreeWidget *widget);
@@ -90,15 +90,14 @@ signals:
private:
void sessionChanged();
- void focusChanged();
+ void update();
void updateFromProjectTreeWidget(Internal::ProjectTreeWidget *widget);
- void documentManagerCurrentFileChanged();
- void updateFromDocumentManager(bool invalidCurrentNode = false);
+ void updateFromDocumentManager();
void updateFromNode(Node *node);
- void update(Node *node, Project *project);
+ void setCurrent(Node *node, Project *project);
void updateContext();
- void updateFromFocus(bool invalidCurrentNode = false);
+ void updateFromFocus();
void updateExternalFileWarning();
static bool hasFocus(Internal::ProjectTreeWidget *widget);
@@ -108,7 +107,7 @@ private:
static ProjectTree *s_instance;
QList<QPointer<Internal::ProjectTreeWidget>> m_projectTreeWidgets;
QVector<TreeManagerFunction> m_treeManagers;
- QPointer<Node> m_currentNode;
+ Node *m_currentNode = nullptr;
Project *m_currentProject = nullptr;
Internal::ProjectTreeWidget *m_focusForContextMenu = nullptr;
Core::Context m_lastProjectContext;
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index 5b1471504e..f310cd1468 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -40,23 +40,28 @@
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/find/itemviewfind.h>
-#include <utils/navigationtreeview.h>
#include <utils/algorithm.h>
+#include <utils/navigationtreeview.h>
+#include <utils/progressindicator.h>
#include <utils/tooltip/tooltip.h>
#include <utils/utilsicons.h>
-#include <QDebug>
+#include <QApplication>
#include <QSettings>
#include <QStyledItemDelegate>
#include <QVBoxLayout>
#include <QToolButton>
+#include <QPainter>
#include <QAction>
#include <QMenu>
+#include <memory>
+
using namespace Core;
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
+using namespace Utils;
QList<ProjectTreeWidget *> ProjectTreeWidget::m_projectTreeWidgets;
@@ -65,22 +70,78 @@ namespace {
class ProjectTreeItemDelegate : public QStyledItemDelegate
{
public:
- ProjectTreeItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
- { }
+ ProjectTreeItemDelegate(QTreeView *view) : QStyledItemDelegate(view),
+ m_view(view)
+ {
+ connect(m_view->model(), &QAbstractItemModel::modelReset,
+ this, &ProjectTreeItemDelegate::deleteAllIndicators);
+
+ // Actually this only needs to delete the indicators in the effected rows and *after* it,
+ // but just be lazy and nuke all the indicators.
+ connect(m_view->model(), &QAbstractItemModel::rowsAboutToBeRemoved,
+ this, &ProjectTreeItemDelegate::deleteAllIndicators);
+ connect(m_view->model(), &QAbstractItemModel::rowsAboutToBeInserted,
+ this, &ProjectTreeItemDelegate::deleteAllIndicators);
+ }
+
+ ~ProjectTreeItemDelegate() override
+ {
+ deleteAllIndicators();
+ }
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
QStyleOptionViewItem opt = option;
if (!index.data(Project::EnabledRole).toBool())
opt.state &= ~QStyle::State_Enabled;
QStyledItemDelegate::paint(painter, opt, index);
+
+ if (index.data(Project::isParsingRole).toBool()) {
+ initStyleOption(&opt, index);
+ ProgressIndicatorPainter *indicator = findOrCreateIndicatorPainter(index);
+
+ QStyle *style = option.widget ? option.widget->style() : QApplication::style();
+ const QRect rect = style->subElementRect(QStyle::SE_ItemViewItemDecoration, &opt, opt.widget);
+
+ indicator->paint(*painter, rect);
+ } else {
+ delete m_indicators.value(index);
+ m_indicators.remove(index);
+ }
}
+
+private:
+ ProgressIndicatorPainter *findOrCreateIndicatorPainter(const QModelIndex &index) const
+ {
+ ProgressIndicatorPainter *indicator = m_indicators.value(index);
+ if (!indicator)
+ indicator = createIndicatorPainter(index);
+ return indicator;
+ }
+
+ ProgressIndicatorPainter *createIndicatorPainter(const QModelIndex &index) const
+ {
+ auto indicator = new ProgressIndicatorPainter(ProgressIndicatorSize::Small);
+ indicator->setUpdateCallback([index, this]() { m_view->update(index); });
+ indicator->startAnimation();
+ m_indicators.insert(index, indicator);
+ return indicator;
+ }
+
+ void deleteAllIndicators()
+ {
+ qDeleteAll(m_indicators);
+ m_indicators.clear();
+ }
+
+ mutable QHash<QModelIndex, ProgressIndicatorPainter *> m_indicators;
+ QTreeView *m_view;
};
bool debug = false;
}
-class ProjectTreeView : public Utils::NavigationTreeView
+class ProjectTreeView : public NavigationTreeView
{
public:
ProjectTreeView()
@@ -138,7 +199,7 @@ public:
connect(newModel, &QAbstractItemModel::rowsRemoved,
this, &ProjectTreeView::invalidateSize);
}
- Utils::NavigationTreeView::setModel(newModel);
+ NavigationTreeView::setModel(newModel);
}
~ProjectTreeView()
@@ -150,7 +211,7 @@ public:
int sizeHintForColumn(int column) const override
{
if (m_cachedSize < 0)
- m_cachedSize = Utils::NavigationTreeView::sizeHintForColumn(column);
+ m_cachedSize = NavigationTreeView::sizeHintForColumn(column);
return m_cachedSize;
}
@@ -172,7 +233,7 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent) : QWidget(parent)
m_model = new FlatModel(this);
m_view = new ProjectTreeView;
m_view->setModel(m_model);
- m_view->setItemDelegate(new ProjectTreeItemDelegate(this));
+ m_view->setItemDelegate(new ProjectTreeItemDelegate(m_view));
setFocusProxy(m_view);
m_view->installEventFilter(this);
@@ -217,14 +278,14 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent) : QWidget(parent)
m_model, &FlatModel::onCollapsed);
m_toggleSync = new QToolButton;
- m_toggleSync->setIcon(Utils::Icons::LINK.icon());
+ m_toggleSync->setIcon(Icons::LINK.icon());
m_toggleSync->setCheckable(true);
m_toggleSync->setChecked(autoSynchronization());
m_toggleSync->setToolTip(tr("Synchronize with Editor"));
connect(m_toggleSync, &QAbstractButton::clicked,
this, &ProjectTreeWidget::toggleAutoSynchronization);
- setCurrentItem(ProjectTree::currentNode());
+ setCurrentItem(ProjectTree::findCurrentNode());
setAutoSynchronization(true);
m_projectTreeWidgets << this;
@@ -276,7 +337,7 @@ void ProjectTreeWidget::rowsInserted(const QModelIndex &parent, int start, int e
}
}
-Node *ProjectTreeWidget::nodeForFile(const Utils::FileName &fileName)
+Node *ProjectTreeWidget::nodeForFile(const FileName &fileName)
{
Node *bestNode = nullptr;
int bestNodeExpandCount = INT_MAX;
@@ -334,7 +395,7 @@ void ProjectTreeWidget::setAutoSynchronization(bool sync)
if (m_autoSync) {
// sync from document manager
- Utils::FileName fileName;
+ FileName fileName;
if (IDocument *doc = EditorManager::currentDocument())
fileName = doc->filePath();
if (!currentNode() || currentNode()->filePath() != fileName)
@@ -354,7 +415,7 @@ void ProjectTreeWidget::editCurrentItem()
m_view->edit(m_view->selectionModel()->currentIndex());
}
-void ProjectTreeWidget::renamed(const Utils::FileName &oldPath, const Utils::FileName &newPath)
+void ProjectTreeWidget::renamed(const FileName &oldPath, const FileName &newPath)
{
update();
Q_UNUSED(oldPath);
@@ -406,8 +467,8 @@ void ProjectTreeWidget::showMessage(Node *node, const QString &message)
m_view->scrollTo(idx);
QPoint pos = m_view->mapToGlobal(m_view->visualRect(idx).bottomLeft());
- pos -= Utils::ToolTip::offsetFromPosition();
- Utils::ToolTip::show(pos, message);
+ pos -= ToolTip::offsetFromPosition();
+ ToolTip::show(pos, message);
}
void ProjectTreeWidget::showContextMenu(const QPoint &pos)
@@ -471,7 +532,7 @@ NavigationView ProjectTreeWidgetFactory::createWidget()
n.widget = ptw;
auto filter = new QToolButton;
- filter->setIcon(Utils::Icons::FILTER.icon());
+ filter->setIcon(Icons::FILTER.icon());
filter->setToolTip(tr("Filter Tree"));
filter->setPopupMode(QToolButton::InstantPopup);
filter->setProperty("noArrow", true);
diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp
index e70f93a707..1c38f85638 100644
--- a/src/plugins/projectexplorer/runconfiguration.cpp
+++ b/src/plugins/projectexplorer/runconfiguration.cpp
@@ -173,34 +173,75 @@ void IRunConfigurationAspect::resetProjectToGlobalSettings()
A run configuration specifies how a target should be run, while a runner
does the actual running.
- All RunControls and the target hold a shared pointer to the run
- configuration. That is, the lifetime of the run configuration might exceed
- the life of the target.
- The user might still have a RunControl running (or output tab of that RunControl open)
- and yet unloaded the target.
-
- Also, a run configuration might be already removed from the list of run
- configurations
- for a target, but still be runnable via the output tab.
+ The target owns the RunConfiguraitons and a RunControl will need to copy all
+ necessary data as the RunControl may continue to exist after the RunConfiguration
+ has been destroyed.
+
+ A RunConfiguration disables itself when the project is parsing or has no parsing
+ data available. The disabledReason() method can be used to get a user-facing string
+ describing why the RunConfiguration considers itself unfit for use.
+
+ Override updateEnabledState() to change the enabled state handling. Override
+ disabledReasons() to provide better/more descriptions to the user.
+
+ Connect signals that may change enabled state of your RunConfiguration to updateEnabledState.
*/
static std::vector<RunConfiguration::AspectFactory> theAspectFactories;
-RunConfiguration::RunConfiguration(Target *target, Core::Id id) :
- ProjectConfiguration(target, id)
+RunConfiguration::RunConfiguration(Target *target)
+ : StatefulProjectConfiguration(target)
{
Q_ASSERT(target);
- ctor();
+
+ connect(target->project(), &Project::parsingStarted,
+ this, [this]() { updateEnabledState(); });
+ connect(target->project(), &Project::parsingFinished,
+ this, [this]() { updateEnabledState(); });
+
+ connect(target, &Target::addedRunConfiguration,
+ this, [this](const RunConfiguration *rc) {
+ if (rc == this)
+ updateEnabledState();
+ });
+
+ connect(this, &RunConfiguration::enabledChanged,
+ this, &RunConfiguration::requestRunActionsUpdate);
+
+ Utils::MacroExpander *expander = macroExpander();
+ expander->setDisplayName(tr("Run Settings"));
+ expander->setAccumulating(true);
+ expander->registerSubProvider([target] {
+ BuildConfiguration *bc = target->activeBuildConfiguration();
+ return bc ? bc->macroExpander() : target->macroExpander();
+ });
+ expander->registerPrefix("CurrentRun:Env", tr("Variables in the current run environment"),
+ [this](const QString &var) {
+ const auto envAspect = extraAspect<EnvironmentAspect>();
+ return envAspect ? envAspect->environment().value(var) : QString();
+ });
+ expander->registerVariable(Constants::VAR_CURRENTRUN_NAME,
+ QCoreApplication::translate("ProjectExplorer", "The currently active run configuration's name."),
+ [this] { return displayName(); }, false);
+}
+
+RunConfiguration::~RunConfiguration()
+{
+ qDeleteAll(m_aspects);
+}
+
+void RunConfiguration::initialize(Core::Id id)
+{
+ StatefulProjectConfiguration::initialize(id);
for (const AspectFactory &factory : theAspectFactories)
addExtraAspect(factory(this));
}
-RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) :
- ProjectConfiguration(target, source)
+void RunConfiguration::copyFrom(const RunConfiguration *source)
{
- Q_ASSERT(target);
- ctor();
+ StatefulProjectConfiguration::copyFrom(source);
+
foreach (IRunConfigurationAspect *aspect, source->m_aspects) {
IRunConfigurationAspect *clone = aspect->clone(this);
if (clone)
@@ -208,9 +249,25 @@ RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) :
}
}
-RunConfiguration::~RunConfiguration()
+bool RunConfiguration::isActive() const
{
- qDeleteAll(m_aspects);
+ return target()->isActive() && target()->activeRunConfiguration() == this;
+}
+
+QString RunConfiguration::disabledReason() const
+{
+ if (target()->project()->isParsing())
+ return tr("The Project is currently being parsed.");
+ if (!target()->project()->hasParsingData())
+ return tr("The project could not be fully parsed.");
+ return QString();
+}
+
+void RunConfiguration::updateEnabledState()
+{
+ Project *p = target()->project();
+
+ setEnabled(!p->isParsing() && p->hasParsingData());
}
void RunConfiguration::addAspectFactory(const AspectFactory &aspectFactory)
@@ -224,28 +281,6 @@ void RunConfiguration::addExtraAspect(IRunConfigurationAspect *aspect)
m_aspects += aspect;
}
-void RunConfiguration::ctor()
-{
- connect(this, &RunConfiguration::enabledChanged,
- this, &RunConfiguration::requestRunActionsUpdate);
-
- Utils::MacroExpander *expander = macroExpander();
- expander->setDisplayName(tr("Run Settings"));
- expander->setAccumulating(true);
- expander->registerSubProvider([this]() -> Utils::MacroExpander * {
- BuildConfiguration *bc = target()->activeBuildConfiguration();
- return bc ? bc->macroExpander() : target()->macroExpander();
- });
- expander->registerPrefix("CurrentRun:Env", tr("Variables in the current run environment"),
- [this](const QString &var) {
- const auto envAspect = extraAspect<EnvironmentAspect>();
- return envAspect ? envAspect->environment().value(var) : QString();
- });
- expander->registerVariable(Constants::VAR_CURRENTRUN_NAME,
- QCoreApplication::translate("ProjectExplorer", "The currently active run configuration's name."),
- [this] { return displayName(); }, false);
-}
-
/*!
* Returns the RunConfiguration of the currently active target
* of the startup project, if such exists, or \c nullptr otherwise.
@@ -260,20 +295,6 @@ RunConfiguration *RunConfiguration::startupRunConfiguration()
return nullptr;
}
-/*!
- Checks whether a run configuration is enabled.
-*/
-
-bool RunConfiguration::isEnabled() const
-{
- return true;
-}
-
-QString RunConfiguration::disabledReason() const
-{
- return QString();
-}
-
bool RunConfiguration::isConfigured() const
{
return true;
@@ -288,7 +309,6 @@ RunConfiguration::ConfigurationState RunConfiguration::ensureConfigured(QString
return UnConfigured;
}
-
BuildConfiguration *RunConfiguration::activeBuildConfiguration() const
{
if (!target())
@@ -301,6 +321,11 @@ Target *RunConfiguration::target() const
return static_cast<Target *>(parent());
}
+Project *RunConfiguration::project() const
+{
+ return target()->project();
+}
+
QVariantMap RunConfiguration::toMap() const
{
QVariantMap map = ProjectConfiguration::toMap();
@@ -591,6 +616,8 @@ public:
outputFormatter = runConfiguration->createOutputFormatter();
device = DeviceKitInformation::device(runConfiguration->target()->kit());
project = runConfiguration->target()->project();
+ } else {
+ outputFormatter = new OutputFormatter();
}
}
@@ -615,6 +642,7 @@ public:
void initiateReStart();
void continueStart();
void initiateStop();
+ void forceStop();
void continueStopOrFinish();
void initiateFinish();
@@ -699,6 +727,11 @@ void RunControl::initiateStop()
d->initiateStop();
}
+void RunControl::forceStop()
+{
+ d->forceStop();
+}
+
void RunControl::initiateFinish()
{
QTimer::singleShot(0, d, &RunControlPrivate::initiateFinish);
@@ -896,6 +929,43 @@ void RunControlPrivate::continueStopOrFinish()
}
}
+void RunControlPrivate::forceStop()
+{
+ if (state == RunControlState::Finished) {
+ debugMessage("Was finished, too late to force Stop");
+ return;
+ }
+ for (RunWorker *worker : m_workers) {
+ if (worker) {
+ const QString &workerId = worker->d->id;
+ debugMessage(" Examining worker " + workerId);
+ switch (worker->d->state) {
+ case RunWorkerState::Initialized:
+ debugMessage(" " + workerId + " was Initialized, setting to Done");
+ break;
+ case RunWorkerState::Stopping:
+ debugMessage(" " + workerId + " was already Stopping. Set it forcefully to Done.");
+ break;
+ case RunWorkerState::Starting:
+ debugMessage(" " + workerId + " was Starting. Set it forcefully to Done.");
+ break;
+ case RunWorkerState::Running:
+ debugMessage(" " + workerId + " was Running. Set it forcefully to Done.");
+ break;
+ case RunWorkerState::Done:
+ debugMessage(" " + workerId + " was Done. Good.");
+ break;
+ }
+ worker->d->state = RunWorkerState::Done;
+ } else {
+ debugMessage("Found unknown deleted worker");
+ }
+ }
+
+ setState(RunControlState::Stopped);
+ debugMessage("All Stopped");
+}
+
void RunControlPrivate::initiateFinish()
{
setState(RunControlState::Finishing);
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index 0460735206..51f5c7b2e2 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -199,15 +199,17 @@ private:
};
// Documentation inside.
-class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
+class PROJECTEXPLORER_EXPORT RunConfiguration : public StatefulProjectConfiguration
{
Q_OBJECT
public:
~RunConfiguration() override;
- virtual bool isEnabled() const;
- virtual QString disabledReason() const;
+ bool isActive() const override;
+
+ QString disabledReason() const override;
+
virtual QWidget *createConfigurationWidget() = 0;
virtual bool isConfigured() const;
@@ -217,6 +219,7 @@ public:
virtual ConfigurationState ensureConfigured(QString *errorMessage = nullptr);
Target *target() const;
+ Project *project() const override;
virtual Utils::OutputFormatter *createOutputFormatter() const;
@@ -252,20 +255,22 @@ public:
}
signals:
- void enabledChanged();
void requestRunActionsUpdate();
void configurationFinished();
protected:
- RunConfiguration(Target *parent, Core::Id id);
- RunConfiguration(Target *parent, RunConfiguration *source);
+ friend class IRunConfigurationFactory;
+
+ RunConfiguration(Target *target);
+ void initialize(Core::Id id);
+ void copyFrom(const RunConfiguration *source);
/// convenience function to get current build configuration.
BuildConfiguration *activeBuildConfiguration() const;
-private:
- void ctor();
+ virtual void updateEnabledState();
+private:
static void addAspectFactory(const AspectFactory &aspectFactory);
QList<IRunConfigurationAspect *> m_aspects;
@@ -293,6 +298,20 @@ public:
static IRunConfigurationFactory *find(Target *parent, RunConfiguration *rc);
static QList<IRunConfigurationFactory *> find(Target *parent);
+ template <class RunConfig, typename ...Args>
+ static RunConfig *createHelper(Target *target, Args ...args) {
+ auto runConfig = new RunConfig(target);
+ runConfig->initialize(args...);
+ return runConfig;
+ }
+
+ template <class RunConfig>
+ static RunConfig *cloneHelper(Target *target, const RunConfiguration *source) {
+ auto runConfig = new RunConfig(target);
+ runConfig->copyFrom(static_cast<const RunConfig *>(source));
+ return runConfig;
+ }
+
signals:
void availableCreationIdsChanged();
@@ -392,6 +411,7 @@ public:
void initiateStart();
void initiateReStart();
void initiateStop();
+ void forceStop();
void initiateFinish();
bool promptToStop(bool *optionalPrompt = nullptr) const;
diff --git a/src/plugins/projectexplorer/runconfigurationmodel.cpp b/src/plugins/projectexplorer/runconfigurationmodel.cpp
deleted file mode 100644
index 45d7bf0668..0000000000
--- a/src/plugins/projectexplorer/runconfigurationmodel.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "runconfigurationmodel.h"
-#include "target.h"
-#include "runconfiguration.h"
-
-#include <utils/algorithm.h>
-
-using namespace ProjectExplorer;
-
-/*!
- \class ProjectExplorer::RunConfigurationModel
-
- \brief The RunConfigurationModel class provides a model to represent the
- run configurations of a target.
-
- To be used in the dropdown lists of comboboxes.
- Automatically adjusts itself to added and removed run configurations.
-*/
-
-class RunConfigurationComparer
-{
-public:
- bool operator()(RunConfiguration *a, RunConfiguration *b)
- {
- return a->displayName() < b->displayName();
- }
-};
-
-RunConfigurationModel::RunConfigurationModel(Target *target, QObject *parent) :
- QAbstractListModel(parent),
- m_target(target)
-{
- QTC_ASSERT(target, return);
- m_runConfigurations = m_target->runConfigurations();
- Utils::sort(m_runConfigurations, RunConfigurationComparer());
-
- connect(target, &Target::addedRunConfiguration,
- this, &RunConfigurationModel::addedRunConfiguration);
- connect(target, &Target::removedRunConfiguration,
- this, &RunConfigurationModel::removedRunConfiguration);
-
- foreach (RunConfiguration *rc, m_runConfigurations)
- connect(rc, &ProjectConfiguration::displayNameChanged,
- this, &RunConfigurationModel::displayNameChanged);
-}
-
-int RunConfigurationModel::rowCount(const QModelIndex &parent) const
-{
- return parent.isValid() ? 0 : m_runConfigurations.size();
-}
-
-int RunConfigurationModel::columnCount(const QModelIndex &parent) const
-{
- return parent.isValid() ? 0 : 1;
-}
-
-void RunConfigurationModel::displayNameChanged()
-{
- RunConfiguration *rc = qobject_cast<RunConfiguration *>(sender());
- if (!rc)
- return;
-
- RunConfigurationComparer compare;
- // Find the old position
- int oldPos = m_runConfigurations.indexOf(rc);
-
- if (oldPos >= 1 && compare(m_runConfigurations.at(oldPos), m_runConfigurations.at(oldPos - 1))) {
- // We need to move up
- int newPos = oldPos - 1;
- while (newPos >= 0 && compare(m_runConfigurations.at(oldPos), m_runConfigurations.at(newPos))) {
- --newPos;
- }
- ++newPos;
-
- beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
- m_runConfigurations.insert(newPos, rc);
- m_runConfigurations.removeAt(oldPos + 1);
- endMoveRows();
- // Not only did we move, we also changed...
- emit dataChanged(index(newPos, 0), index(newPos,0));
- } else if (oldPos < m_runConfigurations.size() - 1
- && compare(m_runConfigurations.at(oldPos + 1), m_runConfigurations.at(oldPos))) {
- // We need to move down
- int newPos = oldPos + 1;
- while (newPos < m_runConfigurations.size()
- && compare(m_runConfigurations.at(newPos), m_runConfigurations.at(oldPos))) {
- ++newPos;
- }
- beginMoveRows(QModelIndex(), oldPos, oldPos, QModelIndex(), newPos);
- m_runConfigurations.insert(newPos, rc);
- m_runConfigurations.removeAt(oldPos);
- endMoveRows();
-
- // We need to subtract one since removing at the old place moves the newIndex down
- emit dataChanged(index(newPos - 1, 0), index(newPos - 1, 0));
- } else {
- emit dataChanged(index(oldPos, 0), index(oldPos, 0));
- }
-}
-
-QVariant RunConfigurationModel::data(const QModelIndex &index, int role) const
-{
- if (role == Qt::DisplayRole) {
- const int row = index.row();
- if (row < m_runConfigurations.size())
- return m_runConfigurations.at(row)->displayName();
- }
-
- return QVariant();
-}
-
-RunConfiguration *RunConfigurationModel::runConfigurationAt(int i)
-{
- if (i > m_runConfigurations.size() || i < 0)
- return nullptr;
- return m_runConfigurations.at(i);
-}
-
-RunConfiguration *RunConfigurationModel::runConfigurationFor(const QModelIndex &idx)
-{
- if (idx.row() > m_runConfigurations.size() || idx.row() < 0)
- return nullptr;
- return m_runConfigurations.at(idx.row());
-}
-
-QModelIndex RunConfigurationModel::indexFor(RunConfiguration *rc)
-{
- int idx = m_runConfigurations.indexOf(rc);
- if (idx == -1)
- return QModelIndex();
- return index(idx, 0);
-}
-
-void RunConfigurationModel::addedRunConfiguration(RunConfiguration *rc)
-{
- // Find the right place to insert
- RunConfigurationComparer compare;
- int i = 0;
- for (; i < m_runConfigurations.size(); ++i) {
- if (compare(rc, m_runConfigurations.at(i)))
- break;
- }
-
- beginInsertRows(QModelIndex(), i, i);
- m_runConfigurations.insert(i, rc);
- endInsertRows();
-
-
- connect(rc, &ProjectConfiguration::displayNameChanged,
- this, &RunConfigurationModel::displayNameChanged);
-}
-
-void RunConfigurationModel::removedRunConfiguration(RunConfiguration *rc)
-{
- int i = m_runConfigurations.indexOf(rc);
- if (i < 0)
- return;
-
- beginRemoveRows(QModelIndex(), i, i);
- m_runConfigurations.removeAt(i);
- endRemoveRows();
-}
diff --git a/src/plugins/projectexplorer/runnables.cpp b/src/plugins/projectexplorer/runnables.cpp
index 3ac15f53ef..33d612f0ad 100644
--- a/src/plugins/projectexplorer/runnables.cpp
+++ b/src/plugins/projectexplorer/runnables.cpp
@@ -46,6 +46,7 @@ QUrl urlFromLocalHostAndFreePort()
{
QUrl serverUrl;
QTcpServer server;
+ serverUrl.setScheme(urlTcpScheme());
if (server.listen(QHostAddress::LocalHost) || server.listen(QHostAddress::LocalHostIPv6)) {
serverUrl.setHost(server.serverAddress().toString());
serverUrl.setPort(server.serverPort());
@@ -68,4 +69,9 @@ QString urlSocketScheme()
return QString("socket");
}
+QString urlTcpScheme()
+{
+ return QString("tcp");
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runnables.h b/src/plugins/projectexplorer/runnables.h
index f28aefeda4..a893545d23 100644
--- a/src/plugins/projectexplorer/runnables.h
+++ b/src/plugins/projectexplorer/runnables.h
@@ -56,5 +56,6 @@ PROJECTEXPLORER_EXPORT bool operator==(const StandardRunnable &r1, const Standar
PROJECTEXPLORER_EXPORT QUrl urlFromLocalHostAndFreePort();
PROJECTEXPLORER_EXPORT QUrl urlFromLocalSocket();
PROJECTEXPLORER_EXPORT QString urlSocketScheme();
+PROJECTEXPLORER_EXPORT QString urlTcpScheme();
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
index 88fb230f05..7930a78336 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp
@@ -27,11 +27,10 @@
#include "buildstepspage.h"
#include "deployconfiguration.h"
-#include "deployconfigurationmodel.h"
-#include "runconfigurationmodel.h"
#include "runconfiguration.h"
#include "target.h"
#include "project.h"
+#include "projectconfigurationmodel.h"
#include "session.h"
#include <extensionsystem/pluginmanager.h>
@@ -39,6 +38,7 @@
#include <projectexplorer/buildmanager.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/utilsicons.h>
#include <QVariant>
#include <QAction>
@@ -184,6 +184,16 @@ RunSettingsWidget::RunSettingsWidget(Target *target) :
m_runLayout->setMargin(0);
m_runLayout->setSpacing(5);
+ m_disabledIcon = new QLabel;
+ m_disabledIcon->setPixmap(Utils::Icons::WARNING.pixmap());
+ m_disabledText = new QLabel;
+ auto disabledHBox = new QHBoxLayout;
+ disabledHBox->addWidget(m_disabledIcon);
+ disabledHBox->addWidget(m_disabledText);
+ disabledHBox->addStretch(255);
+
+ m_runLayout->addLayout(disabledHBox);
+
m_addRunMenu = new QMenu(m_addRunToolButton);
m_addRunToolButton->setMenu(m_addRunMenu);
RunConfiguration *rc = m_target->activeRunConfiguration();
@@ -303,7 +313,7 @@ void RunSettingsWidget::activeRunConfigurationChanged()
QModelIndex actRc = m_runConfigurationsModel->indexFor(m_target->activeRunConfiguration());
m_ignoreChange = true;
m_runConfigurationCombo->setCurrentIndex(actRc.row());
- setConfigurationWidget(m_runConfigurationsModel->runConfigurationAt(actRc.row()));
+ setConfigurationWidget(qobject_cast<RunConfiguration *>(m_runConfigurationsModel->projectConfigurationAt(actRc.row())));
m_ignoreChange = false;
m_renameRunButton->setEnabled(m_target->activeRunConfiguration());
}
@@ -333,7 +343,7 @@ void RunSettingsWidget::currentRunConfigurationChanged(int index)
RunConfiguration *selectedRunConfiguration = nullptr;
if (index >= 0)
- selectedRunConfiguration = m_runConfigurationsModel->runConfigurationAt(index);
+ selectedRunConfiguration = qobject_cast<RunConfiguration *>(m_runConfigurationsModel->projectConfigurationAt(index));
if (selectedRunConfiguration == m_runConfiguration)
return;
@@ -353,7 +363,8 @@ void RunSettingsWidget::currentDeployConfigurationChanged(int index)
if (index == -1)
SessionManager::setActiveDeployConfiguration(m_target, nullptr, SetActive::Cascade);
else
- SessionManager::setActiveDeployConfiguration(m_target, m_deployConfigurationModel->deployConfigurationAt(index),
+ SessionManager::setActiveDeployConfiguration(m_target,
+ qobject_cast<DeployConfiguration *>(m_deployConfigurationModel->projectConfigurationAt(index)),
SetActive::Cascade);
}
@@ -485,9 +496,12 @@ void RunSettingsWidget::setConfigurationWidget(RunConfiguration *rc)
return;
m_runConfigurationWidget = rc->createConfigurationWidget();
m_runConfiguration = rc;
- if (m_runConfigurationWidget)
+ if (m_runConfigurationWidget) {
m_runLayout->addWidget(m_runConfigurationWidget);
-
+ updateEnabledState();
+ connect(m_runConfiguration, &RunConfiguration::enabledChanged,
+ m_runConfigurationWidget, [this]() { updateEnabledState(); });
+ }
addRunControlWidgets();
}
@@ -561,3 +575,15 @@ void RunSettingsWidget::removeSubWidgets()
}
m_subWidgets.clear();
}
+
+void RunSettingsWidget::updateEnabledState()
+{
+ const bool enable = m_runConfiguration ? m_runConfiguration->isEnabled() : false;
+ const QString reason = m_runConfiguration ? m_runConfiguration->disabledReason() : QString();
+
+ m_runConfigurationWidget->setEnabled(enable);
+
+ m_disabledIcon->setVisible(!enable && !reason.isEmpty());
+ m_disabledText->setVisible(!enable && !reason.isEmpty());
+ m_disabledText->setText(reason);
+}
diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.h b/src/plugins/projectexplorer/runsettingspropertiespage.h
index 839a1e5688..5a551f9421 100644
--- a/src/plugins/projectexplorer/runsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/runsettingspropertiespage.h
@@ -80,6 +80,8 @@ private:
void addSubWidget(RunConfigWidget *subWidget);
void removeSubWidgets();
+ void updateEnabledState();
+
Target *m_target;
RunConfigurationModel *m_runConfigurationsModel;
DeployConfigurationModel *m_deployConfigurationModel;
@@ -105,6 +107,8 @@ private:
QPushButton *m_removeRunToolButton;
QPushButton *m_renameRunButton;
QPushButton *m_renameDeployButton;
+ QLabel *m_disabledIcon;
+ QLabel *m_disabledText;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index 432915f777..cc26b09013 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -30,6 +30,7 @@
#include "kit.h"
#include "buildconfiguration.h"
#include "deployconfiguration.h"
+#include "foldernavigationwidget.h"
#include "projectexplorer.h"
#include "projectnodes.h"
#include "editorconfiguration.h"
@@ -117,6 +118,13 @@ private:
static SessionManager *m_instance = nullptr;
static SessionManagerPrivate *d = nullptr;
+static QString projectFolderId(Project *pro)
+{
+ return pro->projectFilePath().toString();
+}
+
+const int PROJECT_SORT_VALUE = 100;
+
SessionManager::SessionManager(QObject *parent) : QObject(parent)
{
m_instance = this;
@@ -134,9 +142,9 @@ SessionManager::SessionManager(QObject *parent) : QObject(parent)
connect(this, &SessionManager::projectDisplayNameChanged,
EditorManager::instance(), &EditorManager::updateWindowTitles);
connect(EditorManager::instance(), &EditorManager::editorOpened,
- [this] { markSessionFileDirty(); });
+ this, [] { markSessionFileDirty(); });
connect(EditorManager::instance(), &EditorManager::editorsClosed,
- [this] { markSessionFileDirty(); });
+ this, [] { markSessionFileDirty(); });
EditorManager::setWindowTitleAdditionHandler(&SessionManagerPrivate::windowTitleAddition);
EditorManager::setSessionTitleHandler(&SessionManagerPrivate::sessionTitle);
@@ -385,8 +393,16 @@ void SessionManager::addProject(Project *pro)
m_instance, [pro]() { m_instance->projectDisplayNameChanged(pro); });
emit m_instance->projectAdded(pro);
+ const auto updateFolderNavigation = [pro] {
+ FolderNavigationWidgetFactory::insertRootDirectory({projectFolderId(pro),
+ PROJECT_SORT_VALUE,
+ pro->displayName(),
+ pro->projectFilePath().parentDir()});
+ };
+ updateFolderNavigation();
configureEditors(pro);
connect(pro, &Project::fileListChanged, [pro](){ configureEditors(pro); });
+ connect(pro, &Project::displayNameChanged, pro, updateFolderNavigation);
}
void SessionManager::removeProject(Project *project)
@@ -695,11 +711,11 @@ void SessionManager::configureEditors(Project *project)
}
}
-void SessionManager::removeProjects(QList<Project *> remove)
+void SessionManager::removeProjects(const QList<Project *> &remove)
{
QMap<QString, QStringList> resMap;
- foreach (Project *pro, remove)
+ for (Project *pro : remove)
emit m_instance->aboutToRemoveProject(pro);
// Refresh dependencies
@@ -722,30 +738,28 @@ void SessionManager::removeProjects(QList<Project *> remove)
}
d->m_depMap = resMap;
-
- // TODO: Clear m_modelProjectHash
+ bool changeStartupProject = false;
// Delete projects
- foreach (Project *pro, remove) {
+ for (Project *pro : remove) {
pro->saveSettings();
// Remove the project node:
d->m_projects.removeOne(pro);
if (pro == d->m_startupProject)
- setStartupProject(nullptr);
+ changeStartupProject = true;
disconnect(pro, &Project::fileListChanged,
m_instance, &SessionManager::clearProjectFileCache);
d->m_projectFileCache.remove(pro);
emit m_instance->projectRemoved(pro);
+ FolderNavigationWidgetFactory::removeRootDirectory(projectFolderId(pro));
delete pro;
}
- if (!startupProject()) {
- if (hasProjects())
- setStartupProject(projects().first());
- }
+ if (changeStartupProject)
+ setStartupProject(hasProjects() ? projects().first() : nullptr);
}
/*!
@@ -855,7 +869,7 @@ bool SessionManager::cloneSession(const QString &original, const QString &clone)
// If the file does not exist, we can still clone
if (!fi.exists() || fi.copy(sessionNameToFileName(clone).toString())) {
d->m_sessions.insert(1, clone);
- d->m_sessionDateTimes.insert(clone, QFileInfo(sessionNameToFileName(clone).toString()).lastModified());
+ d->m_sessionDateTimes.insert(clone, sessionNameToFileName(clone).toFileInfo().lastModified());
return true;
}
return false;
diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h
index a229ce58e1..864bd7c422 100644
--- a/src/plugins/projectexplorer/session.h
+++ b/src/plugins/projectexplorer/session.h
@@ -78,7 +78,7 @@ public:
static void addProject(Project *project);
static void removeProject(Project *project);
- static void removeProjects(QList<Project *> remove);
+ static void removeProjects(const QList<Project *> &remove);
static void setStartupProject(Project *startupProject);
diff --git a/src/plugins/projectexplorer/sessiondialog.ui b/src/plugins/projectexplorer/sessiondialog.ui
index fd41eeacec..21f2195a5c 100644
--- a/src/plugins/projectexplorer/sessiondialog.ui
+++ b/src/plugins/projectexplorer/sessiondialog.ui
@@ -87,9 +87,6 @@
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="autoLoadCheckBox">
- <property name="toolTip">
- <string>Automatically restores the last session when Qt Creator is started.</string>
- </property>
<property name="text">
<string>Restore last session on startup</string>
</property>
diff --git a/src/plugins/projectexplorer/settingsaccessor.cpp b/src/plugins/projectexplorer/settingsaccessor.cpp
index 49b24103f5..6b413d702c 100644
--- a/src/plugins/projectexplorer/settingsaccessor.cpp
+++ b/src/plugins/projectexplorer/settingsaccessor.cpp
@@ -35,6 +35,7 @@
#include "kit.h"
#include "kitmanager.h"
+#include <app/app_version.h>
#include <coreplugin/icore.h>
#include <utils/persistentsettings.h>
#include <utils/hostosinfo.h>
@@ -837,11 +838,12 @@ SettingsAccessor::IssueInfo SettingsAccessor::findIssues(const QVariantMap &data
result.message = QApplication::translate("Utils::SettingsAccessor",
"<p>The versioned backup \"%1\" of the settings "
"file is used, because the non-versioned file was "
- "created by an incompatible version of Qt Creator.</p>"
+ "created by an incompatible version of %2.</p>"
"<p>Settings changes made since the last time this "
- "version of Qt Creator was used are ignored, and "
+ "version of %2 was used are ignored, and "
"changes made now will <b>not</b> be propagated to "
- "the newer version.</p>").arg(path.toUserOutput());
+ "the newer version.</p>").arg(path.toUserOutput())
+ .arg(Core::Constants::IDE_DISPLAY_NAME);
result.buttons.insert(QMessageBox::Ok, Continue);
}
@@ -853,10 +855,11 @@ SettingsAccessor::IssueInfo SettingsAccessor::findIssues(const QVariantMap &data
result.title = differentEnvironmentMsg(project()->displayName());
result.message = QApplication::translate("ProjectExplorer::EnvironmentIdAccessor",
"<p>No .user settings file created by this instance "
- "of Qt Creator was found.</p>"
+ "of %1 was found.</p>"
"<p>Did you work with this project on another machine or "
"using a different settings path before?</p>"
- "<p>Do you still want to load the settings file \"%1\"?</p>")
+ "<p>Do you still want to load the settings file \"%2\"?</p>")
+ .arg(Core::Constants::IDE_DISPLAY_NAME)
.arg(path.toUserOutput());
result.defaultButton = QMessageBox::No;
result.escapeButton = QMessageBox::No;
@@ -1093,8 +1096,9 @@ QVariantMap SettingsAccessor::readSharedSettings(QWidget *parent) const
"Unsupported Shared Settings File"),
QApplication::translate("ProjectExplorer::SettingsAccessor",
"The version of your .shared file is not "
- "supported by Qt Creator. "
- "Do you want to try loading it anyway?"),
+ "supported by %1. "
+ "Do you want to try loading it anyway?")
+ .arg(Core::Constants::IDE_DISPLAY_NAME),
QMessageBox::Yes | QMessageBox::No,
parent);
msgBox.setDefaultButton(QMessageBox::No);
diff --git a/src/plugins/projectexplorer/subscription.cpp b/src/plugins/projectexplorer/subscription.cpp
new file mode 100644
index 0000000000..b878bdacdc
--- /dev/null
+++ b/src/plugins/projectexplorer/subscription.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "subscription.h"
+
+#include "project.h"
+#include "projectconfiguration.h"
+#include "target.h"
+
+#include <utils/asconst.h>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+Subscription::Subscription(const Subscription::Connector &s, const QObject *receiver, QObject *parent) :
+ QObject(parent), m_subscriber(s)
+{
+ if (receiver != parent)
+ connect(receiver, &QObject::destroyed, this, &QObject::deleteLater);
+}
+
+Subscription::~Subscription()
+{
+ for (const auto &c : Utils::asConst(m_connections))
+ disconnect(c);
+}
+
+void Subscription::subscribe(ProjectConfiguration *pc)
+{
+ if (!m_subscriber)
+ return;
+ QMetaObject::Connection conn = m_subscriber(pc);
+ if (conn)
+ m_connections.insert(pc, conn);
+
+ if (auto p = qobject_cast<Project *>(pc)) {
+ for (Target *t : p->targets()) {
+ for (ProjectConfiguration *pc : t->projectConfigurations())
+ m_subscriber(pc);
+ }
+ } else if (auto t = qobject_cast<Target *>(pc)) {
+ for (ProjectConfiguration *pc : t->projectConfigurations())
+ m_subscriber(pc);
+ }
+}
+
+void Subscription::unsubscribe(ProjectConfiguration *pc)
+{
+ auto c = m_connections.value(pc);
+ if (c) {
+ disconnect(c);
+ m_connections.remove(pc);
+ }
+ if (auto p = qobject_cast<Project *>(pc)) {
+ for (Target *t : p->targets()) {
+ for (ProjectConfiguration *pc : t->projectConfigurations())
+ unsubscribe(pc);
+ }
+ } else if (auto t = qobject_cast<Target *>(pc)) {
+ for (ProjectConfiguration *pc : t->projectConfigurations())
+ unsubscribe(pc);
+ }
+
+}
+
+ProjectSubscription::ProjectSubscription(const Subscription::Connector &s, const QObject *r,
+ Project *p) :
+ Subscription(s, r, p)
+{
+ if (m_subscriber) {
+ for (const Target *t : p->targets()) {
+ for (ProjectConfiguration *pc : t->projectConfigurations())
+ m_subscriber(pc);
+ }
+ connect(p, &Project::addedProjectConfiguration, this, &ProjectSubscription::subscribe);
+ connect(p, &Project::removedProjectConfiguration, this, &ProjectSubscription::unsubscribe);
+ }
+}
+
+ProjectSubscription::~ProjectSubscription() = default;
+
+TargetSubscription::TargetSubscription(const Subscription::Connector &s, const QObject *r,
+ Target *t) :
+ Subscription(s, r, t)
+{
+ for (ProjectConfiguration *pc : t->projectConfigurations())
+ m_subscriber(pc);
+ connect(t, &Target::addedProjectConfiguration, this, &TargetSubscription::subscribe);
+ connect(t, &Target::removedProjectConfiguration, this, &TargetSubscription::unsubscribe);
+}
+
+TargetSubscription::~TargetSubscription() = default;
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/deployconfigurationmodel.h b/src/plugins/projectexplorer/subscription.h
index 95b6092898..5c1e0ec1a4 100644
--- a/src/plugins/projectexplorer/deployconfigurationmodel.h
+++ b/src/plugins/projectexplorer/subscription.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -25,35 +25,51 @@
#pragma once
-#include <QAbstractItemModel>
+#include "projectexplorer_export.h"
+
+#include <QHash>
+#include <QObject>
+
+#include <functional>
namespace ProjectExplorer {
+class Project;
+class ProjectConfiguration;
class Target;
-class DeployConfiguration;
-// Documentation inside.
-class DeployConfigurationModel : public QAbstractListModel
+namespace Internal {
+
+class PROJECTEXPLORER_EXPORT Subscription : public QObject
{
Q_OBJECT
public:
- explicit DeployConfigurationModel(Target *target, QObject *parent = nullptr);
+ using Connector = std::function<QMetaObject::Connection(ProjectConfiguration *)>;
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ Subscription(const Connector &s, const QObject *receiver, QObject *parent);
+ ~Subscription() override;
- DeployConfiguration *deployConfigurationAt(int i);
- DeployConfiguration *deployConfigurationFor(const QModelIndex &idx);
- QModelIndex indexFor(DeployConfiguration *rc);
+protected:
+ void subscribe(ProjectConfiguration *pc);
+ void unsubscribe(ProjectConfiguration *pc);
+
+ Connector m_subscriber;
+ QHash<ProjectConfiguration *, QMetaObject::Connection> m_connections;
+};
-private:
- void addedDeployConfiguration(ProjectExplorer::DeployConfiguration*);
- void removedDeployConfiguration(ProjectExplorer::DeployConfiguration*);
- void displayNameChanged();
+class PROJECTEXPLORER_EXPORT ProjectSubscription : public Subscription
+{
+public:
+ ProjectSubscription(const Connector &s, const QObject *receiver, Project *p);
+ ~ProjectSubscription() final;
+};
- Target *m_target;
- QList<DeployConfiguration *> m_deployConfigurations;
+class PROJECTEXPLORER_EXPORT TargetSubscription : public Subscription
+{
+public:
+ TargetSubscription(const Connector &s, const QObject *receiver, Target *t);
+ ~TargetSubscription() final;
};
+} // namespace Internal
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index 3b480e8266..221a8d55a2 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -115,9 +115,10 @@ QList<DeployConfigurationFactory *> TargetPrivate::deployFactories() const
}
Target::Target(Project *project, Kit *k) :
- ProjectConfiguration(project, k->id()),
+ ProjectConfiguration(project),
d(new TargetPrivate(k))
{
+ initialize(k->id());
QTC_CHECK(d->m_kit);
connect(DeviceManager::instance(), &DeviceManager::updated, this, &Target::updateDeviceState);
@@ -153,41 +154,6 @@ Target::~Target()
delete d;
}
-void Target::changeEnvironment()
-{
- auto bc = qobject_cast<BuildConfiguration *>(sender());
- if (bc == activeBuildConfiguration())
- emit environmentChanged();
-}
-
-void Target::changeBuildConfigurationEnabled()
-{
- auto bc = qobject_cast<BuildConfiguration *>(sender());
- if (bc == activeBuildConfiguration())
- emit buildConfigurationEnabledChanged();
-}
-
-void Target::changeDeployConfigurationEnabled()
-{
- auto dc = qobject_cast<DeployConfiguration *>(sender());
- if (dc == activeDeployConfiguration())
- emit deployConfigurationEnabledChanged();
-}
-
-void Target::changeRunConfigurationEnabled()
-{
- auto rc = qobject_cast<RunConfiguration *>(sender());
- if (rc == activeRunConfiguration())
- emit runConfigurationEnabledChanged();
-}
-
-void Target::onBuildDirectoryChanged()
-{
- auto bc = qobject_cast<BuildConfiguration *>(sender());
- if (bc && activeBuildConfiguration() == bc)
- emit buildDirectoryChanged();
-}
-
void Target::handleKitUpdates(Kit *k)
{
if (k != d->m_kit)
@@ -209,6 +175,11 @@ void Target::handleKitRemoval(Kit *k)
project()->removeTarget(this);
}
+bool Target::isActive() const
+{
+ return project()->activeTarget() == this;
+}
+
Project *Target::project() const
{
return static_cast<Project *>(parent());
@@ -238,15 +209,9 @@ void Target::addBuildConfiguration(BuildConfiguration *bc)
// add it
d->m_buildConfigurations.push_back(bc);
+ emit addedProjectConfiguration(bc);
emit addedBuildConfiguration(bc);
- connect(bc, &BuildConfiguration::environmentChanged,
- this, &Target::changeEnvironment);
- connect(bc, &BuildConfiguration::enabledChanged,
- this, &Target::changeBuildConfigurationEnabled);
- connect(bc, &BuildConfiguration::buildDirectoryChanged,
- this, &Target::onBuildDirectoryChanged);
-
if (!activeBuildConfiguration())
setActiveBuildConfiguration(bc);
}
@@ -261,8 +226,9 @@ bool Target::removeBuildConfiguration(BuildConfiguration *bc)
return false;
d->m_buildConfigurations.removeOne(bc);
+ emit aboutToRemoveProjectConfiguration(bc);
+ d->m_buildConfigurations.removeOne(bc);
- emit removedBuildConfiguration(bc);
if (activeBuildConfiguration() == bc) {
if (d->m_buildConfigurations.isEmpty())
@@ -271,6 +237,9 @@ bool Target::removeBuildConfiguration(BuildConfiguration *bc)
SessionManager::setActiveBuildConfiguration(this, d->m_buildConfigurations.at(0), SetActive::Cascade);
}
+ emit removedBuildConfiguration(bc);
+ emit removedProjectConfiguration(bc);
+
delete bc;
return true;
}
@@ -285,16 +254,14 @@ BuildConfiguration *Target::activeBuildConfiguration() const
return d->m_activeBuildConfiguration;
}
-void Target::setActiveBuildConfiguration(BuildConfiguration *configuration)
+void Target::setActiveBuildConfiguration(BuildConfiguration *bc)
{
- if ((!configuration && d->m_buildConfigurations.isEmpty()) ||
- (configuration && d->m_buildConfigurations.contains(configuration) &&
- configuration != d->m_activeBuildConfiguration)) {
- d->m_activeBuildConfiguration = configuration;
+ if ((!bc && d->m_buildConfigurations.isEmpty()) ||
+ (bc && d->m_buildConfigurations.contains(bc) &&
+ bc != d->m_activeBuildConfiguration)) {
+ d->m_activeBuildConfiguration = bc;
+ emit activeProjectConfigurationChanged(d->m_activeBuildConfiguration);
emit activeBuildConfigurationChanged(d->m_activeBuildConfiguration);
- emit environmentChanged();
- emit buildConfigurationEnabledChanged();
- emit buildDirectoryChanged();
}
}
@@ -315,9 +282,7 @@ void Target::addDeployConfiguration(DeployConfiguration *dc)
// add it
d->m_deployConfigurations.push_back(dc);
- connect(dc, &DeployConfiguration::enabledChanged,
- this, &Target::changeDeployConfigurationEnabled);
-
+ emit addedProjectConfiguration(dc);
emit addedDeployConfiguration(dc);
if (!d->m_activeDeployConfiguration)
@@ -334,10 +299,9 @@ bool Target::removeDeployConfiguration(DeployConfiguration *dc)
if (BuildManager::isBuilding(dc))
return false;
+ emit aboutToRemoveProjectConfiguration(dc);
d->m_deployConfigurations.removeOne(dc);
- emit removedDeployConfiguration(dc);
-
if (activeDeployConfiguration() == dc) {
if (d->m_deployConfigurations.isEmpty())
SessionManager::setActiveDeployConfiguration(this, nullptr, SetActive::Cascade);
@@ -346,6 +310,9 @@ bool Target::removeDeployConfiguration(DeployConfiguration *dc)
SetActive::Cascade);
}
+ emit removedProjectConfiguration(dc);
+ emit removedDeployConfiguration(dc);
+
delete dc;
return true;
}
@@ -366,8 +333,8 @@ void Target::setActiveDeployConfiguration(DeployConfiguration *dc)
(dc && d->m_deployConfigurations.contains(dc) &&
dc != d->m_activeDeployConfiguration)) {
d->m_activeDeployConfiguration = dc;
+ emit activeProjectConfigurationChanged(d->m_activeDeployConfiguration);
emit activeDeployConfigurationChanged(d->m_activeDeployConfiguration);
- emit deployConfigurationEnabledChanged();
}
updateDeviceState();
}
@@ -398,6 +365,15 @@ BuildTargetInfoList Target::applicationTargets() const
return d->m_appTargets;
}
+QList<ProjectConfiguration *> Target::projectConfigurations() const
+{
+ QList<ProjectConfiguration *> result;
+ result.append(Utils::transform(buildConfigurations(), [](BuildConfiguration *bc) { return qobject_cast<ProjectConfiguration *>(bc); }));
+ result.append(Utils::transform(deployConfigurations(), [](DeployConfiguration *dc) { return qobject_cast<ProjectConfiguration *>(dc); }));
+ result.append(Utils::transform(runConfigurations(), [](RunConfiguration *rc) { return qobject_cast<ProjectConfiguration *>(rc); }));
+ return result;
+}
+
QList<RunConfiguration *> Target::runConfigurations() const
{
return d->m_runConfigurations;
@@ -416,9 +392,7 @@ void Target::addRunConfiguration(RunConfiguration *rc)
d->m_runConfigurations.push_back(rc);
- connect(rc, &RunConfiguration::enabledChanged,
- this, &Target::changeRunConfigurationEnabled);
-
+ emit addedProjectConfiguration(rc);
emit addedRunConfiguration(rc);
if (!activeRunConfiguration())
@@ -429,6 +403,7 @@ void Target::removeRunConfiguration(RunConfiguration *rc)
{
QTC_ASSERT(rc && d->m_runConfigurations.contains(rc), return);
+ emit aboutToRemoveProjectConfiguration(rc);
d->m_runConfigurations.removeOne(rc);
if (activeRunConfiguration() == rc) {
@@ -439,6 +414,8 @@ void Target::removeRunConfiguration(RunConfiguration *rc)
}
emit removedRunConfiguration(rc);
+ emit removedProjectConfiguration(rc);
+
delete rc;
}
@@ -453,8 +430,8 @@ void Target::setActiveRunConfiguration(RunConfiguration *rc)
(rc && d->m_runConfigurations.contains(rc) &&
rc != d->m_activeRunConfiguration)) {
d->m_activeRunConfiguration = rc;
+ emit activeProjectConfigurationChanged(d->m_activeRunConfiguration);
emit activeRunConfigurationChanged(d->m_activeRunConfiguration);
- emit runConfigurationEnabledChanged();
}
updateDeviceState();
}
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index 61f3ed5615..f3ed83ebf3 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -28,6 +28,8 @@
#include "projectconfiguration.h"
#include "projectexplorer_export.h"
+#include "subscription.h"
+
QT_FORWARD_DECLARE_CLASS(QIcon)
namespace Utils { class Environment; }
@@ -55,14 +57,16 @@ class PROJECTEXPLORER_EXPORT Target : public ProjectConfiguration
public:
~Target() override;
- Project *project() const;
+ Project *project() const override;
+
+ bool isActive() const final;
// Kit:
Kit *kit() const;
// Build configuration
- void addBuildConfiguration(BuildConfiguration *configuration);
- bool removeBuildConfiguration(BuildConfiguration *configuration);
+ void addBuildConfiguration(BuildConfiguration *bc);
+ bool removeBuildConfiguration(BuildConfiguration *bc);
QList<BuildConfiguration *> buildConfigurations() const;
BuildConfiguration *activeBuildConfiguration() const;
@@ -80,13 +84,15 @@ public:
void setApplicationTargets(const BuildTargetInfoList &appTargets);
BuildTargetInfoList applicationTargets() const;
+ QList<ProjectConfiguration *> projectConfigurations() const;
+
// Running
QList<RunConfiguration *> runConfigurations() const;
- void addRunConfiguration(RunConfiguration *runConfiguration);
- void removeRunConfiguration(RunConfiguration *runConfiguration);
+ void addRunConfiguration(RunConfiguration *rc);
+ void removeRunConfiguration(RunConfiguration *rc);
RunConfiguration *activeRunConfiguration() const;
- void setActiveRunConfiguration(RunConfiguration *runConfiguration);
+ void setActiveRunConfiguration(RunConfiguration *rc);
// Returns whether this target is actually available at he time
// of the call. A target may become unavailable e.g. when a Qt version
@@ -108,6 +114,25 @@ public:
QVariant namedSettings(const QString &name) const;
void setNamedSettings(const QString &name, const QVariant &value);
+
+ template<typename S, typename R, typename T>
+ void subscribeSignal(void (S::*sig)(), R*recv, T (R::*sl)()) {
+ new Internal::TargetSubscription([sig, recv, sl, this](ProjectConfiguration *pc) {
+ if (S* sender = qobject_cast<S*>(pc))
+ return connect(sender, sig, recv, sl);
+ return QMetaObject::Connection();
+ }, recv, this);
+ }
+
+ template<typename S, typename R, typename T>
+ void subscribeSignal(void (S::*sig)(), R*recv, T sl) {
+ new Internal::TargetSubscription([sig, recv, sl, this](ProjectConfiguration *pc) {
+ if (S* sender = qobject_cast<S*>(pc))
+ return connect(sender, sig, recv, sl);
+ return QMetaObject::Connection();
+ }, recv, this);
+ }
+
signals:
void targetEnabled(bool);
void iconChanged();
@@ -115,6 +140,12 @@ signals:
void kitChanged();
+ void aboutToRemoveProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
+ void removedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
+ void addedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
+
+ void activeProjectConfigurationChanged(ProjectExplorer::ProjectConfiguration *pc);
+
// TODO clean up signal names
// might be better to also have aboutToRemove signals
void removedRunConfiguration(ProjectExplorer::RunConfiguration *rc);
@@ -129,24 +160,9 @@ signals:
void addedDeployConfiguration(ProjectExplorer::DeployConfiguration *dc);
void activeDeployConfigurationChanged(ProjectExplorer::DeployConfiguration *dc);
- /// convenience signal, emitted if either the active buildconfiguration emits
- /// environmentChanged() or if the active build configuration changes
- void environmentChanged();
-
- /// convenience signal, emitted if either the active configuration emits
- /// enabledChanged() or if the active build configuration changes
- void buildConfigurationEnabledChanged();
- void deployConfigurationEnabledChanged();
- void runConfigurationEnabledChanged();
-
void deploymentDataChanged();
void applicationTargetsChanged();
- // Remove all the signals below, they are stupid
- /// Emitted whenever the current build configuartion changed or the build directory of the current
- /// build configuration was changed.
- void buildDirectoryChanged();
-
private:
Target(Project *parent, Kit *k);
void setEnabled(bool);
@@ -154,10 +170,7 @@ private:
bool fromMap(const QVariantMap &map) override;
void updateDeviceState();
- void onBuildDirectoryChanged();
- void changeEnvironment();
- void changeBuildConfigurationEnabled();
void changeDeployConfigurationEnabled();
void changeRunConfigurationEnabled();
void handleKitUpdates(ProjectExplorer::Kit *k);
diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp
index de40db6c66..955cedc956 100644
--- a/src/plugins/projectexplorer/targetsettingspanel.cpp
+++ b/src/plugins/projectexplorer/targetsettingspanel.cpp
@@ -41,6 +41,8 @@
#include "target.h"
#include "targetsetuppage.h"
+#include <app/app_version.h>
+
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/modemanager.h>
@@ -171,20 +173,22 @@ void TargetSetupPageWrapper::updateNoteText()
bool showHint = false;
if (!k) {
text = tr("The project <b>%1</b> is not yet configured.<br/>"
- "Qt Creator cannot parse the project, because no kit "
+ "%2 cannot parse the project, because no kit "
"has been set up.")
- .arg(m_project->displayName());
+ .arg(m_project->displayName(), Core::Constants::IDE_DISPLAY_NAME);
showHint = true;
} else if (k->isValid()) {
text = tr("The project <b>%1</b> is not yet configured.<br/>"
- "Qt Creator uses the kit <b>%2</b> to parse the project.")
+ "%2 uses the kit <b>%3</b> to parse the project.")
.arg(m_project->displayName())
+ .arg(Core::Constants::IDE_DISPLAY_NAME)
.arg(k->displayName());
showHint = false;
} else {
text = tr("The project <b>%1</b> is not yet configured.<br/>"
- "Qt Creator uses the <b>invalid</b> kit <b>%2</b> to parse the project.")
+ "%2 uses the <b>invalid</b> kit <b>%3</b> to parse the project.")
.arg(m_project->displayName())
+ .arg(Core::Constants::IDE_DISPLAY_NAME)
.arg(k->displayName());
showHint = true;
}
@@ -419,7 +423,7 @@ public:
QAction *disableAction = menu->addAction(tr("Disable Kit \"%1\" for Project \"%2\"").arg(kitName, projectName));
disableAction->setEnabled(m_kitId.isValid() && isEnabled());
- QObject::connect(disableAction, &QAction::triggered, [this, kit] {
+ QObject::connect(disableAction, &QAction::triggered, m_project, [this] {
Target *t = target();
QTC_ASSERT(t, return);
QString kitName = t->displayName();
@@ -763,7 +767,7 @@ TargetItem *TargetGroupItem::targetItem(Target *target) const
{
if (target) {
Id needle = target->id(); // Unconfigured project have no active target.
- return findFirstLevelChild([this, needle](TargetItem *item) { return item->m_kitId == needle; });
+ return findFirstLevelChild([needle](TargetItem *item) { return item->m_kitId == needle; });
}
return 0;
}
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
index 0944b8f5b1..c84beaf226 100644
--- a/src/plugins/projectexplorer/targetsetuppage.cpp
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -285,7 +285,7 @@ void TargetSetupPage::setProjectPath(const QString &path)
if (!m_projectPath.isEmpty()) {
QFileInfo fileInfo(QDir::cleanPath(path));
QStringList subDirsList = fileInfo.absolutePath().split('/');
- m_ui->headerLabel->setText(tr("Qt Creator can use the following kits for project <b>%1</b>:",
+ m_ui->headerLabel->setText(tr("The following kits can be used for project <b>%1</b>:",
"%1: Project name").arg(subDirsList.last()));
}
m_ui->headerLabel->setVisible(!m_projectPath.isEmpty());
diff --git a/src/plugins/projectexplorer/task.cpp b/src/plugins/projectexplorer/task.cpp
index 9d6f4a3316..0b34cec14c 100644
--- a/src/plugins/projectexplorer/task.cpp
+++ b/src/plugins/projectexplorer/task.cpp
@@ -25,6 +25,7 @@
#include "task.h"
+#include <app/app_version.h>
#include <texteditor/textmark.h>
#include <utils/utilsicons.h>
#include <utils/qtcassert.h>
@@ -68,8 +69,9 @@ Task Task::compilerMissingTask()
{
return Task(Task::Error,
QCoreApplication::translate("ProjectExplorer::Task",
- "Qt Creator needs a compiler set up to build. "
- "Configure a compiler in the kit options."),
+ "%1 needs a compiler set up to build. "
+ "Configure a compiler in the kit options.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME),
Utils::FileName(), -1,
Constants::TASK_CATEGORY_BUILDSYSTEM);
}
@@ -78,8 +80,9 @@ Task Task::buildConfigurationMissingTask()
{
return Task(Task::Error,
QCoreApplication::translate("ProjectExplorer::Task",
- "Qt Creator needs a build configuration set up to build. "
- "Configure a build configuration in the project settings."),
+ "%1 needs a build configuration set up to build. "
+ "Configure a build configuration in the project settings.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME),
Utils::FileName(), -1,
Constants::TASK_CATEGORY_BUILDSYSTEM);
}
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index 8c461bd398..4ee56f05a8 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -27,6 +27,7 @@
#include "projectexplorer_export.h"
#include "projectexplorer_global.h"
+#include "projectmacro.h"
#include <coreplugin/id.h>
@@ -122,9 +123,9 @@ public:
virtual WarningFlags warningFlags(const QStringList &cflags) const = 0;
// A PredefinedMacrosRunner is created in the ui thread and runs in another thread.
- using PredefinedMacrosRunner = std::function<QByteArray(const QStringList &cxxflags)>;
+ using PredefinedMacrosRunner = std::function<Macros(const QStringList &cxxflags)>;
virtual PredefinedMacrosRunner createPredefinedMacrosRunner() const = 0;
- virtual QByteArray predefinedMacros(const QStringList &cxxflags) const = 0;
+ virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0;
// A SystemHeaderPathsRunner is created in the ui thread and runs in another thread.
using SystemHeaderPathsRunner = std::function<QList<HeaderPath>(const QStringList &cxxflags, const QString &sysRoot)>;
diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp
index df7d6888ec..b6c79b8773 100644
--- a/src/plugins/projectexplorer/toolchainmanager.cpp
+++ b/src/plugins/projectexplorer/toolchainmanager.cpp
@@ -492,7 +492,7 @@ public:
Abi targetAbi() const override { return Abi::hostAbi(); }
bool isValid() const override { return m_valid; }
PredefinedMacrosRunner createPredefinedMacrosRunner() const override { return PredefinedMacrosRunner(); }
- QByteArray predefinedMacros(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return QByteArray(); }
+ Macros predefinedMacros(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return Macros(); }
CompilerFlags compilerFlags(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return NoFlags; }
WarningFlags warningFlags(const QStringList &cflags) const override { Q_UNUSED(cflags); return WarningFlags::NoWarnings; }
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override { return SystemHeaderPathsRunner(); }
diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp
index bb90706784..30fb0dcbb2 100644
--- a/src/plugins/pythoneditor/pythoneditorplugin.cpp
+++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp
@@ -151,13 +151,11 @@ class PythonRunConfiguration : public RunConfiguration
Q_PROPERTY(QString arguments READ arguments)
public:
- PythonRunConfiguration(Target *parent, Core::Id id);
+ explicit PythonRunConfiguration(Target *target);
QWidget *createConfigurationWidget() override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &map) override;
- bool isEnabled() const override { return m_enabled; }
- QString disabledReason() const override;
Runnable runnable() const override;
bool supportsDebugger() const { return true; }
@@ -165,42 +163,45 @@ public:
QString arguments() const;
QString interpreter() const { return m_interpreter; }
void setInterpreter(const QString &interpreter) { m_interpreter = interpreter; }
- void setEnabled(bool b);
private:
- friend class PythonRunConfigurationFactory;
- PythonRunConfiguration(Target *parent, PythonRunConfiguration *source);
+ friend class ProjectExplorer::IRunConfigurationFactory;
+ void initialize(Core::Id id);
+ void copyFrom(const PythonRunConfiguration *source);
+
QString defaultDisplayName() const;
QString m_interpreter;
QString m_mainScript;
- bool m_enabled;
};
////////////////////////////////////////////////////////////////
-PythonRunConfiguration::PythonRunConfiguration(Target *parent, Core::Id id) :
- RunConfiguration(parent, id),
- m_mainScript(scriptFromId(id)),
- m_enabled(true)
+PythonRunConfiguration::PythonRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
- Environment sysEnv = Environment::systemEnvironment();
- const QString exec = sysEnv.searchInPath("python").toString();
- m_interpreter = exec.isEmpty() ? "python" : exec;
-
addExtraAspect(new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()));
addExtraAspect(new ArgumentsAspect(this, "PythonEditor.RunConfiguration.Arguments"));
addExtraAspect(new TerminalAspect(this, "PythonEditor.RunConfiguration.UseTerminal"));
setDefaultDisplayName(defaultDisplayName());
}
-PythonRunConfiguration::PythonRunConfiguration(Target *parent, PythonRunConfiguration *source) :
- RunConfiguration(parent, source),
- m_interpreter(source->interpreter()),
- m_mainScript(source->m_mainScript),
- m_enabled(source->m_enabled)
+void PythonRunConfiguration::initialize(Core::Id id)
{
- setDefaultDisplayName(defaultDisplayName());
+ RunConfiguration::initialize(id);
+
+ m_mainScript = scriptFromId(id);
+
+ Environment sysEnv = Environment::systemEnvironment();
+ const QString exec = sysEnv.searchInPath("python").toString();
+ m_interpreter = exec.isEmpty() ? "python" : exec;
+}
+
+void PythonRunConfiguration::copyFrom(const PythonRunConfiguration *source)
+{
+ RunConfiguration::copyFrom(source);
+ m_interpreter = source->interpreter();
+ m_mainScript = source->m_mainScript;
}
QVariantMap PythonRunConfiguration::toMap() const
@@ -220,10 +221,7 @@ bool PythonRunConfiguration::fromMap(const QVariantMap &map)
QString PythonRunConfiguration::defaultDisplayName() const
{
- QString result = tr("Run %1").arg(m_mainScript);
- if (!m_enabled)
- result += ' ' + tr("(disabled)");
- return result;
+ return tr("Run %1").arg(m_mainScript);
}
QWidget *PythonRunConfiguration::createConfigurationWidget()
@@ -231,22 +229,6 @@ QWidget *PythonRunConfiguration::createConfigurationWidget()
return new PythonRunConfigurationWidget(this);
}
-void PythonRunConfiguration::setEnabled(bool b)
-{
- if (m_enabled == b)
- return;
- m_enabled = b;
- emit enabledChanged();
- setDefaultDisplayName(defaultDisplayName());
-}
-
-QString PythonRunConfiguration::disabledReason() const
-{
- if (!m_enabled)
- return tr("The script is currently disabled.");
- return QString();
-}
-
Runnable PythonRunConfiguration::runnable() const
{
StandardRunnable r;
@@ -295,8 +277,6 @@ PythonRunConfigurationWidget::PythonRunConfigurationWidget(PythonRunConfiguratio
auto vbx = new QVBoxLayout(this);
vbx->setMargin(0);
vbx->addWidget(m_detailsContainer);
-
- setEnabled(runConfiguration->isEnabled());
}
class PythonRunConfigurationFactory : public IRunConfigurationFactory
@@ -351,7 +331,7 @@ public:
{
if (!canClone(parent, source))
return 0;
- return new PythonRunConfiguration(parent, static_cast<PythonRunConfiguration*>(source));
+ return cloneHelper<PythonRunConfiguration>(parent, source);
}
private:
@@ -359,13 +339,12 @@ private:
RunConfiguration *doCreate(Target *parent, Core::Id id) override
{
- return new PythonRunConfiguration(parent, id);
+ return createHelper<PythonRunConfiguration>(parent, id);
}
RunConfiguration *doRestore(Target *parent, const QVariantMap &map) override
{
- Core::Id id(idFromMap(map));
- return new PythonRunConfiguration(parent, id);
+ return createHelper<PythonRunConfiguration>(parent, idFromMap(map));
}
};
@@ -507,6 +486,7 @@ private:
void PythonProject::refresh()
{
+ emitParsingStarted();
parseProject();
QDir baseDir(projectDirectory().toString());
@@ -517,7 +497,7 @@ void PythonProject::refresh()
}
setRootProjectNode(newRoot);
- emit parsingFinished();
+ emitParsingFinished(true);
}
/**
@@ -601,7 +581,7 @@ Project::RestoreResult PythonProject::fromMap(const QVariantMap &map, QString *e
}
}
if (!alreadyPresent)
- t->addRunConfiguration(new PythonRunConfiguration(t, id));
+ t->addRunConfiguration(IRunConfigurationFactory::createHelper<PythonRunConfiguration>(t, id));
}
}
}
diff --git a/src/plugins/pythoneditor/pythonhighlighter.cpp b/src/plugins/pythoneditor/pythonhighlighter.cpp
index 389beee4b8..b485c2a450 100644
--- a/src/plugins/pythoneditor/pythonhighlighter.cpp
+++ b/src/plugins/pythoneditor/pythonhighlighter.cpp
@@ -37,6 +37,7 @@
#include "pythonscanner.h"
#include <texteditor/textdocument.h>
+#include <texteditor/textdocumentlayout.h>
#include <texteditor/texteditorconstants.h>
#include <utils/qtcassert.h>
@@ -116,6 +117,24 @@ static bool isImportKeyword(const QString &keyword)
return keyword == "import" || keyword == "from";
}
+static int indent(const QString &line)
+{
+ for (int i = 0, size = line.size(); i < size; ++i) {
+ if (!line.at(i).isSpace())
+ return i;
+ }
+ return -1;
+}
+
+static void setFoldingIndent(const QTextBlock &block, int indent)
+{
+ if (TextEditor::TextBlockUserData *userData = TextEditor::TextDocumentLayout::userData(block)) {
+ userData->setFoldingIndent(indent);
+ userData->setFoldingStartIncluded(false);
+ userData->setFoldingEndIncluded(false);
+ }
+}
+
/**
* @brief Highlight line of code, returns new block state
* @param text Source code to highlight
@@ -127,6 +146,23 @@ int PythonHighlighter::highlightLine(const QString &text, int initialState)
Scanner scanner(text.constData(), text.size());
scanner.setState(initialState);
+ const int pos = indent(text);
+ if (pos < 0) {
+ // Empty lines do not change folding indent
+ setFoldingIndent(currentBlock(), m_lastIndent);
+ } else {
+ m_lastIndent = pos;
+ if (pos == 0 && text.startsWith('#') && !text.startsWith("#!")) {
+ // A comment block at indentation 0. Fold on first line.
+ setFoldingIndent(currentBlock(), withinLicenseHeader ? 1 : 0);
+ withinLicenseHeader = true;
+ } else {
+ // Normal Python code. Line indentation can be used as folding indent.
+ setFoldingIndent(currentBlock(), m_lastIndent);
+ withinLicenseHeader = false;
+ }
+ }
+
FormatToken tk;
bool hasOnlyWhitespace = true;
while (!(tk = scanner.read()).isEndOfBlock()) {
diff --git a/src/plugins/pythoneditor/pythonhighlighter.h b/src/plugins/pythoneditor/pythonhighlighter.h
index 778d3727b2..63c35dfaf3 100644
--- a/src/plugins/pythoneditor/pythonhighlighter.h
+++ b/src/plugins/pythoneditor/pythonhighlighter.h
@@ -41,6 +41,9 @@ private:
void highlightBlock(const QString &text) override;
int highlightLine(const QString &text, int initialState);
void highlightImport(Internal::Scanner &scanner);
+
+ int m_lastIndent = 0;
+ bool withinLicenseHeader = false;
};
} // namespace Internal
diff --git a/src/plugins/pythoneditor/pythonindenter.cpp b/src/plugins/pythoneditor/pythonindenter.cpp
index 70b431368c..035f1aef7c 100644
--- a/src/plugins/pythoneditor/pythonindenter.cpp
+++ b/src/plugins/pythoneditor/pythonindenter.cpp
@@ -28,8 +28,28 @@
#include <texteditor/tabsettings.h>
+#include <algorithm>
+
namespace PythonEditor {
+static bool isEmptyLine(const QString &t)
+{
+ return std::all_of(t.cbegin(), t.cend(), [] (QChar c) { return c.isSpace(); });
+}
+
+static inline bool isEmptyLine(const QTextBlock &block)
+{
+ return isEmptyLine(block.text());
+}
+
+static QTextBlock previousNonEmptyBlock(const QTextBlock &block)
+{
+ QTextBlock result = block;
+ while (result.isValid() && isEmptyLine(result))
+ result = result.previous();
+ return result;
+}
+
/**
* @brief Does given character change indentation level?
* @param ch Any value
@@ -46,6 +66,15 @@ int PythonIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSett
if (!previousBlock.isValid())
return 0;
+ // When pasting in actual code, try to skip back past empty lines to an
+ // actual code line to find a suitable indentation. This prevents code from
+ // not being indented when pasting below an empty line.
+ if (!isEmptyLine(block)) {
+ const QTextBlock previousNonEmpty = previousNonEmptyBlock(previousBlock);
+ if (previousNonEmpty.isValid())
+ previousBlock = previousNonEmpty;
+ }
+
QString previousLine = previousBlock.text();
int indentation = tabSettings.indentationColumn(previousLine);
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
index 208ca398fe..2b11012b28 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp
@@ -69,8 +69,8 @@ QbsBuildConfiguration::QbsBuildConfiguration(Target *target) :
m_isParsing(true),
m_parsingError(false)
{
- connect(project(), &QbsProject::projectParsingStarted, this, &BuildConfiguration::enabledChanged);
- connect(project(), &QbsProject::projectParsingDone, this, &BuildConfiguration::enabledChanged);
+ connect(project(), &Project::parsingStarted, this, &BuildConfiguration::enabledChanged);
+ connect(project(), &Project::parsingFinished, this, &BuildConfiguration::enabledChanged);
BuildStepList *bsl = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
connect(bsl, &BuildStepList::stepInserted, this, &QbsBuildConfiguration::buildStepInserted);
@@ -147,7 +147,7 @@ QVariantMap QbsBuildConfiguration::qbsConfiguration() const
Internal::QbsProject *QbsBuildConfiguration::project() const
{
- return qobject_cast<Internal::QbsProject *>(target()->project());
+ return qobject_cast<Internal::QbsProject *>(BuildConfiguration::project());
}
IOutputParser *QbsBuildConfiguration::createOutputParser() const
diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
index 6df507fde6..1a0248d8f6 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
+++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h
@@ -27,6 +27,8 @@
#include "qbsprojectmanager_global.h"
+#include "qbsproject.h"
+
#include <projectexplorer/buildconfiguration.h>
#include <qtsupport/baseqtversion.h>
@@ -56,7 +58,7 @@ public:
QbsBuildStep *qbsStep() const;
QVariantMap qbsConfiguration() const;
- Internal::QbsProject *project() const;
+ Internal::QbsProject *project() const override;
ProjectExplorer::IOutputParser *createOutputParser() const;
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
index 1a678b8965..063e6bf203 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
@@ -346,7 +346,8 @@ void QbsBuildStep::buildingDone(bool success)
void QbsBuildStep::reparsingDone(bool success)
{
- disconnect(qbsProject(), &QbsProject::projectParsingDone, this, &QbsBuildStep::reparsingDone);
+ disconnect(qbsProject(), &ProjectExplorer::Project::parsingFinished,
+ this, &QbsBuildStep::reparsingDone);
m_parsingProject = false;
if (m_job) { // This was a scheduled reparsing after building.
finish();
@@ -485,7 +486,8 @@ void QbsBuildStep::setCleanInstallRoot(bool clean)
void QbsBuildStep::parseProject()
{
m_parsingProject = true;
- connect(qbsProject(), &QbsProject::projectParsingDone, this, &QbsBuildStep::reparsingDone);
+ connect(qbsProject(), &ProjectExplorer::Project::parsingFinished,
+ this, &QbsBuildStep::reparsingDone);
qbsProject()->parseCurrentBuildConfiguration();
}
@@ -551,8 +553,11 @@ QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
this, &QbsBuildStepConfigWidget::updateState);
connect(&QbsProjectManagerSettings::instance(), &QbsProjectManagerSettings::settingsBaseChanged,
this, &QbsBuildStepConfigWidget::updateState);
- connect(step->buildConfiguration()->target(), &ProjectExplorer::Target::buildDirectoryChanged,
- this, &QbsBuildStepConfigWidget::updateState);
+ step->target()->subscribeSignal(&ProjectExplorer::BuildConfiguration::buildDirectoryChanged,
+ this, [this]() {
+ if (m_step->target()->activeBuildConfiguration() == sender())
+ updateState();
+ });
setContentsMargins(0, 0, 0, 0);
diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
index 840cf4eefd..8a4e9ad7b9 100644
--- a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
@@ -286,7 +286,7 @@ QbsInstallStepConfigWidget::QbsInstallStepConfigWidget(QbsInstallStep *step) :
connect(m_ui->keepGoingCheckBox, &QAbstractButton::toggled,
this, &QbsInstallStepConfigWidget::changeKeepGoing);
- connect(project, &QbsProject::projectParsingDone,
+ connect(project, &ProjectExplorer::Project::parsingFinished,
this, &QbsInstallStepConfigWidget::updateState);
updateState();
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp
index e3dd87e23e..37da6326ab 100644
--- a/src/plugins/qbsprojectmanager/qbsnodes.cpp
+++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp
@@ -43,7 +43,6 @@
#include <QtDebug>
#include <QDir>
#include <QIcon>
-#include <QStyle>
using namespace ProjectExplorer;
@@ -51,36 +50,23 @@ using namespace ProjectExplorer;
// Helpers:
// ----------------------------------------------------------------------
-static QIcon generateIcon(const QString &overlay)
-{
- const QSize desiredSize = QSize(16, 16);
- const QIcon overlayIcon(overlay);
- const QPixmap pixmap
- = Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon, overlayIcon, desiredSize);
-
- QIcon result;
- result.addPixmap(pixmap);
-
- return result;
-}
-
namespace QbsProjectManager {
namespace Internal {
-static QbsProjectNode *parentQbsProjectNode(ProjectExplorer::Node *node)
+static const QbsProjectNode *parentQbsProjectNode(const ProjectExplorer::Node *node)
{
- for (ProjectExplorer::FolderNode *pn = node->managingProject(); pn; pn = pn->parentProjectNode()) {
- QbsProjectNode *prjNode = dynamic_cast<QbsProjectNode *>(pn);
+ for (const ProjectExplorer::FolderNode *pn = node->managingProject(); pn; pn = pn->parentProjectNode()) {
+ const QbsProjectNode *prjNode = dynamic_cast<const QbsProjectNode *>(pn);
if (prjNode)
return prjNode;
}
return 0;
}
-static QbsProductNode *parentQbsProductNode(ProjectExplorer::Node *node)
+static const QbsProductNode *parentQbsProductNode(const ProjectExplorer::Node *node)
{
for (; node; node = node->parentFolderNode()) {
- QbsProductNode *prdNode = dynamic_cast<QbsProductNode *>(node);
+ const QbsProductNode *prdNode = dynamic_cast<const QbsProductNode *>(node);
if (prdNode)
return prdNode;
}
@@ -225,7 +211,7 @@ public:
};
-static bool supportsNodeAction(ProjectAction action, Node *node)
+static bool supportsNodeAction(ProjectAction action, const Node *node)
{
const QbsProject * const project = parentQbsProjectNode(node)->project();
if (!project->isProjectEditable())
@@ -270,7 +256,7 @@ QbsFolderNode::QbsFolderNode(const Utils::FileName &folderPath, ProjectExplorer:
{
}
-bool QbsFolderNode::supportsAction(ProjectAction action, Node *node) const
+bool QbsFolderNode::supportsAction(ProjectAction action, const Node *node) const
{
return supportsNodeAction(action, node);
}
@@ -302,7 +288,7 @@ QbsGroupNode::QbsGroupNode(const qbs::GroupData &grp, const QString &productPath
m_qbsGroupData = grp;
}
-bool QbsGroupNode::supportsAction(ProjectAction action, Node *node) const
+bool QbsGroupNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == AddNewFile || action == AddExistingFile)
return true;
@@ -316,13 +302,13 @@ bool QbsGroupNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
if (!notAdded)
notAdded = &notAddedDummy;
- QbsProjectNode *prjNode = parentQbsProjectNode(this);
+ const QbsProjectNode *prjNode = parentQbsProjectNode(this);
if (!prjNode || !prjNode->qbsProject().isValid()) {
*notAdded += filePaths;
return false;
}
- QbsProductNode *prdNode = parentQbsProductNode(this);
+ const QbsProductNode *prdNode = parentQbsProductNode(this);
if (!prdNode || !prdNode->qbsProductData().isValid()) {
*notAdded += filePaths;
return false;
@@ -338,13 +324,13 @@ bool QbsGroupNode::removeFiles(const QStringList &filePaths, QStringList *notRem
if (!notRemoved)
notRemoved = &notRemovedDummy;
- QbsProjectNode *prjNode = parentQbsProjectNode(this);
+ const QbsProjectNode *prjNode = parentQbsProjectNode(this);
if (!prjNode || !prjNode->qbsProject().isValid()) {
*notRemoved += filePaths;
return false;
}
- QbsProductNode *prdNode = parentQbsProductNode(this);
+ const QbsProductNode *prdNode = parentQbsProductNode(this);
if (!prdNode || !prdNode->qbsProductData().isValid()) {
*notRemoved += filePaths;
return false;
@@ -356,10 +342,10 @@ bool QbsGroupNode::removeFiles(const QStringList &filePaths, QStringList *notRem
bool QbsGroupNode::renameFile(const QString &filePath, const QString &newFilePath)
{
- QbsProjectNode * const prjNode = parentQbsProjectNode(this);
+ const QbsProjectNode *prjNode = parentQbsProjectNode(this);
if (!prjNode || !prjNode->qbsProject().isValid())
return false;
- QbsProductNode * const prdNode = parentQbsProductNode(this);
+ const QbsProductNode *prdNode = parentQbsProductNode(this);
if (!prdNode || !prdNode->qbsProductData().isValid())
return false;
@@ -375,7 +361,7 @@ QbsProductNode::QbsProductNode(const qbs::ProductData &prd) :
QbsBaseProjectNode(Utils::FileName::fromString(prd.location().filePath())),
m_qbsProductData(prd)
{
- static QIcon productIcon = generateIcon(QString(Constants::QBS_PRODUCT_OVERLAY_ICON));
+ static QIcon productIcon = Core::FileIconProvider::directoryIcon(Constants::QBS_PRODUCT_OVERLAY_ICON);
setIcon(productIcon);
}
@@ -384,7 +370,7 @@ bool QbsProductNode::showInSimpleTree() const
return true;
}
-bool QbsProductNode::supportsAction(ProjectAction action, Node *node) const
+bool QbsProductNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == AddNewFile || action == AddExistingFile)
return true;
@@ -398,7 +384,7 @@ bool QbsProductNode::addFiles(const QStringList &filePaths, QStringList *notAdde
if (!notAdded)
notAdded = &notAddedDummy;
- QbsProjectNode *prjNode = parentQbsProjectNode(this);
+ const QbsProjectNode *prjNode = parentQbsProjectNode(this);
if (!prjNode || !prjNode->qbsProject().isValid()) {
*notAdded += filePaths;
return false;
@@ -418,7 +404,7 @@ bool QbsProductNode::removeFiles(const QStringList &filePaths, QStringList *notR
if (!notRemoved)
notRemoved = &notRemovedDummy;
- QbsProjectNode *prjNode = parentQbsProjectNode(this);
+ const QbsProjectNode *prjNode = parentQbsProjectNode(this);
if (!prjNode || !prjNode->qbsProject().isValid()) {
*notRemoved += filePaths;
return false;
@@ -435,7 +421,7 @@ bool QbsProductNode::removeFiles(const QStringList &filePaths, QStringList *notR
bool QbsProductNode::renameFile(const QString &filePath, const QString &newFilePath)
{
- QbsProjectNode * const prjNode = parentQbsProjectNode(this);
+ const QbsProjectNode * prjNode = parentQbsProjectNode(this);
if (!prjNode || !prjNode->qbsProject().isValid())
return false;
const qbs::GroupData grp = findMainQbsGroup(m_qbsProductData);
@@ -468,7 +454,7 @@ QList<ProjectExplorer::RunConfiguration *> QbsProductNode::runConfigurations() c
QbsProjectNode::QbsProjectNode(const Utils::FileName &projectDirectory) :
QbsBaseProjectNode(projectDirectory)
{
- static QIcon projectIcon = generateIcon(QString(ProjectExplorer::Constants::FILEOVERLAY_QT));
+ static QIcon projectIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
setIcon(projectIcon);
}
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h
index 904851bc81..f6d02f16b5 100644
--- a/src/plugins/qbsprojectmanager/qbsnodes.h
+++ b/src/plugins/qbsprojectmanager/qbsnodes.h
@@ -55,7 +55,7 @@ public:
const QString &displayName);
private:
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const final;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const final;
};
// ---------------------------------------------------------------------------
@@ -81,7 +81,7 @@ class QbsGroupNode : public QbsBaseProjectNode
public:
QbsGroupNode(const qbs::GroupData &grp, const QString &productPath);
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const final;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const final;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0) override;
bool renameFile(const QString &filePath, const QString &newFilePath) override;
@@ -103,7 +103,7 @@ public:
explicit QbsProductNode(const qbs::ProductData &prd);
bool showInSimpleTree() const override;
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const final;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const final;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0) override;
bool renameFile(const QString &filePath, const QString &newFilePath) override;
diff --git a/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp b/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp
index 8e54900fd6..3e7ac54eb4 100644
--- a/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprofilessettingspage.cpp
@@ -30,6 +30,7 @@
#include "qbsprojectmanagerconstants.h"
#include "qbsprojectmanagersettings.h"
+#include <app/app_version.h>
#include <coreplugin/icore.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitmanager.h>
@@ -105,6 +106,8 @@ QbsProfilesSettingsWidget::QbsProfilesSettingsWidget(QWidget *parent)
{
m_model.setEditable(false);
m_ui.setupUi(this);
+ m_ui.settingsDirCheckBox->setText(tr("Store profiles in %1 settings directory")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
m_ui.settingsDirCheckBox->setChecked(QbsProjectManagerSettings::useCreatorSettingsDirForQbs());
m_ui.versionValueLabel->setText(qbs::LanguageInfo::qbsVersion());
connect(ProjectExplorer::KitManager::instance(), &ProjectExplorer::KitManager::kitsChanged,
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index dbeb13cb60..eb3191e60e 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -138,9 +138,17 @@ QbsProject::QbsProject(const FileName &fileName) :
rebuildProjectTree();
connect(this, &Project::activeTargetChanged, this, &QbsProject::changeActiveTarget);
- connect(this, &Project::addedTarget, this, &QbsProject::targetWasAdded);
- connect(this, &Project::removedTarget, this, &QbsProject::targetWasRemoved);
- connect(this, &Project::environmentChanged, this, &QbsProject::delayParsing);
+ connect(this, &Project::addedTarget,
+ this, [this](Target *t) { m_qbsProjects.insert(t, qbs::Project()); });
+ connect(this, &Project::removedTarget,
+ this, [this](Target *t) {m_qbsProjects.remove(t); });
+ auto delayedParsing = [this]() {
+ if (static_cast<BuildConfiguration *>(sender())->isActive())
+ delayParsing();
+ };
+ subscribeSignal(&BuildConfiguration::environmentChanged, this, delayedParsing);
+ subscribeSignal(&BuildConfiguration::buildDirectoryChanged, this, delayedParsing);
+ subscribeSignal(&Target::activeBuildConfigurationChanged, this, delayedParsing);
connect(&m_parsingDelay, &QTimer::timeout, this, &QbsProject::startParsing);
@@ -439,6 +447,7 @@ bool QbsProject::checkCancelStatus()
qCDebug(qbsPmLog) << "Cancel request while parsing, starting re-parse";
m_qbsProjectParser->deleteLater();
m_qbsProjectParser = 0;
+ emitParsingFinished(false);
parseCurrentBuildConfiguration();
return true;
}
@@ -503,8 +512,7 @@ void QbsProject::handleQbsParsingDone(bool success)
if (dataChanged)
updateAfterParse();
- emit projectParsingDone(success);
- emit parsingFinished();
+ emitParsingFinished(success);
}
void QbsProject::rebuildProjectTree()
@@ -530,19 +538,6 @@ void QbsProject::handleRuleExecutionDone()
QTC_ASSERT(m_qbsProject.isValid(), return);
m_projectData = m_qbsProject.projectData();
updateAfterParse();
- emit projectParsingDone(true);
-}
-
-void QbsProject::targetWasAdded(Target *t)
-{
- m_qbsProjects.insert(t, qbs::Project());
- connect(t, &Target::activeBuildConfigurationChanged, this, &QbsProject::delayParsing);
- connect(t, &Target::buildDirectoryChanged, this, &QbsProject::delayParsing);
-}
-
-void QbsProject::targetWasRemoved(Target *t)
-{
- m_qbsProjects.remove(t);
}
void QbsProject::changeActiveTarget(Target *t)
@@ -724,7 +719,7 @@ void QbsProject::parse(const QVariantMap &config, const Environment &env, const
QbsManager::instance()->updateProfileIfNecessary(activeTarget()->kit());
m_qbsProjectParser->parse(config, env, dir, configName);
- emit projectParsingStarted();
+ emitParsingStarted();
}
void QbsProject::prepareForParsing()
@@ -965,17 +960,7 @@ void QbsProject::updateCppCodeModel()
QStringList list = props.getModulePropertiesAsStringList(
QLatin1String(CONFIG_CPP_MODULE),
QLatin1String(CONFIG_DEFINES));
- QByteArray grpDefines;
- foreach (const QString &def, list) {
- QByteArray data = def.toUtf8();
- int pos = data.indexOf('=');
- if (pos >= 0)
- data[pos] = ' ';
- else
- data.append(" 1"); // cpp.defines: [ "FOO" ] is considered to be "FOO=1"
- grpDefines += (QByteArray("#define ") + data + '\n');
- }
- rpp.setDefines(grpDefines);
+ rpp.setMacros(Utils::transform<QVector>(list, [](const QString &s) { return ProjectExplorer::Macro::fromKeyValue(s); }));
list = props.getModulePropertiesAsStringList(QLatin1String(CONFIG_CPP_MODULE),
QLatin1String(CONFIG_INCLUDEPATHS));
@@ -1004,6 +989,8 @@ void QbsProject::updateCppCodeModel()
rpp.setProjectFileLocation(grp.location().filePath(),
grp.location().line(), grp.location().column());
rpp.setBuildSystemTarget(prd.name());
+ rpp.setBuildTargetType(prd.isRunnable() ? CppTools::ProjectPart::Executable
+ : CppTools::ProjectPart::Library);
QHash<QString, qbs::ArtifactData> filePathToSourceArtifact;
bool hasCFiles = false;
diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h
index 8d2e0c8cbd..fa12083716 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.h
+++ b/src/plugins/qbsprojectmanager/qbsproject.h
@@ -110,21 +110,14 @@ public:
void configureAsExampleProject(const QSet<Core::Id> &platforms) final;
-public:
void invalidate();
void delayParsing();
-signals:
- void projectParsingStarted();
- void projectParsingDone(bool);
-
private:
void handleQbsParsingDone(bool success);
void rebuildProjectTree();
- void targetWasAdded(ProjectExplorer::Target *t);
- void targetWasRemoved(ProjectExplorer::Target *t);
void changeActiveTarget(ProjectExplorer::Target *t);
void buildConfigurationChanged(ProjectExplorer::BuildConfiguration *bc);
void startParsing();
diff --git a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
index 406039e40f..8c038f20a9 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp
@@ -116,7 +116,7 @@ static QStringList candidatesForDirectory(const QString &dir)
QStringList QbsProjectImporter::importCandidates()
{
- const QString projectDir = QFileInfo(projectFilePath().toString()).absolutePath();
+ const QString projectDir = projectFilePath().toFileInfo().absolutePath();
QStringList candidates = candidatesForDirectory(projectDir);
QSet<QString> seenCandidates;
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
index c732facdf4..bfa79ea519 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
@@ -43,6 +43,7 @@ QtcPlugin {
Depends { name: "CppTools" }
Depends { name: "QtSupport" }
Depends { name: "QmlJSTools" }
+ Depends { name: "app_version_header" }
cpp.defines: base.concat([
'QML_BUILD_STATIC_LIB',
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
index 2a34b2f8b1..a4cd157c71 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp
@@ -297,23 +297,23 @@ void QbsProjectManagerPlugin::projectWasAdded(Project *project)
if (!qbsProject)
return;
- connect(qbsProject, &QbsProject::projectParsingStarted,
+ connect(qbsProject, &Project::parsingStarted,
this, &QbsProjectManagerPlugin::projectChanged);
- connect(qbsProject, &QbsProject::projectParsingDone,
+ connect(qbsProject, &Project::parsingFinished,
this, &QbsProjectManagerPlugin::projectChanged);
}
void QbsProjectManagerPlugin::updateContextActions()
{
QbsProject *project = qobject_cast<Internal::QbsProject *>(ProjectTree::currentProject());
- Node *node = ProjectTree::currentNode();
+ const Node *node = ProjectTree::findCurrentNode();
bool isEnabled = !BuildManager::isBuilding(project)
&& project && !project->isParsing()
&& node && node->isEnabled();
bool isFile = project && node && (node->nodeType() == NodeType::File);
- bool isProduct = project && node && dynamic_cast<QbsProductNode *>(node);
- QbsProjectNode *subproject = dynamic_cast<QbsProjectNode *>(node);
+ const bool isProduct = project && node && dynamic_cast<const QbsProductNode *>(node);
+ const QbsProjectNode *subproject = dynamic_cast<const QbsProjectNode *>(node);
bool isSubproject = project && subproject && subproject != project->rootProjectNode();
m_reparseQbsCtx->setEnabled(isEnabled);
@@ -409,7 +409,7 @@ void QbsProjectManagerPlugin::projectChanged()
void QbsProjectManagerPlugin::buildFileContextMenu()
{
- Node *node = ProjectTree::currentNode();
+ const Node *node = ProjectTree::findCurrentNode();
QTC_ASSERT(node, return);
QbsProject *project = dynamic_cast<QbsProject *>(ProjectTree::currentProject());
QTC_ASSERT(project, return);
@@ -446,12 +446,12 @@ void QbsProjectManagerPlugin::rebuildProductContextMenu()
void QbsProjectManagerPlugin::runStepsForProductContextMenu(const QList<Core::Id> &stepTypes)
{
- Node *node = ProjectTree::currentNode();
+ const Node *node = ProjectTree::findCurrentNode();
QTC_ASSERT(node, return);
QbsProject *project = dynamic_cast<QbsProject *>(ProjectTree::currentProject());
QTC_ASSERT(project, return);
- const QbsProductNode * const productNode = dynamic_cast<QbsProductNode *>(node);
+ const QbsProductNode * const productNode = dynamic_cast<const QbsProductNode *>(node);
QTC_ASSERT(productNode, return);
runStepsForProducts(project, {QbsProject::uniqueProductName(productNode->qbsProductData())},
@@ -511,12 +511,12 @@ void QbsProjectManagerPlugin::rebuildSubprojectContextMenu()
void QbsProjectManagerPlugin::runStepsForSubprojectContextMenu(const QList<Core::Id> &stepTypes)
{
- Node *node = ProjectTree::currentNode();
+ const Node *node = ProjectTree::findCurrentNode();
QTC_ASSERT(node, return);
QbsProject *project = dynamic_cast<QbsProject *>(ProjectTree::currentProject());
QTC_ASSERT(project, return);
- QbsProjectNode *subProject = dynamic_cast<QbsProjectNode *>(node);
+ const QbsProjectNode *subProject = dynamic_cast<const QbsProjectNode *>(node);
QTC_ASSERT(subProject, return);
QStringList toBuild;
diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
index e8b90d4377..2a54a8e28a 100644
--- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
+++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp
@@ -30,6 +30,7 @@
#include "qbsproject.h"
#include <coreplugin/messagemanager.h>
+#include <coreplugin/variablechooser.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/buildstep.h>
#include <projectexplorer/buildsteplist.h>
@@ -44,11 +45,11 @@
#include <utils/detailswidget.h>
#include <utils/stringutils.h>
#include <utils/persistentsettings.h>
+#include <utils/utilsicons.h>
#include <qtsupport/qtoutputformatter.h>
#include <qtsupport/qtsupportconstants.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/hostosinfo.h>
-#include <utils/utilsicons.h>
#include "api/runenvironment.h"
@@ -107,77 +108,57 @@ const qbs::ProductData findProduct(const qbs::ProjectData &pro, const QString &u
// QbsRunConfiguration:
// --------------------------------------------------------------------
-QbsRunConfiguration::QbsRunConfiguration(Target *parent, Core::Id id) :
- RunConfiguration(parent, id),
- m_uniqueProductName(uniqueProductNameFromId(id)),
- m_currentInstallStep(0),
- m_currentBuildStepList(0)
+QbsRunConfiguration::QbsRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
- auto * const envAspect = new LocalEnvironmentAspect(this,
+ auto envAspect = new LocalEnvironmentAspect(this,
[](RunConfiguration *rc, Environment &env) {
static_cast<QbsRunConfiguration *>(rc)->addToBaseEnvironment(env);
- }
- );
+ });
addExtraAspect(envAspect);
- connect(static_cast<QbsProject *>(parent->project()), &QbsProject::parsingFinished, this,
+ connect(static_cast<QbsProject *>(target->project()), &Project::parsingFinished, this,
[envAspect]() { envAspect->buildEnvironmentHasChanged(); });
- addExtraAspect(new ArgumentsAspect(this, QStringLiteral("Qbs.RunConfiguration.CommandLineArguments")));
- addExtraAspect(new WorkingDirectoryAspect(this, QStringLiteral("Qbs.RunConfiguration.WorkingDirectory")));
+ addExtraAspect(new ArgumentsAspect(this, "Qbs.RunConfiguration.CommandLineArguments"));
+ addExtraAspect(new WorkingDirectoryAspect(this, "Qbs.RunConfiguration.WorkingDirectory"));
- addExtraAspect(new TerminalAspect(this,
- QStringLiteral("Qbs.RunConfiguration.UseTerminal"),
- isConsoleApplication()));
+ addExtraAspect(new TerminalAspect(this, "Qbs.RunConfiguration.UseTerminal", isConsoleApplication()));
- ctor();
-}
+ QbsProject *project = static_cast<QbsProject *>(target->project());
+ connect(project, &Project::parsingFinished, this, [this](bool success) {
+ auto terminalAspect = extraAspect<TerminalAspect>();
+ if (success && !terminalAspect->isUserSet())
+ terminalAspect->setUseTerminal(isConsoleApplication());
+ });
+ connect(BuildManager::instance(), &BuildManager::buildStateChanged, this,
+ [this, project](Project *p) {
+ if (p == project && !BuildManager::isBuilding(p))
+ emit enabledChanged();
+ }
+ );
-QbsRunConfiguration::QbsRunConfiguration(Target *parent, QbsRunConfiguration *source) :
- RunConfiguration(parent, source),
- m_uniqueProductName(source->m_uniqueProductName),
- m_currentInstallStep(0), // no need to copy this, we will get if from the DC anyway.
- m_currentBuildStepList(0) // ditto
-{
- ctor();
+ connect(target, &Target::activeDeployConfigurationChanged,
+ this, &QbsRunConfiguration::installStepChanged);
}
-bool QbsRunConfiguration::isEnabled() const
+void QbsRunConfiguration::initialize(Core::Id id)
{
- QbsProject *project = static_cast<QbsProject *>(target()->project());
- return !project->isParsing() && project->hasParseResult();
+ m_uniqueProductName = uniqueProductNameFromId(id);
+ ctor();
}
-QString QbsRunConfiguration::disabledReason() const
+void QbsRunConfiguration::copyFrom(const QbsRunConfiguration *source)
{
- QbsProject *project = static_cast<QbsProject *>(target()->project());
- if (project->isParsing())
- return tr("The .qbs files are currently being parsed.");
+ RunConfiguration::copyFrom(source);
+ m_uniqueProductName = source->m_uniqueProductName;
+ m_currentInstallStep = nullptr; // no need to copy this, we will get if from the DC anyway.
+ m_currentBuildStepList = nullptr; // ditto
- if (!project->hasParseResult())
- return tr("Parsing of .qbs files has failed.");
- return QString();
+ ctor();
}
void QbsRunConfiguration::ctor()
{
setDefaultDisplayName(defaultDisplayName());
-
- QbsProject *project = static_cast<QbsProject *>(target()->project());
- connect(project, &QbsProject::projectParsingStarted, this, &RunConfiguration::enabledChanged);
- connect(project, &QbsProject::projectParsingDone, this, [this](bool success) {
- auto terminalAspect = extraAspect<TerminalAspect>();
- if (success && !terminalAspect->isUserSet())
- terminalAspect->setUseTerminal(isConsoleApplication());
- emit enabledChanged();
- });
- connect(BuildManager::instance(), &BuildManager::buildStateChanged, this,
- [this, project](Project *p) {
- if (p == project && !BuildManager::isBuilding(p))
- emit enabledChanged();
- }
- );
-
- connect(target(), &Target::activeDeployConfigurationChanged,
- this, &QbsRunConfiguration::installStepChanged);
installStepChanged();
}
@@ -332,17 +313,6 @@ QbsRunConfigurationWidget::QbsRunConfigurationWidget(QbsRunConfiguration *rc)
auto vboxTopLayout = new QVBoxLayout(this);
vboxTopLayout->setMargin(0);
- auto hl = new QHBoxLayout();
- hl->addStretch();
- m_disabledIcon = new QLabel(this);
- m_disabledIcon->setPixmap(Utils::Icons::WARNING.pixmap());
- hl->addWidget(m_disabledIcon);
- m_disabledReason = new QLabel(this);
- m_disabledReason->setVisible(false);
- hl->addWidget(m_disabledReason);
- hl->addStretch();
- vboxTopLayout->addLayout(hl);
-
auto detailsContainer = new Utils::DetailsWidget(this);
detailsContainer->setState(Utils::DetailsWidget::NoSummary);
vboxTopLayout->addWidget(detailsContainer);
@@ -362,23 +332,13 @@ QbsRunConfigurationWidget::QbsRunConfigurationWidget(QbsRunConfiguration *rc)
m_rc->extraAspect<TerminalAspect>()->addToMainConfigurationWidget(this, toplayout);
- runConfigurationEnabledChange();
-
connect(m_rc, &QbsRunConfiguration::targetInformationChanged,
this, &QbsRunConfigurationWidget::targetInformationHasChanged, Qt::QueuedConnection);
connect(m_rc, &RunConfiguration::enabledChanged,
- this, &QbsRunConfigurationWidget::runConfigurationEnabledChange);
-}
-
-void QbsRunConfigurationWidget::runConfigurationEnabledChange()
-{
- bool enabled = m_rc->isEnabled();
- m_disabledIcon->setVisible(!enabled);
- m_disabledReason->setVisible(!enabled);
- m_disabledReason->setText(m_rc->disabledReason());
+ this, &QbsRunConfigurationWidget::targetInformationHasChanged);
- targetInformationHasChanged();
+ Core::VariableChooser::addSupportForChildWidgets(this, rc->macroExpander());
}
void QbsRunConfigurationWidget::targetInformationHasChanged()
@@ -419,7 +379,7 @@ bool QbsRunConfigurationFactory::canCreate(Target *parent, Core::Id id) const
RunConfiguration *QbsRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
- return new QbsRunConfiguration(parent, id);
+ return createHelper<QbsRunConfiguration>(parent, id);
}
bool QbsRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
@@ -431,7 +391,7 @@ bool QbsRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &m
RunConfiguration *QbsRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
{
- return new QbsRunConfiguration(parent, idFromMap(map));
+ return createHelper<QbsRunConfiguration>(parent, idFromMap(map));
}
bool QbsRunConfigurationFactory::canClone(Target *parent, RunConfiguration *source) const
@@ -443,8 +403,7 @@ RunConfiguration *QbsRunConfigurationFactory::clone(Target *parent, RunConfigura
{
if (!canClone(parent, source))
return 0;
- QbsRunConfiguration *old = static_cast<QbsRunConfiguration *>(source);
- return new QbsRunConfiguration(parent, old);
+ return cloneHelper<QbsRunConfiguration>(parent, source);
}
QList<Core::Id> QbsRunConfigurationFactory::availableCreationIds(Target *parent, CreationMode mode) const
diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
index bff341af46..5367cd2d90 100644
--- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
+++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.h
@@ -31,27 +31,14 @@
#include <QLabel>
#include <QWidget>
-QT_BEGIN_NAMESPACE
-class QCheckBox;
-class QLineEdit;
-class QRadioButton;
-class QComboBox;
-QT_END_NAMESPACE
-
namespace qbs { class InstallOptions; }
-namespace Utils { class PathChooser; }
-
namespace ProjectExplorer { class BuildStepList; }
namespace QbsProjectManager {
-
-class QbsProject;
-
namespace Internal {
class QbsInstallStep;
-class QbsRunConfigurationFactory;
class QbsRunConfiguration : public ProjectExplorer::RunConfiguration
{
@@ -59,13 +46,11 @@ class QbsRunConfiguration : public ProjectExplorer::RunConfiguration
// to change the display name and arguments and set the userenvironmentchanges
friend class QbsRunConfigurationWidget;
- friend class QbsRunConfigurationFactory;
+ friend class ProjectExplorer::IRunConfigurationFactory;
public:
- QbsRunConfiguration(ProjectExplorer::Target *parent, Core::Id id);
+ explicit QbsRunConfiguration(ProjectExplorer::Target *target);
- bool isEnabled() const override;
- QString disabledReason() const override;
QWidget *createConfigurationWidget() override;
ProjectExplorer::Runnable runnable() const override;
@@ -83,10 +68,11 @@ signals:
void targetInformationChanged();
void usingDyldImageSuffixChanged(bool);
-protected:
- QbsRunConfiguration(ProjectExplorer::Target *parent, QbsRunConfiguration *source);
private:
+ void initialize(Core::Id id);
+ void copyFrom(const QbsRunConfiguration *source);
+
void installStepChanged();
void installStepToBeRemoved(int pos);
QString baseWorkingDirectory() const;
@@ -98,8 +84,8 @@ private:
QString m_uniqueProductName;
- QbsInstallStep *m_currentInstallStep; // We do not take ownership!
- ProjectExplorer::BuildStepList *m_currentBuildStepList; // We do not take ownership!
+ QbsInstallStep *m_currentInstallStep = nullptr; // We do not take ownership!
+ ProjectExplorer::BuildStepList *m_currentBuildStepList = nullptr; // We do not take ownership!
};
class QbsRunConfigurationWidget : public QWidget
@@ -115,10 +101,8 @@ private:
void setExecutableLineText(const QString &text = QString());
QbsRunConfiguration *m_rc;
- bool m_ignoreChange = false;
- QLabel *m_disabledIcon;
- QLabel *m_disabledReason;
QLabel *m_executableLineLabel;
+ bool m_ignoreChange = false;
bool m_isShown = false;
};
diff --git a/src/plugins/qmakeandroidsupport/androidpackageinstallationstep.cpp b/src/plugins/qmakeandroidsupport/androidpackageinstallationstep.cpp
index d07d766462..c7d0db210b 100644
--- a/src/plugins/qmakeandroidsupport/androidpackageinstallationstep.cpp
+++ b/src/plugins/qmakeandroidsupport/androidpackageinstallationstep.cpp
@@ -59,9 +59,9 @@ AndroidPackageInstallationStep::AndroidPackageInstallationStep(ProjectExplorer::
bool AndroidPackageInstallationStep::init(QList<const BuildStep *> &earlierSteps)
{
ProjectExplorer::BuildConfiguration *bc = buildConfiguration();
- QString dirPath = bc->buildDirectory().appendPath(QLatin1String(Android::Constants::ANDROID_BUILDDIRECTORY)).toString();
+ QString dirPath = bc->buildDirectory().appendPath(Android::Constants::ANDROID_BUILDDIRECTORY).toString();
if (Utils::HostOsInfo::isWindowsHost())
- if (bc->environment().searchInPath(QLatin1String("sh.exe")).isEmpty())
+ if (bc->environment().searchInPath("sh.exe").isEmpty())
dirPath = QDir::toNativeSeparators(dirPath);
ProjectExplorer::ToolChain *tc
@@ -88,12 +88,8 @@ bool AndroidPackageInstallationStep::init(QList<const BuildStep *> &earlierSteps
m_androidDirsToClean.clear();
// don't remove gradle's cache, it takes ages to rebuild it.
- if (!QFile::exists(dirPath + QLatin1String("/build.xml")) && Android::AndroidManager::useGradle(target())) {
- m_androidDirsToClean << dirPath + QLatin1String("/assets");
- m_androidDirsToClean << dirPath + QLatin1String("/libs");
- } else {
- m_androidDirsToClean << dirPath;
- }
+ m_androidDirsToClean << dirPath + "/assets";
+ m_androidDirsToClean << dirPath + "/libs";
return AbstractProcessStep::init(earlierSteps);
}
diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp
index 4ca9ef9653..68e3e1d632 100644
--- a/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp
+++ b/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp
@@ -129,22 +129,20 @@ bool QmakeAndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps)
return false;
QString command = version->qmakeProperty("QT_HOST_BINS");
- if (!command.endsWith(QLatin1Char('/')))
- command += QLatin1Char('/');
- command += QLatin1String("androiddeployqt");
+ if (!command.endsWith('/'))
+ command += '/';
+ command += "androiddeployqt";
if (Utils::HostOsInfo::isWindowsHost())
- command += QLatin1String(".exe");
+ command += ".exe";
QString deploymentMethod;
if (m_deployAction == MinistroDeployment)
- deploymentMethod = QLatin1String("ministro");
- else if (m_deployAction == DebugDeployment)
- deploymentMethod = QLatin1String("debug");
+ deploymentMethod = "ministro";
else if (m_deployAction == BundleLibrariesDeployment)
- deploymentMethod = QLatin1String("bundled");
+ deploymentMethod = "bundled";
ProjectExplorer::BuildConfiguration *bc = buildConfiguration();
- QString outputDir = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();
+ QString outputDir = bc->buildDirectory().appendPath(Constants::ANDROID_BUILDDIRECTORY).toString();
const auto *pro = static_cast<QmakeProjectManager::QmakeProject *>(project());
const QmakeProjectManager::QmakeProFileNode *node = pro->rootProjectNode()->findProFileFor(proFilePathForInputFile());
@@ -165,43 +163,27 @@ bool QmakeAndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps)
return false;
}
- QStringList arguments;
- arguments << QLatin1String("--input")
- << inputFile
- << QLatin1String("--output")
- << outputDir
- << QLatin1String("--deployment")
- << deploymentMethod
- << QLatin1String("--android-platform")
- << AndroidManager::buildTargetSDK(target())
- << QLatin1String("--jdk")
- << AndroidConfigurations::currentConfig().openJDKLocation().toString();
+ QStringList arguments = {"--input", inputFile,
+ "--output", outputDir,
+ "--deployment", deploymentMethod,
+ "--android-platform", AndroidManager::buildTargetSDK(target()),
+ "--jdk", AndroidConfigurations::currentConfig().openJDKLocation().toString()};
if (m_verbose)
- arguments << QLatin1String("--verbose");
-
- if (m_useGradle)
- arguments << QLatin1String("--gradle");
- else
- arguments << QLatin1String("--ant")
- << AndroidConfigurations::currentConfig().antToolPath().toString();
+ arguments << "--verbose";
+ arguments << "--gradle";
QStringList argumentsPasswordConcealed = arguments;
if (m_signPackage) {
- arguments << QLatin1String("--sign")
- << m_keystorePath.toString()
- << m_certificateAlias
- << QLatin1String("--storepass")
- << m_keystorePasswd;
- argumentsPasswordConcealed << QLatin1String("--sign") << QLatin1String("******")
- << QLatin1String("--storepass") << QLatin1String("******");
+ arguments << "--sign" << m_keystorePath.toString() << m_certificateAlias
+ << "--storepass" << m_keystorePasswd;
+ argumentsPasswordConcealed << "--sign" << "******"
+ << "--storepass" << "******";
if (!m_certificatePasswd.isEmpty()) {
- arguments << QLatin1String("--keypass")
- << m_certificatePasswd;
- argumentsPasswordConcealed << QLatin1String("--keypass")
- << QLatin1String("******");
+ arguments << "--keypass" << m_certificatePasswd;
+ argumentsPasswordConcealed << "--keypass" << "******";
}
}
@@ -210,9 +192,9 @@ bool QmakeAndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps)
// params (e.g. --sign) to choose not to add gdbserver
if (version->qtVersion() >= QtSupport::QtVersionNumber(5, 6, 0)) {
if (m_addDebugger || bc->buildType() == ProjectExplorer::BuildConfiguration::Debug)
- arguments << QLatin1String("--gdbserver");
+ arguments << "--gdbserver";
else
- arguments << QLatin1String("--no-gdbserver");
+ arguments << "--no-gdbserver";
}
ProjectExplorer::ProcessParameters *pp = processParameters();
diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp
index 6cb626ee7e..deb380e49c 100644
--- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp
+++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp
@@ -49,35 +49,35 @@ namespace Internal {
static const char ANDROID_RC_ID_PREFIX[] = "Qt4ProjectManager.AndroidRunConfiguration:";
-static QString pathFromId(const Core::Id id)
+static Utils::FileName pathFromId(const Core::Id id)
{
- return id.suffixAfter(ANDROID_RC_ID_PREFIX);
+ return Utils::FileName::fromString(id.suffixAfter(ANDROID_RC_ID_PREFIX));
}
-QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *parent, Core::Id id, const Utils::FileName &path)
- : AndroidRunConfiguration(parent, id)
- , m_proFilePath(path)
+QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *target)
+ : AndroidRunConfiguration(target)
+{}
+
+void QmakeAndroidRunConfiguration::initialize(Core::Id id)
{
- QmakeProject *project = static_cast<QmakeProject *>(parent->project());
- m_parseSuccess = project->validParse(m_proFilePath);
- m_parseInProgress = project->parseInProgress(m_proFilePath);
- init();
+ AndroidRunConfiguration::initialize(id);
+ m_proFilePath = pathFromId(id);
+
+ ctor();
}
-QmakeAndroidRunConfiguration::QmakeAndroidRunConfiguration(Target *parent, QmakeAndroidRunConfiguration *source)
- : AndroidRunConfiguration(parent, source)
- , m_proFilePath(source->m_proFilePath)
- , m_parseSuccess(source->m_parseSuccess)
- , m_parseInProgress(source->m_parseInProgress)
+void QmakeAndroidRunConfiguration::copyFrom(const QmakeAndroidRunConfiguration *source)
{
- init();
+ AndroidRunConfiguration::copyFrom(source);
+ m_proFilePath = source->m_proFilePath;
+
+ ctor();
}
-void QmakeAndroidRunConfiguration::init()
+void QmakeAndroidRunConfiguration::ctor()
{
setDefaultDisplayName(defaultDisplayName());
- connect(qmakeProject(), &QmakeProject::proFileUpdated,
- this, &QmakeAndroidRunConfiguration::proFileUpdated);
+ QTC_CHECK(!m_proFilePath.isEmpty());
}
bool QmakeAndroidRunConfiguration::fromMap(const QVariantMap &map)
@@ -86,24 +86,17 @@ bool QmakeAndroidRunConfiguration::fromMap(const QVariantMap &map)
QTC_ASSERT(project, return false);
const QDir projectDir = QDir(project->projectDirectory().toString());
m_proFilePath = Utils::FileName::fromUserInput(projectDir.filePath(map.value(PRO_FILE_KEY).toString()));
- m_parseSuccess = project->validParse(m_proFilePath);
- m_parseInProgress = project->parseInProgress(m_proFilePath);
return AndroidRunConfiguration::fromMap(map);
}
QVariantMap QmakeAndroidRunConfiguration::toMap() const
{
- QmakeProject *project = qmakeProject();
- if (m_proFilePath.isEmpty()) {
- if (!project->rootProjectNode())
- return QVariantMap();
- m_proFilePath = project->rootProjectNode()->filePath();
- }
-
- const QDir projectDir = QDir(project->projectDirectory().toString());
QVariantMap map(AndroidRunConfiguration::toMap());
+
+ const QDir projectDir = QDir(target()->project()->projectDirectory().toString());
map.insert(PRO_FILE_KEY, projectDir.relativeFilePath(m_proFilePath.toString()));
+
return map;
}
@@ -117,21 +110,16 @@ QString QmakeAndroidRunConfiguration::defaultDisplayName()
return node->displayName();
}
- return QFileInfo(pathFromId(id())).completeBaseName();
-}
-
-bool QmakeAndroidRunConfiguration::isEnabled() const
-{
- return m_parseSuccess && !m_parseInProgress;
+ return displayNameForId(id());
}
QString QmakeAndroidRunConfiguration::disabledReason() const
{
- if (m_parseInProgress)
+ if (qmakeProject()->isParsing())
return tr("The .pro file \"%1\" is currently being parsed.")
.arg(m_proFilePath.fileName());
- if (!m_parseSuccess)
+ if (!qmakeProject()->hasParsingData())
return qmakeProject()->disabledReasonForRunConfiguration(m_proFilePath);
return QString();
}
@@ -141,25 +129,9 @@ QString QmakeAndroidRunConfiguration::buildSystemTarget() const
return qmakeProject()->mapProFilePathToTarget(m_proFilePath);
}
-void QmakeAndroidRunConfiguration::proFileUpdated(QmakeProjectManager::QmakeProFile *pro,
- bool success, bool parseInProgress)
+QString QmakeAndroidRunConfiguration::displayNameForId(Core::Id id)
{
- QmakeProject *project = qmakeProject();
- if (m_proFilePath.isEmpty() && project->rootProjectNode())
- m_proFilePath = project->rootProjectNode()->filePath();
-
- if (m_proFilePath != pro->filePath())
- return;
-
- bool enabled = isEnabled();
- QString reason = disabledReason();
- m_parseSuccess = success;
- m_parseInProgress = parseInProgress;
- if (enabled != isEnabled() || reason != disabledReason())
- emit enabledChanged();
-
- if (!parseInProgress)
- setDefaultDisplayName(defaultDisplayName());
+ return pathFromId(id).toFileInfo().completeBaseName();
}
QmakeProject *QmakeAndroidRunConfiguration::qmakeProject() const
diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h
index f7ff72987c..c0265b9abb 100644
--- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h
+++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h
@@ -40,34 +40,31 @@ namespace Internal {
class QmakeAndroidRunConfiguration : public Android::AndroidRunConfiguration
{
Q_OBJECT
- friend class QmakeAndroidRunConfigurationFactory;
public:
- QmakeAndroidRunConfiguration(ProjectExplorer::Target *parent, Core::Id id,
- const Utils::FileName &path = Utils::FileName());
+ explicit QmakeAndroidRunConfiguration(ProjectExplorer::Target *target);
Utils::FileName proFilePath() const;
- bool isEnabled() const override;
QString disabledReason() const override;
QString buildSystemTarget() const final;
-protected:
- QmakeAndroidRunConfiguration(ProjectExplorer::Target *parent, QmakeAndroidRunConfiguration *source);
+ static QString displayNameForId(Core::Id id);
+
+private:
+ friend class ProjectExplorer::IRunConfigurationFactory;
+ void initialize(Core::Id id);
+ void copyFrom(const QmakeAndroidRunConfiguration *source);
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
QString defaultDisplayName();
-private:
- void proFileUpdated(QmakeProjectManager::QmakeProFile *pro, bool success, bool parseInProgress);
QmakeProjectManager::QmakeProject *qmakeProject() const;
- void init();
+ void ctor();
mutable Utils::FileName m_proFilePath;
- bool m_parseSuccess;
- bool m_parseInProgress;
};
} // namespace Internal
diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp
index 2f93281ada..4fd903972c 100644
--- a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp
+++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp
@@ -46,11 +46,6 @@ namespace Internal {
static const char ANDROID_RC_ID_PREFIX[] = "Qt4ProjectManager.AndroidRunConfiguration:";
-static Utils::FileName pathFromId(const Core::Id id)
-{
- return Utils::FileName::fromString(id.suffixAfter(ANDROID_RC_ID_PREFIX));
-}
-
QmakeAndroidRunConfigurationFactory::QmakeAndroidRunConfigurationFactory(QObject *parent)
: IRunConfigurationFactory(parent)
{
@@ -58,7 +53,7 @@ QmakeAndroidRunConfigurationFactory::QmakeAndroidRunConfigurationFactory(QObject
QString QmakeAndroidRunConfigurationFactory::displayNameForId(Core::Id id) const
{
- return pathFromId(id).toFileInfo().completeBaseName();
+ return QmakeAndroidRunConfiguration::displayNameForId(id);
}
bool QmakeAndroidRunConfigurationFactory::canCreate(Target *parent, Core::Id id) const
@@ -92,27 +87,21 @@ QList<Core::Id> QmakeAndroidRunConfigurationFactory::availableCreationIds(Target
RunConfiguration *QmakeAndroidRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
- if (parent->project()->rootProjectNode())
- return new QmakeAndroidRunConfiguration(parent, id, pathFromId(id));
- return new QmakeAndroidRunConfiguration(parent, id);
+ return createHelper<QmakeAndroidRunConfiguration>(parent, id);
}
RunConfiguration *QmakeAndroidRunConfigurationFactory::doRestore(Target *parent,
const QVariantMap &map)
{
Core::Id id = ProjectExplorer::idFromMap(map);
- if (parent->project()->rootProjectNode())
- return new QmakeAndroidRunConfiguration(parent, id);
- return new QmakeAndroidRunConfiguration(parent, id);
+ return createHelper<QmakeAndroidRunConfiguration>(parent, id);
}
RunConfiguration *QmakeAndroidRunConfigurationFactory::clone(Target *parent, RunConfiguration *source)
{
if (!canClone(parent, source))
return 0;
-
- QmakeAndroidRunConfiguration *old = static_cast<QmakeAndroidRunConfiguration *>(source);
- return new QmakeAndroidRunConfiguration(parent, old);
+ return cloneHelper<QmakeAndroidRunConfiguration>(parent, source);
}
bool QmakeAndroidRunConfigurationFactory::canHandle(Target *t) const
diff --git a/src/plugins/qmakeprojectmanager/addlibrarywizard.h b/src/plugins/qmakeprojectmanager/addlibrarywizard.h
index 6a0201c398..0c4cb4b760 100644
--- a/src/plugins/qmakeprojectmanager/addlibrarywizard.h
+++ b/src/plugins/qmakeprojectmanager/addlibrarywizard.h
@@ -30,7 +30,6 @@
QT_BEGIN_NAMESPACE
class QRadioButton;
-class QCheckBox;
class QLabel;
QT_END_NAMESPACE
diff --git a/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.h b/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.h
index 2307a4ba77..a2ed5ef749 100644
--- a/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.h
+++ b/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.h
@@ -31,7 +31,6 @@
#include <QMap>
QT_BEGIN_NAMESPACE
-class QWidget;
QT_END_NAMESPACE
namespace Core { class GeneratedFile; }
diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
index a4a1302769..60ba152359 100644
--- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
+++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp
@@ -76,64 +76,33 @@ static Utils::FileName pathFromId(Core::Id id)
// QmakeRunConfiguration
//
-DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *parent, Core::Id id) :
- RunConfiguration(parent, id),
- m_proFilePath(pathFromId(id))
+DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
addExtraAspect(new LocalEnvironmentAspect(this, [](RunConfiguration *rc, Environment &env) {
static_cast<DesktopQmakeRunConfiguration *>(rc)->addToBaseEnvironment(env);
}));
- addExtraAspect(new ArgumentsAspect(this, QStringLiteral("Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments")));
- addExtraAspect(new TerminalAspect(this, QStringLiteral("Qt4ProjectManager.Qt4RunConfiguration.UseTerminal")));
- addExtraAspect(new WorkingDirectoryAspect(this,
- QStringLiteral("Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory")));
- QmakeProject *project = qmakeProject();
- m_parseSuccess = project->validParse(m_proFilePath);
- m_parseInProgress = project->parseInProgress(m_proFilePath);
-
- ctor();
-}
-
-DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *parent, DesktopQmakeRunConfiguration *source) :
- RunConfiguration(parent, source),
- m_proFilePath(source->m_proFilePath),
- m_isUsingDyldImageSuffix(source->m_isUsingDyldImageSuffix),
- m_isUsingLibrarySearchPath(source->m_isUsingLibrarySearchPath),
- m_parseSuccess(source->m_parseSuccess),
- m_parseInProgress(source->m_parseInProgress)
-{
- ctor();
-}
-
-bool DesktopQmakeRunConfiguration::isEnabled() const
-{
- return m_parseSuccess && !m_parseInProgress;
+ addExtraAspect(new ArgumentsAspect(this, "Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"));
+ addExtraAspect(new TerminalAspect(this, "Qt4ProjectManager.Qt4RunConfiguration.UseTerminal"));
+ addExtraAspect(new WorkingDirectoryAspect(this, "Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"));
}
-QString DesktopQmakeRunConfiguration::disabledReason() const
+void DesktopQmakeRunConfiguration::initialize(Core::Id id)
{
- if (m_parseInProgress)
- return tr("The .pro file \"%1\" is currently being parsed.")
- .arg(m_proFilePath.fileName());
+ RunConfiguration::initialize(id);
+ m_proFilePath = pathFromId(id);
- if (!m_parseSuccess)
- return qmakeProject()->disabledReasonForRunConfiguration(m_proFilePath);
- return QString();
+ ctor();
}
-void DesktopQmakeRunConfiguration::proFileUpdated(QmakeProFile *pro, bool success, bool parseInProgress)
+void DesktopQmakeRunConfiguration::copyFrom(const DesktopQmakeRunConfiguration *source)
{
- if (m_proFilePath != pro->filePath())
- return;
- const bool enabled = isEnabled();
- const QString reason = disabledReason();
- m_parseSuccess = success;
- m_parseInProgress = parseInProgress;
- if (enabled != isEnabled() || reason != disabledReason())
- emit enabledChanged();
+ RunConfiguration::copyFrom(source);
+ m_proFilePath = source->m_proFilePath;
+ m_isUsingDyldImageSuffix = source->m_isUsingDyldImageSuffix;
+ m_isUsingLibrarySearchPath = source->m_isUsingLibrarySearchPath;
- if (!parseInProgress)
- updateTargetInformation();
+ ctor();
}
void DesktopQmakeRunConfiguration::proFileEvaluated()
@@ -165,8 +134,8 @@ void DesktopQmakeRunConfiguration::ctor()
setDefaultDisplayName(defaultDisplayName());
QmakeProject *project = qmakeProject();
- connect(project, &QmakeProject::proFileUpdated,
- this, &DesktopQmakeRunConfiguration::proFileUpdated);
+ connect(project, &Project::parsingFinished,
+ this, &DesktopQmakeRunConfiguration::updateTargetInformation);
connect(project, &QmakeProject::proFilesEvaluated,
this, &DesktopQmakeRunConfiguration::proFileEvaluated);
@@ -183,17 +152,6 @@ DesktopQmakeRunConfigurationWidget::DesktopQmakeRunConfigurationWidget(DesktopQm
auto vboxTopLayout = new QVBoxLayout(this);
vboxTopLayout->setMargin(0);
- auto hl = new QHBoxLayout();
- hl->addStretch();
- m_disabledIcon = new QLabel(this);
- m_disabledIcon->setPixmap(Utils::Icons::WARNING.pixmap());
- hl->addWidget(m_disabledIcon);
- m_disabledReason = new QLabel(this);
- m_disabledReason->setVisible(false);
- hl->addWidget(m_disabledReason);
- hl->addStretch();
- vboxTopLayout->addLayout(hl);
-
auto detailsContainer = new DetailsWidget(this);
detailsContainer->setState(DetailsWidget::NoSummary);
vboxTopLayout->addWidget(detailsContainer);
@@ -249,8 +207,6 @@ DesktopQmakeRunConfigurationWidget::DesktopQmakeRunConfigurationWidget(DesktopQm
this, &DesktopQmakeRunConfigurationWidget::usingLibrarySearchPathToggled);
}
- runConfigurationEnabledChange();
-
connect(qmakeRunConfiguration, &DesktopQmakeRunConfiguration::usingDyldImageSuffixChanged,
this, &DesktopQmakeRunConfigurationWidget::usingDyldImageSuffixChanged);
connect(qmakeRunConfiguration, &DesktopQmakeRunConfiguration::usingLibrarySearchPathChanged,
@@ -258,21 +214,10 @@ DesktopQmakeRunConfigurationWidget::DesktopQmakeRunConfigurationWidget(DesktopQm
connect(qmakeRunConfiguration, &DesktopQmakeRunConfiguration::effectiveTargetInformationChanged,
this, &DesktopQmakeRunConfigurationWidget::effectiveTargetInformationChanged, Qt::QueuedConnection);
- connect(qmakeRunConfiguration, &RunConfiguration::enabledChanged,
- this, &DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange);
-
Core::VariableChooser::addSupportForChildWidgets(this, m_qmakeRunConfiguration->macroExpander());
effectiveTargetInformationChanged();
}
-void DesktopQmakeRunConfigurationWidget::runConfigurationEnabledChange()
-{
- bool enabled = m_qmakeRunConfiguration->isEnabled();
- m_disabledIcon->setVisible(!enabled);
- m_disabledReason->setVisible(!enabled);
- m_disabledReason->setText(m_qmakeRunConfiguration->disabledReason());
-}
-
void DesktopQmakeRunConfigurationWidget::usingDyldImageSuffixToggled(bool state)
{
m_ignoreChange = true;
@@ -337,9 +282,6 @@ bool DesktopQmakeRunConfiguration::fromMap(const QVariantMap &map)
m_isUsingDyldImageSuffix = map.value(QLatin1String(USE_DYLD_IMAGE_SUFFIX_KEY), false).toBool();
m_isUsingLibrarySearchPath = map.value(QLatin1String(USE_LIBRARY_SEARCH_PATH), true).toBool();
- m_parseSuccess = qmakeProject()->validParse(m_proFilePath);
- m_parseInProgress = qmakeProject()->parseInProgress(m_proFilePath);
-
return RunConfiguration::fromMap(map);
}
@@ -527,7 +469,7 @@ bool DesktopQmakeRunConfigurationFactory::canCreate(Target *parent, Core::Id id)
RunConfiguration *DesktopQmakeRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
- return new DesktopQmakeRunConfiguration(parent, id);
+ return createHelper<DesktopQmakeRunConfiguration>(parent, id);
}
bool DesktopQmakeRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
@@ -539,7 +481,7 @@ bool DesktopQmakeRunConfigurationFactory::canRestore(Target *parent, const QVari
RunConfiguration *DesktopQmakeRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
{
- return new DesktopQmakeRunConfiguration(parent, idFromMap(map));
+ return createHelper<DesktopQmakeRunConfiguration>(parent, idFromMap(map));
}
bool DesktopQmakeRunConfigurationFactory::canClone(Target *parent, RunConfiguration *source) const
@@ -551,8 +493,7 @@ RunConfiguration *DesktopQmakeRunConfigurationFactory::clone(Target *parent, Run
{
if (!canClone(parent, source))
return 0;
- DesktopQmakeRunConfiguration *old = static_cast<DesktopQmakeRunConfiguration *>(source);
- return new DesktopQmakeRunConfiguration(parent, old);
+ return cloneHelper<DesktopQmakeRunConfiguration>(parent, source);
}
QList<Core::Id> DesktopQmakeRunConfigurationFactory::availableCreationIds(Target *parent, CreationMode mode) const
diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
index ff7c86b5fc..5dde3c3534 100644
--- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
+++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h
@@ -42,7 +42,6 @@ QT_END_NAMESPACE
namespace QmakeProjectManager {
class QmakeProFile;
-class QmakeProFileNode;
class QmakeProject;
namespace Internal {
@@ -53,13 +52,11 @@ class DesktopQmakeRunConfiguration : public ProjectExplorer::RunConfiguration
Q_OBJECT
// to change the display name and arguments and set the userenvironmentchanges
friend class DesktopQmakeRunConfigurationWidget;
- friend class DesktopQmakeRunConfigurationFactory;
+ friend class ProjectExplorer::IRunConfigurationFactory;
public:
- DesktopQmakeRunConfiguration(ProjectExplorer::Target *parent, Core::Id id);
+ explicit DesktopQmakeRunConfiguration(ProjectExplorer::Target *target);
- bool isEnabled() const override;
- QString disabledReason() const override;
QWidget *createConfigurationWidget() override;
ProjectExplorer::Runnable runnable() const override;
@@ -90,11 +87,12 @@ signals:
void effectiveTargetInformationChanged();
protected:
- DesktopQmakeRunConfiguration(ProjectExplorer::Target *parent, DesktopQmakeRunConfiguration *source);
+ void initialize(Core::Id id);
+ void copyFrom(const DesktopQmakeRunConfiguration *source);
+
bool fromMap(const QVariantMap &map) override;
private:
- void proFileUpdated(QmakeProjectManager::QmakeProFile *pro, bool success, bool parseInProgress);
void proFileEvaluated();
void updateTargetInformation();
@@ -113,8 +111,6 @@ private:
// Cached startup sub project information
bool m_isUsingDyldImageSuffix = false;
bool m_isUsingLibrarySearchPath = true;
- bool m_parseSuccess = false;
- bool m_parseInProgress = false;
};
class DesktopQmakeRunConfigurationWidget : public QWidget
@@ -125,7 +121,6 @@ public:
explicit DesktopQmakeRunConfigurationWidget(DesktopQmakeRunConfiguration *qmakeRunConfiguration);
private:
- void runConfigurationEnabledChange();
void effectiveTargetInformationChanged();
void usingDyldImageSuffixToggled(bool);
void usingDyldImageSuffixChanged(bool);
@@ -135,8 +130,6 @@ private:
private:
DesktopQmakeRunConfiguration *m_qmakeRunConfiguration = nullptr;
bool m_ignoreChange = false;
- QLabel *m_disabledIcon = nullptr;
- QLabel *m_disabledReason = nullptr;
QLabel *m_executableLineLabel = nullptr;
QCheckBox *m_useQvfbCheck = nullptr;
QCheckBox *m_usingDyldImageSuffix = nullptr;
diff --git a/src/plugins/qmakeprojectmanager/externaleditors.h b/src/plugins/qmakeprojectmanager/externaleditors.h
index 413b46a7d1..b7441501c4 100644
--- a/src/plugins/qmakeprojectmanager/externaleditors.h
+++ b/src/plugins/qmakeprojectmanager/externaleditors.h
@@ -33,7 +33,6 @@
#include <QMap>
QT_BEGIN_NAMESPACE
-class QProcess;
class QTcpSocket;
QT_END_NAMESPACE
diff --git a/src/plugins/qmakeprojectmanager/makefileparse.h b/src/plugins/qmakeprojectmanager/makefileparse.h
index aefc81e1f5..9a2abeb00e 100644
--- a/src/plugins/qmakeprojectmanager/makefileparse.h
+++ b/src/plugins/qmakeprojectmanager/makefileparse.h
@@ -29,10 +29,6 @@
#include <qtsupport/baseqtversion.h>
#include <qmakeprojectmanager/qmakestep.h>
-QT_BEGIN_NAMESPACE
-class QLogggingCategory;
-QT_END_NAMESPACE
-
namespace QmakeProjectManager {
namespace Internal {
diff --git a/src/plugins/qmakeprojectmanager/makestep.cpp b/src/plugins/qmakeprojectmanager/makestep.cpp
index de4666461b..24c480ffc9 100644
--- a/src/plugins/qmakeprojectmanager/makestep.cpp
+++ b/src/plugins/qmakeprojectmanager/makestep.cpp
@@ -127,10 +127,10 @@ QString MakeStep::effectiveMakeCommand() const
QVariantMap MakeStep::toMap() const
{
QVariantMap map(AbstractProcessStep::toMap());
- map.insert(QLatin1String(MAKE_ARGUMENTS_KEY), m_userArgs);
- map.insert(QLatin1String(MAKE_COMMAND_KEY), m_makeCmd);
- map.insert(QLatin1String(CLEAN_KEY), m_clean);
- map.insert(QLatin1String(AUTOMATICLY_ADDED_MAKE_ARGUMENTS_KEY), automaticallyAddedArguments());
+ map.insert(MAKE_ARGUMENTS_KEY, m_userArgs);
+ map.insert(MAKE_COMMAND_KEY, m_makeCmd);
+ map.insert(CLEAN_KEY, m_clean);
+ map.insert(AUTOMATICLY_ADDED_MAKE_ARGUMENTS_KEY, automaticallyAddedArguments());
return map;
}
@@ -139,20 +139,20 @@ QStringList MakeStep::automaticallyAddedArguments() const
ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
if (!tc || tc->targetAbi().binaryFormat() == Abi::PEFormat)
return QStringList();
- return QStringList() << QLatin1String("-w") << QLatin1String("-r");
+ return QStringList() << "-w" << "-r";
}
bool MakeStep::fromMap(const QVariantMap &map)
{
- m_makeCmd = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString();
- m_userArgs = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toString();
- m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool();
+ m_makeCmd = map.value(MAKE_COMMAND_KEY).toString();
+ m_userArgs = map.value(MAKE_ARGUMENTS_KEY).toString();
+ m_clean = map.value(CLEAN_KEY).toBool();
QStringList oldAddedArgs
- = map.value(QLatin1String(AUTOMATICLY_ADDED_MAKE_ARGUMENTS_KEY)).toStringList();
+ = map.value(AUTOMATICLY_ADDED_MAKE_ARGUMENTS_KEY).toStringList();
foreach (const QString &newArg, automaticallyAddedArguments()) {
if (oldAddedArgs.contains(newArg))
continue;
- m_userArgs.prepend(newArg + QLatin1Char(' '));
+ m_userArgs.prepend(newArg + ' ');
}
return AbstractProcessStep::fromMap(map);
@@ -199,28 +199,28 @@ bool MakeStep::init(QList<const BuildStep *> &earlierSteps)
if (subProFile) {
QString makefile = subProFile->makefile();
if (makefile.isEmpty())
- makefile = QLatin1String("Makefile");
+ makefile = "Makefile";
// Use Makefile.Debug and Makefile.Release
// for file builds, since the rules for that are
// only in those files.
if (subProFile->isDebugAndRelease() && bc->fileNodeBuild()) {
if (bc->buildType() == QmakeBuildConfiguration::Debug)
- makefile += QLatin1String(".Debug");
+ makefile += ".Debug";
else
- makefile += QLatin1String(".Release");
+ makefile += ".Release";
}
- if (makefile != QLatin1String("Makefile")) {
- Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
+ if (makefile != "Makefile") {
+ Utils::QtcProcess::addArg(&args, "-f");
Utils::QtcProcess::addArg(&args, makefile);
}
m_makeFileToCheck = QDir(workingDirectory).filePath(makefile);
} else {
if (!bc->makefile().isEmpty()) {
- Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
+ Utils::QtcProcess::addArg(&args, "-f");
Utils::QtcProcess::addArg(&args, bc->makefile());
m_makeFileToCheck = QDir(workingDirectory).filePath(bc->makefile());
} else {
- m_makeFileToCheck = QDir(workingDirectory).filePath(QLatin1String("Makefile"));
+ m_makeFileToCheck = QDir(workingDirectory).filePath("Makefile");
}
}
@@ -231,16 +231,16 @@ bool MakeStep::init(QList<const BuildStep *> &earlierSteps)
objectsDir = subProFile->buildDir(bc).toString();
if (subProFile->isDebugAndRelease()) {
if (bc->buildType() == QmakeBuildConfiguration::Debug)
- objectsDir += QLatin1String("/debug");
+ objectsDir += "/debug";
else
- objectsDir += QLatin1String("/release");
+ objectsDir += "/release";
}
}
QString relObjectsDir = QDir(pp->workingDirectory()).relativeFilePath(objectsDir);
- if (relObjectsDir == QLatin1String("."))
+ if (relObjectsDir == ".")
relObjectsDir.clear();
if (!relObjectsDir.isEmpty())
- relObjectsDir += QLatin1Char('/');
+ relObjectsDir += '/';
QString objectFile = relObjectsDir +
bc->fileNodeBuild()->filePath().toFileInfo().baseName() +
subProFile->objectExtension();
@@ -252,8 +252,8 @@ bool MakeStep::init(QList<const BuildStep *> &earlierSteps)
if (tc && makeCommand().isEmpty()) {
if (tc->targetAbi().os() == Abi::WindowsOS
&& tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor) {
- const QString makeFlags = QLatin1String("MAKEFLAGS");
- env.set(makeFlags, QLatin1Char('L') + env.value(makeFlags));
+ const QString makeFlags = "MAKEFLAGS";
+ env.set(makeFlags, 'L' + env.value(makeFlags));
}
}
@@ -322,7 +322,7 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep)
m_ui->makePathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_ui->makePathChooser->setBaseDirectory(Utils::PathChooser::homePath());
- m_ui->makePathChooser->setHistoryCompleter(QLatin1String("PE.MakeCommand.History"));
+ m_ui->makePathChooser->setHistoryCompleter("PE.MakeCommand.History");
const QString &makeCmd = m_makeStep->makeCommand();
m_ui->makePathChooser->setPath(makeCmd);
@@ -434,8 +434,8 @@ void MakeStepConfigWidget::updateDetails()
if (tc && m_makeStep->makeCommand().isEmpty()) {
if (tc->targetAbi().os() == Abi::WindowsOS
&& tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor) {
- const QString makeFlags = QLatin1String("MAKEFLAGS");
- env.set(makeFlags, QLatin1Char('L') + env.value(makeFlags));
+ const QString makeFlags = "MAKEFLAGS";
+ env.set(makeFlags, 'L' + env.value(makeFlags));
}
}
param.setArguments(args);
@@ -502,7 +502,7 @@ BuildStep *MakeStepFactory::create(BuildStepList *parent, Core::Id id)
MakeStep *step = new MakeStep(parent);
if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
step->setClean(true);
- step->setUserArguments(QLatin1String("clean"));
+ step->setUserArguments("clean");
}
return step;
}
diff --git a/src/plugins/qmakeprojectmanager/makestep.h b/src/plugins/qmakeprojectmanager/makestep.h
index 9f0abc9192..72a0b54e2e 100644
--- a/src/plugins/qmakeprojectmanager/makestep.h
+++ b/src/plugins/qmakeprojectmanager/makestep.h
@@ -32,7 +32,6 @@
namespace ProjectExplorer {
class BuildStep;
class IBuildStepFactory;
-class Task;
}
namespace QmakeProjectManager {
diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp
index 97c119c456..637cb1b239 100644
--- a/src/plugins/qmakeprojectmanager/profileeditor.cpp
+++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp
@@ -46,6 +46,8 @@
#include <QDir>
#include <QTextBlock>
+#include <algorithm>
+
using namespace TextEditor;
using namespace Utils;
@@ -89,7 +91,40 @@ ProFileEditorWidget::Link ProFileEditorWidget::findLinkAt(const QTextCursor &cur
// find the beginning of a filename
QString buffer;
int beginPos = positionInBlock - 1;
- while (beginPos >= 0) {
+ int endPos = positionInBlock;
+
+ // Check is cursor is somewhere on $${PWD}:
+ const int chunkStart = std::max(0, positionInBlock - 7);
+ const int chunkLength = 14 + std::min(0, positionInBlock - 7);
+ QString chunk = block.mid(chunkStart, chunkLength);
+
+ const QString curlyPwd = "$${PWD}";
+ const QString pwd = "$$PWD";
+ const int posCurlyPwd = chunk.indexOf(curlyPwd);
+ const int posPwd = chunk.indexOf(pwd);
+ bool doBackwardScan = true;
+
+ if (posCurlyPwd >= 0) {
+ const int end = chunkStart + posCurlyPwd + curlyPwd.count();
+ const int start = chunkStart + posCurlyPwd;
+ if (start <= positionInBlock && end >= positionInBlock) {
+ buffer = pwd;
+ beginPos = chunkStart + posCurlyPwd - 1;
+ endPos = end;
+ doBackwardScan = false;
+ }
+ } else if (posPwd >= 0) {
+ const int end = chunkStart + posPwd + pwd.count();
+ const int start = chunkStart + posPwd;
+ if (start <= positionInBlock && end >= positionInBlock) {
+ buffer = pwd;
+ beginPos = start - 1;
+ endPos = end;
+ doBackwardScan = false;
+ }
+ }
+
+ while (doBackwardScan && beginPos >= 0) {
QChar c = block.at(beginPos);
if (isValidFileNameChar(c)) {
buffer.prepend(c);
@@ -99,8 +134,20 @@ ProFileEditorWidget::Link ProFileEditorWidget::findLinkAt(const QTextCursor &cur
}
}
+ if (doBackwardScan
+ && beginPos > 0
+ && block.mid(beginPos - 1, pwd.count()) == pwd
+ && (block.at(beginPos + pwd.count() - 1) == '/' || block.at(beginPos + pwd.count() - 1) == '\\')) {
+ buffer.prepend("$$");
+ beginPos -= 2;
+ } else if (doBackwardScan
+ && beginPos >= curlyPwd.count() - 1
+ && block.mid(beginPos - curlyPwd.count() + 1, curlyPwd.count()) == curlyPwd) {
+ buffer.prepend(pwd);
+ beginPos -= curlyPwd.count();
+ }
+
// find the end of a filename
- int endPos = positionInBlock;
while (endPos < block.count()) {
QChar c = block.at(endPos);
if (isValidFileNameChar(c)) {
@@ -121,13 +168,8 @@ ProFileEditorWidget::Link ProFileEditorWidget::findLinkAt(const QTextCursor &cur
}
// if the buffer starts with $$PWD accept it
- if (buffer.startsWith(QLatin1String("PWD/")) ||
- buffer.startsWith(QLatin1String("PWD\\"))) {
- if (beginPos > 0 && block.mid(beginPos - 1, 2) == QLatin1String("$$")) {
- beginPos -=2;
- buffer = buffer.mid(4);
- }
- }
+ if (buffer.startsWith("$$PWD/") || buffer.startsWith("$$PWD\\"))
+ buffer = buffer.mid(6);
QDir dir(textDocument()->filePath().toFileInfo().absolutePath());
QString fileName = dir.filePath(buffer);
diff --git a/src/plugins/qmakeprojectmanager/profilehoverhandler.h b/src/plugins/qmakeprojectmanager/profilehoverhandler.h
index 381329a93c..cc9f91ef02 100644
--- a/src/plugins/qmakeprojectmanager/profilehoverhandler.h
+++ b/src/plugins/qmakeprojectmanager/profilehoverhandler.h
@@ -29,7 +29,6 @@
#include <texteditor/codeassist/keywordscompletionassist.h>
QT_BEGIN_NAMESPACE
-class QUrl;
QT_END_NAMESPACE
namespace QmakeProjectManager {
diff --git a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp
index 268b01dbc2..57550e2e52 100644
--- a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp
@@ -85,7 +85,8 @@ void QmakeKitInformation::setup(Kit *k)
ToolChain *tc = ToolChainKitInformation::toolChain(k, Constants::CXX_LANGUAGE_ID);
if (!tc || (!tc->suggestedMkspecList().empty() && !tc->suggestedMkspecList().contains(spec))) {
- const QList<ToolChain *> possibleTcs = ToolChainManager::toolChains([version, &spec](const ToolChain *t) {
+ const QList<ToolChain *> possibleTcs = ToolChainManager::toolChains(
+ [version](const ToolChain *t) {
return t->isValid()
&& t->language() == Core::Id(Constants::CXX_LANGUAGE_ID)
&& version->qtAbis().contains(t->targetAbi());
@@ -113,7 +114,7 @@ KitInformation::ItemList QmakeKitInformation::toUserOutput(const Kit *k) const
void QmakeKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
expander->registerVariable("Qmake:mkspec", tr("Mkspec configured for qmake by the Kit."),
- [this, kit]() -> QString {
+ [kit]() -> QString {
return QmakeKitInformation::mkspec(kit).toUserOutput();
});
}
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
index 007e47b018..f19723df95 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
@@ -74,12 +74,12 @@ QmakeProFileNode *QmakePriFileNode::proFileNode() const
return m_qmakeProFileNode;
}
-bool QmakePriFileNode::supportsAction(ProjectAction action, Node *node) const
+bool QmakePriFileNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == Rename || action == DuplicateFile) {
- FileNode *fileNode = node->asFileNode();
+ const FileNode *fileNode = node->asFileNode();
return (fileNode && fileNode->fileType() != FileType::Project)
- || dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(node);
+ || dynamic_cast<const ResourceEditor::ResourceTopLevelNode *>(node);
}
const FolderNode *folderNode = this;
@@ -109,7 +109,7 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, Node *node) const
bool addExistingFiles = true;
if (node->nodeType() == NodeType::VirtualFolder) {
// A virtual folder, we do what the projectexplorer does
- FolderNode *folder = node->asFolderNode();
+ const FolderNode *folder = node->asFolderNode();
if (folder) {
QStringList list;
foreach (FolderNode *f, folder->folderNodes())
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.h b/src/plugins/qmakeprojectmanager/qmakenodes.h
index 719e42a05a..aca17e18a2 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.h
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.h
@@ -47,7 +47,7 @@ public:
QmakePriFile *priFile() const;
// ProjectNode interface
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool showInSimpleTree() const override { return false; }
diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
index fea0898dde..a65b9cd44b 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp
@@ -37,9 +37,6 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
-#include <QApplication>
-#include <QStyle>
-
using namespace Core;
using namespace ProjectExplorer;
using namespace QtSupport;
@@ -106,23 +103,15 @@ QmakeStaticData::QmakeStaticData()
const unsigned count = sizeof(fileTypeDataStorage)/sizeof(FileTypeDataStorage);
fileTypeData.reserve(count);
- // Overlay the SP_DirIcon with the custom icons
- const QSize desiredSize = QSize(16, 16);
-
- const QPixmap dirPixmap = QApplication::style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize);
for (unsigned i = 0 ; i < count; ++i) {
- const QIcon overlayIcon(QLatin1String(fileTypeDataStorage[i].icon));
- QIcon folderIcon;
- folderIcon.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakePriFile", fileTypeDataStorage[i].typeName);
const QString filter = QString::fromUtf8(fileTypeDataStorage[i].addFileFilter);
fileTypeData.push_back(QmakeStaticData::FileTypeData(fileTypeDataStorage[i].type,
- desc, filter, folderIcon));
+ desc, filter,
+ Core::FileIconProvider::directoryIcon(QLatin1String(fileTypeDataStorage[i].icon))));
}
// Project icon
- const QIcon projectBaseIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
- const QPixmap projectPixmap = FileIconProvider::overlayIcon(dirPixmap, projectBaseIcon);
- projectIcon.addPixmap(projectPixmap);
+ projectIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
qAddPostRoutine(clearQmakeStaticData);
}
diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
index 1611156d6b..38e25554cf 100644
--- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp
@@ -1184,9 +1184,9 @@ void QmakeProFile::asyncUpdate()
m_parseFutureWatcher.waitForFinished();
QmakeEvalInput input = evalInput();
QFuture<QmakeEvalResult *> future = Utils::runAsync(ProjectExplorerPlugin::sharedThreadPool(),
- QThread::LowestPriority,
- &QmakeProFile::asyncEvaluate,
- this, input);
+ QThread::LowestPriority,
+ &QmakeProFile::asyncEvaluate,
+ this, input);
m_parseFutureWatcher.setFuture(future);
}
@@ -1473,7 +1473,7 @@ void QmakeProFile::asyncEvaluate(QFutureInterface<QmakeEvalResult *> &fi, QmakeE
void QmakeProFile::applyAsyncEvaluate()
{
applyEvaluate(m_parseFutureWatcher.result());
- m_project->decrementPendingEvaluateFutures();
+ m_project->decrementPendingEvaluateFutures(validParse());
}
bool sortByParserNodes(Node *a, Node *b)
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index cca96c070e..c3b847447a 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -290,9 +290,13 @@ void QmakeProject::updateCppCodeModel()
rpp.setDisplayName(pro->displayName());
rpp.setProjectFileLocation(pro->filePath().toString());
rpp.setBuildSystemTarget(pro->targetInformation().target);
+ const bool isExecutable = pro->projectType() == ProjectType::ApplicationTemplate;
+ rpp.setBuildTargetType(isExecutable ? CppTools::ProjectPart::Executable
+ : CppTools::ProjectPart::Library);
+
// TODO: Handle QMAKE_CFLAGS
rpp.setFlagsForCxx({cxxToolChain, pro->variableValue(Variable::CppFlags)});
- rpp.setDefines(pro->cxxDefines());
+ rpp.setMacros(ProjectExplorer::Macro::toMacros(pro->cxxDefines()));
rpp.setPreCompiledHeaders(pro->variableValue(Variable::PrecompiledHeader));
rpp.setSelectedForBuilding(pro->includedInExactParse());
@@ -410,6 +414,7 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFile *file, QmakeProFile::AsyncUp
return;
}
+ emitParsingStarted();
file->setParseInProgressRecursive(true);
setAllBuildConfigurationsEnabled(false);
@@ -466,6 +471,7 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFile::AsyncUpdateDelay delay)
return;
}
+ emitParsingStarted();
rootProFile()->setParseInProgressRecursive(true);
setAllBuildConfigurationsEnabled(false);
@@ -494,19 +500,26 @@ void QmakeProject::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay)
void QmakeProject::incrementPendingEvaluateFutures()
{
++m_pendingEvaluateFuturesCount;
+ if (m_pendingEvaluateFuturesCount == 1)
+ m_totalEvaluationSuccess = true;
m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(),
- m_asyncUpdateFutureInterface->progressMaximum() + 1);
+ m_asyncUpdateFutureInterface->progressMaximum() + 1);
}
-void QmakeProject::decrementPendingEvaluateFutures()
+void QmakeProject::decrementPendingEvaluateFutures(bool success)
{
--m_pendingEvaluateFuturesCount;
+ m_totalEvaluationSuccess = m_totalEvaluationSuccess && success;
+
m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1);
if (m_pendingEvaluateFuturesCount == 0) {
// We are done!
setRootProjectNode(QmakeNodeTreeBuilder::buildTree(this));
+ if (!m_totalEvaluationSuccess)
+ m_asyncUpdateFutureInterface->reportCanceled();
+
m_asyncUpdateFutureInterface->reportFinished();
delete m_asyncUpdateFutureInterface;
m_asyncUpdateFutureInterface = nullptr;
@@ -514,6 +527,7 @@ void QmakeProject::decrementPendingEvaluateFutures()
// TODO clear the profile cache ?
if (m_asyncUpdateState == AsyncFullUpdatePending || m_asyncUpdateState == AsyncPartialUpdatePending) {
+ // Already parsing!
rootProFile()->setParseInProgressRecursive(true);
setAllBuildConfigurationsEnabled(false);
startAsyncTimer(QmakeProFile::ParseLater);
@@ -528,7 +542,7 @@ void QmakeProject::decrementPendingEvaluateFutures()
activeTarget()->updateDefaultDeployConfigurations();
updateRunConfigurations();
emit proFilesEvaluated();
- emit parsingFinished();
+ emitParsingFinished(true); // Qmake always returns (some) data, even when it failed:-)
}
}
}
@@ -725,22 +739,6 @@ QmakeProFileNode *QmakeProject::rootProjectNode() const
return static_cast<QmakeProFileNode *>(Project::rootProjectNode());
}
-bool QmakeProject::validParse(const FileName &proFilePath) const
-{
- if (!rootProFile())
- return false;
- const QmakeProFile *pro = rootProFile()->findProFile(proFilePath);
- return pro && pro->validParse();
-}
-
-bool QmakeProject::parseInProgress(const FileName &proFilePath) const
-{
- if (!rootProFile())
- return false;
- const QmakeProFile *pro = rootProFile()->findProFile(proFilePath);
- return pro && pro->parseInProgress();
-}
-
QList<QmakeProFile *>
QmakeProject::collectAllProFiles(QmakeProFile *file, Parsing parse,
const QList<ProjectType> &projectTypes)
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h
index 590fe4f46e..b8d3192f09 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.h
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.h
@@ -68,8 +68,6 @@ public:
bool supportsKit(ProjectExplorer::Kit *k, QString *errorMesage) const final;
QmakeProFileNode *rootProjectNode() const final;
- bool validParse(const Utils::FileName &proFilePath) const;
- bool parseInProgress(const Utils::FileName &proFilePath) const;
virtual QStringList filesGeneratedFrom(const QString &file) const final;
@@ -102,7 +100,7 @@ public:
/// \internal
void incrementPendingEvaluateFutures();
/// \internal
- void decrementPendingEvaluateFutures();
+ void decrementPendingEvaluateFutures(bool success);
/// \internal
bool wasEvaluateCanceled();
@@ -188,6 +186,7 @@ private:
// cached data during project rescan
QMakeGlobals *m_qmakeGlobals = nullptr;
int m_qmakeGlobalsRefCnt = 0;
+ bool m_totalEvaluationSuccess = false;
QString m_qmakeSysroot;
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp
index 8a71762ef3..4d62b47075 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp
@@ -98,8 +98,15 @@ QmakeProjectConfigWidget::QmakeProjectConfigWidget(QmakeBuildConfiguration *bc)
this, &QmakeProjectConfigWidget::shadowBuildEdited);
QmakeProject *project = static_cast<QmakeProject *>(bc->target()->project());
- connect(project, &QmakeProject::environmentChanged,
- this, &QmakeProjectConfigWidget::environmentChanged);
+ project->subscribeSignal(&BuildConfiguration::environmentChanged, this, [this]() {
+ if (static_cast<BuildConfiguration *>(sender())->isActive())
+ environmentChanged();
+ });
+ connect(project, &Project::activeProjectConfigurationChanged,
+ this, [this](ProjectConfiguration *pc) {
+ if (pc && pc->isActive())
+ environmentChanged();
+ });
connect(project, &QmakeProject::buildDirectoryInitialized,
this, &QmakeProjectConfigWidget::updateProblemLabel);
connect(project, &QmakeProject::proFilesEvaluated,
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h
index 31829d8acd..a698653d7e 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.h
@@ -35,7 +35,6 @@ namespace Utils { class DetailsWidget; }
namespace QmakeProjectManager {
class QmakeBuildConfiguration;
-class QmakeProFileNode;
namespace Internal {
namespace Ui { class QmakeProjectConfigWidget; }
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
index 666ec0ce51..bfcc2f3d50 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
@@ -55,7 +55,7 @@ namespace QmakeProjectManager {
Node *QmakeManager::contextNode()
{
- return ProjectTree::currentNode();
+ return ProjectTree::findCurrentNode();
}
Project *QmakeManager::contextProject()
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs
index 3e6bff6572..027173ce51 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs
@@ -16,6 +16,7 @@ Project {
Depends { name: "CppTools" }
Depends { name: "TextEditor" }
Depends { name: "ResourceEditor" }
+ Depends { name: "app_version_header" }
pluginRecommends: [
"Designer"
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
index 817676bfee..ee18fd8e9f 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
@@ -279,8 +279,8 @@ void QmakeProjectManagerPlugin::projectChanged()
if (m_previousStartupProject) {
connect(m_previousStartupProject, &Project::activeTargetChanged,
- this, &QmakeProjectManagerPlugin::activeTargetChanged);
- connect(m_previousStartupProject, &QmakeProject::parsingFinished,
+ this, &QmakeProjectManagerPlugin::activeTargetChanged);
+ connect(m_previousStartupProject, &Project::parsingFinished,
this, &QmakeProjectManagerPlugin::updateActions);
}
@@ -326,22 +326,22 @@ void QmakeProjectManagerPlugin::updateRunQMakeAction()
void QmakeProjectManagerPlugin::updateContextActions()
{
- Node *node = ProjectTree::currentNode();
+ const Node *node = ProjectTree::findCurrentNode();
Project *project = ProjectTree::currentProject();
- ContainerNode *containerNode = node ? node->asContainerNode() : nullptr;
- QmakeProFileNode *proFileNode = dynamic_cast<QmakeProFileNode *>(containerNode ? containerNode->rootProjectNode() : node);
+ const ContainerNode *containerNode = node ? node->asContainerNode() : nullptr;
+ const QmakeProFileNode *proFileNode = dynamic_cast<const QmakeProFileNode *>(containerNode ? containerNode->rootProjectNode() : node);
m_addLibraryActionContextMenu->setEnabled(proFileNode);
QmakeProject *qmakeProject = qobject_cast<QmakeProject *>(QmakeManager::contextProject());
QmakeProFileNode *subProjectNode = nullptr;
if (node) {
- auto subPriFileNode = dynamic_cast<QmakePriFileNode *>(node);
+ auto subPriFileNode = dynamic_cast<const QmakePriFileNode *>(node);
if (!subPriFileNode)
subPriFileNode = dynamic_cast<QmakePriFileNode *>(node->parentProjectNode());
subProjectNode = subPriFileNode ? subPriFileNode->proFileNode() : nullptr;
}
- FileNode *fileNode = node ? node->asFileNode() : nullptr;
+ const FileNode *fileNode = node ? node->asFileNode() : nullptr;
bool buildFilePossible = subProjectNode && fileNode && (fileNode->fileType() == FileType::Source);
bool subProjectActionsVisible = false;
diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp
index 54c8d0989d..dd5fa50979 100644
--- a/src/plugins/qmakeprojectmanager/qmakestep.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp
@@ -134,10 +134,10 @@ QString QMakeStep::allArguments(const BaseQtVersion *v, bool shorted) const
arguments << project()->projectFilePath().toUserOutput();
if (v->qtVersion() < QtVersionNumber(5, 0, 0))
- arguments << QLatin1String("-r");
+ arguments << "-r";
bool userProvidedMkspec = false;
for (QtcProcess::ConstArgIterator ait(m_userArgs); ait.next(); ) {
- if (ait.value() == QLatin1String("-spec")) {
+ if (ait.value() == "-spec") {
if (ait.next()) {
userProvidedMkspec = true;
break;
@@ -146,7 +146,7 @@ QString QMakeStep::allArguments(const BaseQtVersion *v, bool shorted) const
}
FileName specArg = mkspec();
if (!userProvidedMkspec && !specArg.isEmpty())
- arguments << QLatin1String("-spec") << specArg.toUserOutput();
+ arguments << "-spec" << specArg.toUserOutput();
// Find out what flags we pass on to qmake
arguments << bc->configCommandLineArguments();
@@ -538,7 +538,7 @@ FileName QMakeStep::mkspec() const
QString additionalArguments = m_userArgs;
QtcProcess::addArgs(&additionalArguments, m_extraArgs);
for (QtcProcess::ArgIterator ait(&additionalArguments); ait.next(); ) {
- if (ait.value() == QLatin1String("-spec")) {
+ if (ait.value() == "-spec") {
if (ait.next())
return FileName::fromUserInput(ait.value());
}
@@ -550,31 +550,31 @@ FileName QMakeStep::mkspec() const
QVariantMap QMakeStep::toMap() const
{
QVariantMap map(AbstractProcessStep::toMap());
- map.insert(QLatin1String(QMAKE_ARGUMENTS_KEY), m_userArgs);
- map.insert(QLatin1String(QMAKE_QMLDEBUGLIB_KEY), m_linkQmlDebuggingLibrary);
- map.insert(QLatin1String(QMAKE_FORCED_KEY), m_forced);
- map.insert(QLatin1String(QMAKE_USE_QTQUICKCOMPILER), m_useQtQuickCompiler);
- map.insert(QLatin1String(QMAKE_SEPARATEDEBUGINFO_KEY), m_separateDebugInfo);
+ map.insert(QMAKE_ARGUMENTS_KEY, m_userArgs);
+ map.insert(QMAKE_QMLDEBUGLIB_KEY, m_linkQmlDebuggingLibrary);
+ map.insert(QMAKE_FORCED_KEY, m_forced);
+ map.insert(QMAKE_USE_QTQUICKCOMPILER, m_useQtQuickCompiler);
+ map.insert(QMAKE_SEPARATEDEBUGINFO_KEY, m_separateDebugInfo);
return map;
}
bool QMakeStep::fromMap(const QVariantMap &map)
{
- m_userArgs = map.value(QLatin1String(QMAKE_ARGUMENTS_KEY)).toString();
- m_forced = map.value(QLatin1String(QMAKE_FORCED_KEY), false).toBool();
- m_useQtQuickCompiler = map.value(QLatin1String(QMAKE_USE_QTQUICKCOMPILER), false).toBool();
+ m_userArgs = map.value(QMAKE_ARGUMENTS_KEY).toString();
+ m_forced = map.value(QMAKE_FORCED_KEY, false).toBool();
+ m_useQtQuickCompiler = map.value(QMAKE_USE_QTQUICKCOMPILER, false).toBool();
// QMAKE_QMLDEBUGLIBAUTO_KEY was used in versions 2.3 to 3.5 (both included) to automatically
// change the qml_debug CONFIG flag based no the qmake build configuration.
- if (map.value(QLatin1String(QMAKE_QMLDEBUGLIBAUTO_KEY), false).toBool()) {
+ if (map.value(QMAKE_QMLDEBUGLIBAUTO_KEY, false).toBool()) {
m_linkQmlDebuggingLibrary =
project()->projectLanguages().contains(
ProjectExplorer::Constants::QMLJS_LANGUAGE_ID) &&
(qmakeBuildConfiguration()->qmakeBuildConfiguration() & BaseQtVersion::DebugBuild);
} else {
- m_linkQmlDebuggingLibrary = map.value(QLatin1String(QMAKE_QMLDEBUGLIB_KEY), false).toBool();
+ m_linkQmlDebuggingLibrary = map.value(QMAKE_QMLDEBUGLIB_KEY, false).toBool();
}
- m_separateDebugInfo = map.value(QLatin1String(QMAKE_SEPARATEDEBUGINFO_KEY), false).toBool();
+ m_separateDebugInfo = map.value(QMAKE_SEPARATEDEBUGINFO_KEY, false).toBool();
return BuildStep::fromMap(map);
}
@@ -910,7 +910,7 @@ ProjectExplorer::BuildStep *QMakeStepFactory::clone(BuildStepList *parent, Proje
QMakeStepConfig::TargetArchConfig QMakeStepConfig::targetArchFor(const Abi &targetAbi, const BaseQtVersion *version)
{
QMakeStepConfig::TargetArchConfig arch = QMakeStepConfig::NoArch;
- if (!version || version->type() != QLatin1String(QtSupport::Constants::DESKTOPQT))
+ if (!version || version->type() != QtSupport::Constants::DESKTOPQT)
return arch;
if ((targetAbi.os() == ProjectExplorer::Abi::DarwinOS)
&& (targetAbi.binaryFormat() == ProjectExplorer::Abi::MachOFormat)) {
@@ -933,7 +933,7 @@ QMakeStepConfig::OsType QMakeStepConfig::osTypeFor(const ProjectExplorer::Abi &t
{
QMakeStepConfig::OsType os = QMakeStepConfig::NoOsType;
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios";
- if (!version || version->type() != QLatin1String(IOSQT))
+ if (!version || version->type() != IOSQT)
return os;
if ((targetAbi.os() == ProjectExplorer::Abi::DarwinOS)
&& (targetAbi.binaryFormat() == ProjectExplorer::Abi::MachOFormat)) {
@@ -950,29 +950,28 @@ QStringList QMakeStepConfig::toArguments() const
{
QStringList arguments;
if (archConfig == X86)
- arguments << QLatin1String("CONFIG+=x86");
+ arguments << "CONFIG+=x86";
else if (archConfig == X86_64)
- arguments << QLatin1String("CONFIG+=x86_64");
+ arguments << "CONFIG+=x86_64";
else if (archConfig == PowerPC)
- arguments << QLatin1String("CONFIG+=ppc");
+ arguments << "CONFIG+=ppc";
else if (archConfig == PowerPC64)
- arguments << QLatin1String("CONFIG+=ppc64");
+ arguments << "CONFIG+=ppc64";
// TODO: make that depend on the actual Qt version that is used
if (osType == IphoneSimulator)
- arguments << QLatin1String("CONFIG+=iphonesimulator") << QLatin1String("CONFIG+=simulator") /*since Qt 5.7*/;
+ arguments << "CONFIG+=iphonesimulator" << "CONFIG+=simulator" /*since Qt 5.7*/;
else if (osType == IphoneOS)
- arguments << QLatin1String("CONFIG+=iphoneos") << QLatin1String("CONFIG+=device") /*since Qt 5.7*/;
+ arguments << "CONFIG+=iphoneos" << "CONFIG+=device" /*since Qt 5.7*/;
if (linkQmlDebuggingQQ2)
- arguments << QLatin1String("CONFIG+=qml_debug");
+ arguments << "CONFIG+=qml_debug";
if (useQtQuickCompiler)
- arguments << QLatin1String("CONFIG+=qtquickcompiler");
+ arguments << "CONFIG+=qtquickcompiler";
if (separateDebugInfo)
- arguments << QLatin1String("CONFIG+=force_debug_info")
- << QLatin1String("CONFIG+=separate_debug_info");
+ arguments << "CONFIG+=force_debug_info" << "CONFIG+=separate_debug_info";
return arguments;
}
diff --git a/src/plugins/qmakeprojectmanager/qmakestep.h b/src/plugins/qmakeprojectmanager/qmakestep.h
index a69db1113e..caf12b129a 100644
--- a/src/plugins/qmakeprojectmanager/qmakestep.h
+++ b/src/plugins/qmakeprojectmanager/qmakestep.h
@@ -38,7 +38,6 @@ class Abi;
class BuildStep;
class IBuildStepFactory;
class Project;
-class Kit;
} // namespace ProjectExplorer
namespace QtSupport { class BaseQtVersion; }
diff --git a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp
index 04e7656173..d6bfb86551 100644
--- a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp
+++ b/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp
@@ -27,6 +27,8 @@
#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
+#include <app/app_version.h>
+
#include <coreplugin/basefilewizard.h>
#include <coreplugin/icore.h>
@@ -134,9 +136,10 @@ SimpleProjectWizard::SimpleProjectWizard()
setDisplayName(tr("Import as qmake Project (Limited Functionality)"));
setId("Z.DummyProFile");
setDescription(tr("Imports existing projects that do not use qmake, CMake or Autotools.<p>"
- "This creates a qmake .pro file that allows you to use Qt Creator as a code editor "
+ "This creates a qmake .pro file that allows you to use %1 as a code editor "
"and as a launcher for debugging and analyzing tools. "
- "If you want to build the project, you might need to edit the generated .pro file."));
+ "If you want to build the project, you might need to edit the generated .pro file.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
setCategory(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY);
setDisplayCategory(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY_DISPLAY);
setFlags(IWizardFactory::PlatformIndependent);
@@ -200,7 +203,8 @@ GeneratedFiles SimpleProjectWizard::generateFiles(const QWizard *w,
GeneratedFile generatedProFile(proFileName);
generatedProFile.setAttributes(Core::GeneratedFile::OpenProjectAttribute);
generatedProFile.setContents(
- "# Created by and for Qt Creator. This file was created for editing the project sources only.\n"
+ "# Created by and for " + QLatin1String(Core::Constants::IDE_DISPLAY_NAME)
+ + " This file was created for editing the project sources only.\n"
"# You may attempt to use it for building too, by modifying this file here.\n\n"
"#TARGET = " + projectName + "\n\n"
+ proHeaders + "\n\n"
diff --git a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
index 812f49f9f5..e365918586 100644
--- a/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/changestyleaction.cpp
@@ -92,7 +92,7 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
connect(comboBox,
static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
this,
- [comboBox, this](const QString &style) {
+ [this](const QString &style) {
if (style.isEmpty())
return;
diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
index 6b0015f082..1ef51816dc 100644
--- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
+++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
@@ -80,10 +80,6 @@ const char positionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContext
const char layoutCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout");
const char stackedContainerCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Stacked Container");
-const char selectParentDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select Parent: %1");
-const char selectDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1");
-const char deSelectDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Deselect: ");
-
const char cutSelectionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Cut");
const char copySelectionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Copy");
const char pasteSelectionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Paste");
diff --git a/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp b/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp
index 24bffa14d0..1d88bf56a0 100644
--- a/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/findimplementation.cpp
@@ -231,7 +231,7 @@ private:
QString m_typeName;
QString m_itemId;
- const ObjectValue *m_typeValue;
+ const ObjectValue *m_typeValue = nullptr;
bool m_insideObject = false;
};
diff --git a/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp b/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
index c3cf12d3cc..298eb855c3 100644
--- a/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/selectioncontext.cpp
@@ -30,15 +30,10 @@
namespace QmlDesigner {
-SelectionContext::SelectionContext() :
- m_toggled(false)
-{
-
-}
+SelectionContext::SelectionContext() = default;
SelectionContext::SelectionContext(AbstractView *view) :
- m_view(view),
- m_toggled(false)
+ m_view(view)
{
}
diff --git a/src/plugins/qmldesigner/components/componentcore/selectioncontext.h b/src/plugins/qmldesigner/components/componentcore/selectioncontext.h
index 17e5981e6d..594fc2f6e5 100644
--- a/src/plugins/qmldesigner/components/componentcore/selectioncontext.h
+++ b/src/plugins/qmldesigner/components/componentcore/selectioncontext.h
@@ -65,9 +65,9 @@ public:
private:
QPointer<AbstractView> m_view;
ModelNode m_targetNode;
- bool m_showSelectionTools;
QPointF m_scenePosition;
- bool m_toggled;
+ bool m_showSelectionTools = false;
+ bool m_toggled = false;
};
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorindicatorgraphicsitem.h b/src/plugins/qmldesigner/components/formeditor/anchorindicatorgraphicsitem.h
index a6cc8a8f17..16946b392f 100644
--- a/src/plugins/qmldesigner/components/formeditor/anchorindicatorgraphicsitem.h
+++ b/src/plugins/qmldesigner/components/formeditor/anchorindicatorgraphicsitem.h
@@ -57,8 +57,8 @@ private:
QPointF m_sourceAnchorLineSecondPoint;
QPointF m_targetAnchorLineFirstPoint;
QPointF m_targetAnchorLineSecondPoint;
- AnchorLineType m_sourceAnchorLineType;
- AnchorLineType m_targetAnchorLineType;
+ AnchorLineType m_sourceAnchorLineType = AnchorLineInvalid;
+ AnchorLineType m_targetAnchorLineType = AnchorLineInvalid;
QRectF m_boundingRect;
};
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp b/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp
index c9d3898504..a4f2f3bff0 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp
@@ -52,6 +52,7 @@ FormEditorToolButton::FormEditorToolButton(QAction *action, QGraphicsItem *paren
setEnabled(m_action->isEnabled());
setVisible(m_action->isVisible());
+ setCursor(Qt::ArrowCursor);
}
void FormEditorToolButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
diff --git a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp
index d0c7b9e5bc..a6e5314343 100644
--- a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp
+++ b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.cpp
@@ -33,6 +33,9 @@
#include "qproxystyle.h"
#include "metainfo.h"
+
+#include <utils/qtcassert.h>
+
#include <QLineEdit>
#include <QPen>
#include <QPixmapCache>
@@ -42,11 +45,11 @@
namespace QmlDesigner {
IconCheckboxItemDelegate::IconCheckboxItemDelegate(QObject *parent,
- const QPixmap &checkedPixmap,
- const QPixmap &uncheckedPixmap)
+ const QIcon &checkedIcon,
+ const QIcon &uncheckedIcon)
: QStyledItemDelegate(parent),
- m_checkedPixmap(checkedPixmap),
- m_uncheckedPixmap(uncheckedPixmap)
+ m_checkedIcon(checkedIcon),
+ m_uncheckedIcon(uncheckedIcon)
{}
QSize IconCheckboxItemDelegate::sizeHint(const QStyleOptionViewItem & /*option*/,
@@ -82,25 +85,28 @@ void IconCheckboxItemDelegate::paint(QPainter *painter,
if (rowIsPropertyRole(modelIndex.model(), modelIndex))
return; //Do not paint icons for property rows
- const int yOffset = (styleOption.rect.height()
- - (m_checkedPixmap.height() / painter->device()->devicePixelRatio())) / 2;
- const int xOffset = 2;
-
- painter->save();
if (styleOption.state & QStyle::State_Selected)
NavigatorTreeView::drawSelectionBackground(painter, styleOption);
if (!getModelNode(modelIndex).isRootNode()) {
+ QWindow *window = dynamic_cast<QWidget*>(painter->device())->window()->windowHandle();
+ QTC_ASSERT(window, return);
- if (!isVisible(modelIndex))
+ const QRect iconRect(styleOption.rect.left() + 2, styleOption.rect.top() + 2, 16, 16);
+ const QIcon &icon = isChecked(modelIndex) ? m_checkedIcon : m_uncheckedIcon;
+ const QPixmap iconPixmap = icon.pixmap(window, iconRect.size());
+ const bool visible = isVisible(modelIndex);
+
+ if (!visible) {
+ painter->save();
painter->setOpacity(0.5);
+ }
- const bool checked = isChecked(modelIndex);
- painter->drawPixmap(styleOption.rect.x() + xOffset, styleOption.rect.y() + yOffset,
- checked ? m_checkedPixmap : m_uncheckedPixmap);
- }
+ painter->drawPixmap(iconRect.topLeft(), iconPixmap);
- painter->restore();
+ if (!visible)
+ painter->restore();
+ }
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h
index a21f333809..17f9a3537e 100644
--- a/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h
+++ b/src/plugins/qmldesigner/components/navigator/iconcheckboxitemdelegate.h
@@ -35,8 +35,8 @@ class IconCheckboxItemDelegate : public QStyledItemDelegate
{
public:
explicit IconCheckboxItemDelegate(QObject *parent,
- const QPixmap &checkedPixmap,
- const QPixmap &uncheckedPixmap);
+ const QIcon &checkedIcon,
+ const QIcon &uncheckedIcon);
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const;
@@ -46,7 +46,7 @@ public:
const QModelIndex &index) const;
private:
- const QPixmap m_checkedPixmap;
- const QPixmap m_uncheckedPixmap;
+ const QIcon m_checkedIcon;
+ const QIcon m_uncheckedIcon;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/navigator.qrc b/src/plugins/qmldesigner/components/navigator/navigator.qrc
index 41599b77be..aa28a4aaee 100644
--- a/src/plugins/qmldesigner/components/navigator/navigator.qrc
+++ b/src/plugins/qmldesigner/components/navigator/navigator.qrc
@@ -12,6 +12,5 @@
<file>export_checked@2x.png</file>
<file>export_unchecked.png</file>
<file>export_unchecked@2x.png</file>
- <file>warning.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h
index 243aa489cf..bedcc2f561 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatormodelinterface.h
@@ -43,6 +43,8 @@ public:
virtual void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
+ virtual void setFilter(bool showObjects) = 0;
+ virtual void resetModel() = 0;
};
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 0b6c3cc6ae..3b78b09de1 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -246,6 +246,16 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const
| Qt::ItemNeverHasChildren;
}
+QList<ModelNode> filteredList(const NodeListProperty &property, bool filter)
+{
+ if (!filter)
+ return property.toModelNodeList();
+
+ return Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
+ return QmlItemNode::isValidQmlItemNode(arg);
+ });
+}
+
QModelIndex NavigatorTreeModel::index(int row, int column,
const QModelIndex &parent) const
{
@@ -262,7 +272,7 @@ QModelIndex NavigatorTreeModel::index(int row, int column,
ModelNode modelNode;
if (parentModelNode.defaultNodeListProperty().isValid())
- modelNode = parentModelNode.defaultNodeListProperty().at(row);
+ modelNode = filteredList(parentModelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).at(row);
if (!modelNode.isValid())
return QModelIndex();
@@ -293,7 +303,7 @@ QModelIndex NavigatorTreeModel::parent(const QModelIndex &index) const
int row = 0;
if (!parentModelNode.isRootNode() && parentModelNode.parentProperty().isNodeListProperty())
- row = parentModelNode.parentProperty().toNodeListProperty().indexOf(parentModelNode);
+ row = filteredList(parentModelNode.parentProperty().toNodeListProperty(), m_showOnlyVisibleItems).indexOf(parentModelNode);
return createIndexFromModelNode(row, 0, parentModelNode);
}
@@ -313,7 +323,7 @@ int NavigatorTreeModel::rowCount(const QModelIndex &parent) const
int rows = 0;
if (modelNode.defaultNodeListProperty().isValid())
- rows = modelNode.defaultNodeListProperty().count();
+ rows = filteredList(modelNode.defaultNodeListProperty(), m_showOnlyVisibleItems).count();
return rows;
}
@@ -628,4 +638,17 @@ void NavigatorTreeModel::notifyModelNodesMoved(const QList<ModelNode> &modelNode
layoutChanged(indexes);
}
+void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems)
+{
+ m_showOnlyVisibleItems = showOnlyVisibleItems;
+ resetModel();
+}
+
+void NavigatorTreeModel::resetModel()
+{
+ beginResetModel();
+ m_nodeIndexHash.clear();
+ endResetModel();
+}
+
} // QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
index 9b6e22b114..92b352fce5 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
@@ -87,6 +87,8 @@ public:
void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
+ void setFilter(bool showOnlyVisibleItems) override;
+ void resetModel() override;
private:
void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes, int targetIndex);
@@ -97,6 +99,7 @@ private:
QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;
+ bool m_showOnlyVisibleItems = true;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index 3db86f7009..48531cf82e 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -34,6 +34,7 @@
#include <bindingproperty.h>
#include <designmodecontext.h>
+#include <designersettings.h>
#include <nodeproperty.h>
#include <nodelistproperty.h>
#include <variantproperty.h>
@@ -88,22 +89,25 @@ NavigatorView::NavigatorView(QObject* parent) :
connect(m_widget.data(), &NavigatorWidget::rightButtonClicked, this, &NavigatorView::rightButtonClicked);
connect(m_widget.data(), &NavigatorWidget::downButtonClicked, this, &NavigatorView::downButtonClicked);
connect(m_widget.data(), &NavigatorWidget::upButtonClicked, this, &NavigatorView::upButtonClicked);
+ connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled);
#ifndef QMLDESIGNER_TEST
NameItemDelegate *idDelegate = new NameItemDelegate(this);
IconCheckboxItemDelegate *showDelegate =
new IconCheckboxItemDelegate(this,
- Utils::Icons::EYE_OPEN_TOOLBAR.pixmap(),
- Utils::Icons::EYE_CLOSED_TOOLBAR.pixmap());
+ Utils::Icons::EYE_OPEN_TOOLBAR.icon(),
+ Utils::Icons::EYE_CLOSED_TOOLBAR.icon());
IconCheckboxItemDelegate *exportDelegate =
new IconCheckboxItemDelegate(this,
- Icons::EXPORT_CHECKED.pixmap(),
- Icons::EXPORT_UNCHECKED.pixmap());
+ Icons::EXPORT_CHECKED.icon(),
+ Icons::EXPORT_UNCHECKED.icon());
#ifdef _LOCK_ITEMS_
- IconCheckboxItemDelegate *lockDelegate = new IconCheckboxItemDelegate(this,":/qmldesigner/images/lock.png",
- ":/qmldesigner/images/hole.png",m_treeModel.data());
+ IconCheckboxItemDelegate *lockDelegate =
+ new IconCheckboxItemDelegate(this,
+ Utils::Icons::LOCKED_TOOLBAR.icon(),
+ Utils::Icons::UNLOCKED_TOOLBAR.icon());
#endif
@@ -143,6 +147,9 @@ void NavigatorView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
+ m_currentModelInterface->setFilter(
+ DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool());
+
QTreeView *treeView = treeWidget();
treeView->expandAll();
@@ -398,6 +405,13 @@ void NavigatorView::downButtonClicked()
blockSelectionChangedSignal(blocked);
}
+void NavigatorView::filterToggled(bool flag)
+{
+ m_currentModelInterface->setFilter(flag);
+ treeWidget()->expandAll();
+ DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, flag);
+}
+
void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
{
if (m_blockSelectionChangedSignal)
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h
index 24c65f2eeb..d02a0d38fe 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h
@@ -99,6 +99,7 @@ private:
void rightButtonClicked();
void upButtonClicked();
void downButtonClicked();
+ void filterToggled(bool);
protected: //functions
QTreeView *treeWidget() const;
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
index d9794f6388..6f7995a185 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.cpp
@@ -27,14 +27,17 @@
#include "navigatorview.h"
#include "qmldesignerconstants.h"
#include "qmldesignericons.h"
+#include <designersettings.h>
#include <theme.h>
#include <QBoxLayout>
#include <QToolButton>
#include <QAbstractItemModel>
+#include <QMenu>
#include <QHeaderView>
#include <QtDebug>
#include <utils/fileutils.h>
+#include <utils/utilsicons.h>
namespace QmlDesigner {
@@ -80,29 +83,49 @@ QList<QToolButton *> NavigatorWidget::createToolBarWidgets()
{
QList<QToolButton *> buttons;
- buttons.append(new QToolButton());
- buttons.last()->setIcon(Icons::ARROW_LEFT.icon());
- buttons.last()->setToolTip(tr("Become last sibling of parent (CTRL + Left)."));
- buttons.last()->setShortcut(QKeySequence(Qt::Key_Left | Qt::CTRL));
- connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::leftButtonClicked);
-
- buttons.append(new QToolButton());
- buttons.last()->setIcon(Icons::ARROW_RIGHT.icon());
- buttons.last()->setToolTip(tr("Become child of last sibling (CTRL + Right)."));
- buttons.last()->setShortcut(QKeySequence(Qt::Key_Right | Qt::CTRL));
- connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::rightButtonClicked);
-
- buttons.append(new QToolButton());
- buttons.last()->setIcon(Icons::ARROW_DOWN.icon());
- buttons.last()->setToolTip(tr("Move down (CTRL + Down)."));
- buttons.last()->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL));
- connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::downButtonClicked);
-
- buttons.append(new QToolButton());
- buttons.last()->setIcon(Icons::ARROW_UP.icon());
- buttons.last()->setToolTip(tr("Move up (CTRL + Up)."));
- buttons.last()->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL));
- connect(buttons.last(), &QAbstractButton::clicked, this, &NavigatorWidget::upButtonClicked);
+
+ auto button = new QToolButton();
+ button->setIcon(Icons::ARROW_LEFT.icon());
+ button->setToolTip(tr("Become last sibling of parent (CTRL + Left)."));
+ button->setShortcut(QKeySequence(Qt::Key_Left | Qt::CTRL));
+ connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::leftButtonClicked);
+ buttons.append(button);
+
+ button = new QToolButton();
+ button->setIcon(Icons::ARROW_RIGHT.icon());
+ button->setToolTip(tr("Become child of last sibling (CTRL + Right)."));
+ button->setShortcut(QKeySequence(Qt::Key_Right | Qt::CTRL));
+ connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::rightButtonClicked);
+ buttons.append(button);
+
+ button = new QToolButton();
+ button->setIcon(Icons::ARROW_DOWN.icon());
+ button->setToolTip(tr("Move down (CTRL + Down)."));
+ button->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL));
+ connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::downButtonClicked);
+ buttons.append(button);
+
+ button = new QToolButton();
+ button->setIcon(Icons::ARROW_UP.icon());
+ button->setToolTip(tr("Move up (CTRL + Up)."));
+ button->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL));
+ connect(button, &QAbstractButton::clicked, this, &NavigatorWidget::upButtonClicked);
+ buttons.append(button);
+
+ auto filter = new QToolButton;
+ filter->setIcon(Utils::Icons::FILTER.icon());
+ filter->setToolTip(tr("Filter Tree"));
+ filter->setPopupMode(QToolButton::InstantPopup);
+ filter->setProperty("noArrow", true);
+ auto filterMenu = new QMenu(filter);
+ auto objectAction = new QAction(tr("Show only visible items."), nullptr);
+ objectAction->setCheckable(true);
+ objectAction->setChecked(
+ DesignerSettings::getValue(DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS).toBool());
+ connect(objectAction, &QAction::toggled, this, &NavigatorWidget::filterToggled);
+ filterMenu->addAction(objectAction);
+ filter->setMenu(filterMenu);
+ buttons.append(filter);
return buttons;
}
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
index 526004cf84..45e8b19c9b 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorwidget.h
@@ -53,6 +53,7 @@ signals:
void rightButtonClicked();
void upButtonClicked();
void downButtonClicked();
+ void filterToggled(bool);
private: // functions
NavigatorView *navigatorView() const;
diff --git a/src/plugins/qmldesigner/components/navigator/warning.png b/src/plugins/qmldesigner/components/navigator/warning.png
deleted file mode 100644
index 38a80acc1e..0000000000
--- a/src/plugins/qmldesigner/components/navigator/warning.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
index 4e8a390bfd..d44bcfc3d3 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/fileresourcesmodel.cpp
@@ -123,7 +123,7 @@ void FileResourcesModel::openFileDialog()
//If that one is not valid we try the path for the current file
if (path.isEmpty() && !m_fileName.isEmpty())
- path = QFileInfo(modelPath + QStringLiteral("/") + m_fileName.toString()).absoluteDir().absolutePath();
+ path = QFileInfo(modelPath + '/' + m_fileName.toString()).absolutePath();
//Next we try to fall back to the path any file browser was opened with
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.png b/src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.png
deleted file mode 100644
index b82f1fd006..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/button2_hovered.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.png b/src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.png
deleted file mode 100644
index 4fef115d3e..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/button2_normal.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.png b/src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.png
deleted file mode 100644
index 305530afaf..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/button2_pressed.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.png b/src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.png
deleted file mode 100644
index 2dc66ec3e3..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/button_hovered.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button_normal.png b/src/plugins/qmldesigner/components/propertyeditor/images/button_normal.png
deleted file mode 100644
index ca29772319..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/button_normal.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.png b/src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.png
deleted file mode 100644
index 7cf55d718d..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/button_pressed.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/frame.png b/src/plugins/qmldesigner/components/propertyeditor/images/frame.png
deleted file mode 100644
index a951609018..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/frame.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/images/gradient.png b/src/plugins/qmldesigner/components/propertyeditor/images/gradient.png
deleted file mode 100644
index ae48afbd7a..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/images/gradient.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
index 5336225b11..d822fbb70d 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.pri
@@ -27,5 +27,3 @@ HEADERS += propertyeditorview.h \
qmlmodelnodeproxy.h
QT += qml quick
-
-RESOURCES += propertyeditor.qrc
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc
deleted file mode 100644
index 61d22611ba..0000000000
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.qrc
+++ /dev/null
@@ -1,12 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>images/button_hovered.png</file>
- <file>images/button_normal.png</file>
- <file>images/button_pressed.png</file>
- <file>images/button2_hovered.png</file>
- <file>images/button2_normal.png</file>
- <file>images/button2_pressed.png</file>
- <file>images/frame.png</file>
- <file>images/gradient.png</file>
- </qresource>
-</RCC>
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index 80b3dc2924..4fa195b3c5 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -94,8 +94,6 @@ PropertyEditorQmlBackend::PropertyEditorQmlBackend(PropertyEditorView *propertyE
m_view(new Quick2PropertyEditorView), m_propertyEditorTransaction(new PropertyEditorTransaction(propertyEditor)), m_dummyPropertyEditorValue(new PropertyEditorValue()),
m_contextObject(new PropertyEditorContextObject())
{
- Q_ASSERT(QFileInfo(QLatin1String(":/images/button_normal.png")).exists());
-
m_view->engine()->setOutputWarningsToStandardError(QmlDesignerPlugin::instance()
->settings().value(DesignerSettingsKey::SHOW_PROPERTYEDITOR_WARNINGS).toBool());
diff --git a/src/plugins/qmldesigner/components/resources/resources.qrc b/src/plugins/qmldesigner/components/resources/resources.qrc
index 5b75f585a2..4100b9da6b 100644
--- a/src/plugins/qmldesigner/components/resources/resources.qrc
+++ b/src/plugins/qmldesigner/components/resources/resources.qrc
@@ -1,6 +1,5 @@
<RCC>
<qresource prefix="/qmldesigner">
- <file>templates/Standard/Form.xml</file>
<file>stylesheet.css</file>
<file>scrollbar.css</file>
<file>formeditorstylesheet.css</file>
diff --git a/src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml b/src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml
deleted file mode 100644
index 4a9aa660d5..0000000000
--- a/src/plugins/qmldesigner/components/resources/templates/Standard/Form.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<QWidget objectName="Form" width="186" height="141">
- <windowTitle><?i18n?>Form</windowTitle>
- <QVBoxLayout objectName="verticalLayout">
- <!--Start of QLayoutItem 1--><QLabel objectName="label">
- <text><?i18n?>Hello world</text>
- </QLabel>
- <!--End of QLayoutItem 1--><!--Start of QLayoutItem 1--><QPlainTextEdit objectName="plainTextEdit"/>
- <!--End of QLayoutItem 1--></QVBoxLayout>
-</QWidget>
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
index 5877424a14..698ce6afc0 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
@@ -173,9 +173,9 @@ void TextEditorView::selectedNodesChanged(const QList<ModelNode> &/*selectedNode
void TextEditorView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList<ModelNode> &/*nodeList*/, const QList<QVariant> &/*data*/)
{
if (identifier == StartRewriterApply)
- m_widget->setBlockCurserSelectionSyncronisation(true);
+ m_widget->setBlockCursorSelectionSynchronisation(true);
else if (identifier == EndRewriterApply)
- m_widget->setBlockCurserSelectionSyncronisation(false);
+ m_widget->setBlockCursorSelectionSynchronisation(false);
}
void TextEditorView::documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &)
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
index 591164138f..1062aa4a96 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
@@ -80,7 +80,7 @@ void TextEditorWidget::setTextEditor(TextEditor::BaseTextEditor *textEditor)
connect(textEditor->editorWidget(), &QPlainTextEdit::cursorPositionChanged,
this, [this]() {
/* Cursor position is changed by rewriter */
- if (!m_blockCurserSelectionSyncronisation)
+ if (!m_blockCursorSelectionSynchronisation)
m_updateSelectionTimer.start();
});
@@ -168,9 +168,9 @@ int TextEditorWidget::currentLine() const
return -1;
}
-void TextEditorWidget::setBlockCurserSelectionSyncronisation(bool b)
+void TextEditorWidget::setBlockCursorSelectionSynchronisation(bool b)
{
- m_blockCurserSelectionSyncronisation = b;
+ m_blockCursorSelectionSynchronisation = b;
}
bool TextEditorWidget::eventFilter( QObject *, QEvent *event)
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h
index 267f93a183..7ab245adbb 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h
@@ -59,7 +59,7 @@ public:
int currentLine() const;
- void setBlockCurserSelectionSyncronisation(bool b);
+ void setBlockCursorSelectionSynchronisation(bool b);
protected:
bool eventFilter(QObject *object, QEvent *event) override;
@@ -71,7 +71,7 @@ private:
QPointer<TextEditorView> m_textEditorView;
QTimer m_updateSelectionTimer;
TextEditorStatusBar *m_statusBar;
- bool m_blockCurserSelectionSyncronisation = false;
+ bool m_blockCursorSelectionSynchronisation = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/designercore-lib.pri b/src/plugins/qmldesigner/designercore/designercore-lib.pri
index 2acf492205..b7f36ac47c 100644
--- a/src/plugins/qmldesigner/designercore/designercore-lib.pri
+++ b/src/plugins/qmldesigner/designercore/designercore-lib.pri
@@ -78,7 +78,9 @@ SOURCES += $$PWD/model/abstractview.cpp \
$$PWD/model/signalhandlerproperty.cpp \
$$PWD/model/internalsignalhandlerproperty.cpp \
$$PWD/model/anchorline.cpp \
- $$PWD/instances/puppetdialog.cpp
+ $$PWD/instances/puppetdialog.cpp \
+ $$PWD/model/qmltimelinemutator.cpp \
+ $$PWD/model/qmltimelinekeyframes.cpp
HEADERS += $$PWD/include/qmldesignercorelib_global.h \
$$PWD/include/abstractview.h \
@@ -152,7 +154,9 @@ HEADERS += $$PWD/include/qmldesignercorelib_global.h \
$$PWD/include/signalhandlerproperty.h \
$$PWD/model/internalsignalhandlerproperty.h \
$$PWD/include/anchorline.h \
- $$PWD/instances/puppetdialog.h
+ $$PWD/instances/puppetdialog.h \
+ $$PWD/include/qmltimelinemutator.h \
+ $$PWD/include/qmltimelinekeyframes.h \
FORMS += \
$$PWD/instances/puppetdialog.ui
diff --git a/src/plugins/qmldesigner/designercore/filemanager/astobjecttextextractor.h b/src/plugins/qmldesigner/designercore/filemanager/astobjecttextextractor.h
index a1dfb7b71a..159b65bdd2 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/astobjecttextextractor.h
+++ b/src/plugins/qmldesigner/designercore/filemanager/astobjecttextextractor.h
@@ -45,7 +45,7 @@ protected:
private:
QmlJS::Document::MutablePtr m_document;
- quint32 m_location;
+ quint32 m_location = 0;
QString m_text;
};
diff --git a/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.h b/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.h
index 9aca188a60..fb306f8bc4 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.h
+++ b/src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.h
@@ -48,7 +48,7 @@ protected:
private:
QmlJS::Document::MutablePtr m_doc;
quint32 m_offset;
- QmlJS::AST::UiObjectDefinition *m_firstObjectDefinition;
+ QmlJS::AST::UiObjectDefinition *m_firstObjectDefinition = nullptr;
};
diff --git a/src/plugins/qmldesigner/designercore/filemanager/moveobjectbeforeobjectvisitor.h b/src/plugins/qmldesigner/designercore/filemanager/moveobjectbeforeobjectvisitor.h
index 909c77ef70..7b5f39d175 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/moveobjectbeforeobjectvisitor.h
+++ b/src/plugins/qmldesigner/designercore/filemanager/moveobjectbeforeobjectvisitor.h
@@ -67,8 +67,8 @@ private:
bool toEnd;
quint32 beforeObjectLocation;
- QmlJS::AST::UiObjectDefinition *movingObject;
- QmlJS::AST::UiObjectDefinition *beforeObject;
+ QmlJS::AST::UiObjectDefinition *movingObject = nullptr;
+ QmlJS::AST::UiObjectDefinition *beforeObject = nullptr;
ASTPath movingObjectParents;
};
diff --git a/src/plugins/qmldesigner/designercore/filemanager/objectlengthcalculator.h b/src/plugins/qmldesigner/designercore/filemanager/objectlengthcalculator.h
index e869bb98b4..1ff31837a1 100644
--- a/src/plugins/qmldesigner/designercore/filemanager/objectlengthcalculator.h
+++ b/src/plugins/qmldesigner/designercore/filemanager/objectlengthcalculator.h
@@ -45,8 +45,8 @@ protected:
private:
QmlJS::Document::MutablePtr m_doc;
- quint32 m_offset;
- quint32 m_length;
+ quint32 m_offset = 0;
+ quint32 m_length = 0;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h
index 6987d747df..8b085f9137 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractview.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractview.h
@@ -55,6 +55,7 @@ namespace QmlDesigner {
class NodeInstanceView;
class RewriterView;
class QmlModelState;
+class QmlTimelineMutator;
enum DesignerWidgetFlags {
DisableOnError,
@@ -232,6 +233,8 @@ public:
virtual void documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings);
+ virtual void currentTimelineChanged(const ModelNode &node);
+
void changeRootNodeType(const TypeName &type, int majorVersion, int minorVersion);
NodeInstanceView *nodeInstanceView() const;
@@ -240,6 +243,7 @@ public:
void setCurrentStateNode(const ModelNode &node);
ModelNode currentStateNode() const;
QmlModelState currentState() const;
+ QmlTimelineMutator currentTimeline() const;
int majorQtQuickVersion() const;
int minorQtQuickVersion() const;
@@ -253,6 +257,9 @@ public:
virtual QString contextHelpId() const;
+ void activateTimelineRecording(const ModelNode &mutator);
+ void deactivateTimelineRecording();
+
protected:
void setModel(Model * model);
void removeModel();
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index 800ef1baad..ebaaf93b3d 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -193,7 +193,6 @@ private: //variables
QHash<ModelNode, NodeInstance> m_nodeInstanceHash;
QHash<ModelNode, QImage> m_statePreviewImage;
- uint m_blockUpdates;
QPointer<NodeInstanceServerInterface> m_nodeInstanceServer;
QImage m_baseStatePreviewImage;
QTime m_lastCrashTime;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
index 3e9d5ff7e4..e5d5891076 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
@@ -28,6 +28,7 @@
#include <qmldesignercorelib_global.h>
#include "qmlmodelnodefacade.h"
#include "qmlstate.h"
+#include "qmltimelinemutator.h"
#include "qmlchangeset.h"
#include <nodeinstance.h>
@@ -63,6 +64,7 @@ public:
QString validId();
QmlModelState currentState() const;
+ QmlTimelineMutator currentTimeline() const;
void setVariantProperty(const PropertyName &name, const QVariant &value);
void setBindingProperty(const PropertyName &name, const QString &expression);
NodeAbstractProperty nodeAbstractProperty(const PropertyName &name) const;
@@ -83,6 +85,7 @@ public:
QString stripedTranslatableText(const PropertyName &name) const;
QString expression(const PropertyName &name) const;
bool isInBaseState() const;
+ bool timelineIsActive() const;
QmlPropertyChanges propertyChangeForCurrentState() const;
virtual bool instanceCanReparent() const;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlstate.h b/src/plugins/qmldesigner/designercore/include/qmlstate.h
index 4ee216f84f..ac6dd39b57 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlstate.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlstate.h
@@ -72,7 +72,6 @@ public:
protected:
void addChangeSetIfNotExists(const ModelNode &node);
static QmlModelState createBaseState(const AbstractView *view);
-
};
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/qmltimelinekeyframes.h b/src/plugins/qmldesigner/designercore/include/qmltimelinekeyframes.h
new file mode 100644
index 0000000000..2969d4dd9a
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/qmltimelinekeyframes.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <qmldesignercorelib_global.h>
+#include "qmlmodelnodefacade.h"
+#include "qmlchangeset.h"
+
+namespace QmlDesigner {
+
+class AbstractViewAbstractVieweGroup;
+class QmlObjectNode;
+
+class QMLDESIGNERCORE_EXPORT QmlTimelineFrames : public QmlModelNodeFacade
+{
+
+public:
+ QmlTimelineFrames();
+ QmlTimelineFrames(const ModelNode &modelNode);
+
+ bool isValid() const;
+ static bool isValidQmlTimelineFrames(const ModelNode &modelNode);
+ void destroy();
+
+ ModelNode target() const;
+ void setTarget(const ModelNode &target);
+
+ PropertyName propertyName() const;
+ void setPropertyName(const PropertyName &propertyName);
+
+ void setValue(const QVariant &value, qreal frame);
+ QVariant value(qreal frame) const;
+
+ qreal currentFrame() const;
+
+ bool hasKeyframe(qreal frame);
+
+ static bool isValidKeyframe(const ModelNode &node);
+ static QmlTimelineFrames keyframesForKeyframe(const ModelNode &node);
+};
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h b/src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h
new file mode 100644
index 0000000000..10e00fc7b3
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/qmltimelinemutator.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <qmldesignercorelib_global.h>
+#include "qmlmodelnodefacade.h"
+
+namespace QmlDesigner {
+
+class AbstractViewAbstractVieweGroup;
+class QmlObjectNode;
+class QmlModelStateGroup;
+class QmlTimelineFrames;
+
+class QMLDESIGNERCORE_EXPORT QmlTimelineMutator : public QmlModelNodeFacade
+{
+
+public:
+ QmlTimelineMutator();
+ QmlTimelineMutator(const ModelNode &modelNode);
+
+ bool isValid() const;
+ static bool isValidQmlTimelineMutator(const ModelNode &modelNode);
+ void destroy();
+
+ QmlTimelineFrames timelineFrames(const ModelNode &modelNode, const PropertyName &propertyName);
+ bool hasTimeline(const ModelNode &modelNode, const PropertyName &propertyName);
+
+ qreal startFrame() const;
+ qreal endFrame() const;
+ qreal currentFrame() const;
+
+private:
+ void addFramesIfNotExists(const ModelNode &node, const PropertyName &propertyName);
+ bool hasFrames(const ModelNode &node, const PropertyName &propertyName) const;
+ QList<QmlTimelineFrames> allTimelineFrames() const;
+};
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
index e8fbe3a71c..eebf3c0f8d 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
@@ -107,15 +107,7 @@ NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceV
: NodeInstanceServerInterface(nodeInstanceView),
m_localServer(new QLocalServer(this)),
m_nodeInstanceView(nodeInstanceView),
- m_firstBlockSize(0),
- m_secondBlockSize(0),
- m_thirdBlockSize(0),
- m_writeCommandCounter(0),
- m_firstLastReadCommandCounter(0),
- m_secondLastReadCommandCounter(0),
- m_thirdLastReadCommandCounter(0),
- m_runModus(runModus),
- m_synchronizeId(-1)
+ m_runModus(runModus)
{
if (instanceViewBenchmark().isInfoEnabled())
m_benchmarkTimer.start();
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
index 9ab15b15c7..4cf8f1241e 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
@@ -118,15 +118,15 @@ private:
QPointer<QProcess> m_qmlPuppetEditorProcess;
QPointer<QProcess> m_qmlPuppetPreviewProcess;
QPointer<QProcess> m_qmlPuppetRenderProcess;
- quint32 m_firstBlockSize;
- quint32 m_secondBlockSize;
- quint32 m_thirdBlockSize;
- quint32 m_writeCommandCounter;
- quint32 m_firstLastReadCommandCounter;
- quint32 m_secondLastReadCommandCounter;
- quint32 m_thirdLastReadCommandCounter;
+ quint32 m_firstBlockSize = 0;
+ quint32 m_secondBlockSize = 0;
+ quint32 m_thirdBlockSize = 0;
+ quint32 m_writeCommandCounter = 0;
+ quint32 m_firstLastReadCommandCounter = 0;
+ quint32 m_secondLastReadCommandCounter = 0;
+ quint32 m_thirdLastReadCommandCounter = 0;
RunModus m_runModus;
- int m_synchronizeId;
+ int m_synchronizeId = -1;
QTime m_benchmarkTimer;
};
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index b7acd55c45..1f972b68a7 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -43,6 +43,9 @@
#include "nodelistproperty.h"
#include "nodeproperty.h"
#include "qmlchangeset.h"
+#include "qmlstate.h"
+#include "qmltimelinemutator.h"
+#include "qmltimelinekeyframes.h"
#include "createscenecommand.h"
#include "createinstancescommand.h"
@@ -651,13 +654,13 @@ void NodeInstanceView::updateChildren(const NodeAbstractProperty &newPropertyPar
void setXValue(NodeInstance &instance, const VariantProperty &variantProperty, QMultiHash<ModelNode, InformationName> &informationChangeHash)
{
instance.setX(variantProperty.value().toDouble());
- informationChangeHash.insert(variantProperty.parentModelNode(), Transform);
+ informationChangeHash.insert(instance.modelNode(), Transform);
}
void setYValue(NodeInstance &instance, const VariantProperty &variantProperty, QMultiHash<ModelNode, InformationName> &informationChangeHash)
{
instance.setY(variantProperty.value().toDouble());
- informationChangeHash.insert(variantProperty.parentModelNode(), Transform);
+ informationChangeHash.insert(instance.modelNode(), Transform);
}
@@ -668,7 +671,7 @@ void NodeInstanceView::updatePosition(const QList<VariantProperty> &propertyList
foreach (const VariantProperty &variantProperty, propertyList) {
if (variantProperty.name() == "x") {
const ModelNode modelNode = variantProperty.parentModelNode();
- if (QmlPropertyChanges::isValidQmlPropertyChanges(modelNode)) {
+ if (!currentState().isBaseState() && QmlPropertyChanges::isValidQmlPropertyChanges(modelNode)) {
ModelNode targetModelNode = QmlPropertyChanges(modelNode).target();
if (targetModelNode.isValid()) {
NodeInstance instance = instanceForModelNode(targetModelNode);
@@ -680,7 +683,7 @@ void NodeInstanceView::updatePosition(const QList<VariantProperty> &propertyList
}
} else if (variantProperty.name() == "y") {
const ModelNode modelNode = variantProperty.parentModelNode();
- if (QmlPropertyChanges::isValidQmlPropertyChanges(modelNode)) {
+ if (!currentState().isBaseState() && QmlPropertyChanges::isValidQmlPropertyChanges(modelNode)) {
ModelNode targetModelNode = QmlPropertyChanges(modelNode).target();
if (targetModelNode.isValid()) {
NodeInstance instance = instanceForModelNode(targetModelNode);
@@ -690,6 +693,21 @@ void NodeInstanceView::updatePosition(const QList<VariantProperty> &propertyList
NodeInstance instance = instanceForModelNode(modelNode);
setYValue(instance, variantProperty, informationChangeHash);
}
+ } else if (currentTimeline().isValid()
+ && variantProperty.name() == "value"
+ && QmlTimelineFrames::isValidKeyframe(variantProperty.parentModelNode())) {
+
+ QmlTimelineFrames frames = QmlTimelineFrames::keyframesForKeyframe(variantProperty.parentModelNode());
+
+ if (frames.isValid() && frames.propertyName() == "x" && frames.target().isValid()) {
+
+ NodeInstance instance = instanceForModelNode(frames.target());
+ setXValue(instance, variantProperty, informationChangeHash);
+ } else if (frames.isValid() && frames.propertyName() == "y" && frames.target().isValid()) {
+ NodeInstance instance = instanceForModelNode(frames.target());
+ setYValue(instance, variantProperty, informationChangeHash);
+ }
+
}
}
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
index 90f72c5d73..c5bb6e9d12 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
@@ -549,7 +549,8 @@ bool PuppetCreator::startBuildProcess(const QString &buildDirectoryPath,
process.setProcessEnvironment(processEnvironment());
process.setWorkingDirectory(buildDirectoryPath);
process.start(command, processArguments);
- process.waitForStarted();
+ if (!process.waitForStarted())
+ return false;
while (process.waitForReadyRead(100) || process.state() == QProcess::Running) {
if (progressDialog->useFallbackPuppet())
return false;
@@ -565,8 +566,8 @@ bool PuppetCreator::startBuildProcess(const QString &buildDirectoryPath,
process.waitForFinished();
- qCInfo(puppetBuild) << Q_FUNC_INFO;
- qCInfo(puppetBuild) << m_compileLog;
+ qCInfo(puppetBuild) << Q_FUNC_INFO;
+ qCInfo(puppetBuild) << m_compileLog;
if (process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0)
return true;
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index f8092b9c7f..57ce5f8ddc 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -30,6 +30,7 @@
#include "internalnode_p.h"
#include "nodeinstanceview.h"
#include <qmlstate.h>
+#include <qmltimelinemutator.h>
#ifndef QMLDESIGNER_TEST
#include <qmldesignerplugin.h>
@@ -359,6 +360,11 @@ void AbstractView::documentMessagesChanged(const QList<DocumentMessage> &/*error
{
}
+void AbstractView::currentTimelineChanged(const ModelNode & /*node*/)
+{
+
+}
+
QList<ModelNode> AbstractView::toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList) const
{
return QmlDesigner::toModelNodeList(nodeList, const_cast<AbstractView*>(this));
@@ -565,6 +571,21 @@ QString AbstractView::contextHelpId() const
return helpId;
}
+void AbstractView::activateTimelineRecording(const ModelNode &mutator)
+{
+ Internal::WriteLocker locker(m_model.data());
+ if (model())
+ model()->d->notifyCurrentTimelineChanged(mutator);
+
+}
+
+void AbstractView::deactivateTimelineRecording()
+{
+ Internal::WriteLocker locker(m_model.data());
+ if (model())
+ model()->d->notifyCurrentTimelineChanged(ModelNode());
+}
+
QList<ModelNode> AbstractView::allModelNodes() const
{
return toModelNodeList(model()->d->allNodes());
@@ -688,6 +709,16 @@ QmlModelState AbstractView::currentState() const
return QmlModelState(currentStateNode());
}
+QmlTimelineMutator AbstractView::currentTimeline() const
+{
+ if (model())
+ return QmlTimelineMutator(ModelNode(m_model.data()->d->currentTimelineNode(),
+ m_model.data(),
+ const_cast<AbstractView*>(this)));
+
+ return QmlTimelineMutator();
+}
+
static int getMinorVersionFromImport(const Model *model)
{
foreach (const Import &import, model->imports()) {
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode_p.h b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
index c19fca55a8..9f70fe1e94 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode_p.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
@@ -150,7 +150,7 @@ private:
QStringList m_scriptFunctionList;
QString m_nodeSource;
- int m_nodeSourceType;
+ int m_nodeSourceType = 0;
};
uint qHash(const InternalNodePointer& node);
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index 011a5271d3..561910006c 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -85,6 +85,7 @@ ModelPrivate::ModelPrivate(Model *model) :
{
m_rootInternalNode = createNode("QtQuick.Item", 1, 0, PropertyListType(), PropertyListType(), QString(), ModelNode::NodeWithoutSource,true);
m_currentStateNode = m_rootInternalNode;
+ m_currentTimelineMutatorNode = m_rootInternalNode;
}
ModelPrivate::~ModelPrivate()
@@ -641,6 +642,33 @@ void ModelPrivate::notifyCurrentStateChanged(const ModelNode &node)
resetModelByRewriter(description);
}
+void ModelPrivate::notifyCurrentTimelineChanged(const ModelNode &node)
+{
+ bool resetModel = false;
+ QString description;
+
+ m_currentTimelineMutatorNode = node.internalNode();
+
+ try {
+ if (rewriterView())
+ rewriterView()->currentTimelineChanged(ModelNode(node.internalNode(), model(), rewriterView()));
+ } catch (const RewritingException &e) {
+ description = e.description();
+ resetModel = true;
+ }
+
+ for (const QPointer<AbstractView> &view : m_viewList) {
+ Q_ASSERT(view != 0);
+ view->currentTimelineChanged(ModelNode(node.internalNode(), model(), view.data()));
+ }
+
+ if (nodeInstanceView())
+ nodeInstanceView()->currentTimelineChanged(ModelNode(node.internalNode(), model(), nodeInstanceView()));
+
+ if (resetModel)
+ resetModelByRewriter(description);
+}
+
void ModelPrivate::notifyRewriterBeginTransaction()
{
bool resetModel = false;
@@ -1707,6 +1735,11 @@ NodeInstanceView *ModelPrivate::nodeInstanceView() const
return m_nodeInstanceView.data();
}
+InternalNodePointer ModelPrivate::currentTimelineNode() const
+{
+ return m_currentTimelineMutatorNode;
+}
+
InternalNodePointer ModelPrivate::nodeForId(const QString &id) const
{
return m_idNodeHash.value(id);
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index 882ea0599d..f67e59aed1 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -157,6 +157,7 @@ public:
void notifyInstanceToken(const QString &token, int number, const QVector<ModelNode> &nodeVector);
void notifyCurrentStateChanged(const ModelNode &node);
+ void notifyCurrentTimelineChanged(const ModelNode &node);
void setDocumentMessages(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings);
@@ -226,6 +227,7 @@ public:
NodeInstanceView *nodeInstanceView() const;
InternalNodePointer currentStateNode() const;
+ InternalNodePointer currentTimelineNode() const;
private: //functions
void removePropertyWithoutNotification(const InternalPropertyPointer &property);
@@ -249,6 +251,7 @@ private:
QSet<InternalNodePointer> m_nodeSet;
InternalNodePointer m_currentStateNode;
InternalNodePointer m_rootInternalNode;
+ InternalNodePointer m_currentTimelineMutatorNode;
QUrl m_fileUrl;
QPointer<RewriterView> m_rewriterView;
QPointer<NodeInstanceView> m_nodeInstanceView;
diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
index ce53270814..d73f96df94 100644
--- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
@@ -749,10 +749,6 @@ bool operator <(const ModelNode &firstNode, const ModelNode &secondNode)
Internal::InternalNodePointer ModelNode::internalNode() const
{
- if (!isValid()) {
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "model node is invalid");
- throw InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
- }
return m_internalNode;
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
index 4c58c15dc1..218601d409 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
@@ -26,6 +26,7 @@
#include "qmlobjectnode.h"
#include "qmlitemnode.h"
#include "qmlstate.h"
+#include "qmltimelinekeyframes.h"
#include "variantproperty.h"
#include "nodeproperty.h"
#include <invalidmodelnodeexception.h>
@@ -48,6 +49,19 @@ void QmlObjectNode::setVariantProperty(const PropertyName &name, const QVariant
if (!isValid())
throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ if (timelineIsActive()) {
+ modelNode().validId();
+
+ QmlTimelineFrames timelineFrames(currentTimeline().timelineFrames(modelNode(), name));
+
+ Q_ASSERT(timelineFrames.isValid());
+
+ qreal frame = currentTimeline().modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
+ timelineFrames.setValue(value, frame);
+
+ return;
+ }
+
if (isInBaseState()) {
modelNode().variantProperty(name).setValue(value); //basestate
} else {
@@ -83,6 +97,14 @@ QmlModelState QmlObjectNode::currentState() const
return QmlModelState();
}
+QmlTimelineMutator QmlObjectNode::currentTimeline() const
+{
+ if (isValid())
+ return view()->currentTimeline();
+ else
+ return QmlTimelineMutator();
+}
+
bool QmlObjectNode::isRootModelNode() const
{
return modelNode().isRootNode();
@@ -161,6 +183,9 @@ bool QmlObjectNode::propertyAffectedByCurrentState(const PropertyName &name) con
if (currentState().isBaseState())
return modelNode().hasProperty(name);
+ if (timelineIsActive() && currentTimeline().hasTimeline(modelNode(), name))
+ return true;
+
if (!currentState().hasPropertyChanges(modelNode()))
return false;
@@ -172,6 +197,21 @@ QVariant QmlObjectNode::modelValue(const PropertyName &name) const
if (!isValid())
throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+ if (timelineIsActive() && currentTimeline().hasTimeline(modelNode(), name)) {
+ QmlTimelineFrames timelineFrames(currentTimeline().timelineFrames(modelNode(), name));
+
+ Q_ASSERT(timelineFrames.isValid());
+
+ qreal frame = currentTimeline().modelNode().auxiliaryData("currentFrame@NodeInstance").toReal();
+
+ QVariant value = timelineFrames.value(frame);
+
+ if (!value.isValid()) //interpolation is not done in the model
+ value = instanceValue(name);
+
+ return value;
+ }
+
if (currentState().isBaseState())
return modelNode().variantProperty(name).value();
@@ -239,6 +279,11 @@ bool QmlObjectNode::isInBaseState() const
return currentState().isBaseState();
}
+bool QmlObjectNode::timelineIsActive() const
+{
+ return currentTimeline().isValid();
+}
+
bool QmlObjectNode::instanceCanReparent() const
{
return isInBaseState();
diff --git a/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframes.cpp b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframes.cpp
new file mode 100644
index 0000000000..959f2ea3f6
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/qmltimelinekeyframes.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmltimelinekeyframes.h"
+#include "abstractview.h"
+#include <nodelistproperty.h>
+#include <variantproperty.h>
+#include <metainfo.h>
+#include <invalidmodelnodeexception.h>
+#include "bindingproperty.h"
+#include "qmlitemnode.h"
+
+#include <utils/qtcassert.h>
+
+namespace QmlDesigner {
+
+QmlTimelineFrames::QmlTimelineFrames()
+{
+
+}
+
+QmlTimelineFrames::QmlTimelineFrames(const ModelNode &modelNode) : QmlModelNodeFacade(modelNode)
+{
+
+}
+
+bool QmlTimelineFrames::isValid() const
+{
+ return isValidQmlTimelineFrames(modelNode());
+}
+
+bool QmlTimelineFrames::isValidQmlTimelineFrames(const ModelNode &modelNode)
+{
+ return isValidQmlModelNodeFacade(modelNode)
+ && modelNode.metaInfo().isValid()
+ && modelNode.metaInfo().isSubclassOf("QtQuick.Timeline.Keyframes");
+}
+
+void QmlTimelineFrames::destroy()
+{
+ Q_ASSERT(isValid());
+ modelNode().destroy();
+}
+
+ModelNode QmlTimelineFrames::target() const
+{
+ if (modelNode().property("target").isBindingProperty())
+ return modelNode().bindingProperty("target").resolveToModelNode();
+ else
+ return ModelNode(); //exception?
+}
+
+void QmlTimelineFrames::setTarget(const ModelNode &target)
+{
+ modelNode().bindingProperty("target").setExpression(target.id());
+}
+
+
+PropertyName QmlTimelineFrames::propertyName() const
+{
+ return modelNode().variantProperty("property").value().toString().toUtf8();
+}
+
+void QmlTimelineFrames::setPropertyName(const PropertyName &propertyName)
+{
+ modelNode().variantProperty("property").setValue(QString::fromUtf8(propertyName));
+}
+
+void QmlTimelineFrames::setValue(const QVariant &value, qreal currentFrame)
+{
+
+ for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) {
+ if (qFuzzyCompare(childNode.variantProperty("frame").value().toReal(), currentFrame)) {
+ childNode.variantProperty("value").setValue(value);
+ return;
+ }
+ }
+
+ const QList<QPair<PropertyName, QVariant> > propertyPairList{{PropertyName("frame"), QVariant(currentFrame)},
+ {PropertyName("value"), value}};
+
+ ModelNode frame = modelNode().view()->createModelNode("QtQuick.Timeline.Keyframe", 1, 0, propertyPairList);
+ modelNode().defaultNodeListProperty().reparentHere(frame);
+}
+
+QVariant QmlTimelineFrames::value(qreal frame) const
+{
+ for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) {
+ if (qFuzzyCompare(childNode.variantProperty("frame").value().toReal(), frame)) {
+ return childNode.variantProperty("value").value();
+ }
+ }
+
+ return QVariant();
+}
+
+bool QmlTimelineFrames::hasKeyframe(qreal frame)
+{
+ for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) {
+ if (qFuzzyCompare(childNode.variantProperty("frame").value().toReal(), frame))
+ return true;
+ }
+
+ return false;
+}
+
+bool QmlTimelineFrames::isValidKeyframe(const ModelNode &node)
+{
+ return isValidQmlModelNodeFacade(node)
+ && node.metaInfo().isValid()
+ && node.metaInfo().isSubclassOf("QtQuick.Timeline.Keyframe");
+}
+
+QmlTimelineFrames QmlTimelineFrames::keyframesForKeyframe(const ModelNode &node)
+{
+ if (isValidKeyframe(node) && node.hasParentProperty()) {
+ const QmlTimelineFrames timeline(node.parentProperty().parentModelNode());
+ if (timeline.isValid())
+ return timeline;
+ }
+
+ return QmlTimelineFrames();
+}
+
+} // QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp b/src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp
new file mode 100644
index 0000000000..a028b61890
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/qmltimelinemutator.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmltimelinemutator.h"
+#include "qmltimelinekeyframes.h"
+#include "abstractview.h"
+#include <nodelistproperty.h>
+#include <variantproperty.h>
+#include <nodelistproperty.h>
+#include <metainfo.h>
+#include <invalidmodelnodeexception.h>
+#include "bindingproperty.h"
+#include "qmlitemnode.h"
+
+#include <utils/qtcassert.h>
+
+namespace QmlDesigner {
+
+QmlTimelineMutator::QmlTimelineMutator()
+{
+
+}
+
+QmlTimelineMutator::QmlTimelineMutator(const ModelNode &modelNode) : QmlModelNodeFacade(modelNode)
+{
+
+}
+
+bool QmlTimelineMutator::isValid() const
+{
+ return isValidQmlTimelineMutator(modelNode());
+}
+
+bool QmlTimelineMutator::isValidQmlTimelineMutator(const ModelNode &modelNode)
+{
+ return isValidQmlModelNodeFacade(modelNode)
+ && modelNode.metaInfo().isValid()
+ && modelNode.metaInfo().isSubclassOf("QtQuick.Timeline.KeyframeMutator");
+}
+
+void QmlTimelineMutator::destroy()
+{
+ Q_ASSERT(isValid());
+ modelNode().destroy();
+}
+
+QmlTimelineFrames QmlTimelineMutator::timelineFrames(const ModelNode &node, const PropertyName &propertyName)
+{
+ if (isValid()) {
+ addFramesIfNotExists(node, propertyName);
+ for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) {
+ if (QmlTimelineFrames::isValidQmlTimelineFrames(childNode)) {
+ const QmlTimelineFrames frames(childNode);
+
+ if (frames.target().isValid()
+ && frames.target() == node
+ && frames.propertyName() == propertyName)
+ return frames;
+ }
+ }
+ }
+
+ return QmlTimelineFrames(); //not found
+}
+
+bool QmlTimelineMutator::hasTimeline(const ModelNode &node, const PropertyName &propertyName)
+{
+ if (isValid()) {
+ for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) {
+ if (QmlTimelineFrames::isValidQmlTimelineFrames(childNode)) {
+ const QmlTimelineFrames frames(childNode);
+
+ if (frames.target().isValid()
+ && frames.target() == node
+ && frames.propertyName() == propertyName)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+qreal QmlTimelineMutator::startFrame() const
+{
+ if (isValid())
+ return QmlObjectNode(modelNode()).instanceValue("startFrame").toReal();
+ return 0;
+}
+
+qreal QmlTimelineMutator::endFrame() const
+{
+ if (isValid())
+ return QmlObjectNode(modelNode()).instanceValue("endFrame").toReal();
+ return 0;
+}
+
+qreal QmlTimelineMutator::currentFrame() const
+{
+ if (isValid())
+ return QmlObjectNode(modelNode()).instanceValue("currentFrame").toReal();
+ return 0;
+}
+
+void QmlTimelineMutator::addFramesIfNotExists(const ModelNode &node, const PropertyName &propertyName)
+{
+ if (!isValid())
+ throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
+
+ if (!hasFrames(node, propertyName)) {
+ ModelNode frames = modelNode().view()->createModelNode("QtQuick.Timeline.Keyframes", 1, 0);
+ modelNode().defaultNodeListProperty().reparentHere(frames);
+
+ QmlTimelineFrames(frames).setTarget(node);
+ QmlTimelineFrames(frames).setPropertyName(propertyName);
+
+ Q_ASSERT(QmlTimelineFrames::isValidQmlTimelineFrames(frames));
+ }
+}
+
+
+bool QmlTimelineMutator::hasFrames(const ModelNode &node, const PropertyName &propertyName) const
+{
+ for (const QmlTimelineFrames &frames : allTimelineFrames()) {
+ if (frames.target().isValid()
+ && frames.target() == node
+ && frames.propertyName() == propertyName)
+ return true;
+ }
+
+ return false;
+}
+
+QList<QmlTimelineFrames> QmlTimelineMutator::allTimelineFrames() const
+{
+ QList<QmlTimelineFrames> returnList;
+
+ for (const ModelNode &childNode : modelNode().defaultNodeListProperty().toModelNodeList()) {
+ if (QmlTimelineFrames::isValidQmlTimelineFrames(childNode))
+ returnList.append(QmlTimelineFrames(childNode));
+ }
+
+ return returnList;
+}
+
+} // QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
index 6779b5cc3d..154a80f760 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp
@@ -181,6 +181,8 @@ bool ChangePropertyRewriteAction::execute(QmlRefactoring &refactoring, ModelNode
{
if (m_sheduledInHierarchy) {
const int nodeLocation = positionStore.nodeOffset(m_property.parentModelNode());
+ if (nodeLocation < 0)
+ return true;
bool result = false;
if (m_property.isDefaultProperty()) {
diff --git a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp
index 8b5ea35ff1..9016619f6d 100644
--- a/src/plugins/qmldesigner/designercore/model/textmodifier.cpp
+++ b/src/plugins/qmldesigner/designercore/model/textmodifier.cpp
@@ -26,7 +26,8 @@
#include "textmodifier.h"
#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <texteditor/convenience.h>
+
+#include <utils/textutils.h>
using namespace QmlDesigner;
@@ -38,7 +39,7 @@ int TextModifier::getLineInDocument(QTextDocument *document, int offset)
{
int line = -1;
int column = -1;
- TextEditor::Convenience::convertPosition(document, offset, &line, &column);
+ Utils::Text::convertPosition(document, offset, &line, &column);
return line;
}
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 0af1d0a234..47ce2bad15 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -71,7 +71,7 @@ static inline bool isSupportedAttachedProperties(const QString &propertyName)
static inline QStringList supportedVersionsList()
{
static const QStringList list = {
- "2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "2.8", "2.9"
+ "2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "2.8", "2.9", "2.10"
};
return list;
}
diff --git a/src/plugins/qmldesigner/designercore/rewritertransaction.h b/src/plugins/qmldesigner/designercore/rewritertransaction.h
index 87e50c53fe..9a91f0d23f 100644
--- a/src/plugins/qmldesigner/designercore/rewritertransaction.h
+++ b/src/plugins/qmldesigner/designercore/rewritertransaction.h
@@ -54,7 +54,7 @@ private:
QPointer<AbstractView> m_view;
QByteArray m_identifier;
mutable bool m_valid;
- int m_identifierNumber;
+ int m_identifierNumber = 0;
static QList<QByteArray> m_identifierList;
static bool m_activeIdentifier;
bool m_ignoreSemanticChecks = false;
diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp
index c75c98c80b..ec7d139728 100644
--- a/src/plugins/qmldesigner/designersettings.cpp
+++ b/src/plugins/qmldesigner/designersettings.cpp
@@ -74,6 +74,8 @@ void DesignerSettings::fromSettings(QSettings *settings)
restoreValue(settings, DesignerSettingsKey::FORWARD_PUPPET_OUTPUT, QString());
restoreValue(settings, DesignerSettingsKey::REFORMAT_UI_QML_FILES, true);
restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false);
+ restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, false);
+ restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true);
settings->endGroup();
settings->endGroup();
diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h
index a3710d278d..7172c10491 100644
--- a/src/plugins/qmldesigner/designersettings.h
+++ b/src/plugins/qmldesigner/designersettings.h
@@ -60,6 +60,7 @@ const char PUPPET_KILL_TIMEOUT[] = "PuppetKillTimeout";
const char DEBUG_PUPPET[] = "DebugPuppet";
const char FORWARD_PUPPET_OUTPUT[] = "ForwardPuppetOutput";
const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded";
+const char NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS[] = "NavigatorShowOnlyVisibleItems";
const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */
const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */
}
diff --git a/src/plugins/qmldesigner/openuiqmlfiledialog.cpp b/src/plugins/qmldesigner/openuiqmlfiledialog.cpp
index 75837654dc..545719623f 100644
--- a/src/plugins/qmldesigner/openuiqmlfiledialog.cpp
+++ b/src/plugins/qmldesigner/openuiqmlfiledialog.cpp
@@ -55,7 +55,7 @@ OpenUiQmlFileDialog::OpenUiQmlFileDialog(QWidget *parent) :
}
close();
});
- connect(ui->checkBox, &QCheckBox::toggled, [this](bool b){
+ connect(ui->checkBox, &QCheckBox::toggled, this, [](bool b){
DesignerSettings settings = QmlDesignerPlugin::instance()->settings();
settings.insert(DesignerSettingsKey::WARNING_FOR_QML_FILES_INSTEAD_OF_UIQML_FILES, !b);
QmlDesignerPlugin::instance()->setSettings(settings);
diff --git a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp
index 7bd706f834..2ad6d34d3d 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp
+++ b/src/plugins/qmldesigner/qmldesignerextension/connectioneditor/connectionviewwidget.cpp
@@ -69,17 +69,13 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) :
ui->tabBar->addTab(tr("Backends", "Title of dynamic properties view"));
ui->tabBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- ui->connectionView->setStyleSheet(Theme::replaceCssColors(
- QLatin1String(Utils::FileReader::fetchQrc(QLatin1String(":/qmldesigner/scrollbar.css")))));
+ const QString themedScrollBarCss = Theme::replaceCssColors(
+ QLatin1String(Utils::FileReader::fetchQrc(QLatin1String(":/qmldesigner/scrollbar.css"))));
- ui->bindingView->setStyleSheet(Theme::replaceCssColors(
- QLatin1String(Utils::FileReader::fetchQrc(QLatin1String(":/qmldesigner/scrollbar.css")))));
-
- ui->dynamicPropertiesView->setStyleSheet(Theme::replaceCssColors(
- QLatin1String(Utils::FileReader::fetchQrc(QLatin1String(":/qmldesigner/scrollbar.css")))));
-
- ui->backendView->setStyleSheet(Theme::replaceCssColors(
- QLatin1String(Utils::FileReader::fetchQrc(QLatin1String(":/qmldesigner/scrollbar.css")))));
+ ui->connectionView->setStyleSheet(themedScrollBarCss);
+ ui->bindingView->setStyleSheet(themedScrollBarCss);
+ ui->dynamicPropertiesView->setStyleSheet(themedScrollBarCss);
+ ui->backendView->setStyleSheet(themedScrollBarCss);
connect(ui->tabBar, &QTabBar::currentChanged,
ui->stackedWidget, &QStackedWidget::setCurrentIndex);
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs
index 9f040daf76..50ad382b1a 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.qbs
+++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs
@@ -25,6 +25,7 @@ Project {
Depends { name: "ProjectExplorer" }
Depends { name: "LanguageUtils" }
Depends { name: "QtSupport" }
+ Depends { name: "app_version_header" }
cpp.defines: base.concat("DESIGNER_CORE_LIBRARY")
cpp.enableExceptions: true
@@ -279,6 +280,8 @@ Project {
"include/subcomponentmanager.h",
"include/textmodifier.h",
"include/variantproperty.h",
+ "include/qmltimelinekeyframes.h",
+ "include/qmltimelinemutator.h",
"instances/nodeinstance.cpp",
"instances/nodeinstanceserverproxy.cpp",
"instances/nodeinstanceserverproxy.h",
@@ -356,6 +359,8 @@ Project {
"model/texttomodelmerger.h",
"model/variantproperty.cpp",
"model/viewmanager.cpp",
+ "model/qmltimelinekeyframes.cpp",
+ "model/qmltimelinemutator.cpp",
"pluginmanager/widgetpluginmanager.cpp",
"pluginmanager/widgetpluginmanager.h",
"pluginmanager/widgetpluginpath.cpp",
@@ -550,7 +555,6 @@ Project {
"propertyeditor/fileresourcesmodel.h",
"propertyeditor/gradientmodel.cpp",
"propertyeditor/gradientmodel.h",
- "propertyeditor/propertyeditor.qrc",
"propertyeditor/propertyeditorcontextobject.cpp",
"propertyeditor/propertyeditorcontextobject.h",
"propertyeditor/propertyeditortransaction.cpp",
diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp
index cc0136dc4c..0a32af56ea 100644
--- a/src/plugins/qmldesigner/settingspage.cpp
+++ b/src/plugins/qmldesigner/settingspage.cpp
@@ -29,6 +29,8 @@
#include "designersettings.h"
#include "puppetcreator.h"
+#include <app/app_version.h>
+
#include <coreplugin/icore.h>
#include <qmljseditor/qmljseditorconstants.h>
@@ -251,7 +253,8 @@ void SettingsPage::apply()
if (currentSettings.value(key) != newSettings.value(key)) {
QMessageBox::information(Core::ICore::mainWindow(), tr("Restart Required"),
tr("The made changes will take effect after a "
- "restart of the QML Emulation layer or Qt Creator."));
+ "restart of the QML Emulation layer or %1.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME));
break;
}
}
diff --git a/src/plugins/qmldesigner/settingspage.ui b/src/plugins/qmldesigner/settingspage.ui
index 9fed112a68..ca00b6fc41 100644
--- a/src/plugins/qmldesigner/settingspage.ui
+++ b/src/plugins/qmldesigner/settingspage.ui
@@ -252,14 +252,14 @@
<bool>true</bool>
</property>
<property name="toolTip">
- <string>Path where Qt Creator can find the QML emulation layer executable (qmlpuppet).</string>
+ <string>Path to the QML emulation layer executable (qmlpuppet).</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="resetFallbackPuppetPathButton">
<property name="toolTip">
- <string>Resets the path to the QML emulation layer that comes with Qt Creator.</string>
+ <string>Resets the path to the built-in QML emulation layer.</string>
</property>
<property name="text">
<string>Reset Path</string>
diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp
index 864d4046f4..8b45efc853 100644
--- a/src/plugins/qmldesigner/shortcutmanager.cpp
+++ b/src/plugins/qmldesigner/shortcutmanager.cpp
@@ -175,7 +175,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
//Close All Others Action
Core::ActionManager::registerAction(&m_closeOtherEditorsAction, Core::Constants::CLOSEOTHERS, qmlDesignerMainContext);
- connect(&m_closeOtherEditorsAction, &QAction::triggered, em, [em] {
+ connect(&m_closeOtherEditorsAction, &QAction::triggered, em, [] {
Core::EditorManager::closeOtherDocuments();
});
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp
index 3b9a50866f..34f2fa818a 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.cpp
+++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp
@@ -54,6 +54,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <texteditor/snippets/snippetprovider.h>
#include <texteditor/texteditorconstants.h>
+#include <texteditor/tabsettings.h>
#include <utils/qtcassert.h>
#include <utils/json.h>
@@ -258,8 +259,10 @@ void QmlJSEditorPlugin::reformatFile()
if (!document->isParsedCorrectly())
return;
-
- const QString &newText = QmlJS::reformat(document);
+ TextEditor::TabSettings tabSettings = m_currentDocument->tabSettings();
+ const QString &newText = QmlJS::reformat(document,
+ tabSettings.m_indentSize,
+ tabSettings.m_tabSize);
QmlJSEditorWidget *widget = EditorManager::currentEditor()
? qobject_cast<QmlJSEditorWidget*>(EditorManager::currentEditor()->widget())
: nullptr;
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp
index 2e8bb9e407..7806d9c385 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.cpp
+++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp
@@ -959,7 +959,9 @@ void FindReferences::displayResults(int first, int last)
this, &FindReferences::onReplaceButtonClicked);
}
connect(m_currentSearch.data(), &SearchResult::activated,
- this, &FindReferences::openEditor);
+ [](const Core::SearchResultItem& item) {
+ Core::EditorManager::openEditorAtSearchResult(item);
+ });
connect(m_currentSearch.data(), &SearchResult::cancelled, this, &FindReferences::cancel);
connect(m_currentSearch.data(), &SearchResult::paused, this, &FindReferences::setPaused);
SearchResultWindow::instance()->popup(IOutputPane::Flags(IOutputPane::ModeSwitch | IOutputPane::WithFocus));
@@ -1005,17 +1007,6 @@ void FindReferences::setPaused(bool paused)
m_watcher.setPaused(paused);
}
-void FindReferences::openEditor(const SearchResultItem &item)
-{
- if (item.path.size() > 0) {
- EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
- item.mainRange.begin.line,
- item.mainRange.begin.column);
- } else {
- EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
- }
-}
-
void FindReferences::onReplaceButtonClicked(const QString &text, const QList<SearchResultItem> &items, bool preserveCase)
{
const QStringList fileNames = TextEditor::BaseFileFind::replaceAll(text, items, preserveCase);
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.h b/src/plugins/qmljseditor/qmljsfindreferences.h
index e7075b4799..0de23bd722 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.h
+++ b/src/plugins/qmljseditor/qmljsfindreferences.h
@@ -82,7 +82,6 @@ private:
void searchFinished();
void cancel();
void setPaused(bool paused);
- void openEditor(const Core::SearchResultItem &item);
void onReplaceButtonClicked(const QString &text, const QList<Core::SearchResultItem> &items, bool preserveCase);
QPointer<Core::SearchResult> m_currentSearch;
diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.h b/src/plugins/qmljseditor/qmljssemantichighlighter.h
index c32a69df89..f1714b7a8e 100644
--- a/src/plugins/qmljseditor/qmljssemantichighlighter.h
+++ b/src/plugins/qmljseditor/qmljssemantichighlighter.h
@@ -31,7 +31,6 @@
#include <QVector>
namespace QmlJS {
-class ScopeChain;
namespace AST { class SourceLocation; }
}
diff --git a/src/plugins/qmljstools/qmljsfunctionfilter.cpp b/src/plugins/qmljstools/qmljsfunctionfilter.cpp
index 7c00e6c9f0..930eff714a 100644
--- a/src/plugins/qmljstools/qmljsfunctionfilter.cpp
+++ b/src/plugins/qmljstools/qmljsfunctionfilter.cpp
@@ -28,9 +28,9 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
+#include <utils/camelhumpmatcher.h>
-#include <QRegExp>
-#include <QStringMatcher>
+#include <QRegularExpression>
using namespace QmlJSTools::Internal;
@@ -59,12 +59,12 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
{
QList<Core::LocatorFilterEntry> goodEntries;
QList<Core::LocatorFilterEntry> betterEntries;
- const Qt::CaseSensitivity cs = caseSensitivity(entry);
- QStringMatcher matcher(entry, cs);
- QRegExp regexp(entry, cs, QRegExp::Wildcard);
+ QList<Core::LocatorFilterEntry> bestEntries;
+ const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
+
+ const QRegularExpression regexp = createRegExp(entry);
if (!regexp.isValid())
return goodEntries;
- bool hasWildcard = containsWildcard(entry);
QHashIterator<QString, QList<LocatorData::Entry> > it(m_data->entries());
while (it.hasNext()) {
@@ -78,16 +78,19 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
if (info.type != LocatorData::Function)
continue;
- const int index = hasWildcard ? regexp.indexIn(info.symbolName)
- : matcher.indexIn(info.symbolName);
- if (index >= 0) {
+ const QRegularExpressionMatch match = regexp.match(info.symbolName);
+ if (match.hasMatch()) {
QVariant id = qVariantFromValue(info);
Core::LocatorFilterEntry filterEntry(this, info.displayName, id/*, info.icon*/);
+ const CamelHumpMatcher::HighlightingPositions positions =
+ CamelHumpMatcher::highlightingPositions(match);
filterEntry.extraInfo = info.extraInfo;
- const int length = hasWildcard ? regexp.matchedLength() : entry.length();
- filterEntry.highlightInfo = {index, length};
+ filterEntry.highlightInfo.starts = positions.starts;
+ filterEntry.highlightInfo.lengths = positions.lengths;
- if (index == 0)
+ if (filterEntry.displayName.startsWith(entry, caseSensitivityForPrefix))
+ bestEntries.append(filterEntry);
+ else if (filterEntry.displayName.contains(entry, caseSensitivityForPrefix))
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
@@ -99,9 +102,12 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
Utils::sort(goodEntries, Core::LocatorFilterEntry::compareLexigraphically);
if (betterEntries.size() < 1000)
Utils::sort(betterEntries, Core::LocatorFilterEntry::compareLexigraphically);
+ if (bestEntries.size() < 1000)
+ Utils::sort(bestEntries, Core::LocatorFilterEntry::compareLexigraphically);
- betterEntries += goodEntries;
- return betterEntries;
+ bestEntries += betterEntries;
+ bestEntries += goodEntries;
+ return bestEntries;
}
void FunctionFilter::accept(Core::LocatorFilterEntry selection,
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index d28cc3ab87..9f05506ee0 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -163,8 +163,7 @@ void setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &projectInfo)
if (projectInfo.project) {
QSet<Kit *> currentKits;
foreach (const Target *t, projectInfo.project->targets())
- if (t->kit())
- currentKits.insert(t->kit());
+ currentKits.insert(t->kit());
currentKits.remove(activeKit);
foreach (Kit *kit, currentKits) {
foreach (IBundleProvider *bp, bundleProviders)
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.h b/src/plugins/qmlprofiler/flamegraphmodel.h
index 587de41cf7..cc8150fb29 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.h
+++ b/src/plugins/qmlprofiler/flamegraphmodel.h
@@ -87,7 +87,6 @@ public:
QHash<int, QByteArray> roleNames() const override;
QmlProfilerModelManager *modelManager() const;
-public slots:
void loadEvent(const QmlEvent &event, const QmlEventType &type);
void finalize();
void onModelManagerStateChanged();
@@ -95,6 +94,10 @@ public slots:
void loadNotes(int typeId, bool emitSignal);
void clear();
+signals:
+ void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
+ void typeSelected(int typeIndex);
+
private:
QVariant lookup(const FlameGraphData &data, int role) const;
FlameGraphData *pushChild(FlameGraphData *parent, const QmlEvent &data);
diff --git a/src/plugins/qmlprofiler/flamegraphview.cpp b/src/plugins/qmlprofiler/flamegraphview.cpp
index d26d4747a3..4de7fd1601 100644
--- a/src/plugins/qmlprofiler/flamegraphview.cpp
+++ b/src/plugins/qmlprofiler/flamegraphview.cpp
@@ -67,10 +67,9 @@ FlameGraphView::FlameGraphView(QmlProfilerModelManager *manager, QWidget *parent
layout->addWidget(m_content);
setLayout(layout);
- connect(m_content->rootObject(), SIGNAL(typeSelected(int)),
- this, SIGNAL(typeSelected(int)));
- connect(m_content->rootObject(), SIGNAL(gotoSourceLocation(QString,int,int)),
- this, SIGNAL(gotoSourceLocation(QString,int,int)));
+ connect(m_model, &FlameGraphModel::typeSelected, this, &FlameGraphView::typeSelected);
+ connect(m_model, &FlameGraphModel::gotoSourceLocation,
+ this, &FlameGraphView::gotoSourceLocation);
}
void FlameGraphView::selectByTypeId(int typeIndex)
diff --git a/src/plugins/qmlprofiler/flamegraphview.h b/src/plugins/qmlprofiler/flamegraphview.h
index 60c817584e..ed4c23a136 100644
--- a/src/plugins/qmlprofiler/flamegraphview.h
+++ b/src/plugins/qmlprofiler/flamegraphview.h
@@ -40,7 +40,6 @@ class FlameGraphView : public QmlProfilerEventsView
public:
FlameGraphView(QmlProfilerModelManager *manager, QWidget *parent = nullptr);
-public slots:
void selectByTypeId(int typeIndex) override;
void onVisibleFeaturesChanged(quint64 features) override;
diff --git a/src/plugins/qmlprofiler/inputeventsmodel.cpp b/src/plugins/qmlprofiler/inputeventsmodel.cpp
index 0c7e9b50fc..2c8be86fe4 100644
--- a/src/plugins/qmlprofiler/inputeventsmodel.cpp
+++ b/src/plugins/qmlprofiler/inputeventsmodel.cpp
@@ -126,7 +126,7 @@ QVariantMap InputEventsModel::details(int index) const
type = tr("Mouse Event");
break;
default:
- Q_UNREACHABLE();
+ type = tr("Unknown");
break;
}
diff --git a/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml
index 34bca26cfa..b49c16f562 100644
--- a/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml
+++ b/src/plugins/qmlprofiler/qml/QmlProfilerFlameGraphView.qml
@@ -32,8 +32,6 @@ import "../flamegraph/"
ScrollView {
id: root
- signal typeSelected(int typeIndex)
- signal gotoSourceLocation(string filename, int line, int column)
property int selectedTypeId: -1
property int sizeRole: QmlProfilerFlameGraphModel.DurationRole
@@ -157,9 +155,9 @@ ScrollView {
onClicked: {
if (flamegraphItem.FlameGraph.dataValid) {
tooltip.selectedNode = flamegraphItem;
- root.typeSelected(flamegraphItem.FlameGraph.data(
+ flameGraphModel.typeSelected(flamegraphItem.FlameGraph.data(
QmlProfilerFlameGraphModel.TypeIdRole));
- root.gotoSourceLocation(
+ flameGraphModel.gotoSourceLocation(
flamegraphItem.FlameGraph.data(
QmlProfilerFlameGraphModel.FilenameRole),
flamegraphItem.FlameGraph.data(
@@ -269,7 +267,7 @@ ScrollView {
onClearSelection: {
selectedTypeId = -1;
selectedNode = null;
- root.typeSelected(-1);
+ flameGraphModel.typeSelected(-1);
}
dialogTitle: {
diff --git a/src/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofiler/qmlprofiler.qbs
index 02a08fb656..629641c415 100644
--- a/src/plugins/qmlprofiler/qmlprofiler.qbs
+++ b/src/plugins/qmlprofiler/qmlprofiler.qbs
@@ -16,6 +16,7 @@ QtcPlugin {
Depends { name: "ProjectExplorer" }
Depends { name: "QtSupport" }
Depends { name: "TextEditor" }
+ Depends { name: "app_version_header" }
Group {
name: "General"
@@ -92,7 +93,10 @@ QtcPlugin {
"qmlprofilerbindingloopsrenderpass_test.h",
"qmlprofilerclientmanager_test.cpp", "qmlprofilerclientmanager_test.h",
"qmlprofilerconfigwidget_test.cpp", "qmlprofilerconfigwidget_test.h",
+ "qmlprofilerdetailsrewriter_test.cpp", "qmlprofilerdetailsrewriter_test.h",
"qmlprofilertraceview_test.cpp", "qmlprofilertraceview_test.h",
+
+ "tests.qrc"
]
}
}
diff --git a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp
index 0dca25645d..1c00071ad3 100644
--- a/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofileranimationsmodel.cpp
@@ -85,7 +85,6 @@ void QmlProfilerAnimationsModel::loadEvent(const QmlEvent &event, const QmlEvent
lastEvent.typeId = event.typeIndex();
lastEvent.framerate = event.number<qint32>(0);
lastEvent.animationcount = event.number<qint32>(1);
- QTC_ASSERT(lastEvent.animationcount > 0, return);
m_data.insert(insert(realStartTime, realEndTime - realStartTime, lastThread), lastEvent);
diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
index 2b919e7f42..0152d994e4 100644
--- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
@@ -29,6 +29,7 @@
#include "qmlprofilerstatemanager.h"
#include <utils/qtcassert.h>
+#include <projectexplorer/runnables.h>
namespace QmlProfiler {
namespace Internal {
@@ -65,13 +66,19 @@ void QmlProfilerClientManager::setRetryParams(int interval, int maxAttempts)
m_maximumRetries = maxAttempts;
}
-void QmlProfilerClientManager::setServerUrl(const QUrl &server)
+void QmlProfilerClientManager::connectToServer(const QUrl &server)
{
if (m_server != server) {
m_server = server;
disconnectClient();
stopConnectionTimer();
}
+ if (server.scheme() == ProjectExplorer::urlTcpScheme())
+ connectToTcpServer();
+ else if (server.scheme() == ProjectExplorer::urlSocketScheme())
+ startLocalServer();
+ else
+ QTC_ASSERT(false, emit connectionFailed());
}
void QmlProfilerClientManager::clearConnection()
@@ -166,9 +173,9 @@ void QmlProfilerClientManager::stopRecording()
void QmlProfilerClientManager::retryConnect()
{
- if (m_server.scheme() == "socket") {
+ if (m_server.scheme() == ProjectExplorer::urlSocketScheme()) {
startLocalServer();
- } else if (!m_server.host().isEmpty() && m_server.port() > 0) {
+ } else if (m_server.scheme() == ProjectExplorer::urlTcpScheme()) {
disconnectClient();
connectToTcpServer();
} else {
diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h
index 61a9d17800..c64429abc7 100644
--- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h
+++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h
@@ -47,7 +47,7 @@ public:
~QmlProfilerClientManager();
void setProfilerStateManager(QmlProfilerStateManager *profilerState);
- void setServerUrl(const QUrl &server);
+ void connectToServer(const QUrl &server);
void clearConnection();
void clearBufferedData();
@@ -58,8 +58,6 @@ public:
void setRetryParams(int interval, int maxAttempts);
void retryConnect();
- void connectToTcpServer();
- void startLocalServer();
void stopRecording();
@@ -69,6 +67,9 @@ signals:
void connectionClosed();
private:
+ void connectToTcpServer();
+ void startLocalServer();
+
QPointer<QmlProfilerStateManager> m_profilerState;
QPointer<QmlProfilerModelManager> m_modelManager;
QScopedPointer<QmlDebug::QmlDebugConnection> m_connection;
diff --git a/src/plugins/qmlprofiler/qmlprofilerconfigwidget.h b/src/plugins/qmlprofiler/qmlprofilerconfigwidget.h
index 2f3b0022b7..0daf884b78 100644
--- a/src/plugins/qmlprofiler/qmlprofilerconfigwidget.h
+++ b/src/plugins/qmlprofiler/qmlprofilerconfigwidget.h
@@ -44,10 +44,9 @@ public:
explicit QmlProfilerConfigWidget(QmlProfilerSettings *settings, QWidget *parent = 0);
~QmlProfilerConfigWidget();
-private slots:
+private:
void updateUi();
-private:
Ui::QmlProfilerConfigWidget *m_ui;
QmlProfilerSettings *m_settings;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilerconfigwidget.ui b/src/plugins/qmlprofiler/qmlprofilerconfigwidget.ui
index 9c7bdb50dc..df66e67b80 100644
--- a/src/plugins/qmlprofiler/qmlprofilerconfigwidget.ui
+++ b/src/plugins/qmlprofiler/qmlprofilerconfigwidget.ui
@@ -21,7 +21,7 @@
<item row="0" column="1">
<widget class="QCheckBox" name="flushEnabled">
<property name="toolTip">
- <string>Periodically flush pending data to Qt Creator. This reduces the delay when loading the
+ <string>Periodically flush pending data to the profiler. This reduces the delay when loading the
data and the memory usage in the application. It distorts the profile as the flushing
itself takes time.</string>
</property>
diff --git a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
index a5199491f6..59d236cc1a 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp
@@ -42,53 +42,53 @@ namespace Internal {
class PropertyVisitor: protected QmlJS::AST::Visitor
{
- QmlJS::AST::Node * _lastValidNode;
- unsigned _line;
- unsigned _col;
public:
- QmlJS::AST::Node * operator()(QmlJS::AST::Node *node, unsigned line, unsigned col)
+ QmlJS::AST::Node *operator()(QmlJS::AST::Node *node, int line, int column)
{
- _line = line;
- _col = col;
- _lastValidNode = 0;
- accept(node);
- return _lastValidNode;
+ QTC_ASSERT(line >= 0, return nullptr);
+ QTC_ASSERT(column >= 0, return nullptr);
+ QTC_ASSERT(node, return nullptr);
+ m_line = line;
+ m_column = column;
+ m_lastValidNode = nullptr;
+ node->accept(this);
+ return m_lastValidNode;
}
protected:
using QmlJS::AST::Visitor::visit;
- void accept(QmlJS::AST::Node *node)
- {
- if (node)
- node->accept(this);
- }
-
- bool containsLocation(QmlJS::AST::SourceLocation start, QmlJS::AST::SourceLocation end)
- {
- return (_line > start.startLine || (_line == start.startLine && _col >= start.startColumn))
- && (_line < end.startLine || (_line == end.startLine && _col <= end.startColumn));
- }
-
-
- virtual bool preVisit(QmlJS::AST::Node *node)
+ bool preVisit(QmlJS::AST::Node *node) override
{
if (QmlJS::AST::cast<QmlJS::AST::UiQualifiedId *>(node))
return false;
return containsLocation(node->firstSourceLocation(), node->lastSourceLocation());
}
- virtual bool visit(QmlJS::AST::UiScriptBinding *ast)
+ bool visit(QmlJS::AST::UiScriptBinding *ast) override
{
- _lastValidNode = ast;
+ m_lastValidNode = ast;
return true;
}
- virtual bool visit(QmlJS::AST::UiPublicMember *ast)
+ bool visit(QmlJS::AST::UiPublicMember *ast) override
{
- _lastValidNode = ast;
+ m_lastValidNode = ast;
return true;
}
+
+private:
+ QmlJS::AST::Node *m_lastValidNode = nullptr;
+ quint32 m_line = 0;
+ quint32 m_column = 0;
+
+ bool containsLocation(QmlJS::AST::SourceLocation start, QmlJS::AST::SourceLocation end)
+ {
+ return (m_line > start.startLine
+ || (m_line == start.startLine && m_column >= start.startColumn))
+ && (m_line < end.startLine
+ || (m_line == end.startLine && m_column <= end.startColumn));
+ }
};
QmlProfilerDetailsRewriter::QmlProfilerDetailsRewriter(QObject *parent)
@@ -148,7 +148,6 @@ void QmlProfilerDetailsRewriter::rewriteDetailsForLocation(
{
PropertyVisitor propertyVisitor;
QmlJS::AST::Node *node = propertyVisitor(doc->ast(), location.line(), location.column());
-
if (!node)
return;
@@ -174,7 +173,7 @@ void QmlProfilerDetailsRewriter::disconnectQmlModel()
}
}
-void QmlProfilerDetailsRewriter::clearRequests()
+void QmlProfilerDetailsRewriter::clear()
{
m_filesCache.clear();
m_pendingEvents.clear();
@@ -257,6 +256,7 @@ void QmlProfilerDetailsRewriter::populateFileFinder(
m_projectFinder.setProjectDirectory(projectDirectory);
m_projectFinder.setProjectFiles(sourceFiles);
m_projectFinder.setSysroot(activeSysroot);
+ m_filesCache.clear();
}
} // namespace Internal
diff --git a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h
index d5dcf6e773..ae0b55cde7 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h
+++ b/src/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h
@@ -42,23 +42,22 @@ class QmlProfilerDetailsRewriter : public QObject
public:
explicit QmlProfilerDetailsRewriter(QObject *parent = nullptr);
- void clearRequests();
+ void clear();
void requestDetailsForLocation(int typeId, const QmlEventLocation &location);
QString getLocalFile(const QString &remoteFile);
void reloadDocuments();
- void documentReady(QmlJS::Document::Ptr doc);
void populateFileFinder(const ProjectExplorer::RunConfiguration *runConfiguration);
- struct PendingEvent {
- QmlEventLocation location;
- int typeId;
- };
-
signals:
void rewriteDetailsString(int typeId, const QString &details);
void eventDetailsChanged();
private:
+ struct PendingEvent {
+ QmlEventLocation location;
+ int typeId;
+ };
+
QMultiHash<QString, PendingEvent> m_pendingEvents;
Utils::FileInProjectFinder m_projectFinder;
QHash<QString, QString> m_filesCache;
@@ -67,6 +66,9 @@ private:
const QmlEventLocation &location);
void connectQmlModel();
void disconnectQmlModel();
+ void documentReady(QmlJS::Document::Ptr doc);
+
+ friend class QTypeInfo<PendingEvent>;
};
} // namespace Internal
diff --git a/src/plugins/qmlprofiler/qmlprofilereventsview.h b/src/plugins/qmlprofiler/qmlprofilereventsview.h
index e48f64ab95..85cfe31e5c 100644
--- a/src/plugins/qmlprofiler/qmlprofilereventsview.h
+++ b/src/plugins/qmlprofiler/qmlprofilereventsview.h
@@ -40,14 +40,13 @@ public:
QmlProfilerEventsView(QWidget *parent = 0) : QWidget(parent) {}
virtual void clear() {}
+ virtual void selectByTypeId(int typeIndex) = 0;
+ virtual void onVisibleFeaturesChanged(quint64 features) = 0;
+
signals:
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
void typeSelected(int typeIndex);
void showFullRange();
-
-public slots:
- virtual void selectByTypeId(int typeIndex) = 0;
- virtual void onVisibleFeaturesChanged(quint64 features) = 0;
};
} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
index 3902167af2..7c85817841 100644
--- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
@@ -92,18 +92,23 @@ bool QmlProfilerTraceTime::isRestrictedToRange() const
void QmlProfilerTraceTime::clear()
{
restrictToRange(-1, -1);
- setTime(-1, -1);
+ m_startTime = -1;
+ m_endTime = -1;
}
-void QmlProfilerTraceTime::setTime(qint64 startTime, qint64 endTime)
+void QmlProfilerTraceTime::update(qint64 time)
{
- QTC_ASSERT(startTime <= endTime, endTime = startTime);
- m_startTime = startTime;
- m_endTime = endTime;
+ QTC_ASSERT(time >= 0, return);
+ if (m_startTime > time || m_startTime == -1)
+ m_startTime = time;
+ if (m_endTime < time || m_endTime == -1)
+ m_endTime = time;
+ QTC_ASSERT(m_endTime >= m_startTime, m_startTime = m_endTime);
}
void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
{
+ QTC_ASSERT(time >= 0, return);
if (m_startTime > time || m_startTime == -1) {
m_startTime = time;
if (m_endTime == -1)
@@ -115,6 +120,7 @@ void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
void QmlProfilerTraceTime::increaseEndTime(qint64 time)
{
+ QTC_ASSERT(time >= 0, return);
if (m_endTime < time || m_endTime == -1) {
m_endTime = time;
if (m_startTime == -1)
@@ -244,6 +250,7 @@ void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events)
{
for (const QmlEvent &event : events) {
d->eventStream << event;
+ d->traceTime->update(event.timestamp());
d->dispatch(event, d->eventTypes[event.typeIndex()]);
}
}
@@ -251,6 +258,7 @@ void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events)
void QmlProfilerModelManager::addEvent(const QmlEvent &event)
{
d->eventStream << event;
+ d->traceTime->update(event.timestamp());
QTC_ASSERT(event.typeIndex() < d->eventTypes.size(),
d->eventTypes.resize(event.typeIndex() + 1));
d->dispatch(event, d->eventTypes.at(event.typeIndex()));
@@ -554,12 +562,12 @@ void QmlProfilerModelManager::save(const QString &filename)
emit error(message);
}, Qt::QueuedConnection);
- connect(writer, &QmlProfilerFileWriter::success, this, [this, file]() {
+ connect(writer, &QmlProfilerFileWriter::success, this, [file]() {
file->close();
delete file;
}, Qt::QueuedConnection);
- connect(writer, &QmlProfilerFileWriter::canceled, this, [this, file]() {
+ connect(writer, &QmlProfilerFileWriter::canceled, this, [file]() {
file->close();
file->remove();
delete file;
@@ -606,7 +614,10 @@ void QmlProfilerModelManager::load(const QString &filename)
this, &QmlProfilerModelManager::addEvents);
connect(reader, &QmlProfilerFileReader::success, this, [this, reader]() {
- d->traceTime->setTime(reader->traceStart(), reader->traceEnd());
+ if (reader->traceStart() >= 0)
+ d->traceTime->decreaseStartTime(reader->traceStart());
+ if (reader->traceEnd() >= 0)
+ d->traceTime->increaseEndTime(reader->traceEnd());
setRecordedFeatures(reader->loadedFeatures());
delete reader;
acquiringDone();
@@ -692,7 +703,7 @@ void QmlProfilerModelManager::clear()
else
emit error(tr("Cannot open temporary trace file to store events."));
d->eventTypes.clear();
- d->detailsRewriter->clearRequests();
+ d->detailsRewriter->clear();
d->traceTime->clear();
d->notesModel->clear();
setVisibleFeatures(0);
diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
index 8cce222c51..f09537667e 100644
--- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
+++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
@@ -56,10 +56,9 @@ public:
qint64 duration() const;
bool isRestrictedToRange() const;
-public slots:
void clear();
- void setTime(qint64 startTime, qint64 endTime);
+ void update(qint64 time);
void decreaseStartTime(qint64 time);
void increaseEndTime(qint64 time);
void restrictToRange(qint64 startTime, qint64 endTime);
@@ -135,6 +134,15 @@ public:
static const char *featureName(ProfileFeature feature);
+ void clear();
+ void restrictToRange(qint64 startTime, qint64 endTime);
+ bool isRestrictedToRange() const;
+
+ void startAcquiring();
+
+ void save(const QString &filename);
+ void load(const QString &filename);
+
signals:
void error(const QString &error);
void stateChanged();
@@ -145,21 +153,10 @@ signals:
void visibleFeaturesChanged(quint64 features);
void recordedFeaturesChanged(quint64 features);
-public slots:
- void clear();
- void restrictToRange(qint64 startTime, qint64 endTime);
- bool isRestrictedToRange() const;
-
- void startAcquiring();
-
- void save(const QString &filename);
- void load(const QString &filename);
-
private:
void setState(State state);
void detailsChanged(int typeId, const QString &newString);
-private:
class QmlProfilerModelManagerPrivate;
QmlProfilerModelManagerPrivate *d;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
index 273666e35b..d18514eb88 100644
--- a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp
@@ -48,6 +48,7 @@
#include "tests/qmlprofilerbindingloopsrenderpass_test.h"
#include "tests/qmlprofilerclientmanager_test.h"
#include "tests/qmlprofilerconfigwidget_test.h"
+#include "tests/qmlprofilerdetailsrewriter_test.h"
#include "tests/qmlprofilertraceview_test.h"
// Force QML Debugging to be enabled, so that we can selftest the profiler
@@ -103,7 +104,7 @@ void QmlProfilerPlugin::extensionsInitialized()
};
RunControl::registerWorkerCreator(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE,
- [this](RunControl *runControl) { return new QmlProfilerRunner(runControl); });
+ [](RunControl *runControl) { return new QmlProfilerRunner(runControl); });
RunControl::registerWorker<LocalQmlProfilerSupport>
(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, constraint);
@@ -145,6 +146,7 @@ QList<QObject *> QmlProfiler::Internal::QmlProfilerPlugin::createTestObjects() c
tests << new QmlProfilerBindingLoopsRenderPassTest;
tests << new QmlProfilerClientManagerTest;
tests << new QmlProfilerConfigWidgetTest;
+ tests << new QmlProfilerDetailsRewriterTest;
tests << new QmlProfilerTraceViewTest;
tests << new QQmlEngine; // Trigger debug connector to be started
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
index 949eab3176..7a24026e93 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
@@ -28,6 +28,8 @@
#include "qmlprofilerclientmanager.h"
#include "qmlprofilertool.h"
+#include <app/app_version.h>
+
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
@@ -100,7 +102,7 @@ void QmlProfilerRunner::start()
this, [this, clientManager] {
QMessageBox *infoBox = new QMessageBox(ICore::mainWindow());
infoBox->setIcon(QMessageBox::Critical);
- infoBox->setWindowTitle(QmlProfilerTool::tr("Qt Creator"));
+ infoBox->setWindowTitle(Core::Constants::IDE_DISPLAY_NAME);
infoBox->setText(QmlProfilerTool::tr("Could not connect to the in-process QML profiler.\n"
"Do you want to retry?"));
infoBox->setStandardButtons(QMessageBox::Retry | QMessageBox::Cancel | QMessageBox::Help);
@@ -125,17 +127,10 @@ void QmlProfilerRunner::start()
});
infoBox->show();
- });
-
- clientManager->setServerUrl(serverUrl);
- if (serverUrl.port() != -1) {
- clientManager->connectToTcpServer();
- } else {
- clientManager->startLocalServer();
- }
+ }, Qt::QueuedConnection); // Queue any connection failures after reportStarted()
+ clientManager->connectToServer(serverUrl);
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
-
reportStarted();
}
@@ -281,7 +276,17 @@ LocalQmlProfilerSupport::LocalQmlProfilerSupport(RunControl *runControl, const Q
addStartDependency(m_profiler);
StandardRunnable debuggee = runnable().as<StandardRunnable>();
- QString arguments = QmlDebug::qmlDebugArguments(QmlDebug::QmlProfilerServices, serverUrl);
+
+ QString code;
+ if (serverUrl.scheme() == urlSocketScheme())
+ code = QString("file:%1").arg(serverUrl.path());
+ else if (serverUrl.scheme() == urlTcpScheme())
+ code = QString("port:%1").arg(serverUrl.port());
+ else
+ QTC_CHECK(false);
+
+ QString arguments = QmlDebug::qmlDebugCommandLineArguments(QmlDebug::QmlProfilerServices,
+ code, true);
if (!debuggee.commandLineArguments.isEmpty())
arguments += ' ' + debuggee.commandLineArguments;
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatemanager.h b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h
index 35b9bca98a..e04870ab1c 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatemanager.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h
@@ -51,6 +51,12 @@ public:
QString currentStateAsString();
+ void setCurrentState(QmlProfilerState newState);
+ void setClientRecording(bool recording);
+ void setServerRecording(bool recording);
+ void setRequestedFeatures(quint64 features);
+ void setRecordedFeatures(quint64 features);
+
signals:
void stateChanged();
void clientRecordingChanged(bool);
@@ -58,13 +64,6 @@ signals:
void requestedFeaturesChanged(quint64);
void recordedFeaturesChanged(quint64);
-public slots:
- void setCurrentState(QmlProfilerState newState);
- void setClientRecording(bool recording);
- void setServerRecording(bool recording);
- void setRequestedFeatures(quint64 features);
- void setRecordedFeatures(quint64 features);
-
private:
class QmlProfilerStateManagerPrivate;
QmlProfilerStateManagerPrivate *d;
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatewidget.h b/src/plugins/qmlprofiler/qmlprofilerstatewidget.h
index 68322b2a71..bce98d9ce8 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatewidget.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatewidget.h
@@ -41,13 +41,12 @@ public:
QmlProfilerModelManager *modelManager, QWidget *parent = 0);
~QmlProfilerStateWidget();
-private slots:
+private:
void showText(const QString &text);
void updateDisplay();
void update();
void reposition();
-private:
class QmlProfilerStateWidgetPrivate;
QmlProfilerStateWidgetPrivate *d;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
index cab4e5f545..f83ef3c26e 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
@@ -87,11 +87,9 @@ private:
void loadEvent(const QmlEvent &event, const QmlEventType &type);
void finalize();
-private slots:
void dataChanged();
void notesChanged(int typeIndex);
-private:
class QmlProfilerStatisticsModelPrivate;
QmlProfilerStatisticsModelPrivate *d;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
index a23b871176..651bc97a19 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
@@ -82,7 +82,6 @@ public:
QString summary(const QVector<int> &typeIds) const;
QStringList details(int typeId) const;
-public slots:
void selectByTypeId(int typeIndex) override;
void onVisibleFeaturesChanged(quint64 features) override;
@@ -121,27 +120,24 @@ public:
void setShowExtendedStatistics(bool);
bool showExtendedStatistics() const;
-signals:
- void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
- void typeSelected(int typeIndex);
-
-public slots:
void clear();
void jumpToItem(const QModelIndex &index);
void selectType(int typeIndex);
void buildModel();
void updateNotes(int typeIndex);
+signals:
+ void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
+ void typeSelected(int typeIndex);
+
private:
void selectItem(const QStandardItem *item);
void setHeaderLabels();
void parseModel();
QStandardItem *itemFromIndex(const QModelIndex &index) const;
-private:
class QmlProfilerStatisticsMainViewPrivate;
QmlProfilerStatisticsMainViewPrivate *d;
-
};
class QmlProfilerStatisticsRelativesView : public Utils::TreeView
@@ -152,15 +148,14 @@ public:
QWidget *parent);
~QmlProfilerStatisticsRelativesView();
-signals:
- void typeClicked(int typeIndex);
- void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
-
-public slots:
void displayType(int typeIndex);
void jumpToItem(const QModelIndex &);
void clear();
+signals:
+ void typeClicked(int typeIndex);
+ void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
+
private:
void rebuildTree(const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap &map);
void updateHeader();
diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
index bbc0bf3fc0..4a7bf4ae38 100644
--- a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
@@ -22,8 +22,12 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
+
#include "qmlprofilertextmark.h"
+
#include "qmlprofilerconstants.h"
+#include "qmlprofilerviewmanager.h"
+#include "qmlprofilerstatisticsview.h"
#include <QLabel>
#include <QLayout>
@@ -32,9 +36,9 @@
namespace QmlProfiler {
namespace Internal {
-QmlProfilerTextMark::QmlProfilerTextMark(QmlProfilerTool *tool, int typeId, const QString &fileName,
- int lineNumber) :
- TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY, 3.5), m_tool(tool),
+QmlProfilerTextMark::QmlProfilerTextMark(QmlProfilerViewManager *viewManager, int typeId,
+ const QString &fileName, int lineNumber) :
+ TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY, 3.5), m_viewManager(viewManager),
m_typeIds(1, typeId)
{
}
@@ -50,7 +54,8 @@ void QmlProfilerTextMark::paintIcon(QPainter *painter, const QRect &paintRect) c
painter->setPen(Qt::black);
painter->fillRect(paintRect, Qt::white);
painter->drawRect(paintRect);
- painter->drawText(paintRect, m_tool->summary(m_typeIds), Qt::AlignRight | Qt::AlignVCenter);
+ painter->drawText(paintRect, m_viewManager->statisticsView()->summary(m_typeIds),
+ Qt::AlignRight | Qt::AlignVCenter);
painter->restore();
}
@@ -58,7 +63,7 @@ void QmlProfilerTextMark::clicked()
{
int typeId = m_typeIds.takeFirst();
m_typeIds.append(typeId);
- m_tool->selectType(typeId);
+ m_viewManager->typeSelected(typeId);
}
QmlProfilerTextMarkModel::QmlProfilerTextMarkModel(QObject *parent) : QObject(parent)
@@ -82,7 +87,8 @@ void QmlProfilerTextMarkModel::addTextMarkId(int typeId, const QmlEventLocation
m_ids.insert(location.filename(), {typeId, location.line(), location.column()});
}
-void QmlProfilerTextMarkModel::createMarks(QmlProfilerTool *tool, const QString &fileName)
+void QmlProfilerTextMarkModel::createMarks(QmlProfilerViewManager *viewManager,
+ const QString &fileName)
{
auto first = m_ids.find(fileName);
QVarLengthArray<TextMarkId> ids;
@@ -103,7 +109,7 @@ void QmlProfilerTextMarkModel::createMarks(QmlProfilerTool *tool, const QString
m_marks.last()->addTypeId(it->typeId);
} else {
lineNumber = it->lineNumber;
- m_marks.append(new QmlProfilerTextMark(tool, it->typeId, fileName, it->lineNumber));
+ m_marks << new QmlProfilerTextMark(viewManager, it->typeId, fileName, it->lineNumber);
}
}
}
@@ -113,7 +119,7 @@ bool QmlProfilerTextMark::addToolTipContent(QLayout *target) const
QGridLayout *layout = new QGridLayout;
layout->setHorizontalSpacing(10);
for (int row = 0, rowEnd = m_typeIds.length(); row != rowEnd; ++row) {
- const QStringList typeDetails = m_tool->details(m_typeIds[row]);
+ const QStringList typeDetails = m_viewManager->statisticsView()->details(m_typeIds[row]);
for (int column = 0, columnEnd = typeDetails.length(); column != columnEnd; ++column) {
QLabel *label = new QLabel;
label->setAlignment(column == columnEnd - 1 ? Qt::AlignRight : Qt::AlignLeft);
diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.h b/src/plugins/qmlprofiler/qmlprofilertextmark.h
index 894e5fc517..19d13dcf79 100644
--- a/src/plugins/qmlprofiler/qmlprofilertextmark.h
+++ b/src/plugins/qmlprofiler/qmlprofilertextmark.h
@@ -25,16 +25,18 @@
#pragma once
#include "qmleventlocation.h"
-#include "qmlprofilertool.h"
#include <texteditor/textmark.h>
namespace QmlProfiler {
namespace Internal {
+class QmlProfilerViewManager;
+
class QmlProfilerTextMark : public TextEditor::TextMark
{
public:
- QmlProfilerTextMark(QmlProfilerTool *tool, int typeId, const QString &fileName, int lineNumber);
+ QmlProfilerTextMark(QmlProfilerViewManager *viewManager, int typeId,
+ const QString &fileName, int lineNumber);
void addTypeId(int typeId);
void paintIcon(QPainter *painter, const QRect &rect) const override;
@@ -43,7 +45,7 @@ public:
bool addToolTipContent(QLayout *target) const override;
private:
- QmlProfilerTool *m_tool;
+ QmlProfilerViewManager *m_viewManager;
QVector<int> m_typeIds;
};
@@ -55,7 +57,7 @@ public:
void clear();
void addTextMarkId(int typeId, const QmlEventLocation &location);
- void createMarks(QmlProfilerTool *tool, const QString &fileName);
+ void createMarks(QmlProfilerViewManager *viewManager, const QString &fileName);
private:
struct TextMarkId {
diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
index bfb4e26785..742bec73b4 100644
--- a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
@@ -55,14 +55,13 @@ public:
virtual void loadEvent(const QmlEvent &event, const QmlEventType &type) = 0;
virtual void finalize() = 0;
-private slots:
- void dataChanged();
- void onVisibleFeaturesChanged(quint64 features);
-
protected:
void announceFeatures(quint64 features);
private:
+ void dataChanged();
+ void onVisibleFeaturesChanged(quint64 features);
+
const Message m_message;
const RangeType m_rangeType;
const ProfileFeature m_mainFeature;
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index 423b8c655a..3488c93f14 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -290,7 +290,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
connect(editorManager, &EditorManager::editorCreated,
model, [this, model](Core::IEditor *editor, const QString &fileName) {
Q_UNUSED(editor);
- model->createMarks(this, fileName);
+ model->createMarks(d->m_viewContainer, fileName);
});
}
@@ -393,9 +393,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
// Initialize m_projectFinder
//
- if (runConfiguration) {
- d->m_profilerModelManager->populateFileFinder(runConfiguration);
- }
+ d->m_profilerModelManager->populateFileFinder(runConfiguration);
}
void QmlProfilerTool::recordingButtonChanged(bool recording)
@@ -439,11 +437,6 @@ void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber,
EditorManager::DoNotSwitchToDesignMode | EditorManager::DoNotSwitchToEditMode);
}
-void QmlProfilerTool::selectType(int typeId)
-{
- d->m_viewContainer->typeSelected(typeId);
-}
-
void QmlProfilerTool::updateTimeDisplay()
{
double seconds = 0;
@@ -502,7 +495,7 @@ void QmlProfilerTool::createTextMarks()
{
QmlProfilerTextMarkModel *model = d->m_profilerModelManager->textMarkModel();
foreach (IDocument *document, DocumentModel::openedDocuments())
- model->createMarks(this, document->filePath().toString());
+ model->createMarks(d->m_viewContainer, document->filePath().toString());
}
void QmlProfilerTool::clearTextMarks()
@@ -571,16 +564,6 @@ void QmlProfilerTool::attachToWaitingApplication()
ProjectExplorerPlugin::startRunControl(runControl);
}
-QString QmlProfilerTool::summary(const QVector<int> &typeIds) const
-{
- return d->m_viewContainer->statisticsView()->summary(typeIds);
-}
-
-QStringList QmlProfilerTool::details(int typeId) const
-{
- return d->m_viewContainer->statisticsView()->details(typeId);
-}
-
void QmlProfilerTool::logState(const QString &msg)
{
MessageManager::write(msg, MessageManager::Flash);
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.h b/src/plugins/qmlprofiler/qmlprofilertool.h
index c50747e85b..4b784dfe8e 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.h
+++ b/src/plugins/qmlprofiler/qmlprofilertool.h
@@ -55,9 +55,6 @@ public:
bool prepareTool();
void attachToWaitingApplication();
- QString summary(const QVector<int> &typeIds) const;
- QStringList details(int typeId) const;
-
static QList <QAction *> profilerContextMenuActions();
// display dialogs / log output
@@ -67,7 +64,6 @@ public:
static QmlProfilerClientManager *clientManager();
-public slots:
void profilerStateChanged();
void serverRecordingChanged();
void clientsDisconnected();
@@ -76,9 +72,8 @@ public slots:
void recordingButtonChanged(bool recording);
void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber);
- void selectType(int typeId);
-private slots:
+private:
void clearData();
void showErrorDialog(const QString &error);
void profilerDataModelStateChanged();
@@ -94,7 +89,6 @@ private slots:
void toggleRequestedFeature(QAction *action);
void toggleVisibleFeature(QAction *action);
-private:
void updateRunActions();
void clearDisplay();
template<ProfileFeature feature>
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
index 76dbf37009..39cdb96ede 100644
--- a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
@@ -138,7 +138,8 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent()
break;
case RangeEnd: {
int typeIndex = resolveStackTop();
- QTC_ASSERT(typeIndex != -1, break);
+ if (typeIndex == -1)
+ break;
currentEvent.event.setTypeIndex(typeIndex);
while (!pendingMessages.isEmpty())
modelManager->addEvent(pendingMessages.dequeue());
@@ -147,10 +148,12 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent()
break;
}
case RangeData:
- rangesInProgress.top().type.setData(currentEvent.type.data());
+ if (!rangesInProgress.isEmpty())
+ rangesInProgress.top().type.setData(currentEvent.type.data());
break;
case RangeLocation:
- rangesInProgress.top().type.setLocation(currentEvent.type.location());
+ if (!rangesInProgress.isEmpty())
+ rangesInProgress.top().type.setLocation(currentEvent.type.location());
break;
default: {
int typeIndex = resolveType(currentEvent);
@@ -166,7 +169,7 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent()
void QmlProfilerTraceClientPrivate::sendRecordingStatus(int engineId)
{
- QmlDebug::QPacket stream(q->connection()->currentDataStreamVersion());
+ QmlDebug::QPacket stream(q->dataStreamVersion());
stream << recording << engineId; // engineId -1 is OK. It means "all of them"
if (recording) {
stream << requestedFeatures << flushInterval;
@@ -244,7 +247,7 @@ void QmlProfilerTraceClient::setRequestedFeatures(quint64 features)
const QmlDebug::QDebugContextInfo &context)
{
d->updateFeatures(ProfileDebugMessages);
- d->currentEvent.event.setTimestamp(context.timestamp);
+ d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0);
d->currentEvent.event.setTypeIndex(-1);
d->currentEvent.event.setString(text);
d->currentEvent.type = QmlEventType(DebugMessage, MaximumRangeType, type,
@@ -282,7 +285,7 @@ void QmlProfilerTraceClient::stateChanged(State status)
void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
{
- QmlDebug::QPacket stream(connection()->currentDataStreamVersion(), data);
+ QmlDebug::QPacket stream(dataStreamVersion(), data);
stream >> d->currentEvent;
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.h b/src/plugins/qmlprofiler/qmlprofilertraceclient.h
index 237fdc002a..b0f17c9789 100644
--- a/src/plugins/qmlprofiler/qmlprofilertraceclient.h
+++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.h
@@ -52,8 +52,9 @@ public:
bool isRecording() const;
void setRecording(bool);
quint64 recordedFeatures() const;
+ virtual void messageReceived(const QByteArray &) override;
+ virtual void stateChanged(State status) override;
-public slots:
void clearData();
void sendRecordingStatus(int engineId = -1);
void setRequestedFeatures(quint64 features);
@@ -69,10 +70,6 @@ signals:
void cleared();
-protected:
- virtual void stateChanged(State status);
- virtual void messageReceived(const QByteArray &);
-
private:
class QmlProfilerTraceClientPrivate *d;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
index b84de415ae..87f6e89e44 100644
--- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
@@ -108,7 +108,7 @@ static QString qmlTypeAsString(Message message, RangeType rangeType)
{
if (rangeType < MaximumRangeType)
return _(RANGE_TYPE_STRINGS[rangeType]);
- else if (message != MaximumMessage)
+ else if (message < MaximumMessage)
return _(MESSAGE_STRINGS[message]);
else
return QString::number((int)rangeType);
@@ -257,6 +257,8 @@ void QmlProfilerFileReader::loadQzt(QIODevice *device)
return;
}
m_loadedFeatures |= (1ULL << m_eventTypes[event.typeIndex()].feature());
+ if (event.timestamp() < 0)
+ event.setTimestamp(0);
} else if (bufferStream.status() == QDataStream::ReadPastEnd) {
break; // Apparently EOF is a character so we end up here after the last event.
} else if (bufferStream.status() == QDataStream::ReadCorruptData) {
@@ -506,15 +508,16 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream)
continue;
}
- event.setTimestamp(attributes.value(_("startTime")).toLongLong());
+ const qint64 timestamp = attributes.value(_("startTime")).toLongLong();
+ event.setTimestamp(timestamp > 0 ? timestamp : 0);
event.setTypeIndex(attributes.value(_("eventIndex")).toInt());
if (attributes.hasAttribute(_("duration"))) {
event.setRangeStage(RangeStart);
QmlEvent rangeEnd(event);
rangeEnd.setRangeStage(RangeEnd);
- rangeEnd.setTimestamp(event.timestamp()
- + attributes.value(_("duration")).toLongLong());
+ const qint64 duration = attributes.value(_("duration")).toLongLong();
+ rangeEnd.setTimestamp(event.timestamp() + (duration > 0 ? duration : 0));
events.addRange(event, rangeEnd);
} else {
// attributes for special events
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp
index a7bf3fe468..7efdefa93a 100644
--- a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp
@@ -183,8 +183,8 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag
d->m_zoomControl);
d->m_mainView->setSource(QUrl(QLatin1String("qrc:/timeline/MainView.qml")));
- QQuickItem *rootObject = d->m_mainView->rootObject();
- connect(rootObject, SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
+ connect(d->m_modelProxy, &Timeline::TimelineModelAggregator::updateCursorPosition,
+ this, &QmlProfilerTraceView::updateCursorPosition);
}
QmlProfilerTraceView::~QmlProfilerTraceView()
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.h b/src/plugins/qmlprofiler/qmlprofilertraceview.h
index 79063ac261..0c5fc2efed 100644
--- a/src/plugins/qmlprofiler/qmlprofilertraceview.h
+++ b/src/plugins/qmlprofiler/qmlprofilertraceview.h
@@ -55,7 +55,6 @@ public:
bool isUsable() const;
bool isSuspended() const;
-public slots:
void clear();
void selectByTypeId(int typeId);
void selectByEventIndex(int modelId, int eventIndex);
diff --git a/src/plugins/qmlprofiler/qmltypedevent.cpp b/src/plugins/qmlprofiler/qmltypedevent.cpp
index e5007345b5..30bfeb9b70 100644
--- a/src/plugins/qmlprofiler/qmltypedevent.cpp
+++ b/src/plugins/qmlprofiler/qmltypedevent.cpp
@@ -36,15 +36,20 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
stream >> time >> messageType;
+ if (messageType < 0 || messageType > MaximumMessage)
+ messageType = MaximumMessage;
+
RangeType rangeType = MaximumRangeType;
if (!stream.atEnd()) {
stream >> subtype;
rangeType = static_cast<RangeType>(subtype);
+ if (rangeType < 0 || rangeType > MaximumRangeType)
+ rangeType = MaximumRangeType;
} else {
subtype = -1;
}
- event.event.setTimestamp(time);
+ event.event.setTimestamp(time > 0 ? time : 0);
event.event.setTypeIndex(-1);
event.serverTypeId = 0;
@@ -180,6 +185,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
break;
}
default:
+ event.event.setNumbers<char>({});
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype);
break;
}
diff --git a/src/plugins/qmlprofiler/tests/Test.qml b/src/plugins/qmlprofiler/tests/Test.qml
new file mode 100644
index 0000000000..e0fc79d1da
--- /dev/null
+++ b/src/plugins/qmlprofiler/tests/Test.qml
@@ -0,0 +1,7 @@
+import QtQml 2.0
+
+QtObject {
+ property int dings: 12 + 12 + 12
+ property string no: "nonono"
+ objectName: { return no + Math.random(); }
+}
diff --git a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp
index 781a14d4e9..0d24d359ac 100644
--- a/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/inputeventsmodel_test.cpp
@@ -32,6 +32,11 @@
namespace QmlProfiler {
namespace Internal {
+static InputEventType inputType(int i)
+{
+ return static_cast<InputEventType>(i % (MaximumInputEventType + 1));
+}
+
InputEventsModelTest::InputEventsModelTest(QObject *parent) :
QObject(parent), manager(nullptr), model(&manager)
{
@@ -48,13 +53,14 @@ void InputEventsModelTest::initTestCase()
for (int i = 0; i < 10; ++i) {
event.setTimestamp(i);
- InputEventType type = static_cast<InputEventType>(i % MaximumInputEventType);
+ InputEventType type = inputType(i);
event.setTypeIndex(type <= InputKeyUnknown ? keyTypeId : mouseTypeId);
event.setNumbers({static_cast<qint32>(type),
(i * 32) % 256,
static_cast<qint32>((i * 0x02000000) & Qt::KeyboardModifierMask)});
manager.addEvent(event);
}
+
manager.acquiringDone();
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
}
@@ -71,7 +77,7 @@ void InputEventsModelTest::testAccepted()
void InputEventsModelTest::testTypeId()
{
for (int i = 0; i < 10; ++i) {
- InputEventType type = static_cast<InputEventType>(i % MaximumInputEventType);
+ InputEventType type = inputType(i);
QCOMPARE(model.typeId(i), type <= InputKeyUnknown ? keyTypeId : mouseTypeId);
}
}
@@ -81,7 +87,7 @@ void InputEventsModelTest::testColor()
QRgb keyColor = 0;
QRgb mouseColor = 0;
for (int i = 0; i < 10; ++i) {
- InputEventType type = static_cast<InputEventType>(i % MaximumInputEventType);
+ InputEventType type = inputType(i);
int selectionId = (type <= InputKeyUnknown ? Key : Mouse);
QCOMPARE(selectionId, model.selectionId(i));
@@ -112,7 +118,7 @@ void InputEventsModelTest::testDetails()
QCOMPARE(details[model.tr("Timestamp")].toString(), Timeline::formatTime(i));
QString displayName = details[QString("displayName")].toString();
QVERIFY(!displayName.isEmpty());
- switch (static_cast<InputEventType>(i % MaximumInputEventType)) {
+ switch (inputType(i)) {
case InputKeyPress:
QCOMPARE(displayName, model.tr("Key Press"));
if (i == 0) {
@@ -177,7 +183,7 @@ void InputEventsModelTest::testDetails()
QVERIFY(!details.contains(model.tr("Result")));
break;
default:
- Q_UNREACHABLE();
+ QCOMPARE(displayName, model.tr("Unknown"));
break;
}
}
@@ -186,7 +192,7 @@ void InputEventsModelTest::testDetails()
void InputEventsModelTest::testExpandedRow()
{
for (int i = 0; i < 10; ++i) {
- InputEventType type = static_cast<InputEventType>(i % MaximumInputEventType);
+ InputEventType type = inputType(i);
QCOMPARE(model.expandedRow(i), (type <= InputKeyUnknown ? 2 : 1));
}
}
diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
index 53489eaee8..3bf680be5b 100644
--- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
+++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
@@ -56,6 +56,7 @@ void LocalQmlProfilerRunnerTest::testRunner()
debuggee.environment = Utils::Environment::systemEnvironment();
// should not be used anywhere but cannot be empty
+ serverUrl.setScheme(ProjectExplorer::urlSocketScheme());
serverUrl.setPath("invalid");
runControl = new ProjectExplorer::RunControl(nullptr,
@@ -92,8 +93,8 @@ void LocalQmlProfilerRunnerTest::testRunner()
runControl->initiateStart();
- QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 20000);
- QTRY_VERIFY_WITH_TIMEOUT(!started, 20000);
+ QTRY_COMPARE_WITH_TIMEOUT(startCount, 1, 30000);
+ QTRY_VERIFY_WITH_TIMEOUT(!started, 30000);
QCOMPARE(stopCount, 1);
QCOMPARE(runCount, 0);
@@ -113,8 +114,8 @@ void LocalQmlProfilerRunnerTest::testRunner()
connectRunner();
runControl->initiateStart();
- QTRY_VERIFY_WITH_TIMEOUT(running, 20000);
- QTRY_VERIFY_WITH_TIMEOUT(!running, 20000);
+ QTRY_VERIFY_WITH_TIMEOUT(running, 30000);
+ QTRY_VERIFY_WITH_TIMEOUT(!running, 30000);
QCOMPARE(startCount, 2);
QCOMPARE(stopCount, 2);
QCOMPARE(runCount, 1);
@@ -133,9 +134,9 @@ void LocalQmlProfilerRunnerTest::testRunner()
connectRunner();
runControl->initiateStart();
- QTRY_VERIFY_WITH_TIMEOUT(running, 20000);
+ QTRY_VERIFY_WITH_TIMEOUT(running, 30000);
runControl->initiateStop();
- QTRY_VERIFY_WITH_TIMEOUT(!running, 20000);
+ QTRY_VERIFY_WITH_TIMEOUT(!running, 30000);
QCOMPARE(startCount, 3);
QCOMPARE(stopCount, 3);
QCOMPARE(runCount, 2);
diff --git a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp
index 0b4d39fdc6..903e2b1332 100644
--- a/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/pixmapcachemodel_test.cpp
@@ -38,7 +38,8 @@ PixmapCacheModelTest::PixmapCacheModelTest(QObject *parent) : QObject(parent),
void PixmapCacheModelTest::initTestCase()
{
manager.startAcquiring();
- manager.traceTime()->setTime(1, 300);
+ manager.traceTime()->decreaseStartTime(1);
+ manager.traceTime()->increaseEndTime(300);
for (int i = 0; i < MaximumPixmapEventType; ++i) {
eventTypeIndices[i] = manager.numLoadedEventTypes();
diff --git a/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp
index 846ff731d6..d5723dd731 100644
--- a/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp
+++ b/src/plugins/qmlprofiler/tests/qmlprofileranimationsmodel_test.cpp
@@ -51,7 +51,7 @@ void QmlProfilerAnimationsModelTest::initTestCase()
for (int i = 0; i < 10; ++i) {
event.setTimestamp(i);
- event.setNumbers<int>({frameRate(i), 20 - i, (i % 2) ? RenderThread : GuiThread});
+ event.setNumbers<int>({frameRate(i), 9 - i, (i % 2) ? RenderThread : GuiThread});
manager.addEvent(event);
}
manager.acquiringDone();
@@ -69,8 +69,8 @@ void QmlProfilerAnimationsModelTest::testAccepted()
void QmlProfilerAnimationsModelTest::testRowMaxValue()
{
QCOMPARE(model.rowMaxValue(0), 0);
- QCOMPARE(model.rowMaxValue(1), 20);
- QCOMPARE(model.rowMaxValue(2), 19);
+ QCOMPARE(model.rowMaxValue(1), 9);
+ QCOMPARE(model.rowMaxValue(2), 8);
}
void QmlProfilerAnimationsModelTest::testRowNumbers()
@@ -133,7 +133,7 @@ void QmlProfilerAnimationsModelTest::testDetails()
QCOMPARE(details[QmlProfilerAnimationsModel::tr("Framerate")].toString(),
QString::fromLatin1("%1 FPS").arg(frameRate(i)));
QCOMPARE(details[QmlProfilerAnimationsModel::tr("Animations")].toString(),
- QString::number(20 - i));
+ QString::number(9 - i));
QCOMPARE(details[QmlProfilerAnimationsModel::tr("Context")].toString(), i % 2 ?
QmlProfilerAnimationsModel::tr("Render Thread") :
QmlProfilerAnimationsModel::tr("GUI Thread"));
diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp
index d2347d4264..0318a6b618 100644
--- a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp
+++ b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp
@@ -73,38 +73,32 @@ void QmlProfilerClientManagerTest::testConnectionFailure_data()
QUrl localUrl = urlFromLocalHostAndFreePort();
QTest::addColumn<QUrl>("serverUrl");
- QVarLengthArray<QString> hosts({"", "/-/|\\-\\|/-", localUrl.host()});
- QVarLengthArray<int> ports({-1, 5, localUrl.port()});
- QVarLengthArray<QString> sockets({"", "/-/|\\-\\|/-", urlFromLocalSocket().path()});
-
- foreach (QmlProfilerModelManager *modelManager, modelManagers) {
- foreach (QmlProfilerStateManager *stateManager, stateManagers) {
- foreach (QString host, hosts) {
- foreach (int port, ports) {
- QString tag = QString::fromLatin1("%1, %2, %3, %4, %5")
- .arg(QLatin1String(modelManager ? "modelManager" : "<null>"))
- .arg(QLatin1String(stateManager ? "stateManager" : "<null>"))
- .arg(host.isEmpty() ? "<empty>" : host)
- .arg(Utils::Port(port).isValid() ? port : 0)
- .arg("<empty>");
- QUrl url;
- url.setHost(host);
- url.setPort(port);
- QTest::newRow(tag.toLatin1().constData()) << modelManager << stateManager << url;
+ const QVarLengthArray<QString> hosts({"", "/-/|\\-\\|/-", localUrl.host()});
+ const QVarLengthArray<int> ports({-1, 5, localUrl.port()});
+ const QVarLengthArray<QString> sockets({"", "/-/|\\-\\|/-", urlFromLocalSocket().path()});
+ const QVarLengthArray<QString> schemes({"", urlSocketScheme(), urlTcpScheme()});
+
+ for (QmlProfilerModelManager *modelManager : modelManagers) {
+ for (QmlProfilerStateManager *stateManager : stateManagers) {
+ for (const QString &host : hosts) {
+ for (int port : ports) {
+ for (const QString &socket : sockets) {
+ for (const QString &scheme : schemes ) {
+ QUrl url;
+ url.setScheme(scheme);
+ url.setHost(host);
+ url.setPort(port);
+ url.setPath(socket);
+ QString tag = QString::fromLatin1("%1, %2, %3")
+ .arg(QLatin1String(modelManager ? "modelManager" : "<null>"))
+ .arg(QLatin1String(stateManager ? "stateManager" : "<null>"))
+ .arg(url.toString());
+ QTest::newRow(tag.toLatin1().constData()) << modelManager
+ << stateManager << url;
+ }
+ }
}
}
- foreach (QString socket, sockets) {
- QString tag = QString::fromLatin1("%1, %2, %3, %4, %5")
- .arg(QLatin1String(modelManager ? "modelManager" : "<null>"))
- .arg(QLatin1String(stateManager ? "stateManager" : "<null>"))
- .arg("<empty>")
- .arg(0)
- .arg(socket);
- QUrl url;
- url.setScheme(urlSocketScheme());
- url.setPath(socket);
- QTest::newRow(tag.toLatin1().constData()) << modelManager << stateManager << url;
- }
}
}
}
@@ -137,24 +131,17 @@ void QmlProfilerClientManagerTest::testConnectionFailure()
clientManager.setModelManager(modelManager);
clientManager.setProfilerStateManager(stateManager);
- clientManager.setServerUrl(serverUrl);
QVERIFY(!clientManager.isConnected());
- clientManager.connectToTcpServer();
+ clientManager.connectToServer(serverUrl);
QTRY_COMPARE(failedSpy.count(), 1);
QCOMPARE(closedSpy.count(), 0);
QCOMPARE(openedSpy.count(), 0);
QVERIFY(!clientManager.isConnected());
- clientManager.startLocalServer();
- QTRY_COMPARE(failedSpy.count(), 2);
- QCOMPARE(closedSpy.count(), 0);
- QCOMPARE(openedSpy.count(), 0);
- QVERIFY(!clientManager.isConnected());
-
clientManager.retryConnect();
- QTRY_COMPARE(failedSpy.count(), 3);
+ QTRY_COMPARE(failedSpy.count(), 2);
QCOMPARE(closedSpy.count(), 0);
QCOMPARE(openedSpy.count(), 0);
QVERIFY(!clientManager.isConnected());
@@ -181,8 +168,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveTcp()
server.listen(QHostAddress(serverUrl.host()), serverUrl.port());
QSignalSpy connectionSpy(&server, SIGNAL(newConnection()));
- clientManager.setServerUrl(serverUrl);
- clientManager.connectToTcpServer();
+ clientManager.connectToServer(serverUrl);
QTRY_VERIFY(connectionSpy.count() > 0);
QTRY_COMPARE(failedSpy.count(), 1);
@@ -208,8 +194,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveLocal()
QLocalSocket socket;
QSignalSpy connectionSpy(&socket, SIGNAL(connected()));
- clientManager.setServerUrl(socketUrl);
- clientManager.startLocalServer();
+ clientManager.connectToServer(socketUrl);
socket.connectToServer(socketUrl.path());
QTRY_COMPARE(connectionSpy.count(), 1);
@@ -280,8 +265,7 @@ void QmlProfilerClientManagerTest::testResponsiveTcp()
connect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
- clientManager.setServerUrl(serverUrl);
- clientManager.connectToTcpServer();
+ clientManager.connectToServer(serverUrl);
QTRY_COMPARE(openedSpy.count(), 1);
QCOMPARE(closedSpy.count(), 0);
@@ -329,8 +313,7 @@ void QmlProfilerClientManagerTest::testResponsiveLocal()
connect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
- clientManager.setServerUrl(socketUrl);
- clientManager.startLocalServer();
+ clientManager.connectToServer(socketUrl);
{
QScopedPointer<QLocalSocket> socket(new QLocalSocket(this));
@@ -397,8 +380,7 @@ void QmlProfilerClientManagerTest::testInvalidData()
server.listen(QHostAddress(serverUrl.host()), serverUrl.port());
- clientManager.setServerUrl(serverUrl);
- clientManager.connectToTcpServer();
+ clientManager.connectToServer(serverUrl);
QTRY_VERIFY(dataSent);
QTRY_COMPARE(failedSpy.count(), 1);
@@ -427,8 +409,7 @@ void QmlProfilerClientManagerTest::testStopRecording()
connect(&clientManager, &QmlProfilerClientManager::connectionFailed,
&clientManager, &QmlProfilerClientManager::retryConnect);
- clientManager.setServerUrl(socketUrl);
- clientManager.startLocalServer();
+ clientManager.connectToServer(socketUrl);
QScopedPointer<QLocalSocket> socket(new QLocalSocket(this));
socket->connectToServer(socketUrl.path());
diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp
new file mode 100644
index 0000000000..3363619d78
--- /dev/null
+++ b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "qmlprofilerdetailsrewriter_test.h"
+
+#include <projectexplorer/customexecutablerunconfiguration.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/kitmanager.h>
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/kitinformation.h>
+
+#include <QLibraryInfo>
+#include <QTest>
+
+namespace QmlProfiler {
+namespace Internal {
+
+class DummyProjectNode : public ProjectExplorer::ProjectNode
+{
+public:
+ DummyProjectNode(const Utils::FileName &file) : ProjectExplorer::ProjectNode(file)
+ {}
+};
+
+class DummyProject : public ProjectExplorer::Project
+{
+ Q_OBJECT
+public:
+ DummyProject(const Utils::FileName &file) :
+ ProjectExplorer::Project(QString(), file, {})
+ {
+ ProjectExplorer::FileNode *fileNode
+ = new ProjectExplorer::FileNode(file, ProjectExplorer::FileType::Source, false);
+ DummyProjectNode *root = new DummyProjectNode(file);
+ root->addNode(fileNode);
+ fileNode = new ProjectExplorer::FileNode(
+ Utils::FileName::fromLatin1(
+ ":/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.cpp"),
+ ProjectExplorer::FileType::Source, false);
+ root->addNode(fileNode);
+ setRootProjectNode(root);
+ }
+};
+
+QmlProfilerDetailsRewriterTest::QmlProfilerDetailsRewriterTest(QObject *parent) : QObject(parent)
+{
+ connect(&m_rewriter, &QmlProfilerDetailsRewriter::eventDetailsChanged,
+ this, [this]() {
+ m_rewriterDone = true;
+ });
+}
+
+void QmlProfilerDetailsRewriterTest::testMissingModelManager()
+{
+ seedRewriter();
+ delete m_modelManager;
+ m_modelManager = nullptr;
+
+ // Verify it doesn't crash if model manager is missing.
+ QVERIFY(!m_rewriterDone);
+ auto rewriteConnection = connect(&m_rewriter, &QmlProfilerDetailsRewriter::rewriteDetailsString,
+ this, [&](int typeId, const QString &string) {
+ Q_UNUSED(typeId);
+ Q_UNUSED(string);
+ QFAIL("found nonexisting file in nonexisting model manager");
+ });
+ m_rewriter.requestDetailsForLocation(44, QmlEventLocation("Test.qml", 12, 12));
+ m_rewriter.reloadDocuments();
+ QVERIFY(m_rewriterDone);
+ m_rewriterDone = false;
+ disconnect(rewriteConnection);
+}
+
+void QmlProfilerDetailsRewriterTest::testRequestDetailsForLocation()
+{
+ seedRewriter();
+ QVERIFY(!m_rewriterDone);
+ bool found1 = false;
+ bool found2 = false;
+ auto rewriteConnection = connect(&m_rewriter, &QmlProfilerDetailsRewriter::rewriteDetailsString,
+ this, [&](int typeId, const QString &string) {
+ if (typeId == 1) {
+ QCOMPARE(string, QString::fromLatin1("property int dings: 12 + 12 + 12"));
+ found1 = true;
+ } else if (typeId == 2) {
+ QCOMPARE(string, QString::fromLatin1("objectName: { return no + Math.random(); }"));
+ found2 = true;
+ } else {
+ QFAIL("invalid typeId");
+ }
+ });
+
+ m_rewriter.requestDetailsForLocation(12, QmlEventLocation("Test.qml", 5, 25));
+ // simulate unrelated document update: Shouldn't send any events our way.
+ emit m_modelManager->documentUpdated(QmlJS::Document::create("gibtsnich.qml",
+ QmlJS::Dialect::Qml));
+ m_rewriter.clear();
+ QVERIFY(!found1);
+ QVERIFY(!found2);
+ QVERIFY(!m_rewriterDone);
+
+ m_rewriter.requestDetailsForLocation(1, QmlEventLocation("Test.qml", 4, 25));
+ m_rewriter.requestDetailsForLocation(2, QmlEventLocation("Test.qml", 6, 17));
+ m_rewriter.requestDetailsForLocation(42, QmlEventLocation("gibtsnich.qml", 6, 17));
+ m_rewriter.requestDetailsForLocation(14, QmlEventLocation("Test.qml", 55, 4));
+ m_rewriter.reloadDocuments();
+
+ QTRY_VERIFY(found1);
+ QTRY_VERIFY(found2);
+ QTRY_VERIFY(m_rewriterDone);
+
+ found1 = found2 = m_rewriterDone = false;
+ m_rewriter.reloadDocuments();
+ QVERIFY(!found1);
+ QVERIFY(!found2);
+ QVERIFY(m_rewriterDone);
+ m_rewriterDone = false;
+
+ disconnect(rewriteConnection);
+}
+
+void QmlProfilerDetailsRewriterTest::testGetLocalFile()
+{
+ seedRewriter();
+ QCOMPARE(m_rewriter.getLocalFile("notthere.qml"), QString());
+ QCOMPARE(m_rewriter.getLocalFile("Test.qml"),
+ QString::fromLatin1(":/qmlprofiler/tests/Test.qml"));
+ QCOMPARE(m_rewriter.getLocalFile("qmlprofilerdetailsrewriter_test.cpp"), QString());
+}
+
+void QmlProfilerDetailsRewriterTest::testPopulateFileFinder()
+{
+ m_rewriter.populateFileFinder(nullptr);
+ QCOMPARE(m_rewriter.getLocalFile("Test.qml"), QString());
+
+ // Test that the rewriter will populate from available projects if given nullptr as parameter.
+ DummyProject *project1 = new DummyProject(Utils::FileName::fromString(":/nix.nix"));
+ ProjectExplorer::SessionManager::addProject(project1);
+ DummyProject *project2 = new DummyProject(
+ Utils::FileName::fromString(":/qmlprofiler/tests/Test.qml"));
+ ProjectExplorer::SessionManager::addProject(project2);
+ m_rewriter.populateFileFinder(nullptr);
+ QCOMPARE(m_rewriter.getLocalFile("Test.qml"),
+ QString::fromLatin1(":/qmlprofiler/tests/Test.qml"));
+
+ ProjectExplorer::SessionManager::removeProject(project1);
+ ProjectExplorer::SessionManager::removeProject(project2);
+}
+
+void QmlProfilerDetailsRewriterTest::seedRewriter()
+{
+ delete m_modelManager;
+ m_modelManager = new QmlJS::ModelManagerInterface(this);
+ QString filename = ":/qmlprofiler/tests/Test.qml";
+
+ QFutureInterface<void> result;
+ QmlJS::PathsAndLanguages lPaths;
+ for (auto p : QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath))
+ lPaths.maybeInsert(Utils::FileName::fromString(p), QmlJS::Dialect::Qml);
+ QmlJS::ModelManagerInterface::importScan(result, QmlJS::ModelManagerInterface::workingCopy(),
+ lPaths, m_modelManager, false);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly | QFile::Text);
+ const QString content = QString::fromUtf8(file.readAll());
+ file.close();
+
+ QmlJS::Document::MutablePtr doc = QmlJS::Document::create(filename, QmlJS::Dialect::Qml);
+ doc->setSource(content);
+ doc->parse();
+ QVERIFY(!doc->source().isEmpty());
+
+ ProjectExplorer::Kit *kit = new ProjectExplorer::Kit;
+ ProjectExplorer::SysRootKitInformation::setSysRoot(
+ kit, Utils::FileName::fromLatin1("/nowhere"));
+
+ DummyProject *project = new DummyProject(Utils::FileName::fromString(filename));
+ ProjectExplorer::SessionManager::addProject(project);
+ ProjectExplorer::Target *target = project->createTarget(kit);
+
+ ProjectExplorer::CustomExecutableRunConfiguration *rc
+ = new ProjectExplorer::CustomExecutableRunConfiguration(target);
+ m_rewriter.populateFileFinder(rc);
+ ProjectExplorer::SessionManager::removeProject(project);
+ ProjectExplorer::KitManager::deleteKit(kit);
+}
+
+} // namespace Internal
+} // namespace QmlProfiler
+
+#include "qmlprofilerdetailsrewriter_test.moc"
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.h
index cabf468806..35142952c2 100644
--- a/src/plugins/debugger/gdb/attachgdbadapter.h
+++ b/src/plugins/qmlprofiler/tests/qmlprofilerdetailsrewriter_test.h
@@ -25,33 +25,31 @@
#pragma once
-#include "gdbengine.h"
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmlprofiler/qmlprofilerdetailsrewriter.h>
-namespace Debugger {
+namespace QmlProfiler {
namespace Internal {
-///////////////////////////////////////////////////////////////////////
-//
-// AttachGdbAdapter
-//
-///////////////////////////////////////////////////////////////////////
-
-class GdbAttachEngine : public GdbEngine
+class QmlProfilerDetailsRewriterTest : public QObject
{
Q_OBJECT
-
public:
- explicit GdbAttachEngine(bool useTerminal);
+ explicit QmlProfilerDetailsRewriterTest(QObject *parent = nullptr);
+
+private slots:
+ void testMissingModelManager();
+ void testRequestDetailsForLocation();
+ void testGetLocalFile();
+ void testPopulateFileFinder();
private:
- void setupEngine() override;
- void setupInferior() override;
- void runEngine() override;
- void interruptInferior2() override;
- void shutdownEngine() override;
+ QmlJS::ModelManagerInterface *m_modelManager = nullptr;
+ QmlProfilerDetailsRewriter m_rewriter;
+ bool m_rewriterDone = false;
- void handleAttach(const DebuggerResponse &response);
+ void seedRewriter();
};
} // namespace Internal
-} // namespace Debugger
+} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/tests/tests.pri b/src/plugins/qmlprofiler/tests/tests.pri
index feeda0cc40..c456010043 100644
--- a/src/plugins/qmlprofiler/tests/tests.pri
+++ b/src/plugins/qmlprofiler/tests/tests.pri
@@ -15,6 +15,7 @@ SOURCES += \
$$PWD/qmlprofilerbindingloopsrenderpass_test.cpp \
$$PWD/qmlprofilerclientmanager_test.cpp \
$$PWD/qmlprofilerconfigwidget_test.cpp \
+ $$PWD/qmlprofilerdetailsrewriter_test.cpp \
$$PWD/qmlprofilertraceview_test.cpp
HEADERS += \
@@ -34,4 +35,8 @@ HEADERS += \
$$PWD/qmlprofilerbindingloopsrenderpass_test.h \
$$PWD/qmlprofilerclientmanager_test.h \
$$PWD/qmlprofilerconfigwidget_test.h \
+ $$PWD/qmlprofilerdetailsrewriter_test.h \
$$PWD/qmlprofilertraceview_test.h
+
+RESOURCES += \
+ $$PWD/tests.qrc
diff --git a/src/plugins/qmlprofiler/tests/tests.qrc b/src/plugins/qmlprofiler/tests/tests.qrc
new file mode 100644
index 0000000000..323fb37b14
--- /dev/null
+++ b/src/plugins/qmlprofiler/tests/tests.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qmlprofiler/tests">
+ <file>Test.qml</file>
+ <file>qmlprofilerdetailsrewriter_test.cpp</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 49de48f762..4e2ca8c259 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -101,7 +101,7 @@ void QmlProject::addedRunConfiguration(RunConfiguration *rc)
// they have been added to a project
QmlProjectRunConfiguration *qmlrc = qobject_cast<QmlProjectRunConfiguration *>(rc);
if (qmlrc)
- qmlrc->updateEnabled();
+ qmlrc->updateEnabledState();
}
QDir QmlProject::projectDir() const
@@ -170,6 +170,7 @@ void QmlProject::parseProject(RefreshOptions options)
void QmlProject::refresh(RefreshOptions options)
{
+ emitParsingStarted();
parseProject(options);
if (options & Files)
@@ -187,7 +188,7 @@ void QmlProject::refresh(RefreshOptions options)
modelManager->updateProjectInfo(projectInfo, this);
- emit parsingFinished();
+ emitParsingFinished(true);
}
QString QmlProject::mainFile() const
diff --git a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
index ecf191a02f..10d804dfa8 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
@@ -32,8 +32,6 @@
#include <utils/algorithm.h>
-#include <QStyle>
-
using namespace ProjectExplorer;
namespace QmlProjectManager {
@@ -43,13 +41,9 @@ QmlProjectNode::QmlProjectNode(QmlProject *project) : ProjectNode(project->proje
m_project(project)
{
setDisplayName(project->projectFilePath().toFileInfo().completeBaseName());
- // make overlay
- const QSize desiredSize = QSize(16, 16);
- const QIcon projectBaseIcon(QLatin1String(":/qmlproject/images/qmlfolder.png"));
- const QPixmap projectPixmap = Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon,
- projectBaseIcon,
- desiredSize);
- setIcon(QIcon(projectPixmap));
+
+ static QIcon qmlProjectIcon = Core::FileIconProvider::directoryIcon(QLatin1String(":/qmlproject/images/qmlfolder.png"));
+ setIcon(qmlProjectIcon);
}
bool QmlProjectNode::showInSimpleTree() const
@@ -57,13 +51,15 @@ bool QmlProjectNode::showInSimpleTree() const
return true;
}
-bool QmlProjectNode::supportsAction(ProjectAction action, Node *node) const
+bool QmlProjectNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == AddNewFile || action == EraseFile)
return true;
+ QTC_ASSERT(node, return false);
if (action == Rename && node->nodeType() == NodeType::File) {
- FileNode *fileNode = static_cast<FileNode *>(node);
+ const FileNode *fileNode = node->asFileNode();
+ QTC_ASSERT(fileNode, return false);
return fileNode->fileType() != FileType::Project;
}
diff --git a/src/plugins/qmlprojectmanager/qmlprojectnodes.h b/src/plugins/qmlprojectmanager/qmlprojectnodes.h
index bc715d86f6..35ebf428f8 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectnodes.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectnodes.h
@@ -39,7 +39,7 @@ public:
QmlProjectNode(QmlProject *project);
bool showInSimpleTree() const override;
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0) override;
bool deleteFiles(const QStringList &filePaths) override;
bool renameFile(const QString &filePath, const QString &newFilePath) override;
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index 1c2e77fb04..f1ee22c7e6 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -51,14 +51,43 @@ namespace QmlProjectManager {
const char M_CURRENT_FILE[] = "CurrentFile";
-QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *parent, Id id) :
- RunConfiguration(parent, id),
- m_scriptFile(QLatin1String(M_CURRENT_FILE)),
- m_isEnabled(false)
+QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
addExtraAspect(new QmlProjectEnvironmentAspect(this));
- ctor();
+ // reset default settings in constructor
+ connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
+ this, &QmlProjectRunConfiguration::changeCurrentFile);
+ connect(EditorManager::instance(), &EditorManager::currentDocumentStateChanged,
+ this, [this] { changeCurrentFile(); });
+
+ connect(target, &Target::kitChanged,
+ this, &QmlProjectRunConfiguration::updateEnabledState);
+}
+
+void QmlProjectRunConfiguration::initialize(Id id)
+{
+ RunConfiguration::initialize(id);
+ m_scriptFile = M_CURRENT_FILE;
+
+ if (id == Constants::QML_SCENE_RC_ID)
+ setDisplayName(tr("QML Scene", "QMLRunConfiguration display name."));
+ else
+ setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));
+
+ updateEnabledState();
+}
+
+void QmlProjectRunConfiguration::copyFrom(const QmlProjectRunConfiguration *source)
+{
+ RunConfiguration::copyFrom(source);
+ m_currentFileFilename = source->m_currentFileFilename;
+ m_mainScriptFilename = source->m_mainScriptFilename;
+ m_scriptFile = source->m_scriptFile;
+ m_qmlViewerArgs = source->m_qmlViewerArgs;
+
+ updateEnabledState();
}
Runnable QmlProjectRunConfiguration::runnable() const
@@ -73,46 +102,13 @@ Runnable QmlProjectRunConfiguration::runnable() const
return r;
}
-QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *parent,
- QmlProjectRunConfiguration *source) :
- RunConfiguration(parent, source),
- m_currentFileFilename(source->m_currentFileFilename),
- m_mainScriptFilename(source->m_mainScriptFilename),
- m_scriptFile(source->m_scriptFile),
- m_qmlViewerArgs(source->m_qmlViewerArgs),
- m_isEnabled(source->m_isEnabled)
-{
- ctor();
-}
-
-bool QmlProjectRunConfiguration::isEnabled() const
-{
- return m_isEnabled;
-}
-
QString QmlProjectRunConfiguration::disabledReason() const
{
- if (!m_isEnabled)
+ if (mainScript().isEmpty())
+ return tr("No script file to execute.");
+ if (!QFileInfo(executable()).exists())
return tr("No qmlviewer or qmlscene found.");
- return QString();
-}
-
-void QmlProjectRunConfiguration::ctor()
-{
- // reset default settings in constructor
- connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
- this, &QmlProjectRunConfiguration::changeCurrentFile);
- connect(EditorManager::instance(), &EditorManager::currentDocumentStateChanged,
- this, [this] { changeCurrentFile(); });
-
- connect(target(), &Target::kitChanged,
- this, &QmlProjectRunConfiguration::updateEnabled);
-
- if (id() == Constants::QML_SCENE_RC_ID)
- setDisplayName(tr("QML Scene", "QMLRunConfiguration display name."));
- else
- setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));
- updateEnabled();
+ return RunConfiguration::disabledReason();
}
QString QmlProjectRunConfiguration::executable() const
@@ -215,7 +211,7 @@ void QmlProjectRunConfiguration::setScriptSource(MainScriptSource source,
m_mainScriptFilename
= target()->project()->projectDirectory().toString() + QLatin1Char('/') + m_scriptFile;
}
- updateEnabled();
+ updateEnabledState();
emit scriptSourceChanged();
}
@@ -258,10 +254,10 @@ void QmlProjectRunConfiguration::changeCurrentFile(IEditor *editor)
if (editor)
m_currentFileFilename = editor->document()->filePath().toString();
- updateEnabled();
+ updateEnabledState();
}
-void QmlProjectRunConfiguration::updateEnabled()
+void QmlProjectRunConfiguration::updateEnabledState()
{
bool qmlFileFound = false;
if (mainScriptSource() == FileInEditor) {
@@ -293,11 +289,10 @@ void QmlProjectRunConfiguration::updateEnabled()
qmlFileFound = !mainScript().isEmpty();
}
- bool newValue = QFileInfo::exists(executable()) && qmlFileFound;
- m_isEnabled = newValue;
-
- // Always emit change signal to force reevaluation of run/debug buttons
- emit enabledChanged();
+ if (QFileInfo::exists(executable()) && qmlFileFound)
+ RunConfiguration::updateEnabledState();
+ else
+ setEnabled(false);
}
bool QmlProjectRunConfiguration::isValidVersion(QtSupport::BaseQtVersion *version)
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
index cfab4cfd5f..0dcdf19a59 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
@@ -40,20 +40,17 @@ namespace QtSupport { class BaseQtVersion; }
namespace QmlProjectManager {
class QmlProject;
-namespace Internal {
- class QmlProjectRunConfigurationFactory;
- class QmlProjectRunConfigurationWidget;
-}
+namespace Internal { class QmlProjectRunConfigurationWidget; }
class QMLPROJECTMANAGER_EXPORT QmlProjectRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
- friend class Internal::QmlProjectRunConfigurationFactory;
+ friend class ProjectExplorer::IRunConfigurationFactory;
friend class Internal::QmlProjectRunConfigurationWidget;
friend class QmlProject; // to call updateEnabled()
public:
- QmlProjectRunConfiguration(ProjectExplorer::Target *parent, Core::Id id);
+ explicit QmlProjectRunConfiguration(ProjectExplorer::Target *target);
ProjectExplorer::Runnable runnable() const override;
@@ -70,7 +67,6 @@ public:
QString mainScript() const;
// RunConfiguration
- bool isEnabled() const override;
QString disabledReason() const override;
virtual QWidget *createConfigurationWidget() override;
Utils::OutputFormatter *createOutputFormatter() const override;
@@ -80,17 +76,13 @@ public:
signals:
void scriptSourceChanged();
-protected:
- QmlProjectRunConfiguration(ProjectExplorer::Target *parent,
- QmlProjectRunConfiguration *source);
- virtual bool fromMap(const QVariantMap &map) override;
- void setEnabled(bool value);
-
private:
- void ctor();
+ void initialize(Core::Id id);
+ void copyFrom(const QmlProjectRunConfiguration *source);
+ virtual bool fromMap(const QVariantMap &map) override;
void changeCurrentFile(Core::IEditor* = 0);
- void updateEnabled();
+ void updateEnabledState() final;
QString executable() const;
QString commandLineArguments() const;
@@ -106,8 +98,6 @@ private:
QString m_scriptFile;
QString m_qmlViewerArgs;
-
- bool m_isEnabled;
};
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp
index 7cf17cb7bb..98d3c53c54 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationfactory.cpp
@@ -104,7 +104,7 @@ bool QmlProjectRunConfigurationFactory::canCreate(ProjectExplorer::Target *paren
ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::doCreate(ProjectExplorer::Target *parent, Core::Id id)
{
- return new QmlProjectRunConfiguration(parent, id);
+ return createHelper<QmlProjectRunConfiguration>(parent, id);
}
bool QmlProjectRunConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const
@@ -115,7 +115,7 @@ bool QmlProjectRunConfigurationFactory::canRestore(ProjectExplorer::Target *pare
ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::doRestore(ProjectExplorer::Target *parent,
const QVariantMap &map)
{
- return new QmlProjectRunConfiguration(parent, ProjectExplorer::idFromMap(map));
+ return createHelper<QmlProjectRunConfiguration>(parent, ProjectExplorer::idFromMap(map));
}
bool QmlProjectRunConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source) const
@@ -128,7 +128,7 @@ ProjectExplorer::RunConfiguration *QmlProjectRunConfigurationFactory::clone(Proj
{
if (!canClone(parent, source))
return 0;
- return new QmlProjectRunConfiguration(parent, qobject_cast<QmlProjectRunConfiguration *>(source));
+ return cloneHelper<QmlProjectRunConfiguration>(parent, source);
}
bool QmlProjectRunConfigurationFactory::canHandle(ProjectExplorer::Target *parent) const
diff --git a/src/plugins/qnx/images/qnx-target.png b/src/plugins/qnx/images/qnx-target.png
deleted file mode 100644
index be59d15b82..0000000000
--- a/src/plugins/qnx/images/qnx-target.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/qnx/images/qnxdevice.png b/src/plugins/qnx/images/qnxdevice.png
new file mode 100644
index 0000000000..fedd002bf7
--- /dev/null
+++ b/src/plugins/qnx/images/qnxdevice.png
Binary files differ
diff --git a/src/plugins/qnx/images/qnxdevice@2x.png b/src/plugins/qnx/images/qnxdevice@2x.png
new file mode 100644
index 0000000000..0634693aa4
--- /dev/null
+++ b/src/plugins/qnx/images/qnxdevice@2x.png
Binary files differ
diff --git a/src/plugins/qnx/images/qnxdevicesmall.png b/src/plugins/qnx/images/qnxdevicesmall.png
new file mode 100644
index 0000000000..34a5ba9432
--- /dev/null
+++ b/src/plugins/qnx/images/qnxdevicesmall.png
Binary files differ
diff --git a/src/plugins/qnx/images/qnxdevicesmall@2x.png b/src/plugins/qnx/images/qnxdevicesmall@2x.png
new file mode 100644
index 0000000000..ab2100c1e9
--- /dev/null
+++ b/src/plugins/qnx/images/qnxdevicesmall@2x.png
Binary files differ
diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro
index bcfad2f36e..30708de764 100644
--- a/src/plugins/qnx/qnx.pro
+++ b/src/plugins/qnx/qnx.pro
@@ -23,8 +23,6 @@ SOURCES += qnxplugin.cpp \
qnxdeviceprocesslist.cpp \
qnxtoolchain.cpp \
slog2inforunner.cpp \
- qnxattachdebugsupport.cpp \
- qnxattachdebugdialog.cpp \
qnxconfiguration.cpp \
qnxsettingswidget.cpp \
qnxconfigurationmanager.cpp \
@@ -55,8 +53,6 @@ HEADERS += qnxplugin.h\
qnxdeviceprocesslist.h \
qnxtoolchain.h \
slog2inforunner.h \
- qnxattachdebugsupport.h \
- qnxattachdebugdialog.h \
qnxconfiguration.h \
qnxsettingswidget.h \
qnxconfigurationmanager.h \
diff --git a/src/plugins/qnx/qnx.qbs b/src/plugins/qnx/qnx.qbs
index b617fc1b6a..0ffc887fdf 100644
--- a/src/plugins/qnx/qnx.qbs
+++ b/src/plugins/qnx/qnx.qbs
@@ -24,10 +24,6 @@ QtcPlugin {
"qnxtoolchain.cpp",
"qnxtoolchain.h",
"qnx.qrc",
- "qnxattachdebugsupport.cpp",
- "qnxattachdebugsupport.h",
- "qnxattachdebugdialog.cpp",
- "qnxattachdebugdialog.h",
"qnxbaseqtconfigwidget.cpp",
"qnxbaseqtconfigwidget.h",
"qnxconstants.h",
diff --git a/src/plugins/qnx/qnx.qrc b/src/plugins/qnx/qnx.qrc
index 97a16398cc..7a7d425e8d 100644
--- a/src/plugins/qnx/qnx.qrc
+++ b/src/plugins/qnx/qnx.qrc
@@ -1,5 +1,8 @@
<RCC>
<qresource prefix="/qnx">
- <file>images/qnx-target.png</file>
+ <file>images/qnxdevice.png</file>
+ <file>images/qnxdevice@2x.png</file>
+ <file>images/qnxdevicesmall.png</file>
+ <file>images/qnxdevicesmall@2x.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/qnx/qnxattachdebugdialog.cpp b/src/plugins/qnx/qnxattachdebugdialog.cpp
deleted file mode 100644
index 6c780bad15..0000000000
--- a/src/plugins/qnx/qnxattachdebugdialog.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
-** Contact: info@kdab.com
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "qnxattachdebugdialog.h"
-
-#include <utils/pathchooser.h>
-#include <utils/qtcassert.h>
-
-#include <QFormLayout>
-#include <QLabel>
-#include <QVBoxLayout>
-
-using namespace Qnx;
-using namespace Qnx::Internal;
-
-QnxAttachDebugDialog::QnxAttachDebugDialog(ProjectExplorer::KitChooser *kitChooser, QWidget *parent)
- : ProjectExplorer::DeviceProcessesDialog(kitChooser, parent)
-{
- auto sourceLabel = new QLabel(tr("Project source directory:"), this);
- m_projectSource = new Utils::PathChooser(this);
- m_projectSource->setExpectedKind(Utils::PathChooser::ExistingDirectory);
-
- auto binaryLabel = new QLabel(tr("Local executable:"), this);
- m_localExecutable = new Utils::PathChooser(this);
- m_localExecutable->setExpectedKind(Utils::PathChooser::File);
-
- auto formLayout = new QFormLayout;
- formLayout->addRow(sourceLabel, m_projectSource);
- formLayout->addRow(binaryLabel, m_localExecutable);
-
- auto mainLayout = dynamic_cast<QVBoxLayout*>(layout());
- QTC_ASSERT(mainLayout, return);
- mainLayout->insertLayout(mainLayout->count() - 2, formLayout);
-}
-
-QString QnxAttachDebugDialog::projectSource() const
-{
- return m_projectSource->path();
-}
-
-QString QnxAttachDebugDialog::localExecutable() const
-{
- return m_localExecutable->path();
-}
diff --git a/src/plugins/qnx/qnxattachdebugdialog.h b/src/plugins/qnx/qnxattachdebugdialog.h
deleted file mode 100644
index ef124555ff..0000000000
--- a/src/plugins/qnx/qnxattachdebugdialog.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
-** Contact: info@kdab.com
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
-
-namespace Utils { class PathChooser; }
-
-namespace Qnx {
-namespace Internal {
-
-class QnxAttachDebugDialog : public ProjectExplorer::DeviceProcessesDialog
-{
- Q_OBJECT
-
-public:
- explicit QnxAttachDebugDialog(ProjectExplorer::KitChooser *kitChooser, QWidget *parent = 0);
-
- QString projectSource() const;
- QString localExecutable() const;
-
-private:
- Utils::PathChooser *m_projectSource;
- Utils::PathChooser *m_localExecutable;
-};
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxattachdebugsupport.cpp b/src/plugins/qnx/qnxattachdebugsupport.cpp
deleted file mode 100644
index 43714da762..0000000000
--- a/src/plugins/qnx/qnxattachdebugsupport.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
-** Contact: info@kdab.com
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "qnxattachdebugsupport.h"
-
-#include "qnxattachdebugdialog.h"
-#include "qnxconstants.h"
-#include "qnxqtversion.h"
-#include "qnxutils.h"
-
-#include <debugger/debuggerkitinformation.h>
-#include <debugger/debuggerruncontrol.h>
-#include <debugger/debuggerstartparameters.h>
-#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
-#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
-#include <projectexplorer/kit.h>
-#include <projectexplorer/kitchooser.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/runnables.h>
-#include <projectexplorer/toolchain.h>
-#include <qtsupport/qtkitinformation.h>
-#include <utils/portlist.h>
-#include <utils/qtcassert.h>
-
-using namespace ProjectExplorer;
-
-namespace Qnx {
-namespace Internal {
-
-QnxAttachDebugSupport::QnxAttachDebugSupport(QObject *parent)
- : QObject(parent)
-{
- m_launcher = new ApplicationLauncher(this);
- m_portsGatherer = new DeviceUsedPortsGatherer(this);
-
- connect(m_portsGatherer, &DeviceUsedPortsGatherer::portListReady,
- this, &QnxAttachDebugSupport::launchPDebug);
- connect(m_portsGatherer, &DeviceUsedPortsGatherer::error,
- this, &QnxAttachDebugSupport::handleError);
- connect(m_launcher, &ApplicationLauncher::remoteProcessStarted,
- this, &QnxAttachDebugSupport::attachToProcess);
- connect(m_launcher, &ApplicationLauncher::reportError,
- this, &QnxAttachDebugSupport::handleError);
- connect(m_launcher, &ApplicationLauncher::reportProgress,
- this, &QnxAttachDebugSupport::handleProgressReport);
- connect(m_launcher, &ApplicationLauncher::remoteStdout,
- this, &QnxAttachDebugSupport::handleRemoteOutput);
- connect(m_launcher, &ApplicationLauncher::remoteStderr,
- this, &QnxAttachDebugSupport::handleRemoteOutput);
-}
-
-void QnxAttachDebugSupport::showProcessesDialog()
-{
- auto kitChooser = new KitChooser;
- kitChooser->setKitPredicate([](const Kit *k){
- return k->isValid() && DeviceTypeKitInformation::deviceTypeId(k) == Core::Id(Constants::QNX_QNX_OS_TYPE);
- });
-
- QnxAttachDebugDialog dlg(kitChooser, 0);
- dlg.addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
- dlg.showAllDevices();
- if (dlg.exec() == QDialog::Rejected)
- return;
-
- m_kit = kitChooser->currentKit();
- if (!m_kit)
- return;
-
- m_device = DeviceKitInformation::device(m_kit);
- QTC_ASSERT(m_device, return);
- m_process = dlg.currentProcess();
-
- m_projectSourceDirectory = dlg.projectSource();
- m_localExecutablePath = dlg.localExecutable();
-
- m_portsGatherer->start(m_device);
-}
-
-void QnxAttachDebugSupport::launchPDebug()
-{
- Utils::PortList portList = m_device->freePorts();
- m_pdebugPort = m_portsGatherer->getNextFreePort(&portList);
- if (!m_pdebugPort.isValid()) {
- handleError(tr("No free ports for debugging."));
- return;
- }
-
- StandardRunnable r;
- r.executable = QLatin1String("pdebug");
- r.commandLineArguments = QString::number(m_pdebugPort.number());
- m_launcher->start(r, m_device);
-}
-
-void QnxAttachDebugSupport::attachToProcess()
-{
- Debugger::DebuggerStartParameters sp;
- sp.attachPID = Utils::ProcessHandle(m_process.pid);
- sp.startMode = Debugger::AttachToRemoteServer;
- sp.closeMode = Debugger::DetachAtClose;
- sp.remoteChannel = QString("%1:%2").arg(m_device->sshParameters().host).arg(m_pdebugPort.number());
- sp.displayName = tr("Remote: \"%1\" - Process %2").arg(sp.remoteChannel).arg(m_process.pid);
- sp.inferior.executable = m_localExecutablePath;
- sp.useCtrlCStub = true;
-
- QnxQtVersion *qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(m_kit));
- if (qtVersion)
- sp.solibSearchPath = QnxUtils::searchPaths(qtVersion);
-
- auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
- (void) new Debugger::DebuggerRunTool(runControl, sp);
-// connect(qobject_cast<Debugger::DebuggerRunTool *>(runControl->toolRunner()),
-// &Debugger::DebuggerRunTool::stateChanged,
-// this, &QnxAttachDebugSupport::handleDebuggerStateChanged);
- ProjectExplorerPlugin::startRunControl(runControl);
-}
-
-void QnxAttachDebugSupport::handleDebuggerStateChanged(Debugger::DebuggerState state)
-{
- if (state == Debugger::DebuggerFinished)
- stopPDebug();
-}
-
-void QnxAttachDebugSupport::handleError(const QString &message)
-{
- if (m_runTool)
- m_runTool->showMessage(message, Debugger::AppError);
-}
-
-void QnxAttachDebugSupport::handleProgressReport(const QString &message)
-{
- if (m_runTool)
- m_runTool->showMessage(message + QLatin1Char('\n'), Debugger::AppStuff);
-}
-
-void QnxAttachDebugSupport::handleRemoteOutput(const QString &output)
-{
- if (m_runTool)
- m_runTool->showMessage(output, Debugger::AppOutput);
-}
-
-void QnxAttachDebugSupport::stopPDebug()
-{
- m_launcher->stop();
-}
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxattachdebugsupport.h b/src/plugins/qnx/qnxattachdebugsupport.h
deleted file mode 100644
index 1bb00a42f4..0000000000
--- a/src/plugins/qnx/qnxattachdebugsupport.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
-** Contact: info@kdab.com
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <debugger/debuggerconstants.h>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
-#include <projectexplorer/devicesupport/idevice.h>
-#include <utils/port.h>
-
-#include <QObject>
-
-namespace Debugger { class DebuggerRunTool; }
-
-namespace ProjectExplorer {
-class ApplicationLauncher;
-class DeviceUsedPortsGatherer;
-class Kit;
-}
-
-namespace Qnx {
-namespace Internal {
-
-class QnxAttachDebugSupport : public QObject
-{
- Q_OBJECT
-public:
- explicit QnxAttachDebugSupport(QObject *parent = 0);
-
-public slots:
- void showProcessesDialog();
-
-private slots:
- void launchPDebug();
- void attachToProcess();
-
- void handleDebuggerStateChanged(Debugger::DebuggerState state);
- void handleError(const QString &message);
- void handleProgressReport(const QString &message);
- void handleRemoteOutput(const QString &output);
-
-private:
- void stopPDebug();
-
- ProjectExplorer::Kit *m_kit = 0;
- ProjectExplorer::IDevice::ConstPtr m_device;
- ProjectExplorer::DeviceProcessItem m_process;
-
- ProjectExplorer::ApplicationLauncher *m_launcher;
- ProjectExplorer::DeviceUsedPortsGatherer *m_portsGatherer;
- Debugger::DebuggerRunTool *m_runTool = 0;
-
- Utils::Port m_pdebugPort;
- QString m_projectSourceDirectory;
- QString m_localExecutablePath;
-};
-
-} // namespace Internal
-} // namespace Qnx
diff --git a/src/plugins/qnx/qnxconfiguration.cpp b/src/plugins/qnx/qnxconfiguration.cpp
index 22718c6385..282e598085 100644
--- a/src/plugins/qnx/qnxconfiguration.cpp
+++ b/src/plugins/qnx/qnxconfiguration.cpp
@@ -320,7 +320,6 @@ ProjectExplorer::Kit *QnxConfiguration::createKit(
"Kit for %1 (%2)")
.arg(displayName())
.arg(target.shortDescription()));
- kit->setIconPath(FileName::fromString(QLatin1String(Constants::QNX_CATEGORY_ICON)));
kit->setAutoDetected(true);
kit->setAutoDetectionSource(envFile().toString());
diff --git a/src/plugins/qnx/qnxconstants.h b/src/plugins/qnx/qnxconstants.h
index 13656eccf7..63d9a2d50b 100644
--- a/src/plugins/qnx/qnxconstants.h
+++ b/src/plugins/qnx/qnxconstants.h
@@ -28,7 +28,6 @@
#include <QtGlobal>
namespace Qnx {
-
namespace Constants {
const char QNX_TARGET_KEY[] = "QNX_TARGET";
@@ -49,7 +48,6 @@ const char QNX_DEBUG_EXECUTABLE[] = "pdebug";
const char QNX_TOOLCHAIN_ID[] = "Qnx.QccToolChain";
// QNX settings constants
-const char QNX_CATEGORY_ICON[] = ":/qnx/images/qnx-target.png";
const char QNX_SETTINGS_ID[] = "DD.Qnx Configuration";
const char QNX_CONFIGS_FILENAME[] = "qnxconfigurations.xml";
diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp
index 766b55b2e2..c8339239e0 100644
--- a/src/plugins/qnx/qnxdebugsupport.cpp
+++ b/src/plugins/qnx/qnxdebugsupport.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "qnxdebugsupport.h"
+
#include "qnxconstants.h"
#include "qnxdevice.h"
#include "qnxrunconfiguration.h"
@@ -31,26 +32,64 @@
#include "qnxqtversion.h"
#include "qnxutils.h"
+#include <coreplugin/icore.h>
+
+#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
#include <projectexplorer/applicationlauncher.h>
+#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
+#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
+#include <projectexplorer/kit.h>
+#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/runnables.h>
#include <projectexplorer/target.h>
+#include <projectexplorer/toolchain.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
+
#include <qtsupport/qtkitinformation.h>
+#include <utils/pathchooser.h>
+#include <utils/portlist.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
+#include <QFormLayout>
+#include <QLabel>
+#include <QVBoxLayout>
+
using namespace Debugger;
using namespace ProjectExplorer;
+using namespace Utils;
namespace Qnx {
namespace Internal {
+static QStringList searchPaths(Kit *kit)
+{
+ auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(kit));
+ if (!qtVersion)
+ return {};
+
+ const QDir pluginDir(qtVersion->qmakeProperty("QT_INSTALL_PLUGINS"));
+ const QStringList pluginSubDirs = pluginDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+
+ QStringList searchPaths;
+
+ for (const QString &dir : pluginSubDirs)
+ searchPaths << qtVersion->qmakeProperty("QT_INSTALL_PLUGINS") + '/' + dir;
+
+ searchPaths << qtVersion->qmakeProperty("QT_INSTALL_LIBS");
+ searchPaths << qtVersion->qnxTarget() + '/' + qtVersion->cpuDir() + "/lib";
+ searchPaths << qtVersion->qnxTarget() + '/' + qtVersion->cpuDir() + "/usr/lib";
+
+ return searchPaths;
+}
+
// QnxDebuggeeRunner
class QnxDebuggeeRunner : public ProjectExplorer::SimpleTargetRunner
@@ -63,12 +102,12 @@ public:
}
private:
- void start() override
+ void start() final
{
StandardRunnable r = runnable().as<StandardRunnable>();
QStringList arguments;
if (m_portsGatherer->useGdbServer()) {
- Utils::Port pdebugPort = m_portsGatherer->gdbServerPort();
+ Port pdebugPort = m_portsGatherer->gdbServerPort();
r.executable = Constants::QNX_DEBUG_EXECUTABLE;
arguments.append(pdebugPort.toString());
}
@@ -76,8 +115,8 @@ private:
arguments.append(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
m_portsGatherer->qmlServerPort()));
}
- arguments.append(Utils::QtcProcess::splitArgs(r.commandLineArguments));
- r.commandLineArguments = Utils::QtcProcess::joinArgs(arguments);
+ arguments.append(QtcProcess::splitArgs(r.commandLineArguments));
+ r.commandLineArguments = QtcProcess::joinArgs(arguments);
setRunnable(r);
@@ -94,7 +133,7 @@ QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
: DebuggerRunTool(runControl)
{
setDisplayName("QnxDebugSupport");
- appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat);
+ appendMessage(tr("Preparing remote side..."), LogMessageFormat);
m_portsGatherer = new GdbServerPortsGatherer(runControl);
m_portsGatherer->setUseGdbServer(isCppDebugging());
@@ -111,38 +150,160 @@ QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
void QnxDebugSupport::start()
{
- Utils::Port pdebugPort = m_portsGatherer->gdbServerPort();
-
auto runConfig = qobject_cast<QnxRunConfiguration *>(runControl()->runConfiguration());
QTC_ASSERT(runConfig, return);
Target *target = runConfig->target();
Kit *k = target->kit();
- DebuggerStartParameters params;
- params.startMode = AttachToRemoteServer;
- params.useCtrlCStub = true;
- params.inferior.executable = runConfig->remoteExecutableFilePath();
- params.symbolFile = runConfig->localExecutableFilePath();
- params.remoteChannel = QString("%1:%2").arg(device()->sshParameters().host).arg(pdebugPort.number());
- params.closeMode = KillAtClose;
- params.inferior.commandLineArguments = runConfig->arguments();
-
- if (isQmlDebugging()) {
- params.qmlServer.host = device()->sshParameters().host;
- params.qmlServer.port = m_portsGatherer->qmlServerPort();
- params.inferior.commandLineArguments.replace("%qml_port%", params.qmlServer.port.toString());
+ setStartMode(AttachToRemoteServer);
+ setCloseMode(KillAtClose);
+ setUseCtrlCStub(true);
+ setRemoteChannel(m_portsGatherer->gdbServerChannel());
+ setQmlServer(m_portsGatherer->qmlServer());
+ setSolibSearchPath(searchPaths(k));
+ if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(k)))
+ setSysRoot(qtVersion->qnxTarget());
+ setSymbolFile(runConfig->localExecutableFilePath());
+
+ DebuggerRunTool::start();
+}
+
+
+// QnxAttachDebugDialog
+
+class QnxAttachDebugDialog : public DeviceProcessesDialog
+{
+public:
+ QnxAttachDebugDialog(KitChooser *kitChooser)
+ : DeviceProcessesDialog(kitChooser, Core::ICore::dialogParent())
+ {
+ auto sourceLabel = new QLabel(QnxDebugSupport::tr("Project source directory:"), this);
+ m_projectSource = new PathChooser(this);
+ m_projectSource->setExpectedKind(PathChooser::ExistingDirectory);
+
+ auto binaryLabel = new QLabel(QnxDebugSupport::tr("Local executable:"), this);
+ m_localExecutable = new PathChooser(this);
+ m_localExecutable->setExpectedKind(PathChooser::File);
+
+ auto formLayout = new QFormLayout;
+ formLayout->addRow(sourceLabel, m_projectSource);
+ formLayout->addRow(binaryLabel, m_localExecutable);
+
+ auto mainLayout = dynamic_cast<QVBoxLayout*>(layout());
+ QTC_ASSERT(mainLayout, return);
+ mainLayout->insertLayout(mainLayout->count() - 2, formLayout);
+ }
+
+ QString projectSource() const { return m_projectSource->path(); }
+ QString localExecutable() const { return m_localExecutable->path(); }
+
+private:
+ PathChooser *m_projectSource;
+ PathChooser *m_localExecutable;
+};
+
+
+// QnxAttachDebugSupport
+
+class PDebugRunner : public ProjectExplorer::SimpleTargetRunner
+{
+public:
+ PDebugRunner(RunControl *runControl, GdbServerPortsGatherer *portsGatherer)
+ : SimpleTargetRunner(runControl), m_portsGatherer(portsGatherer)
+ {
+ setDisplayName("PDebugRunner");
}
- auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(k));
- if (qtVersion) {
- params.solibSearchPath = QnxUtils::searchPaths(qtVersion);
- params.sysRoot = qtVersion->qnxTarget();
+private:
+ void start() final
+ {
+ Port pdebugPort = m_portsGatherer->gdbServerPort();
+
+ StandardRunnable r;
+ r.executable = Constants::QNX_DEBUG_EXECUTABLE;
+ r.commandLineArguments = pdebugPort.toString();
+ setRunnable(r);
+
+ SimpleTargetRunner::start();
}
- setStartParameters(params);
+ GdbServerPortsGatherer *m_portsGatherer;
+};
+
+QnxAttachDebugSupport::QnxAttachDebugSupport(RunControl *runControl)
+ : DebuggerRunTool(runControl)
+{
+ setDisplayName("QnxAttachDebugSupport");
+
+ m_portsGatherer = new GdbServerPortsGatherer(runControl);
+ m_portsGatherer->setUseGdbServer(isCppDebugging());
+ m_portsGatherer->setUseQmlServer(isQmlDebugging());
+
+ if (isCppDebugging()) {
+ m_pdebugRunner = new PDebugRunner(runControl, m_portsGatherer);
+ m_pdebugRunner->addStartDependency(m_portsGatherer);
+ addStartDependency(m_pdebugRunner);
+ } else {
+ // No pdebug needed for Qml-only debugging.
+ addStartDependency(m_portsGatherer);
+ }
+}
+
+void QnxAttachDebugSupport::start()
+{
+ setRemoteChannel(m_portsGatherer->gdbServerChannel());
+ setQmlServer(m_portsGatherer->qmlServer());
DebuggerRunTool::start();
}
+void QnxAttachDebugSupport::showProcessesDialog()
+{
+ auto kitChooser = new KitChooser;
+ kitChooser->setKitPredicate([](const Kit *k) {
+ return k->isValid() && DeviceTypeKitInformation::deviceTypeId(k) == Constants::QNX_QNX_OS_TYPE;
+ });
+
+ QnxAttachDebugDialog dlg(kitChooser);
+ dlg.addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
+ dlg.showAllDevices();
+ if (dlg.exec() == QDialog::Rejected)
+ return;
+
+ Kit *kit = kitChooser->currentKit();
+ if (!kit)
+ return;
+
+ // FIXME: That should be somehow related to the selected kit.
+ auto startRunConfig = RunConfiguration::startupRunConfiguration();
+ auto runConfig = qobject_cast<QnxRunConfiguration *>(startRunConfig);
+ if (!runConfig)
+ return;
+
+ DeviceProcessItem process = dlg.currentProcess();
+ const int pid = process.pid;
+// QString projectSourceDirectory = dlg.projectSource();
+ QString localExecutable = dlg.localExecutable();
+ if (localExecutable.isEmpty())
+ localExecutable = runConfig->localExecutableFilePath();
+
+ auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+ auto debugger = new QnxAttachDebugSupport(runControl);
+ debugger->setStartMode(AttachToRemoteServer);
+ debugger->setCloseMode(DetachAtClose);
+ debugger->setNeedFixup(false);
+ debugger->setSymbolFile(localExecutable);
+ debugger->setUseCtrlCStub(true);
+ debugger->setAttachPid(pid);
+// setRunControlName(tr("Remote: \"%1\" - Process %2").arg(remoteChannel).arg(m_process.pid));
+ debugger->setRunControlName(tr("Remote QNX process %1").arg(pid));
+ debugger->setSolibSearchPath(searchPaths(kit));
+ if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(kit)))
+ debugger->setSysRoot(qtVersion->qnxTarget());
+ debugger->setUseContinueInsteadOfRun(true);
+
+ ProjectExplorerPlugin::startRunControl(runControl);
+}
+
} // namespace Internal
} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdebugsupport.h b/src/plugins/qnx/qnxdebugsupport.h
index 4bc75283c4..bfce06231f 100644
--- a/src/plugins/qnx/qnxdebugsupport.h
+++ b/src/plugins/qnx/qnxdebugsupport.h
@@ -43,5 +43,21 @@ private:
Debugger::GdbServerPortsGatherer *m_portsGatherer;
};
+class QnxAttachDebugSupport : public Debugger::DebuggerRunTool
+{
+ Q_OBJECT
+
+public:
+ explicit QnxAttachDebugSupport(ProjectExplorer::RunControl *runControl);
+
+ static void showProcessesDialog();
+
+private:
+ void start() final;
+
+ Debugger::GdbServerPortsGatherer *m_portsGatherer;
+ ProjectExplorer::SimpleTargetRunner *m_pdebugRunner;
+};
+
} // namespace Internal
} // namespace Qnx
diff --git a/src/plugins/qnx/qnxdevice.cpp b/src/plugins/qnx/qnxdevice.cpp
index 31a8d9064d..01d6fec0f4 100644
--- a/src/plugins/qnx/qnxdevice.cpp
+++ b/src/plugins/qnx/qnxdevice.cpp
@@ -35,6 +35,7 @@
#include <ssh/sshconnection.h>
#include <utils/port.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
#include <QApplication>
#include <QRegExp>
@@ -59,37 +60,19 @@ class QnxPortsGatheringMethod : public PortsGatheringMethod
{
Q_UNUSED(protocol);
StandardRunnable runnable;
- // FIXME: Is this extra shell needed?
- runnable.executable = "/bin/sh";
- runnable.commandLineArguments = "-c \""
- "netstat -na "
- "| sed 's/[a-z]\\+\\s\\+[0-9]\\+\\s\\+[0-9]\\+\\s\\+\\(\\*\\|[0-9\\.]\\+\\)\\.\\([0-9]\\+\\).*/\\2/g' "
- "| while read line; do "
- "if [[ $line != udp* ]] && [[ $line != Active* ]]; then "
- "printf '%x\n' $line; "
- "fi; "
- "done"
- "\"";
+ runnable.executable = "netstat";
+ runnable.commandLineArguments = "-na";
return runnable;
}
QList<Port> usedPorts(const QByteArray &output) const override
{
- QList<Port> ports;
- QList<QByteArray> portStrings = output.split('\n');
- portStrings.removeFirst();
- foreach (const QByteArray &portString, portStrings) {
- if (portString.isEmpty())
- continue;
- bool ok;
- const Port port(portString.toInt(&ok, 16));
- if (ok) {
- if (!ports.contains(port))
- ports << port;
- } else {
- qWarning("%s: Unexpected string '%s' is not a port.",
- Q_FUNC_INFO, portString.data());
- }
+ QList<Utils::Port> ports;
+ const QList<QByteArray> lines = output.split('\n');
+ for (const QByteArray &line : lines) {
+ const Port port(Utils::parseUsedPortFromNetstatOutput(line));
+ if (port.isValid() && !ports.contains(port))
+ ports.append(port);
}
return ports;
}
diff --git a/src/plugins/qnx/qnxdevicefactory.cpp b/src/plugins/qnx/qnxdevicefactory.cpp
index f489c10d74..1546171afd 100644
--- a/src/plugins/qnx/qnxdevicefactory.cpp
+++ b/src/plugins/qnx/qnxdevicefactory.cpp
@@ -30,6 +30,7 @@
#include "qnxdevice.h"
#include <utils/qtcassert.h>
+#include <utils/icon.h>
#include <QIcon>
@@ -55,7 +56,13 @@ QList<Core::Id> QnxDeviceFactory::availableCreationIds() const
QIcon QnxDeviceFactory::iconForId(Core::Id type) const
{
Q_UNUSED(type)
- return QIcon();
+ using namespace Utils;
+ static const QIcon icon =
+ Icon::combinedIcon({Icon({{":/qnx/images/qnxdevicesmall.png",
+ Theme::PanelTextColorDark}}, Icon::Tint),
+ Icon({{":/qnx/images/qnxdevice.png",
+ Theme::IconsBaseColor}})});
+ return icon;
}
bool QnxDeviceFactory::canCreate() const
diff --git a/src/plugins/qnx/qnxplugin.cpp b/src/plugins/qnx/qnxplugin.cpp
index a1f1cffc9c..07306e81e3 100644
--- a/src/plugins/qnx/qnxplugin.cpp
+++ b/src/plugins/qnx/qnxplugin.cpp
@@ -26,7 +26,6 @@
#include "qnxplugin.h"
#include "qnxanalyzesupport.h"
-#include "qnxattachdebugsupport.h"
#include "qnxconfigurationmanager.h"
#include "qnxconstants.h"
#include "qnxdebugsupport.h"
@@ -108,12 +107,10 @@ bool QnxPlugin::initialize(const QStringList &arguments, QString *errorString)
void QnxPlugin::extensionsInitialized()
{
- // Debug support
- QnxAttachDebugSupport *debugSupport = new QnxAttachDebugSupport(this);
-
+ // Attach support
m_attachToQnxApplication = new QAction(this);
m_attachToQnxApplication->setText(tr("Attach to remote QNX application..."));
- connect(m_attachToQnxApplication, &QAction::triggered, debugSupport, &QnxAttachDebugSupport::showProcessesDialog);
+ connect(m_attachToQnxApplication, &QAction::triggered, this, [] { QnxAttachDebugSupport::showProcessesDialog(); });
Core::ActionContainer *mstart = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING);
mstart->appendGroup(Constants::QNX_DEBUGGING_GROUP);
@@ -142,8 +139,8 @@ void QnxPlugin::updateDebuggerActions()
}
}
- m_attachToQnxApplication->setVisible(false && hasValidQnxKit); // FIXME
- m_debugSeparator->setVisible(false && hasValidQnxKit); // FIXME QTCREATORBUG-16608
+ m_attachToQnxApplication->setVisible(hasValidQnxKit);
+ m_debugSeparator->setVisible(hasValidQnxKit);
}
} // Internal
diff --git a/src/plugins/qnx/qnxrunconfiguration.cpp b/src/plugins/qnx/qnxrunconfiguration.cpp
index 2ccedf4df8..c7b4b80559 100644
--- a/src/plugins/qnx/qnxrunconfiguration.cpp
+++ b/src/plugins/qnx/qnxrunconfiguration.cpp
@@ -41,14 +41,19 @@ namespace Internal {
const char QtLibPathKey[] = "Qt4ProjectManager.QnxRunConfiguration.QtLibPath";
-QnxRunConfiguration::QnxRunConfiguration(Target *parent, Core::Id id, const QString &targetName)
- : RemoteLinuxRunConfiguration(parent, id, targetName)
+QnxRunConfiguration::QnxRunConfiguration(Target *target)
+ : RemoteLinuxRunConfiguration(target)
+{}
+
+void QnxRunConfiguration::initialize(Core::Id id, const QString &targetName)
{
+ RemoteLinuxRunConfiguration::initialize(id, targetName);
}
-QnxRunConfiguration::QnxRunConfiguration(Target *parent, QnxRunConfiguration *source)
- : RemoteLinuxRunConfiguration(parent, source), m_qtLibPath(source->m_qtLibPath)
+void QnxRunConfiguration::copyFrom(const QnxRunConfiguration *source)
{
+ RemoteLinuxRunConfiguration::copyFrom(source);
+ m_qtLibPath = source->m_qtLibPath;
}
Runnable QnxRunConfiguration::runnable() const
diff --git a/src/plugins/qnx/qnxrunconfiguration.h b/src/plugins/qnx/qnxrunconfiguration.h
index f897aefa2a..7ce0ec9114 100644
--- a/src/plugins/qnx/qnxrunconfiguration.h
+++ b/src/plugins/qnx/qnxrunconfiguration.h
@@ -35,8 +35,7 @@ class QnxRunConfiguration : public RemoteLinux::RemoteLinuxRunConfiguration
Q_OBJECT
public:
- QnxRunConfiguration(ProjectExplorer::Target *parent, Core::Id id,
- const QString &targetName);
+ explicit QnxRunConfiguration(ProjectExplorer::Target *target);
ProjectExplorer::Runnable runnable() const override;
@@ -44,9 +43,11 @@ public:
QVariantMap toMap() const override;
private:
- friend class QnxRunConfigurationFactory;
+ friend class ProjectExplorer::IRunConfigurationFactory;
+
+ void copyFrom(const QnxRunConfiguration *source);
+ void initialize(Core::Id id, const QString &targetName);
- QnxRunConfiguration(ProjectExplorer::Target *parent, QnxRunConfiguration *source);
bool fromMap(const QVariantMap &map) override;
QString m_qtLibPath;
diff --git a/src/plugins/qnx/qnxrunconfigurationfactory.cpp b/src/plugins/qnx/qnxrunconfigurationfactory.cpp
index 6cfab76b2d..af474f3a29 100644
--- a/src/plugins/qnx/qnxrunconfigurationfactory.cpp
+++ b/src/plugins/qnx/qnxrunconfigurationfactory.cpp
@@ -91,7 +91,7 @@ ProjectExplorer::RunConfiguration *QnxRunConfigurationFactory::doCreate(ProjectE
QTC_ASSERT(project, return nullptr);
for (const QmakeProjectManager::QmakeProFile *file : project->applicationProFiles()) {
if (file->filePath() == projectFilePath)
- return new QnxRunConfiguration(parent, id, file->targetInformation().target);
+ return createHelper<QnxRunConfiguration>(parent, id, file->targetInformation().target);
}
QTC_CHECK(false);
return nullptr;
@@ -107,7 +107,7 @@ ProjectExplorer::RunConfiguration *QnxRunConfigurationFactory::doRestore(Project
const QVariantMap &map)
{
Q_UNUSED(map);
- return new QnxRunConfiguration(parent, Core::Id(Constants::QNX_QNX_RUNCONFIGURATION_PREFIX), QString());
+ return createHelper<QnxRunConfiguration>(parent, Constants::QNX_QNX_RUNCONFIGURATION_PREFIX, QString());
}
bool QnxRunConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source) const
@@ -120,8 +120,7 @@ ProjectExplorer::RunConfiguration *QnxRunConfigurationFactory::clone(ProjectExpl
if (!canClone(parent, source))
return 0;
- QnxRunConfiguration *old = static_cast<QnxRunConfiguration *>(source);
- return new QnxRunConfiguration(parent, old);
+ return cloneHelper<QnxRunConfiguration>(parent, source);
}
bool QnxRunConfigurationFactory::canHandle(ProjectExplorer::Target *t) const
diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp
index 2206e67a92..37351cd92d 100644
--- a/src/plugins/qnx/qnxutils.cpp
+++ b/src/plugins/qnx/qnxutils.cpp
@@ -73,27 +73,6 @@ QString QnxUtils::cpuDirShortDescription(const QString &cpuDir)
return cpuDir;
}
-QStringList QnxUtils::searchPaths(QnxQtVersion *qtVersion)
-{
- const QDir pluginDir(qtVersion->qmakeProperty("QT_INSTALL_PLUGINS"));
- const QStringList pluginSubDirs = pluginDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
-
- QStringList searchPaths;
-
- Q_FOREACH (const QString &dir, pluginSubDirs) {
- searchPaths << qtVersion->qmakeProperty("QT_INSTALL_PLUGINS")
- + QLatin1Char('/') + dir;
- }
-
- searchPaths << qtVersion->qmakeProperty("QT_INSTALL_LIBS");
- searchPaths << qtVersion->qnxTarget() + QLatin1Char('/') + qtVersion->cpuDir()
- + QLatin1String("/lib");
- searchPaths << qtVersion->qnxTarget() + QLatin1Char('/') + qtVersion->cpuDir()
- + QLatin1String("/usr/lib");
-
- return searchPaths;
-}
-
QList<Utils::EnvironmentItem> QnxUtils::qnxEnvironmentFromEnvFile(const QString &fileName)
{
QList <Utils::EnvironmentItem> items;
diff --git a/src/plugins/qnx/qnxutils.h b/src/plugins/qnx/qnxutils.h
index af0ed5823f..505a1a5bff 100644
--- a/src/plugins/qnx/qnxutils.h
+++ b/src/plugins/qnx/qnxutils.h
@@ -70,7 +70,6 @@ class QnxUtils
public:
static QString addQuotes(const QString &string);
static QString cpuDirShortDescription(const QString &cpuDir);
- static QStringList searchPaths(Qnx::Internal::QnxQtVersion *qtVersion);
static QList<Utils::EnvironmentItem> qnxEnvironmentFromEnvFile(const QString &fileName);
static QString envFilePath(const QString &sdpPath);
static QString defaultTargetVersion(const QString &sdpPath);
diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
index c5ca314c05..a5f4019475 100644
--- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
+++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
@@ -124,7 +124,7 @@ QString ExamplesWelcomePage::copyToAlternativeLocation(const QFileInfo& proFileI
chooser->setHistoryCompleter(QLatin1String("Qt.WritableExamplesDir.History"));
QSettings *settings = ICore::settings();
chooser->setPath(settings->value(QString::fromLatin1(C_FALLBACK_ROOT),
- DocumentManager::projectsDirectory()).toString());
+ DocumentManager::projectsDirectory().toString()).toString());
lay->addWidget(txt, 1, 0);
lay->addWidget(chooser, 1, 1);
enum { Copy = QDialog::Accepted + 1, Keep = QDialog::Accepted + 2 };
diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp
index 93997c901e..972df564a8 100644
--- a/src/plugins/qtsupport/qtkitinformation.cpp
+++ b/src/plugins/qtsupport/qtkitinformation.cpp
@@ -126,18 +126,18 @@ ProjectExplorer::IOutputParser *QtKitInformation::createOutputParser(const Proje
void QtKitInformation::addToMacroExpander(Kit *kit, MacroExpander *expander) const
{
expander->registerSubProvider(
- [this, kit]() -> MacroExpander * {
+ [kit]() -> MacroExpander * {
BaseQtVersion *version = qtVersion(kit);
return version ? version->macroExpander() : 0;
});
expander->registerVariable("Qt:Name", tr("Name of Qt Version"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
BaseQtVersion *version = qtVersion(kit);
return version ? version->displayName() : tr("unknown");
});
expander->registerVariable("Qt:qmakeExecutable", tr("Path to the qmake executable"),
- [this, kit]() -> QString {
+ [kit]() -> QString {
BaseQtVersion *version = qtVersion(kit);
return version ? version->qmakeCommand().toString() : QString();
});
diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp
index 23e10b9a17..bdd358c199 100644
--- a/src/plugins/qtsupport/qtoptionspage.cpp
+++ b/src/plugins/qtsupport/qtoptionspage.cpp
@@ -337,7 +337,7 @@ void QtOptionsPageWidget::toolChainsUpdated()
void QtOptionsPageWidget::qtVersionsDumpUpdated(const FileName &qmakeCommand)
{
- m_model->forItemsAtLevel<2>([this, qmakeCommand](QtVersionItem *item) {
+ m_model->forItemsAtLevel<2>([qmakeCommand](QtVersionItem *item) {
if (item->version()->qmakeCommand() == qmakeCommand)
item->version()->recheckDumper();
});
@@ -769,7 +769,7 @@ void QtOptionsPageWidget::apply()
QList<BaseQtVersion *> versions;
- m_model->forItemsAtLevel<2>([this, &versions](QtVersionItem *item) {
+ m_model->forItemsAtLevel<2>([&versions](QtVersionItem *item) {
item->setChanged(false);
versions.append(item->version()->clone());
});
diff --git a/src/plugins/remotelinux/abstractremotelinuxrunsupport.cpp b/src/plugins/remotelinux/abstractremotelinuxrunsupport.cpp
deleted file mode 100644
index 48aac08813..0000000000
--- a/src/plugins/remotelinux/abstractremotelinuxrunsupport.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "abstractremotelinuxrunsupport.h"
-
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/runnables.h>
-#include <projectexplorer/target.h>
-
-#include <utils/environment.h>
-#include <utils/portlist.h>
-#include <utils/qtcprocess.h>
-
-#include <qmldebug/qmldebugcommandlinearguments.h>
-
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace RemoteLinux {
-
-// FifoGatherer
-
-FifoGatherer::FifoGatherer(RunControl *runControl)
- : RunWorker(runControl)
-{
- setDisplayName("FifoGatherer");
-}
-
-FifoGatherer::~FifoGatherer()
-{
-}
-
-void FifoGatherer::start()
-{
- appendMessage(tr("Creating remote socket...") + '\n', NormalMessageFormat);
-
- StandardRunnable r;
- r.executable = QLatin1String("/bin/sh");
- r.commandLineArguments = "-c 'd=`mktemp -d` && mkfifo $d/fifo && echo -n $d/fifo'";
- r.workingDirectory = QLatin1String("/tmp");
- r.runMode = ApplicationLauncher::Console;
-
- QSharedPointer<QString> output(new QString);
- QSharedPointer<QString> errors(new QString);
-
- connect(&m_fifoCreator, &ApplicationLauncher::finished,
- this, [this, output, errors](bool success) {
- if (!success) {
- reportFailure(QString("Failed to create fifo: %1").arg(*errors));
- } else {
- m_fifo = *output;
- appendMessage(tr("Created fifo: %1").arg(m_fifo), NormalMessageFormat);
- reportStarted();
- }
- });
-
- connect(&m_fifoCreator, &ApplicationLauncher::remoteStdout,
- this, [output](const QString &data) {
- output->append(data);
- });
-
- connect(&m_fifoCreator, &ApplicationLauncher::remoteStderr,
- this, [this, errors](const QString &) {
- reportFailure();
-// errors->append(data);
- });
-
- m_fifoCreator.start(r, device());
-}
-
-void FifoGatherer::stop()
-{
- m_fifoCreator.stop();
- reportStopped();
-}
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/abstractremotelinuxrunsupport.h b/src/plugins/remotelinux/abstractremotelinuxrunsupport.h
deleted file mode 100644
index 4f6589ab1f..0000000000
--- a/src/plugins/remotelinux/abstractremotelinuxrunsupport.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "remotelinux_export.h"
-
-#include <projectexplorer/runconfiguration.h>
-
-namespace RemoteLinux {
-
-class REMOTELINUX_EXPORT FifoGatherer : public ProjectExplorer::RunWorker
-{
- Q_OBJECT
-
-public:
- explicit FifoGatherer(ProjectExplorer::RunControl *runControl);
- ~FifoGatherer();
-
- QString fifo() const { return m_fifo; }
-
-private:
- void start() override;
- void stop() override;
-
- void createRemoteFifo();
-
- ProjectExplorer::ApplicationLauncher m_fifoCreator;
- QString m_fifo;
-};
-
-} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro
index 5167f61ace..b667c040ab 100644
--- a/src/plugins/remotelinux/remotelinux.pro
+++ b/src/plugins/remotelinux/remotelinux.pro
@@ -43,7 +43,6 @@ HEADERS += \
remotelinuxcheckforfreediskspaceservice.h \
remotelinuxcheckforfreediskspacestep.h \
remotelinuxanalyzesupport.h \
- abstractremotelinuxrunsupport.h \
linuxdeviceprocess.h \
remotelinuxcustomrunconfiguration.h \
remotelinuxsignaloperation.h \
@@ -88,7 +87,6 @@ SOURCES += \
remotelinuxcheckforfreediskspaceservice.cpp \
remotelinuxcheckforfreediskspacestep.cpp \
remotelinuxanalyzesupport.cpp \
- abstractremotelinuxrunsupport.cpp \
linuxdeviceprocess.cpp \
remotelinuxcustomrunconfiguration.cpp \
remotelinuxsignaloperation.cpp \
diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs
index 3855efc24b..5ad7f7abe4 100644
--- a/src/plugins/remotelinux/remotelinux.qbs
+++ b/src/plugins/remotelinux/remotelinux.qbs
@@ -23,8 +23,6 @@ Project {
"abstractremotelinuxdeployservice.h",
"abstractremotelinuxdeploystep.cpp",
"abstractremotelinuxdeploystep.h",
- "abstractremotelinuxrunsupport.cpp",
- "abstractremotelinuxrunsupport.h",
"abstractuploadandinstallpackageservice.cpp",
"abstractuploadandinstallpackageservice.h",
"deploymenttimeinfo.cpp",
diff --git a/src/plugins/remotelinux/remotelinuxanalyzesupport.cpp b/src/plugins/remotelinux/remotelinuxanalyzesupport.cpp
index de1a9efde1..aaf384cf67 100644
--- a/src/plugins/remotelinux/remotelinuxanalyzesupport.cpp
+++ b/src/plugins/remotelinux/remotelinuxanalyzesupport.cpp
@@ -25,30 +25,17 @@
#include "remotelinuxanalyzesupport.h"
-#include "remotelinuxrunconfiguration.h"
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/toolchain.h>
-#include <projectexplorer/kitinformation.h>
#include <projectexplorer/runnables.h>
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-
#include <ssh/sshconnection.h>
-#include <qmldebug/qmloutputparser.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
-#include <QPointer>
-
-using namespace QSsh;
using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux {
+namespace Internal {
// RemoteLinuxQmlProfilerSupport
@@ -89,62 +76,5 @@ void RemoteLinuxQmlProfilerSupport::start()
SimpleTargetRunner::start();
}
-
-// RemoteLinuxPerfSupport
-
-RemoteLinuxPerfSupport::RemoteLinuxPerfSupport(RunControl *runControl)
- : RunWorker(runControl)
-{
- setDisplayName("RemoteLinuxPerfSupport");
-
- RunConfiguration *runConfiguration = runControl->runConfiguration();
- QTC_ASSERT(runConfiguration, return);
- IRunConfigurationAspect *perfAspect =
- runConfiguration->extraAspect("Analyzer.Perf.Settings");
- QTC_ASSERT(perfAspect, return);
- m_perfRecordArguments =
- perfAspect->currentSettings()->property("perfRecordArguments").toStringList()
- .join(' ');
-
- auto toolRunner = runControl->createWorker(runControl->runMode());
- toolRunner->addStartDependency(this);
-// connect(&m_outputGatherer, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
-// this, &RemoteLinuxPerfSupport::remoteIsRunning);
-
-// addDependency(FifoCreatorWorkerId);
-}
-
-void RemoteLinuxPerfSupport::start()
-{
-// m_remoteFifo = targetRunner()->fifo();
- if (m_remoteFifo.isEmpty()) {
- reportFailure(tr("FIFO for profiling data could not be created."));
- return;
- }
-
-// ApplicationLauncher *runner = targetRunner()->applicationLauncher();
-
- auto r = runnable().as<StandardRunnable>();
-
- r.commandLineArguments = "-c 'perf record -o - " + m_perfRecordArguments
- + " -- " + r.executable + " "
- + r.commandLineArguments + " > " + m_remoteFifo
- + "'";
- r.executable = "sh";
-
- connect(&m_outputGatherer, SIGNAL(remoteStdout(QByteArray)),
- runControl(), SIGNAL(analyzePerfOutput(QByteArray)));
- connect(&m_outputGatherer, SIGNAL(finished(bool)),
- runControl(), SIGNAL(perfFinished()));
-
- StandardRunnable outputRunner;
- outputRunner.executable = "sh";
- outputRunner.commandLineArguments = QString("-c 'cat %1 && rm -r `dirname %1`'").arg(m_remoteFifo);
- m_outputGatherer.start(outputRunner, device());
-// remoteIsRunning();
-// runControl()->notifyRemoteSetupDone(d->qmlPort);
-
-// runner->start(r, device());
-}
-
+} // namespace Internal
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxanalyzesupport.h b/src/plugins/remotelinux/remotelinuxanalyzesupport.h
index 6684753333..6b444fc97c 100644
--- a/src/plugins/remotelinux/remotelinuxanalyzesupport.h
+++ b/src/plugins/remotelinux/remotelinuxanalyzesupport.h
@@ -25,48 +25,23 @@
#pragma once
-#include "abstractremotelinuxrunsupport.h"
-
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/runconfiguration.h>
-#include <utils/outputformat.h>
-
-#include <qmldebug/qmloutputparser.h>
-
namespace RemoteLinux {
+namespace Internal {
-class REMOTELINUX_EXPORT RemoteLinuxQmlProfilerSupport
- : public ProjectExplorer::SimpleTargetRunner
+class RemoteLinuxQmlProfilerSupport : public ProjectExplorer::SimpleTargetRunner
{
- Q_OBJECT
-
public:
RemoteLinuxQmlProfilerSupport(ProjectExplorer::RunControl *runControl);
private:
void start() override;
- QmlDebug::QmlOutputParser m_outputParser;
ProjectExplorer::PortsGatherer *m_portsGatherer;
ProjectExplorer::RunWorker *m_profiler;
};
-
-class REMOTELINUX_EXPORT RemoteLinuxPerfSupport : public ProjectExplorer::RunWorker
-{
- Q_OBJECT
-
-public:
- RemoteLinuxPerfSupport(ProjectExplorer::RunControl *runControl);
-
-private:
- void start() override;
-
- QString m_remoteFifo;
- QString m_perfRecordArguments;
-
- ProjectExplorer::ApplicationLauncher m_outputGatherer;
-};
-
+} // namespace Internal
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
index 1f0b9fc210..7ae8d9b9fa 100644
--- a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp
@@ -96,21 +96,29 @@ private:
Ui::RemoteLinuxCustomRunConfigurationWidget m_ui;
};
-RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(ProjectExplorer::Target *parent)
- : RunConfiguration(parent, runConfigId())
+RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(Target *target)
+ : RunConfiguration(target)
{
- init();
+ addExtraAspect(new RemoteLinuxEnvironmentAspect(this));
}
-RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(ProjectExplorer::Target *parent,
- RemoteLinuxCustomRunConfiguration *source)
- : RunConfiguration(parent, source)
- , m_localExecutable(source->m_localExecutable)
- , m_remoteExecutable(source->m_remoteExecutable)
- , m_arguments(source->m_arguments)
- , m_workingDirectory(source->m_workingDirectory)
+void RemoteLinuxCustomRunConfiguration::initialize()
{
- init();
+ RunConfiguration::initialize(runConfigId());
+
+ setDefaultDisplayName(runConfigDefaultDisplayName());
+}
+
+void RemoteLinuxCustomRunConfiguration::copyFrom(const RemoteLinuxCustomRunConfiguration *source)
+{
+ RunConfiguration::copyFrom(source);
+
+ m_localExecutable = source->m_localExecutable;
+ m_remoteExecutable = source->m_remoteExecutable;
+ m_arguments = source->m_arguments;
+ m_workingDirectory = source->m_workingDirectory;
+
+ setDefaultDisplayName(runConfigDefaultDisplayName());
}
bool RemoteLinuxCustomRunConfiguration::isConfigured() const
@@ -167,12 +175,6 @@ QString RemoteLinuxCustomRunConfiguration::runConfigDefaultDisplayName()
return tr("Custom Executable (on Remote Generic Linux Host)");
}
-void RemoteLinuxCustomRunConfiguration::init()
-{
- setDefaultDisplayName(runConfigDefaultDisplayName());
- addExtraAspect(new RemoteLinuxEnvironmentAspect(this));
-}
-
static QString localExeKey()
{
return QLatin1String("RemoteLinux.CustomRunConfig.LocalExecutable");
diff --git a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.h b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.h
index be97dad96c..06d29cf48c 100644
--- a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.h
+++ b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.h
@@ -34,14 +34,14 @@ class RemoteLinuxCustomRunConfiguration : public ProjectExplorer::RunConfigurati
{
Q_OBJECT
public:
- RemoteLinuxCustomRunConfiguration(ProjectExplorer::Target *parent);
- RemoteLinuxCustomRunConfiguration(ProjectExplorer::Target *parent,
- RemoteLinuxCustomRunConfiguration *source);
+ explicit RemoteLinuxCustomRunConfiguration(ProjectExplorer::Target *target);
+
+ void initialize();
+ void copyFrom(const RemoteLinuxCustomRunConfiguration *source);
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
- bool isEnabled() const override { return true; }
bool isConfigured() const override;
ConfigurationState ensureConfigured(QString *errorMessage) override;
QWidget *createConfigurationWidget() override;
@@ -58,8 +58,6 @@ public:
static QString runConfigDefaultDisplayName();
private:
- void init();
-
QString m_localExecutable;
QString m_remoteExecutable;
QString m_arguments;
diff --git a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
index 4ce28bbc16..1687eb1808 100644
--- a/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
+++ b/src/plugins/remotelinux/remotelinuxdebugsupport.cpp
@@ -28,24 +28,11 @@
#include "remotelinuxcustomrunconfiguration.h"
#include "remotelinuxrunconfiguration.h"
-#include <debugger/debuggerruncontrol.h>
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/runnables.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/toolchain.h>
-
-#include <qmldebug/qmldebugcommandlinearguments.h>
-
-#include <utils/qtcassert.h>
-#include <utils/qtcprocess.h>
-
using namespace Debugger;
using namespace ProjectExplorer;
-using namespace Utils;
namespace RemoteLinux {
+namespace Internal {
LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl)
: DebuggerRunTool(runControl)
@@ -61,54 +48,25 @@ LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl)
addStartDependency(gdbServer);
+ setStartMode(AttachToRemoteServer);
+ setCloseMode(KillAndExitMonitorAtClose);
+ setUseExtendedRemote(true);
+
RunConfiguration *runConfig = runControl->runConfiguration();
if (auto rlrc = qobject_cast<RemoteLinuxRunConfiguration *>(runConfig))
- m_symbolFile = rlrc->localExecutableFilePath();
+ setSymbolFile(rlrc->localExecutableFilePath());
else if (auto rlrc = qobject_cast<Internal::RemoteLinuxCustomRunConfiguration *>(runConfig))
- m_symbolFile = rlrc->localExecutableFilePath();
+ setSymbolFile(rlrc->localExecutableFilePath());
}
void LinuxDeviceDebugSupport::start()
{
- if (m_symbolFile.isEmpty()) {
- reportFailure(tr("Cannot debug: Local executable is not set."));
- return;
- }
-
- const QString host = device()->sshParameters().host;
- const Port gdbServerPort = m_portsGatherer->gdbServerPort();
- const Port qmlServerPort = m_portsGatherer->qmlServerPort();
-
- DebuggerStartParameters params;
- params.startMode = AttachToRemoteServer;
- params.closeMode = KillAndExitMonitorAtClose;
-
- if (isQmlDebugging()) {
- params.qmlServer.host = host;
- params.qmlServer.port = qmlServerPort;
- params.inferior.commandLineArguments.replace("%qml_port%",
- QString::number(qmlServerPort.number()));
- }
- if (isCppDebugging()) {
- Runnable r = runnable();
- QTC_ASSERT(r.is<StandardRunnable>(), return);
- auto stdRunnable = r.as<StandardRunnable>();
- params.useExtendedRemote = true;
- params.inferior.executable = stdRunnable.executable;
- params.inferior.commandLineArguments = stdRunnable.commandLineArguments;
- if (isQmlDebugging()) {
- params.inferior.commandLineArguments.prepend(' ');
- params.inferior.commandLineArguments.prepend(
- QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices));
- }
-
- params.remoteChannel = QString("%1:%2").arg(host).arg(gdbServerPort.number());
- params.symbolFile = m_symbolFile;
- }
-
- setStartParameters(params);
+ setRemoteChannel(m_portsGatherer->gdbServerChannel());
+ setQmlServer(m_portsGatherer->qmlServer());
+ addQmlServerInferiorCommandLineArgumentIfNeeded();
DebuggerRunTool::start();
}
+} // namespace Internal
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxdebugsupport.h b/src/plugins/remotelinux/remotelinuxdebugsupport.h
index 81ecb85c35..1b7a0ee3ac 100644
--- a/src/plugins/remotelinux/remotelinuxdebugsupport.h
+++ b/src/plugins/remotelinux/remotelinuxdebugsupport.h
@@ -25,25 +25,21 @@
#pragma once
-#include "abstractremotelinuxrunsupport.h"
-
#include <debugger/debuggerruncontrol.h>
namespace RemoteLinux {
+namespace Internal {
-class REMOTELINUX_EXPORT LinuxDeviceDebugSupport : public Debugger::DebuggerRunTool
+class LinuxDeviceDebugSupport : public Debugger::DebuggerRunTool
{
- Q_OBJECT
-
public:
LinuxDeviceDebugSupport(ProjectExplorer::RunControl *runControl);
private:
void start() override;
-protected:
- QString m_symbolFile;
Debugger::GdbServerPortsGatherer *m_portsGatherer = nullptr;
};
+} // namespace Internal
} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp
index 78b82378df..cc18906fbe 100644
--- a/src/plugins/remotelinux/remotelinuxplugin.cpp
+++ b/src/plugins/remotelinux/remotelinuxplugin.cpp
@@ -63,7 +63,6 @@ bool RemoteLinuxPlugin::initialize(const QStringList &arguments,
RunControl::registerWorker<SimpleTargetRunner>(NORMAL_RUN_MODE, constraint);
RunControl::registerWorker<LinuxDeviceDebugSupport>(DEBUG_RUN_MODE, constraint);
RunControl::registerWorker<RemoteLinuxQmlProfilerSupport>(QML_PROFILER_RUN_MODE, constraint);
- //RunControl::registerWorker<RemoteLinuxPerfSupport>(PERFPROFILER_RUN_MODE, constraint);
addAutoReleasedObject(new GenericLinuxDeviceConfigurationFactory);
addAutoReleasedObject(new RemoteLinuxRunConfigurationFactory);
diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
index 4dcca9c9cc..ea8b4f6505 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp
@@ -51,26 +51,12 @@ const char WorkingDirectoryKey[] = "RemoteLinux.RunConfig.WorkingDirectory";
} // anonymous namespace
-class RemoteLinuxRunConfigurationPrivate {
+class RemoteLinuxRunConfigurationPrivate
+{
public:
- RemoteLinuxRunConfigurationPrivate(const QString &targetName)
- : targetName(targetName),
- useAlternateRemoteExecutable(false)
- {
- }
-
- RemoteLinuxRunConfigurationPrivate(const RemoteLinuxRunConfigurationPrivate *other)
- : targetName(other->targetName),
- arguments(other->arguments),
- useAlternateRemoteExecutable(other->useAlternateRemoteExecutable),
- alternateRemoteExecutable(other->alternateRemoteExecutable),
- workingDirectory(other->workingDirectory)
- {
- }
-
QString targetName;
QString arguments;
- bool useAlternateRemoteExecutable;
+ bool useAlternateRemoteExecutable = false;
QString alternateRemoteExecutable;
QString workingDirectory;
};
@@ -79,45 +65,40 @@ public:
using namespace Internal;
-RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *parent, Core::Id id,
- const QString &targetName)
- : RunConfiguration(parent, id),
- d(new RemoteLinuxRunConfigurationPrivate(targetName))
+RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *target)
+ : RunConfiguration(target), d(new RemoteLinuxRunConfigurationPrivate)
{
- init();
-}
+ addExtraAspect(new RemoteLinuxEnvironmentAspect(this));
-RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *parent,
- RemoteLinuxRunConfiguration *source)
- : RunConfiguration(parent, source),
- d(new RemoteLinuxRunConfigurationPrivate(source->d))
-{
- init();
+ connect(target, &Target::deploymentDataChanged,
+ this, &RemoteLinuxRunConfiguration::handleBuildSystemDataUpdated);
+ connect(target, &Target::applicationTargetsChanged,
+ this, &RemoteLinuxRunConfiguration::handleBuildSystemDataUpdated);
+ // Handles device changes, etc.
+ connect(target, &Target::kitChanged,
+ this, &RemoteLinuxRunConfiguration::handleBuildSystemDataUpdated);
}
-RemoteLinuxRunConfiguration::~RemoteLinuxRunConfiguration()
+void RemoteLinuxRunConfiguration::initialize(Core::Id id, const QString &targetName)
{
- delete d;
-}
+ RunConfiguration::initialize(id);
+
+ d->targetName = targetName;
-void RemoteLinuxRunConfiguration::init()
-{
setDefaultDisplayName(defaultDisplayName());
+}
- addExtraAspect(new RemoteLinuxEnvironmentAspect(this));
+void RemoteLinuxRunConfiguration::copyFrom(const RemoteLinuxRunConfiguration *source)
+{
+ RunConfiguration::copyFrom(source);
+ *d = *source->d;
- connect(target(), &Target::deploymentDataChanged,
- this, &RemoteLinuxRunConfiguration::handleBuildSystemDataUpdated);
- connect(target(), &Target::applicationTargetsChanged,
- this, &RemoteLinuxRunConfiguration::handleBuildSystemDataUpdated);
- // Handles device changes, etc.
- connect(target(), &Target::kitChanged,
- this, &RemoteLinuxRunConfiguration::handleBuildSystemDataUpdated);
+ setDefaultDisplayName(defaultDisplayName());
}
-bool RemoteLinuxRunConfiguration::isEnabled() const
+RemoteLinuxRunConfiguration::~RemoteLinuxRunConfiguration()
{
- return true;
+ delete d;
}
QWidget *RemoteLinuxRunConfiguration::createConfigurationWidget()
diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.h b/src/plugins/remotelinux/remotelinuxrunconfiguration.h
index a1926c4cd5..b4ef39a737 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfiguration.h
+++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.h
@@ -34,24 +34,18 @@
namespace RemoteLinux {
class RemoteLinuxRunConfigurationWidget;
-namespace Internal {
-class RemoteLinuxRunConfigurationPrivate;
-class RemoteLinuxRunConfigurationFactory;
-} // namespace Internal
+namespace Internal { class RemoteLinuxRunConfigurationPrivate; }
class REMOTELINUX_EXPORT RemoteLinuxRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
- Q_DISABLE_COPY(RemoteLinuxRunConfiguration)
- friend class Internal::RemoteLinuxRunConfigurationFactory;
friend class RemoteLinuxRunConfigurationWidget;
+ friend class ProjectExplorer::IRunConfigurationFactory;
public:
- RemoteLinuxRunConfiguration(ProjectExplorer::Target *parent, Core::Id id,
- const QString &targetName);
+ explicit RemoteLinuxRunConfiguration(ProjectExplorer::Target *target);
~RemoteLinuxRunConfiguration() override;
- bool isEnabled() const override;
QWidget *createConfigurationWidget() override;
Utils::OutputFormatter *createOutputFormatter() const override;
@@ -80,14 +74,14 @@ signals:
void targetInformationChanged() const;
protected:
- RemoteLinuxRunConfiguration(ProjectExplorer::Target *parent,
- RemoteLinuxRunConfiguration *source);
+ void initialize(Core::Id id, const QString &targetName);
+ void copyFrom(const RemoteLinuxRunConfiguration *source);
+
bool fromMap(const QVariantMap &map) override;
QString defaultDisplayName();
private:
void handleBuildSystemDataUpdated();
- void init();
Internal::RemoteLinuxRunConfigurationPrivate * const d;
};
diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp
index 8745163fca..53363b19c4 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp
+++ b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp
@@ -107,27 +107,25 @@ QString RemoteLinuxRunConfigurationFactory::displayNameForId(Core::Id id) const
RunConfiguration *RemoteLinuxRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
if (id == RemoteLinuxCustomRunConfiguration::runConfigId())
- return new RemoteLinuxCustomRunConfiguration(parent);
- return new RemoteLinuxRunConfiguration(parent, id, stringFromId(id));
+ return createHelper<RemoteLinuxCustomRunConfiguration>(parent);
+ return createHelper<RemoteLinuxRunConfiguration>(parent, id, stringFromId(id));
}
RunConfiguration *RemoteLinuxRunConfigurationFactory::doRestore(Target *parent,
const QVariantMap &map)
{
if (idFromMap(map) == RemoteLinuxCustomRunConfiguration::runConfigId())
- return new RemoteLinuxCustomRunConfiguration(parent);
- return new RemoteLinuxRunConfiguration(parent,
- Core::Id(RemoteLinuxRunConfiguration::IdPrefix), QString());
+ return createHelper<RemoteLinuxCustomRunConfiguration>(parent);
+ return createHelper<RemoteLinuxRunConfiguration>(parent, RemoteLinuxRunConfiguration::IdPrefix, QString());
}
RunConfiguration *RemoteLinuxRunConfigurationFactory::clone(Target *parent,
RunConfiguration *source)
{
QTC_ASSERT(canClone(parent, source), return 0);
- if (RemoteLinuxCustomRunConfiguration *old = qobject_cast<RemoteLinuxCustomRunConfiguration *>(source))
- return new RemoteLinuxCustomRunConfiguration(parent, old);
- RemoteLinuxRunConfiguration *old = static_cast<RemoteLinuxRunConfiguration *>(source);
- return new RemoteLinuxRunConfiguration(parent, old);
+ if (qobject_cast<RemoteLinuxCustomRunConfiguration *>(source))
+ return cloneHelper<RemoteLinuxCustomRunConfiguration>(parent, source);
+ return cloneHelper<RemoteLinuxRunConfiguration>(parent, source);
}
bool RemoteLinuxRunConfigurationFactory::canHandle(const Target *target) const
diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp
index 8e3442efaf..1f898bfdc6 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp
+++ b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.cpp
@@ -58,9 +58,6 @@ public:
RemoteLinuxRunConfiguration * const runConfiguration;
bool ignoreChange;
- QWidget topWidget;
- QLabel disabledIcon;
- QLabel disabledReason;
QLineEdit argsLineEdit;
QLineEdit workingDirLineEdit;
QLabel localExecutableLabel;
@@ -79,17 +76,9 @@ RemoteLinuxRunConfigurationWidget::RemoteLinuxRunConfigurationWidget(RemoteLinux
QWidget *parent)
: QWidget(parent), d(new RemoteLinuxRunConfigurationWidgetPrivate(runConfiguration))
{
- QVBoxLayout *topLayout = new QVBoxLayout(this);
- topLayout->setMargin(0);
- addDisabledLabel(topLayout);
- topLayout->addWidget(&d->topWidget);
- QVBoxLayout *mainLayout = new QVBoxLayout(&d->topWidget);
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(0);
addGenericWidgets(mainLayout);
-
- connect(d->runConfiguration, &RemoteLinuxRunConfiguration::enabledChanged,
- this, &RemoteLinuxRunConfigurationWidget::runConfigurationEnabledChange);
- runConfigurationEnabledChange();
}
RemoteLinuxRunConfigurationWidget::~RemoteLinuxRunConfigurationWidget()
@@ -102,27 +91,6 @@ void RemoteLinuxRunConfigurationWidget::addFormLayoutRow(QWidget *label, QWidget
d->genericWidgetsLayout.addRow(label, field);
}
-void RemoteLinuxRunConfigurationWidget::addDisabledLabel(QVBoxLayout *topLayout)
-{
- QHBoxLayout * const hl = new QHBoxLayout;
- hl->addStretch();
- d->disabledIcon.setPixmap(Utils::Icons::WARNING.pixmap());
- hl->addWidget(&d->disabledIcon);
- d->disabledReason.setVisible(false);
- hl->addWidget(&d->disabledReason);
- hl->addStretch();
- topLayout->addLayout(hl);
-}
-
-void RemoteLinuxRunConfigurationWidget::runConfigurationEnabledChange()
-{
- bool enabled = d->runConfiguration->isEnabled();
- d->topWidget.setEnabled(enabled);
- d->disabledIcon.setVisible(!enabled);
- d->disabledReason.setVisible(!enabled);
- d->disabledReason.setText(d->runConfiguration->disabledReason());
-}
-
void RemoteLinuxRunConfigurationWidget::addGenericWidgets(QVBoxLayout *mainLayout)
{
Utils::DetailsWidget *detailsContainer = new Utils::DetailsWidget(this);
diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h
index a25d74220a..0ac60985c6 100644
--- a/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h
+++ b/src/plugins/remotelinux/remotelinuxrunconfigurationwidget.h
@@ -49,9 +49,6 @@ public:
void addFormLayoutRow(QWidget *label, QWidget *field);
- void addDisabledLabel(QVBoxLayout *topLayout);
- void runConfigurationEnabledChange();
-
private:
void argumentsEdited(const QString &args);
void updateTargetInformation();
diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp
index b139e7fda4..5e17105cfa 100644
--- a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp
+++ b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp
@@ -564,8 +564,8 @@ void ResourceFile::clearPrefixList()
ResourceModel::ResourceModel(QObject *parent)
: QAbstractItemModel(parent), m_dirty(false)
{
- m_prefixIcon = Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon,
- QIcon(QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QRC)), QSize(16, 16));
+ static QIcon resourceFolderIcon = Core::FileIconProvider::directoryIcon(QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QRC));
+ m_prefixIcon = resourceFolderIcon;
}
void ResourceModel::setDirty(bool b)
diff --git a/src/plugins/resourceeditor/qrceditor/resourceview.h b/src/plugins/resourceeditor/qrceditor/resourceview.h
index d53f954685..d15a638993 100644
--- a/src/plugins/resourceeditor/qrceditor/resourceview.h
+++ b/src/plugins/resourceeditor/qrceditor/resourceview.h
@@ -32,9 +32,6 @@
#include <QPoint>
QT_BEGIN_NAMESPACE
-class QAction;
-class QMenu;
-class QMouseEvent;
class QUndoStack;
QT_END_NAMESPACE
diff --git a/src/plugins/resourceeditor/resourceeditorplugin.cpp b/src/plugins/resourceeditor/resourceeditorplugin.cpp
index 75cce17542..bc28f94747 100644
--- a/src/plugins/resourceeditor/resourceeditorplugin.cpp
+++ b/src/plugins/resourceeditor/resourceeditorplugin.cpp
@@ -245,7 +245,7 @@ void ResourceEditorPlugin::onRefresh()
void ResourceEditorPlugin::addPrefixContextMenu()
{
- auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::currentNode());
+ auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::findCurrentNode());
QTC_ASSERT(topLevel, return);
PrefixLangDialog dialog(tr("Add Prefix"), QString(), QString(), Core::ICore::mainWindow());
if (dialog.exec() != QDialog::Accepted)
@@ -258,7 +258,7 @@ void ResourceEditorPlugin::addPrefixContextMenu()
void ResourceEditorPlugin::removePrefixContextMenu()
{
- auto rfn = dynamic_cast<ResourceFolderNode *>(ProjectTree::currentNode());
+ auto rfn = dynamic_cast<ResourceFolderNode *>(ProjectTree::findCurrentNode());
QTC_ASSERT(rfn, return);
if (QMessageBox::question(Core::ICore::mainWindow(),
tr("Remove Prefix"),
@@ -271,7 +271,7 @@ void ResourceEditorPlugin::removePrefixContextMenu()
void ResourceEditorPlugin::removeNonExisting()
{
- auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::currentNode());
+ auto topLevel = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::findCurrentNode());
QTC_ASSERT(topLevel, return);
topLevel->removeNonExistingFiles();
}
@@ -283,7 +283,7 @@ void ResourceEditorPlugin::renameFileContextMenu()
void ResourceEditorPlugin::removeFileContextMenu()
{
- auto rfn = dynamic_cast<ResourceFolderNode *>(ProjectTree::currentNode());
+ auto rfn = dynamic_cast<ResourceTopLevelNode *>(ProjectTree::findCurrentNode());
QTC_ASSERT(rfn, return);
QString path = rfn->filePath().toString();
FolderNode *parent = rfn->parentFolderNode();
@@ -296,26 +296,26 @@ void ResourceEditorPlugin::removeFileContextMenu()
void ResourceEditorPlugin::openEditorContextMenu()
{
- Core::EditorManager::openEditor(ProjectTree::currentNode()->filePath().toString());
+ Core::EditorManager::openEditor(ProjectTree::findCurrentNode()->filePath().toString());
}
void ResourceEditorPlugin::copyPathContextMenu()
{
- auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::currentNode());
+ auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::findCurrentNode());
QTC_ASSERT(node, return);
QApplication::clipboard()->setText(QLatin1String(resourcePrefix) + node->qrcPath());
}
void ResourceEditorPlugin::copyUrlContextMenu()
{
- auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::currentNode());
+ auto node = dynamic_cast<ResourceFileNode *>(ProjectTree::findCurrentNode());
QTC_ASSERT(node, return);
QApplication::clipboard()->setText(QLatin1String(urlPrefix) + node->qrcPath());
}
void ResourceEditorPlugin::renamePrefixContextMenu()
{
- auto node = dynamic_cast<ResourceFolderNode *>(ProjectTree::currentNode());
+ auto node = dynamic_cast<ResourceFolderNode *>(ProjectTree::findCurrentNode());
QTC_ASSERT(node, return);
PrefixLangDialog dialog(tr("Rename Prefix"), node->prefix(), node->lang(), Core::ICore::mainWindow());
@@ -330,8 +330,8 @@ void ResourceEditorPlugin::renamePrefixContextMenu()
void ResourceEditorPlugin::updateContextActions()
{
- Node *node = ProjectTree::currentNode();
- bool isResourceNode = dynamic_cast<ResourceTopLevelNode *>(node);
+ const Node *node = ProjectTree::findCurrentNode();
+ const bool isResourceNode = dynamic_cast<const ResourceTopLevelNode *>(node);
m_addPrefix->setEnabled(isResourceNode);
m_addPrefix->setVisible(isResourceNode);
@@ -352,7 +352,7 @@ void ResourceEditorPlugin::updateContextActions()
m_openInEditor->setEnabled(isResourceNode);
m_openInEditor->setVisible(isResourceNode);
- bool isResourceFolder = dynamic_cast<ResourceFolderNode *>(node);
+ const bool isResourceFolder = dynamic_cast<const ResourceFolderNode *>(node);
m_removePrefix->setEnabled(isResourceFolder);
m_removePrefix->setVisible(isResourceFolder);
@@ -368,13 +368,13 @@ void ResourceEditorPlugin::updateContextActions()
m_openWithMenu->clear();
m_openWithMenu->menuAction()->setVisible(!m_openWithMenu->actions().isEmpty());
- bool isResourceFile = dynamic_cast<ResourceFileNode *>(node);
+ const bool isResourceFile = dynamic_cast<const ResourceFileNode *>(node);
m_copyPath->setEnabled(isResourceFile);
m_copyPath->setVisible(isResourceFile);
m_copyUrl->setEnabled(isResourceFile);
m_copyUrl->setVisible(isResourceFile);
if (isResourceFile) {
- auto fileNode = dynamic_cast<ResourceFileNode *>(node);
+ auto fileNode = dynamic_cast<const ResourceFileNode *>(node);
QTC_ASSERT(fileNode, return);
QString qrcPath = fileNode->qrcPath();
m_copyPath->setParameter(QLatin1String(resourcePrefix) + qrcPath);
diff --git a/src/plugins/resourceeditor/resourceeditorplugin.h b/src/plugins/resourceeditor/resourceeditorplugin.h
index 0baf20f924..6da0079463 100644
--- a/src/plugins/resourceeditor/resourceeditorplugin.h
+++ b/src/plugins/resourceeditor/resourceeditorplugin.h
@@ -38,8 +38,6 @@ namespace ResourceEditor {
namespace Internal {
class ResourceEditorW;
-class ResourceWizard;
-class ResourceEditorFactory;
class ResourceEditorPlugin : public ExtensionSystem::IPlugin
{
diff --git a/src/plugins/resourceeditor/resourcenode.cpp b/src/plugins/resourceeditor/resourcenode.cpp
index 45c57c9126..0ca93ea5b5 100644
--- a/src/plugins/resourceeditor/resourcenode.cpp
+++ b/src/plugins/resourceeditor/resourcenode.cpp
@@ -160,7 +160,7 @@ public:
ResourceTopLevelNode *topLevel, ResourceFolderNode *prefixNode);
QString displayName() const final;
- bool supportsAction(ProjectAction, Node *node) const final;
+ bool supportsAction(ProjectAction, const Node *node) const final;
bool addFiles(const QStringList &filePaths, QStringList *notAdded) final;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) final;
bool renameFile(const QString &filePath, const QString &newFilePath) final;
@@ -199,7 +199,7 @@ SimpleResourceFolderNode::SimpleResourceFolderNode(const QString &afolderName, c
}
-bool SimpleResourceFolderNode::supportsAction(ProjectAction action, Node *) const
+bool SimpleResourceFolderNode::supportsAction(ProjectAction action, const Node *) const
{
return action == AddNewFile
|| action == AddExistingFile
@@ -390,7 +390,7 @@ QString ResourceTopLevelNode::addFileFilter() const
return QLatin1String("*.png; *.jpg; *.gif; *.svg; *.ico; *.qml; *.qml.ui");
}
-bool ResourceTopLevelNode::supportsAction(ProjectAction action, Node *node) const
+bool ResourceTopLevelNode::supportsAction(ProjectAction action, const Node *node) const
{
if (node != this)
return false;
@@ -513,7 +513,7 @@ ResourceFolderNode::~ResourceFolderNode()
}
-bool ResourceFolderNode::supportsAction(ProjectAction action, Node *node) const
+bool ResourceFolderNode::supportsAction(ProjectAction action, const Node *node) const
{
Q_UNUSED(node)
@@ -678,7 +678,7 @@ QString ResourceFileNode::qrcPath() const
return m_qrcPath;
}
-bool ResourceFileNode::supportsAction(ProjectAction action, Node *node) const
+bool ResourceFileNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == HidePathActions)
return false;
diff --git a/src/plugins/resourceeditor/resourcenode.h b/src/plugins/resourceeditor/resourcenode.h
index f9b9e65c37..6752eb6855 100644
--- a/src/plugins/resourceeditor/resourcenode.h
+++ b/src/plugins/resourceeditor/resourcenode.h
@@ -42,7 +42,7 @@ public:
QString addFileFilter() const override;
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) override;
@@ -69,7 +69,7 @@ public:
ResourceFolderNode(const QString &prefix, const QString &lang, ResourceTopLevelNode *parent);
~ResourceFolderNode() override;
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
QString displayName() const override;
@@ -99,7 +99,7 @@ public:
QString displayName() const override;
QString qrcPath() const;
- bool supportsAction(ProjectExplorer::ProjectAction action, Node *node) const override;
+ bool supportsAction(ProjectExplorer::ProjectAction action, const Node *node) const override;
private:
QString m_qrcPath;
diff --git a/src/plugins/scxmleditor/common/stateproperties.cpp b/src/plugins/scxmleditor/common/stateproperties.cpp
index 32272833b2..568336295f 100644
--- a/src/plugins/scxmleditor/common/stateproperties.cpp
+++ b/src/plugins/scxmleditor/common/stateproperties.cpp
@@ -30,6 +30,7 @@
#include "scxmluifactory.h"
#include <coreplugin/minisplitter.h>
+#include <utils/qtcfallthrough.h>
#include <QHeaderView>
#include <QLabel>
@@ -84,6 +85,7 @@ void StateProperties::tagChange(ScxmlDocument::TagChange change, ScxmlTag *tag,
case ScxmlDocument::TagContentChanged:
if (tag != m_tag)
return;
+ Q_FALLTHROUGH();
case ScxmlDocument::TagCurrentChanged:
setTag(tag);
break;
diff --git a/src/plugins/scxmleditor/outputpane/warningmodel.cpp b/src/plugins/scxmleditor/outputpane/warningmodel.cpp
index 23a406a323..6b4bb0ea03 100644
--- a/src/plugins/scxmleditor/outputpane/warningmodel.cpp
+++ b/src/plugins/scxmleditor/outputpane/warningmodel.cpp
@@ -237,14 +237,15 @@ Warning *WarningModel::getWarning(const QModelIndex &ind)
return nullptr;
}
-void WarningModel::warningDestroyed(QObject *ww)
+void WarningModel::warningDestroyed(QObject *w)
{
- auto w = static_cast<Warning*>(ww);
- if (m_warnings.contains(w)) {
- int ind = m_warnings.indexOf(w);
+ // Intentional static_cast.
+ // The Warning is being destroyed, so qobject_cast doesn't work anymore.
+ const int ind = m_warnings.indexOf(static_cast<Warning *>(w));
+ if (ind >= 0) {
beginRemoveRows(QModelIndex(), ind, ind);
m_warnings.removeAt(ind);
- endResetModel();
+ endRemoveRows();
}
m_countChecker->start();
diff --git a/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp b/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
index 82200f2a57..130c86bf5c 100644
--- a/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
@@ -33,6 +33,8 @@
#include "serializer.h"
#include "stateitem.h"
+#include <utils/qtcfallthrough.h>
+
#include <QDebug>
#include <QPainter>
#include <QPen>
@@ -491,7 +493,7 @@ QVariant ConnectableItem::itemChange(GraphicsItemChange change, const QVariant &
case ItemParentHasChanged:
updateTransitions(true);
updateTransitionAttributes(true);
- // FIXME: intended fallthrough?
+ Q_FALLTHROUGH();
case ItemPositionHasChanged:
if (!m_releasedFromParent && !blockUpdates())
checkParentBoundingRect();
diff --git a/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp b/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
index e5681fbc6e..b1347007be 100644
--- a/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
@@ -541,7 +541,7 @@ void GraphicsScene::endTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag,
item->finalizeCreation();
}
}
- // FIXME: intended fallthrough?
+ break;
case ScxmlDocument::TagAddChild: {
ScxmlTag *childTag = tag->child(value.toInt());
if (childTag) {
diff --git a/src/plugins/scxmleditor/plugin_interface/scattributeitemmodel.cpp b/src/plugins/scxmleditor/plugin_interface/scattributeitemmodel.cpp
index 38fe97e667..7ea007bdff 100644
--- a/src/plugins/scxmleditor/plugin_interface/scattributeitemmodel.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/scattributeitemmodel.cpp
@@ -26,6 +26,8 @@
#include "scattributeitemmodel.h"
#include "mytypes.h"
+#include <utils/qtcfallthrough.h>
+
#include <QBrush>
using namespace ScxmlEditor::PluginInterface;
@@ -91,6 +93,7 @@ QVariant SCAttributeItemModel::data(const QModelIndex &index, int role) const
case Qt::DisplayRole:
if (bExtraRow)
return index.column() == 0 ? tr("- name -") : tr(" - value -");
+ Q_FALLTHROUGH();
case Qt::EditRole: {
if (index.column() == 0) {
if (bEditable) {
diff --git a/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp b/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp
index 154324fd98..acf0116ac6 100644
--- a/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp
+++ b/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp
@@ -244,7 +244,7 @@ void TransitionItem::snapToAnyPoint(int id, const QPointF &newPoint, int diff)
void TransitionItem::snapPointToPoint(int idSnap, const QPointF &p, int diff)
{
- if (idSnap >= 0 && idSnap < m_cornerPoints.count()) {
+ if (idSnap >= 0 && static_cast<uint>(idSnap) < static_cast<uint>(m_cornerPoints.count())) {
if (qAbs(p.x() - m_cornerPoints[idSnap].x()) < diff)
m_cornerPoints[idSnap].setX(p.x());
if (qAbs(p.y() - m_cornerPoints[idSnap].y()) < diff)
diff --git a/src/plugins/subversion/settingspage.h b/src/plugins/subversion/settingspage.h
index afb0c6a879..d532394027 100644
--- a/src/plugins/subversion/settingspage.h
+++ b/src/plugins/subversion/settingspage.h
@@ -33,10 +33,6 @@
#include <QPointer>
#include <QString>
-QT_BEGIN_NAMESPACE
-class QSettings;
-QT_END_NAMESPACE
-
namespace Subversion {
namespace Internal {
diff --git a/src/plugins/subversion/subversionclient.h b/src/plugins/subversion/subversionclient.h
index b3ed32c2c2..aa45c124da 100644
--- a/src/plugins/subversion/subversionclient.h
+++ b/src/plugins/subversion/subversionclient.h
@@ -25,16 +25,15 @@
#pragma once
-#include "subversionsettings.h"
#include <vcsbase/vcsbaseclient.h>
-#include <vcsbase/vcscommand.h>
#include <utils/fileutils.h>
+namespace VcsBase { class VcsCommand; }
+
namespace Subversion {
namespace Internal {
-class SubversionSettings;
class SubversionDiffEditorController;
class SubversionClient : public VcsBase::VcsBaseClient
diff --git a/src/plugins/subversion/subversioncontrol.cpp b/src/plugins/subversion/subversioncontrol.cpp
index e7265534ea..8bd9e36f37 100644
--- a/src/plugins/subversion/subversioncontrol.cpp
+++ b/src/plugins/subversion/subversioncontrol.cpp
@@ -32,6 +32,7 @@
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsbaseclientsettings.h>
+#include <vcsbase/vcscommand.h>
#include <utils/fileutils.h>
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index aaf43d9195..d35d027b57 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -210,7 +210,7 @@ bool SubversionPlugin::initialize(const QStringList & /*arguments */, QString *e
Context context(SUBVERSION_CONTEXT);
- initializeVcs(new SubversionControl(this), context);
+ initializeVcs<SubversionControl>(context, this);
m_subversionPluginInstance = this;
@@ -642,6 +642,9 @@ void SubversionPlugin::startCommitProject()
* commit will start. */
void SubversionPlugin::startCommit(const QString &workingDir, const QStringList &files)
{
+ if (!promptBeforeCommit())
+ return;
+
if (raiseSubmitEditor())
return;
if (isCommitEditorOpen()) {
diff --git a/src/plugins/subversion/subversionsettings.cpp b/src/plugins/subversion/subversionsettings.cpp
index 5870f2f423..78a0f4728a 100644
--- a/src/plugins/subversion/subversionsettings.cpp
+++ b/src/plugins/subversion/subversionsettings.cpp
@@ -46,8 +46,8 @@ SubversionSettings::SubversionSettings()
declareKey(binaryPathKey, QLatin1String("svn" QTC_HOST_EXE_SUFFIX));
declareKey(logCountKey, 1000);
declareKey(useAuthenticationKey, false);
- declareKey(userKey, QLatin1String(""));
- declareKey(passwordKey, QLatin1String(""));
+ declareKey(userKey, QString());
+ declareKey(passwordKey, QString());
declareKey(spaceIgnorantAnnotationKey, true);
declareKey(diffIgnoreWhiteSpaceKey, false);
declareKey(logVerboseKey, false);
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index 7486cfd0d4..dcb33b50ae 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -448,16 +448,8 @@ void BaseFileFind::openEditor(const SearchResultItem &item)
FileFindParameters parameters = result->userData().value<FileFindParameters>();
IEditor *openedEditor =
d->m_searchEngines[parameters.searchEngineIndex]->openEditor(item, parameters);
- if (!openedEditor) {
- if (item.path.size() > 0) {
- openedEditor = EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
- item.mainRange.begin.line,
- item.mainRange.begin.column, Id(),
- EditorManager::DoNotSwitchToDesignMode);
- } else {
- openedEditor = EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
- }
- }
+ if (!openedEditor)
+ EditorManager::openEditorAtSearchResult(item, EditorManager::DoNotSwitchToDesignMode);
if (d->m_currentFindSupport)
d->m_currentFindSupport->clearHighlights();
d->m_currentFindSupport = 0;
diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h
index 56bbb4e5fd..d921b4f2f0 100644
--- a/src/plugins/texteditor/basefilefind.h
+++ b/src/plugins/texteditor/basefilefind.h
@@ -33,15 +33,9 @@
#include <QFuture>
-QT_BEGIN_NAMESPACE
-class QLabel;
-class QComboBox;
-QT_END_NAMESPACE
-
namespace Utils { class FileIterator; }
namespace Core {
class IEditor;
-class IFindSupport;
class SearchResult;
class SearchResultItem;
} // namespace Core
diff --git a/src/plugins/texteditor/behaviorsettingspage.cpp b/src/plugins/texteditor/behaviorsettingspage.cpp
index 22b0443932..1c26e30a54 100644
--- a/src/plugins/texteditor/behaviorsettingspage.cpp
+++ b/src/plugins/texteditor/behaviorsettingspage.cpp
@@ -57,13 +57,13 @@ struct BehaviorSettingsPage::BehaviorSettingsPagePrivate
const BehaviorSettingsPageParameters m_parameters;
QPointer<QWidget> m_widget;
- Internal::Ui::BehaviorSettingsPage *m_page;
+ Internal::Ui::BehaviorSettingsPage *m_page = nullptr;
void init();
- CodeStylePool *m_defaultCodeStylePool;
- SimpleCodeStylePreferences *m_codeStyle;
- SimpleCodeStylePreferences *m_pageCodeStyle;
+ CodeStylePool *m_defaultCodeStylePool = nullptr;
+ SimpleCodeStylePreferences *m_codeStyle = nullptr;
+ SimpleCodeStylePreferences *m_pageCodeStyle = nullptr;
TypingSettings m_typingSettings;
StorageSettings m_storageSettings;
BehaviorSettings m_behaviorSettings;
@@ -72,7 +72,7 @@ struct BehaviorSettingsPage::BehaviorSettingsPagePrivate
BehaviorSettingsPage::BehaviorSettingsPagePrivate::BehaviorSettingsPagePrivate
(const BehaviorSettingsPageParameters &p)
- : m_parameters(p), m_page(0), m_pageCodeStyle(0)
+ : m_parameters(p)
{
}
diff --git a/src/plugins/texteditor/behaviorsettingswidget.ui b/src/plugins/texteditor/behaviorsettingswidget.ui
index bc3d4e5b76..a342858801 100644
--- a/src/plugins/texteditor/behaviorsettingswidget.ui
+++ b/src/plugins/texteditor/behaviorsettingswidget.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>801</width>
- <height>459</height>
+ <height>480</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
@@ -290,7 +290,7 @@ Specifies how backspace interacts with indentation.
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;
&lt;p&gt;How text editors should deal with UTF-8 Byte Order Marks. The options are:&lt;/p&gt;
-&lt;ul &gt;&lt;li&gt;&lt;i&gt;Add If Encoding Is UTF-8:&lt;/i&gt; always add a BOM when saving a file in UTF-8 encoding. Note that this will not work if the encoding is &lt;i&gt;System&lt;/i&gt;, as Qt Creator does not know what it actually is.&lt;/li&gt;
+&lt;ul &gt;&lt;li&gt;&lt;i&gt;Add If Encoding Is UTF-8:&lt;/i&gt; always add a BOM when saving a file in UTF-8 encoding. Note that this will not work if the encoding is &lt;i&gt;System&lt;/i&gt;, as the text editor does not know what it actually is.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Keep If Already Present: &lt;/i&gt;save the file with a BOM if it already had one when it was loaded.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Always Delete:&lt;/i&gt; never write an UTF-8 BOM, possibly deleting a pre-existing one.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Note that UTF-8 BOMs are uncommon and treated incorrectly by some editors, so it usually makes little sense to add any.&lt;/p&gt;
diff --git a/src/plugins/texteditor/codeassist/assistinterface.cpp b/src/plugins/texteditor/codeassist/assistinterface.cpp
index 4267067889..3577718dfb 100644
--- a/src/plugins/texteditor/codeassist/assistinterface.cpp
+++ b/src/plugins/texteditor/codeassist/assistinterface.cpp
@@ -91,7 +91,7 @@ using namespace TextEditor;
#include "assistinterface.h"
-#include <texteditor/convenience.h>
+#include <utils/textutils.h>
#include <QTextBlock>
#include <QTextDocument>
@@ -125,7 +125,7 @@ QChar AssistInterface::characterAt(int position) const
QString AssistInterface::textAt(int pos, int length) const
{
- return Convenience::textAt(QTextCursor(m_textDocument), pos, length);
+ return Utils::Text::textAt(QTextCursor(m_textDocument), pos, length);
}
void AssistInterface::prepareForAsyncUse()
diff --git a/src/plugins/texteditor/codeassist/assistproposalitem.h b/src/plugins/texteditor/codeassist/assistproposalitem.h
index 8d957a2f81..286eef67dc 100644
--- a/src/plugins/texteditor/codeassist/assistproposalitem.h
+++ b/src/plugins/texteditor/codeassist/assistproposalitem.h
@@ -35,7 +35,6 @@
namespace TextEditor {
-class TextEditorWidget;
class TEXTEDITOR_EXPORT AssistProposalItem : public AssistProposalItemInterface
{
diff --git a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
index 69bc1d91e3..a4f925f4d9 100644
--- a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
+++ b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
@@ -32,14 +32,12 @@
QT_BEGIN_NAMESPACE
class QIcon;
class QString;
-class QVariant;
QT_END_NAMESPACE
#include <QString>
namespace TextEditor {
-class TextEditorWidget;
class TEXTEDITOR_EXPORT AssistProposalItemInterface
{
diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp
index 0622f29f10..5de47c3b09 100644
--- a/src/plugins/texteditor/codeassist/codeassistant.cpp
+++ b/src/plugins/texteditor/codeassist/codeassistant.cpp
@@ -74,6 +74,9 @@ public:
bool hasContext() const;
void destroyContext();
+ QVariant userData() const;
+ void setUserData(const QVariant &data);
+
CompletionAssistProvider *identifyActivationSequence();
void stopAutomaticProposalTimer();
@@ -105,6 +108,7 @@ private:
CompletionSettings m_settings;
int m_abortedBasePosition;
static const QChar m_null;
+ QVariant m_userData;
};
// --------------------
@@ -248,7 +252,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason,
}
case IAssistProvider::Asynchronous: {
processor->setAsyncCompletionAvailableHandler(
- [this, processor, reason](IAssistProposal *newProposal){
+ [this, reason](IAssistProposal *newProposal){
QTC_CHECK(newProposal);
invalidateCurrentRequestData();
displayProposal(newProposal, reason);
@@ -340,6 +344,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR
m_proposalWidget->setAssistant(q);
m_proposalWidget->setReason(reason);
m_proposalWidget->setKind(m_assistKind);
+ m_proposalWidget->setBasePosition(basePosition);
m_proposalWidget->setUnderlyingWidget(m_editorWidget);
m_proposalWidget->setModel(proposalCandidateModel.take());
m_proposalWidget->setDisplayRect(m_editorWidget->cursorRect(basePosition));
@@ -441,8 +446,6 @@ void CodeAssistantPrivate::notifyChange()
m_proposalWidget->updateProposal(
m_editorWidget->textAt(m_proposal->basePosition(),
m_editorWidget->position() - m_proposal->basePosition()));
- if (m_proposal->isFragile())
- startAutomaticProposalTimer();
}
}
}
@@ -467,6 +470,16 @@ void CodeAssistantPrivate::destroyContext()
}
}
+QVariant CodeAssistantPrivate::userData() const
+{
+ return m_userData;
+}
+
+void CodeAssistantPrivate::setUserData(const QVariant &data)
+{
+ m_userData = data;
+}
+
void CodeAssistantPrivate::startAutomaticProposalTimer()
{
if (m_settings.m_completionTrigger == AutomaticCompletion)
@@ -574,6 +587,16 @@ void CodeAssistant::destroyContext()
d->destroyContext();
}
+QVariant CodeAssistant::userData() const
+{
+ return d->userData();
+}
+
+void CodeAssistant::setUserData(const QVariant &data)
+{
+ d->setUserData(data);
+}
+
void CodeAssistant::invoke(AssistKind kind, IAssistProvider *provider)
{
d->invoke(kind, provider);
diff --git a/src/plugins/texteditor/codeassist/codeassistant.h b/src/plugins/texteditor/codeassist/codeassistant.h
index dca761f4ac..46ffa9a85c 100644
--- a/src/plugins/texteditor/codeassist/codeassistant.h
+++ b/src/plugins/texteditor/codeassist/codeassistant.h
@@ -34,7 +34,6 @@
namespace TextEditor {
class CodeAssistantPrivate;
-class CompletionSettings;
class IAssistProvider;
class TextEditorWidget;
@@ -53,6 +52,9 @@ public:
bool hasContext() const;
void destroyContext();
+ QVariant userData() const;
+ void setUserData(const QVariant &data);
+
void invoke(AssistKind assistKind, IAssistProvider *provider = 0);
signals:
diff --git a/src/plugins/texteditor/codeassist/functionhintproposal.cpp b/src/plugins/texteditor/codeassist/functionhintproposal.cpp
index 5a2bb07cfd..048ce8da56 100644
--- a/src/plugins/texteditor/codeassist/functionhintproposal.cpp
+++ b/src/plugins/texteditor/codeassist/functionhintproposal.cpp
@@ -32,16 +32,13 @@ using namespace TextEditor;
FunctionHintProposal::FunctionHintProposal(int cursorPos, IFunctionHintProposalModel *model)
: IAssistProposal(cursorPos)
, m_model(model)
-{}
+{
+ setFragile(true);
+}
FunctionHintProposal::~FunctionHintProposal()
{}
-bool FunctionHintProposal::isFragile() const
-{
- return true;
-}
-
IAssistProposalModel *FunctionHintProposal::model() const
{
return m_model;
diff --git a/src/plugins/texteditor/codeassist/functionhintproposal.h b/src/plugins/texteditor/codeassist/functionhintproposal.h
index fd73886b05..5374653454 100644
--- a/src/plugins/texteditor/codeassist/functionhintproposal.h
+++ b/src/plugins/texteditor/codeassist/functionhintproposal.h
@@ -38,7 +38,6 @@ public:
FunctionHintProposal(int cursorPos, IFunctionHintProposalModel *model);
~FunctionHintProposal();
- bool isFragile() const override;
IAssistProposalModel *model() const override;
IAssistProposalWidget *createWidget() const override;
diff --git a/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp b/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp
index 4ad414d44e..dc952e1994 100644
--- a/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp
+++ b/src/plugins/texteditor/codeassist/functionhintproposalwidget.cpp
@@ -27,6 +27,7 @@
#include "ifunctionhintproposalmodel.h"
#include "codeassistant.h"
+#include <utils/algorithm.h>
#include <utils/faketooltip.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
@@ -42,6 +43,56 @@
namespace TextEditor {
+static const int maxSelectedFunctionHints = 20;
+
+class SelectedFunctionHints
+{
+public:
+ void insert(int basePosition, const QString &hintId)
+ {
+ if (basePosition < 0 || hintId.isEmpty())
+ return;
+
+ const int index = indexOf(basePosition);
+
+ // Add new item
+ if (index == -1) {
+ if (m_items.size() + 1 > maxSelectedFunctionHints)
+ m_items.removeLast();
+ m_items.prepend(FunctionHintItem(basePosition, hintId));
+ return;
+ }
+
+ // Update existing item
+ m_items[index].hintId = hintId;
+ }
+
+ QString hintId(int basePosition) const
+ {
+ const int index = indexOf(basePosition);
+ return index == -1 ? QString() : m_items.at(index).hintId;
+ }
+
+private:
+ int indexOf(int basePosition) const
+ {
+ return Utils::indexOf(m_items, [&](const FunctionHintItem &item) {
+ return item.basePosition == basePosition;
+ });
+ }
+
+private:
+ struct FunctionHintItem {
+ FunctionHintItem(int basePosition, const QString &hintId)
+ : basePosition(basePosition), hintId(hintId) {}
+
+ int basePosition = -1;
+ QString hintId;
+ };
+
+ QList<FunctionHintItem> m_items;
+};
+
// -------------------------
// HintProposalWidgetPrivate
// -------------------------
@@ -158,7 +209,7 @@ void FunctionHintProposalWidget::showProposal(const QString &prefix)
QTC_ASSERT(d->m_totalHints != 0, abort(); return; );
d->m_pager->setVisible(d->m_totalHints > 1);
- d->m_currentHint = 0;
+ d->m_currentHint = loadSelectedHint();
if (!updateAndCheck(prefix))
return;
@@ -184,6 +235,32 @@ void FunctionHintProposalWidget::abort()
deleteLater();
}
+static SelectedFunctionHints selectedFunctionHints(CodeAssistant &codeAssistant)
+{
+ const QVariant variant = codeAssistant.userData();
+ return variant.value<SelectedFunctionHints>();
+}
+
+int FunctionHintProposalWidget::loadSelectedHint() const
+{
+ const QString hintId = selectedFunctionHints(*d->m_assistant).hintId(basePosition());
+
+ for (int i = 0; i < d->m_model->size(); ++i) {
+ if (d->m_model->id(i) == hintId)
+ return i;
+ }
+
+ return 0;
+}
+
+void FunctionHintProposalWidget::storeSelectedHint()
+{
+ SelectedFunctionHints table = selectedFunctionHints(*d->m_assistant);
+ table.insert(basePosition(), d->m_model->id(d->m_currentHint));
+
+ d->m_assistant->setUserData(QVariant::fromValue(table));
+}
+
bool FunctionHintProposalWidget::eventFilter(QObject *obj, QEvent *e)
{
switch (e->type()) {
@@ -257,6 +334,8 @@ bool FunctionHintProposalWidget::eventFilter(QObject *obj, QEvent *e)
void FunctionHintProposalWidget::nextPage()
{
d->m_currentHint = (d->m_currentHint + 1) % d->m_totalHints;
+
+ storeSelectedHint();
updateContent();
}
@@ -266,6 +345,8 @@ void FunctionHintProposalWidget::previousPage()
d->m_currentHint = d->m_totalHints - 1;
else
--d->m_currentHint;
+
+ storeSelectedHint();
updateContent();
}
@@ -322,3 +403,5 @@ void FunctionHintProposalWidget::updatePosition()
}
} // TextEditor
+
+Q_DECLARE_METATYPE(TextEditor::SelectedFunctionHints)
diff --git a/src/plugins/texteditor/codeassist/functionhintproposalwidget.h b/src/plugins/texteditor/codeassist/functionhintproposalwidget.h
index d42d1e3e69..21a85395dc 100644
--- a/src/plugins/texteditor/codeassist/functionhintproposalwidget.h
+++ b/src/plugins/texteditor/codeassist/functionhintproposalwidget.h
@@ -63,6 +63,9 @@ private:
void updatePosition();
void abort();
+ int loadSelectedHint() const;
+ void storeSelectedHint();
+
private:
FunctionHintProposalWidgetPrivate *d;
};
diff --git a/src/plugins/texteditor/codeassist/genericproposal.cpp b/src/plugins/texteditor/codeassist/genericproposal.cpp
index 5feac5810b..33fb0c547f 100644
--- a/src/plugins/texteditor/codeassist/genericproposal.cpp
+++ b/src/plugins/texteditor/codeassist/genericproposal.cpp
@@ -44,11 +44,6 @@ GenericProposal::GenericProposal(int cursorPos, const QList<AssistProposalItemIn
GenericProposal::~GenericProposal()
{}
-bool GenericProposal::isFragile() const
-{
- return false;
-}
-
bool GenericProposal::hasItemsToPropose(const QString &prefix, AssistReason reason) const
{
if (!prefix.isEmpty()) {
diff --git a/src/plugins/texteditor/codeassist/genericproposal.h b/src/plugins/texteditor/codeassist/genericproposal.h
index 385f9978df..1155ab52ad 100644
--- a/src/plugins/texteditor/codeassist/genericproposal.h
+++ b/src/plugins/texteditor/codeassist/genericproposal.h
@@ -40,7 +40,6 @@ public:
GenericProposal(int cursorPos, const QList<AssistProposalItemInterface *> &items);
~GenericProposal();
- bool isFragile() const override;
bool hasItemsToPropose(const QString &prefix, AssistReason reason) const override;
IAssistProposalModel *model() const override;
IAssistProposalWidget *createWidget() const override;
diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp
index 34a51a4ba1..0357bb8034 100644
--- a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp
+++ b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp
@@ -30,7 +30,7 @@
#include <texteditor/completionsettings.h>
#include <QDebug>
-#include <QRegExp>
+#include <QRegularExpression>
#include <QtAlgorithms>
#include <QHash>
@@ -255,64 +255,15 @@ void GenericProposalModel::filter(const QString &prefix)
if (prefix.isEmpty())
return;
- /*
- * This code builds a regular expression in order to more intelligently match
- * camel-case and underscore names.
- *
- * For any but the first letter, the following replacements are made:
- * A => [a-z0-9_]*A
- * a => (?:[a-zA-Z0-9]*_)?a
- *
- * That means any sequence of lower-case or underscore characters can preceed an
- * upper-case character. And any sequence of lower-case or upper case characters -
- * followed by an underscore can preceed a lower-case character.
- *
- * Examples: (case sensitive mode)
- * gAC matches getActionController
- * gac matches get_action_controller
- *
- * It also implements the fully and first-letter-only case sensitivity.
- */
- const CaseSensitivity caseSensitivity =
- TextEditorSettings::completionSettings().m_caseSensitivity;
-
- QString keyRegExp;
- keyRegExp += QLatin1Char('^');
- bool first = true;
- const QLatin1String uppercaseWordContinuation("[a-z0-9_]*");
- const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?");
- foreach (const QChar &c, prefix) {
- if (caseSensitivity == CaseInsensitive ||
- (caseSensitivity == FirstLetterCaseSensitive && !first)) {
-
- keyRegExp += QLatin1String("(?:");
- if (!first)
- keyRegExp += uppercaseWordContinuation;
- keyRegExp += QRegExp::escape(c.toUpper());
- keyRegExp += QLatin1Char('|');
- if (!first)
- keyRegExp += lowercaseWordContinuation;
- keyRegExp += QRegExp::escape(c.toLower());
- keyRegExp += QLatin1Char(')');
- } else {
- if (!first) {
- if (c.isUpper())
- keyRegExp += uppercaseWordContinuation;
- else
- keyRegExp += lowercaseWordContinuation;
- }
- keyRegExp += QRegExp::escape(c);
- }
-
- first = false;
- }
- QRegExp regExp(keyRegExp);
+ const CamelHumpMatcher::CaseSensitivity caseSensitivity =
+ convertCaseSensitivity(TextEditorSettings::completionSettings().m_caseSensitivity);
+ const QRegularExpression regExp = CamelHumpMatcher::createCamelHumpRegExp(prefix, caseSensitivity);
m_currentItems.clear();
const QString lowerPrefix = prefix.toLower();
foreach (const auto &item, m_originalItems) {
const QString &text = item->text();
- if (regExp.indexIn(text) == 0) {
+ if (regExp.match(text).hasMatch()) {
m_currentItems.append(item);
if (text.startsWith(prefix)) {
// Direct match
@@ -328,6 +279,19 @@ void GenericProposalModel::filter(const QString &prefix)
}
}
+CamelHumpMatcher::CaseSensitivity
+ GenericProposalModel::convertCaseSensitivity(TextEditor::CaseSensitivity textEditorCaseSensitivity)
+{
+ switch (textEditorCaseSensitivity) {
+ case TextEditor::CaseSensitive:
+ return CamelHumpMatcher::CaseSensitivity::CaseSensitive;
+ case TextEditor::FirstLetterCaseSensitive:
+ return CamelHumpMatcher::CaseSensitivity::FirstLetterCaseSensitive;
+ default:
+ return CamelHumpMatcher::CaseSensitivity::CaseInsensitive;
+ }
+}
+
bool GenericProposalModel::isSortable(const QString &prefix) const
{
Q_UNUSED(prefix);
diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.h b/src/plugins/texteditor/codeassist/genericproposalmodel.h
index 32cfd008a8..1a9fd7df57 100644
--- a/src/plugins/texteditor/codeassist/genericproposalmodel.h
+++ b/src/plugins/texteditor/codeassist/genericproposalmodel.h
@@ -28,8 +28,9 @@
#include "iassistproposalmodel.h"
#include "assistenums.h"
+#include <texteditor/completionsettings.h>
#include <texteditor/texteditor_global.h>
-
+#include <utils/camelhumpmatcher.h>
#include <QHash>
#include <QList>
@@ -71,6 +72,8 @@ public:
bool isPrefiltered(const QString &prefix) const;
void setPrefilterPrefix(const QString &prefix);
+ CamelHumpMatcher::CaseSensitivity convertCaseSensitivity(TextEditor::CaseSensitivity textEditorCaseSensitivity);
+
protected:
QList<AssistProposalItemInterface *> m_currentItems;
diff --git a/src/plugins/texteditor/codeassist/iassistprocessor.h b/src/plugins/texteditor/codeassist/iassistprocessor.h
index d2c618ac4b..a05c0bf826 100644
--- a/src/plugins/texteditor/codeassist/iassistprocessor.h
+++ b/src/plugins/texteditor/codeassist/iassistprocessor.h
@@ -31,7 +31,6 @@
namespace TextEditor {
-class IAssistProvider;
class AssistInterface;
class IAssistProposal;
diff --git a/src/plugins/texteditor/codeassist/iassistproposal.cpp b/src/plugins/texteditor/codeassist/iassistproposal.cpp
index 2880235ac2..fcbe2e8386 100644
--- a/src/plugins/texteditor/codeassist/iassistproposal.cpp
+++ b/src/plugins/texteditor/codeassist/iassistproposal.cpp
@@ -85,6 +85,11 @@ int IAssistProposal::basePosition() const
return m_basePosition;
}
+bool IAssistProposal::isFragile() const
+{
+ return m_isFragile;
+}
+
/*!
\fn bool TextEditor::IAssistProposal::isCorrective() const
@@ -110,6 +115,11 @@ void IAssistProposal::makeCorrection(TextEditorWidget *editorWidget)
Q_UNUSED(editorWidget);
}
+void IAssistProposal::setFragile(bool fragile)
+{
+ m_isFragile = fragile;
+}
+
/*!
\fn IAssistModel *TextEditor::IAssistProposal::model() const
diff --git a/src/plugins/texteditor/codeassist/iassistproposal.h b/src/plugins/texteditor/codeassist/iassistproposal.h
index 732fe9a468..4e93993dc2 100644
--- a/src/plugins/texteditor/codeassist/iassistproposal.h
+++ b/src/plugins/texteditor/codeassist/iassistproposal.h
@@ -42,15 +42,17 @@ public:
virtual ~IAssistProposal();
int basePosition() const;
+ bool isFragile() const;
virtual bool hasItemsToPropose(const QString &, AssistReason) const { return true; }
- virtual bool isFragile() const = 0;
virtual bool isCorrective(TextEditorWidget *editorWidget) const;
virtual void makeCorrection(TextEditorWidget *editorWidget);
virtual IAssistProposalModel *model() const = 0;
virtual IAssistProposalWidget *createWidget() const = 0;
+ void setFragile(bool fragile);
protected:
int m_basePosition;
+ bool m_isFragile = false;
};
} // TextEditor
diff --git a/src/plugins/texteditor/codeassist/iassistproposalmodel.h b/src/plugins/texteditor/codeassist/iassistproposalmodel.h
index 7519636393..fdb6289ce1 100644
--- a/src/plugins/texteditor/codeassist/iassistproposalmodel.h
+++ b/src/plugins/texteditor/codeassist/iassistproposalmodel.h
@@ -31,7 +31,6 @@ QT_FORWARD_DECLARE_CLASS(QString)
namespace TextEditor {
-class AssistProposalItem;
class TEXTEDITOR_EXPORT IAssistProposalModel
{
diff --git a/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp b/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp
index 6e3d7d34e0..4be7453bd0 100644
--- a/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp
+++ b/src/plugins/texteditor/codeassist/iassistproposalwidget.cpp
@@ -55,6 +55,16 @@ IAssistProposalWidget::IAssistProposalWidget()
IAssistProposalWidget::~IAssistProposalWidget()
{}
+int IAssistProposalWidget::basePosition() const
+{
+ return m_basePosition;
+}
+
+void IAssistProposalWidget::setBasePosition(int basePosition)
+{
+ m_basePosition = basePosition;
+}
+
/*!
\fn void TextEditor::IAssistProposalWidget::setAssistant(CodeAssistant *assistant)
diff --git a/src/plugins/texteditor/codeassist/iassistproposalwidget.h b/src/plugins/texteditor/codeassist/iassistproposalwidget.h
index 2f2f6e8bf6..fd86bb5722 100644
--- a/src/plugins/texteditor/codeassist/iassistproposalwidget.h
+++ b/src/plugins/texteditor/codeassist/iassistproposalwidget.h
@@ -57,10 +57,16 @@ public:
virtual void updateProposal(const QString &prefix) = 0;
virtual void closeProposal() = 0;
+ int basePosition() const;
+ void setBasePosition(int basePosition);
+
signals:
void prefixExpanded(const QString &newPrefix);
void proposalItemActivated(AssistProposalItemInterface *proposalItem);
void explicitlyAborted();
+
+protected:
+ int m_basePosition = -1;
};
} // TextEditor
diff --git a/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.cpp b/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.cpp
index 2a28dfc5a1..f1685c58d6 100644
--- a/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.cpp
+++ b/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.cpp
@@ -25,6 +25,8 @@
#include "ifunctionhintproposalmodel.h"
+#include <QString>
+
using namespace TextEditor;
IFunctionHintProposalModel::IFunctionHintProposalModel()
@@ -32,3 +34,8 @@ IFunctionHintProposalModel::IFunctionHintProposalModel()
IFunctionHintProposalModel::~IFunctionHintProposalModel()
{}
+
+QString IFunctionHintProposalModel::id(int /*index*/) const
+{
+ return QString();
+}
diff --git a/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.h b/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.h
index 1af6bf1219..fe329e7c82 100644
--- a/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.h
+++ b/src/plugins/texteditor/codeassist/ifunctionhintproposalmodel.h
@@ -29,6 +29,8 @@
#include <texteditor/texteditor_global.h>
+QT_FORWARD_DECLARE_CLASS(QString);
+
namespace TextEditor {
class TEXTEDITOR_EXPORT IFunctionHintProposalModel : public IAssistProposalModel
@@ -38,6 +40,7 @@ public:
~IFunctionHintProposalModel();
virtual int activeArgument(const QString &prefix) const = 0;
+ virtual QString id(int index) const;
};
} // TextEditor
diff --git a/src/plugins/texteditor/codeassist/runner.cpp b/src/plugins/texteditor/codeassist/runner.cpp
index d801a59341..2306ecd328 100644
--- a/src/plugins/texteditor/codeassist/runner.cpp
+++ b/src/plugins/texteditor/codeassist/runner.cpp
@@ -33,10 +33,6 @@ using namespace TextEditor;
using namespace Internal;
ProcessorRunner::ProcessorRunner()
- : m_processor(0)
- , m_interface(0)
- , m_discardProposal(false)
- , m_proposal(0)
{}
ProcessorRunner::~ProcessorRunner()
diff --git a/src/plugins/texteditor/codeassist/runner.h b/src/plugins/texteditor/codeassist/runner.h
index 6dcdf5e0e4..48ede43753 100644
--- a/src/plugins/texteditor/codeassist/runner.h
+++ b/src/plugins/texteditor/codeassist/runner.h
@@ -54,11 +54,11 @@ public:
IAssistProposal *proposal() const;
private:
- IAssistProcessor *m_processor;
- AssistInterface *m_interface;
- bool m_discardProposal;
- IAssistProposal *m_proposal;
- AssistReason m_reason;
+ IAssistProcessor *m_processor = nullptr;
+ AssistInterface *m_interface = nullptr;
+ bool m_discardProposal = false;
+ IAssistProposal *m_proposal = nullptr;
+ AssistReason m_reason = IdleEditor;
};
} // Internal
diff --git a/src/plugins/texteditor/codestyleselectorwidget.h b/src/plugins/texteditor/codestyleselectorwidget.h
index 05ae0c41d8..f498ecacd7 100644
--- a/src/plugins/texteditor/codestyleselectorwidget.h
+++ b/src/plugins/texteditor/codestyleselectorwidget.h
@@ -29,14 +29,6 @@
#include <QWidget>
-QT_BEGIN_NAMESPACE
-class QHBoxLayout;
-class QComboBox;
-class QLabel;
-class QCheckBox;
-class QPushButton;
-QT_END_NAMESPACE
-
namespace TextEditor {
namespace Internal { namespace Ui { class CodeStyleSelectorWidget; } }
diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h
index ab8d93bad7..f5df340ebd 100644
--- a/src/plugins/texteditor/findinfiles.h
+++ b/src/plugins/texteditor/findinfiles.h
@@ -33,7 +33,7 @@
#include <QStringListModel>
QT_BEGIN_NAMESPACE
-class QLabel;
+class QComboBox;
class QStackedWidget;
QT_END_NAMESPACE
diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp
index 18d324a7e8..64d1209a7c 100644
--- a/src/plugins/texteditor/fontsettingspage.cpp
+++ b/src/plugins/texteditor/fontsettingspage.cpp
@@ -349,7 +349,7 @@ QWidget *FontSettingsPage::widget()
d_ptr->m_ui = new Ui::FontSettingsPage;
d_ptr->m_ui->setupUi(d_ptr->m_widget);
d_ptr->m_ui->colorSchemeGroupBox->setTitle(
- tr("Color Scheme for Qt Creator Theme \"%1\"")
+ tr("Color Scheme for Theme \"%1\"")
.arg(Utils::creatorTheme()->displayName()));
d_ptr->m_ui->schemeComboBox->setModel(d_ptr->m_schemeListModel);
diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp
index 0065239032..c9d83b6893 100644
--- a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp
@@ -352,7 +352,8 @@ void HighlightDefinitionHandler::keywordStarted(const QXmlAttributes &atts)
// Handle broken files. makefile.xml references an invalid list.
Core::MessageManager::write(
QCoreApplication::translate("GenericHighlighter",
- "Generic highlighter warning: ") + e.message());
+ "Generic highlighter warning: %1")
+ .arg(e.message()));
}
rule->setInsensitive(atts.value(kInsensitive));
ruleElementStarted(atts, QSharedPointer<Rule>(rule));
diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp
index b2a12fb02f..2902f09a63 100644
--- a/src/plugins/texteditor/generichighlighter/highlighter.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp
@@ -253,8 +253,9 @@ void Highlighter::highlightBlock(const QString &text)
} catch (const HighlighterException &e) {
Core::MessageManager::write(
QCoreApplication::translate("GenericHighlighter",
- "Generic highlighter error: ") + e.message(),
- Core::MessageManager::WithFocus);
+ "Generic highlighter error: %1")
+ .arg(e.message()),
+ Core::MessageManager::WithFocus);
m_isBroken = true;
}
}
diff --git a/src/plugins/texteditor/generichighlighter/manager.h b/src/plugins/texteditor/generichighlighter/manager.h
index 5b602d2e03..080e649e3a 100644
--- a/src/plugins/texteditor/generichighlighter/manager.h
+++ b/src/plugins/texteditor/generichighlighter/manager.h
@@ -38,7 +38,6 @@
QT_BEGIN_NAMESPACE
class QFileInfo;
-class QStringList;
class QIODevice;
template <class> class QFutureInterface;
QT_END_NAMESPACE
diff --git a/src/plugins/texteditor/generichighlighter/specificrules.h b/src/plugins/texteditor/generichighlighter/specificrules.h
index 674c3fbd7b..051ab81d26 100644
--- a/src/plugins/texteditor/generichighlighter/specificrules.h
+++ b/src/plugins/texteditor/generichighlighter/specificrules.h
@@ -107,14 +107,13 @@ private:
virtual void doReplaceExpressions(const QStringList &captures);
QString m_string;
- int m_length;
- Qt::CaseSensitivity m_caseSensitivity;
+ int m_length = 0;
+ Qt::CaseSensitivity m_caseSensitivity = Qt::CaseSensitive;
};
class RegExprRule : public DynamicRule
{
public:
- RegExprRule() : m_onlyBegin(false), m_isCached(false) {}
virtual ~RegExprRule() {}
void setPattern(const QString &pattern);
@@ -131,10 +130,10 @@ private:
bool isExactMatch(ProgressData *progress);
- bool m_onlyBegin;
- bool m_isCached;
- int m_offset;
- int m_length;
+ bool m_onlyBegin = false;
+ bool m_isCached = false;
+ int m_offset = 0;
+ int m_length = 0;
QStringList m_captures;
QRegExp m_expression;
};
diff --git a/src/plugins/texteditor/helpitem.h b/src/plugins/texteditor/helpitem.h
index f7ea8ee4f3..2618f7f5e4 100644
--- a/src/plugins/texteditor/helpitem.h
+++ b/src/plugins/texteditor/helpitem.h
@@ -75,7 +75,7 @@ private:
private:
QString m_helpId;
QString m_docMark;
- Category m_category;
+ Category m_category = Unknown;
mutable QMap<QString, QUrl> m_helpLinks; // cached help links
};
diff --git a/src/plugins/texteditor/icodestylepreferencesfactory.h b/src/plugins/texteditor/icodestylepreferencesfactory.h
index 0e9b1b8d8f..f9d534376f 100644
--- a/src/plugins/texteditor/icodestylepreferencesfactory.h
+++ b/src/plugins/texteditor/icodestylepreferencesfactory.h
@@ -33,7 +33,6 @@ namespace Core { class Id; }
namespace TextEditor {
class ICodeStylePreferences;
-class CodeStylePool;
class Indenter;
class SnippetProvider;
diff --git a/src/plugins/texteditor/linenumberfilter.h b/src/plugins/texteditor/linenumberfilter.h
index de35e95696..6643e218f0 100644
--- a/src/plugins/texteditor/linenumberfilter.h
+++ b/src/plugins/texteditor/linenumberfilter.h
@@ -51,7 +51,7 @@ public:
void refresh(QFutureInterface<void> &) override {}
private:
- bool m_hasCurrentEditor;
+ bool m_hasCurrentEditor = false;
};
} // namespace Internal
diff --git a/src/plugins/texteditor/outlinefactory.cpp b/src/plugins/texteditor/outlinefactory.cpp
index 31eeabde17..0b04789099 100644
--- a/src/plugins/texteditor/outlinefactory.cpp
+++ b/src/plugins/texteditor/outlinefactory.cpp
@@ -62,7 +62,11 @@ OutlineWidgetStack::OutlineWidgetStack(OutlineFactory *factory) :
connect(m_toggleSync, &QAbstractButton::clicked,
this, &OutlineWidgetStack::toggleCursorSynchronization);
- m_filterButton = new QToolButton;
+ m_filterButton = new QToolButton(this);
+ // The ToolButton needs a parent because updateFilterMenu() sets
+ // it visible. That would open a top-level window if the button
+ // did not have a parent in that moment.
+
m_filterButton->setIcon(Utils::Icons::FILTER.icon());
m_filterButton->setToolTip(tr("Filter tree"));
m_filterButton->setPopupMode(QToolButton::InstantPopup);
diff --git a/src/plugins/texteditor/semantichighlighter.h b/src/plugins/texteditor/semantichighlighter.h
index 1ffc03d76a..f57b037957 100644
--- a/src/plugins/texteditor/semantichighlighter.h
+++ b/src/plugins/texteditor/semantichighlighter.h
@@ -33,10 +33,6 @@
#include <QFuture>
#include <QTextCharFormat>
-QT_BEGIN_NAMESPACE
-class QTextDocument;
-QT_END_NAMESPACE
-
namespace TextEditor {
class SyntaxHighlighter;
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index 7c53c81296..1bb79b9e83 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -25,7 +25,6 @@
#include "textdocument.h"
-#include "convenience.h"
#include "extraencodingsettings.h"
#include "fontsettings.h"
#include "indenter.h"
@@ -39,6 +38,7 @@
#include <texteditor/generichighlighter/highlighter.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/documentmodel.h>
+#include <utils/textutils.h>
#include <utils/guard.h>
#include <utils/mimetypes/mimedatabase.h>
@@ -303,7 +303,7 @@ QString TextDocument::plainText() const
QString TextDocument::textAt(int pos, int length) const
{
- return Convenience::textAt(QTextCursor(document()), pos, length);
+ return Utils::Text::textAt(QTextCursor(document()), pos, length);
}
QChar TextDocument::characterAt(int pos) const
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 40971354f4..0fe63bbc95 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -37,7 +37,6 @@
#include "circularclipboardassist.h"
#include "codecselector.h"
#include "completionsettings.h"
-#include "convenience.h"
#include "highlighterutils.h"
#include "icodestylepreferences.h"
#include "indenter.h"
@@ -77,6 +76,7 @@
#include <coreplugin/find/highlightscrollbar.h>
#include <utils/algorithm.h>
#include <utils/asconst.h>
+#include <utils/textutils.h>
#include <utils/linecolumnlabel.h>
#include <utils/fileutils.h>
#include <utils/dropsupport.h>
@@ -154,6 +154,7 @@ namespace Internal {
enum { NExtraSelectionKinds = 12 };
typedef QString (TransformationMethod)(const QString &);
+typedef void (ListTransformationMethod)(QStringList &);
static QString QString_toUpper(const QString &str)
{
@@ -247,7 +248,7 @@ class BaseTextEditorPrivate
public:
BaseTextEditorPrivate() {}
- TextEditorFactoryPrivate *m_origin;
+ TextEditorFactoryPrivate *m_origin = nullptr;
};
class HoverHandlerRunner
@@ -266,7 +267,7 @@ public:
// Does the last handler still applies?
const int documentRevision = textCursor.document()->revision();
- const int position = Convenience::wordStartCursor(textCursor).position();
+ const int position = Text::wordStartCursor(textCursor).position();
if (m_lastHandlerInfo.applies(documentRevision, position)) {
m_lastHandlerInfo.handler->showToolTip(m_widget, point, /*decorate=*/ false);
return;
@@ -419,6 +420,8 @@ public:
void transformSelection(TransformationMethod method);
void transformBlockSelection(TransformationMethod method);
+ void transformSelectedLines(ListTransformationMethod method);
+
void slotUpdateExtraAreaWidth();
void slotUpdateRequest(const QRect &r, int dy);
void slotUpdateBlockNotify(const QTextBlock &);
@@ -565,7 +568,7 @@ public:
void disableBlockSelection(BlockSelectionUpdateKind kind);
void resetCursorFlashTimer();
QBasicTimer m_cursorFlashTimer;
- bool m_cursorVisible;
+ bool m_cursorVisible = true;
bool m_moveLineUndoHack = false;
QTextCursor m_findScopeStart;
@@ -1159,19 +1162,37 @@ void TextEditorWidgetPrivate::updateCannotDecodeInfo()
}
}
+// Skip over shebang to license header (Python, Perl, sh)
+// '#!/bin/sh'
+// ''
+// '###############'
+
+static QTextBlock skipShebang(const QTextBlock &block)
+{
+ if (!block.isValid() || !block.text().startsWith("#!"))
+ return block;
+ const QTextBlock nextBlock1 = block.next();
+ if (!nextBlock1.isValid() || !nextBlock1.text().isEmpty())
+ return block;
+ const QTextBlock nextBlock2 = nextBlock1.next();
+ return nextBlock2.isValid() && nextBlock2.text().startsWith('#') ? nextBlock2 : block;
+}
+
/*
- Collapses the first comment in a file, if there is only whitespace above
+ Collapses the first comment in a file, if there is only whitespace/shebang line
+ above
*/
void TextEditorWidgetPrivate::foldLicenseHeader()
{
QTextDocument *doc = q->document();
TextDocumentLayout *documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
QTC_ASSERT(documentLayout, return);
- QTextBlock block = doc->firstBlock();
+ QTextBlock block = skipShebang(doc->firstBlock());
while (block.isValid() && block.isVisible()) {
QString text = block.text();
if (TextDocumentLayout::canFold(block) && block.next().isVisible()) {
- if (text.trimmed().startsWith(QLatin1String("/*"))) {
+ const QString trimmedText = text.trimmed();
+ if (trimmedText.startsWith("/*") || trimmedText.startsWith('#')) {
TextDocumentLayout::doFoldOrUnfold(block, false);
moveCursorVisible();
documentLayout->requestUpdate();
@@ -1432,7 +1453,7 @@ bool TextEditorWidget::selectBlockUp()
if (!TextBlockUserData::findNextClosingParenthesis(&cursor, true))
return false;
- setTextCursor(Convenience::flippedCursor(cursor));
+ setTextCursor(Text::flippedCursor(cursor));
d->_q_matchParentheses();
return true;
}
@@ -1457,7 +1478,7 @@ bool TextEditorWidget::selectBlockDown()
if ( cursor != d->m_selectBlockAnchor)
TextBlockUserData::findNextClosingParenthesis(&cursor, true);
- setTextCursor(Convenience::flippedCursor(cursor));
+ setTextCursor(Text::flippedCursor(cursor));
d->_q_matchParentheses();
return true;
}
@@ -1621,6 +1642,11 @@ void TextEditorWidget::lowercaseSelection()
d->transformSelection(&QString_toLower);
}
+void TextEditorWidget::sortSelectedLines()
+{
+ d->transformSelectedLines([](QStringList &list) { list.sort(); });
+}
+
void TextEditorWidget::indent()
{
int offset = 0;
@@ -2781,7 +2807,7 @@ QRect TextEditorWidget::cursorRect(int pos) const
void TextEditorWidget::convertPosition(int pos, int *line, int *column) const
{
- Convenience::convertPosition(document(), pos, line, column);
+ Text::convertPosition(document(), pos, line, column);
}
bool TextEditorWidget::event(QEvent *e)
@@ -7897,6 +7923,41 @@ void TextEditorWidgetPrivate::transformBlockSelection(TransformationMethod metho
enableBlockSelection(positionBlock, anchorColumn, anchorBlock, positionColumn);
}
+void TextEditorWidgetPrivate::transformSelectedLines(ListTransformationMethod method)
+{
+ if (!method || q->hasBlockSelection())
+ return;
+
+ QTextCursor cursor = q->textCursor();
+ if (!cursor.hasSelection())
+ return;
+
+ const bool downwardDirection = cursor.anchor() < cursor.position();
+ int startPosition = cursor.selectionStart();
+ int endPosition = cursor.selectionEnd();
+
+ cursor.setPosition(startPosition);
+ cursor.movePosition(QTextCursor::StartOfBlock);
+ startPosition = cursor.position();
+
+ cursor.setPosition(endPosition, QTextCursor::KeepAnchor);
+ if (cursor.positionInBlock() == 0)
+ cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+ endPosition = qMax(cursor.position(), endPosition);
+
+ const QString text = cursor.selectedText();
+ QStringList lines = text.split(QChar::ParagraphSeparator);
+ method(lines);
+ cursor.insertText(lines.join(QChar::ParagraphSeparator));
+
+ // (re)select the changed lines
+ // Note: this assumes the transformation did not change the length
+ cursor.setPosition(downwardDirection ? startPosition : endPosition);
+ cursor.setPosition(downwardDirection ? endPosition : startPosition, QTextCursor::KeepAnchor);
+ q->setTextCursor(cursor);
+}
+
void TextEditorWidget::inSnippetMode(bool *active)
{
*active = d->m_snippetOverlay->isVisible();
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index f6fb864404..b2f3d0a9fa 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -52,11 +52,9 @@ QT_END_NAMESPACE
namespace TextEditor {
class TextDocument;
class BaseHoverHandler;
-class TabSettings;
class RefactorOverlay;
struct RefactorMarker;
class SyntaxHighlighter;
-class IAssistMonitorInterface;
class AssistInterface;
class IAssistProvider;
class ICodeStylePreferences;
@@ -423,6 +421,8 @@ public:
void uppercaseSelection();
void lowercaseSelection();
+ void sortSelectedLines();
+
void cleanWhitespace();
void indent();
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index 1ef00e0517..d83d165443 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -77,7 +77,6 @@ SOURCES += texteditorplugin.cpp \
snippets/snippetassistcollector.cpp \
codeassist/assistinterface.cpp \
codeassist/assistproposalitem.cpp \
- convenience.cpp \
codeassist/runner.cpp \
codeassist/completionassistprovider.cpp \
codeassist/genericproposalmodel.cpp \
@@ -187,7 +186,6 @@ HEADERS += texteditorplugin.h \
snippets/snippetassistcollector.h \
codeassist/assistinterface.h \
codeassist/assistproposalitem.h \
- convenience.h \
codeassist/assistenums.h \
codeassist/runner.h \
codeassist/assistproposaliteminterface.h \
diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs
index 2b5f43e247..1dfbde68a8 100644
--- a/src/plugins/texteditor/texteditor.qbs
+++ b/src/plugins/texteditor/texteditor.qbs
@@ -58,8 +58,6 @@ Project {
"completionsettingspage.cpp",
"completionsettingspage.h",
"completionsettingspage.ui",
- "convenience.cpp",
- "convenience.h",
"displaysettings.cpp",
"displaysettings.h",
"displaysettingspage.cpp",
diff --git a/src/plugins/texteditor/texteditor_p.h b/src/plugins/texteditor/texteditor_p.h
index ec2ad4ab7f..09a9cf2a12 100644
--- a/src/plugins/texteditor/texteditor_p.h
+++ b/src/plugins/texteditor/texteditor_p.h
@@ -35,8 +35,6 @@ namespace TextEditor {
class TextDocument;
namespace Internal {
-class TextEditorOverlay;
-class ClipboardAssistProvider;
class TEXTEDITOR_EXPORT TextBlockSelection
{
diff --git a/src/plugins/texteditor/texteditor_test.cpp b/src/plugins/texteditor/texteditor_test.cpp
index c5e81ec3af..78b8564e43 100644
--- a/src/plugins/texteditor/texteditor_test.cpp
+++ b/src/plugins/texteditor/texteditor_test.cpp
@@ -44,10 +44,10 @@ enum TransFormationType { Uppercase, Lowercase };
struct TestBlockSelection
{
- int positionBlock;
- int positionColumn;
- int anchorBlock;
- int anchorColumn;
+ int positionBlock = 0;
+ int positionColumn = 0;
+ int anchorBlock = 0;
+ int anchorColumn = 0;
TestBlockSelection(int positionBlock, int positionColumn, int anchorBlock, int anchorColumn)
: positionBlock(positionBlock), positionColumn(positionColumn)
, anchorBlock(anchorBlock), anchorColumn(anchorColumn) {}
diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp
index cb2515acec..be12984f67 100644
--- a/src/plugins/texteditor/texteditoractionhandler.cpp
+++ b/src/plugins/texteditor/texteditoractionhandler.cpp
@@ -176,6 +176,7 @@ public:
QAction *m_insertLineBelowAction = nullptr;
QAction *m_upperCaseSelectionAction = nullptr;
QAction *m_lowerCaseSelectionAction = nullptr;
+ QAction *m_sortSelectedLinesAction = nullptr;
QAction *m_indentAction = nullptr;
QAction *m_unindentAction = nullptr;
QAction *m_followSymbolAction = nullptr;
@@ -214,18 +215,18 @@ void TextEditorActionHandlerPrivate::createActions()
using namespace TextEditor::Constants;
m_undoAction = registerAction(UNDO,
- [this] (TextEditorWidget *w) { w->undo(); }, true, tr("&Undo"));
+ [] (TextEditorWidget *w) { w->undo(); }, true, tr("&Undo"));
m_redoAction = registerAction(REDO,
- [this] (TextEditorWidget *w) { w->redo(); }, true, tr("&Redo"));
+ [] (TextEditorWidget *w) { w->redo(); }, true, tr("&Redo"));
m_copyAction = registerAction(COPY,
- [this] (TextEditorWidget *w) { w->copy(); }, true);
+ [] (TextEditorWidget *w) { w->copy(); }, true);
m_cutAction = registerAction(CUT,
- [this] (TextEditorWidget *w) { w->cut(); }, true);
+ [] (TextEditorWidget *w) { w->cut(); }, true);
m_pasteAction = registerAction(PASTE,
- [this] (TextEditorWidget *w) { w->paste(); }, true);
+ [] (TextEditorWidget *w) { w->paste(); }, true);
m_selectAllAction = registerAction(SELECTALL,
- [this] (TextEditorWidget *w) { w->selectAll(); }, true);
- m_gotoAction = registerAction(GOTO, [this] (TextEditorWidget *) {
+ [] (TextEditorWidget *w) { w->selectAll(); }, true);
+ m_gotoAction = registerAction(GOTO, [] (TextEditorWidget *) {
QString locatorString = TextEditorPlugin::lineNumberFilter()->shortcutString();
locatorString += QLatin1Char(' ');
const int selectionStart = locatorString.size();
@@ -233,101 +234,101 @@ void TextEditorActionHandlerPrivate::createActions()
Core::LocatorManager::show(locatorString, selectionStart, locatorString.size() - selectionStart);
});
m_printAction = registerAction(PRINT,
- [this] (TextEditorWidget *widget) { widget->print(Core::ICore::printer()); });
+ [] (TextEditorWidget *widget) { widget->print(Core::ICore::printer()); });
m_deleteLineAction = registerAction(DELETE_LINE,
- [this] (TextEditorWidget *w) { w->deleteLine(); }, true, tr("Delete &Line"));
+ [] (TextEditorWidget *w) { w->deleteLine(); }, true, tr("Delete &Line"));
m_deleteEndOfLineAction = registerAction(DELETE_END_OF_LINE,
- [this] (TextEditorWidget *w) { w->deleteEndOfLine(); }, true, tr("Delete Line from Cursor On"));
+ [] (TextEditorWidget *w) { w->deleteEndOfLine(); }, true, tr("Delete Line from Cursor On"));
m_deleteEndOfWordAction = registerAction(DELETE_END_OF_WORD,
- [this] (TextEditorWidget *w) { w->deleteEndOfWord(); }, true, tr("Delete Word from Cursor On"));
+ [] (TextEditorWidget *w) { w->deleteEndOfWord(); }, true, tr("Delete Word from Cursor On"));
m_deleteEndOfWordCamelCaseAction = registerAction(DELETE_END_OF_WORD_CAMEL_CASE,
- [this] (TextEditorWidget *w) { w->deleteEndOfWordCamelCase(); }, true, tr("Delete Word Camel Case from Cursor On"));
+ [] (TextEditorWidget *w) { w->deleteEndOfWordCamelCase(); }, true, tr("Delete Word Camel Case from Cursor On"));
m_deleteStartOfLineAction = registerAction(DELETE_START_OF_LINE,
- [this] (TextEditorWidget *w) { w->deleteStartOfLine(); }, true, tr("Delete Line up to Cursor"));
+ [] (TextEditorWidget *w) { w->deleteStartOfLine(); }, true, tr("Delete Line up to Cursor"));
m_deleteStartOfWordAction = registerAction(DELETE_START_OF_WORD,
- [this] (TextEditorWidget *w) { w->deleteStartOfWord(); }, true, tr("Delete Word up to Cursor"));
+ [] (TextEditorWidget *w) { w->deleteStartOfWord(); }, true, tr("Delete Word up to Cursor"));
m_deleteStartOfWordCamelCaseAction = registerAction(DELETE_START_OF_WORD_CAMEL_CASE,
- [this] (TextEditorWidget *w) { w->deleteStartOfWordCamelCase(); }, true, tr("Delete Word Camel Case up to Cursor"));
+ [] (TextEditorWidget *w) { w->deleteStartOfWordCamelCase(); }, true, tr("Delete Word Camel Case up to Cursor"));
m_gotoBlockStartWithSelectionAction = registerAction(GOTO_BLOCK_START_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoBlockStartWithSelection(); }, true, tr("Go to Block Start with Selection"),
+ [] (TextEditorWidget *w) { w->gotoBlockStartWithSelection(); }, true, tr("Go to Block Start with Selection"),
QKeySequence(tr("Ctrl+{")));
m_gotoBlockEndWithSelectionAction = registerAction(GOTO_BLOCK_END_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoBlockEndWithSelection(); }, true, tr("Go to Block End with Selection"),
+ [] (TextEditorWidget *w) { w->gotoBlockEndWithSelection(); }, true, tr("Go to Block End with Selection"),
QKeySequence(tr("Ctrl+}")));
m_moveLineUpAction = registerAction(MOVE_LINE_UP,
- [this] (TextEditorWidget *w) { w->moveLineUp(); }, true, tr("Move Line Up"),
+ [] (TextEditorWidget *w) { w->moveLineUp(); }, true, tr("Move Line Up"),
QKeySequence(tr("Ctrl+Shift+Up")));
m_moveLineDownAction = registerAction(MOVE_LINE_DOWN,
- [this] (TextEditorWidget *w) { w->moveLineDown(); }, true, tr("Move Line Down"),
+ [] (TextEditorWidget *w) { w->moveLineDown(); }, true, tr("Move Line Down"),
QKeySequence(tr("Ctrl+Shift+Down")));
m_copyLineUpAction = registerAction(COPY_LINE_UP,
- [this] (TextEditorWidget *w) { w->copyLineUp(); }, true, tr("Copy Line Up"),
+ [] (TextEditorWidget *w) { w->copyLineUp(); }, true, tr("Copy Line Up"),
QKeySequence(tr("Ctrl+Alt+Up")));
m_copyLineDownAction = registerAction(COPY_LINE_DOWN,
- [this] (TextEditorWidget *w) { w->copyLineDown(); }, true, tr("Copy Line Down"),
+ [] (TextEditorWidget *w) { w->copyLineDown(); }, true, tr("Copy Line Down"),
QKeySequence(tr("Ctrl+Alt+Down")));
m_joinLinesAction = registerAction(JOIN_LINES,
- [this] (TextEditorWidget *w) { w->joinLines(); }, true, tr("Join Lines"),
+ [] (TextEditorWidget *w) { w->joinLines(); }, true, tr("Join Lines"),
QKeySequence(tr("Ctrl+J")));
m_insertLineAboveAction = registerAction(INSERT_LINE_ABOVE,
- [this] (TextEditorWidget *w) { w->insertLineAbove(); }, true, tr("Insert Line Above Current Line"),
+ [] (TextEditorWidget *w) { w->insertLineAbove(); }, true, tr("Insert Line Above Current Line"),
QKeySequence(tr("Ctrl+Shift+Return")));
m_insertLineBelowAction = registerAction(INSERT_LINE_BELOW,
- [this] (TextEditorWidget *w) { w->insertLineBelow(); }, true, tr("Insert Line Below Current Line"),
+ [] (TextEditorWidget *w) { w->insertLineBelow(); }, true, tr("Insert Line Below Current Line"),
QKeySequence(tr("Ctrl+Return")));
m_switchUtf8bomAction = registerAction(SWITCH_UTF8BOM,
- [this] (TextEditorWidget *w) { w->switchUtf8bom(); }, true, tr("Toggle UTF-8 BOM"));
+ [] (TextEditorWidget *w) { w->switchUtf8bom(); }, true, tr("Toggle UTF-8 BOM"));
m_indentAction = registerAction(INDENT,
- [this] (TextEditorWidget *w) { w->indent(); }, true, tr("Indent"));
+ [] (TextEditorWidget *w) { w->indent(); }, true, tr("Indent"));
m_unindentAction = registerAction(UNINDENT,
- [this] (TextEditorWidget *w) { w->unindent(); }, true, tr("Unindent"));
+ [] (TextEditorWidget *w) { w->unindent(); }, true, tr("Unindent"));
m_followSymbolAction = registerAction(FOLLOW_SYMBOL_UNDER_CURSOR,
- [this] (TextEditorWidget *w) { w->openLinkUnderCursor(); }, true, tr("Follow Symbol Under Cursor"),
+ [] (TextEditorWidget *w) { w->openLinkUnderCursor(); }, true, tr("Follow Symbol Under Cursor"),
QKeySequence(Qt::Key_F2));
m_followSymbolInNextSplitAction = registerAction(FOLLOW_SYMBOL_UNDER_CURSOR_IN_NEXT_SPLIT,
- [this] (TextEditorWidget *w) { w->openLinkUnderCursorInNextSplit(); }, true, tr("Follow Symbol Under Cursor in Next Split"),
+ [] (TextEditorWidget *w) { w->openLinkUnderCursorInNextSplit(); }, true, tr("Follow Symbol Under Cursor in Next Split"),
QKeySequence(Utils::HostOsInfo::isMacHost() ? tr("Meta+E, F2") : tr("Ctrl+E, F2")));
m_jumpToFileAction = registerAction(JUMP_TO_FILE_UNDER_CURSOR,
- [this] (TextEditorWidget *w) { w->openLinkUnderCursor(); }, true, tr("Jump to File Under Cursor"),
+ [] (TextEditorWidget *w) { w->openLinkUnderCursor(); }, true, tr("Jump to File Under Cursor"),
QKeySequence(Qt::Key_F2));
m_jumpToFileInNextSplitAction = registerAction(JUMP_TO_FILE_UNDER_CURSOR_IN_NEXT_SPLIT,
- [this] (TextEditorWidget *w) { w->openLinkUnderCursorInNextSplit(); }, true, tr("Jump to File Under Cursor in Next Split"),
+ [] (TextEditorWidget *w) { w->openLinkUnderCursorInNextSplit(); }, true, tr("Jump to File Under Cursor in Next Split"),
QKeySequence(Utils::HostOsInfo::isMacHost() ? tr("Meta+E, F2") : tr("Ctrl+E, F2")).toString());
m_viewPageUpAction = registerAction(VIEW_PAGE_UP,
- [this] (TextEditorWidget *w) { w->viewPageUp(); }, true, tr("Move the View a Page Up and Keep the Cursor Position"),
+ [] (TextEditorWidget *w) { w->viewPageUp(); }, true, tr("Move the View a Page Up and Keep the Cursor Position"),
QKeySequence(tr("Ctrl+PgUp")));
m_viewPageDownAction = registerAction(VIEW_PAGE_DOWN,
- [this] (TextEditorWidget *w) { w->viewPageDown(); }, true, tr("Move the View a Page Down and Keep the Cursor Position"),
+ [] (TextEditorWidget *w) { w->viewPageDown(); }, true, tr("Move the View a Page Down and Keep the Cursor Position"),
QKeySequence(tr("Ctrl+PgDown")));
m_viewLineUpAction = registerAction(VIEW_LINE_UP,
- [this] (TextEditorWidget *w) { w->viewLineUp(); }, true, tr("Move the View a Line Up and Keep the Cursor Position"),
+ [] (TextEditorWidget *w) { w->viewLineUp(); }, true, tr("Move the View a Line Up and Keep the Cursor Position"),
QKeySequence(tr("Ctrl+Up")));
m_viewLineDownAction = registerAction(VIEW_LINE_DOWN,
- [this] (TextEditorWidget *w) { w->viewLineDown(); }, true, tr("Move the View a Line Down and Keep the Cursor Position"),
+ [] (TextEditorWidget *w) { w->viewLineDown(); }, true, tr("Move the View a Line Down and Keep the Cursor Position"),
QKeySequence(tr("Ctrl+Down")));
// register "Edit" Menu Actions
Core::ActionContainer *editMenu = Core::ActionManager::actionContainer(M_EDIT);
m_selectEncodingAction = registerAction(SELECT_ENCODING,
- [this] (TextEditorWidget *w) { w->selectEncoding(); }, false, tr("Select Encoding..."),
+ [] (TextEditorWidget *w) { w->selectEncoding(); }, false, tr("Select Encoding..."),
QKeySequence(), G_EDIT_OTHER, editMenu);
m_circularPasteAction = registerAction(CIRCULAR_PASTE,
- [this] (TextEditorWidget *w) { w->circularPaste(); }, false, tr("Paste from Clipboard History"),
+ [] (TextEditorWidget *w) { w->circularPaste(); }, false, tr("Paste from Clipboard History"),
QKeySequence(tr("Ctrl+Shift+V")), G_EDIT_COPYPASTE, editMenu);
// register "Edit -> Advanced" Menu Actions
Core::ActionContainer *advancedEditMenu = Core::ActionManager::actionContainer(M_EDIT_ADVANCED);
m_formatAction = registerAction(AUTO_INDENT_SELECTION,
- [this] (TextEditorWidget *w) { w->format(); }, true, tr("Auto-&indent Selection"),
+ [] (TextEditorWidget *w) { w->format(); }, true, tr("Auto-&indent Selection"),
QKeySequence(tr("Ctrl+I")),
G_EDIT_FORMAT, advancedEditMenu);
m_rewrapParagraphAction = registerAction(REWRAP_PARAGRAPH,
- [this] (TextEditorWidget *w) { w->rewrapParagraph(); }, true, tr("&Rewrap Paragraph"),
+ [] (TextEditorWidget *w) { w->rewrapParagraph(); }, true, tr("&Rewrap Paragraph"),
QKeySequence(Core::UseMacShortcuts ? tr("Meta+E, R") : tr("Ctrl+E, R")),
G_EDIT_FORMAT, advancedEditMenu);
m_visualizeWhitespaceAction = registerBoolAction(VISUALIZE_WHITESPACE,
- [this] (TextEditorWidget *widget, bool checked) {
+ [] (TextEditorWidget *widget, bool checked) {
if (widget) {
DisplaySettings ds = widget->displaySettings();
ds.m_visualizeWhitespace = checked;
@@ -339,11 +340,11 @@ void TextEditorActionHandlerPrivate::createActions()
G_EDIT_FORMAT, advancedEditMenu);
m_visualizeWhitespaceAction->setCheckable(true);
m_cleanWhitespaceAction = registerAction(CLEAN_WHITESPACE,
- [this] (TextEditorWidget *w) { w->cleanWhitespace(); }, true, tr("Clean Whitespace"),
+ [] (TextEditorWidget *w) { w->cleanWhitespace(); }, true, tr("Clean Whitespace"),
QKeySequence(),
G_EDIT_FORMAT, advancedEditMenu);
m_textWrappingAction = registerBoolAction(TEXT_WRAPPING,
- [this] (TextEditorWidget *widget, bool checked) {
+ [] (TextEditorWidget *widget, bool checked) {
if (widget) {
DisplaySettings ds = widget->displaySettings();
ds.m_textWrapping = checked;
@@ -355,120 +356,124 @@ void TextEditorActionHandlerPrivate::createActions()
G_EDIT_FORMAT, advancedEditMenu);
m_textWrappingAction->setCheckable(true);
m_unCommentSelectionAction = registerAction(UN_COMMENT_SELECTION,
- [this] (TextEditorWidget *w) { w->unCommentSelection(); }, true, tr("Toggle Comment &Selection"),
+ [] (TextEditorWidget *w) { w->unCommentSelection(); }, true, tr("Toggle Comment &Selection"),
QKeySequence(tr("Ctrl+/")),
G_EDIT_FORMAT, advancedEditMenu);
m_cutLineAction = registerAction(CUT_LINE,
- [this] (TextEditorWidget *w) { w->cutLine(); }, true, tr("Cut &Line"),
+ [] (TextEditorWidget *w) { w->cutLine(); }, true, tr("Cut &Line"),
QKeySequence(tr("Shift+Del")),
G_EDIT_TEXT, advancedEditMenu);
m_copyLineAction = registerAction(COPY_LINE,
- [this] (TextEditorWidget *w) { w->copyLine(); }, false, tr("Copy &Line"),
+ [] (TextEditorWidget *w) { w->copyLine(); }, false, tr("Copy &Line"),
QKeySequence(tr("Ctrl+Ins")),
G_EDIT_TEXT, advancedEditMenu);
m_duplicateSelectionAction = registerAction(DUPLICATE_SELECTION,
- [this] (TextEditorWidget *w) { w->duplicateSelection(); }, false, tr("&Duplicate Selection"),
+ [] (TextEditorWidget *w) { w->duplicateSelection(); }, false, tr("&Duplicate Selection"),
QKeySequence(),
G_EDIT_TEXT, advancedEditMenu);
m_duplicateSelectionAndCommentAction = registerAction(DUPLICATE_SELECTION_AND_COMMENT,
- [this] (TextEditorWidget *w) { w->duplicateSelectionAndComment(); }, false, tr("&Duplicate Selection and Comment"),
+ [] (TextEditorWidget *w) { w->duplicateSelectionAndComment(); }, false, tr("&Duplicate Selection and Comment"),
QKeySequence(),
G_EDIT_TEXT, advancedEditMenu);
m_upperCaseSelectionAction = registerAction(UPPERCASE_SELECTION,
- [this] (TextEditorWidget *w) { w->uppercaseSelection(); }, true, tr("Uppercase Selection"),
+ [] (TextEditorWidget *w) { w->uppercaseSelection(); }, true, tr("Uppercase Selection"),
QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+U") : tr("Alt+Shift+U")),
G_EDIT_TEXT, advancedEditMenu);
m_lowerCaseSelectionAction = registerAction(LOWERCASE_SELECTION,
- [this] (TextEditorWidget *w) { w->lowercaseSelection(); }, true, tr("Lowercase Selection"),
+ [] (TextEditorWidget *w) { w->lowercaseSelection(); }, true, tr("Lowercase Selection"),
QKeySequence(Core::UseMacShortcuts ? tr("Meta+U") : tr("Alt+U")),
G_EDIT_TEXT, advancedEditMenu);
+ m_sortSelectedLinesAction = registerAction(SORT_SELECTED_LINES,
+ [] (TextEditorWidget *w) { w->sortSelectedLines(); }, false, tr("&Sort Selected Lines"),
+ QKeySequence(Core::UseMacShortcuts ? tr("Meta+Shift+S") : tr("Alt+Shift+S")),
+ G_EDIT_TEXT, advancedEditMenu);
m_foldAction = registerAction(FOLD,
- [this] (TextEditorWidget *w) { w->fold(); }, true, tr("Fold"),
+ [] (TextEditorWidget *w) { w->fold(); }, true, tr("Fold"),
QKeySequence(tr("Ctrl+<")),
G_EDIT_COLLAPSING, advancedEditMenu);
m_unfoldAction = registerAction(UNFOLD,
- [this] (TextEditorWidget *w) { w->unfold(); }, true, tr("Unfold"),
+ [] (TextEditorWidget *w) { w->unfold(); }, true, tr("Unfold"),
QKeySequence(tr("Ctrl+>")),
G_EDIT_COLLAPSING, advancedEditMenu);
m_unfoldAllAction = registerAction(UNFOLD_ALL,
- [this] (TextEditorWidget *w) { w->unfoldAll(); }, true, tr("Toggle &Fold All"),
+ [] (TextEditorWidget *w) { w->unfoldAll(); }, true, tr("Toggle &Fold All"),
QKeySequence(),
G_EDIT_COLLAPSING, advancedEditMenu);
m_increaseFontSizeAction = registerAction(INCREASE_FONT_SIZE,
- [this] (TextEditorWidget *w) { w->zoomF(1.f); }, false, tr("Increase Font Size"),
+ [] (TextEditorWidget *w) { w->zoomF(1.f); }, false, tr("Increase Font Size"),
QKeySequence(tr("Ctrl++")),
G_EDIT_FONT, advancedEditMenu);
m_decreaseFontSizeAction = registerAction(DECREASE_FONT_SIZE,
- [this] (TextEditorWidget *w) { w->zoomF(-1.f); }, false, tr("Decrease Font Size"),
+ [] (TextEditorWidget *w) { w->zoomF(-1.f); }, false, tr("Decrease Font Size"),
QKeySequence(tr("Ctrl+-")),
G_EDIT_FONT, advancedEditMenu);
m_resetFontSizeAction = registerAction(RESET_FONT_SIZE,
- [this] (TextEditorWidget *w) { w->zoomReset(); }, false, tr("Reset Font Size"),
+ [] (TextEditorWidget *w) { w->zoomReset(); }, false, tr("Reset Font Size"),
QKeySequence(Core::UseMacShortcuts ? tr("Meta+0") : tr("Ctrl+0")),
G_EDIT_FONT, advancedEditMenu);
m_gotoBlockStartAction = registerAction(GOTO_BLOCK_START,
- [this] (TextEditorWidget *w) { w->gotoBlockStart(); }, true, tr("Go to Block Start"),
+ [] (TextEditorWidget *w) { w->gotoBlockStart(); }, true, tr("Go to Block Start"),
QKeySequence(tr("Ctrl+[")),
G_EDIT_BLOCKS, advancedEditMenu);
m_gotoBlockEndAction = registerAction(GOTO_BLOCK_END,
- [this] (TextEditorWidget *w) { w->gotoBlockEnd(); }, true, tr("Go to Block End"),
+ [] (TextEditorWidget *w) { w->gotoBlockEnd(); }, true, tr("Go to Block End"),
QKeySequence(tr("Ctrl+]")),
G_EDIT_BLOCKS, advancedEditMenu);
m_selectBlockUpAction = registerAction(SELECT_BLOCK_UP,
- [this] (TextEditorWidget *w) { w->selectBlockUp(); }, true, tr("Select Block Up"),
+ [] (TextEditorWidget *w) { w->selectBlockUp(); }, true, tr("Select Block Up"),
QKeySequence(tr("Ctrl+U")),
G_EDIT_BLOCKS, advancedEditMenu);
m_selectBlockDownAction = registerAction(SELECT_BLOCK_DOWN,
- [this] (TextEditorWidget *w) { w->selectBlockDown(); }, true, tr("Select Block Down"),
+ [] (TextEditorWidget *w) { w->selectBlockDown(); }, true, tr("Select Block Down"),
QKeySequence(tr("Ctrl+Shift+Alt+U")),
G_EDIT_BLOCKS, advancedEditMenu);
registerAction(SELECT_WORD_UNDER_CURSOR,
- [this] (TextEditorWidget *w) { w->selectWordUnderCursor(); }, true,
+ [] (TextEditorWidget *w) { w->selectWordUnderCursor(); }, true,
tr("Select Word Under Cursor"));
// register GOTO Actions
registerAction(GOTO_LINE_START,
- [this] (TextEditorWidget *w) { w->gotoLineStart(); }, true, tr("Go to Line Start"));
+ [] (TextEditorWidget *w) { w->gotoLineStart(); }, true, tr("Go to Line Start"));
registerAction(GOTO_LINE_END,
- [this] (TextEditorWidget *w) { w->gotoLineEnd(); }, true, tr("Go to Line End"));
+ [] (TextEditorWidget *w) { w->gotoLineEnd(); }, true, tr("Go to Line End"));
registerAction(GOTO_NEXT_LINE,
- [this] (TextEditorWidget *w) { w->gotoNextLine(); }, true, tr("Go to Next Line"));
+ [] (TextEditorWidget *w) { w->gotoNextLine(); }, true, tr("Go to Next Line"));
registerAction(GOTO_PREVIOUS_LINE,
- [this] (TextEditorWidget *w) { w->gotoPreviousLine(); }, true, tr("Go to Previous Line"));
+ [] (TextEditorWidget *w) { w->gotoPreviousLine(); }, true, tr("Go to Previous Line"));
registerAction(GOTO_PREVIOUS_CHARACTER,
- [this] (TextEditorWidget *w) { w->gotoPreviousCharacter(); }, true, tr("Go to Previous Character"));
+ [] (TextEditorWidget *w) { w->gotoPreviousCharacter(); }, true, tr("Go to Previous Character"));
registerAction(GOTO_NEXT_CHARACTER,
- [this] (TextEditorWidget *w) { w->gotoNextCharacter(); }, true, tr("Go to Next Character"));
+ [] (TextEditorWidget *w) { w->gotoNextCharacter(); }, true, tr("Go to Next Character"));
registerAction(GOTO_PREVIOUS_WORD,
- [this] (TextEditorWidget *w) { w->gotoPreviousWord(); }, true, tr("Go to Previous Word"));
+ [] (TextEditorWidget *w) { w->gotoPreviousWord(); }, true, tr("Go to Previous Word"));
registerAction(GOTO_NEXT_WORD,
- [this] (TextEditorWidget *w) { w->gotoNextWord(); }, true, tr("Go to Next Word"));
+ [] (TextEditorWidget *w) { w->gotoNextWord(); }, true, tr("Go to Next Word"));
registerAction(GOTO_PREVIOUS_WORD_CAMEL_CASE,
- [this] (TextEditorWidget *w) { w->gotoPreviousWordCamelCase(); }, false, tr("Go to Previous Word Camel Case"));
+ [] (TextEditorWidget *w) { w->gotoPreviousWordCamelCase(); }, false, tr("Go to Previous Word Camel Case"));
registerAction(GOTO_NEXT_WORD_CAMEL_CASE,
- [this] (TextEditorWidget *w) { w->gotoNextWordCamelCase(); }, false, tr("Go to Next Word Camel Case"));
+ [] (TextEditorWidget *w) { w->gotoNextWordCamelCase(); }, false, tr("Go to Next Word Camel Case"));
// register GOTO actions with selection
registerAction(GOTO_LINE_START_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoLineStartWithSelection(); }, true, tr("Go to Line Start with Selection"));
+ [] (TextEditorWidget *w) { w->gotoLineStartWithSelection(); }, true, tr("Go to Line Start with Selection"));
registerAction(GOTO_LINE_END_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoLineEndWithSelection(); }, true, tr("Go to Line End with Selection"));
+ [] (TextEditorWidget *w) { w->gotoLineEndWithSelection(); }, true, tr("Go to Line End with Selection"));
registerAction(GOTO_NEXT_LINE_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoNextLineWithSelection(); }, true, tr("Go to Next Line with Selection"));
+ [] (TextEditorWidget *w) { w->gotoNextLineWithSelection(); }, true, tr("Go to Next Line with Selection"));
registerAction(GOTO_PREVIOUS_LINE_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoPreviousLineWithSelection(); }, true, tr("Go to Previous Line with Selection"));
+ [] (TextEditorWidget *w) { w->gotoPreviousLineWithSelection(); }, true, tr("Go to Previous Line with Selection"));
registerAction(GOTO_PREVIOUS_CHARACTER_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoPreviousCharacterWithSelection(); }, true, tr("Go to Previous Character with Selection"));
+ [] (TextEditorWidget *w) { w->gotoPreviousCharacterWithSelection(); }, true, tr("Go to Previous Character with Selection"));
registerAction(GOTO_NEXT_CHARACTER_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoNextCharacterWithSelection(); }, true, tr("Go to Next Character with Selection"));
+ [] (TextEditorWidget *w) { w->gotoNextCharacterWithSelection(); }, true, tr("Go to Next Character with Selection"));
registerAction(GOTO_PREVIOUS_WORD_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoPreviousWordWithSelection(); }, true, tr("Go to Previous Word with Selection"));
+ [] (TextEditorWidget *w) { w->gotoPreviousWordWithSelection(); }, true, tr("Go to Previous Word with Selection"));
registerAction(GOTO_NEXT_WORD_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoNextWordWithSelection(); }, true, tr("Go to Next Word with Selection"));
+ [] (TextEditorWidget *w) { w->gotoNextWordWithSelection(); }, true, tr("Go to Next Word with Selection"));
registerAction(GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoPreviousWordCamelCaseWithSelection(); }, false, tr("Go to Previous Word Camel Case with Selection"));
+ [] (TextEditorWidget *w) { w->gotoPreviousWordCamelCaseWithSelection(); }, false, tr("Go to Previous Word Camel Case with Selection"));
registerAction(GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION,
- [this] (TextEditorWidget *w) { w->gotoNextWordCamelCaseWithSelection(); }, false, tr("Go to Next Word Camel Case with Selection"));
+ [] (TextEditorWidget *w) { w->gotoNextWordCamelCaseWithSelection(); }, false, tr("Go to Next Word Camel Case with Selection"));
// Collect all modifying actions so we can check for them inside a readonly file
// and disable them
@@ -500,6 +505,7 @@ void TextEditorActionHandlerPrivate::createActions()
m_modifyingActions << m_unCommentSelectionAction;
m_modifyingActions << m_unindentAction;
m_modifyingActions << m_upperCaseSelectionAction;
+ m_modifyingActions << m_sortSelectedLinesAction;
// set enabled state of optional actions
m_followSymbolAction->setEnabled(m_optionalActions & TextEditorActionHandler::FollowSymbolUnderCursor);
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index af56524362..8cf692d022 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -143,6 +143,7 @@ const char INSERT_LINE_ABOVE[] = "TextEditor.InsertLineAboveCurrentLine";
const char INSERT_LINE_BELOW[] = "TextEditor.InsertLineBelowCurrentLine";
const char UPPERCASE_SELECTION[] = "TextEditor.UppercaseSelection";
const char LOWERCASE_SELECTION[] = "TextEditor.LowercaseSelection";
+const char SORT_SELECTED_LINES[] = "TextEditor.SortSelectedLines";
const char CUT_LINE[] = "TextEditor.CutLine";
const char COPY_LINE[] = "TextEditor.CopyLine";
const char DUPLICATE_SELECTION[] = "TextEditor.DuplicateSelection";
diff --git a/src/plugins/texteditor/texteditorsettings.h b/src/plugins/texteditor/texteditorsettings.h
index 2c0ce20fab..656d585684 100644
--- a/src/plugins/texteditor/texteditorsettings.h
+++ b/src/plugins/texteditor/texteditorsettings.h
@@ -39,7 +39,6 @@ QT_END_NAMESPACE
namespace TextEditor {
class FontSettings;
-class TabSettings;
class TypingSettings;
class StorageSettings;
class BehaviorSettings;
diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp
index 1e3c7bd4b5..d4f9db7c50 100644
--- a/src/plugins/texteditor/textmark.cpp
+++ b/src/plugins/texteditor/textmark.cpp
@@ -92,7 +92,7 @@ TextMark::~TextMark()
TextMarkRegistry::remove(this);
if (m_baseTextDocument)
m_baseTextDocument->removeMark(this);
- m_baseTextDocument = 0;
+ m_baseTextDocument = nullptr;
}
QString TextMark::fileName() const
diff --git a/src/plugins/texteditor/textmark.h b/src/plugins/texteditor/textmark.h
index f744da7dc9..d9c09ee513 100644
--- a/src/plugins/texteditor/textmark.h
+++ b/src/plugins/texteditor/textmark.h
@@ -42,7 +42,6 @@ QT_END_NAMESPACE
namespace TextEditor {
-class BaseTextEditor;
class TextDocument;
class TEXTEDITOR_EXPORT TextMark
@@ -125,9 +124,9 @@ private:
QString m_fileName;
int m_lineNumber = 0;
Priority m_priority = LowPriority;
- bool m_visible = false;
QIcon m_icon;
- Utils::Theme::Color m_color;
+ Utils::Theme::Color m_color = Utils::Theme::TextColorNormal;
+ bool m_visible = false;
bool m_hasColor = false;
Core::Id m_category;
double m_widthFactor = 1.0;
diff --git a/src/plugins/todo/todoitemsprovider.cpp b/src/plugins/todo/todoitemsprovider.cpp
index d7a584179f..54a525cf7d 100644
--- a/src/plugins/todo/todoitemsprovider.cpp
+++ b/src/plugins/todo/todoitemsprovider.cpp
@@ -145,7 +145,7 @@ void TodoItemsProvider::setItemsListWithinStartupProject()
void TodoItemsProvider::setItemsListWithinSubproject()
{
// TODO prefer current editor as source of sub-project
- Node *node = ProjectTree::currentNode();
+ const Node *node = ProjectTree::findCurrentNode();
if (node) {
ProjectNode *projectNode = node->parentProjectNode();
if (projectNode) {
diff --git a/src/plugins/todo/todoplugin.cpp b/src/plugins/todo/todoplugin.cpp
index b99ec94bd1..5b2fef62cd 100644
--- a/src/plugins/todo/todoplugin.cpp
+++ b/src/plugins/todo/todoplugin.cpp
@@ -71,7 +71,7 @@ bool TodoPlugin::initialize(const QStringList& args, QString *errMsg)
auto panelFactory = new ProjectExplorer::ProjectPanelFactory;
panelFactory->setPriority(100);
panelFactory->setDisplayName(TodoProjectSettingsWidget::tr("To-Do"));
- panelFactory->setCreateWidgetFunction([this, panelFactory](ProjectExplorer::Project *project) {
+ panelFactory->setCreateWidgetFunction([this](ProjectExplorer::Project *project) {
auto widget = new TodoProjectSettingsWidget(project);
connect(widget, &TodoProjectSettingsWidget::projectSettingsChanged,
m_todoItemsProvider, [this, project] { m_todoItemsProvider->projectSettingsChanged(project); });
diff --git a/src/plugins/updateinfo/settingspage.cpp b/src/plugins/updateinfo/settingspage.cpp
index e8e07a7d9d..03a1045a32 100644
--- a/src/plugins/updateinfo/settingspage.cpp
+++ b/src/plugins/updateinfo/settingspage.cpp
@@ -116,7 +116,7 @@ void SettingsPage::checkRunningChanged(bool running)
if (running) {
if (!m_progressIndicator) {
- m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large);
+ m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large);
m_progressIndicator->attachToWidget(m_widget);
}
m_progressIndicator->show();
diff --git a/src/plugins/updateinfo/settingspage.ui b/src/plugins/updateinfo/settingspage.ui
index 7e16862038..de6357b956 100644
--- a/src/plugins/updateinfo/settingspage.ui
+++ b/src/plugins/updateinfo/settingspage.ui
@@ -42,7 +42,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>Qt Creator automatically runs a scheduled check for updates on a time interval basis. If Qt Creator is not in use on the scheduled date, the automatic check for updates will be performed next time Qt Creator starts.</string>
+ <string>Automatically runs a scheduled check for updates on a time interval basis. The automatic check for updates will be performed at the scheduled date, or the next startup following it.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
diff --git a/src/plugins/valgrind/callgrindvisualisation.h b/src/plugins/valgrind/callgrindvisualisation.h
index cbb38ca6e5..f03b4775b5 100644
--- a/src/plugins/valgrind/callgrindvisualisation.h
+++ b/src/plugins/valgrind/callgrindvisualisation.h
@@ -29,7 +29,6 @@
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
-class QModelIndex;
QT_END_NAMESPACE
namespace Valgrind {
diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp
deleted file mode 100644
index 8e80ef1165..0000000000
--- a/src/plugins/valgrind/memcheckengine.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "memcheckengine.h"
-#include "memchecktool.h"
-#include "valgrindsettings.h"
-#include "xmlprotocol/error.h"
-#include "xmlprotocol/status.h"
-
-#include <debugger/debuggerkitinformation.h>
-#include <debugger/debuggerstartparameters.h>
-#include <debugger/debuggerruncontrol.h>
-
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/toolchain.h>
-
-#include <utils/qtcassert.h>
-
-using namespace Debugger;
-using namespace ProjectExplorer;
-using namespace Valgrind::XmlProtocol;
-
-namespace Valgrind {
-namespace Internal {
-
-class LocalAddressFinder : public RunWorker
-{
-public:
- LocalAddressFinder(RunControl *runControl, QHostAddress *localServerAddress)
- : RunWorker(runControl), connection(device()->sshParameters())
- {
- connect(&connection, &QSsh::SshConnection::connected, this, [this, localServerAddress] {
- *localServerAddress = connection.connectionInfo().localAddress;
- reportStarted();
- });
- connect(&connection, &QSsh::SshConnection::error, this, [this] {
- reportFailure();
- });
- }
-
- void start() override
- {
- connection.connectToHost();
- }
-
- QSsh::SshConnection connection;
-};
-
-MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb)
- : ValgrindToolRunner(runControl),
- m_withGdb(withGdb),
- m_localServerAddress(QHostAddress::LocalHost)
-{
- setDisplayName("MemcheckToolRunner");
- connect(m_runner.parser(), &XmlProtocol::ThreadedParser::error,
- this, &MemcheckToolRunner::parserError);
- connect(m_runner.parser(), &XmlProtocol::ThreadedParser::suppressionCount,
- this, &MemcheckToolRunner::suppressionCount);
-
- if (withGdb) {
- connect(&m_runner, &ValgrindRunner::valgrindStarted,
- this, &MemcheckToolRunner::startDebugger);
- connect(&m_runner, &ValgrindRunner::logMessageReceived,
- this, &MemcheckToolRunner::appendLog);
-// m_runner.disableXml();
- } else {
- connect(m_runner.parser(), &XmlProtocol::ThreadedParser::internalError,
- this, &MemcheckToolRunner::internalParserError);
- }
-
- // We need a real address to connect to from the outside.
- if (device()->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
- addStartDependency(new LocalAddressFinder(runControl, &m_localServerAddress));
-}
-
-QString MemcheckToolRunner::progressTitle() const
-{
- return tr("Analyzing Memory");
-}
-
-void MemcheckToolRunner::start()
-{
- m_runner.setLocalServerAddress(m_localServerAddress);
- ValgrindToolRunner::start();
-}
-
-void MemcheckToolRunner::stop()
-{
- disconnect(m_runner.parser(), &ThreadedParser::internalError,
- this, &MemcheckToolRunner::internalParserError);
- ValgrindToolRunner::stop();
-}
-
-QStringList MemcheckToolRunner::toolArguments() const
-{
- QStringList arguments = {"--tool=memcheck", "--gen-suppressions=all"};
-
- QTC_ASSERT(m_settings, return arguments);
-
- if (m_settings->trackOrigins())
- arguments << "--track-origins=yes";
-
- if (m_settings->showReachable())
- arguments << "--show-reachable=yes";
-
- QString leakCheckValue;
- switch (m_settings->leakCheckOnFinish()) {
- case ValgrindBaseSettings::LeakCheckOnFinishNo:
- leakCheckValue = "no";
- break;
- case ValgrindBaseSettings::LeakCheckOnFinishYes:
- leakCheckValue = "full";
- break;
- case ValgrindBaseSettings::LeakCheckOnFinishSummaryOnly:
- default:
- leakCheckValue = "summary";
- break;
- }
- arguments << "--leak-check=" + leakCheckValue;
-
- foreach (const QString &file, m_settings->suppressionFiles())
- arguments << QString("--suppressions=%1").arg(file);
-
- arguments << QString("--num-callers=%1").arg(m_settings->numCallers());
-
- if (m_withGdb)
- arguments << "--vgdb=yes" << "--vgdb-error=0";
-
- return arguments;
-}
-
-QStringList MemcheckToolRunner::suppressionFiles() const
-{
- return m_settings->suppressionFiles();
-}
-
-void MemcheckToolRunner::startDebugger(qint64 valgrindPid)
-{
- Debugger::DebuggerStartParameters sp;
- sp.inferior = runnable().as<StandardRunnable>();
- sp.startMode = Debugger::AttachToRemoteServer;
- sp.displayName = QString("VGdb %1").arg(valgrindPid);
- sp.remoteChannel = QString("| vgdb --pid=%1").arg(valgrindPid);
- sp.useContinueInsteadOfRun = true;
- sp.expectedSignals.append("SIGTRAP");
-
- auto gdbWorker = new Debugger::DebuggerRunTool(runControl());
- gdbWorker->setStartParameters(sp);
- gdbWorker->initiateStart();
- connect(runControl(), &RunControl::stopped, gdbWorker, &RunControl::deleteLater);
-}
-
-void MemcheckToolRunner::appendLog(const QByteArray &data)
-{
- appendMessage(QString::fromUtf8(data), Utils::StdOutFormat);
-}
-
-} // namespace Internal
-} // namespace Valgrind
diff --git a/src/plugins/valgrind/memcheckengine.h b/src/plugins/valgrind/memcheckengine.h
deleted file mode 100644
index 6113390e91..0000000000
--- a/src/plugins/valgrind/memcheckengine.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "valgrindengine.h"
-
-#include "valgrindrunner.h"
-#include "xmlprotocol/threadedparser.h"
-
-#include <QHostAddress>
-
-namespace Valgrind {
-namespace Internal {
-
-class MemcheckToolRunner : public ValgrindToolRunner
-{
- Q_OBJECT
-
-public:
- explicit MemcheckToolRunner(ProjectExplorer::RunControl *runControl,
- bool withGdb = false);
-
- void start() override;
- void stop() override;
-
- QStringList suppressionFiles() const;
-
-signals:
- void internalParserError(const QString &errorString);
- void parserError(const Valgrind::XmlProtocol::Error &error);
- void suppressionCount(const QString &name, qint64 count);
-
-private:
- QString progressTitle() const override;
- QStringList toolArguments() const override;
-
- void startDebugger(qint64 valgrindPid);
- void appendLog(const QByteArray &data);
-
- const bool m_withGdb;
- QHostAddress m_localServerAddress;
-};
-
-} // namespace Internal
-} // namespace Valgrind
diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp
index cab6dea44c..f668ee3a5f 100644
--- a/src/plugins/valgrind/memchecktool.cpp
+++ b/src/plugins/valgrind/memchecktool.cpp
@@ -25,37 +25,44 @@
****************************************************************************/
#include "memchecktool.h"
-#include "memcheckengine.h"
+
#include "memcheckerrorview.h"
#include "valgrindsettings.h"
#include "valgrindplugin.h"
-
+#include "valgrindengine.h"
+#include "valgrindsettings.h"
+#include "valgrindrunner.h"
+
+#include "xmlprotocol/error.h"
+#include "xmlprotocol/error.h"
+#include "xmlprotocol/errorlistmodel.h"
+#include "xmlprotocol/frame.h"
+#include "xmlprotocol/stack.h"
+#include "xmlprotocol/stackmodel.h"
+#include "xmlprotocol/status.h"
+#include "xmlprotocol/suppression.h"
+#include "xmlprotocol/threadedparser.h"
+
+#include <debugger/debuggerkitinformation.h>
+#include <debugger/debuggerruncontrol.h>
#include <debugger/analyzer/analyzerconstants.h>
#include <debugger/analyzer/analyzermanager.h>
-#include <debugger/analyzer/analyzerutils.h>
#include <debugger/analyzer/startremotedialog.h>
-#include <valgrind/valgrindsettings.h>
-#include <valgrind/xmlprotocol/errorlistmodel.h>
-#include <valgrind/xmlprotocol/stackmodel.h>
-#include <valgrind/xmlprotocol/error.h>
-#include <valgrind/xmlprotocol/frame.h>
-#include <valgrind/xmlprotocol/stack.h>
-#include <valgrind/xmlprotocol/suppression.h>
-
-#include <extensionsystem/iplugin.h>
-#include <extensionsystem/pluginmanager.h>
-
+#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/deploymentdata.h>
-#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
-#include <projectexplorer/session.h>
-#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/toolchain.h>
+
+#include <extensionsystem/iplugin.h>
+#include <extensionsystem/pluginmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
@@ -65,32 +72,23 @@
#include <utils/fancymainwindow.h>
#include <utils/qtcassert.h>
-#include <utils/styledbar.h>
-#include <utils/stylehelper.h>
#include <utils/utilsicons.h>
#include <QAction>
-#include <QCheckBox>
-#include <QComboBox>
-#include <QDir>
-#include <QDockWidget>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
-#include <QHBoxLayout>
#include <QLabel>
-#include <QLatin1String>
#include <QMenu>
-#include <QSortFilterProxyModel>
-#include <QSpinBox>
-#include <QString>
#include <QToolButton>
+#include <QSortFilterProxyModel>
using namespace Core;
using namespace Debugger;
using namespace ProjectExplorer;
using namespace Utils;
using namespace Valgrind::XmlProtocol;
+
using namespace std::placeholders;
namespace Valgrind {
@@ -102,6 +100,167 @@ const char MEMCHECK_WITH_GDB_RUN_MODE[] = "MemcheckTool.MemcheckWithGdbRunMode";
const char MemcheckPerspectiveId[] = "Memcheck.Perspective";
const char MemcheckErrorDockId[] = "Memcheck.Dock.Error";
+
+class MemcheckToolRunner : public ValgrindToolRunner
+{
+ Q_OBJECT
+
+public:
+ explicit MemcheckToolRunner(ProjectExplorer::RunControl *runControl,
+ bool withGdb = false);
+
+ void start() override;
+ void stop() override;
+
+ QStringList suppressionFiles() const;
+
+signals:
+ void internalParserError(const QString &errorString);
+ void parserError(const Valgrind::XmlProtocol::Error &error);
+ void suppressionCount(const QString &name, qint64 count);
+
+private:
+ QString progressTitle() const override;
+ QStringList toolArguments() const override;
+
+ void startDebugger(qint64 valgrindPid);
+ void appendLog(const QByteArray &data);
+
+ const bool m_withGdb;
+ QHostAddress m_localServerAddress;
+};
+
+class LocalAddressFinder : public RunWorker
+{
+public:
+ LocalAddressFinder(RunControl *runControl, QHostAddress *localServerAddress)
+ : RunWorker(runControl), connection(device()->sshParameters())
+ {
+ connect(&connection, &QSsh::SshConnection::connected, this, [this, localServerAddress] {
+ *localServerAddress = connection.connectionInfo().localAddress;
+ reportStarted();
+ });
+ connect(&connection, &QSsh::SshConnection::error, this, [this] {
+ reportFailure();
+ });
+ }
+
+ void start() override
+ {
+ connection.connectToHost();
+ }
+
+ QSsh::SshConnection connection;
+};
+
+MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb)
+ : ValgrindToolRunner(runControl),
+ m_withGdb(withGdb),
+ m_localServerAddress(QHostAddress::LocalHost)
+{
+ setDisplayName("MemcheckToolRunner");
+ connect(m_runner.parser(), &XmlProtocol::ThreadedParser::error,
+ this, &MemcheckToolRunner::parserError);
+ connect(m_runner.parser(), &XmlProtocol::ThreadedParser::suppressionCount,
+ this, &MemcheckToolRunner::suppressionCount);
+
+ if (withGdb) {
+ connect(&m_runner, &ValgrindRunner::valgrindStarted,
+ this, &MemcheckToolRunner::startDebugger);
+ connect(&m_runner, &ValgrindRunner::logMessageReceived,
+ this, &MemcheckToolRunner::appendLog);
+// m_runner.disableXml();
+ } else {
+ connect(m_runner.parser(), &XmlProtocol::ThreadedParser::internalError,
+ this, &MemcheckToolRunner::internalParserError);
+ }
+
+ // We need a real address to connect to from the outside.
+ if (device()->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
+ addStartDependency(new LocalAddressFinder(runControl, &m_localServerAddress));
+}
+
+QString MemcheckToolRunner::progressTitle() const
+{
+ return tr("Analyzing Memory");
+}
+
+void MemcheckToolRunner::start()
+{
+ m_runner.setLocalServerAddress(m_localServerAddress);
+ ValgrindToolRunner::start();
+}
+
+void MemcheckToolRunner::stop()
+{
+ disconnect(m_runner.parser(), &ThreadedParser::internalError,
+ this, &MemcheckToolRunner::internalParserError);
+ ValgrindToolRunner::stop();
+}
+
+QStringList MemcheckToolRunner::toolArguments() const
+{
+ QStringList arguments = {"--tool=memcheck", "--gen-suppressions=all"};
+
+ QTC_ASSERT(m_settings, return arguments);
+
+ if (m_settings->trackOrigins())
+ arguments << "--track-origins=yes";
+
+ if (m_settings->showReachable())
+ arguments << "--show-reachable=yes";
+
+ QString leakCheckValue;
+ switch (m_settings->leakCheckOnFinish()) {
+ case ValgrindBaseSettings::LeakCheckOnFinishNo:
+ leakCheckValue = "no";
+ break;
+ case ValgrindBaseSettings::LeakCheckOnFinishYes:
+ leakCheckValue = "full";
+ break;
+ case ValgrindBaseSettings::LeakCheckOnFinishSummaryOnly:
+ default:
+ leakCheckValue = "summary";
+ break;
+ }
+ arguments << "--leak-check=" + leakCheckValue;
+
+ foreach (const QString &file, m_settings->suppressionFiles())
+ arguments << QString("--suppressions=%1").arg(file);
+
+ arguments << QString("--num-callers=%1").arg(m_settings->numCallers());
+
+ if (m_withGdb)
+ arguments << "--vgdb=yes" << "--vgdb-error=0";
+
+ return arguments;
+}
+
+QStringList MemcheckToolRunner::suppressionFiles() const
+{
+ return m_settings->suppressionFiles();
+}
+
+void MemcheckToolRunner::startDebugger(qint64 valgrindPid)
+{
+ auto debugger = new Debugger::DebuggerRunTool(runControl());
+ debugger->setStartMode(Debugger::AttachToRemoteServer);
+ debugger->setRunControlName(QString("VGdb %1").arg(valgrindPid));
+ debugger->setRemoteChannel(QString("| vgdb --pid=%1").arg(valgrindPid));
+ debugger->setUseContinueInsteadOfRun(true);
+ debugger->addExpectedSignal("SIGTRAP");
+
+ connect(runControl(), &RunControl::stopped, debugger, &RunControl::deleteLater);
+
+ debugger->initiateStart();
+}
+
+void MemcheckToolRunner::appendLog(const QByteArray &data)
+{
+ appendMessage(QString::fromUtf8(data), Utils::StdOutFormat);
+}
+
+
static ErrorListModel::RelevantFrameFinder makeFrameFinder(const QStringList &projectFiles)
{
return [projectFiles](const Error &error) {
@@ -352,7 +511,7 @@ MemcheckTool::MemcheckTool()
// Load external XML log file
auto action = new QAction(this);
- action->setIcon(Utils::Icons::OPENFILE.icon());
+ action->setIcon(Icons::OPENFILE.icon());
action->setToolTip(tr("Load External XML Log File"));
connect(action, &QAction::triggered, this, &MemcheckTool::loadExternalXmlLogFile);
m_loadExternalLogFile = action;
@@ -360,7 +519,7 @@ MemcheckTool::MemcheckTool()
// Go to previous leak.
action = new QAction(this);
action->setDisabled(true);
- action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
+ action->setIcon(Icons::PREV_TOOLBAR.icon());
action->setToolTip(tr("Go to previous leak."));
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goBack);
m_goBack = action;
@@ -368,13 +527,13 @@ MemcheckTool::MemcheckTool()
// Go to next leak.
action = new QAction(this);
action->setDisabled(true);
- action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
+ action->setIcon(Icons::NEXT_TOOLBAR.icon());
action->setToolTip(tr("Go to next leak."));
connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goNext);
m_goNext = action;
auto filterButton = new QToolButton;
- filterButton->setIcon(Utils::Icons::FILTER.icon());
+ filterButton->setIcon(Icons::FILTER.icon());
filterButton->setText(tr("Error Filter"));
filterButton->setPopupMode(QToolButton::InstantPopup);
filterButton->setProperty("noArrow", true);
@@ -391,7 +550,7 @@ MemcheckTool::MemcheckTool()
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
QString toolTip = tr("Valgrind Analyze Memory uses the Memcheck tool to find memory leaks.");
- if (!Utils::HostOsInfo::isWindowsHost()) {
+ if (!HostOsInfo::isWindowsHost()) {
action = new QAction(this);
action->setText(tr("Valgrind Memory Analyzer"));
action->setToolTip(toolTip);
@@ -434,7 +593,7 @@ MemcheckTool::MemcheckTool()
action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, "Memcheck.Remote"),
Debugger::Constants::G_ANALYZER_REMOTE_TOOLS);
- QObject::connect(action, &QAction::triggered, this, [this, action] {
+ QObject::connect(action, &QAction::triggered, this, [action] {
auto runConfig = RunConfiguration::startupRunConfiguration();
if (!runConfig) {
showCannotStartDialog(action->text());
@@ -552,9 +711,7 @@ void MemcheckTool::maybeActiveRunConfigurationChanged()
RunWorker *MemcheckTool::createRunWorker(RunControl *runControl)
{
- RunConfiguration *runConfig = runControl->runConfiguration();
- m_errorModel.setRelevantFrameFinder(makeFrameFinder(runConfig
- ? runConfig->target()->project()->files(Project::AllFiles) : QStringList()));
+ m_errorModel.setRelevantFrameFinder(makeFrameFinder(runControl->project()->files(Project::AllFiles)));
auto runTool = new MemcheckToolRunner(runControl, runControl->runMode() == MEMCHECK_WITH_GDB_RUN_MODE);
@@ -572,19 +729,16 @@ RunWorker *MemcheckTool::createRunWorker(RunControl *runControl)
clearErrorView();
m_loadExternalLogFile->setDisabled(true);
- QString dir;
- if (RunConfiguration *rc = runTool->runControl()->runConfiguration())
- dir = rc->target()->project()->projectDirectory().toString() + QLatin1Char('/');
+ QString dir = runControl->project()->projectDirectory().toString() + '/';
+ const QString name = FileName::fromString(runTool->executable()).fileName();
- const QString name = Utils::FileName::fromString(runTool->executable()).fileName();
-
- m_errorView->setDefaultSuppressionFile(dir + name + QLatin1String(".supp"));
+ m_errorView->setDefaultSuppressionFile(dir + name + ".supp");
foreach (const QString &file, runTool->suppressionFiles()) {
- QAction *action = m_filterMenu->addAction(Utils::FileName::fromString(file).fileName());
+ QAction *action = m_filterMenu->addAction(FileName::fromString(file).fileName());
action->setToolTip(file);
- connect(action, &QAction::triggered, this, [this, file]() {
- Core::EditorManager::openEditorAt(file, 0);
+ connect(action, &QAction::triggered, this, [file] {
+ EditorManager::openEditorAt(file, 0);
});
m_suppressionActions.append(action);
}
@@ -595,7 +749,7 @@ RunWorker *MemcheckTool::createRunWorker(RunControl *runControl)
void MemcheckTool::loadExternalXmlLogFile()
{
const QString filePath = QFileDialog::getOpenFileName(
- Core::ICore::mainWindow(),
+ ICore::mainWindow(),
tr("Open Memcheck XML Log File"),
QString(),
tr("XML Files (*.xml);;All Files (*)"));
@@ -726,3 +880,5 @@ void destroyMemcheckTool()
} // namespace Internal
} // namespace Valgrind
+
+#include "memchecktool.moc"
diff --git a/src/plugins/valgrind/valgrind.pro b/src/plugins/valgrind/valgrind.pro
index 4bbd41fc5c..216e356817 100644
--- a/src/plugins/valgrind/valgrind.pro
+++ b/src/plugins/valgrind/valgrind.pro
@@ -21,7 +21,6 @@ HEADERS += \
workarounds.h \
callgrindtextmark.h \
memchecktool.h \
- memcheckengine.h \
memcheckerrorview.h \
suppressiondialog.h
@@ -41,7 +40,6 @@ SOURCES += \
workarounds.cpp \
callgrindtextmark.cpp \
memchecktool.cpp \
- memcheckengine.cpp \
memcheckerrorview.cpp \
suppressiondialog.cpp
diff --git a/src/plugins/valgrind/valgrind.qbs b/src/plugins/valgrind/valgrind.qbs
index c7e992921e..5b7fb8f040 100644
--- a/src/plugins/valgrind/valgrind.qbs
+++ b/src/plugins/valgrind/valgrind.qbs
@@ -27,10 +27,10 @@ QtcPlugin {
"callgrindtextmark.cpp", "callgrindtextmark.h",
"callgrindtool.cpp", "callgrindtool.h",
"callgrindvisualisation.cpp", "callgrindvisualisation.h",
- "memcheckengine.cpp", "memcheckengine.h",
"memcheckerrorview.cpp", "memcheckerrorview.h",
"memchecktool.cpp", "memchecktool.h",
"suppressiondialog.cpp", "suppressiondialog.h",
+ "valgrind.qrc",
"valgrindconfigwidget.cpp", "valgrindconfigwidget.h", "valgrindconfigwidget.ui",
"valgrindengine.cpp", "valgrindengine.h",
"valgrindplugin.cpp", "valgrindplugin.h",
diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp
index 13beca1fa0..cfe6648b01 100644
--- a/src/plugins/valgrind/valgrindengine.cpp
+++ b/src/plugins/valgrind/valgrindengine.cpp
@@ -177,7 +177,7 @@ void ValgrindToolRunner::receiveProcessError(const QString &message, QProcess::P
} else if (m_isStopping && error == QProcess::Crashed) { // process gets killed on stop
appendMessage(tr("Process terminated."), ErrorMessageFormat);
} else {
- appendMessage(QString("** %1 **\n").arg(message), ErrorMessageFormat);
+ appendMessage(tr("Process exited with return value %1\n").arg(message), NormalMessageFormat);
}
if (m_isStopping)
diff --git a/src/plugins/valgrind/xmlprotocol/error.h b/src/plugins/valgrind/xmlprotocol/error.h
index f7b56f301f..8a235348b1 100644
--- a/src/plugins/valgrind/xmlprotocol/error.h
+++ b/src/plugins/valgrind/xmlprotocol/error.h
@@ -37,7 +37,6 @@ QT_END_NAMESPACE
namespace Valgrind {
namespace XmlProtocol {
-class Frame;
class Stack;
class Suppression;
diff --git a/src/plugins/vcsbase/basevcseditorfactory.cpp b/src/plugins/vcsbase/basevcseditorfactory.cpp
index 8b183e5c01..2e26d4026e 100644
--- a/src/plugins/vcsbase/basevcseditorfactory.cpp
+++ b/src/plugins/vcsbase/basevcseditorfactory.cpp
@@ -63,7 +63,7 @@ VcsEditorFactory::VcsEditorFactory(const VcsBaseEditorParameters *parameters,
setEditorActionHandlers(TextEditorActionHandler::None);
setDuplicatedSupported(false);
- setDocumentCreator([this, parameters]() -> TextDocument* {
+ setDocumentCreator([parameters]() -> TextDocument* {
auto document = new TextDocument(parameters->id);
// if (QLatin1String(parameters->mimeType) != QLatin1String(DiffEditor::Constants::DIFF_EDITOR_MIMETYPE))
document->setMimeType(QLatin1String(parameters->mimeType));
@@ -71,7 +71,7 @@ VcsEditorFactory::VcsEditorFactory(const VcsBaseEditorParameters *parameters,
return document;
});
- setEditorWidgetCreator([this, parameters, editorWidgetCreator, describeFunc]() -> TextEditorWidget * {
+ setEditorWidgetCreator([parameters, editorWidgetCreator, describeFunc]() -> TextEditorWidget * {
auto widget = qobject_cast<VcsBaseEditorWidget *>(editorWidgetCreator());
widget->setDescribeFunc(describeFunc);
widget->setParameters(parameters);
diff --git a/src/plugins/vcsbase/commonsettingspage.cpp b/src/plugins/vcsbase/commonsettingspage.cpp
index 735defb4ae..12f374bcbb 100644
--- a/src/plugins/vcsbase/commonsettingspage.cpp
+++ b/src/plugins/vcsbase/commonsettingspage.cpp
@@ -61,7 +61,7 @@ CommonSettingsWidget::CommonSettingsWidget(QWidget *parent) :
connect(Core::VcsManager::instance(), &Core::VcsManager::configurationChanged,
this, &CommonSettingsWidget::updatePath);
connect(m_ui->cacheResetButton, &QPushButton::clicked,
- this, [] { Core::VcsManager::clearVersionControlCache(); });
+ Core::VcsManager::instance(), &Core::VcsManager::clearVersionControlCache);
}
CommonSettingsWidget::~CommonSettingsWidget()
diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.cpp b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
index ab67910c2f..ab31348c1a 100644
--- a/src/plugins/vcsbase/vcsbaseclientsettings.cpp
+++ b/src/plugins/vcsbase/vcsbaseclientsettings.cpp
@@ -201,9 +201,9 @@ const QLatin1String VcsBaseClientSettings::pathKey("Path");
VcsBaseClientSettings::VcsBaseClientSettings() :
d(new Internal::VcsBaseClientSettingsPrivate)
{
- declareKey(binaryPathKey, QLatin1String(""));
- declareKey(userNameKey, QLatin1String(""));
- declareKey(userEmailKey, QLatin1String(""));
+ declareKey(binaryPathKey, QString());
+ declareKey(userNameKey, QString());
+ declareKey(userEmailKey, QString());
declareKey(logCountKey, 100);
declareKey(promptOnSubmitKey, true);
declareKey(timeoutKey, 30);
@@ -363,7 +363,7 @@ Utils::FileName VcsBaseClientSettings::binaryPath() const
QStringList VcsBaseClientSettings::searchPathList() const
{
- return stringValue(pathKey).split(Utils::HostOsInfo::pathListSeparator());
+ return stringValue(pathKey).split(Utils::HostOsInfo::pathListSeparator(), QString::SkipEmptyParts);
}
QString VcsBaseClientSettings::settingsGroup() const
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 063d2695d7..2d17bb3692 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -1398,7 +1398,7 @@ void VcsBaseEditorWidget::setCommand(VcsCommand *command)
}
d->m_command = command;
if (command) {
- d->m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicator::Large);
+ d->m_progressIndicator = new Utils::ProgressIndicator(Utils::ProgressIndicatorSize::Large);
d->m_progressIndicator->attachToWidget(this);
connect(command, &VcsCommand::finished, this, &VcsBaseEditorWidget::reportCommandFinished);
QTimer::singleShot(100, this, &VcsBaseEditorWidget::showProgressIndicator);
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index 0a62647a05..92b2fb44a3 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -34,9 +34,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/id.h>
#include <coreplugin/idocument.h>
-#include <coreplugin/iversioncontrol.h>
#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/vcsmanager.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
@@ -552,9 +550,10 @@ VcsBasePlugin::~VcsBasePlugin()
void VcsBasePlugin::initializeVcs(IVersionControl *vc, const Context &context)
{
+ QTC_ASSERT(vc, return);
+
d->m_versionControl = vc;
d->m_context = context;
- addAutoReleasedObject(vc);
Internal::VcsPlugin *plugin = Internal::VcsPlugin::instance();
connect(plugin, &Internal::VcsPlugin::submitEditorAboutToClose,
@@ -642,6 +641,16 @@ bool VcsBasePlugin::enableMenuAction(ActionState as, QAction *menuAction) const
return true;
}
+QString VcsBasePlugin::commitDisplayName() const
+{
+ return tr("commit", "name of \"commit\" action of the VCS.");
+}
+
+bool VcsBasePlugin::promptBeforeCommit()
+{
+ return DocumentManager::saveAllModifiedDocuments(tr("Save before %1?").arg(commitDisplayName()));
+}
+
void VcsBasePlugin::promptToDeleteCurrentFile()
{
const VcsBasePluginState state = currentState();
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index dc719111b2..72b2c5a46e 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -27,6 +27,8 @@
#include "vcsbase_global.h"
+#include <coreplugin/iversioncontrol.h>
+#include <coreplugin/vcsmanager.h>
#include <extensionsystem/iplugin.h>
#include <QList>
@@ -128,7 +130,14 @@ class VCSBASE_EXPORT VcsBasePlugin : public ExtensionSystem::IPlugin
protected:
explicit VcsBasePlugin();
- void initializeVcs(Core::IVersionControl *vc, const Core::Context &context);
+ template<class T, typename... Args>
+ T *initializeVcs(const Core::Context &context, Args&&... args)
+ {
+ T *vc = Core::VcsManager::registerVersionControl<T>(std::forward<Args>(args)...);
+ initializeVcs(vc, context);
+ return vc;
+ }
+
void extensionsInitialized() override;
public:
@@ -169,6 +178,11 @@ public:
const QProcessEnvironment &env = QProcessEnvironment());
protected:
+ // Display name of the commit action:
+ virtual QString commitDisplayName() const;
+ // Prompt to save all files before commit:
+ bool promptBeforeCommit();
+
// Convenience slot for "Delete current file" action. Prompts to
// delete the file via VcsManager.
void promptToDeleteCurrentFile();
@@ -204,6 +218,8 @@ private:
void slotSubmitEditorAboutToClose(VcsBaseSubmitEditor *submitEditor, bool *result);
void slotStateChanged(const VcsBase::Internal::State &s, Core::IVersionControl *vc);
+ void initializeVcs(Core::IVersionControl *vc, const Core::Context &context);
+
VcsBasePluginPrivate *d;
};
diff --git a/src/plugins/vcsbase/vcsprojectcache.cpp b/src/plugins/vcsbase/vcsprojectcache.cpp
index 6540daf2a7..a2ca3987a6 100644
--- a/src/plugins/vcsbase/vcsprojectcache.cpp
+++ b/src/plugins/vcsbase/vcsprojectcache.cpp
@@ -74,9 +74,9 @@ VcsProjectCache::VcsProjectCache()
m_instance = this;
connect(ProjectExplorer::SessionManager::instance(), &ProjectExplorer::SessionManager::projectAdded,
- this, [this]() { VcsProjectCache::invalidate(); });
+ this, []() { VcsProjectCache::invalidate(); });
connect(ProjectExplorer::SessionManager::instance(), &ProjectExplorer::SessionManager::projectRemoved,
- this, [this]() { VcsProjectCache::invalidate(); });
+ this, []() { VcsProjectCache::invalidate(); });
}
VcsProjectCache::~VcsProjectCache()
diff --git a/src/plugins/welcome/images/mode_edit_mask.png b/src/plugins/welcome/images/mode_edit_mask.png
deleted file mode 100644
index 221f491519..0000000000
--- a/src/plugins/welcome/images/mode_edit_mask.png
+++ /dev/null
Binary files differ
diff --git a/src/plugins/welcome/images/mode_welcome.png b/src/plugins/welcome/images/mode_welcome.png
index 24cfcd8cc8..186b85f191 100644
--- a/src/plugins/welcome/images/mode_welcome.png
+++ b/src/plugins/welcome/images/mode_welcome.png
Binary files differ
diff --git a/src/plugins/welcome/images/mode_welcome@2x.png b/src/plugins/welcome/images/mode_welcome@2x.png
index f1e9189523..f911a46254 100644
--- a/src/plugins/welcome/images/mode_welcome@2x.png
+++ b/src/plugins/welcome/images/mode_welcome@2x.png
Binary files differ
diff --git a/src/plugins/welcome/images/mode_welcome_mask.png b/src/plugins/welcome/images/mode_welcome_mask.png
index 86912bb069..696af0c549 100644
--- a/src/plugins/welcome/images/mode_welcome_mask.png
+++ b/src/plugins/welcome/images/mode_welcome_mask.png
Binary files differ
diff --git a/src/plugins/welcome/images/mode_welcome_mask@2x.png b/src/plugins/welcome/images/mode_welcome_mask@2x.png
index daee953529..060ada0cf5 100644
--- a/src/plugins/welcome/images/mode_welcome_mask@2x.png
+++ b/src/plugins/welcome/images/mode_welcome_mask@2x.png
Binary files differ
diff --git a/src/plugins/welcome/welcome.qbs b/src/plugins/welcome/welcome.qbs
index d7febc088c..4209a04116 100644
--- a/src/plugins/welcome/welcome.qbs
+++ b/src/plugins/welcome/welcome.qbs
@@ -7,6 +7,7 @@ QtcPlugin {
Depends { name: "Utils" }
Depends { name: "Core" }
+ Depends { name: "app_version_header" }
files: [
"welcome.qrc",
diff --git a/src/plugins/welcome/welcome.qrc b/src/plugins/welcome/welcome.qrc
index 5321c6ebd4..28e8d22d1c 100644
--- a/src/plugins/welcome/welcome.qrc
+++ b/src/plugins/welcome/welcome.qrc
@@ -8,7 +8,6 @@
<file>images/blogs@2x.png</file>
<file>images/community.png</file>
<file>images/community@2x.png</file>
- <file>images/mode_edit_mask.png</file>
<file>images/open.png</file>
<file>images/open@2x.png</file>
<file>images/project.png</file>
diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp
index d0bde8e994..848e0e6449 100644
--- a/src/plugins/welcome/welcomeplugin.cpp
+++ b/src/plugins/welcome/welcomeplugin.cpp
@@ -26,6 +26,8 @@
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
+#include <app/app_version.h>
+
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
@@ -228,7 +230,8 @@ public:
l->addWidget(newLabel);
auto learnLabel = new QLabel(tr("Learn how to develop your own applications "
- "and explore Qt Creator."), this);
+ "and explore %1.")
+ .arg(Core::Constants::IDE_DISPLAY_NAME), this);
learnLabel->setMaximumWidth(200);
learnLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
learnLabel->setWordWrap(true);
@@ -398,7 +401,7 @@ void WelcomeMode::addPage(IWelcomePage *page)
stackPage->setAutoFillBackground(true);
m_pageStack->insertWidget(idx, stackPage);
- auto onClicked = [this, page, pageId, stackPage] {
+ auto onClicked = [this, pageId, stackPage] {
m_activePage = pageId;
m_pageStack->setCurrentWidget(stackPage);
for (WelcomePageButton *pageButton : m_pageButtons)
diff --git a/src/plugins/winrt/images/winrtdevice.png b/src/plugins/winrt/images/winrtdevice.png
index d8f5bb7121..2b45adb69a 100644
--- a/src/plugins/winrt/images/winrtdevice.png
+++ b/src/plugins/winrt/images/winrtdevice.png
Binary files differ
diff --git a/src/plugins/winrt/images/winrtdevice@2x.png b/src/plugins/winrt/images/winrtdevice@2x.png
index 305c2e9376..a57f2b4978 100644
--- a/src/plugins/winrt/images/winrtdevice@2x.png
+++ b/src/plugins/winrt/images/winrtdevice@2x.png
Binary files differ
diff --git a/src/plugins/winrt/winrt.qbs b/src/plugins/winrt/winrt.qbs
index ea9c8f9746..96ccca3690 100644
--- a/src/plugins/winrt/winrt.qbs
+++ b/src/plugins/winrt/winrt.qbs
@@ -9,6 +9,7 @@ QtcPlugin {
Depends { name: "QtSupport" }
Depends { name: "QmakeProjectManager" }
Depends { name: "Qt.gui" }
+ Depends { name: "app_version_header" }
files: [
"winrtconstants.h",
diff --git a/src/plugins/winrt/winrtdebugsupport.cpp b/src/plugins/winrt/winrtdebugsupport.cpp
index 7499200df1..03945602a0 100644
--- a/src/plugins/winrt/winrtdebugsupport.cpp
+++ b/src/plugins/winrt/winrtdebugsupport.cpp
@@ -27,6 +27,8 @@
#include "winrtrunconfiguration.h"
#include "winrtrunnerhelper.h"
+#include <app/app_version.h>
+
#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>
@@ -49,26 +51,27 @@ WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl)
: DebuggerRunTool(runControl)
{
// FIXME: This is just working for local debugging;
- DebuggerStartParameters params;
- params.startMode = AttachExternal;
+ setStartMode(AttachExternal);
// The first Thread needs to be resumed manually.
- params.commandsAfterConnect = "~0 m";
+ setCommandsAfterConnect("~0 m");
QFileInfo debuggerHelper(QCoreApplication::applicationDirPath()
+ QLatin1String("/winrtdebughelper.exe"));
if (!debuggerHelper.isExecutable()) {
- reportFailure(tr("The WinRT debugging helper is missing from your Qt Creator "
- "installation. It was assumed to be located at %1").arg(
- debuggerHelper.absoluteFilePath()));
+ reportFailure(tr("The WinRT debugging helper is missing from your %1 "
+ "installation. It was assumed to be located at %2")
+ .arg(Core::Constants::IDE_DISPLAY_NAME)
+ .arg(debuggerHelper.absoluteFilePath()));
return;
}
if (isQmlDebugging()) {
- Utils::Port qmlDebugPort;
- if (!getFreePort(qmlDebugPort))
+ QUrl qmlServer = ProjectExplorer::urlFromLocalHostAndFreePort();
+ if (qmlServer.port() <= 0) {
+ reportFailure(tr("Not enough free ports for QML debugging."));
return;
- params.qmlServer.host = QHostAddress(QHostAddress::LocalHost).toString();
- params.qmlServer.port = qmlDebugPort;
+ }
+ setQmlServer(qmlServer);
}
QString errorMessage;
@@ -99,14 +102,14 @@ WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl)
QList<QByteArray> arg = output.split(':');
if (arg.first() == "PID") {
bool ok =false;
- params.attachPID = Utils::ProcessHandle(arg.last().toInt(&ok));
+ int pid = arg.last().toInt(&ok);
if (!ok) {
reportFailure(tr("Cannot extract the PID from the WinRT debugging helper. "
"(output: %1)").arg(QString::fromLocal8Bit(output)));
return;
}
+ setAttachPid(Utils::ProcessHandle(pid));
server.close();
- setStartParameters(params);
return;
}
}
@@ -118,18 +121,6 @@ WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl)
"the current run configuration."));
}
-bool WinRtDebugSupport::getFreePort(Utils::Port &qmlDebuggerPort)
-{
- QTcpServer server;
- if (!server.listen(QHostAddress::LocalHost,
- qmlDebuggerPort.isValid() ? qmlDebuggerPort.number() : 0)) {
- reportFailure(tr("Not enough free ports for QML debugging."));
- return false;
- }
- qmlDebuggerPort = Utils::Port(server.serverPort());
- return true;
-}
-
WinRtDebugSupport::~WinRtDebugSupport()
{
delete m_runner;
diff --git a/src/plugins/winrt/winrtdebugsupport.h b/src/plugins/winrt/winrtdebugsupport.h
index 0a8ed4e31a..b8e3c6846a 100644
--- a/src/plugins/winrt/winrtdebugsupport.h
+++ b/src/plugins/winrt/winrtdebugsupport.h
@@ -42,8 +42,6 @@ public:
~WinRtDebugSupport();
private:
- bool getFreePort(Utils::Port &qmlDebuggerPort);
-
WinRtRunnerHelper *m_runner = nullptr;
};
diff --git a/src/plugins/winrt/winrtrunconfiguration.cpp b/src/plugins/winrt/winrtrunconfiguration.cpp
index 4a29b722e8..6e83042dc9 100644
--- a/src/plugins/winrt/winrtrunconfiguration.cpp
+++ b/src/plugins/winrt/winrtrunconfiguration.cpp
@@ -44,14 +44,16 @@ static QString pathFromId(Core::Id id)
return id.suffixAfter(Constants::WINRT_RC_PREFIX);
}
-WinRtRunConfiguration::WinRtRunConfiguration(ProjectExplorer::Target *parent, Core::Id id)
- : RunConfiguration(parent, id)
- , m_proFilePath(pathFromId(id))
- , m_uninstallAfterStop(false)
+WinRtRunConfiguration::WinRtRunConfiguration(ProjectExplorer::Target *target)
+ : RunConfiguration(target)
{
setDisplayName(tr("Run App Package"));
- addExtraAspect(new ProjectExplorer::ArgumentsAspect(this,
- QLatin1String("WinRtRunConfigurationArgumentsId")));
+ addExtraAspect(new ProjectExplorer::ArgumentsAspect(this, "WinRtRunConfigurationArgumentsId"));
+}
+
+void WinRtRunConfiguration::initialize(Core::Id id)
+{
+ m_proFilePath = pathFromId(id);
}
QWidget *WinRtRunConfiguration::createConfigurationWidget()
diff --git a/src/plugins/winrt/winrtrunconfiguration.h b/src/plugins/winrt/winrtrunconfiguration.h
index 36bcf1ad43..9e3c13878c 100644
--- a/src/plugins/winrt/winrtrunconfiguration.h
+++ b/src/plugins/winrt/winrtrunconfiguration.h
@@ -35,10 +35,9 @@ class WinRtRunConfiguration : public ProjectExplorer::RunConfiguration
Q_OBJECT
public:
- explicit WinRtRunConfiguration(ProjectExplorer::Target *parent, Core::Id id);
+ explicit WinRtRunConfiguration(ProjectExplorer::Target *target);
QWidget *createConfigurationWidget() override;
- bool isEnabled() const override { return true; } // Always enabled like DLL run control
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &map) override;
@@ -54,8 +53,11 @@ signals:
void uninstallAfterStopChanged(bool);
private:
+ friend class ProjectExplorer::IRunConfigurationFactory;
+ void initialize(Core::Id id);
+
QString m_proFilePath;
- bool m_uninstallAfterStop;
+ bool m_uninstallAfterStop = false;
};
} // namespace Internal
diff --git a/src/plugins/winrt/winrtrunfactories.cpp b/src/plugins/winrt/winrtrunfactories.cpp
index 4adde53974..0c004f0c44 100644
--- a/src/plugins/winrt/winrtrunfactories.cpp
+++ b/src/plugins/winrt/winrtrunfactories.cpp
@@ -81,7 +81,7 @@ bool WinRtRunConfigurationFactory::canCreate(Target *parent, Core::Id id) const
RunConfiguration *WinRtRunConfigurationFactory::doCreate(Target *parent, Core::Id id)
{
- return new WinRtRunConfiguration(parent, id);
+ return createHelper<WinRtRunConfiguration>(parent, id);
}
bool WinRtRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
@@ -94,9 +94,7 @@ bool WinRtRunConfigurationFactory::canRestore(Target *parent, const QVariantMap
RunConfiguration *WinRtRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map)
{
- RunConfiguration *config = new WinRtRunConfiguration(parent, idFromMap(map));
- config->fromMap(map);
- return config;
+ return createHelper<WinRtRunConfiguration>(parent, idFromMap(map));
}
bool WinRtRunConfigurationFactory::canClone(Target *parent, RunConfiguration *product) const
diff --git a/src/plugins/winrt/winrtrunnerhelper.cpp b/src/plugins/winrt/winrtrunnerhelper.cpp
index 0b4c6653bb..60ca4f870c 100644
--- a/src/plugins/winrt/winrtrunnerhelper.cpp
+++ b/src/plugins/winrt/winrtrunnerhelper.cpp
@@ -185,7 +185,8 @@ void WinRtRunnerHelper::startWinRtRunner(const RunConf &conf)
if (m_device->type() == Constants::WINRT_DEVICE_TYPE_LOCAL)
QtcProcess::addArgs(&runnerArgs, QStringLiteral("--profile appx"));
- else if (m_device->type() == Constants::WINRT_DEVICE_TYPE_PHONE)
+ else if (m_device->type() == Constants::WINRT_DEVICE_TYPE_PHONE ||
+ m_device->type() == Constants::WINRT_DEVICE_TYPE_EMULATOR)
QtcProcess::addArgs(&runnerArgs, QStringLiteral("--profile appxphone"));
QtcProcess::addArg(&runnerArgs, m_executableFilePath);
diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri
index 517ded4e4b..45fb643b5c 100644
--- a/src/shared/clang/clang_installation.pri
+++ b/src/shared/clang/clang_installation.pri
@@ -3,10 +3,11 @@ LLVM_INSTALL_DIR = $$clean_path($$LLVM_INSTALL_DIR)
isEmpty(LLVM_INSTALL_DIR): error("No LLVM_INSTALL_DIR provided")
!exists($$LLVM_INSTALL_DIR): error("LLVM_INSTALL_DIR does not exist: $$LLVM_INSTALL_DIR")
-defineReplace(extractVersion) { return($$replace(1, ^(\\d+\\.\\d+\\.\\d+)$, \\1)) }
-defineReplace(extractMajorVersion) { return($$replace(1, ^(\\d+)\\.\\d+\\.\\d+$, \\1)) }
-defineReplace(extractMinorVersion) { return($$replace(1, ^\\d+\\.(\\d+)\\.\\d+$, \\1)) }
-defineReplace(extractPatchVersion) { return($$replace(1, ^\\d+\\.\\d+\\.(\\d+)$, \\1)) }
+# Expected input: "3.9.1", "5.0.0svn", "5.0.1git-81029f14223"
+defineReplace(extractVersion) { return($$replace(1, ^(\\d+\\.\\d+\\.\\d+).*$, \\1)) }
+defineReplace(extractMajorVersion) { return($$replace(1, ^(\\d+)\\.\\d+\\.\\d+.*$, \\1)) }
+defineReplace(extractMinorVersion) { return($$replace(1, ^\\d+\\.(\\d+)\\.\\d+.*$, \\1)) }
+defineReplace(extractPatchVersion) { return($$replace(1, ^\\d+\\.\\d+\\.(\\d+).*$, \\1)) }
defineTest(versionIsAtLeast) {
actual_major_version = $$extractMajorVersion($$1)
diff --git a/src/shared/help/bookmarkmanager.cpp b/src/shared/help/bookmarkmanager.cpp
index 7b6015811b..979ca7c5bf 100644
--- a/src/shared/help/bookmarkmanager.cpp
+++ b/src/shared/help/bookmarkmanager.cpp
@@ -217,7 +217,7 @@ void BookmarkDialog::customContextMenuRequested(const QPoint &point)
if (!index.isValid())
return;
- QMenu menu(QLatin1String(""), this);
+ QMenu menu(this);
QAction *removeItem = menu.addAction(tr("Delete Folder"));
QAction *renameItem = menu.addAction(tr("Rename Folder"));
@@ -322,7 +322,7 @@ void BookmarkWidget::filterChanged()
regExp.setPattern(searchField->text());
filterBookmarkModel->setSourceModel(bookmarkManager->listBookmarkModel());
} else {
- regExp.setPattern(QLatin1String(""));
+ regExp.setPattern(QString());
filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel());
}
@@ -366,7 +366,7 @@ void BookmarkWidget::customContextMenuRequested(const QPoint &point)
QAction *renameItem = 0;
QAction *showItemNewTab = 0;
- QMenu menu(QLatin1String(""), this);
+ QMenu menu(this);
QString data = index.data(Qt::UserRole + 10).toString();
if (data == QLatin1String("Folder")) {
removeItem = menu.addAction(tr("Delete Folder"));
diff --git a/src/tools/clangbackend/clangbackend.pro b/src/tools/clangbackend/clangbackend.pro
index f75775c8e7..32ca5f0842 100644
--- a/src/tools/clangbackend/clangbackend.pro
+++ b/src/tools/clangbackend/clangbackend.pro
@@ -1,10 +1,10 @@
QTC_LIB_DEPENDS += \
sqlite \
- clangbackendipc
+ clangsupport
include(../../qtcreatortool.pri)
include(../../shared/clang/clang_installation.pri)
-include(ipcsource/clangbackendclangipc-source.pri)
+include(source/clangbackendclangipc-source.pri)
QT += core network
QT -= gui
diff --git a/src/tools/clangbackend/clangbackend.qbs b/src/tools/clangbackend/clangbackend.qbs
index 457c218501..495c586f85 100644
--- a/src/tools/clangbackend/clangbackend.qbs
+++ b/src/tools/clangbackend/clangbackend.qbs
@@ -3,11 +3,11 @@ import qbs 1.0
QtcTool {
name: "clangbackend"
- Depends { name: "ClangBackEndIpc" }
+ Depends { name: "ClangSupport" }
Depends { name: "libclang"; required: false }
Group {
- prefix: "ipcsource/"
+ prefix: "source/"
files: [
"*.h",
"*.cpp"
@@ -26,7 +26,7 @@ QtcTool {
condition: libclang.present
- cpp.includePaths: base.concat(["ipcsource", libclang.llvmIncludeDir])
+ cpp.includePaths: base.concat(["source", libclang.llvmIncludeDir])
cpp.libraryPaths: base.concat(libclang.llvmLibDir)
cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
cpp.rpaths: base.concat(libclang.llvmLibDir)
diff --git a/src/tools/clangbackend/ipcsource/clangiasyncjob.cpp b/src/tools/clangbackend/ipcsource/clangiasyncjob.cpp
deleted file mode 100644
index db3aebfe8e..0000000000
--- a/src/tools/clangbackend/ipcsource/clangiasyncjob.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangiasyncjob.h"
-
-#include "clangcompletecodejob.h"
-#include "clangcreateinitialdocumentpreamblejob.h"
-#include "clangparsesupportivetranslationunitjob.h"
-#include "clangreparsesupportivetranslationunitjob.h"
-#include "clangrequestdocumentannotationsjob.h"
-#include "clangrequestreferencesjob.h"
-#include "clangresumedocumentjob.h"
-#include "clangsuspenddocumentjob.h"
-#include "clangupdatedocumentannotationsjob.h"
-
-Q_LOGGING_CATEGORY(jobsLog, "qtc.clangbackend.jobs");
-
-namespace ClangBackEnd {
-
-IAsyncJob *IAsyncJob::create(JobRequest::Type type)
-{
- switch (type) {
- case JobRequest::Type::UpdateDocumentAnnotations:
- return new UpdateDocumentAnnotationsJob();
- case JobRequest::Type::ParseSupportiveTranslationUnit:
- return new ParseSupportiveTranslationUnitJob();
- case JobRequest::Type::ReparseSupportiveTranslationUnit:
- return new ReparseSupportiveTranslationUnitJob();
- case JobRequest::Type::CreateInitialDocumentPreamble:
- return new CreateInitialDocumentPreambleJob();
- case JobRequest::Type::CompleteCode:
- return new CompleteCodeJob();
- case JobRequest::Type::RequestDocumentAnnotations:
- return new RequestDocumentAnnotationsJob();
- case JobRequest::Type::RequestReferences:
- return new RequestReferencesJob();
- case JobRequest::Type::SuspendDocument:
- return new SuspendDocumentJob();
- case JobRequest::Type::ResumeDocument:
- return new ResumeDocumentJob();
- }
-
- return nullptr;
-}
-
-IAsyncJob::IAsyncJob()
- : m_context(JobContext())
-{
-}
-
-IAsyncJob::~IAsyncJob()
-{
-}
-
-JobContext IAsyncJob::context() const
-{
- return m_context;
-}
-
-void IAsyncJob::setContext(const JobContext &context)
-{
- m_context = context;
-}
-
-IAsyncJob::FinishedHandler IAsyncJob::finishedHandler() const
-{
- return m_finishedHandler;
-}
-
-void IAsyncJob::setFinishedHandler(const IAsyncJob::FinishedHandler &finishedHandler)
-{
- m_finishedHandler = finishedHandler;
-}
-
-bool IAsyncJob::isFinished() const
-{
- return m_isFinished;
-}
-
-void IAsyncJob::setIsFinished(bool isFinished)
-{
- m_isFinished = isFinished;
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp
deleted file mode 100644
index fa8937c195..0000000000
--- a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangparsesupportivetranslationunitjob.h"
-
-#include <clangbackendipc/clangbackendipcdebugutils.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-static ParseSupportiveTranslationUnitJob::AsyncResult runAsyncHelper(
- const TranslationUnit &translationUnit,
- const TranslationUnitUpdateInput &translationUnitUpdateInput)
-{
- TIME_SCOPE_DURATION("ParseSupportiveTranslationUnitJob");
-
- TranslationUnitUpdateInput updateInput = translationUnitUpdateInput;
- updateInput.parseNeeded = true;
-
- ParseSupportiveTranslationUnitJob::AsyncResult asyncResult;
- asyncResult.updateResult = translationUnit.update(updateInput);
-
- return asyncResult;
-}
-
-IAsyncJob::AsyncPrepareResult ParseSupportiveTranslationUnitJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::ParseSupportiveTranslationUnit, return AsyncPrepareResult());
-
- try {
- m_pinnedDocument = context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
-
- const TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
- setRunner([translationUnit, updateInput]() {
- return runAsyncHelper(translationUnit, updateInput);
- });
- return AsyncPrepareResult{translationUnit.id()};
-
- } catch (const std::exception &exception) {
- qWarning() << "Error in ParseForSupportiveTranslationUnitJob::prepareAsyncRun:"
- << exception.what();
- return AsyncPrepareResult();
- }
-}
-
-void ParseSupportiveTranslationUnitJob::finalizeAsyncRun()
-{
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp b/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp
deleted file mode 100644
index 45b06c0203..0000000000
--- a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangrequestdocumentannotationsjob.h"
-
-#include <clangbackendipc/clangbackendipcdebugutils.h>
-#include <clangbackendipc/documentannotationschangedmessage.h>
-#include <clangbackendipc/clangcodemodelclientinterface.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-static RequestDocumentAnnotationsJob::AsyncResult runAsyncHelper(
- const TranslationUnit &translationUnit)
-{
- TIME_SCOPE_DURATION("RequestDocumentAnnotationsJobRunner");
-
- RequestDocumentAnnotationsJob::AsyncResult asyncResult;
-
- translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic,
- asyncResult.diagnostics,
- asyncResult.highlightingMarks,
- asyncResult.skippedSourceRanges);
-
- return asyncResult;
-}
-
-IAsyncJob::AsyncPrepareResult RequestDocumentAnnotationsJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestDocumentAnnotations,
- return AsyncPrepareResult());
-
- try {
- m_pinnedDocument = context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
-
- const TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- setRunner([translationUnit]() {
- return runAsyncHelper(translationUnit);
- });
- return AsyncPrepareResult{translationUnit.id()};
-
- } catch (const std::exception &exception) {
- qWarning() << "Error in RequestDocumentAnnotationsJob::prepareAsyncRun:" << exception.what();
- return AsyncPrepareResult();
- }
-}
-
-void RequestDocumentAnnotationsJob::finalizeAsyncRun()
-{
- if (context().isDocumentOpen()) {
- const AsyncResult result = asyncResult();
- sendAnnotations(result);
- }
-}
-
-void RequestDocumentAnnotationsJob::sendAnnotations(
- const RequestDocumentAnnotationsJob::AsyncResult &result)
-{
- const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer,
- result.diagnostics,
- result.firstHeaderErrorDiagnostic,
- result.highlightingMarks,
- result.skippedSourceRanges);
-
- context().client->documentAnnotationsChanged(message);
-}
-
-} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp b/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp
deleted file mode 100644
index b4b56fe534..0000000000
--- a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangupdatedocumentannotationsjob.h"
-
-#include <clangbackendipc/clangbackendipcdebugutils.h>
-#include <clangbackendipc/clangcodemodelclientinterface.h>
-#include <clangbackendipc/documentannotationschangedmessage.h>
-
-#include <utils/qtcassert.h>
-
-namespace ClangBackEnd {
-
-static UpdateDocumentAnnotationsJob::AsyncResult runAsyncHelper(
- const TranslationUnit &translationUnit,
- const TranslationUnitUpdateInput &translationUnitUpdatInput)
-{
- TIME_SCOPE_DURATION("UpdateDocumentAnnotationsJobRunner");
-
- UpdateDocumentAnnotationsJob::AsyncResult asyncResult;
-
- // Update
- asyncResult.updateResult = translationUnit.update(translationUnitUpdatInput);
-
- // Collect
- translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic,
- asyncResult.diagnostics,
- asyncResult.highlightingMarks,
- asyncResult.skippedSourceRanges);
-
- return asyncResult;
-}
-
-IAsyncJob::AsyncPrepareResult UpdateDocumentAnnotationsJob::prepareAsyncRun()
-{
- const JobRequest jobRequest = context().jobRequest;
- QTC_ASSERT(isExpectedJobRequestType(jobRequest), return AsyncPrepareResult());
-
- try {
- m_pinnedDocument = context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
-
- const TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- const TranslationUnitUpdateInput updateInput = createUpdateInput(m_pinnedDocument);
- setRunner([translationUnit, updateInput]() {
- return runAsyncHelper(translationUnit, updateInput);
- });
- return AsyncPrepareResult{translationUnit.id()};
-
- } catch (const std::exception &exception) {
- qWarning() << "Error in UpdateDocumentAnnotationsJob::prepareAsyncRun:" << exception.what();
- return AsyncPrepareResult();
- }
-}
-
-void UpdateDocumentAnnotationsJob::finalizeAsyncRun()
-{
- if (!context().isOutdated()) {
- const AsyncResult result = asyncResult();
-
- incorporateUpdaterResult(result);
- sendAnnotations(result);
- }
-}
-
-bool UpdateDocumentAnnotationsJob::isExpectedJobRequestType(const JobRequest &jobRequest) const
-{
- return jobRequest.type == JobRequest::Type::UpdateDocumentAnnotations;
-}
-
-TranslationUnitUpdateInput
-UpdateDocumentAnnotationsJob::createUpdateInput(const Document &document) const
-{
- return document.createUpdateInput();
-}
-
-void UpdateDocumentAnnotationsJob::incorporateUpdaterResult(const AsyncResult &result)
-{
- m_pinnedDocument.incorporateUpdaterResult(result.updateResult);
-}
-
-void UpdateDocumentAnnotationsJob::sendAnnotations(const AsyncResult &result)
-{
- const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer,
- result.diagnostics,
- result.firstHeaderErrorDiagnostic,
- result.highlightingMarks,
- result.skippedSourceRanges);
-
- context().client->documentAnnotationsChanged(message);
-}
-
-} // namespace ClangBackEnd
-
diff --git a/src/tools/clangbackend/ipcsource/clangasyncjob.h b/src/tools/clangbackend/source/clangasyncjob.h
index c8a7b79947..58b6a1f845 100644
--- a/src/tools/clangbackend/ipcsource/clangasyncjob.h
+++ b/src/tools/clangbackend/source/clangasyncjob.h
@@ -47,7 +47,7 @@ public:
Result asyncResult() const { return m_futureWatcher.future().result(); }
- QFuture<void> runAsync() override
+ QFuture<void> runAsync() final
{
const auto onFinished = [this]() {
finalizeAsyncRun();
@@ -64,7 +64,7 @@ public:
return future;
}
- void preventFinalization() override
+ void preventFinalization() final
{
m_futureWatcher.disconnect();
}
diff --git a/src/tools/clangbackend/ipcsource/clangbackend_global.h b/src/tools/clangbackend/source/clangbackend_global.h
index d806afc98c..d806afc98c 100644
--- a/src/tools/clangbackend/ipcsource/clangbackend_global.h
+++ b/src/tools/clangbackend/source/clangbackend_global.h
diff --git a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri b/src/tools/clangbackend/source/clangbackendclangipc-source.pri
index 877d63ca9c..6919db6839 100644
--- a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri
+++ b/src/tools/clangbackend/source/clangbackendclangipc-source.pri
@@ -9,6 +9,7 @@ HEADERS += \
$$PWD/clangcompletecodejob.h \
$$PWD/clangcreateinitialdocumentpreamblejob.h \
$$PWD/clangdocument.h \
+ $$PWD/clangdocumentjob.h \
$$PWD/clangdocumentprocessor.h \
$$PWD/clangdocumentprocessors.h \
$$PWD/clangdocuments.h \
@@ -16,6 +17,8 @@ HEADERS += \
$$PWD/clangexceptions.h \
$$PWD/clangfilepath.h \
$$PWD/clangfilesystemwatcher.h \
+ $$PWD/clangfollowsymboljob.h \
+ $$PWD/clangfollowsymbol.h \
$$PWD/clangiasyncjob.h \
$$PWD/clangjobcontext.h \
$$PWD/clangjobqueue.h \
@@ -55,7 +58,7 @@ HEADERS += \
$$PWD/sourcerange.h \
$$PWD/unsavedfile.h \
$$PWD/unsavedfiles.h \
- $$PWD/utf8positionfromlinecolumn.h \
+ $$PWD/utf8positionfromlinecolumn.h
SOURCES += \
$$PWD/clangcodecompleteresults.cpp \
@@ -70,6 +73,8 @@ SOURCES += \
$$PWD/clangexceptions.cpp \
$$PWD/clangfilepath.cpp \
$$PWD/clangfilesystemwatcher.cpp \
+ $$PWD/clangfollowsymboljob.cpp \
+ $$PWD/clangfollowsymbol.cpp \
$$PWD/clangiasyncjob.cpp \
$$PWD/clangjobcontext.cpp \
$$PWD/clangjobqueue.cpp \
@@ -106,4 +111,4 @@ SOURCES += \
$$PWD/sourcerange.cpp \
$$PWD/unsavedfile.cpp \
$$PWD/unsavedfiles.cpp \
- $$PWD/utf8positionfromlinecolumn.cpp \
+ $$PWD/utf8positionfromlinecolumn.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangclock.h b/src/tools/clangbackend/source/clangclock.h
index 68d91478f7..68d91478f7 100644
--- a/src/tools/clangbackend/ipcsource/clangclock.h
+++ b/src/tools/clangbackend/source/clangclock.h
diff --git a/src/tools/clangbackend/ipcsource/clangcodecompleteresults.cpp b/src/tools/clangbackend/source/clangcodecompleteresults.cpp
index af80d739bf..af80d739bf 100644
--- a/src/tools/clangbackend/ipcsource/clangcodecompleteresults.cpp
+++ b/src/tools/clangbackend/source/clangcodecompleteresults.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangcodecompleteresults.h b/src/tools/clangbackend/source/clangcodecompleteresults.h
index 0b1ae11df8..0b1ae11df8 100644
--- a/src/tools/clangbackend/ipcsource/clangcodecompleteresults.h
+++ b/src/tools/clangbackend/source/clangcodecompleteresults.h
diff --git a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp b/src/tools/clangbackend/source/clangcodemodelserver.cpp
index 6dae8b266f..9def46b2db 100644
--- a/src/tools/clangbackend/ipcsource/clangcodemodelserver.cpp
+++ b/src/tools/clangbackend/source/clangcodemodelserver.cpp
@@ -35,8 +35,8 @@
#include "clangexceptions.h"
#include "skippedsourceranges.h"
-#include <clangbackendipc/clangbackendipcdebugutils.h>
-#include <clangbackendipc/clangcodemodelservermessages.h>
+#include <clangsupport/clangsupportdebugutils.h>
+#include <clangsupport/clangcodemodelservermessages.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -212,6 +212,8 @@ void ClangCodeModelServer::completeCode(const ClangBackEnd::CompleteCodeMessage
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::CompleteCode);
jobRequest.line = message.line();
jobRequest.column = message.column();
+ jobRequest.funcNameStartLine = message.funcNameStartLine();
+ jobRequest.funcNameStartColumn = message.funcNameStartColumn();
jobRequest.ticketNumber = message.ticketNumber();
processor.addJob(jobRequest);
@@ -237,6 +239,17 @@ void ClangCodeModelServer::requestDocumentAnnotations(const RequestDocumentAnnot
}
}
+template <class MessageType>
+static void fillJobRequest(JobRequest &jobRequest, const MessageType &message)
+{
+ jobRequest.line = message.line();
+ jobRequest.column = message.column();
+ jobRequest.ticketNumber = message.ticketNumber();
+ // The unsaved files might get updater later, so take the current
+ // revision for the request.
+ jobRequest.documentRevision = message.fileContainer().documentRevision();
+}
+
void ClangCodeModelServer::requestReferences(const RequestReferencesMessage &message)
{
TIME_SCOPE_DURATION("ClangCodeModelServer::requestReferences");
@@ -247,13 +260,7 @@ void ClangCodeModelServer::requestReferences(const RequestReferencesMessage &mes
DocumentProcessor processor = documentProcessors().processor(document);
JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::RequestReferences);
- jobRequest.line = message.line();
- jobRequest.column = message.column();
- jobRequest.ticketNumber = message.ticketNumber();
- // The unsaved files might get updater later, so take the current
- // revision for the request.
- jobRequest.documentRevision = message.fileContainer().documentRevision();
-
+ fillJobRequest(jobRequest, message);
processor.addJob(jobRequest);
processor.process();
} catch (const std::exception &exception) {
@@ -261,6 +268,26 @@ void ClangCodeModelServer::requestReferences(const RequestReferencesMessage &mes
}
}
+void ClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage &message)
+{
+ TIME_SCOPE_DURATION("ClangCodeModelServer::requestFollowSymbol");
+
+ try {
+ auto projectPartId = message.fileContainer().projectPartId();
+ Document document = documents.document(message.fileContainer().filePath(),
+ projectPartId);
+ DocumentProcessor processor = documentProcessors().processor(document);
+
+ JobRequest jobRequest = processor.createJobRequest(JobRequest::Type::FollowSymbol);
+ fillJobRequest(jobRequest, message);
+ jobRequest.dependentFiles = message.dependentFiles();
+ processor.addJob(jobRequest);
+ processor.process();
+ } catch (const std::exception &exception) {
+ qWarning() << "Error in ClangCodeModelServer::requestFollowSymbol:" << exception.what();
+ }
+}
+
void ClangCodeModelServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
TIME_SCOPE_DURATION("ClangCodeModelServer::updateVisibleTranslationUnits");
diff --git a/src/tools/clangbackend/ipcsource/clangcodemodelserver.h b/src/tools/clangbackend/source/clangcodemodelserver.h
index d5fc33250b..5e9e2934a6 100644
--- a/src/tools/clangbackend/ipcsource/clangcodemodelserver.h
+++ b/src/tools/clangbackend/source/clangcodemodelserver.h
@@ -25,8 +25,6 @@
#pragma once
-#include "clangcodemodelserverinterface.h"
-
#include "projectpart.h"
#include "projects.h"
#include "clangdocument.h"
@@ -35,6 +33,8 @@
#include "clangjobrequest.h"
#include "unsavedfiles.h"
+#include <clangcodemodelserverinterface.h>
+#include <ipcclientprovider.h>
#include <utf8string.h>
#include <QScopedPointer>
@@ -42,7 +42,8 @@
namespace ClangBackEnd {
-class ClangCodeModelServer : public ClangCodeModelServerInterface
+class ClangCodeModelServer : public ClangCodeModelServerInterface,
+ public IpcClientProvider<ClangCodeModelClientInterface>
{
public:
ClangCodeModelServer();
@@ -59,6 +60,7 @@ public:
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
+ void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
public: // for tests
const Documents &documentsForTestOnly() const;
diff --git a/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp b/src/tools/clangbackend/source/clangcompletecodejob.cpp
index d45f53fdda..9970d59269 100644
--- a/src/tools/clangbackend/ipcsource/clangcompletecodejob.cpp
+++ b/src/tools/clangbackend/source/clangcompletecodejob.cpp
@@ -25,53 +25,43 @@
#include "clangcompletecodejob.h"
-#include <clangbackendipc/clangbackendipcdebugutils.h>
-#include <clangbackendipc/clangcodemodelclientinterface.h>
-#include <clangbackendipc/cmbcodecompletedmessage.h>
+#include <clangsupport/clangsupportdebugutils.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
+#include <clangsupport/cmbcodecompletedmessage.h>
#include <utils/qtcassert.h>
namespace ClangBackEnd {
-static CompleteCodeJob::AsyncResult runAsyncHelper(const TranslationUnit &translationUnit,
- UnsavedFiles unsavedFiles,
- quint32 line,
- quint32 column)
-{
- TIME_SCOPE_DURATION("CompleteCodeJobRunner");
-
- const TranslationUnit::CodeCompletionResult results
- = translationUnit.complete(unsavedFiles, line, column);
-
- CompleteCodeJob::AsyncResult asyncResult;
- asyncResult.completions = results.completions;
- asyncResult.correction = results.correction;
-
- return asyncResult;
-}
-
IAsyncJob::AsyncPrepareResult CompleteCodeJob::prepareAsyncRun()
{
const JobRequest jobRequest = context().jobRequest;
QTC_ASSERT(jobRequest.type == JobRequest::Type::CompleteCode, return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
- try {
- m_pinnedDocument = context().documentForJobRequest();
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const UnsavedFiles unsavedFiles = *context().unsavedFiles;
+ const quint32 line = jobRequest.line;
+ const quint32 column = jobRequest.column;
+ const qint32 funcNameStartLine = jobRequest.funcNameStartLine;
+ const qint32 funcNameStartColumn = jobRequest.funcNameStartColumn;
+ setRunner([translationUnit, unsavedFiles, line, column,
+ funcNameStartLine, funcNameStartColumn]() {
+ TIME_SCOPE_DURATION("CompleteCodeJobRunner");
- const TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- const UnsavedFiles unsavedFiles = *context().unsavedFiles;
- const quint32 line = jobRequest.line;
- const quint32 column = jobRequest.column;
- setRunner([translationUnit, unsavedFiles, line, column]() {
- return runAsyncHelper(translationUnit, unsavedFiles, line, column);
- });
- return AsyncPrepareResult{translationUnit.id()};
+ UnsavedFiles theUnsavedFiles = unsavedFiles;
+ const TranslationUnit::CodeCompletionResult results
+ = translationUnit.complete(theUnsavedFiles, line, column,
+ funcNameStartLine, funcNameStartColumn);
- } catch (const std::exception &exception) {
- qWarning() << "Error in CompleteCodeJob::prepareAsyncRun:" << exception.what();
- return AsyncPrepareResult();
- }
+ CompleteCodeJob::AsyncResult asyncResult;
+ asyncResult.completions = results.completions;
+ asyncResult.correction = results.correction;
+
+ return asyncResult;
+ });
+
+ return AsyncPrepareResult{translationUnit.id()};
}
void CompleteCodeJob::finalizeAsyncRun()
diff --git a/src/tools/clangbackend/ipcsource/clangcompletecodejob.h b/src/tools/clangbackend/source/clangcompletecodejob.h
index 142988d740..4e9c274faf 100644
--- a/src/tools/clangbackend/ipcsource/clangcompletecodejob.h
+++ b/src/tools/clangbackend/source/clangcompletecodejob.h
@@ -25,10 +25,9 @@
#pragma once
-#include "clangasyncjob.h"
-#include "clangdocument.h"
+#include "clangdocumentjob.h"
-#include <clangbackendipc/codecompletion.h>
+#include <clangsupport/codecompletion.h>
namespace ClangBackEnd {
@@ -38,16 +37,13 @@ struct CompleteCodeJobResult
CompletionCorrection correction = CompletionCorrection::NoCorrection;
};
-class CompleteCodeJob : public AsyncJob<CompleteCodeJobResult>
+class CompleteCodeJob : public DocumentJob<CompleteCodeJobResult>
{
public:
using AsyncResult = CompleteCodeJobResult;
AsyncPrepareResult prepareAsyncRun() override;
void finalizeAsyncRun() override;
-
-private:
- Document m_pinnedDocument;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp b/src/tools/clangbackend/source/clangcreateinitialdocumentpreamblejob.cpp
index a9bf669866..aab58b0edb 100644
--- a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.cpp
+++ b/src/tools/clangbackend/source/clangcreateinitialdocumentpreamblejob.cpp
@@ -25,42 +25,26 @@
#include "clangcreateinitialdocumentpreamblejob.h"
-#include <clangbackendipc/clangbackendipcdebugutils.h>
+#include <clangsupport/clangsupportdebugutils.h>
#include <utils/qtcassert.h>
namespace ClangBackEnd {
-static void runAsyncHelper(const TranslationUnit &translationUnit,
- const TranslationUnitUpdateInput &translationUnitUpdateInput)
-{
- TIME_SCOPE_DURATION("CreateInitialDocumentPreambleJobRunner");
-
- translationUnit.reparse(translationUnitUpdateInput);
-}
-
IAsyncJob::AsyncPrepareResult CreateInitialDocumentPreambleJob::prepareAsyncRun()
{
const JobRequest jobRequest = context().jobRequest;
QTC_ASSERT(jobRequest.type == JobRequest::Type::CreateInitialDocumentPreamble, return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
- try {
- m_pinnedDocument = context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
-
- const TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
- setRunner([translationUnit, updateInput]() {
- return runAsyncHelper(translationUnit, updateInput);
- });
- return AsyncPrepareResult{translationUnit.id()};
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
+ setRunner([translationUnit, updateInput]() {
+ TIME_SCOPE_DURATION("CreateInitialDocumentPreambleJobRunner");
+ translationUnit.reparse(updateInput);
+ });
- } catch (const std::exception &exception) {
- qWarning() << "Error in CreateInitialDocumentPreambleJob::prepareAsyncRun:"
- << exception.what();
- return AsyncPrepareResult();
- }
+ return AsyncPrepareResult{translationUnit.id()};
}
void CreateInitialDocumentPreambleJob::finalizeAsyncRun()
diff --git a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.h b/src/tools/clangbackend/source/clangcreateinitialdocumentpreamblejob.h
index 570b746460..f8b790ea36 100644
--- a/src/tools/clangbackend/ipcsource/clangcreateinitialdocumentpreamblejob.h
+++ b/src/tools/clangbackend/source/clangcreateinitialdocumentpreamblejob.h
@@ -25,20 +25,15 @@
#pragma once
-#include "clangasyncjob.h"
-#include "clangdocument.h"
+#include "clangdocumentjob.h"
namespace ClangBackEnd {
-class CreateInitialDocumentPreambleJob : public AsyncJob<void>
+class CreateInitialDocumentPreambleJob : public DocumentJob<void>
{
public:
AsyncPrepareResult prepareAsyncRun() override;
void finalizeAsyncRun() override;
-
-private:
- Document m_pinnedDocument;
- FileContainer m_pinnedFileContainer;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangdocument.cpp b/src/tools/clangbackend/source/clangdocument.cpp
index cbbaf51b33..cbbaf51b33 100644
--- a/src/tools/clangbackend/ipcsource/clangdocument.cpp
+++ b/src/tools/clangbackend/source/clangdocument.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangdocument.h b/src/tools/clangbackend/source/clangdocument.h
index 415deefbe9..415deefbe9 100644
--- a/src/tools/clangbackend/ipcsource/clangdocument.h
+++ b/src/tools/clangbackend/source/clangdocument.h
diff --git a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h b/src/tools/clangbackend/source/clangdocumentjob.h
index 6d4d01131e..7808286ce0 100644
--- a/src/tools/clangbackend/ipcsource/clangparsesupportivetranslationunitjob.h
+++ b/src/tools/clangbackend/source/clangdocumentjob.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -28,24 +28,37 @@
#include "clangasyncjob.h"
#include "clangdocument.h"
-namespace ClangBackEnd {
+#include <clangsupport/filecontainer.h>
-struct ParseSupportiveTranslationUnitJobResult
-{
- TranslationUnitUpdateResult updateResult;
-};
+#include <memory>
-class ParseSupportiveTranslationUnitJob : public AsyncJob<ParseSupportiveTranslationUnitJobResult>
+namespace ClangBackEnd {
+
+template<class Result>
+class DocumentJob : public AsyncJob<Result>
{
-public:
- using AsyncResult = ParseSupportiveTranslationUnitJobResult;
+protected:
+ bool acquireDocument()
+ {
+ try {
+ m_pinnedDocument = IAsyncJob::context().documentForJobRequest();
+ m_pinnedFileContainer = m_pinnedDocument.fileContainer();
- AsyncPrepareResult prepareAsyncRun() override;
- void finalizeAsyncRun() override;
+ const PreferredTranslationUnit preferredTranslationUnit
+ = IAsyncJob::context().jobRequest.preferredTranslationUnit;
+ m_translationUnit.reset(
+ new TranslationUnit(m_pinnedDocument.translationUnit(preferredTranslationUnit)));
+ return true;
+ } catch (const std::exception &) {
+ return false;
+ }
+ }
-private:
+protected:
Document m_pinnedDocument;
FileContainer m_pinnedFileContainer;
+
+ std::unique_ptr<TranslationUnit> m_translationUnit;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangdocumentprocessor.cpp b/src/tools/clangbackend/source/clangdocumentprocessor.cpp
index 1aa5906214..1aa5906214 100644
--- a/src/tools/clangbackend/ipcsource/clangdocumentprocessor.cpp
+++ b/src/tools/clangbackend/source/clangdocumentprocessor.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangdocumentprocessor.h b/src/tools/clangbackend/source/clangdocumentprocessor.h
index 9c3fb147f9..9c3fb147f9 100644
--- a/src/tools/clangbackend/ipcsource/clangdocumentprocessor.h
+++ b/src/tools/clangbackend/source/clangdocumentprocessor.h
diff --git a/src/tools/clangbackend/ipcsource/clangdocumentprocessors.cpp b/src/tools/clangbackend/source/clangdocumentprocessors.cpp
index 611611a41f..611611a41f 100644
--- a/src/tools/clangbackend/ipcsource/clangdocumentprocessors.cpp
+++ b/src/tools/clangbackend/source/clangdocumentprocessors.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangdocumentprocessors.h b/src/tools/clangbackend/source/clangdocumentprocessors.h
index 83e37f5276..83e37f5276 100644
--- a/src/tools/clangbackend/ipcsource/clangdocumentprocessors.h
+++ b/src/tools/clangbackend/source/clangdocumentprocessors.h
diff --git a/src/tools/clangbackend/ipcsource/clangdocuments.cpp b/src/tools/clangbackend/source/clangdocuments.cpp
index 5fc8f294a7..5fc8f294a7 100644
--- a/src/tools/clangbackend/ipcsource/clangdocuments.cpp
+++ b/src/tools/clangbackend/source/clangdocuments.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangdocuments.h b/src/tools/clangbackend/source/clangdocuments.h
index a267becc27..a267becc27 100644
--- a/src/tools/clangbackend/ipcsource/clangdocuments.h
+++ b/src/tools/clangbackend/source/clangdocuments.h
diff --git a/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.cpp b/src/tools/clangbackend/source/clangdocumentsuspenderresumer.cpp
index bae9889318..cd0e29b5d0 100644
--- a/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.cpp
+++ b/src/tools/clangbackend/source/clangdocumentsuspenderresumer.cpp
@@ -25,7 +25,7 @@
#include "clangdocumentsuspenderresumer.h"
-#include "clangbackendipc_global.h"
+#include "clangsupport_global.h"
#include "clangdocumentprocessors.h"
#include "clangdocuments.h"
diff --git a/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.h b/src/tools/clangbackend/source/clangdocumentsuspenderresumer.h
index 7e2bd8722d..7e2bd8722d 100644
--- a/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.h
+++ b/src/tools/clangbackend/source/clangdocumentsuspenderresumer.h
diff --git a/src/tools/clangbackend/ipcsource/clangexceptions.cpp b/src/tools/clangbackend/source/clangexceptions.cpp
index 62527b6ce7..62527b6ce7 100644
--- a/src/tools/clangbackend/ipcsource/clangexceptions.cpp
+++ b/src/tools/clangbackend/source/clangexceptions.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangexceptions.h b/src/tools/clangbackend/source/clangexceptions.h
index ffc1c09da1..ffc1c09da1 100644
--- a/src/tools/clangbackend/ipcsource/clangexceptions.h
+++ b/src/tools/clangbackend/source/clangexceptions.h
diff --git a/src/tools/clangbackend/ipcsource/clangfilepath.cpp b/src/tools/clangbackend/source/clangfilepath.cpp
index a5fc26b11d..a5fc26b11d 100644
--- a/src/tools/clangbackend/ipcsource/clangfilepath.cpp
+++ b/src/tools/clangbackend/source/clangfilepath.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangfilepath.h b/src/tools/clangbackend/source/clangfilepath.h
index 014c0129ed..014c0129ed 100644
--- a/src/tools/clangbackend/ipcsource/clangfilepath.h
+++ b/src/tools/clangbackend/source/clangfilepath.h
diff --git a/src/tools/clangbackend/ipcsource/clangfilesystemwatcher.cpp b/src/tools/clangbackend/source/clangfilesystemwatcher.cpp
index a51676abe0..a51676abe0 100644
--- a/src/tools/clangbackend/ipcsource/clangfilesystemwatcher.cpp
+++ b/src/tools/clangbackend/source/clangfilesystemwatcher.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangfilesystemwatcher.h b/src/tools/clangbackend/source/clangfilesystemwatcher.h
index 549870eab0..549870eab0 100644
--- a/src/tools/clangbackend/ipcsource/clangfilesystemwatcher.h
+++ b/src/tools/clangbackend/source/clangfilesystemwatcher.h
diff --git a/src/tools/clangbackend/source/clangfollowsymbol.cpp b/src/tools/clangbackend/source/clangfollowsymbol.cpp
new file mode 100644
index 0000000000..bc151bc93c
--- /dev/null
+++ b/src/tools/clangbackend/source/clangfollowsymbol.cpp
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangfollowsymbol.h"
+#include "clangfollowsymboljob.h"
+#include "commandlinearguments.h"
+#include "cursor.h"
+#include "clangstring.h"
+#include "sourcerange.h"
+#include "clangsupportdebugutils.h"
+
+#include <utils/qtcassert.h>
+
+#include <future>
+
+namespace ClangBackEnd {
+
+namespace {
+
+struct Tokens
+{
+ Tokens(const Tokens &) = delete;
+ Tokens(const Cursor &cursor) {
+ tu = cursor.cxTranslationUnit();
+ clang_tokenize(tu, cursor.cxSourceRange(), &data, &tokenCount);
+ }
+ Tokens(const CXTranslationUnit &tu) {
+ const CXSourceRange range
+ = clang_getCursorExtent(clang_getTranslationUnitCursor(tu));
+ clang_tokenize(tu, range, &data, &tokenCount);
+ }
+ ~Tokens() {
+ clang_disposeTokens(tu, data, tokenCount);
+ }
+
+ CXToken *data = nullptr;
+ uint tokenCount = 0;
+private:
+ CXTranslationUnit tu;
+};
+
+class FollowSymbolData {
+public:
+ FollowSymbolData() = delete;
+ FollowSymbolData(const Utf8String &usr, const Utf8String &tokenSpelling, bool isFunctionLike,
+ std::atomic<bool> &ready)
+ : m_usr(usr)
+ , m_spelling(tokenSpelling)
+ , m_isFunctionLike(isFunctionLike)
+ , m_ready(ready)
+ {}
+ FollowSymbolData(const FollowSymbolData &other)
+ : m_usr(other.m_usr)
+ , m_spelling(other.m_spelling)
+ , m_isFunctionLike(other.m_isFunctionLike)
+ , m_ready(other.m_ready)
+ {}
+
+ const Utf8String &usr() const { return m_usr; }
+ const Utf8String &spelling() const { return m_spelling; }
+ bool isFunctionLike() const { return m_isFunctionLike; }
+ bool ready() const { return m_ready; }
+ const SourceRangeContainer &result() const { return m_result; }
+
+ void setReady(bool ready = true) { m_ready = ready; }
+ void setResult(const SourceRangeContainer &result) { m_result = result; }
+private:
+ const Utf8String &m_usr;
+ const Utf8String &m_spelling;
+ SourceRangeContainer m_result;
+ bool m_isFunctionLike;
+ std::atomic<bool> &m_ready;
+};
+
+} // anonymous namespace
+
+static SourceRange getOperatorRange(const CXTranslationUnit tu,
+ const Tokens &tokens,
+ uint operatorIndex)
+{
+ const CXSourceLocation start = clang_getTokenLocation(tu, tokens.data[operatorIndex]);
+ operatorIndex += 2;
+ while (operatorIndex < tokens.tokenCount
+ && !(ClangString(clang_getTokenSpelling(tu, tokens.data[operatorIndex])) == "(")) {
+ ++operatorIndex;
+ }
+ const CXSourceLocation end = clang_getTokenLocation(tu, tokens.data[operatorIndex]);
+ return SourceRange(clang_getRange(start, end));
+}
+
+static SourceRangeContainer extractMatchingTokenRange(const Cursor &cursor,
+ const Utf8String &tokenStr)
+{
+ Tokens tokens(cursor);
+ const CXTranslationUnit tu = cursor.cxTranslationUnit();
+ for (uint i = 0; i < tokens.tokenCount; ++i) {
+ if (!(tokenStr == ClangString(clang_getTokenSpelling(tu, tokens.data[i]))))
+ continue;
+
+ if (cursor.isFunctionLike() || cursor.isConstructorOrDestructor()) {
+ if (tokenStr == "operator")
+ return getOperatorRange(tu, tokens, i);
+
+ if (i+1 > tokens.tokenCount
+ || !(ClangString(clang_getTokenSpelling(tu, tokens.data[i+1])) == "(")) {
+ continue;
+ }
+ }
+ return SourceRange(clang_getTokenExtent(tu, tokens.data[i]));
+ }
+ return SourceRangeContainer();
+}
+
+static void handleDeclaration(CXClientData client_data, const CXIdxDeclInfo *declInfo)
+{
+ if (!declInfo || !declInfo->isDefinition)
+ return;
+
+ const Cursor currentCursor(declInfo->cursor);
+ auto* data = reinterpret_cast<FollowSymbolData*>(client_data);
+ if (data->ready())
+ return;
+
+ if (data->usr() != currentCursor.canonical().unifiedSymbolResolution())
+ return;
+
+ QString str = Utf8String(currentCursor.displayName());
+ if (currentCursor.isFunctionLike() || currentCursor.isConstructorOrDestructor()) {
+ if (!data->isFunctionLike())
+ return;
+ str = str.mid(0, str.indexOf('('));
+ } else if (data->isFunctionLike()) {
+ return;
+ }
+ if (!str.endsWith(data->spelling()))
+ return;
+ const CXTranslationUnit tu = clang_Cursor_getTranslationUnit(declInfo->cursor);
+ Tokens tokens(currentCursor);
+
+ for (uint i = 0; i < tokens.tokenCount; ++i) {
+ Utf8String curSpelling = ClangString(clang_getTokenSpelling(tu, tokens.data[i]));
+ if (data->spelling() == curSpelling) {
+ if (data->isFunctionLike()
+ && (i+1 >= tokens.tokenCount
+ || !(ClangString(clang_getTokenSpelling(tu, tokens.data[i+1])) == "("))) {
+ continue;
+ }
+ data->setResult(SourceRange(clang_getTokenExtent(tu, tokens.data[i])));
+ data->setReady();
+ return;
+ }
+ }
+}
+
+static int getTokenIndex(CXTranslationUnit tu, const Tokens &tokens, uint line, uint column)
+{
+ int tokenIndex = -1;
+ for (int i = static_cast<int>(tokens.tokenCount - 1); i >= 0; --i) {
+ const SourceRange range = clang_getTokenExtent(tu, tokens.data[i]);
+ if (range.contains(line, column)) {
+ tokenIndex = i;
+ break;
+ }
+ }
+ return tokenIndex;
+}
+
+static IndexerCallbacks createIndexerCallbacks()
+{
+ return {
+ [](CXClientData client_data, void *) {
+ auto* data = reinterpret_cast<FollowSymbolData*>(client_data);
+ return data->ready() ? 1 : 0;
+ },
+ [](CXClientData, CXDiagnosticSet, void *) {},
+ [](CXClientData, CXFile, void *) { return CXIdxClientFile(); },
+ [](CXClientData, const CXIdxIncludedFileInfo *) { return CXIdxClientFile(); },
+ [](CXClientData, const CXIdxImportedASTFileInfo *) { return CXIdxClientASTFile(); },
+ [](CXClientData, void *) { return CXIdxClientContainer(); },
+ handleDeclaration,
+ [](CXClientData, const CXIdxEntityRefInfo *) {}
+ };
+}
+
+static SourceRangeContainer followSymbolInDependentFiles(CXIndex index,
+ const Cursor &cursor,
+ const Utf8String &tokenSpelling,
+ const QVector<Utf8String> &dependentFiles,
+ const CommandLineArguments &currentArgs)
+{
+ int argsCount = 0;
+ if (currentArgs.data())
+ argsCount = currentArgs.count() - 1;
+
+ const Utf8String usr = cursor.canonical().unifiedSymbolResolution();
+
+ // ready is shared for all data in vector
+ std::atomic<bool> ready {false};
+ std::vector<FollowSymbolData> dataVector(
+ dependentFiles.size(),
+ FollowSymbolData(usr, tokenSpelling,
+ cursor.isFunctionLike() || cursor.isConstructorOrDestructor(),
+ ready));
+
+ std::vector<std::future<void>> indexFutures;
+
+ for (int i = 0; i < dependentFiles.size(); ++i) {
+ if (i > 0 && ready)
+ break;
+ indexFutures.emplace_back(std::async([&, i]() {
+ TIME_SCOPE_DURATION("Dependent file " + dependentFiles.at(i) + " indexer runner");
+
+ const CXIndexAction indexAction = clang_IndexAction_create(index);
+ IndexerCallbacks callbacks = createIndexerCallbacks();
+ clang_indexSourceFile(indexAction,
+ &dataVector[i],
+ &callbacks,
+ sizeof(callbacks),
+ CXIndexOpt_SkipParsedBodiesInSession
+ | CXIndexOpt_SuppressRedundantRefs
+ | CXIndexOpt_SuppressWarnings,
+ dependentFiles.at(i).constData(),
+ currentArgs.data(),
+ argsCount,
+ nullptr,
+ 0,
+ nullptr,
+ CXTranslationUnit_SkipFunctionBodies
+ | CXTranslationUnit_KeepGoing);
+ clang_IndexAction_dispose(indexAction);
+ }));
+ }
+
+ for (const std::future<void> &future: indexFutures)
+ future.wait();
+
+ for (const FollowSymbolData &data: dataVector) {
+ if (!data.result().start().filePath().isEmpty()) {
+ return data.result();
+ }
+ }
+ return SourceRangeContainer();
+}
+
+SourceRangeContainer FollowSymbol::followSymbol(CXTranslationUnit tu,
+ CXIndex index,
+ const Cursor &fullCursor,
+ uint line,
+ uint column,
+ const QVector<Utf8String> &dependentFiles,
+ const CommandLineArguments &currentArgs)
+{
+ std::unique_ptr<Tokens> tokens(new Tokens(fullCursor));
+
+ if (!tokens->tokenCount)
+ tokens.reset(new Tokens(tu));
+
+ if (!tokens->tokenCount)
+ return SourceRangeContainer();
+
+ QVector<CXCursor> cursors(static_cast<int>(tokens->tokenCount));
+ clang_annotateTokens(tu, tokens->data, tokens->tokenCount, cursors.data());
+ int tokenIndex = getTokenIndex(tu, *tokens, line, column);
+ QTC_ASSERT(tokenIndex >= 0, return SourceRangeContainer());
+
+ const Utf8String tokenSpelling = ClangString(
+ clang_getTokenSpelling(tu, tokens->data[tokenIndex]));
+ if (tokenSpelling.isEmpty())
+ return SourceRangeContainer();
+
+ Cursor cursor{cursors[tokenIndex]};
+
+ if (cursor.kind() == CXCursor_InclusionDirective) {
+ CXFile file = clang_getIncludedFile(cursors[tokenIndex]);
+ const ClangString filename(clang_getFileName(file));
+ const SourceLocation loc(tu, filename, 1, 1);
+ return SourceRange(loc, loc);
+ }
+
+ // For definitions we can always find a declaration in current TU
+ if (cursor.isDefinition())
+ return extractMatchingTokenRange(cursor.canonical(), tokenSpelling);
+
+ SourceRangeContainer result;
+ if (!cursor.isDeclaration()) {
+ // This is the symbol usage
+ // We want to return definition or at least declaration of this symbol
+ const Cursor referencedCursor = cursor.referenced();
+ if (referencedCursor.isNull() || referencedCursor == cursor)
+ return SourceRangeContainer();
+ result = extractMatchingTokenRange(referencedCursor, tokenSpelling);
+
+ // We've already found what we need
+ if (referencedCursor.isDefinition())
+ return result;
+ cursor = referencedCursor;
+ }
+
+ const Cursor definitionCursor = cursor.definition();
+ if (!definitionCursor.isNull() && definitionCursor != cursor) {
+ // If we are able to find a definition in current TU
+ return extractMatchingTokenRange(definitionCursor, tokenSpelling);
+ }
+
+ // Search for the definition in the dependent files
+ SourceRangeContainer dependentFilesResult = followSymbolInDependentFiles(index,
+ cursor,
+ tokenSpelling,
+ dependentFiles,
+ currentArgs);
+ return dependentFilesResult.start().filePath().isEmpty() ?
+ result : dependentFilesResult;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfollowsymbol.h b/src/tools/clangbackend/source/clangfollowsymbol.h
new file mode 100644
index 0000000000..a881bd9631
--- /dev/null
+++ b/src/tools/clangbackend/source/clangfollowsymbol.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QVector>
+
+#include <clang-c/Index.h>
+
+class Utf8String;
+
+namespace ClangBackEnd {
+
+class Cursor;
+class SourceRangeContainer;
+class CommandLineArguments;
+
+class FollowSymbol
+{
+public:
+ static SourceRangeContainer followSymbol(CXTranslationUnit tu,
+ CXIndex index,
+ const Cursor &fullCursor,
+ uint line,
+ uint column,
+ const QVector<Utf8String> &dependentFiles,
+ const CommandLineArguments &currentArgs);
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangfollowsymboljob.cpp b/src/tools/clangbackend/source/clangfollowsymboljob.cpp
new file mode 100644
index 0000000000..7136db3432
--- /dev/null
+++ b/src/tools/clangbackend/source/clangfollowsymboljob.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangfollowsymboljob.h"
+
+#include <clangsupport/clangsupportdebugutils.h>
+#include <clangsupport/followsymbolmessage.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
+
+#include <utils/qtcassert.h>
+
+namespace ClangBackEnd {
+
+IAsyncJob::AsyncPrepareResult FollowSymbolJob::prepareAsyncRun()
+{
+ const JobRequest jobRequest = context().jobRequest;
+ QTC_ASSERT(jobRequest.type == JobRequest::Type::FollowSymbol,
+ return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
+
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
+ const CommandLineArguments currentArgs(updateInput.filePath.constData(),
+ updateInput.projectArguments,
+ updateInput.fileArguments,
+ false);
+
+ const quint32 line = jobRequest.line;
+ const quint32 column = jobRequest.column;
+ const QVector<Utf8String> &dependentFiles = jobRequest.dependentFiles;
+ setRunner([translationUnit, line, column, dependentFiles, currentArgs]() {
+ TIME_SCOPE_DURATION("FollowSymbolJobRunner");
+ return translationUnit.followSymbol(line, column, dependentFiles, currentArgs);
+ });
+
+ return AsyncPrepareResult{translationUnit.id()};
+}
+
+void FollowSymbolJob::finalizeAsyncRun()
+{
+ if (!context().isOutdated()) {
+ const AsyncResult result = asyncResult();
+
+ const FollowSymbolMessage message(m_pinnedFileContainer,
+ result,
+ context().jobRequest.ticketNumber);
+ context().client->followSymbol(message);
+ }
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.h b/src/tools/clangbackend/source/clangfollowsymboljob.h
index 179f8b845b..3a8741db1c 100644
--- a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.h
+++ b/src/tools/clangbackend/source/clangfollowsymboljob.h
@@ -25,25 +25,18 @@
#pragma once
-#include "clangasyncjob.h"
-#include "clangreferencescollector.h"
-#include "clangdocument.h"
+#include "clangdocumentjob.h"
-#include <clangbackendipc/sourcerangecontainer.h>
+#include <clangsupport/sourcerangecontainer.h>
namespace ClangBackEnd {
-class RequestReferencesJob : public AsyncJob<ReferencesResult>
+class FollowSymbolJob : public DocumentJob<SourceRangeContainer>
{
public:
- using AsyncResult = ReferencesResult;
+ using AsyncResult = SourceRangeContainer;
AsyncPrepareResult prepareAsyncRun() override;
void finalizeAsyncRun() override;
-
-private:
- Document m_pinnedDocument;
- FileContainer m_pinnedFileContainer;
};
-
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangiasyncjob.cpp b/src/tools/clangbackend/source/clangiasyncjob.cpp
new file mode 100644
index 0000000000..c325c494c9
--- /dev/null
+++ b/src/tools/clangbackend/source/clangiasyncjob.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangiasyncjob.h"
+
+Q_LOGGING_CATEGORY(jobsLog, "qtc.clangbackend.jobs");
+
+namespace ClangBackEnd {
+
+IAsyncJob::IAsyncJob()
+ : m_context(JobContext())
+{
+}
+
+IAsyncJob::~IAsyncJob()
+{
+}
+
+JobContext IAsyncJob::context() const
+{
+ return m_context;
+}
+
+void IAsyncJob::setContext(const JobContext &context)
+{
+ m_context = context;
+}
+
+IAsyncJob::FinishedHandler IAsyncJob::finishedHandler() const
+{
+ return m_finishedHandler;
+}
+
+void IAsyncJob::setFinishedHandler(const IAsyncJob::FinishedHandler &finishedHandler)
+{
+ m_finishedHandler = finishedHandler;
+}
+
+bool IAsyncJob::isFinished() const
+{
+ return m_isFinished;
+}
+
+void IAsyncJob::setIsFinished(bool isFinished)
+{
+ m_isFinished = isFinished;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangiasyncjob.h b/src/tools/clangbackend/source/clangiasyncjob.h
index 98f61e857a..e4481fcbf5 100644
--- a/src/tools/clangbackend/ipcsource/clangiasyncjob.h
+++ b/src/tools/clangbackend/source/clangiasyncjob.h
@@ -39,8 +39,6 @@ namespace ClangBackEnd {
class IAsyncJob
{
public:
- static IAsyncJob *create(JobRequest::Type type);
-
struct AsyncPrepareResult {
operator bool() const { return !translationUnitId.isEmpty(); }
Utf8String translationUnitId;
diff --git a/src/tools/clangbackend/ipcsource/clangjobcontext.cpp b/src/tools/clangbackend/source/clangjobcontext.cpp
index e0eb444a94..e0eb444a94 100644
--- a/src/tools/clangbackend/ipcsource/clangjobcontext.cpp
+++ b/src/tools/clangbackend/source/clangjobcontext.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangjobcontext.h b/src/tools/clangbackend/source/clangjobcontext.h
index 629d8320bd..629d8320bd 100644
--- a/src/tools/clangbackend/ipcsource/clangjobcontext.h
+++ b/src/tools/clangbackend/source/clangjobcontext.h
diff --git a/src/tools/clangbackend/ipcsource/clangjobqueue.cpp b/src/tools/clangbackend/source/clangjobqueue.cpp
index 383c2ecaa4..4ea098db3a 100644
--- a/src/tools/clangbackend/ipcsource/clangjobqueue.cpp
+++ b/src/tools/clangbackend/source/clangjobqueue.cpp
@@ -105,11 +105,11 @@ void JobQueue::removeExpiredRequests()
bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest)
{
- const JobRequest::ExpirationReasons expirationReasons = jobRequest.expirationReasons;
+ const JobRequest::ExpirationConditions conditions = jobRequest.expirationConditions;
const UnsavedFiles unsavedFiles = m_documents.unsavedFiles();
- using ExpirationReason = JobRequest::ExpirationReason;
+ using Condition = JobRequest::ExpirationCondition;
- if (expirationReasons.testFlag(ExpirationReason::UnsavedFilesChanged)) {
+ if (conditions.testFlag(Condition::UnsavedFilesChanged)) {
if (jobRequest.unsavedFilesChangeTimePoint != unsavedFiles.lastChangeTimePoint()) {
qCDebug(jobsLog) << "Removing due to outdated unsaved files:" << jobRequest;
return true;
@@ -118,7 +118,7 @@ bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest)
bool projectCheckedAndItExists = false;
- if (expirationReasons.testFlag(ExpirationReason::DocumentClosed)) {
+ if (conditions.testFlag(Condition::DocumentClosed)) {
if (!m_documents.hasDocument(jobRequest.filePath, jobRequest.projectPartId)) {
qCDebug(jobsLog) << "Removing due to already closed document:" << jobRequest;
return true;
@@ -138,7 +138,7 @@ bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest)
return true;
}
- if (expirationReasons.testFlag(ExpirationReason::DocumentRevisionChanged)) {
+ if (conditions.testFlag(Condition::DocumentRevisionChanged)) {
if (document.documentRevision() > jobRequest.documentRevision) {
qCDebug(jobsLog) << "Removing due to changed document revision:" << jobRequest;
return true;
@@ -146,7 +146,7 @@ bool JobQueue::isJobRequestExpired(const JobRequest &jobRequest)
}
}
- if (expirationReasons.testFlag(ExpirationReason::ProjectChanged)) {
+ if (conditions.testFlag(Condition::ProjectChanged)) {
if (!projectCheckedAndItExists && !m_projectParts.hasProjectPart(jobRequest.projectPartId)) {
qCDebug(jobsLog) << "Removing due to already closed project:" << jobRequest;
return true;
@@ -194,10 +194,10 @@ void JobQueue::cancelJobRequest(const JobRequest &jobRequest)
m_cancelJobRequest(jobRequest);
}
-static bool passesPreconditions(const JobRequest &request, const Document &document)
+static bool areRunConditionsMet(const JobRequest &request, const Document &document)
{
- using Condition = JobRequest::Condition;
- const JobRequest::Conditions conditions = request.conditions;
+ using Condition = JobRequest::RunCondition;
+ const JobRequest::RunConditions conditions = request.runConditions;
if (conditions.testFlag(Condition::DocumentSuspended) && !document.isSuspended()) {
qCDebug(jobsLog) << "Not choosing due to unsuspended document:" << request;
@@ -250,7 +250,7 @@ JobRequests JobQueue::takeJobRequestsToRunNow()
const Document &document = m_documents.document(request.filePath,
request.projectPartId);
- if (!passesPreconditions(request, document))
+ if (!areRunConditionsMet(request, document))
continue;
const Utf8String id = document.translationUnit(request.preferredTranslationUnit).id();
diff --git a/src/tools/clangbackend/ipcsource/clangjobqueue.h b/src/tools/clangbackend/source/clangjobqueue.h
index 0d9c49ef04..0d9c49ef04 100644
--- a/src/tools/clangbackend/ipcsource/clangjobqueue.h
+++ b/src/tools/clangbackend/source/clangjobqueue.h
diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp b/src/tools/clangbackend/source/clangjobrequest.cpp
index 7dc16812ce..9f8eb55f77 100644
--- a/src/tools/clangbackend/ipcsource/clangjobrequest.cpp
+++ b/src/tools/clangbackend/source/clangjobrequest.cpp
@@ -25,6 +25,24 @@
#include "clangjobrequest.h"
+#include "clangcompletecodejob.h"
+#include "clangcreateinitialdocumentpreamblejob.h"
+#include "clangfollowsymboljob.h"
+#include "clangparsesupportivetranslationunitjob.h"
+#include "clangreparsesupportivetranslationunitjob.h"
+#include "clangrequestdocumentannotationsjob.h"
+#include "clangrequestreferencesjob.h"
+#include "clangresumedocumentjob.h"
+#include "clangsuspenddocumentjob.h"
+#include "clangupdatedocumentannotationsjob.h"
+
+#include <clangsupport/clangcodemodelclientinterface.h>
+#include <clangsupport/cmbcodecompletedmessage.h>
+#include <clangsupport/followsymbolmessage.h>
+#include <clangsupport/referencesmessage.h>
+
+#include <utils/qtcassert.h>
+
#include <QFileInfo>
#include <ostream>
@@ -35,6 +53,7 @@ namespace ClangBackEnd {
static const char *JobRequestTypeToText(JobRequest::Type type)
{
switch (type) {
+ RETURN_TEXT_FOR_CASE(Invalid);
RETURN_TEXT_FOR_CASE(UpdateDocumentAnnotations);
RETURN_TEXT_FOR_CASE(ParseSupportiveTranslationUnit);
RETURN_TEXT_FOR_CASE(ReparseSupportiveTranslationUnit);
@@ -42,6 +61,7 @@ static const char *JobRequestTypeToText(JobRequest::Type type)
RETURN_TEXT_FOR_CASE(CompleteCode);
RETURN_TEXT_FOR_CASE(RequestDocumentAnnotations);
RETURN_TEXT_FOR_CASE(RequestReferences);
+ RETURN_TEXT_FOR_CASE(FollowSymbol);
RETURN_TEXT_FOR_CASE(SuspendDocument);
RETURN_TEXT_FOR_CASE(ResumeDocument);
}
@@ -95,46 +115,31 @@ QDebug operator<<(QDebug debug, const JobRequest &jobRequest)
return debug.space();
}
-JobRequest::JobRequest()
+static JobRequest::ExpirationConditions expirationConditionsForType(JobRequest::Type type)
{
- static quint64 idCounter = 0;
- id = ++idCounter;
-}
-
-bool JobRequest::operator==(const JobRequest &other) const
-{
- return type == other.type
- && expirationReasons == other.expirationReasons
- && conditions == other.conditions
-
- && filePath == other.filePath
- && projectPartId == other.projectPartId
- && unsavedFilesChangeTimePoint == other.unsavedFilesChangeTimePoint
- && projectChangeTimePoint == other.projectChangeTimePoint
- && documentRevision == other.documentRevision
- && preferredTranslationUnit == other.preferredTranslationUnit
-
- && line == other.line
- && column == other.column
- && ticketNumber == other.ticketNumber;
-}
+ using Type = JobRequest::Type;
+ using Condition = JobRequest::ExpirationCondition;
+ using Conditions = JobRequest::ExpirationConditions;
-JobRequest::ExpirationReasons JobRequest::expirationReasonsForType(Type type)
-{
switch (type) {
case Type::UpdateDocumentAnnotations:
- return ExpirationReasons(ExpirationReason::AnythingChanged);
+ return Conditions(Condition::AnythingChanged);
case Type::RequestReferences:
case Type::RequestDocumentAnnotations:
- return ExpirationReasons(ExpirationReason::DocumentClosed)
- | ExpirationReasons(ExpirationReason::DocumentRevisionChanged);
+ case Type::FollowSymbol:
+ return Conditions(Condition::DocumentClosed)
+ | Conditions(Condition::DocumentRevisionChanged);
default:
- return ExpirationReason::DocumentClosed;
+ return Condition::DocumentClosed;
}
}
-JobRequest::Conditions JobRequest::conditionsForType(JobRequest::Type type)
+static JobRequest::RunConditions conditionsForType(JobRequest::Type type)
{
+ using Type = JobRequest::Type;
+ using Condition = JobRequest::RunCondition;
+ using Conditions = JobRequest::RunConditions;
+
if (type == Type::SuspendDocument) {
return Conditions(Condition::DocumentUnsuspended)
| Conditions(Condition::DocumentNotVisible);
@@ -154,4 +159,100 @@ JobRequest::Conditions JobRequest::conditionsForType(JobRequest::Type type)
return conditions;
}
+JobRequest::JobRequest(Type type)
+{
+ static quint64 idCounter = 0;
+
+ id = ++idCounter;
+ this->type = type;
+ runConditions = conditionsForType(type);
+ expirationConditions = expirationConditionsForType(type);
+}
+
+IAsyncJob *JobRequest::createJob() const
+{
+ switch (type) {
+ case JobRequest::Type::Invalid:
+ QTC_CHECK(false && "Cannot create job for invalid job request.");
+ break;
+ case JobRequest::Type::UpdateDocumentAnnotations:
+ return new UpdateDocumentAnnotationsJob();
+ case JobRequest::Type::ParseSupportiveTranslationUnit:
+ return new ParseSupportiveTranslationUnitJob();
+ case JobRequest::Type::ReparseSupportiveTranslationUnit:
+ return new ReparseSupportiveTranslationUnitJob();
+ case JobRequest::Type::CreateInitialDocumentPreamble:
+ return new CreateInitialDocumentPreambleJob();
+ case JobRequest::Type::CompleteCode:
+ return new CompleteCodeJob();
+ case JobRequest::Type::RequestDocumentAnnotations:
+ return new RequestDocumentAnnotationsJob();
+ case JobRequest::Type::RequestReferences:
+ return new RequestReferencesJob();
+ case JobRequest::Type::FollowSymbol:
+ return new FollowSymbolJob();
+ case JobRequest::Type::SuspendDocument:
+ return new SuspendDocumentJob();
+ case JobRequest::Type::ResumeDocument:
+ return new ResumeDocumentJob();
+ }
+
+ return nullptr;
+}
+
+void JobRequest::cancelJob(ClangCodeModelClientInterface &client) const
+{
+ // If a job request with a ticket number is cancelled, the plugin side
+ // must get back some results in order to clean up the state there.
+
+ switch (type) {
+ case JobRequest::Type::Invalid:
+ case JobRequest::Type::UpdateDocumentAnnotations:
+ case JobRequest::Type::ParseSupportiveTranslationUnit:
+ case JobRequest::Type::ReparseSupportiveTranslationUnit:
+ case JobRequest::Type::CreateInitialDocumentPreamble:
+ case JobRequest::Type::RequestDocumentAnnotations:
+ case JobRequest::Type::SuspendDocument:
+ case JobRequest::Type::ResumeDocument:
+ break;
+ case JobRequest::Type::RequestReferences:
+ client.references(ReferencesMessage(FileContainer(),
+ QVector<SourceRangeContainer>(),
+ false,
+ ticketNumber));
+ break;
+ case JobRequest::Type::CompleteCode:
+ client.codeCompleted(CodeCompletedMessage(CodeCompletions(),
+ CompletionCorrection::NoCorrection,
+ ticketNumber));
+ break;
+ case JobRequest::Type::FollowSymbol:
+ client.followSymbol(FollowSymbolMessage(FileContainer(),
+ SourceRangeContainer(),
+ ticketNumber));
+ break;
+ }
+}
+
+bool JobRequest::operator==(const JobRequest &other) const
+{
+ return type == other.type
+ && expirationConditions == other.expirationConditions
+ && runConditions == other.runConditions
+
+ && filePath == other.filePath
+ && projectPartId == other.projectPartId
+ && unsavedFilesChangeTimePoint == other.unsavedFilesChangeTimePoint
+ && projectChangeTimePoint == other.projectChangeTimePoint
+ && documentRevision == other.documentRevision
+ && preferredTranslationUnit == other.preferredTranslationUnit
+
+ && line == other.line
+ && column == other.column
+ && ticketNumber == other.ticketNumber;
+
+ // Additional members that are not compared here explicitly are
+ // supposed to depend on the already compared ones.
+}
+
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangjobrequest.h b/src/tools/clangbackend/source/clangjobrequest.h
index 33b68cb60f..78aaed6618 100644
--- a/src/tools/clangbackend/ipcsource/clangjobrequest.h
+++ b/src/tools/clangbackend/source/clangjobrequest.h
@@ -29,6 +29,7 @@
#include "clangclock.h"
#include <utf8string.h>
+#include <utf8stringvector.h>
#include <QFlags>
#include <QDebug>
@@ -38,12 +39,16 @@
namespace ClangBackEnd {
+class ClangCodeModelClientInterface;
class Document;
+class IAsyncJob;
class JobRequest
{
public:
enum class Type {
+ Invalid,
+
UpdateDocumentAnnotations,
CreateInitialDocumentPreamble,
@@ -53,12 +58,13 @@ public:
CompleteCode,
RequestDocumentAnnotations,
RequestReferences,
+ FollowSymbol,
SuspendDocument,
ResumeDocument,
};
- enum class Condition {
+ enum class RunCondition {
NoCondition = 1 << 0,
DocumentVisible = 1 << 1,
DocumentNotVisible = 1 << 2,
@@ -66,9 +72,9 @@ public:
DocumentUnsuspended = 1 << 4,
CurrentDocumentRevision = 1 << 5,
};
- Q_DECLARE_FLAGS(Conditions, Condition)
+ Q_DECLARE_FLAGS(RunConditions, RunCondition)
- enum class ExpirationReason {
+ enum class ExpirationCondition {
Never = 1 << 0,
DocumentClosed = 1 << 1,
@@ -81,21 +87,21 @@ public:
| UnsavedFilesChanged
| ProjectChanged,
};
- Q_DECLARE_FLAGS(ExpirationReasons, ExpirationReason)
+ Q_DECLARE_FLAGS(ExpirationConditions, ExpirationCondition)
public:
- static ExpirationReasons expirationReasonsForType(Type type);
- static Conditions conditionsForType(Type type);
+ JobRequest(Type type = Type::Invalid);
- JobRequest();
+ IAsyncJob *createJob() const;
+ void cancelJob(ClangCodeModelClientInterface &client) const;
bool operator==(const JobRequest &other) const;
public:
quint64 id = 0;
Type type;
- ExpirationReasons expirationReasons;
- Conditions conditions;
+ ExpirationConditions expirationConditions;
+ RunConditions runConditions;
// General
Utf8String filePath;
@@ -108,7 +114,10 @@ public:
// Specific to some jobs
quint32 line = 0;
quint32 column = 0;
+ qint32 funcNameStartLine = -1;
+ qint32 funcNameStartColumn = -1;
quint64 ticketNumber = 0;
+ Utf8StringVector dependentFiles;
};
using JobRequests = QVector<JobRequest>;
diff --git a/src/tools/clangbackend/ipcsource/clangjobs.cpp b/src/tools/clangbackend/source/clangjobs.cpp
index f168387505..033dc4ef1a 100644
--- a/src/tools/clangbackend/ipcsource/clangjobs.cpp
+++ b/src/tools/clangbackend/source/clangjobs.cpp
@@ -29,9 +29,6 @@
#include "clangiasyncjob.h"
#include "projects.h"
-#include <clangbackendipc/cmbcodecompletedmessage.h>
-#include <clangbackendipc/referencesmessage.h>
-
#include <QDebug>
#include <QFutureSynchronizer>
#include <QLoggingCategory>
@@ -58,7 +55,7 @@ Jobs::Jobs(Documents &documents,
return isJobRunningForJobRequest(jobRequest);
});
m_queue.setCancelJobRequest([this](const JobRequest &jobRequest) {
- return cancelJobRequest(jobRequest);
+ jobRequest.cancelJob(m_client);
});
}
@@ -79,10 +76,7 @@ JobRequest Jobs::createJobRequest(const Document &document,
JobRequest::Type type,
PreferredTranslationUnit preferredTranslationUnit) const
{
- JobRequest jobRequest;
- jobRequest.type = type;
- jobRequest.expirationReasons = JobRequest::expirationReasonsForType(type);
- jobRequest.conditions = JobRequest::conditionsForType(type);
+ JobRequest jobRequest(type);
jobRequest.filePath = document.filePath();
jobRequest.projectPartId = document.projectPart().id();
jobRequest.unsavedFilesChangeTimePoint = m_unsavedFiles.lastChangeTimePoint();
@@ -131,7 +125,7 @@ JobRequests Jobs::runJobs(const JobRequests &jobsRequests)
bool Jobs::runJob(const JobRequest &jobRequest)
{
- IAsyncJob *asyncJob = IAsyncJob::create(jobRequest.type);
+ IAsyncJob *asyncJob = jobRequest.createJob();
QTC_ASSERT(asyncJob, return false);
JobContext context(jobRequest, &m_documents, &m_unsavedFiles, &m_client);
@@ -203,29 +197,4 @@ bool Jobs::isJobRunningForJobRequest(const JobRequest &jobRequest) const
return Utils::anyOf(m_running.values(), hasJobRequest);
}
-void Jobs::cancelJobRequest(const JobRequest &jobRequest)
-{
- // TODO: Consider to refactor this. Jobs should not know anything about
- // concrete messages. On the other hand, having this here avoids
- // duplication in multiple job classes.
-
- // If a job request with a ticket number is cancelled, the plugin side
- // must get back some results in order to clean up the state there.
- switch (jobRequest.type) {
- case JobRequest::Type::RequestReferences:
- m_client.references(ReferencesMessage(FileContainer(),
- QVector<SourceRangeContainer>(),
- false,
- jobRequest.ticketNumber));
- break;
- case JobRequest::Type::CompleteCode:
- m_client.codeCompleted(CodeCompletedMessage(CodeCompletions(),
- CompletionCorrection::NoCorrection,
- jobRequest.ticketNumber));
- break;
- default:
- break;
- }
-}
-
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangjobs.h b/src/tools/clangbackend/source/clangjobs.h
index 711f15e67a..d154d401e8 100644
--- a/src/tools/clangbackend/ipcsource/clangjobs.h
+++ b/src/tools/clangbackend/source/clangjobs.h
@@ -27,7 +27,7 @@
#include "clangjobqueue.h"
-#include <clangbackendipc/clangcodemodelclientinterface.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
#include <QFuture>
@@ -80,7 +80,6 @@ public /*for tests*/:
bool isJobRunningForJobRequest(const JobRequest &jobRequest) const;
private:
- void cancelJobRequest(const JobRequest &jobRequest);
JobRequests runJobs(const JobRequests &jobRequest);
bool runJob(const JobRequest &jobRequest);
void onJobFinished(IAsyncJob *asyncJob);
diff --git a/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp
new file mode 100644
index 0000000000..017426ab02
--- /dev/null
+++ b/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangparsesupportivetranslationunitjob.h"
+
+#include <clangsupport/clangsupportdebugutils.h>
+
+#include <utils/qtcassert.h>
+
+namespace ClangBackEnd {
+
+IAsyncJob::AsyncPrepareResult ParseSupportiveTranslationUnitJob::prepareAsyncRun()
+{
+ const JobRequest jobRequest = context().jobRequest;
+ QTC_ASSERT(jobRequest.type == JobRequest::Type::ParseSupportiveTranslationUnit, return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
+
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
+ setRunner([translationUnit, updateInput]() {
+ TIME_SCOPE_DURATION("ParseSupportiveTranslationUnitJob");
+
+ TranslationUnitUpdateInput theUpdateInput = updateInput;
+ theUpdateInput.parseNeeded = true;
+
+ return translationUnit.update(updateInput);
+ });
+
+ return AsyncPrepareResult{translationUnit.id()};
+}
+
+void ParseSupportiveTranslationUnitJob::finalizeAsyncRun()
+{
+}
+
+} // namespace ClangBackEnd
+
diff --git a/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h b/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h
new file mode 100644
index 0000000000..5a0cfec183
--- /dev/null
+++ b/src/tools/clangbackend/source/clangparsesupportivetranslationunitjob.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangdocumentjob.h"
+#include "clangtranslationunitupdater.h"
+
+namespace ClangBackEnd {
+
+class ParseSupportiveTranslationUnitJob : public DocumentJob<TranslationUnitUpdateResult>
+{
+public:
+ using AsyncResult = TranslationUnitUpdateResult;
+
+ AsyncPrepareResult prepareAsyncRun() override;
+ void finalizeAsyncRun() override;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangreferencescollector.cpp b/src/tools/clangbackend/source/clangreferencescollector.cpp
index df9d937de0..d2b7bf5431 100644
--- a/src/tools/clangbackend/ipcsource/clangreferencescollector.cpp
+++ b/src/tools/clangbackend/source/clangreferencescollector.cpp
@@ -29,7 +29,7 @@
#include "cursor.h"
#include "sourcerange.h"
-#include <clangbackendipc/sourcerangecontainer.h>
+#include <clangsupport/sourcerangecontainer.h>
#include <utils/qtcassert.h>
#include <utf8string.h>
diff --git a/src/tools/clangbackend/ipcsource/clangreferencescollector.h b/src/tools/clangbackend/source/clangreferencescollector.h
index 6feee77c79..263ba07fd9 100644
--- a/src/tools/clangbackend/ipcsource/clangreferencescollector.h
+++ b/src/tools/clangbackend/source/clangreferencescollector.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangbackendipc/sourcerangecontainer.h>
+#include <clangsupport/sourcerangecontainer.h>
#include <QVector>
diff --git a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp b/src/tools/clangbackend/source/clangreparsesupportivetranslationunitjob.cpp
index da922db8e9..a02821fff4 100644
--- a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.cpp
+++ b/src/tools/clangbackend/source/clangreparsesupportivetranslationunitjob.cpp
@@ -25,49 +25,33 @@
#include "clangreparsesupportivetranslationunitjob.h"
-#include <clangbackendipc/clangbackendipcdebugutils.h>
+#include <clangsupport/clangsupportdebugutils.h>
#include <utils/qtcassert.h>
namespace ClangBackEnd {
-static ReparseSupportiveTranslationUnitJob::AsyncResult runAsyncHelper(
- const TranslationUnit &translationUnit,
- const TranslationUnitUpdateInput &translationUnitUpdateInput)
-{
- TIME_SCOPE_DURATION("ReparseSupportiveTranslationUnitJob");
-
- TranslationUnitUpdateInput updateInput = translationUnitUpdateInput;
- updateInput.reparseNeeded = true;
-
- ReparseSupportiveTranslationUnitJob::AsyncResult asyncResult;
- asyncResult.updateResult = translationUnit.reparse(updateInput);
-
- return asyncResult;
-}
-
IAsyncJob::AsyncPrepareResult ReparseSupportiveTranslationUnitJob::prepareAsyncRun()
{
const JobRequest jobRequest = context().jobRequest;
QTC_ASSERT(jobRequest.type == JobRequest::Type::ReparseSupportiveTranslationUnit, return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
- try {
- m_pinnedDocument = context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
+ setRunner([translationUnit, updateInput]() {
+ TIME_SCOPE_DURATION("ReparseSupportiveTranslationUnitJob");
- const TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
- setRunner([translationUnit, updateInput]() {
- return runAsyncHelper(translationUnit, updateInput);
- });
- return AsyncPrepareResult{translationUnit.id()};
+ TranslationUnitUpdateInput theUpdateInput = updateInput;
+ theUpdateInput.reparseNeeded = true;
- } catch (const std::exception &exception) {
- qWarning() << "Error in ReparseSupportiveTranslationUnitJob::prepareAsyncRun:"
- << exception.what();
- return AsyncPrepareResult();
- }
+ ReparseSupportiveTranslationUnitJob::AsyncResult asyncResult;
+ asyncResult.updateResult = translationUnit.reparse(theUpdateInput);
+
+ return asyncResult;
+ });
+
+ return AsyncPrepareResult{translationUnit.id()};
}
void ReparseSupportiveTranslationUnitJob::finalizeAsyncRun()
diff --git a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.h b/src/tools/clangbackend/source/clangreparsesupportivetranslationunitjob.h
index 1b352c2c36..cb146299c7 100644
--- a/src/tools/clangbackend/ipcsource/clangreparsesupportivetranslationunitjob.h
+++ b/src/tools/clangbackend/source/clangreparsesupportivetranslationunitjob.h
@@ -25,8 +25,7 @@
#pragma once
-#include "clangasyncjob.h"
-#include "clangdocument.h"
+#include "clangdocumentjob.h"
namespace ClangBackEnd {
@@ -35,17 +34,13 @@ struct ReparseSupportiveTranslationUnitJobResult
TranslationUnitUpdateResult updateResult;
};
-class ReparseSupportiveTranslationUnitJob : public AsyncJob<ReparseSupportiveTranslationUnitJobResult>
+class ReparseSupportiveTranslationUnitJob : public DocumentJob<ReparseSupportiveTranslationUnitJobResult>
{
public:
using AsyncResult = ReparseSupportiveTranslationUnitJobResult;
AsyncPrepareResult prepareAsyncRun() override;
void finalizeAsyncRun() override;
-
-private:
- Document m_pinnedDocument;
- FileContainer m_pinnedFileContainer;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangrequestdocumentannotationsjob.cpp b/src/tools/clangbackend/source/clangrequestdocumentannotationsjob.cpp
new file mode 100644
index 0000000000..99ac98eec2
--- /dev/null
+++ b/src/tools/clangbackend/source/clangrequestdocumentannotationsjob.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangrequestdocumentannotationsjob.h"
+
+#include <clangsupport/clangsupportdebugutils.h>
+#include <clangsupport/documentannotationschangedmessage.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
+
+#include <utils/qtcassert.h>
+
+namespace ClangBackEnd {
+
+IAsyncJob::AsyncPrepareResult RequestDocumentAnnotationsJob::prepareAsyncRun()
+{
+ const JobRequest jobRequest = context().jobRequest;
+ QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestDocumentAnnotations,
+ return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
+
+ const TranslationUnit translationUnit = *m_translationUnit;
+ setRunner([translationUnit]() {
+ TIME_SCOPE_DURATION("RequestDocumentAnnotationsJobRunner");
+
+ RequestDocumentAnnotationsJob::AsyncResult asyncResult;
+ translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic,
+ asyncResult.diagnostics,
+ asyncResult.highlightingMarks,
+ asyncResult.skippedSourceRanges);
+ return asyncResult;
+ });
+
+ return AsyncPrepareResult{translationUnit.id()};
+}
+
+void RequestDocumentAnnotationsJob::finalizeAsyncRun()
+{
+ if (context().isDocumentOpen()) {
+ const AsyncResult result = asyncResult();
+ context().client->documentAnnotationsChanged(
+ DocumentAnnotationsChangedMessage(m_pinnedFileContainer,
+ result.diagnostics,
+ result.firstHeaderErrorDiagnostic,
+ result.highlightingMarks,
+ result.skippedSourceRanges));
+ }
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h b/src/tools/clangbackend/source/clangrequestdocumentannotationsjob.h
index e6bb4f9edc..1c78621119 100644
--- a/src/tools/clangbackend/ipcsource/clangrequestdocumentannotationsjob.h
+++ b/src/tools/clangbackend/source/clangrequestdocumentannotationsjob.h
@@ -25,12 +25,11 @@
#pragma once
-#include "clangasyncjob.h"
-#include "clangdocument.h"
+#include "clangdocumentjob.h"
-#include <clangbackendipc/diagnosticcontainer.h>
-#include <clangbackendipc/highlightingmarkcontainer.h>
-#include <clangbackendipc/sourcerangecontainer.h>
+#include <clangsupport/diagnosticcontainer.h>
+#include <clangsupport/highlightingmarkcontainer.h>
+#include <clangsupport/sourcerangecontainer.h>
namespace ClangBackEnd {
@@ -42,20 +41,13 @@ struct RequestDocumentAnnotationsJobResult
QVector<SourceRangeContainer> skippedSourceRanges;
};
-class RequestDocumentAnnotationsJob : public AsyncJob<RequestDocumentAnnotationsJobResult>
+class RequestDocumentAnnotationsJob : public DocumentJob<RequestDocumentAnnotationsJobResult>
{
public:
using AsyncResult = RequestDocumentAnnotationsJobResult;
AsyncPrepareResult prepareAsyncRun() override;
void finalizeAsyncRun() override;
-
-private:
- void sendAnnotations(const AsyncResult &result);
-
-private:
- Document m_pinnedDocument;
- FileContainer m_pinnedFileContainer;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp b/src/tools/clangbackend/source/clangrequestreferencesjob.cpp
index f80072c0ed..39b3319488 100644
--- a/src/tools/clangbackend/ipcsource/clangrequestreferencesjob.cpp
+++ b/src/tools/clangbackend/source/clangrequestreferencesjob.cpp
@@ -25,46 +25,30 @@
#include "clangrequestreferencesjob.h"
-#include <clangbackendipc/clangbackendipcdebugutils.h>
-#include <clangbackendipc/referencesmessage.h>
-#include <clangbackendipc/clangcodemodelclientinterface.h>
+#include <clangsupport/clangsupportdebugutils.h>
+#include <clangsupport/referencesmessage.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
#include <utils/qtcassert.h>
namespace ClangBackEnd {
-static RequestReferencesJob::AsyncResult runAsyncHelper(const TranslationUnit &translationUnit,
- quint32 line,
- quint32 column)
-{
- TIME_SCOPE_DURATION("RequestReferencesJobRunner");
-
- return translationUnit.references(line, column);
-}
-
IAsyncJob::AsyncPrepareResult RequestReferencesJob::prepareAsyncRun()
{
const JobRequest jobRequest = context().jobRequest;
QTC_ASSERT(jobRequest.type == JobRequest::Type::RequestReferences,
return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
- try {
- m_pinnedDocument = context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
-
- const TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- const quint32 line = jobRequest.line;
- const quint32 column = jobRequest.column;
- setRunner([translationUnit, line, column]() {
- return runAsyncHelper(translationUnit, line, column);
- });
- return AsyncPrepareResult{translationUnit.id()};
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const quint32 line = jobRequest.line;
+ const quint32 column = jobRequest.column;
+ setRunner([translationUnit, line, column]() {
+ TIME_SCOPE_DURATION("RequestReferencesJobRunner");
+ return translationUnit.references(line, column);
+ });
- } catch (const std::exception &exception) {
- qWarning() << "Error in RequestReferencesJob::prepareAsyncRun:" << exception.what();
- return AsyncPrepareResult();
- }
+ return AsyncPrepareResult{translationUnit.id()};
}
void RequestReferencesJob::finalizeAsyncRun()
diff --git a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.h b/src/tools/clangbackend/source/clangrequestreferencesjob.h
index 16d5b52a1e..d92d869a9b 100644
--- a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.h
+++ b/src/tools/clangbackend/source/clangrequestreferencesjob.h
@@ -25,20 +25,18 @@
#pragma once
-#include "clangasyncjob.h"
-#include "clangdocument.h"
+#include "clangdocumentjob.h"
+#include "clangreferencescollector.h"
namespace ClangBackEnd {
-class SuspendDocumentJob : public AsyncJob<bool>
+class RequestReferencesJob : public DocumentJob<ReferencesResult>
{
public:
+ using AsyncResult = ReferencesResult;
+
AsyncPrepareResult prepareAsyncRun() override;
void finalizeAsyncRun() override;
-
-private:
- Document m_pinnedDocument;
- FileContainer m_pinnedFileContainer;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangresumedocumentjob.cpp b/src/tools/clangbackend/source/clangresumedocumentjob.cpp
index c628d4444a..c628d4444a 100644
--- a/src/tools/clangbackend/ipcsource/clangresumedocumentjob.cpp
+++ b/src/tools/clangbackend/source/clangresumedocumentjob.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangresumedocumentjob.h b/src/tools/clangbackend/source/clangresumedocumentjob.h
index aff8e780f7..aff8e780f7 100644
--- a/src/tools/clangbackend/ipcsource/clangresumedocumentjob.h
+++ b/src/tools/clangbackend/source/clangresumedocumentjob.h
diff --git a/src/tools/clangbackend/ipcsource/clangstring.h b/src/tools/clangbackend/source/clangstring.h
index 685055cff0..685055cff0 100644
--- a/src/tools/clangbackend/ipcsource/clangstring.h
+++ b/src/tools/clangbackend/source/clangstring.h
diff --git a/src/tools/clangbackend/ipcsource/clangsupportivetranslationunitinitializer.cpp b/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.cpp
index 9c162eb8cf..9c162eb8cf 100644
--- a/src/tools/clangbackend/ipcsource/clangsupportivetranslationunitinitializer.cpp
+++ b/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangsupportivetranslationunitinitializer.h b/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.h
index 18a01864dd..18a01864dd 100644
--- a/src/tools/clangbackend/ipcsource/clangsupportivetranslationunitinitializer.h
+++ b/src/tools/clangbackend/source/clangsupportivetranslationunitinitializer.h
diff --git a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp b/src/tools/clangbackend/source/clangsuspenddocumentjob.cpp
index e3406fcf32..87fe54bfae 100644
--- a/src/tools/clangbackend/ipcsource/clangsuspenddocumentjob.cpp
+++ b/src/tools/clangbackend/source/clangsuspenddocumentjob.cpp
@@ -25,39 +25,25 @@
#include "clangsuspenddocumentjob.h"
-#include <clangbackendipc/clangbackendipcdebugutils.h>
+#include <clangsupport/clangsupportdebugutils.h>
#include <utils/qtcassert.h>
namespace ClangBackEnd {
-static bool runAsyncHelper(const TranslationUnit &translationUnit)
-{
- TIME_SCOPE_DURATION("SuspendDocumentJobRunner");
-
- return translationUnit.suspend();
-}
-
IAsyncJob::AsyncPrepareResult SuspendDocumentJob::prepareAsyncRun()
{
const JobRequest jobRequest = context().jobRequest;
QTC_ASSERT(jobRequest.type == JobRequest::Type::SuspendDocument, return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
- try {
- m_pinnedDocument = context().documentForJobRequest();
- m_pinnedFileContainer = m_pinnedDocument.fileContainer();
-
- TranslationUnit translationUnit
- = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
- setRunner([translationUnit]() {
- return runAsyncHelper(translationUnit);
- });
- return AsyncPrepareResult{translationUnit.id()};
+ TranslationUnit translationUnit = *m_translationUnit;
+ setRunner([translationUnit]() {
+ TIME_SCOPE_DURATION("SuspendDocumentJobRunner");
+ return translationUnit.suspend();
+ });
- } catch (const std::exception &exception) {
- qWarning() << "Error in SuspendDocumentJob::prepareAsyncRun:" << exception.what();
- return AsyncPrepareResult();
- }
+ return AsyncPrepareResult{translationUnit.id()};
}
void SuspendDocumentJob::finalizeAsyncRun()
diff --git a/src/tools/clangbackend/source/clangsuspenddocumentjob.h b/src/tools/clangbackend/source/clangsuspenddocumentjob.h
new file mode 100644
index 0000000000..5948f8226f
--- /dev/null
+++ b/src/tools/clangbackend/source/clangsuspenddocumentjob.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangdocumentjob.h"
+
+namespace ClangBackEnd {
+
+class SuspendDocumentJob : public DocumentJob<bool>
+{
+public:
+ AsyncPrepareResult prepareAsyncRun() override;
+ void finalizeAsyncRun() override;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp b/src/tools/clangbackend/source/clangtranslationunit.cpp
index 0bc0509a5e..720bfb9255 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp
+++ b/src/tools/clangbackend/source/clangtranslationunit.cpp
@@ -28,6 +28,8 @@
#include "clangbackend_global.h"
#include "clangreferencescollector.h"
#include "clangtranslationunitupdater.h"
+#include "clangfollowsymbol.h"
+#include "clangfollowsymboljob.h"
#include <codecompleter.h>
#include <cursor.h>
@@ -38,6 +40,7 @@
#include <skippedsourceranges.h>
#include <sourcelocation.h>
#include <sourcerange.h>
+#include <commandlinearguments.h>
#include <utils/qtcassert.h>
@@ -116,11 +119,15 @@ bool TranslationUnit::suspend() const
TranslationUnit::CodeCompletionResult TranslationUnit::complete(
UnsavedFiles &unsavedFiles,
uint line,
- uint column) const
+ uint column,
+ int funcNameStartLine,
+ int funcNameStartColumn) const
{
CodeCompleter codeCompleter(*this, unsavedFiles);
- const CodeCompletions completions = codeCompleter.complete(line, column);
+ const CodeCompletions completions = codeCompleter.complete(line, column,
+ funcNameStartLine,
+ funcNameStartColumn);
const CompletionCorrection correction = codeCompleter.neededCorrection();
return CodeCompletionResult{completions, correction};
@@ -236,4 +243,13 @@ void TranslationUnit::extractDiagnostics(DiagnosticContainer &firstHeaderErrorDi
}
}
+SourceRangeContainer TranslationUnit::followSymbol(uint line,
+ uint column,
+ const QVector<Utf8String> &dependentFiles,
+ const CommandLineArguments &currentArgs) const
+{
+ return FollowSymbol::followSymbol(m_cxTranslationUnit, m_cxIndex, cursorAt(line, column), line,
+ column, dependentFiles, currentArgs);
+}
+
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.h b/src/tools/clangbackend/source/clangtranslationunit.h
index cc398e9a72..9634c8cb51 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunit.h
+++ b/src/tools/clangbackend/source/clangtranslationunit.h
@@ -25,14 +25,10 @@
#pragma once
-#include <clangbackendipc/codecompletion.h>
-
-#include <utf8string.h>
+#include <clangsupport/codecompletion.h>
#include <clang-c/Index.h>
-class Utf8String;
-
namespace ClangBackEnd {
class Cursor;
@@ -48,6 +44,7 @@ class SourceRangeContainer;
class TranslationUnitUpdateInput;
class TranslationUnitUpdateResult;
class UnsavedFiles;
+class CommandLineArguments;
class TranslationUnit
{
@@ -77,7 +74,8 @@ public:
TranslationUnitUpdateResult parse(const TranslationUnitUpdateInput &parseInput) const;
TranslationUnitUpdateResult reparse(const TranslationUnitUpdateInput &parseInput) const;
- CodeCompletionResult complete(UnsavedFiles &unsavedFiles, uint line, uint column) const;
+ CodeCompletionResult complete(UnsavedFiles &unsavedFiles, uint line, uint column,
+ int funcNameStartLine, int funcNameStartColumn) const;
void extractDiagnostics(DiagnosticContainer &firstHeaderErrorDiagnostic,
QVector<DiagnosticContainer> &mainFileDiagnostics) const;
@@ -102,6 +100,10 @@ public:
HighlightingMarks highlightingMarksInRange(const SourceRange &range) const;
SkippedSourceRanges skippedSourceRanges() const;
+ SourceRangeContainer followSymbol(uint line,
+ uint column,
+ const QVector<Utf8String> &dependentFiles,
+ const CommandLineArguments &currentArgs) const;
private:
const Utf8String m_id;
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunits.cpp b/src/tools/clangbackend/source/clangtranslationunits.cpp
index 432da3d02c..432da3d02c 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunits.cpp
+++ b/src/tools/clangbackend/source/clangtranslationunits.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunits.h b/src/tools/clangbackend/source/clangtranslationunits.h
index e89d0ebd25..e89d0ebd25 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunits.h
+++ b/src/tools/clangbackend/source/clangtranslationunits.h
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunitupdater.cpp b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
index ade9cb35f9..ade9cb35f9 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunitupdater.cpp
+++ b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunitupdater.h b/src/tools/clangbackend/source/clangtranslationunitupdater.h
index 547c6838bc..547c6838bc 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunitupdater.h
+++ b/src/tools/clangbackend/source/clangtranslationunitupdater.h
diff --git a/src/tools/clangbackend/ipcsource/clangtype.cpp b/src/tools/clangbackend/source/clangtype.cpp
index 8fc09d8c4a..8fc09d8c4a 100644
--- a/src/tools/clangbackend/ipcsource/clangtype.cpp
+++ b/src/tools/clangbackend/source/clangtype.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangtype.h b/src/tools/clangbackend/source/clangtype.h
index f26fe080f6..f26fe080f6 100644
--- a/src/tools/clangbackend/ipcsource/clangtype.h
+++ b/src/tools/clangbackend/source/clangtype.h
diff --git a/src/tools/clangbackend/ipcsource/clangunsavedfilesshallowarguments.cpp b/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.cpp
index 6fe23d606f..6fe23d606f 100644
--- a/src/tools/clangbackend/ipcsource/clangunsavedfilesshallowarguments.cpp
+++ b/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangunsavedfilesshallowarguments.h b/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.h
index 20c8981ef2..20c8981ef2 100644
--- a/src/tools/clangbackend/ipcsource/clangunsavedfilesshallowarguments.h
+++ b/src/tools/clangbackend/source/clangunsavedfilesshallowarguments.h
diff --git a/src/tools/clangbackend/source/clangupdatedocumentannotationsjob.cpp b/src/tools/clangbackend/source/clangupdatedocumentannotationsjob.cpp
new file mode 100644
index 0000000000..7333ca6878
--- /dev/null
+++ b/src/tools/clangbackend/source/clangupdatedocumentannotationsjob.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangupdatedocumentannotationsjob.h"
+
+#include <clangsupport/clangsupportdebugutils.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
+#include <clangsupport/documentannotationschangedmessage.h>
+
+#include <utils/qtcassert.h>
+
+namespace ClangBackEnd {
+
+IAsyncJob::AsyncPrepareResult UpdateDocumentAnnotationsJob::prepareAsyncRun()
+{
+ const JobRequest jobRequest = context().jobRequest;
+ QTC_ASSERT(isExpectedJobRequestType(jobRequest), return AsyncPrepareResult());
+ QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());
+
+ const TranslationUnit translationUnit = *m_translationUnit;
+ const TranslationUnitUpdateInput updateInput = createUpdateInput(m_pinnedDocument);
+ setRunner([translationUnit, updateInput]() {
+ TIME_SCOPE_DURATION("UpdateDocumentAnnotationsJobRunner");
+
+ // Update
+ UpdateDocumentAnnotationsJob::AsyncResult asyncResult;
+ asyncResult.updateResult = translationUnit.update(updateInput);
+
+ // Collect
+ translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic,
+ asyncResult.diagnostics,
+ asyncResult.highlightingMarks,
+ asyncResult.skippedSourceRanges);
+
+ return asyncResult;
+ });
+
+ return AsyncPrepareResult{translationUnit.id()};
+}
+
+void UpdateDocumentAnnotationsJob::finalizeAsyncRun()
+{
+ if (!context().isOutdated()) {
+ const AsyncResult result = asyncResult();
+
+ m_pinnedDocument.incorporateUpdaterResult(result.updateResult);
+ context().client->documentAnnotationsChanged(
+ DocumentAnnotationsChangedMessage(m_pinnedFileContainer,
+ result.diagnostics,
+ result.firstHeaderErrorDiagnostic,
+ result.highlightingMarks,
+ result.skippedSourceRanges));
+ }
+}
+
+bool UpdateDocumentAnnotationsJob::isExpectedJobRequestType(const JobRequest &jobRequest) const
+{
+ return jobRequest.type == JobRequest::Type::UpdateDocumentAnnotations;
+}
+
+TranslationUnitUpdateInput
+UpdateDocumentAnnotationsJob::createUpdateInput(const Document &document) const
+{
+ return document.createUpdateInput();
+}
+
+} // namespace ClangBackEnd
+
diff --git a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h b/src/tools/clangbackend/source/clangupdatedocumentannotationsjob.h
index fdbe9068a6..141b3535a0 100644
--- a/src/tools/clangbackend/ipcsource/clangupdatedocumentannotationsjob.h
+++ b/src/tools/clangbackend/source/clangupdatedocumentannotationsjob.h
@@ -25,13 +25,11 @@
#pragma once
-#include "clangasyncjob.h"
-#include "clangdocument.h"
-#include "clangtranslationunitupdater.h"
+#include "clangdocumentjob.h"
-#include <clangbackendipc/diagnosticcontainer.h>
-#include <clangbackendipc/highlightingmarkcontainer.h>
-#include <clangbackendipc/sourcerangecontainer.h>
+#include <clangsupport/diagnosticcontainer.h>
+#include <clangsupport/highlightingmarkcontainer.h>
+#include <clangsupport/sourcerangecontainer.h>
namespace ClangBackEnd {
@@ -45,7 +43,7 @@ struct UpdateDocumentAnnotationsJobResult
QVector<SourceRangeContainer> skippedSourceRanges;
};
-class UpdateDocumentAnnotationsJob : public AsyncJob<UpdateDocumentAnnotationsJobResult>
+class UpdateDocumentAnnotationsJob : public DocumentJob<UpdateDocumentAnnotationsJobResult>
{
public:
using AsyncResult = UpdateDocumentAnnotationsJobResult;
@@ -56,16 +54,6 @@ public:
protected:
virtual bool isExpectedJobRequestType(const JobRequest &jobRequest) const;
virtual TranslationUnitUpdateInput createUpdateInput(const Document &document) const;
-
-private:
- void incorporateUpdaterResult(const AsyncResult &result);
- void sendAnnotations(const AsyncResult &result);
-
-protected:
- Document m_pinnedDocument;
-
-private:
- FileContainer m_pinnedFileContainer;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/codecompleter.cpp b/src/tools/clangbackend/source/codecompleter.cpp
index fe746c8cfd..8fa5c9cce2 100644
--- a/src/tools/clangbackend/ipcsource/codecompleter.cpp
+++ b/src/tools/clangbackend/source/codecompleter.cpp
@@ -81,11 +81,22 @@ CodeCompleter::CodeCompleter(const TranslationUnit &translationUnit,
{
}
-CodeCompletions CodeCompleter::complete(uint line, uint column)
+CodeCompletions CodeCompleter::complete(uint line, uint column,
+ int funcNameStartLine,
+ int funcNameStartColumn)
{
neededCorrection_ = CompletionCorrection::NoCorrection;
- ClangCodeCompleteResults results = completeHelper(line, column);
+ // Check if we have a smart pointer completion and get proper constructor signatures in results.
+ // Results are empty when it's not a smart pointer or this completion failed.
+ ClangCodeCompleteResults results = completeSmartPointerCreation(line,
+ column,
+ funcNameStartLine,
+ funcNameStartColumn);
+
+ if (results.isNull() || results.isEmpty())
+ results = completeHelper(line, column);
+
filterUnknownContextResults(results, unsavedFile(), line, column);
tryDotArrowCorrectionIfNoResults(results, line, column);
@@ -97,6 +108,62 @@ CompletionCorrection CodeCompleter::neededCorrection() const
return neededCorrection_;
}
+// For given "make_unique<T>" / "make_shared<T>" / "QSharedPointer<T>::create" return "new T("
+// Otherwize return empty QString
+static QString tweakName(const QString &oldName)
+{
+ QString fullName = oldName.trimmed();
+ if (!fullName.contains('>'))
+ return QString();
+
+ if (!fullName.endsWith('>')) {
+ // This is the class<type>::method case - remove ::method part
+ if (!fullName.endsWith("create") || !fullName.contains("QSharedPointer"))
+ return QString();
+ fullName = fullName.mid(0, fullName.lastIndexOf(':') - 1);
+ } else if (!fullName.contains("make_unique") && !fullName.contains("make_shared")) {
+ return QString();
+ }
+ int templateStart = fullName.indexOf('<');
+ QString name = fullName.mid(0, templateStart);
+ QString templatePart = fullName.mid(templateStart + 1,
+ fullName.length() - templateStart - 2);
+ return "new " + templatePart + "(";
+}
+
+ClangCodeCompleteResults CodeCompleter::completeSmartPointerCreation(uint line,
+ uint column,
+ int funcNameStartLine,
+ int funcNameStartColumn)
+{
+ if (column <= 1 || funcNameStartLine == -1)
+ return ClangCodeCompleteResults();
+
+ UnsavedFile &file = unsavedFiles.unsavedFile(translationUnit.filePath());
+ if (!file.hasCharacterAt(line, column - 1, '('))
+ return ClangCodeCompleteResults();
+
+ bool ok;
+ const uint startPos = file.toUtf8Position(funcNameStartLine, funcNameStartColumn, &ok);
+ const uint endPos = file.toUtf8Position(line, column - 1, &ok);
+
+ Utf8String content = file.fileContent();
+ const QString oldName = content.mid(startPos, endPos - startPos);
+ const QString updatedName = tweakName(oldName);
+ if (updatedName.isEmpty())
+ return ClangCodeCompleteResults();
+
+ column += updatedName.length();
+ file.replaceAt(endPos + 1, 0, updatedName);
+
+ ClangCodeCompleteResults results = completeHelper(line, column);
+ if (results.isEmpty()) {
+ column -= updatedName.length();
+ file.replaceAt(endPos + 1, updatedName.length(), QString());
+ }
+ return results;
+}
+
ClangCodeCompleteResults CodeCompleter::completeHelper(uint line, uint column)
{
const Utf8String nativeFilePath = FilePath::toNativeSeparators(translationUnit.filePath());
diff --git a/src/tools/clangbackend/ipcsource/codecompleter.h b/src/tools/clangbackend/source/codecompleter.h
index 1b2dc4bb37..2026e9ba2c 100644
--- a/src/tools/clangbackend/ipcsource/codecompleter.h
+++ b/src/tools/clangbackend/source/codecompleter.h
@@ -43,7 +43,9 @@ public:
CodeCompleter(const TranslationUnit &translationUnit,
const UnsavedFiles &unsavedFiles);
- CodeCompletions complete(uint line, uint column);
+ CodeCompletions complete(uint line, uint column,
+ int funcNameStartLine = -1,
+ int funcNameStartColumn = -1);
CompletionCorrection neededCorrection() const;
@@ -56,6 +58,10 @@ private:
uint column);
ClangCodeCompleteResults completeHelper(uint line, uint column);
+ ClangCodeCompleteResults completeSmartPointerCreation(uint line,
+ uint column,
+ int funcNameStartLine,
+ int funcNameStartColumn);
ClangCodeCompleteResults completeWithArrowInsteadOfDot(uint line,
uint column,
uint dotPosition);
diff --git a/src/tools/clangbackend/ipcsource/codecompletionchunkconverter.cpp b/src/tools/clangbackend/source/codecompletionchunkconverter.cpp
index 76c578643f..76c578643f 100644
--- a/src/tools/clangbackend/ipcsource/codecompletionchunkconverter.cpp
+++ b/src/tools/clangbackend/source/codecompletionchunkconverter.cpp
diff --git a/src/tools/clangbackend/ipcsource/codecompletionchunkconverter.h b/src/tools/clangbackend/source/codecompletionchunkconverter.h
index 0bfb1a19c1..0bfb1a19c1 100644
--- a/src/tools/clangbackend/ipcsource/codecompletionchunkconverter.h
+++ b/src/tools/clangbackend/source/codecompletionchunkconverter.h
diff --git a/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp b/src/tools/clangbackend/source/codecompletionsextractor.cpp
index 1c810e5069..89dec4b1bf 100644
--- a/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp
+++ b/src/tools/clangbackend/source/codecompletionsextractor.cpp
@@ -42,8 +42,6 @@ bool CodeCompletionsExtractor::next()
{
const uint cxCodeCompleteResultCount = cxCodeCompleteResults->NumResults;
- ++cxCodeCompleteResultIndex;
-
if (cxCodeCompleteResultIndex < cxCodeCompleteResultCount) {
currentCxCodeCompleteResult = cxCodeCompleteResults->Results[cxCodeCompleteResultIndex];
@@ -58,6 +56,8 @@ bool CodeCompletionsExtractor::next()
extractCompletionChunks();
adaptPriority();
+ ++cxCodeCompleteResultIndex;
+
return true;
}
@@ -68,7 +68,7 @@ bool CodeCompletionsExtractor::peek(const Utf8String &name)
{
const uint cxCodeCompleteResultCount = cxCodeCompleteResults->NumResults;
- uint peekCxCodeCompleteResultIndex = cxCodeCompleteResultIndex + 1;
+ uint peekCxCodeCompleteResultIndex = cxCodeCompleteResultIndex;
while (peekCxCodeCompleteResultIndex < cxCodeCompleteResultCount) {
if (hasText(name, cxCodeCompleteResults->Results[peekCxCodeCompleteResultIndex].CompletionString))
diff --git a/src/tools/clangbackend/ipcsource/codecompletionsextractor.h b/src/tools/clangbackend/source/codecompletionsextractor.h
index 57e9bd5afc..bbb3611bf6 100644
--- a/src/tools/clangbackend/ipcsource/codecompletionsextractor.h
+++ b/src/tools/clangbackend/source/codecompletionsextractor.h
@@ -77,7 +77,7 @@ private:
CodeCompletion currentCodeCompletion_;
CXCompletionResult currentCxCodeCompleteResult;
CXCodeCompleteResults *cxCodeCompleteResults;
- uint cxCodeCompleteResultIndex = -1;
+ uint cxCodeCompleteResultIndex = 0;
};
std::ostream &operator<<(std::ostream &os, const CodeCompletionsExtractor &extractor);
diff --git a/src/tools/clangbackend/ipcsource/commandlinearguments.cpp b/src/tools/clangbackend/source/commandlinearguments.cpp
index a7f29b870f..a7f29b870f 100644
--- a/src/tools/clangbackend/ipcsource/commandlinearguments.cpp
+++ b/src/tools/clangbackend/source/commandlinearguments.cpp
diff --git a/src/tools/clangbackend/ipcsource/commandlinearguments.h b/src/tools/clangbackend/source/commandlinearguments.h
index aa0b2bafbf..aa0b2bafbf 100644
--- a/src/tools/clangbackend/ipcsource/commandlinearguments.h
+++ b/src/tools/clangbackend/source/commandlinearguments.h
diff --git a/src/tools/clangbackend/ipcsource/cursor.cpp b/src/tools/clangbackend/source/cursor.cpp
index 518fd013d2..6ad50307cd 100644
--- a/src/tools/clangbackend/ipcsource/cursor.cpp
+++ b/src/tools/clangbackend/source/cursor.cpp
@@ -273,6 +273,11 @@ CXSourceRange Cursor::cxSourceRange() const
return clang_getCursorExtent(cxCursor);
}
+CXTranslationUnit Cursor::cxTranslationUnit() const
+{
+ return clang_Cursor_getTranslationUnit(cxCursor);
+}
+
SourceRange Cursor::commentRange() const
{
return clang_Cursor_getCommentRange(cxCursor);
diff --git a/src/tools/clangbackend/ipcsource/cursor.h b/src/tools/clangbackend/source/cursor.h
index 0187d8448b..6520366b36 100644
--- a/src/tools/clangbackend/ipcsource/cursor.h
+++ b/src/tools/clangbackend/source/cursor.h
@@ -86,6 +86,7 @@ public:
CXSourceLocation cxSourceLocation() const;
SourceRange sourceRange() const;
CXSourceRange cxSourceRange() const;
+ CXTranslationUnit cxTranslationUnit() const;
SourceRange commentRange() const;
bool hasSameSourceLocationAs(const Cursor &other) const;
diff --git a/src/tools/clangbackend/ipcsource/diagnostic.cpp b/src/tools/clangbackend/source/diagnostic.cpp
index 5e74970ac2..5e74970ac2 100644
--- a/src/tools/clangbackend/ipcsource/diagnostic.cpp
+++ b/src/tools/clangbackend/source/diagnostic.cpp
diff --git a/src/tools/clangbackend/ipcsource/diagnostic.h b/src/tools/clangbackend/source/diagnostic.h
index 64d4eff9b7..140322931f 100644
--- a/src/tools/clangbackend/ipcsource/diagnostic.h
+++ b/src/tools/clangbackend/source/diagnostic.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangbackendipc_global.h>
+#include <clangsupport_global.h>
#include <clang-c/Index.h>
diff --git a/src/tools/clangbackend/ipcsource/diagnosticset.cpp b/src/tools/clangbackend/source/diagnosticset.cpp
index ce3504a114..ce3504a114 100644
--- a/src/tools/clangbackend/ipcsource/diagnosticset.cpp
+++ b/src/tools/clangbackend/source/diagnosticset.cpp
diff --git a/src/tools/clangbackend/ipcsource/diagnosticset.h b/src/tools/clangbackend/source/diagnosticset.h
index e715ad2627..e715ad2627 100644
--- a/src/tools/clangbackend/ipcsource/diagnosticset.h
+++ b/src/tools/clangbackend/source/diagnosticset.h
diff --git a/src/tools/clangbackend/ipcsource/diagnosticsetiterator.h b/src/tools/clangbackend/source/diagnosticsetiterator.h
index 7739dfd365..7739dfd365 100644
--- a/src/tools/clangbackend/ipcsource/diagnosticsetiterator.h
+++ b/src/tools/clangbackend/source/diagnosticsetiterator.h
diff --git a/src/tools/clangbackend/ipcsource/fixit.cpp b/src/tools/clangbackend/source/fixit.cpp
index c2de39c922..c2de39c922 100644
--- a/src/tools/clangbackend/ipcsource/fixit.cpp
+++ b/src/tools/clangbackend/source/fixit.cpp
diff --git a/src/tools/clangbackend/ipcsource/fixit.h b/src/tools/clangbackend/source/fixit.h
index f866bc8c18..f866bc8c18 100644
--- a/src/tools/clangbackend/ipcsource/fixit.h
+++ b/src/tools/clangbackend/source/fixit.h
diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.cpp b/src/tools/clangbackend/source/highlightingmark.cpp
index 510192b6e7..9339d4ba9e 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmark.cpp
+++ b/src/tools/clangbackend/source/highlightingmark.cpp
@@ -105,7 +105,8 @@ bool HighlightingMark::hasFunctionArguments() const
HighlightingMark::operator HighlightingMarkContainer() const
{
- return HighlightingMarkContainer(m_line, m_column, m_length, m_types);
+ return HighlightingMarkContainer(m_line, m_column, m_length, m_types, m_isIdentifier,
+ m_isInclusion);
}
namespace {
@@ -288,6 +289,8 @@ void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion)
void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
{
+ m_isIdentifier = (cursor.kind() != CXCursor_PreprocessingDirective);
+
switch (cursor.kind()) {
case CXCursor_Destructor:
case CXCursor_Constructor:
@@ -352,6 +355,7 @@ HighlightingType literalKind(const Cursor &cursor)
switch (cursor.kind()) {
case CXCursor_CharacterLiteral:
case CXCursor_StringLiteral:
+ case CXCursor_InclusionDirective:
case CXCursor_ObjCStringLiteral: return HighlightingType::StringLiteral;
case CXCursor_IntegerLiteral:
case CXCursor_ImaginaryLiteral:
@@ -438,6 +442,8 @@ void HighlightingMark::collectKinds(CXTranslationUnit cxTranslationUnit,
case CXToken_Comment: m_types.mainHighlightingType = HighlightingType::Comment; break;
case CXToken_Literal: m_types.mainHighlightingType = literalKind(cursor); break;
}
+
+ m_isInclusion = (cursor.kind() == CXCursor_InclusionDirective);
}
std::ostream &operator<<(std::ostream &os, const HighlightingMark& highlightingMark)
diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.h b/src/tools/clangbackend/source/highlightingmark.h
index a749a5c922..b322391c49 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmark.h
+++ b/src/tools/clangbackend/source/highlightingmark.h
@@ -25,7 +25,7 @@
#pragma once
-#include <clangbackendipc_global.h>
+#include <clangsupport_global.h>
#include <highlightingmarkcontainer.h>
#include "cursor.h"
@@ -87,6 +87,8 @@ private:
uint m_length;
uint m_offset = 0;
HighlightingTypes m_types;
+ bool m_isIdentifier = false;
+ bool m_isInclusion = false;
};
diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp b/src/tools/clangbackend/source/highlightingmarks.cpp
index 2e157ff835..ed8ddfdd65 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp
+++ b/src/tools/clangbackend/source/highlightingmarks.cpp
@@ -68,15 +68,12 @@ QVector<HighlightingMarkContainer> HighlightingMarks::toHighlightingMarksContain
const auto isValidHighlightMark = [] (const HighlightingMark &highlightMark) {
return !highlightMark.hasInvalidMainType()
- && !highlightMark.hasMainType(HighlightingType::StringLiteral)
- && !highlightMark.hasMainType(HighlightingType::NumberLiteral)
- && !highlightMark.hasMainType(HighlightingType::Comment);
+ && !highlightMark.hasMainType(HighlightingType::NumberLiteral)
+ && !highlightMark.hasMainType(HighlightingType::Comment);
};
-
- for (const HighlightingMark &highlightMark : *this) {
+ for (const HighlightingMark &highlightMark : *this)
if (isValidHighlightMark(highlightMark))
containers.push_back(highlightMark);
- }
return containers;
}
diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.h b/src/tools/clangbackend/source/highlightingmarks.h
index e573dc267e..e573dc267e 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmarks.h
+++ b/src/tools/clangbackend/source/highlightingmarks.h
diff --git a/src/tools/clangbackend/ipcsource/highlightingmarksiterator.h b/src/tools/clangbackend/source/highlightingmarksiterator.h
index daeada47a7..daeada47a7 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmarksiterator.h
+++ b/src/tools/clangbackend/source/highlightingmarksiterator.h
diff --git a/src/tools/clangbackend/ipcsource/projectpart.cpp b/src/tools/clangbackend/source/projectpart.cpp
index 4ea8db6609..4ea8db6609 100644
--- a/src/tools/clangbackend/ipcsource/projectpart.cpp
+++ b/src/tools/clangbackend/source/projectpart.cpp
diff --git a/src/tools/clangbackend/ipcsource/projectpart.h b/src/tools/clangbackend/source/projectpart.h
index b96089d283..b96089d283 100644
--- a/src/tools/clangbackend/ipcsource/projectpart.h
+++ b/src/tools/clangbackend/source/projectpart.h
diff --git a/src/tools/clangbackend/ipcsource/projects.cpp b/src/tools/clangbackend/source/projects.cpp
index 1a28b9e785..1a28b9e785 100644
--- a/src/tools/clangbackend/ipcsource/projects.cpp
+++ b/src/tools/clangbackend/source/projects.cpp
diff --git a/src/tools/clangbackend/ipcsource/projects.h b/src/tools/clangbackend/source/projects.h
index 4354aebbeb..4354aebbeb 100644
--- a/src/tools/clangbackend/ipcsource/projects.h
+++ b/src/tools/clangbackend/source/projects.h
diff --git a/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp b/src/tools/clangbackend/source/skippedsourceranges.cpp
index ca38510cf2..ca38510cf2 100644
--- a/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp
+++ b/src/tools/clangbackend/source/skippedsourceranges.cpp
diff --git a/src/tools/clangbackend/ipcsource/skippedsourceranges.h b/src/tools/clangbackend/source/skippedsourceranges.h
index 80bc943676..80bc943676 100644
--- a/src/tools/clangbackend/ipcsource/skippedsourceranges.h
+++ b/src/tools/clangbackend/source/skippedsourceranges.h
diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.cpp b/src/tools/clangbackend/source/sourcelocation.cpp
index 161ed5b0a5..161ed5b0a5 100644
--- a/src/tools/clangbackend/ipcsource/sourcelocation.cpp
+++ b/src/tools/clangbackend/source/sourcelocation.cpp
diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.h b/src/tools/clangbackend/source/sourcelocation.h
index 65c3ec69ad..65c3ec69ad 100644
--- a/src/tools/clangbackend/ipcsource/sourcelocation.h
+++ b/src/tools/clangbackend/source/sourcelocation.h
diff --git a/src/tools/clangbackend/ipcsource/sourcerange.cpp b/src/tools/clangbackend/source/sourcerange.cpp
index 20c6efb5e6..20c6efb5e6 100644
--- a/src/tools/clangbackend/ipcsource/sourcerange.cpp
+++ b/src/tools/clangbackend/source/sourcerange.cpp
diff --git a/src/tools/clangbackend/ipcsource/sourcerange.h b/src/tools/clangbackend/source/sourcerange.h
index b8083e8695..b8083e8695 100644
--- a/src/tools/clangbackend/ipcsource/sourcerange.h
+++ b/src/tools/clangbackend/source/sourcerange.h
diff --git a/src/tools/clangbackend/ipcsource/unsavedfile.cpp b/src/tools/clangbackend/source/unsavedfile.cpp
index 923d4456e8..923d4456e8 100644
--- a/src/tools/clangbackend/ipcsource/unsavedfile.cpp
+++ b/src/tools/clangbackend/source/unsavedfile.cpp
diff --git a/src/tools/clangbackend/ipcsource/unsavedfile.h b/src/tools/clangbackend/source/unsavedfile.h
index 3021da89b5..3021da89b5 100644
--- a/src/tools/clangbackend/ipcsource/unsavedfile.h
+++ b/src/tools/clangbackend/source/unsavedfile.h
diff --git a/src/tools/clangbackend/ipcsource/unsavedfiles.cpp b/src/tools/clangbackend/source/unsavedfiles.cpp
index 64f2afe3ff..64f2afe3ff 100644
--- a/src/tools/clangbackend/ipcsource/unsavedfiles.cpp
+++ b/src/tools/clangbackend/source/unsavedfiles.cpp
diff --git a/src/tools/clangbackend/ipcsource/unsavedfiles.h b/src/tools/clangbackend/source/unsavedfiles.h
index eacab0bc34..eacab0bc34 100644
--- a/src/tools/clangbackend/ipcsource/unsavedfiles.h
+++ b/src/tools/clangbackend/source/unsavedfiles.h
diff --git a/src/tools/clangbackend/ipcsource/utf8positionfromlinecolumn.cpp b/src/tools/clangbackend/source/utf8positionfromlinecolumn.cpp
index 1d7ea1a88f..1d7ea1a88f 100644
--- a/src/tools/clangbackend/ipcsource/utf8positionfromlinecolumn.cpp
+++ b/src/tools/clangbackend/source/utf8positionfromlinecolumn.cpp
diff --git a/src/tools/clangbackend/ipcsource/utf8positionfromlinecolumn.h b/src/tools/clangbackend/source/utf8positionfromlinecolumn.h
index facb152772..facb152772 100644
--- a/src/tools/clangbackend/ipcsource/utf8positionfromlinecolumn.h
+++ b/src/tools/clangbackend/source/utf8positionfromlinecolumn.h
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro b/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro
index b115782dfe..8dab349dd3 100644
--- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro
+++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackend.pro
@@ -1,5 +1,5 @@
QTC_LIB_DEPENDS += \
- clangbackendipc
+ clangsupport
include(../../qtcreatortool.pri)
include(../../shared/clang/clang_installation.pri)
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
index a8eb4ce09a..5622179272 100644
--- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
+++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
@@ -50,7 +50,7 @@ using ClangBackEnd::PchGenerator;
using ClangBackEnd::PchManagerClientProxy;
using ClangBackEnd::PchManagerServer;
using ClangBackEnd::ProjectParts;
-using ClangBackEnd::StringCache;
+using ClangBackEnd::FilePathCache;
class ApplicationEnvironment : public ClangBackEnd::Environment
{
@@ -103,7 +103,7 @@ int main(int argc, char *argv[])
const QString connection = processArguments(application);
- StringCache<Utils::PathString> filePathCache;
+ FilePathCache<> filePathCache;
ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache);
ApplicationEnvironment environment;
PchGenerator<QProcess> pchGenerator(environment);
diff --git a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h
index ba990c6cf9..85ad8bbd63 100644
--- a/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h
+++ b/src/tools/clangpchmanagerbackend/source/clangpathwatcher.h
@@ -37,8 +37,8 @@ namespace ClangBackEnd {
class WatcherEntry
{
public:
- uint id;
- uint path;
+ FilePathIndex id;
+ FilePathIndex path;
friend bool operator==(const WatcherEntry &first, const WatcherEntry &second)
{
@@ -50,12 +50,12 @@ public:
return std::tie(first.path, first.id) < std::tie(second.path, second.id);
}
- friend bool operator<(const WatcherEntry &entry, uint path)
+ friend bool operator<(const WatcherEntry &entry, FilePathIndex path)
{
return entry.path < path;
}
- friend bool operator<(uint path, const WatcherEntry &entry)
+ friend bool operator<(FilePathIndex path, const WatcherEntry &entry)
{
return path < entry.path;
}
@@ -63,12 +63,18 @@ public:
using WatcherEntries = std::vector<WatcherEntry>;
+using IdCache = StringCache<Utils::SmallString,
+ FilePathIndex,
+ NonLockingMutex,
+ decltype(&Utils::compare),
+ Utils::compare>;
+
template <typename FileSystemWatcher,
typename Timer>
class ClangPathWatcher : public ClangPathWatcherInterface
{
public:
- ClangPathWatcher(StringCache<Utils::PathString> &pathCache,
+ ClangPathWatcher(FilePathCache<> &pathCache,
ClangPathWatcherNotifier *notifier=nullptr)
: m_pathCache(pathCache),
m_notifier(notifier)
@@ -130,9 +136,9 @@ unittest_public:
return ids;
}
- std::vector<uint> convertToIdNumbers(const Utils::SmallStringVector &ids)
+ std::vector<FilePathIndex> convertToIdNumbers(const Utils::SmallStringVector &ids)
{
- std::vector<uint> idNumbers = m_idCache.stringIds(ids);
+ std::vector<FilePathIndex> idNumbers = m_idCache.stringIds(ids);
std::sort(idNumbers.begin(), idNumbers.end());
@@ -149,19 +155,19 @@ unittest_public:
}
- std::pair<WatcherEntries,std::vector<uint>>
+ std::pair<WatcherEntries,std::vector<FilePathIndex>>
convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
{
WatcherEntries entries;
entries.reserve(sizeOfIdPaths(idPaths));
- std::vector<uint> ids;
+ std::vector<FilePathIndex> ids;
ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths)
{
- uint id = m_idCache.stringId(idPath.id);
+ FilePathIndex id = m_idCache.stringId(idPath.id);
ids.push_back(id);
@@ -190,7 +196,7 @@ unittest_public:
}
void removeUnusedEntries(const WatcherEntries &entries,
- const std::vector<uint> &ids)
+ const std::vector<FilePathIndex> &ids)
{
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
@@ -216,7 +222,7 @@ unittest_public:
std::transform(watcherEntries.begin(),
watcherEntries.end(),
std::back_inserter(paths),
- [&] (const WatcherEntry &entry) { return m_pathCache.string(entry.path); });
+ [&] (const WatcherEntry &entry) { return QString(m_pathCache.string(entry.path)); });
return paths;
}
@@ -272,7 +278,7 @@ unittest_public:
WatcherEntries notAnymoreWatchedEntriesWithIds(
const WatcherEntries &newEntries,
- const std::vector<uint> &ids) const
+ const std::vector<FilePathIndex> &ids) const
{
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
@@ -328,7 +334,7 @@ unittest_public:
return m_watchedEntries;
}
- WatcherEntries removeIdsFromWatchedEntries(const std::vector<uint> &ids)
+ WatcherEntries removeIdsFromWatchedEntries(const std::vector<FilePathIndex> &ids)
{
auto keep = [&] (const WatcherEntry &entry) {
@@ -368,7 +374,7 @@ unittest_public:
WatcherEntries watchedEntriesForPaths(Utils::PathStringVector &&filePaths)
{
- std::vector<uint> pathIds = m_pathCache.stringIds(filePaths);
+ std::vector<FilePathIndex> pathIds = m_pathCache.stringIds(filePaths);
WatcherEntries foundEntries;
@@ -388,7 +394,7 @@ unittest_public:
foundEntries.end(),
std::back_inserter(ids),
[&] (const WatcherEntry &entry) {
- return m_idCache.string(entry.id);
+ return Utils::SmallString(m_idCache.string(entry.id));
});
return ids;
@@ -414,22 +420,22 @@ unittest_public:
}
}
- StringCache<Utils::PathString> &pathCache()
+ FilePathCache<> &pathCache()
{
return m_pathCache;
}
- StringCache<Utils::SmallString> &idCache()
+ IdCache &idCache()
{
return m_idCache;
}
private:
- StringCache<Utils::SmallString> m_idCache;
+ IdCache m_idCache;
WatcherEntries m_watchedEntries;
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor;
FileSystemWatcher m_fileSystemWatcher;
- StringCache<Utils::PathString> &m_pathCache;
+ FilePathCache<> &m_pathCache;
ClangPathWatcherNotifier *m_notifier;
};
diff --git a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h
index 5b8b8ad5e6..339d491848 100644
--- a/src/tools/clangpchmanagerbackend/source/collectincludesaction.h
+++ b/src/tools/clangpchmanagerbackend/source/collectincludesaction.h
@@ -38,10 +38,10 @@ namespace ClangBackEnd {
class CollectIncludesAction final : public clang::PreprocessOnlyAction
{
public:
- CollectIncludesAction(std::vector<uint> &includeIds,
- StringCache<Utils::PathString> &filePathCache,
- std::vector<uint> &excludedIncludeUID,
- std::vector<uint> &alreadyIncludedFileUIDs)
+ CollectIncludesAction(FilePathIndices &includeIds,
+ FilePathCache<> &filePathCache,
+ FilePathIndices &excludedIncludeUID,
+ FilePathIndices &alreadyIncludedFileUIDs)
: m_includeIds(includeIds),
m_filePathCache(filePathCache),
m_excludedIncludeUID(excludedIncludeUID),
@@ -78,10 +78,10 @@ public:
}
private:
- std::vector<uint> &m_includeIds;
- StringCache<Utils::PathString> &m_filePathCache;
- std::vector<uint> &m_excludedIncludeUID;
- std::vector<uint> &m_alreadyIncludedFileUIDs;
+ FilePathIndices &m_includeIds;
+ FilePathCache<> &m_filePathCache;
+ FilePathIndices &m_excludedIncludeUID;
+ FilePathIndices &m_alreadyIncludedFileUIDs;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h
index ba86822fce..a57d72adfc 100644
--- a/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h
+++ b/src/tools/clangpchmanagerbackend/source/collectincludespreprocessorcallbacks.h
@@ -47,10 +47,10 @@ class CollectIncludesPreprocessorCallbacks final : public clang::PPCallbacks
{
public:
CollectIncludesPreprocessorCallbacks(clang::HeaderSearch &headerSearch,
- std::vector<uint> &includeIds,
- StringCache<Utils::PathString> &filePathCache,
- const std::vector<uint> &excludedIncludeUID,
- std::vector<uint> &alreadyIncludedFileUIDs)
+ std::vector<FilePathIndex> &includeIds,
+ FilePathCache<> &filePathCache,
+ const std::vector<FilePathIndex> &excludedIncludeUID,
+ std::vector<FilePathIndex> &alreadyIncludedFileUIDs)
: m_headerSearch(headerSearch),
m_includeIds(includeIds),
m_filePathCache(filePathCache),
@@ -78,7 +78,7 @@ public:
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second, fileUID);
Utils::PathString filePath = filePathFromFile(file);
if (!filePath.isEmpty()) {
- uint includeId = m_filePathCache.stringId(filePath);
+ FilePathIndex includeId = m_filePathCache.stringId(filePath);
m_includeIds.emplace_back(includeId);
}
}
@@ -132,7 +132,7 @@ public:
uid);
}
- std::pair<bool, std::vector<uint>::iterator> isNotAlreadyIncluded(uint uid) const
+ std::pair<bool, std::vector<FilePathIndex>::iterator> isNotAlreadyIncluded(FilePathIndex uid) const
{
auto range = std::equal_range(m_alreadyIncludedFileUIDs.begin(),
m_alreadyIncludedFileUIDs.end(),
@@ -174,10 +174,10 @@ public:
private:
clang::HeaderSearch &m_headerSearch;
- std::vector<uint> &m_includeIds;
- StringCache<Utils::PathString> &m_filePathCache;
- const std::vector<uint> &m_excludedIncludeUID;
- std::vector<uint> &m_alreadyIncludedFileUIDs;
+ std::vector<FilePathIndex> &m_includeIds;
+ FilePathCache<> &m_filePathCache;
+ const std::vector<FilePathIndex> &m_excludedIncludeUID;
+ std::vector<FilePathIndex> &m_alreadyIncludedFileUIDs;
bool m_skipInclude = false;
};
diff --git a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h
index 87e92c1df3..42b8a62cea 100644
--- a/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h
+++ b/src/tools/clangpchmanagerbackend/source/collectincludestoolaction.h
@@ -36,8 +36,8 @@ namespace ClangBackEnd {
class CollectIncludesToolAction final : public clang::tooling::FrontendActionFactory
{
public:
- CollectIncludesToolAction(std::vector<uint> &includeIds,
- StringCache<Utils::PathString> &filePathCache,
+ CollectIncludesToolAction(std::vector<FilePathIndex> &includeIds,
+ FilePathCache<> &filePathCache,
const Utils::PathStringVector &excludedIncludes)
: m_includeIds(includeIds),
m_filePathCache(filePathCache),
@@ -72,9 +72,9 @@ public:
m_alreadyIncludedFileUIDs);
}
- std::vector<uint> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
+ std::vector<FilePathIndex> generateExcludedIncludeFileUIDs(clang::FileManager &fileManager) const
{
- std::vector<uint> fileUIDs;
+ std::vector<FilePathIndex> fileUIDs;
fileUIDs.reserve(m_excludedIncludes.size());
for (const Utils::PathString &filePath : m_excludedIncludes) {
@@ -90,10 +90,10 @@ public:
}
private:
- std::vector<uint> m_alreadyIncludedFileUIDs;
- std::vector<uint> m_excludedIncludeUIDs;
- std::vector<uint> &m_includeIds;
- StringCache<Utils::PathString> &m_filePathCache;
+ std::vector<FilePathIndex> m_alreadyIncludedFileUIDs;
+ std::vector<FilePathIndex> m_excludedIncludeUIDs;
+ std::vector<FilePathIndex> &m_includeIds;
+ FilePathCache<> &m_filePathCache;
const Utils::PathStringVector &m_excludedIncludes;
};
diff --git a/src/tools/clangpchmanagerbackend/source/idpaths.h b/src/tools/clangpchmanagerbackend/source/idpaths.h
index f6f312f05f..a407e24530 100644
--- a/src/tools/clangpchmanagerbackend/source/idpaths.h
+++ b/src/tools/clangpchmanagerbackend/source/idpaths.h
@@ -29,13 +29,15 @@
#include <iosfwd>
+#include <stringcachefwd.h>
+
namespace ClangBackEnd {
class IdPaths
{
public:
Utils::SmallString id;
- std::vector<uint> paths;
+ std::vector<FilePathIndex> paths;
friend bool operator==(const IdPaths &first, const IdPaths &second)
{
diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.cpp b/src/tools/clangpchmanagerbackend/source/includecollector.cpp
index b380fa2b8b..421123b3a7 100644
--- a/src/tools/clangpchmanagerbackend/source/includecollector.cpp
+++ b/src/tools/clangpchmanagerbackend/source/includecollector.cpp
@@ -33,7 +33,7 @@
namespace ClangBackEnd {
-IncludeCollector::IncludeCollector(StringCache<Utils::PathString> &filePathCache)
+IncludeCollector::IncludeCollector(FilePathCache<> &filePathCache)
: m_filePathCache(filePathCache)
{
}
@@ -69,7 +69,7 @@ void IncludeCollector::setExcludedIncludes(Utils::PathStringVector &&excludedInc
#endif
}
-std::vector<uint> IncludeCollector::takeIncludeIds()
+std::vector<FilePathIndex> IncludeCollector::takeIncludeIds()
{
std::sort(m_includeIds.begin(), m_includeIds.end());
diff --git a/src/tools/clangpchmanagerbackend/source/includecollector.h b/src/tools/clangpchmanagerbackend/source/includecollector.h
index ba485ea33d..73f9b948af 100644
--- a/src/tools/clangpchmanagerbackend/source/includecollector.h
+++ b/src/tools/clangpchmanagerbackend/source/includecollector.h
@@ -34,19 +34,19 @@ namespace ClangBackEnd {
class IncludeCollector : public ClangTool
{
public:
- IncludeCollector(StringCache<Utils::PathString> &filePathCache);
+ IncludeCollector(FilePathCache<> &filePathCache);
void collectIncludes();
void setExcludedIncludes(Utils::PathStringVector &&excludedIncludes);
- std::vector<uint> takeIncludeIds();
+ std::vector<FilePathIndex> takeIncludeIds();
private:
Utils::PathStringVector m_excludedIncludes;
- std::vector<uint> m_includeIds;
+ std::vector<FilePathIndex> m_includeIds;
Utils::SmallStringVector m_directories;
- StringCache<Utils::PathString> &m_filePathCache;
+ FilePathCache<> &m_filePathCache;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
index 31485b8ed1..fd6da58012 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
@@ -37,7 +37,7 @@
namespace ClangBackEnd {
-PchCreator::PchCreator(Environment &environment, StringCache<Utils::PathString> &filePathCache)
+PchCreator::PchCreator(Environment &environment, FilePathCache<> &filePathCache)
: m_environment(environment),
m_filePathCache(filePathCache)
{
@@ -45,7 +45,7 @@ PchCreator::PchCreator(Environment &environment, StringCache<Utils::PathString>
PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment,
- StringCache<Utils::PathString> &filePathCache,
+ FilePathCache<> &filePathCache,
PchGeneratorInterface *pchGenerator,
V2::FileContainers &&generatedFiles)
: m_projectParts(std::move(projectsParts)),
@@ -66,24 +66,24 @@ template <typename Source,
typename Target>
void append(Target &target, const Source &source)
{
+ using ValueType = typename Target::value_type;
Source clonedSource = source.clone();
target.reserve(target.size() + source.size());
- std::move(clonedSource.begin(),
- clonedSource.end(),
- std::back_inserter(target));
+ for (auto &&entry : clonedSource)
+ target.push_back(ValueType(std::move(entry)));
}
template <typename Source,
typename Target>
void append(Target &target, Source &source)
{
+ using ValueType = typename Target::value_type;
target.reserve(target.size() + source.size());
- std::move(source.begin(),
- source.end(),
- std::back_inserter(target));
+ for (auto &&entry : source)
+ target.push_back(ValueType(entry));
}
template <typename GetterFunction>
@@ -239,7 +239,7 @@ Utils::SmallStringVector PchCreator::generateGlobalClangCompilerArguments() cons
return compilerArguments;
}
-std::vector<uint> PchCreator::generateGlobalPchIncludeIds() const
+std::vector<FilePathIndex> PchCreator::generateGlobalPchIncludeIds() const
{
IncludeCollector collector(m_filePathCache);
@@ -267,7 +267,7 @@ std::size_t contentSize(const std::vector<Utils::PathString> &includes)
}
Utils::SmallString PchCreator::generatePchIncludeFileContent(
- const std::vector<uint> &includeIds) const
+ const std::vector<FilePathIndex> &includeIds) const
{
Utils::SmallString fileContent;
const std::size_t lineTemplateSize = 12;
@@ -461,7 +461,7 @@ Utils::PathStringVector PchCreator::generateProjectPartHeaderAndSourcePaths(
return includeAndSources;
}
-std::vector<uint> PchCreator::generateProjectPartPchIncludes(
+std::vector<FilePathIndex> PchCreator::generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const
{
Utils::SmallString jointedFileContent = generateProjectPartHeaderAndSourcesContent(projectPart);
@@ -469,14 +469,14 @@ std::vector<uint> PchCreator::generateProjectPartPchIncludes(
auto jointFile = generateFileWithContent(jointedFilePath, jointedFileContent);
Utils::SmallStringVector arguments = generateProjectPartCommandLine(projectPart);
arguments.push_back(jointedFilePath);
- FilePath filePath(jointedFilePath.clone());
+ FilePath filePath{Utils::PathString(jointedFilePath)};
IncludeCollector collector(m_filePathCache);
collector.setExcludedIncludes(generateProjectPartHeaderAndSourcePaths(projectPart));
- collector.addFile(filePath.directory(),
- filePath.name(),
+ collector.addFile(std::string(filePath.directory()),
+ std::string(filePath.name()),
{},
arguments);
@@ -581,11 +581,11 @@ std::unique_ptr<QFile> PchCreator::generateFileWithContent(
const Utils::SmallString &filePath,
const Utils::SmallString &content)
{
- std::unique_ptr<QFile> precompiledIncludeFile(new QFile(filePath));
+ std::unique_ptr<QFile> precompiledIncludeFile(new QFile(QString(filePath)));
precompiledIncludeFile->open(QIODevice::WriteOnly);
- precompiledIncludeFile->write(content.data(), content.size());
+ precompiledIncludeFile->write(content.data(), qint64(content.size()));
precompiledIncludeFile->close();
return precompiledIncludeFile;
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h
index 1b418ad3db..5548ec7acd 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.h
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h
@@ -48,10 +48,10 @@ class PchCreator final : public PchCreatorInterface
{
public:
PchCreator(Environment &environment,
- StringCache<Utils::PathString> &filePathCache);
+ FilePathCache<> &filePathCache);
PchCreator(V2::ProjectPartContainers &&projectsParts,
Environment &environment,
- StringCache<Utils::PathString> &filePathCache,
+ FilePathCache<> &filePathCache,
PchGeneratorInterface *pchGenerator,
V2::FileContainers &&generatedFiles);
@@ -70,9 +70,9 @@ unittest_public:
Utils::SmallStringVector generateGlobalPchCompilerArguments() const;
Utils::SmallStringVector generateGlobalClangCompilerArguments() const;
- std::vector<uint> generateGlobalPchIncludeIds() const;
+ std::vector<FilePathIndex> generateGlobalPchIncludeIds() const;
- Utils::SmallString generatePchIncludeFileContent(const std::vector<uint> &includeIds) const;
+ Utils::SmallString generatePchIncludeFileContent(const std::vector<FilePathIndex> &includeIds) const;
Utils::SmallString generateGlobalPchHeaderFileContent() const;
std::unique_ptr<QFile> generateGlobalPchHeaderFile();
void generatePch(Utils::SmallStringVector &&commandLineArguments,
@@ -97,7 +97,7 @@ unittest_public:
const V2::ProjectPartContainer &projectPart);
static Utils::PathStringVector generateProjectPartHeaderAndSourcePaths(
const V2::ProjectPartContainer &projectPart);
- std::vector<uint> generateProjectPartPchIncludes(
+ std::vector<FilePathIndex> generateProjectPartPchIncludes(
const V2::ProjectPartContainer &projectPart) const;
Utils::SmallString generateProjectPathPchHeaderFilePath(
const V2::ProjectPartContainer &projectPart) const;
@@ -127,7 +127,7 @@ private:
std::vector<ProjectPartPch> m_projectPartPchs;
std::vector<IdPaths> m_projectsIncludeIds;
Environment &m_environment;
- StringCache<Utils::PathString> &m_filePathCache;
+ FilePathCache<> &m_filePathCache;
PchGeneratorInterface *m_pchGenerator = nullptr;
};
diff --git a/src/tools/clangpchmanagerbackend/source/pchgenerator.h b/src/tools/clangpchmanagerbackend/source/pchgenerator.h
index ca8438506f..144f21bffa 100644
--- a/src/tools/clangpchmanagerbackend/source/pchgenerator.h
+++ b/src/tools/clangpchmanagerbackend/source/pchgenerator.h
@@ -70,8 +70,8 @@ unittest_public:
Process *processPointer = process.get();
process->setProcessChannelMode(QProcess::ForwardedChannels);
- process->setArguments(compilerArguments);
- process->setProgram(m_environment.clangCompilerPath());
+ process->setArguments(QStringList(compilerArguments));
+ process->setProgram(QString(m_environment.clangCompilerPath()));
connectProcess(processPointer, std::move(projectPartPch));
diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
index f22458c8b3..03261ae164 100644
--- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp
@@ -36,7 +36,7 @@
namespace ClangBackEnd {
-PchManagerServer::PchManagerServer(StringCache<Utils::PathString> &filePathCache,
+PchManagerServer::PchManagerServer(FilePathCache<> &filePathCache,
ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts)
diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h
index e28a3658e2..7be9c75966 100644
--- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h
+++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h
@@ -33,16 +33,20 @@
#include "projectpartsinterface.h"
#include "stringcache.h"
+#include <ipcclientprovider.h>
+
namespace ClangBackEnd {
class SourceRangesAndDiagnosticsForQueryMessage;
class PchManagerServer : public PchManagerServerInterface,
public ClangPathWatcherNotifier,
- public PchGeneratorNotifierInterface
+ public PchGeneratorNotifierInterface,
+ public IpcClientProvider<PchManagerClientInterface>
+
{
public:
- PchManagerServer(StringCache<Utils::PathString> &filePathCache,
+ PchManagerServer(FilePathCache<> &filePathCache,
ClangPathWatcherInterface &fileSystemWatcher,
PchCreatorInterface &pchCreator,
ProjectPartsInterface &projectParts);
@@ -56,7 +60,7 @@ public:
void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override;
private:
- StringCache<Utils::PathString> &m_filePathCache;
+ FilePathCache<> &m_filePathCache;
ClangPathWatcherInterface &m_fileSystemWatcher;
PchCreatorInterface &m_pchCreator;
ProjectPartsInterface &m_projectParts;
diff --git a/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro b/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro
index 705198f216..3b94d003c0 100644
--- a/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro
+++ b/src/tools/clangrefactoringbackend/clangrefactoringbackend.pro
@@ -1,5 +1,5 @@
QTC_LIB_DEPENDS += \
- clangbackendipc
+ clangsupport
include(../../qtcreatortool.pri)
include(../../shared/clang/clang_installation.pri)
diff --git a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp
index fca9a0c9fc..8c5fe3f751 100644
--- a/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp
+++ b/src/tools/clangrefactoringbackend/clangrefactoringbackendmain.cpp
@@ -26,14 +26,19 @@
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QLoggingCategory>
+#include <QDir>
#include <connectionserver.h>
+#include <stringcache.h>
#include <refactoringserver.h>
#include <refactoringclientproxy.h>
+#include <symbolindexing.h>
+using ClangBackEnd::FilePathCache;
using ClangBackEnd::RefactoringClientProxy;
using ClangBackEnd::RefactoringServer;
using ClangBackEnd::ConnectionServer;
+using ClangBackEnd::SymbolIndexing;
QString processArguments(QCoreApplication &application)
{
@@ -52,7 +57,7 @@ QString processArguments(QCoreApplication &application)
}
int main(int argc, char *argv[])
-{
+try {
//QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false"));
QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
@@ -64,13 +69,17 @@ int main(int argc, char *argv[])
const QString connection = processArguments(application);
- RefactoringServer clangCodeModelServer;
+ FilePathCache<std::mutex> filePathCache;
+ SymbolIndexing symbolIndexing{filePathCache, Utils::PathString{QDir::tempPath() + "/symbol.db"}};
+ RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache};
ConnectionServer<RefactoringServer, RefactoringClientProxy> connectionServer(connection);
connectionServer.start();
connectionServer.setServer(&clangCodeModelServer);
return application.exec();
+} catch (const Sqlite::Exception &exception) {
+ exception.printWarning();
}
diff --git a/src/tools/clangrefactoringbackend/source/clangquery.cpp b/src/tools/clangrefactoringbackend/source/clangquery.cpp
index b625e9e197..620a7ebaab 100644
--- a/src/tools/clangrefactoringbackend/source/clangquery.cpp
+++ b/src/tools/clangrefactoringbackend/source/clangquery.cpp
@@ -54,7 +54,7 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
}
};
-ClangQuery::ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache,
+ClangQuery::ClangQuery(FilePathCache<std::mutex> &filePathCache,
Utils::SmallString &&query)
: query(std::move(query)),
filePathCache(filePathCache)
diff --git a/src/tools/clangrefactoringbackend/source/clangquery.h b/src/tools/clangrefactoringbackend/source/clangquery.h
index faa5821ca3..7d99766008 100644
--- a/src/tools/clangrefactoringbackend/source/clangquery.h
+++ b/src/tools/clangrefactoringbackend/source/clangquery.h
@@ -51,7 +51,7 @@ namespace ClangBackEnd {
class ClangQuery : public ClangTool
{
public:
- ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, Utils::SmallString &&query={});
+ ClangQuery(FilePathCache<std::mutex> &filePathCache, Utils::SmallString &&query={});
void setQuery(Utils::SmallString &&query);
@@ -69,7 +69,7 @@ private:
SourceRangesContainer sourceRangesContainer;
Utils::SmallString query;
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_;
- StringCache<Utils::PathString, std::mutex> &filePathCache;
+ FilePathCache<std::mutex> &filePathCache;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp
index 319cfaa47d..692065a9e7 100644
--- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp
+++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp
@@ -29,7 +29,7 @@
namespace ClangBackEnd {
-ClangQueryGatherer::ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache,
+ClangQueryGatherer::ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query)
@@ -43,17 +43,17 @@ ClangQueryGatherer::ClangQueryGatherer(StringCache<Utils::PathString, std::mutex
SourceRangesForQueryMessage
ClangQueryGatherer::createSourceRangesForSource(
- StringCache<Utils::PathString, std::mutex> *filePathCache,
+ FilePathCache<std::mutex> *filePathCache,
V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query)
{
ClangQuery clangQuery(*filePathCache, std::move(query));
- clangQuery.addFile(source.filePath().directory(),
- source.filePath().name(),
- source.takeUnsavedFileContent(),
- source.takeCommandLineArguments());
+ clangQuery.addFile(std::string(source.filePath().directory()),
+ std::string(source.filePath().name()),
+ std::string(source.takeUnsavedFileContent()),
+ std::vector<std::string>(source.takeCommandLineArguments()));
clangQuery.addUnsavedFiles(unsaved);
diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h
index 7d93560eec..c1fd6341fa 100644
--- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h
+++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h
@@ -41,13 +41,13 @@ public:
using Future = std::future<SourceRangesForQueryMessage>;
ClangQueryGatherer() = default;
- ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache,
+ ClangQueryGatherer(FilePathCache<std::mutex> *filePathCache,
std::vector<V2::FileContainer> &&sources,
std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query);
static SourceRangesForQueryMessage createSourceRangesForSource(
- StringCache<Utils::PathString, std::mutex> *filePathCache,
+ FilePathCache<std::mutex> *filePathCache,
V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query);
@@ -69,7 +69,7 @@ protected:
std::vector<Future> finishedFutures();
private:
- StringCache<Utils::PathString, std::mutex> *m_filePathCache = nullptr;
+ FilePathCache<std::mutex> *m_filePathCache = nullptr;
SourceRangeFilter m_sourceRangeFilter;
std::vector<V2::FileContainer> m_sources;
std::vector<V2::FileContainer> m_unsaved;
diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri
index 8af6b89974..50041e596a 100644
--- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri
+++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri
@@ -2,7 +2,16 @@ INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/clangrefactoringbackend_global.h \
- $$PWD/sourcerangefilter.h
+ $$PWD/sourcerangefilter.h \
+ $$PWD/symbolindexer.h \
+ $$PWD/symbolentry.h \
+ $$PWD/sourcelocationentry.h \
+ $$PWD/symbolscollectorinterface.h \
+ $$PWD/symbolstorageinterface.h \
+ $$PWD/symbolstorage.h \
+ $$PWD/storagesqlitestatementfactory.h \
+ $$PWD/symbolindexing.h \
+ $$PWD/symbolindexinginterface.h
!isEmpty(LIBTOOLING_LIBS) {
SOURCES += \
@@ -16,7 +25,12 @@ SOURCES += \
$$PWD/clangtool.cpp \
$$PWD/sourcerangeextractor.cpp \
$$PWD/locationsourcefilecallbacks.cpp \
- $$PWD/clangquerygatherer.cpp
+ $$PWD/collectsymbolsaction.cpp \
+ $$PWD/collectmacrossourcefilecallbacks.cpp \
+ $$PWD/symbolscollector.cpp \
+ $$PWD/clangquerygatherer.cpp \
+ $$PWD/symbolstorage.cpp \
+ $$PWD/symbolindexing.cpp
HEADERS += \
$$PWD/refactoringcompilationdatabase.h \
@@ -32,8 +46,16 @@ HEADERS += \
$$PWD/clangtool.h \
$$PWD/sourcerangeextractor.h \
$$PWD/locationsourcefilecallbacks.h \
+ $$PWD/collectsymbolsconsumer.h \
+ $$PWD/collectsymbolsaction.h \
+ $$PWD/collectsymbolsastvisitor.h \
+ $$PWD/collectmacrossourcefilecallbacks.h \
+ $$PWD/symbolscollector.h \
$$PWD/clangquerygatherer.h
}
SOURCES += \
- $$PWD/sourcerangefilter.cpp
+ $$PWD/sourcerangefilter.cpp \
+ $$PWD/symbolindexer.cpp \
+ $$PWD/symbolentry.cpp \
+ $$PWD/sourcelocationentry.cpp
diff --git a/src/tools/clangrefactoringbackend/source/clangtool.cpp b/src/tools/clangrefactoringbackend/source/clangtool.cpp
index 2ffad73965..61d3f96840 100644
--- a/src/tools/clangrefactoringbackend/source/clangtool.cpp
+++ b/src/tools/clangrefactoringbackend/source/clangtool.cpp
@@ -43,19 +43,19 @@ String toNativePath(String &&path)
}
void ClangTool::addFile(std::string &&directory,
- std::string &&fileName,
- std::string &&content,
- std::vector<std::string> &&commandLine)
+ std::string &&fileName,
+ std::string &&content,
+ std::vector<std::string> &&commandLine)
{
- fileContents.emplace_back(toNativePath(std::move(directory)),
+ m_fileContents.emplace_back(toNativePath(std::move(directory)),
std::move(fileName),
std::move(content),
std::move(commandLine));
- const auto &fileContent = fileContents.back();
+ const auto &fileContent = m_fileContents.back();
- compilationDatabase.addFile(fileContent.directory, fileContent.fileName, fileContent.commandLine);
- sourceFilePaths.push_back(fileContent.filePath);
+ m_compilationDatabase.addFile(fileContent.directory, fileContent.fileName, fileContent.commandLine);
+ m_sourceFilePaths.push_back(fileContent.filePath);
}
template <typename Container>
@@ -68,7 +68,7 @@ void ClangTool::addFiles(const Container &filePaths,
auto fileNameBegin = found.base();
std::vector<std::string> commandLine(arguments.begin(), arguments.end());
- commandLine.push_back(filePath);
+ commandLine.push_back(std::string(filePath));
addFile({filePath.begin(), std::prev(fileNameBegin)},
{fileNameBegin, filePath.end()},
@@ -86,7 +86,7 @@ void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector
void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
{
- unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size());
+ m_unsavedFileContents.reserve(m_unsavedFileContents.size() + unsavedFiles.size());
auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) {
return UnsavedFileContent{toNativePath(unsavedFile.filePath().path().clone()),
@@ -95,7 +95,7 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
std::transform(unsavedFiles.begin(),
unsavedFiles.end(),
- std::back_inserter(unsavedFileContents),
+ std::back_inserter(m_unsavedFileContents),
convertToUnsavedFileContent);
}
@@ -109,14 +109,14 @@ llvm::StringRef toStringRef(const String &string)
clang::tooling::ClangTool ClangTool::createTool() const
{
- clang::tooling::ClangTool tool(compilationDatabase, sourceFilePaths);
+ clang::tooling::ClangTool tool(m_compilationDatabase, m_sourceFilePaths);
- for (const auto &fileContent : fileContents) {
+ for (const auto &fileContent : m_fileContents) {
if (!fileContent.content.empty())
tool.mapVirtualFile(fileContent.filePath, fileContent.content);
}
- for (const auto &unsavedFileContent : unsavedFileContents)
+ for (const auto &unsavedFileContent : m_unsavedFileContents)
tool.mapVirtualFile(toStringRef(unsavedFileContent.filePath),
toStringRef(unsavedFileContent.content));
diff --git a/src/tools/clangrefactoringbackend/source/clangtool.h b/src/tools/clangrefactoringbackend/source/clangtool.h
index c643920914..0f436a0e37 100644
--- a/src/tools/clangrefactoringbackend/source/clangtool.h
+++ b/src/tools/clangrefactoringbackend/source/clangtool.h
@@ -104,10 +104,17 @@ public:
clang::tooling::ClangTool createTool() const;
private:
- RefactoringCompilationDatabase compilationDatabase;
- std::vector<FileContent> fileContents;
- std::vector<std::string> sourceFilePaths;
- std::vector<UnsavedFileContent> unsavedFileContents;
+ RefactoringCompilationDatabase m_compilationDatabase;
+ std::vector<FileContent> m_fileContents;
+ std::vector<std::string> m_sourceFilePaths;
+ std::vector<UnsavedFileContent> m_unsavedFileContents;
};
+extern template
+void ClangTool::addFiles<Utils::SmallStringVector>(const Utils::SmallStringVector &filePaths,
+ const Utils::SmallStringVector &arguments);
+extern template
+void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths,
+ const Utils::SmallStringVector &arguments);
+
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp
new file mode 100644
index 0000000000..ade4904e46
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.cpp
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "collectmacrossourcefilecallbacks.h"
+
+namespace ClangBackEnd {
+
+CollectMacrosSourceFileCallbacks::CollectMacrosSourceFileCallbacks()
+{
+
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h
new file mode 100644
index 0000000000..2c28f19f7b
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/collectmacrossourcefilecallbacks.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <clang/Tooling/Tooling.h>
+
+namespace ClangBackEnd {
+
+class CollectMacrosSourceFileCallbacks : public clang::tooling::SourceFileCallbacks
+{
+public:
+ CollectMacrosSourceFileCallbacks();
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp
new file mode 100644
index 0000000000..011477e4ba
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.cpp
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "collectsymbolsaction.h"
+
+#include "collectsymbolsconsumer.h"
+
+namespace ClangBackEnd {
+
+std::unique_ptr<clang::ASTConsumer> CollectSymbolsAction::newASTConsumer()
+{
+ return std::make_unique<CollectSymbolsConsumer>(m_symbolEntries,
+ m_sourceLocationEntries,
+ m_filePathCache);
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h
new file mode 100644
index 0000000000..1ddd34b595
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/collectsymbolsaction.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangrefactoringbackend_global.h"
+#include "sourcelocationentry.h"
+#include "symbolentry.h"
+
+#include <utils/smallstring.h>
+
+#include <stringcachefwd.h>
+
+#include <clang/Frontend/FrontendAction.h>
+
+#include <mutex>
+
+namespace ClangBackEnd {
+
+class CollectSymbolsAction
+{
+public:
+ CollectSymbolsAction(FilePathCache<std::mutex> &filePathCache)
+ : m_filePathCache(filePathCache)
+ {}
+
+ std::unique_ptr<clang::ASTConsumer> newASTConsumer();
+
+ SymbolEntries takeSymbols()
+ {
+ return std::move(m_symbolEntries);
+ }
+
+ const SymbolEntries &symbols() const
+ {
+ return m_symbolEntries;
+ }
+
+ const SourceLocationEntries &sourceLocations() const
+ {
+ return m_sourceLocationEntries;
+ }
+
+private:
+ SymbolEntries m_symbolEntries;
+ SourceLocationEntries m_sourceLocationEntries;
+ FilePathCache<std::mutex> &m_filePathCache;
+
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h
new file mode 100644
index 0000000000..fcedd6a6d0
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/collectsymbolsastvisitor.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "symbolentry.h"
+#include "sourcelocationentry.h"
+
+#include <stringcache.h>
+
+#include <clang/AST/AST.h>
+#include <clang/AST/ASTContext.h>
+#include <clang/AST/RecursiveASTVisitor.h>
+#include <clang/Index/USRGeneration.h>
+#include <llvm/ADT/SmallVector.h>
+
+#include <vector>
+
+namespace ClangBackEnd {
+
+Utils::SmallStringView toStringView(clang::StringRef stringReference)
+{
+ return Utils::SmallStringView(stringReference.data(), stringReference.size());
+}
+
+class CollectSymbolsASTVisitor : public clang::RecursiveASTVisitor<CollectSymbolsASTVisitor>
+{
+public:
+ CollectSymbolsASTVisitor(SymbolEntries &symbolEntries,
+ SourceLocationEntries &sourceLocationEntries,
+ FilePathCache<std::mutex> &filePathCache,
+ const clang::SourceManager &sourceManager)
+ : m_symbolEntries(symbolEntries),
+ m_sourceLocationEntries(sourceLocationEntries),
+ m_filePathCache(filePathCache),
+ m_sourceManager(sourceManager)
+ {}
+
+ bool shouldVisitTemplateInstantiations() const
+ {
+ return true;
+ }
+
+ bool VisitNamedDecl(const clang::NamedDecl *declaration)
+ {
+ if (!declaration->getIdentifier())
+ return true;
+
+ SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
+ auto sourceLocation = declaration->getLocation();
+
+ auto found = m_symbolEntries.find(globalId);
+ if (found == m_symbolEntries.end()) {
+ m_symbolEntries.emplace(std::piecewise_construct,
+ std::forward_as_tuple(globalId),
+ std::forward_as_tuple(generateUSR(declaration), symbolName(declaration)));
+ }
+
+ m_sourceLocationEntries.emplace_back(globalId,
+ filePathId(sourceLocation),
+ lineColum(sourceLocation),
+ SymbolType::Declaration);
+
+ return true;
+ }
+
+ bool VisitDeclRefExpr(const clang::DeclRefExpr *expression)
+ {
+ auto declaration = expression->getFoundDecl();
+ SymbolIndex globalId = toSymbolIndex(declaration->getCanonicalDecl());
+ auto sourceLocation = expression->getLocation();
+
+ m_sourceLocationEntries.emplace_back(globalId,
+ filePathId(sourceLocation),
+ lineColum(sourceLocation),
+ SymbolType::DeclarationReference);
+
+ return true;
+ }
+
+ FilePathIndex filePathId(clang::SourceLocation sourceLocation)
+ {
+ uint clangFileId = m_sourceManager.getFileID(sourceLocation).getHashValue();
+
+ auto found = m_filePathIndices.find(clangFileId);
+
+ if (found != m_filePathIndices.end())
+ return found->second;
+
+ auto filePath = m_sourceManager.getFilename(sourceLocation);
+
+ FilePathIndex index = m_filePathCache.stringId(toStringView(filePath));
+
+ m_filePathIndices.emplace(clangFileId, index);
+
+ return index;
+ }
+
+ LineColumn lineColum(clang::SourceLocation sourceLocation)
+ {
+ return {m_sourceManager.getSpellingLineNumber(sourceLocation),
+ m_sourceManager.getSpellingColumnNumber(sourceLocation)};
+ }
+
+ Utils::PathString generateUSR(const clang::Decl *declaration)
+ {
+ llvm::SmallVector<char, 128> usr;
+
+ clang::index::generateUSRForDecl(declaration, usr);
+
+ return {usr.data(), usr.size()};
+ }
+
+ Utils::SmallString symbolName(const clang::NamedDecl *declaration)
+ {
+ const llvm::StringRef symbolName{declaration->getName()};
+
+ return {symbolName.data(), symbolName.size()};
+ }
+
+ static SymbolIndex toSymbolIndex(const void *pointer)
+ {
+ return SymbolIndex(reinterpret_cast<std::uintptr_t>(pointer));
+ }
+
+private:
+ SymbolEntries &m_symbolEntries;
+ std::unordered_map<uint, FilePathIndex> m_filePathIndices;
+ SourceLocationEntries &m_sourceLocationEntries;
+ FilePathCache<std::mutex> &m_filePathCache;
+ const clang::SourceManager &m_sourceManager;
+};
+
+
+} // namespace ClangBackend
+
diff --git a/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h b/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h
new file mode 100644
index 0000000000..0eeb7a73f2
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/collectsymbolsconsumer.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "collectsymbolsastvisitor.h"
+
+#include <clang/AST/AST.h>
+#include <clang/AST/ASTConsumer.h>
+#include <clang/AST/ASTContext.h>
+
+#include <stringcachefwd.h>
+
+namespace ClangBackEnd {
+
+class CollectSymbolsConsumer : public clang::ASTConsumer
+{
+public:
+ CollectSymbolsConsumer(SymbolEntries &symbolEntries,
+ SourceLocationEntries &sourceLocationEntries,
+ FilePathCache<std::mutex> &filePathCache)
+ : m_symbolEntries(symbolEntries),
+ m_sourceLocationEntries(sourceLocationEntries),
+ m_filePathCache(filePathCache)
+ {}
+
+ void HandleTranslationUnit(clang::ASTContext &astContext) override
+ {
+ CollectSymbolsASTVisitor visitor{m_symbolEntries,
+ m_sourceLocationEntries,
+ m_filePathCache,
+ astContext.getSourceManager()};
+ visitor.TraverseDecl(astContext.getTranslationUnitDecl());
+ }
+
+ bool shouldSkipFunctionBody(clang::Decl *declation) override
+ {
+ const clang::SourceManager &sourceManager = declation->getASTContext().getSourceManager();
+ const clang::SourceLocation location = declation->getLocation();
+
+ if (sourceManager.isInSystemHeader(location))
+ return true;
+
+ return false;
+ }
+
+private:
+ SymbolEntries &m_symbolEntries;
+ SourceLocationEntries &m_sourceLocationEntries;
+ FilePathCache<std::mutex> &m_filePathCache;
+};
+}
diff --git a/src/tools/clangrefactoringbackend/source/findcursorusr.h b/src/tools/clangrefactoringbackend/source/findcursorusr.h
index 0c228c67e8..549086cd3a 100644
--- a/src/tools/clangrefactoringbackend/source/findcursorusr.h
+++ b/src/tools/clangrefactoringbackend/source/findcursorusr.h
@@ -25,26 +25,12 @@
#pragma once
-#if defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#elif defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning( disable : 4100 )
-#endif
-
#include <clang/AST/AST.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Index/USRGeneration.h>
#include <llvm/ADT/SmallVector.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic pop
-#elif defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-
#include <vector>
namespace ClangBackEnd {
@@ -54,8 +40,8 @@ class FindNamedDeclarationASTVisitor : public clang::RecursiveASTVisitor<FindNam
public:
explicit FindNamedDeclarationASTVisitor(const clang::SourceManager &sourceManager,
const clang::SourceLocation cursorSourceLocation)
- : sourceManager(sourceManager),
- cursorSourceLocation(cursorSourceLocation)
+ : m_sourceManager(sourceManager),
+ m_cursorSourceLocation(cursorSourceLocation)
{
}
@@ -96,7 +82,7 @@ public:
std::vector<const clang::NamedDecl*> takeNamedDecl()
{
- return std::move(namedDeclarations);
+ return std::move(m_namedDeclarations);
}
private:
@@ -138,7 +124,7 @@ private:
bool isValid = isValidLocationWithCursorInside(startLocation, endLocation);
if (isValid)
- namedDeclarations.push_back(declaration);
+ m_namedDeclarations.push_back(declaration);
return !isValid;
}
@@ -153,20 +139,20 @@ private:
bool isCursorLocationBetween(const clang::SourceLocation startLocation,
const clang::SourceLocation endLocation)
{
- return cursorSourceLocation == startLocation
- || cursorSourceLocation == endLocation
- || (sourceManager.isBeforeInTranslationUnit(startLocation, cursorSourceLocation)
- && sourceManager.isBeforeInTranslationUnit(cursorSourceLocation, endLocation));
+ return m_cursorSourceLocation == startLocation
+ || m_cursorSourceLocation == endLocation
+ || (m_sourceManager.isBeforeInTranslationUnit(startLocation, m_cursorSourceLocation)
+ && m_sourceManager.isBeforeInTranslationUnit(m_cursorSourceLocation, endLocation));
}
- std::vector<const clang::NamedDecl*> namedDeclarations;
- const clang::SourceManager &sourceManager;
- const clang::SourceLocation cursorSourceLocation;
+ std::vector<const clang::NamedDecl*> m_namedDeclarations;
+ const clang::SourceManager &m_sourceManager;
+ const clang::SourceLocation m_cursorSourceLocation;
};
inline
std::vector<const clang::NamedDecl *> namedDeclarationsAt(const clang::ASTContext &Context,
- const clang::SourceLocation cursorSourceLocation)
+ const clang::SourceLocation cursorSourceLocation)
{
const auto &sourceManager = Context.getSourceManager();
const auto currentFile = sourceManager.getFilename(cursorSourceLocation);
diff --git a/src/tools/clangrefactoringbackend/source/findusrforcursoraction.cpp b/src/tools/clangrefactoringbackend/source/findusrforcursoraction.cpp
index 50f7230586..6fa964f531 100644
--- a/src/tools/clangrefactoringbackend/source/findusrforcursoraction.cpp
+++ b/src/tools/clangrefactoringbackend/source/findusrforcursoraction.cpp
@@ -27,24 +27,10 @@
#include "findcursorusr.h"
-#if defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#elif defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning( disable : 4100 )
-#endif
-
#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic pop
-#elif defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-
#include <algorithm>
#include <vector>
@@ -54,16 +40,16 @@ namespace {
std::vector<USRName> collectConstructorUnifiedSymbolResolutions(const clang::CXXRecordDecl *declarations)
{
- std::vector<USRName> unifiedSymbolResolutions;
+ std::vector<USRName> unifiedSymbolResolutions;
- const auto constructorDeclarations = declarations->getDefinition()->ctors();
+ const auto constructorDeclarations = declarations->getDefinition()->ctors();
- std::transform(constructorDeclarations.begin(),
- constructorDeclarations.end(),
- std::back_inserter(unifiedSymbolResolutions),
- USROfDeclaration);
+ std::transform(constructorDeclarations.begin(),
+ constructorDeclarations.end(),
+ std::back_inserter(unifiedSymbolResolutions),
+ USROfDeclaration);
- return unifiedSymbolResolutions;
+ return unifiedSymbolResolutions;
}
void addUnifiedSymbolResolutionsForDeclaration(const std::vector<const clang::NamedDecl *> &declarations,
@@ -87,18 +73,18 @@ public:
std::vector<USRName> &unifiedSymbolResolutions,
uint line,
uint column)
- : symbolName(symbolName),
- unifiedSymbolResolutions(unifiedSymbolResolutions),
- line(line),
- column(column)
+ : m_symbolName(symbolName),
+ m_unifiedSymbolResolutions(unifiedSymbolResolutions),
+ m_line(line),
+ m_column(column)
{
}
void HandleTranslationUnit(clang::ASTContext &astContext) override {
const auto &sourceManager = astContext.getSourceManager();
const auto cursorSourceLocation = sourceManager.translateLineCol(sourceManager.getMainFileID(),
- line,
- column);
+ m_line,
+ m_column);
if (cursorSourceLocation.isValid())
collectUnifiedSymbolResoltions(astContext, cursorSourceLocation);
@@ -114,32 +100,29 @@ public:
if (const auto *constructorDecl = clang::dyn_cast<clang::CXXConstructorDecl>(firstFoundDeclaration)) {
const clang::CXXRecordDecl *foundDeclarationParent = constructorDecl->getParent();
- unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(foundDeclarationParent);
+ m_unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(foundDeclarationParent);
} else if (const auto *destructorDecl = clang::dyn_cast<clang::CXXDestructorDecl>(firstFoundDeclaration)) {
const clang::CXXRecordDecl *foundDeclarationParent = destructorDecl->getParent();
- unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(foundDeclarationParent);
+ m_unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(foundDeclarationParent);
} else if (const auto *recordDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(firstFoundDeclaration)) {
- unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(recordDeclaration);
+ m_unifiedSymbolResolutions = collectConstructorUnifiedSymbolResolutions(recordDeclaration);
}
- addUnifiedSymbolResolutionsForDeclaration(foundDeclarations, unifiedSymbolResolutions);
- symbolName = firstFoundDeclaration->getNameAsString();
+ addUnifiedSymbolResolutionsForDeclaration(foundDeclarations, m_unifiedSymbolResolutions);
+ m_symbolName = firstFoundDeclaration->getNameAsString();
}
}
private:
- Utils::SmallString &symbolName;
- std::vector<USRName> &unifiedSymbolResolutions;
- uint line;
- uint column;
+ Utils::SmallString &m_symbolName;
+ std::vector<USRName> &m_unifiedSymbolResolutions;
+ uint m_line;
+ uint m_column;
};
std::unique_ptr<clang::ASTConsumer>
USRFindingAction::newASTConsumer() {
- std::unique_ptr<FindDeclarationsConsumer> Consumer(
- new FindDeclarationsConsumer(symbolName, unifiedSymbolResolutions_, line, column));
-
- return std::move(Consumer);
+ return std::make_unique<FindDeclarationsConsumer>(m_symbolName, m_unifiedSymbolResolutions, m_line, m_column);
}
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/findusrforcursoraction.h b/src/tools/clangrefactoringbackend/source/findusrforcursoraction.h
index 65ec394e7d..bfa4a373a4 100644
--- a/src/tools/clangrefactoringbackend/source/findusrforcursoraction.h
+++ b/src/tools/clangrefactoringbackend/source/findusrforcursoraction.h
@@ -29,21 +29,7 @@
#include <utils/smallstring.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#elif defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning( disable : 4100 )
-#endif
-
-#include "clang/Frontend/FrontendAction.h"
-
-#if defined(__GNUC__)
-# pragma GCC diagnostic pop
-#elif defined(_MSC_VER)
-# pragma warning(pop)
-#endif
+#include <clang/Frontend/FrontendAction.h>
namespace clang {
class ASTConsumer;
@@ -57,8 +43,8 @@ class USRFindingAction
{
public:
USRFindingAction(uint line, uint column)
- : line(line),
- column(column)
+ : m_line(line),
+ m_column(column)
{
}
@@ -66,19 +52,19 @@ public:
std::string takeSymbolName()
{
- return std::move(symbolName);
+ return std::string(m_symbolName);
}
std::vector<USRName> takeUnifiedSymbolResolutions()
{
- return std::move(unifiedSymbolResolutions_);
+ return std::move(m_unifiedSymbolResolutions);
}
private:
- Utils::SmallString symbolName;
- std::vector<USRName> unifiedSymbolResolutions_;
- uint line;
- uint column;
+ Utils::SmallString m_symbolName;
+ std::vector<USRName> m_unifiedSymbolResolutions;
+ uint m_line;
+ uint m_column;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h b/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h
index fe23e3e5a5..cb9560ae7d 100644
--- a/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h
+++ b/src/tools/clangrefactoringbackend/source/locationsourcefilecallbacks.h
@@ -27,22 +27,8 @@
#include <sourcelocationscontainer.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#elif defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning( disable : 4100 )
-#endif
-
#include <clang/Tooling/Tooling.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic pop
-#elif defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-
namespace llvm {
class StringRef;
}
diff --git a/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h b/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h
index bac6465c8e..d25407438b 100644
--- a/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h
+++ b/src/tools/clangrefactoringbackend/source/refactoringcompilationdatabase.h
@@ -54,8 +54,8 @@ public:
std::vector<clang::tooling::CompileCommand> getAllCompileCommands() const override;
void addFile(const std::string &directory,
- const std::string &fileName,
- const std::vector<std::string> &commandLine);
+ const std::string &fileName,
+ const std::vector<std::string> &commandLine);
private:
std::vector<clang::tooling::CompileCommand> compileCommands;
diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp
index ff4f06babe..84b588118e 100644
--- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp
+++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp
@@ -27,6 +27,7 @@
#include "symbolfinder.h"
#include "clangquery.h"
+#include "symbolindexing.h"
#include <refactoringclientinterface.h>
#include <clangrefactoringmessages.h>
@@ -38,7 +39,10 @@
namespace ClangBackEnd {
-RefactoringServer::RefactoringServer()
+RefactoringServer::RefactoringServer(SymbolIndexingInterface &symbolIndexing,
+ FilePathCache<std::mutex> &filePathCache)
+ : m_symbolIndexing(symbolIndexing),
+ m_filePathCache(filePathCache)
{
m_pollTimer.setInterval(100);
@@ -56,10 +60,10 @@ void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLo
{
SymbolFinder symbolFinder(message.line(), message.column());
- symbolFinder.addFile(message.filePath().directory(),
- message.filePath().name(),
- message.unsavedContent(),
- message.commandLine());
+ symbolFinder.addFile(std::string(message.filePath().directory()),
+ std::string(message.filePath().name()),
+ std::string(message.unsavedContent()),
+ std::vector<std::string>(message.commandLine()));
symbolFinder.findSymbol();
@@ -73,10 +77,10 @@ void RefactoringServer::requestSourceRangesAndDiagnosticsForQueryMessage(
{
ClangQuery clangQuery(m_filePathCache, message.takeQuery());
- clangQuery.addFile(message.source().filePath().directory(),
- message.source().filePath().name(),
- message.source().unsavedFileContent(),
- message.source().commandLineArguments());
+ clangQuery.addFile(std::string(message.source().filePath().directory()),
+ std::string(message.source().filePath().name()),
+ std::string(message.source().unsavedFileContent()),
+ std::vector<std::string>(message.source().commandLineArguments()));
clangQuery.findLocations();
@@ -88,7 +92,17 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo
{
gatherSourceRangesForQueryMessages(message.takeSources(),
message.takeUnsavedContent(),
- message.takeQuery());
+ message.takeQuery());
+}
+
+void RefactoringServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&message)
+{
+ m_symbolIndexing.updateProjectParts(message.takeProjectsParts(), message.takeGeneratedFiles());
+}
+
+void RefactoringServer::removePchProjectParts(RemovePchProjectPartsMessage &&)
+{
+
}
void RefactoringServer::cancel()
diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h
index 94eeb3dcc6..b11cf3fc21 100644
--- a/src/tools/clangrefactoringbackend/source/refactoringserver.h
+++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h
@@ -30,6 +30,7 @@
#include <refactoringserverinterface.h>
#include <QTimer>
+#include <ipcclientprovider.h>
#include <stringcache.h>
#include <utils/smallstring.h>
@@ -41,21 +42,26 @@
namespace ClangBackEnd {
class SourceRangesForQueryMessage;
+class SymbolIndexingInterface;
namespace V2 {
class FileContainer;
}
-class RefactoringServer : public RefactoringServerInterface
+class RefactoringServer : public RefactoringServerInterface,
+ public IpcClientProvider<RefactoringClientInterface>
{
using Future = std::future<SourceRangesForQueryMessage>;
public:
- RefactoringServer();
+ RefactoringServer(SymbolIndexingInterface &symbolIndexing,
+ FilePathCache<std::mutex> &filePathCache);
void end() override;
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override;
void requestSourceRangesForQueryMessage(RequestSourceRangesForQueryMessage &&message) override;
+ void updatePchProjectParts(UpdatePchProjectPartsMessage &&message) override;
+ void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
void cancel() override;
bool isCancelingJobs() const;
@@ -73,9 +79,10 @@ private:
Utils::SmallString &&query);
private:
- StringCache<Utils::PathString, std::mutex> m_filePathCache;
ClangQueryGatherer m_gatherer;
QTimer m_pollTimer;
+ SymbolIndexingInterface &m_symbolIndexing;
+ FilePathCache<std::mutex> &m_filePathCache;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationentry.cpp b/src/tools/clangrefactoringbackend/source/sourcelocationentry.cpp
new file mode 100644
index 0000000000..9cea242fa8
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/sourcelocationentry.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sourcelocationentry.h"
+
+#include <utils/smallstringio.h>
+
+namespace ClangBackEnd {
+
+std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry)
+{
+ out << "("
+ << entry.fileId << ", "
+ << entry.line << ", "
+ << entry.column << ")";
+
+ return out;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationentry.h b/src/tools/clangrefactoringbackend/source/sourcelocationentry.h
new file mode 100644
index 0000000000..dbe7012388
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/sourcelocationentry.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <stringcachefwd.h>
+
+#include <limits>
+#include <vector>
+#include <iosfwd>
+
+using uint = unsigned int;
+
+namespace ClangBackEnd {
+
+enum class SymbolType
+{
+ Declaration,
+ DeclarationReference
+};
+
+class LineColumn
+{
+public:
+ LineColumn(uint line, uint column)
+ : line(line),
+ column(column)
+ {}
+
+ uint line = 0;
+ uint column = 0;
+};
+
+using SymbolIndex = long long;
+
+class SourceLocationEntry
+{
+public:
+ SourceLocationEntry(SymbolIndex symbolId,
+ FilePathIndex fileId,
+ LineColumn lineColumn,
+ SymbolType symbolType)
+ : symbolId(symbolId),
+ fileId(fileId),
+ line(lineColumn.line),
+ column(lineColumn.column),
+ symbolType(symbolType)
+ {}
+
+ SymbolIndex symbolId = 0;
+ FilePathIndex fileId = std::numeric_limits<uint>::max();
+ uint line = 0;
+ uint column = 0;
+ SymbolType symbolType;
+
+ friend bool operator==(const SourceLocationEntry &first, const SourceLocationEntry &second)
+ {
+ return first.symbolId == second.symbolId
+ && first.fileId == second.fileId
+ && first.line == second.line
+ && first.column == second.column
+ && first.symbolType == second.symbolType;
+ }
+};
+
+using SourceLocationEntries = std::vector<SourceLocationEntry>;
+
+std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp
index 9788d65683..399a7353f3 100644
--- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp
+++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp
@@ -54,7 +54,7 @@ namespace ClangBackEnd {
SourceRangeExtractor::SourceRangeExtractor(
const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions,
- ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache,
+ ClangBackEnd::FilePathCache<std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer)
: sourceManager(sourceManager),
languageOptions(languageOptions),
@@ -146,7 +146,7 @@ void SourceRangeExtractor::insertSourceRange(uint fileId,
std::move(lineSnippet));
}
-uint SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const
+FilePathIndex SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const
{
auto found = m_fileIdMapping.find(fileId.getHashValue());
if (found != m_fileIdMapping.end()) {
diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h
index 7a07e5c3f8..3064642974 100644
--- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h
+++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h
@@ -59,7 +59,7 @@ class SourceRangeExtractor
public:
SourceRangeExtractor(const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions,
- ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache,
+ ClangBackEnd::FilePathCache<std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer);
void addSourceRange(const clang::SourceRange &sourceRange);
@@ -82,13 +82,13 @@ private:
uint endOffset,
Utils::SmallString &&lineSnippet);
- uint findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
+ FilePathIndex findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
private:
mutable std::unordered_map<uint, uint> m_fileIdMapping;
const clang::SourceManager &sourceManager;
const clang::LangOptions &languageOptions;
- ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache;
+ ClangBackEnd::FilePathCache<std::mutex> &filePathCache;
SourceRangesContainer &sourceRangesContainer;
};
diff --git a/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h
new file mode 100644
index 0000000000..c144c7a9c5
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/storagesqlitestatementfactory.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <createtablesqlstatementbuilder.h>
+
+#include <sqlitetransaction.h>
+#include <sqlitetable.h>
+
+namespace ClangBackEnd {
+
+template<typename Database,
+ typename ReadStatement,
+ typename WriteStatement>
+class StorageSqliteStatementFactory
+{
+public:
+ using DatabaseType = Database;
+ using ReadStatementType = ReadStatement;
+ using WriteStatementType = WriteStatement;
+
+ StorageSqliteStatementFactory(Database &database)
+ : database(database)
+ {
+ }
+
+ Sqlite::Table createNewSymbolsTable() const
+ {
+ Sqlite::Table table;
+ table.setName("newSymbols");
+ table.setUseTemporaryTable(true);
+ table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
+ const Sqlite::Column &symbolIdColumn = table.addColumn("symbolId", Sqlite::ColumnType::Integer);
+ const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
+ const Sqlite::Column &symbolNameColumn = table.addColumn("symbolName", Sqlite::ColumnType::Text);
+ table.addIndex({usrColumn, symbolNameColumn});
+ table.addIndex({symbolIdColumn});
+
+ Sqlite::ImmediateTransaction<DatabaseType> transaction(database);
+ table.initialize(database);
+ transaction.commit();
+
+ return table;
+ }
+
+ Sqlite::Table createNewLocationsTable() const
+ {
+ Sqlite::Table table;
+ table.setName("newLocations");
+ table.setUseTemporaryTable(true);
+ table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer);
+ table.addColumn("symbolId", Sqlite::ColumnType::Integer);
+ table.addColumn("line", Sqlite::ColumnType::Integer);
+ table.addColumn("column", Sqlite::ColumnType::Integer);
+ const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
+ table.addIndex({sourceIdColumn});
+
+ Sqlite::ImmediateTransaction<DatabaseType> transaction(database);
+ table.initialize(database);
+ transaction.commit();
+
+ return table;
+ }
+
+public:
+ Database &database;
+ Sqlite::Table newSymbolsTablet{createNewSymbolsTable()};
+ Sqlite::Table newLocationsTable{createNewLocationsTable()};
+ WriteStatement insertSymbolsToNewSymbolsStatement{
+ "INSERT INTO newSymbols(temporarySymbolId, usr, symbolName) VALUES(?,?,?)",
+ database};
+ WriteStatement insertLocationsToNewLocationsStatement{
+ "INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)",
+ database
+ };
+// WriteStatement syncNewLocationsToLocationsStatement{
+// "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
+// database};
+ ReadStatement selectNewSourceIdsStatement{
+ "SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)",
+ database
+ };
+ WriteStatement addNewSymbolsToSymbolsStatement{
+ "INSERT INTO symbols(usr, symbolName) "
+ "SELECT usr, symbolName FROM newSymbols WHERE NOT EXISTS "
+ "(SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)",
+ database
+ };
+ WriteStatement insertSourcesStatement{
+ "INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)",
+ database
+ };
+ WriteStatement syncNewSymbolsFromSymbolsStatement{
+ "UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)",
+ database
+ };
+ WriteStatement syncSymbolsIntoNewLocationsStatement{
+ "UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)",
+ database
+ };
+ WriteStatement deleteAllLocationsFromUpdatedFilesStatement{
+ "DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)",
+ database
+ };
+ WriteStatement insertNewLocationsInLocationsStatement{
+ "INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations",
+ database
+ };
+ WriteStatement deleteNewSymbolsTableStatement{
+ "DELETE FROM newSymbols",
+ database
+ };
+ WriteStatement deleteNewLocationsTableStatement{
+ "DELETE FROM newLocations",
+ database
+ };
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolentry.cpp b/src/tools/clangrefactoringbackend/source/symbolentry.cpp
new file mode 100644
index 0000000000..ee606cf9ab
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolentry.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "symbolentry.h"
+
+#include <utils/smallstringio.h>
+
+namespace ClangBackEnd {
+
+std::ostream &operator<<(std::ostream &out, const SymbolEntry &entry)
+{
+ out << "("
+ << entry.symbolName << ", "
+ << entry.usr <<")";
+
+ return out;
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolentry.h b/src/tools/clangrefactoringbackend/source/symbolentry.h
new file mode 100644
index 0000000000..7312f45bd6
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolentry.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <stringcachefwd.h>
+
+#include <utils/smallstring.h>
+
+#include <limits>
+#include <unordered_map>
+#include <iosfwd>
+
+namespace ClangBackEnd {
+
+using SymbolIndex = long long;
+
+class SymbolEntry
+{
+public:
+ SymbolEntry(Utils::PathString &&usr,
+ Utils::SmallString &&symbolName)
+ : usr(std::move(usr)),
+ symbolName(std::move(symbolName))
+ {}
+
+ Utils::PathString usr;
+ Utils::SmallString symbolName;
+
+ friend bool operator==(const SymbolEntry &first, const SymbolEntry &second)
+ {
+ return first.usr == second.usr && first.symbolName == second.symbolName;
+ }
+};
+
+using SymbolEntries = std::unordered_map<SymbolIndex, SymbolEntry>;
+
+std::ostream &operator<<(std::ostream &out, const SymbolEntry &entry);
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolfinder.h b/src/tools/clangrefactoringbackend/source/symbolfinder.h
index 42c7098f1e..a76639aa26 100644
--- a/src/tools/clangrefactoringbackend/source/symbolfinder.h
+++ b/src/tools/clangrefactoringbackend/source/symbolfinder.h
@@ -32,22 +32,6 @@
#include <sourcelocationscontainer.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#elif defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning( disable : 4100 )
-#endif
-
-#include "clang/Tooling/Refactoring.h"
-
-#if defined(__GNUC__)
-# pragma GCC diagnostic pop
-#elif defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-
namespace ClangBackEnd {
class SymbolFinder : public ClangTool
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
new file mode 100644
index 0000000000..ed48d920a6
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "symbolindexer.h"
+
+namespace ClangBackEnd {
+
+SymbolIndexer::SymbolIndexer(SymbolsCollectorInterface &symbolsCollector, SymbolStorageInterface &symbolStorage)
+ : m_symbolsCollector(symbolsCollector),
+ m_symbolStorage(symbolStorage)
+{
+}
+
+void SymbolIndexer::updateProjectParts(V2::ProjectPartContainers &&projectParts,
+ V2::FileContainers &&generatedFiles)
+{
+ for (const V2::ProjectPartContainer &projectPart : projectParts)
+ m_symbolsCollector.addFiles(projectPart.sourcePaths(), projectPart.arguments());
+
+ m_symbolsCollector.addUnsavedFiles(generatedFiles);
+
+ m_symbolsCollector.collectSymbols();
+
+ m_symbolStorage.addSymbolsAndSourceLocations(m_symbolsCollector.symbols(),
+ m_symbolsCollector.sourceLocations());
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.h b/src/tools/clangrefactoringbackend/source/symbolindexer.h
new file mode 100644
index 0000000000..283e761da5
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolindexer.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "symbolscollectorinterface.h"
+#include "symbolstorageinterface.h"
+
+#include <projectpartcontainerv2.h>
+#include <filecontainerv2.h>
+
+namespace ClangBackEnd {
+
+class SymbolIndexer
+{
+public:
+ SymbolIndexer(SymbolsCollectorInterface &symbolsCollector,
+ SymbolStorageInterface &symbolStorage);
+
+ void updateProjectParts(V2::ProjectPartContainers &&projectParts,
+ V2::FileContainers &&generatedFiles);
+
+private:
+ SymbolsCollectorInterface &m_symbolsCollector;
+ SymbolStorageInterface &m_symbolStorage;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.cpp b/src/tools/clangrefactoringbackend/source/symbolindexing.cpp
new file mode 100644
index 0000000000..11e34e449f
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolindexing.cpp
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "symbolindexing.h"
+
+namespace ClangBackEnd {
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h
new file mode 100644
index 0000000000..4dd173e1bf
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "symbolindexinginterface.h"
+
+#include "storagesqlitestatementfactory.h"
+#include "symbolindexer.h"
+#include "symbolscollector.h"
+#include "symbolstorage.h"
+
+#include <refactoringdatabaseinitializer.h>
+#include <stringcache.h>
+
+#include <sqlitedatabase.h>
+#include <sqlitereadstatement.h>
+#include <sqlitewritestatement.h>
+
+namespace ClangBackEnd {
+
+class SymbolIndexing final : public SymbolIndexingInterface
+{
+public:
+ using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<Sqlite::Database,
+ Sqlite::ReadStatement,
+ Sqlite::WriteStatement>;
+ using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
+ using DatabaseInitializer = RefactoringDatabaseInitializer<Sqlite::Database>;
+
+ SymbolIndexing(FilePathCache<std::mutex> &filePathCache,
+ Utils::PathString &&databaseFilePath)
+ : m_filePathCache(filePathCache),
+ m_database(std::move(databaseFilePath)),
+ m_databaseInitializer(m_database)
+ {
+ }
+
+ SymbolIndexer &indexer()
+ {
+ return m_indexer;
+ }
+
+ Sqlite::Database &database()
+ {
+ return m_database;
+ }
+
+ void updateProjectParts(V2::ProjectPartContainers &&projectParts,
+ V2::FileContainers &&generatedFiles)
+ {
+ m_indexer.updateProjectParts(std::move(projectParts), std::move(generatedFiles));
+ }
+
+private:
+ FilePathCache<std::mutex> &m_filePathCache;
+ Sqlite::Database m_database;
+ DatabaseInitializer m_databaseInitializer;
+ SymbolsCollector m_collector{m_filePathCache};
+ StatementFactory m_statementFactory{m_database};
+ Storage m_symbolStorage{m_statementFactory, m_filePathCache};
+ SymbolIndexer m_indexer{m_collector, m_symbolStorage};
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexinginterface.h b/src/tools/clangrefactoringbackend/source/symbolindexinginterface.h
new file mode 100644
index 0000000000..8c331aadce
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolindexinginterface.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectpartcontainerv2.h>
+#include <filecontainerv2.h>
+
+namespace ClangBackEnd {
+
+class SymbolIndexingInterface
+{
+public:
+ virtual void updateProjectParts(V2::ProjectPartContainers &&projectParts,
+ V2::FileContainers &&generatedFiles) = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp
index c5aba6ca90..2b07e893f5 100644
--- a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp
+++ b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.cpp
@@ -39,7 +39,7 @@ class FindingSymbolsASTConsumer : public clang::ASTConsumer
{
public:
FindingSymbolsASTConsumer(std::vector<USRName> &unifiedSymbolResolutions)
- : unifiedSymbolResolutions(unifiedSymbolResolutions)
+ : m_unifiedSymbolResolutions(unifiedSymbolResolutions)
{
}
@@ -48,7 +48,7 @@ public:
std::vector<clang::SourceLocation> sourceLocations;
- auto &&sourceLocationsOfUsr = takeLocationsOfUSRs(unifiedSymbolResolutions, context.getTranslationUnitDecl());
+ auto &&sourceLocationsOfUsr = takeLocationsOfUSRs(m_unifiedSymbolResolutions, context.getTranslationUnitDecl());
sourceLocations.insert(sourceLocations.end(),
sourceLocationsOfUsr.begin(),
sourceLocationsOfUsr.end());
@@ -65,24 +65,24 @@ public:
void updateSourceLocations(const std::vector<clang::SourceLocation> &sourceLocations,
const clang::SourceManager &sourceManager)
{
- appendSourceLocationsToSourceLocationsContainer(*sourceLocationsContainer, sourceLocations, sourceManager);
+ appendSourceLocationsToSourceLocationsContainer(*m_sourceLocationsContainer, sourceLocations, sourceManager);
}
void setSourceLocations(ClangBackEnd::SourceLocationsContainer *sourceLocations)
{
- sourceLocationsContainer = sourceLocations;
+ m_sourceLocationsContainer = sourceLocations;
}
private:
- ClangBackEnd::SourceLocationsContainer *sourceLocationsContainer = nullptr;
- std::vector<USRName> &unifiedSymbolResolutions;
+ ClangBackEnd::SourceLocationsContainer *m_sourceLocationsContainer = nullptr;
+ std::vector<USRName> &m_unifiedSymbolResolutions;
};
std::unique_ptr<clang::ASTConsumer> SymbolLocationFinderAction::newASTConsumer()
{
- auto consumer = std::unique_ptr<FindingSymbolsASTConsumer>(new FindingSymbolsASTConsumer(unifiedSymbolResolutions_));
+ auto consumer = std::unique_ptr<FindingSymbolsASTConsumer>(new FindingSymbolsASTConsumer(m_unifiedSymbolResolutions_));
- consumer->setSourceLocations(&sourceLocations);
+ consumer->setSourceLocations(&m_sourceLocations);
return std::move(consumer);
}
diff --git a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h
index 7bee18f94b..ae601d8219 100644
--- a/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h
+++ b/src/tools/clangrefactoringbackend/source/symbollocationfinderaction.h
@@ -29,22 +29,8 @@
#include <sourcelocationscontainer.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#elif defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning( disable : 4100 )
-#endif
-
#include <clang/Tooling/Refactoring.h>
-#if defined(__GNUC__)
-# pragma GCC diagnostic pop
-#elif defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-
namespace clang {
class ASTConsumer;
}
@@ -59,22 +45,22 @@ public:
SourceLocationsContainer takeSourceLocations()
{
- return std::move(sourceLocations);
+ return std::move(m_sourceLocations);
}
void setUnifiedSymbolResolutions(std::vector<USRName> &&unifiedSymbolResolutions)
{
- unifiedSymbolResolutions_ = std::move(unifiedSymbolResolutions);
+ m_unifiedSymbolResolutions_ = std::move(unifiedSymbolResolutions);
}
const std::vector<USRName> &unifiedSymbolResolutions() const
{
- return unifiedSymbolResolutions_;
+ return m_unifiedSymbolResolutions_;
}
private:
- ClangBackEnd::SourceLocationsContainer sourceLocations;
- std::vector<USRName> unifiedSymbolResolutions_;
+ ClangBackEnd::SourceLocationsContainer m_sourceLocations;
+ std::vector<USRName> m_unifiedSymbolResolutions_;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
new file mode 100644
index 0000000000..c759232a04
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "symbolscollector.h"
+
+namespace ClangBackEnd {
+
+SymbolsCollector::SymbolsCollector(FilePathCache<std::mutex> &filePathCache)
+ : m_collectSymbolsAction(filePathCache)
+{
+}
+
+void SymbolsCollector::addFiles(const Utils::PathStringVector &filePaths, const Utils::SmallStringVector &arguments)
+{
+ ClangTool::addFiles(filePaths, arguments);
+}
+
+void SymbolsCollector::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
+{
+ ClangTool::addUnsavedFiles(unsavedFiles);
+}
+
+void SymbolsCollector::collectSymbols()
+{
+ auto tool = createTool();
+
+ tool.run(clang::tooling::newFrontendActionFactory(&m_collectSymbolsAction,
+ &m_collectMacrosSourceFileCallbacks).get());
+}
+
+const SymbolEntries &SymbolsCollector::symbols() const
+{
+ return m_collectSymbolsAction.symbols();
+}
+
+const SourceLocationEntries &SymbolsCollector::sourceLocations() const
+{
+ return m_collectSymbolsAction.sourceLocations();
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.h b/src/tools/clangrefactoringbackend/source/symbolscollector.h
new file mode 100644
index 0000000000..6bbdfbcf9e
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolscollector.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "clangtool.h"
+#include "collectmacrossourcefilecallbacks.h"
+#include "collectsymbolsaction.h"
+#include "symbolscollectorinterface.h"
+#include "symbolentry.h"
+#include "stringcache.h"
+
+namespace ClangBackEnd {
+
+class SymbolsCollector : public ClangTool, public SymbolsCollectorInterface
+{
+public:
+ SymbolsCollector(FilePathCache<std::mutex> &filePathCache);
+
+ void addFiles(const Utils::PathStringVector &filePaths,
+ const Utils::SmallStringVector &arguments) override;
+
+ void addUnsavedFiles(const V2::FileContainers &unsavedFiles) override;
+
+ void collectSymbols() override;
+
+ const SymbolEntries &symbols() const override;
+ const SourceLocationEntries &sourceLocations() const override;
+
+private:
+ CollectSymbolsAction m_collectSymbolsAction;
+ CollectMacrosSourceFileCallbacks m_collectMacrosSourceFileCallbacks;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h
new file mode 100644
index 0000000000..fcb909bdc8
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "symbolentry.h"
+#include "sourcelocationentry.h"
+
+#include <filecontainerv2.h>
+
+#include <utils/smallstringvector.h>
+
+#include <string>
+#include <vector>
+
+namespace ClangBackEnd {
+
+class SymbolsCollectorInterface
+{
+public:
+ virtual void addFiles(const Utils::PathStringVector &filePaths,
+ const Utils::SmallStringVector &arguments) = 0;
+
+ virtual void addUnsavedFiles(const V2::FileContainers &unsavedFiles) = 0;
+
+ virtual void collectSymbols() = 0;
+
+ virtual const SymbolEntries &symbols() const = 0;
+ virtual const SourceLocationEntries &sourceLocations() const = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.cpp b/src/tools/clangrefactoringbackend/source/symbolstorage.cpp
new file mode 100644
index 0000000000..793f06f882
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolstorage.cpp
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "symbolstorage.h"
+
+namespace ClangBackEnd {
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h
new file mode 100644
index 0000000000..835f7dec92
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "symbolstorageinterface.h"
+
+#include <sqliteexception.h>
+#include <sqlitetransaction.h>
+#include <stringcache.h>
+
+#include <mutex>
+
+namespace ClangBackEnd {
+
+template <typename StatementFactory>
+class SymbolStorage : public SymbolStorageInterface
+{
+ using Transaction = Sqlite::ImmediateTransaction<typename StatementFactory::DatabaseType>;
+ using ReadStatement = typename StatementFactory::ReadStatementType;
+ using WriteStatement = typename StatementFactory::WriteStatementType;
+ using Database = typename StatementFactory::DatabaseType;
+
+public:
+ SymbolStorage(StatementFactory &statementFactory,
+ FilePathCache<std::mutex> &filePathCache)
+ : m_statementFactory(statementFactory),
+ m_filePathCache(filePathCache)
+ {
+ }
+
+ void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
+ const SourceLocationEntries &sourceLocations) override
+ {
+ Transaction transaction{m_statementFactory.database};
+
+ fillTemporarySymbolsTable(symbolEntries);
+ fillTemporaryLocationsTable(sourceLocations);
+ addNewSymbolsToSymbols();
+ syncNewSymbolsFromSymbols();
+ syncSymbolsIntoNewLocations();
+ insertNewSources();
+ deleteAllLocationsFromUpdatedFiles();
+ insertNewLocationsInLocations();
+ deleteNewSymbolsTable();
+ deleteNewLocationsTable();
+
+ transaction.commit();
+ }
+
+ void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries)
+ {
+ WriteStatement &statement = m_statementFactory.insertSymbolsToNewSymbolsStatement;
+
+ for (const auto &symbolEntry : symbolEntries) {
+ statement.write(symbolEntry.first,
+ symbolEntry.second.usr,
+ symbolEntry.second.symbolName);
+ }
+ }
+
+ void fillTemporaryLocationsTable(const SourceLocationEntries &sourceLocations)
+ {
+ WriteStatement &statement = m_statementFactory.insertLocationsToNewLocationsStatement;
+
+ for (const auto &locationsEntry : sourceLocations) {
+ statement.write(locationsEntry.symbolId,
+ locationsEntry.line,
+ locationsEntry.column,
+ locationsEntry.fileId);
+ }
+ }
+
+ void addNewSymbolsToSymbols()
+ {
+ m_statementFactory.addNewSymbolsToSymbolsStatement.execute();
+ }
+
+ void syncNewSymbolsFromSymbols()
+ {
+ m_statementFactory.syncNewSymbolsFromSymbolsStatement.execute();
+ }
+
+ void syncSymbolsIntoNewLocations()
+ {
+ m_statementFactory.syncSymbolsIntoNewLocationsStatement.execute();
+ }
+
+ void deleteAllLocationsFromUpdatedFiles()
+ {
+ m_statementFactory.deleteAllLocationsFromUpdatedFilesStatement.execute();
+ }
+
+ void insertNewLocationsInLocations()
+ {
+ m_statementFactory.insertNewLocationsInLocationsStatement.execute();
+ }
+
+ FilePathIndices selectNewSourceIds() const
+ {
+ ReadStatement &statement = m_statementFactory.selectNewSourceIdsStatement;
+
+ return statement.template values<FilePathIndex>(16);
+ }
+
+ void insertNewSources()
+ {
+ WriteStatement &statement = m_statementFactory.insertSourcesStatement;
+
+ FilePathIndices newSourceIds = selectNewSourceIds();
+
+ for (FilePathIndex sourceId : newSourceIds)
+ statement.write(sourceId, m_filePathCache.string(sourceId));
+ }
+
+ void deleteNewSymbolsTable()
+ {
+ m_statementFactory.deleteNewSymbolsTableStatement.execute();
+ }
+
+ void deleteNewLocationsTable()
+ {
+ m_statementFactory.deleteNewLocationsTableStatement.execute();
+ }
+
+ SourceLocationEntries sourceLocations() const
+ {
+ return SourceLocationEntries();
+ }
+
+private:
+ StatementFactory &m_statementFactory;
+ FilePathCache<std::mutex> &m_filePathCache;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
new file mode 100644
index 0000000000..05d449748c
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "sourcelocationentry.h"
+#include "symbolentry.h"
+
+namespace ClangBackEnd {
+
+class SymbolStorageInterface
+{
+public:
+ virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
+ const SourceLocationEntries &sourceLocations) = 0;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg
index 4e1fbadcd2..297f6aaff1 100644
--- a/src/tools/icons/qtcreatoricons.svg
+++ b/src/tools/icons/qtcreatoricons.svg
@@ -18,6 +18,18 @@
sodipodi:docname="qtcreatoricons.svg">
<defs
id="defs4">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient9821">
+ <stop
+ style="stop-color:#000000;stop-opacity:1"
+ offset="0"
+ id="stop9817" />
+ <stop
+ style="stop-color:#fffff1;stop-opacity:1"
+ offset="1"
+ id="stop9819" />
+ </linearGradient>
<inkscape:path-effect
effect="clone_original"
linkedpath="#path2727"
@@ -457,26 +469,13 @@
</clipPath>
<linearGradient
inkscape:collect="always"
- xlink:href="#linearGradient5340"
- id="linearGradient5346"
- x1="515.5"
- y1="439"
- x2="515.5"
- y2="442"
+ xlink:href="#linearGradient9821"
+ id="linearGradient9824"
gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-5.25,-362.50001)" />
- <linearGradient
- inkscape:collect="always"
- id="linearGradient5340">
- <stop
- style="stop-color:#000000;stop-opacity:1"
- offset="0"
- id="stop5342" />
- <stop
- style="stop-color:#ffffff;stop-opacity:1"
- offset="1"
- id="stop5344" />
- </linearGradient>
+ x1="510.75"
+ y1="73.5"
+ x2="510.75"
+ y2="75.5" />
</defs>
<sodipodi:namedview
id="base"
@@ -512,31 +511,38 @@
<sodipodi:guide
orientation="0,1"
position="0,32"
- id="guide2989" />
+ id="guide2989"
+ inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="0,0"
- id="guide2991" />
+ id="guide2991"
+ inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="56,16"
- id="guide3045" />
+ id="guide3045"
+ inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="0,48"
- id="guide4261" />
+ id="guide4261"
+ inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="0,64"
- id="guide4543" />
+ id="guide4543"
+ inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="0,80"
- id="guide4545" />
+ id="guide4545"
+ inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="0,100"
- id="guide4574" />
+ id="guide4574"
+ inkscape:locked="false" />
</sodipodi:namedview>
<metadata
id="metadata7">
@@ -591,6 +597,13 @@
style="fill:#00ff00;fill-opacity:1;stroke:none" />
</g>
<rect
+ y="436"
+ x="-16"
+ height="16"
+ width="16"
+ id="backgroundRect"
+ style="display:inline;fill:#ffffff" />
+ <rect
y="452"
x="-16"
height="16"
@@ -2208,7 +2221,7 @@
inkscape:connector-curvature="0" />
</g>
<g
- id="share/qtcreator/templates/wizards/projects/qtquickapplication/icon-empty"
+ id="share/qtcreator/templates/wizards/projects/qtquickapplication/empty/icon"
transform="translate(-23,-82)">
<use
style="display:inline"
@@ -2242,7 +2255,7 @@
</g>
</g>
<g
- id="share/qtcreator/templates/wizards/projects/qtquickapplication/icon-swipe"
+ id="share/qtcreator/templates/wizards/projects/qtquickapplication/swipe/icon"
transform="translate(-57,-82)">
<use
style="display:inline"
@@ -2311,7 +2324,7 @@
x="0" />
</g>
<g
- id="share/qtcreator/templates/wizards/projects/qtquickapplication/icon-stack"
+ id="share/qtcreator/templates/wizards/projects/qtquickapplication/stack/icon"
transform="translate(-91,-82)">
<use
style="display:inline"
@@ -2379,7 +2392,7 @@
transform="matrix(0,1,1,0,-78,95)" />
</g>
<g
- id="share/qtcreator/templates/wizards/projects/qtquickapplication/icon-scroll"
+ id="share/qtcreator/templates/wizards/projects/qtquickapplication/scroll/icon"
transform="translate(-125,-83)">
<use
style="display:inline"
@@ -2501,7 +2514,7 @@
height="100%" />
</g>
<g
- id="share/qtcreator/templates/wizards/projects/qtcanvas3dapplication/3dapplication"
+ id="share/qtcreator/templates/wizards/projects/qtquickapplication/canvas3d/icon"
transform="translate(-159,-83)">
<use
style="display:inline"
@@ -4423,7 +4436,7 @@
y="0"
x="0"
style="display:inline"
- transform="translate(387,509)" />
+ transform="translate(388,513)" />
</g>
<g
transform="translate(32,0)"
@@ -5283,6 +5296,71 @@
width="100%"
height="100%"
transform="matrix(-1,0,0,1,2293,0)" />
+ <g
+ id="src/plugins/autotest/images/benchmark">
+ <rect
+ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
+ x="1676"
+ y="568"
+ width="16"
+ height="16"
+ id="rect4959-4-5-4-4-9-6" />
+ <circle
+ cy="576"
+ cx="1684"
+ id="path5907"
+ style="fill:#e6e6e6;stroke:#000000;stroke-width:1;stroke-opacity:1"
+ r="5.5" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path5911"
+ d="m 1683.5,576.5 3.8812,-3.88134"
+ style="stroke:#000000;stroke-width:0.60000002" />
+ <path
+ style="fill:#000000;stroke-width:1"
+ d="m 1682.5,569 v 1 h 3 v -1 z"
+ id="rect5909"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <g
+ id="src/plugins/autotest/images/text">
+ <rect
+ id="rect4959-4-5-4-4-9-6-3"
+ height="16"
+ width="16"
+ y="568"
+ x="1692"
+ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none" />
+ <path
+ id="path9930"
+ style="fill:none;stroke:#000000"
+ d="m 1700,581.5 h 7 m -12.5,-11 5.5,5.5 -5.5,5.5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <g
+ id="src/plugins/autotest/images/visual">
+ <rect
+ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
+ x="1708"
+ y="568"
+ width="16"
+ height="16"
+ id="rect4959-4-5-4-4-9-6-3-6" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0"
+ d="m 1714.5,577.5 h 3.5 m -3.5,-4 v 4.5 m -4,-4.5 h 4.5 m -4.5,-2.5 v 11 m 3.5,-0.5 h -3.5"
+ style="stroke:#666666"
+ id="path9999" />
+ <path
+ id="rect9970-2-1"
+ d="m 1714,581 h 5 v 2 h -5 z m -4,-12 h 5 v 2 h -5 z m 4,4 h 5 v 2 h -5 z m 4,4 h 5 v 2 h -5 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ </g>
</g>
<g
inkscape:groupmode="layer"
@@ -5365,68 +5443,6 @@
style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1.0;stroke-dasharray:none" />
</g>
<g
- style="display:inline"
- id="src/plugins/projectexplorer/images/rebuildhammerhandles"
- transform="translate(-1266.5,289)">
- <rect
- y="263"
- x="1339.5"
- height="16"
- width="16"
- id="rect6249-7"
- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0"
- id="smallhammerhandle"
- d="m 1343,269 9,9 1.5,-1.5 -9,-9 z" />
- <use
- height="100%"
- width="100%"
- transform="matrix(-1,0,0,1,2695,0)"
- id="use6253-7"
- xlink:href="#smallhammerhandle"
- y="0"
- x="0" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1347.675,273.675 1.5,-1.5"
- id="path6284"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc" />
- <path
- style="display:inline;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.50006026;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1345.8268,271.82353 1.5,-1.50041"
- id="path6284-5"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc" />
- </g>
- <g
- style="display:inline"
- id="src/plugins/projectexplorer/images/rebuildhammerheads"
- transform="translate(-1250.5,289)">
- <rect
- y="263"
- x="1339.5"
- height="16"
- width="16"
- id="rect6249"
- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- sodipodi:nodetypes="ccccc"
- inkscape:connector-curvature="0"
- id="smallhammerhead"
- d="m 1339.5,268.5 2,2.5 6,-6 -4.5,0 z" />
- <use
- height="100%"
- width="100%"
- transform="matrix(-1,0,0,1,2695,0)"
- id="use6253"
- xlink:href="#smallhammerhead"
- y="0"
- x="0" />
- </g>
- <g
transform="translate(-34,374)"
id="src/plugins/welcome/images/new">
<rect
@@ -6223,6 +6239,77 @@
cy="564"
r="3.5" />
</g>
+ <g
+ style="display:inline"
+ id="src/plugins/projectexplorer/images/buildhammerhandle"
+ transform="translate(-802.5,289)">
+ <rect
+ y="263"
+ x="1339.5"
+ height="16"
+ width="16"
+ id="rect6249-7-2"
+ style="fill:#ffffff" />
+ <path
+ d="m 1352,269 -9,9 -1.5,-1.5 9,-9 z"
+ id="use6253-7-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <g
+ style="display:inline"
+ id="src/plugins/projectexplorer/images/buildhammerhead"
+ transform="translate(-786.5,289)">
+ <rect
+ y="263"
+ x="1339.5"
+ height="16"
+ width="16"
+ id="rect6249-2"
+ style="fill:#ffffff" />
+ <path
+ d="m 1355.5,268.5 -2,2.5 -6,-6 h 4.5 z"
+ id="use6253-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <g
+ style="display:inline"
+ id="src/plugins/projectexplorer/images/rebuildhammerhandles"
+ transform="translate(-770.5,289)">
+ <rect
+ y="263"
+ x="1339.5"
+ height="16"
+ width="16"
+ id="rect6249-7"
+ style="fill:#ffffff" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="smallhammerhandle"
+ d="m 1343,269 9,9 1.5,-1.5 -9,-9 z" />
+ <path
+ style="stroke:#ffffff;stroke-width:0.5"
+ d="m 1347.675,273.675 1.5,-1.5"
+ id="path6284"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="stroke:#ffffff;stroke-width:0.5"
+ d="m 1345.8268,271.82353 1.5,-1.5"
+ id="path6284-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <use
+ x="0"
+ y="0"
+ xlink:href="#src/plugins/projectexplorer/images/buildhammerhead"
+ id="src/plugins/projectexplorer/images/rebuildhammerheads"
+ transform="matrix(-1,0,0,1,1154,0)"
+ width="100%"
+ height="100%" />
</g>
<g
inkscape:groupmode="layer"
@@ -6672,38 +6759,28 @@
</g>
</g>
<g
- style="display:inline"
- id="src/libs/utils/images/magnifier"
- transform="translate(37,-80)">
+ id="src/libs/utils/images/magnifier">
<rect
style="fill:#ffffff;fill-opacity:1"
id="rect3817-2-9-1-9-6-0"
- width="17"
- height="11"
- x="171"
- y="589" />
- <g
- transform="translate(-231.13585,386.05488)"
- id="magnifying_lense-1"
- style="display:inline;fill:#000000;fill-opacity:1">
- <path
- id="path4719-8-0"
- d="m 402.25285,212.41599 c -0.156,0.155 -0.156,0.41 0,0.565 l 0.84663,0.84863 c 0.156,0.154 0.41,0.154 0.566,0 L 407.231,210.24 c 0.156,-0.154 0.156,-0.41 0.001,-0.565 l -0.84763,-0.84763 c -0.156,-0.156 -0.41,-0.156 -0.566,0 z"
- inkscape:connector-curvature="0"
- style="fill-opacity:1"
- sodipodi:nodetypes="cccccsscc" />
- <circle
- style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.17697227;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path5669-9"
- cx="409"
- cy="206.94511"
- r="3.4115138" />
- </g>
+ width="16"
+ height="16"
+ x="208"
+ y="504" />
+ <use
+ transform="translate(-193,303)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#magnifying_lense"
+ id="use5882"
+ width="100%"
+ height="100%" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4784-5"
- d="m 186,597 -2.5,2.5 -2.5,-2.5 z"
+ d="m 224,516 -2.5,2.5 -2.5,-2.5 z"
style="display:inline;fill:#000000;fill-opacity:1;stroke:none" />
</g>
<g
@@ -6920,147 +6997,164 @@
id="g4718"
inkscape:label="Side Bar Icons">
<g
- transform="translate(-34,308)"
+ transform="translate(-41,264)"
style="display:inline"
id="src/plugins/welcome/images/mode_welcome_mask">
- <rect
- style="fill:#ffffff;fill-opacity:1"
- x="34"
- y="42"
- width="48"
- height="32"
- id="rect5694-0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="backgroundRect_32_28"
+ transform="matrix(2.125,0,0,2.125,75,-888.5)"
+ width="100%"
+ height="100%"
+ style="stroke-width:0.88038999" />
<path
inkscape:connector-curvature="0"
- d="m 62,62 5,0 0,5 -5,0 z m -7,0 5,0 0,5 -5,0 z m -7,0 5,0 0,5 -5,0 z m 14,-7 5,0 0,5 -5,0 z m -7,0 5,0 0,5 -5,0 z m -7,0 5,0 0,5 -5,0 z m 14,-7 5,0 0,5 -5,0 z m -7,0 5,0 0,5 -5,0 z m -7,0 5,0 0,5 -5,0 z"
+ d="m 62,59 h 5 v 5 h -5 z m -7,0 h 5 v 5 h -5 z m -7,0 h 5 v 5 h -5 z m 14,-7 h 5 v 5 h -5 z m -7,0 h 5 v 5 h -5 z m -7,0 h 5 v 5 h -5 z m 14,-7 h 5 v 5 h -5 z m -7,0 h 5 v 5 h -5 z m -7,0 h 5 v 5 h -5 z"
id="rect5371-8" />
</g>
<g
- transform="translate(-36,308)"
+ transform="translate(-55,264)"
style="display:inline;fill:#000000"
id="src/plugins/coreplugin/images/mode_edit_mask">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="84"
- y="42"
- width="48"
- height="32"
- id="rect5706-3-8" />
+ <use
+ transform="translate(50)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913"
+ width="100%"
+ height="100%" />
<path
id="path5381-3"
- d="m 98,48 0,19 19,0 0,-19 z m 4,9 9,0 0,1 -9,0 z m 9,5 -9,0 0,-1 9,0 z m 2,-2 -11,0 0,-1 11,0 z m 0,-4 -11,0 0,-1 11,0 z m 0,-2 -11,0 0,-1 11,0 z"
+ d="m 98,45 v 19 h 19 V 45 Z m 4,9 h 9 v 1 h -9 z m 9,5 h -9 v -1 h 9 z m 2,-2 h -11 v -1 h 11 z m 0,-4 h -11 v -1 h 11 z m 0,-2 h -11 v -1 h 11 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
</g>
<g
- transform="translate(-38,308)"
+ transform="translate(-69,264)"
style="display:inline"
id="src/plugins/coreplugin/images/mode_design_mask">
- <rect
- style="fill:#ffffff;fill-opacity:1"
- x="134"
- y="42"
- width="48"
- height="32"
- id="rect5706-2" />
+ <use
+ transform="translate(100)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0"
+ width="100%"
+ height="100%" />
<g
- transform="translate(-5,-4)"
+ transform="translate(-5,-6)"
id="g5387-8">
<path
id="polygon5391-6"
- d="m 167.909,59.778 -3.535,-3.536 -10.96,10.96 -1.414,4.95 4.949,-1.414 z m -2.4715,-4.589696 3.18214,-3.180343 3.5338,3.535793 -3.18215,3.180343 z"
+ d="m 167.909,58.778 -3.535,-3.536 -10.96,10.96 -1.414,4.95 4.949,-1.414 z m -2.4715,-4.589696 3.18214,-3.180343 3.5338,3.535793 -3.18215,3.180343 z"
inkscape:connector-curvature="0" />
</g>
</g>
<g
- transform="translate(-40,308)"
+ transform="translate(-83,264)"
style="display:inline"
id="src/plugins/debugger/images/mode_debug_mask">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
- x="184"
- y="42"
- width="48"
- height="32"
- id="rect5706-4-6" />
+ <use
+ transform="translate(150)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8"
+ width="100%"
+ height="100%" />
<g
- transform="translate(-4.5,-5)"
+ transform="translate(-4.5,-7)"
id="g5397-4">
<path
- d="M 167.5 356 C 166.225 356 164.19123 357.17695 163.61523 358.75195 L 167.5 360.9375 L 171.38477 358.75195 C 170.80877 357.17595 168.775 356 167.5 356 z M 162.82422 359.68359 L 160.83789 361.44922 L 159.44141 360.05469 C 159.24741 359.86069 158.92837 359.86069 158.73438 360.05469 C 158.54038 360.24869 158.54038 360.56772 158.73438 360.76172 L 160.42188 362.44922 L 159.53516 366 L 158 366 C 157.725 366 157.5 366.225 157.5 366.5 C 157.5 366.775 157.725 367 158 367 L 159.48828 367 L 160.67969 370.8125 L 159.05273 372.43945 C 158.85873 372.63345 158.85873 372.95248 159.05273 373.14648 C 159.24673 373.34048 159.56577 373.34048 159.75977 373.14648 L 161.13477 371.77148 L 164.6875 374.13867 L 167 374.72461 L 167 362 L 162.82422 359.68359 z M 172.17578 359.68359 L 168 362 L 168 374.72461 L 170.3125 374.13867 L 173.86328 371.77148 L 175.23828 373.14648 C 175.43228 373.34048 175.75131 373.34048 175.94531 373.14648 C 176.13931 372.95248 176.13931 372.63345 175.94531 372.43945 L 174.32031 370.81445 L 175.51172 367 L 177 367 C 177.275 367 177.5 366.775 177.5 366.5 C 177.5 366.225 177.275 366 177 366 L 175.46484 366 L 174.57812 362.44922 L 176.26562 360.76172 C 176.45963 360.56772 176.45962 360.24869 176.26562 360.05469 C 176.07163 359.86069 175.75259 359.86069 175.55859 360.05469 L 174.16211 361.44922 L 172.17578 359.68359 z "
- transform="translate(44.5,-303)"
- id="path5403-3" />
+ d="m 212,52 c -1.275,0 -3.30877,1.17695 -3.88477,2.75195 L 212,56.9375 215.88477,54.75195 C 215.30877,53.17595 213.275,52 212,52 Z m -4.67578,3.68359 -1.98633,1.76563 -1.39648,-1.39453 c -0.194,-0.194 -0.51304,-0.194 -0.70703,0 -0.194,0.194 -0.194,0.51303 0,0.70703 l 1.6875,1.6875 L 204.03516,62 H 202.5 c -0.275,0 -0.5,0.225 -0.5,0.5 0,0.275 0.225,0.5 0.5,0.5 h 1.48828 l 1.19141,3.8125 -1.62696,1.62695 c -0.194,0.194 -0.194,0.51303 0,0.70703 0.194,0.194 0.51304,0.194 0.70704,0 l 1.375,-1.375 3.55273,2.36719 2.3125,0.58594 V 58 Z m 9.35156,0 L 212.5,58 v 12.72461 l 2.3125,-0.58594 3.55078,-2.36719 1.375,1.375 c 0.194,0.194 0.51303,0.194 0.70703,0 0.194,-0.194 0.194,-0.51303 0,-0.70703 l -1.625,-1.625 L 220.01172,63 H 221.5 c 0.275,0 0.5,-0.225 0.5,-0.5 0,-0.275 -0.225,-0.5 -0.5,-0.5 h -1.53516 l -0.88672,-3.55078 1.6875,-1.6875 c 0.19401,-0.194 0.194,-0.51303 0,-0.70703 -0.19399,-0.194 -0.51303,-0.194 -0.70703,0 l -1.39648,1.39453 z"
+ id="path5403-3"
+ inkscape:connector-curvature="0" />
</g>
</g>
<g
- transform="translate(-42,308)"
+ transform="translate(-97,264)"
style="display:inline"
id="src/plugins/projectexplorer/images/mode_project_mask">
- <rect
- style="fill:#ffffff;fill-opacity:1"
- x="234"
- y="42"
- width="48"
- height="32"
- id="rect5722-4" />
+ <use
+ transform="translate(200)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-3"
+ width="100%"
+ height="100%" />
<path
id="path5439-0"
- d="m 265.554,57.885 c 1.51,-1.511 1.955,-3.68 1.34,-5.583 l -2.754,2.754 c -0.584,0.583 -1.538,0.583 -2.121,0 l -1.414,-1.415 c -0.584,-0.583 -0.584,-1.538 0,-2.121 l 2.754,-2.754 c -1.903,-0.614 -4.073,-0.17 -5.583,1.34 -1.647,1.647 -2.025,4.081 -1.145,6.095 l -8.048,8.047 c -0.777,0.778 -0.777,2.051 0,2.829 0.777,0.777 2.051,0.777 2.828,0 l 8.048,-8.048 c 2.015,0.882 4.447,0.503 6.095,-1.144 z"
+ d="m 265.554,54.885 c 1.51,-1.511 1.955,-3.68 1.34,-5.583 l -2.754,2.754 c -0.584,0.583 -1.538,0.583 -2.121,0 l -1.414,-1.415 c -0.584,-0.583 -0.584,-1.538 0,-2.121 l 2.754,-2.754 c -1.903,-0.614 -4.073,-0.17 -5.583,1.34 -1.647,1.647 -2.025,4.081 -1.145,6.095 l -8.048,8.047 c -0.777,0.778 -0.777,2.051 0,2.829 0.777,0.777 2.051,0.777 2.828,0 l 8.048,-8.048 c 2.015,0.882 4.447,0.503 6.095,-1.144 z"
inkscape:connector-curvature="0" />
</g>
<g
- transform="translate(-46,308)"
+ transform="translate(-162,264)"
style="display:inline"
id="src/plugins/help/images/mode_help_mask">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="334"
- y="42"
- width="48"
- height="32"
- id="rect5706-9-7" />
+ <use
+ transform="translate(301)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-7"
+ width="100%"
+ height="100%" />
<path
id="path5457-0"
- d="m 358,48 c -5.522,0 -10,4.478 -10,10 0,5.522 4.478,10 10,10 5.522,0 10,-4.478 10,-10 0,-5.522 -4.478,-10 -10,-10 z m 1.136,16.182 c -0.274,0.269 -0.604,0.402 -0.989,0.402 -0.187,0 -0.364,-0.035 -0.533,-0.105 -0.169,-0.07 -0.318,-0.163 -0.446,-0.28 -0.129,-0.117 -0.23,-0.257 -0.307,-0.42 -0.076,-0.163 -0.113,-0.338 -0.113,-0.525 0,-0.373 0.137,-0.694 0.411,-0.962 0.273,-0.268 0.603,-0.402 0.988,-0.402 0.374,0 0.7,0.128 0.98,0.385 0.28,0.257 0.42,0.572 0.42,0.945 0,0.372 -0.138,0.693 -0.411,0.962 z m 2.738,-7.98 c -0.104,0.292 -0.245,0.56 -0.42,0.805 -0.175,0.245 -0.376,0.479 -0.604,0.7 -0.228,0.222 -0.47,0.455 -0.727,0.7 -0.163,0.151 -0.303,0.286 -0.42,0.402 -0.116,0.117 -0.213,0.236 -0.288,0.359 -0.076,0.122 -0.132,0.262 -0.167,0.42 -0.034,0.157 -0.052,0.347 -0.052,0.569 l 0,0.665 -2.101,0 0,-0.962 c 0,-0.256 0.015,-0.475 0.044,-0.656 0.029,-0.181 0.081,-0.344 0.157,-0.49 0.076,-0.146 0.175,-0.286 0.298,-0.42 0.122,-0.134 0.271,-0.295 0.446,-0.481 l 1.348,-1.365 c 0.291,-0.292 0.438,-0.67 0.438,-1.137 0,-0.455 -0.149,-0.825 -0.446,-1.111 -0.298,-0.286 -0.674,-0.429 -1.129,-0.429 -0.49,0 -0.893,0.166 -1.208,0.499 -0.314,0.333 -0.495,0.738 -0.542,1.216 l -2.24,-0.175 c 0.07,-0.56 0.216,-1.059 0.438,-1.496 0.222,-0.438 0.511,-0.808 0.866,-1.111 0.355,-0.303 0.768,-0.534 1.234,-0.691 0.466,-0.158 0.979,-0.236 1.54,-0.236 0.524,0 1.012,0.076 1.461,0.228 0.449,0.152 0.84,0.371 1.172,0.656 0.333,0.286 0.593,0.642 0.779,1.067 0.186,0.426 0.28,0.913 0.28,1.461 10e-4,0.382 -0.052,0.721 -0.157,1.013 z"
+ d="m 359,45 c -5.522,0 -10,4.478 -10,10 0,5.522 4.478,10 10,10 5.522,0 10,-4.478 10,-10 0,-5.522 -4.478,-10 -10,-10 z m 1.136,16.182 c -0.274,0.269 -0.604,0.402 -0.989,0.402 -0.187,0 -0.364,-0.035 -0.533,-0.105 -0.169,-0.07 -0.318,-0.163 -0.446,-0.28 -0.129,-0.117 -0.23,-0.257 -0.307,-0.42 -0.076,-0.163 -0.113,-0.338 -0.113,-0.525 0,-0.373 0.137,-0.694 0.411,-0.962 0.273,-0.268 0.603,-0.402 0.988,-0.402 0.374,0 0.7,0.128 0.98,0.385 0.28,0.257 0.42,0.572 0.42,0.945 0,0.372 -0.138,0.693 -0.411,0.962 z m 2.738,-7.98 c -0.104,0.292 -0.245,0.56 -0.42,0.805 -0.175,0.245 -0.376,0.479 -0.604,0.7 -0.228,0.222 -0.47,0.455 -0.727,0.7 -0.163,0.151 -0.303,0.286 -0.42,0.402 -0.116,0.117 -0.213,0.236 -0.288,0.359 -0.076,0.122 -0.132,0.262 -0.167,0.42 -0.034,0.157 -0.052,0.347 -0.052,0.569 v 0.665 h -2.101 V 56.86 c 0,-0.256 0.015,-0.475 0.044,-0.656 0.029,-0.181 0.081,-0.344 0.157,-0.49 0.076,-0.146 0.175,-0.286 0.298,-0.42 0.122,-0.134 0.271,-0.295 0.446,-0.481 l 1.348,-1.365 c 0.291,-0.292 0.438,-0.67 0.438,-1.137 0,-0.455 -0.149,-0.825 -0.446,-1.111 -0.298,-0.286 -0.674,-0.429 -1.129,-0.429 -0.49,0 -0.893,0.166 -1.208,0.499 -0.314,0.333 -0.495,0.738 -0.542,1.216 l -2.24,-0.175 c 0.07,-0.56 0.216,-1.059 0.438,-1.496 0.222,-0.438 0.511,-0.808 0.866,-1.111 0.355,-0.303 0.768,-0.534 1.234,-0.691 0.466,-0.158 0.979,-0.236 1.54,-0.236 0.524,0 1.012,0.076 1.461,0.228 0.449,0.152 0.84,0.371 1.172,0.656 0.333,0.286 0.593,0.642 0.779,1.067 0.186,0.426 0.28,0.913 0.28,1.461 10e-4,0.382 -0.052,0.721 -0.157,1.013 z"
inkscape:connector-curvature="0" />
</g>
<g
- transform="translate(-262,305)"
+ transform="translate(-595,297)"
style="display:inline"
id="src/plugins/projectexplorer/images/run_mask">
- <rect
- style="fill:#ffffff;fill-opacity:1"
- x="600"
- y="50"
- width="24"
- height="24"
- id="rect5751-4" />
+ <use
+ transform="translate(554,3)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1"
+ width="100%"
+ height="100%" />
<polygon
style="fill:#000000"
- points="621,61 603,72 603,50 "
- id="polygon5749-6" />
+ points="603,50 621,61 603,72 "
+ id="polygon5749-6"
+ transform="translate(0,-4)" />
</g>
<g
- transform="translate(-388,305)"
+ transform="translate(-708,297)"
style="display:inline"
id="src/plugins/projectexplorer/images/debugger_beetle_mask">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="750"
- y="50"
- width="24"
- height="24"
- id="rect5759-4-1" />
+ <use
+ transform="translate(703,3)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-3"
+ width="100%"
+ height="100%" />
<g
id="big_bug"
- transform="translate(-4,2.999762)">
+ transform="translate(-5,-1.000238)">
<path
d="m 769.50001,58.836563 c -0.65839,0 -1.70859,0.724548 -2.00602,1.694142 l 2.00602,1.345458 2.006,-1.345458 c -0.29742,-0.97021 -1.34763,-1.694142 -2.006,-1.694142 z"
id="path4874"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cccccccccccccccc"
- d="m 767.12627,61.068318 c -0.25633,0.152637 -0.64848,0.411162 -1.25704,1.062795 l -1.53472,-1.238122 -0.75352,0.91144 1.76081,1.340958 C 765.1929,63.665163 764.94085,64.148012 764.875,65 l -1.875,0 0,1 1.875,0 c 0.13153,0.564121 0.25703,1.128242 0.58926,1.692363 l -1.66595,1.498516 0.73938,0.89637 1.61151,-1.446886 c 1.00647,0.777187 1.78541,1.06964 2.8508,1.139875 l 0,-7.354264 z"
+ d="m 767.12627,61.068318 c -0.25633,0.152637 -0.64848,0.411162 -1.25704,1.062795 l -1.53472,-1.238122 -0.75352,0.91144 1.76081,1.340958 C 765.1929,63.665163 764.94085,64.148012 764.875,65 H 763 v 1 h 1.875 c 0.13153,0.564121 0.25703,1.128242 0.58926,1.692363 l -1.66595,1.498516 0.73938,0.89637 1.61151,-1.446886 c 1.00647,0.777187 1.78541,1.06964 2.8508,1.139875 v -7.354264 z"
id="path4872"
inkscape:connector-curvature="0" />
<use
@@ -7075,142 +7169,176 @@
</g>
<g
id="src/plugins/debugger/images/debugger_interrupt_mask"
- transform="translate(-364,305)"
+ transform="translate(-673,297)"
style="display:inline">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="750"
- y="50"
- width="24"
- height="24"
- id="rect4791" />
+ <use
+ transform="translate(704,3)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-7"
+ width="100%"
+ height="100%" />
<rect
style="display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4608-0"
width="7"
height="18"
x="753"
- y="52" />
+ y="48" />
<rect
style="display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4610-6"
width="7"
height="18"
x="763"
- y="52" />
+ y="48" />
</g>
<g
id="src/plugins/debugger/images/debugger_continue_1_mask"
- transform="translate(-340,305)"
+ transform="translate(-636,297)"
style="display:inline">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="750"
- y="50"
- width="24"
- height="24"
- id="rect4791-9" />
+ <use
+ transform="translate(703,3)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-30"
+ width="100%"
+ height="100%" />
<rect
style="display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4608-0-4"
width="7"
height="18"
- x="753"
- y="52" />
+ x="752"
+ y="48" />
</g>
<g
id="src/plugins/debugger/images/debugger_continue_2_mask"
- transform="translate(-316,305)"
+ transform="translate(-602,297)"
style="display:inline">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="750"
- y="50"
- width="24"
- height="24"
- id="rect4791-9-8" />
+ <use
+ transform="translate(705,3)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-8"
+ width="100%"
+ height="100%" />
<path
style="display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 763,52 9,9 -9,9 z"
+ d="m 764,48 9,9 -9,9 z"
id="rect4610-6-2-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
<g
- transform="translate(-392,305)"
+ transform="translate(-664,297)"
style="display:inline"
id="src/plugins/projectexplorer/images/build_hammerhandle_mask">
- <rect
- style="fill:#ffffff;fill-opacity:1"
- x="850"
- y="50"
- width="24"
- height="24"
- id="rect5759-5" />
+ <use
+ transform="translate(803,3)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-89"
+ width="100%"
+ height="100%" />
<g
style="fill:#030303;fill-opacity:1"
- id="build-5">
+ id="build-5"
+ transform="translate(-1,-3)">
<rect
- style="fill:#030303;fill-opacity:1"
- x="856.98199"
- y="53.081001"
- transform="matrix(0.7071,0.7071,-0.7071,0.7071,296.0486,-588.562)"
- width="3"
- height="20"
+ style="fill:#030303;fill-opacity:1;stroke-width:0.9999904"
+ x="649.42847"
+ y="-573.14081"
+ transform="rotate(45)"
+ width="2.9999712"
+ height="19.999807"
id="rect5755-4" />
</g>
</g>
<g
- transform="translate(-368,305)"
+ transform="translate(-628,297)"
style="display:inline"
id="src/plugins/projectexplorer/images/build_hammerhead_mask">
- <rect
- style="fill:#ffffff;fill-opacity:1"
- x="850"
- y="50"
- width="24"
- height="24"
- id="rect5759-5-9" />
+ <use
+ transform="translate(803,3)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5"
+ width="100%"
+ height="100%" />
<g
style="fill:#030303;fill-opacity:1"
- id="build-5-2">
+ id="build-5-2"
+ transform="translate(-1,-3)">
<polygon
style="fill:#030303;fill-opacity:1"
- points="866.613,50 873.684,57.071 870.148,60.606 859.542,50 "
- id="polygon5757-3-4" />
+ points="873.684,57.071 870.148,60.606 859.542,50 866.613,50 "
+ id="polygon5757-3-4"
+ transform="translate(0,-1)" />
</g>
</g>
<g
- transform="translate(6.5,297)"
+ transform="translate(-247.5,256)"
id="src/plugins/projectexplorer/images/desktopdevice">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="499.5"
- y="50"
- width="32"
- height="32"
- id="rect5759-5-9-0" />
- <path
- d="m 525.5,54 -20,0 c -1.1,0 -2,0.9 -2,2 l 0,14 c 0,1.1 0.9,2 2,2 l 20,0 c 1.1,0 2,-0.9 2,-2 l 0,-14 c 0,-1.1 -0.9,-2 -2,-2 l 0,0 z"
- id="path5514" />
- <path
- d="m 521,78 -3.5,-7 -4,0 -3.5,7 z"
- id="polygon5516"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccc" />
- <path
- d="m 525.5,56 0,14 -20,0 0,-14 20,0"
- id="path4825"
- style="fill:#b3b3b3" />
+ <use
+ transform="translate(458.5,7)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6"
+ width="100%"
+ height="100%" />
+ <g
+ id="desktopDevice"
+ transform="translate(1,-4)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path5514"
+ d="m 525.5,54 h -20 c -1.1,0 -2,0.9 -2,2 v 14 c 0,1.1 0.9,2 2,2 h 20 c 1.1,0 2,-0.9 2,-2 V 56 c 0,-1.1 -0.9,-2 -2,-2 z" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="polygon5516"
+ d="m 521,78 -3.5,-7 h -4 l -3.5,7 z" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#b3b3b3"
+ id="path4825"
+ d="m 525.5,56 v 14 h -20 V 56 h 20" />
+ </g>
</g>
- <use
- x="0"
- y="0"
- xlink:href="#src/plugins/projectexplorer/images/desktopdevice"
+ <g
id="src/libs/utils/images/desktopdevicesmall"
- transform="matrix(0.5,0,0,0.5,285,189.5)"
- width="100%"
- height="100%" />
+ transform="translate(-190,-45)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054"
+ width="100%"
+ height="100%"
+ transform="translate(458,-54)" />
+ <use
+ transform="matrix(0.5,0,0,0.5,191.75,359)"
+ x="0"
+ y="0"
+ xlink:href="#desktopDevice"
+ id="use8907"
+ width="100%"
+ height="100%"
+ style="stroke-width:2" />
+ </g>
<g
id="src/plugins/projectexplorer/images/fileoverlay_qt">
<rect
@@ -7667,36 +7795,40 @@
sodipodi:nodetypes="ccccc" />
</g>
<g
- id="src/plugins/ios/images/iosdevice">
- <rect
- style="fill:#ffffff"
- x="554"
- y="347"
- width="32"
- height="32"
- id="rect5230" />
+ id="src/plugins/ios/images/iosdevice"
+ transform="translate(-266,-42)">
+ <use
+ transform="translate(513,305)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8"
+ width="100%"
+ height="100%" />
<g
- id="phone_body_big">
+ id="phone_body_big"
+ transform="translate(1,-3)">
<path
sodipodi:nodetypes="csssssssc"
id="path5232"
- d="m 578,374 0,-22 c 0,-1.1 -1,-2 -2,-2 l -12,0 c -1.1,0 -2,1 -2,2 l 0,22 c 0,1.1 1,2 2,2 l 12,0 c 1.1,0 2,-1 2,-2 z"
+ d="m 578,374 v -22 c 0,-1.1 -1,-2 -2,-2 h -12 c -1.1,0 -2,1 -2,2 v 22 c 0,1.1 1,2 2,2 h 12 c 1.1,0 2,-1 2,-2 z"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccccc"
style="fill:#b3b3b3"
id="path5234"
- d="m 564,371 0,-19 12,0 0,19 z"
+ d="m 564,371 v -19 h 12 v 19 z"
inkscape:connector-curvature="0" />
</g>
<circle
style="fill:#b3b3b3"
id="circle5236"
- cx="570"
- cy="373.5"
+ cx="571"
+ cy="370.5"
r="1.5" />
<use
- transform="matrix(1.7179779,0,0,1.7179779,-422.96128,-273.18602)"
+ transform="matrix(1.7179779,0,0,1.7179779,-421.96128,-276.18602)"
x="0"
y="0"
xlink:href="#ioslogo"
@@ -7706,24 +7838,25 @@
</g>
<g
id="src/plugins/ios/images/iosdevicesmall"
- transform="translate(16,0)">
- <rect
- id="rect5759-5-9-0-8"
- height="16"
- width="16"
- y="363"
- x="570"
- style="fill:#ffffff" />
+ transform="translate(-282,-26)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-9"
+ width="100%"
+ height="100%"
+ transform="translate(586,-73)" />
<g
id="phone_body_small">
<path
inkscape:connector-curvature="0"
- d="m 582,377 0,-12 c 0,-0.55 -0.5,-1 -1,-1 l -6,0 c -0.55,0 -1,0.5 -1,1 l 0,12 c 0,0.55 0.5,1 1,1 l 6,0 c 0.55,0 1,-0.5 1,-1 z"
+ d="m 582,377 v -12 c 0,-0.55 -0.5,-1 -1,-1 h -6 c -0.55,0 -1,0.5 -1,1 v 12 c 0,0.55 0.5,1 1,1 h 6 c 0.55,0 1,-0.5 1,-1 z"
id="path5514-4"
sodipodi:nodetypes="csssssssc" />
<path
inkscape:connector-curvature="0"
- d="m 575,375 0,-10 6,0 0,10 z"
+ d="m 575,375 v -10 h 6 v 10 z"
id="path4825-5"
style="fill:#b3b3b3"
sodipodi:nodetypes="ccccc" />
@@ -7736,20 +7869,22 @@
style="fill:#b3b3b3" />
<path
id="ioslogo"
- style="fill:#000000;fill-opacity:1.0"
+ style="fill:#000000;fill-opacity:1"
d="m 578.70257,367.62846 c 0.17676,-0.2141 0.29609,-0.51179 0.26322,-0.80851 -0.25463,0.0103 -0.56283,0.16975 -0.74567,0.38384 -0.16367,0.18922 -0.30725,0.49232 -0.26834,0.783 0.28398,0.022 0.574,-0.14455 0.75079,-0.35833 m 0.6373,1.88113 c -0.006,-0.64069 0.52327,-0.94828 0.5472,-0.96327 -0.29769,-0.43553 -0.76098,-0.4952 -0.92626,-0.50222 -0.39405,-0.0399 -0.76928,0.23197 -0.96901,0.23197 -0.19974,0 -0.5086,-0.22622 -0.83533,-0.21984 -0.4301,0.006 -0.82607,0.24984 -1.0475,0.63463 -0.44638,0.77438 -0.11391,1.92207 0.32066,2.55064 0.21282,0.30726 0.46616,0.65345 0.79927,0.64069 0.32098,-0.0128 0.44223,-0.2074 0.82958,-0.2074 0.38735,0 0.49647,0.2074 0.83565,0.20134 0.34491,-0.007 0.56379,-0.31397 0.77501,-0.62219 0.24377,-0.35672 0.3446,-0.70195 0.35034,-0.72014 -0.008,-0.003 -0.67259,-0.25813 -0.67961,-1.02421"
inkscape:connector-curvature="0" />
</g>
<g
- transform="translate(48,0)"
+ transform="translate(-230,-42)"
id="src/plugins/android/images/androiddevice">
- <rect
- style="fill:#ffffff"
- x="554"
- y="347"
- width="32"
- height="32"
- id="rect5230-4" />
+ <use
+ transform="translate(513,305)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-7"
+ width="100%"
+ height="100%" />
<use
x="0"
y="0"
@@ -7762,23 +7897,23 @@
id="rect4318"
width="4"
height="2"
- x="568"
- y="373" />
+ x="569"
+ y="370" />
<g
- transform="translate(-48,0)"
+ transform="translate(-47,-3)"
id="g5128"
- style="fill:#000000;fill-opacity:1.0">
+ style="fill:#000000;fill-opacity:1">
<path
sodipodi:nodetypes="ccccccccccccc"
inkscape:connector-curvature="0"
id="path4309"
- d="m 620.5,360 0,5 -0.5,0 0,2 -1,0 0,-2 -2,0 0,2 -1,0 0,-2 -0.5,0 0,-5 z"
+ d="m 620.5,360 v 5 H 620 v 2 h -1 v -2 h -2 v 2 h -1 v -2 h -0.5 v -5 z"
style="fill-opacity:1" />
<path
sodipodi:nodetypes="cccccccccc"
inkscape:connector-curvature="0"
id="path4311"
- d="m 616.29102,356.80664 -0.58204,0.38672 1,1.5 0.58204,-0.38672 z M 614,360 l 0,4 1,0 0,-4 z"
+ d="m 616.29102,356.80664 -0.58204,0.38672 1,1.5 0.58204,-0.38672 z M 614,360 v 4 h 1 v -4 z"
style="fill-opacity:1" />
<use
height="100%"
@@ -7793,20 +7928,21 @@
sodipodi:nodetypes="cczc"
inkscape:connector-curvature="0"
id="path4315"
- d="m 615.5,359.5 5,0 c 0,0 -0.5,-2 -2.5,-2 -2,0 -2.5,2 -2.5,2 z"
+ d="m 615.5,359.5 h 5 c 0,0 -0.5,-2 -2.5,-2 -2,0 -2.5,2 -2.5,2 z"
style="fill-opacity:1" />
</g>
</g>
<g
id="src/plugins/android/images/androiddevicesmall"
- transform="translate(64,0)">
- <rect
- id="rect5759-5-9-0-8-6"
- height="16"
- width="16"
- y="363"
- x="570"
- style="fill:#ffffff" />
+ transform="translate(-246,-26)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-0"
+ width="100%"
+ height="100%"
+ transform="translate(586,-73)" />
<use
x="0"
y="0"
@@ -7822,27 +7958,29 @@
x="577"
y="376" />
<path
- style="fill:#000000;fill-opacity:1.0"
- d="m 642,367.5 c -1,0 -1,1.25 -1,1.25 l 2,0 c 0,0 0,-1.25 -1,-1.25 z m -2,1.5 0,2 0.75,0 0,-2 -0.75,0 z m 1,0 0,2 2,0 0,-2 -2,0 z m 2.25,0 0,2 0.75,0 0,-2 -0.75,0 z m -2.25,2.25 0,1.75 2,0 0,-1.75 -2,0 z"
- transform="translate(-64,0)"
+ style="fill:#000000;fill-opacity:1"
+ d="m 642,367.5 c -1,0 -1,1.25 -1,1.25 h 2 c 0,0 0,-1.25 -1,-1.25 z m -2,1.5 v 2 h 0.75 v -2 z m 1,0 v 2 h 2 v -2 z m 2.25,0 v 2 H 644 v -2 z M 641,371.25 V 373 h 2 v -1.75 z"
+ transform="translate(-64)"
id="path5131"
inkscape:connector-curvature="0" />
</g>
<g
- transform="translate(-286,-205)"
+ transform="translate(-503,-249)"
style="display:inline"
id="src/plugins/projectexplorer/images/devicestatusindicator">
- <rect
- id="rect6782-96-9-2"
- height="32"
- width="32"
- y="552"
- x="936"
- style="fill:#ffffff" />
+ <use
+ transform="translate(894,512)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-11-2"
+ width="100%"
+ height="100%" />
<circle
style="fill:#000000"
id="path4864-5"
- cx="961.5"
+ cx="962.5"
cy="577.5"
r="5.5" />
</g>
@@ -8029,34 +8167,36 @@
style="fill:#0dbf0d;fill-opacity:1" />
</g>
<g
- transform="translate(-48,32)"
+ transform="translate(-194,-42)"
id="src/plugins/baremetal/images/baremetaldevice">
- <rect
- style="fill:#ffffff"
- x="554"
- y="347"
- width="32"
- height="32"
- id="rect5230-4-4" />
+ <use
+ transform="translate(513,305)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-1"
+ width="100%"
+ height="100%" />
<path
style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-opacity:1"
- d="m 563.5,354.5 13,0 2,2 0,13 -2,2 -13,0 -2,-2 0,-13 z"
+ d="m 564.5,351.5 h 13 l 2,2 v 13 l -2,2 h -13 l -2,-2 v -13 z"
id="rect5155"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<circle
style="fill:#000000"
id="path5159"
- cx="565"
- cy="368"
+ cx="566"
+ cy="365"
r="1.5" />
<g
id="g5189"
- transform="translate(-0.5,-1)">
+ transform="translate(0.5,-4)">
<path
id="path5432-0"
style="color:#000000"
- d="m 565.5,352 1,0 0,3 -1,0 z m 3,0 1,0 0,3 -1,0 z m 3,0 1,0 0,3 -1,0 z m 3,0 1,0 0,3 -1,0 z"
+ d="m 565.5,352 h 1 v 3 h -1 z m 3,0 h 1 v 3 h -1 z m 3,0 h 1 v 3 h -1 z m 3,0 h 1 v 3 h -1 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccccc" />
</g>
@@ -8065,7 +8205,7 @@
y="0"
xlink:href="#g5189"
id="use5200"
- transform="matrix(1,0,0,-1,0,726)"
+ transform="matrix(1,0,0,-1,0,720)"
width="100%"
height="100%" />
<use
@@ -8073,7 +8213,7 @@
y="0"
xlink:href="#g5189"
id="use5202"
- transform="matrix(0,1,-1,0,933,-207)"
+ transform="rotate(90,571,360)"
width="100%"
height="100%" />
<use
@@ -8081,36 +8221,37 @@
y="0"
xlink:href="#g5189"
id="use5204"
- transform="matrix(0,-1,1,0,207,933)"
+ transform="rotate(-90,571,360)"
width="100%"
height="100%" />
<path
id="rect5208-6-6"
style="fill:#000000"
- d="m 565,363 7,0 0,1 -7,0 z m 0,-2 6,0 0,1 -6,0 z m 0,-3 10,0 0,2 -10,0 z"
+ d="m 566,360 h 7 v 1 h -7 z m 0,-2 h 6 v 1 h -6 z m 0,-3 h 10 v 2 h -10 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccc" />
</g>
<g
id="src/plugins/baremetal/images/baremetaldevicesmall"
- transform="translate(-32,32)">
- <rect
- id="rect5759-5-9-0-8-6-4"
- height="16"
- width="16"
- y="363"
- x="570"
- style="fill:#ffffff" />
+ transform="translate(-210,-26)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-7"
+ width="100%"
+ height="100%"
+ transform="translate(586,-73)" />
<path
style="fill:#999999;fill-opacity:1;stroke:#000000;stroke-width:0.5"
- d="m 575.5,367.25 6,0 1.25,1.25 0,6 -1.25,1.25 -6,0 -1.25,-1.25 0,-6 z"
+ d="m 575.5,367.25 h 6 l 1.25,1.25 v 6 l -1.25,1.25 h -6 l -1.25,-1.25 v -6 z"
id="rect5492"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
id="rect5494-5"
style="fill:#4d4d4d"
- d="m 580,365 1,0 0,2 -1,0 z m -2,0 1,0 0,2 -1,0 z m -2,0 1,0 0,2 -1,0 z"
+ d="m 580,365 h 1 v 2 h -1 z m -2,0 h 1 v 2 h -1 z m -2,0 h 1 v 2 h -1 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccscc" />
<use
@@ -8118,7 +8259,7 @@
y="0"
xlink:href="#rect5494-5"
id="use5529"
- transform="matrix(0,1,-1,0,950,-207)"
+ transform="rotate(90,578.5,371.5)"
width="100%"
height="100%" />
<use
@@ -8134,7 +8275,7 @@
y="0"
xlink:href="#rect5494-5"
id="use5533"
- transform="matrix(0,-1,1,0,207,950)"
+ transform="rotate(-90,578.5,371.5)"
width="100%"
height="100%" />
<circle
@@ -8146,66 +8287,69 @@
<path
id="rect5535-8"
style="fill:#000000;fill-opacity:1"
- d="m 576,371 4,0 0,0.5 -4,0 z m 0,-2 5,0 0,0.5 -5,0 z"
+ d="m 576,371 h 4 v 0.5 h -4 z m 0,-2 h 5 v 0.5 h -5 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g>
<g
- transform="translate(6.25,362.5)"
+ transform="translate(-247.75,309.5)"
id="src/boot2qtdevice">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="499.75"
- y="48.5"
- width="32"
- height="32"
- id="rect5759-5-9-0-5" />
+ <use
+ transform="translate(458.75,6.5)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-74"
+ width="100%"
+ height="100%" />
<rect
style="fill:#555555"
id="rect6230"
width="30"
height="20"
- x="500.75"
- y="53.5" />
+ x="501.75"
+ y="50.5" />
<path
id="path7535"
style="fill:#b3b3b3;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 522.75,58.5 3,0 0,3 -3,0 z m 0,5 3,0 0,1 -3,0 z m 0,2 3,0 0,1 -3,0 z m 4,-2 3,0 0,1 -3,0 z m 0,2 3,0 0,1 -3,0 z m -1,4.5 c 0,0.828427 -0.67157,1.5 -1.5,1.5 -0.82843,0 -1.5,-0.671573 -1.5,-1.5 0,-0.828427 0.67157,-1.5 1.5,-1.5 0.82843,0 1.5,0.671573 1.5,1.5 z m -17,-0.5 3,0 0,3.5 -3,0 z m 4,1 3,0 0,2.5 -3,0 z m 17.5,-12 0,3 -3.5,0 0,-3 z"
+ d="m 523.75,55.5 h 3 v 3 h -3 z m 0,5 h 3 v 1 h -3 z m 0,2 h 3 v 1 h -3 z m 4,-2 h 3 v 1 h -3 z m 0,2 h 3 v 1 h -3 z m -1,4.5 c 0,0.828427 -0.67157,1.5 -1.5,1.5 -0.82843,0 -1.5,-0.671573 -1.5,-1.5 0,-0.828427 0.67157,-1.5 1.5,-1.5 0.82843,0 1.5,0.671573 1.5,1.5 z m -17,-0.5 h 3 V 70 h -3 z m 4,1 h 3 V 70 h -3 z m 17.5,-12 v 3 h -3.5 v -3 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccccccccccsssssccccccccccccccc" />
<path
inkscape:connector-curvature="0"
style="fill:#b3b3b3;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 520.75,68.5 -18,0 0,-12 18,0 z"
+ d="m 521.75,65.5 h -18 v -12 h 18 z"
id="rect5261-2-0"
sodipodi:nodetypes="ccccc" />
<g
id="boottoqtscreen"
- bottoqtscreen="">
+ bottoqtscreen=""
+ transform="translate(1,-3)">
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="use7459-1-0-9-4"
- d="m 505.75,67.5 10,0 2,-2 0,-8 -10,0 -2,2 z"
+ d="m 505.75,67.5 h 10 l 2,-2 v -8 h -10 l -2,2 z"
style="fill:#000000;fill-opacity:1" />
<path
id="path4482-08"
style="fill:#ffffff;fill-opacity:1"
- d="m 514.75034,61.49797 0,2.06092 c 0,0.3626 0.0286,0.6013 0.0811,0.7205 0.0525,0.1193 0.14667,0.1766 0.3614,0.1766 l 0.72529,-0.029 0.0429,0.773 c -0.39605,0.076 -0.69666,0.1145 -0.90661,0.1145 -0.50103,0 -0.84458,-0.1145 -1.03068,-0.3435 -0.18609,-0.2291 -0.28153,-0.6633 -0.28153,-1.3027 l 0,-2.16592 -0.99227,0 0,-1.00235 0.99705,0 0.003,-1.00002 1,0 3.4e-4,1.00002 0.99967,-2e-5 0,0.99765 z m -4.99647,3.84385 c -0.74662,0 -1.26886,-0.2316 -1.56286,-0.69479 C 507.897,64.18374 507.75,63.44871 507.75,62.45099 c 0,-1.00219 0.15087,-1.74609 0.44874,-2.23159 0.29788,-0.48551 0.82012,-0.73046 1.55513,-0.73046 0.73888,0 1.25725,0.24047 1.55126,0.72597 0.29787,0.48112 0.44487,1.22502 0.44487,2.2317 0,0.66361 -0.0619,1.19813 -0.18182,1.60345 -0.12379,0.4099 -0.32108,0.72168 -0.59961,0.93545 l 0.69187,1.26167 -0.73888,0.39645 -0.72669,-1.35082 c -0.0928,0.0364 -0.23984,0.0495 -0.441,0.0495 z m -0.9323,-1.28728 c 0.16247,0.32066 0.47582,0.48551 0.93617,0.48551 0.46035,0 0.76982,-0.16028 0.9323,-0.47655 0.15861,-0.31626 0.15145,-0.85526 0.15145,-1.60803 0,-0.75724 0.007,-1.30511 -0.15919,-1.64807 -0.16634,-0.34306 -0.47195,-0.42391 -0.92456,-0.42391 -0.44875,0 -0.75822,0.0808 -0.92844,0.42391 -0.16634,0.34296 -0.16306,0.88644 -0.16306,1.63921 0,0.74828 -0.007,1.28728 0.15533,1.60793 z"
+ d="m 514.75034,61.49797 v 2.06092 c 0,0.3626 0.0286,0.6013 0.0811,0.7205 0.0525,0.1193 0.14667,0.1766 0.3614,0.1766 l 0.72529,-0.029 0.0429,0.773 c -0.39605,0.076 -0.69666,0.1145 -0.90661,0.1145 -0.50103,0 -0.84458,-0.1145 -1.03068,-0.3435 -0.18609,-0.2291 -0.28153,-0.6633 -0.28153,-1.3027 v -2.16592 h -0.99227 v -1.00235 h 0.99705 l 0.003,-1.00002 h 1 l 3.4e-4,1.00002 0.99967,-2e-5 v 0.99765 z m -4.99647,3.84385 c -0.74662,0 -1.26886,-0.2316 -1.56286,-0.69479 C 507.897,64.18374 507.75,63.44871 507.75,62.45099 c 0,-1.00219 0.15087,-1.74609 0.44874,-2.23159 0.29788,-0.48551 0.82012,-0.73046 1.55513,-0.73046 0.73888,0 1.25725,0.24047 1.55126,0.72597 0.29787,0.48112 0.44487,1.22502 0.44487,2.2317 0,0.66361 -0.0619,1.19813 -0.18182,1.60345 -0.12379,0.4099 -0.32108,0.72168 -0.59961,0.93545 l 0.69187,1.26167 -0.73888,0.39645 -0.72669,-1.35082 c -0.0928,0.0364 -0.23984,0.0495 -0.441,0.0495 z m -0.9323,-1.28728 c 0.16247,0.32066 0.47582,0.48551 0.93617,0.48551 0.46035,0 0.76982,-0.16028 0.9323,-0.47655 0.15861,-0.31626 0.15145,-0.85526 0.15145,-1.60803 0,-0.75724 0.007,-1.30511 -0.15919,-1.64807 -0.16634,-0.34306 -0.47195,-0.42391 -0.92456,-0.42391 -0.44875,0 -0.75822,0.0808 -0.92844,0.42391 -0.16634,0.34296 -0.16306,0.88644 -0.16306,1.63921 0,0.74828 -0.007,1.28728 0.15533,1.60793 z"
inkscape:connector-curvature="0" />
</g>
<circle
style="fill:#ffffff"
id="path6232"
- cx="502.25"
- cy="55"
+ cx="503.25"
+ cy="52"
r="0.75" />
<use
x="0"
y="0"
xlink:href="#path6232"
id="use6261"
- transform="translate(27,0)"
+ transform="translate(27)"
width="100%"
height="100%" />
<use
@@ -8225,38 +8369,40 @@
width="100%"
height="100%" />
<path
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 508.75,73.5 1,1.5 0,1.5 1,0 0,-1.5 1,-1.5 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 509.75,70.5 1,1.5 v 1.5 h 1 V 72 l 1,-1.5 z"
id="path5336"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<rect
- style="fill:url(#linearGradient5346);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:url(#linearGradient9824);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="devicecable"
width="1"
- height="3"
- x="509.75"
- y="76.5"
+ height="2"
+ x="510.75"
+ y="73.5"
inkscape:label="#rect5338" />
</g>
<g
id="src/boot2qtdevicesmall"
- transform="translate(-32,64)">
- <rect
- id="rect5759-5-9-0-8-6-4-8"
- height="16"
- width="16"
- y="363"
- x="570"
- style="fill:#ffffff" />
+ transform="translate(-318,27)">
<use
- transform="translate(64.25,299)"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-39"
+ width="100%"
+ height="100%"
+ transform="translate(586,-73)" />
+ <use
+ transform="matrix(1,0,0,1.25,63.25,283.625)"
x="0"
y="0"
xlink:href="#devicecable"
id="use5375"
width="100%"
- height="100%" />
+ height="100%"
+ style="stroke-width:0.89442718" />
<rect
style="fill:#333333"
id="rect5347"
@@ -8267,7 +8413,7 @@
<path
id="rect5404-4-2-3"
style="fill:#b3b3b3"
- d="m 584,373 0,2 -1,0 0,-2 z m 0,-2 0,0.5 -1,0 0,-0.5 z m 0,-1 0,0.5 -1,0 0,-0.5 z m 0,-1 0,0.5 -1,0 0,-0.5 z m 0,-3 0,2 -1,0 0,-2 z m -6,9 3,0 0,0.5 -3,0 z m -5,0 3,0 0,0.5 -3,0 z m -1,-9 10,0 0,8 -10,0 z"
+ d="m 584,373 v 2 h -1 v -2 z m 0,-2 v 0.5 h -1 V 371 Z m 0,-1 v 0.5 h -1 V 370 Z m 0,-1 v 0.5 h -1 V 369 Z m 0,-3 v 2 h -1 v -2 z m -6,9 h 3 v 0.5 h -3 z m -5,0 h 3 v 0.5 h -3 z m -1,-9 h 10 v 8 h -10 z"
inkscape:connector-curvature="0" />
<g
id="boottoqtscreensmall">
@@ -8275,11 +8421,11 @@
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5089-53"
- d="m 581,371.5 -1.5,1.5 -6.5,0 0,-4.5 1.5,-1.5 6.5,0 z"
+ d="m 581,371.5 -1.5,1.5 H 573 v -4.5 l 1.5,-1.5 h 6.5 z"
style="fill:#000000;fill-opacity:1" />
<path
id="path4957-9"
- d="m 577.5,369.5 2.5,0 m -1.48438,-1.54688 -0.0227,2.94133 c 0.002,0.96521 0.83838,0.77673 1.50706,0.60555 m -3.69064,0 1.19887,1.38951 M 575.5,368.5 c 1,0 1,0.28518 1,1.5 0,1.21481 0,1.5 -1,1.5 -1,0 -1,-0.30273 -1,-1.5 0,-1.19726 0,-1.5 1,-1.5 z"
+ d="m 577.5,369.5 h 2.5 m -1.48438,-1.54688 -0.0227,2.94133 c 0.002,0.96521 0.83838,0.77673 1.50706,0.60555 m -3.69064,0 1.19887,1.38951 M 575.5,368.5 c 1,0 1,0.28518 1,1.5 0,1.21481 0,1.5 -1,1.5 -1,0 -1,-0.30273 -1,-1.5 0,-1.19726 0,-1.5 1,-1.5 z"
inkscape:connector-curvature="0"
style="fill:none;stroke:#ffffff;stroke-width:0.89999998" />
</g>
@@ -8295,7 +8441,7 @@
y="0"
xlink:href="#rect5349"
id="use5495"
- transform="translate(12.5,0)"
+ transform="translate(12.5)"
width="100%"
height="100%" />
<use
@@ -8316,26 +8462,28 @@
height="100%" />
</g>
<g
- transform="translate(6.25,394.5)"
+ transform="translate(-211.75,309.5)"
id="src/boot2qtemulator">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="499.75"
- y="48.5"
- width="32"
- height="32"
- id="rect5759-5-9-0-5-2" />
+ <use
+ transform="translate(458.75,6.5)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-74-0"
+ width="100%"
+ height="100%" />
<rect
style="fill:#000000;fill-opacity:1"
id="rect7751"
width="16"
height="16"
- x="500.75"
- y="56.5" />
+ x="501.75"
+ y="53.5" />
<path
id="rect7756"
style="fill:#b3b3b3"
- d="m 514.75,57.5 1,0 0,1 -1,0 z m -4,0 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z m -11,2 14,0 0,12 -14,0 z"
+ d="m 515.75,54.5 h 1 v 1 h -1 z m -4,0 h 1 v 1 h -1 z m 2,0 h 1 v 1 h -1 z m -11,2 h 14 v 12 h -14 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccscc" />
<use
@@ -8348,7 +8496,7 @@
height="100%" />
<g
id="g7856"
- transform="translate(1,0)">
+ transform="translate(2,-3)">
<rect
y="54.5"
x="516.75"
@@ -8359,7 +8507,7 @@
<path
id="rect5261-2-0-1-9-5"
style="fill:#b3b3b3"
- d="m 528.75,74.5 -11,0 0,-6.5 11,0 z m 0,-7 -11,0 0,-6.5 11,0 z m 0,-7 -11,0 0,-3 11,0 z m -5,-5 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z"
+ d="m 528.75,74.5 h -11 V 68 h 11 z m 0,-7 h -11 V 61 h 11 z m 0,-7 h -11 v -3 h 11 z m -5,-5 h 1 v 1 h -1 z m 2,0 h 1 v 1 h -1 z m 2,0 h 1 v 1 h -1 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
</g>
@@ -8367,19 +8515,20 @@
inkscape:connector-curvature="0"
id="rect7899-2-7-1-7"
style="fill:#333333"
- d="m 524.75,71.5 4,0 0,1 -4,0 z m -5,0 4,0 0,1 -4,0 z m 5,-2 4,0 0,1 -4,0 z m -3,0 2,0 0,1 -2,0 z m 3,-5 4,0 0,1 -4,0 z m -3,0 2,0 0,1 -2,0 z m 3,-2 4,0 0,1 -4,0 z m -5,0 4,0 0,1 -4,0 z m 5,-4 4,0 0,1 -4,0 z m -4,0 3,0 0,1 -3,0 z"
+ d="m 525.75,68.5 h 4 v 1 h -4 z m -5,0 h 4 v 1 h -4 z m 5,-2 h 4 v 1 h -4 z m -3,0 h 2 v 1 h -2 z m 3,-5 h 4 v 1 h -4 z m -3,0 h 2 v 1 h -2 z m 3,-2 h 4 v 1 h -4 z m -5,0 h 4 v 1 h -4 z m 5,-4 h 4 v 1 h -4 z m -4,0 h 3 v 1 h -3 z"
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccc" />
</g>
<g
id="src/boot2qtemulatorsmall"
- transform="translate(-32,96)">
- <rect
- id="rect5759-5-9-0-8-6-4-8-7"
- height="16"
- width="16"
- y="363"
- x="570"
- style="fill:#ffffff" />
+ transform="translate(-282,27)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-6"
+ width="100%"
+ height="100%"
+ transform="translate(586,-73)" />
<rect
style="fill:#000000;fill-opacity:1"
id="rect7751-2"
@@ -8390,7 +8539,7 @@
<path
id="rect7756-5"
style="fill:#b3b3b3"
- d="m 582,366 1,0 0,1 -1,0 z m -4,0 1,0 0,1 -1,0 z m 2,0 1,0 0,1 -1,0 z m -7,2 10,0 0,8 -10,0 z"
+ d="m 582,366 h 1 v 1 h -1 z m -4,0 h 1 v 1 h -1 z m 2,0 h 1 v 1 h -1 z m -7,2 h 10 v 8 h -10 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccscc" />
<use
@@ -8403,15 +8552,17 @@
height="100%" />
</g>
<g
- transform="translate(-25.75,394.5)"
+ transform="translate(-175.75,309.5)"
id="src/boot2qtstartvm">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="499.75"
- y="48.5"
- width="32"
- height="32"
- id="rect5759-5-9-0-5-2-7" />
+ <use
+ transform="translate(458.75,6.5)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-74-6"
+ width="100%"
+ height="100%" />
<use
x="0"
y="0"
@@ -8425,17 +8576,19 @@
id="rect8268-8"
width="21"
height="17"
- x="507.25"
- y="58"
- rx="2" />
+ x="508.25"
+ y="55"
+ rx="2"
+ ry="2" />
<rect
style="fill:#b3b3b3;fill-opacity:1;stroke:#000000"
id="rect8268"
width="21"
height="17"
- x="507.25"
- y="58"
- rx="2" />
+ x="508.25"
+ y="55"
+ rx="2"
+ ry="2" />
<use
transform="translate(6,4)"
x="0"
@@ -8446,34 +8599,37 @@
height="100%" />
</g>
<g
- transform="translate(54.25,362.5)"
+ transform="translate(-139.75,310.5)"
id="src/vxworksqtdevice">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="499.75"
- y="48.5"
- width="32"
- height="32"
- id="rect5759-5-9-0-5-9" />
+ <use
+ transform="translate(458.75,5.5)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-74-5"
+ width="100%"
+ height="100%" />
<path
style="fill:#000000"
- d="M 521.18792,71.036287 523.69993,75.5 518.68,75.5 Z M 502.39828,53.5 l 8.75116,0 8.36478,14.341164 -4.39783,7.401968 z m 14.5378,4.930014 2.79243,-4.930014 8.49821,0 -7.09801,12.136563 z"
+ d="M 522.18792,67.036287 524.69993,71.5 H 519.68 Z M 503.39828,49.5 h 8.75116 l 8.36478,14.341164 -4.39783,7.401968 z m 14.5378,4.930014 L 520.72851,49.5 h 8.49821 l -7.09801,12.136563 z"
id="vxworxkslogo"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccc" />
</g>
<g
id="src/vxworksdevicesmall"
- transform="translate(16,64)">
- <rect
- id="rect5759-5-9-0-8-6-4-8-8"
- height="16"
- width="16"
- y="363"
- x="570"
- style="fill:#ffffff;fill-opacity:1" />
+ transform="translate(-210,27)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-1"
+ width="100%"
+ height="100%"
+ transform="translate(586,-73)" />
<use
- transform="matrix(0.54545415,0,0,0.54545415,297.22355,335.8182)"
+ transform="matrix(0.54545415,0,0,0.54545415,296.67809,338.00004)"
x="0"
y="0"
xlink:href="#vxworxkslogo"
@@ -8482,35 +8638,83 @@
height="100%" />
</g>
<g
- id="src/plugins/winrt/images/winrtdevice">
- <rect
- style="display:inline;fill:#ffffff;fill-opacity:1"
- x="602"
- y="379"
- width="32"
- height="32"
- id="rect5759-5-9-0-5-9-1" />
+ transform="translate(-103.75,310.5)"
+ id="src/plugins/qnx/images/qnxdevice">
+ <use
+ transform="translate(458.75,5.5)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-74-5-1"
+ width="100%"
+ height="100%" />
+ <path
+ id="blackberry"
+ d="m 515.06297,73.5 h -3.15014 l 0.85972,-4 h 3.02638 c 1.96151,0 2.4261,1.015671 2.4261,1.774073 0,1.070118 -0.69797,2.225927 -3.16206,2.225927 m 8.5136,-2.5 h -3.14687 l 0.85972,-4 h 3.01986 c 1.9626,0 2.4272,1.116222 2.4272,1.868193 C 526.73648,69.942592 526.0385,71 523.57657,71 M 524.75,65 h -3.14796 l 0.85972,-4 h 3.02313 c 1.95933,0 2.4261,0.940839 2.4261,1.69602 0,1.071189 -0.70123,2.30398 -3.16099,2.30398 m -8.51252,2.577828 h -3.15556 L 513.94164,63.5 h 3.02855 c 1.95826,0 2.42502,0.843508 2.42502,1.6019 0,1.070119 -0.69907,2.475928 -3.15773,2.475928 m -8.14671,0 h -3.14796 L 505.80035,63.5 h 3.02205 c 1.96259,0 2.42936,0.843508 2.42936,1.6019 0,1.070119 -0.70015,2.475928 -3.16099,2.475928 M 517.32516,61.5 h -3.15123 l 0.85864,-4 h 3.02855 c 1.95934,0 2.42285,0.917706 2.42285,1.672896 0,1.071189 -0.69906,2.327104 -3.15881,2.327104 m -8.14237,0 h -3.14905 l 0.85972,-4 h 3.01879 c 1.96368,0 2.43153,0.917706 2.43153,1.672896 0,1.071189 -0.70124,2.327104 -3.16099,2.327104"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccssccccssccccssccccssccccssccccssccccssc" />
+ <path
+ id="path3909-9"
+ d="m 521.75,54.500748 v -4.981742 l 2.95707,2.459226 z M 511.18081,52.065359 510.83284,51.5 h -2.78812 l 2.03148,1.617477 c -0.49426,0.153392 -1.12523,0.430859 -1.70723,0.430859 -0.71452,0 -1.92399,-0.321794 -2.38436,-0.578386 -0.44254,-0.247107 -0.44462,-0.651625 -0.44462,-1.022467 0,-0.370476 7.9e-4,-0.847848 0.44462,-1.094219 0.46037,-0.256625 1.67019,-0.500015 2.38436,-0.500015 0.71381,0 1.91697,0.257662 2.38435,0.500015 0.48868,0.253328 0.42749,1.212098 0.42749,1.212098 M 530.25,49.481268 h -2.62516 l -1.60552,1.351125 -1.60487,-1.351125 H 519.75 v 3.382879 l -3.6299,-3.382879 -2.3701,-2.74e-4 v 4.132984 l -1.19187,-0.506386 c 0.11364,-0.389513 0.11671,-0.813799 0.11671,-1.160112 0,-0.662977 -0.003,-1.685442 -0.79489,-2.126935 -0.82355,-0.458699 -2.23406,-0.56523 -3.51098,-0.56523 -1.27696,0 -2.91534,0.106531 -3.73927,0.56523 -0.79209,0.441493 -0.79455,1.463958 -0.79455,2.126935 0,0.662974 0.004,1.614423 0.79455,2.054816 0.82428,0.460535 2.46128,0.522414 3.73927,0.522414 1.07454,0 2.40078,-0.03221 3.28657,-0.329489 l 0.4964,0.304032 h 3.26835 v -3.40328 l 3.82072,3.40328 h 5.18083 l 1.59748,-1.375555 1.59786,1.375555 h 2.62516 l -2.91041,-2.521021 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccscscsccccccccccccscscscsccccccccccc" />
+ </g>
+ <g
+ id="src/plugins/qnx/images/qnxdevicesmall"
+ transform="translate(-174,27)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-1-3"
+ width="100%"
+ height="100%"
+ transform="translate(586,-73)" />
+ <use
+ transform="matrix(0.60951707,0,0,0.80579423,263.28972,318.71157)"
+ x="0"
+ y="0"
+ xlink:href="#blackberry"
+ id="use1449"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ id="src/plugins/winrt/images/winrtdevice"
+ transform="translate(-206,-74)">
+ <use
+ transform="translate(561,337)"
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect_32_28"
+ id="use5913-0-8-1-5-6-8-11"
+ width="100%"
+ height="100%" />
<path
sodipodi:nodetypes="cccccccccccccccccccc"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0"
- d="m 606,394 10,0 0,-10.16502 -10,1.1313 z m 12,-10.3911 0,10.3911 12,0 0,-11.74108 z m 0,22.75938 12,1.34794 0,-11.71622 -12,0 z m -12,-1.35943 10,1.12952 0,-10.13837 -10,0 z"
+ d="m 607,391 h 10 v -10.16502 l -10,1.1313 z m 12,-10.3911 V 391 h 12 v -11.74108 z m 0,22.75938 12,1.34794 V 393 h -12 z m -12,-1.35943 10,1.12952 V 393 h -10 z"
id="path5333-0" />
</g>
<g
- id="src/plugins/winrt/images/winrtdevicesmall">
- <rect
- id="rect5759-5-9-0-8-6-4-8-8-5"
- height="16"
- width="16"
- y="395"
- x="634"
- style="fill:#ffffff;fill-opacity:1" />
+ id="src/plugins/winrt/images/winrtdevicesmall"
+ transform="translate(-238,-58)">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#backgroundRect"
+ id="use6054-3"
+ width="100%"
+ height="100%"
+ transform="translate(650,-41)" />
<path
sodipodi:nodetypes="cccccccccccccccccccc"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0"
- d="m 636.00003,403 4.99997,0 0,-4.67861 -4.99997,0.67433 z M 642,398.18129 642,403 l 6.00003,0 0,-5.6287 z m 0,10.72061 6.00003,0.81345 0,-5.71535 L 642,404 Z M 636.00003,408.09093 641,408.7667 641,404 l -4.99997,0 z"
+ d="M 636.00003,403 H 641 v -4.67861 l -4.99997,0.67433 z M 642,398.18129 V 403 h 6.00003 v -5.6287 z m 0,10.72061 6.00003,0.81345 V 404 H 642 Z M 636.00003,408.09093 641,408.7667 V 404 h -4.99997 z"
id="path5333" />
</g>
<g
diff --git a/src/tools/qml2puppet/qml2puppet/qml2puppet.pro b/src/tools/qml2puppet/qml2puppet/qml2puppet.pro
index 9644cf4bca..af8591e8ec 100644
--- a/src/tools/qml2puppet/qml2puppet/qml2puppet.pro
+++ b/src/tools/qml2puppet/qml2puppet/qml2puppet.pro
@@ -1,7 +1,7 @@
TARGET = qml2puppet
TEMPLATE = app
-
+QTC_LIB_DEPENDS += utils
include(../../../../qtcreator.pri)
osx: DESTDIR = $$IDE_LIBEXEC_PATH/qmldesigner
@@ -9,6 +9,7 @@ else: DESTDIR = $$IDE_LIBEXEC_PATH
include(../../../rpath.pri)
+include(../../../libs/qt-breakpad/qtbreakpad.pri)
include(../../../../share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri)
isEmpty(PRECOMPILED_HEADER):PRECOMPILED_HEADER = $$PWD/../../../shared/qtcreator_pch.h
diff --git a/src/tools/qtcrashhandler/qtcrashhandler.pro b/src/tools/qtcrashhandler/qtcrashhandler.pro
index f6ba7590ae..f2a75957d5 100644
--- a/src/tools/qtcrashhandler/qtcrashhandler.pro
+++ b/src/tools/qtcrashhandler/qtcrashhandler.pro
@@ -1,9 +1,6 @@
TARGET = qtcrashhandler
TEMPLATE = app
-QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
-include($${QT_BREAKPAD_ROOT_PATH}/qtcrashhandler.pri)
-include(../../../qtcreator.pri)
-DESTDIR = $$IDE_BIN_PATH
-include(../../rpath.pri)
+include(../../qtcreatortool.pri)
+include(../../libs/qt-breakpad/qtcrashhandler.pri)
diff --git a/src/tools/sdktool/addcmakeoperation.cpp b/src/tools/sdktool/addcmakeoperation.cpp
index d6e6146d75..bddf275c51 100644
--- a/src/tools/sdktool/addcmakeoperation.cpp
+++ b/src/tools/sdktool/addcmakeoperation.cpp
@@ -55,7 +55,7 @@ QString AddCMakeOperation::name() const
QString AddCMakeOperation::helpText() const
{
- return QString("add a cmake tool to Qt Creator");
+ return QString("add a cmake tool");
}
QString AddCMakeOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/adddebuggeroperation.cpp b/src/tools/sdktool/adddebuggeroperation.cpp
index a39af5a71d..6ec0716491 100644
--- a/src/tools/sdktool/adddebuggeroperation.cpp
+++ b/src/tools/sdktool/adddebuggeroperation.cpp
@@ -56,7 +56,7 @@ QString AddDebuggerOperation::name() const
QString AddDebuggerOperation::helpText() const
{
- return QLatin1String("add a debugger to Qt Creator");
+ return QLatin1String("add a debugger");
}
QString AddDebuggerOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/adddeviceoperation.cpp b/src/tools/sdktool/adddeviceoperation.cpp
index 34d0d26455..91eff774cf 100644
--- a/src/tools/sdktool/adddeviceoperation.cpp
+++ b/src/tools/sdktool/adddeviceoperation.cpp
@@ -50,7 +50,7 @@ QString AddDeviceOperation::name() const
QString AddDeviceOperation::helpText() const
{
- return QLatin1String("add a Device to Qt Creator");
+ return QLatin1String("add a Device");
}
QString AddDeviceOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/addkeysoperation.cpp b/src/tools/sdktool/addkeysoperation.cpp
index 8fa6f46556..b7abd5aaca 100644
--- a/src/tools/sdktool/addkeysoperation.cpp
+++ b/src/tools/sdktool/addkeysoperation.cpp
@@ -34,7 +34,7 @@ QString AddKeysOperation::name() const
QString AddKeysOperation::helpText() const
{
- return QLatin1String("add settings to Qt Creator configuration");
+ return QLatin1String("add arbitrary settings to configuration");
}
QString AddKeysOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/addkitoperation.cpp b/src/tools/sdktool/addkitoperation.cpp
index e46945e1a5..e5767be7e8 100644
--- a/src/tools/sdktool/addkitoperation.cpp
+++ b/src/tools/sdktool/addkitoperation.cpp
@@ -78,7 +78,7 @@ QString AddKitOperation::name() const
QString AddKitOperation::helpText() const
{
- return QString("add a Kit to Qt Creator");
+ return QString("add a Kit");
}
QString AddKitOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/addqtoperation.cpp b/src/tools/sdktool/addqtoperation.cpp
index 0039e4217c..59a0b1b555 100644
--- a/src/tools/sdktool/addqtoperation.cpp
+++ b/src/tools/sdktool/addqtoperation.cpp
@@ -63,7 +63,7 @@ QString AddQtOperation::name() const
QString AddQtOperation::helpText() const
{
- return QLatin1String("add a Qt version to Qt Creator");
+ return QLatin1String("add a Qt version");
}
QString AddQtOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/addtoolchainoperation.cpp b/src/tools/sdktool/addtoolchainoperation.cpp
index 60aba4558d..51f98fe555 100644
--- a/src/tools/sdktool/addtoolchainoperation.cpp
+++ b/src/tools/sdktool/addtoolchainoperation.cpp
@@ -61,7 +61,7 @@ QString AddToolChainOperation::name() const
QString AddToolChainOperation::helpText() const
{
- return QString("add a tool chain to Qt Creator");
+ return QString("add a tool chain");
}
QString AddToolChainOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/findkeyoperation.cpp b/src/tools/sdktool/findkeyoperation.cpp
index 1085b20f34..58d3b31ed2 100644
--- a/src/tools/sdktool/findkeyoperation.cpp
+++ b/src/tools/sdktool/findkeyoperation.cpp
@@ -34,7 +34,7 @@ QString FindKeyOperation::name() const
QString FindKeyOperation::helpText() const
{
- return QLatin1String("find a key in the settings of Qt Creator");
+ return QLatin1String("find a key in the settings");
}
QString FindKeyOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/findvalueoperation.cpp b/src/tools/sdktool/findvalueoperation.cpp
index e7d31892f7..e59a0fa115 100644
--- a/src/tools/sdktool/findvalueoperation.cpp
+++ b/src/tools/sdktool/findvalueoperation.cpp
@@ -34,7 +34,7 @@ QString FindValueOperation::name() const
QString FindValueOperation::helpText() const
{
- return QLatin1String("find a value in the settings of Qt Creator");
+ return QLatin1String("find a value in the settings");
}
QString FindValueOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/getoperation.cpp b/src/tools/sdktool/getoperation.cpp
index b43346dd6f..fb15d42142 100644
--- a/src/tools/sdktool/getoperation.cpp
+++ b/src/tools/sdktool/getoperation.cpp
@@ -34,7 +34,7 @@ QString GetOperation::name() const
QString GetOperation::helpText() const
{
- return QLatin1String("get settings from Qt Creator configuration");
+ return QLatin1String("get settings from configuration");
}
QString GetOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/main.cpp b/src/tools/sdktool/main.cpp
index 0e5b4320fa..f480543fbb 100644
--- a/src/tools/sdktool/main.cpp
+++ b/src/tools/sdktool/main.cpp
@@ -45,6 +45,8 @@
#include "rmqtoperation.h"
#include "rmtoolchainoperation.h"
+#include <app/app_version.h>
+
#include <iostream>
#include <QCoreApplication>
@@ -52,7 +54,7 @@
void printHelp(const Operation *op)
{
- std::cout << "Qt Creator SDK setup tool." << std::endl;
+ std::cout << Core::Constants::IDE_DISPLAY_NAME << " SDK setup tool." << std::endl;
std::cout << "Help for operation " << qPrintable(op->name()) << std::endl;
std::cout << std::endl;
@@ -68,7 +70,7 @@ const QString tabular(const Operation *o)
void printHelp(const QList<Operation *> &operations)
{
- std::cout << "Qt Creator SDK setup tool." << std::endl;
+ std::cout << Core::Constants::IDE_DISPLAY_NAME << "SDK setup tool." << std::endl;
std::cout << " Usage: " << qPrintable(QCoreApplication::arguments().at(0))
<< " <ARGS> <OPERATION> <OPERATION_ARGS>" << std::endl << std::endl;
std::cout << "ARGS:" << std::endl;
diff --git a/src/tools/sdktool/rmcmakeoperation.cpp b/src/tools/sdktool/rmcmakeoperation.cpp
index dc41b748c3..2eaf84b9d0 100644
--- a/src/tools/sdktool/rmcmakeoperation.cpp
+++ b/src/tools/sdktool/rmcmakeoperation.cpp
@@ -48,7 +48,7 @@ QString RmCMakeOperation::name() const
QString RmCMakeOperation::helpText() const
{
- return QString("remove a cmake tool from Qt Creator");
+ return QString("remove a cmake tool");
}
QString RmCMakeOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/rmdebuggeroperation.cpp b/src/tools/sdktool/rmdebuggeroperation.cpp
index 129947271a..8c2a6bea0d 100644
--- a/src/tools/sdktool/rmdebuggeroperation.cpp
+++ b/src/tools/sdktool/rmdebuggeroperation.cpp
@@ -53,7 +53,7 @@ QString RmDebuggerOperation::name() const
QString RmDebuggerOperation::helpText() const
{
- return QLatin1String("remove a debugger from Qt Creator");
+ return QLatin1String("remove a debugger");
}
QString RmDebuggerOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/rmdeviceoperation.cpp b/src/tools/sdktool/rmdeviceoperation.cpp
index b678bb07fc..4558352ab3 100644
--- a/src/tools/sdktool/rmdeviceoperation.cpp
+++ b/src/tools/sdktool/rmdeviceoperation.cpp
@@ -39,7 +39,7 @@ QString RmDeviceOperation::name() const
QString RmDeviceOperation::helpText() const
{
- return QLatin1String("remove a Device from Qt Creator");
+ return QLatin1String("remove a Device");
}
QString RmDeviceOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/rmkeysoperation.cpp b/src/tools/sdktool/rmkeysoperation.cpp
index 138506bbb8..ff1f7f8baf 100644
--- a/src/tools/sdktool/rmkeysoperation.cpp
+++ b/src/tools/sdktool/rmkeysoperation.cpp
@@ -34,7 +34,7 @@ QString RmKeysOperation::name() const
QString RmKeysOperation::helpText() const
{
- return QLatin1String("remove settings from Qt Creator configuration");
+ return QLatin1String("remove settings from configuration");
}
QString RmKeysOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/rmkitoperation.cpp b/src/tools/sdktool/rmkitoperation.cpp
index caa4c2f0e0..5abfe9ecdd 100644
--- a/src/tools/sdktool/rmkitoperation.cpp
+++ b/src/tools/sdktool/rmkitoperation.cpp
@@ -57,7 +57,7 @@ QString RmKitOperation::name() const
QString RmKitOperation::helpText() const
{
- return QString("remove a Kit from Qt Creator");
+ return QString("remove a Kit");
}
QString RmKitOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/rmqtoperation.cpp b/src/tools/sdktool/rmqtoperation.cpp
index 50e6e66bfe..292b8fdb3f 100644
--- a/src/tools/sdktool/rmqtoperation.cpp
+++ b/src/tools/sdktool/rmqtoperation.cpp
@@ -47,7 +47,7 @@ QString RmQtOperation::name() const
QString RmQtOperation::helpText() const
{
- return QLatin1String("remove a Qt version from Qt Creator");
+ return QLatin1String("remove a Qt version");
}
QString RmQtOperation::argumentsHelpText() const
diff --git a/src/tools/sdktool/rmtoolchainoperation.cpp b/src/tools/sdktool/rmtoolchainoperation.cpp
index bb1e8d1728..1cefe02060 100644
--- a/src/tools/sdktool/rmtoolchainoperation.cpp
+++ b/src/tools/sdktool/rmtoolchainoperation.cpp
@@ -48,7 +48,7 @@ QString RmToolChainOperation::name() const
QString RmToolChainOperation::helpText() const
{
- return QString("remove a tool chain from Qt Creator");
+ return QString("remove a tool chain");
}
QString RmToolChainOperation::argumentsHelpText() const
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
index cfe34abaa0..23268020b7 100644
--- a/src/tools/tools.pro
+++ b/src/tools/tools.pro
@@ -41,8 +41,7 @@ isEmpty(BUILD_CPLUSPLUS_TOOLS):BUILD_CPLUSPLUS_TOOLS=$$(BUILD_CPLUSPLUS_TOOLS)
cplusplus-update-frontend
}
-QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
-!isEmpty(QT_BREAKPAD_ROOT_PATH) {
+!isEmpty(BREAKPAD_SOURCE_DIR) {
SUBDIRS += qtcrashhandler
} else {
linux-* {
diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp
index 5c565cdc4f..115bdc68a0 100644
--- a/tests/auto/debugger/tst_dumpers.cpp
+++ b/tests/auto/debugger/tst_dumpers.cpp
@@ -671,6 +671,7 @@ struct ForceC {};
struct EigenProfile {};
struct UseDebugImage {};
struct DwarfProfile { explicit DwarfProfile(int v) : version(v) {} int version; };
+struct CoreFoundationProfile {};
struct CoreProfile {};
struct CorePrivateProfile {};
@@ -903,6 +904,19 @@ public:
return *this;
}
+ const Data &operator+(const CoreFoundationProfile &) const
+ {
+ profileExtra +=
+ "CXX_FLAGS += -g -O0\n"
+ "LIBS += -framework CoreFoundation -framework Foundation\n"
+ "CONFIG -= app_bundle qt\n";
+
+ useQt = false;
+ useQHash = false;
+ mainFile = "main.mm";
+ return *this;
+ }
+
const Data &operator+(const ForceC &) const
{
mainFile = "main.c";
@@ -6830,6 +6844,55 @@ void tst_Dumpers::dumper_data()
+ Check("s.storage_.@1.size_", "4", "int");
+ QTest::newRow("Internal4")
+ << Data("template<class T>\n"
+ "struct QtcDumperTest_List\n"
+ "{\n"
+ " struct Node\n"
+ " {\n"
+ " virtual ~Node() {}\n"
+ " Node *prev = nullptr;\n"
+ " Node *next = nullptr;\n"
+ " };\n\n"
+ " QtcDumperTest_List()\n"
+ " {\n"
+ " root.prev = &root;\n"
+ " root.next = &root;\n"
+ " }\n\n"
+ " void insert(Node *n)\n"
+ " {\n"
+ " if (n->next)\n"
+ " return;\n"
+ " Node *r = root.prev;\n"
+ " Node *node = r->next;\n"
+ " n->next = node;\n"
+ " node->prev = n;\n"
+ " r->next = n;\n"
+ " n->prev = r;\n"
+ " }\n"
+ " Node root;\n"
+ "};\n\n"
+ "struct Base\n"
+ "{\n"
+ " virtual ~Base() {}\n"
+ " int foo = 42;\n"
+ "};\n\n"
+ "struct Derived : Base, QtcDumperTest_List<Derived>::Node\n"
+ "{\n"
+ " int baz = 84;\n"
+ "};\n\n",
+ "Derived d1, d2; unused(&d1, &d2);\n"
+ "QtcDumperTest_List<Derived> list; unused(&list);\n"
+ "list.insert(&d1);\n"
+ "list.insert(&d2);\n")
+ + Cxx11Profile()
+ + Check("d1.@1.foo", "42", "int")
+ + Check("d1.baz", "84", "int")
+ + Check("d2.@1.foo", "42", "int")
+ + Check("d2.baz", "84", "int")
+ //+ Check("list.1.baz", "15", "int")
+ ;
+
QTest::newRow("BufArray")
<< Data("#include <new>\n"
"static int c = 0;\n"
@@ -6856,6 +6919,25 @@ void tst_Dumpers::dumper_data()
+ Check("arr.2.baz", "5", "int");
+ QTest::newRow("StringDisplay")
+ << Data("#include <string.h>\n"
+ "struct QtcDumperTest_String"
+ "{\n"
+ " char *first;\n"
+ " const char *second = \"second\";\n"
+ " const char third[6] = \"third\";\n"
+ " QtcDumperTest_String()\n"
+ " {\n"
+ " first = new char[6];\n"
+ " strcpy(first, \"first\");\n"
+ " }\n"
+ " ~QtcDumperTest_String() { delete[] first; }\n"
+ "};\n\n",
+ "QtcDumperTest_String str; unused(&str);\n")
+ + Cxx11Profile()
+ + Check("str", "first, second, third", "QtcDumperTest_String");
+
+
QTest::newRow("UndefinedStaticMembers")
<< Data("struct Foo { int a = 15; static int b; }; \n",
"Foo f; unused(&f);\n")
@@ -6889,6 +6971,40 @@ void tst_Dumpers::dumper_data()
+ Check("p.FlagBit", "", "<Value unavailable error>", "") % CdbEngine;
#endif
+#ifdef Q_OS_MAC
+ QTest::newRow("CFStrings")
+ << Data("#include <CoreFoundation/CoreFoundation.h>\n"
+ "#include <string>\n"
+ "#import <Foundation/Foundation.h>\n",
+ "std::string stdString = \"A std::string\"; (void)stdString;\n\n"
+ "std::string &stdStringReference = stdString; (void)stdStringReference;\n\n"
+ "CFStringRef cfStringRef = CFSTR(\"A cfstringref\"); (void)cfStringRef;\n\n"
+ "NSString *aNSString = (NSString *)cfStringRef; (void)aNSString;\n\n"
+ "NSString *nsString = @\"A nsstring\"; (void)nsString;\n\n"
+
+ "NSURL *nsUrl = [NSURL URLWithString:@\"http://example.com\"];\n"
+ "CFURLRef url = (__bridge CFURLRef)nsUrl; (void)url;\n\n"
+
+ "CFStringRef& cfStringRefReference = cfStringRef; (void)cfStringRefReference;\n"
+ "NSString *&aNSStringReference = aNSString; (void)aNSStringReference;\n"
+ "NSURL *&nsUrlReference = nsUrl; (void)nsUrlReference;\n"
+ "CFURLRef &urlReference = url; (void)urlReference;\n")
+ + CoreFoundationProfile()
+ + Check("stdString", "\"A std::string\"", "std::string")
+ + Check("stdStringReference", "\"A std::string\"", "std::string &")
+ + Check("cfStringRef", "\"A cfstringref\"", "CFStringRef")
+ + Check("aNSString", "\"A cfstringref\"", "__NSCFConstantString *")
+ + Check("nsString", "\"A nsstring\"", "__NSCFConstantString *")
+ + Check("nsUrl", "\"http://example.com\"", "NSURL *")
+ + Check("url", "\"http://example.com\"", "CFURLRef")
+ + Check("cfStringRefReference", "\"A cfstringref\"", "CFStringRef &")
+ + Check("aNSStringReference", "\"A cfstringref\"", "NSString * &")
+ + Check("nsUrlReference", "\"http://example.com\"", "NSURL * &")
+ // FIXME: Fails.
+ // + Check("urlReference", "\"http://example.com\"", "CFURLRef &")
+ ;
+#endif
+
QTest::newRow("ArrayOfFunctionPointers")
<< Data("typedef int (*FP)(int *); \n"
"int func(int *param) { unused(param); return 0; } \n",
diff --git a/tests/auto/environment/tst_environment.cpp b/tests/auto/environment/tst_environment.cpp
index 48fb26c92d..1fc8ae0730 100644
--- a/tests/auto/environment/tst_environment.cpp
+++ b/tests/auto/environment/tst_environment.cpp
@@ -38,6 +38,23 @@ private slots:
void environment_data();
void environment();
+ void environmentSetup_data();
+ void environmentSetup();
+
+ void environmentSetWindows();
+ void environmentSetWindowsFuzzy();
+ void environmentSetUnix();
+
+ void environmentSetNewWindows();
+ void environmentSetNewUnix();
+
+ void environmentUnsetWindows();
+ void environmentUnsetWindowsFuzzy();
+ void environmentUnsetUnix();
+
+ void environmentUnsetUnknownWindows();
+ void environmentUnsetUnknownUnix();
+
private:
Environment env;
};
@@ -98,6 +115,138 @@ void tst_Environment::environment()
QCOMPARE(env.expandVariables(in), out);
}
+void tst_Environment::environmentSetup_data()
+{
+ QTest::addColumn<int>("osType");
+ QTest::addColumn<QStringList>("in");
+ QTest::addColumn<QStringList>("out");
+
+ QTest::newRow("EmptyWin")
+ << static_cast<int>(Utils::OsTypeWindows) << QStringList() << QStringList();
+ QTest::newRow("EmptyLinux")
+ << static_cast<int>(Utils::OsTypeLinux) << QStringList() << QStringList();
+
+ QTest::newRow("SimpleWin")
+ << static_cast<int>(Utils::OsTypeWindows) << QStringList({"Foo=bar"}) << QStringList({"Foo=bar"});
+ QTest::newRow("EmptyLinux")
+ << static_cast<int>(Utils::OsTypeLinux) << QStringList({"Foo=bar"}) << QStringList({"Foo=bar"});
+
+ QTest::newRow("MultiWin")
+ << static_cast<int>(Utils::OsTypeWindows)
+ << QStringList({"Foo=bar", "Hi=HO"}) << QStringList({"Foo=bar", "Hi=HO"});
+ QTest::newRow("MultiLinux")
+ << static_cast<int>(Utils::OsTypeLinux)
+ << QStringList({"Foo=bar", "Hi=HO"}) << QStringList({"Foo=bar", "Hi=HO"});
+
+ QTest::newRow("DuplicateWin")
+ << static_cast<int>(Utils::OsTypeWindows)
+ << QStringList({"Foo=bar", "FOO=HO"}) << QStringList({"Foo=HO"});
+ QTest::newRow("DuplicateLinux")
+ << static_cast<int>(Utils::OsTypeLinux)
+ << QStringList({"Foo=bar", "FOO=HO"}) << QStringList({"FOO=HO", "Foo=bar"});
+}
+
+void tst_Environment::environmentSetup()
+{
+ QFETCH(int, osType);
+ QFETCH(QStringList, in);
+ QFETCH(QStringList, out);
+
+ Environment env(in, static_cast<Utils::OsType>(osType));
+
+ QCOMPARE(env.toStringList(), out);
+}
+
+void tst_Environment::environmentSetWindows()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeWindows);
+
+ env.set("Foo", "baz");
+
+ QCOMPARE(env.toStringList(), QStringList({"Foo=baz", "Hi=HO"}));
+}
+
+void tst_Environment::environmentSetWindowsFuzzy()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeWindows);
+
+ env.set("FOO", "baz");
+
+ QCOMPARE(env.toStringList(), QStringList({"Foo=baz", "Hi=HO"}));
+}
+
+void tst_Environment::environmentSetUnix()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeLinux);
+
+ env.set("Foo", "baz");
+
+ QCOMPARE(env.toStringList(), QStringList({"Foo=baz", "Hi=HO"}));
+}
+
+void tst_Environment::environmentSetNewWindows()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeWindows);
+
+ env.set("bar", "baz");
+
+ QCOMPARE(env.toStringList(), QStringList({"Foo=bar", "Hi=HO", "bar=baz"}));
+}
+
+void tst_Environment::environmentSetNewUnix()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeLinux);
+
+ env.set("bar", "baz");
+
+ QCOMPARE(env.toStringList(), QStringList({"Foo=bar", "Hi=HO", "bar=baz"}));
+}
+
+void tst_Environment::environmentUnsetWindows()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeWindows);
+
+ env.unset("Foo");
+
+ QCOMPARE(env.toStringList(), QStringList({"Hi=HO"}));
+}
+
+void tst_Environment::environmentUnsetWindowsFuzzy()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeWindows);
+
+ env.unset("FOO");
+
+ QCOMPARE(env.toStringList(), QStringList({"Hi=HO"}));
+}
+
+void tst_Environment::environmentUnsetUnix()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeLinux);
+
+ env.unset("Foo");
+
+ QCOMPARE(env.toStringList(), QStringList({"Hi=HO"}));
+}
+
+void tst_Environment::environmentUnsetUnknownWindows()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeWindows);
+
+ env.unset("baz");
+
+ QCOMPARE(env.toStringList(), QStringList({"Foo=bar", "Hi=HO"}));
+}
+
+void tst_Environment::environmentUnsetUnknownUnix()
+{
+ Environment env(QStringList({"Foo=bar", "Hi=HO"}), Utils::OsTypeLinux);
+
+ env.unset("baz");
+
+ QCOMPARE(env.toStringList(), QStringList({"Foo=bar", "Hi=HO"}));
+}
+
QTEST_MAIN(tst_Environment)
#include "tst_environment.moc"
diff --git a/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.pro b/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.pro
new file mode 100644
index 0000000000..74469073f6
--- /dev/null
+++ b/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.pro
@@ -0,0 +1,6 @@
+QTC_LIB_DEPENDS += utils
+include(../../qttest.pri)
+
+DEFINES += QTCREATOR_UTILS_LIB
+
+SOURCES += tst_camelhumpmatcher.cpp
diff --git a/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs b/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs
new file mode 100644
index 0000000000..2ecb08dd98
--- /dev/null
+++ b/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs
@@ -0,0 +1,8 @@
+import qbs
+import "../../autotest.qbs" as Autotest
+
+Autotest {
+ name: "CamelHumpMatcher autotest"
+ Depends { name: "Utils" }
+ files: "tst_camelhumpmatcher.cpp"
+}
diff --git a/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp b/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp
new file mode 100644
index 0000000000..6884ee8d7b
--- /dev/null
+++ b/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp
@@ -0,0 +1,145 @@
+/**************************************************************************
+**
+** Copyright (C) 2017 BlackBerry Limited <qt@blackberry.com>
+** Copyright (C) 2017 Andre Hartmann <aha_1980@gmx.de>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include <utils/camelhumpmatcher.h>
+
+#include <QtTest>
+
+class tst_CamelHumpMatcher : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void camelHumpMatcher();
+ void camelHumpMatcher_data();
+ void highlighting();
+ void highlighting_data();
+};
+
+void tst_CamelHumpMatcher::camelHumpMatcher()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QString, candidate);
+ QFETCH(int, expectedIndex);
+
+ const QRegularExpression regExp = CamelHumpMatcher::createCamelHumpRegExp(pattern);
+ const QRegularExpressionMatch match = regExp.match(candidate);
+ QCOMPARE(match.capturedStart(), expectedIndex);
+}
+
+void tst_CamelHumpMatcher::camelHumpMatcher_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QString>("candidate");
+ QTest::addColumn<int>("expectedIndex");
+
+ QTest::newRow("underscore") << "vl" << "very_long_camel_hump" << 0;
+ QTest::newRow("underscore-uppercase") << "vl" << "VERY_LONG_CAMEL_HUMP" << 0;
+ QTest::newRow("exact") << "VeryLongCamelHump" << "VeryLongCamelHump" << 0;
+ QTest::newRow("prefix-segments") << "velo" << "very_long_Camel_hump" << 0;
+ QTest::newRow("humps") << "vlc" << "VeryLongCamelHump" << 0;
+ QTest::newRow("case-insensitive-humps") << "VlCh" << "VeryLongCamelHump" << 0;
+ QTest::newRow("incorrect-hump") << "vxc" << "VeryLongCamelHump" << -1;
+ QTest::newRow("skipped-hump") << "vc" << "VeryLongCamelHump" << -1;
+ QTest::newRow("middle-humps") << "lc" << "VeryLongCamelHump" << 4;
+ QTest::newRow("incorrect-hump") << "lyn" << "VeryLongCamelHump" << -1;
+ QTest::newRow("humps") << "VL" << "VeryLongCamelHump" << 0;
+ QTest::newRow("skipped-humps-upper") << "VH" << "VeryLongCamelHump" << -1;
+ QTest::newRow("question-wildcard") << "Lon?Ca" << "VeryLongCamelHump" << 4;
+ QTest::newRow("unmatched-question-wildcard") << "Long?Ca" << "VeryLongCamelHump" << -1;
+ QTest::newRow("asterix-wildcard") << "Long*Ca" << "VeryLongCamelHump" << 4;
+ QTest::newRow("empty-asterix-wildcard") << "Lo*Ca" << "VeryLongCamelHump" << 4;
+ QTest::newRow("no-partial") << "NCH" << "LongCamelHump" << -1;
+ QTest::newRow("middle-after-number") << "CH" << "Long1CamelHump" << 5;
+ QTest::newRow("middle-after-underscore") << "CH" << "long_camel_hump" << 5;
+ QTest::newRow("middle-after-underscore-uppercase") << "CH" << "LONG_CAMEL_HUMP" << 5;
+ QTest::newRow("middle-continued") << "cahu" << "LongCamelHump" << 4;
+ QTest::newRow("middle-no-hump") << "window" << "mainwindow.cpp" << 4;
+}
+
+typedef QVector<int> MatchStart;
+typedef QVector<int> MatchLength;
+
+void tst_CamelHumpMatcher::highlighting()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QString, candidate);
+ QFETCH(MatchStart, matchStart);
+ QFETCH(MatchLength, matchLength);
+
+ const QRegularExpression regExp = CamelHumpMatcher::createCamelHumpRegExp(pattern);
+ const QRegularExpressionMatch match = regExp.match(candidate);
+ const CamelHumpMatcher::HighlightingPositions positions =
+ CamelHumpMatcher::highlightingPositions(match);
+
+ QCOMPARE(positions.starts.size(), matchStart.size());
+ for (int i = 0; i < positions.starts.size(); ++i) {
+ QCOMPARE(positions.starts.at(i), matchStart.at(i));
+ QCOMPARE(positions.lengths.at(i), matchLength.at(i));
+ }
+}
+
+void tst_CamelHumpMatcher::highlighting_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QString>("candidate");
+ QTest::addColumn<MatchStart>("matchStart");
+ QTest::addColumn<MatchLength>("matchLength");
+
+ QTest::newRow("prefix-snake") << "very" << "very_long_camel_hump"
+ << MatchStart{0} << MatchLength{4};
+ QTest::newRow("middle-snake") << "long" << "very_long_camel_hump"
+ << MatchStart{5} << MatchLength{4};
+ QTest::newRow("suffix-snake") << "hump" << "very_long_camel_hump"
+ << MatchStart{16} << MatchLength{4};
+ QTest::newRow("prefix-camel") << "very" << "VeryLongCamelHump"
+ << MatchStart{0} << MatchLength{4};
+ QTest::newRow("middle-camel") << "Long" << "VeryLongCamelHump"
+ << MatchStart{4} << MatchLength{4};
+ QTest::newRow("suffix-camel") << "Hump" << "VeryLongCamelHump"
+ << MatchStart{13} << MatchLength{4};
+ QTest::newRow("humps-camel") << "vlch" << "VeryLongCamelHump"
+ << MatchStart{0, 4, 8, 13} << MatchLength{1, 1, 1, 1};
+ QTest::newRow("humps-camel-lower") << "vlch" << "veryLongCamelHump"
+ << MatchStart{0, 4, 8, 13} << MatchLength{1, 1, 1, 1};
+ QTest::newRow("humps-snake") << "vlch" << "very_long_camel_hump"
+ << MatchStart{0, 5, 10, 16} << MatchLength{1, 1, 1, 1};
+ QTest::newRow("humps-middle") << "lc" << "VeryLongCamelHump"
+ << MatchStart{4, 8} << MatchLength{1, 1};
+ QTest::newRow("humps-last") << "h" << "VeryLongCamelHump"
+ << MatchStart{13} << MatchLength{1};
+ QTest::newRow("humps-continued") << "LoCa" << "VeryLongCamelHump"
+ << MatchStart{4, 8} << MatchLength{2, 2};
+ QTest::newRow("wildcard-asterisk") << "Lo*Hu" << "VeryLongCamelHump"
+ << MatchStart{4, 13} << MatchLength{2, 2};
+ QTest::newRow("wildcard-question") << "Lo?g" << "VeryLongCamelHump"
+ << MatchStart{4, 7} << MatchLength{2, 1};
+ QTest::newRow("middle-no-hump") << "window" << "mainwindow.cpp"
+ << MatchStart{4} << MatchLength{6};
+}
+
+QTEST_APPLESS_MAIN(tst_CamelHumpMatcher)
+#include "tst_camelhumpmatcher.moc"
diff --git a/tests/auto/utils/stringutils/tst_stringutils.cpp b/tests/auto/utils/stringutils/tst_stringutils.cpp
index 6fbdfb4326..8e51c89300 100644
--- a/tests/auto/utils/stringutils/tst_stringutils.cpp
+++ b/tests/auto/utils/stringutils/tst_stringutils.cpp
@@ -243,6 +243,18 @@ void tst_StringUtils::testParseUsedPortFromNetstatOutput_data()
QTest::newRow("Mac6") << "tcp6 0 0 *.631 *.* LISTEN" << 631;
QTest::newRow("Mac7") << "udp4 0 0 192.168.79.1.123 *.*" << 123;
QTest::newRow("Mac9") << "udp4 0 0 192.168.8.1.123 *.*" << 123;
+
+ // QNX
+ QTest::newRow("Qnx1") << "Active Internet connections (including servers)" << -1;
+ QTest::newRow("Qnx2") << "Proto Recv-Q Send-Q Local Address Foreign Address State " << -1;
+ QTest::newRow("Qnx3") << "tcp 0 0 10.9.7.5.22 10.9.7.4.46592 ESTABLISHED" << 22;
+ QTest::newRow("Qnx4") << "tcp 0 0 *.8000 *.* LISTEN " << 8000;
+ QTest::newRow("Qnx5") << "tcp 0 0 *.22 *.* LISTEN " << 22;
+ QTest::newRow("Qnx6") << "udp 0 0 *.* *.* " << -1;
+ QTest::newRow("Qnx7") << "udp 0 0 *.* *.* " << -1;
+ QTest::newRow("Qnx8") << "Active Internet6 connections (including servers)" << -1;
+ QTest::newRow("Qnx9") << "Proto Recv-Q Send-Q Local Address Foreign Address (state) " << -1;
+ QTest::newRow("QnxA") << "tcp6 0 0 *.22 *.* LISTEN " << 22;
}
QTEST_MAIN(tst_StringUtils)
diff --git a/tests/auto/utils/utils.pro b/tests/auto/utils/utils.pro
index f5d9e94b00..b5b44098a5 100644
--- a/tests/auto/utils/utils.pro
+++ b/tests/auto/utils/utils.pro
@@ -3,6 +3,7 @@ TEMPLATE = subdirs
SUBDIRS = \
fileutils \
ansiescapecodehandler \
+ camelhumpmatcher \
objectpool \
stringutils \
templateengine \
diff --git a/tests/cpplocators/testdata_basic/file1.cpp b/tests/cpplocators/testdata_basic/file1.cpp
index 98a5375237..5c1e3caff3 100644
--- a/tests/cpplocators/testdata_basic/file1.cpp
+++ b/tests/cpplocators/testdata_basic/file1.cpp
@@ -12,6 +12,10 @@ int myVariable;
int myFunction(bool yesno, int number) {}
+void pointOfService() {}
+int getPosition() { return 0; }
+int positiveNumber() { return 2; }
+
enum MyEnum { V1, V2 };
class MyClass
diff --git a/tests/manual/clang-format-for-qtc/clang-format-for-qtc.pro b/tests/manual/clang-format-for-qtc/clang-format-for-qtc.pro
new file mode 100644
index 0000000000..370c349d4a
--- /dev/null
+++ b/tests/manual/clang-format-for-qtc/clang-format-for-qtc.pro
@@ -0,0 +1,4 @@
+QT -= gui
+CONFIG += c++14 console
+CONFIG -= app_bundle
+SOURCES += test.cpp
diff --git a/tests/manual/clang-format-for-qtc/test.cpp b/tests/manual/clang-format-for-qtc/test.cpp
new file mode 100644
index 0000000000..3edaa85739
--- /dev/null
+++ b/tests/manual/clang-format-for-qtc/test.cpp
@@ -0,0 +1,690 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+//
+// KEEP THIS FILE COMPILABLE TO ENSURE THAT WE TEST AGAINST VALID CODE.
+//
+
+// NOTE: Nice, includes are sorted
+#include <QCoreApplication>
+#include <QFile>
+#include <QLoggingCategory>
+#include <QObject>
+#include <QVector>
+
+#include <functional>
+#include <iostream>
+#include <vector>
+
+static int aGlobalInt = 3;
+
+// -------------------------------------------------------------------------------------------------
+// Preprocessor
+// -------------------------------------------------------------------------------------------------
+
+// NOTE: Ops, preprocessor branches are not indented ("#define" vs "# define")
+#if defined(TEXTEDITOR_LIBRARY)
+#define TEXTEDITOR_EXPORT Q_DECL_EXPORT
+#else
+#define TEXTEDITOR_EXPORT Q_DECL_IMPORT
+#endif
+
+// -------------------------------------------------------------------------------------------------
+// Macros
+// -------------------------------------------------------------------------------------------------
+
+#define QTCREATOR_UTILS_EXPORT
+
+// qtcassert.h:
+namespace Utils {
+QTCREATOR_UTILS_EXPORT void writeAssertLocation(const char *msg);
+}
+
+#define QTC_ASSERT_STRINGIFY_HELPER(x) #x
+#define QTC_ASSERT_STRINGIFY(x) QTC_ASSERT_STRINGIFY_HELPER(x)
+#define QTC_ASSERT_STRING(cond) \
+ ::Utils::writeAssertLocation("\"" cond "\" in file " __FILE__ \
+ ", line " QTC_ASSERT_STRINGIFY(__LINE__))
+
+// NOTE: Ops, macro definitions: are more verbose
+#define QTC_ASSERT(cond, action) \
+ if (cond) { \
+ } else { \
+ QTC_ASSERT_STRING(#cond); \
+ action; \
+ } \
+ do { \
+ } while (0)
+#define QTC_CHECK(cond) \
+ if (cond) { \
+ } else { \
+ QTC_ASSERT_STRING(#cond); \
+ } \
+ do { \
+ } while (0)
+#define QTC_GUARD(cond) ((cond) ? true : (QTC_ASSERT_STRING(#cond), false))
+
+void lala(int foo)
+{
+ Q_UNUSED(foo)
+ Q_UNUSED(foo);
+ QTC_ASSERT(true, return ); // NOTE: Ops, extra space with QTC_ASSERT macro and return keyword
+ QTC_ASSERT(true, return;);
+ while (true)
+ QTC_ASSERT(true, break); // ...but this is fine
+}
+
+// -------------------------------------------------------------------------------------------------
+// Namespaces
+// -------------------------------------------------------------------------------------------------
+
+namespace N {
+namespace C {
+
+struct Foo
+{};
+
+struct Bar
+{};
+
+namespace {
+class ClassInUnnamedNamespace
+{};
+} // namespace
+
+// NOTE: Nice, namespace end comments are added/updated automatically
+} // namespace C
+
+struct Baz
+{};
+
+} // namespace N
+namespace N2 {
+}
+
+// -------------------------------------------------------------------------------------------------
+// Forward declarations
+// -------------------------------------------------------------------------------------------------
+
+// NOTE: Ops, no one-liner anymore: forward declarations within namespace
+namespace N {
+struct Baz;
+}
+
+class SourceLocation;
+class SourceRange;
+class ClangString;
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+QT_FORWARD_DECLARE_CLASS(QTextBlock);
+
+// -------------------------------------------------------------------------------------------------
+// Using declarations, using directives, using alias, typedefs
+// -------------------------------------------------------------------------------------------------
+
+// NOTE: OK, using directives are not sorted
+using namespace std;
+using namespace N2;
+using namespace N;
+
+// NOTE: Nice, using declarations are sorted
+using N::C::Bar;
+using N::C::Foo;
+
+// NOTE: OK, typedefs are not sorted
+typedef N::C::Foo TypedefedFoor;
+typedef N::C::Bar TypedefedBar;
+
+// NOTE: OK, using aliases are not sorted
+using AliasedFoor = N::C::Foo;
+using AliasedBar = N::C::Bar;
+
+// -------------------------------------------------------------------------------------------------
+// Comments
+// -------------------------------------------------------------------------------------------------
+
+// NOTE: OK, reflowing/wrapping of comments is turned off for now.
+// This is a fancy comment that might be reflowed or not or not or not or not or not or not or not or not or not.
+
+// NOTE: Nice, comments after declarations are aligned
+int foo; // fancy comment describing foo
+int superDuperFoo; // fancy comment describing superDuperFoo
+int lalaFoo; // fancy comment describing lalaFoo
+
+// -------------------------------------------------------------------------------------------------
+// Function declarations
+// -------------------------------------------------------------------------------------------------
+
+void f();
+
+void f2() {}
+
+void f3(int parameter1, int parameter2, int parameter3);
+
+// NOTE: Ops, awkward placement of parameter list, there is no equivalent of
+// PenaltyBreakBeforeFirstCallParameter for parameter list
+void f3(
+ int parameter1, int parameter2, int parameter3, int parameter4, int parameter5, int parameter6);
+
+void f3(int parameter1,
+ int parameter2,
+ int parameter3,
+ int parameter4,
+ int parameter5,
+ int parameter6,
+ int parrameter7,
+ int p = aGlobalInt);
+
+bool operator==(N::Baz, N::Baz);
+
+template<class T>
+void fancyTemplateFunction();
+
+template<typename... Type>
+void variadicTemplateFunction(Type *... arg);
+
+// -------------------------------------------------------------------------------------------------
+// Inside functions
+// -------------------------------------------------------------------------------------------------
+
+int myfunction(int parameter1, int parameter2)
+{
+ // Function calls
+ myfunction(parameter1, parameter2);
+
+ // Casts
+ int value = 3;
+ int z = (int) value;
+ int a = static_cast<int>(value + z);
+
+ // Pointer/references alignment
+ int *p = nullptr;
+ int &r = *p;
+
+ // Operators
+ int result = parameter1 + parameter1 + parameter1 + parameter1 + parameter1 + parameter1
+ + parameter1 + parameter1;
+
+ // Long expressions
+ int someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt = -1;
+ bool condition1 = false;
+ bool condition2 = false;
+ // NOTE: Ops, alignment of readable, boolean and complex expressions will be reverted
+ if (condition1 || condition2
+ || someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt) {
+ return value;
+ }
+
+ // Initializer lists
+ vector<int> x{1, 2, 3, 4};
+ vector<Foo> y{{}, {}, {}, {}};
+ new int[3]{1, 2, 3};
+
+ // Streams
+ // NOTE: OK, there is a heuristic (endl, '\n') to wrap statements with stream operators.
+ cout << "Hello" << parameter1 << endl
+ << parameter2 << endl
+ << result << endl
+ << condition1 << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt;
+ cout << "Hello" << parameter1 << '\n'
+ << parameter2 << '\n'
+ << a << '\n'
+ << condition1 << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt;
+ // ...but here not:
+ cout << "Hello" << parameter1 << '\t' << parameter2 << '\t' << z << '\t' << condition1
+ << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt << r;
+
+ return 1;
+}
+
+// -------------------------------------------------------------------------------------------------
+// Ternary Operator
+// -------------------------------------------------------------------------------------------------
+
+bool ternary()
+{
+ bool someWhatLongerName;
+ bool someWhatLongerName2;
+ bool isThatReallyReallyReallyReallyReallyReallyReallyReallyTrue = false;
+ bool isThatReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyTrue = false;
+
+ bool yesno = true ? true : false;
+ bool sino = isThatReallyReallyReallyReallyReallyReallyReallyReallyTrue ? someWhatLongerName
+ : someWhatLongerName2;
+ bool danet = isThatReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyTrue
+ ? someWhatLongerName
+ : someWhatLongerName2;
+
+ return yesno && sino && danet;
+}
+
+// -------------------------------------------------------------------------------------------------
+// Penalty Test
+// -------------------------------------------------------------------------------------------------
+
+int functionToCall(int parameter1)
+{
+ return 1;
+}
+
+int functionToCall(int paramter1, int parameter2)
+{
+ return 1;
+}
+
+int functionToCall(int paramter1, int parameter2, int parameter3)
+{
+ return 1;
+}
+
+int functionToCall(int paramter1, int parameter2, int parameter3, int parameter4, int parameter5)
+{
+ return 1;
+}
+
+int functionToCall(
+ int paramter1, int parameter2, int parameter3, int parameter4, int parameter5, int paramete6)
+{
+ return 1;
+}
+
+int functionToCall(int paramter1,
+ int parameter2,
+ int parameter3,
+ int parameter4,
+ int parameter5,
+ int paramete6,
+ int parameter6)
+{
+ return 1;
+}
+
+bool functionToCallSt(const QString &paramter1, const QStringList &list)
+{
+ return 1;
+}
+
+void emitAddOutput(const QString &text, int priority) {}
+void emitAddOutput(const QString &text, int priority, int category) {}
+
+void penaltyTests(bool isThatTrue)
+{
+ int valueX = 3;
+ int valueY = 1;
+ int valueZ = 1;
+ int valueXTimesY = valueX * valueY;
+ int unbelievableBigValue = 1000000;
+ int unlimitedValueunbelievableBigValue = 1000000;
+ QString arguments;
+ QString argumentsVeryLong;
+
+ const QFile::OpenMode openMode = isThatTrue ? QIODevice::ReadOnly
+ : (QIODevice::ReadOnly | QIODevice::Text);
+
+ const auto someValue10 = functionToCall(valueX, valueY, valueXTimesY);
+ const auto someValue11 = functionToCall(valueX,
+ valueY,
+ valueXTimesY,
+ unbelievableBigValue,
+ unbelievableBigValue);
+ const auto someValue12 = functionToCall(valueX,
+ valueY,
+ valueXTimesY,
+ unbelievableBigValue,
+ unbelievableBigValue * unbelievableBigValue,
+ unbelievableBigValue);
+
+ const auto someValue13 = functionToCall(valueX,
+ valueY,
+ valueXTimesY,
+ unbelievableBigValue,
+ functionToCall(functionToCall(valueX),
+ functionToCall(valueY)),
+ unbelievableBigValue);
+
+ const auto someValue14WithAnOutstandingLongName
+ = functionToCall(valueX,
+ valueY,
+ valueXTimesY,
+ unbelievableBigValue,
+ functionToCall(functionToCall(valueX), functionToCall(valueY)),
+ unbelievableBigValue);
+
+ const bool someValue20 = functionToCall(valueX, valueY, valueXTimesY) || functionToCall(3);
+ const bool someValue21 = functionToCall(valueX, valueY, valueXTimesY)
+ || functionToCall(valueX, valueY);
+
+ emitAddOutput(QCoreApplication::tr("Starting: \"%1\" %2")
+ .arg("/some/very/very/very/very/long/path/to/an/executable", arguments),
+ functionToCall(3),
+ functionToCall(3) | valueX);
+
+ emitAddOutput(QCoreApplication::tr("Starting: \"%1\" %2")
+ .arg("/some/very/very/very/very/long/path/to/an/executable",
+ argumentsVeryLong),
+ functionToCall(3),
+ functionToCall(3) | unlimitedValueunbelievableBigValue
+ | unlimitedValueunbelievableBigValue);
+
+ const QString path;
+ const bool someLongerNameNNNNNNNNNN = functionToCallSt(path,
+ QStringList(QLatin1String("-print-env")));
+}
+
+// -------------------------------------------------------------------------------------------------
+// Classes and member functions
+// -------------------------------------------------------------------------------------------------
+
+class Base1
+{};
+class Base2
+{};
+
+class MyClass : public Base1, public Base2, public QObject
+{
+ Q_OBJECT
+
+public:
+ friend class FriendX; // for X::foo()
+ friend class OtherFriendY; // for Y::bar()
+
+ MyClass() {}
+
+ MyClass(int d1)
+ : data1(d1)
+ {}
+
+ MyClass(int d1, int d2)
+ : data1(d1)
+ , data2(d2)
+ , data3(d2)
+ {}
+
+ MyClass(int initialData1,
+ int initialData2,
+ int initialData3,
+ int initialData4,
+ int initialData5,
+ int initialData6)
+ : data1(initialData1)
+ , data2(initialData2)
+ , data3(initialData3)
+ , data4(initialData4)
+ , data5(initialData5)
+ , data6(initialData6)
+ {
+ // NOTE: Ops, manual alignment of QObject::connect() arguments is reverted
+ // (we tend to write emitter/receiver on separate lines)
+ connect(this, &MyClass::inlineZeroStatements, this, &MyClass::nonInlineSingleStatement);
+ }
+
+ void inlineZeroStatements() {}
+ void inlineSingleStatement() { aGlobalInt = 2; }
+ void inlineMultipleStatements()
+ {
+ aGlobalInt = 2;
+ aGlobalInt = 3;
+ }
+
+ void nonInlineZeroStatements();
+ void nonInlineSingleStatement();
+ void nonInlineMultipleStatements();
+
+ virtual void shortVirtual(int parameter1, int parameter2, int parameter3) = 0;
+
+ // NOTE: Ops, awkward placement of "= 0;"
+ virtual void longerVirtual(
+ int parameter1, int parameter2, int parameter3, int parameter4, int parameter5)
+ = 0;
+
+ int someGetter() const;
+
+private:
+ int data1 = 0;
+ int data2 = 0;
+ int data3 = 0;
+ int data4 = 0;
+ int data5 = 0;
+ int data6 = 0;
+};
+
+void MyClass::nonInlineZeroStatements() {}
+
+void MyClass::nonInlineSingleStatement()
+{
+ aGlobalInt = 2;
+}
+
+void MyClass::nonInlineMultipleStatements()
+{
+ aGlobalInt = 2;
+ aGlobalInt = 2;
+}
+
+template<class T>
+class TemplateClass
+{
+};
+
+// -------------------------------------------------------------------------------------------------
+// Enums
+// -------------------------------------------------------------------------------------------------
+
+// NOTE: OK, enums: one-liner are possible
+enum MyEnum { SourceFiles = 0x1, GeneratedFiles = 0x2, AllFiles = SourceFiles | GeneratedFiles };
+
+// NOTE: OK, enums: a comment breaks one-liners
+enum MyEnumX {
+ OSourceFiles = 0x1 // fancy
+};
+
+// NOTE: OK, enums: longer ones are wrapped
+enum MyOtherEnum {
+ XSourceFiles = 0x1,
+ XGeneratedFiles = 0x2,
+ XAllFiles = XSourceFiles | XGeneratedFiles
+};
+
+enum {
+ Match_None,
+ Match_TooManyArgs,
+ Match_TooFewArgs,
+ Match_Ok
+} matchType
+ = Match_None; // NOTE: Ops, awkward placement of "= value;" at enum definition+use
+
+// -------------------------------------------------------------------------------------------------
+// Lambdas
+// -------------------------------------------------------------------------------------------------
+
+void takeLambda(std::function<int()>) {}
+void takeLambdaWithSomeLongerNameHa(std::function<int()>) {}
+bool UtilsFiltered(QVector<N::Baz>, std::function<int(const N::Baz &)>)
+{
+ return true;
+}
+
+void lambda()
+{
+ auto shortLambda = []() { return 1; };
+ auto longLambda = []() {
+ aGlobalInt = 3;
+ return;
+ };
+
+ takeLambda([]() { return true; });
+ takeLambda([]() {
+ aGlobalInt = 3;
+ return aGlobalInt;
+ });
+
+ // NOTE: Ops, lambda: capture and parameter list should be on separate line
+ int thisCouldBeSomeLongerFunctionCallExpressionOrSoSoSo;
+ takeLambdaWithSomeLongerNameHa(
+ [&]() { return thisCouldBeSomeLongerFunctionCallExpressionOrSoSoSo; });
+
+ QVector<N::Baz> myClasses;
+ UtilsFiltered(myClasses, [](const N::Baz &) { return 1; });
+
+ // NOTE: Ops, lambda: lambda not started on new line in if-condition
+ if (UtilsFiltered(myClasses, [](const N::Baz &) { return 1; })) {
+ ++aGlobalInt;
+ }
+}
+
+// -------------------------------------------------------------------------------------------------
+// Control flow
+// -------------------------------------------------------------------------------------------------
+
+int fn(int, int, int)
+{
+ return 1;
+}
+
+void controlFlow(int x)
+{
+ int y = -1;
+
+ // if
+ if (true)
+ fn(1, 2, 3);
+
+ int value = 3;
+ if (value) {
+ value += value + 1;
+ --value;
+ }
+
+ if (x == y)
+ fn(1, 2, 3);
+ else if (x > y)
+ fn(1, 2, 3);
+ else
+ fn(1, 2, 3);
+
+ if (x == y) {
+ fn(1, 2, 3);
+ return;
+ } else if (x > y) {
+ fn(1, 2, 3);
+ } else {
+ fn(1, 2, 3);
+ }
+
+ // switch
+ switch (x) {
+ case 0:
+ ++aGlobalInt;
+ return;
+ case 1:
+ fn(1, 2, 3);
+ ++aGlobalInt;
+ break;
+ case 2:
+ fn(1, 2, 3);
+ break;
+ default:
+ break;
+ }
+
+ // do-while
+ do {
+ value += value + 1;
+ ++value;
+ } while (true);
+
+ // for
+ QVector<int> myVector;
+ for (int i = 0; i < myVector.size(); ++i)
+ ++aGlobalInt;
+
+ for (QVector<int>::const_iterator i = myVector.begin(); i != myVector.end(); ++i)
+ ++aGlobalInt;
+
+ QVector<int> myVectorWithLongName;
+ for (QVector<int>::const_iterator i = myVectorWithLongName.begin(),
+ ei = myVectorWithLongName.end();
+ i != ei;
+ ++i) {
+ }
+
+ forever {
+ ++aGlobalInt;
+ --aGlobalInt;
+ }
+}
+
+// -------------------------------------------------------------------------------------------------
+// Function declarations and calls - extreme cases
+// -------------------------------------------------------------------------------------------------
+
+void extremeFunction(const char[]) {}
+void extremeFunction(
+ int uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongParameter)
+{
+ extremeFunction(
+ uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongParameter);
+
+ int uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongValue
+ = 3;
+ ++uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongValue;
+
+ extremeFunction(
+ "some super duper super duper super duper super duper super duper super duper super duper long");
+}
+
+void extremeFunction2(int parameter1,
+ int parameter2,
+ int parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLong)
+{
+ extremeFunction2(parameter1,
+ parameter2,
+ parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLong);
+}
+
+void extremeFunction3(int parameter1,
+ int parameter2,
+ int parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLongNameX)
+{
+ extremeFunction3(parameter1,
+ parameter2,
+ parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLongNameX);
+}
+
+// -------------------------------------------------------------------------------------------------
+// Misc
+// -------------------------------------------------------------------------------------------------
+
+static Q_LOGGING_CATEGORY(log, "qtc.cpptools.builtineditordocumentprocessor")
+
+ int hello; // NOTE: Ops, awkward placement of next token after Q_LOGGING_CATEGORY (semicolon helps)
+
+// -------------------------------------------------------------------------------------------------
+
+int main() {}
diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp
index 3bbe0d5520..c4fc3b705b 100644
--- a/tests/manual/debugger/simple/simple_test_app.cpp
+++ b/tests/manual/debugger/simple/simple_test_app.cpp
@@ -2355,7 +2355,7 @@ namespace final {
BREAK_HERE;
// Continue.
- return; // Uncomment.
+ return; // Comment out.
*(int *)0 = a + b;
}
@@ -2364,7 +2364,7 @@ namespace final {
BREAK_HERE;
// Continue.
- return; // Uncomment.
+ return; // Comment out.
testEndlessRecursion(i + 1);
}
@@ -2429,7 +2429,7 @@ namespace final {
// Check pp 21 int &.
// Check qq <null reference> int &.
// Continue.
- return; // Uncomment.
+ return; // Comment out.
testNullReferenceHelper(pp, qq);
dummyStatement(p, q, &i);
}
diff --git a/tests/system/objects.map b/tests/system/objects.map
index e9cd3f8c4a..02020a785f 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -7,7 +7,7 @@
:*Qt Creator.Interrupt_Core::Internal::FancyToolButton {toolTip='Interrupt' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.ProjectSelectorDockWidget_QDockWidget {name='ProjectSelectorDockWidget' type='QDockWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.Run_Core::Internal::FancyToolButton {text='Run' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:*Qt Creator.Start Debugging_Core::Internal::FancyToolButton {toolTip?='Start Debugging *' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:*Qt Creator.Start Debugging_Core::Internal::FancyToolButton {toolTip?='Start Debugging*' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.Widget Box_QDockWidget {name='WidgetBoxDockWidget' type='QDockWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Widget Box'}
:*Qt Creator.findEdit_Utils::FilterLineEdit {name='findEdit' type='Utils::FancyLineEdit' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator_Core::Internal::FancyToolButton {occurrence='3' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
@@ -178,7 +178,7 @@
:QtVersionLabel_KitPage {container=':qt_tabwidget_stackedwidget_QWidget' text='Qt version:' type='QLabel' unnamed='1' visible='1'}
:Remove_QPushButton {container=':qt_tabwidget_stackedwidget_QScrollArea' text='Remove' type='QPushButton' unnamed='1' visible='1'}
:Restart required.OK_QPushButton {text='OK' type='QPushButton' unnamed='1' visible='1' window=':Restart required_QMessageBox'}
-:Restart required_QMessageBox {text='The language change will take effect after a restart of Qt Creator.' type='QMessageBox' unnamed='1' visible='1'}
+:Restart required_QMessageBox {text='The language change will take effect after restart.' type='QMessageBox' unnamed='1' visible='1'}
:Revert to Saved.Proceed_QPushButton {text='Proceed' type='QPushButton' unnamed='1' visible='1' window=':Revert to Saved_QMessageBox'}
:Revert to Saved_QMessageBox {text?='You will lose your current changes if you proceed reverting*' type='QMessageBox' unnamed='1' visible='1'}
:RunSettingsEnvironmentDetails_Utils::DetailsButton {leftWidget=':RunSettingsUseBuildEnvironment_QLabel' text='Details' type='Utils::DetailsButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py
index 00135f668b..80bada05c9 100644
--- a/tests/system/shared/project.py
+++ b/tests/system/shared/project.py
@@ -281,12 +281,12 @@ def createProject_Qt_Console(path, projectName, checks = True, buildSystem = Non
return checkedTargets
def createNewQtQuickApplication(workingDir, projectName = None,
- targets=Targets.desktopTargetClasses(), minimumQtVersion="5.3",
+ targets=Targets.desktopTargetClasses(), minimumQtVersion="5.6",
withControls = False, fromWelcome = False, buildSystem = None):
if withControls:
- template = "Qt Quick Controls 2 Application"
+ template = "Qt Quick Application - Swipe"
else:
- template = "Qt Quick Application"
+ template = "Qt Quick Application - Empty"
available = __createProjectOrFileSelectType__(" Application", template, fromWelcome)
projectName = __createProjectSetNameAndPath__(workingDir, projectName)
__handleBuildSystem__(buildSystem)
@@ -309,7 +309,7 @@ def createNewQtQuickApplication(workingDir, projectName = None,
return checkedTargets, projectName
-def createNewQtQuickUI(workingDir, qtVersion = "5.3"):
+def createNewQtQuickUI(workingDir, qtVersion = "5.6"):
__createProjectOrFileSelectType__(" Other Project", 'Qt Quick UI Prototype')
if workingDir == None:
workingDir = tempDir()
diff --git a/tests/system/suite_SCOM/tst_SCOM02/test.py b/tests/system/suite_SCOM/tst_SCOM02/test.py
index 7c9dd60cea..64fbf7d65c 100644
--- a/tests/system/suite_SCOM/tst_SCOM02/test.py
+++ b/tests/system/suite_SCOM/tst_SCOM02/test.py
@@ -35,7 +35,7 @@ def main():
createNewQtQuickApplication(tempDir(), "SampleApp")
# create syntax error in qml file
openDocument("SampleApp.Resources.qml\.qrc./.main\\.qml")
- if not appendToLine(waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget"), "TextEdit {", "SyntaxError"):
+ if not appendToLine(waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget"), "Window {", "SyntaxError"):
invokeMenuItem("File", "Exit")
return
# save all to invoke qml parsing
diff --git a/tests/system/suite_debugger/tst_simple_analyze/test.py b/tests/system/suite_debugger/tst_simple_analyze/test.py
index 89c5fe3091..5de123db4d 100644
--- a/tests/system/suite_debugger/tst_simple_analyze/test.py
+++ b/tests/system/suite_debugger/tst_simple_analyze/test.py
@@ -35,7 +35,9 @@ def main():
analyzerTargets = Targets.desktopTargetClasses()
checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=analyzerTargets)
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
- if placeCursorToLine(editor, "MouseArea.*", True):
+ if placeCursorToLine(editor, "}"):
+ type(editor, '<Left>')
+ type(editor, '<Return>')
type(editor, '<Up>')
type(editor, '<Return>')
typeLines(editor, ['Timer {',
@@ -110,7 +112,7 @@ def performTest(workingDir, projectName, targetCount, availableConfigs):
test.compare(dumpItems(model, column=colPercent)[0], '100.00 %')
# cannot run following test on colShortest (unstable)
for i in [colTotal, colMean, colMedian, colLongest]:
- for item in dumpItems(model, column=i)[1:5]:
+ for item in dumpItems(model, column=i)[2:5]:
test.verify(item.endswith('ms'), "Verify that '%s' ends with 'ms'" % item)
for i in [colTotal, colMean, colMedian, colLongest, colShortest]:
for item in dumpItems(model, column=i):
diff --git a/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv b/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv
index 7e1b41e342..cd25a9eb10 100644
--- a/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv
+++ b/tests/system/suite_debugger/tst_simple_analyze/testdata/events_qt5.tsv
@@ -3,18 +3,7 @@
"main.qml:15" "Handling Signal" "2" "onTriggered: { runCount += 1; var i; for (i = 1; i < 2500; ++i) { var j = i * i; console.log(j); } }"
"main.qml:15" "JavaScript" "2" "onTriggered"
"main.qml:4" "Creating" "2" "QtQuick.Window/Window"
-"main.qml:33" "Creating" "2" "QtQuick/TextEdit"
"main.qml:1" "Compiling" "1" "main.qml"
"main.qml:10" "Creating" "2" "QtQuick/Timer"
-"main.qml:37" "Binding" "1" "anchors.top: parent.top"
-"main.qml:40" "Creating" "2" "QtQuick/Rectangle"
-"main.qml:37" "JavaScript" "1" "expression for top"
"main.qml:14" "Binding" "3" "running: runCount < 2"
-"main.qml:26" "Creating" "2" "QtQuick/MouseArea"
-"main.qml:38" "Binding" "1" "anchors.horizontalCenter: parent.horizontalCenter"
-"main.qml:38" "JavaScript" "1" "expression for horizontalCenter"
-"main.qml:41" "Binding" "1" "anchors.fill: parent"
-"main.qml:27" "Binding" "1" "anchors.fill: parent"
"main.qml:14" "JavaScript" "3" "expression for running"
-"main.qml:41" "JavaScript" "1" "expression for fill"
-"main.qml:27" "JavaScript" "1" "expression for fill"
diff --git a/tests/system/suite_debugger/tst_simple_debug/test.py b/tests/system/suite_debugger/tst_simple_debug/test.py
index 54b0d652ee..c726d6468b 100644
--- a/tests/system/suite_debugger/tst_simple_debug/test.py
+++ b/tests/system/suite_debugger/tst_simple_debug/test.py
@@ -35,7 +35,9 @@ def main():
workingDir = tempDir()
checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=targets)
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
- if placeCursorToLine(editor, "MouseArea.*", True):
+ if placeCursorToLine(editor, "}"):
+ type(editor, '<Left>')
+ type(editor, '<Return>')
type(editor, '<Up>')
type(editor, '<Return>')
typeLines(editor, ['Timer {',
@@ -50,7 +52,7 @@ def main():
test.log("Setting breakpoints")
result = setBreakpointsForCurrentProject(filesAndLines)
if result:
- expectedBreakpointsOrder = [{os.path.join(workingDir, projectName, "main.cpp"):8},
+ expectedBreakpointsOrder = [{os.path.join(workingDir, projectName, "main.cpp"):10},
{os.path.join(workingDir, projectName, "main.qml"):13}]
availableConfigs = iterateBuildConfigs(len(checkedTargets), "Debug")
progressBarWait()
diff --git a/tests/system/suite_editors/tst_delete_externally/test.py b/tests/system/suite_editors/tst_delete_externally/test.py
index fa85df88ae..89d72c6a88 100644
--- a/tests/system/suite_editors/tst_delete_externally/test.py
+++ b/tests/system/suite_editors/tst_delete_externally/test.py
@@ -45,7 +45,8 @@ def main():
contentBefore = readFile(currentFile)
os.remove(currentFile)
if not currentFile.endswith(".bin"):
- popupText = "The file %s was removed. Do you want to save it under a different name, or close the editor?"
+ popupText = ("The file %s has been removed from disk. Do you want to "
+ "save it under a different name, or close the editor?")
test.compare(waitForObject(":File has been removed_QMessageBox").text,
popupText % currentFile)
clickButton(waitForObject(":File has been removed.Save_QPushButton"))
@@ -56,11 +57,10 @@ def main():
test.compare(readFile(currentFile), contentBefore,
"Verifying that file '%s' was restored correctly" % currentFile)
- # Different warning because of QTCREATORBUG-8130
- popupText2 = "The file %s has been removed outside Qt Creator. Do you want to save it under a different name, or close the editor?"
+ # Test for QTCREATORBUG-8130
os.remove(currentFile)
test.compare(waitForObject(":File has been removed_QMessageBox").text,
- popupText2 % currentFile)
+ popupText % currentFile)
clickButton(waitForObject(":File has been removed.Close_QPushButton"))
test.verify(checkIfObjectExists(objectMap.realName(editor), False),
"Was the editor closed after deleting the file?")
diff --git a/tests/system/suite_editors/tst_edit_externally/test.py b/tests/system/suite_editors/tst_edit_externally/test.py
index e48232e9a4..c545b64dea 100644
--- a/tests/system/suite_editors/tst_edit_externally/test.py
+++ b/tests/system/suite_editors/tst_edit_externally/test.py
@@ -45,9 +45,9 @@ def main():
if not startedWithoutPluginError():
return
- mBox = ("{text?='The file * has changed outside Qt Creator. Do you want to reload it?' "
+ mBox = ("{text?='The file * has been changed on disk. Do you want to reload it?' "
"type='QMessageBox' unnamed='1' visible='1'}")
- popupText = "The file <i>%s</i> has changed outside Qt Creator. Do you want to reload it?"
+ popupText = "The file <i>%s</i> has been changed on disk. Do you want to reload it?"
formerContent = None
for i, currentFile in enumerate(files):
diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py
index 917f7d76a6..4621bcd517 100644
--- a/tests/system/suite_general/tst_create_proj_wizard/test.py
+++ b/tests/system/suite_general/tst_create_proj_wizard/test.py
@@ -27,10 +27,8 @@ source("../../shared/qtcreator.py")
def main():
global tmpSettingsDir, availableBuildSystems
- qtVersionsForQuick = ["5.3"]
+ qtVersionsForQuick = ["5.6"]
availableBuildSystems = ["qmake", "Qbs"]
- if platform.system() != 'Darwin':
- qtVersionsForQuick.append("5.4")
if which("cmake"):
availableBuildSystems.append("CMake")
else:
@@ -73,7 +71,7 @@ def main():
category = current.keys()[0]
template = current.values()[0]
displayedPlatforms = __createProject__(category, template)
- if template == "Qt Quick Application" or template == "Qt Quick Controls Application":
+ if template.startswith("Qt Quick Application - "):
for counter, qtVersion in enumerate(qtVersionsForQuick):
def additionalFunc(displayedPlatforms, qtVersion):
requiredQtVersion = __createProjectHandleQtQuickSelection__(qtVersion)
@@ -84,11 +82,6 @@ def main():
if counter < len(qtVersionsForQuick) - 1:
displayedPlatforms = __createProject__(category, template)
continue
- elif template == "Qt Quick Controls 2 Application": # needs a Qt5.7
- def additionalFunc(displayedPlatforms):
- clickButton(waitForObject(":Next_QPushButton")) # ignore this details page for now
- handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms, additionalFunc)
- continue
elif template.startswith("Plain C"):
handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms)
continue
@@ -139,7 +132,11 @@ def handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms,
test.log("Using build system '%s'" % buildSystem)
selectFromCombo(combo, buildSystem)
clickButton(waitForObject(":Next_QPushButton"))
- if specialHandlingFunc:
+ if (template.startswith("Qt Quick Application - ")
+ and template != "Qt Quick Application - Empty"):
+ test.warning("No suitable Qt version available for '%s'" % template)
+ clickButton(waitForObject(":Next_QPushButton"))
+ elif specialHandlingFunc:
specialHandlingFunc(displayedPlatforms, *args)
verifyKitCheckboxes(kits, displayedPlatforms)
safeClickButton("Cancel")
diff --git a/tests/system/suite_qtquick/tst_qtquick_creation/test.py b/tests/system/suite_qtquick/tst_qtquick_creation/test.py
index 233ec3d8a0..2b767cde89 100644
--- a/tests/system/suite_qtquick/tst_qtquick_creation/test.py
+++ b/tests/system/suite_qtquick/tst_qtquick_creation/test.py
@@ -30,17 +30,11 @@ def main():
if not startedWithoutPluginError():
return
- available = [("5.3", False), ("5.3", True)]
- if platform.system() != 'Darwin':
- available.extend([("5.4", False), ("5.4", True)])
+ available = [("5.6", False), ("5.6", True)]
for qtVersion, controls in available:
- if qtVersion == "5.3":
- targ = [Targets.DESKTOP_531_DEFAULT]
- quick = "2.3"
- else:
- targ = [Targets.DESKTOP_541_GCC]
- quick = "2.4"
+ targ = [Targets.DESKTOP_561_DEFAULT]
+ quick = "2.6"
# using a temporary directory won't mess up a potentially existing
workingDir = tempDir()
checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=targ,
diff --git a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py
index c04b39de8a..507abffba3 100644
--- a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py
+++ b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py
@@ -30,29 +30,17 @@ def main():
if not startedWithoutPluginError():
return
available = ["5.6"]
- if platform.system() != 'Darwin':
- available.extend(["5.4"])
for qtVersion in available:
# using a temporary directory won't mess up a potentially existing
workingDir = tempDir()
projectName = createNewQtQuickUI(workingDir, qtVersion)
- if qtVersion == "5.6":
- kit = Targets.getStringForTarget(Targets.DESKTOP_561_DEFAULT)
- if addAndActivateKit(Targets.DESKTOP_561_DEFAULT):
- quick = "2.6"
- else:
- test.fatal("Failed to activate kit %s" % kit)
- continue
- else: # qtVersion == '5.4'
- if platform.system() == 'Darwin':
- continue
- kit = Targets.getStringForTarget(Targets.DESKTOP_541_GCC)
- if addAndActivateKit(Targets.DESKTOP_541_GCC):
- quick = "2.4"
- else:
- test.fatal("Failed to activate kit %s" % kit)
- continue
+ kit = Targets.getStringForTarget(Targets.DESKTOP_561_DEFAULT)
+ if addAndActivateKit(Targets.DESKTOP_561_DEFAULT):
+ quick = "2.6"
+ else:
+ test.fatal("Failed to activate kit %s" % kit)
+ continue
test.log("Running project Qt Quick UI Prototype (%s)" % kit)
qmlViewer = modifyRunSettingsForHookIntoQtQuickUI(2, 1, workingDir, projectName, 11223, quick)
if qmlViewer!=None:
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.cpp b/tests/unit/echoserver/echoclangcodemodelserver.cpp
index 0764cf7af1..b5de4ba539 100644
--- a/tests/unit/echoserver/echoclangcodemodelserver.cpp
+++ b/tests/unit/echoserver/echoclangcodemodelserver.cpp
@@ -25,8 +25,8 @@
#include "echoclangcodemodelserver.h"
-#include <clangbackendipc/clangcodemodelservermessages.h>
-#include <clangbackendipc/connectionserver.h>
+#include <clangsupport/clangcodemodelservermessages.h>
+#include <clangsupport/connectionserver.h>
#include <QCoreApplication>
#include <QDebug>
@@ -95,6 +95,11 @@ void EchoClangCodeModelServer::requestReferences(const RequestReferencesMessage
echoMessage(message);
}
+void EchoClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMessage &message)
+{
+ echoMessage(message);
+}
+
void EchoClangCodeModelServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
echoMessage(message);
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.h b/tests/unit/echoserver/echoclangcodemodelserver.h
index d381c0bdea..2dc8c30913 100644
--- a/tests/unit/echoserver/echoclangcodemodelserver.h
+++ b/tests/unit/echoserver/echoclangcodemodelserver.h
@@ -25,11 +25,13 @@
#pragma once
-#include <clangbackendipc/clangcodemodelserverinterface.h>
+#include <clangsupport/clangcodemodelserverinterface.h>
+#include <ipcclientprovider.h>
namespace ClangBackEnd {
-class EchoClangCodeModelServer : public ClangCodeModelServerInterface
+class EchoClangCodeModelServer : public ClangCodeModelServerInterface,
+ public IpcClientProvider<ClangCodeModelClientInterface>
{
public:
void dispatch(const MessageEnvelop &message) override;
@@ -44,6 +46,7 @@ public:
void completeCode(const CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
+ void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
private:
diff --git a/tests/unit/echoserver/echoserver.pro b/tests/unit/echoserver/echoserver.pro
index 0f9ed76afa..38d0ff2078 100644
--- a/tests/unit/echoserver/echoserver.pro
+++ b/tests/unit/echoserver/echoserver.pro
@@ -15,7 +15,7 @@ IDE_BIN_PATH=$$PWD
include($$PWD/../../../src/libs/utils/utils-lib.pri)
include(../../../qtcreator.pri)
-include(../../../src/libs/clangbackendipc/clangbackendipc-lib.pri)
+include(../../../src/libs/clangsupport/clangsupport-lib.pri)
include(../../../src/libs/sqlite/sqlite-lib.pri)
INCLUDEPATH += ../../../src/libs
@@ -27,7 +27,7 @@ SOURCES += \
HEADERS += \
echoclangcodemodelserver.h
-DEFINES += CLANGBACKENDIPC_TESTS
+DEFINES += CLANGSUPPORT_TESTS
DEFINES += DONT_CHECK_MESSAGE_COUNTER
win32:DESTDIR = ..
diff --git a/tests/unit/echoserver/echoserverprocessmain.cpp b/tests/unit/echoserver/echoserverprocessmain.cpp
index a627c11fae..a153feaf15 100644
--- a/tests/unit/echoserver/echoserverprocessmain.cpp
+++ b/tests/unit/echoserver/echoserverprocessmain.cpp
@@ -25,8 +25,8 @@
#include "echoclangcodemodelserver.h"
-#include <clangbackendipc/clangcodemodelclientproxy.h>
-#include <clangbackendipc/connectionserver.h>
+#include <clangsupport/clangcodemodelclientproxy.h>
+#include <clangsupport/connectionserver.h>
#include <QCoreApplication>
diff --git a/tests/unit/mockup/projectexplorer/toolchain.h b/tests/unit/mockup/projectexplorer/toolchain.h
index 33bfa836df..9bcf43a59b 100644
--- a/tests/unit/mockup/projectexplorer/toolchain.h
+++ b/tests/unit/mockup/projectexplorer/toolchain.h
@@ -27,6 +27,7 @@
#include <projectexplorer/headerpath.h>
#include <projectexplorer/abi.h>
+#include <projectexplorer/projectmacro.h>
#include <coreplugin/id.h>
#include <functional>
@@ -59,7 +60,7 @@ public:
using SystemHeaderPathsRunner = std::function<QList<HeaderPath>(const QStringList &cxxflags, const QString &sysRoot)>;
virtual SystemHeaderPathsRunner createSystemHeaderPathsRunner() const { return SystemHeaderPathsRunner(); }
- using PredefinedMacrosRunner = std::function<QByteArray(const QStringList &cxxflags)>;
+ using PredefinedMacrosRunner = std::function<Macros(const QStringList &cxxflags)>;
virtual PredefinedMacrosRunner createPredefinedMacrosRunner() const { return PredefinedMacrosRunner(); }
virtual QString originalTargetTriple() const { return QString(); }
diff --git a/tests/unit/unittest/activationsequencecontextprocessor-test.cpp b/tests/unit/unittest/activationsequencecontextprocessor-test.cpp
index aca0ae4e97..5ccc7d500a 100644
--- a/tests/unit/unittest/activationsequencecontextprocessor-test.cpp
+++ b/tests/unit/unittest/activationsequencecontextprocessor-test.cpp
@@ -144,6 +144,14 @@ TEST(ActivationSequenceContextProcessor, TemplateFunctionLeftParen)
ASSERT_THAT(processor.completionKind(), CPlusPlus::T_LPAREN);
}
+TEST(ActivationSequenceContextProcessor, TemplateFunctionSecondParameter)
+{
+ ClangCompletionAssistInterface interface("foo<X>(", 7);
+ int startOfname = ContextProcessor::findStartOfName(&interface, 6);
+
+ ASSERT_THAT(startOfname, 0);
+}
+
TEST(ActivationSequenceContextProcessor, ExpressionLeftParen)
{
ClangCompletionAssistInterface interface("x * (", 5);
diff --git a/tests/unit/unittest/clang_dependency.pri b/tests/unit/unittest/clang_dependency.pri
index 354ebd0c90..bbce04a527 100644
--- a/tests/unit/unittest/clang_dependency.pri
+++ b/tests/unit/unittest/clang_dependency.pri
@@ -20,7 +20,7 @@ win32 {
LIBS += $$LIBTOOLING_LIBS $$LIBCLANG_LIBS
QMAKE_RPATHDIR += $$LLVM_LIBDIR
-LLVM_CXXFLAGS ~= s,-g,
+LLVM_CXXFLAGS ~= s,-g\d?,
QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS
}
diff --git a/tests/unit/unittest/clangasyncjob-base.cpp b/tests/unit/unittest/clangasyncjob-base.cpp
index c3695d9639..6535a15ef7 100644
--- a/tests/unit/unittest/clangasyncjob-base.cpp
+++ b/tests/unit/unittest/clangasyncjob-base.cpp
@@ -26,7 +26,7 @@
#include "clangasyncjob-base.h"
#include "processevents-utilities.h"
-#include <clangbackendipc/filecontainer.h>
+#include <clangsupport/filecontainer.h>
using namespace ClangBackEnd;
@@ -49,10 +49,7 @@ void ClangAsyncJobTest::BaseSetUp(ClangBackEnd::JobRequest::Type jobRequestType,
JobRequest ClangAsyncJobTest::createJobRequest(const Utf8String &filePath,
JobRequest::Type type) const
{
- JobRequest jobRequest;
- jobRequest.type = type;
- jobRequest.expirationReasons = JobRequest::expirationReasonsForType(type);
- jobRequest.conditions = JobRequest::conditionsForType(type);
+ JobRequest jobRequest(type);
jobRequest.filePath = filePath;
jobRequest.projectPartId = projectPartId;
jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
diff --git a/tests/unit/unittest/clangcodemodelserver-test.cpp b/tests/unit/unittest/clangcodemodelserver-test.cpp
index 0dad554a0b..b1b4e8dc8a 100644
--- a/tests/unit/unittest/clangcodemodelserver-test.cpp
+++ b/tests/unit/unittest/clangcodemodelserver-test.cpp
@@ -126,6 +126,7 @@ protected:
void requestDocumentAnnotations(const Utf8String &filePath);
void requestReferences(quint32 documentRevision = 0);
+ void requestFollowSymbol(quint32 documentRevision = 0);
void completeCode(const Utf8String &filePath, uint line = 1, uint column = 1,
const Utf8String &projectPartId = Utf8String());
@@ -144,6 +145,7 @@ protected:
void expectCompletionFromFileAUnsavedMethodVersion2();
void expectNoCompletionWithUnsavedMethod();
void expectReferences();
+ void expectFollowSymbol();
void expectDocumentAnnotationsChangedForFileBWithSpecificHighlightingMark();
static const Utf8String unsavedContent(const QString &unsavedFilePath);
@@ -206,6 +208,25 @@ TEST_F(ClangCodeModelServerSlowTest, RequestReferencesTakesRevisionFromMessage)
queue.clear(); // Avoid blocking
}
+TEST_F(ClangCodeModelServerSlowTest, RequestFollowSymbolForCurrentDocumentRevision)
+{
+ registerProjectAndFileAndWaitForFinished(filePathC);
+
+ expectFollowSymbol();
+ requestFollowSymbol();
+}
+
+TEST_F(ClangCodeModelServerSlowTest, RequestFollowSymbolTakesRevisionFromMessage)
+{
+ registerProjectAndFileAndWaitForFinished(filePathC);
+
+ requestFollowSymbol(/*documentRevision=*/ 99);
+
+ JobRequests &queue = documentProcessorForFile(filePathC).queue();
+ Utils::anyOf(queue, [](const JobRequest &request) { return request.documentRevision == 99; });
+ queue.clear(); // Avoid blocking
+}
+
TEST_F(ClangCodeModelServerSlowTest, NoInitialDocumentAnnotationsForClosedDocument)
{
const int expectedDocumentAnnotationsChangedCount = 0;
@@ -555,6 +576,20 @@ void ClangCodeModelServer::expectReferences()
.Times(1);
}
+void ClangCodeModelServer::expectFollowSymbol()
+{
+ const ClangBackEnd::SourceRangeContainer classDefinition{
+ {filePathC, 40, 7},
+ {filePathC, 40, 10}
+ };
+
+ EXPECT_CALL(mockClangCodeModelClient,
+ followSymbol(
+ Property(&FollowSymbolMessage::sourceRange,
+ Eq(classDefinition))))
+ .Times(1);
+}
+
void ClangCodeModelServer::expectCompletionFromFileA()
{
const CodeCompletion completion(Utf8StringLiteral("Function"),
@@ -580,12 +615,21 @@ void ClangCodeModelServer::requestReferences(quint32 documentRevision)
clangServer.requestReferences(message);
}
+void ClangCodeModelServer::requestFollowSymbol(quint32 documentRevision)
+{
+ const FileContainer fileContainer{filePathC, projectPartId, Utf8StringVector(),
+ documentRevision};
+ const RequestFollowSymbolMessage message{fileContainer, QVector<Utf8String>(), 43, 9};
+
+ clangServer.requestFollowSymbol(message);
+}
+
void ClangCodeModelServer::expectDocumentAnnotationsChangedForFileBWithSpecificHighlightingMark()
{
HighlightingTypes types;
types.mainHighlightingType = ClangBackEnd::HighlightingType::Function;
types.mixinHighlightingTypes.push_back(ClangBackEnd::HighlightingType::Declaration);
- const HighlightingMarkContainer highlightingMark(1, 6, 8, types);
+ const HighlightingMarkContainer highlightingMark(1, 6, 8, types, true);
EXPECT_CALL(mockClangCodeModelClient,
documentAnnotationsChanged(
diff --git a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp b/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp
index 5ca579a1d4..09938b2c5d 100644
--- a/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp
+++ b/tests/unit/unittest/clangcompletioncontextanalyzer-test.cpp
@@ -490,4 +490,27 @@ TEST_F(ClangCompletionContextAnalyzer, AsteriskLeftParen)
ASSERT_THAT(analyzer, IsPassThroughToClang());
}
+TEST_F(ClangCompletionContextAnalyzer, TemplatedFunctionSecondArgument)
+{
+ auto analyzer = runAnalyzer("f < decltype(bar -> member) > (1, @");
+
+ ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText));
+}
+
+TEST_F(ClangCompletionContextAnalyzer, FunctionNameStartPosition)
+{
+ auto analyzer = runAnalyzer(" f<Bar>(1, @");
+ int functionNameStartPosition = analyzer.functionNameStart();
+
+ ASSERT_THAT(functionNameStartPosition, 1);
+}
+
+TEST_F(ClangCompletionContextAnalyzer, QualifiedFunctionNameStartPosition)
+{
+ auto analyzer = runAnalyzer(" Namespace::f<Bar>(1, @");
+ int functionNameStartPosition = analyzer.functionNameStart();
+
+ ASSERT_THAT(functionNameStartPosition, 1);
+}
+
}
diff --git a/tests/unit/unittest/clangfollowsymbol-test.cpp b/tests/unit/unittest/clangfollowsymbol-test.cpp
new file mode 100644
index 0000000000..566c02b0e5
--- /dev/null
+++ b/tests/unit/unittest/clangfollowsymbol-test.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+#include "testenvironment.h"
+
+#include <clangsupport_global.h>
+#include <clangfollowsymboljob.h>
+#include <clangdocument.h>
+#include <clangdocuments.h>
+#include <clangtranslationunit.h>
+#include <fixitcontainer.h>
+#include <projectpart.h>
+#include <projects.h>
+#include <sourcelocationcontainer.h>
+#include <sourcerangecontainer.h>
+#include <unsavedfiles.h>
+#include <commandlinearguments.h>
+
+#include <utils/qtcassert.h>
+
+#include <clang-c/Index.h>
+
+using ::testing::Contains;
+using ::testing::Not;
+using ::testing::ContainerEq;
+using ::testing::Eq;
+using ::testing::PrintToString;
+
+using ::ClangBackEnd::ProjectPart;
+using ::ClangBackEnd::SourceLocationContainer;
+using ::ClangBackEnd::Document;
+using ::ClangBackEnd::UnsavedFiles;
+using ::ClangBackEnd::ReferencesResult;
+using ::ClangBackEnd::SourceRangeContainer;
+
+namespace {
+const Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_main.cpp");
+const Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/followsymbol_header.h");
+const Utf8String cursorPath = Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp");
+
+MATCHER_P3(MatchesHeaderSourceRange, line, column, length,
+ std::string(negation ? "isn't " : "is ")
+ + PrintToString(SourceRangeContainer {
+ SourceLocationContainer(headerFilePath, line, column),
+ SourceLocationContainer(headerFilePath, line, column + length)
+ })
+ )
+{
+ const SourceRangeContainer expected = {
+ SourceLocationContainer(headerFilePath, line, column),
+ SourceLocationContainer(headerFilePath, line, column + length)
+ };
+
+ return arg == expected;
+}
+
+MATCHER_P3(MatchesSourceRange, line, column, length,
+ std::string(negation ? "isn't " : "is ")
+ + PrintToString(SourceRangeContainer {
+ SourceLocationContainer(sourceFilePath, line, column),
+ SourceLocationContainer(sourceFilePath, line, column + length)
+ })
+ )
+{
+ const SourceRangeContainer expected = {
+ SourceLocationContainer(sourceFilePath, line, column),
+ SourceLocationContainer(sourceFilePath, line, column + length)
+ };
+
+ return arg == expected;
+}
+
+MATCHER_P4(MatchesFileSourceRange, filename, line, column, length,
+ std::string(negation ? "isn't " : "is ")
+ + PrintToString(SourceRangeContainer {
+ SourceLocationContainer(filename, line, column),
+ SourceLocationContainer(filename, line, column + length)
+ })
+ )
+{
+ const SourceRangeContainer expected = {
+ SourceLocationContainer(filename, line, column),
+ SourceLocationContainer(filename, line, column + length)
+ };
+
+ return arg == expected;
+}
+
+class Data {
+public:
+ Data()
+ {
+ m_document.parse();
+ m_headerDocument.parse();
+ }
+
+ const Document &document() const { return m_document; }
+ const Document &headerDocument() const { return m_headerDocument; }
+ const QVector<Utf8String> &deps() const { return m_deps; }
+private:
+ ProjectPart m_projectPart{
+ Utf8StringLiteral("projectPartId"),
+ TestEnvironment::addPlatformArguments({Utf8StringLiteral("-std=c++14")})};
+ ClangBackEnd::ProjectParts m_projects;
+ ClangBackEnd::UnsavedFiles m_unsavedFiles;
+ ClangBackEnd::Documents m_documents{m_projects, m_unsavedFiles};
+ Document m_document = {sourceFilePath,
+ m_projectPart,
+ Utf8StringVector(),
+ m_documents};
+ Document m_headerDocument = {headerFilePath,
+ m_projectPart,
+ Utf8StringVector(),
+ m_documents};
+ QVector<Utf8String> m_deps {sourceFilePath, cursorPath};
+};
+
+class FollowSymbol : public ::testing::Test
+{
+protected:
+ SourceRangeContainer followSymbol(uint line, uint column)
+ {
+ ClangBackEnd::TranslationUnitUpdateInput updateInput = d->document().createUpdateInput();
+ const ClangBackEnd::CommandLineArguments currentArgs(updateInput.filePath.constData(),
+ updateInput.projectArguments,
+ updateInput.fileArguments,
+ false);
+ return d->document().translationUnit().followSymbol(line, column,
+ d->deps(),
+ currentArgs);
+ }
+
+ SourceRangeContainer followHeaderSymbol(uint line, uint column)
+ {
+ ClangBackEnd::TranslationUnitUpdateInput updateInput
+ = d->headerDocument().createUpdateInput();
+ const ClangBackEnd::CommandLineArguments currentArgs(updateInput.filePath.constData(),
+ updateInput.projectArguments,
+ updateInput.fileArguments,
+ false);
+ return d->headerDocument().translationUnit().followSymbol(line, column,
+ d->deps(),
+ currentArgs);
+ }
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+private:
+ static std::unique_ptr<Data> d;
+};
+
+TEST_F(FollowSymbol, CursorOnNamespace)
+{
+ const auto namespaceDefinition = followSymbol(27, 1);
+
+ ASSERT_THAT(namespaceDefinition, MatchesHeaderSourceRange(28, 11, 6));
+}
+
+TEST_F(FollowSymbol, CursorOnClassReference)
+{
+ const auto classDefinition = followSymbol(27, 9);
+
+ ASSERT_THAT(classDefinition, MatchesHeaderSourceRange(34, 7, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnClassForwardDeclarationFollowToHeader)
+{
+ const auto classDefinition = followHeaderSymbol(32, 7);
+
+ ASSERT_THAT(classDefinition, MatchesHeaderSourceRange(34, 7, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnClassForwardDeclarationFollowToCpp)
+{
+ const auto classDefinition = followHeaderSymbol(48, 9);
+
+ ASSERT_THAT(classDefinition, MatchesSourceRange(54, 7, 8));
+}
+
+TEST_F(FollowSymbol, CursorOnClassDefinition)
+{
+ const auto classForwardDeclaration = followHeaderSymbol(34, 7);
+
+ ASSERT_THAT(classForwardDeclaration, MatchesHeaderSourceRange(32, 7, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnClassDefinitionInCpp)
+{
+ const auto classForwardDeclaration = followSymbol(54, 7);
+
+ ASSERT_THAT(classForwardDeclaration, MatchesHeaderSourceRange(48, 7, 8));
+}
+
+TEST_F(FollowSymbol, CursorOnConstructorDeclaration)
+{
+ const auto constructorDefinition = followHeaderSymbol(36, 5);
+
+ ASSERT_THAT(constructorDefinition, MatchesSourceRange(27, 14, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnConstructorDefinition)
+{
+ const auto constructorDeclaration = followSymbol(27, 14);
+
+ ASSERT_THAT(constructorDeclaration, MatchesHeaderSourceRange(36, 5, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnMemberReference)
+{
+ const auto memberDeclaration = followSymbol(39, 10);
+
+ ASSERT_THAT(memberDeclaration, MatchesHeaderSourceRange(38, 18, 6));
+}
+
+TEST_F(FollowSymbol, CursorOnMemberDeclaration)
+{
+ const auto sameMemberDeclaration = followHeaderSymbol(38, 18);
+
+ ASSERT_THAT(sameMemberDeclaration, MatchesHeaderSourceRange(38, 18, 6));
+}
+
+TEST_F(FollowSymbol, CursorOnFunctionReference)
+{
+ const auto functionDefinition = followSymbol(66, 12);
+
+ ASSERT_THAT(functionDefinition, MatchesSourceRange(35, 5, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnMemberFunctionReference)
+{
+ const auto memberFunctionDefinition = followSymbol(42, 12);
+
+ ASSERT_THAT(memberFunctionDefinition, MatchesSourceRange(49, 21, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnFunctionWithoutDefinitionReference)
+{
+ const auto functionDeclaration = followSymbol(43, 5);
+
+ ASSERT_THAT(functionDeclaration, MatchesHeaderSourceRange(59, 5, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnFunctionDefinition)
+{
+ const auto functionDeclaration = followSymbol(35, 5);
+
+ ASSERT_THAT(functionDeclaration, MatchesHeaderSourceRange(52, 5, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnMemberFunctionDefinition)
+{
+ const auto memberFunctionDeclaration = followSymbol(49, 21);
+
+ ASSERT_THAT(memberFunctionDeclaration, MatchesHeaderSourceRange(43, 9, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnMemberFunctionDeclaration)
+{
+ const auto memberFunctionDefinition = followHeaderSymbol(43, 9);
+
+ ASSERT_THAT(memberFunctionDefinition, MatchesSourceRange(49, 21, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnInclude)
+{
+ const auto startOfIncludeFile = followSymbol(25, 13);
+
+ ASSERT_THAT(startOfIncludeFile, MatchesHeaderSourceRange(1, 1, 0));
+}
+
+TEST_F(FollowSymbol, CursorOnLocalVariable)
+{
+ const auto variableDeclaration = followSymbol(39, 6);
+
+ ASSERT_THAT(variableDeclaration, MatchesSourceRange(36, 9, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnClassAlias)
+{
+ const auto aliasDefinition = followSymbol(36, 5);
+
+ ASSERT_THAT(aliasDefinition, MatchesSourceRange(33, 7, 3));
+}
+
+TEST_F(FollowSymbol, CursorOnStaticVariable)
+{
+ const auto staticVariableDeclaration = followSymbol(40, 27);
+
+ ASSERT_THAT(staticVariableDeclaration, MatchesHeaderSourceRange(30, 7, 7));
+}
+
+TEST_F(FollowSymbol, CursorOnFunctionFromOtherClass)
+{
+ const auto functionDefinition = followSymbol(62, 39);
+
+ ASSERT_THAT(functionDefinition, MatchesFileSourceRange(cursorPath, 104, 22, 8));
+}
+
+TEST_F(FollowSymbol, CursorOnDefineReference)
+{
+ const auto functionDefinition = followSymbol(66, 43);
+
+ ASSERT_THAT(functionDefinition, MatchesHeaderSourceRange(27, 9, 11));
+}
+
+
+TEST_F(FollowSymbol, CursorInTheMiddleOfNamespace)
+{
+ const auto namespaceDefinition = followSymbol(27, 3);
+
+ ASSERT_THAT(namespaceDefinition, MatchesHeaderSourceRange(28, 11, 6));
+}
+
+TEST_F(FollowSymbol, CursorAfterNamespace)
+{
+ const auto namespaceDefinition = followSymbol(27, 7);
+
+ ASSERT_THAT(namespaceDefinition, MatchesFileSourceRange(QString(""), 0, 0, 0));
+}
+
+TEST_F(FollowSymbol, CursorOnOneSymbolOperatorDefinition)
+{
+ const auto namespaceDefinition = followSymbol(76, 13);
+
+ ASSERT_THAT(namespaceDefinition, MatchesSourceRange(72, 9, 9));
+}
+
+TEST_F(FollowSymbol, CursorOnTwoSymbolOperatorDefinition)
+{
+ const auto namespaceDefinition = followSymbol(80, 15);
+
+ ASSERT_THAT(namespaceDefinition, MatchesSourceRange(73, 10, 10));
+}
+
+TEST_F(FollowSymbol, CursorOnOneSymbolOperatorDeclaration)
+{
+ const auto namespaceDefinition = followSymbol(72, 12);
+
+ ASSERT_THAT(namespaceDefinition, MatchesSourceRange(76, 10, 9));
+}
+
+TEST_F(FollowSymbol, CursorOnTwoSymbolOperatorDeclaration)
+{
+ const auto namespaceDefinition = followSymbol(73, 12);
+
+ ASSERT_THAT(namespaceDefinition, MatchesSourceRange(80, 11, 10));
+}
+
+std::unique_ptr<Data> FollowSymbol::d;
+
+void FollowSymbol::SetUpTestCase()
+{
+ d.reset(new Data);
+}
+
+void FollowSymbol::TearDownTestCase()
+{
+ d.reset();
+}
+
+} // anonymous namespace
diff --git a/tests/unit/unittest/clangjobqueue-test.cpp b/tests/unit/unittest/clangjobqueue-test.cpp
index c3236a4d6d..dd3f4fc036 100644
--- a/tests/unit/unittest/clangjobqueue-test.cpp
+++ b/tests/unit/unittest/clangjobqueue-test.cpp
@@ -538,10 +538,7 @@ JobRequest JobQueue::createJobRequest(
JobRequest::Type type,
PreferredTranslationUnit preferredTranslationUnit) const
{
- JobRequest jobRequest;
- jobRequest.type = type;
- jobRequest.expirationReasons = JobRequest::expirationReasonsForType(type);
- jobRequest.conditions = JobRequest::conditionsForType(type);
+ JobRequest jobRequest(type);
jobRequest.filePath = filePath;
jobRequest.projectPartId = projectPartId;
jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
diff --git a/tests/unit/unittest/clangpathwatcher-test.cpp b/tests/unit/unittest/clangpathwatcher-test.cpp
index 7f2c4b7e61..4bbadca3a3 100644
--- a/tests/unit/unittest/clangpathwatcher-test.cpp
+++ b/tests/unit/unittest/clangpathwatcher-test.cpp
@@ -42,11 +42,12 @@ using testing::NiceMock;
using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>;
using ClangBackEnd::WatcherEntry;
+using ClangBackEnd::FilePathIndices;
class ClangPathWatcher : public testing::Test
{
protected:
- ClangBackEnd::StringCache<Utils::PathString> pathCache;
+ ClangBackEnd::FilePathCache<> pathCache;
NiceMock<MockClangPathWatcherNotifier> notifier;
Watcher watcher{pathCache, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
@@ -55,8 +56,8 @@ protected:
Utils::SmallString id3{"id3"};
Utils::PathString path1{"/path/path1"};
Utils::PathString path2{"/path/path2"};
- std::vector<uint> paths = watcher.pathCache().stringIds({path1, path2});
- std::vector<uint> ids = watcher.idCache().stringIds({id1, id2, id3});
+ FilePathIndices paths{watcher.pathCache().stringIds({path1, path2})};
+ FilePathIndices ids{watcher.idCache().stringIds({id1, id2, id3})};
WatcherEntry watcherEntry1{ids[0], paths[0]};
WatcherEntry watcherEntry2{ids[1], paths[0]};
WatcherEntry watcherEntry3{ids[0], paths[1]};
@@ -68,7 +69,7 @@ TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList)
{
auto convertedList = watcher.convertWatcherEntriesToQStringList({watcherEntry1, watcherEntry3});
- ASSERT_THAT(convertedList, ElementsAre(path1, path2));
+ ASSERT_THAT(convertedList, ElementsAre(QString(path1), QString(path2)));
}
TEST_F(ClangPathWatcher, UniquePaths)
@@ -89,7 +90,7 @@ TEST_F(ClangPathWatcher, NotWatchedEntries)
TEST_F(ClangPathWatcher, AddIdPaths)
{
- EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1, path2}));
+ EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1), QString(path2)}));
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}});
}
@@ -98,7 +99,7 @@ TEST_F(ClangPathWatcher, UpdateIdPathsCallsAddPathInFileWatcher)
{
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}});
- EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path2}));
+ EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path2)}));
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}});
}
@@ -107,7 +108,7 @@ TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsCallsRemovePathInFileW
{
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}});
- EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2}));
+ EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)}));
watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}});
}
@@ -116,7 +117,7 @@ TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsDoNotCallsRemovePathIn
{
watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}});
- EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2}))
+ EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)}))
.Times(0);
watcher.updateIdPaths({{id1, {paths[1]}}, {id2, {paths[0]}}});
@@ -189,14 +190,14 @@ TEST_F(ClangPathWatcher, AddEmptyEntries)
TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths)
{
- EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1, path2}));
+ EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1), QString(path2)}));
watcher.addEntries({watcherEntry1, watcherEntry3});
}
TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths)
{
- EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1}));
+ EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)}));
watcher.addEntries({watcherEntry1, watcherEntry2});
}
@@ -205,7 +206,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithSameIdAndSamePaths)
{
watcher.addEntries({watcherEntry1});
- EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1}))
+ EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)}))
.Times(0);
watcher.addEntries({watcherEntry1});
@@ -215,7 +216,7 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths)
{
watcher.addEntries({watcherEntry1});
- EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1}))
+ EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{QString(path1)}))
.Times(0);
watcher.addEntries({watcherEntry2});
@@ -252,7 +253,7 @@ TEST_F(ClangPathWatcher, RemovePathForOneId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3});
- EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2}));
+ EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path2)}));
watcher.removeIds({id1});
}
@@ -261,7 +262,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
- EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1, path2}));
+ EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path1), QString(path2)}));
watcher.removeIds({id1, id2, id3});
}
@@ -270,7 +271,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
{
watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5});
- EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1}));
+ EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{QString(path1)}));
watcher.removeIds({id1, id2});
}
diff --git a/tests/unit/unittest/clangquery-test.cpp b/tests/unit/unittest/clangquery-test.cpp
index 3b1a196e94..792c234570 100644
--- a/tests/unit/unittest/clangquery-test.cpp
+++ b/tests/unit/unittest/clangquery-test.cpp
@@ -33,7 +33,7 @@
#include <mutex>
using ClangBackEnd::ClangQuery;
-using ClangBackEnd::StringCache;
+using ClangBackEnd::FilePathCache;
using testing::AllOf;
using testing::Contains;
@@ -48,7 +48,7 @@ protected:
void SetUp() override;
protected:
- StringCache<Utils::PathString, std::mutex> filePathCache;
+ FilePathCache<std::mutex> filePathCache;
::ClangQuery simpleFunctionQuery{filePathCache};
::ClangQuery simpleClassQuery{filePathCache};
};
diff --git a/tests/unit/unittest/clangquerygatherer-test.cpp b/tests/unit/unittest/clangquerygatherer-test.cpp
index 47719f031d..a9a191383c 100644
--- a/tests/unit/unittest/clangquerygatherer-test.cpp
+++ b/tests/unit/unittest/clangquerygatherer-test.cpp
@@ -75,7 +75,7 @@ protected:
void SetUp() override;
protected:
- ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache;
+ ClangBackEnd::FilePathCache<std::mutex> filePathCache;
Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(),
diff --git a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp
index 824905f188..c33b8ab38a 100644
--- a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp
+++ b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp
@@ -170,7 +170,7 @@ TEST_F(ClangQueryProjectFindFilter, CallingRequestSourceRangesAndDiagnostics)
Property(&FileContainer::unsavedFileContent, exampleContent)),
Property(&Message::query, queryText))));
- findFilter.requestSourceRangesAndDiagnostics(queryText, exampleContent);
+ findFilter.requestSourceRangesAndDiagnostics(QString(queryText), QString(exampleContent));
}
std::vector<CppTools::ProjectPart::Ptr> createProjectParts()
diff --git a/tests/unit/unittest/clangreferencescollector-test.cpp b/tests/unit/unittest/clangreferencescollector-test.cpp
index 7141ee2afb..4fae0785ea 100644
--- a/tests/unit/unittest/clangreferencescollector-test.cpp
+++ b/tests/unit/unittest/clangreferencescollector-test.cpp
@@ -26,7 +26,7 @@
#include "googletest.h"
#include "testenvironment.h"
-#include <clangbackendipc_global.h>
+#include <clangsupport_global.h>
#include <clangreferencescollector.h>
#include <clangdocument.h>
#include <clangdocuments.h>
diff --git a/tests/unit/unittest/clientserverinprocess-test.cpp b/tests/unit/unittest/clientserverinprocess-test.cpp
index d085a3f779..f45677e447 100644
--- a/tests/unit/unittest/clientserverinprocess-test.cpp
+++ b/tests/unit/unittest/clientserverinprocess-test.cpp
@@ -30,7 +30,6 @@
#include <clangcodemodelclientproxy.h>
#include <clangcodemodelserverproxy.h>
-#include <projectpartsdonotexistmessage.h>
#include <clangcodemodelservermessages.h>
@@ -226,29 +225,6 @@ TEST_F(ClientServerInProcess, UpdateVisibleTranslationUnitsMessage)
scheduleServerMessages();
}
-TEST_F(ClientServerInProcess, SendTranslationUnitDoesNotExistMessage)
-{
- ClangBackEnd::TranslationUnitDoesNotExistMessage message(fileContainer);
-
- EXPECT_CALL(mockClangCodeModelClient, translationUnitDoesNotExist(message))
- .Times(1);
-
- clientProxy.translationUnitDoesNotExist(message);
- scheduleClientMessages();
-}
-
-
-TEST_F(ClientServerInProcess, SendProjectPartDoesNotExistMessage)
-{
- ClangBackEnd::ProjectPartsDoNotExistMessage message({Utf8StringLiteral("projectId")});
-
- EXPECT_CALL(mockClangCodeModelClient, projectPartsDoNotExist(message))
- .Times(1);
-
- clientProxy.projectPartsDoNotExist(message);
- scheduleClientMessages();
-}
-
TEST_F(ClientServerInProcess, SendDocumentAnnotationsChangedMessage)
{
ClangBackEnd::HighlightingMarkContainer highlightingMark(1, 1, 1, ClangBackEnd::HighlightingType::Keyword);
diff --git a/tests/unit/unittest/codecompleter-test.cpp b/tests/unit/unittest/codecompleter-test.cpp
index 439374d45b..76802d7ca2 100644
--- a/tests/unit/unittest/codecompleter-test.cpp
+++ b/tests/unit/unittest/codecompleter-test.cpp
@@ -188,6 +188,12 @@ protected:
readFileContent(QStringLiteral("/complete_withGlobalCompletionAfterForwardDeclaredClassPointer.cpp")),
true
};
+ ClangBackEnd::FileContainer smartPointerCompletion{
+ Utf8StringLiteral(TESTDATA_DIR"/complete_smartpointer.cpp"),
+ projectPart.projectPartId(),
+ readFileContent(QStringLiteral("/complete_smartpointer.cpp")),
+ true
+ };
};
using CodeCompleterSlowTest = CodeCompleter;
@@ -297,6 +303,33 @@ TEST_F(CodeCompleterSlowTest, FunctionInIncludedHeader)
CodeCompletion::FunctionCompletionKind)));
}
+TEST_F(CodeCompleterSlowTest, UniquePointerCompletion)
+{
+ auto myCompleter = setupCompleter(smartPointerCompletion);
+
+ ASSERT_THAT(myCompleter.complete(55, 54, 55, 32),
+ Contains(IsCodeCompletion(Utf8StringLiteral("Bar"),
+ CodeCompletion::ConstructorCompletionKind)));
+}
+
+TEST_F(CodeCompleterSlowTest, SharedPointerCompletion)
+{
+ auto myCompleter = setupCompleter(smartPointerCompletion);
+
+ ASSERT_THAT(myCompleter.complete(56, 55, 56, 33),
+ Contains(IsCodeCompletion(Utf8StringLiteral("Bar"),
+ CodeCompletion::ConstructorCompletionKind)));
+}
+
+TEST_F(CodeCompleterSlowTest, QSharedPointerCompletion)
+{
+ auto myCompleter = setupCompleter(smartPointerCompletion);
+
+ ASSERT_THAT(myCompleter.complete(57, 60, 57, 32),
+ Contains(IsCodeCompletion(Utf8StringLiteral("Bar"),
+ CodeCompletion::ConstructorCompletionKind)));
+}
+
TEST_F(CodeCompleterSlowTest, FunctionInUnsavedIncludedHeader)
{
unsavedFiles.createOrUpdate({unsavedTargetHeaderFileContainer});
diff --git a/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp b/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp
index 7b1dc4d42a..9a56777a17 100644
--- a/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp
+++ b/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp
@@ -25,25 +25,28 @@
#include "googletest.h"
-#include <QString>
-
#include <createtablesqlstatementbuilder.h>
#include <sqlstatementbuilderexception.h>
-#include <utf8stringvector.h>
+namespace {
+
+using Sqlite::ColumnType;
+using Sqlite::Contraint;
+using Sqlite::JournalMode;
+using Sqlite::OpenMode;
+using Sqlite::Column;
+using Sqlite::SqliteColumns;
+
+using Sqlite::SqlStatementBuilderException;
class CreateTableSqlStatementBuilder : public ::testing::Test
{
protected:
- void SetUp() override;
-
void bindValues();
- static const QVector<Internal::ColumnDefinition> createColumnDefintions();
- static const Internal::ColumnDefinition createColumnDefintion(const Utf8String &name,
- ColumnType type,
- bool isPrimaryKey = false);
+ static SqliteColumns createColumns();
- Internal::CreateTableSqlStatementBuilder builder;
+protected:
+ Sqlite::CreateTableSqlStatementBuilder builder;
};
TEST_F(CreateTableSqlStatementBuilder, IsNotValidAfterCreation)
@@ -82,25 +85,28 @@ TEST_F(CreateTableSqlStatementBuilder, SqlStatement)
bindValues();
ASSERT_THAT(builder.sqlStatement(),
- Utf8StringLiteral("CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC)"));}
+ "CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC)");
+}
TEST_F(CreateTableSqlStatementBuilder, AddColumnToExistingColumns)
{
bindValues();
- builder.addColumnDefinition(Utf8StringLiteral("number2"), ColumnType::Real);
+ builder.addColumn("number2", ColumnType::Real);
ASSERT_THAT(builder.sqlStatement(),
- Utf8StringLiteral("CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC, number2 REAL)"));}
+ "CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC, number2 REAL)");
+}
TEST_F(CreateTableSqlStatementBuilder, ChangeTable)
{
bindValues();
- builder.setTable(Utf8StringLiteral("test2"));
+ builder.setTableName("test2");
ASSERT_THAT(builder.sqlStatement(),
- Utf8StringLiteral("CREATE TABLE IF NOT EXISTS test2(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC)"));
+ "CREATE TABLE test2(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC)"
+ );
}
TEST_F(CreateTableSqlStatementBuilder, IsInvalidAfterClearColumsOnly)
@@ -118,11 +124,11 @@ TEST_F(CreateTableSqlStatementBuilder, ClearColumnsAndAddColumnNewColumns)
bindValues();
builder.clearColumns();
- builder.addColumnDefinition(Utf8StringLiteral("name3"), ColumnType::Text);
- builder.addColumnDefinition(Utf8StringLiteral("number3"), ColumnType::Real);
+ builder.addColumn("name3", ColumnType::Text);
+ builder.addColumn("number3", ColumnType::Real);
ASSERT_THAT(builder.sqlStatement(),
- Utf8StringLiteral("CREATE TABLE IF NOT EXISTS test(name3 TEXT, number3 REAL)"));
+ "CREATE TABLE test(name3 TEXT, number3 REAL)");
}
TEST_F(CreateTableSqlStatementBuilder, SetWitoutRowId)
@@ -132,51 +138,72 @@ TEST_F(CreateTableSqlStatementBuilder, SetWitoutRowId)
builder.setUseWithoutRowId(true);
ASSERT_THAT(builder.sqlStatement(),
- Utf8StringLiteral("CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC) WITHOUT ROWID"));
+ "CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC) WITHOUT ROWID");
}
TEST_F(CreateTableSqlStatementBuilder, SetColumnDefinitions)
{
builder.clear();
- builder.setTable(Utf8StringLiteral("test"));
+ builder.setTableName("test");
- builder.setColumnDefinitions(createColumnDefintions());
+ builder.setColumns(createColumns());
ASSERT_THAT(builder.sqlStatement(),
- Utf8StringLiteral("CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC)"));
+ "CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT, number NUMERIC)");
}
-void CreateTableSqlStatementBuilder::SetUp()
+TEST_F(CreateTableSqlStatementBuilder, UniqueContraint)
{
- builder = Internal::CreateTableSqlStatementBuilder();
+ builder.clear();
+ builder.setTableName("test");
+
+ builder.addColumn("id", ColumnType::Integer, Contraint::Unique);
+
+ ASSERT_THAT(builder.sqlStatement(),
+ "CREATE TABLE test(id INTEGER UNIQUE)");
}
-void CreateTableSqlStatementBuilder::bindValues()
+TEST_F(CreateTableSqlStatementBuilder, IfNotExitsModifier)
{
builder.clear();
- builder.setTable(Utf8StringLiteral("test"));
- builder.addColumnDefinition(Utf8StringLiteral("id"), ColumnType::Integer, true);
- builder.addColumnDefinition(Utf8StringLiteral("name"), ColumnType::Text);
- builder.addColumnDefinition(Utf8StringLiteral("number"),ColumnType:: Numeric);
+ builder.setTableName("test");
+ builder.addColumn("id", ColumnType::Integer, Contraint::NoConstraint);
+
+ builder.setUseIfNotExists(true);
+
+ ASSERT_THAT(builder.sqlStatement(),
+ "CREATE TABLE IF NOT EXISTS test(id INTEGER)");
}
-const QVector<Internal::ColumnDefinition> CreateTableSqlStatementBuilder::createColumnDefintions()
+TEST_F(CreateTableSqlStatementBuilder, TemporaryTable)
{
- QVector<Internal::ColumnDefinition> columnDefinitions;
- columnDefinitions.append(createColumnDefintion(Utf8StringLiteral("id"), ColumnType::Integer, true));
- columnDefinitions.append(createColumnDefintion(Utf8StringLiteral("name"), ColumnType::Text));
- columnDefinitions.append(createColumnDefintion(Utf8StringLiteral("number"), ColumnType::Numeric));
+ builder.clear();
+ builder.setTableName("test");
+ builder.addColumn("id", ColumnType::Integer, Contraint::NoConstraint);
+
+ builder.setUseTemporaryTable(true);
+
+ ASSERT_THAT(builder.sqlStatement(),
+ "CREATE TEMPORARY TABLE test(id INTEGER)");
+}
- return columnDefinitions;
+void CreateTableSqlStatementBuilder::bindValues()
+{
+ builder.clear();
+ builder.setTableName("test");
+ builder.addColumn("id", ColumnType::Integer, Contraint::PrimaryKey);
+ builder.addColumn("name", ColumnType::Text);
+ builder.addColumn("number",ColumnType:: Numeric);
}
-const Internal::ColumnDefinition CreateTableSqlStatementBuilder::createColumnDefintion(const Utf8String &name, ColumnType type, bool isPrimaryKey)
+SqliteColumns CreateTableSqlStatementBuilder::createColumns()
{
- Internal::ColumnDefinition columnDefinition;
+ SqliteColumns columns;
+ columns.emplace_back("id", ColumnType::Integer, Contraint::PrimaryKey);
+ columns.emplace_back("name", ColumnType::Text);
+ columns.emplace_back("number", ColumnType::Numeric);
- columnDefinition.setName(name);
- columnDefinition.setType(type);
- columnDefinition.setIsPrimaryKey(isPrimaryKey);
+ return columns;
+}
- return columnDefinition;
}
diff --git a/tests/unit/unittest/creator_dependency.pri b/tests/unit/unittest/creator_dependency.pri
index 1932640249..2a960f323e 100644
--- a/tests/unit/unittest/creator_dependency.pri
+++ b/tests/unit/unittest/creator_dependency.pri
@@ -5,18 +5,18 @@ IDE_BIN_PATH=$$PWD
include($$PWD/../../../src/libs/utils/utils-lib.pri)
include($$PWD/../../../src/libs/sqlite/sqlite-lib.pri)
-include($$PWD/../../../src/libs/clangbackendipc/clangbackendipc-lib.pri)
+include($$PWD/../../../src/libs/clangsupport/clangsupport-lib.pri)
include($$PWD/../../../src/plugins/coreplugin/corepluginunittestfiles.pri)
+include($$PWD/../../../src/plugins/projectexplorer/projectexplorerunittestfiles.pri)
include($$PWD/../../../src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri)
include($$PWD/../../../src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri)
include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri)
include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri)
include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri)
include(cplusplus.pri)
-
!isEmpty(LLVM_INSTALL_DIR) {
include($$PWD/../../../src/shared/clang/clang_defines.pri)
-include($$PWD/../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri)
+include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri)
include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)
} else {
DEFINES += CLANG_VERSION=\\\"3.9.1\\\"
diff --git a/tests/unit/unittest/data/complete_smartpointer.cpp b/tests/unit/unittest/data/complete_smartpointer.cpp
new file mode 100644
index 0000000000..1a9bbaf978
--- /dev/null
+++ b/tests/unit/unittest/data/complete_smartpointer.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+namespace std {
+template<class Type, class... Args>
+class unique_ptr {};
+
+template<class Type, class... Args>
+class shared_ptr {};
+
+template<class Type, class... Args>
+unique_ptr<Type> make_unique(Args&&... args);
+
+template<class Type, class... Args>
+shared_ptr<Type> make_shared(Args&&... args);
+} // namespace std
+
+template<class Type>
+class QSharedPointer
+{
+public:
+ template<class... Args>
+ static QSharedPointer<Type> create(Args&&... args);
+};
+
+class Bar
+{
+public:
+ Bar();
+ Bar(int, int);
+};
+void f2()
+{
+ std::unique_ptr<Bar> bar = std::make_unique<Bar>();
+ std::shared_ptr<Bar> bar2 = std::make_shared<Bar>();
+ QSharedPointer<Bar> bar3 = QSharedPointer<Bar>::create();
+}
diff --git a/src/libs/sqlite/tablewriteworker.h b/tests/unit/unittest/data/followsymbol_header.h
index 8ae95c44c3..8630834023 100644
--- a/src/libs/sqlite/tablewriteworker.h
+++ b/tests/unit/unittest/data/followsymbol_header.h
@@ -22,27 +22,38 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
-
#pragma once
-#include "createtablecommand.h"
+#define TEST_DEFINE 1
+namespace Fooish
+{
+float flvalue = 100.f;
-#include <QObject>
+class Bar;
-namespace Internal {
+class Bar {
+public:
+ Bar();
+
+ volatile int member = 0;
+};
-class TableWriteWorker : public QObject
+struct Barish
{
- Q_OBJECT
-public:
- explicit TableWriteWorker(QObject *parent = 0);
- ~TableWriteWorker();
+ int foo(float p, int u);
+ int mem = 10;
+};
+}
- void createTable(const CreateTableCommand &command);
+class FooClass;
-signals:
- void tableCreated();
+int foo(const float p, int u);
-};
+int foo();
+
+int foo(float p, int u)
+{
+ return foo() + p + u;
+}
-} // namespace Internal
+int foo(int x, float y);
diff --git a/src/libs/sqlite/tablewriteworkerproxy.h b/tests/unit/unittest/data/followsymbol_main.cpp
index 0bf481e69d..9b16158e40 100644
--- a/src/libs/sqlite/tablewriteworkerproxy.h
+++ b/tests/unit/unittest/data/followsymbol_main.cpp
@@ -22,42 +22,61 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
+#include "followsymbol_header.h"
+#include "cursor.h"
+Fooish::Bar::Bar() {
-#pragma once
+}
-#include "createtablecommand.h"
+class X;
-#include <QObject>
+using YYY = Fooish::Bar;
-#include <memory>
+int foo() {
+ YYY bar;
+ bar.member = 30;
+ Fooish::Barish barish;
+ bar.member++;
+ barish.mem = Fooish::flvalue;
-QT_BEGIN_NAMESPACE
-class QThread;
-QT_END_NAMESPACE
+ barish.foo(1.f, 2);
+ foo(1, 2.f);
+ return 1;
-class SqliteTable;
+ X* x;
+}
-namespace Internal {
-
-class TableWriteWorker;
+int Fooish::Barish::foo(float p, int u)
+{
+ return ::foo() + p + u;
+}
-class TableWriteWorkerProxy : public QObject
+class FooClass
{
- Q_OBJECT
public:
- explicit TableWriteWorkerProxy();
- ~TableWriteWorkerProxy();
-
- void connectWithWorker(SqliteTable *sqliterTable);
- void disconnectWithWorker(SqliteTable *sqliterTable);
+ FooClass();
+ static int mememember;
+};
- void moveWorkerToThread(QThread *workerThread);
+FooClass::FooClass() {
+ NonFinalStruct nfStruct; nfStruct.function();
+}
-signals:
- void createTable(const CreateTableCommand &command);
+int main() {
+ return foo() + FooClass::mememember + TEST_DEFINE;
+}
-private:
- TableWriteWorker *worker;
+class Bar
+{
+public:
+ int operator&();
+ Bar& operator[](int);
};
-} // namespace Internal
+int Bar::operator&() {
+ return 0;
+}
+
+Bar& Bar::operator[](int) {
+ return *this;
+}
diff --git a/tests/unit/unittest/data/symbolindexing_main1.cpp b/tests/unit/unittest/data/symbolindexing_main1.cpp
new file mode 100644
index 0000000000..58df77916a
--- /dev/null
+++ b/tests/unit/unittest/data/symbolindexing_main1.cpp
@@ -0,0 +1,36 @@
+void function();
+
+void function()
+{
+ int x;
+ x = 20;
+}
+
+template <typename T>
+T templateFunction(T t)
+{
+ return t;
+}
+
+template <>
+int templateFunction(int t)
+{
+ return t;
+}
+
+extern template double templateFunction<double>(double);
+template double templateFunction<double>(double);
+
+template<typename T>
+using TemplateFunctionType = T(&)(T);
+
+
+TemplateFunctionType<int> aliasToTemplateFunction = templateFunction<int>;
+
+void f()
+{
+ aliasToTemplateFunction(1);
+}
+
+void f(int);
+void f(double);
diff --git a/tests/unit/unittest/data/symbolscollector_simple.cpp b/tests/unit/unittest/data/symbolscollector_simple.cpp
new file mode 100644
index 0000000000..494af8c8b4
--- /dev/null
+++ b/tests/unit/unittest/data/symbolscollector_simple.cpp
@@ -0,0 +1,15 @@
+void function();
+void function();
+void function(int x);
+void function()
+{
+ int x;
+ x = 4;
+ int y = 4;
+ y = x + 3;
+}
+
+void f()
+{
+ function();
+}
diff --git a/tests/unit/unittest/data/symbolscollector_unsaved.cpp b/tests/unit/unittest/data/symbolscollector_unsaved.cpp
new file mode 100644
index 0000000000..a57a4e69f7
--- /dev/null
+++ b/tests/unit/unittest/data/symbolscollector_unsaved.cpp
@@ -0,0 +1 @@
+#include "symbolscollector_generated_file.h"
diff --git a/tests/unit/unittest/diagnosticset-test.cpp b/tests/unit/unittest/diagnosticset-test.cpp
index 007c8d2f5f..7f67e8c2ca 100644
--- a/tests/unit/unittest/diagnosticset-test.cpp
+++ b/tests/unit/unittest/diagnosticset-test.cpp
@@ -27,7 +27,7 @@
#include "diagnosticcontainer-matcher.h"
#include "testenvironment.h"
-#include <clangbackendipc_global.h>
+#include <clangsupport_global.h>
#include <clangdocument.h>
#include <diagnosticcontainer.h>
#include <diagnosticset.h>
diff --git a/tests/unit/unittest/dummyclangipcclient.h b/tests/unit/unittest/dummyclangipcclient.h
index a9dca6ead6..3908f9e89f 100644
--- a/tests/unit/unittest/dummyclangipcclient.h
+++ b/tests/unit/unittest/dummyclangipcclient.h
@@ -35,8 +35,7 @@ public:
void alive() override {}
void echo(const ClangBackEnd::EchoMessage &) override {}
void codeCompleted(const ClangBackEnd::CodeCompletedMessage &) override {}
- void translationUnitDoesNotExist(const ClangBackEnd::TranslationUnitDoesNotExistMessage &) override {}
- void projectPartsDoNotExist(const ClangBackEnd::ProjectPartsDoNotExistMessage &) override {}
void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &) override {}
void references(const ClangBackEnd::ReferencesMessage &) override {}
+ void followSymbol(const ClangBackEnd::FollowSymbolMessage &) override {}
};
diff --git a/tests/unit/unittest/google-using-declarations.h b/tests/unit/unittest/google-using-declarations.h
new file mode 100644
index 0000000000..7a1fe3b30f
--- /dev/null
+++ b/tests/unit/unittest/google-using-declarations.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+using testing::_;
+using testing::AllOf;
+using testing::AnyOf;
+using testing::Contains;
+using testing::ElementsAre;
+using testing::Eq;
+using testing::Field;
+using testing::InSequence;
+using testing::IsEmpty;
+using testing::NiceMock;
+using testing::Pair;
+using testing::PrintToString;
+using testing::Property;
+using testing::Return;
+using testing::ReturnRef;
+using testing::Sequence;
+using testing::StrEq;
+using testing::UnorderedElementsAre;
diff --git a/tests/unit/unittest/googletest.h b/tests/unit/unittest/googletest.h
index 1a164bb530..087a5c2bcb 100644
--- a/tests/unit/unittest/googletest.h
+++ b/tests/unit/unittest/googletest.h
@@ -37,3 +37,7 @@
#ifdef CLANG_UNIT_TESTS
# include "gtest-clang-printing.h"
#endif
+
+#include "google-using-declarations.h"
+
+#include "unittest-matchers.h"
diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 5980ec6c63..d7cb22b7ce 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -29,6 +29,8 @@
#include <coreplugin/find/searchresultitem.h>
+#include <projectexplorer/projectmacro.h>
+
namespace Core {
namespace Search {
@@ -54,3 +56,35 @@ void PrintTo(const TextRange &range, ::std::ostream *os)
}
}
+
+namespace ProjectExplorer {
+
+static const char *typeToString(const MacroType &type)
+{
+ switch (type) {
+ case MacroType::Invalid: return "MacroType::Invalid";
+ case MacroType::Define: return "MacroType::Define";
+ case MacroType::Undefine: return "MacroType::Undefine";
+ }
+
+ return "";
+}
+
+std::ostream &operator<<(std::ostream &out, const MacroType &type)
+{
+ out << typeToString(type);
+
+ return out;
+}
+
+std::ostream &operator<<(std::ostream &out, const Macro &macro)
+{
+ out << "("
+ << macro.key.data() << ", "
+ << macro.value.data() << ", "
+ << macro.type << ")";
+
+ return out;
+}
+
+}
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 7792475d8f..92db70f6ed 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -25,6 +25,8 @@
#pragma once
+#include <utils/smallstringio.h>
+
#include <QtGlobal>
#include <iosfwd>
@@ -40,3 +42,13 @@ void PrintTo(const TextRange &range, ::std::ostream *os);
}
}
+
+namespace ProjectExplorer {
+
+enum class MacroType;
+class Macro;
+
+std::ostream &operator<<(std::ostream &out, const MacroType &type);
+std::ostream &operator<<(std::ostream &out, const Macro &macro);
+
+}
diff --git a/tests/unit/unittest/highlightingmarks-test.cpp b/tests/unit/unittest/highlightingmarks-test.cpp
index cbedd9d844..1aeeb734fe 100644
--- a/tests/unit/unittest/highlightingmarks-test.cpp
+++ b/tests/unit/unittest/highlightingmarks-test.cpp
@@ -30,7 +30,7 @@
#include <clangdocuments.h>
#include <clangtranslationunit.h>
#include <cursor.h>
-#include <clangbackendipc_global.h>
+#include <clangsupport_global.h>
#include <clangstring.h>
#include <projectpart.h>
#include <projects.h>
@@ -1184,6 +1184,42 @@ TEST_F(HighlightingMarks, UsingTemplateFunction)
ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Function));
}
+TEST_F(HighlightingMarks, HeaderNameIsInclusion)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(239, 31));
+ ClangBackEnd::HighlightingMarkContainer container(infos[2]);
+ ASSERT_THAT(container.isIncludeDirectivePath(), true);
+}
+
+TEST_F(HighlightingMarks, HeaderNameIsInclusionWithAngleBrackets)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(289, 31));
+ ClangBackEnd::HighlightingMarkContainer container(infos[2]);
+ ASSERT_THAT(container.isIncludeDirectivePath(), true);
+}
+
+
+TEST_F(HighlightingMarks, NotInclusion)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(241, 13));
+ ClangBackEnd::HighlightingMarkContainer container(infos[1]);
+ ASSERT_THAT(container.isIncludeDirectivePath(), false);
+}
+
+TEST_F(HighlightingMarks, MacroIsIdentifier)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(232, 30));
+ ClangBackEnd::HighlightingMarkContainer container(infos[2]);
+ ASSERT_THAT(container.isIdentifier(), true);
+}
+
+TEST_F(HighlightingMarks, DefineIsNotIdentifier)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(232, 30));
+ ClangBackEnd::HighlightingMarkContainer container(infos[1]);
+ ASSERT_THAT(container.isIncludeDirectivePath(), false);
+}
+
Data *HighlightingMarks::d;
void HighlightingMarks::SetUpTestCase()
diff --git a/tests/unit/unittest/includecollector-test.cpp b/tests/unit/unittest/includecollector-test.cpp
index d2c0d06b71..ad405e55d7 100644
--- a/tests/unit/unittest/includecollector-test.cpp
+++ b/tests/unit/unittest/includecollector-test.cpp
@@ -43,7 +43,7 @@ protected:
uint id(const Utils::SmallString &path);
protected:
- ClangBackEnd::StringCache<Utils::PathString> filePathCache;
+ ClangBackEnd::FilePathCache<> filePathCache;
ClangBackEnd::IncludeCollector collector{filePathCache};
ClangBackEnd::IncludeCollector emptyCollector{filePathCache};
Utils::PathStringVector excludePaths = {TESTDATA_DIR "/includecollector_main.h",
diff --git a/tests/unit/unittest/mockclangcodemodelclient.h b/tests/unit/unittest/mockclangcodemodelclient.h
index 0f5a8693bc..2e287909dd 100644
--- a/tests/unit/unittest/mockclangcodemodelclient.h
+++ b/tests/unit/unittest/mockclangcodemodelclient.h
@@ -27,8 +27,8 @@
#include "googletest.h"
-#include <clangbackendipc/clangcodemodelclientinterface.h>
-#include <clangbackendipc/clangcodemodelclientmessages.h>
+#include <clangsupport/clangcodemodelclientinterface.h>
+#include <clangsupport/clangcodemodelclientmessages.h>
class MockClangCodeModelClient : public ClangBackEnd::ClangCodeModelClientInterface
{
@@ -39,12 +39,10 @@ public:
void(const ClangBackEnd::EchoMessage &message));
MOCK_METHOD1(codeCompleted,
void(const ClangBackEnd::CodeCompletedMessage &message));
- MOCK_METHOD1(translationUnitDoesNotExist,
- void(const ClangBackEnd::TranslationUnitDoesNotExistMessage &message));
- MOCK_METHOD1(projectPartsDoNotExist,
- void(const ClangBackEnd::ProjectPartsDoNotExistMessage &message));
MOCK_METHOD1(documentAnnotationsChanged,
void(const ClangBackEnd::DocumentAnnotationsChangedMessage &message));
MOCK_METHOD1(references,
void(const ClangBackEnd::ReferencesMessage &message));
+ MOCK_METHOD1(followSymbol,
+ void(const ClangBackEnd::FollowSymbolMessage &message));
};
diff --git a/tests/unit/unittest/mockclangcodemodelserver.h b/tests/unit/unittest/mockclangcodemodelserver.h
index 6285c48d2c..d1f895d667 100644
--- a/tests/unit/unittest/mockclangcodemodelserver.h
+++ b/tests/unit/unittest/mockclangcodemodelserver.h
@@ -56,6 +56,8 @@ public:
void(const ClangBackEnd::RequestDocumentAnnotationsMessage &message));
MOCK_METHOD1(requestReferences,
void(const ClangBackEnd::RequestReferencesMessage &message));
+ MOCK_METHOD1(requestFollowSymbol,
+ void(const ClangBackEnd::RequestFollowSymbolMessage &message));
MOCK_METHOD1(updateVisibleTranslationUnits,
void(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message));
};
diff --git a/tests/unit/unittest/mockmutex.h b/tests/unit/unittest/mockmutex.h
new file mode 100644
index 0000000000..cccb34e2ff
--- /dev/null
+++ b/tests/unit/unittest/mockmutex.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+class MockMutex
+{
+public:
+ using MutexType = MockMutex;
+
+ MOCK_METHOD0(lock, void ());
+ MOCK_METHOD0(unlock, void ());
+};
diff --git a/tests/unit/unittest/mockrefactoringserver.h b/tests/unit/unittest/mockrefactoringserver.h
index abafc15244..c265f88cbc 100644
--- a/tests/unit/unittest/mockrefactoringserver.h
+++ b/tests/unit/unittest/mockrefactoringserver.h
@@ -44,6 +44,12 @@ public:
MOCK_METHOD1(requestSourceRangesForQueryMessage,
void (const ClangBackEnd::RequestSourceRangesForQueryMessage&));
+ MOCK_METHOD1(updatePchProjectParts,
+ void (const ClangBackEnd::UpdatePchProjectPartsMessage&));
+
+ MOCK_METHOD1(removePchProjectParts,
+ void (const ClangBackEnd::RemovePchProjectPartsMessage&));
+
MOCK_METHOD0(cancel,
void());
@@ -61,4 +67,14 @@ public:
{
requestSourceRangesForQueryMessage(message);
}
+
+ void updatePchProjectParts(ClangBackEnd::UpdatePchProjectPartsMessage &&message) override
+ {
+ updatePchProjectParts(message);
+ }
+
+ void removePchProjectParts(ClangBackEnd::RemovePchProjectPartsMessage &&message) override
+ {
+ removePchProjectParts(message);
+ }
};
diff --git a/tests/unit/unittest/mocksqlitedatabase.h b/tests/unit/unittest/mocksqlitedatabase.h
new file mode 100644
index 0000000000..bad4eefda2
--- /dev/null
+++ b/tests/unit/unittest/mocksqlitedatabase.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include "mockmutex.h"
+
+#include <sqlitetable.h>
+
+#include <utils/smallstringview.h>
+
+class MockSqliteDatabase
+{
+public:
+ using MutexType = MockMutex;
+
+ MockSqliteDatabase() = default;
+ MockSqliteDatabase(const MockMutex &mockMutex)
+ {
+ ON_CALL(*this, databaseMutex())
+ .WillByDefault(ReturnRef(const_cast<MockMutex &>(mockMutex)));
+ }
+
+ MOCK_METHOD1(execute,
+ void (Utils::SmallStringView sqlStatement));
+
+ MOCK_METHOD0(databaseMutex,
+ MockMutex &());
+};
+
diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp
new file mode 100644
index 0000000000..386424386f
--- /dev/null
+++ b/tests/unit/unittest/mocksqlitereadstatement.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "mocksqlitereadstatement.h"
+
+template <>
+std::vector<FilePathIndex> MockSqliteReadStatement::values<FilePathIndex>(std::size_t reserveSize)
+{
+ return valuesReturnStdVectorInt(reserveSize);
+}
+
+template <>
+std::vector<Location>
+MockSqliteReadStatement::values<Location, 3>(std::size_t reserveSize,
+ const Utils::PathString &sourcePath,
+ const uint &line,
+ const uint &column)
+{
+ return valuesReturnStdVectorLocation(reserveSize, sourcePath, line, column);
+}
+
+template <>
+std::vector<Source>
+MockSqliteReadStatement::values<Source, 2>(std::size_t reserveSize, const std::vector<qint64> &sourceIds)
+{
+ return valuesReturnStdVectorSource(reserveSize, sourceIds);
+}
+
+template <>
+Utils::optional<uint32_t>
+MockSqliteReadStatement::value<uint32_t>(const Utils::SmallStringView &text)
+{
+ return valueReturnUInt32(text);
+}
diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h
new file mode 100644
index 0000000000..b97ab1dc7d
--- /dev/null
+++ b/tests/unit/unittest/mocksqlitereadstatement.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <stringcachefwd.h>
+
+#include <sourcelocations.h>
+
+#include "mocksqlitedatabase.h"
+
+#include <utils/optional.h>
+#include <utils/smallstring.h>
+
+#include <cstdint>
+#include <tuple>
+#include <vector>
+
+using std::int64_t;
+using ClangBackEnd::FilePathIndex;
+using Location = ClangRefactoring::SourceLocations::Location;
+using Source = ClangRefactoring::SourceLocations::Source;
+
+class MockSqliteReadStatement
+{
+public:
+ MockSqliteReadStatement() = default;
+ MockSqliteReadStatement(Utils::SmallStringView sqlStatement, MockSqliteDatabase &)
+ : sqlStatement(sqlStatement)
+ {}
+
+ MOCK_CONST_METHOD1(valuesReturnStdVectorInt,
+ std::vector<FilePathIndex>(std::size_t));
+
+ MOCK_CONST_METHOD4(valuesReturnStdVectorLocation,
+ std::vector<Location>(std::size_t, Utils::SmallStringView, qint64, qint64));
+
+ MOCK_CONST_METHOD2(valuesReturnStdVectorSource,
+ std::vector<Source>(std::size_t, const std::vector<qint64> &));
+
+ MOCK_CONST_METHOD1(valueReturnUInt32,
+ Utils::optional<uint32_t>(Utils::SmallStringView));
+
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ typename... QueryType>
+ std::vector<ResultType> values(std::size_t reserveSize, const QueryType&... queryValues);
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ template <typename...> class QueryContainerType,
+ typename QueryElementType>
+ std::vector<ResultType> values(std::size_t reserveSize,
+ const QueryContainerType<QueryElementType> &queryValues);
+
+ template <typename ResultType,
+ typename... QueryTypes>
+ Utils::optional<ResultType> value(const QueryTypes&... queryValues);
+
+public:
+ Utils::SmallString sqlStatement;
+};
+
+template <>
+std::vector<int> MockSqliteReadStatement::values<int>(std::size_t reserveSize);
+
+template <>
+std::vector<Location>
+MockSqliteReadStatement::values<Location, 3>(
+ std::size_t reserveSize,
+ const Utils::PathString &sourcePath,
+ const uint &line,
+ const uint &column);
+
+template <>
+std::vector<Source>
+MockSqliteReadStatement::values<Source, 2>(
+ std::size_t reserveSize,
+ const std::vector<qint64> &);
+
+
+template <>
+Utils::optional<uint32_t>
+MockSqliteReadStatement::value<uint32_t>(const Utils::SmallStringView&);
diff --git a/tests/unit/unittest/mocksqlitewritestatement.h b/tests/unit/unittest/mocksqlitewritestatement.h
new file mode 100644
index 0000000000..98ea4e7e24
--- /dev/null
+++ b/tests/unit/unittest/mocksqlitewritestatement.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "mocksqlitedatabase.h"
+
+#include <utils/smallstring.h>
+
+class MockSqliteWriteStatement
+{
+public:
+ MockSqliteWriteStatement() = default;
+ MockSqliteWriteStatement(Utils::SmallStringView sqlStatement, MockSqliteDatabase &)
+ : sqlStatement(sqlStatement)
+ {}
+
+ MOCK_METHOD0(execute,
+ void ());
+
+ MOCK_METHOD2(bind,
+ void (int index, Utils::SmallStringView value));
+
+ MOCK_METHOD2(bindValues,
+ void (Utils::SmallStringView, Utils::SmallStringView));
+
+ MOCK_METHOD3(write,
+ void (uint, Utils::SmallStringView, Utils::SmallStringView));
+
+ MOCK_METHOD4(write,
+ void (uint, uint, uint, uint));
+
+ MOCK_METHOD2(write,
+ void (uint, Utils::SmallStringView));
+
+ Utils::SmallString sqlStatement;
+};
diff --git a/tests/unit/unittest/mocksymbolindexing.h b/tests/unit/unittest/mocksymbolindexing.h
new file mode 100644
index 0000000000..8a42ebfbc9
--- /dev/null
+++ b/tests/unit/unittest/mocksymbolindexing.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <symbolindexinginterface.h>
+
+class MockSymbolIndexing : public ClangBackEnd::SymbolIndexingInterface
+{
+public:
+ MOCK_METHOD2(updateProjectParts,
+ void(const ClangBackEnd::V2::ProjectPartContainers &projectParts,
+ const ClangBackEnd::V2::FileContainers &generatedFiles));
+
+ void updateProjectParts(ClangBackEnd::V2::ProjectPartContainers &&projectParts,
+ ClangBackEnd::V2::FileContainers &&generatedFiles) override
+ {
+ updateProjectParts(projectParts, generatedFiles);
+ }
+};
+
diff --git a/tests/unit/unittest/mocksymbolscollector.h b/tests/unit/unittest/mocksymbolscollector.h
new file mode 100644
index 0000000000..14f8f6cdf5
--- /dev/null
+++ b/tests/unit/unittest/mocksymbolscollector.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <symbolscollectorinterface.h>
+
+class MockSymbolsCollector : public ClangBackEnd::SymbolsCollectorInterface
+{
+public:
+ MOCK_METHOD0(collectSymbols,
+ void());
+
+ MOCK_METHOD2(addFiles,
+ void(const Utils::PathStringVector &filePaths,
+ const Utils::SmallStringVector &arguments));
+
+ MOCK_METHOD1(addUnsavedFiles,
+ void(const ClangBackEnd::V2::FileContainers &unsavedFiles));
+
+ MOCK_CONST_METHOD0(symbols,
+ const ClangBackEnd::SymbolEntries &());
+
+ MOCK_CONST_METHOD0(sourceLocations,
+ const ClangBackEnd::SourceLocationEntries &());
+};
diff --git a/tests/unit/unittest/mocksymbolstorage.h b/tests/unit/unittest/mocksymbolstorage.h
new file mode 100644
index 0000000000..84bf012f8a
--- /dev/null
+++ b/tests/unit/unittest/mocksymbolstorage.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <symbolstorageinterface.h>
+
+class MockSymbolStorage : public ClangBackEnd::SymbolStorageInterface
+{
+public:
+ MOCK_METHOD2(addSymbolsAndSourceLocations,
+ void(const ClangBackEnd::SymbolEntries &symbolEentries,
+ const ClangBackEnd::SourceLocationEntries &sourceLocations));
+};
diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp
index 763521da42..bb99b3a4aa 100644
--- a/tests/unit/unittest/pchcreator-test.cpp
+++ b/tests/unit/unittest/pchcreator-test.cpp
@@ -51,7 +51,6 @@ using testing::AtLeast;
using testing::ContainerEq;
using testing::Contains;
using testing::ElementsAre;
-using testing::EndsWith;
using testing::Eq;
using testing::Field;
using testing::HasSubstr;
@@ -61,14 +60,15 @@ using testing::Not;
using testing::Property;
using testing::SizeIs;
using testing::UnorderedElementsAre;
+using UnitTests::EndsWith;
class PchCreator: public ::testing::Test
{
protected:
- uint id(const Utils::SmallString &path);
+ ClangBackEnd::FilePathIndex id(const Utils::PathString &path);
protected:
- ClangBackEnd::StringCache<Utils::PathString> filePathCache;
+ ClangBackEnd::FilePathCache<> filePathCache;
PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp";
PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/includecollector_header1.h";
@@ -148,7 +148,7 @@ TEST_F(PchCreatorVerySlowTest, CreateGlobalPchFileContent)
{
auto content = creator.generateGlobalPchHeaderFileContent();
- ASSERT_THAT(content,
+ ASSERT_THAT(std::string(content),
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external3.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external1.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external2.h\"\n")));
@@ -228,7 +228,7 @@ TEST_F(PchCreatorSlowTest, CreateProjectPartPchFileContent)
auto content = creator.generatePchIncludeFileContent(includes);
- ASSERT_THAT(content,
+ ASSERT_THAT(std::string(content),
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector_header2.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external1.h\"\n"),
HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external2.h\"\n")));
@@ -282,7 +282,7 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchsExistsAfterCreation)
creator.generateProjectPartPch(projectPart1);
- ASSERT_TRUE(QFileInfo::exists(creator.generateProjectPathPchHeaderFilePath(projectPart1)));
+ ASSERT_TRUE(QFileInfo::exists(QString(creator.generateProjectPathPchHeaderFilePath(projectPart1))));
}
TEST_F(PchCreatorVerySlowTest, DISABLED_CreatePartPchs)
@@ -340,7 +340,7 @@ TEST_F(PchCreator, CreateProjectPartHeaderAndSourcesContent)
"#include \"" TESTDATA_DIR "/includecollector_main3.cpp\"\n"));
}
-uint PchCreator::id(const Utils::SmallString &path)
+ClangBackEnd::FilePathIndex PchCreator::id(const Utils::PathString &path)
{
return filePathCache.stringId(path);
}
diff --git a/tests/unit/unittest/pchmanagerclient-test.cpp b/tests/unit/unittest/pchmanagerclient-test.cpp
index 6e0ac27101..53a544841d 100644
--- a/tests/unit/unittest/pchmanagerclient-test.cpp
+++ b/tests/unit/unittest/pchmanagerclient-test.cpp
@@ -29,7 +29,7 @@
#include "mockpchmanagerserver.h"
#include <pchmanagerclient.h>
-#include <projectupdater.h>
+#include <pchmanagerprojectupdater.h>
#include <precompiledheadersupdatedmessage.h>
#include <removepchprojectpartsmessage.h>
@@ -49,7 +49,7 @@ protected:
MockPchManagerServer mockPchManagerServer;
ClangPchManager::PchManagerClient client;
MockPchManagerNotifier mockPchManagerNotifier{client};
- ClangPchManager::ProjectUpdater projectUpdater{mockPchManagerServer, client};
+ ClangPchManager::PchManagerProjectUpdater projectUpdater{mockPchManagerServer, client};
Utils::SmallString projectPartId{"projectPartId"};
Utils::SmallString pchFilePath{"/path/to/pch"};
PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone()}}};
@@ -86,7 +86,8 @@ TEST_F(PchManagerClient, Remove)
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString()))
.Times(2);
- projectUpdater.removeProjectParts({projectPartId.clone(), projectPartId.clone()});
+ projectUpdater.removeProjectParts({QString(projectPartId.clone()),
+ QString(projectPartId.clone())});
}
}
diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp
index 8ac039b16a..b9b170e3dc 100644
--- a/tests/unit/unittest/pchmanagerserver-test.cpp
+++ b/tests/unit/unittest/pchmanagerserver-test.cpp
@@ -59,7 +59,7 @@ protected:
NiceMock<MockPchCreator> mockPchCreator;
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
NiceMock<MockProjectParts> mockProjectParts;
- ClangBackEnd::StringCache<Utils::PathString> filePathCache;
+ ClangBackEnd::FilePathCache<> filePathCache;
ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts};
NiceMock<MockPchManagerClient> mockPchManagerClient;
SmallString projectPartId1 = "project1";
diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp
index 39ddc4ff14..071f9ea5db 100644
--- a/tests/unit/unittest/projectupdater-test.cpp
+++ b/tests/unit/unittest/projectupdater-test.cpp
@@ -29,7 +29,7 @@
#include "mockpchmanagernotifier.h"
#include "mockpchmanagerserver.h"
-#include <projectupdater.h>
+#include <pchmanagerprojectupdater.h>
#include <pchmanagerclient.h>
#include <precompiledheadersupdatedmessage.h>
@@ -60,15 +60,15 @@ protected:
ClangPchManager::PchManagerClient pchManagerClient;
MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient};
NiceMock<MockPchManagerServer> mockPchManagerServer;
- ClangPchManager::ProjectUpdater updater{mockPchManagerServer, pchManagerClient};
+ ClangPchManager::ProjectUpdater updater{mockPchManagerServer};
Utils::SmallString projectPartId{"project1"};
Utils::SmallString projectPartId2{"project2"};
Utils::PathStringVector headerPaths = {"/path/to/header1.h", "/path/to/header2.h"};
Utils::PathStringVector sourcePaths = {"/path/to/source1.cpp", "/path/to/source2.cpp"};
- CppTools::ProjectFile header1ProjectFile{headerPaths[0], CppTools::ProjectFile::CXXHeader};
- CppTools::ProjectFile header2ProjectFile{headerPaths[1], CppTools::ProjectFile::CXXHeader};
- CppTools::ProjectFile source1ProjectFile{sourcePaths[0], CppTools::ProjectFile::CXXSource};
- CppTools::ProjectFile source2ProjectFile{sourcePaths[1], CppTools::ProjectFile::CXXSource};
+ CppTools::ProjectFile header1ProjectFile{QString(headerPaths[0]), CppTools::ProjectFile::CXXHeader};
+ CppTools::ProjectFile header2ProjectFile{QString(headerPaths[1]), CppTools::ProjectFile::CXXHeader};
+ CppTools::ProjectFile source1ProjectFile{QString(sourcePaths[0]), CppTools::ProjectFile::CXXSource};
+ CppTools::ProjectFile source2ProjectFile{QString(sourcePaths[1]), CppTools::ProjectFile::CXXSource};
CppTools::ProjectPart projectPart;
ProjectPartContainer expectedContainer;
FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}};
@@ -87,22 +87,23 @@ TEST_F(ProjectUpdater, CallUpdatePchProjectParts)
TEST_F(ProjectUpdater, CallRemovePchProjectParts)
{
- EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(_)).Times(AnyNumber());
+
ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}};
EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message));
- updater.removeProjectParts({projectPartId, projectPartId2});
+ updater.removeProjectParts({QString(projectPartId), QString(projectPartId2)});
}
-TEST_F(ProjectUpdater, CallPrecompiledHeaderRemoved)
+TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater)
{
+ ClangPchManager::PchManagerProjectUpdater pchUpdater{mockPchManagerServer, pchManagerClient};
ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}};
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString()));
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString()));
- updater.removeProjectParts({projectPartId, projectPartId2});
+ pchUpdater.removeProjectParts({QString(projectPartId), QString(projectPartId2)});
}
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)
@@ -134,7 +135,7 @@ void ProjectUpdater::SetUp()
projectPart.files.push_back(header2ProjectFile);
projectPart.files.push_back(source1ProjectFile);
projectPart.files.push_back(source2ProjectFile);
- projectPart.displayName = projectPartId;
+ projectPart.displayName = QString(projectPartId);
Utils::SmallStringVector arguments{ClangPchManager::ProjectUpdater::compilerArguments(
&projectPart)};
diff --git a/src/plugins/debugger/gdb/termgdbadapter.h b/tests/unit/unittest/querysqlitestatementfactory-test.cpp
index 73a2413637..d751cea6da 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.h
+++ b/tests/unit/unittest/querysqlitestatementfactory-test.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,45 +23,40 @@
**
****************************************************************************/
-#pragma once
+#include "googletest.h"
-#include "gdbengine.h"
+#include "mocksqlitedatabase.h"
+#include "mocksqlitereadstatement.h"
+#include "mocksqlitewritestatement.h"
-#include <utils/consoleprocess.h>
+#include <querysqlitestatementfactory.h>
-namespace Debugger {
-namespace Internal {
+namespace {
-///////////////////////////////////////////////////////////////////////
-//
-// TermGdbAdapter
-//
-///////////////////////////////////////////////////////////////////////
+using StatementFactory = ClangRefactoring::QuerySqliteStatementFactory<MockSqliteDatabase,
+ MockSqliteReadStatement>;
-class GdbTermEngine : public GdbEngine
+class QuerySqliteStatementFactory : public testing::Test
{
- Q_OBJECT
-
-public:
- explicit GdbTermEngine(bool useTerminal);
- ~GdbTermEngine() override;
-
-private:
- void setupEngine() override;
- void handleGdbStartFailed() override;
- void setupInferior() override;
- void runEngine() override;
- void interruptInferior2() override;
- void shutdownEngine() override;
-
- void handleStubAttached(const DebuggerResponse &response);
-
- void stubStarted();
- void stubExited();
- void stubError(const QString &msg);
-
- Utils::ConsoleProcess m_stubProc;
+protected:
+ MockSqliteDatabase mockDatabase;
+ StatementFactory factory{mockDatabase};
};
-} // namespace Internal
-} // namespace Debugger
+TEST_F(QuerySqliteStatementFactory, SelectLocationsForSymbolLocation)
+{
+ ASSERT_THAT(factory.selectLocationsForSymbolLocation.sqlStatement,
+ "SELECT sourceId, line, column FROM locations WHERE symbolId = "
+ " (SELECT symbolId FROM locations WHERE sourceId="
+ " (SELECT sourceId FROM sources WHERE sourcePath =?)"
+ " AND line=? AND column=?) "
+ "ORDER BY sourceId, line, column");
+}
+
+TEST_F(QuerySqliteStatementFactory, SelectSourcePathForId)
+{
+ ASSERT_THAT(factory.selectSourcePathForId.sqlStatement,
+ "SELECT sourceId, sourcePath FROM sources WHERE sourceId = ?");
+}
+
+}
diff --git a/tests/unit/unittest/readandwritemessageblock-test.cpp b/tests/unit/unittest/readandwritemessageblock-test.cpp
index a95e2866b4..445743543a 100644
--- a/tests/unit/unittest/readandwritemessageblock-test.cpp
+++ b/tests/unit/unittest/readandwritemessageblock-test.cpp
@@ -203,6 +203,14 @@ TEST_F(ReadAndWriteMessageBlock, CompareRequestReferences)
CompareMessage(ClangBackEnd::RequestReferencesMessage{fileContainer, 13, 37});
}
+TEST_F(ReadAndWriteMessageBlock, CompareRequestFollowSymbol)
+{
+ QVector<Utf8String> dependentFiles;
+ dependentFiles.push_back(QString("somefile.cpp"));
+ dependentFiles.push_back(QString("otherfile.cpp"));
+ CompareMessage(ClangBackEnd::RequestFollowSymbolMessage{fileContainer, dependentFiles, 13, 37});
+}
+
TEST_F(ReadAndWriteMessageBlock, CompareReferences)
{
const QVector<ClangBackEnd::SourceRangeContainer> references{
diff --git a/tests/unit/unittest/refactoringclient-test.cpp b/tests/unit/unittest/refactoringclient-test.cpp
index 5bbcb8178f..8935f0968a 100644
--- a/tests/unit/unittest/refactoringclient-test.cpp
+++ b/tests/unit/unittest/refactoringclient-test.cpp
@@ -125,9 +125,7 @@ TEST_F(RefactoringClient, AfterSourceLocationsForRenamingEngineIsUsableAgain)
TEST_F(RefactoringClient, AfterStartLocalRenameHasValidCallback)
{
- engine.startLocalRenaming(cursor,
- filePath,
- textDocument.revision(),
+ engine.startLocalRenaming(CppTools::CursorInEditor{cursor, filePath},
projectPart.data(),
[&] (const QString &,
const ClangBackEnd::SourceLocationsContainer &,
diff --git a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp
index aaac7c1433..f1ce7a9f5f 100644
--- a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp
+++ b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp
@@ -47,6 +47,11 @@ using ::testing::Args;
using ::testing::Property;
using ::testing::Eq;
+using ClangBackEnd::UpdatePchProjectPartsMessage;
+using ClangBackEnd::V2::FileContainer;
+using ClangBackEnd::V2::ProjectPartContainer;
+using ClangBackEnd::RemovePchProjectPartsMessage;
+
class RefactoringClientServerInProcess : public ::testing::Test
{
protected:
@@ -169,6 +174,31 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesForQueryMessage)
scheduleServerMessages();
}
+TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage)
+{
+ ProjectPartContainer projectPart2{"projectPartId",
+ {"-x", "c++-header", "-Wno-pragma-once-outside-header"},
+ {TESTDATA_DIR "/includecollector_header.h"},
+ {TESTDATA_DIR "/includecollector_main.cpp"}};
+ FileContainer fileContainer{{"/path/to/", "file"}, "content", {}};
+ UpdatePchProjectPartsMessage message{{projectPart2}, {fileContainer}};
+
+ EXPECT_CALL(mockRefactoringServer, updatePchProjectParts(message));
+
+ serverProxy.updatePchProjectParts(message.clone());
+ scheduleServerMessages();
+}
+
+TEST_F(RefactoringClientServerInProcess, SendRemovePchProjectPartsMessage)
+{
+ RemovePchProjectPartsMessage message{{"projectPartId1", "projectPartId2"}};
+
+ EXPECT_CALL(mockRefactoringServer, removePchProjectParts(message));
+
+ serverProxy.removePchProjectParts(message.clone());
+ scheduleServerMessages();
+}
+
TEST_F(RefactoringClientServerInProcess, CancelMessage)
{
EXPECT_CALL(mockRefactoringServer, cancel());
diff --git a/tests/unit/unittest/refactoringcompilationdatabase-test.cpp b/tests/unit/unittest/refactoringcompilationdatabase-test.cpp
index 84f426cacd..50d7773a63 100644
--- a/tests/unit/unittest/refactoringcompilationdatabase-test.cpp
+++ b/tests/unit/unittest/refactoringcompilationdatabase-test.cpp
@@ -69,7 +69,7 @@ TEST_F(RefactoringCompilationDatabase, GetAllFilesContainsTranslationUnit)
{
auto filePaths = database.getAllFiles();
- ASSERT_THAT(filePaths, Contains(temporarySourceFilePath));
+ ASSERT_THAT(filePaths, Contains(std::string(temporarySourceFilePath)));
}
TEST_F(RefactoringCompilationDatabase, CompileCommandForFilePath)
@@ -94,12 +94,12 @@ TEST_F(RefactoringCompilationDatabase, FilePaths)
{
auto filePaths = database.getAllFiles();
- ASSERT_THAT(filePaths, Contains(temporarySourceFilePath));
+ ASSERT_THAT(filePaths, Contains(std::string(temporarySourceFilePath)));
}
void RefactoringCompilationDatabase::SetUp()
{
- database.addFile(temporaryDirectoryPath, "data.cpp", {"cc", "data.cpp", "-DNO_DEBUG"});
+ database.addFile(std::string(temporaryDirectoryPath), "data.cpp", {"cc", "data.cpp", "-DNO_DEBUG"});
}
}
diff --git a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
new file mode 100644
index 0000000000..3f1c52a021
--- /dev/null
+++ b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include <mocksqlitedatabase.h>
+
+#include <refactoringdatabaseinitializer.h>
+
+namespace {
+
+using Initializer = ClangBackEnd::RefactoringDatabaseInitializer<NiceMock<MockSqliteDatabase>>;
+
+using Sqlite::Table;
+
+class RefactoringDatabaseInitializer : public testing::Test
+{
+protected:
+ NiceMock<MockMutex> mockMutex;
+ NiceMock<MockSqliteDatabase> mockDatabase{mockMutex};
+ Initializer initializer{mockDatabase};
+};
+
+TEST_F(RefactoringDatabaseInitializer, AddSymbolsTable)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
+
+ initializer.createSymbolsTable();
+}
+
+TEST_F(RefactoringDatabaseInitializer, AddLocationsTable)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
+
+ initializer.createLocationsTable();
+}
+
+TEST_F(RefactoringDatabaseInitializer, AddSourcesTable)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
+
+ initializer.createSourcesTable();
+}
+
+
+TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ Initializer initializer{mockDatabase};
+}
+}
diff --git a/tests/unit/unittest/refactoringengine-test.cpp b/tests/unit/unittest/refactoringengine-test.cpp
index 5383841d8a..a4f7d32d04 100644
--- a/tests/unit/unittest/refactoringengine-test.cpp
+++ b/tests/unit/unittest/refactoringengine-test.cpp
@@ -86,14 +86,16 @@ TEST_F(RefactoringEngine, SendRequestSourceLocationsForRenamingMessage)
EXPECT_CALL(mockRefactoringServer, requestSourceLocationsForRenamingMessage(message))
.Times(1);
- engine.startLocalRenaming(cursor, filePath, textDocument.revision(), projectPart.data(), {});
+ engine.startLocalRenaming(CppTools::CursorInEditor{cursor, filePath},
+ projectPart.data(), {});
}
TEST_F(RefactoringEngine, AfterSendRequestSourceLocationsForRenamingMessageIsUnusable)
{
EXPECT_CALL(mockRefactoringServer, requestSourceLocationsForRenamingMessage(_));
- engine.startLocalRenaming(cursor, filePath, textDocument.revision(), projectPart.data(), {});
+ engine.startLocalRenaming(CppTools::CursorInEditor{cursor, filePath},
+ projectPart.data(), {});
ASSERT_FALSE(engine.isUsable());
}
@@ -127,12 +129,12 @@ void RefactoringEngine::SetUp()
projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
projectPart->files.push_back(projectFile);
- commandLine = Utils::SmallStringVector(ClangCompilerOptionsBuilder::build(
- projectPart.data(),
- projectFile.kind,
- CppTools::CompilerOptionsBuilder::PchUsage::None,
+ ClangCompilerOptionsBuilder clangCOBuilder(*projectPart,
CLANG_VERSION,
- CLANG_RESOURCE_DIR));
+ CLANG_RESOURCE_DIR);
+ commandLine = Utils::SmallStringVector(clangCOBuilder.build(
+ projectFile.kind,
+ CppTools::CompilerOptionsBuilder::PchUsage::None));
commandLine.push_back(qStringFilePath);
}
diff --git a/tests/unit/unittest/refactoringserver-test.cpp b/tests/unit/unittest/refactoringserver-test.cpp
index b07d490a12..8b2586ba0b 100644
--- a/tests/unit/unittest/refactoringserver-test.cpp
+++ b/tests/unit/unittest/refactoringserver-test.cpp
@@ -27,6 +27,7 @@
#include "filesystem-utilities.h"
#include "mockrefactoringclient.h"
+#include "mocksymbolindexing.h"
#include "sourcerangecontainer-matcher.h"
#include <refactoringserver.h>
@@ -57,6 +58,9 @@ using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage;
using ClangBackEnd::SourceRangesForQueryMessage;
using ClangBackEnd::SourceRangesContainer;
using ClangBackEnd::V2::FileContainer;
+using ClangBackEnd::V2::FileContainers;
+using ClangBackEnd::V2::ProjectPartContainer;
+using ClangBackEnd::V2::ProjectPartContainers;
MATCHER_P2(IsSourceLocation, line, column,
std::string(negation ? "isn't " : "is ")
@@ -76,8 +80,10 @@ protected:
void TearDown() override;
protected:
- ClangBackEnd::RefactoringServer refactoringServer;
NiceMock<MockRefactoringClient> mockRefactoringClient;
+ NiceMock<MockSymbolIndexing> mockSymbolIndexing;
+ ClangBackEnd::FilePathCache<std::mutex> filePathCache;
+ ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, filePathCache};
Utils::SmallString sourceContent{"void f()\n {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(),
@@ -283,6 +289,23 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message));
}
+TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectParts)
+{
+ ProjectPartContainers projectParts{{{"projectPartId",
+ {"-I", TESTDATA_DIR},
+ {"header1.h"},
+ {"main.cpp"}}}};
+ FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
+ "void f();",
+ {}}};
+
+
+ EXPECT_CALL(mockSymbolIndexing,
+ updateProjectParts(projectParts, unsaved));
+
+ refactoringServer.updatePchProjectParts({Utils::clone(projectParts), Utils::clone(unsaved)});
+}
+
void RefactoringServer::SetUp()
{
temporaryFile.open();
diff --git a/tests/unit/unittest/smallstring-test.cpp b/tests/unit/unittest/smallstring-test.cpp
index 29c4063542..345480182b 100644
--- a/tests/unit/unittest/smallstring-test.cpp
+++ b/tests/unit/unittest/smallstring-test.cpp
@@ -286,21 +286,21 @@ TEST(SmallString, LongSmallStringHasShortSmallStringSizeZero)
ASSERT_THAT(longText.shortStringSize(), 0);
}
-TEST(SmallString, BeginIsEqualEndForEmptySmallString)
+TEST(SmallString, SmallStringBeginIsEqualEndForEmptySmallString)
{
SmallString text;
ASSERT_THAT(text.begin(), Eq(text.end()));
}
-TEST(SmallString, BeginIsNotEqualEndForNonEmptySmallString)
+TEST(SmallString, SmallStringBeginIsNotEqualEndForNonEmptySmallString)
{
SmallString text("x");
ASSERT_THAT(text.begin(), Ne(text.end()));
}
-TEST(SmallString, BeginPlusOneIsEqualEndForSmallStringWidthSizeOne)
+TEST(SmallString, SmallStringBeginPlusOneIsEqualEndForSmallStringWidthSizeOne)
{
SmallString text("x");
@@ -309,21 +309,21 @@ TEST(SmallString, BeginPlusOneIsEqualEndForSmallStringWidthSizeOne)
ASSERT_THAT(beginPlusOne, Eq(text.end()));
}
-TEST(SmallString, RBeginIsEqualREndForEmptySmallString)
+TEST(SmallString, SmallStringRBeginIsEqualREndForEmptySmallString)
{
SmallString text;
ASSERT_THAT(text.rbegin(), Eq(text.rend()));
}
-TEST(SmallString, RBeginIsNotEqualREndForNonEmptySmallString)
+TEST(SmallString, SmallStringRBeginIsNotEqualREndForNonEmptySmallString)
{
SmallString text("x");
ASSERT_THAT(text.rbegin(), Ne(text.rend()));
}
-TEST(SmallString, RBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
+TEST(SmallString, SmallStringRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
{
SmallString text("x");
@@ -332,21 +332,21 @@ TEST(SmallString, RBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
ASSERT_THAT(beginPlusOne, Eq(text.rend()));
}
-TEST(SmallString, ConstRBeginIsEqualREndForEmptySmallString)
+TEST(SmallString, SmallStringConstRBeginIsEqualREndForEmptySmallString)
{
const SmallString text;
ASSERT_THAT(text.rbegin(), Eq(text.rend()));
}
-TEST(SmallString, ConstRBeginIsNotEqualREndForNonEmptySmallString)
+TEST(SmallString, SmallStringConstRBeginIsNotEqualREndForNonEmptySmallString)
{
const SmallString text("x");
ASSERT_THAT(text.rbegin(), Ne(text.rend()));
}
-TEST(SmallString, ConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
+TEST(SmallString, SmallStringSmallStringConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
{
const SmallString text("x");
@@ -355,6 +355,273 @@ TEST(SmallString, ConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
ASSERT_THAT(beginPlusOne, Eq(text.rend()));
}
+TEST(SmallString, SmallStringDistanceBetweenBeginAndEndIsZeroForEmptyText)
+{
+ SmallString text("");
+
+ auto distance = std::distance(text.begin(), text.end());
+
+ ASSERT_THAT(distance, 0);
+}
+
+TEST(SmallString, SmallStringDistanceBetweenBeginAndEndIsOneForOneSign)
+{
+ SmallString text("x");
+
+ auto distance = std::distance(text.begin(), text.end());
+
+ ASSERT_THAT(distance, 1);
+}
+
+TEST(SmallString, SmallStringDistanceBetweenRBeginAndREndIsZeroForEmptyText)
+{
+ SmallString text("");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 0);
+}
+
+TEST(SmallString, SmallStringDistanceBetweenRBeginAndREndIsOneForOneSign)
+{
+ SmallString text("x");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 1);
+}
+
+TEST(SmallString, SmallStringBeginPointsToX)
+{
+ SmallString text("x");
+
+ auto sign = *text.begin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, SmallStringRBeginPointsToX)
+{
+ SmallString text("x");
+
+ auto sign = *text.rbegin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, ConstSmallStringBeginPointsToX)
+{
+ const SmallString text("x");
+
+ auto sign = *text.begin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, ConstSmallStringRBeginPointsToX)
+{
+ const SmallString text("x");
+
+ auto sign = *text.rbegin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, SmallStringViewBeginIsEqualEndForEmptySmallString)
+{
+ SmallStringView text{""};
+
+ ASSERT_THAT(text.begin(), Eq(text.end()));
+}
+
+TEST(SmallString, SmallStringViewBeginIsNotEqualEndForNonEmptySmallString)
+{
+ SmallStringView text("x");
+
+ ASSERT_THAT(text.begin(), Ne(text.end()));
+}
+
+TEST(SmallString, SmallStringViewBeginPlusOneIsEqualEndForSmallStringWidthSizeOne)
+{
+ SmallStringView text("x");
+
+ auto beginPlusOne = text.begin() + std::size_t(1);
+
+ ASSERT_THAT(beginPlusOne, Eq(text.end()));
+}
+
+TEST(SmallString, SmallStringViewRBeginIsEqualREndForEmptySmallString)
+{
+ SmallStringView text{""};
+
+ ASSERT_THAT(text.rbegin(), Eq(text.rend()));
+}
+
+TEST(SmallString, SmallStringViewRBeginIsNotEqualREndForNonEmptySmallString)
+{
+ SmallStringView text("x");
+
+ ASSERT_THAT(text.rbegin(), Ne(text.rend()));
+}
+
+TEST(SmallString, SmallStringViewRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
+{
+ SmallStringView text("x");
+
+ auto beginPlusOne = text.rbegin() + 1l;
+
+ ASSERT_THAT(beginPlusOne, Eq(text.rend()));
+}
+
+TEST(SmallString, SmallStringViewConstRBeginIsEqualREndForEmptySmallString)
+{
+ const SmallStringView text{""};
+
+ ASSERT_THAT(text.rbegin(), Eq(text.rend()));
+}
+
+TEST(SmallString, SmallStringViewConstRBeginIsNotEqualREndForNonEmptySmallString)
+{
+ const SmallStringView text("x");
+
+ ASSERT_THAT(text.rbegin(), Ne(text.rend()));
+}
+
+TEST(SmallString, SmallStringViewConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne)
+{
+ const SmallStringView text("x");
+
+ auto beginPlusOne = text.rbegin() + 1l;
+
+ ASSERT_THAT(beginPlusOne, Eq(text.rend()));
+}
+
+TEST(SmallString, SmallStringViewDistanceBetweenBeginAndEndIsZeroForEmptyText)
+{
+ SmallStringView text("");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 0);
+}
+
+TEST(SmallString, SmallStringViewDistanceBetweenBeginAndEndIsOneForOneSign)
+{
+ SmallStringView text("x");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 1);
+}
+
+TEST(SmallString, SmallStringViewDistanceBetweenRBeginAndREndIsZeroForEmptyText)
+{
+ SmallStringView text("");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 0);
+}
+
+TEST(SmallString, SmallStringViewDistanceBetweenRBeginAndREndIsOneForOneSign)
+{
+ SmallStringView text("x");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 1);
+}
+
+TEST(SmallString, ConstSmallStringViewDistanceBetweenBeginAndEndIsZeroForEmptyText)
+{
+ const SmallStringView text("");
+
+ auto distance = std::distance(text.begin(), text.end());
+
+ ASSERT_THAT(distance, 0);
+}
+
+TEST(SmallString, ConstSmallStringViewDistanceBetweenBeginAndEndIsOneForOneSign)
+{
+ const SmallStringView text("x");
+
+ auto distance = std::distance(text.begin(), text.end());
+
+ ASSERT_THAT(distance, 1);
+}
+
+TEST(SmallString, ConstSmallStringViewDistanceBetweenRBeginAndREndIsZeroForEmptyText)
+{
+ const SmallStringView text("");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 0);
+}
+
+TEST(SmallString, ConstSmallStringViewDistanceBetweenRBeginAndREndIsOneForOneSign)
+{
+ const SmallStringView text("x");
+
+ auto distance = std::distance(text.rbegin(), text.rend());
+
+ ASSERT_THAT(distance, 1);
+}
+
+TEST(SmallString, SmallStringViewBeginPointsToX)
+{
+ SmallStringView text("x");
+
+ auto sign = *text.begin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, SmallStringViewRBeginPointsToX)
+{
+ SmallStringView text("x");
+
+ auto sign = *text.rbegin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, ConstSmallStringViewBeginPointsToX)
+{
+ const SmallStringView text("x");
+
+ auto sign = *text.begin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, ConstSmallStringViewRBeginPointsToX)
+{
+ const SmallStringView text("x");
+
+ auto sign = *text.rbegin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, SmallStringLiteralViewRBeginPointsToX)
+{
+ SmallStringLiteral text("x");
+
+ auto sign = *text.rbegin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
+TEST(SmallString, ConstSmallStringLiteralViewRBeginPointsToX)
+{
+ const SmallStringLiteral text("x");
+
+ auto sign = *text.rbegin();
+
+ ASSERT_THAT(sign, 'x');
+}
+
TEST(SmallString, ConstructorStandardString)
{
std::string stdStringText = "short string";
@@ -731,6 +998,18 @@ TEST(SmallString, IsEmpty)
ASSERT_TRUE(SmallString().isEmpty());
}
+TEST(SmallString, StringViewIsEmpty)
+{
+ ASSERT_FALSE(SmallStringView("text").isEmpty());
+ ASSERT_TRUE(SmallStringView("").isEmpty());
+}
+
+TEST(SmallString, StringViewEmpty)
+{
+ ASSERT_FALSE(SmallStringView("text").empty());
+ ASSERT_TRUE(SmallStringView("").empty());
+}
+
TEST(SmallString, HasContent)
{
ASSERT_TRUE(SmallString("text").hasContent());
@@ -747,6 +1026,42 @@ TEST(SmallString, Clear)
ASSERT_TRUE(text.isEmpty());
}
+TEST(SmallString, NoOccurrencesForEmptyText)
+{
+ SmallString text;
+
+ auto occurrences = text.countOccurrence("text");
+
+ ASSERT_THAT(occurrences, 0);
+}
+
+TEST(SmallString, NoOccurrencesInText)
+{
+ SmallString text("here is some text, here is some text, here is some text");
+
+ auto occurrences = text.countOccurrence("texts");
+
+ ASSERT_THAT(occurrences, 0);
+}
+
+TEST(SmallString, SomeOccurrences)
+{
+ SmallString text("here is some text, here is some text, here is some text");
+
+ auto occurrences = text.countOccurrence("text");
+
+ ASSERT_THAT(occurrences, 3);
+}
+
+TEST(SmallString, SomeMoreOccurrences)
+{
+ SmallString text("texttexttext");
+
+ auto occurrences = text.countOccurrence("text");
+
+ ASSERT_THAT(occurrences, 3);
+}
+
TEST(SmallString, ReplaceWithCharacter)
{
SmallString text("here is some text, here is some text, here is some text");
@@ -823,9 +1138,9 @@ TEST(SmallString, ReplaceLongSmallStringWithLongerText)
{
SmallString text = SmallString::fromUtf8("some very very very very very very very very very very very long string");
- text.replace("some", "much more");
+ text.replace("long", "much much much much much much much much much much much much much much much much much much more");
- ASSERT_THAT(text, Eq(SmallString("much more very very very very very very very very very very very long string")));
+ ASSERT_THAT(text, "some very very very very very very very very very very very much much much much much much much much much much much much much much much much much much more string");
}
TEST(SmallString, MultipleReplaceSmallStringWithLongerText)
@@ -855,11 +1170,41 @@ TEST(SmallString, DontReplaceReplacedText)
ASSERT_THAT(text, SmallString("here is some foofoo text"));
}
+TEST(SmallString, DontReserveIfNothingIsReplacedForLongerReplacementText)
+{
+ SmallString text("here is some text with some longer text");
+
+ text.replace("bar", "foofoo");
+
+ ASSERT_TRUE(text.isReadOnlyReference());
+}
+
+TEST(SmallString, DontReserveIfNothingIsReplacedForShorterReplacementText)
+{
+ SmallString text("here is some text with some longer text");
+
+ text.replace("foofoo", "bar");
+
+ ASSERT_TRUE(text.isReadOnlyReference());
+}
TEST(SmallString, StartsWith)
{
SmallString text("$column");
+ ASSERT_FALSE(text.startsWith("$columnxxx"));
+ ASSERT_TRUE(text.startsWith("$column"));
+ ASSERT_TRUE(text.startsWith("$col"));
+ ASSERT_FALSE(text.startsWith("col"));
+ ASSERT_TRUE(text.startsWith('$'));
+ ASSERT_FALSE(text.startsWith('@'));
+}
+
+TEST(SmallString, StartsWithStringView)
+{
+ SmallStringView text("$column");
+
+ ASSERT_FALSE(text.startsWith("$columnxxx"));
ASSERT_TRUE(text.startsWith("$column"));
ASSERT_TRUE(text.startsWith("$col"));
ASSERT_FALSE(text.startsWith("col"));
@@ -895,6 +1240,15 @@ TEST(SmallString, ReserveSmallerThanShortStringCapacity)
ASSERT_THAT(text.capacity(), AnyOf(30, 4));
}
+TEST(SmallString, ReserveSmallerThanShortStringCapacityIsShortString)
+{
+ SmallString text("text");
+
+ text.reserve(2);
+
+ ASSERT_TRUE(text.isShortString());
+}
+
TEST(SmallString, ReserveSmallerThanReference)
{
SmallString text("some very very very very very very very very very very very long string");
@@ -986,13 +1340,13 @@ TEST(SmallString, OptimalHeapCacheLineForSize)
ASSERT_THAT(SmallString::optimalHeapCapacity(191), 192);
ASSERT_THAT(SmallString::optimalHeapCapacity(193), 256);
ASSERT_THAT(SmallString::optimalHeapCapacity(255), 256);
- ASSERT_THAT(SmallString::optimalHeapCapacity(257), 384);
- ASSERT_THAT(SmallString::optimalHeapCapacity(257), 384);
+ ASSERT_THAT(SmallString::optimalHeapCapacity(256), 256);
+ ASSERT_THAT(SmallString::optimalHeapCapacity(257), 320);
ASSERT_THAT(SmallString::optimalHeapCapacity(383), 384);
- ASSERT_THAT(SmallString::optimalHeapCapacity(385), 512);
+ ASSERT_THAT(SmallString::optimalHeapCapacity(385), 448);
ASSERT_THAT(SmallString::optimalHeapCapacity(4095), 4096);
ASSERT_THAT(SmallString::optimalHeapCapacity(4096), 4096);
- ASSERT_THAT(SmallString::optimalHeapCapacity(4097), 6144);
+ ASSERT_THAT(SmallString::optimalHeapCapacity(4097), 4160);
}
TEST(SmallString, OptimalCapacityForSize)
@@ -1256,3 +1610,72 @@ TEST(SmallString, InitializerListNullTerminated)
ASSERT_THAT(end, '\0');
}
+
+TEST(SmallString, NumberToString)
+{
+ ASSERT_THAT(SmallString::number(-0), "0");
+ ASSERT_THAT(SmallString::number(1), "1");
+ ASSERT_THAT(SmallString::number(-1), "-1");
+ ASSERT_THAT(SmallString::number(std::numeric_limits<int>::max()), "2147483647");
+ ASSERT_THAT(SmallString::number(std::numeric_limits<int>::min()), "-2147483648");
+ ASSERT_THAT(SmallString::number(std::numeric_limits<long long int>::max()), "9223372036854775807");
+ ASSERT_THAT(SmallString::number(std::numeric_limits<long long int>::min()), "-9223372036854775808");
+ ASSERT_THAT(SmallString::number(1.2), "1.200000");
+ ASSERT_THAT(SmallString::number(-1.2), "-1.200000");
+}
+
+TEST(SmallString, StringViewPlusOperator)
+{
+ SmallStringView text = "text";
+
+ auto result = text + " and more text";
+
+ ASSERT_THAT(result, "text and more text");
+}
+
+TEST(SmallString, StringPlusOperator)
+{
+ SmallString text = "text";
+
+ auto result = text + " and more text";
+
+ ASSERT_THAT(result, "text and more text");
+}
+
+TEST(SmallString, ShortStringCapacity)
+{
+ ASSERT_THAT(SmallString().shortStringCapacity(), 30);
+ ASSERT_THAT(PathString().shortStringCapacity(), 189);
+}
+
+TEST(SmallString, ToView)
+{
+ SmallString text = "text";
+
+ auto view = text.toView();
+
+ ASSERT_THAT(view, "text");
+
+}
+
+TEST(SmallString, Compare)
+{
+ ASSERT_THAT(Utils::compare("", ""), Eq(0));
+ ASSERT_THAT(Utils::compare("text", "text"), Eq(0));
+ ASSERT_THAT(Utils::compare("", "text"), Le(0));
+ ASSERT_THAT(Utils::compare("textx", "text"), Gt(0));
+ ASSERT_THAT(Utils::compare("text", "textx"), Le(0));
+ ASSERT_THAT(Utils::compare("textx", "texta"), Gt(0));
+ ASSERT_THAT(Utils::compare("texta", "textx"), Le(0));
+}
+
+TEST(SmallString, ReverseCompare)
+{
+ ASSERT_THAT(Utils::reverseCompare("", ""), Eq(0));
+ ASSERT_THAT(Utils::reverseCompare("text", "text"), Eq(0));
+ ASSERT_THAT(Utils::reverseCompare("", "text"), Le(0));
+ ASSERT_THAT(Utils::reverseCompare("textx", "text"), Gt(0));
+ ASSERT_THAT(Utils::reverseCompare("text", "textx"), Le(0));
+ ASSERT_THAT(Utils::reverseCompare("textx", "texta"), Gt(0));
+ ASSERT_THAT(Utils::reverseCompare("texta", "textx"), Le(0));
+}
diff --git a/tests/unit/unittest/sourcerangeextractor-test.cpp b/tests/unit/unittest/sourcerangeextractor-test.cpp
index 8bf676b796..8235f51858 100644
--- a/tests/unit/unittest/sourcerangeextractor-test.cpp
+++ b/tests/unit/unittest/sourcerangeextractor-test.cpp
@@ -54,7 +54,7 @@ protected:
TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}};
ClangBackEnd::SourceRangesContainer sourceRangesContainer;
const clang::SourceManager &sourceManager{clangTool.sourceManager()};
- ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache;
+ ClangBackEnd::FilePathCache<std::mutex> filePathCache;
ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), filePathCache, sourceRangesContainer};
clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID());
clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4);
@@ -167,7 +167,7 @@ TEST_F(SourceRangeExtractorSlowTest, EpandText)
auto expandedText = ::SourceRangeExtractor::getExpandedText(text, 15, 25);
- ASSERT_THAT(expandedText, StrEq("second line\nthird line"));
+ ASSERT_THAT(expandedText, Eq("second line\nthird line"));
}
void SourceRangeExtractor::SetUp()
diff --git a/tests/unit/unittest/sqlitecolumn-test.cpp b/tests/unit/unittest/sqlitecolumn-test.cpp
index b520fc40eb..3daa32bd23 100644
--- a/tests/unit/unittest/sqlitecolumn-test.cpp
+++ b/tests/unit/unittest/sqlitecolumn-test.cpp
@@ -29,19 +29,30 @@
namespace {
+using testing::AllOf;
+using testing::Contains;
+using testing::Property;
+
+using Sqlite::ColumnType;
+using Sqlite::Contraint;
+using Sqlite::JournalMode;
+using Sqlite::OpenMode;
+using Column = Sqlite::Column;
+using Sqlite::SqliteColumns;
+
class SqliteColumn : public ::testing::Test
{
protected:
void SetUp() override;
- ::SqliteColumn column;
+ Sqlite::Column column;
};
TEST_F(SqliteColumn, ChangeName)
{
- column.setName(Utf8StringLiteral("Claudia"));
+ column.setName("Claudia");
- ASSERT_THAT(column.name(), Utf8StringLiteral("Claudia"));
+ ASSERT_THAT(column.name(), "Claudia");
}
TEST_F(SqliteColumn, DefaultType)
@@ -56,27 +67,27 @@ TEST_F(SqliteColumn, ChangeType)
ASSERT_THAT(column.type(), ColumnType::Text);
}
-TEST_F(SqliteColumn, DefaultPrimaryKey)
+TEST_F(SqliteColumn, DefaultConstraint)
{
- ASSERT_FALSE(column.isPrimaryKey());
+ ASSERT_THAT(column.constraint(), Contraint::NoConstraint);
}
-TEST_F(SqliteColumn, SetPrimaryKey)
+TEST_F(SqliteColumn, SetConstraint)
{
- column.setIsPrimaryKey(true);
+ column.setContraint(Contraint::PrimaryKey);
- ASSERT_TRUE(column.isPrimaryKey());
+ ASSERT_THAT(column.constraint(), Contraint::PrimaryKey);
}
TEST_F(SqliteColumn, GetColumnDefinition)
{
- column.setName(Utf8StringLiteral("Claudia"));
-
- Internal::ColumnDefinition columnDefintion = column.columnDefintion();
+ column.setName("Claudia");
- ASSERT_THAT(columnDefintion.name(), Utf8StringLiteral("Claudia"));
- ASSERT_THAT(columnDefintion.type(), ColumnType::Numeric);
- ASSERT_FALSE(columnDefintion.isPrimaryKey());
+ ASSERT_THAT(column,
+ AllOf(
+ Property(&Column::name, "Claudia"),
+ Property(&Column::type, ColumnType::Numeric),
+ Property(&Column::constraint, Contraint::NoConstraint)));
}
void SqliteColumn::SetUp()
diff --git a/tests/unit/unittest/sqlitedatabase-test.cpp b/tests/unit/unittest/sqlitedatabase-test.cpp
index 1e417aefb6..98b1435945 100644
--- a/tests/unit/unittest/sqlitedatabase-test.cpp
+++ b/tests/unit/unittest/sqlitedatabase-test.cpp
@@ -29,6 +29,7 @@
#include <sqlitedatabase.h>
#include <sqlitetable.h>
+#include <sqlitewritestatement.h>
#include <utf8string.h>
#include <QSignalSpy>
@@ -36,6 +37,13 @@
namespace {
+using testing::Contains;
+
+using Sqlite::ColumnType;
+using Sqlite::JournalMode;
+using Sqlite::OpenMode;
+using Sqlite::Table;
+
class SqliteDatabase : public ::testing::Test
{
protected:
@@ -44,7 +52,7 @@ protected:
SpyDummy spyDummy;
QString databaseFilePath = QStringLiteral(":memory:");
- ::SqliteDatabase database;
+ Sqlite::Database database;
};
TEST_F(SqliteDatabase, SetDatabaseFilePath)
@@ -59,46 +67,86 @@ TEST_F(SqliteDatabase, SetJournalMode)
ASSERT_THAT(database.journalMode(), JournalMode::Memory);
}
+TEST_F(SqliteDatabase, SetOpenlMode)
+{
+ database.setOpenMode(OpenMode::ReadOnly);
+
+ ASSERT_THAT(database.openMode(), OpenMode::ReadOnly);
+}
+
TEST_F(SqliteDatabase, OpenDatabase)
{
database.close();
- QSignalSpy signalSpy(&spyDummy, &SpyDummy::databaseIsOpened);
+
database.open();
- ASSERT_TRUE(signalSpy.wait(100000));
ASSERT_TRUE(database.isOpen());
}
TEST_F(SqliteDatabase, CloseDatabase)
{
- QSignalSpy signalSpy(&spyDummy, &SpyDummy::databaseIsClosed);
-
database.close();
- ASSERT_TRUE(signalSpy.wait(100000));
ASSERT_FALSE(database.isOpen());
}
TEST_F(SqliteDatabase, AddTable)
{
- SqliteTable *sqliteTable = new SqliteTable;
+ auto sqliteTable = database.addTable();
- database.addTable(sqliteTable);
+ ASSERT_THAT(database.tables(), Contains(sqliteTable));
+}
+
+TEST_F(SqliteDatabase, GetChangesCount)
+{
+ Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database);
+ statement.write(42);
- ASSERT_THAT(database.tables().first(), sqliteTable);
+ ASSERT_THAT(database.changesCount(), 1);
}
-void SqliteDatabase::SetUp()
+TEST_F(SqliteDatabase, GetTotalChangesCount)
+{
+ Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database);
+ statement.write(42);
+
+ ASSERT_THAT(database.lastInsertedRowId(), 1);
+}
+
+TEST_F(SqliteDatabase, GetLastInsertedRowId)
+{
+ Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database);
+ statement.write(42);
+
+ ASSERT_THAT(database.lastInsertedRowId(), 1);
+}
+
+TEST_F(SqliteDatabase, TableIsReadyAfterOpenDatabase)
{
- QObject::connect(&database, &::SqliteDatabase::databaseIsOpened, &spyDummy, &SpyDummy::databaseIsOpened);
- QObject::connect(&database, &::SqliteDatabase::databaseIsClosed, &spyDummy, &SpyDummy::databaseIsClosed);
+ database.close();
+ auto &table = database.addTable();
+ table.setName("foo");
+ table.addColumn("name");
+
+ database.open();
+ ASSERT_TRUE(table.isReady());
+}
+
+void SqliteDatabase::SetUp()
+{
database.setJournalMode(JournalMode::Memory);
database.setDatabaseFilePath(databaseFilePath);
+ auto &table = database.addTable();
+ table.setName("test");
+ table.addColumn("name");
+
+ database.open();
}
void SqliteDatabase::TearDown()
{
- database.close();
+ if (database.isOpen())
+ database.close();
}
}
diff --git a/tests/unit/unittest/sqlitedatabasebackend-test.cpp b/tests/unit/unittest/sqlitedatabasebackend-test.cpp
index 99e443da30..7663139f01 100644
--- a/tests/unit/unittest/sqlitedatabasebackend-test.cpp
+++ b/tests/unit/unittest/sqlitedatabasebackend-test.cpp
@@ -25,40 +25,57 @@
#include "googletest.h"
+#include <sqlitedatabase.h>
#include <sqlitedatabasebackend.h>
#include <sqliteexception.h>
#include <sqlitewritestatement.h>
+#include <sqlite3.h>
+
#include <QDir>
namespace {
+using Backend = Sqlite::DatabaseBackend;
+
+using Sqlite::ColumnType;
+using Sqlite::Contraint;
+using Sqlite::JournalMode;
+using Sqlite::OpenMode;
+using Sqlite::TextEncoding;
+using Sqlite::Exception;
+using Sqlite::WriteStatement;
+
class SqliteDatabaseBackend : public ::testing::Test
{
protected:
void SetUp() override;
void TearDown() override;
- QString databaseFilePath = QDir::tempPath() + QStringLiteral("/SqliteDatabaseBackendTest.db");
- ::SqliteDatabaseBackend databaseBackend;
+ Utils::PathString databaseFilePath = QDir::tempPath() + "/SqliteDatabaseBackendTest.db";
+ Sqlite::Database database;
+ Sqlite::DatabaseBackend &databaseBackend = database.backend();
};
using SqliteDatabaseBackendSlowTest = SqliteDatabaseBackend;
TEST_F(SqliteDatabaseBackend, OpenAlreadyOpenDatabase)
{
- ASSERT_THROW(databaseBackend.open(databaseFilePath), SqliteException);
+ ASSERT_THROW(databaseBackend.open(databaseFilePath, OpenMode::ReadWrite),
+ Sqlite::DatabaseIsAlreadyOpen);
}
TEST_F(SqliteDatabaseBackend, CloseAlreadyClosedDatabase)
{
databaseBackend.close();
- ASSERT_THROW(databaseBackend.close(), SqliteException);
+
+ ASSERT_THROW(databaseBackend.close(), Sqlite::DatabaseIsAlreadyClosed);
}
TEST_F(SqliteDatabaseBackend, OpenWithWrongPath)
{
- ASSERT_THROW(databaseBackend.open(QStringLiteral("/xxx/SqliteDatabaseBackendTest.db")), SqliteException);
+ ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db", OpenMode::ReadWrite),
+ Sqlite::WrongFilePath);
}
TEST_F(SqliteDatabaseBackend, DefaultJournalMode)
@@ -96,50 +113,65 @@ TEST_F(SqliteDatabaseBackend, PersistJournalMode)
TEST_F(SqliteDatabaseBackend, DefaultTextEncoding)
{
- ASSERT_THAT(databaseBackend.textEncoding(), Utf8);
+ ASSERT_THAT(databaseBackend.textEncoding(), TextEncoding::Utf8);
}
TEST_F(SqliteDatabaseBackend, Utf16TextEncoding)
{
- databaseBackend.setTextEncoding(Utf16);
+ databaseBackend.setTextEncoding(TextEncoding::Utf16);
- ASSERT_THAT(databaseBackend.textEncoding(), Utf16);
+ ASSERT_THAT(databaseBackend.textEncoding(), TextEncoding::Utf16);
}
TEST_F(SqliteDatabaseBackend, Utf16beTextEncoding)
{
- databaseBackend.setTextEncoding(Utf16be);
+ databaseBackend.setTextEncoding(TextEncoding::Utf16be);
- ASSERT_THAT(databaseBackend.textEncoding(), Utf16be);
+ ASSERT_THAT(databaseBackend.textEncoding(),TextEncoding::Utf16be);
}
TEST_F(SqliteDatabaseBackend, Utf16leTextEncoding)
{
- databaseBackend.setTextEncoding(Utf16le);
+ databaseBackend.setTextEncoding(TextEncoding::Utf16le);
- ASSERT_THAT(databaseBackend.textEncoding(), Utf16le);
+ ASSERT_THAT(databaseBackend.textEncoding(), TextEncoding::Utf16le);
}
TEST_F(SqliteDatabaseBackend, Utf8TextEncoding)
{
- databaseBackend.setTextEncoding(Utf8);
+ databaseBackend.setTextEncoding(TextEncoding::Utf8);
- ASSERT_THAT(databaseBackend.textEncoding(), Utf8);
+ ASSERT_THAT(databaseBackend.textEncoding(), TextEncoding::Utf8);
}
TEST_F(SqliteDatabaseBackend, TextEncodingCannotBeChangedAfterTouchingDatabase)
{
databaseBackend.setJournalMode(JournalMode::Memory);
- SqliteWriteStatement::execute(Utf8StringLiteral("CREATE TABLE text(name, number)"));
+ databaseBackend.execute("CREATE TABLE text(name, number)");
+
+ ASSERT_THROW(databaseBackend.setTextEncoding(TextEncoding::Utf16),
+ Sqlite::PragmaValueNotSet);
+}
+
+TEST_F(SqliteDatabaseBackend, OpenModeReadOnly)
+{
+ auto mode = Backend::openMode(OpenMode::ReadOnly);
+
+ ASSERT_THAT(mode, SQLITE_OPEN_CREATE | SQLITE_OPEN_READONLY);
+}
+
+TEST_F(SqliteDatabaseBackend, OpenModeReadWrite)
+{
+ auto mode = Backend::openMode(OpenMode::ReadWrite);
- ASSERT_THROW(databaseBackend.setTextEncoding(Utf16), SqliteException);
+ ASSERT_THAT(mode, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE);
}
void SqliteDatabaseBackend::SetUp()
{
QDir::temp().remove(QStringLiteral("SqliteDatabaseBackendTest.db"));
- databaseBackend.open(databaseFilePath);
+ databaseBackend.open(databaseFilePath, OpenMode::ReadWrite);
}
void SqliteDatabaseBackend::TearDown()
diff --git a/tests/unit/unittest/sqliteindex-test.cpp b/tests/unit/unittest/sqliteindex-test.cpp
new file mode 100644
index 0000000000..4c21c7f935
--- /dev/null
+++ b/tests/unit/unittest/sqliteindex-test.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include <sqliteindex.h>
+
+namespace {
+
+using Sqlite::Exception;
+using Sqlite::Index;
+
+TEST(Index, OneColumn)
+{
+ Index index{"tableName", {"column1"}};
+
+ auto sqlStatement = index.sqlStatement();
+
+ ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1 ON tableName(column1)"));
+}
+
+TEST(Index, TwoColumn)
+{
+ Index index{"tableName", {"column1", "column2"}};
+
+ auto sqlStatement = index.sqlStatement();
+
+ ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1_column2 ON tableName(column1, column2)"));
+}
+
+TEST(Index, EmptyTableName)
+{
+ Index index{"", {"column1", "column2"}};
+
+ ASSERT_THROW(index.sqlStatement(), Exception);
+}
+
+TEST(Index, EmptyColumns)
+{
+ Index index{"tableName", {}};
+
+ ASSERT_THROW(index.sqlStatement(), Exception);
+}
+}
diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp
index 8975eee591..30ea9cbca8 100644
--- a/tests/unit/unittest/sqlitestatement-test.cpp
+++ b/tests/unit/unittest/sqlitestatement-test.cpp
@@ -24,540 +24,521 @@
****************************************************************************/
#include "googletest.h"
+#include "sqliteteststatement.h"
-#include <sqlitedatabasebackend.h>
+#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitereadwritestatement.h>
#include <sqlitewritestatement.h>
-#include <utf8string.h>
-#include <QByteArray>
+#include <utils/smallstringio.h>
+
#include <QDir>
-#include <QMap>
-#include <QString>
-#include <QStringList>
-#include <QVariant>
+
+#include <vector>
namespace {
+
+using Sqlite::JournalMode;
+using Sqlite::Exception;
+using Sqlite::Database;
+using Sqlite::ReadStatement;
+using Sqlite::ReadWriteStatement;
+using Sqlite::WriteStatement;
+
+MATCHER_P3(HasValues, value1, value2, rowid,
+ std::string(negation ? "isn't" : "is")
+ + PrintToString(value1)
+ + ", " + PrintToString(value2)
+ + " and " + PrintToString(rowid)
+ )
+{
+ Database &database = arg.database();
+
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE rowid=?", database);
+ statement.bind(1, rowid);
+
+ statement.next();
+
+ return statement.text(0) == value1 && statement.text(1) == value2;
+}
+
class SqliteStatement : public ::testing::Test
{
protected:
void SetUp() override;
void TearDown() override;
- SqliteDatabaseBackend databaseBackend;
+protected:
+ Database database;
};
-TEST_F(SqliteStatement, PrepareFailure)
+struct Output
{
- ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("blah blah blah")), SqliteException);
- ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("blah blah blah")), SqliteException);
- ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)")), SqliteException);
- ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("SELECT name, number FROM test '")), SqliteException);
+ Output(Utils::SmallString name, Utils::SmallString number, long long value)
+ : name(name), number(number), value(value)
+ {}
+
+ Utils::SmallString name;
+ Utils::SmallString number;
+ long long value;
+ friend bool operator==(const Output &f, const Output &s)
+ {
+ return f.name == s.name && f.number == s.number && f.value == s.value;
+ }
+ friend std::ostream &operator<<(std::ostream &out, const Output &o)
+ {
+ return out << "(" << o.name << ", " << ", " << o.number<< ", " << o.value<< ")";
+ }
+};
+
+TEST_F(SqliteStatement, ThrowsStatementHasErrorForWrongSqlStatement)
+{
+ ASSERT_THROW(ReadStatement("blah blah blah", database), Sqlite::StatementHasError);
+}
+
+TEST_F(SqliteStatement, ThrowsNotReadOnlySqlStatementForWritableSqlStatementInReadStatement)
+{
+ ASSERT_THROW(ReadStatement("INSERT INTO test(name, number) VALUES (?, ?)", database),
+ Sqlite::NotReadOnlySqlStatement);
+}
+
+TEST_F(SqliteStatement, ThrowsNotReadonlySqlStatementForWritableSqlStatementInReadStatement)
+{
+ ASSERT_THROW(WriteStatement("SELECT name, number FROM test", database),
+ Sqlite::NotWriteSqlStatement);
}
TEST_F(SqliteStatement, CountRows)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT * FROM test"));
+ SqliteTestStatement statement("SELECT * FROM test", database);
int nextCount = 0;
while (statement.next())
++nextCount;
- int sqlCount = SqliteReadStatement::toValue<int>(Utf8StringLiteral("SELECT count(*) FROM test"));
+ int sqlCount = ReadStatement::toValue<int>("SELECT count(*) FROM test", database);
ASSERT_THAT(nextCount, sqlCount);
}
TEST_F(SqliteStatement, Value)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER BY name"));
-
+ SqliteTestStatement statement("SELECT name, number FROM test ORDER BY name", database);
statement.next();
- ASSERT_THAT(statement.value<QVariant>(1).type(), QVariant::ByteArray);
-
statement.next();
- ASSERT_THAT(statement.value<int>(0), 0);
- ASSERT_THAT(statement.value<qint64>(0), 0);
- ASSERT_THAT(statement.value<double>(0), 0.0);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("foo"));
- ASSERT_THAT(statement.value<Utf8String>(0), Utf8StringLiteral("foo"));
- ASSERT_THAT(statement.value<QVariant>(0), QVariant::fromValue(QStringLiteral("foo")));
- ASSERT_THAT(statement.value<QVariant>(0).type(), QVariant::String);
-
- ASSERT_THAT(statement.value<int>(1), 23);
- ASSERT_THAT(statement.value<qint64>(1), 23);
- ASSERT_THAT(statement.value<double>(1), 23.3);
- ASSERT_THAT(statement.value<QString>(1), QStringLiteral("23.3"));
- ASSERT_THAT(statement.value<Utf8String>(1), Utf8StringLiteral("23.3"));
- ASSERT_THAT(statement.value<QVariant>(1), QVariant::fromValue(23.3));
- ASSERT_THAT(statement.value<QVariant>(1).type(), QVariant::Double);
+ ASSERT_THAT(statement.fetchValue<int>(0), 0);
+ ASSERT_THAT(statement.fetchValue<int64_t>(0), 0);
+ ASSERT_THAT(statement.fetchValue<double>(0), 0.0);
+ ASSERT_THAT(statement.text(0), "foo");
+ ASSERT_THAT(statement.fetchValue<int>(1), 23);
+ ASSERT_THAT(statement.fetchValue<int64_t>(1), 23);
+ ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
+ ASSERT_THAT(statement.text(1), "23.3");
+}
- statement.next();
+TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
- ASSERT_THAT(statement.value<QVariant>(1).type(), QVariant::LongLong);
+ ASSERT_THROW(statement.fetchValue<int>(0), Sqlite::NoValuesToFetch);
}
-TEST_F(SqliteStatement, ValueFailure)
+TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"));
- ASSERT_THROW(statement.value<int>(0), SqliteException);
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
+ while (statement.next()) {}
- statement.reset();
+ ASSERT_THROW(statement.fetchValue<int>(0), Sqlite::NoValuesToFetch);
+}
- while (statement.next()) {}
- ASSERT_THROW(statement.value<int>(0), SqliteException);
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
+ statement.next();
- statement.reset();
+ ASSERT_THROW(statement.fetchValue<int>(-1), Sqlite::InvalidColumnFetched);
+}
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
statement.next();
- ASSERT_THROW(statement.value<int>(-1), SqliteException);
- ASSERT_THROW(statement.value<int>(2), SqliteException);
+
+ ASSERT_THROW(statement.fetchValue<int>(2), Sqlite::InvalidColumnFetched);
}
TEST_F(SqliteStatement, ToIntergerValue)
{
- ASSERT_THAT(SqliteReadStatement::toValue<int>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'")), 23);
+ auto value = ReadStatement::toValue<int>("SELECT number FROM test WHERE name='foo'", database);
+
+ ASSERT_THAT(value, 23);
}
TEST_F(SqliteStatement, ToLongIntergerValue)
{
- ASSERT_THAT(SqliteReadStatement::toValue<qint64>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'")), 23LL);
+ ASSERT_THAT(ReadStatement::toValue<qint64>("SELECT number FROM test WHERE name='foo'", database), Eq(23));
}
TEST_F(SqliteStatement, ToDoubleValue)
{
- ASSERT_THAT(SqliteReadStatement::toValue<double>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'")), 23.3);
+ ASSERT_THAT(ReadStatement::toValue<double>("SELECT number FROM test WHERE name='foo'", database), 23.3);
}
-TEST_F(SqliteStatement, ToQStringValue)
+TEST_F(SqliteStatement, ToStringValue)
{
- ASSERT_THAT(SqliteReadStatement::toValue<QString>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")), QStringLiteral("foo"));
+ ASSERT_THAT(ReadStatement::toValue<Utils::SmallString>("SELECT name FROM test WHERE name='foo'", database), "foo");
}
-TEST_F(SqliteStatement, ToUtf8StringValue)
+TEST_F(SqliteStatement, ColumnNames)
{
- ASSERT_THAT(SqliteReadStatement::toValue<Utf8String>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")), Utf8StringLiteral("foo"));
-}
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
-TEST_F(SqliteStatement, ToQByteArrayValueIsNull)
-{
- ASSERT_TRUE(SqliteReadStatement::toValue<QByteArray>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")).isNull());
-}
+ auto columnNames = statement.columnNames();
-TEST_F(SqliteStatement, ToQVariantValue)
-{
- ASSERT_THAT(SqliteReadStatement::toValue<QVariant>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")), QVariant::fromValue(QStringLiteral("foo")));
+ ASSERT_THAT(columnNames, ElementsAre("name", "number"));
}
-TEST_F(SqliteStatement, Utf8Values)
+TEST_F(SqliteStatement, BindString)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name"));
- Utf8StringVector values = statement.values<Utf8StringVector>();
- ASSERT_THAT(values.count(), 3);
- ASSERT_THAT(values.at(0), Utf8StringLiteral("bar"));
- ASSERT_THAT(values.at(1), Utf8StringLiteral("foo"));
- ASSERT_THAT(values.at(2), Utf8StringLiteral("poo"));
-}
-TEST_F(SqliteStatement, DoubleValues)
-{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE name=?", database);
- QVector<double> values = statement.values<QVector<double>>(1);
+ statement.bind(1, "foo");
+
+ statement.next();
- ASSERT_THAT(values.count(), 3);
- ASSERT_THAT(values.at(0), 0.0);
- ASSERT_THAT(values.at(1), 23.3);
- ASSERT_THAT(values.at(2), 40.0);
+ ASSERT_THAT(statement.text(0), "foo");
+ ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
}
-TEST_F(SqliteStatement, QVariantValues)
+TEST_F(SqliteStatement, BindInteger)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database);
- QVector<QVariant> values = statement.values<QVector<QVariant>>(QVector<int>() << 0 << 1);
+ statement.bind(1, 40);
+ statement.next();
- ASSERT_THAT(values.count(), 6);
- ASSERT_THAT(values.at(0), QVariant::fromValue(QStringLiteral("bar")));
- ASSERT_THAT(values.at(1), QVariant::fromValue(QByteArray::fromHex("0500")));
- ASSERT_THAT(values.at(2), QVariant::fromValue(QStringLiteral("foo")));
- ASSERT_THAT(values.at(3), QVariant::fromValue(23.3));
- ASSERT_THAT(values.at(4), QVariant::fromValue(QStringLiteral("poo")));
- ASSERT_THAT(values.at(5), QVariant::fromValue(40));
+ ASSERT_THAT(statement.text(0),"poo");
}
-TEST_F(SqliteStatement, RowColumnValueMapCountForValidRow)
+TEST_F(SqliteStatement, BindLongInteger)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=1"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database);
- QMap<QString, QVariant> values = statement.rowColumnValueMap();
+ statement.bind(1, int64_t(40));
+ statement.next();
- ASSERT_THAT(values.count(), 2);
+ ASSERT_THAT(statement.text(0), "poo");
}
-TEST_F(SqliteStatement, RowColumnValueMapCountForInvalidRow)
+TEST_F(SqliteStatement, BindDouble)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=100"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database);
- QMap<QString, QVariant> values = statement.rowColumnValueMap();
+ statement.bind(1, 23.3);
+ statement.next();
- ASSERT_THAT(values.count(), 0);
+ ASSERT_THAT(statement.text(0), "foo");
}
-TEST_F(SqliteStatement, RowColumnValueMapValues)
+TEST_F(SqliteStatement, BindIntegerByParameter)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=2"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@number", database);
- QMap<QString, QVariant> values = statement.rowColumnValueMap();
+ statement.bind("@number", 40);
+ statement.next();
- ASSERT_THAT(values.value(QStringLiteral("name")).toString(), QStringLiteral("foo"));
- ASSERT_THAT(values.value(QStringLiteral("number")).toDouble(), 23.3);
+ ASSERT_THAT(statement.text(0), "poo");
}
-TEST_F(SqliteStatement, TwoColumnValueMapCount)
+TEST_F(SqliteStatement, BindLongIntegerByParameter)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@number", database);
- QMap<QString, QVariant> values = statement.twoColumnValueMap();
+ statement.bind("@number", int64_t(40));
+ statement.next();
- ASSERT_THAT(values.count(), 3);
+ ASSERT_THAT(statement.text(0), "poo");
}
-TEST_F(SqliteStatement, TwoColumnValueMapValues)
+TEST_F(SqliteStatement, BindDoubleByIndex)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@number", database);
- QMap<QString, QVariant> values = statement.twoColumnValueMap();
+ statement.bind(statement.bindingIndexForName("@number"), 23.3);
+ statement.next();
- ASSERT_THAT(values.value(QStringLiteral("foo")).toDouble(), 23.3);
+ ASSERT_THAT(statement.text(0), "foo");
}
-TEST_F(SqliteStatement, ValuesFailure)
+TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBound)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"));
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
- ASSERT_THROW(statement.values<QVector<QVariant>>(QVector<int>() << 1 << 2);, SqliteException);
- ASSERT_THROW(statement.values<QVector<QVariant>>(QVector<int>() << -1 << 1);, SqliteException);
+ ASSERT_THROW(statement.bind(0, 40), Sqlite::BindingIndexIsOutOfRange);
}
-TEST_F(SqliteStatement, ColumnNames)
+TEST_F(SqliteStatement, BindIndexIsTpLargeIsThrowingBindingIndexIsOutOfBound)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"));
-
- Utf8StringVector columnNames = statement.columnNames();
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
- ASSERT_THAT(columnNames.count(), statement.columnCount());
-
- ASSERT_THAT(columnNames.at(0), Utf8StringLiteral("name"));
- ASSERT_THAT(columnNames.at(1), Utf8StringLiteral("number"));
+ ASSERT_THROW(statement.bind(2, 40), Sqlite::BindingIndexIsOutOfRange);
}
-TEST_F(SqliteStatement, BindQString)
+TEST_F(SqliteStatement, WrongBindingNameThrowingBindingIndexIsOutOfBound)
{
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE number=@name", database);
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name=?"));
-
- statement.bind(1, QStringLiteral("foo"));
-
- statement.next();
-
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("foo"));
- ASSERT_THAT(statement.value<double>(1), 23.3);
+ ASSERT_THROW(statement.bind("@name2", 40), Sqlite::WrongBingingName);
}
-TEST_F(SqliteStatement, BindInteger)
+TEST_F(SqliteStatement, RequestBindingNamesFromStatement)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
-
- statement.bind(1, 40);
- statement.next();
+ SqliteTestStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("poo"));
+ ASSERT_THAT(statement.bindingColumnNames(), ElementsAre("name", "number", "id"));
}
-TEST_F(SqliteStatement, BindLongInteger)
+TEST_F(SqliteStatement, BindValues)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
+ SqliteTestStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
- statement.bind(1, qint64(40));
- statement.next();
+ statement.bindValues("see", 7.23, 1);
+ statement.execute();
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("poo"));
+ ASSERT_THAT(statement, HasValues("see", "7.23", 1));
}
-TEST_F(SqliteStatement, BindByteArray)
+TEST_F(SqliteStatement, WriteValues)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
+ WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
- statement.bind(1, QByteArray::fromHex("0500"));
- statement.next();
+ statement.write("see", 7.23, 1);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("bar"));
+ ASSERT_THAT(statement, HasValues("see", "7.23", 1));
}
-TEST_F(SqliteStatement, BindDouble)
+TEST_F(SqliteStatement, BindNamedValues)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
+ SqliteTestStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database);
- statement.bind(1, 23.3);
- statement.next();
+ statement.bindNameValues("@name", "see", "@number", 7.23, "@id", 1);
+ statement.execute();
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("foo"));
+ ASSERT_THAT(statement, HasValues("see", "7.23", 1));
}
-TEST_F(SqliteStatement, BindIntergerQVariant)
+TEST_F(SqliteStatement, WriteNamedValues)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
+ WriteStatement statement("UPDATE test SET name=@name, number=@number WHERE rowid=@id", database);
- statement.bind(1, QVariant::fromValue(40));
- statement.next();
+ statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("poo"));
+ ASSERT_THAT(statement, HasValues("see", "7.23", 1));
}
-TEST_F(SqliteStatement, BindLongIntergerQVariant)
+TEST_F(SqliteStatement, CannotWriteToClosedDatabase)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
+ database.close();
- statement.bind(1, QVariant::fromValue(qint64(40)));
- statement.next();
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("poo"));
+ ASSERT_THROW(WriteStatement("INSERT INTO test(name, number) VALUES (?, ?)", database),
+ Sqlite::DatabaseIsNotOpen);
}
-TEST_F(SqliteStatement, BindDoubleQVariant)
+TEST_F(SqliteStatement, CannotReadFromClosedDatabase)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
-
- statement.bind(1, QVariant::fromValue(23.3));
- statement.next();
+ database.close();
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("foo"));
- }
+ ASSERT_THROW(ReadStatement("SELECT * FROM test", database),
+ Sqlite::DatabaseIsNotOpen);
+}
-TEST_F(SqliteStatement, BindByteArrayQVariant)
+TEST_F(SqliteStatement, GetTupleValuesWithoutArguments)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"));
+ using Tuple = std::tuple<Utils::SmallString, double, int>;
+ ReadStatement statement("SELECT name, number, value FROM test", database);
- statement.bind(1, QVariant::fromValue(QByteArray::fromHex("0500")));
- statement.next();
+ auto values = statement.values<Tuple, 3>(3);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("bar"));
+ ASSERT_THAT(values, ElementsAre(Tuple{"bar", 0, 1},
+ Tuple{"foo", 23.3, 2},
+ Tuple{"poo", 40.0, 3}));
}
-TEST_F(SqliteStatement, BindIntegerByParameter)
+TEST_F(SqliteStatement, GetSingleValuesWithoutArguments)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"));
+ ReadStatement statement("SELECT name FROM test", database);
- statement.bind(Utf8StringLiteral("@number"), 40);
- statement.next();
+ std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("poo"));
+ ASSERT_THAT(values, ElementsAre("bar", "foo", "poo"));
}
-TEST_F(SqliteStatement, BindLongIntegerByParameter)
+TEST_F(SqliteStatement, GetStructValuesWithoutArguments)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"));
+ ReadStatement statement("SELECT name, number, value FROM test", database);
- statement.bind(Utf8StringLiteral("@number"), qint64(40));
- statement.next();
+ auto values = statement.values<Output, 3>(3);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("poo"));
+ ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1},
+ Output{"foo", "23.3", 2},
+ Output{"poo", "40", 3}));
}
-TEST_F(SqliteStatement, BindByteArrayByParameter)
+TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"));
+ ReadStatement statement("SELECT name FROM test WHERE number=?", database);
+ statement.values<Utils::SmallString>(3, 40);
- statement.bind(Utf8StringLiteral("@number"), QByteArray::fromHex("0500"));
- statement.next();
+ std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3, 40);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("bar"));
+ ASSERT_THAT(values, ElementsAre("poo"));
}
-TEST_F(SqliteStatement, BindDoubleByIndex)
+TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndContainerQueryValues)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"));
+ using Tuple = std::tuple<Utils::SmallString, double, double>;
+ std::vector<double> queryValues = {40, 23.3};
+ ReadStatement statement("SELECT name, number, value FROM test WHERE number=?", database);
- statement.bind(statement.bindingIndexForName(Utf8StringLiteral("@number")), 23.3);
- statement.next();
+ auto values = statement.values<Tuple, 3>(3, queryValues);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("foo"));
+ ASSERT_THAT(values, ElementsAre(Tuple{"poo", 40, 3.},
+ Tuple{"foo", 23.3, 2.}));
}
-TEST_F(SqliteStatement, BindQVariantByIndex)
+TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryValues)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"));
-
- statement.bind(statement.bindingIndexForName(Utf8StringLiteral("@number")), QVariant::fromValue((40)));
- statement.next();
+ std::vector<double> queryValues = {40, 23.3};
+ ReadStatement statement("SELECT name, number FROM test WHERE number=?", database);
- ASSERT_THAT(statement.value<QString>(0), QStringLiteral("poo"));
+ std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3, queryValues);
+ ASSERT_THAT(values, ElementsAre("poo", "foo"));
}
-TEST_F(SqliteStatement, BindFailure)
+TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndContainerQueryTupleValues)
{
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"));
+ using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, int>;
+ using ResultTuple = std::tuple<Utils::SmallString, double, int>;
+ std::vector<Tuple> queryValues = {{"poo", "40", 3}, {"bar", "blah", 1}};
+ ReadStatement statement("SELECT name, number, value FROM test WHERE name= ? AND number=? AND value=?", database);
+
+ auto values = statement.values<ResultTuple, 3>(3, queryValues);
- ASSERT_THROW(statement.bind(0, 40), SqliteException);
- ASSERT_THROW(statement.bind(2, 40), SqliteException);
- ASSERT_THROW(statement.bind(Utf8StringLiteral("@name"), 40), SqliteException);
+ ASSERT_THAT(values, ElementsAre(ResultTuple{"poo", 40, 3},
+ ResultTuple{"bar", 0, 1}));
}
-TEST_F(SqliteStatement, RequestBindingNamesFromStatement)
+TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryTupleValues)
{
- Utf8StringVector expectedValues({Utf8StringLiteral("name"), Utf8StringLiteral("number"), Utf8StringLiteral("id")});
+ using Tuple = std::tuple<Utils::SmallString, Utils::SmallString>;
+ std::vector<Tuple> queryValues = {{"poo", "40"}, {"bar", "blah"}};
+ ReadStatement statement("SELECT name, number FROM test WHERE name= ? AND number=?", database);
- SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET name=@name, number=@number WHERE rowid=@id"));
+ std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3, queryValues);
- ASSERT_THAT(statement.bindingColumnNames(), expectedValues);
+ ASSERT_THAT(values, ElementsAre("poo", "bar"));
}
-TEST_F(SqliteStatement, WriteUpdateWidthUnamedParameter)
+TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndMultipleQueryValue)
{
- {
- int startTotalCount = databaseBackend.totalChangesCount();
- RowDictionary firstValueMap;
- firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
- firstValueMap.insert(Utf8StringLiteral("number"), 66.6);
+ using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
+ ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
- RowDictionary secondValueMap;
- secondValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("bar"));
- secondValueMap.insert(Utf8StringLiteral("number"), 77.7);
+ auto values = statement.values<Tuple, 3>(3, "bar", "blah", 1);
- SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=? WHERE name=?"));
- statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("number") << Utf8StringLiteral("name"));
+ ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
+}
- statement.write(firstValueMap);
+TEST_F(SqliteStatement, CallGetValuesForMultipleOutputValuesAndMultipleQueryValueMultipleTimes)
+{
+ using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
+ ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=?", database);
+ statement.values<Tuple, 3>(3, "bar", "blah");
- ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1);
+ auto values = statement.values<Tuple, 3>(3, "bar", "blah");
- statement.write(firstValueMap);
+ ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
+}
- ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 2);
+TEST_F(SqliteStatement, GetStructOutputValuesAndMultipleQueryValue)
+{
+ ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
- statement.write(secondValueMap);
+ auto values = statement.values<Output, 3>(3, "bar", "blah", 1);
- ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 3);
- }
+ ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1}));
+}
- {
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'"));
+TEST_F(SqliteStatement, GetStructOutputValuesAndContainerQueryValues)
+{
+ std::vector<double> queryValues = {40, 23.3};
+ ReadStatement statement("SELECT name, number, value FROM test WHERE number=?", database);
- statement.next();
+ auto values = statement.values<Output, 3>(3, queryValues);
- ASSERT_THAT(statement.value<double>(1), 66.6);
- }
+ ASSERT_THAT(values, ElementsAre(Output{"poo", "40", 3},
+ Output{"foo", "23.3", 2}));
}
-TEST_F(SqliteStatement, WriteUpdateWidthNamedParameter)
+TEST_F(SqliteStatement, GetStructOutputValuesAndContainerQueryTupleValues)
{
- {
- int startTotalCount = databaseBackend.totalChangesCount();
- RowDictionary firstValueMap;
- firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
- firstValueMap.insert(Utf8StringLiteral("number"), 99.9);
-
- SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=@number WHERE name=@name"));
- statement.write(firstValueMap);
- ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1);
- }
+ using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, int>;
+ std::vector<Tuple> queryValues = {{"poo", "40", 3}, {"bar", "blah", 1}};
+ ReadStatement statement("SELECT name, number, value FROM test WHERE name= ? AND number=? AND value=?", database);
- {
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'"));
- statement.next();
- ASSERT_THAT(statement.value<double>(1), 99.9);
- }
+ auto values = statement.values<Output, 3>(3, queryValues);
+
+ ASSERT_THAT(values, ElementsAre(Output{"poo", "40", 3},
+ Output{"bar", "blah", 1}));
}
-TEST_F(SqliteStatement, WriteUpdateWidthNamedParameterAndBindNotAllParameter)
+TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue)
{
- {
- int startTotalCount = databaseBackend.totalChangesCount();
- RowDictionary firstValueMap;
- firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
+ ReadStatement statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", database);
- SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=@number WHERE name=@name"));
- statement.writeUnchecked(firstValueMap);
- ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1);
- }
+ auto value = statement.value<Utils::SmallString>("bar", "blah", 1);
- {
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'"));
- statement.next();
- ASSERT_THAT(statement.value<double>(1), 0.0);
- }
+ ASSERT_THAT(value.value(), Eq("bar"));
}
-TEST_F(SqliteStatement, WriteInsert)
+TEST_F(SqliteStatement, GetOptionalOutputValueAndMultipleQueryValue)
{
- {
- int startTotalCount = databaseBackend.totalChangesCount();
-
- RowDictionary valueMap;
- valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("jane"));
- valueMap.insert(Utf8StringLiteral("number"), 232.3);
-
- SqliteWriteStatement statement(Utf8StringLiteral("INSERT OR IGNORE INTO test(name, number) VALUES (?, ?)"));
- statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
- statement.write(valueMap);
- ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1);
- statement.write(valueMap);
- ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1);
- }
+ ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
- {
- SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='jane'"));
- statement.next();
- ASSERT_THAT(statement.value<double>(1), 232.3);
- }
+ auto value = statement.value<Output, 3>("bar", "blah", 1);
+
+ ASSERT_THAT(value.value(), Eq(Output{"bar", "blah", 1}));
}
-TEST_F(SqliteStatement, WriteFailure)
+TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue)
{
- {
- RowDictionary valueMap;
- valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
- valueMap.insert(Utf8StringLiteral("number"), 323.3);
-
- SqliteWriteStatement statement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)"));
- statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
- ASSERT_THROW(statement.write(valueMap), SqliteException);
- }
+ using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
+ ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
- {
- RowDictionary valueMap;
- valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("bar"));
+ auto value = statement.value<Tuple, 3>("bar", "blah", 1);
- SqliteWriteStatement statement(Utf8StringLiteral("INSERT OR IGNORE INTO test(name, number) VALUES (?, ?)"));
- statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
- ASSERT_THROW(statement.write(valueMap), SqliteException);
- }
+ ASSERT_THAT(value.value(), Eq(Tuple{"bar", "blah", 1}));
}
-TEST_F(SqliteStatement, ClosedDatabase)
-{
- databaseBackend.close();
- ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)")), SqliteException);
- ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("SELECT * FROM test")), SqliteException);
- ASSERT_THROW(SqliteReadWriteStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)")), SqliteException);
- databaseBackend.open(QDir::tempPath() + QStringLiteral("/SqliteStatementTest.db"));
-}
void SqliteStatement::SetUp()
{
- databaseBackend.open(QStringLiteral(":memory:"));
- SqliteWriteStatement::execute(Utf8StringLiteral("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC)"));
- SqliteWriteStatement::execute(Utf8StringLiteral("INSERT INTO test VALUES ('bar', x'0500')"));
- SqliteWriteStatement::execute(Utf8StringLiteral("INSERT INTO test VALUES ('foo', 23.3)"));
- SqliteWriteStatement::execute(Utf8StringLiteral("INSERT INTO test VALUES ('poo', 40)"));
+ database.setJournalMode(JournalMode::Memory);
+ database.open(":memory:");
+ database.execute("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC, value NUMERIC)");
+ database.execute("INSERT INTO test VALUES ('bar', 'blah', 1)");
+ database.execute("INSERT INTO test VALUES ('foo', 23.3, 2)");
+ database.execute("INSERT INTO test VALUES ('poo', 40, 3)");
}
void SqliteStatement::TearDown()
{
- databaseBackend.close();
+ if (database.isOpen())
+ database.close();
}
}
diff --git a/tests/unit/unittest/sqlitetable-test.cpp b/tests/unit/unittest/sqlitetable-test.cpp
index 9ca59576fc..658e593b62 100644
--- a/tests/unit/unittest/sqlitetable-test.cpp
+++ b/tests/unit/unittest/sqlitetable-test.cpp
@@ -27,89 +27,87 @@
#include "spydummy.h"
#include <sqlitecolumn.h>
-#include <sqlitedatabase.h>
+#include <mocksqlitedatabase.h>
#include <sqlitetable.h>
-#include <utf8string.h>
-
-#include <QSignalSpy>
-#include <QVariant>
namespace {
+using Sqlite::ColumnType;
+using Sqlite::JournalMode;
+using Sqlite::OpenMode;
+using Sqlite::Column;
+using Sqlite::Database;
+
class SqliteTable : public ::testing::Test
{
protected:
- void SetUp() override;
- void TearDown() override;
-
- SqliteColumn *addColumn(const Utf8String &columnName);
-
- SpyDummy spyDummy;
- SqliteDatabase *database = nullptr;
- ::SqliteTable *table = nullptr;
- Utf8String tableName = Utf8StringLiteral("testTable");
+ NiceMock<MockSqliteDatabase> mockDatabase;
+ Sqlite::Table table;
+ Utils::SmallString tableName = "testTable";
};
TEST_F(SqliteTable, ColumnIsAddedToTable)
{
- table->setUseWithoutRowId(true);
+ table.setUseWithoutRowId(true);
- ASSERT_TRUE(table->useWithoutRowId());
+ ASSERT_TRUE(table.useWithoutRowId());
}
TEST_F(SqliteTable, SetTableName)
{
- table->setName(tableName);
+ table.setName(tableName.clone());
- ASSERT_THAT(table->name(), tableName);
+ ASSERT_THAT(table.name(), tableName);
}
TEST_F(SqliteTable, SetUseWithoutRowid)
{
- table->setUseWithoutRowId(true);
+ table.setUseWithoutRowId(true);
- ASSERT_TRUE(table->useWithoutRowId());
+ ASSERT_TRUE(table.useWithoutRowId());
}
-TEST_F(SqliteTable, TableIsReadyAfterOpenDatabase)
+TEST_F(SqliteTable, AddIndex)
{
- QSignalSpy signalSpy(&spyDummy, &SpyDummy::tableIsReady);
- table->setName(tableName);
- addColumn(Utf8StringLiteral("name"));
+ table.setName(tableName.clone());
+ auto &column = table.addColumn("name");
+ auto &column2 = table.addColumn("value");
- database->open();
+ auto index = table.addIndex({column, column2});
- ASSERT_TRUE(signalSpy.wait(100000));
+ ASSERT_THAT(Utils::SmallStringView(index.sqlStatement()),
+ Eq("CREATE INDEX IF NOT EXISTS index_testTable_name_value ON testTable(name, value)"));
}
-void SqliteTable::SetUp()
+TEST_F(SqliteTable, InitializeTable)
{
- table = new ::SqliteTable;
- QObject::connect(table, &::SqliteTable::tableIsReady, &spyDummy, &SpyDummy::tableIsReady);
+ table.setName(tableName.clone());
+ table.setUseIfNotExists(true);
+ table.setUseTemporaryTable(true);
+ table.setUseWithoutRowId(true);
+ table.addColumn("name");
+ table.addColumn("value");
- database = new SqliteDatabase;
- database->setJournalMode(JournalMode::Memory);
- database->setDatabaseFilePath( QStringLiteral(":memory:"));
- database->addTable(table);
-}
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name NUMERIC, value NUMERIC) WITHOUT ROWID")));
-void SqliteTable::TearDown()
-{
- database->close();
- delete database;
- database = nullptr;
- table = nullptr;
+ table.initialize(mockDatabase);
}
-SqliteColumn *SqliteTable::addColumn(const Utf8String &columnName)
+TEST_F(SqliteTable, InitializeTableWithIndex)
{
- SqliteColumn *newSqliteColum = new SqliteColumn;
-
- newSqliteColum->setName(columnName);
-
- table->addColumn(newSqliteColum);
-
- return newSqliteColum;
+ InSequence sequence;
+ table.setName(tableName.clone());
+ auto &column = table.addColumn("name");
+ auto &column2 = table.addColumn("value");
+ table.addIndex({column});
+ table.addIndex({column2});
+
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE testTable(name NUMERIC, value NUMERIC)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_name ON testTable(name)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_value ON testTable(value)")));
+
+ table.initialize(mockDatabase);
}
+
}
diff --git a/tests/unit/unittest/sqliteteststatement.h b/tests/unit/unittest/sqliteteststatement.h
new file mode 100644
index 0000000000..870180b5d0
--- /dev/null
+++ b/tests/unit/unittest/sqliteteststatement.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#pragma once
+
+#include <sqlitestatement.h>
+
+class SQLITE_EXPORT SqliteTestStatement : public Sqlite::Statement
+{
+public:
+ explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database)
+ : Sqlite::Statement(sqlStatement, database)
+ {}
+
+ using Statement::bind;
+ using Statement::bindingColumnNames;
+ using Statement::bindingIndexForName;
+ using Statement::bindNameValues;
+ using Statement::bindValues;
+ using Statement::columnNames;
+ using Statement::database;
+ using Statement::execute;
+ using Statement::next;
+ using Statement::text;
+ using Statement::fetchValue;
+
+protected:
+ void checkIsWritableStatement();
+};
+
diff --git a/tests/unit/unittest/sqlitetransaction-test.cpp b/tests/unit/unittest/sqlitetransaction-test.cpp
new file mode 100644
index 0000000000..69f90a7122
--- /dev/null
+++ b/tests/unit/unittest/sqlitetransaction-test.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include <sqlitetransaction.h>
+#include <mocksqlitedatabase.h>
+
+namespace {
+
+using DeferredTransaction = Sqlite::DeferredTransaction<MockSqliteDatabase>;
+using ImmediateTransaction = Sqlite::ImmediateTransaction<MockSqliteDatabase>;
+using ExclusiveTransaction = Sqlite::ExclusiveTransaction<MockSqliteDatabase>;
+
+class SqliteTransaction : public testing::Test
+{
+protected:
+ MockMutex mockMutex;
+ MockSqliteDatabase mockDatabase{mockMutex};
+};
+
+TEST_F(SqliteTransaction, DeferredTransactionCommit)
+{
+ EXPECT_CALL(mockDatabase, databaseMutex());
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ DeferredTransaction transaction{mockDatabase};
+ transaction.commit();
+}
+
+TEST_F(SqliteTransaction, DeferredTransactionRollBack)
+{
+ EXPECT_CALL(mockDatabase, databaseMutex());
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN")));
+ EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ DeferredTransaction transaction{mockDatabase};
+}
+
+TEST_F(SqliteTransaction, ImmediateTransactionCommit)
+{
+ EXPECT_CALL(mockDatabase, databaseMutex());
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ ImmediateTransaction transaction{mockDatabase};
+ transaction.commit();
+}
+
+TEST_F(SqliteTransaction, ImmediateTransactionRollBack)
+{
+ EXPECT_CALL(mockDatabase, databaseMutex());
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
+ EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ ImmediateTransaction transaction{mockDatabase};
+}
+
+TEST_F(SqliteTransaction, ExclusiveTransactionCommit)
+{
+ EXPECT_CALL(mockDatabase, databaseMutex());
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN EXCLUSIVE")));
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ ExclusiveTransaction transaction{mockDatabase};
+ transaction.commit();
+}
+
+TEST_F(SqliteTransaction, ExclusiveTransactionRollBack)
+{
+ EXPECT_CALL(mockDatabase, databaseMutex());
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN EXCLUSIVE")));
+ EXPECT_CALL(mockDatabase, execute(Eq("ROLLBACK")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ ExclusiveTransaction transaction{mockDatabase};
+}
+
+}
+
+
diff --git a/tests/unit/unittest/sqlstatementbuilder-test.cpp b/tests/unit/unittest/sqlstatementbuilder-test.cpp
index 7959dd5799..ef3a66e1da 100644
--- a/tests/unit/unittest/sqlstatementbuilder-test.cpp
+++ b/tests/unit/unittest/sqlstatementbuilder-test.cpp
@@ -27,105 +27,108 @@
#include <sqlstatementbuilderexception.h>
#include <sqlstatementbuilder.h>
-#include <utf8stringvector.h>
-
-#include <QString>
using namespace ::testing;
+using Sqlite::ColumnType;
+using Sqlite::SqlStatementBuilder;
+using Sqlite::SqlStatementBuilderException;
+
+using SV = Utils::SmallStringVector;
+
TEST(SqlStatementBuilder, Bind)
{
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("SELECT $columns FROM $table WHERE $column = 'foo' AND rowid=$row AND rowid IN ($rows)"));
+ SqlStatementBuilder sqlStatementBuilder("SELECT $columns FROM $table WHERE $column = 'foo' AND rowid=$row AND rowid IN ($rows)");
- sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$column"), Utf8StringLiteral("name"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$row"), 20);
- sqlStatementBuilder.bind(Utf8StringLiteral("$rows"), QVector<int>() << 1 << 2 << 3);
+ sqlStatementBuilder.bind("$columns", SV{"name", "number"});
+ sqlStatementBuilder.bind("$column", "name");
+ sqlStatementBuilder.bind("$table", "test");
+ sqlStatementBuilder.bind("$row", 20);
+ sqlStatementBuilder.bind("$rows", {1, 2, 3});
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("SELECT name, number FROM test WHERE name = 'foo' AND rowid=20 AND rowid IN (1, 2, 3)"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "SELECT name, number FROM test WHERE name = 'foo' AND rowid=20 AND rowid IN (1, 2, 3)");
}
TEST(SqlStatementBuilder, BindEmpty)
{
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("SELECT $columns FROM $table$emptyPart"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
+ SqlStatementBuilder sqlStatementBuilder("SELECT $columns FROM $table$emptyPart");
+ sqlStatementBuilder.bind("$columns", SV{"name", "number"});
+ sqlStatementBuilder.bind("$table", "test");
- sqlStatementBuilder.bindEmptyText(Utf8StringLiteral("$emptyPart"));
+ sqlStatementBuilder.bindEmptyText("$emptyPart");
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("SELECT name, number FROM test"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "SELECT name, number FROM test");
}
TEST(SqlStatementBuilder, BindFailure)
{
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("SELECT $columns FROM $table"));
+ SqlStatementBuilder sqlStatementBuilder("SELECT $columns FROM $table");
- Utf8StringVector columns;
+ Utils::SmallStringVector columns;
- ASSERT_THROW(sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), Utf8StringLiteral("")), SqlStatementBuilderException);
- ASSERT_THROW(sqlStatementBuilder.bind(Utf8StringLiteral("columns"), Utf8StringLiteral("test")), SqlStatementBuilderException);
- ASSERT_THROW(sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), columns), SqlStatementBuilderException);
- ASSERT_THROW(sqlStatementBuilder.bindWithInsertTemplateParameters(Utf8StringLiteral("$columns"), columns), SqlStatementBuilderException);
- ASSERT_THROW(sqlStatementBuilder.bindWithUpdateTemplateParameters(Utf8StringLiteral("$columns"), columns), SqlStatementBuilderException);
+ ASSERT_THROW(sqlStatementBuilder.bind("$columns", ""), SqlStatementBuilderException);
+ ASSERT_THROW(sqlStatementBuilder.bind("columns", "test"), SqlStatementBuilderException);
+ ASSERT_THROW(sqlStatementBuilder.bind("$columns", columns), SqlStatementBuilderException);
+ ASSERT_THROW(sqlStatementBuilder.bindWithInsertTemplateParameters("$columns", columns), SqlStatementBuilderException);
+ ASSERT_THROW(sqlStatementBuilder.bindWithUpdateTemplateParameters("$columns", columns), SqlStatementBuilderException);
}
TEST(SqlStatementBuilder, BindWithInsertTemplateParameters)
{
- Utf8StringVector columns({Utf8StringLiteral("name"), Utf8StringLiteral("number")});
+ Utils::SmallStringVector columns = {"name", "number"};
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("INSERT OR IGNORE INTO $table ($columns) VALUES ($values)"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), columns);
- sqlStatementBuilder.bindWithInsertTemplateParameters(Utf8StringLiteral("$values"), columns);
+ SqlStatementBuilder sqlStatementBuilder("INSERT OR IGNORE INTO $table ($columns) VALUES ($values)");
+ sqlStatementBuilder.bind("$table", "test");
+ sqlStatementBuilder.bind("$columns", columns);
+ sqlStatementBuilder.bindWithInsertTemplateParameters("$values", columns);
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("INSERT OR IGNORE INTO test (name, number) VALUES (?, ?)"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "INSERT OR IGNORE INTO test (name, number) VALUES (?, ?)");
}
TEST(SqlStatementBuilder, BindWithUpdateTemplateParameters)
{
- Utf8StringVector columns({Utf8StringLiteral("name"), Utf8StringLiteral("number")});
+ Utils::SmallStringVector columns = {"name", "number"};
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("UPDATE $table SET $columnValues WHERE id=?"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
- sqlStatementBuilder.bindWithUpdateTemplateParameters(Utf8StringLiteral("$columnValues"), columns);
+ SqlStatementBuilder sqlStatementBuilder("UPDATE $table SET $columnValues WHERE id=?");
+ sqlStatementBuilder.bind("$table", "test");
+ sqlStatementBuilder.bindWithUpdateTemplateParameters("$columnValues", columns);
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("UPDATE test SET name=?, number=? WHERE id=?"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "UPDATE test SET name=?, number=? WHERE id=?");
}
TEST(SqlStatementBuilder, BindWithUpdateTemplateNames)
{
- Utf8StringVector columns({Utf8StringLiteral("name"), Utf8StringLiteral("number")});
+ Utils::SmallStringVector columns = {"name", "number"};
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("UPDATE $table SET $columnValues WHERE id=@id"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
- sqlStatementBuilder.bindWithUpdateTemplateNames(Utf8StringLiteral("$columnValues"), columns);
+ SqlStatementBuilder sqlStatementBuilder("UPDATE $table SET $columnValues WHERE id=@id");
+ sqlStatementBuilder.bind("$table", "test");
+ sqlStatementBuilder.bindWithUpdateTemplateNames("$columnValues", columns);
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("UPDATE test SET name=@name, number=@number WHERE id=@id"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "UPDATE test SET name=@name, number=@number WHERE id=@id");
}
TEST(SqlStatementBuilder, ClearOnRebinding)
{
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("SELECT $columns FROM $table"));
+ SqlStatementBuilder sqlStatementBuilder("SELECT $columns FROM $table");
- sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), Utf8StringLiteral("name, number"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
+ sqlStatementBuilder.bind("$columns", "name, number");
+ sqlStatementBuilder.bind("$table", "test");
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("SELECT name, number FROM test"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "SELECT name, number FROM test");
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test2"));
+ sqlStatementBuilder.bind("$table", "test2");
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("SELECT name, number FROM test2"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "SELECT name, number FROM test2");
}
TEST(SqlStatementBuilder, ClearBinding)
{
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("SELECT $columns FROM $table"));
+ SqlStatementBuilder sqlStatementBuilder("SELECT $columns FROM $table");
- sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), Utf8StringLiteral("name, number"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
+ sqlStatementBuilder.bind("$columns", "name, number");
+ sqlStatementBuilder.bind("$table", "test");
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("SELECT name, number FROM test"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "SELECT name, number FROM test");
sqlStatementBuilder.clear();
@@ -134,32 +137,32 @@ TEST(SqlStatementBuilder, ClearBinding)
TEST(SqlStatementBuilder, ColumnType)
{
- ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Numeric), Utf8StringLiteral("NUMERIC"));
- ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Integer), Utf8StringLiteral("INTEGER"));
- ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Real), Utf8StringLiteral("REAL"));
- ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Text), Utf8StringLiteral("TEXT"));
+ ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Numeric), "NUMERIC");
+ ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Integer), "INTEGER");
+ ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Real), "REAL");
+ ASSERT_THAT(SqlStatementBuilder::columnTypeToString(ColumnType::Text), "TEXT");
ASSERT_TRUE(SqlStatementBuilder::columnTypeToString(ColumnType::None).isEmpty());
}
TEST(SqlStatementBuilder, SqlStatementFailure)
{
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("SELECT $columns FROM $table"));
+ SqlStatementBuilder sqlStatementBuilder("SELECT $columns FROM $table");
- sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), Utf8StringLiteral("name, number"));
+ sqlStatementBuilder.bind("$columns", "name, number");
ASSERT_THROW(sqlStatementBuilder.sqlStatement(), SqlStatementBuilderException);
}
TEST(SqlStatementBuilder, IsBuild)
{
- SqlStatementBuilder sqlStatementBuilder(Utf8StringLiteral("SELECT $columns FROM $table"));
+ SqlStatementBuilder sqlStatementBuilder("SELECT $columns FROM $table");
- sqlStatementBuilder.bind(Utf8StringLiteral("$columns"), Utf8StringLiteral("name, number"));
- sqlStatementBuilder.bind(Utf8StringLiteral("$table"), Utf8StringLiteral("test"));
+ sqlStatementBuilder.bind("$columns", "name, number");
+ sqlStatementBuilder.bind("$table", "test");
ASSERT_FALSE(sqlStatementBuilder.isBuild());
- ASSERT_THAT(sqlStatementBuilder.sqlStatement(), Utf8StringLiteral("SELECT name, number FROM test"));
+ ASSERT_THAT(sqlStatementBuilder.sqlStatement(), "SELECT name, number FROM test");
ASSERT_TRUE(sqlStatementBuilder.isBuild());
diff --git a/tests/unit/unittest/storagesqlitestatementfactory-test.cpp b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp
new file mode 100644
index 0000000000..0995663ad4
--- /dev/null
+++ b/tests/unit/unittest/storagesqlitestatementfactory-test.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include "mocksqlitedatabase.h"
+#include "mocksqlitereadstatement.h"
+#include "mocksqlitewritestatement.h"
+
+#include <storagesqlitestatementfactory.h>
+
+namespace {
+
+using StatementFactory = ClangBackEnd::StorageSqliteStatementFactory<NiceMock<MockSqliteDatabase>,
+ MockSqliteReadStatement,
+ MockSqliteWriteStatement>;
+
+using Sqlite::Table;
+
+class StorageSqliteStatementFactory : public testing::Test
+{
+protected:
+ NiceMock<MockMutex> mockMutex;
+ NiceMock<MockSqliteDatabase> mockDatabase{mockMutex};
+ StatementFactory factory{mockDatabase};
+};
+
+TEST_F(StorageSqliteStatementFactory, AddNewSymbolsTable)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ factory.createNewSymbolsTable();
+}
+
+
+TEST_F(StorageSqliteStatementFactory, AddNewLocationsTable)
+{
+ InSequence s;
+
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newLocations_sourceId ON newLocations(sourceId)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ factory.createNewLocationsTable();
+}
+
+TEST_F(StorageSqliteStatementFactory, AddTablesInConstructor)
+{
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))).Times(2);
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(2);
+ EXPECT_CALL(mockMutex, lock()).Times(2);
+ EXPECT_CALL(mockMutex, unlock()).Times(2);
+
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newLocations(temporarySymbolId INTEGER, symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
+ EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newLocations_sourceId ON newLocations(sourceId)")));
+
+ StatementFactory factory{mockDatabase};
+}
+
+TEST_F(StorageSqliteStatementFactory, InsertNewSymbolsStatement)
+{
+ ASSERT_THAT(factory.insertSymbolsToNewSymbolsStatement.sqlStatement,
+ Eq("INSERT INTO newSymbols(temporarySymbolId, usr, symbolName) VALUES(?,?,?)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, InsertNewLocationsToLocations)
+{
+ ASSERT_THAT(factory.insertLocationsToNewLocationsStatement.sqlStatement,
+ Eq("INSERT INTO newLocations(temporarySymbolId, line, column, sourceId) VALUES(?,?,?,?)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, SelectNewSourceIdsStatement)
+{
+ ASSERT_THAT(factory.selectNewSourceIdsStatement.sqlStatement,
+ Eq("SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, AddNewSymbolsToSymbolsStatement)
+{
+ ASSERT_THAT(factory.addNewSymbolsToSymbolsStatement.sqlStatement,
+ Eq("INSERT INTO symbols(usr, symbolName) SELECT usr, symbolName FROM newSymbols WHERE NOT EXISTS (SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, InsertSourcesStatement)
+{
+ ASSERT_THAT(factory.insertSourcesStatement.sqlStatement,
+ Eq("INSERT INTO sources(sourceId, sourcePath) VALUES(?,?)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, SyncNewSymbolsFromSymbolsStatement)
+{
+ ASSERT_THAT(factory.syncNewSymbolsFromSymbolsStatement.sqlStatement,
+ Eq("UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, SyncSymbolsIntoNewLocations)
+{
+ ASSERT_THAT(factory.syncSymbolsIntoNewLocationsStatement.sqlStatement,
+ Eq("UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, DeleteAllLocationsFromUpdatedFiles)
+{
+ ASSERT_THAT(factory.deleteAllLocationsFromUpdatedFilesStatement.sqlStatement,
+ Eq("DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)"));
+}
+
+TEST_F(StorageSqliteStatementFactory, InsertNewLocationsInLocations)
+{
+ ASSERT_THAT(factory.insertNewLocationsInLocationsStatement.sqlStatement,
+ Eq("INSERT INTO locations(symbolId, line, column, sourceId) SELECT symbolId, line, column, sourceId FROM newLocations"));
+}
+
+TEST_F(StorageSqliteStatementFactory, DeleteNewSymbolsTableStatement)
+{
+ ASSERT_THAT(factory.deleteNewSymbolsTableStatement.sqlStatement,
+ Eq("DELETE FROM newSymbols"));
+}
+
+TEST_F(StorageSqliteStatementFactory, DeleteNewLocationsTableStatement)
+{
+ ASSERT_THAT(factory.deleteNewLocationsTableStatement.sqlStatement,
+ Eq("DELETE FROM newLocations"));
+}
+
+}
+
diff --git a/tests/unit/unittest/stringcache-test.cpp b/tests/unit/unittest/stringcache-test.cpp
index 92a2be71a3..e023ae7ff2 100644
--- a/tests/unit/unittest/stringcache-test.cpp
+++ b/tests/unit/unittest/stringcache-test.cpp
@@ -31,16 +31,38 @@
namespace {
-using testing::ElementsAre;
+using ClangBackEnd::StringCacheException;
+
+using uint64 = unsigned long long;
+
+using Utils::compare;
+using Utils::reverseCompare;
+using ClangBackEnd::findInSorted;
+
+using CacheEntries = ClangBackEnd::FileCacheCacheEntries;
class StringCache : public testing::Test
{
protected:
- ClangBackEnd::StringCache<Utils::PathString> cache;
+ void SetUp();
+
+protected:
+ ClangBackEnd::FilePathCache<> cache;
Utils::PathString filePath1{"/file/pathOne"};
Utils::PathString filePath2{"/file/pathTwo"};
Utils::PathString filePath3{"/file/pathThree"};
Utils::PathString filePath4{"/file/pathFour"};
+ Utils::PathString filePath5{"/file/pathFife"};
+ Utils::PathStringVector filePaths{filePath1,
+ filePath2,
+ filePath3,
+ filePath4,
+ filePath5};
+ Utils::PathStringVector reverseFilePaths{filePath1,
+ filePath2,
+ filePath3,
+ filePath4,
+ filePath5};
};
TEST_F(StringCache, AddFilePath)
@@ -125,4 +147,175 @@ TEST_F(StringCache, AddFilePaths)
ASSERT_THAT(ids, ElementsAre(0, 1, 2, 3));
}
+TEST_F(StringCache, IsEmpty)
+{
+ auto isEmpty = cache.isEmpty();
+
+ ASSERT_TRUE(isEmpty);
+}
+
+TEST_F(StringCache, IsNotEmpty)
+{
+ cache.stringId(filePath1);
+
+ auto isEmpty = cache.isEmpty();
+
+ ASSERT_FALSE(isEmpty);
+}
+
+TEST_F(StringCache, PopulateWithEmptyVector)
+{
+ CacheEntries entries;
+
+ cache.uncheckedPopulate(std::move(entries));
+
+ ASSERT_TRUE(cache.isEmpty());
+}
+
+TEST_F(StringCache, IsNotEmptyAfterPopulateWithSomeEntries)
+{
+ CacheEntries entries{{filePath1.clone(), 0},
+ {filePath2.clone(), 1},
+ {filePath3.clone(), 2},
+ {filePath4.clone(), 3}};
+
+ cache.uncheckedPopulate(std::move(entries));
+
+ ASSERT_TRUE(!cache.isEmpty());
+}
+
+TEST_F(StringCache, GetEntryAfterPopulateWithSomeEntries)
+{
+ CacheEntries entries{{filePath1.clone(), 0},
+ {filePath2.clone(), 1},
+ {filePath3.clone(), 2},
+ {filePath4.clone(), 3}};
+ cache.uncheckedPopulate(std::move(entries));
+
+ auto string = cache.string(2);
+
+ ASSERT_THAT(string, filePath3);
+}
+
+TEST_F(StringCache, EntriesHaveUniqueIds)
+{
+ CacheEntries entries{{filePath1.clone(), 0},
+ {filePath2.clone(), 1},
+ {filePath3.clone(), 2},
+ {filePath4.clone(), 2}};
+
+ ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException);
+}
+
+TEST_F(StringCache, IdsAreHigherLowerEntriesSize)
+{
+ CacheEntries entries{{filePath1.clone(), 0},
+ {filePath2.clone(), 1},
+ {filePath3.clone(), 4},
+ {filePath4.clone(), 3}};
+
+ ASSERT_THROW(cache.populate(std::move(entries)), std::out_of_range);
+}
+
+TEST_F(StringCache, MultipleEntries)
+{
+ CacheEntries entries{{filePath1.clone(), 0},
+ {filePath1.clone(), 1},
+ {filePath3.clone(), 2},
+ {filePath4.clone(), 3}};
+
+ ASSERT_THROW(cache.populate(std::move(entries)), StringCacheException);
+}
+
+TEST_F(StringCache, DontFindInSorted)
+{
+ auto found = findInSorted(filePaths.cbegin(), filePaths.cend(), "/file/pathFoo", compare);
+
+ ASSERT_FALSE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedOne)
+{
+ auto found = findInSorted(filePaths.cbegin(), filePaths.cend(), "/file/pathOne", compare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedTwo)
+{
+ auto found = findInSorted(filePaths.cbegin(), filePaths.cend(), "/file/pathTwo", compare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedTree)
+{
+ auto found = findInSorted(filePaths.cbegin(), filePaths.cend(), "/file/pathThree", compare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedFour)
+{
+ auto found = findInSorted(filePaths.cbegin(), filePaths.cend(), "/file/pathFour", compare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedFife)
+{
+ auto found = findInSorted(filePaths.cbegin(), filePaths.cend(), "/file/pathFife", compare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, DontFindInSortedReverse)
+{
+ auto found = findInSorted(reverseFilePaths.cbegin(), reverseFilePaths.cend(), "/file/pathFoo", reverseCompare);
+
+ ASSERT_FALSE(found.wasFound);
}
+
+TEST_F(StringCache, FindInSortedOneReverse)
+{
+ auto found = findInSorted(reverseFilePaths.cbegin(), reverseFilePaths.cend(), "/file/pathOne", reverseCompare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedTwoReverse)
+{
+ auto found = findInSorted(reverseFilePaths.cbegin(), reverseFilePaths.cend(), "/file/pathTwo", reverseCompare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedTreeReverse)
+{
+ auto found = findInSorted(reverseFilePaths.cbegin(), reverseFilePaths.cend(), "/file/pathThree", reverseCompare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedFourReverse)
+{
+ auto found = findInSorted(reverseFilePaths.cbegin(), reverseFilePaths.cend(), "/file/pathFour", reverseCompare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+TEST_F(StringCache, FindInSortedFifeReverse)
+{
+ auto found = findInSorted(reverseFilePaths.cbegin(), reverseFilePaths.cend(), "/file/pathFife", reverseCompare);
+
+ ASSERT_TRUE(found.wasFound);
+}
+
+
+void StringCache::SetUp()
+{
+ std::sort(filePaths.begin(), filePaths.end(), [] (auto &f, auto &l) { return compare(f, l) < 0;});
+ std::sort(reverseFilePaths.begin(), reverseFilePaths.end(), [] (auto &f, auto &l) { return reverseCompare(f, l) < 0;});
+}
+}
+
diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp
new file mode 100644
index 0000000000..6684b2cddb
--- /dev/null
+++ b/tests/unit/unittest/symbolindexer-test.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+#include "mocksymbolscollector.h"
+#include "mocksymbolstorage.h"
+
+#include <symbolindexer.h>
+#include <updatepchprojectpartsmessage.h>
+#include <projectpartcontainerv2.h>
+
+namespace {
+
+using testing::_;
+using testing::Contains;
+using testing::Field;
+using testing::IsEmpty;
+using testing::NiceMock;
+using testing::Property;
+using testing::Return;
+using testing::ReturnRef;
+using testing::Sequence;
+
+using Utils::PathString;
+using ClangBackEnd::V2::ProjectPartContainer;
+using ClangBackEnd::V2::ProjectPartContainers;
+using ClangBackEnd::V2::FileContainers;
+using ClangBackEnd::SymbolEntries;
+using ClangBackEnd::SymbolEntry;
+using ClangBackEnd::SourceLocationEntries;
+using ClangBackEnd::SourceLocationEntry;
+using ClangBackEnd::SymbolType;
+
+class SymbolIndexer : public testing::Test
+{
+protected:
+ void SetUp();
+
+protected:
+ PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp";
+ PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
+ PathString header1Path = TESTDATA_DIR "/includecollector_header1.h";
+ PathString header2Path = TESTDATA_DIR "/includecollector_header2.h";
+ PathString generatedFileName = "includecollector_generated_file.h";
+ PathString generatedFilePath = TESTDATA_DIR "/includecollector_generated_file.h";
+ ProjectPartContainer projectPart1{"project1",
+ {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
+ {header1Path.clone()},
+ {main1Path.clone()}};
+ ProjectPartContainer projectPart2{"project2",
+ {"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"},
+ {header2Path.clone()},
+ {main2Path.clone()}};
+ FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
+ "void f();",
+ {}}};
+ SymbolEntries symbolEntries{{1, {"function", "function"}}};
+ SourceLocationEntries sourceLocations{{1, 1, {42, 23}, SymbolType::Declaration}};
+ NiceMock<MockSymbolsCollector> mockCollector;
+ NiceMock<MockSymbolStorage> mockStorage;
+ ClangBackEnd::SymbolIndexer indexer{mockCollector, mockStorage};
+};
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
+{
+ EXPECT_CALL(mockCollector, addFiles(projectPart1.sourcePaths(), projectPart1.arguments()));
+
+ indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollectorForEveryProjectPart)
+{
+ EXPECT_CALL(mockCollector, addFiles(_, _))
+ .Times(2);
+
+ indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved));
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsDoesNotCallAddFilesInCollectorForEmptyEveryProjectParts)
+{
+ EXPECT_CALL(mockCollector, addFiles(_, _))
+ .Times(0);
+
+ indexer.updateProjectParts({}, {});
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallscollectSymbolsInCollector)
+{
+ EXPECT_CALL(mockCollector, collectSymbols());
+
+ indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsSymbolsInCollector)
+{
+ EXPECT_CALL(mockCollector, symbols());
+
+ indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsSourceLocationsInCollector)
+{
+ EXPECT_CALL(mockCollector, sourceLocations());
+
+ indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddUnsavedFilesInCollector)
+{
+ EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved));
+
+ indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddSymbolsAndSourceLocationsInStorage)
+{
+ EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+
+ indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
+}
+
+TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder)
+{
+ EXPECT_CALL(mockCollector, addFiles(_, _));
+ EXPECT_CALL(mockCollector, addUnsavedFiles(unsaved));
+ EXPECT_CALL(mockCollector, collectSymbols());
+ EXPECT_CALL(mockCollector, symbols());
+ EXPECT_CALL(mockCollector, sourceLocations());
+ EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
+
+ indexer.updateProjectParts({projectPart1}, Utils::clone(unsaved));
+}
+
+void SymbolIndexer::SetUp()
+{
+ ON_CALL(mockCollector, symbols()).WillByDefault(ReturnRef(symbolEntries));
+ ON_CALL(mockCollector, sourceLocations()).WillByDefault(ReturnRef(sourceLocations));
+}
+
+}
+
diff --git a/tests/unit/unittest/symbolindexing-test.cpp b/tests/unit/unittest/symbolindexing-test.cpp
new file mode 100644
index 0000000000..a80e434254
--- /dev/null
+++ b/tests/unit/unittest/symbolindexing-test.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include <projectpartcontainerv2.h>
+
+#include <symbolindexing.h>
+#include <symbolquery.h>
+#include <querysqlitestatementfactory.h>
+
+#include <QDir>
+
+namespace {
+
+using Sqlite::Database;
+using Sqlite::ReadStatement;
+using ClangBackEnd::SymbolIndexer;
+using ClangBackEnd::SymbolsCollector;
+using ClangBackEnd::SymbolStorage;
+using ClangBackEnd::FilePathCache;
+using ClangBackEnd::FilePathCache;
+using ClangBackEnd::V2::ProjectPartContainer;
+using ClangBackEnd::V2::ProjectPartContainer;
+using ClangRefactoring::SymbolQuery;
+using ClangRefactoring::QuerySqliteStatementFactory;
+using Utils::PathString;
+using SL = ClangRefactoring::SourceLocations;
+
+using StatementFactory = QuerySqliteStatementFactory<Database, ReadStatement>;
+using Query = SymbolQuery<StatementFactory>;
+
+MATCHER_P3(IsLocation, sourceId, line, column,
+ std::string(negation ? "isn't" : "is")
+ + " source id " + PrintToString(sourceId)
+ + " line " + PrintToString(line)
+ + " and column " + PrintToString(column)
+ )
+{
+ const SL::Location &location = arg;
+
+ return location.sourceId == sourceId
+ && location.line == line
+ && location.column == column;
+};
+
+class SymbolIndexing : public testing::Test
+{
+protected:
+ FilePathCache<std::mutex> filePathCache;
+ ClangBackEnd::SymbolIndexing indexing{filePathCache, QDir::tempPath() + "/symbol.db"};
+ StatementFactory queryFactory{indexing.database()};
+ Query query{queryFactory};
+ PathString main1Path = TESTDATA_DIR "/symbolindexing_main1.cpp";
+ ProjectPartContainer projectPart1{"project1",
+ {"cc", "-I", TESTDATA_DIR, "-std=c++1z"},
+ {},
+ {main1Path.clone()}};
+};
+
+TEST_F(SymbolIndexing, Locations)
+{
+ indexing.indexer().updateProjectParts({projectPart1}, {});
+
+ auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 6, 5);
+ ASSERT_THAT(locations.locations,
+ ElementsAre(
+ IsLocation(0, 5, 9),
+ IsLocation(0, 6, 5)));
+}
+
+TEST_F(SymbolIndexing, Sources)
+{
+ indexing.indexer().updateProjectParts({projectPart1}, {});
+
+ auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 6, 5);
+ ASSERT_THAT(locations.sources, ElementsAre(Pair(0, Eq(TESTDATA_DIR "/symbolindexing_main1.cpp"))));
+}
+
+TEST_F(SymbolIndexing, DISABLED_TemplateFunction)
+{
+ indexing.indexer().updateProjectParts({projectPart1}, {});
+
+ auto locations = query.locationsAt(TESTDATA_DIR "/symbolindexing_main1.cpp", 21, 24);
+ ASSERT_THAT(locations.locations,
+ ElementsAre(
+ IsLocation(0, 5, 9),
+ IsLocation(0, 6, 5)));
+}
+}
diff --git a/tests/unit/unittest/symbolquery-test.cpp b/tests/unit/unittest/symbolquery-test.cpp
new file mode 100644
index 0000000000..50925bd7f3
--- /dev/null
+++ b/tests/unit/unittest/symbolquery-test.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include "mocksqlitedatabase.h"
+#include "mocksqlitereadstatement.h"
+
+#include <symbolquery.h>
+#include <querysqlitestatementfactory.h>
+
+#include <sqlitedatabase.h>
+
+namespace {
+
+using ClangRefactoring::QuerySqliteStatementFactory;
+using Sqlite::Database;
+
+using StatementFactory = QuerySqliteStatementFactory<MockSqliteDatabase,
+ MockSqliteReadStatement>;
+using Query = ClangRefactoring::SymbolQuery<StatementFactory>;
+
+using Location = Query::Location;
+using Source = Query::Source;
+
+class SymbolQuery : public testing::Test
+{
+protected:
+ NiceMock<MockSqliteDatabase> mockDatabase;
+ StatementFactory statementFactory{mockDatabase};
+ MockSqliteReadStatement &selectLocationsForSymbolLocation = statementFactory.selectLocationsForSymbolLocation;
+ MockSqliteReadStatement &selectSourcePathForId = statementFactory.selectSourcePathForId;
+ std::vector<Location> locations{{1, 1, 1},
+ {1, 2, 3},
+ {2, 1, 1},
+ {2, 3, 1},
+ {4, 1, 1},
+ {4, 1, 3}};
+ Query query{statementFactory};
+};
+
+TEST_F(SymbolQuery, LocationsAt)
+{
+ EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnStdVectorLocation(_, Eq("/path/to/file.cpp"), 14, 7))
+ .WillRepeatedly(Return(locations));
+ EXPECT_CALL(selectSourcePathForId, valuesReturnStdVectorSource(_, ElementsAre(1, 2, 4)));
+
+ query.locationsAt("/path/to/file.cpp", 14, 7);
+}
+
+TEST_F(SymbolQuery, UniqueSourceIds)
+{
+ auto uniqueSourceIds = query.uniqueSourceIds(locations);
+
+ ASSERT_THAT(uniqueSourceIds, ElementsAre(1, 2, 4));
+}
+
+TEST_F(SymbolQuery, SourcesToHashMap)
+{
+ std::vector<Source> sources{{1, "/path/first"},
+ {2, "/path/second"},
+ {4, "/path/third"}};
+
+ auto hashMap = query.sourcesToHashMap(sources);
+
+ ASSERT_THAT(hashMap, UnorderedElementsAre(Pair(1, Eq("/path/first")),
+ Pair(2, Eq("/path/second")),
+ Pair(4, Eq("/path/third"))));
+}
+
+}
diff --git a/tests/unit/unittest/symbolscollector-test.cpp b/tests/unit/unittest/symbolscollector-test.cpp
new file mode 100644
index 0000000000..9b1f046cbd
--- /dev/null
+++ b/tests/unit/unittest/symbolscollector-test.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include <symbolscollector.h>
+
+#include "filesystem-utilities.h"
+
+using testing::PrintToString;
+using testing::AllOf;
+using testing::Contains;
+using testing::Not;
+using testing::Field;
+using testing::Key;
+using testing::Pair;
+using testing::Value;
+using testing::_;
+
+using ClangBackEnd::V2::FileContainers;
+using ClangBackEnd::SourceLocationEntry;
+using ClangBackEnd::SymbolEntry;
+using ClangBackEnd::SymbolType;
+using ClangBackEnd::SymbolIndex;
+
+namespace {
+
+class SymbolsCollector : public testing::Test
+{
+protected:
+ uint stringId(Utils::SmallStringView string)
+ {
+ return filePathCache.stringId(string);
+ }
+
+ SymbolIndex symbolIdForSymbolName(const Utils::SmallString &symbolName);
+
+protected:
+ ClangBackEnd::FilePathCache<std::mutex> filePathCache;
+ ClangBackEnd::SymbolsCollector collector{filePathCache};
+};
+
+TEST_F(SymbolsCollector, CollectSymbolName)
+{
+ collector.addFile(TESTDATA_DIR, "symbolscollector_simple.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_simple.cpp"});
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.symbols(),
+ Contains(
+ Pair(_, Field(&SymbolEntry::symbolName, "x"))));
+}
+
+TEST_F(SymbolsCollector, SymbolMatchesLocation)
+{
+ collector.addFile(TESTDATA_DIR, "symbolscollector_simple.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_simple.cpp"});
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.sourceLocations(),
+ Contains(
+ AllOf(Field(&SourceLocationEntry::symbolId, symbolIdForSymbolName("function")),
+ Field(&SourceLocationEntry::line, 1),
+ Field(&SourceLocationEntry::column, 6))));
+}
+
+TEST_F(SymbolsCollector, OtherSymboldMatchesLocation)
+{
+ collector.addFile(TESTDATA_DIR, "symbolscollector_simple.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_simple.cpp"});
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.sourceLocations(),
+ Contains(
+ AllOf(Field(&SourceLocationEntry::symbolId, symbolIdForSymbolName("function")),
+ Field(&SourceLocationEntry::line, 2),
+ Field(&SourceLocationEntry::column, 6))));
+}
+
+TEST_F(SymbolsCollector, CollectFilePath)
+{
+ collector.addFile(TESTDATA_DIR, "symbolscollector_simple.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_simple.cpp"});
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.sourceLocations(),
+ Contains(
+ AllOf(Field(&SourceLocationEntry::fileId,
+ stringId(TESTDATA_DIR"/symbolscollector_simple.cpp")),
+ Field(&SourceLocationEntry::symbolType, SymbolType::Declaration))));
+}
+
+TEST_F(SymbolsCollector, CollectLineColumn)
+{
+ collector.addFile(TESTDATA_DIR, "symbolscollector_simple.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_simple.cpp"});
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.sourceLocations(),
+ Contains(
+ AllOf(Field(&SourceLocationEntry::line, 1),
+ Field(&SourceLocationEntry::column, 6),
+ Field(&SourceLocationEntry::symbolType, SymbolType::Declaration))));
+}
+
+TEST_F(SymbolsCollector, CollectReference)
+{
+ collector.addFile(TESTDATA_DIR, "symbolscollector_simple.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_simple.cpp"});
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.sourceLocations(),
+ Contains(
+ AllOf(Field(&SourceLocationEntry::line, 14),
+ Field(&SourceLocationEntry::column, 5),
+ Field(&SourceLocationEntry::symbolType, SymbolType::DeclarationReference))));
+}
+
+TEST_F(SymbolsCollector, ReferencedSymboldMatchesLocation)
+{
+ collector.addFile(TESTDATA_DIR, "symbolscollector_simple.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_simple.cpp"});
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.sourceLocations(),
+ Contains(
+ AllOf(Field(&SourceLocationEntry::symbolId, symbolIdForSymbolName("function")),
+ Field(&SourceLocationEntry::line, 14),
+ Field(&SourceLocationEntry::column, 5))));
+}
+
+TEST_F(SymbolsCollector, DISABLED_ON_WINDOWS(CollectInUnsavedFile))
+{
+ FileContainers unsaved{{{TESTDATA_DIR, "symbolscollector_generated_file.h"},
+ "void function();",
+ {}}};
+ collector.addFile(TESTDATA_DIR, "symbolscollector_unsaved.cpp", "", {"cc", TESTDATA_DIR"/symbolscollector_unsaved.cpp"});
+ collector.addUnsavedFiles(std::move(unsaved));
+
+ collector.collectSymbols();
+
+ ASSERT_THAT(collector.symbols(),
+ Contains(
+ Pair(_, Field(&SymbolEntry::symbolName, "function"))));
+}
+
+SymbolIndex SymbolsCollector::symbolIdForSymbolName(const Utils::SmallString &symbolName)
+{
+ for (const auto &entry : collector.symbols()) {
+ if (entry.second.symbolName == symbolName)
+ return entry.first;
+ }
+
+ return 0;
+}
+
+}
diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp
new file mode 100644
index 0000000000..2628157a33
--- /dev/null
+++ b/tests/unit/unittest/symbolstorage-test.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include "mocksqlitereadstatement.h"
+#include "mocksqlitewritestatement.h"
+
+#include <storagesqlitestatementfactory.h>
+#include <symbolstorage.h>
+#include <sqlitedatabase.h>
+
+#include <storagesqlitestatementfactory.h>
+
+namespace {
+
+using Utils::PathString;
+using ClangBackEnd::FilePathCache;
+using ClangBackEnd::SymbolEntries;
+using ClangBackEnd::SymbolEntry;
+using ClangBackEnd::SourceLocationEntries;
+using ClangBackEnd::SourceLocationEntry;
+using ClangBackEnd::StorageSqliteStatementFactory;
+using ClangBackEnd::SymbolType;
+using Sqlite::Database;
+using Sqlite::Table;
+
+using StatementFactory = StorageSqliteStatementFactory<MockSqliteDatabase,
+ MockSqliteReadStatement,
+ MockSqliteWriteStatement>;
+using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
+
+class SymbolStorage : public testing::Test
+{
+protected:
+ void SetUp();
+
+protected:
+ FilePathCache<std::mutex> filePathCache;
+ NiceMock<MockMutex> mockMutex;
+ NiceMock<MockSqliteDatabase> mockDatabase{mockMutex};
+ StatementFactory statementFactory{mockDatabase};
+ MockSqliteWriteStatement &insertSymbolsToNewSymbolsStatement = statementFactory.insertSymbolsToNewSymbolsStatement;
+ MockSqliteWriteStatement &insertLocationsToNewLocationsStatement = statementFactory.insertLocationsToNewLocationsStatement;
+ MockSqliteWriteStatement &insertSourcesStatement = statementFactory.insertSourcesStatement;
+ MockSqliteReadStatement &selectNewSourceIdsStatement = statementFactory.selectNewSourceIdsStatement;
+ MockSqliteWriteStatement &addNewSymbolsToSymbolsStatement = statementFactory.addNewSymbolsToSymbolsStatement;
+ MockSqliteWriteStatement &syncNewSymbolsFromSymbolsStatement = statementFactory.syncNewSymbolsFromSymbolsStatement;
+ MockSqliteWriteStatement &syncSymbolsIntoNewLocationsStatement = statementFactory.syncSymbolsIntoNewLocationsStatement;
+ MockSqliteWriteStatement &deleteAllLocationsFromUpdatedFilesStatement = statementFactory.deleteAllLocationsFromUpdatedFilesStatement;
+ MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = statementFactory.insertNewLocationsInLocationsStatement;
+ MockSqliteWriteStatement &deleteNewSymbolsTableStatement = statementFactory.deleteNewSymbolsTableStatement;
+ MockSqliteWriteStatement &deleteNewLocationsTableStatement = statementFactory.deleteNewLocationsTableStatement;
+ SymbolEntries symbolEntries{{1, {"functionUSR", "function"}},
+ {2, {"function2USR", "function2"}}};
+ SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SymbolType::Declaration},
+ {2, 4, {7, 11}, SymbolType::Declaration}};
+ Storage storage{statementFactory, filePathCache};
+};
+
+TEST_F(SymbolStorage, CreateAndFillTemporaryLocationsTable)
+{
+ InSequence sequence;
+
+ EXPECT_CALL(insertLocationsToNewLocationsStatement, write(1, 42, 23, 3));
+ EXPECT_CALL(insertLocationsToNewLocationsStatement, write(2, 7, 11, 4));
+
+ storage.fillTemporaryLocationsTable(sourceLocations);
+}
+
+TEST_F(SymbolStorage, AddNewSymbolsToSymbols)
+{
+ EXPECT_CALL(addNewSymbolsToSymbolsStatement, execute());
+
+ storage.addNewSymbolsToSymbols();
+}
+
+TEST_F(SymbolStorage, SyncNewSymbolsFromSymbols)
+{
+ EXPECT_CALL(syncNewSymbolsFromSymbolsStatement, execute());
+
+ storage.syncNewSymbolsFromSymbols();
+}
+
+TEST_F(SymbolStorage, SyncSymbolsIntoNewLocations)
+{
+ EXPECT_CALL(syncSymbolsIntoNewLocationsStatement, execute());
+
+ storage.syncSymbolsIntoNewLocations();
+}
+
+TEST_F(SymbolStorage, DeleteAllLocationsFromUpdatedFiles)
+{
+ EXPECT_CALL(deleteAllLocationsFromUpdatedFilesStatement, execute());
+
+ storage.deleteAllLocationsFromUpdatedFiles();
+}
+
+TEST_F(SymbolStorage, InsertNewLocationsInLocations)
+{
+ EXPECT_CALL(insertNewLocationsInLocationsStatement, execute());
+
+ storage.insertNewLocationsInLocations();
+}
+
+TEST_F(SymbolStorage, SelectNewSourceIdsCalls)
+{
+ EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
+
+ storage.selectNewSourceIds();
+}
+
+TEST_F(SymbolStorage, SelectNewSourceIds)
+{
+ EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
+
+ auto sourceIds = storage.selectNewSourceIds();
+
+ ASSERT_THAT(sourceIds, ElementsAre(0, 1, 2));
+}
+
+TEST_F(SymbolStorage, InserNewSources)
+{
+ InSequence sequence;
+ EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
+
+ EXPECT_CALL(insertSourcesStatement, write(0, Eq("/path/to/source1")));
+ EXPECT_CALL(insertSourcesStatement, write(1, Eq("/path/to/source2")));
+ EXPECT_CALL(insertSourcesStatement, write(2, Eq("/path/to/source3")));
+
+ storage.insertNewSources();
+}
+
+
+TEST_F(SymbolStorage, DropNewSymbolsTable)
+{
+ EXPECT_CALL(deleteNewSymbolsTableStatement, execute());
+
+ storage.deleteNewSymbolsTable();
+}
+
+TEST_F(SymbolStorage, DropNewLocationsTable)
+{
+ EXPECT_CALL(deleteNewLocationsTableStatement, execute());
+
+ storage.deleteNewLocationsTable();
+}
+
+TEST_F(SymbolStorage, AddSymbolsAndSourceLocationsCallsWrite)
+{
+ InSequence sequence;
+
+ EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
+ EXPECT_CALL(insertSymbolsToNewSymbolsStatement, write(_, _, _)).Times(2);
+ EXPECT_CALL(insertLocationsToNewLocationsStatement, write(1, 42, 23, 3));
+ EXPECT_CALL(insertLocationsToNewLocationsStatement, write(2, 7, 11, 4));
+ EXPECT_CALL(addNewSymbolsToSymbolsStatement, execute());
+ EXPECT_CALL(syncNewSymbolsFromSymbolsStatement, execute());
+ EXPECT_CALL(syncSymbolsIntoNewLocationsStatement, execute());
+ EXPECT_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_));
+ EXPECT_CALL(insertSourcesStatement, write(0, Eq("/path/to/source1")));
+ EXPECT_CALL(insertSourcesStatement, write(1, Eq("/path/to/source2")));
+ EXPECT_CALL(insertSourcesStatement, write(2, Eq("/path/to/source3")));
+ EXPECT_CALL(deleteAllLocationsFromUpdatedFilesStatement, execute());
+ EXPECT_CALL(insertNewLocationsInLocationsStatement, execute());
+ EXPECT_CALL(deleteNewSymbolsTableStatement, execute());
+ EXPECT_CALL(deleteNewLocationsTableStatement, execute());
+ EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
+ EXPECT_CALL(mockMutex, unlock());
+
+ storage.addSymbolsAndSourceLocations(symbolEntries, sourceLocations);
+}
+
+void SymbolStorage::SetUp()
+{
+ ON_CALL(selectNewSourceIdsStatement, valuesReturnStdVectorInt(_))
+ .WillByDefault(Return(std::vector<FilePathIndex>{0, 1, 2}));
+
+ filePathCache.stringIds({"/path/to/source1", "/path/to/source2", "/path/to/source3"});
+}
+}
+
diff --git a/tests/unit/unittest/unittest-matchers.h b/tests/unit/unittest/unittest-matchers.h
new file mode 100644
index 0000000000..4e9fc6568d
--- /dev/null
+++ b/tests/unit/unittest/unittest-matchers.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <gmock/gmock-matchers.h>
+
+#include <utils/smallstringio.h>
+
+namespace UnitTests {
+
+template <typename StringType>
+class EndsWithMatcher
+{
+ public:
+ explicit EndsWithMatcher(const StringType& suffix) : m_suffix(suffix) {}
+
+
+ template <typename CharType>
+ bool MatchAndExplain(CharType *s, testing::MatchResultListener *listener) const
+ {
+ return s != NULL && MatchAndExplain(StringType(s), listener);
+ }
+
+
+ template <typename MatcheeStringType>
+ bool MatchAndExplain(const MatcheeStringType& s,
+ testing::MatchResultListener* /* listener */) const
+ {
+ return s.endsWith(m_suffix);
+ }
+
+ void DescribeTo(::std::ostream* os) const
+ {
+ *os << "ends with " << m_suffix;
+ }
+
+ void DescribeNegationTo(::std::ostream* os) const
+ {
+ *os << "doesn't end with " << m_suffix;
+ }
+
+ EndsWithMatcher(EndsWithMatcher const &) = default;
+ EndsWithMatcher &operator=(EndsWithMatcher const &) = delete;
+
+private:
+ const StringType m_suffix;
+};
+
+inline
+testing::PolymorphicMatcher<EndsWithMatcher<Utils::SmallString> >
+EndsWith(const Utils::SmallString &suffix)
+{
+ return testing::MakePolymorphicMatcher(EndsWithMatcher<Utils::SmallString>(suffix));
+}
+}
diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro
index 67226416af..25ba21f42f 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -65,9 +65,18 @@ SOURCES += \
smallstring-test.cpp \
sourcerangefilter-test.cpp \
spydummy.cpp \
+ symbolindexer-test.cpp \
stringcache-test.cpp \
unittests-main.cpp \
utf8-test.cpp \
+ symbolstorage-test.cpp \
+ mocksqlitereadstatement.cpp \
+ symbolquery-test.cpp \
+ storagesqlitestatementfactory-test.cpp \
+ querysqlitestatementfactory-test.cpp \
+ sqliteindex-test.cpp \
+ sqlitetransaction-test.cpp \
+ refactoringdatabaseinitializer-test.cpp
!isEmpty(LIBCLANG_LIBS) {
SOURCES += \
@@ -87,6 +96,7 @@ SOURCES += \
clangdocumentsuspenderresumer-test.cpp \
clangdocument-test.cpp \
clangfixitoperation-test.cpp \
+ clangfollowsymbol-test.cpp \
clangisdiagnosticrelatedtolocation-test.cpp \
clangjobqueue-test.cpp \
clangjobs-test.cpp \
@@ -143,6 +153,8 @@ SOURCES += \
refactoringengine-test.cpp \
refactoringserver-test.cpp \
sourcerangeextractor-test.cpp \
+ symbolindexing-test.cpp \
+ symbolscollector-test.cpp \
symbolfinder-test.cpp \
testclangtool.cpp \
}
@@ -184,6 +196,15 @@ HEADERS += \
sourcerangecontainer-matcher.h \
spydummy.h \
testenvironment.h \
+ mocksymbolscollector.h \
+ mocksymbolstorage.h \
+ mocksqlitewritestatement.h \
+ mocksqlitedatabase.h \
+ mocksqlitereadstatement.h \
+ google-using-declarations.h \
+ mocksymbolindexing.h \
+ sqliteteststatement.h \
+ mockmutex.h
!isEmpty(LIBCLANG_LIBS) {
HEADERS += \
diff --git a/tests/unit/unittest/unittests-main.cpp b/tests/unit/unittest/unittests-main.cpp
index 3229a4e252..3fb5505eff 100644
--- a/tests/unit/unittest/unittests-main.cpp
+++ b/tests/unit/unittest/unittests-main.cpp
@@ -44,8 +44,6 @@ int main(int argc, char *argv[])
qputenv("TMPDIR", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8());
qputenv("TEMP", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8());
- Sqlite::registerTypes();
-
QCoreApplication application(argc, argv);
QLoggingCategory::setFilterRules(QStringLiteral("*.info=false\n*.debug=false\n*.warning=true"));